use an Enum for the cm_fields vector instead of nameless chars
[citadel.git] / citadel / internet_addressing.c
index 23c08d4bf8ae6777b7b5f3a6dec3bc6093b61b23..b4663fc36e3a2d1d654d5a69aefa93d5edca8e33 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * $Id$
- *
  * This file contains functions which handle the mapping of Internet addresses
  * to users on the Citadel system.
  */
 #include "room_ops.h"
 #include "parsedate.h"
 #include "database.h"
-
 #include "ctdl_module.h"
-
-#ifndef HAVE_SNPRINTF
-#include "snprintf.h"
-#endif
-
-
 #ifdef HAVE_ICONV
 #include <iconv.h>
 
@@ -388,20 +379,30 @@ void unfold_rfc822_field(char **field, char **FieldEnd)
             sField < pFieldEnd; 
             pField++, sField++)
        {
-               if (*pField=='\"') quote = 1 - quote;
-               if (!quote) {
-                       if (isspace(*sField))
-                       {
-                               *pField = ' ';
-                               pField++;
-                               sField++;
-                       
-                               while ((sField < pFieldEnd) && 
-                                      isspace(*sField))
+               if ((*sField=='\r') || (*sField=='\n')) {
+                   sField++;
+                   if  (*sField == '\n')
+                       sField++;
+                   *pField = *sField;
+               }
+               else {
+                       if (*sField=='\"') quote = 1 - quote;
+                       if (!quote) {
+                               if (isspace(*sField))
+                               {
+                                       *pField = ' ';
+                                       pField++;
                                        sField++;
+                                       
+                                       while ((sField < pFieldEnd) && 
+                                              isspace(*sField))
+                                               sField++;
+                                       *pField = *sField;
+                               }
+                               else *pField = *sField;
                        }
+                       else *pField = *sField;
                }
-               else *pField = *sField;
        }
        *pField = '\0';
        *FieldEnd = pField - 1;
@@ -573,8 +574,10 @@ int convert_field(struct CtdlMessage *msg, const char *beg, const char *end) {
        valueend = key + len;
        * ( key + (colonpos - beg) ) = '\0';
        value = &key[(colonpos - beg) + 1];
+/*     printf("Header: [%s]\nValue: [%s]\n", key, value); */
        unfold_rfc822_field(&value, &valueend);
-       valuelen = valueend - value;
+       valuelen = valueend - value + 1;
+/*     printf("UnfoldedValue: [%s]\n", value); */
 
        /*
         * Here's the big rfc822-to-citadel loop.
@@ -587,91 +590,98 @@ int convert_field(struct CtdlMessage *msg, const char *beg, const char *end) {
                parsed_date = parsedate(value);
                if (parsed_date < 0L) parsed_date = time(NULL);
                snprintf(buf, sizeof buf, "%ld", (long)parsed_date );
-               if (msg->cm_fields['T'] == NULL)
-                       msg->cm_fields['T'] = strdup(buf);
+               if (msg->cm_fields[eTimestamp] == NULL)
+                       msg->cm_fields[eTimestamp] = strdup(buf);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "From")) {
                process_rfc822_addr(value, user, node, name);
-               CtdlLogPrintf(CTDL_DEBUG, "Converted to <%s@%s> (%s)\n", user, node, name);
+               syslog(LOG_DEBUG, "Converted to <%s@%s> (%s)\n", user, node, name);
                snprintf(addr, sizeof addr, "%s@%s", user, node);
-               if (msg->cm_fields['A'] == NULL)
-                       msg->cm_fields['A'] = strdup(name);
-               processed = 1;
-               if (msg->cm_fields['F'] == NULL)
-                       msg->cm_fields['F'] = strdup(addr);
+               if (msg->cm_fields[eAuthor] == NULL)
+                       msg->cm_fields[eAuthor] = strdup(name);
+               if (msg->cm_fields[erFc822Addr] == NULL)
+                       msg->cm_fields[erFc822Addr] = strdup(addr);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "Subject")) {
-               if (msg->cm_fields['U'] == NULL)
-                       msg->cm_fields['U'] = strndup(value, valuelen);
+               if (msg->cm_fields[eMsgSubject] == NULL)
+                       msg->cm_fields[eMsgSubject] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "List-ID")) {
-               if (msg->cm_fields['L'] == NULL)
-                       msg->cm_fields['L'] = strndup(value, valuelen);
+               if (msg->cm_fields[eListID] == NULL)
+                       msg->cm_fields[eListID] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "To")) {
-               if (msg->cm_fields['R'] == NULL)
-                       msg->cm_fields['R'] = strndup(value, valuelen);
+               if (msg->cm_fields[eRecipient] == NULL)
+                       msg->cm_fields[eRecipient] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "CC")) {
-               if (msg->cm_fields['Y'] == NULL)
-                       msg->cm_fields['Y'] = strndup(value, valuelen);
+               if (msg->cm_fields[eCarbonCopY] == NULL)
+                       msg->cm_fields[eCarbonCopY] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "Message-ID")) {
-               if (msg->cm_fields['I'] != NULL) {
-                       CtdlLogPrintf(CTDL_WARNING, "duplicate message id\n");
+               if (msg->cm_fields[emessageId] != NULL) {
+                       syslog(LOG_WARNING, "duplicate message id\n");
                }
 
-               if (msg->cm_fields['I'] == NULL) {
-                       msg->cm_fields['I'] = strndup(value, valuelen);
+               if (msg->cm_fields[emessageId] == NULL) {
+                       msg->cm_fields[emessageId] = strndup(value, valuelen);
 
                        /* Strip angle brackets */
-                       while (haschar(msg->cm_fields['I'], '<') > 0) {
-                               strcpy(&msg->cm_fields['I'][0],
-                                       &msg->cm_fields['I'][1]);
+                       while (haschar(msg->cm_fields[emessageId], '<') > 0) {
+                               strcpy(&msg->cm_fields[emessageId][0],
+                                       &msg->cm_fields[emessageId][1]);
                        }
-                       for (i = 0; i<strlen(msg->cm_fields['I']); ++i)
-                               if (msg->cm_fields['I'][i] == '>')
-                                       msg->cm_fields['I'][i] = 0;
+                       for (i = 0; i<strlen(msg->cm_fields[emessageId]); ++i)
+                               if (msg->cm_fields[emessageId][i] == '>')
+                                       msg->cm_fields[emessageId][i] = 0;
                }
 
                processed = 1;
        }
 
        else if (!strcasecmp(key, "Return-Path")) {
-               if (msg->cm_fields['P'] == NULL)
-                       msg->cm_fields['P'] = strndup(value, valuelen);
+               if (msg->cm_fields[eMessagePath] == NULL)
+                       msg->cm_fields[eMessagePath] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "Envelope-To")) {
-               if (msg->cm_fields['V'] == NULL)
-                       msg->cm_fields['V'] = strndup(value, valuelen);
+               if (msg->cm_fields[eenVelopeTo] == NULL)
+                       msg->cm_fields[eenVelopeTo] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "References")) {
-               if (msg->cm_fields['W'] != NULL) {
-                       free(msg->cm_fields['W']);
+               if (msg->cm_fields[eWeferences] != NULL) {
+                       free(msg->cm_fields[eWeferences]);
                }
-               msg->cm_fields['W'] = strndup(value, valuelen);
+               msg->cm_fields[eWeferences] = strndup(value, valuelen);
+               processed = 1;
+       }
+
+       else if (!strcasecmp(key, "Reply-To")) {
+               if (msg->cm_fields[eReplyTo] != NULL) {
+                       free(msg->cm_fields[eReplyTo]);
+               }
+               msg->cm_fields[eReplyTo] = strndup(value, valuelen);
                processed = 1;
        }
 
        else if (!strcasecmp(key, "In-reply-to")) {
-               if (msg->cm_fields['W'] == NULL) {              /* References: supersedes In-reply-to: */
-                       msg->cm_fields['W'] = strndup(value, valuelen);
+               if (msg->cm_fields[eWeferences] == NULL) {              /* References: supersedes In-reply-to: */
+                       msg->cm_fields[eWeferences] = strndup(value, valuelen);
                }
                processed = 1;
        }
@@ -768,8 +778,7 @@ struct CtdlMessage *convert_internet_message_buf(StrBuf **rfc822)
                       (done == 0) ) 
                {
 
-                       if ((*pos=='\n') &&
-                           (!isspace(*(pos+1)))) 
+                       if ( (*pos=='\n') && ((*(pos+1))!=0x20) && ((*(pos+1))!=0x09) )
                        {
                                end = pos;
                        }
@@ -798,6 +807,7 @@ struct CtdlMessage *convert_internet_message_buf(StrBuf **rfc822)
                /* Strip the field out of the RFC822 header if we used it */
                if (!converted) {
                        StrBufAppendBufPlain(OtherHeaders, beg, end - beg, 0);
+                       StrBufAppendBufPlain(OtherHeaders, HKEY("\n"), 0);
                }
 
                /* If we've hit the end of the message, bail out */
@@ -808,21 +818,21 @@ struct CtdlMessage *convert_internet_message_buf(StrBuf **rfc822)
        if (pos < totalend)
                StrBufAppendBufPlain(OtherHeaders, pos, totalend - pos, 0);
        FreeStrBuf(rfc822);
-       msg->cm_fields['M'] = SmashStrBuf(&OtherHeaders);
+       msg->cm_fields[eMesageText] = SmashStrBuf(&OtherHeaders);
 
        /* Follow-up sanity checks... */
 
        /* If there's no timestamp on this message, set it to now. */
-       if (msg->cm_fields['T'] == NULL) {
+       if (msg->cm_fields[eTimestamp] == NULL) {
                snprintf(buf, sizeof buf, "%ld", (long)time(NULL));
-               msg->cm_fields['T'] = strdup(buf);
+               msg->cm_fields[eTimestamp] = strdup(buf);
        }
 
        /* If a W (references, or rather, Wefewences) field is present, we
         * have to convert it from RFC822 format to Citadel format.
         */
-       if (msg->cm_fields['W'] != NULL) {
-               convert_references_to_wefewences(msg->cm_fields['W']);
+       if (msg->cm_fields[eWeferences] != NULL) {
+               convert_references_to_wefewences(msg->cm_fields[eWeferences]);
        }
 
        return msg;
@@ -837,11 +847,11 @@ struct CtdlMessage *convert_internet_message_buf(StrBuf **rfc822)
  * 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) {
+char *rfc822_fetch_field(const char *rfc822, const char *fieldname) {
        char *fieldbuf = NULL;
-       char *end_of_headers;
-       char *field_start;
-       char *ptr;
+       const char *end_of_headers;
+       const char *field_start;
+       const char *ptr;
        char *cont;
        char fieldhdr[SIZ];
 
@@ -852,13 +862,13 @@ char *rfc822_fetch_field(char *rfc822, char *fieldname) {
        snprintf(fieldhdr, sizeof fieldhdr, "%s:", fieldname);
 
        /* Locate the end of the headers, so we don't run past that point */
-       end_of_headers = bmstrcasestr(rfc822, "\n\r\n");
+       end_of_headers = cbmstrcasestr(rfc822, "\n\r\n");
        if (end_of_headers == NULL) {
-               end_of_headers = bmstrcasestr(rfc822, "\n\n");
+               end_of_headers = cbmstrcasestr(rfc822, "\n\n");
        }
        if (end_of_headers == NULL) return (NULL);
 
-       field_start = bmstrcasestr(rfc822, fieldhdr);
+       field_start = cbmstrcasestr(rfc822, fieldhdr);
        if (field_start == NULL) return(NULL);
        if (field_start > end_of_headers) return(NULL);
 
@@ -866,11 +876,11 @@ char *rfc822_fetch_field(char *rfc822, char *fieldname) {
        strcpy(fieldbuf, "");
 
        ptr = field_start;
-       ptr = memreadline(ptr, fieldbuf, SIZ-strlen(fieldbuf) );
+       ptr = cmemreadline(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) );
+               ptr = cmemreadline(ptr, cont, SIZ-strlen(fieldbuf) );
                striplt(cont);
        }
 
@@ -901,7 +911,7 @@ void directory_key(char *key, char *addr) {
        }
        key[keylen++] = 0;
 
-       CtdlLogPrintf(CTDL_DEBUG, "Directory key is <%s>\n", key);
+       syslog(LOG_DEBUG, "Directory key is <%s>\n", key);
 }
 
 
@@ -941,13 +951,15 @@ void CtdlDirectoryInit(void) {
 /*
  * Add an Internet e-mail address to the directory for a user
  */
-void CtdlDirectoryAddUser(char *internet_addr, char *citadel_addr) {
+int CtdlDirectoryAddUser(char *internet_addr, char *citadel_addr) {
        char key[SIZ];
 
-       if (IsDirectory(internet_addr, 0) == 0) return;
-       CtdlLogPrintf(CTDL_DEBUG, "Create directory entry: %s --> %s\n", internet_addr, citadel_addr);
+       if (IsDirectory(internet_addr, 0) == 0) 
+               return 0;
+       syslog(LOG_DEBUG, "Create directory entry: %s --> %s\n", internet_addr, citadel_addr);
        directory_key(key, internet_addr);
        cdb_store(CDB_DIRECTORY, key, strlen(key), citadel_addr, strlen(citadel_addr)+1 );
+       return 1;
 }
 
 
@@ -957,12 +969,12 @@ void CtdlDirectoryAddUser(char *internet_addr, char *citadel_addr) {
  * (NOTE: we don't actually use or need the citadel_addr variable; it's merely
  * here because the callback API expects to be able to send it.)
  */
-void CtdlDirectoryDelUser(char *internet_addr, char *citadel_addr) {
+int CtdlDirectoryDelUser(char *internet_addr, char *citadel_addr) {
        char key[SIZ];
 
-       CtdlLogPrintf(CTDL_DEBUG, "Delete directory entry: %s --> %s\n", internet_addr, citadel_addr);
+       syslog(LOG_DEBUG, "Delete directory entry: %s --> %s\n", internet_addr, citadel_addr);
        directory_key(key, internet_addr);
-       cdb_delete(CDB_DIRECTORY, key, strlen(key) );
+       return cdb_delete(CDB_DIRECTORY, key, strlen(key) ) == 0;
 }
 
 
@@ -1006,20 +1018,20 @@ char *harvest_collected_addresses(struct CtdlMessage *msg) {
        char user[256], node[256], name[256];
        int is_harvestable;
        int i, j, h;
-       int field = 0;
+       eMsgField field = 0;
 
        if (msg == NULL) return(NULL);
 
        is_harvestable = 1;
        strcpy(addr, "");       
-       if (msg->cm_fields['A'] != NULL) {
-               strcat(addr, msg->cm_fields['A']);
+       if (msg->cm_fields[eAuthor] != NULL) {
+               strcat(addr, msg->cm_fields[eAuthor]);
        }
-       if (msg->cm_fields['F'] != NULL) {
+       if (msg->cm_fields[erFc822Addr] != NULL) {
                strcat(addr, " <");
-               strcat(addr, msg->cm_fields['F']);
+               strcat(addr, msg->cm_fields[erFc822Addr]);
                strcat(addr, ">");
-               if (IsDirectory(msg->cm_fields['F'], 0)) {
+               if (IsDirectory(msg->cm_fields[erFc822Addr], 0)) {
                        is_harvestable = 0;
                }
        }
@@ -1035,8 +1047,8 @@ char *harvest_collected_addresses(struct CtdlMessage *msg) {
 
        /* Scan both the R (To) and Y (CC) fields */
        for (i = 0; i < 2; ++i) {
-               if (i == 0) field = 'R' ;
-               if (i == 1) field = 'Y' ;
+               if (i == 0) field = eRecipient;
+               if (i == 1) field = eCarbonCopY;
 
                if (msg->cm_fields[field] != NULL) {
                        for (j=0; j<num_tokens(msg->cm_fields[field], ','); ++j) {