worked on sieve config load/save
authorArt Cancro <ajc@citadel.org>
Tue, 10 Oct 2006 20:57:03 +0000 (20:57 +0000)
committerArt Cancro <ajc@citadel.org>
Tue, 10 Oct 2006 20:57:03 +0000 (20:57 +0000)
citadel/citadel.h
citadel/serv_sieve.c
citadel/serv_sieve.h

index c6e988a5ddc563f95d344c2a7a5030e04671de28..b8f094973edcb6a05b5f5232e0f8226b4b53976f 100644 (file)
@@ -235,6 +235,7 @@ enum {
 #define IGNETCFG       "application/x-citadel-ignet-config"
 #define IGNETMAP       "application/x-citadel-ignet-map"
 #define FILTERLIST     "application/x-citadel-filter-list"
+#define SIEVECONFIG    "application/x-citadel-sieve-config"
 
 #define TRACE  lprintf(CTDL_DEBUG, "Checkpoint: %s, %d\n", __FILE__, __LINE__)
 
index 067e143fddbe183b8040dc94a7bf9d198f90afda..fae02f387d31962f9fc57c5aa818e4bb8a1059b7 100644 (file)
@@ -313,7 +313,6 @@ int ctdl_discard(sieve2_context_t *s, void *my)
 
 /*
  * Callback function to retrieve the sieve script
- * FIXME fetch script from Citadel instead of hardcode
  */
 int ctdl_getscript(sieve2_context_t *s, void *my) {
 
@@ -368,12 +367,23 @@ void sieve_queue_room(struct ctdlroom *which_room) {
 
 
 /* 
- * We need this struct to pass a bunch of information
+ * We need these structs to pass a bunch of information
  * between sieve_do_msg() and sieve_do_room()
  */
+
+struct sdm_script {
+       struct sdm_script *next;
+       char script_name[256];
+       int script_active;
+       char *script_content;
+};
+
 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;
 };
 
 
@@ -429,6 +439,79 @@ void sieve_do_msg(long msgnum, void *userdata) {
 }
 
 
+
+/*
+ * Given the on-disk representation of our Sieve config, load
+ * it into an in-memory data structure.
+ */
+void parse_sieve_config(char *conf, struct sdm_userdata *u) {
+       char *ptr;
+       char *c;
+
+       c = conf;
+       while (ptr = bmstrcasestr(conf, CTDLSIEVECONFIGSEPARATOR), ptr != NULL) {
+               *ptr = 0;
+               ptr += strlen(CTDLSIEVECONFIGSEPARATOR);
+
+               lprintf(CTDL_DEBUG, "CONFIG: <%s>\n", c);
+
+               /* FIXME finish this */
+
+       }
+}
+
+/*
+ * We found the Sieve configuration for this user.
+ * Now do something with it.
+ */
+void get_sieve_config_backend(long msgnum, void *userdata) {
+       struct sdm_userdata *u = (struct sdm_userdata *) userdata;
+       struct CtdlMessage *msg;
+       char *conf;
+
+       u->config_msgnum = msgnum;
+       msg = CtdlFetchMessage(u->config_msgnum, 1);
+       if (msg == NULL) {
+               u->config_msgnum = (-1) ;
+               return;
+       }
+
+       conf = msg->cm_fields['M'];
+       msg->cm_fields['M'] = NULL;
+       CtdlFreeMessage(msg);
+
+       if (conf != NULL) {
+               parse_sieve_config(conf, u);
+               free(conf);
+       }
+}
+
+
+/* 
+ * Write our citadel sieve config back to disk
+ */
+void rewrite_ctdl_sieve_config(struct sdm_userdata *u) {
+       char *text;
+
+       text =
+               "Content-type: application/x-citadel-sieve-config\n"
+               "\n"
+       ;
+
+       /* Save the config */
+       quickie_message("Citadel", NULL, u->config_roomname,
+                       text,
+                       4,
+                       "Sieve configuration"
+       );
+
+       /* And delete the old one */
+       CtdlDeleteMessages(u->config_roomname, &u->config_msgnum, 1, "", 0);
+
+}
+
+
+
 /*
  * Perform sieve processing for a single room
  */
@@ -437,7 +520,7 @@ void sieve_do_room(char *roomname) {
        struct sdm_userdata u;
        sieve2_context_t *sieve2_context = NULL;        /* Context for sieve parser */
        int res;                                        /* Return code from libsieve calls */
-       char sieveroomname[ROOMNAMELEN];
+       long orig_lastproc = 0;
 
        /*
         * This is our callback registration table for libSieve.
@@ -465,15 +548,25 @@ void sieve_do_room(char *roomname) {
        /* See if the user who owns this 'mailbox' has any Sieve scripts that
         * require execution.
         */
-       snprintf(sieveroomname, sizeof sieveroomname, "%010ld.%s", atol(roomname), SIEVERULES);
-       if (getroom(&CC->room, sieveroomname) != 0) {
-               lprintf(CTDL_DEBUG, "<%s> does not exist.  No processing is required.\n", sieveroomname);
+       snprintf(u.config_roomname, sizeof u.config_roomname, "%010ld.%s", atol(roomname), SIEVERULES);
+       if (getroom(&CC->room, u.config_roomname) != 0) {
+               lprintf(CTDL_DEBUG, "<%s> does not exist.  No processing is required.\n", u.config_roomname);
                return;
        }
 
-       /* CtdlForEachMessage(FIXME find the sieve scripts and control record and do something */
+       /*
+        * 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 );
 
-       lprintf(CTDL_DEBUG, "Performing Sieve processing for <%s>\n", roomname);
+       if (u.config_msgnum < 0) {
+               lprintf(CTDL_DEBUG, "No Sieve rules exist.  No processing is required.\n");
+               return;
+       }
+
+       lprintf(CTDL_DEBUG, "Rules found.  Performing Sieve processing for <%s>\n", roomname);
 
        if (getroom(&CC->room, roomname) != 0) {
                lprintf(CTDL_CRIT, "ERROR: cannot load <%s>\n", roomname);
@@ -504,6 +597,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
@@ -514,6 +608,11 @@ BAIL:
        if (res != SIEVE2_OK) {
                lprintf(CTDL_CRIT, "sieve2_free() returned %d: %s\n", res, sieve2_errstr(res));
        }
+
+       /* Rewrite the config if we have to */
+       if (u.lastproc > orig_lastproc) {
+               rewrite_ctdl_sieve_config(&u);
+       }
 }
 
 
@@ -552,7 +651,7 @@ void perform_sieve_processing(void) {
 
 
 
-/**
+/*
  *     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
index 54c48c9e1c0f9735eea658467ef74dd523490f48..d70be0506f3113ad1493fe9d71c1ae5e86ab75fa 100644 (file)
@@ -6,3 +6,6 @@ extern struct RoomProcList *sieve_list;
 
 void sieve_queue_room(struct ctdlroom *);
 void perform_sieve_processing(void);
+
+/* If you change this string you will break all of your Sieve configs. */
+#define CTDLSIEVECONFIGSEPARATOR       "\n-=<CtdlSieveConfigSeparator>=-\n"