Back to index

courier  0.68.2
maildirfilter.c
Go to the documentation of this file.
00001 /*
00002 ** Copyright 2000-2010 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #include      "config.h"
00007 #include      "maildirfilter.h"
00008 #include      "maildirfiltertypelist.h"
00009 #include      "maildirgetquota.h"
00010 #include      "mailbot.h"
00011 
00012 #include      "autoresponse.h"
00013 #include      "numlib/numlib.h"
00014 #include      <stdlib.h>
00015 #include      <string.h>
00016 #include      <stdio.h>
00017 #include      <ctype.h>
00018 #include      <errno.h>
00019 #include      <sys/types.h>
00020 #include      "maildirmisc.h"
00021 
00022 #if HAVE_SYSEXITS_H
00023 #include      <sysexits.h>
00024 #else
00025 #define       EX_SOFTWARE   70
00026 #endif
00027 
00028 #if    HAVE_PCRE_H
00029 #include      <pcre.h>
00030 #else
00031 #if    HAVE_PCRE_PCRE_H
00032 #include      <pcre/pcre.h>
00033 #define HAVE_PCRE_H  1
00034 #endif
00035 #endif
00036 
00037 #if    HAVE_SYS_STAT_H
00038 #include      <sys/stat.h>
00039 #endif
00040 #if    HAVE_UNISTD_H
00041 #include      <unistd.h>
00042 #endif
00043 
00044 
00045 struct maildirfilterrule *maildir_filter_appendrule(struct maildirfilter *r,
00046                                    const char *name,
00047                                    enum maildirfiltertype type,
00048                                    int flags,
00049                                    const char *header,
00050                                    const char *value,
00051                                    const char *folder,
00052                                    const char *fromhdr,
00053                                    int *errcode)
00054 {
00055 struct maildirfilterrule *p=malloc(sizeof(struct maildirfilterrule));
00056 
00057        *errcode=MF_ERR_INTERNAL;
00058 
00059        if (!p)       return (0);
00060        memset(p, 0, sizeof(*p));
00061 
00062        if ((p->prev=r->last) != 0)
00063               p->prev->next=p;
00064        else
00065               r->first=p;
00066        r->last=p;
00067 
00068        if (maildir_filter_ruleupdate(r, p, name, type, flags,
00069                        header, value, folder, fromhdr, errcode))
00070        {
00071               maildir_filter_ruledel(r, p);
00072               return (0);
00073        }
00074        return (p);
00075 }
00076 
00077 int maildir_filter_ruleupdate(struct maildirfilter *r,
00078                 struct maildirfilterrule *p,
00079                 const char *name,
00080                 enum maildirfiltertype type,
00081                 int flags,
00082                 const char *header,
00083                 const char *value,
00084                 const char *folder,
00085                 const char *fromhdr,
00086                 int *errcode)
00087 {
00088        const char *c;
00089        struct maildirfilterrule *pom;
00090 
00091 /*
00092 ** Before creating a new rule, validate all input.
00093 */
00094 
00095        *errcode=0;
00096 
00097        /* rule name: may not contain quotes or control characters. */
00098        *errcode=MF_ERR_BADRULENAME;
00099        if (!name || !*name || strlen(name) > 200)
00100               return (-1);
00101 
00102        for (c=name; *c; c++)
00103               if ((unsigned char)*c < ' ' || *c == '\'' || *c == '"' ||
00104                      *c == '`')
00105                      return (-1);
00106 
00107        /* rule name: may not already exist */
00108        *errcode=MF_ERR_EXISTS;
00109        
00110        for (pom=r->first; pom->next; pom=pom->next) {
00111            if (p!=pom && !strcmp(name, pom->rulename))
00112               return (-1);
00113        }
00114 
00115        /* rule type: we must know what it is */
00116 
00117        switch (type) {
00118        case startswith:
00119        case endswith:
00120        case contains:
00121        case hasrecipient:
00122        case mimemultipart:
00123        case textplain:
00124        case islargerthan:
00125        case anymessage:
00126               break;
00127        default:
00128               *errcode=MF_ERR_BADRULETYPE;
00129               break;
00130        } ;
00131 
00132        /* header: */
00133 
00134        *errcode=MF_ERR_BADRULEHEADER;
00135 
00136        c=header;
00137        if (c && strlen(c) > 200)   return (-1);
00138        if (c == 0 || *c == 0)
00139        {
00140               switch (type) {
00141               case hasrecipient:
00142               case islargerthan:
00143               case mimemultipart:
00144               case textplain:
00145               case anymessage:
00146                      break;
00147               case contains:
00148               case startswith:
00149               case endswith:
00150                      if (flags & MFR_BODY)
00151                             break;
00152                      /* FALLTHRU */
00153               default:
00154                      /* required */
00155 
00156                      return (-1);
00157               }
00158        }
00159        else for ( ; *c; c++)
00160        {
00161               /* no control characters */
00162               if (*c <= ' ' || *c == MDIRSEP[0] || *c >= 127 || *c == '\'' ||
00163                      *c == '\\' || *c == '"' || *c == '`' || *c == '/')
00164                      return (-1);
00165        }
00166 
00167        /* rule pattern */
00168 
00169        *errcode=MF_ERR_BADRULEVALUE;
00170 
00171        c=value;
00172        if (c && strlen(c) > 200)   return (-1);
00173        if (c == 0 || *c == 0)
00174        {
00175               switch (type) {
00176               case mimemultipart:
00177               case textplain:
00178               case anymessage:
00179                      break;
00180               default:
00181                      /* required */
00182 
00183                      return (-1);
00184               }
00185        }
00186        else if (!(flags & MFR_PLAINSTRING))
00187        {
00188               /*
00189               ** Let PCRE decide if this is a valid pattern.
00190               **
00191               ** One exception: the forward slash character, and some other
00192               ** special characters, must always be escaped.
00193               */
00194 
00195               while (*c)
00196               {
00197                      if (*c == '/' || *c == '$' || *c == '!'
00198                             || *c == '`' || (int)(unsigned char)*c < ' '
00199                             || *c == '\'' || *c == '"') return (-1);
00200                                           /* must be escaped */
00201 
00202                      if (type == islargerthan)
00203                      {
00204                             if (!isdigit((int)(unsigned char)*c))
00205                                    return (-1);
00206                      }
00207 
00208                      if (*c == '(')
00209                      {
00210                             if (type == hasrecipient)   return (-1);
00211                             ++c;
00212                             if (*c == ')')       return (-1);
00213                             continue;
00214                      }
00215                      if (*c == ')')
00216                      {
00217                             if (type == hasrecipient)   return (-1);
00218                             ++c;
00219                             continue;
00220                      }
00221                      if (*c == '[')       /* This is a set */
00222                      {
00223                             if (type == hasrecipient)   return (-1);
00224                             ++c;
00225                             for (;;)
00226                             {
00227                                    if (*c == '\'' || *c == '"' ||
00228                                           *c == '`')
00229                                           return (-1); /* must be quoted*/
00230                                    if (*c == '\\')
00231                                           ++c;
00232                                    if (!*c)      return (-1);
00233                                    if ((int)(unsigned char)*c < ' ')
00234                                           return (-1);
00235                                    ++c;
00236                                    if (*c == ']')       break;
00237                                    if (*c != '-')       continue;
00238                                    ++c;
00239 
00240                                    if (*c == '\'' || *c == '"' ||
00241                                           *c == '`')
00242                                           return (-1); /* must be quoted*/
00243                                    if (*c == '\\')
00244                                           ++c;
00245                                    if ((int)(unsigned char)*c < ' ')
00246                                           return (-1);
00247                                    if (!*c)      return (-1);
00248                                    ++c;
00249                                    if (*c == ']')       break;
00250                             }
00251                             ++c;
00252                             continue;
00253                      }
00254 
00255                      if (*c == '\\')
00256                      {
00257                             if (type == hasrecipient)   return (-1);
00258                             ++c;
00259                      }
00260                      if (!*c)      return (-1);
00261                      ++c;
00262               }
00263 
00264 #if HAVE_PCRE_H
00265               switch (type) {
00266               case contains:
00267               case startswith:
00268               case endswith:
00269                      {
00270                             const char *errptr;
00271                             int errindex;
00272 
00273                             pcre *p=pcre_compile(value, 0,
00274                                                &errptr,
00275                                                &errindex,
00276                                                0);
00277 
00278 
00279                             if (p == NULL)
00280                                    return -1;
00281                             pcre_free(p);
00282                      }
00283                      break;
00284               default:
00285                      break;
00286               }
00287 #endif
00288        }
00289 
00290        /* validate FROM header */
00291 
00292        *errcode=MF_ERR_BADFROMHDR;
00293 
00294        while (fromhdr && *fromhdr && isspace((int)(unsigned char)*fromhdr))
00295               ++fromhdr;
00296 
00297        for (c=fromhdr; *c; c++)
00298               if ((int)(unsigned char)*c < ' ')
00299                      return (-1);
00300 
00301        *errcode=MF_ERR_BADRULEFOLDER;
00302 
00303        /* validate name of destination folder */
00304 
00305        c=folder;
00306        if (!c)       return (-1);
00307        if (strlen(c) > 200) return (-1);
00308 
00309        if (*c == '*' || *c == '!')
00310        {
00311               /* Forward, or bounce with an error */
00312 
00313               ++c;
00314               for ( ; *c; c++)
00315               {
00316                      if (strchr("'\"$\\`;(){}#&<>~", *c) ||
00317                             (unsigned char)*c < ' ')
00318                             return (-1);
00319               }
00320        }
00321        else if (*c == '+')  /* Autorespond */
00322        {
00323               struct maildir_filter_autoresp_info ai;
00324 
00325               if (maildir_filter_autoresp_info_init_str(&ai, c+1))
00326                      return (-1);
00327 
00328               maildir_filter_autoresp_info_free(&ai);
00329        }
00330        else if (strcmp(c, "exit") == 0)   /* Purge */
00331        {
00332        }
00333        else
00334        {
00335               char *s;
00336 
00337               if (strcmp(c, INBOX) &&
00338                   strncmp(c, INBOX ".", sizeof(INBOX)))
00339                      return -1;
00340 
00341               s=maildir_name2dir(".", c);
00342 
00343               if (!s)
00344                      return -1;
00345               free(s);
00346        }
00347 
00348        /* OK, we're good */
00349 
00350        *errcode=MF_ERR_INTERNAL;
00351 
00352        if (p->rulename)     free(p->rulename);
00353        if ((p->rulename=strdup(name)) == 0)      return (-1);
00354        p->type=type;
00355        if (p->fieldname)    free(p->fieldname);
00356        if ((p->fieldname=strdup(header ? header:"")) == 0)     return (-1);
00357        if (p->fieldvalue)   free(p->fieldvalue);
00358        if ((p->fieldvalue=strdup(value ? value:"")) == 0)      return (-1);
00359        if (p->tofolder)     free(p->tofolder);
00360        if ((p->tofolder=malloc(strlen(folder)+1)) == 0) return (-1);
00361        strcpy(p->tofolder, folder);
00362 
00363        if (p->fromhdr)             free(p->fromhdr);
00364        if ((p->fromhdr=strdup(fromhdr ? fromhdr:"")) == NULL)
00365               return (-1);
00366 
00367        p->flags=flags;
00368        return (0);
00369 }
00370 
00371 void maildir_filter_ruledel(struct maildirfilter *r, struct maildirfilterrule *p)
00372 {
00373        if (p->prev)  p->prev->next=p->next;
00374        else          r->first=p->next;
00375 
00376        if (p->next)  p->next->prev=p->prev;
00377        else          r->last=p->prev;
00378 
00379        if (p->rulename)     free(p->rulename);
00380        if (p->fieldname)    free(p->fieldname);
00381        if (p->fieldvalue)   free(p->fieldvalue);
00382        if (p->tofolder)     free(p->tofolder);
00383        if (p->fromhdr)             free(p->fromhdr);
00384        free(p);
00385 }
00386 
00387 void maildir_filter_ruleup(struct maildirfilter *r, struct maildirfilterrule *p)
00388 {
00389 struct maildirfilterrule *q;
00390 
00391        q=p->prev;
00392        if (!q)       return;
00393        q->next=p->next;
00394        if (p->next)  p->next->prev=q;
00395        else          r->last=q;
00396 
00397        if ((p->prev=q->prev) != 0) p->prev->next=p;
00398        else   r->first=p;
00399 
00400        p->next=q;
00401        q->prev=p;
00402 }
00403 
00404 void maildir_filter_ruledown(struct maildirfilter *r, struct maildirfilterrule *p)
00405 {
00406 struct maildirfilterrule *q;
00407 
00408        q=p->next;
00409        if (!q)       return;
00410        q->prev=p->prev;
00411        if (q->prev)  q->prev->next=q;
00412        else          r->first=q;
00413 
00414        if ((p->next=q->next) != 0) p->next->prev=p;
00415        else   r->last=p;
00416 
00417        p->prev=q;
00418        q->next=p;
00419 }
00420 
00421 static void print_pattern(FILE *f, int flags, const char *v)
00422 {
00423        if (!(flags & MFR_PLAINSTRING))
00424        {
00425               fprintf(f, "%s%s",
00426                      *v && isspace((int)(unsigned char)*v) ? "\\":"", v);
00427               return;
00428        }
00429 
00430        while (*v)
00431        {
00432               if (!isalnum((int)(unsigned char)*v))
00433                      putc('\\', f);
00434               putc((int)(unsigned char)*v, f);
00435               ++v;
00436        }
00437 }
00438 
00439 int maildir_filter_saverules(struct maildirfilter *r, const char *filename,
00440                const char *maildir,
00441                const char *maildirpath, const char *fromaddr)
00442 {
00443 FILE   *f=fopen(filename, "w");
00444 struct maildirfilterrule *p;
00445 
00446        if (!f)       return (-1);
00447 
00448        fprintf(f,    "#MFMAILDROP=2\n"
00449                      "#\n"
00450                      "# DO NOT EDIT THIS FILE.  This is an automatically"
00451                                           " generated filter.\n"
00452                      "\n");
00453 
00454        for (fprintf(f, "FROM='"); *fromaddr; fromaddr++)
00455        {
00456               if (*fromaddr == '\'' || *fromaddr == '\\')
00457                      putc('\\', f);
00458               putc(*fromaddr, f);
00459        }
00460        fprintf(f, "\'\n");
00461 
00462        for (p=r->first; p; p=p->next)
00463        {
00464        const char *fieldname=p->fieldname ? p->fieldname:"";
00465        const char *fieldvalue=p->fieldvalue ? p->fieldvalue:"";
00466        const char *tofolder=p->tofolder ? p->tofolder:"";
00467 
00468               fprintf(f, "##Op:%s\n",
00469                      typelist[p->type].name);
00470               fprintf(f, "##Header:%s\n", fieldname);
00471               fprintf(f, "##Value:%s\n", fieldvalue);
00472               fprintf(f, "##Folder:%s\n",
00473                      strcmp(tofolder, INBOX) == 0 ? ".":
00474                      strncmp(tofolder, INBOX ".", sizeof(INBOX)) == 0
00475                      ? strchr(tofolder, '.'):tofolder);
00476               fprintf(f, "##From:%s\n", p->fromhdr ? p->fromhdr:"");
00477 
00478               if (p->flags & MFR_PLAINSTRING)
00479                      fprintf(f, "##PlainString\n");
00480               if (p->flags & MFR_DOESNOT)
00481                      fprintf(f, "##DoesNot\n");
00482               if (p->flags & MFR_BODY)
00483                      fprintf(f, "##Body\n");
00484               if (p->flags & MFR_CONTINUE)
00485                      fprintf(f, "##Continue\n");
00486 
00487               fprintf(f, "##Name:%s\n\n", p->rulename ? p->rulename:"");
00488 
00489               fprintf(f, "\nif (");
00490 
00491               if (p->flags & MFR_DOESNOT)
00492                      fprintf(f, "!");
00493               fprintf(f, "(");
00494 
00495               switch (p->type)     {
00496               case startswith:
00497                      if (p->flags & MFR_BODY)
00498                      {
00499                             fprintf(f, "/^");
00500                             print_pattern(f, p->flags, fieldvalue);
00501                             fprintf(f, "/:b");
00502                      }
00503                      else
00504                      {
00505                             fprintf(f, "/^%s: *", fieldname);
00506                             print_pattern(f, p->flags, fieldvalue);
00507                             fprintf(f, "/");
00508                      }
00509                      break;
00510               case endswith:
00511                      if (p->flags & MFR_BODY)
00512                      {
00513                             fprintf(f, "/");
00514                             print_pattern(f, p->flags, fieldvalue);
00515                             fprintf(f, "$/:b");
00516                      }
00517                      else
00518                      {
00519                             fprintf(f, "/^%s:.*", fieldname);
00520                             print_pattern(f, p->flags, fieldvalue);
00521                             fprintf(f, "$/");
00522                      }
00523                      break;
00524               case contains:
00525                      if (p->flags & MFR_BODY)
00526                      {
00527                             fprintf(f, "/");
00528                             print_pattern(f, p->flags, fieldvalue);
00529                             fprintf(f, "/:b");
00530                      }
00531                      else
00532                      {
00533                             fprintf(f, "/^%s:.*", fieldname);
00534                             print_pattern(f, p->flags, fieldvalue);
00535                             fprintf(f, "/");
00536                      }
00537                      break;
00538               case hasrecipient:
00539                      fprintf(f, "hasaddr(\"%s\")", fieldvalue);
00540                      break;
00541               case mimemultipart:
00542                      fprintf(f, "/^Content-Type: *multipart\\/mixed/");
00543                      break;
00544               case textplain:
00545                      fprintf(f, " (! /^Content-Type:/) || "
00546                                    "/^Content-Type: text\\/plain$/ || "
00547                                    "/^Content-Type: text\\/plain;/");
00548                      break;
00549               case islargerthan:
00550                      fprintf(f, "$SIZE > %s", fieldvalue);
00551                      break;
00552               case anymessage:
00553                      fprintf(f, "1");
00554                      break;
00555               }
00556               fprintf(f, "))\n"
00557                      "{\n");
00558 
00559               if (*tofolder == '!')
00560               {
00561                      fprintf(f, "    %s \"| $SENDMAIL -f \" '\"\"' \" %s\"\n",
00562                             p->flags & MFR_CONTINUE ? "cc":"to",
00563                                    tofolder+1);
00564               }
00565               else if (*tofolder == '*')
00566               {
00567                      fprintf(f, "    echo \"%s\"\n"
00568                             "    EXITCODE=%d\n"
00569                             "    exit\n", tofolder+1, EX_SOFTWARE);
00570               }
00571               else if (*tofolder == '+')
00572               {
00573                      struct maildir_filter_autoresp_info ai;
00574 
00575                      if (maildir_filter_autoresp_info_init_str(&ai, tofolder+1) == 0)
00576                      {
00577                             if (p->fromhdr && p->fromhdr[0])
00578                             {
00579                                    const char *cp;
00580 
00581                                    fprintf(f, "    AUTOREPLYFROM='");
00582 
00583 
00584                                    for (cp=p->fromhdr; *cp; ++cp)
00585                                    {
00586                                           if (*cp == '\'' || *cp == '\\')
00587                                                  putc('\\', f);
00588                                           putc(*cp, f);
00589                                    }
00590                                    fprintf(f, "'\n");
00591                             }
00592                             else
00593                                    fprintf(f, "    AUTOREPLYFROM=\"$FROM\"\n"
00594                                           );
00595 
00596                             fprintf(f, "   `%s -A \"X-Sender: $FROM\""
00597                                    " -A \"From: $AUTOREPLYFROM\"",
00598                                    MAILBOT);
00599                             if (ai.dsnflag)
00600                                    fprintf(f, " -M \"$FROM\"");
00601                             fprintf(f, " -m \"%s/autoresponses/%s\"",
00602                                    maildirpath, ai.name);
00603                             if (ai.noquote)
00604                                    fprintf(f, " -N");
00605                             if (ai.days > 0)
00606                                    fprintf(f,
00607                                           " -d \"%s/autoresponses/"
00608                                           "%s.dat\" -D %u",
00609                                    maildirpath, ai.name, ai.days);
00610                             fprintf(f, " $SENDMAIL -t -f \"\"`\n");
00611                             maildir_filter_autoresp_info_free(&ai);
00612                      }
00613               }
00614               else if (strcmp(tofolder, "exit") == 0)
00615               {
00616                      fprintf(f, "    exit\n");
00617               }
00618               else
00619               {
00620                      char *s;
00621 
00622                      s=maildir_name2dir(maildirpath, tofolder);
00623 
00624                      if (!s)
00625                             fprintf(f, "  # INTERNAL ERROR in maildir_name2dir\n");
00626                      else
00627                      {
00628                             fprintf(f,
00629                                    "   %s \"%s/.\"\n",
00630                                    p->flags & MFR_CONTINUE ? "cc":"to",
00631                                    s);
00632                             free(s);
00633                      }
00634               }
00635               fprintf(f, "}\n\n");
00636        }
00637        fflush(f);
00638        if (ferror(f))
00639        {
00640               fclose(f);
00641               return (-1);
00642        }
00643        fprintf(f, "to \"%s/.\"\n", maildirpath);
00644        if (fclose(f))
00645               return (-1);
00646        if (chmod(filename, 0600))
00647               return (-1);
00648 
00649        return (0);
00650 }
00651 
00652 int maildir_filter_loadrules(struct maildirfilter *r, const char *filename)
00653 {
00654 FILE   *f=fopen(filename, "r");
00655 char   buf[BUFSIZ];
00656 char   *p;
00657 
00658 enum   maildirfiltertype new_type;
00659 char   new_header[256];
00660 char   new_value[256];
00661 char   new_folder[256];
00662 char   new_autoreplyfrom[512];
00663 
00664 int    flags;
00665 
00666        if (!f)       return (MF_LOADNOTFOUND);
00667 
00668        if (fgets(buf, sizeof(buf), f) == 0 ||
00669               strncmp(buf, "#MFMAILDROP=", 12))
00670        {
00671               fclose(f);
00672               return (MF_LOADFOREIGN);
00673        }
00674 
00675        flags=atoi(buf+12);
00676        if (flags != 1 && flags != 2)
00677        {
00678               fclose(f);
00679               return (MF_LOADFOREIGN);
00680        }
00681 
00682        new_type=contains;
00683        new_header[0]=0;
00684        new_value[0]=0;
00685        new_folder[0]=0;
00686        new_autoreplyfrom[0]=0;
00687        flags=0;
00688 
00689 #define       SET(f,b) { f[0]=0; strncat( (f), (b), sizeof(f)-1); }
00690 
00691        while ( fgets(buf, sizeof(buf), f))
00692        {
00693        int    i;
00694 
00695               p=strchr(buf, '\n');
00696               if (p) *p=0;
00697               if (strncmp(buf, "##", 2))  continue;
00698               p=buf+2;
00699               while ( *p && isspace((int)(unsigned char)*p))
00700                      ++p;
00701 
00702               if (strncasecmp(p, "From:", 5) == 0)
00703               {
00704                      p += 5;
00705                      SET(new_autoreplyfrom, p);
00706                      continue;
00707               }
00708 
00709 
00710               if (strncasecmp(p, "Op:", 3) == 0)
00711               {
00712                      p += 3;
00713 
00714                      for (i=0; typelist[i].name; i++)
00715                             if (strcasecmp(typelist[i].name, p) == 0)
00716                                    break;
00717                      if (!typelist[i].name)
00718                      {
00719                             fclose(f);
00720                             return (MF_LOADFOREIGN);
00721                      }
00722                      new_type=typelist[i].type;
00723                      continue;
00724               }
00725 
00726               if (strncasecmp(p, "Header:", 7) == 0)
00727               {
00728                      p += 7;
00729                      SET(new_header, p);
00730                      continue;
00731               }
00732 
00733               if (strncasecmp(p, "Value:", 6) == 0)
00734               {
00735                      p += 6;
00736                      SET(new_value, p);
00737                      continue;
00738               }
00739 
00740               if (strncasecmp(p, "Folder:", 7) == 0)
00741               {
00742                      p += 7;
00743 
00744                      if (*p == '.')
00745                      {
00746                             strcpy(new_folder, INBOX);
00747                      }
00748                      else
00749                             new_folder[0]=0;
00750 
00751                      if (strcmp(p, "."))
00752                             strncat(new_folder, p,
00753                                    sizeof(new_folder)-1-strlen(new_folder));
00754                      continue;
00755               }
00756 
00757               if (strcasecmp(p, "plainstring") == 0)
00758               {
00759                      flags |= MFR_PLAINSTRING;
00760                      continue;
00761               }
00762 
00763               if (strcasecmp(p, "doesnot") == 0)
00764               {
00765                      flags |= MFR_DOESNOT;
00766                      continue;
00767               }
00768 
00769               if (strcasecmp(p, "continue") == 0)
00770               {
00771                      flags |= MFR_CONTINUE;
00772                      continue;
00773               }
00774 
00775               if (strcasecmp(p, "body") == 0)
00776               {
00777                      flags |= MFR_BODY;
00778                      continue;
00779               }
00780 
00781               if (strncasecmp(p, "Name:", 5) == 0)
00782               {
00783               int dummy;
00784 
00785                      p += 5;
00786                      maildir_filter_appendrule(r, p, new_type, flags,
00787                                             new_header,
00788                                             new_value, new_folder,
00789                                             new_autoreplyfrom, &dummy);
00790                      new_type=contains;
00791                      new_header[0]=0;
00792                      new_value[0]=0;
00793                      new_folder[0]=0;
00794                      new_autoreplyfrom[0]=0;
00795                      flags=0;
00796               }
00797        }
00798        fclose(f);
00799        return (MF_LOADOK);
00800 }
00801 
00802 int maildir_filter_autoresp_info_init(struct maildir_filter_autoresp_info *i, const char *c)
00803 {
00804        memset(i, 0, sizeof(*i));
00805 
00806        if (maildir_autoresponse_validate(NULL, c))
00807               return (-1);
00808        i->name=strdup(c);
00809        if (!(i->name))
00810               return (-1);
00811        return (0);
00812 }
00813 
00814 int maildir_filter_autoresp_info_init_str(struct maildir_filter_autoresp_info *i, const char *c)
00815 {
00816        char *p;
00817 
00818        memset(i, 0, sizeof(*i));
00819        i->name=strdup(c);
00820        if (!(i->name))
00821               return (-1);
00822 
00823        if (strtok(i->name, " \t\r\n") == NULL)
00824        {
00825               errno=EINVAL;
00826               free(i->name);
00827               i->name=0;
00828               return (-1);
00829        }
00830 
00831        while ((p=strtok(NULL, " \t\r\n")) != NULL)
00832        {
00833               if (strncmp(p, "dsn=", 4) == 0)
00834                      i->dsnflag=atoi(p+4) ? 1:0;
00835               else if (strncmp(p, "days=", 5) == 0)
00836                      i->days=atoi(p+5);
00837               else if (strcmp(p, "noquote") == 0)
00838                      i->noquote=1;
00839        }
00840        return (0);
00841 }
00842 
00843 void maildir_filter_autoresp_info_free(struct maildir_filter_autoresp_info *i)
00844 {
00845        if (i->name)
00846        {
00847               free(i->name);
00848               i->name=0;
00849        }
00850 }
00851 
00852 char *maildir_filter_autoresp_info_asstr(struct maildir_filter_autoresp_info *i)
00853 {
00854        char days_buf[NUMBUFSIZE+10];
00855 
00856        const char *dsn_arg="";
00857        const char *days_arg="";
00858        const char *noquote_arg="";
00859 
00860        char *p;
00861 
00862        if (i->dsnflag)
00863               dsn_arg=" dsn=1";
00864        if (i->days > 0)
00865        {
00866               strcpy(days_buf, " days=");
00867               libmail_str_size_t(i->days, days_buf+6);
00868               days_arg=days_buf;
00869        }
00870 
00871        if (i->noquote)
00872               noquote_arg=" noquote";
00873 
00874        p=malloc(strlen(i->name)+1+strlen(dsn_arg)+strlen(days_arg)+
00875                strlen(noquote_arg));
00876        if (!p)
00877               return (NULL);
00878 
00879        strcat(strcat(strcat(strcpy(p, i->name), dsn_arg), days_arg),
00880               noquote_arg);
00881        return (p);
00882 }