New base64 decoder (can handle unusual line lengths).
authorSergey Vlasov <vsu@users.sourceforge.net>
Sat, 16 Jun 2001 09:43:54 +0000 (09:43 +0000)
committerSergey Vlasov <vsu@users.sourceforge.net>
Sat, 16 Jun 2001 09:43:54 +0000 (09:43 +0000)
ChangeLog.claws
src/base64.c
src/base64.h
src/procmime.c

index d3f4dc0..568a225 100644 (file)
@@ -1,3 +1,11 @@
+2001-06-16 [sergey]
+
+       * src/base64.c, src/base64.h (Base64Decoder, base64_decoder_new,
+       base64_decoder_free, base64_decoder_decode): new object and
+       functions for decoding base64 streams.
+       * src/procmime.c (procmime_decode_content): modified to use the
+       new base64 decoder.
+
 2001-06-15 [paul]
 
         0.4.99claws10
index 3cd3bcb..f0ef206 100644 (file)
@@ -9,7 +9,14 @@
  *
  * Modified by Hiroyuki Yamamoto <hiro-y@kcn.ne.jp>
  */
+
+#include "defs.h"
+
 #include <ctype.h>
+#include <string.h>
+#include <glib.h>
+
+#include "base64.h"
 
 static const char base64digits[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -95,4 +102,75 @@ int from64tobits(char *out, const char *in)
     return len;
 }
 
+struct _Base64Decoder
+{
+       int buf_len;
+       unsigned char buf[4];
+};
+
+Base64Decoder *
+base64_decoder_new (void)
+{
+       Base64Decoder *decoder;
+
+       decoder = g_new0 (Base64Decoder, 1);
+       return decoder;
+}
+
+void
+base64_decoder_free (Base64Decoder *decoder)
+{
+       g_free (decoder);
+}
+
+int
+base64_decoder_decode (Base64Decoder *decoder,
+                      const char    *in, 
+                      char          *out)
+{
+       int len = 0;
+       int buf_len;
+       unsigned char buf[4];
+
+       g_return_val_if_fail (decoder != NULL, -1);
+       g_return_val_if_fail (in != NULL, -1);
+       g_return_val_if_fail (out != NULL, -1);
+
+       buf_len = decoder->buf_len;
+       memcpy (buf, decoder->buf, sizeof(buf));
+       while (1) {
+               while (buf_len < 4) {
+                       int c = *(unsigned char *)in++;
+                       if (c == '\0') break;
+                       if (c == '\r' || c == '\n') continue;
+                       if (c != '=' && DECODE64(c) == BAD)
+                               return -1;
+                       buf[buf_len++] = c;
+               }
+               if (buf_len < 4 || buf[0] == '=' || buf[1] == '=') {
+                       decoder->buf_len = buf_len;
+                       memcpy (decoder->buf, buf, sizeof(buf));
+                       return len;
+               }
+               *out++ = ((DECODE64(buf[0]) << 2)
+                         | ((DECODE64(buf[1]) >> 4) & 0x03));
+               ++len;
+               if (buf[2] != '=') {
+                       *out++ = (((DECODE64(buf[1]) << 4) & 0xf0)
+                                 | (DECODE64(buf[2]) >> 2));
+                       ++len;
+                       if (buf[3] != '=') {
+                               *out++ = (((DECODE64(buf[2]) << 6) & 0xc0)
+                                         | DECODE64(buf[3]));
+                               ++len;
+                       }
+               }
+               buf_len = 0;
+               if (buf[2] == '=' || buf[3] == '=') {
+                       decoder->buf_len = 0;
+                       return len;
+               }
+       }
+}
+
 /* base64.c ends here */
index 24e16d7..327dfbf 100644 (file)
@@ -1,6 +1,14 @@
 #ifndef __BASE64_H__
 #define __BASE64_H__
 
+typedef struct _Base64Decoder Base64Decoder;
+
+Base64Decoder * base64_decoder_new     (void);
+void           base64_decoder_free     (Base64Decoder *decoder);
+int            base64_decoder_decode   (Base64Decoder *decoder,
+                                        const char    *in, 
+                                        char          *out);
+
 void to64frombits(unsigned char *, const unsigned char *, int);
 int from64tobits(char *, const char *);
 
index abc52c2..6d03f22 100644 (file)
@@ -528,17 +528,20 @@ FILE *procmime_decode_content(FILE *outfp, FILE *infp, MimeInfo *mimeinfo)
        } else if (mimeinfo->encoding_type == ENC_BASE64) {
                gchar outbuf[BUFFSIZE];
                gint len;
+               Base64Decoder *decoder;
 
+               decoder = base64_decoder_new();
                while (fgets(buf, sizeof(buf), infp) != NULL &&
                       (!boundary ||
                        !IS_BOUNDARY(buf, boundary, boundary_len))) {
-                       len = from64tobits(outbuf, buf);
+                       len = base64_decoder_decode(decoder, buf, outbuf);
                        if (len < 0) {
                                g_warning("Bad BASE64 content\n");
                                break;
                        }
                        fwrite(outbuf, sizeof(gchar), len, outfp);
                }
+               base64_decoder_free(decoder);
        } else if (mimeinfo->encoding_type == ENC_X_UUENCODE) {
                gchar outbuf[BUFFSIZE];
                gint len;