diff options
-rw-r--r-- | camel/ChangeLog | 10 | ||||
-rw-r--r-- | camel/camel-mime-filter-basic.c | 24 | ||||
-rw-r--r-- | camel/camel-mime-filter-basic.h | 4 | ||||
-rw-r--r-- | camel/camel-mime-utils.c | 160 | ||||
-rw-r--r-- | camel/camel-mime-utils.h | 4 |
5 files changed, 199 insertions, 3 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index d6cf01ed49..afb97d6b39 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,13 @@ +2001-10-06 Jeffrey Stedfast <fejj@ximian.com> + + * camel-mime-filter-basic.c (filter): Implemented uuencoding and + decoding. + (complete): Implemented uuencoding and decoding. + + * camel-mime-utils.c (uuencode_close): New function to flush the + uu encoder. + (uuencode_step): New function to uuencode a block of data. + 2001-10-05 <NotZed@Ximian.com> * providers/imap/camel-imap-store.c (subscribe_folder): Use a diff --git a/camel/camel-mime-filter-basic.c b/camel/camel-mime-filter-basic.c index 056110695c..63db68f9d9 100644 --- a/camel/camel-mime-filter-basic.c +++ b/camel/camel-mime-filter-basic.c @@ -108,6 +108,13 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, newlen = quoted_encode_close(in, len, mf->outbuf, &f->state, &f->save); g_assert(newlen <= len*4+4); break; + case CAMEL_MIME_FILTER_BASIC_UU_ENC: + /* won't go to more than 2 * (x + 2) + 62 */ + camel_mime_filter_set_size (mf, (len + 2) * 2 + 62, FALSE); + newlen = uuencode_close (in, len, mf->outbuf, f->uubuf, &f->state, + &f->save, &f->uulen); + g_assert (newlen <= (len + 2) * 2 + 62); + break; case CAMEL_MIME_FILTER_BASIC_BASE64_DEC: /* output can't possibly exceed the input size */ camel_mime_filter_set_size(mf, len, FALSE); @@ -120,6 +127,11 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, newlen = quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save); g_assert(newlen <= len); break; + case CAMEL_MIME_FILTER_BASIC_UU_DEC: + /* output can't possibly exceed the input size */ + camel_mime_filter_set_size (mf, len, FALSE); + newlen = uudecode_step (in, len, mf->outbuf, &f->state, &f->save, &f->uulen); + break; default: g_warning("unknown type %d in CamelMimeFilterBasic", f->type); goto donothing; @@ -156,6 +168,11 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s newlen = quoted_encode_step(in, len, mf->outbuf, &f->state, &f->save); g_assert(newlen <= len*4+4); break; + case CAMEL_MIME_FILTER_BASIC_UU_ENC: + /* won't go to more than 2 * (x + 2) + 62 */ + camel_mime_filter_set_size (mf, (len + 2) * 2 + 62, FALSE); + newlen = uuencode_step (in, len, mf->outbuf, f->uubuf, &f->state, &f->save, &f->uulen); + g_assert (newlen <= (len + 2) * 2 + 62); case CAMEL_MIME_FILTER_BASIC_BASE64_DEC: /* output can't possibly exceed the input size */ camel_mime_filter_set_size(mf, len+3, FALSE); @@ -168,6 +185,11 @@ filter(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, s newlen = quoted_decode_step(in, len, mf->outbuf, &f->state, &f->save); g_assert(newlen <= len); break; + case CAMEL_MIME_FILTER_BASIC_UU_DEC: + /* output can't possibly exceed the input size */ + camel_mime_filter_set_size (mf, len, FALSE); + newlen = uudecode_step (in, len, mf->outbuf, &f->state, &f->save, &f->uulen); + break; default: g_warning("unknown type %d in CamelMimeFilterBasic", f->type); goto donothing; @@ -208,6 +230,8 @@ camel_mime_filter_basic_new_type(CamelMimeFilterBasicType type) case CAMEL_MIME_FILTER_BASIC_QP_ENC: case CAMEL_MIME_FILTER_BASIC_BASE64_DEC: case CAMEL_MIME_FILTER_BASIC_QP_DEC: + case CAMEL_MIME_FILTER_BASIC_UU_ENC: + case CAMEL_MIME_FILTER_BASIC_UU_DEC: new = camel_mime_filter_basic_new(); new->type = type; break; diff --git a/camel/camel-mime-filter-basic.h b/camel/camel-mime-filter-basic.h index f466f3a488..bf8088623b 100644 --- a/camel/camel-mime-filter-basic.h +++ b/camel/camel-mime-filter-basic.h @@ -34,6 +34,8 @@ typedef enum { CAMEL_MIME_FILTER_BASIC_BASE64_DEC, CAMEL_MIME_FILTER_BASIC_QP_ENC, CAMEL_MIME_FILTER_BASIC_QP_DEC, + CAMEL_MIME_FILTER_BASIC_UU_ENC, + CAMEL_MIME_FILTER_BASIC_UU_DEC, } CamelMimeFilterBasicType; struct _CamelMimeFilterBasic { @@ -43,8 +45,10 @@ struct _CamelMimeFilterBasic { CamelMimeFilterBasicType type; + unsigned char uubuf[60]; int state; int save; + char uulen; }; struct _CamelMimeFilterBasicClass { diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index d5ca9b436b..57d1b13ed4 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -76,6 +76,7 @@ int free_count = 0; #define d(x) #define d2(x) +#define CAMEL_UUENCODE_CHAR(c) ((c) ? (c) + ' ' : '`') #define CAMEL_UUDECODE_CHAR(c) (((c) - ' ') & 077) static char *base64_alphabet = @@ -490,19 +491,171 @@ base64_decode_simple (char *data, int len) (unsigned char *)data, &state, &save); } +/** + * uuencode_close: uuencode a chunk of data + * @in: input stream + * @len: input stream length + * @out: output stream + * @uubuf: temporary buffer of 60 bytes + * @state: holds the number of bits that are stored in @save + * @save: leftover bits that have not yet been encoded + * @uulen: holds the value of the length-char which is used to calculate + * how many more chars need to be decoded for that 'line' + * + * Returns the number of bytes encoded. Call this when finished + * encoding data with uuencode_step to flush off the last little + * bit. + **/ +int +uuencode_close (unsigned char *in, int len, unsigned char *out, unsigned char *uubuf, int *state, guint32 *save, char *uulen) +{ + register unsigned char *inptr, *outptr, *bufptr; + register guint32 saved; + int i; + + outptr = out; + + if (len > 0) + outptr += uuencode_step (in, len, out, uubuf, state, save, uulen); + + bufptr = uubuf + ((*uulen / 3) * 4); + saved = *save; + i = *state; + + if (i > 0) { + while (i < 3) { + saved <<= 8 | 0; + i++; + } + + if (i == 3) { + /* convert 3 normal bytes into 4 uuencoded bytes */ + unsigned char b0, b1, b2; + + b0 = saved >> 16; + b1 = saved >> 8 & 0xff; + b2 = saved & 0xff; + + *bufptr++ = CAMEL_UUENCODE_CHAR ((b0 >> 2) & 0x3f); + *bufptr++ = CAMEL_UUENCODE_CHAR (((b0 << 4) | ((b1 >> 4) & 0xf)) & 0x3f); + *bufptr++ = CAMEL_UUENCODE_CHAR (((b1 << 2) | ((b2 >> 6) & 0x3)) & 0x3f); + *bufptr++ = CAMEL_UUENCODE_CHAR (b2 & 0x3f); + } + } + + if (*uulen || *state) { + int cplen = (((*uulen + (*state ? 3 : 0)) / 3) * 4); + + *outptr++ = CAMEL_UUENCODE_CHAR (*uulen + *state); + memcpy (outptr, uubuf, cplen); + outptr += cplen; + *outptr++ = '\n'; + *uulen = 0; + } + + *outptr++ = CAMEL_UUENCODE_CHAR (*uulen); + *outptr++ = '\n'; + + *save = 0; + *state = 0; + + return outptr - out; +} + + +/** + * uuencode_step: uuencode a chunk of data + * @in: input stream + * @len: input stream length + * @out: output stream + * @uubuf: temporary buffer of 60 bytes + * @state: holds the number of bits that are stored in @save + * @save: leftover bits that have not yet been encoded + * @uulen: holds the value of the length-char which is used to calculate + * how many more chars need to be decoded for that 'line' + * + * Returns the number of bytes encoded. Performs an 'encode step', + * only encodes blocks of 45 characters to the output at a time, saves + * left-over state in @uubuf, @state and @save (initialize to 0 on first + * invocation). + **/ +int +uuencode_step (unsigned char *in, int len, unsigned char *out, unsigned char *uubuf, int *state, guint32 *save, char *uulen) +{ + register unsigned char *inptr, *outptr, *bufptr; + unsigned char *inend, ch; + register guint32 saved; + int i; + + if (*uulen <= 0) + *uulen = 0; + + inptr = in; + inend = in + len; + + outptr = out; + + bufptr = uubuf + ((*uulen / 3) * 4); + + saved = *save; + i = *state; + + while (inptr < inend) { + while (*uulen < 45 && inptr < inend) { + while (i < 3 && inptr < inend) { + saved = (saved << 8) | *inptr++; + i++; + } + + if (i == 3) { + /* convert 3 normal bytes into 4 uuencoded bytes */ + unsigned char b0, b1, b2; + + b0 = saved >> 16; + b1 = saved >> 8 & 0xff; + b2 = saved & 0xff; + + *bufptr++ = CAMEL_UUENCODE_CHAR ((b0 >> 2) & 0x3f); + *bufptr++ = CAMEL_UUENCODE_CHAR (((b0 << 4) | ((b1 >> 4) & 0xf)) & 0x3f); + *bufptr++ = CAMEL_UUENCODE_CHAR (((b1 << 2) | ((b2 >> 6) & 0x3)) & 0x3f); + *bufptr++ = CAMEL_UUENCODE_CHAR (b2 & 0x3f); + + i = 0; + saved = 0; + *uulen += 3; + } + } + + if (*uulen >= 45) { + *outptr++ = CAMEL_UUENCODE_CHAR (*uulen); + memcpy (outptr, uubuf, ((*uulen / 3) * 4)); + outptr += ((*uulen / 3) * 4); + *outptr++ = '\n'; + *uulen = 0; + bufptr = uubuf; + } + } + + *save = saved; + *state = i; + + return outptr - out; +} + /** * uudecode_step: uudecode a chunk of data * @in: input stream - * @len: max length of data to decode ( normally strlen(in) ??) + * @inlen: max length of data to decode ( normally strlen(in) ??) * @out: output stream * @state: holds the number of bits that are stored in @save * @save: leftover bits that have not yet been decoded * @uulen: holds the value of the length-char which is used to calculate * how many more chars need to be decoded for that 'line' * - * uudecodes a chunk of data. Assumes the "begin <mode> <file name>" line - * has been stripped off. + * Returns the number of bytes decoded. Performs a 'decode step' on + * a chunk of uuencoded data. Assumes the "begin <mode> <file name>" + * line has been stripped off. **/ int uudecode_step (unsigned char *in, int len, unsigned char *out, int *state, guint32 *save, char *uulen) @@ -579,6 +732,7 @@ uudecode_step (unsigned char *in, int len, unsigned char *out, int *state, guint return outptr - out; } + /* complete qp encoding */ int quoted_encode_close(unsigned char *in, int len, unsigned char *out, int *state, int *save) diff --git a/camel/camel-mime-utils.h b/camel/camel-mime-utils.h index 899fffbae5..d426668cb7 100644 --- a/camel/camel-mime-utils.h +++ b/camel/camel-mime-utils.h @@ -189,6 +189,10 @@ int base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigne int base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned char *out, int *state, int *save); int uudecode_step (unsigned char *in, int len, unsigned char *out, int *state, guint32 *save, char *uulen); +int uuencode_step (unsigned char *in, int len, unsigned char *out, unsigned char *uubuf, int *state, + guint32 *save, char *uulen); +int uuencode_close (unsigned char *in, int len, unsigned char *out, unsigned char *uubuf, int *state, + guint32 *save, char *uulen); int quoted_decode_step(unsigned char *in, int len, unsigned char *out, int *savestate, int *saveme); |