more work on the inboxrules module. don't run this in production. it isn't finished.
[citadel.git] / citadel / modules / inboxrules / serv_inboxrules.c
index fa9cca82acd06320d5d0c7aafafccc061b9b6e1c..a3e0420307a65929d87f918d7bd31768128f9e6a 100644 (file)
@@ -834,8 +834,8 @@ char *final_keys[] = {
 
 // This data structure represents ONE inbox rule within the configuration.
 struct irule {
-       int field_compare_op;
        int compared_field;
+       int field_compare_op;
        char compared_value[128];
        int size_compare_op;
        long compared_size;
@@ -967,18 +967,18 @@ struct inboxrules *deserialize_inbox_rules(char *serialized_rules) {
                        free(decoded_rule);
 
                        // if we re-serialized this now, what would it look like?
-                       //syslog(LOG_DEBUG, "test reserialize: 0|%s|%s|%s|%s|%ld|%s|%s|%s|%s|%s",
-                               //field_keys[new_rule->compared_field],
-                               //fcomp_keys[new_rule->field_compare_op],
-                               //new_rule->compared_value,
-                               //scomp_keys[new_rule->size_compare_op],
-                               //new_rule->compared_size,
-                               //action_keys[new_rule->action],
-                               //new_rule->file_into,
-                               //new_rule->redirect_to,
-                               //new_rule->autoreply_message,
-                               //final_keys[new_rule->final_action]
-                       //);
+                       syslog(LOG_DEBUG, "test reserialize: 0|%s|%s|%s|%s|%ld|%s|%s|%s|%s|%s",
+                               field_keys[new_rule->compared_field],
+                               fcomp_keys[new_rule->field_compare_op],
+                               new_rule->compared_value,
+                               scomp_keys[new_rule->size_compare_op],
+                               new_rule->compared_size,
+                               action_keys[new_rule->action],
+                               new_rule->file_into,
+                               new_rule->redirect_to,
+                               new_rule->autoreply_message,
+                               final_keys[new_rule->final_action]
+                       );
                        // delete the above after moving it to a reserialize function
 
                }
@@ -1000,13 +1000,212 @@ struct inboxrules *deserialize_inbox_rules(char *serialized_rules) {
  */
 void inbox_do_msg(long msgnum, void *userdata) {
        struct inboxrules *ii = (struct inboxrules *) userdata;
-       struct CtdlMessage *msg;
+       struct CtdlMessage *msg = NULL;
+       int headers_loaded = 0;
+       int body_loaded = 0;
+       int metadata_loaded = 0;
+       int rule_activated = 0;                 // On each rule, this is set if the compare succeeds and the rule activates.
+       char compare_me[SIZ];                   // On each rule, we will store the field to be compared here.
+       int i;
+
        syslog(LOG_DEBUG, "inboxrules: processing message #%ld which is higher than %ld, we are in %s", msgnum, ii->lastproc, CC->room.QRname);
 
-       // FIXME    you are here
+       if (ii->num_rules <= 0) {
+               syslog(LOG_DEBUG, "inboxrules: rule set is empty");
+               return;
+       }
+
+       for (i=0; i<ii->num_rules; ++i) {
+               syslog(LOG_DEBUG, "inboxrules: processing rule %d is %s", i, field_keys[ ii->rules[i].compared_field ]);
+               rule_activated = 0;
+
+               // Before doing a field compare, check to see if we have the correct parts of the message in memory.
+
+               switch(ii->rules[i].compared_field) {
+                       // These fields require loading only the top-level headers
+                       case field_from:                // From:
+                       case field_tocc:                // To: or Cc:
+                       case field_subject:             // Subject:
+                       case field_replyto:             // Reply-to:
+                       case field_listid:              // List-ID:
+                       case field_envto:               // Envelope-to:
+                       case field_envfrom:             // Return-path:
+                               if (!headers_loaded) {
+                                       syslog(LOG_DEBUG, "inboxrules: loading headers for message %ld", msgnum);
+                                       msg = CtdlFetchMessage(msgnum, 0);
+                                       if (!msg) {
+                                               return;
+                                       }
+                                       headers_loaded = 1;
+                               }
+                               break;
+                       // These fields are not stored as Citadel headers, and therefore require a full message load.
+                       case field_sender:
+                       case field_resentfrom:
+                       case field_resentto:
+                       case field_xmailer:
+                       case field_xspamflag:
+                       case field_xspamstatus:
+                               if (!body_loaded) {
+                                       syslog(LOG_DEBUG, "inboxrules: loading all of message %ld", msgnum);
+                                       if (msg != NULL) {
+                                               CM_Free(msg);
+                                       }
+                                       msg = CtdlFetchMessage(msgnum, 1);
+                                       if (!msg) {
+                                               return;
+                                       }
+                                       headers_loaded = 1;
+                                       body_loaded = 1;
+                               }
+                               break;
+                       case field_size:
+                               if (!metadata_loaded) {
+                                       syslog(LOG_DEBUG, "inboxrules: loading metadata for message %ld", msgnum);
+                                       // FIXME do this
+                                       metadata_loaded = 1;
+                               }
+                               break;
+                       case field_all:
+                               syslog(LOG_DEBUG, "this is an always-on rule");
+                               break;
+                       default:
+                               syslog(LOG_DEBUG, "inboxrules: unknown rule key");
+               }
+
+               // If the rule involves a field comparison, load the field to be compared.
+               compare_me[0] = 0;
+               switch(ii->rules[i].compared_field) {
+
+                       case field_from:                // From:
+
+                               // FIXME we actually need the rfc822 address
+                               syslog(LOG_DEBUG, "eAuthor is <%s>", msg->cm_fields[eAuthor]);
 
+                               safestrncpy(compare_me, msg->cm_fields[eAuthor], sizeof compare_me);
+                               break;
+                       case field_tocc:                // To: or Cc:
+                               if (!IsEmptyStr(msg->cm_fields[eRecipient])) {
+                                       safestrncpy(compare_me, msg->cm_fields[eRecipient], sizeof compare_me);
+                               }
+                               if (!IsEmptyStr(msg->cm_fields[eCarbonCopY])) {
+                                       if (!IsEmptyStr(compare_me)) {
+                                               strcat(compare_me, ",");
+                                       }
+                                       safestrncpy(&compare_me[strlen(compare_me)], msg->cm_fields[eCarbonCopY], (sizeof compare_me - strlen(compare_me)));
+                               }
+                               break;
+                       case field_subject:             // Subject:
+                               safestrncpy(compare_me, msg->cm_fields[eMsgSubject], sizeof compare_me);
+                               break;
+                       case field_replyto:             // Reply-to:
+                               safestrncpy(compare_me, msg->cm_fields[eReplyTo], sizeof compare_me);
+                               break;
+                       case field_listid:              // List-ID:
+                               safestrncpy(compare_me, msg->cm_fields[eListID], sizeof compare_me);
+                               break;
+                       case field_envto:               // Envelope-to:
+                               safestrncpy(compare_me, msg->cm_fields[eenVelopeTo], sizeof compare_me);
+                               break;
+                       case field_envfrom:             // Return-path:
+                               safestrncpy(compare_me, msg->cm_fields[eMessagePath], sizeof compare_me);
+                               break;
+
+                       case field_sender:
+                       case field_resentfrom:
+                       case field_resentto:
+                       case field_xmailer:
+                       case field_xspamflag:
+                       case field_xspamstatus:
+
+                       default:
+                               break;
+               }
+
+               // Message data to compare is loaded, now do something.
+               switch(ii->rules[i].compared_field) {
+                       case field_from:                // From:
+                       case field_tocc:                // To: or Cc:
+                       case field_subject:             // Subject:
+                       case field_replyto:             // Reply-to:
+                       case field_listid:              // List-ID:
+                       case field_envto:               // Envelope-to:
+                       case field_envfrom:             // Return-path:
+                       case field_sender:
+                       case field_resentfrom:
+                       case field_resentto:
+                       case field_xmailer:
+                       case field_xspamflag:
+                       case field_xspamstatus:
+
+                               // For all of the above fields, we can compare the field we've loaded into the buffer.
+                               // FIXME you are here YOU ARE HERE
+                               syslog(LOG_DEBUG, "Value of field to compare is: <%s>", compare_me);
+                               switch(ii->rules[i].field_compare_op) {
+                                       case fcomp_contains:
+                                       case fcomp_matches:
+                                               rule_activated = (bmstrcasestr(compare_me, ii->rules[i].compared_value) ? 1 : 0);
+                                               break;
+                                       case fcomp_notcontains:
+                                       case fcomp_notmatches:
+                                               rule_activated = (bmstrcasestr(compare_me, ii->rules[i].compared_value) ? 0 : 1);
+                                               break;
+                                       case fcomp_is:
+                                               rule_activated = (strcasecmp(compare_me, ii->rules[i].compared_value) ? 0 : 1);
+                                               break;
+                                       case fcomp_isnot:
+                                               rule_activated = (strcasecmp(compare_me, ii->rules[i].compared_value) ? 1 : 0);
+                                               break;
+                               }
+
+                       case field_size:
+                               rule_activated = 0;     // FIXME
+                               break;
+                       case field_all:                 // This rule always triggers
+                               rule_activated = 1;
+                               break;
+                       default:
+                               TRACE;
+                               break;
+               }
+
+               if (rule_activated) {
+                       syslog(LOG_DEBUG, "rule activated");
+               }
+               else {
+                       syslog(LOG_DEBUG, "rule NOT activated");
+               }
+
+       
+       }
+
+       TRACE;
+       if (msg != NULL) {
+               CM_Free(msg);
+       }
 
-       //msg = CtdlFetchMessage(msgnum, 
+//struct irule {
+       //int field_compare_op;
+       //int compared_field;
+       //char compared_value[128];
+       //int size_compare_op;
+       //long compared_size;
+       //int action;
+       //char file_into[ROOMNAMELEN];
+       //char redirect_to[1024];
+       //char autoreply_message[SIZ];
+       //int final_action;
+//};
+
+//struct inboxrules {
+       //long lastproc;
+       //int num_rules;
+       //struct irule *rules;
+
+
+       // Fetch the message, including the body, we need all of it to run our rules.
+       //msg = CtdlFetchMessage(msgnum, 0);
+       //CM_Free(msg);
 
 }