Back to index

courier  0.68.2
mailfilter.c
Go to the documentation of this file.
00001 #include "config.h"
00002 /*
00003 */
00004 
00005 /*
00006 ** Copyright 2000-2010 Double Precision, Inc.  See COPYING for
00007 ** distribution information.
00008 */
00009 
00010 #include      "mailfilter.h"
00011 #include      "sqwebmail.h"
00012 #include      "maildir.h"
00013 #include      "auth.h"
00014 #include      "maildir/maildirmisc.h"
00015 #include      "maildir/maildirfilter.h"
00016 #include      "maildir/autoresponse.h"
00017 #include      "numlib/numlib.h"
00018 #include      "cgi/cgi.h"
00019 #include      <string.h>
00020 #include      <stdlib.h>
00021 #include      <stdio.h>
00022 
00023 extern void list_folder(const char *);
00024 extern void output_attrencoded(const char *);
00025 
00026 static const char *internal_err=0;
00027 
00028 static void clrfields()
00029 {
00030        cgi_put("currentfilternum", "");
00031        cgi_put("rulename", "");
00032        cgi_put("filtertype", "");
00033        cgi_put("hasrecipienttype", "");
00034        cgi_put("hasrecipientaddr", "");
00035        cgi_put("headername", "");
00036        cgi_put("headervalue", "");
00037        cgi_put("headermatchtype", "");
00038        cgi_put("action", "");
00039        cgi_put("forwardaddy", "");
00040        cgi_put("bouncemsg", "");
00041        cgi_put("savefolder", "");
00042        cgi_put("sizecompare", "");
00043        cgi_put("bytecount", "");
00044        cgi_put("continuefiltering", "");
00045        cgi_put("autoresponse_choose", "");
00046        cgi_put("autoresponse_dsn", "");
00047        cgi_put("autoresponse_regexp", "");
00048        cgi_put("autoresponse_dupe", "");
00049        cgi_put("autoresponse_days", "");
00050        cgi_put("autoresponse_from", "");
00051        cgi_put("autoresponse_noquote", "");
00052 }
00053 
00054 void mailfilter_list()
00055 {
00056 struct maildirfilter mf;
00057 struct maildirfilterrule *r;
00058 unsigned cnt;
00059 
00060        memset(&mf, 0, sizeof(mf));
00061 
00062        if (maildir_filter_loadmaildirfilter(&mf, "."))
00063        {
00064               maildir_filter_freerules(&mf);
00065               return;
00066        }
00067 
00068        for (cnt=0, r=mf.first; r; r=r->next, ++cnt)
00069        {
00070               printf("<option value=\"%u\">", cnt);
00071               output_attrencoded(r->rulename);
00072               printf("</option>");
00073        }
00074        maildir_filter_freerules(&mf);
00075 }
00076 
00077 void mailfilter_init()
00078 {
00079 const char *p;
00080 unsigned n;
00081 struct maildirfilter mf;
00082 struct maildirfilterrule *r;
00083 
00084        if (*cgi("import"))
00085        {
00086               if (maildir_filter_importmaildirfilter("."))
00087               {
00088                      printf("%s", getarg("BADIMPORT"));
00089                      return;
00090               }
00091        }
00092 
00093        if (*cgi("internalerr"))
00094        {
00095        const char *p=internal_err;
00096 
00097        if (*cgi("currentfilternum")) 
00098               printf("<input name=\"currentfilternum\""
00099                      " type=\"hidden\""
00100                      " value=\"%s\" />", cgi("currentfilternum"));
00101               if (p)
00102                      printf("%s", getarg(p));
00103        }
00104        internal_err=0;
00105 
00106        if (*cgi("do.save"))
00107        {
00108               if (maildir_filter_exportmaildirfilter(".") ||
00109                      maildir_filter_importmaildirfilter("."))
00110                      printf("%s", getarg("INTERNAL"));
00111               else
00112                      printf("%s", getarg("UPDATED"));
00113               clrfields();
00114        }
00115 
00116        if (*cgi("do.add"))
00117               clrfields();
00118        memset(&mf, 0, sizeof(mf));
00119 
00120        if (maildir_filter_loadmaildirfilter(&mf, "."))
00121        {
00122               maildir_filter_freerules(&mf);
00123               printf("%s", getarg("BADIMPORT"));
00124               return;
00125        }
00126        if (*(p=cgi("currentfilter")) == 0)
00127        {
00128               maildir_filter_freerules(&mf);
00129               return;
00130        }
00131        n=atoi(p);
00132 
00133        for (r=mf.first; n && r; r=r->next)
00134               --n;
00135        if (!r)
00136        {
00137               maildir_filter_freerules(&mf);
00138               return;
00139        }
00140 
00141        if (*cgi("do.moveup") && r)
00142        {
00143               maildir_filter_ruleup(&mf, r);
00144               maildir_filter_savemaildirfilter(&mf, ".", login_returnaddr());
00145               clrfields();
00146        }
00147        else if (*cgi("do.movedown") && r)
00148        {
00149               maildir_filter_ruledown(&mf, r);
00150               maildir_filter_savemaildirfilter(&mf, ".", login_returnaddr());
00151               clrfields();
00152        }
00153        else if (*cgi("do.delete") && r)
00154        {
00155               maildir_filter_ruledel(&mf, r);
00156               maildir_filter_savemaildirfilter(&mf, ".", login_returnaddr());
00157               clrfields();
00158        }
00159        else if (*cgi("do.edit"))
00160        {
00161        static char *namebuf=0;
00162        static char *headernamebuf=0;
00163        static char *headervaluebuf=0;
00164        static char *actionbuf=0;
00165        char   numbuf[NUMBUFSIZE+1];
00166 
00167               printf("<input name=\"currentfilternum\""
00168                      " type=\"hidden\""
00169                      " value=\"%s\" />", p);
00170 
00171               cgi_put("filtertype",
00172                      r->type == startswith || 
00173                      r->type == endswith ||
00174                      r->type == contains ?
00175                             r->flags & MFR_BODY ? "body":"header":
00176                      r->type == hasrecipient
00177                                    ? "hasrecipient":
00178                      r->type == mimemultipart ?
00179                             r->flags & MFR_DOESNOT ?
00180                                    "nothasmultipart":
00181                                    "hasmultipart":
00182                      r->type == islargerthan ? "hassize":
00183                      r->type == anymessage
00184                                    ? "anymessage":
00185                      r->type == textplain ?
00186                             r->flags & MFR_DOESNOT ?
00187                                    "nothastextplain":
00188                                    "hastextplain":""
00189                             ) ;
00190 
00191               cgi_put("continuefiltering",
00192                             r->flags & MFR_CONTINUE ? "1":"");
00193 
00194               cgi_put("headermatch",
00195                      r->type == startswith ?
00196                             r->flags & MFR_DOESNOT ? "notstartswith":"startswith":
00197                      r->type == endswith ?
00198                             r->flags & MFR_DOESNOT ? "notendswith":"endswith":
00199                      r->type == contains ?
00200                             r->flags & MFR_DOESNOT ? "notcontains":"contains":"");
00201 
00202               if (namebuf)  free(namebuf);
00203               p=r->rulename ? r->rulename:"";
00204               namebuf=malloc(strlen(p)+1);
00205               if (!namebuf) enomem();
00206               strcpy(namebuf, p);
00207               cgi_put("rulename", namebuf);
00208 
00209               p=r->fieldname ? r->fieldname:"";
00210               if (r->type != startswith &&
00211                      r->type != endswith &&
00212                      r->type != contains) p="";
00213               if (r->flags & MFR_BODY)    p="";
00214 
00215               if (headernamebuf)   free(headernamebuf);
00216               headernamebuf=malloc(strlen(p)+1);
00217               if (!headernamebuf)  enomem();
00218               strcpy(headernamebuf, p);
00219               cgi_put("headername", headernamebuf);
00220 
00221               p=r->fieldvalue ? r->fieldvalue:"";
00222               if (r->type != startswith &&
00223                      r->type != endswith &&
00224                      r->type != contains &&
00225                      r->type != hasrecipient &&
00226                      r->type != islargerthan)    p="";
00227 
00228               if (r->type == islargerthan)
00229                      p=libmail_str_size_t( atol(p)+( r->flags & MFR_DOESNOT ? 1:0),
00230                             numbuf);
00231 
00232               if (headervaluebuf)  free(headervaluebuf);
00233 
00234 
00235 
00236               headervaluebuf=malloc(strlen(p)+1);
00237               if (!headervaluebuf) enomem();
00238               strcpy(headervaluebuf, p);
00239 
00240               cgi_put("hasrecipientaddr", "");
00241               cgi_put("headervalue", "");
00242               cgi_put("bytecount", "");
00243               cgi_put("sizecompare", "");
00244 
00245               cgi_put(r->type == hasrecipient ? "hasrecipientaddr":
00246                      r->type == islargerthan ? "bytecount":
00247                             "headervalue", headervaluebuf);
00248 
00249               if (r->type == hasrecipient)
00250                      cgi_put("hasrecipienttype",
00251                             r->flags & MFR_DOESNOT ? "nothasrecipient":
00252                                    "hasrecipient");
00253               if (r->type == islargerthan)
00254                      cgi_put("sizecompare",
00255                             r->flags & MFR_DOESNOT
00256                                    ? "issmallerthan":"islargerthan");
00257               if (actionbuf)       actionbuf=0;
00258               p=r->tofolder;
00259               if (!p)       p="";
00260               actionbuf=malloc(strlen(p)+1);
00261               if (!actionbuf)      enomem();
00262               strcpy(actionbuf, p);
00263 
00264               cgi_put("bouncemsg", "");
00265               cgi_put("forwardaddy", "");
00266               cgi_put("savefolder", "");
00267 
00268               cgi_put("autoresponse_regexp",
00269                      r->flags & MFR_PLAINSTRING ? "":"1");
00270 
00271               if (actionbuf[0] == '!')
00272               {
00273                      cgi_put("action", "forwardto");
00274                      cgi_put("forwardaddy", actionbuf+1);
00275               }
00276               else if (actionbuf[0] == '*')
00277               {
00278                      cgi_put("action", "bounce");
00279                      cgi_put("bouncemsg", actionbuf+1);
00280               }
00281               else if (actionbuf[0] == '+')
00282               {
00283                      struct maildir_filter_autoresp_info mfai;
00284                      static char *autoresp_name_buf=0;
00285                      static char days_buf[NUMBUFSIZE];
00286                      static char *fromhdr=0;
00287 
00288                      if (maildir_filter_autoresp_info_init_str(&mfai, actionbuf+1))
00289                             enomem();
00290 
00291                      if (autoresp_name_buf)
00292                             free(autoresp_name_buf);
00293 
00294                      if ((autoresp_name_buf=strdup(mfai.name)) == NULL)
00295                             enomem();
00296 
00297                      cgi_put("action", "autoresponse");
00298                      cgi_put("autoresponse_choose", autoresp_name_buf);
00299                      cgi_put("autoresponse_dsn",
00300                             mfai.dsnflag ? "1":"");
00301                      
00302                      cgi_put("autoresponse_dupe",
00303                             mfai.days > 0 ? "1":"");
00304 
00305                      libmail_str_size_t(mfai.days, days_buf);
00306                      cgi_put("autoresponse_days", mfai.days ?
00307                             days_buf:"");
00308                      maildir_filter_autoresp_info_free(&mfai);
00309 
00310                      if (fromhdr)
00311                             free(fromhdr);
00312                      fromhdr=strdup(r->fromhdr ? r->fromhdr:"");
00313                      if (!fromhdr)
00314                             enomem();
00315                      cgi_put("autoresponse_from", fromhdr);
00316 
00317                      if (mfai.noquote)
00318                             cgi_put("autoresponse_noquote", "1");
00319               }
00320               else if (strcmp(actionbuf, "exit") == 0)
00321               {
00322                      cgi_put("action", "purge");
00323               }
00324               else
00325               {
00326                      cgi_put("action", "savefolder");
00327                      cgi_put("savefolder",
00328                             strcmp(actionbuf, ".") == 0 ? INBOX:
00329                             *actionbuf == '.' ? actionbuf+1:actionbuf);
00330               }
00331        }
00332        else if (*(p=cgi("currentfilternum")) != 0)
00333        {
00334               printf("<input name=\"currentfilternum\""
00335                      " type=\"hidden\""
00336                      " value=\"%s\" />", p);
00337        }
00338        
00339        
00340 
00341        maildir_filter_freerules(&mf);
00342 }
00343 
00344 void mailfilter_listfolders()
00345 {
00346 char   **folders;
00347 int    i;
00348 const char *f=cgi("savefolder");
00349 
00350        printf("<select name=\"savefolder\">");
00351 
00352        maildir_listfolders(INBOX, ".", &folders);
00353 
00354        for (i=0; folders[i]; i++)
00355        {
00356               const char *p=folders[i];
00357               int selected=0;
00358 
00359               if (strcmp(p, INBOX) &&
00360                   strncmp(p, INBOX ".", sizeof(INBOX)))
00361                      continue;
00362 
00363               printf("<option value=\"");
00364               output_attrencoded(p);
00365               if (strcmp(p, f) == 0)
00366                      selected=1;
00367 
00368               if (strcmp(p, INBOX) == 0)
00369               {
00370                      p=getarg("INBOX");
00371                      selected=0;
00372                      if (strcmp(f, ".") == 0)
00373                             selected=1;
00374               }
00375               else if (strcmp(p, INBOX "." DRAFTS) == 0)
00376                      p=getarg("DRAFTS");
00377               else if (strcmp(p, INBOX "." TRASH) == 0)
00378                      p=getarg("TRASH");
00379               else if (strcmp(p, INBOX "." SENT) == 0)
00380                      p=getarg("SENT");
00381               else
00382                      p=strchr(p, '.')+1;
00383 
00384               printf("\"");
00385               if (selected)
00386                      printf(" selected='selected'");
00387               printf(">");
00388               list_folder(p);
00389               printf("</option>\n");
00390        }
00391 
00392        maildir_freefolders(&folders);
00393        printf("</select>");
00394 }
00395 
00396 void mailfilter_submit()
00397 {
00398 struct maildirfilter mf;
00399 struct maildirfilterrule *r;
00400 const char *p;
00401 enum maildirfiltertype type;
00402 int flags=0;
00403 const char *rulename=0;
00404 const char *fieldname=0;
00405 const char *fieldvalue=0;
00406 char *tofolder=0;
00407 char *fieldname_cpy;
00408 int    err_num;
00409 char   numbuf[NUMBUFSIZE];
00410 const char *autoreply_from="";
00411 
00412        memset(&mf, 0, sizeof(mf));
00413        if (maildir_filter_loadmaildirfilter(&mf, "."))
00414        {
00415               maildir_filter_freerules(&mf);
00416               return;
00417        }
00418 
00419        r=0;
00420        p=cgi("currentfilternum");
00421        if (*p)
00422        {
00423        unsigned n=atoi(p);
00424 
00425               for (r=mf.first; r && n; r=r->next)
00426                      --n;
00427        }
00428 
00429        rulename=cgi("rulename");
00430 
00431        p=cgi("filtertype");
00432        if (strcmp(p, "hasrecipient") == 0)
00433        {
00434               type=hasrecipient;
00435               if (strcmp(cgi("hasrecipienttype"), "nothasrecipient") == 0)
00436                      flags |= MFR_DOESNOT;
00437 
00438               fieldvalue=cgi("hasrecipientaddr");
00439        }
00440        else if (strcmp(p, "hastextplain") == 0)
00441        {
00442               type=textplain;
00443        }
00444        else if (strcmp(p, "nothastextplain") == 0)
00445        {
00446               type=textplain;
00447               flags |= MFR_DOESNOT;
00448        }
00449        else if (strcmp(p, "hasmultipart") == 0)
00450        {
00451               type=mimemultipart;
00452        }
00453        else if (strcmp(p, "nothasmultipart") == 0)
00454        {
00455               type=mimemultipart;
00456               flags |= MFR_DOESNOT;
00457        }
00458        else if (strcmp(p, "hassize") == 0)
00459        {
00460        unsigned long n=atol(cgi("bytecount"));
00461 
00462               type=islargerthan;
00463               if (strcmp(cgi("sizecompare"), "issmallerthan") == 0)
00464               {
00465                      flags |= MFR_DOESNOT;
00466                      if (n) --n;
00467               }
00468               fieldvalue=libmail_str_size_t(n, numbuf);
00469        }
00470        else if (strcmp(p, "anymessage") == 0)
00471        {
00472               type=anymessage;
00473        }
00474        else
00475        {
00476               if (strcmp(p, "body") == 0)
00477                      flags |= MFR_BODY;
00478 
00479               fieldname=cgi("headername");
00480               p=cgi("headermatchtype");
00481               type=strcmp(p, "startswith") == 0 ||
00482                      strcmp(p, "notstartswith") == 0 ? startswith:
00483                      strcmp(p, "contains") == 0 ||
00484                      strcmp(p, "notcontains") == 0 ? contains:endswith;
00485               if (strncmp(p, "not", 3) == 0)
00486                      flags |= MFR_DOESNOT;
00487               fieldvalue=cgi("headervalue");
00488        }
00489 
00490        if (*cgi("continuefiltering"))
00491               flags |= MFR_CONTINUE;
00492 
00493        if (!*cgi("autoresponse_regexp"))
00494               flags |= MFR_PLAINSTRING;
00495 
00496        p=cgi("action");
00497        if (strcmp(p, "forwardto") == 0)
00498        {
00499               p=cgi("forwardaddy");
00500               tofolder=malloc(strlen(p)+2);
00501               if (!tofolder)       enomem();
00502               strcat(strcpy(tofolder, "!"), p);
00503        }
00504        else if (strcmp(p, "bounce") == 0)
00505        {
00506               p=cgi("bouncemsg");
00507               tofolder=malloc(strlen(p)+2);
00508               if (!tofolder)       enomem();
00509               strcat(strcpy(tofolder, "*"), p);
00510        }
00511        else if (strcmp(p, "autoresponse") == 0)
00512        {
00513               struct maildir_filter_autoresp_info mfaii;
00514               char *q;
00515 
00516               p=cgi("autoresponse_choose");
00517 
00518               if (maildir_filter_autoresp_info_init(&mfaii, p))
00519               {
00520                      internal_err="AUTOREPLY";
00521                      cgi_put("internal_err", "1");
00522                      return;
00523               }
00524 
00525               p=cgi("autoresponse_dsn");
00526 
00527               if (*p)
00528                      mfaii.dsnflag=1;
00529 
00530               p=cgi("autoresponse_dupe");
00531               if (*p)
00532               {
00533                      p=cgi("autoresponse_days");
00534                      mfaii.days=atoi(p);
00535               }
00536 
00537               p=cgi("autoresponse_noquote");
00538 
00539               if (*p)
00540                      mfaii.noquote=1;
00541 
00542               q=maildir_filter_autoresp_info_asstr(&mfaii);
00543               maildir_filter_autoresp_info_free(&mfaii);
00544 
00545               if (!q)
00546                      enomem();
00547 
00548               if (!(tofolder=malloc(strlen(q)+2)))
00549               {
00550                      free(q);
00551                      enomem();
00552               }
00553 
00554               tofolder[0]='+';
00555               strcpy(tofolder+1, q);
00556               free(q);
00557               autoreply_from=cgi("autoresponse_from");
00558        }
00559        else if (strcmp(p, "purge") == 0)
00560        {
00561               tofolder = strdup("exit");
00562               if (!tofolder) enomem();
00563        }
00564        else
00565        {
00566               tofolder=strdup(cgi("savefolder"));
00567               if (!tofolder)       enomem();
00568        }
00569 
00570        fieldname_cpy=NULL;
00571 
00572        if (fieldname)
00573        {
00574               char *p;
00575 
00576               fieldname_cpy=strdup(fieldname);
00577 
00578               p=strrchr(fieldname_cpy, ':');
00579 
00580               if (p && p[1] == 0)
00581                      *p=0;
00582        }
00583 
00584        if (!r)
00585               r=maildir_filter_appendrule(&mf, rulename, type, flags, fieldname_cpy,
00586                      fieldvalue, tofolder, autoreply_from, &err_num);
00587        else if (maildir_filter_ruleupdate(&mf, r, rulename, type, flags, fieldname_cpy,
00588                      fieldvalue, tofolder, autoreply_from, &err_num))
00589               r=0;
00590        free(tofolder);
00591        if (fieldname_cpy)
00592               free(fieldname_cpy);
00593        if (r)
00594        {
00595               maildir_filter_savemaildirfilter(&mf, ".", login_returnaddr());
00596               maildir_filter_freerules(&mf);
00597               clrfields();
00598               return;
00599        }
00600        maildir_filter_freerules(&mf);
00601 
00602        internal_err="INTERNAL";
00603        if (err_num == MF_ERR_BADRULENAME)
00604               internal_err= "BADRULENAME";
00605        if (err_num == MF_ERR_EXISTS)
00606               internal_err= "EXISTS";
00607        if (err_num == MF_ERR_BADRULEHEADER)
00608               internal_err= "BADHEADER";
00609        if (err_num == MF_ERR_BADRULEVALUE)
00610               internal_err= "BADVALUE";
00611        if (err_num == MF_ERR_BADRULEFOLDER)
00612               internal_err= "ERRTOFOLDER";
00613        if (err_num == MF_ERR_BADFROMHDR)
00614               internal_err= "FROMHDR";
00615 
00616        cgi_put("internalerr", "1");
00617 }
00618 
00619 int mailfilter_folderused(const char *foldername)
00620 {
00621 struct maildirfilter mf;
00622 struct maildirfilterrule *r;
00623 int    rc;
00624 
00625        memset(&mf, 0, sizeof(mf));
00626        if (maildir_filter_hasmaildirfilter(".") ||
00627               maildir_filter_importmaildirfilter("."))  return (0);
00628 
00629        rc=maildir_filter_loadmaildirfilter(&mf, ".");
00630        maildir_filter_endmaildirfilter(".");
00631        if (rc)
00632        {
00633               maildir_filter_freerules(&mf);
00634               return (0);
00635        }
00636 
00637        for (r=mf.first; r; r=r->next)
00638        {
00639               if (r->tofolder == 0)       continue;
00640               if (strcmp(foldername, r->tofolder) == 0)
00641               {
00642                      maildir_filter_freerules(&mf);
00643                      return (-1);
00644               }
00645        }
00646        maildir_filter_freerules(&mf);
00647        return (0);
00648 }
00649 
00650 int mailfilter_autoreplyused(const char *autoreply)
00651 {
00652        struct maildirfilter mf;
00653        struct maildirfilterrule *r;
00654        int    rc;
00655 
00656        memset(&mf, 0, sizeof(mf));
00657        if (maildir_filter_hasmaildirfilter(".") ||
00658            maildir_filter_importmaildirfilter("."))     return (0);
00659 
00660        rc=maildir_filter_loadmaildirfilter(&mf, ".");
00661        maildir_filter_endmaildirfilter(".");
00662        if (rc)
00663        {
00664               maildir_filter_freerules(&mf);
00665               return (0);
00666        }
00667 
00668        for (r=mf.first; r; r=r->next)
00669        {
00670               struct maildir_filter_autoresp_info mfai;
00671 
00672               if (r->tofolder == 0)       continue;
00673               if (r->tofolder[0] != '+')
00674                      continue;
00675 
00676               if (maildir_filter_autoresp_info_init_str(&mfai, r->tofolder+1))
00677                      enomem();
00678 
00679               if (strcmp(autoreply, mfai.name) == 0)
00680               {
00681                      maildir_filter_autoresp_info_free(&mfai);
00682                      maildir_filter_freerules(&mf);
00683                      return (-1);
00684               }
00685               maildir_filter_autoresp_info_free(&mfai);
00686        }
00687        maildir_filter_freerules(&mf);
00688        return (0);
00689 }
00690 
00691 void mailfilter_cleanup()
00692 {
00693        internal_err=0;
00694 }