Changeset 3232 in MondoRescue for branches/3.2/mindi-busybox/libbb/uuencode.c


Ignore:
Timestamp:
Jan 1, 2014, 12:47:38 AM (10 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.21.1
File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/3.2/mindi-busybox/libbb/uuencode.c

    r2725 r3232  
    1111
    1212/* Conversion table.  for base 64 */
    13 const char bb_uuenc_tbl_base64[65 + 2] ALIGN1 = {
     13const char bb_uuenc_tbl_base64[65 + 1] ALIGN1 = {
    1414    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
    1515    'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
     
    2121    '4', '5', '6', '7', '8', '9', '+', '/',
    2222    '=' /* termination character */,
    23     '\n', '\0' /* needed for uudecode.c */
     23    '\0' /* needed for uudecode.c only */
    2424};
    2525
     
    7474
    7575/*
     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 */
     82const 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/*
    76158 * Decode base64 encoded stream.
    77159 * Can stop on EOF, specified char, or on uuencode-style "====" line:
     
    84166#define uu_style_end (flags & BASE64_FLAG_UU_STOP)
    85167
    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;
    87179
    88180    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:
    102196             */
    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    }
    145224}
Note: See TracChangeset for help on using the changeset viewer.