base64.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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 https://curl.haxx.se/docs/copyright.html.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ***************************************************************************/
22 
23 /* Base64 encoding/decoding */
24 
25 #include "curl_setup.h"
26 #include "urldata.h" /* for the Curl_easy definition */
27 #include "warnless.h"
28 #include "curl_base64.h"
29 #include "non-ascii.h"
30 
31 /* The last 3 #include files should be in this order */
32 #include "curl_printf.h"
33 #include "curl_memory.h"
34 #include "memdebug.h"
35 
36 /* ---- Base64 Encoding/Decoding Table --- */
37 static const char base64[]=
38  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
39 
40 /* The Base 64 encoding with an URL and filename safe alphabet, RFC 4648
41  section 5 */
42 static const char base64url[]=
43  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
44 
45 static size_t decodeQuantum(unsigned char *dest, const char *src)
46 {
47  size_t padding = 0;
48  const char *s, *p;
49  unsigned long i, x = 0;
50 
51  for(i = 0, s = src; i < 4; i++, s++) {
52  unsigned long v = 0;
53 
54  if(*s == '=') {
55  x = (x << 6);
56  padding++;
57  }
58  else {
59  p = base64;
60 
61  while(*p && (*p != *s)) {
62  v++;
63  p++;
64  }
65 
66  if(*p == *s)
67  x = (x << 6) + v;
68  else
69  return 0;
70  }
71  }
72 
73  if(padding < 1)
74  dest[2] = curlx_ultouc(x & 0xFFUL);
75 
76  x >>= 8;
77  if(padding < 2)
78  dest[1] = curlx_ultouc(x & 0xFFUL);
79 
80  x >>= 8;
81  dest[0] = curlx_ultouc(x & 0xFFUL);
82 
83  return 3 - padding;
84 }
85 
86 /*
87  * Curl_base64_decode()
88  *
89  * Given a base64 NUL-terminated string at src, decode it and return a
90  * pointer in *outptr to a newly allocated memory area holding decoded
91  * data. Size of decoded data is returned in variable pointed by outlen.
92  *
93  * Returns CURLE_OK on success, otherwise specific error code. Function
94  * output shall not be considered valid unless CURLE_OK is returned.
95  *
96  * When decoded data length is 0, returns NULL in *outptr.
97  *
98  * @unittest: 1302
99  */
100 CURLcode Curl_base64_decode(const char *src,
101  unsigned char **outptr, size_t *outlen)
102 {
103  size_t srclen = 0;
104  size_t length = 0;
105  size_t padding = 0;
106  size_t i;
107  size_t numQuantums;
108  size_t rawlen = 0;
109  unsigned char *pos;
110  unsigned char *newstr;
111 
112  *outptr = NULL;
113  *outlen = 0;
114  srclen = strlen(src);
115 
116  /* Check the length of the input string is valid */
117  if(!srclen || srclen % 4)
119 
120  /* Find the position of any = padding characters */
121  while((src[length] != '=') && src[length])
122  length++;
123 
124  /* A maximum of two = padding characters is allowed */
125  if(src[length] == '=') {
126  padding++;
127  if(src[length + 1] == '=')
128  padding++;
129  }
130 
131  /* Check the = padding characters weren't part way through the input */
132  if(length + padding != srclen)
134 
135  /* Calculate the number of quantums */
136  numQuantums = srclen / 4;
137 
138  /* Calculate the size of the decoded string */
139  rawlen = (numQuantums * 3) - padding;
140 
141  /* Allocate our buffer including room for a zero terminator */
142  newstr = malloc(rawlen + 1);
143  if(!newstr)
144  return CURLE_OUT_OF_MEMORY;
145 
146  pos = newstr;
147 
148  /* Decode the quantums */
149  for(i = 0; i < numQuantums; i++) {
150  size_t result = decodeQuantum(pos, src);
151  if(!result) {
152  free(newstr);
153 
155  }
156 
157  pos += result;
158  src += 4;
159  }
160 
161  /* Zero terminate */
162  *pos = '\0';
163 
164  /* Return the decoded data */
165  *outptr = newstr;
166  *outlen = rawlen;
167 
168  return CURLE_OK;
169 }
170 
171 static CURLcode base64_encode(const char *table64,
172  struct Curl_easy *data,
173  const char *inputbuff, size_t insize,
174  char **outptr, size_t *outlen)
175 {
177  unsigned char ibuf[3];
178  unsigned char obuf[4];
179  int i;
180  int inputparts;
181  char *output;
182  char *base64data;
183  char *convbuf = NULL;
184 
185  const char *indata = inputbuff;
186 
187  *outptr = NULL;
188  *outlen = 0;
189 
190  if(!insize)
191  insize = strlen(indata);
192 
193 #if SIZEOF_SIZE_T == 4
194  if(insize > UINT_MAX/4)
195  return CURLE_OUT_OF_MEMORY;
196 #endif
197 
198  base64data = output = malloc(insize * 4 / 3 + 4);
199  if(!output)
200  return CURLE_OUT_OF_MEMORY;
201 
202  /*
203  * The base64 data needs to be created using the network encoding
204  * not the host encoding. And we can't change the actual input
205  * so we copy it to a buffer, translate it, and use that instead.
206  */
207  result = Curl_convert_clone(data, indata, insize, &convbuf);
208  if(result) {
209  free(output);
210  return result;
211  }
212 
213  if(convbuf)
214  indata = (char *)convbuf;
215 
216  while(insize > 0) {
217  for(i = inputparts = 0; i < 3; i++) {
218  if(insize > 0) {
219  inputparts++;
220  ibuf[i] = (unsigned char) *indata;
221  indata++;
222  insize--;
223  }
224  else
225  ibuf[i] = 0;
226  }
227 
228  obuf[0] = (unsigned char) ((ibuf[0] & 0xFC) >> 2);
229  obuf[1] = (unsigned char) (((ibuf[0] & 0x03) << 4) | \
230  ((ibuf[1] & 0xF0) >> 4));
231  obuf[2] = (unsigned char) (((ibuf[1] & 0x0F) << 2) | \
232  ((ibuf[2] & 0xC0) >> 6));
233  obuf[3] = (unsigned char) (ibuf[2] & 0x3F);
234 
235  switch(inputparts) {
236  case 1: /* only one byte read */
237  snprintf(output, 5, "%c%c==",
238  table64[obuf[0]],
239  table64[obuf[1]]);
240  break;
241 
242  case 2: /* two bytes read */
243  snprintf(output, 5, "%c%c%c=",
244  table64[obuf[0]],
245  table64[obuf[1]],
246  table64[obuf[2]]);
247  break;
248 
249  default:
250  snprintf(output, 5, "%c%c%c%c",
251  table64[obuf[0]],
252  table64[obuf[1]],
253  table64[obuf[2]],
254  table64[obuf[3]]);
255  break;
256  }
257  output += 4;
258  }
259 
260  /* Zero terminate */
261  *output = '\0';
262 
263  /* Return the pointer to the new data (allocated memory) */
264  *outptr = base64data;
265 
266  free(convbuf);
267 
268  /* Return the length of the new data */
269  *outlen = strlen(base64data);
270 
271  return CURLE_OK;
272 }
273 
274 /*
275  * Curl_base64_encode()
276  *
277  * Given a pointer to an input buffer and an input size, encode it and
278  * return a pointer in *outptr to a newly allocated memory area holding
279  * encoded data. Size of encoded data is returned in variable pointed by
280  * outlen.
281  *
282  * Input length of 0 indicates input buffer holds a NUL-terminated string.
283  *
284  * Returns CURLE_OK on success, otherwise specific error code. Function
285  * output shall not be considered valid unless CURLE_OK is returned.
286  *
287  * When encoded data length is 0, returns NULL in *outptr.
288  *
289  * @unittest: 1302
290  */
292  const char *inputbuff, size_t insize,
293  char **outptr, size_t *outlen)
294 {
295  return base64_encode(base64, data, inputbuff, insize, outptr, outlen);
296 }
297 
298 /*
299  * Curl_base64url_encode()
300  *
301  * Given a pointer to an input buffer and an input size, encode it and
302  * return a pointer in *outptr to a newly allocated memory area holding
303  * encoded data. Size of encoded data is returned in variable pointed by
304  * outlen.
305  *
306  * Input length of 0 indicates input buffer holds a NUL-terminated string.
307  *
308  * Returns CURLE_OK on success, otherwise specific error code. Function
309  * output shall not be considered valid unless CURLE_OK is returned.
310  *
311  * When encoded data length is 0, returns NULL in *outptr.
312  *
313  * @unittest: 1302
314  */
316  const char *inputbuff, size_t insize,
317  char **outptr, size_t *outlen)
318 {
319  return base64_encode(base64url, data, inputbuff, insize, outptr, outlen);
320 }
#define free(ptr)
Definition: curl_memory.h:130
CURLcode Curl_convert_clone(struct Curl_easy *data, const char *indata, size_t insize, char **outbuf)
Definition: getpart.c:81
CURLcode Curl_base64_decode(const char *src, unsigned char **outptr, size_t *outlen)
Definition: base64.c:100
unsigned char curlx_ultouc(unsigned long ulnum)
Definition: warnless.c:143
XmlRpcServer s
CURLcode Curl_base64_encode(struct Curl_easy *data, const char *inputbuff, size_t insize, char **outptr, size_t *outlen)
Definition: base64.c:291
CURLcode
Definition: curl.h:454
#define malloc(size)
Definition: curl_memory.h:124
UNITTEST_START int result
Definition: unit1304.c:49
const char ** p
Definition: unit1394.c:76
unsigned int i
Definition: unit1303.c:79
CURLcode Curl_base64url_encode(struct Curl_easy *data, const char *inputbuff, size_t insize, char **outptr, size_t *outlen)
Definition: base64.c:315
UNITTEST_START char * output
Definition: unit1302.c:50
static struct input indata[NUM_HANDLES]
Definition: http2-upload.c:183
TFSIMD_FORCE_INLINE const tfScalar & x() const
Definition: curl.h:455
static const char base64url[]
Definition: base64.c:42
static CURLcode base64_encode(const char *table64, struct Curl_easy *data, const char *inputbuff, size_t insize, char **outptr, size_t *outlen)
Definition: base64.c:171
static size_t decodeQuantum(unsigned char *dest, const char *src)
Definition: base64.c:45
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
#define snprintf
Definition: curl_printf.h:42
Definition: debug.c:29
static const char base64[]
Definition: base64.c:37


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:08