]> code.citadel.org Git - citadel.git/blobdiff - citadel/server/internet_addressing.c
citadel.h is now citadel_defs.h
[citadel.git] / citadel / server / internet_addressing.c
index fa550d75fa4952edfa142f04dd7363249ac0e773..9cfbe3b8ad1f32077870904c793ef239fcb4ac7c 100644 (file)
@@ -21,7 +21,7 @@
 #include <string.h>
 #include <limits.h>
 #include <libcitadel.h>
-#include "citadel.h"
+#include "citadel_defs.h"
 #include "server.h"
 #include "sysdep_decls.h"
 #include "citserver.h"
 #include "parsedate.h"
 #include "database.h"
 #include "ctdl_module.h"
-#ifdef HAVE_ICONV
-#include <iconv.h>
 
-// This is the non-define version in case it is needed for debugging
-#if 0
-inline void FindNextEnd (char *bptr, char *end)
-{
-       /* Find the next ?Q? */
-       end = strchr(bptr + 2, '?');
-       if (end == NULL) return NULL;
-       if (((*(end + 1) == 'B') || (*(end + 1) == 'Q')) && 
-           (*(end + 2) == '?')) {
-               /* skip on to the end of the cluster, the next ?= */
-               end = strstr(end + 3, "?=");
-       }
-       else
-               /* sort of half valid encoding, try to find an end. */
-               end = strstr(bptr, "?=");
-}
-#endif
-
-#define FindNextEnd(bptr, end) { \
-       end = strchr(bptr + 2, '?'); \
-       if (end != NULL) { \
-               if (((*(end + 1) == 'B') || (*(end + 1) == 'Q')) && (*(end + 2) == '?')) { \
-                       end = strstr(end + 3, "?="); \
-               } else end = strstr(bptr, "?="); \
-       } \
-}
-
-// Handle subjects with RFC2047 encoding such as:
-// =?koi8-r?B?78bP0s3Mxc7JxSDXz9rE1dvO2c3JINvB0sHNySDP?=
-void utf8ify_rfc822_string(char *buf) {
-       char *start, *end, *next, *nextend, *ptr;
-       char newbuf[1024];
-       char charset[128];
-       char encoding[16];
-       char istr[1024];
-       iconv_t ic = (iconv_t)(-1) ;
-       char *ibuf;                     // Buffer of characters to be converted
-       char *obuf;                     // Buffer for converted characters
-       size_t ibuflen;                 // Length of input buffer
-       size_t obuflen;                 // Length of output buffer
-       char *isav;                     // Saved pointer to input buffer
-       char *osav;                     // Saved pointer to output buffer
-       int passes = 0;
-       int i, len, delta;
-       int illegal_non_rfc2047_encoding = 0;
-
-       // Sometimes, badly formed messages contain strings which were simply
-       // written out directly in some foreign character set instead of
-       // using RFC2047 encoding.  This is illegal but we will attempt to
-       // handle it anyway by converting from a user-specified default
-       // charset to UTF-8 if we see any nonprintable characters.
-       len = strlen(buf);
-       for (i=0; i<len; ++i) {
-               if ((buf[i] < 32) || (buf[i] > 126)) {
-                       illegal_non_rfc2047_encoding = 1;
-                       i = len;        // take a shortcut, it won't be more than one.
-               }
-       }
-       if (illegal_non_rfc2047_encoding) {
-               const char *default_header_charset = "iso-8859-1";
-               if ( (strcasecmp(default_header_charset, "UTF-8")) && (strcasecmp(default_header_charset, "us-ascii")) ) {
-                       ctdl_iconv_open("UTF-8", default_header_charset, &ic);
-                       if (ic != (iconv_t)(-1) ) {
-                               ibuf = malloc(1024);
-                               isav = ibuf;
-                               safestrncpy(ibuf, buf, 1024);
-                               ibuflen = strlen(ibuf);
-                               obuflen = 1024;
-                               obuf = (char *) malloc(obuflen);
-                               osav = obuf;
-                               iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
-                               osav[1024-obuflen] = 0;
-                               strcpy(buf, osav);
-                               free(osav);
-                               iconv_close(ic);
-                               free(isav);
-                       }
-               }
-       }
-
-       // pre evaluate the first pair
-       nextend = end = NULL;
-       len = strlen(buf);
-       start = strstr(buf, "=?");
-       if (start != NULL) 
-               FindNextEnd (start, end);
-
-       while ((start != NULL) && (end != NULL)) {
-               next = strstr(end, "=?");
-               if (next != NULL)
-                       FindNextEnd(next, nextend);
-               if (nextend == NULL)
-                       next = NULL;
-
-               // did we find two partitions
-               if ((next != NULL) && ((next - end) > 2)) {
-                       ptr = end + 2;
-                       while ((ptr < next) && 
-                              (isspace(*ptr) ||
-                               (*ptr == '\r') ||
-                               (*ptr == '\n') || 
-                               (*ptr == '\t')))
-                               ptr ++;
-                       // did we find a gab just filled with blanks?
-                       if (ptr == next) {
-                               memmove(end + 2, next, len - (next - start));
-
-                               // now terminate the gab at the end
-                               delta = (next - end) - 2;
-                               len -= delta;
-                               buf[len] = '\0';
-
-                               // move next to its new location.
-                               next -= delta;
-                               nextend -= delta;
-                       }
-               }
-               // our next-pair is our new first pair now.
-               start = next;
-               end = nextend;
-       }
-
-       // Now we handle foreign character sets properly encoded in RFC2047 format.
-       start = strstr(buf, "=?");
-       FindNextEnd((start != NULL)? start : buf, end);
-       while (start != NULL && end != NULL && end > start) {
-               extract_token(charset, start, 1, '?', sizeof charset);
-               extract_token(encoding, start, 2, '?', sizeof encoding);
-               extract_token(istr, start, 3, '?', sizeof istr);
-
-               ibuf = malloc(1024);
-               isav = ibuf;
-               if (!strcasecmp(encoding, "B")) {       // base64
-                       ibuflen = CtdlDecodeBase64(ibuf, istr, strlen(istr));
-               }
-               else if (!strcasecmp(encoding, "Q")) {  // quoted-printable
-                       size_t len;
-                       unsigned long pos;
-                       
-                       len = strlen(istr);
-                       pos = 0;
-                       while (pos < len) {
-                               if (istr[pos] == '_') istr[pos] = ' ';
-                               pos++;
-                       }
-                       ibuflen = CtdlDecodeQuotedPrintable(ibuf, istr, len);
-               }
-               else {
-                       strcpy(ibuf, istr);             // unknown encoding
-                       ibuflen = strlen(istr);
-               }
-
-               ctdl_iconv_open("UTF-8", charset, &ic);
-               if (ic != (iconv_t)(-1) ) {
-                       obuflen = 1024;
-                       obuf = (char *) malloc(obuflen);
-                       osav = obuf;
-                       iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
-                       osav[1024-obuflen] = 0;
-
-                       end = start;
-                       end++;
-                       strcpy(start, "");
-                       remove_token(end, 0, '?');
-                       remove_token(end, 0, '?');
-                       remove_token(end, 0, '?');
-                       remove_token(end, 0, '?');
-                       strcpy(end, &end[1]);
-
-                       snprintf(newbuf, sizeof newbuf, "%s%s%s", buf, osav, end);
-                       strcpy(buf, newbuf);
-                       free(osav);
-                       iconv_close(ic);
-               }
-               else {
-                       end = start;
-                       end++;
-                       strcpy(start, "");
-                       remove_token(end, 0, '?');
-                       remove_token(end, 0, '?');
-                       remove_token(end, 0, '?');
-                       remove_token(end, 0, '?');
-                       strcpy(end, &end[1]);
-
-                       snprintf(newbuf, sizeof newbuf, "%s(unreadable)%s", buf, end);
-                       strcpy(buf, newbuf);
-               }
-
-               free(isav);
-
-               // Since spammers will go to all sorts of absurd lengths to get their
-               // messages through, there are LOTS of corrupt headers out there.
-               // So, prevent a really badly formed RFC2047 header from throwing
-               // this function into an infinite loop.
-               ++passes;
-               if (passes > 20) return;
-
-               start = strstr(buf, "=?");
-               FindNextEnd((start != NULL)? start : buf, end);
-       }
-
-}
-#else
-inline void utf8ify_rfc822_string(char *a){};
-
-#endif
 
 
 char *inetcfg = NULL;
@@ -382,8 +174,8 @@ int expand_aliases(char *name, char *aliases) {
                        if (bar) {
                                bar[0] = 0;
                                ++bar;
-                               striplt(aaa);
-                               striplt(bar);
+                               string_trim(aaa);
+                               string_trim(bar);
                                if ( (!IsEmptyStr(aaa)) && (!strcasecmp(name, aaa)) ) {
                                        syslog(LOG_DEBUG, "internet_addressing: global alias <%s> to <%s>", name, bar);
                                        strcpy(name, bar);
@@ -399,7 +191,7 @@ int expand_aliases(char *name, char *aliases) {
        safestrncpy(original_name, name, sizeof original_name);
 
        // should these checks still be here, or maybe move them to split_recps() ?
-       striplt(name);
+       string_trim(name);
        remove_any_whitespace_to_the_left_or_right_of_at_symbol(name);
        stripallbut(name, '<', '>');
 
@@ -485,7 +277,7 @@ Array *split_recps(char *addresses, Array *append_to) {
        for (i=0; i<num_addresses; ++i) {
                char this_address[256];
                extract_token(this_address, a, i, ',', sizeof this_address);
-               striplt(this_address);                          // strip leading and trailing whitespace
+               string_trim(this_address);                              // strip leading and trailing whitespace
                stripout(this_address, '(', ')');               // remove any portion in parentheses
                stripallbut(this_address, '<', '>');            // if angle brackets are present, keep only what is inside them
                if (!IsEmptyStr(this_address)) {
@@ -921,9 +713,6 @@ void unfold_rfc822_field(char **field, char **FieldEnd)
 
 
 // Split an RFC822-style address into userid, host, and full name
-//
-// Note: This still handles obsolete address syntaxes such as user%node@node and ...node!user
-//       We should probably remove that.
 void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name) {
        int a;
 
@@ -937,20 +726,12 @@ void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name)
        strcpy(name, rfc822);
        stripout(name, '<', '>');
 
-       // strip anything to the left of a bang
-       while ((!IsEmptyStr(name)) && (haschar(name, '!') > 0))
-               strcpy(name, &name[1]);
-
-       // and anything to the right of a @ or %
+       // and anything to the right of a @
        for (a = 0; name[a] != '\0'; ++a) {
                if (name[a] == '@') {
                        name[a] = 0;
                        break;
                }
-               if (name[a] == '%') {
-                       name[a] = 0;
-                       break;
-               }
        }
 
        // but if there are parentheses, that changes the rules...
@@ -983,23 +764,14 @@ void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name)
                stripallbut(user, '<', '>');
        }
 
-       // strip anything to the left of a bang
-       while ((!IsEmptyStr(user)) && (haschar(user, '!') > 0))
-               strcpy(user, &user[1]);
-
-       // and anything to the right of a @ or %
+       // and anything to the right of a @
        for (a = 0; user[a] != '\0'; ++a) {
                if (user[a] == '@') {
                        user[a] = 0;
                        break;
                }
-               if (user[a] == '%') {
-                       user[a] = 0;
-                       break;
-               }
        }
 
-
        // extract node name
        strcpy(node, rfc822);
 
@@ -1012,39 +784,20 @@ void process_rfc822_addr(const char *rfc822, char *user, char *node, char *name)
        }
 
        // If no node specified, tack ours on instead
-       if (
-               (haschar(node, '@')==0)
-               && (haschar(node, '%')==0)
-               && (haschar(node, '!')==0)
-       ) {
+       if (haschar(node, '@') == 0) {
                strcpy(node, CtdlGetConfigStr("c_nodename"));
        }
        else {
-
                // strip anything to the left of a @
-               while ((!IsEmptyStr(node)) && (haschar(node, '@') > 0))
-                       strcpy(node, &node[1]);
-       
-               // strip anything to the left of a %
-               while ((!IsEmptyStr(node)) && (haschar(node, '%') > 0))
-                       strcpy(node, &node[1]);
-       
-               // reduce multiple system bang paths to node!user
-               while ((!IsEmptyStr(node)) && (haschar(node, '!') > 1))
+               while ((!IsEmptyStr(node)) && (haschar(node, '@') > 0)) {
                        strcpy(node, &node[1]);
-       
-               // now get rid of the user portion of a node!user string
-               for (a = 0; node[a] != '\0'; ++a)
-                       if (node[a] == '!') {
-                               node[a] = 0;
-                               break;
-                       }
+               }
        }
 
        // strip leading and trailing spaces in all strings
-       striplt(user);
-       striplt(node);
-       striplt(name);
+       string_trim(user);
+       string_trim(node);
+       string_trim(name);
 
        // If we processed a string that had the address in angle brackets
        // but no name outside the brackets, we now have an empty name.  In
@@ -1388,11 +1141,11 @@ char *rfc822_fetch_field(const char *rfc822, const char *fieldname) {
                strcat(fieldbuf, " ");
                cont = &fieldbuf[strlen(fieldbuf)];
                ptr = cmemreadline(ptr, cont, SIZ-strlen(fieldbuf) );
-               striplt(cont);
+               string_trim(cont);
        }
 
        strcpy(fieldbuf, &fieldbuf[strlen(fieldhdr)]);
-       striplt(fieldbuf);
+       string_trim(fieldbuf);
 
        return(fieldbuf);
 }
@@ -1429,7 +1182,7 @@ int IsDirectory(char *addr, int allow_masq_domains) {
        int h;
 
        extract_token(domain, addr, 1, '@', sizeof domain);
-       striplt(domain);
+       string_trim(domain);
 
        h = CtdlHostAlias(domain);
 
@@ -1555,8 +1308,9 @@ char *harvest_collected_addresses(struct CtdlMessage *msg) {
                if (!CM_IsEmpty(msg, field)) {
                        for (j=0; j<num_tokens(msg->cm_fields[field], ','); ++j) {
                                extract_token(addr, msg->cm_fields[field], j, ',', sizeof addr);
-                               if (strstr(addr, "=?") != NULL)
+                               if (strstr(addr, "=?") != NULL) {
                                        utf8ify_rfc822_string(addr);
+                               }
                                process_rfc822_addr(addr, user, node, name);
                                h = CtdlHostAlias(node);
                                if (h != hostalias_localhost) {
@@ -1565,7 +1319,7 @@ char *harvest_collected_addresses(struct CtdlMessage *msg) {
                                        if (!IsEmptyStr(coll)) {
                                                strcat(coll, ",");
                                        }
-                                       striplt(addr);
+                                       string_trim(addr);
                                        strcat(coll, addr);
                                }
                        }