libbb: merge mail and uudecode's base64 decoders
No binary (build failed)
—
(log yok)
| @@ -13,7 +13,7 @@ | |
| #include "libbb.h" | |
| #if ENABLE_UUDECODE | |
| - | static void read_stduu(FILE *src_stream, FILE *dst_stream) |
| + | static void FAST_FUNC read_stduu(FILE *src_stream, FILE *dst_stream, int flags UNUSED_PARAM) |
| { | |
| char *line; | |
| @@ -75,71 +75,6 @@ static void read_stduu(FILE *src_stream, FILE *dst_stream) | |
| } | |
| #endif | |
| - | static void read_base64(FILE *src_stream, FILE *dst_stream) |
| - | { |
| - | int term_count = 0; |
| - | |
| - | while (1) { |
| - | unsigned char translated[4]; |
| - | int count = 0; |
| - | |
| - | /* Process one group of 4 chars */ |
| - | while (count < 4) { |
| - | char *table_ptr; |
| - | int ch; |
| - | |
| - | /* Get next _valid_ character. |
| - | * bb_uuenc_tbl_base64[] contains this string: |
| - | * 0 1 2 3 4 5 6 |
| - | * 012345678901234567890123456789012345678901234567890123456789012345 |
| - | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" |
| - | */ |
| - | do { |
| - | ch = fgetc(src_stream); |
| - | if (ch == EOF) { |
| - | if (ENABLE_BASE64 |
| - | && (!ENABLE_UUDECODE || applet_name[0] == 'b') |
| - | && count == 0 |
| - | ) { |
| - | return; |
| - | } |
| - | bb_error_msg_and_die("short file"); |
| - | } |
| - | table_ptr = strchr(bb_uuenc_tbl_base64, ch); |
| - | } while (!table_ptr); |
| - | |
| - | /* Convert encoded character to decimal */ |
| - | ch = table_ptr - bb_uuenc_tbl_base64; |
| - | |
| - | if (ch == 65 /* '\n' */) { |
| - | /* Terminating "====" line? */ |
| - | if (term_count == 4) |
| - | return; /* yes */ |
| - | term_count = 0; |
| - | continue; |
| - | } |
| - | /* ch is 64 is char was '=', otherwise 0..63 */ |
| - | translated[count] = ch & 63; /* 64 -> 0 */ |
| - | if (ch == 64) { |
| - | term_count++; |
| - | break; |
| - | } |
| - | count++; |
| - | } |
| - | |
| - | /* Merge 6 bit chars to 8 bit. |
| - | * count can be < 4 when we decode the tail: |
| - | * "eQ==" -> "y", not "y NUL NUL" |
| - | */ |
| - | if (count > 1) |
| - | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); |
| - | if (count > 2) |
| - | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); |
| - | if (count > 3) |
| - | fputc(translated[2] << 6 | translated[3], dst_stream); |
| - | } /* while (1) */ |
| - | } |
| - | |
| #if ENABLE_UUDECODE | |
| int uudecode_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int uudecode_main(int argc UNUSED_PARAM, char **argv) | |
| @@ -158,7 +93,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |
| /* Search for the start of the encoding */ | |
| while ((line = xmalloc_fgetline(src_stream)) != NULL) { | |
| - | void (*decode_fn_ptr)(FILE *src, FILE *dst); |
| + | void FAST_FUNC (*decode_fn_ptr)(FILE *src, FILE *dst, int flags); |
| char *line_ptr; | |
| FILE *dst_stream; | |
| int mode; | |
| @@ -189,7 +124,7 @@ int uudecode_main(int argc UNUSED_PARAM, char **argv) | |
| fchmod(fileno(dst_stream), mode & (S_IRWXU | S_IRWXG | S_IRWXO)); | |
| } | |
| free(line); | |
| - | decode_fn_ptr(src_stream, dst_stream); |
| + | decode_fn_ptr(src_stream, dst_stream, /*flags:*/ BASE64_FLAG_UU_STOP + BASE64_FLAG_NO_STOP_CHAR); |
| /* fclose_if_not_stdin(src_stream); - redundant */ | |
| return EXIT_SUCCESS; | |
| } | |
| @@ -231,7 +166,7 @@ int base64_main(int argc UNUSED_PARAM, char **argv) | |
| *--argv = (char*)"-"; | |
| src_stream = xfopen_stdin(argv[0]); | |
| if (opts) { | |
| - | read_base64(src_stream, stdout); |
| + | read_base64(src_stream, stdout, /*flags:*/ (char)EOF); |
| } else { | |
| enum { | |
| SRC_BUF_SIZE = 76/4*3, /* This *MUST* be a multiple of 3 */ | |
| @@ -1505,6 +1505,12 @@ unsigned get_cpu_count(void) FAST_FUNC; | |
| extern const char bb_uuenc_tbl_base64[]; | |
| extern const char bb_uuenc_tbl_std[]; | |
| void bb_uuencode(char *store, const void *s, int length, const char *tbl) FAST_FUNC; | |
| + | enum { |
| + | BASE64_FLAG_UU_STOP = 0x100, |
| + | /* Sign-extends to a value which never matches fgetc result: */ |
| + | BASE64_FLAG_NO_STOP_CHAR = 0x80, |
| + | }; |
| + | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags); |
| typedef struct sha1_ctx_t { | |
| uint32_t hash[8]; /* 5, +3 elements for sha256 */ | |
| @@ -0,0 +1,78 @@ | |
| + | /* vi: set sw=4 ts=4: */ |
| + | /* |
| + | * Utility routines. |
| + | * |
| + | * Copyright 2003, Glenn McGrath |
| + | * Copyright 2010, Denys Vlasenko |
| + | * |
| + | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| + | */ |
| + | #include "libbb.h" |
| + | |
| + | //kbuild:lib-y += base64.o |
| + | |
| + | void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags) |
| + | { |
| + | /* Note that EOF _can_ be passed as exit_char too */ |
| + | #define exit_char ((int)(signed char)flags) |
| + | #define uu_style_end (flags & BASE64_FLAG_UUEND) |
| + | |
| + | int term_count = 0; |
| + | |
| + | while (1) { |
| + | unsigned char translated[4]; |
| + | int count = 0; |
| + | |
| + | /* Process one group of 4 chars */ |
| + | while (count < 4) { |
| + | char *table_ptr; |
| + | int ch; |
| + | |
| + | /* Get next _valid_ character. |
| + | * bb_uuenc_tbl_base64[] contains this string: |
| + | * 0 1 2 3 4 5 6 |
| + | * 012345678901234567890123456789012345678901234567890123456789012345 |
| + | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" |
| + | */ |
| + | do { |
| + | ch = fgetc(src_stream); |
| + | if (ch == exit_char && count == 0) |
| + | return; |
| + | if (ch == EOF) |
| + | bb_error_msg_and_die("truncated base64 input"); |
| + | table_ptr = strchr(bb_uuenc_tbl_base64, ch); |
| + | //TODO: add BASE64_FLAG_foo to die on bad char? |
| + | //Note that then we may need to still allow '\r' (for mail processing) |
| + | } while (!table_ptr); |
| + | |
| + | /* Convert encoded character to decimal */ |
| + | ch = table_ptr - bb_uuenc_tbl_base64; |
| + | |
| + | if (ch == 65 /* '\n' */) { |
| + | /* Terminating "====" line? */ |
| + | if (uu_style_end && term_count == 4) |
| + | return; /* yes */ |
| + | continue; |
| + | } |
| + | /* ch is 64 if char was '=', otherwise 0..63 */ |
| + | translated[count] = ch & 63; /* 64 -> 0 */ |
| + | if (ch == 64) { |
| + | term_count++; |
| + | break; |
| + | } |
| + | term_count = 0; |
| + | count++; |
| + | } |
| + | |
| + | /* Merge 6 bit chars to 8 bit. |
| + | * count can be < 4 when we decode the tail: |
| + | * "eQ==" -> "y", not "y NUL NUL" |
| + | */ |
| + | if (count > 1) |
| + | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); |
| + | if (count > 2) |
| + | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); |
| + | if (count > 3) |
| + | fputc(translated[2] << 6 | translated[3], dst_stream); |
| + | } /* while (1) */ |
| + | } |
| @@ -161,73 +161,6 @@ void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol) | |
| #undef src_buf | |
| } | |
| - | void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream) |
| - | { |
| - | int term_count = 1; |
| - | |
| - | while (1) { |
| - | char translated[4]; |
| - | int count = 0; |
| - | |
| - | while (count < 4) { |
| - | char *table_ptr; |
| - | int ch; |
| - | |
| - | /* Get next _valid_ character. |
| - | * global vector bb_uuenc_tbl_base64[] contains this string: |
| - | * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n" |
| - | */ |
| - | do { |
| - | ch = fgetc(src_stream); |
| - | if (ch == EOF) { |
| - | bb_error_msg_and_die(bb_msg_read_error); |
| - | } |
| - | // - means end of MIME section |
| - | if ('-' == ch) { |
| - | // push it back |
| - | ungetc(ch, src_stream); |
| - | return; |
| - | } |
| - | table_ptr = strchr(bb_uuenc_tbl_base64, ch); |
| - | } while (table_ptr == NULL); |
| - | |
| - | /* Convert encoded character to decimal */ |
| - | ch = table_ptr - bb_uuenc_tbl_base64; |
| - | |
| - | if (*table_ptr == '=') { |
| - | if (term_count == 0) { |
| - | translated[count] = '\0'; |
| - | break; |
| - | } |
| - | term_count++; |
| - | } else if (*table_ptr == '\n') { |
| - | /* Check for terminating line */ |
| - | if (term_count == 5) { |
| - | return; |
| - | } |
| - | term_count = 1; |
| - | continue; |
| - | } else { |
| - | translated[count] = ch; |
| - | count++; |
| - | term_count = 0; |
| - | } |
| - | } |
| - | |
| - | /* Merge 6 bit chars to 8 bit */ |
| - | if (count > 1) { |
| - | fputc(translated[0] << 2 | translated[1] >> 4, dst_stream); |
| - | } |
| - | if (count > 2) { |
| - | fputc(translated[1] << 4 | translated[2] >> 2, dst_stream); |
| - | } |
| - | if (count > 3) { |
| - | fputc(translated[2] << 6 | translated[3], dst_stream); |
| - | } |
| - | } |
| - | } |
| - | |
| - | |
| /* | |
| * get username and password from a file descriptor | |
| */ | |
| @@ -32,4 +32,3 @@ void FAST_FUNC get_cred_or_die(int fd); | |
| const FAST_FUNC char *command(const char *fmt, const char *param); | |
| void FAST_FUNC encode_base64(char *fname, const char *text, const char *eol); | |
| - | void FAST_FUNC decode_base64(FILE *src_stream, FILE *dst_stream); |
| @@ -225,7 +225,7 @@ static int parse(const char *boundary, char **argv) | |
| // prepare unique string pattern | |
| uniq = xasprintf("%%llu.%u.%s", (unsigned)getpid(), safe_gethostname()); | |
| - | //bb_info_msg("PARSE[%s]", terminator); |
| + | //bb_info_msg("PARSE[%s]", uniq); |
| while ((line = xmalloc_fgets_str(stdin, "\r\n\r\n")) != NULL) { | |
| @@ -306,7 +306,7 @@ static int parse(const char *boundary, char **argv) | |
| // dump to fp | |
| if (0 == strcasecmp(encoding, "base64")) { | |
| - | decode_base64(stdin, fp); |
| + | read_base64(stdin, fp, '-'); |
| } else if (0 != strcasecmp(encoding, "7bit") | |
| && 0 != strcasecmp(encoding, "8bit") | |
| ) { | |