00001 /********************************************************************************* 00002 00003 Copyright 2006-2008 MakingThings 00004 00005 Licensed under the Apache License, 00006 Version 2.0 (the "License"); you may not use this file except in compliance 00007 with the License. You may obtain a copy of the License at 00008 00009 http://www.apache.org/licenses/LICENSE-2.0 00010 00011 Unless required by applicable law or agreed to in writing, software distributed 00012 under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 00013 CONDITIONS OF ANY KIND, either express or implied. See the License for 00014 the specific language governing permissions and limitations under the License. 00015 00016 *********************************************************************************/ 00017 00018 /* 00019 Written by Simon Josefsson. Partially adapted from GNU MailUtils 00020 (mailbox/filter_trans.c, as of 2004-11-28). Improved by review 00021 from Paul Eggert, Bruno Haible, and Stepan Kasal 00022 */ 00023 00024 #include "base64.h" 00025 00026 bool isbase64 (char ch); 00027 00028 /* C89 compliant way to cast 'char' to 'unsigned char'. */ 00029 static inline unsigned char to_uchar (char ch) 00030 { 00031 return ch; 00032 } 00033 00034 /** \defgroup base64 Base 64 00035 The Make Controller Base 64 library provides a way to decode and encode base 64 data. 00036 00037 This is often handy when you need to send raw/binary data (as opposed to text) through a 00038 text based format, like XML or JSON. 00039 00040 Most code lifted from gnulib - http://savannah.gnu.org/projects/gnulib - and written by Simon Josefsson. 00041 \par 00042 00043 \ingroup Libraries 00044 @{ 00045 */ 00046 00047 /** 00048 Base 64 encode a block of data. 00049 Provide a buffer to write into and to read from. As Base64 encoding results in 00050 4 bytes for every 3 source bytes, ensure your destination buffer is large enough. 00051 00052 @param dest The buffer that the encoded string will be written into. 00053 @param dest_size The maximum number of bytes to write into the destination buffer. 00054 @param src A block of data to encode. 00055 @param src_size The number of bytes from src to encode. 00056 @return The length of the generated string (not including null termination). 00057 00058 \par Example 00059 \code 00060 #define BUFF_SIZE 256 00061 char encode_buf[BUFF_SIZE]; 00062 int len = Base64_Encode(encode_buf, BUFF_SIZE, "test", 4); 00063 // we now have "dGVzdA==" in encode_buf, and len is 8 00064 \endcode 00065 */ 00066 int Base64_Encode(char* dest, int dest_size, const char* src, int src_size) 00067 { 00068 // our library of valid b64 chars 00069 static const unsigned char b64str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00070 int orig_size = dest_size; 00071 00072 while(dest_size && src_size) 00073 { 00074 *dest++ = b64str[(to_uchar (src[0]) >> 2) & 0x3f]; 00075 if(!--dest_size) 00076 break; 00077 00078 *dest++ = b64str[((to_uchar (src[0]) << 4) 00079 + (--src_size ? to_uchar (src[1]) >> 4 : 0)) 00080 & 0x3f]; 00081 if(!--dest_size) 00082 break; 00083 00084 *dest++ = (src_size ? b64str[((to_uchar (src[1]) << 2) 00085 + (--src_size ? to_uchar (src[2]) >> 6 : 0)) & 0x3f] : '='); 00086 if(!--dest_size) 00087 break; 00088 00089 *dest++ = src_size ? b64str[to_uchar (src[2]) & 0x3f] : '='; 00090 if(!--dest_size) 00091 break; 00092 00093 if(src_size) 00094 src_size--; 00095 if(src_size) 00096 src += 3; 00097 } 00098 if(dest_size) 00099 *dest = '\0'; 00100 return orig_size - dest_size; 00101 } 00102 00103 /* With this approach this file works independent of the charset used 00104 (think EBCDIC). However, it does assume that the characters in the 00105 Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX 00106 1003.1-2001 require that char and unsigned char are 8-bit 00107 quantities, though, taking care of that problem. But this may be a 00108 potential problem on non-POSIX C99 platforms. 00109 00110 IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_" 00111 as the formal parameter rather than "x". */ 00112 #define B64(_) \ 00113 ((_) == 'A' ? 0 \ 00114 : (_) == 'B' ? 1 \ 00115 : (_) == 'C' ? 2 \ 00116 : (_) == 'D' ? 3 \ 00117 : (_) == 'E' ? 4 \ 00118 : (_) == 'F' ? 5 \ 00119 : (_) == 'G' ? 6 \ 00120 : (_) == 'H' ? 7 \ 00121 : (_) == 'I' ? 8 \ 00122 : (_) == 'J' ? 9 \ 00123 : (_) == 'K' ? 10 \ 00124 : (_) == 'L' ? 11 \ 00125 : (_) == 'M' ? 12 \ 00126 : (_) == 'N' ? 13 \ 00127 : (_) == 'O' ? 14 \ 00128 : (_) == 'P' ? 15 \ 00129 : (_) == 'Q' ? 16 \ 00130 : (_) == 'R' ? 17 \ 00131 : (_) == 'S' ? 18 \ 00132 : (_) == 'T' ? 19 \ 00133 : (_) == 'U' ? 20 \ 00134 : (_) == 'V' ? 21 \ 00135 : (_) == 'W' ? 22 \ 00136 : (_) == 'X' ? 23 \ 00137 : (_) == 'Y' ? 24 \ 00138 : (_) == 'Z' ? 25 \ 00139 : (_) == 'a' ? 26 \ 00140 : (_) == 'b' ? 27 \ 00141 : (_) == 'c' ? 28 \ 00142 : (_) == 'd' ? 29 \ 00143 : (_) == 'e' ? 30 \ 00144 : (_) == 'f' ? 31 \ 00145 : (_) == 'g' ? 32 \ 00146 : (_) == 'h' ? 33 \ 00147 : (_) == 'i' ? 34 \ 00148 : (_) == 'j' ? 35 \ 00149 : (_) == 'k' ? 36 \ 00150 : (_) == 'l' ? 37 \ 00151 : (_) == 'm' ? 38 \ 00152 : (_) == 'n' ? 39 \ 00153 : (_) == 'o' ? 40 \ 00154 : (_) == 'p' ? 41 \ 00155 : (_) == 'q' ? 42 \ 00156 : (_) == 'r' ? 43 \ 00157 : (_) == 's' ? 44 \ 00158 : (_) == 't' ? 45 \ 00159 : (_) == 'u' ? 46 \ 00160 : (_) == 'v' ? 47 \ 00161 : (_) == 'w' ? 48 \ 00162 : (_) == 'x' ? 49 \ 00163 : (_) == 'y' ? 50 \ 00164 : (_) == 'z' ? 51 \ 00165 : (_) == '0' ? 52 \ 00166 : (_) == '1' ? 53 \ 00167 : (_) == '2' ? 54 \ 00168 : (_) == '3' ? 55 \ 00169 : (_) == '4' ? 56 \ 00170 : (_) == '5' ? 57 \ 00171 : (_) == '6' ? 58 \ 00172 : (_) == '7' ? 59 \ 00173 : (_) == '8' ? 60 \ 00174 : (_) == '9' ? 61 \ 00175 : (_) == '+' ? 62 \ 00176 : (_) == '/' ? 63 \ 00177 : -1) 00178 00179 static const signed char b64[0x100] = { 00180 B64 (0), B64 (1), B64 (2), B64 (3), 00181 B64 (4), B64 (5), B64 (6), B64 (7), 00182 B64 (8), B64 (9), B64 (10), B64 (11), 00183 B64 (12), B64 (13), B64 (14), B64 (15), 00184 B64 (16), B64 (17), B64 (18), B64 (19), 00185 B64 (20), B64 (21), B64 (22), B64 (23), 00186 B64 (24), B64 (25), B64 (26), B64 (27), 00187 B64 (28), B64 (29), B64 (30), B64 (31), 00188 B64 (32), B64 (33), B64 (34), B64 (35), 00189 B64 (36), B64 (37), B64 (38), B64 (39), 00190 B64 (40), B64 (41), B64 (42), B64 (43), 00191 B64 (44), B64 (45), B64 (46), B64 (47), 00192 B64 (48), B64 (49), B64 (50), B64 (51), 00193 B64 (52), B64 (53), B64 (54), B64 (55), 00194 B64 (56), B64 (57), B64 (58), B64 (59), 00195 B64 (60), B64 (61), B64 (62), B64 (63), 00196 B64 (64), B64 (65), B64 (66), B64 (67), 00197 B64 (68), B64 (69), B64 (70), B64 (71), 00198 B64 (72), B64 (73), B64 (74), B64 (75), 00199 B64 (76), B64 (77), B64 (78), B64 (79), 00200 B64 (80), B64 (81), B64 (82), B64 (83), 00201 B64 (84), B64 (85), B64 (86), B64 (87), 00202 B64 (88), B64 (89), B64 (90), B64 (91), 00203 B64 (92), B64 (93), B64 (94), B64 (95), 00204 B64 (96), B64 (97), B64 (98), B64 (99), 00205 B64 (100), B64 (101), B64 (102), B64 (103), 00206 B64 (104), B64 (105), B64 (106), B64 (107), 00207 B64 (108), B64 (109), B64 (110), B64 (111), 00208 B64 (112), B64 (113), B64 (114), B64 (115), 00209 B64 (116), B64 (117), B64 (118), B64 (119), 00210 B64 (120), B64 (121), B64 (122), B64 (123), 00211 B64 (124), B64 (125), B64 (126), B64 (127), 00212 B64 (128), B64 (129), B64 (130), B64 (131), 00213 B64 (132), B64 (133), B64 (134), B64 (135), 00214 B64 (136), B64 (137), B64 (138), B64 (139), 00215 B64 (140), B64 (141), B64 (142), B64 (143), 00216 B64 (144), B64 (145), B64 (146), B64 (147), 00217 B64 (148), B64 (149), B64 (150), B64 (151), 00218 B64 (152), B64 (153), B64 (154), B64 (155), 00219 B64 (156), B64 (157), B64 (158), B64 (159), 00220 B64 (160), B64 (161), B64 (162), B64 (163), 00221 B64 (164), B64 (165), B64 (166), B64 (167), 00222 B64 (168), B64 (169), B64 (170), B64 (171), 00223 B64 (172), B64 (173), B64 (174), B64 (175), 00224 B64 (176), B64 (177), B64 (178), B64 (179), 00225 B64 (180), B64 (181), B64 (182), B64 (183), 00226 B64 (184), B64 (185), B64 (186), B64 (187), 00227 B64 (188), B64 (189), B64 (190), B64 (191), 00228 B64 (192), B64 (193), B64 (194), B64 (195), 00229 B64 (196), B64 (197), B64 (198), B64 (199), 00230 B64 (200), B64 (201), B64 (202), B64 (203), 00231 B64 (204), B64 (205), B64 (206), B64 (207), 00232 B64 (208), B64 (209), B64 (210), B64 (211), 00233 B64 (212), B64 (213), B64 (214), B64 (215), 00234 B64 (216), B64 (217), B64 (218), B64 (219), 00235 B64 (220), B64 (221), B64 (222), B64 (223), 00236 B64 (224), B64 (225), B64 (226), B64 (227), 00237 B64 (228), B64 (229), B64 (230), B64 (231), 00238 B64 (232), B64 (233), B64 (234), B64 (235), 00239 B64 (236), B64 (237), B64 (238), B64 (239), 00240 B64 (240), B64 (241), B64 (242), B64 (243), 00241 B64 (244), B64 (245), B64 (246), B64 (247), 00242 B64 (248), B64 (249), B64 (250), B64 (251), 00243 B64 (252), B64 (253), B64 (254), B64 (255) 00244 }; 00245 00246 /* Return true if CH is a character from the Base64 alphabet, and 00247 false otherwise. Note that '=' is padding and not considered to be 00248 part of the alphabet. */ 00249 bool isbase64 (char ch) 00250 { 00251 //return uchar_in_range(to_uchar (ch)); && (0 <= b64[to_uchar(ch)]); -- uchar_in_range is always true for a uchar 00252 return (0 <= b64[to_uchar(ch)]); 00253 } 00254 00255 /** 00256 Decode a Base64 string into a block of data. 00257 00258 @param dest A pointer to the block of data to write in. 00259 @param dest_size A pointer to the maximum number of bytes to write into dest. The number of bytes successfully written 00260 will be stored in this value upon return. 00261 @param src The base 64 string to decode. 00262 @param src_size The size of the base 64 string. 00263 @return True on successful decode, false on failure. 00264 00265 \par Example 00266 \code 00267 #define BUFF_SIZE 256 00268 char decode_buf[BUFF_SIZE]; 00269 int decode_size = BUFF_SIZE; 00270 bool result = Base64_Decode(decode_buf, &decode_size, "dGVzdA==", 8); 00271 // we now have "test" in decode_buf, and decode_size is set to 6 00272 \endcode 00273 */ 00274 bool Base64_Decode(char* dest, int* dest_size, const char* src, int src_size) 00275 { 00276 int out_remaining = *dest_size; 00277 00278 while(src_size >= 2) 00279 { 00280 if(!isbase64 (src[0]) || !isbase64 (src[1])) 00281 break; 00282 if(out_remaining) 00283 { 00284 *dest++ = ((b64[to_uchar (src[0])] << 2) | (b64[to_uchar (src[1])] >> 4)); 00285 out_remaining--; 00286 } 00287 if(src_size == 2) 00288 break; 00289 if(src[2] == '=') 00290 { 00291 if(src_size != 4) 00292 break; 00293 if(src[3] != '=') 00294 break; 00295 } 00296 else 00297 { 00298 if(!isbase64 (src[2])) 00299 break; 00300 if(out_remaining) 00301 { 00302 *dest++ = (((b64[to_uchar (src[1])] << 4) & 0xf0) | (b64[to_uchar (src[2])] >> 2)); 00303 out_remaining--; 00304 } 00305 if(src_size == 3) 00306 break; 00307 if(src[3] == '=') 00308 { 00309 if(src_size != 4) 00310 break; 00311 } 00312 else 00313 { 00314 if(!isbase64 (src[3])) 00315 break; 00316 if(out_remaining) 00317 { 00318 *dest++ = (((b64[to_uchar (src[2])] << 6) & 0xc0) | b64[to_uchar (src[3])]); 00319 out_remaining--; 00320 } 00321 } 00322 } 00323 src += 4; 00324 src_size -= 4; 00325 } 00326 *dest_size -= out_remaining; 00327 if(src_size != 0) 00328 return false; 00329 00330 return true; 00331 } 00332 00333 /** @} 00334 */ 00335 00336 00337 00338
The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.