glib/: fully remove galias hacks
[platform/upstream/glib.git] / glib / gbase64.c
1 /* gbase64.c - Base64 encoding/decoding
2  *
3  *  Copyright (C) 2006 Alexander Larsson <alexl@redhat.com>
4  *  Copyright (C) 2000-2003 Ximian Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  *
21  * This is based on code in camel, written by:
22  *    Michael Zucchi <notzed@ximian.com>
23  *    Jeffrey Stedfast <fejj@ximian.com>
24  */
25
26 #include "config.h"
27
28 #include <string.h>
29
30 #include "gbase64.h"
31 #include "glib.h"
32 #include "glibintl.h"
33
34
35 /**
36  * SECTION:base64 Base64 Encoding
37  * @short_description: encodes and decodes data in Base64 format
38  *
39  * Base64 is an encoding that allows a sequence of arbitrary bytes to be
40  * encoded as a sequence of printable ASCII characters. For the definition
41  * of Base64, see <ulink url="http://www.ietf.org/rfc/rfc1421.txt">RFC
42  * 1421</ulink> or <ulink url="http://www.ietf.org/rfc/rfc2045.txt">RFC
43  * 2045</ulink>. Base64 is most commonly used as a MIME transfer encoding
44  * for email.
45  *
46  * GLib supports incremental encoding using g_base64_encode_step() and
47  * g_base64_encode_close(). Incremental decoding can be done with
48  * g_base64_decode_step(). To encode or decode data in one go, use
49  * g_base64_encode() or g_base64_decode(). To avoid memory allocation when
50  * decoding, you can use g_base64_decode_inplace().
51  *
52  * Support for Base64 encoding has been added in GLib 2.12.
53  */
54
55 static const char base64_alphabet[] =
56         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
57
58 /**
59  * g_base64_encode_step:
60  * @in: the binary data to encode
61  * @len: the length of @in
62  * @break_lines: whether to break long lines
63  * @out: pointer to destination buffer
64  * @state: Saved state between steps, initialize to 0
65  * @save: Saved state between steps, initialize to 0
66  *
67  * Incrementally encode a sequence of binary data into its Base-64 stringified
68  * representation. By calling this function multiple times you can convert 
69  * data in chunks to avoid having to have the full encoded data in memory.
70  *
71  * When all of the data has been converted you must call 
72  * g_base64_encode_close() to flush the saved state.
73  *
74  * The output buffer must be large enough to fit all the data that will
75  * be written to it. Due to the way base64 encodes you will need
76  * at least: (@len / 3 + 1) * 4 + 4 bytes (+ 4 may be needed in case of
77  * non-zero state). If you enable line-breaking you will need at least:
78  * ((@len / 3 + 1) * 4 + 4) / 72 + 1 bytes of extra space.
79  *
80  * @break_lines is typically used when putting base64-encoded data in emails.
81  * It breaks the lines at 72 columns instead of putting all of the text on 
82  * the same line. This avoids problems with long lines in the email system.
83  *
84  * Return value: The number of bytes of output that was written
85  *
86  * Since: 2.12
87  */
88 gsize
89 g_base64_encode_step (const guchar *in, 
90                       gsize         len, 
91                       gboolean      break_lines, 
92                       gchar        *out, 
93                       gint         *state, 
94                       gint         *save)
95 {
96   char *outptr;
97   const guchar *inptr;
98   
99   g_return_val_if_fail (in != NULL, 0);
100   g_return_val_if_fail (out != NULL, 0);
101   g_return_val_if_fail (state != NULL, 0);
102   g_return_val_if_fail (save != NULL, 0);
103
104   if (len <= 0)
105     return 0;
106   
107   inptr = in;
108   outptr = out;
109   
110   if (len + ((char *) save) [0] > 2)
111     {
112       const guchar *inend = in+len-2;
113       int c1, c2, c3;
114       int already;
115       
116       already = *state;
117       
118       switch (((char *) save) [0])
119         {       
120         case 1: 
121           c1 = ((unsigned char *) save) [1]; 
122           goto skip1;
123         case 2: 
124           c1 = ((unsigned char *) save) [1];
125           c2 = ((unsigned char *) save) [2]; 
126           goto skip2;
127         }
128       
129       /* 
130        * yes, we jump into the loop, no i'm not going to change it, 
131        * it's beautiful! 
132        */
133       while (inptr < inend)
134         {
135           c1 = *inptr++;
136         skip1:
137           c2 = *inptr++;
138         skip2:
139           c3 = *inptr++;
140           *outptr++ = base64_alphabet [ c1 >> 2 ];
141           *outptr++ = base64_alphabet [ c2 >> 4 | 
142                                         ((c1&0x3) << 4) ];
143           *outptr++ = base64_alphabet [ ((c2 &0x0f) << 2) | 
144                                         (c3 >> 6) ];
145           *outptr++ = base64_alphabet [ c3 & 0x3f ];
146           /* this is a bit ugly ... */
147           if (break_lines && (++already) >= 19)
148             {
149               *outptr++ = '\n';
150               already = 0;
151             }
152         }
153       
154       ((char *)save)[0] = 0;
155       len = 2 - (inptr - inend);
156       *state = already;
157     }
158   
159   if (len>0)
160     {
161       char *saveout;
162       
163       /* points to the slot for the next char to save */
164       saveout = & (((char *)save)[1]) + ((char *)save)[0];
165       
166       /* len can only be 0 1 or 2 */
167       switch(len)
168         {
169         case 2: *saveout++ = *inptr++;
170         case 1: *saveout++ = *inptr++;
171         }
172       ((char *)save)[0] += len;
173     }
174   
175   return outptr - out;
176 }
177
178 /**
179  * g_base64_encode_close:
180  * @break_lines: whether to break long lines
181  * @out: pointer to destination buffer
182  * @state: Saved state from g_base64_encode_step()
183  * @save: Saved state from g_base64_encode_step()
184  *
185  * Flush the status from a sequence of calls to g_base64_encode_step().
186  *
187  * The output buffer must be large enough to fit all the data that will
188  * be written to it. It will need up to 4 bytes, or up to 5 bytes if
189  * line-breaking is enabled.
190  *
191  * Return value: The number of bytes of output that was written
192  *
193  * Since: 2.12
194  */
195 gsize
196 g_base64_encode_close (gboolean  break_lines,
197                        gchar    *out,
198                        gint     *state,
199                        gint     *save)
200 {
201   int c1, c2;
202   char *outptr = out;
203
204   g_return_val_if_fail (out != NULL, 0);
205   g_return_val_if_fail (state != NULL, 0);
206   g_return_val_if_fail (save != NULL, 0);
207
208   c1 = ((unsigned char *) save) [1];
209   c2 = ((unsigned char *) save) [2];
210   
211   switch (((char *) save) [0])
212     {
213     case 2:
214       outptr [2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ];
215       g_assert (outptr [2] != 0);
216       goto skip;
217     case 1:
218       outptr[2] = '=';
219     skip:
220       outptr [0] = base64_alphabet [ c1 >> 2 ];
221       outptr [1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )];
222       outptr [3] = '=';
223       outptr += 4;
224       break;
225     }
226   if (break_lines)
227     *outptr++ = '\n';
228   
229   *save = 0;
230   *state = 0;
231   
232   return outptr - out;
233 }
234
235 /**
236  * g_base64_encode:
237  * @data: the binary data to encode
238  * @len: the length of @data
239  *
240  * Encode a sequence of binary data into its Base-64 stringified
241  * representation.
242  *
243  * Return value: a newly allocated, zero-terminated Base-64 encoded
244  *               string representing @data. The returned string must 
245  *               be freed with g_free().
246  *
247  * Since: 2.12
248  */
249 gchar *
250 g_base64_encode (const guchar *data, 
251                  gsize         len)
252 {
253   gchar *out;
254   gint state = 0, outlen;
255   gint save = 0;
256
257   g_return_val_if_fail (data != NULL, NULL);
258   g_return_val_if_fail (len > 0, NULL);
259
260   /* We can use a smaller limit here, since we know the saved state is 0,
261      +1 is needed for trailing \0, also check for unlikely integer overflow */
262   if (len >= ((G_MAXSIZE - 1) / 4 - 1) * 3)
263     g_error("%s: input too large for Base64 encoding (%"G_GSIZE_FORMAT" chars)",
264         G_STRLOC, len);
265
266   out = g_malloc ((len / 3 + 1) * 4 + 1);
267
268   outlen = g_base64_encode_step (data, len, FALSE, out, &state, &save);
269   outlen += g_base64_encode_close (FALSE, out + outlen, &state, &save);
270   out[outlen] = '\0';
271
272   return (gchar *) out;
273 }
274
275 static const unsigned char mime_base64_rank[256] = {
276   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
277   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
278   255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63,
279    52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255,
280   255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
281    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255,
282   255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
283    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255,
284   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
285   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
286   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
287   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
288   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
289   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
290   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
291   255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
292 };
293
294 /**
295  * g_base64_decode_step: 
296  * @in: binary input data
297  * @len: max length of @in data to decode
298  * @out: output buffer
299  * @state: Saved state between steps, initialize to 0
300  * @save: Saved state between steps, initialize to 0
301  *
302  * Incrementally decode a sequence of binary data from its Base-64 stringified
303  * representation. By calling this function multiple times you can convert 
304  * data in chunks to avoid having to have the full encoded data in memory.
305  *
306  * The output buffer must be large enough to fit all the data that will
307  * be written to it. Since base64 encodes 3 bytes in 4 chars you need
308  * at least: (@len / 4) * 3 + 3 bytes (+ 3 may be needed in case of non-zero
309  * state).
310  * 
311  * Return value: The number of bytes of output that was written
312  *
313  * Since: 2.12
314  **/
315 gsize
316 g_base64_decode_step (const gchar  *in, 
317                       gsize         len, 
318                       guchar       *out, 
319                       gint         *state, 
320                       guint        *save)
321 {
322   const guchar *inptr;
323   guchar *outptr;
324   const guchar *inend;
325   guchar c, rank;
326   guchar last[2];
327   unsigned int v;
328   int i;
329
330   g_return_val_if_fail (in != NULL, 0);
331   g_return_val_if_fail (out != NULL, 0);
332   g_return_val_if_fail (state != NULL, 0);
333   g_return_val_if_fail (save != NULL, 0);
334
335   if (len <= 0)
336     return 0;
337   
338   inend = (const guchar *)in+len;
339   outptr = out;
340   
341   /* convert 4 base64 bytes to 3 normal bytes */
342   v=*save;
343   i=*state;
344   inptr = (const guchar *)in;
345   last[0] = last[1] = 0;
346   while (inptr < inend)
347     {
348       c = *inptr++;
349       rank = mime_base64_rank [c];
350       if (rank != 0xff)
351         {
352           last[1] = last[0];
353           last[0] = c;
354           v = (v<<6) | rank;
355           i++;
356           if (i==4)
357             {
358               *outptr++ = v>>16;
359               if (last[1] != '=')
360                 *outptr++ = v>>8;
361               if (last[0] != '=')
362                 *outptr++ = v;
363               i=0;
364             }
365         }
366     }
367   
368   *save = v;
369   *state = i;
370   
371   return outptr - out;
372 }
373
374 /**
375  * g_base64_decode:
376  * @text: zero-terminated string with base64 text to decode
377  * @out_len: The length of the decoded data is written here
378  *
379  * Decode a sequence of Base-64 encoded text into binary data
380  *
381  * Return value: a newly allocated buffer containing the binary data
382  *               that @text represents. The returned buffer must
383  *               be freed with g_free().
384  *
385  * Since: 2.12
386  */
387 guchar *
388 g_base64_decode (const gchar *text,
389                  gsize       *out_len)
390 {
391   guchar *ret;
392   gsize input_length;
393   gint state = 0;
394   guint save = 0;
395   
396   g_return_val_if_fail (text != NULL, NULL);
397   g_return_val_if_fail (out_len != NULL, NULL);
398
399   input_length = strlen (text);
400
401   g_return_val_if_fail (input_length > 1, NULL);
402
403   /* We can use a smaller limit here, since we know the saved state is 0,
404      +1 used to avoid calling g_malloc0(0), and hence retruning NULL */
405   ret = g_malloc0 ((input_length / 4) * 3 + 1);
406   
407   *out_len = g_base64_decode_step (text, input_length, ret, &state, &save);
408   
409   return ret; 
410 }
411  
412 /**
413  * g_base64_decode_inplace:
414  * @text: zero-terminated string with base64 text to decode
415  * @out_len: The length of the decoded data is written here
416  *
417  * Decode a sequence of Base-64 encoded text into binary data
418  * by overwriting the input data.
419  *
420  * Return value: The binary data that @text responds. This pointer
421  *               is the same as the input @text.
422  *
423  * Since: 2.20
424  */
425 guchar *
426 g_base64_decode_inplace (gchar *text,
427                          gsize *out_len)
428 {
429   gint input_length, state = 0;
430   guint save = 0;
431   
432   g_return_val_if_fail (text != NULL, NULL);
433   g_return_val_if_fail (out_len != NULL, NULL);
434
435   input_length = strlen (text);
436
437   g_return_val_if_fail (input_length > 1, NULL);
438
439   *out_len = g_base64_decode_step (text, input_length, (guchar *) text, &state, &save);
440   
441   return (guchar *) text; 
442 }