Back to index

webcit  8.12-dfsg
sieve.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1996-2012 by the citadel.org team
00003  *
00004  * This program is open source software.  You can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License version 3.
00006  *
00007  * This program is distributed in the hope that it will be useful,
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00010  * GNU General Public License for more details.
00011  *
00012  * FIXME: add logic to exclude the webcit-generated script from the manual script selection
00013  */
00014 
00015 #include "webcit.h"
00016 
00017 #define MAX_SCRIPTS  100
00018 #define MAX_RULES    50
00019 #define RULES_SCRIPT "__WebCit_Generated_Script__"
00020 
00021 
00022 /*
00023  * Helper function for output_sieve_rule() to output strings with quotes escaped
00024  */
00025 void osr_sanitize(char *str) {
00026        int i, len;
00027 
00028        if (str == NULL) return;
00029        len = strlen(str);
00030        for (i=0; i<len; ++i) {
00031               if (str[i]=='\"') {
00032                      str[i] = '\'' ;
00033               }
00034               else if (isspace(str[i])) {
00035                      str[i] = ' ';
00036               }
00037        }
00038 }
00039 
00040 
00041 /*
00042  * Output parseable Sieve script code based on rules input
00043  */
00044 void output_sieve_rule(char *hfield, char *compare, char *htext, char *sizecomp, int sizeval,
00045                      char *action, char *fileinto, char *redirect, char *automsg, char *final,
00046                      char *my_addresses)
00047 {
00048        char *comp1 = "";
00049        char *comp2 = "";
00050 
00051        osr_sanitize(htext);
00052        osr_sanitize(fileinto);
00053        osr_sanitize(redirect);
00054        osr_sanitize(automsg);
00055 
00056        /* Prepare negation and match operators that will be used iff we apply a conditional */
00057 
00058        if (!strcasecmp(compare, "contains")) {
00059               comp1 = "";
00060               comp2 = ":contains";
00061        }
00062        else if (!strcasecmp(compare, "notcontains")) {
00063               comp1 = "not";
00064               comp2 = ":contains";
00065        }
00066        else if (!strcasecmp(compare, "is")) {
00067               comp1 = "";
00068               comp2 = ":is";
00069        }
00070        else if (!strcasecmp(compare, "isnot")) {
00071               comp1 = "not";
00072               comp2 = ":is";
00073        }
00074        else if (!strcasecmp(compare, "matches")) {
00075               comp1 = "";
00076               comp2 = ":matches";
00077        }
00078        else if (!strcasecmp(compare, "notmatches")) {
00079               comp1 = "not";
00080               comp2 = ":matches";
00081        }
00082 
00083        /* Now do the conditional */
00084 
00085        if (!strcasecmp(hfield, "from")) {
00086               serv_printf("if%s header %s \"From\" \"%s\"",
00087                      comp1, comp2,
00088                      htext
00089               );
00090        }
00091 
00092        else if (!strcasecmp(hfield, "tocc")) {
00093               serv_printf("if%s header %s [\"To\", \"Cc\"] \"%s\"",
00094                      comp1, comp2,
00095                      htext
00096               );
00097        }
00098 
00099        else if (!strcasecmp(hfield, "subject")) {
00100               serv_printf("if%s header %s \"Subject\" \"%s\"",
00101                      comp1, comp2,
00102                      htext
00103               );
00104        }
00105 
00106        else if (!strcasecmp(hfield, "replyto")) {
00107               serv_printf("if%s header %s \"Reply-to\" \"%s\"",
00108                      comp1, comp2,
00109                      htext
00110               );
00111        }
00112 
00113        else if (!strcasecmp(hfield, "sender")) {
00114               serv_printf("if%s header %s \"Sender\" \"%s\"",
00115                      comp1, comp2,
00116                      htext
00117               );
00118        }
00119 
00120        else if (!strcasecmp(hfield, "resentfrom")) {
00121               serv_printf("if%s header %s \"Resent-from\" \"%s\"",
00122                      comp1, comp2,
00123                      htext
00124               );
00125        }
00126 
00127        else if (!strcasecmp(hfield, "resentto")) {
00128               serv_printf("if%s header %s \"Resent-to\" \"%s\"",
00129                      comp1, comp2,
00130                      htext
00131               );
00132        }
00133 
00134        else if (!strcasecmp(hfield, "xmailer")) {
00135               serv_printf("if%s header %s \"X-Mailer\" \"%s\"",
00136                      comp1, comp2,
00137                      htext
00138               );
00139        }
00140 
00141        else if (!strcasecmp(hfield, "xspamflag")) {
00142               serv_printf("if%s header %s \"X-Spam-Flag\" \"%s\"",
00143                      comp1, comp2,
00144                      htext
00145               );
00146        }
00147 
00148        else if (!strcasecmp(hfield, "xspamstatus")) {
00149               serv_printf("if%s header %s \"X-Spam-Status\" \"%s\"",
00150                      comp1, comp2,
00151                      htext
00152               );
00153        }
00154 
00155        else if (!strcasecmp(hfield, "listid")) {
00156               serv_printf("if%s header %s \"List-ID\" \"%s\"",
00157                      comp1, comp2,
00158                      htext
00159               );
00160        }
00161 
00162        else if (!strcasecmp(hfield, "envfrom")) {
00163               serv_printf("if%s envelope %s \"From\" \"%s\"",
00164                      comp1, comp2,
00165                      htext
00166               );
00167        }
00168 
00169        else if (!strcasecmp(hfield, "envto")) {
00170               serv_printf("if%s envelope %s \"To\" \"%s\"",
00171                      comp1, comp2,
00172                      htext
00173               );
00174        }
00175 
00176        else if (!strcasecmp(hfield, "size")) {
00177               if (!strcasecmp(sizecomp, "larger")) {
00178                      serv_printf("if size :over %d", sizeval);
00179               }
00180               else if (!strcasecmp(sizecomp, "smaller")) {
00181                      serv_printf("if size :under %d", sizeval);
00182               }
00183               else { /* failsafe - should never get here, but just in case... */
00184                      serv_printf("if size :over 1");
00185               }
00186        }
00187 
00188        /* Open braces if we're in a conditional loop */
00189 
00190        if (strcasecmp(hfield, "all")) {
00191               serv_printf("{");
00192        }
00193 
00194        /* Do action */
00195 
00196        if (!strcasecmp(action, "keep")) {
00197               serv_printf("keep;");
00198        }
00199 
00200        else if (!strcasecmp(action, "discard")) {
00201               serv_printf("discard;");
00202        }
00203 
00204        else if (!strcasecmp(action, "reject")) {
00205               serv_printf("reject \"%s\";", automsg);
00206        }
00207 
00208        else if (!strcasecmp(action, "fileinto")) {
00209               serv_printf("fileinto \"%s\";", fileinto);
00210        }
00211 
00212        else if (!strcasecmp(action, "redirect")) {
00213               serv_printf("redirect \"%s\";", redirect);
00214        }
00215 
00216        else if (!strcasecmp(action, "vacation")) {
00217               serv_printf("vacation :addresses [%s]\n\"%s\";", my_addresses, automsg);
00218        }
00219 
00220        /* Do 'final' action */
00221 
00222        if (!strcasecmp(final, "stop")) {
00223               serv_printf("stop;");
00224        }
00225 
00226        /* Close the braces if we're in a conditional loop */
00227 
00228        if (strcasecmp(hfield, "all")) {
00229               serv_printf("}");
00230        }
00231 
00232        /* End of rule. */
00233 }
00234 
00235 
00236 /*
00237  * Translate the fields from the rule editor into something we can save...
00238  */
00239 void parse_fields_from_rule_editor(void) {
00240 
00241        int active;
00242        char hfield[256];
00243        char compare[32];
00244        char htext[256];
00245        char sizecomp[32];
00246        int sizeval;
00247        char action[32];
00248        char fileinto[128];
00249        char redirect[256];
00250        char automsg[1024];
00251        char final[32];
00252        int i;
00253        char buf[256];
00254        char fname[256];
00255        char rule[2048];
00256        char encoded_rule[4096];
00257        char my_addresses[4096];
00258        
00259        /* Enumerate my email addresses in case they are needed for a vacation rule */
00260        my_addresses[0] = 0;
00261        serv_puts("GVEA");
00262        serv_getln(buf, sizeof buf);
00263        if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
00264               if (!IsEmptyStr(my_addresses)) {
00265                      strcat(my_addresses, ",\n");
00266               }
00267               strcat(my_addresses, "\"");
00268               strcat(my_addresses, buf);
00269               strcat(my_addresses, "\"");
00270        }
00271 
00272        /* Now generate the script and write it to the Citadel server */
00273        serv_printf("MSIV putscript|%s|", RULES_SCRIPT);
00274        serv_getln(buf, sizeof buf);
00275        if (buf[0] != '4') {
00276               return;
00277        }
00278 
00279        serv_puts("# THIS SCRIPT WAS AUTOMATICALLY GENERATED BY WEBCIT.");
00280        serv_puts("# ");
00281        serv_puts("# Do not attempt to manually edit it.  If you do so,");
00282        serv_puts("# your changes will be overwritten the next time WebCit");
00283        serv_puts("# saves its mail filtering rule set.  If you really want");
00284        serv_puts("# to use these rules as the basis for another script,");
00285        serv_puts("# copy them to another script and save that instead.");
00286        serv_puts("");
00287        serv_puts("require \"fileinto\";");
00288        serv_puts("require \"reject\";");
00289        serv_puts("require \"vacation\";");
00290        serv_puts("require \"envelope\";");
00291        serv_puts("");
00292 
00293        for (i=0; i<MAX_RULES; ++i) {
00294               
00295               strcpy(rule, "");
00296 
00297               sprintf(fname, "active%d", i);
00298               active = !strcasecmp(BSTR(fname), "on") ;
00299 
00300               if (active) {
00301 
00302                      sprintf(fname, "hfield%d", i);
00303                      safestrncpy(hfield, BSTR(fname), sizeof hfield);
00304        
00305                      sprintf(fname, "compare%d", i);
00306                      safestrncpy(compare, BSTR(fname), sizeof compare);
00307        
00308                      sprintf(fname, "htext%d", i);
00309                      safestrncpy(htext, BSTR(fname), sizeof htext);
00310        
00311                      sprintf(fname, "sizecomp%d", i);
00312                      safestrncpy(sizecomp, BSTR(fname), sizeof sizecomp);
00313        
00314                      sprintf(fname, "sizeval%d", i);
00315                      sizeval = IBSTR(fname);
00316        
00317                      sprintf(fname, "action%d", i);
00318                      safestrncpy(action, BSTR(fname), sizeof action);
00319        
00320                      sprintf(fname, "fileinto%d", i);
00321                      safestrncpy(fileinto, BSTR(fname), sizeof fileinto);
00322        
00323                      sprintf(fname, "redirect%d", i);
00324                      safestrncpy(redirect, BSTR(fname), sizeof redirect);
00325        
00326                      sprintf(fname, "automsg%d", i);
00327                      safestrncpy(automsg, BSTR(fname), sizeof automsg);
00328        
00329                      sprintf(fname, "final%d", i);
00330                      safestrncpy(final, BSTR(fname), sizeof final);
00331        
00332                      snprintf(rule, sizeof rule, "%d|%s|%s|%s|%s|%d|%s|%s|%s|%s|%s",
00333                             active, hfield, compare, htext, sizecomp, sizeval, action, fileinto,
00334                             redirect, automsg, final
00335                      );
00336        
00337                      CtdlEncodeBase64(encoded_rule, rule, strlen(rule)+1, 0);
00338                      serv_printf("# WEBCIT_RULE|%d|%s|", i, encoded_rule);
00339                      output_sieve_rule(hfield, compare, htext, sizecomp, sizeval,
00340                                    action, fileinto, redirect, automsg, final, my_addresses);
00341                      serv_puts("");
00342               }
00343 
00344 
00345        }
00346 
00347        serv_puts("stop;");
00348        serv_puts("000");
00349 }
00350 
00351 
00352 /*
00353  * save sieve config
00354  */
00355 void save_sieve(void) {
00356        int bigaction;
00357        char script_names[MAX_SCRIPTS][64];
00358        int num_scripts = 0;
00359        int i;
00360        char this_name[64];
00361        char buf[256];
00362 
00363        if (!havebstr("save_button")) {
00364               AppendImportantMessage(_("Cancelled.  Changes were not saved."), -1);
00365               display_main_menu();
00366               return;
00367        }
00368 
00369        parse_fields_from_rule_editor();
00370 
00371        serv_puts("MSIV listscripts");
00372        serv_getln(buf, sizeof(buf));
00373        if (buf[0] == '1') while (serv_getln(buf, sizeof(buf)), strcmp(buf, "000")) {
00374               if (num_scripts < MAX_SCRIPTS) {
00375                      extract_token(script_names[num_scripts], buf, 0, '|', 64);
00376                      ++num_scripts;
00377               }
00378        }
00379 
00380        bigaction = ibstr("bigaction");
00381 
00382        if (bigaction == 0) {
00383               serv_puts("MSIV setactive||");
00384               serv_getln(buf, sizeof buf);
00385        }
00386 
00387        else if (bigaction == 1) {
00388               serv_printf("MSIV setactive|%s|", RULES_SCRIPT);
00389               serv_getln(buf, sizeof buf);
00390        }
00391 
00392        else if (bigaction == 2) {
00393               serv_printf("MSIV setactive|%s|", bstr("active_script"));
00394               serv_getln(buf, sizeof buf);
00395        }
00396 
00397        if (num_scripts > 0) {
00398               for (i=0; i<num_scripts; ++i) {
00399                      /*
00400                       * We only want to save the scripts from the "manually edited scripts"
00401                       * screen.  The script that WebCit generates from its ruleset will be
00402                       * auto-generated by parse_fields_from_rule_editor() and saved there.
00403                       */
00404                      if (strcasecmp(script_names[i], RULES_SCRIPT)) {
00405                             serv_printf("MSIV putscript|%s|", script_names[i]);
00406                             serv_getln(buf, sizeof buf);
00407                             if (buf[0] == '4') {
00408                                    snprintf(this_name, sizeof this_name, "text_%s", script_names[i]);
00409                                    striplt((char *)BSTR(this_name)); /* TODO: get rid of typecast*/
00410                                    serv_write(BSTR(this_name), strlen(BSTR(this_name)));
00411                                    serv_puts("\n000");
00412                             }
00413                      }
00414               }
00415        }
00416 
00417        AppendImportantMessage(_("Your changes have been saved."), -1);
00418        display_main_menu();
00419        return;
00420 }
00421 
00422 
00423 void display_sieve_add_or_delete(void) {
00424        output_headers(1, 1, 2, 0, 0, 0);
00425        do_template("sieve_add");
00426        wDumpContent(1);
00427 }
00428 
00429 
00430 
00431 /*
00432  * create a new script
00433  * take the web environment script name and create it on the citadel server
00434  */
00435 void create_script(void) {
00436        char buf[256];
00437 
00438        serv_printf("MSIV getscript|%s", bstr("script_name"));
00439        serv_getln(buf, sizeof buf);
00440        if (buf[0] == '1') {        // does script exist already?
00441               while (serv_getln(buf, sizeof(buf)), strcmp(buf, "000")) {
00442                                    // yes -- flush the output
00443               }
00444        }
00445        else {
00446                                    // no -- safe to create a new one by this name
00447               serv_printf("MSIV putscript|%s", bstr("script_name"));
00448               serv_getln(buf, sizeof buf);
00449               if (buf[0] == '4') {
00450                      serv_puts("keep;");
00451                      serv_puts("000");
00452               }
00453        }
00454 
00455        display_sieve_add_or_delete();
00456 }
00457 
00458 
00459 /*
00460  * delete a script
00461  */
00462 void delete_script(void) {
00463        char buf[256];
00464 
00465        serv_printf("MSIV deletescript|%s", bstr("script_name"));
00466        serv_getln(buf, sizeof buf);
00467        display_sieve_add_or_delete();
00468 }
00469 
00470 
00471 /*
00472  * dummy panel indicating to the user that the server doesn't support Sieve
00473  */
00474 void display_no_sieve(void) {
00475 
00476        output_headers(1, 1, 1, 0, 0, 0);
00477        do_template("sieve_none");
00478        wDumpContent(1);
00479 }
00480 
00481 
00482 typedef struct __SieveListing {
00483        int IsActive;
00484        int IsRulesScript;
00485        StrBuf *Name;
00486        StrBuf *Content;
00487 } SieveListing;
00488 
00489 int ConditionalSieveScriptIsActive(StrBuf *Target, WCTemplputParams *TP)
00490 {
00491        SieveListing     *SieveList = (SieveListing *)CTX;
00492        return SieveList->IsActive;
00493 }
00494 int ConditionalSieveScriptIsRulesScript(StrBuf *Target, WCTemplputParams *TP)
00495 {
00496        SieveListing     *SieveList = (SieveListing *)CTX;
00497        return SieveList->IsActive;
00498 }
00499 void tmplput_SieveScriptName(StrBuf *Target, WCTemplputParams *TP) 
00500 {
00501        SieveListing     *SieveList = (SieveListing *)CTX;
00502        StrBufAppendTemplate(Target, TP, SieveList->Name, 0);
00503 }
00504 void tmplput_SieveScriptContent(StrBuf *Target, WCTemplputParams *TP) 
00505 {
00506        SieveListing     *SieveList = (SieveListing *)CTX;
00507        StrBufAppendTemplate(Target, TP, SieveList->Content, 0);
00508 }
00509 void FreeSieveListing(void *vSieveListing)
00510 {
00511        SieveListing *List = (SieveListing*) vSieveListing;
00512 
00513        FreeStrBuf(&List->Name);
00514        free(List);
00515 }
00516 
00517 HashList *GetSieveScriptListing(StrBuf *Target, WCTemplputParams *TP)
00518 {
00519         wcsession *WCC = WC;
00520        StrBuf *Line;
00521        int num_scripts = 0;
00522        int rules_script_active = 0;
00523        int have_rules_script = 0;
00524        const char *pch;
00525        HashPos  *it;
00526        int Done = 0;
00527        SieveListing *Ruleset;
00528 
00529        if (WCC->KnownSieveScripts != NULL) {
00530               return WCC->KnownSieveScripts;
00531        }
00532 
00533        serv_puts("MSIV listscripts");
00534        Line = NewStrBuf();
00535        StrBuf_ServGetln(Line);
00536        if (GetServerStatus(Line, NULL) == 1) 
00537        {
00538               WCC->KnownSieveScripts = NewHash(1, Flathash);
00539 
00540               while(!Done && (StrBuf_ServGetln(Line) >= 0) )
00541                      if ( (StrLength(Line)==3) && 
00542                           !strcmp(ChrPtr(Line), "000")) 
00543                      {
00544                             Done = 1;
00545                      }
00546                      else
00547                      {
00548                             pch = NULL;
00549                             Ruleset = (SieveListing *) malloc(sizeof(SieveListing));
00550                             Ruleset->Name = NewStrBufPlain(NULL, StrLength(Line));
00551                             StrBufExtract_NextToken(Ruleset->Name, Line, &pch, '|');
00552                             Ruleset->IsActive = StrBufExtractNext_int(Line, &pch, '|'); 
00553                             Ruleset->Content = NULL;
00554 
00555                             if (!strcasecmp(ChrPtr(Ruleset->Name), RULES_SCRIPT))
00556                             {
00557                                    Ruleset->IsRulesScript = 1;
00558                                    have_rules_script = 1;
00559                                    if (Ruleset->IsActive)
00560                                    {
00561                                           rules_script_active = 1;
00562                                           PutBstr(HKEY("__SIEVE:RULESSCRIPT"), NewStrBufPlain(HKEY("1")));
00563                                    }
00564                             }
00565                             Put(WCC->KnownSieveScripts, IKEY(num_scripts), Ruleset, FreeSieveListing);
00566 
00567                             ++num_scripts;
00568                      }
00569        }
00570 
00571        if ((num_scripts > 0) && (rules_script_active == 0)) {
00572               PutBstr(HKEY("__SIEVE:EXTERNAL_SCRIPT"), NewStrBufPlain(HKEY("1")));
00573        }
00574 
00575        if (num_scripts > have_rules_script)
00576        {
00577               long rc = 0;
00578               long len;
00579               const char *Key;
00580               void *vRuleset;
00581 
00582               /* 
00583                * ok; we have custom scripts, expose that via bstr, and load the payload.
00584                */
00585               PutBstr(HKEY("__SIEVE:HAVE_EXTERNAL_SCRIPT"), NewStrBufPlain(HKEY("1")));
00586 
00587               it = GetNewHashPos(WCC->KnownSieveScripts, 0);
00588               while (GetNextHashPos(WCC->KnownSieveScripts, it, &len, &Key, &vRuleset) && 
00589                      (vRuleset != NULL))
00590               {
00591                      Ruleset = (SieveListing *) vRuleset;
00592                      serv_printf("MSIV getscript|%s", ChrPtr(Ruleset->Name));
00593                      StrBuf_ServGetln(Line);
00594                      if (GetServerStatus(Line, NULL) == 1) 
00595                      {
00596                             Ruleset->Content = NewStrBuf();
00597                             Done = 0;
00598                             while(!Done && (rc = StrBuf_ServGetln(Line), rc >= 0) )
00599                                    if ( (StrLength(Line)==3) && 
00600                                         !strcmp(ChrPtr(Line), "000")) 
00601                                    {
00602                                           Done = 1;
00603                                    }
00604                                    else
00605                                    {
00606                                           if (StrLength(Ruleset->Content)>0)
00607                                                  StrBufAppendBufPlain(Ruleset->Content, HKEY("\n"), 0);
00608                                           StrBufAppendBuf(Ruleset->Content, Line, 0);
00609                                    }
00610                             if (rc < 0) break;
00611                      }
00612               }
00613        }
00614        FreeStrBuf(&Line);
00615        return WCC->KnownSieveScripts;
00616 }
00617 
00618 
00619 typedef enum __eSieveHfield 
00620 {
00621        from,         
00622        tocc,         
00623        subject,      
00624        replyto,      
00625        sender,       
00626        resentfrom,   
00627        resentto,     
00628        envfrom,      
00629        envto, 
00630        xmailer,      
00631        xspamflag,    
00632        xspamstatus,  
00633        listid,       
00634        size,         
00635        all
00636 } eSieveHfield;
00637 
00638 typedef enum __eSieveCompare {
00639        contains,
00640        notcontains,
00641        is,
00642        isnot,
00643        matches,
00644        notmatches
00645 } eSieveCompare;
00646 
00647 typedef enum __eSieveAction {
00648        keep,
00649        discard,
00650        reject,
00651        fileinto,
00652        redirect,
00653        vacation
00654 } eSieveAction;
00655 
00656 
00657 typedef enum __eSieveSizeComp {
00658        larger,
00659        smaller
00660 } eSieveSizeComp;
00661 
00662 typedef enum __eSieveFinal {
00663        econtinue,
00664        estop
00665 } eSieveFinal;
00666 
00667 
00668 typedef struct __SieveRule {
00669        int active;
00670        int sizeval;
00671        eSieveHfield hfield;
00672        eSieveCompare compare;
00673        StrBuf *htext;
00674        eSieveSizeComp sizecomp;
00675        eSieveAction Action;
00676        StrBuf *fileinto;
00677        StrBuf *redirect;
00678        StrBuf *automsg;
00679        eSieveFinal final;
00680 }SieveRule;
00681 
00682 
00683 
00684 int ConditionalSieveRule_hfield(StrBuf *Target, WCTemplputParams *TP)
00685 {
00686        SieveRule     *Rule = (SieveRule *)CTX;
00687        
00688         return GetTemplateTokenNumber(Target, 
00689                                       TP, 
00690                                       3, 
00691                                       from)
00692                 ==
00693                 Rule->hfield;
00694 }
00695 int ConditionalSieveRule_compare(StrBuf *Target, WCTemplputParams *TP)
00696 {
00697        SieveRule     *Rule = (SieveRule *)CTX;
00698         return GetTemplateTokenNumber(Target, 
00699                                       TP, 
00700                                       3, 
00701                                       contains)
00702                 ==
00703               Rule->compare;
00704 }
00705 int ConditionalSieveRule_action(StrBuf *Target, WCTemplputParams *TP)
00706 {
00707        SieveRule     *Rule = (SieveRule *)CTX;
00708         return GetTemplateTokenNumber(Target, 
00709                                       TP, 
00710                                       3, 
00711                                       keep)
00712                 ==
00713               Rule->Action; 
00714 }
00715 int ConditionalSieveRule_sizecomp(StrBuf *Target, WCTemplputParams *TP)
00716 {
00717        SieveRule     *Rule = (SieveRule *)CTX;
00718         return GetTemplateTokenNumber(Target, 
00719                                       TP, 
00720                                       3, 
00721                                       larger)
00722                 ==
00723               Rule->sizecomp;
00724 }
00725 int ConditionalSieveRule_final(StrBuf *Target, WCTemplputParams *TP)
00726 {
00727        SieveRule     *Rule = (SieveRule *)CTX;
00728         return GetTemplateTokenNumber(Target, 
00729                                       TP, 
00730                                       3, 
00731                                       econtinue)
00732                 ==
00733               Rule->final;
00734 }
00735 int ConditionalSieveRule_ThisRoom(StrBuf *Target, WCTemplputParams *TP)
00736 {
00737        SieveRule     *Rule = (SieveRule *)CTX;
00738         return GetTemplateTokenNumber(Target, 
00739                                       TP, 
00740                                       3, 
00741                                       econtinue)
00742                 ==
00743               Rule->final;
00744 }
00745 int ConditionalSieveRule_Active(StrBuf *Target, WCTemplputParams *TP)
00746 {
00747        SieveRule     *Rule = (SieveRule *)CTX;
00748         return Rule->active;
00749 }
00750 void tmplput_SieveRule_htext(StrBuf *Target, WCTemplputParams *TP) 
00751 {
00752        SieveRule     *Rule = (SieveRule *)CTX;
00753        StrBufAppendTemplate(Target, TP, Rule->htext, 0);
00754 }
00755 void tmplput_SieveRule_fileinto(StrBuf *Target, WCTemplputParams *TP) 
00756 {
00757        SieveRule     *Rule = (SieveRule *)CTX;
00758        StrBufAppendTemplate(Target, TP, Rule->fileinto, 0);
00759 }
00760 void tmplput_SieveRule_redirect(StrBuf *Target, WCTemplputParams *TP) 
00761 {
00762        SieveRule     *Rule = (SieveRule *)CTX;
00763        StrBufAppendTemplate(Target, TP, Rule->redirect, 0);
00764 }
00765 void tmplput_SieveRule_automsg(StrBuf *Target, WCTemplputParams *TP) 
00766 {
00767        SieveRule     *Rule = (SieveRule *)CTX;
00768        StrBufAppendTemplate(Target, TP, Rule->automsg, 0);
00769 }
00770 void tmplput_SieveRule_sizeval(StrBuf *Target, WCTemplputParams *TP) 
00771 {
00772        SieveRule     *Rule = (SieveRule *)CTX;
00773        StrBufAppendPrintf(Target, "%d", Rule->sizeval);
00774 }
00775 
00776 void tmplput_SieveRule_lookup_FileIntoRoom(StrBuf *Target, WCTemplputParams *TP) 
00777 {
00778        void *vRoom;
00779        SieveRule     *Rule = (SieveRule *)CTX;
00780         wcsession *WCC = WC;
00781        HashList *Rooms = GetRoomListHashLKRA(Target, TP);
00782 
00783        GetHash(Rooms, SKEY(Rule->fileinto), &vRoom);
00784        WCC->ThisRoom = (folder*) vRoom;
00785 }
00786 
00787 void FreeSieveRule(void *vRule)
00788 {
00789        SieveRule *Rule = (SieveRule*) vRule;
00790 
00791        FreeStrBuf(&Rule->htext);
00792        FreeStrBuf(&Rule->fileinto);
00793        FreeStrBuf(&Rule->redirect);
00794        FreeStrBuf(&Rule->automsg);
00795        
00796        free(Rule);
00797 }
00798 
00799 #define WC_RULE_HEADER "# WEBCIT_RULE|"
00800 HashList *GetSieveRules(StrBuf *Target, WCTemplputParams *TP)
00801 {
00802        StrBuf *Line = NULL;
00803        StrBuf *EncodedRule = NULL;
00804        int n = 0;
00805        const char *pch = NULL;
00806        HashList *SieveRules = NULL;
00807        int Done = 0;
00808        SieveRule *Rule = NULL;
00809 
00810        SieveRules = NewHash(1, Flathash);
00811        serv_printf("MSIV getscript|"RULES_SCRIPT);
00812        Line = NewStrBuf();
00813        EncodedRule = NewStrBuf();
00814        StrBuf_ServGetln(Line);
00815        if (GetServerStatus(Line, NULL) == 1) 
00816        {
00817               while(!Done && (StrBuf_ServGetln(Line) >= 0) )
00818                      if ( (StrLength(Line)==3) && 
00819                           !strcmp(ChrPtr(Line), "000")) 
00820                      {
00821                             Done = 1;
00822                      }
00823                      else
00824                      {
00825                             pch = NULL;
00826                             /* We just care for our encoded header and skip everything else */
00827                             if ((StrLength(Line) > sizeof(WC_RULE_HEADER) - 1) &&
00828                                 (!strncasecmp(ChrPtr(Line), HKEY(WC_RULE_HEADER))))
00829                             {
00830                                    StrBufSkip_NTokenS(Line, &pch, '|', 1);
00831                                    n = StrBufExtractNext_int(Line, &pch, '|'); 
00832                                    StrBufExtract_NextToken(EncodedRule, Line, &pch, '|');
00833                                    StrBufDecodeBase64(EncodedRule);
00834 
00835                                    Rule = (SieveRule*) malloc(sizeof(SieveRule));
00836 
00837                                    Rule->htext = NewStrBufPlain (NULL, StrLength(EncodedRule));
00838 
00839                                    Rule->fileinto = NewStrBufPlain (NULL, StrLength(EncodedRule));
00840                                    Rule->redirect = NewStrBufPlain (NULL, StrLength(EncodedRule));
00841                                    Rule->automsg = NewStrBufPlain (NULL, StrLength(EncodedRule));
00842 
00843                                    /* Grab our existing values to populate */
00844                                    pch = NULL;
00845                                    Rule->active = StrBufExtractNext_int(EncodedRule, &pch, '|');
00846                                    StrBufExtract_NextToken(Line, EncodedRule, &pch, '|');
00847                                    
00848                                    Rule->hfield = (eSieveHfield) GetTokenDefine(SKEY(Line), tocc);
00849                                    StrBufExtract_NextToken(Line, EncodedRule, &pch, '|');
00850                                    Rule->compare = (eSieveCompare) GetTokenDefine(SKEY(Line), contains);
00851                                    StrBufExtract_NextToken(Rule->htext, EncodedRule, &pch, '|');
00852                                    StrBufExtract_NextToken(Line, EncodedRule, &pch, '|');
00853                                    Rule->sizecomp = (eSieveSizeComp) GetTokenDefine(SKEY(Line), larger);
00854                                    Rule->sizeval = StrBufExtractNext_int(EncodedRule, &pch, '|');
00855                                    StrBufExtract_NextToken(Line, EncodedRule, &pch, '|');
00856                                    Rule->Action = (eSieveAction) GetTokenDefine(SKEY(Line), keep);
00857                                    StrBufExtract_NextToken(Rule->fileinto, EncodedRule, &pch, '|');
00858                                    StrBufExtract_NextToken(Rule->redirect, EncodedRule, &pch, '|');
00859                                    StrBufExtract_NextToken(Rule->automsg, EncodedRule, &pch, '|');
00860                                    StrBufExtract_NextToken(Line, EncodedRule, &pch, '|');
00861                                    Rule->final = (eSieveFinal) GetTokenDefine(SKEY(Line), econtinue);
00862                                    Put(SieveRules, IKEY(n), Rule, FreeSieveRule);
00863                                    n++;
00864                             }
00865                      }
00866        }
00867 
00868        while (n < MAX_RULES) {
00869               Rule = (SieveRule*) malloc(sizeof(SieveRule));
00870               memset(Rule, 0, sizeof(SieveRule));
00871               Put(SieveRules, IKEY(n), Rule, FreeSieveRule);
00872            
00873               n++;
00874        }
00875 
00876 
00877        FreeStrBuf(&EncodedRule);
00878        FreeStrBuf(&Line);
00879        return SieveRules;
00880 }
00881 
00882 void
00883 SessionDetachModule_SIEVE
00884 (wcsession *sess)
00885 {
00886        DeleteHash(&sess->KnownSieveScripts);
00887 }
00888 
00889 void 
00890 InitModule_SIEVE
00891 (void)
00892 {
00893        REGISTERTokenParamDefine(from);           
00894        REGISTERTokenParamDefine(tocc);           
00895        REGISTERTokenParamDefine(subject); 
00896        REGISTERTokenParamDefine(replyto); 
00897        REGISTERTokenParamDefine(sender);  
00898        REGISTERTokenParamDefine(resentfrom);     
00899        REGISTERTokenParamDefine(resentto);       
00900        REGISTERTokenParamDefine(envfrom); 
00901        REGISTERTokenParamDefine(envto);   
00902        REGISTERTokenParamDefine(xmailer); 
00903        REGISTERTokenParamDefine(xspamflag);      
00904        REGISTERTokenParamDefine(xspamstatus);    
00905        REGISTERTokenParamDefine(listid);  
00906        REGISTERTokenParamDefine(size);           
00907        REGISTERTokenParamDefine(all);
00908 
00909        REGISTERTokenParamDefine(contains);
00910        REGISTERTokenParamDefine(notcontains);
00911        REGISTERTokenParamDefine(is);
00912        REGISTERTokenParamDefine(isnot);
00913        REGISTERTokenParamDefine(matches);
00914        REGISTERTokenParamDefine(notmatches);
00915 
00916        REGISTERTokenParamDefine(keep);
00917        REGISTERTokenParamDefine(discard);
00918        REGISTERTokenParamDefine(reject);
00919        REGISTERTokenParamDefine(fileinto);
00920        REGISTERTokenParamDefine(redirect);
00921        REGISTERTokenParamDefine(vacation);
00922 
00923        REGISTERTokenParamDefine(larger);
00924        REGISTERTokenParamDefine(smaller);
00925 
00926        /* these are c-keyworads, so do it by hand. */
00927        RegisterTokenParamDefine(HKEY("continue"), econtinue);
00928        RegisterTokenParamDefine(HKEY("stop"), estop);
00929 
00930        RegisterIterator("SIEVE:SCRIPTS", 0, NULL, GetSieveScriptListing, NULL, NULL, CTX_SIEVELIST, CTX_NONE, IT_NOFLAG);
00931 
00932        RegisterConditional(HKEY("COND:SIEVE:SCRIPT:ACTIVE"), 0, ConditionalSieveScriptIsActive, CTX_SIEVELIST);
00933        RegisterConditional(HKEY("COND:SIEVE:SCRIPT:ISRULES"), 0, ConditionalSieveScriptIsRulesScript, CTX_SIEVELIST);
00934        RegisterNamespace("SIEVE:SCRIPT:NAME", 0, 1, tmplput_SieveScriptName, NULL, CTX_SIEVELIST);
00935        RegisterNamespace("SIEVE:SCRIPT:CONTENT", 0, 1, tmplput_SieveScriptContent, NULL, CTX_SIEVELIST);
00936 
00937  
00938        RegisterIterator("SIEVE:RULES", 0, NULL, GetSieveRules, NULL, DeleteHash, CTX_SIEVESCRIPT, CTX_NONE, IT_NOFLAG);
00939 
00940        RegisterConditional(HKEY("COND:SIEVE:ACTIVE"), 1, ConditionalSieveRule_Active, CTX_SIEVESCRIPT);
00941        RegisterConditional(HKEY("COND:SIEVE:HFIELD"), 1, ConditionalSieveRule_hfield, CTX_SIEVESCRIPT);
00942        RegisterConditional(HKEY("COND:SIEVE:COMPARE"), 1, ConditionalSieveRule_compare, CTX_SIEVESCRIPT);
00943        RegisterConditional(HKEY("COND:SIEVE:ACTION"), 1, ConditionalSieveRule_action, CTX_SIEVESCRIPT);
00944        RegisterConditional(HKEY("COND:SIEVE:SIZECOMP"), 1, ConditionalSieveRule_sizecomp, CTX_SIEVESCRIPT);
00945        RegisterConditional(HKEY("COND:SIEVE:FINAL"), 1, ConditionalSieveRule_final, CTX_SIEVESCRIPT);
00946        RegisterConditional(HKEY("COND:SIEVE:THISROOM"), 1, ConditionalSieveRule_ThisRoom, CTX_SIEVESCRIPT);
00947 
00948        RegisterNamespace("SIEVE:SCRIPT:HTEXT", 0, 1, tmplput_SieveRule_htext, NULL, CTX_SIEVESCRIPT);
00949        RegisterNamespace("SIEVE:SCRIPT:SIZE", 0, 1, tmplput_SieveRule_sizeval, NULL, CTX_SIEVESCRIPT);
00950        RegisterNamespace("SIEVE:SCRIPT:FILEINTO", 0, 1, tmplput_SieveRule_fileinto, NULL, CTX_SIEVESCRIPT);
00951        RegisterNamespace("SIEVE:SCRIPT:REDIRECT", 0, 1, tmplput_SieveRule_redirect, NULL, CTX_SIEVESCRIPT);
00952        RegisterNamespace("SIEVE:SCRIPT:AUTOMSG", 0, 1, tmplput_SieveRule_automsg, NULL, CTX_SIEVESCRIPT);
00953 
00954        /* fetch our room into WCC->ThisRoom, to evaluate while iterating over rooms with COND:THIS:THAT:ROOM */
00955        RegisterNamespace("SIEVE:SCRIPT:LOOKUP_FILEINTO", 0, 1, tmplput_SieveRule_lookup_FileIntoRoom, NULL, CTX_SIEVESCRIPT);
00956        WebcitAddUrlHandler(HKEY("save_sieve"), "", 0, save_sieve, 0);
00957        WebcitAddUrlHandler(HKEY("create_script"), "", 0, create_script, 0);
00958        WebcitAddUrlHandler(HKEY("delete_script"), "", 0, delete_script, 0);
00959        WebcitAddUrlHandler(HKEY("display_sieve_add_or_delete"), "", 0, display_sieve_add_or_delete, 0);
00960 }