#include <sys/wait.h>
#include <string.h>
#include <limits.h>
+#include <regex.h>
#include <libcitadel.h>
#include "../../citadel_defs.h"
#include "../../server.h"
int compare_compound = 0; // Set to 1 when we are comparing both display name and email address
int keep_message = 1; // Nonzero to keep the message in the inbox after processing, 0 to delete it.
int i;
+ const char *ptr,*ptr1; // Temporary variables to get X-Spam-Status
+ int len;
syslog(LOG_DEBUG, "inboxrules: processing message #%ld which is higher than %ld, we are in %s", msgnum, ii->lastproc, CC->room.QRname);
}
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 ]);
+ syslog(LOG_DEBUG, "inboxrules: processing rule: %d , field: %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.
}
break;
+ case field_xspamstatus:
+ if (!IsEmptyStr(msg->cm_fields[eMessageText])) {
+ if ((ptr=strstr(msg->cm_fields[eMessageText],"X-Spam-Status"))!=NULL) {
+ len=0;
+ ptr1=ptr;
+ while (*ptr1 && (*ptr1!='\r') && (*ptr1!='\n')) {
+ ptr1++;
+ len++;
+ }
+ if (len && (len<SIZ)) {
+ memcpy(compare_me, ptr, len);
+ compare_me[len]='\0';
+ }
+ }
+ }
+ break;
+
case field_sender:
case field_resentfrom:
case field_resentto:
case field_xmailer:
case field_xspamflag:
- case field_xspamstatus:
default:
break;
case field_xspamstatus:
// For all of the above fields, we can compare the field we've loaded into the buffer.
- syslog(LOG_DEBUG, "Value of field to compare is: <%s>", compare_me);
- int substring_match = (bmstrcasestr(compare_me, ii->rules[i].compared_value) ? 1 : 0);
+ syslog(LOG_DEBUG, "inboxrules: rule %d: field \"%s\" is \"%s\", looking for \"%s\"",
+ i,
+ field_keys[ii->rules[i].compared_field],
+ compare_me,
+ ii->rules[i].compared_value
+ );
+ int substring_match = 0;
+ int regex_match = 0;
int exact_match = 0;
- if (compare_compound) {
+ int rc = 0;
+
+ regex_t regex;
+
+ rc = regcomp(®ex, ii->rules[i].compared_value, (REG_EXTENDED | REG_ICASE | REG_NOSUB | REG_NEWLINE));
+ if (rc) {
+ syslog(LOG_ERR, "inboxrules: regcomp: error %d trying to compile \"%s\"", rc, ii->rules[i].compared_value);
+ }
+
+ if (compare_compound) { // comparing a compound field such as name+address
char *sep = strchr(compare_me, '|');
if (sep) {
*sep = 0;
+ ++sep;
exact_match =
(strcasecmp(compare_me, ii->rules[i].compared_value) ? 0 : 1)
- + (strcasecmp(++sep, ii->rules[i].compared_value) ? 0 : 1)
+ + (strcasecmp(sep, ii->rules[i].compared_value) ? 0 : 1)
+ ;
+ substring_match =
+ (bmstrcasestr(compare_me, ii->rules[i].compared_value) ? 1 : 0)
+ + (bmstrcasestr(sep, ii->rules[i].compared_value) ? 1 : 0)
+ ;
+ if (!rc) regex_match =
+ (regexec(®ex, compare_me, 0, 0, 0) ? 0 : 1)
+ + (regexec(®ex, sep, 0, 0, 0) ? 0 : 1)
;
}
}
- else {
+ else { // comparing a single field only
exact_match = (strcasecmp(compare_me, ii->rules[i].compared_value) ? 0 : 1);
+ substring_match = (bmstrcasestr(compare_me, ii->rules[i].compared_value) ? 1 : 0);
+ if (!rc) regex_match = (regexec(®ex, compare_me, 0, 0, 0) ? 0 : 1);
}
- syslog(LOG_DEBUG, "substring match: %d", substring_match);
- syslog(LOG_DEBUG, "exact match: %d", exact_match);
+
+ regfree(®ex);
+ syslog(LOG_DEBUG, "inboxrules: substring match: %d", substring_match);
+ syslog(LOG_DEBUG, "inboxrules: regex match: %d", regex_match);
+ syslog(LOG_DEBUG, "inboxrules: exact match: %d", exact_match);
switch(ii->rules[i].field_compare_op) {
case fcomp_contains:
- case fcomp_matches:
rule_activated = substring_match;
break;
+ case fcomp_matches:
+ rule_activated = regex_match;
+ break;
case fcomp_notcontains:
- case fcomp_notmatches:
rule_activated = !substring_match;
break;
+ case fcomp_notmatches:
+ rule_activated = !regex_match;
+ break;
case fcomp_is:
rule_activated = exact_match;
break;
return; // config msgnum is set but that message does not exist
}
- ii = deserialize_inbox_rules(msg->cm_fields[eMesageText]);
+ ii = deserialize_inbox_rules(msg->cm_fields[eMessageText]);
CM_Free(msg);
if (ii == NULL) {
struct CtdlMessage *msg = CtdlFetchMessage(CC->user.msgnum_inboxrules, 1);
if (msg != NULL) {
- if (!CM_IsEmpty(msg, eMesageText)) {
+ if (!CM_IsEmpty(msg, eMessageText)) {
char *token;
- char *rest = msg->cm_fields[eMesageText];
+ char *rest = msg->cm_fields[eMessageText];
while ((token = strtok_r(rest, "\n", &rest))) {
// for backwards compatibility, "# WEBCIT_RULE" is an alias for "rule"