Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/libbb/uuencode.c
- Timestamp:
- Jan 1, 2014, 12:47:38 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/3.2/mindi-busybox/libbb/uuencode.c
r2725 r3232 11 11 12 12 /* Conversion table. for base 64 */ 13 const char bb_uuenc_tbl_base64[65 + 2] ALIGN1 = {13 const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = { 14 14 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 15 15 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', … … 21 21 '4', '5', '6', '7', '8', '9', '+', '/', 22 22 '=' /* termination character */, 23 '\ n', '\0' /* needed for uudecode.c*/23 '\0' /* needed for uudecode.c only */ 24 24 }; 25 25 … … 74 74 75 75 /* 76 * Decode base64 encoded string. Stops on '\0'. 77 * 78 * Returns: pointer to the undecoded part of source. 79 * If points to '\0', then the source was fully decoded. 80 * (*pp_dst): advanced past the last written byte. 81 */ 82 const char* FAST_FUNC decode_base64(char **pp_dst, const char *src) 83 { 84 char *dst = *pp_dst; 85 const char *src_tail; 86 87 while (1) { 88 unsigned char six_bit[4]; 89 int count = 0; 90 91 /* Fetch up to four 6-bit values */ 92 src_tail = src; 93 while (count < 4) { 94 char *table_ptr; 95 int ch; 96 97 /* Get next _valid_ character. 98 * bb_uuenc_tbl_base64[] contains this string: 99 * 0 1 2 3 4 5 6 100 * 01234567890123456789012345678901234567890123456789012345678901234 101 * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" 102 */ 103 do { 104 ch = *src; 105 if (ch == '\0') { 106 if (count == 0) { 107 /* Example: 108 * If we decode "QUJD <NUL>", we want 109 * to return ptr to NUL, not to ' ', 110 * because we did fully decode 111 * the string (to "ABC"). 112 */ 113 src_tail = src; 114 } 115 goto ret; 116 } 117 src++; 118 table_ptr = strchr(bb_uuenc_tbl_base64, ch); 119 //TODO: add BASE64_FLAG_foo to die on bad char? 120 } while (!table_ptr); 121 122 /* Convert encoded character to decimal */ 123 ch = table_ptr - bb_uuenc_tbl_base64; 124 125 /* ch is 64 if char was '=', otherwise 0..63 */ 126 if (ch == 64) 127 break; 128 six_bit[count] = ch; 129 count++; 130 } 131 132 /* Transform 6-bit values to 8-bit ones. 133 * count can be < 4 when we decode the tail: 134 * "eQ==" -> "y", not "y NUL NUL". 135 * Note that (count > 1) is always true, 136 * "x===" encoding is not valid: 137 * even a single zero byte encodes as "AA==". 138 * However, with current logic we come here with count == 1 139 * when we decode "==" tail. 140 */ 141 if (count > 1) 142 *dst++ = six_bit[0] << 2 | six_bit[1] >> 4; 143 if (count > 2) 144 *dst++ = six_bit[1] << 4 | six_bit[2] >> 2; 145 if (count > 3) 146 *dst++ = six_bit[2] << 6 | six_bit[3]; 147 /* Note that if we decode "AA==" and ate first '=', 148 * we just decoded one char (count == 2) and now we'll 149 * do the loop once more to decode second '='. 150 */ 151 } /* while (1) */ 152 ret: 153 *pp_dst = dst; 154 return src_tail; 155 } 156 157 /* 76 158 * Decode base64 encoded stream. 77 159 * Can stop on EOF, specified char, or on uuencode-style "====" line: … … 84 166 #define uu_style_end (flags & BASE64_FLAG_UU_STOP) 85 167 86 int term_count = 0; 168 /* uuencoded files have 61 byte lines. Use 64 byte buffer 169 * to process line at a time. 170 */ 171 enum { BUFFER_SIZE = 64 }; 172 173 char in_buf[BUFFER_SIZE + 2]; 174 char out_buf[BUFFER_SIZE / 4 * 3 + 2]; 175 char *out_tail; 176 const char *in_tail; 177 int term_seen = 0; 178 int in_count = 0; 87 179 88 180 while (1) { 89 unsigned char translated[4]; 90 int count = 0; 91 92 /* Process one group of 4 chars */ 93 while (count < 4) { 94 char *table_ptr; 95 int ch; 96 97 /* Get next _valid_ character. 98 * bb_uuenc_tbl_base64[] contains this string: 99 * 0 1 2 3 4 5 6 100 * 012345678901234567890123456789012345678901234567890123456789012345 101 * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" 181 while (in_count < BUFFER_SIZE) { 182 int ch = fgetc(src_stream); 183 if (ch == exit_char) { 184 if (in_count == 0) 185 return; 186 term_seen = 1; 187 break; 188 } 189 if (ch == EOF) { 190 term_seen = 1; 191 break; 192 } 193 /* Prevent "====" line to be split: stop if we see '\n'. 194 * We can also skip other whitespace and skirt the problem 195 * of files with NULs by stopping on any control char or space: 102 196 */ 103 do { 104 ch = fgetc(src_stream); 105 if (ch == exit_char && count == 0) 106 return; 107 if (ch == EOF) 108 bb_error_msg_and_die("truncated base64 input"); 109 table_ptr = strchr(bb_uuenc_tbl_base64, ch); 110 //TODO: add BASE64_FLAG_foo to die on bad char? 111 //Note that then we may need to still allow '\r' (for mail processing) 112 } while (!table_ptr); 113 114 /* Convert encoded character to decimal */ 115 ch = table_ptr - bb_uuenc_tbl_base64; 116 117 if (ch == 65 /* '\n' */) { 118 /* Terminating "====" line? */ 119 if (uu_style_end && term_count == 4) 120 return; /* yes */ 121 term_count = 0; 122 continue; 123 } 124 /* ch is 64 if char was '=', otherwise 0..63 */ 125 translated[count] = ch & 63; /* 64 -> 0 */ 126 if (ch == 64) { 127 term_count++; 128 break; 129 } 130 count++; 131 term_count = 0; 132 } 133 134 /* Merge 6 bit chars to 8 bit. 135 * count can be < 4 when we decode the tail: 136 * "eQ==" -> "y", not "y NUL NUL" 137 */ 138 if (count > 1) 139 fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); 140 if (count > 2) 141 fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); 142 if (count > 3) 143 fputc(translated[2] << 6 | translated[3], dst_stream); 144 } /* while (1) */ 197 if (ch <= ' ') 198 break; 199 in_buf[in_count++] = ch; 200 } 201 in_buf[in_count] = '\0'; 202 203 /* Did we encounter "====" line? */ 204 if (uu_style_end && strcmp(in_buf, "====") == 0) 205 return; 206 207 out_tail = out_buf; 208 in_tail = decode_base64(&out_tail, in_buf); 209 210 fwrite(out_buf, (out_tail - out_buf), 1, dst_stream); 211 212 if (term_seen) { 213 /* Did we consume ALL characters? */ 214 if (*in_tail == '\0') 215 return; 216 /* No */ 217 bb_error_msg_and_die("truncated base64 input"); 218 } 219 220 /* It was partial decode */ 221 in_count = strlen(in_tail); 222 memmove(in_buf, in_tail, in_count); 223 } 145 224 }
Note:
See TracChangeset
for help on using the changeset viewer.