Fixed expansion of empty fields in matchactions
[claws.git] / src / matcher.c
index f85878154b0f0335cd83dab8c5af4dc991243125..c5019c5ba8cf4ac886b893934993cdec5c57f7a0 100644 (file)
@@ -91,7 +91,7 @@ static MatchParser matchparser_tab[] = {
        {MATCHACTION_FORWARD_AS_ATTACHMENT, "forward_as_attachment"},
        {MATCHACTION_EXECUTE, "execute"},
        {MATCHACTION_COLOR, "color"},
-       {MATCHACTION_BOUNCE, "bounce"},
+       {MATCHACTION_REDIRECT, "redirect"},
        {MATCHACTION_DELETE_ON_SERVER, "delete_on_server"}
 };
 
@@ -109,6 +109,35 @@ gchar * get_matchparser_tab_str(gint id)
        return NULL;
 }
 
+/* matcher_escape_str() - escapes a string returns newly allocated escaped string */
+gchar *matcher_escape_str(const gchar *str)
+{
+       register const gchar *walk;
+       register int escape;
+       gchar *res;
+       register char *reswalk;
+
+       if (str == NULL)
+               return NULL;
+
+       for (escape = 0, walk = str; *walk; walk++)
+               if (*walk == '\'' || *walk == '\"')
+                       escape++;
+
+       if (!escape)
+               return g_strdup(str);
+       
+       reswalk = res = g_new0(gchar, (walk - str) + escape + 1);
+       for (walk = str; *walk; walk++, reswalk++) {
+               if (*walk == '\'' || *walk == '\"')
+                       *reswalk++ = '\\';
+               *reswalk = *walk;
+       }
+
+       *reswalk = 0;
+       return res;
+}
+
 /* matcher_unescape_str() - assumes that unescaping frees up room
  * in the string, so it returns the unescaped string in the 
  * source */
@@ -265,6 +294,7 @@ gboolean matcherprop_match_execute(MatcherProp * prop, MsgInfo * info)
 {
        gchar * file;
        gchar * cmd;
+       gint retval;
 
        file = procmsg_get_message_file(info);
        if (file == NULL)
@@ -274,7 +304,10 @@ gboolean matcherprop_match_execute(MatcherProp * prop, MsgInfo * info)
        if (cmd == NULL)
                return FALSE;
 
-       return (system(cmd) == 0);
+       retval = system(cmd);
+       debug_print(_("Command exit code: %d\n"), retval);
+
+       return (retval == 0);
 }
 
 /* match a message and his headers, hlist can be NULL if you don't
@@ -817,6 +850,9 @@ gchar * matcherprop_to_string(MatcherProp * matcher)
        case MATCHCRITERIA_FORWARDED:
        case MATCHCRITERIA_NOT_FORWARDED:
                return g_strdup(criteria_str);
+       case MATCHCRITERIA_EXECUTE:
+       case MATCHCRITERIA_NOT_EXECUTE:
+               return g_strdup_printf("%s \"%s\"", criteria_str, matcher->expr);
        }
 
        matchtype_str = NULL;
@@ -880,6 +916,8 @@ gchar * matcherlist_to_string(MatcherList * matchers)
        return result;
 }
 
+#define STRLEN_ZERO(s) ((s) ? strlen(s) : 0)
+#define STRLEN_DEFAULT(s,d) ((s) ? strlen(s) : STRLEN_ZERO(d))
 /* matching_build_command() - preferably cmd should be unescaped */
 gchar * matching_build_command(gchar * cmd, MsgInfo * info)
 {
@@ -889,7 +927,16 @@ gchar * matching_build_command(gchar * cmd, MsgInfo * info)
        gchar * p;
        gint size;
 
-       size = strlen(cmd) + 1;
+       gchar *no_subject    = _("(none)") ;
+       gchar *no_from       = _("(none)") ;
+       gchar *no_to         = _("(none)") ;
+       gchar *no_cc         = _("(none)") ;
+       gchar *no_date       = _("(none)") ;
+       gchar *no_msgid      = _("(none)") ;
+       gchar *no_newsgroups = _("(none)") ;
+       gchar *no_references = _("(none)") ;
+
+       size = STRLEN_ZERO(cmd) + 1;
        while (*s != '\0') {
                if (*s == '%') {
                        s++;
@@ -898,28 +945,28 @@ gchar * matching_build_command(gchar * cmd, MsgInfo * info)
                                size -= 1;
                                break;
                        case 's': /* subject */
-                               size += strlen(info->subject) - 2;
+                               size += STRLEN_DEFAULT(info->subject, no_subject) - 2;
                                break;
                        case 'f': /* from */
-                               size += strlen(info->from) - 2;
+                               size += STRLEN_DEFAULT(info->from, no_from) - 2;
                                break;
                        case 't': /* to */
-                               size += strlen(info->to) - 2;
+                               size += STRLEN_DEFAULT(info->to, no_to) - 2;
                                break;
                        case 'c': /* cc */
-                               size += strlen(info->cc) - 2;
+                               size += STRLEN_DEFAULT(info->cc, no_cc) - 2;
                                break;
                        case 'd': /* date */
-                               size += strlen(info->date) - 2;
+                               size += STRLEN_DEFAULT(info->date, no_date) - 2;
                                break;
                        case 'i': /* message-id */
-                               size += strlen(info->msgid) - 2;
+                               size += STRLEN_DEFAULT(info->msgid, no_msgid) - 2;
                                break;
                        case 'n': /* newsgroups */
-                               size += strlen(info->newsgroups) - 2;
+                               size += STRLEN_DEFAULT(info->newsgroups, no_newsgroups) - 2;
                                break;
                        case 'r': /* references */
-                               size += strlen(info->references) - 2;
+                               size += STRLEN_DEFAULT(info->references, no_references) - 2;
                                break;
                        case 'F': /* file */
                                filename = folder_item_fetch_msg(info->folder,
@@ -955,56 +1002,56 @@ gchar * matching_build_command(gchar * cmd, MsgInfo * info)
                                if (info->subject != NULL)
                                        strcpy(p, info->subject);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_subject);
                                p += strlen(p);
                                break;
                        case 'f': /* from */
                                if (info->from != NULL)
                                        strcpy(p, info->from);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_from);
                                p += strlen(p);
                                break;
                        case 't': /* to */
                                if (info->to != NULL)
                                        strcpy(p, info->to);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_to);
                                p += strlen(p);
                                break;
                        case 'c': /* cc */
                                if (info->cc != NULL)
                                        strcpy(p, info->cc);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_cc);
                                p += strlen(p);
                                break;
                        case 'd': /* date */
                                if (info->date != NULL)
                                        strcpy(p, info->date);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_date);
                                p += strlen(p);
                                break;
                        case 'i': /* message-id */
                                if (info->msgid != NULL)
                                        strcpy(p, info->msgid);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_msgid);
                                p += strlen(p);
                                break;
                        case 'n': /* newsgroups */
                                if (info->newsgroups != NULL)
                                        strcpy(p, info->newsgroups);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_newsgroups);
                                p += strlen(p);
                                break;
                        case 'r': /* references */
                                if (info->references != NULL)
                                        strcpy(p, info->references);
                                else
-                                       strcpy(p, _("(none)"));
+                                       strcpy(p, no_references);
                                p += strlen(p);
                                break;
                        case 'F': /* file */
@@ -1030,6 +1077,8 @@ gchar * matching_build_command(gchar * cmd, MsgInfo * info)
        debug_print("*** exec string \"%s\"\n", processed_cmd);
        return processed_cmd;
 }
+#undef STRLEN_DEFAULT
+#undef STRLEN_ZERO
 
 /* ************************************************************ */
 
@@ -1175,12 +1224,14 @@ void prefs_matcher_read_config(void)
        f = fopen(rcpath, "rb");
        g_free(rcpath);
 
-       if (f != NULL)
+       if (f != NULL) {
                matcher_parser_start_parsing(f);
+               fclose(f);
+       }
        else {
                /* previous version compatibily */
 
-               printf("reading filtering\n");
+               /* printf("reading filtering\n"); */
                rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                     FILTERING_RC, NULL);
                f = fopen(rcpath, "rb");
@@ -1191,7 +1242,7 @@ void prefs_matcher_read_config(void)
                        fclose(matcher_parserin);
                }
                
-               printf("reading scoring\n");
+               /* printf("reading scoring\n"); */
                rcpath = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
                                     SCORING_RC, NULL);
                f = fopen(rcpath, "rb");