]> code.citadel.org Git - citadel.git/blobdiff - citadel/internet_addressing.c
* Added an API function to extract and unfold specific RFC822 fields.
[citadel.git] / citadel / internet_addressing.c
index 0c00d9fe3a3b39d9cd7ccb70f87927055168b8e0..00fde5ca64b38fb5e3d86e7760a47e908ebf1da8 100644 (file)
@@ -286,7 +286,7 @@ void process_rfc822_addr(char *rfc822, char *user, char *node, char *name)
 void try_name(struct usersupp *us, void *data) {
        struct trynamebuf *tnb;
        tnb = (struct trynamebuf *)data;
-       
+
        if (!strncasecmp(tnb->buffer1, "cit", 3))
                if (atol(&tnb->buffer1[3]) == us->usernum)
                        strcpy(tnb->buffer2, us->fullname);
@@ -420,8 +420,6 @@ int convert_field(struct CtdlMessage *msg, int beg, int end) {
        value = &key[(colonpos - beg) + 1];
        unfold_rfc822_field(value);
 
-       lprintf(9, "Key=<%s> Value=<%s>\n", key, value);
-
        /*
         * Here's the big rfc822-to-citadel loop.
         */
@@ -432,9 +430,7 @@ int convert_field(struct CtdlMessage *msg, int beg, int end) {
        if (!strcasecmp(key, "Date")) {
                parsed_date = parsedate(value);
                if (parsed_date < 0L) parsed_date = time(NULL);
-               lprintf(9, "Parsed date is %s",
-                       asctime(localtime(&parsed_date)));
-               sprintf(buf, "%ld", parsed_date );
+               snprintf(buf, sizeof buf, "%ld", parsed_date );
                if (msg->cm_fields['T'] == NULL)
                        msg->cm_fields['T'] = strdoop(buf);
                processed = 1;
@@ -443,7 +439,7 @@ int convert_field(struct CtdlMessage *msg, int beg, int end) {
        else if (!strcasecmp(key, "From")) {
                process_rfc822_addr(value, user, node, name);
                lprintf(9, "Converted to <%s@%s> (%s)\n", user, node, name);
-               sprintf(addr, "%s@%s", user, node);
+               snprintf(addr, sizeof addr, "%s@%s", user, node);
                if (msg->cm_fields['A'] == NULL)
                        msg->cm_fields['A'] = strdoop(name);
                processed = 1;
@@ -458,6 +454,33 @@ int convert_field(struct CtdlMessage *msg, int beg, int end) {
                processed = 1;
        }
 
+       else if (!strcasecmp(key, "Message-ID")) {
+               if (msg->cm_fields['I'] != NULL) {
+                       lprintf(5, "duplicate message id\n");
+               }
+
+               if (msg->cm_fields['I'] == NULL) {
+                       msg->cm_fields['I'] = strdoop(value);
+
+                       /* Strip angle brackets */
+                       if ((haschar(msg->cm_fields['I'], '<') == 1)
+                          && (haschar(msg->cm_fields['I'], '>') == 1)) {
+                               while ((strlen(msg->cm_fields['I']) > 0)
+                                     && (msg->cm_fields['I'][0] != '<')) {
+                                       strcpy(&msg->cm_fields['I'][0],
+                                               &msg->cm_fields['I'][1]);
+                               }
+                               strcpy(&msg->cm_fields['I'][0],
+                                       &msg->cm_fields['I'][1]);
+                               for (i = 0; i<strlen(msg->cm_fields['I']); ++i)
+                                       if (msg->cm_fields['I'][i] == '>')
+                                               msg->cm_fields['I'][i] = 0;
+                       }
+               }
+
+               processed = 1;
+       }
+
        /* Clean up and move on. */
        phree(key);     /* Don't free 'value', it's actually the same buffer */
        return(processed);
@@ -526,7 +549,7 @@ struct CtdlMessage *convert_internet_message(char *rfc822) {
 
        /* If there's no timestamp on this message, set it to now. */
        if (msg->cm_fields['T'] == NULL) {
-               sprintf(buf, "%ld", time(NULL));
+               snprintf(buf, sizeof buf, "%ld", time(NULL));
                msg->cm_fields['T'] = strdoop(buf);
        }
 
@@ -535,3 +558,70 @@ struct CtdlMessage *convert_internet_message(char *rfc822) {
        return msg;
 }
 
+
+
+/*
+ * Look for a particular header field in an RFC822 message text.  If the
+ * requested field is found, it is unfolded (if necessary) and returned to
+ * the caller.  The field name is stripped out, leaving only its contents.
+ * The caller is responsible for freeing the returned buffer.  If the requested
+ * 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;
+
+       /* 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;
+                       }
+
+               }
+
+               /* 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);
+               }
+
+               /* If we've hit the end of the message, bail out */
+               if (pos > strlen(rfc822)) done = 1;
+       }
+       return(NULL);
+}