]> code.citadel.org Git - citadel.git/blobdiff - webcit/mime_parser.c
* Header file adjustments to make it work on FreeBSD
[citadel.git] / webcit / mime_parser.c
index 9579d5cb858e4016eb962d1c47e0d1e08c29db95..7067bb1a8d2d684ee470260cda225e7629d582b3 100644 (file)
@@ -3,26 +3,42 @@
  *
  * This is the MIME parser for Citadel.  Sometimes it actually works.
  *
- * Copyright (c) 1998-2001 by Art Cancro
+ * Copyright (c) 1998-2003 by Art Cancro
  * This code is distributed under the terms of the GNU General Public License.
  *
  */
 
-#ifdef DLL_EXPORT
-#define IN_LIBCIT
-#endif
-
+#include <ctype.h>
 #include <stdlib.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <stdio.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
 #include <signal.h>
 #include <sys/types.h>
-#include <ctype.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
 #include <string.h>
-#include <sys/stat.h>
+#include <pwd.h>
 #include <errno.h>
-
+#include <stdarg.h>
+#include <pthread.h>
+#include <signal.h>
 #include "webcit.h"
+#include "webserver.h"
+
 #include "mime_parser.h"
 
 
@@ -62,7 +78,7 @@ char *fixed_partnum(char *supplied_partnum) {
 /*
  * Convert "quoted-printable" to binary.  Returns number of bytes decoded.
  */
-int decode_quoted_printable(char *decoded, char *encoded, int sourcelen) {
+int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen) {
        char buf[SIZ];
        int buf_length = 0;
        int soft_line_break = 0;
@@ -207,7 +223,7 @@ void mime_decode(char *partnum,
                bytes_decoded = CtdlDecodeBase64(decoded, part_start, length);
        }
        else if (!strcasecmp(encoding, "quoted-printable")) {
-               bytes_decoded = decode_quoted_printable(decoded,
+               bytes_decoded = CtdlDecodeQuotedPrintable(decoded,
                                                        part_start, length);
        }
 
@@ -274,7 +290,9 @@ void the_mime_parser(char *partnum,
        size_t content_length;
        char *encoding;
        char *disposition;
-       char *name;
+       char *name = NULL;
+       char *content_type_name;
+       char *content_disposition_name;
        char *filename;
        int is_multipart;
        int part_seq = 0;
@@ -303,8 +321,11 @@ void the_mime_parser(char *partnum,
        encoding = mallok(SIZ);
        memset(encoding, 0, SIZ);
 
-       name = mallok(SIZ);
-       memset(name, 0, SIZ);
+       content_type_name = mallok(SIZ);
+       memset(content_type_name, 0, SIZ);
+
+       content_disposition_name = mallok(SIZ);
+       memset(content_disposition_name, 0, SIZ);
 
        filename = mallok(SIZ);
        memset(filename, 0, SIZ);
@@ -331,7 +352,7 @@ void the_mime_parser(char *partnum,
                if (!isspace(buf[0])) {
                        if (!strncasecmp(header, "Content-type: ", 14)) {
                                strcpy(content_type, &header[14]);
-                               extract_key(name, content_type, "name");
+                               extract_key(content_type_name, content_type, "name");
                                /* Deal with weird headers */
                                if (strchr(content_type, ' '))
                                        *(strchr(content_type, ' ')) = '\0';
@@ -340,6 +361,7 @@ void the_mime_parser(char *partnum,
                        }
                        if (!strncasecmp(header, "Content-Disposition: ", 21)) {
                                strcpy(disposition, &header[21]);
+                               extract_key(content_disposition_name, disposition, "name");
                                extract_key(filename, disposition, "filename");
                        }
                        if (!strncasecmp(header, "Content-length: ", 16)) {
@@ -413,7 +435,16 @@ void the_mime_parser(char *partnum,
                                part_end = ptr;
                                ++ptr;
                        }
-               } while ( (strcasecmp(ptr, endary)) && (ptr <= content_end) );
+                       /* If we pass out of scope in the MIME multipart (by
+                        * hitting the end boundary), force the pointer out
+                        * of scope so this loop ends.
+                        */
+                       if (ptr < content_end) {
+                               if (!strcasecmp(ptr, endary)) {
+                                       ptr = content_end++;
+                               }
+                       }
+               } while (ptr <= content_end);
                if (PostMultiPartCallBack != NULL) {
                        PostMultiPartCallBack("", "", partnum, "", NULL,
                                content_type, 0, encoding, userdata);
@@ -430,11 +461,25 @@ void the_mime_parser(char *partnum,
                        ++length;
                }
                part_end = content_end;
+               /* fix an off-by-one error */
+               --part_end;
+               --length;
                
                /* Truncate if the header told us to */
                if ( (content_length > 0) && (length > content_length) ) {
                        length = content_length;
                }
+
+               /* Sometimes the "name" field is tacked on to Content-type,
+                * and sometimes it's tacked on to Content-disposition.  Use
+                * whichever one we have.
+                */
+               if (strlen(content_disposition_name) > strlen(content_type_name)) {
+                       name = content_disposition_name;
+               }
+               else {
+                       name = content_type_name;
+               }
                
                mime_decode(partnum,
                            part_start, length,
@@ -451,7 +496,8 @@ end_parser: /* free the buffers!  end the oppression!! */
        phree(header);
        phree(content_type);
        phree(encoding);
-       phree(name);
+       phree(content_type_name);
+       phree(content_disposition_name);
        phree(filename);
        phree(disposition);
 }
@@ -511,3 +557,4 @@ void mime_parser(char *content_start,
                        PostMultiPartCallBack,
                        userdata, dont_decode);
 }
+