1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 /* Base64 encoding/decoding */
25 #include "curl_setup.h"
27 #define _MPRINTF_REPLACE /* use our functions only */
28 #include <curl/mprintf.h>
30 #include "urldata.h" /* for the SessionHandle definition */
32 #include "curl_base64.h"
33 #include "curl_memory.h"
34 #include "non-ascii.h"
36 /* include memdebug.h last */
39 /* ---- Base64 Encoding/Decoding Table --- */
40 static const char table64[]=
41 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
43 static void decodeQuantum(unsigned char *dest, const char *src)
46 unsigned long i, v, x = 0;
48 for(i = 0, s = src; i < 4; i++, s++) {
51 while(*p && (*p != *s)) {
61 dest[2] = curlx_ultouc(x & 0xFFUL);
63 dest[1] = curlx_ultouc(x & 0xFFUL);
65 dest[0] = curlx_ultouc(x & 0xFFUL);
69 * Curl_base64_decode()
71 * Given a base64 NUL-terminated string at src, decode it and return a
72 * pointer in *outptr to a newly allocated memory area holding decoded
73 * data. Size of decoded data is returned in variable pointed by outlen.
75 * Returns CURLE_OK on success, otherwise specific error code. Function
76 * output shall not be considered valid unless CURLE_OK is returned.
78 * When decoded data length is 0, returns NULL in *outptr.
82 CURLcode Curl_base64_decode(const char *src,
83 unsigned char **outptr, size_t *outlen)
86 size_t equalsTerm = 0;
89 unsigned char lastQuantum[3];
91 unsigned char *newstr;
96 while((src[length] != '=') && src[length])
98 /* A maximum of two = padding characters is allowed */
99 if(src[length] == '=') {
101 if(src[length+equalsTerm] == '=')
104 numQuantums = (length + equalsTerm) / 4;
106 /* Don't allocate a buffer if the decoded length is 0 */
110 rawlen = (numQuantums * 3) - equalsTerm;
112 /* The buffer must be large enough to make room for the last quantum
113 (which may be partially thrown out) and the zero terminator. */
114 newstr = malloc(rawlen+4);
116 return CURLE_OUT_OF_MEMORY;
120 /* Decode all but the last quantum (which may not decode to a
121 multiple of 3 bytes) */
122 for(i = 0; i < numQuantums - 1; i++) {
123 decodeQuantum(newstr, src);
124 newstr += 3; src += 4;
127 /* This final decode may actually read slightly past the end of the buffer
128 if the input string is missing pad bytes. This will almost always be
130 decodeQuantum(lastQuantum, src);
131 for(i = 0; i < 3 - equalsTerm; i++)
132 newstr[i] = lastQuantum[i];
134 newstr[i] = '\0'; /* zero terminate */
136 *outlen = rawlen; /* return size of decoded data */
142 * Curl_base64_encode()
144 * Given a pointer to an input buffer and an input size, encode it and
145 * return a pointer in *outptr to a newly allocated memory area holding
146 * encoded data. Size of encoded data is returned in variable pointed by
149 * Input length of 0 indicates input buffer holds a NUL-terminated string.
151 * Returns CURLE_OK on success, otherwise specific error code. Function
152 * output shall not be considered valid unless CURLE_OK is returned.
154 * When encoded data length is 0, returns NULL in *outptr.
158 CURLcode Curl_base64_encode(struct SessionHandle *data,
159 const char *inputbuff, size_t insize,
160 char **outptr, size_t *outlen)
163 unsigned char ibuf[3];
164 unsigned char obuf[4];
169 char *convbuf = NULL;
171 const char *indata = inputbuff;
177 insize = strlen(indata);
179 base64data = output = malloc(insize*4/3+4);
181 return CURLE_OUT_OF_MEMORY;
184 * The base64 data needs to be created using the network encoding
185 * not the host encoding. And we can't change the actual input
186 * so we copy it to a buffer, translate it, and use that instead.
188 error = Curl_convert_clone(data, indata, insize, &convbuf);
195 indata = (char *)convbuf;
198 for(i = inputparts = 0; i < 3; i++) {
201 ibuf[i] = (unsigned char) *indata;
209 obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
210 obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
211 ((ibuf[1] & 0xF0) >> 4));
212 obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
213 ((ibuf[2] & 0xC0) >> 6));
214 obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
217 case 1: /* only one byte read */
218 snprintf(output, 5, "%c%c==",
222 case 2: /* two bytes read */
223 snprintf(output, 5, "%c%c%c=",
229 snprintf(output, 5, "%c%c%c%c",
239 *outptr = base64data; /* return pointer to new data, allocated memory */
244 *outlen = strlen(base64data); /* return the length of the new data */
248 /* ---- End of Base64 Encoding ---- */