jabberd2  2.2.16
util/base64.c
Go to the documentation of this file.
00001 /* Licensed to the Apache Software Foundation (ASF) under one or more
00002  * contributor license agreements.  See the NOTICE file distributed with
00003  * this work for additional information regarding copyright ownership.
00004  * The ASF licenses this file to You under the Apache License, Version 2.0
00005  * (the "License"); you may not use this file except in compliance with
00006  * the License.  You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 /* base64 encoder/decoder. Originally part of main/util.c
00018  * but moved here so that support/ab and apr_sha1.c could
00019  * use it. This meant removing the apr_palloc()s and adding
00020  * ugly 'len' functions, which is quite a nasty cost.
00021  */
00022 
00023 #include "util.h"
00024 
00025 /* aaaack but it's fast and const should make it shared text page. */
00026 static const unsigned char pr2six[256] =
00027 {
00028     /* ASCII table */
00029     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00030     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00031     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
00032     52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
00033     64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
00034     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
00035     64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00036     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
00037     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00038     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00039     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00040     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00041     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00042     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00043     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00044     64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
00045 };
00046 
00047 int apr_base64_decode_len(const char *bufcoded, int buflen)
00048 {
00049     int nbytesdecoded;
00050     register const unsigned char *bufin;
00051     register int nprbytes;
00052 
00053     bufin = (const unsigned char *) bufcoded;
00054     while (pr2six[*(bufin++)] <= 63 && buflen-- > 0);
00055 
00056     nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
00057     nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
00058 
00059     return nbytesdecoded + 1;
00060 }
00061 
00062 int apr_base64_decode_binary(unsigned char *bufplain, const char *bufcoded, int buflen);
00063 
00064 int apr_base64_decode(char *bufplain, const char *bufcoded, int buflen)
00065 {
00066     int len;
00067     
00068     len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded, buflen);
00069     bufplain[len] = '\0';
00070     return len;
00071 }
00072 
00073 int apr_base64_decode_binary(unsigned char *bufplain,
00074                    const char *bufcoded, int buflen)
00075 {
00076     int nbytesdecoded;
00077     register const unsigned char *bufin;
00078     register unsigned char *bufout;
00079     register int nprbytes;
00080 
00081     bufin = (const unsigned char *) bufcoded;
00082     while (pr2six[*(bufin++)] <= 63 && buflen-- > 0);
00083     nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
00084     nbytesdecoded = (((int)nprbytes + 3) / 4) * 3;
00085 
00086     bufout = (unsigned char *) bufplain;
00087     bufin = (const unsigned char *) bufcoded;
00088 
00089     while (nprbytes > 4) {
00090     *(bufout++) =
00091         (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
00092     *(bufout++) =
00093         (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
00094     *(bufout++) =
00095         (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
00096     bufin += 4;
00097     nprbytes -= 4;
00098     }
00099 
00100     /* Note: (nprbytes == 1) would be an error, so just ingore that case */
00101     if (nprbytes > 1) {
00102     *(bufout++) =
00103         (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
00104     }
00105     if (nprbytes > 2) {
00106     *(bufout++) =
00107         (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
00108     }
00109     if (nprbytes > 3) {
00110     *(bufout++) =
00111         (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
00112     }
00113 
00114     nbytesdecoded -= (4 - (int)nprbytes) & 3;
00115     return nbytesdecoded;
00116 }
00117 
00118 static const char basis_64[] =
00119     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00120 
00121 int apr_base64_encode_len(int len)
00122 {
00123     return ((len + 2) / 3 * 4) + 1;
00124 }
00125 
00126 int apr_base64_encode_binary(char *encoded, const unsigned char *string, int len);
00127 
00128 int apr_base64_encode(char *encoded, const char *string, int len)
00129 {
00130     return apr_base64_encode_binary(encoded, (const unsigned char *) string, len);
00131 }
00132 
00133 int apr_base64_encode_binary(char *encoded,
00134                                       const unsigned char *string, int len)
00135 {
00136     int i;
00137     char *p;
00138 
00139     p = encoded;
00140     for (i = 0; i < len - 2; i += 3) {
00141     *p++ = basis_64[(string[i] >> 2) & 0x3F];
00142     *p++ = basis_64[((string[i] & 0x3) << 4) |
00143                     ((int) (string[i + 1] & 0xF0) >> 4)];
00144     *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
00145                     ((int) (string[i + 2] & 0xC0) >> 6)];
00146     *p++ = basis_64[string[i + 2] & 0x3F];
00147     }
00148     if (i < len) {
00149     *p++ = basis_64[(string[i] >> 2) & 0x3F];
00150     if (i == (len - 1)) {
00151         *p++ = basis_64[((string[i] & 0x3) << 4)];
00152         *p++ = '=';
00153     }
00154     else {
00155         *p++ = basis_64[((string[i] & 0x3) << 4) |
00156                         ((int) (string[i + 1] & 0xF0) >> 4)];
00157         *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
00158     }
00159     *p++ = '=';
00160     }
00161 
00162     *p++ = '\0';
00163     return (int)(p - encoded);
00164 }
00165 
00166 /* convenience functions for j2 */
00167 char *b64_encode(char *buf, int len) {
00168     int elen;
00169     char *out;
00170 
00171     if(len == 0)
00172         len = strlen(buf);
00173 
00174     elen = apr_base64_encode_len(len);
00175     out = (char *) malloc(sizeof(char) * (elen + 1));
00176 
00177     apr_base64_encode(out, buf, len);
00178 
00179     return out;
00180 }
00181 
00182 char *b64_decode(char *buf) {
00183     int elen;
00184     char *out;
00185 
00186     elen = apr_base64_decode_len(buf, -1);
00187     out = (char *) malloc(sizeof(char) * (elen + 1));
00188 
00189     apr_base64_decode(out, buf, -1);
00190 
00191     return out;
00192 }