it now builds but does not do inbox filtering
authorArt Cancro <ajc@citadel.org>
Thu, 16 Jul 2020 20:53:15 +0000 (16:53 -0400)
committerArt Cancro <ajc@citadel.org>
Thu, 16 Jul 2020 20:53:15 +0000 (16:53 -0400)
16 files changed:
citadel/citadel.h
citadel/config.h
citadel/configure.ac
citadel/control.c
citadel/docs/citadelapi.txt
citadel/docs/test_suite.txt [deleted file]
citadel/include/ctdl_module.h
citadel/internet_addressing.c
citadel/modules/ctdlproto/serv_session.c
citadel/modules/migrate/serv_migrate.c
citadel/modules/sieve/serv_sieve.c
citadel/modules/upgrade/serv_upgrade.c
citadel/serv_extensions.c
citadel/serv_sieve.h [deleted file]
webcit/sieve.c
webcit/webcit.h

index 6289547c8ff595bff6933d6376313430235b8285..fe109090c63502f96e674e99a0999b3e8066da3d 100644 (file)
@@ -35,7 +35,7 @@ extern "C" {
  */
 #define CITADEL        PACKAGE_STRING
 
-#define REV_LEVEL      929             // This version
+#define REV_LEVEL      930             // This version
 #define REV_MIN                591             // Oldest compatible database
 #define EXPORT_REV_MIN 760             // Oldest compatible export files
 #define LIBCITADEL_MIN 922             // Minimum required version of libcitadel
@@ -111,6 +111,7 @@ struct ctdluser {                   // User record
        long msgnum_bio;                // msgnum of user's profile (bio)
        long msgnum_pic;                // msgnum of user's avatar (photo)
        char emailaddrs[512];           // Internet email addresses
+       long msgnum_inboxrules;         // msgnum of user's inbox filtering rules
 };
 
 
index 9fc59f48050ae6aeebda4f49d110eadfe49ab9f4..4c6d050ab5e51848fd9d523d71cd72c2b15e7366 100644 (file)
@@ -79,12 +79,12 @@ struct legacy_config {
        char c_journal_dest[128];
        char c_default_cal_zone[128];
        int c_pftcpdict_port;
-       int c_managesieve_port;
+       int c_niu_9;
        int c_auth_mode;
        char c_niu_8[256];
-       int c_niu_9;
-       char c_niu_10[256];
+       int c_niu_10;
        char c_niu_11[256];
+       char c_niu_12[256];
        char c_rbl_at_greeting;
        char c_master_user[32];
        char c_master_pass[32];
index 02507872000b55f127cfce6b534bb059066e4b98..1c7d7ae58d5cabdc5a798f80c9ffb9feca7bfc2d 100644 (file)
@@ -510,22 +510,6 @@ AC_CHECK_HEADER(libical/ical.h,
 )
 
 
-dnl Checks for the libsieve mailbox sorting library.
-AC_CHECK_HEADER(sieve2.h,
-       [AC_CHECK_LIB(sieve, sieve2_license,
-               [
-                       SERVER_LIBS="-lsieve $SERVER_LIBS"
-               ],
-               [
-                       AC_MSG_ERROR(libsieve was not found and is required.  More info: http://www.citadel.org/doku.php/installation:start)
-               ]
-       ,
-       )],
-       [
-               AC_MSG_ERROR(sieve2.h was not found and is required.  More info: http://www.citadel.org/doku.php/installation:start)
-       ]
-)
-
 saved_CFLAGS="$CFLAGS"
 CFLAGS="$CFLAGS $SERVER_LIBS"
 dnl Check for libcitadel
index cabf6df1314a3cc439230345db9f0f2798f0b8c9..936deae33c2b5643eb8806994586d44700ca4eb4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This module handles states which are global to the entire server.
  *
- * Copyright (c) 1987-2019 by the citadel.org team
+ * Copyright (c) 1987-2020 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3.
@@ -181,7 +181,7 @@ long get_new_message_number(void)
 /*
  * CtdlGetCurrentMessageNumber()  -  Obtain the current highest message number in the system
  * This provides a quick way to initialise a variable that might be used to indicate
- * messages that should not be processed. EG. a new Sieve script will use this
+ * messages that should not be processed.   For example, an inbox rules script will use this
  * to record determine that messages older than this should not be processed.
  *
  * (Why is this function here?  Can't we just go straight to the config variable it fetches?)
index 6c983540ef947aa32cdf28e6aa0abae116a7daf2..d0c754a7814e66272a060e491ba5a36f790e87d5 100644 (file)
@@ -203,8 +203,7 @@ cause the message to be rejected by the SMTP server.
 
  Register or remove a function with the room processing system.
 Registered functions are called in the order they are registered when a message
-is added to a room. This allows modules such as Sieve to process new messages
-appearing in a room.
+is added to a room. This allows modules to process new messages appearing in a room.
 
 
  void CtdlRegisterXmsgHook(int (*fcn_ptr) (char *, char *, char *), int order)
diff --git a/citadel/docs/test_suite.txt b/citadel/docs/test_suite.txt
deleted file mode 100644 (file)
index bb975e6..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-SYSTEM TESTING PROPOSAL
-
-This document is intended as a discussion of possible automated tests. It does
-not describe any existing tests.
-
-
----
-
-
-First we should create a client that leverages expect (or something similar) to
-perform automated testing of the client interface. Tests can be written as
-expect scripts.
-
-Each system being tested will need to create an aide level user for the test
-client to connect as.
-
-The test client will create another user to carry out the tests. This allows the
-aide level user to vary the level of the test user and check the access level
-code.
-
-----
-
-
-For a first step each test site should create a test user that can send internet
-mail.
-This test user needs some sieve rules to forward mail around (eventually this
-will be created automatically by the test client). These rules will forward mail
-to other test users at other sites participating in the test system and to a
-networked room.
-Each system participating in the test should share some rooms.
-
-The idea is:
-       1. A test site posts a message to its test user using citmail or some
-other email prog.
-       2. The sieve rules forward the message to each of the other test users
-at the other sites.
-       3. The sieve rules for the other test users detect that the message was
-forwarded to them and they file it into a networked room
-       4. By virtue of the networked room the message returns to the
-originating system where the administrator can see it.
-
-Once I (davew) have written my module to alter the message body we can have it
-add text to the message to indicate the full path of the message.
-
-
index b1d8b0219f1a298a69f10fb77b2b89c7bf6d2931..6d16624b584d93dcd9d45e6f8d2ce6f32a8b76cc 100644 (file)
@@ -196,7 +196,7 @@ void CtdlBumpNewMailCounter(long which_user);
 /*
  * CtdlGetCurrentMessageNumber()  -  Obtain the current highest message number in the system
  * This provides a quick way to initialise a variable that might be used to indicate
- * messages that should not be processed. EG. a new Sieve script will use this
+ * messages that should not be processed.  For example, a new inbox script will use this
  * to record determine that messages older than this should not be processed.
  * This function is defined in control.c
  */
index 416586bedeb0e9bd35503e1715aca1dc661737c9..a9561d6312aa1980335d0748d9ff9fe4c28e9a7c 100644 (file)
@@ -2,7 +2,7 @@
  * This file contains functions which handle the mapping of Internet addresses
  * to users on the Citadel system.
  *
- * Copyright (c) 1987-2019 by the citadel.org team
+ * Copyright (c) 1987-2020 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3.
@@ -353,7 +353,7 @@ int CtdlIsMe(char *addr, int addr_buf_len)
 
 
 /* If the last item in a list of recipients was truncated to a partial address,
- * remove it completely in order to avoid choking libSieve
+ * remove it completely in order to avoid choking library functions.
  */
 void sanitize_truncated_recipient(char *str)
 {
index b1b6d42350f87d7590614a04f91f747c84caec81..739de3fa9adb9a721d4cf429d13825bbfcbcc6b7 100644 (file)
@@ -1,7 +1,7 @@
 /* 
  * Server functions which perform operations on user objects.
  *
- * Copyright (c) 1987-2019 by the citadel.org team
+ * Copyright (c) 1987-2020 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License, version 3.
@@ -64,7 +64,7 @@ void cmd_info(char *cmdbuf) {
        cprintf("%s\n", CtdlGetConfigStr("c_moreprompt"));
        cprintf("1\n"); /* 1 = yes, this system supports floors */
        cprintf("1\n"); /* 1 = we support the extended paging options */
-       cprintf("\n");  /* nonce no longer supported */
+       cprintf("\n");  /* no longer used */
        cprintf("1\n"); /* 1 = yes, this system supports the QNOP command */
 
 #ifdef HAVE_LDAP
@@ -83,10 +83,10 @@ void cmd_info(char *cmdbuf) {
 
        cprintf("%s\n", CtdlGetConfigStr("c_default_cal_zone"));
 
-       cprintf("0\n");         /* load average         (no longer used) */
-       cprintf("0\n");         /* worker average       (no longer used) */
-       cprintf("0\n");         /* thread count         (no longer used) */
-       cprintf("1\n");         /* yes, Sieve mail filtering is supported */
+       cprintf("0\n"); /* no longer used */
+       cprintf("0\n"); /* no longer used */
+       cprintf("0\n"); /* no longer used */
+       cprintf("0\n"); /* no longer used */
 
        cprintf("%d\n", CtdlGetConfigInt("c_enable_fulltext"));
        cprintf("%s\n", svn_revision());
index 7c62d34652754747a03a03ab6e433f6e67965d1e..f6d705568d691fc52d8f27f4dea8c610c44d0396 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This module dumps and/or loads the Citadel database in XML format.
  *
- * Copyright (c) 1987-2019 by the citadel.org team
+ * Copyright (c) 1987-2020 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 3.
@@ -135,6 +135,8 @@ void migr_export_users_backend(char *username, void *data) {
        client_write(HKEY("<u_fullname>"));     xml_strout(u.fullname);         client_write(HKEY("</u_fullname>\n"));
        cprintf("<u_msgnum_bio>%ld</u_msgnum_bio>\n", u.msgnum_bio);
        cprintf("<u_msgnum_pic>%ld</u_msgnum_pic>\n", u.msgnum_pic);
+       cprintf("<u_emailaddrs>%s</u_emailaddrs>\n", u.emailaddrs);
+       cprintf("<u_msgnum_inboxrules>%ld</u_msgnum_inboxrules>\n", u.msgnum_inboxrules);
        client_write(HKEY("</user>\n"));
 }
 
@@ -586,6 +588,8 @@ int migr_userrecord(void *data, const char *el)
        else if (!strcasecmp(el, "u_fullname"))                 safestrncpy(usbuf.fullname, ChrPtr(migr_chardata), sizeof usbuf.fullname);
        else if (!strcasecmp(el, "u_msgnum_bio"))               usbuf.msgnum_bio = atol(ChrPtr(migr_chardata));
        else if (!strcasecmp(el, "u_msgnum_pic"))               usbuf.msgnum_pic = atol(ChrPtr(migr_chardata));
+       else if (!strcasecmp(el, "u_emailaddrs"))               safestrncpy(usbuf.emailaddrs, ChrPtr(migr_chardata), sizeof usbuf.emailaddrs);
+       else if (!strcasecmp(el, "u_msgnum_inboxrules"))        usbuf.msgnum_inboxrules = atol(ChrPtr(migr_chardata));
        else return 0;
        return 1;
 }
index 437bd662b8d37c7abcaa292578cf4cfcfe445803..24438b0b9bf2fff12154197cba05372cc97754c7 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * This module glues libSieve to the Citadel server in order to implement
- * the Sieve mailbox filtering language (RFC 3028).
+ * Inbox handling rules
  *
  * Copyright (c) 1987-2020 by the citadel.org team
  *
 #include "msgbase.h"
 #include "internet_addressing.h"
 #include "ctdl_module.h"
-#include "serv_sieve.h"
 
-struct RoomProcList *sieve_list = NULL;
-char *msiv_extensions = NULL;
-
-
-/*
- * Callback function to send libSieve trace messages to Citadel log facility
- */
-int ctdl_debug(sieve2_context_t *s, void *my)
-{
-       syslog(LOG_DEBUG, "%s", sieve2_getvalue_string(s, "message"));
-       return SIEVE2_OK;
-}
-
-
-/*
- * Callback function to log script parsing errors
- */
-int ctdl_errparse(sieve2_context_t *s, void *my)
-{
-       syslog(LOG_WARNING, "Error in script, line %d: %s",
-                 sieve2_getvalue_int(s, "lineno"),
-                 sieve2_getvalue_string(s, "message")
-       );
-       return SIEVE2_OK;
-}
-
-
-/*
- * Callback function to log script execution errors
- */
-int ctdl_errexec(sieve2_context_t *s, void *my)
-{
-       syslog(LOG_WARNING, "Error executing script: %s",
-                 sieve2_getvalue_string(s, "message")
-               );
-       return SIEVE2_OK;
-}
 
+#if 0
 
 /*
  * Callback function to redirect a message to a different folder
  */
-int ctdl_redirect(sieve2_context_t *s, void *my)
+int ctdl_redirect(void)
 {
        struct ctdl_sieve *cs = (struct ctdl_sieve *)my;
        struct CtdlMessage *msg = NULL;
@@ -354,28 +316,6 @@ int ctdl_vacation(sieve2_context_t *s, void *my)
 }
 
 
-#if 0
-/*
- * Callback function to parse addresses per local system convention
- * It is disabled because we don't support subaddresses.
- */
-int ctdl_getsubaddress(sieve2_context_t *s, void *my)
-{
-       struct ctdl_sieve *cs = (struct ctdl_sieve *)my;
-
-       /* libSieve does not take ownership of the memory used here.  But, since we
-        * are just pointing to locations inside a struct which we are going to free
-        * later, we're ok.
-        */
-       sieve2_setvalue_string(s, "user", cs->recp_user);
-       sieve2_setvalue_string(s, "detail", "");
-       sieve2_setvalue_string(s, "localpart", cs->recp_user);
-       sieve2_setvalue_string(s, "domain", cs->recp_node);
-       return SIEVE2_OK;
-}
-#endif
-
-
 /*
  * Callback function to parse message envelope
  */
@@ -416,18 +356,6 @@ int ctdl_getenvelope(sieve2_context_t *s, void *my)
 }
 
 
-#if 0
-/*
- * Callback function to fetch message body
- * (Uncomment the code if we implement this extension)
- *
- */
-int ctdl_getbody(sieve2_context_t *s, void *my)
-{
-       return SIEVE2_ERROR_UNSUPPORTED;
-}
-#endif
-
 
 /*
  * Callback function to fetch message size
@@ -496,23 +424,6 @@ int ctdl_getheaders(sieve2_context_t *s, void *my) {
 }
 
 
-/*
- * Add a room to the list of those rooms which potentially require sieve processing
- */
-void sieve_queue_room(struct ctdlroom *which_room) {
-       struct RoomProcList *ptr;
-
-       ptr = (struct RoomProcList *) malloc(sizeof (struct RoomProcList));
-       if (ptr == NULL) return;
-
-       safestrncpy(ptr->name, which_room->QRname, sizeof ptr->name);
-       begin_critical_section(S_SIEVELIST);
-       ptr->next = sieve_list;
-       sieve_list = ptr;
-       end_critical_section(S_SIEVELIST);
-       syslog(LOG_DEBUG, "<%s> queued for Sieve processing", which_room->QRname);
-}
-
 
 /*
  * Perform sieve processing for one message (called by sieve_do_room() for each message)
@@ -835,14 +746,6 @@ sieve2_callback_t ctdl_sieve_callbacks[] = {
        { SIEVE2_MESSAGE_GETALLHEADERS, ctdl_getheaders         },
        { SIEVE2_MESSAGE_GETSIZE,       ctdl_getsize            },
        { SIEVE2_MESSAGE_GETENVELOPE,   ctdl_getenvelope        },
-/*
- * These actions are unsupported by Citadel so we don't declare them.
- *
-       { SIEVE2_ACTION_NOTIFY,         ctdl_notify             },
-       { SIEVE2_MESSAGE_GETSUBADDRESS, ctdl_getsubaddress      },
-       { SIEVE2_MESSAGE_GETBODY,       ctdl_getbody            },
- *
- */
        { 0 }
 };
 
@@ -872,8 +775,7 @@ void sieve_do_room(char *roomname) {
         * Find the sieve scripts and control record and do something
         */
        u.config_msgnum = (-1);
-       CtdlForEachMessage(MSGS_LAST, 1, NULL, SIEVECONFIG, NULL,
-               get_sieve_config_backend, (void *)&u );
+       CtdlForEachMessage(MSGS_LAST, 1, NULL, SIEVECONFIG, NULL, get_sieve_config_backend, (void *)&u );
 
        if (u.config_msgnum < 0) {
                syslog(LOG_DEBUG, "No Sieve rules exist.  No processing is required.");
@@ -915,7 +817,7 @@ void sieve_do_room(char *roomname) {
 
        /* Validate the script */
 
-       struct ctdl_sieve my;           /* dummy ctdl_sieve struct just to pass "u" slong */
+       struct ctdl_sieve my;           /* dummy ctdl_sieve struct just to pass "u" along */
        memset(&my, 0, sizeof my);
        my.u = &u;
        res = sieve2_validate(sieve2_context, &my);
@@ -927,10 +829,7 @@ void sieve_do_room(char *roomname) {
        /* Do something useful */
        u.sieve2_context = sieve2_context;
        orig_lastproc = u.lastproc;
-       CtdlForEachMessage(MSGS_GT, u.lastproc, NULL, NULL, NULL,
-               sieve_do_msg,
-               (void *) &u
-       );
+       CtdlForEachMessage(MSGS_GT, u.lastproc, NULL, NULL, NULL, sieve_do_msg, (void *) &u);
 
 BAIL:
        res = sieve2_free(&sieve2_context);
@@ -938,390 +837,108 @@ BAIL:
                syslog(LOG_ERR, "sieve2_free() returned %d: %s", res, sieve2_errstr(res));
        }
 
-       /* Rewrite the config if we have to */
+       /* Rewrite the config if we have to (we're not the user right now) */
        rewrite_ctdl_sieve_config(&u, (u.lastproc > orig_lastproc) ) ;
 }
 
 
-/*
- * Perform sieve processing for all rooms which require it
- */
-void perform_sieve_processing(void) {
-       struct RoomProcList *ptr = NULL;
-
-       if (sieve_list != NULL) {
-               syslog(LOG_DEBUG, "Begin Sieve processing");
-               while (sieve_list != NULL) {
-                       char spoolroomname[ROOMNAMELEN];
-                       safestrncpy(spoolroomname, sieve_list->name, sizeof spoolroomname);
-                       begin_critical_section(S_SIEVELIST);
-
-                       /* pop this record off the list */
-                       ptr = sieve_list;
-                       sieve_list = sieve_list->next;
-                       free(ptr);
-
-                       /* invalidate any duplicate entries to prevent double processing */
-                       for (ptr=sieve_list; ptr!=NULL; ptr=ptr->next) {
-                               if (!strcasecmp(ptr->name, spoolroomname)) {
-                                       ptr->name[0] = 0;
-                               }
-                       }
-
-                       end_critical_section(S_SIEVELIST);
-                       if (spoolroomname[0] != 0) {
-                               sieve_do_room(spoolroomname);
-                       }
-               }
-       }
-}
-
-
-void msiv_load(struct sdm_userdata *u) {
-       char hold_rm[ROOMNAMELEN];
-
-       strcpy(hold_rm, CC->room.QRname);       /* save current room */
-
-       /* Take a spin through the user's personal address book */
-       if (CtdlGetRoom(&CC->room, USERCONFIGROOM) == 0) {
-       
-               u->config_msgnum = (-1);
-               strcpy(u->config_roomname, CC->room.QRname);
-               CtdlForEachMessage(MSGS_LAST, 1, NULL, SIEVECONFIG, NULL,
-                       get_sieve_config_backend, (void *)u );
-
-       }
-
-       if (strcmp(CC->room.QRname, hold_rm)) {
-               CtdlGetRoom(&CC->room, hold_rm);    /* return to saved room */
-       }
-}
-
-void msiv_store(struct sdm_userdata *u, int yes_write_to_disk) {
-/*
- * Initialise the sieve configs last processed message number.
- * We don't need to get the highest message number for the users inbox since the systems
- * highest message number will be higher than that and loer than this scripts message number
- * This prevents this new script from processing any old messages in the inbox.
- * Most importantly it will prevent vacation messages being sent to lots of old messages
- * in the inbox.
- */
-       u->lastproc = CtdlGetCurrentMessageNumber();
-       rewrite_ctdl_sieve_config(u, yes_write_to_disk);
-}
-
-
-/*
- * Select the active script.
- * (Set script_name to an empty string to disable all scripts)
- * 
- * Returns 0 on success or nonzero for error.
- */
-int msiv_setactive(struct sdm_userdata *u, char *script_name) {
-       int ok = 0;
-       struct sdm_script *s;
-
-       /* First see if the supplied value is ok */
-
-       if (IsEmptyStr(script_name)) {
-               ok = 1;
-       }
-       else {
-               for (s=u->first_script; s!=NULL; s=s->next) {
-                       if (!strcasecmp(s->script_name, script_name)) {
-                               ok = 1;
-                       }
-               }
-       }
-
-       if (!ok) return(-1);
-
-       /* Now set the active script */
-       for (s=u->first_script; s!=NULL; s=s->next) {
-               if (!strcasecmp(s->script_name, script_name)) {
-                       s->script_active = 1;
-               }
-               else {
-                       s->script_active = 0;
-               }
-       }
-       
-       return(0);
-}
 
 
-/*
- * Fetch a script by name.
- *
- * Returns NULL if the named script was not found, or a pointer to the script
- * if it was found.   NOTE: the caller does *not* own the memory returned by
- * this function.  Copy it if you need to keep it.
- */
-char *msiv_getscript(struct sdm_userdata *u, char *script_name) {
-       struct sdm_script *s;
+#endif
 
-       for (s=u->first_script; s!=NULL; s=s->next) {
-               if (!strcasecmp(s->script_name, script_name)) {
-                       if (s->script_content != NULL) {
-                               return (s->script_content);
-                       }
-               }
-       }
 
-       return(NULL);
-}
 
 
 /*
- * Delete a script by name.
+ * Get InBox Rules
  *
- * Returns 0 if the script was deleted.
- *      1 if the script was not found.
- *      2 if the script cannot be deleted because it is active.
+ * This is a client-facing function which fetches the user's inbox rules -- it omits all lines containing anything other than a rule.
  */
-int msiv_deletescript(struct sdm_userdata *u, char *script_name) {
-       struct sdm_script *s = NULL;
-       struct sdm_script *script_to_delete = NULL;
-
-       for (s=u->first_script; s!=NULL; s=s->next) {
-               if (!strcasecmp(s->script_name, script_name)) {
-                       script_to_delete = s;
-                       if (s->script_active) {
-                               return(2);
-                       }
-               }
-       }
+void cmd_gibr(char *argbuf) {
 
-       if (script_to_delete == NULL) return(1);
+       if (CtdlAccessCheck(ac_logged_in)) return;
 
-       if (u->first_script == script_to_delete) {
-               u->first_script = u->first_script->next;
-       }
-       else for (s=u->first_script; s!=NULL; s=s->next) {
-               if (s->next == script_to_delete) {
-                       s->next = s->next->next;
-               }
-       }
+       cprintf("%d inbox rules for %s\n", LISTING_FOLLOWS, CC->user.fullname);
 
-       free(script_to_delete->script_content);
-       free(script_to_delete);
-       return(0);
-}
+       struct CtdlMessage *msg = CtdlFetchMessage(CC->user.msgnum_inboxrules, 1, 1);
+       if (msg != NULL) {
+               if (!CM_IsEmpty(msg, eMesageText)) {
+                       char *token; 
+                       char *rest = msg->cm_fields[eMesageText];
+                       while ((token = strtok_r(rest, "\n", &rest))) {
 
+                               // for backwards compatibility, "# WEBCIT_RULE" is an alias for "rule" 
+                               if (!strncasecmp(token, "# WEBCIT_RULE|", 14)) {
+                                       strcpy(token, "rule|"); 
+                                       strcpy(&token[5], &token[14]);
+                               }
 
-/*
- * Add or replace a new script.  
- * NOTE: after this function returns, "u" owns the memory that "script_content"
- * was pointing to.
- */
-void msiv_putscript(struct sdm_userdata *u, char *script_name, char *script_content) {
-       int replaced = 0;
-       struct sdm_script *s, *sptr;
-
-       for (s=u->first_script; s!=NULL; s=s->next) {
-               if (!strcasecmp(s->script_name, script_name)) {
-                       if (s->script_content != NULL) {
-                               free(s->script_content);
+                               // Output only lines containing rules.
+                               if (!strncasecmp(token, "rule|", 5)) {
+                                       cprintf("%s\n", token); 
+                               }
                        }
-                       s->script_content = script_content;
-                       replaced = 1;
                }
+               CM_Free(msg);
        }
-
-       if (replaced == 0) {
-               sptr = malloc(sizeof(struct sdm_script));
-               safestrncpy(sptr->script_name, script_name, sizeof sptr->script_name);
-               sptr->script_content = script_content;
-               sptr->script_active = 0;
-               sptr->next = u->first_script;
-               u->first_script = sptr;
-       }
+       cprintf("000\n");
 }
 
 
-
 /*
- * Citadel protocol to manage sieve scripts.
- * This is basically a simplified (read: doesn't resemble IMAP) version
- * of the 'managesieve' protocol.
+ * Put InBox Rules
+ *
+ * User transmits the new inbox rules for the account.  They are inserted into the account, replacing the ones already there.
  */
-void cmd_msiv(char *argbuf) {
-       char subcmd[256];
-       struct sdm_userdata u;
-       char script_name[256];
-       char *script_content = NULL;
-       struct sdm_script *s;
-       int i;
-       int changes_made = 0;
-
-       memset(&u, 0, sizeof(struct sdm_userdata));
-
+void cmd_pibr(char *argbuf) {
        if (CtdlAccessCheck(ac_logged_in)) return;
-       extract_token(subcmd, argbuf, 0, '|', sizeof subcmd);
-       msiv_load(&u);
-
-       if (!strcasecmp(subcmd, "putscript")) {
-               extract_token(script_name, argbuf, 1, '|', sizeof script_name);
-               if (!IsEmptyStr(script_name)) {
-                       cprintf("%d Transmit script now\n", SEND_LISTING);
-                       script_content = CtdlReadMessageBody(HKEY("000"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0);
-                       msiv_putscript(&u, script_name, script_content);
-                       changes_made = 1;
-               }
-               else {
-                       cprintf("%d Invalid script name.\n", ERROR + ILLEGAL_VALUE);
-               }
-       }       
-       
-       else if (!strcasecmp(subcmd, "listscripts")) {
-               cprintf("%d Scripts:\n", LISTING_FOLLOWS);
-               for (s=u.first_script; s!=NULL; s=s->next) {
-                       if (s->script_content != NULL) {
-                               cprintf("%s|%d|\n", s->script_name, s->script_active);
-                       }
-               }
-               cprintf("000\n");
-       }
 
-       else if (!strcasecmp(subcmd, "setactive")) {
-               extract_token(script_name, argbuf, 1, '|', sizeof script_name);
-               if (msiv_setactive(&u, script_name) == 0) {
-                       cprintf("%d ok\n", CIT_OK);
-                       changes_made = 1;
-               }
-               else {
-                       cprintf("%d Script '%s' does not exist.\n",
-                               ERROR + ILLEGAL_VALUE,
-                               script_name
-                       );
-               }
-       }
-
-       else if (!strcasecmp(subcmd, "getscript")) {
-               extract_token(script_name, argbuf, 1, '|', sizeof script_name);
-               script_content = msiv_getscript(&u, script_name);
-               if (script_content != NULL) {
-                       int script_len;
-
-                       cprintf("%d Script:\n", LISTING_FOLLOWS);
-                       script_len = strlen(script_content);
-                       client_write(script_content, script_len);
-                       if (script_content[script_len-1] != '\n') {
-                               cprintf("\n");
+       unbuffer_output();
+       cprintf("%d send new rules\n", SEND_LISTING);
+       char *newrules = CtdlReadMessageBody(HKEY("000"), CtdlGetConfigLong("c_maxmsglen"), NULL, 0);
+       StrBuf *NewConfig = NewStrBufPlain("Content-type: application/x-citadel-sieve-config; charset=UTF-8\nContent-transfer-encoding: 8bit\n\n", -1);
+
+       char *token; 
+       char *rest = newrules;
+       while ((token = strtok_r(rest, "\n", &rest))) {
+               // Accept only lines containing rules
+               if (!strncasecmp(token, "rule|", 5)) {
+                       StrBufAppendBufPlain(NewConfig, token, -1, 0);
+                       StrBufAppendBufPlain(NewConfig, HKEY("\n"), 0);
+               }
+       }
+       free(newrules);
+
+       // Fetch the existing config so we can merge in anything that is NOT a rule 
+       // (Does not start with "rule|" but has at least one vertical bar)
+       struct CtdlMessage *msg = CtdlFetchMessage(CC->user.msgnum_inboxrules, 1, 1);
+       if (msg != NULL) {
+               if (!CM_IsEmpty(msg, eMesageText)) {
+                       rest = msg->cm_fields[eMesageText];
+                       while ((token = strtok_r(rest, "\n", &rest))) {
+                               // for backwards compatibility, "# WEBCIT_RULE" is an alias for "rule" 
+                               if ((strncasecmp(token, "# WEBCIT_RULE|", 14)) && (strncasecmp(token, "rule|", 5)) && (haschar(token, '|'))) {
+                                       StrBufAppendBufPlain(NewConfig, token, -1, 0);
+                                       StrBufAppendBufPlain(NewConfig, HKEY("\n"), 0);
+                               }
                        }
-                       cprintf("000\n");
-               }
-               else {
-                       cprintf("%d Invalid script name.\n", ERROR + ILLEGAL_VALUE);
                }
+               CM_Free(msg);
        }
 
-       else if (!strcasecmp(subcmd, "deletescript")) {
-               extract_token(script_name, argbuf, 1, '|', sizeof script_name);
-               i = msiv_deletescript(&u, script_name);
-               if (i == 0) {
-                       cprintf("%d ok\n", CIT_OK);
-                       changes_made = 1;
-               }
-               else if (i == 1) {
-                       cprintf("%d Script '%s' does not exist.\n",
-                               ERROR + ILLEGAL_VALUE,
-                               script_name
-                       );
-               }
-               else if (i == 2) {
-                       cprintf("%d Script '%s' is active and cannot be deleted.\n",
-                               ERROR + ILLEGAL_VALUE,
-                               script_name
-                       );
-               }
-               else {
-                       cprintf("%d unknown error\n", ERROR);
-               }
-       }
-
-       else {
-               cprintf("%d Invalid subcommand\n", ERROR + CMD_NOT_SUPPORTED);
-       }
-
-       msiv_store(&u, changes_made);
-}
-
-
-
-void ctdl_sieve_init(void) {
-       char *cred = NULL;
-       sieve2_context_t *sieve2_context = NULL;
-       int res;
-
-       /*
-        *      We don't really care about dumping the entire credits to the log
-        *      every time the server is initialized.  The documentation will suffice
-        *      for that purpose.  We are making a call to sieve2_credits() in order
-        *      to demonstrate that we have successfully linked in to libsieve.
-        */
-       cred = strdup(sieve2_credits());
-       if (cred == NULL) return;
-
-       if (strlen(cred) > 60) {
-               strcpy(&cred[55], "...");
-       }
-
-       syslog(LOG_INFO, "%s",cred);
-       free(cred);
-
-       /* Briefly initialize a Sieve parser instance just so we can list the
-        * extensions that are available.
-        */
-       res = sieve2_alloc(&sieve2_context);
-       if (res != SIEVE2_OK) {
-               syslog(LOG_ERR, "sieve2_alloc() returned %d: %s", res, sieve2_errstr(res));
-               return;
-       }
-
-       res = sieve2_callbacks(sieve2_context, ctdl_sieve_callbacks);
-       if (res != SIEVE2_OK) {
-               syslog(LOG_ERR, "sieve2_callbacks() returned %d: %s", res, sieve2_errstr(res));
-               goto BAIL;
-       }
-
-       msiv_extensions = strdup(sieve2_listextensions(sieve2_context));
-       syslog(LOG_INFO, "Extensions: %s", msiv_extensions);
-
-BAIL:  res = sieve2_free(&sieve2_context);
-       if (res != SIEVE2_OK) {
-               syslog(LOG_ERR, "sieve2_free() returned %d: %s", res, sieve2_errstr(res));
-       }
-
-}
-
-
-void cleanup_sieve(void)
-{
-        struct RoomProcList *ptr, *ptr2;
-
-       if (msiv_extensions != NULL)
-               free(msiv_extensions);
-       msiv_extensions = NULL;
-
-        begin_critical_section(S_SIEVELIST);
-       ptr=sieve_list;
-       while (ptr != NULL) {
-               ptr2 = ptr->next;
-               free(ptr);
-               ptr = ptr2;
-       }
-        sieve_list = NULL;
-        end_critical_section(S_SIEVELIST);
-}
-
-
-int serv_sieve_room(struct ctdlroom *room)
-{
-       if (!strcasecmp(&room->QRname[11], MAILROOM)) {
-               sieve_queue_room(room);
+       /* we have composed the new configuration , now save it */
+       long old_msgnum = CC->user.msgnum_inboxrules;
+       char userconfigroomname[ROOMNAMELEN];
+       CtdlMailboxName(userconfigroomname, sizeof userconfigroomname, &CC->user, USERCONFIGROOM);
+       long new_msgnum = quickie_message("Citadel", NULL, NULL, userconfigroomname, ChrPtr(NewConfig), FMT_RFC822, "inbox rules configuration");
+       FreeStrBuf(&NewConfig);
+       CtdlGetUserLock(&CC->user, CC->curr_user);
+       CC->user.msgnum_inboxrules = new_msgnum;
+       CtdlPutUserLock(&CC->user);
+       if (old_msgnum > 0) {
+               syslog(LOG_DEBUG, "Deleting old message %ld from %s", old_msgnum, userconfigroomname);
+               CtdlDeleteMessages(userconfigroomname, &old_msgnum, 1, "");
        }
-       return 0;
 }
 
 
@@ -1329,11 +946,11 @@ CTDL_MODULE_INIT(sieve)
 {
        if (!threading)
        {
-               ctdl_sieve_init();
-               CtdlRegisterProtoHook(cmd_msiv, "MSIV", "Manage Sieve scripts");
-               CtdlRegisterRoomHook(serv_sieve_room);
-               CtdlRegisterSessionHook(perform_sieve_processing, EVT_HOUSE, PRIO_HOUSE + 10);
-               CtdlRegisterCleanupHook(cleanup_sieve);
+               // ctdl_sieve_init();
+               CtdlRegisterProtoHook(cmd_gibr, "GIBR", "Get InBox Rules");
+               CtdlRegisterProtoHook(cmd_pibr, "PIBR", "Put InBox Rules");
+               // CtdlRegisterSessionHook(perform_sieve_processing, EVT_HOUSE, PRIO_HOUSE + 10);
+               // CtdlRegisterCleanupHook(cleanup_sieve);
        }
        
         /* return our module name for the log */
index 86e2947f440bf5e072a19756abc7a1569de49f2c..b7167625b6bae2ad521b2386b84117c5282a27d7 100644 (file)
@@ -471,6 +471,48 @@ void move_inet_addrs_from_vcards_to_user_records(void)
 }
 
 
+
+
+/*
+ * We found the legacy sieve config in the user's config room.  Store the message number in the user record.
+ */
+void mifm_found_config(long msgnum, void *userdata) {
+       struct ctdluser *us = (struct ctdluser *)userdata;
+
+       us->msgnum_inboxrules = msgnum;
+       syslog(LOG_DEBUG, "user: <%s> inbox filter msgnum: <%ld>", us->fullname, us->msgnum_inboxrules);
+}
+
+
+/*
+ * Helper function for migrate_inbox_filter_msgnums()
+ */
+void mifm_backend(char *username, void *data) {
+       struct ctdluser us;
+       char roomname[ROOMNAMELEN];
+
+       if (CtdlGetUserLock(&us, username) == 0) {
+               /* Take a spin through the user's personal config room */
+               syslog(LOG_DEBUG, "Processing <%s> (%ld)", us.fullname, us.usernum);
+               snprintf(roomname, sizeof roomname, "%010ld.%s", us.usernum, USERCONFIGROOM);
+               if (CtdlGetRoom(&CC->room, roomname) == 0) {
+                       CtdlForEachMessage(MSGS_LAST, 1, NULL, SIEVECONFIG, NULL, mifm_found_config, (void *)&us );
+               }
+               CtdlPutUserLock(&us);
+       }
+}
+
+
+/*
+ * Prior to version 930 we used a MIME type search to locate the user's inbox filter rules. 
+ * This function locates those ruleset messages and simply stores the message number in the user record.
+ */
+void migrate_inbox_filter_msgnums(void)
+{
+       ForEachUser(mifm_backend, NULL);
+}
+
+
 /*
  * Create a default administrator account so we can log in to a new installation
  */
@@ -583,6 +625,11 @@ void post_startup_upgrades(void) {
        if ((oldver > 000) && (oldver < 922)) {
                ProcessOldStyleAdjRefCountQueue();
        }
+
+       if ((oldver > 000) && (oldver < 930)) {
+               migrate_inbox_filter_msgnums();
+       }
+
 }
 
 
index 73a1b7911094dc48858a5cf95b5d2c824c1fcee5..7c16b6e0af37c9c9097822fef629186668304411 100644 (file)
@@ -2,7 +2,7 @@
  * Citadel Extension Loader
  * Originally written by Brian Costello <btx@calyx.net>
  *
- * Copyright (c) 1987-2019 by the citadel.org team
+ * Copyright (c) 1987-2020 by the citadel.org team
  *
  * This program is open source software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, version 3.
@@ -110,7 +110,7 @@ XmsgFunctionHook *XmsgHookTable = NULL;
 
 /*
  * RoomFunctionHook extensions are used for hooks which impliment room
- * processing functions when new messages are added EG. SIEVE.
+ * processing functions when new messages are added.
  */
 typedef struct RoomFunctionHook RoomFunctionHook;
 struct RoomFunctionHook {
diff --git a/citadel/serv_sieve.h b/citadel/serv_sieve.h
deleted file mode 100644 (file)
index 5b98b66..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-
-#include <sieve2.h>
-#include <sieve2_error.h>
-
-struct sdm_script {
-       struct sdm_script *next;
-       char script_name[256];
-       int script_active;
-       char *script_content;
-};
-
-struct sdm_vacation {
-       struct sdm_vacation *next;
-       char fromaddr[256];
-       time_t timestamp;
-};
-
-struct sdm_userdata {
-       sieve2_context_t *sieve2_context;       /* for libsieve's use */
-       long config_msgnum;                     /* confirms that a sieve config was located */
-       char config_roomname[ROOMNAMELEN];
-       long lastproc;                          /* last message processed */
-       struct sdm_script *first_script;
-       struct sdm_vacation *first_vacation;
-};
-
-struct ctdl_sieve {
-       char *rfc822headers;
-       int cancel_implicit_keep;       /* Set to 1 if the message was successfully acted upon */
-       int keep;                       /* Set to 1 to suppress message deletion from the inbox */
-       long usernum;                   /* Owner of the mailbox we're processing */
-       long msgnum;                    /* Message base ID of the message being processed */
-       struct sdm_userdata *u;         /* Info related to the current session */
-       char recp_user[256];
-       char recp_node[256];
-       char recp_name[256];
-       char sender[256];               /* To whom shall we send reject bounces or vacation messages? */
-       char subject[1024];             /* Retain msg subject so we can use it in vacation messages */
-       char envelope_from[1024];
-       char envelope_to[1024];
-};
-
-
-/* If you change this string you will break all of your Sieve configs. */
-#define CTDLSIEVECONFIGSEPARATOR       "\n-=<CtdlSieveConfigSeparator>=-\n"
-
-/* Maximum time we keep vacation fromaddr records online.  This implies that a vacation
- * rule cannot exceed this amount of time.   (Any more than 30 days is a ridiculously
- * long vacation which the person probably doesn't deserve.)
- */
-#define MAX_VACATION   30
-
-extern struct RoomProcList *sieve_list;
-
-void sieve_queue_room(struct ctdlroom *);
-void perform_sieve_processing(void);
-
-void msiv_load(struct sdm_userdata *u);
-void msiv_store(struct sdm_userdata *u, int changes_made);
-int msiv_setactive(struct sdm_userdata *u, char *script_name);
-char *msiv_getscript(struct sdm_userdata *u, char *script_name);
-int msiv_deletescript(struct sdm_userdata *u, char *script_name);
-void msiv_putscript(struct sdm_userdata *u, char *script_name, char *script_content);
-extern char *msiv_extensions;
index cce70574ae927c451f165af0488e47215e27ac8c..735cffc0c7729b59df9618a338dbb6ee73e56abf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996-2012 by the citadel.org team
+ * Copyright (c) 1996-2020 by the citadel.org team
  *
  * This program is open source software.  You can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 3.
@@ -9,7 +9,11 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * FIXME: add logic to exclude the webcit-generated script from the manual script selection
+ * 
+ * Implementation note: this was kind of hacked up when we switched from Sieve to custom rules.
+ * As a result there's probably some cruft in here...
+ * ajc 2020jul12
+ *
  */
 
 #include "webcit.h"
@@ -22,220 +26,6 @@ CtxType CTX_SIEVESCRIPT = CTX_NONE;
 #define RULES_SCRIPT   "__WebCit_Generated_Script__"
 
 
-/*
- * Helper function for output_sieve_rule() to output strings with quotes escaped
- */
-void osr_sanitize(char *str) {
-       int i, len;
-
-       if (str == NULL) return;
-       len = strlen(str);
-       for (i=0; i<len; ++i) {
-               if (str[i]=='\"') {
-                       str[i] = '\'' ;
-               }
-               else if (isspace(str[i])) {
-                       str[i] = ' ';
-               }
-       }
-}
-
-
-/*
- * Output parseable Sieve script code based on rules input
- */
-void output_sieve_rule(char *hfield, char *compare, char *htext, char *sizecomp, int sizeval,
-                       char *action, char *fileinto, char *redirect, char *automsg, char *final,
-                       char *my_addresses)
-{
-       char *comp1 = "";
-       char *comp2 = "";
-
-       osr_sanitize(htext);
-       osr_sanitize(fileinto);
-       osr_sanitize(redirect);
-       osr_sanitize(automsg);
-
-       /* Prepare negation and match operators that will be used iff we apply a conditional */
-
-       if (!strcasecmp(compare, "contains")) {
-               comp1 = "";
-               comp2 = ":contains";
-       }
-       else if (!strcasecmp(compare, "notcontains")) {
-               comp1 = "not";
-               comp2 = ":contains";
-       }
-       else if (!strcasecmp(compare, "is")) {
-               comp1 = "";
-               comp2 = ":is";
-       }
-       else if (!strcasecmp(compare, "isnot")) {
-               comp1 = "not";
-               comp2 = ":is";
-       }
-       else if (!strcasecmp(compare, "matches")) {
-               comp1 = "";
-               comp2 = ":matches";
-       }
-       else if (!strcasecmp(compare, "notmatches")) {
-               comp1 = "not";
-               comp2 = ":matches";
-       }
-
-       /* Now do the conditional */
-
-       if (!strcasecmp(hfield, "from")) {
-               serv_printf("if%s header %s \"From\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "tocc")) {
-               serv_printf("if%s header %s [\"To\", \"Cc\"] \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "subject")) {
-               serv_printf("if%s header %s \"Subject\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "replyto")) {
-               serv_printf("if%s header %s \"Reply-to\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "sender")) {
-               serv_printf("if%s header %s \"Sender\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "resentfrom")) {
-               serv_printf("if%s header %s \"Resent-from\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "resentto")) {
-               serv_printf("if%s header %s \"Resent-to\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "xmailer")) {
-               serv_printf("if%s header %s \"X-Mailer\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "xspamflag")) {
-               serv_printf("if%s header %s \"X-Spam-Flag\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "xspamstatus")) {
-               serv_printf("if%s header %s \"X-Spam-Status\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "listid")) {
-               serv_printf("if%s header %s \"List-ID\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "envfrom")) {
-               serv_printf("if%s envelope %s \"From\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "envto")) {
-               serv_printf("if%s envelope %s \"To\" \"%s\"",
-                       comp1, comp2,
-                       htext
-               );
-       }
-
-       else if (!strcasecmp(hfield, "size")) {
-               if (!strcasecmp(sizecomp, "larger")) {
-                       serv_printf("if size :over %d", sizeval);
-               }
-               else if (!strcasecmp(sizecomp, "smaller")) {
-                       serv_printf("if size :under %d", sizeval);
-               }
-               else {  /* failsafe - should never get here, but just in case... */
-                       serv_printf("if size :over 1");
-               }
-       }
-
-       /* Open braces if we're in a conditional loop */
-
-       if (strcasecmp(hfield, "all")) {
-               serv_printf("{");
-       }
-
-       /* Do action */
-
-       if (!strcasecmp(action, "keep")) {
-               serv_printf("keep;");
-       }
-
-       else if (!strcasecmp(action, "discard")) {
-               serv_printf("discard;");
-       }
-
-       else if (!strcasecmp(action, "reject")) {
-               serv_printf("reject \"%s\";", automsg);
-       }
-
-       else if (!strcasecmp(action, "fileinto")) {
-               serv_printf("fileinto \"%s\";", fileinto);
-       }
-
-       else if (!strcasecmp(action, "redirect")) {
-               serv_printf("redirect \"%s\";", redirect);
-       }
-
-       else if (!strcasecmp(action, "vacation")) {
-               serv_printf("vacation :addresses [%s]\n\"%s\";", my_addresses, automsg);
-       }
-
-       /* Do 'final' action */
-
-       if (!strcasecmp(final, "stop")) {
-               serv_printf("stop;");
-       }
-
-       /* Close the braces if we're in a conditional loop */
-
-       if (strcasecmp(hfield, "all")) {
-               serv_printf("}");
-       }
-
-       /* End of rule. */
-}
-
-
 /*
  * Translate the fields from the rule editor into something we can save...
  */
@@ -273,26 +63,12 @@ void parse_fields_from_rule_editor(void) {
        }
 
        /* Now generate the script and write it to the Citadel server */
-       serv_printf("MSIV putscript|%s|", RULES_SCRIPT);
+       serv_printf("PIBR");
        serv_getln(buf, sizeof buf);
        if (buf[0] != '4') {
                return;
        }
 
-       serv_puts("# THIS SCRIPT WAS AUTOMATICALLY GENERATED BY WEBCIT.");
-       serv_puts("# ");
-       serv_puts("# Do not attempt to manually edit it.  If you do so,");
-       serv_puts("# your changes will be overwritten the next time WebCit");
-       serv_puts("# saves its mail filtering rule set.  If you really want");
-       serv_puts("# to use these rules as the basis for another script,");
-       serv_puts("# copy them to another script and save that instead.");
-       serv_puts("");
-       serv_puts("require \"fileinto\";");
-       serv_puts("require \"reject\";");
-       serv_puts("require \"vacation\";");
-       serv_puts("require \"envelope\";");
-       serv_puts("");
-
        for (i=0; i<MAX_RULES; ++i) {
                
                strcpy(rule, "");
@@ -341,16 +117,11 @@ void parse_fields_from_rule_editor(void) {
                        if (encoded_rule[len - 1] == '\n') {
                                encoded_rule[len - 1] = '\0';
                        }
-                       serv_printf("# WEBCIT_RULE|%d|%s|", i, encoded_rule);
-                       output_sieve_rule(hfield, compare, htext, sizecomp, sizeval,
-                                       action, fileinto, redirect, automsg, final, my_addresses);
+                       serv_printf("rule|%d|%s|", i, encoded_rule);
                        serv_puts("");
                }
-
-
        }
 
-       serv_puts("stop;");
        serv_puts("000");
 }
 
@@ -359,12 +130,6 @@ void parse_fields_from_rule_editor(void) {
  * save sieve config
  */
 void save_sieve(void) {
-       int bigaction;
-       char script_names[MAX_SCRIPTS][64];
-       int num_scripts = 0;
-       int i;
-       char this_name[64];
-       char buf[256];
 
        if (!havebstr("save_button")) {
                AppendImportantMessage(_("Cancelled.  Changes were not saved."), -1);
@@ -374,52 +139,6 @@ void save_sieve(void) {
 
        parse_fields_from_rule_editor();
 
-       serv_puts("MSIV listscripts");
-       serv_getln(buf, sizeof(buf));
-       if (buf[0] == '1') while (serv_getln(buf, sizeof(buf)), strcmp(buf, "000")) {
-               if (num_scripts < MAX_SCRIPTS) {
-                       extract_token(script_names[num_scripts], buf, 0, '|', 64);
-                       ++num_scripts;
-               }
-       }
-
-       bigaction = ibstr("bigaction");
-
-       if (bigaction == 0) {
-               serv_puts("MSIV setactive||");
-               serv_getln(buf, sizeof buf);
-       }
-
-       else if (bigaction == 1) {
-               serv_printf("MSIV setactive|%s|", RULES_SCRIPT);
-               serv_getln(buf, sizeof buf);
-       }
-
-       else if (bigaction == 2) {
-               serv_printf("MSIV setactive|%s|", bstr("active_script"));
-               serv_getln(buf, sizeof buf);
-       }
-
-       if (num_scripts > 0) {
-               for (i=0; i<num_scripts; ++i) {
-                       /*
-                        * We only want to save the scripts from the "manually edited scripts"
-                        * screen.  The script that WebCit generates from its ruleset will be
-                        * auto-generated by parse_fields_from_rule_editor() and saved there.
-                        */
-                       if (strcasecmp(script_names[i], RULES_SCRIPT)) {
-                               serv_printf("MSIV putscript|%s|", script_names[i]);
-                               serv_getln(buf, sizeof buf);
-                               if (buf[0] == '4') {
-                                       snprintf(this_name, sizeof this_name, "text_%s", script_names[i]);
-                                       striplt((char *)BSTR(this_name)); /* TODO: get rid of typecast*/
-                                       serv_write(BSTR(this_name), strlen(BSTR(this_name)));
-                                       serv_puts("\n000");
-                               }
-                       }
-               }
-       }
-
        AppendImportantMessage(_("Your changes have been saved."), -1);
        display_main_menu();
        return;
@@ -434,46 +153,6 @@ void display_sieve_add_or_delete(void) {
 
 
 
-/*
- * create a new script
- * take the web environment script name and create it on the citadel server
- */
-void create_script(void) {
-       char buf[256];
-
-       serv_printf("MSIV getscript|%s", bstr("script_name"));
-       serv_getln(buf, sizeof buf);
-       if (buf[0] == '1') {            // does script exist already?
-               while (serv_getln(buf, sizeof(buf)), strcmp(buf, "000")) {
-                                       // yes -- flush the output
-               }
-       }
-       else {
-                                       // no -- safe to create a new one by this name
-               serv_printf("MSIV putscript|%s", bstr("script_name"));
-               serv_getln(buf, sizeof buf);
-               if (buf[0] == '4') {
-                       serv_puts("keep;");
-                       serv_puts("000");
-               }
-       }
-
-       display_sieve_add_or_delete();
-}
-
-
-/*
- * delete a script
- */
-void delete_script(void) {
-       char buf[256];
-
-       serv_printf("MSIV deletescript|%s", bstr("script_name"));
-       serv_getln(buf, sizeof buf);
-       display_sieve_add_or_delete();
-}
-
-
 /*
  * dummy panel indicating to the user that the server doesn't support Sieve
  */
@@ -802,7 +481,7 @@ void FreeSieveRule(void *vRule)
        free(Rule);
 }
 
-#define WC_RULE_HEADER "# WEBCIT_RULE|"
+#define WC_RULE_HEADER "rule|"
 HashList *GetSieveRules(StrBuf *Target, WCTemplputParams *TP)
 {
        StrBuf *Line = NULL;
@@ -814,7 +493,7 @@ HashList *GetSieveRules(StrBuf *Target, WCTemplputParams *TP)
        SieveRule *Rule = NULL;
 
        SieveRules = NewHash(1, Flathash);
-       serv_printf("MSIV getscript|"RULES_SCRIPT);
+       serv_printf("GIBR");
        Line = NewStrBuf();
        EncodedRule = NewStrBuf();
        StrBuf_ServGetln(Line);
@@ -830,8 +509,7 @@ HashList *GetSieveRules(StrBuf *Target, WCTemplputParams *TP)
                        {
                                pch = NULL;
                                /* We just care for our encoded header and skip everything else */
-                               if ((StrLength(Line) > sizeof(WC_RULE_HEADER) - 1) &&
-                                   (!strncasecmp(ChrPtr(Line), HKEY(WC_RULE_HEADER))))
+                               if ((StrLength(Line) > sizeof(WC_RULE_HEADER) - 1) && (!strncasecmp(ChrPtr(Line), HKEY(WC_RULE_HEADER))))
                                {
                                        StrBufSkip_NTokenS(Line, &pch, '|', 1);
                                        n = StrBufExtractNext_int(Line, &pch, '|'); 
@@ -962,7 +640,5 @@ InitModule_SIEVE
        /* fetch our room into WCC->ThisRoom, to evaluate while iterating over rooms with COND:THIS:THAT:ROOM */
        RegisterNamespace("SIEVE:SCRIPT:LOOKUP_FILEINTO", 0, 1, tmplput_SieveRule_lookup_FileIntoRoom, NULL, CTX_SIEVESCRIPT);
        WebcitAddUrlHandler(HKEY("save_sieve"), "", 0, save_sieve, 0);
-       WebcitAddUrlHandler(HKEY("create_script"), "", 0, create_script, 0);
-       WebcitAddUrlHandler(HKEY("delete_script"), "", 0, delete_script, 0);
        WebcitAddUrlHandler(HKEY("display_sieve_add_or_delete"), "", 0, display_sieve_add_or_delete, 0);
 }
index 5764fbd205860002553e006a41f959d6444ab144..915883613baa1c1a63980079f1e1596d403d755c 100644 (file)
@@ -128,7 +128,7 @@ extern char *ssl_cipher_list;
 #define DEVELOPER_ID           0
 #define CLIENT_ID              4
 #define CLIENT_VERSION         927             /* This version of WebCit */
-#define MINIMUM_CIT_VERSION    924             /* Minimum required version of Citadel server */
+#define MINIMUM_CIT_VERSION    930             /* Minimum required version of Citadel server */
 #define        LIBCITADEL_MIN          924             /* Minimum required version of libcitadel */
 #define DEFAULT_HOST           "localhost"     /* Default Citadel server */
 #define DEFAULT_PORT           "504"