Back to index

courier  0.68.2
imapsubj.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 /*
00007 */
00008 #include      "config.h"
00009 #include      <stdio.h>
00010 #include      <ctype.h>
00011 #include      <stdlib.h>
00012 #include      <string.h>
00013 #include      "rfc822.h"
00014 
00015 #if    HAVE_STRCASECMP
00016 
00017 #else
00018 #define       strcasecmp    stricmp
00019 #endif
00020 
00021 #if    HAVE_STRNCASECMP
00022 
00023 #else
00024 #define       strncasecmp   strnicmp
00025 #endif
00026 
00027 /* Skip over blobs */
00028 
00029 static char *skipblob(char *p, char **save_blob_ptr)
00030 {
00031        char *q;
00032        char *orig_p=p;
00033        int isalldigits=1;
00034 
00035        if (*p == '[')
00036        {
00037               for (q= p+1; *q; q++)
00038                      if (*q == '[' || *q == ']')
00039                             break;
00040                      else if (strchr("0123456789", *q) == NULL)
00041                             isalldigits=0;
00042 
00043               if (*q == ']')
00044               {
00045                      p=q+1;
00046 
00047                      while (isspace((int)(unsigned char)*p))
00048                      {
00049                             ++p;
00050                      }
00051 
00052                      if (save_blob_ptr && *save_blob_ptr && !isalldigits)
00053                      {
00054                             while (orig_p != p)
00055                                    *(*save_blob_ptr)++=*orig_p++;
00056                      }
00057 
00058                      return (p);
00059               }
00060        }
00061        return (p);
00062 }
00063 
00064 static char *skipblobs(char *p, char **save_blob_ptr)
00065 {
00066        char *q=p;
00067 
00068        do
00069        {
00070               p=q;
00071               q=skipblob(p, save_blob_ptr);
00072        } while (q != p);
00073        return (q);
00074 }
00075 
00076 /* Remove artifacts from the subject header */
00077 
00078 static void stripsubj(char *s, int *hasrefwd, char *save_blob_buf)
00079 {
00080        char   *p;
00081        char   *q;
00082        int doit;
00083 
00084        for (p=q=s; *p; p++)
00085        {
00086               if (!isspace((int)(unsigned char)*p))
00087               {
00088                      *q++=*p;
00089                      continue;
00090               }
00091               while (p[1] && isspace((int)(unsigned char)p[1]))
00092               {
00093                      ++p;
00094               }
00095               *q++=' ';
00096        }
00097        *q=0;
00098 
00099        do
00100        {
00101               doit=0;
00102               /*
00103               **
00104               ** (2) Remove all trailing text of the subject that matches
00105               ** the subj-trailer ABNF, repeat until no more matches are
00106               ** possible.
00107               **
00108               **  subj-trailer    = "(fwd)" / WSP
00109               */
00110 
00111               for (p=s; *p; p++)
00112                      ;
00113               while (p > s)
00114               {
00115                      if ( isspace((int)(unsigned char)p[-1]))
00116                      {
00117                             --p;
00118                             continue;
00119                      }
00120                      if (p-s >= 5 && strncasecmp(p-5, "(FWD)", 5) == 0)
00121                      {
00122                             p -= 5;
00123                             *hasrefwd |= CORESUBJ_FWD;
00124                             continue;
00125                      }
00126                      break;
00127               }
00128               *p=0;
00129 
00130               for (p=s; *p; )
00131               {
00132                      for (;;)
00133                      {
00134                             char *orig_blob_ptr;
00135                             int flag=CORESUBJ_FWD;
00136 
00137                             /*
00138                             **
00139                             ** (3) Remove all prefix text of the subject
00140                             ** that matches the subj-leader ABNF.
00141                             **
00142                             **   subj-leader     = (*subj-blob subj-refwd) / WSP
00143                             **
00144                             **   subj-blob       = "[" *BLOBCHAR "]" *WSP
00145                             **
00146                             **   subj-refwd      = ("re" / ("fw" ["d"])) *WSP [subj-blob] ":"
00147                             **
00148                             **   BLOBCHAR        = %x01-5a / %x5c / %x5e-7f
00149                             **                   ; any CHAR except '[' and ']'
00150                             */
00151 
00152                             if (isspace((int)(unsigned char)*p))
00153                             {
00154                                    ++p;
00155                                    continue;
00156                             }
00157 
00158                             q=skipblobs(p, NULL);
00159 
00160                             if (strncasecmp(q, "RE", 2) == 0)
00161                             {
00162                                    flag=CORESUBJ_RE;
00163                                    q += 2;
00164                             }
00165                             else if (strncasecmp(q, "FWD", 3) == 0)
00166                             {
00167                                    q += 3;
00168                             }
00169                             else if (strncasecmp(q, "FW", 2) == 0)
00170                             {
00171                                    q += 2;
00172                             }
00173                             else q=0;
00174 
00175                             if (q)
00176                             {
00177                                    orig_blob_ptr=save_blob_buf;
00178 
00179                                    q=skipblob(q, &save_blob_buf);
00180                                    if (*q == ':')
00181                                    {
00182                                           p=q+1;
00183                                           *hasrefwd |= flag;
00184                                           continue;
00185                                    }
00186 
00187                                    save_blob_buf=orig_blob_ptr;
00188                             }
00189 
00190 
00191                             /*
00192                             ** (4) If there is prefix text of the subject
00193                             ** that matches the subj-blob ABNF, and
00194                             ** removing that prefix leaves a non-empty
00195                             ** subj-base, then remove the prefix text.
00196                             **
00197                             **   subj-base       = NONWSP *([*WSP] NONWSP)
00198                             **                   ; can be a subj-blob
00199                             */
00200 
00201                             orig_blob_ptr=save_blob_buf;
00202 
00203                             q=skipblob(p, &save_blob_buf);
00204 
00205                             if (q != p && *q)
00206                             {
00207                                    p=q;
00208                                    continue;
00209                             }
00210                             save_blob_buf=orig_blob_ptr;
00211                             break;
00212                      }
00213 
00214                      /*
00215                      **
00216                      ** (6) If the resulting text begins with the
00217                      ** subj-fwd-hdr ABNF and ends with the subj-fwd-trl
00218                      ** ABNF, remove the subj-fwd-hdr and subj-fwd-trl and
00219                      ** repeat from step (2).
00220                      **
00221                      **   subj-fwd-hdr    = "[fwd:"
00222                      **
00223                      **   subj-fwd-trl    = "]"
00224                      */
00225 
00226                      if (strncasecmp(p, "[FWD:", 5) == 0)
00227                      {
00228                             q=strrchr(p, ']');
00229                             if (q && q[1] == 0)
00230                             {
00231                                    *q=0;
00232                                    p += 5;
00233                                    *hasrefwd |= CORESUBJ_FWD;
00234 
00235                                    for (q=s; (*q++=*p++) != 0; )
00236                                           ;
00237                                    doit=1;
00238                             }
00239                      }
00240                      break;
00241               }
00242        } while (doit);
00243 
00244        q=s;
00245        while ( (*q++ = *p++) != 0)
00246               ;
00247        if (save_blob_buf)
00248               *save_blob_buf=0;
00249 }
00250 
00251 char *rfc822_coresubj(const char *s, int *hasrefwd)
00252 {
00253        char *q=strdup(s), *r;
00254        int dummy;
00255 
00256        if (!hasrefwd)
00257               hasrefwd= &dummy;
00258 
00259        *hasrefwd=0;
00260        if (!q)       return (0);
00261 
00262        for (r=q; *r; r++)
00263               if ((*r & 0x80) == 0)       /* Just US-ASCII casing, thanks */
00264               {
00265                      if (*r >= 'a' && *r <= 'z')
00266                             *r += 'A'-'a';
00267               }
00268        stripsubj(q, hasrefwd, 0);
00269        return (q);
00270 }
00271 
00272 char *rfc822_coresubj_nouc(const char *s, int *hasrefwd)
00273 {
00274        char *q=strdup(s);
00275        int dummy;
00276 
00277        if (!hasrefwd)
00278               hasrefwd= &dummy;
00279 
00280        *hasrefwd=0;
00281        if (!q)       return (0);
00282 
00283        stripsubj(q, hasrefwd, 0);
00284        return (q);
00285 }
00286 
00287 char *rfc822_coresubj_keepblobs(const char *s)
00288 {
00289        char *q=strdup(s), *r;
00290        int dummy;
00291 
00292        if (!q)       return (0);
00293 
00294        r=strdup(s);
00295        if (!r)
00296        {
00297               free(q);
00298               return (0);
00299        }
00300 
00301        stripsubj(q, &dummy, r);
00302        strcat(r, q);
00303        free(q);
00304        return (r);
00305 }