aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-mime-utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-mime-utils.c')
-rw-r--r--camel/camel-mime-utils.c160
1 files changed, 157 insertions, 3 deletions
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)