]> code.citadel.org Git - citadel.git/blobdiff - citadel/internet_addressing.c
* MUCH faster implementation of rfc822_fetch_field()
[citadel.git] / citadel / internet_addressing.c
index fd16a6f1813e1bb1385b859be08d00c2e3690369..2ee15507727776fc12b3c93817c50b416f1774d6 100644 (file)
@@ -483,62 +483,46 @@ struct CtdlMessage *convert_internet_message(char *rfc822) {
  * field is not present, or anything else goes wrong, it returns NULL.
  */
 char *rfc822_fetch_field(char *rfc822, char *fieldname) {
-       int pos = 0;
-       int beg, end;
-       int done = 0;
-       int colonpos, i;
        char *fieldbuf = NULL;
+       char *end_of_headers;
+       char *field_start;
+       char *ptr;
+       char *cont;
+       char fieldhdr[SIZ];
 
        /* Should never happen, but sometimes we get stupid */
        if (rfc822 == NULL) return(NULL);
        if (fieldname == NULL) return(NULL);
 
-       while (!done) {
-
-               /* Locate beginning and end of field, keeping in mind that
-                * some fields might be multiline
-                */
-               beg = pos;
-               end = (-1);
-               for (pos=beg; ((pos<=strlen(rfc822))&&(end<0)); ++pos) {
-                       if ((rfc822[pos]=='\n')
-                          && (!isspace(rfc822[pos+1]))) {
-                               end = pos;
-                       }
-                       if ( (rfc822[pos]=='\n')        /* done w. headers? */
-                          && ( (rfc822[pos+1]=='\n')
-                             ||(rfc822[pos+1]=='\r'))) {
-                               end = pos;
-                               done = 1;
-                       }
+       snprintf(fieldhdr, sizeof fieldhdr, "%s:", fieldname);
 
-               }
+       /* Locate the end of the headers, so we don't run past that point */
+       end_of_headers = bmstrstr(rfc822, "\n\r\n", strncmp);
+       if (end_of_headers == NULL) {
+               end_of_headers = bmstrstr(rfc822, "\n\n", strncmp);
+       }
+       if (end_of_headers == NULL) return (NULL);
+
+       field_start = bmstrstr(rfc822, fieldhdr, strncasecmp);
+       if (field_start == NULL) return(NULL);
+       if (field_start > end_of_headers) return(NULL);
+
+       fieldbuf = mallok(SIZ);
+       strcpy(fieldbuf, "");
+
+       ptr = field_start;
+       ptr = memreadline(ptr, fieldbuf, SIZ-strlen(fieldbuf) );
+       while ( (isspace(ptr[0])) && (ptr < end_of_headers) ) {
+               strcat(fieldbuf, " ");
+               cont = &fieldbuf[strlen(fieldbuf)];
+               ptr = memreadline(ptr, cont, SIZ-strlen(fieldbuf) );
+               striplt(cont);
+       }
 
-               /* At this point we have a field.  Is it The One? */
-               if (end > beg) {
-                       fieldbuf = mallok((end-beg)+3);
-                       if (fieldbuf == NULL) return(NULL);
-                       safestrncpy(fieldbuf, &rfc822[beg], (end-beg)+1);
-                       unfold_rfc822_field(fieldbuf);
-                       colonpos = (-1);
-                       for (i = strlen(fieldbuf); i >= 0; --i) {
-                               if (fieldbuf[i] == ':') colonpos = i;
-                       }
-                       if (colonpos > 0) {
-                               fieldbuf[colonpos] = 0;
-                               if (!strcasecmp(fieldbuf, fieldname)) {
-                                       strcpy(fieldbuf, &fieldbuf[colonpos+1]);
-                                       striplt(fieldbuf);
-                                       return(fieldbuf);
-                               }
-                       }
-                       phree(fieldbuf);
-               }
+       strcpy(fieldbuf, &fieldbuf[strlen(fieldhdr)]);
+       striplt(fieldbuf);
 
-               /* If we've hit the end of the message, bail out */
-               if (pos > strlen(rfc822)) done = 1;
-       }
-       return(NULL);
+       return(fieldbuf);
 }