]> code.citadel.org Git - citadel.git/blobdiff - webcit/mime_parser.c
* serv_crypto.c: made changes to OpenSSL calls ... removed unnecessary
[citadel.git] / webcit / mime_parser.c
index 8fe888197365a7e0329a9004c56da33fd1976ed6..613b9258e51cccd2fa2ab5fb72fceffb2515855f 100644 (file)
@@ -3,14 +3,11 @@
  *
  * 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 <stdlib.h>
 #include <unistd.h>
@@ -274,7 +271,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 +302,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 +333,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 +342,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 +416,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 +442,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 +477,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 +538,4 @@ void mime_parser(char *content_start,
                        PostMultiPartCallBack,
                        userdata, dont_decode);
 }
+