aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog10
-rw-r--r--camel/camel-mime-filter-basic.c24
-rw-r--r--camel/camel-mime-filter-basic.h4
-rw-r--r--camel/camel-mime-utils.c160
-rw-r--r--camel/camel-mime-utils.h4
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);