+2001-12-12 [alfons] 0.6.5claws81
+
+ 0.6.5claws80 was tagged as LAST_STABLE
+
+ * src/filtering.[ch]
+ * src/matcher.[ch]
+ * src/matcher_parser_lex.c
+ fix the filtering; my last attempt to get it right,
+ if it does not work, it's Hoa's turn. ;-)
+
+ for my honourable peers:
+
+ the code now makes a clear distinction between
+ rules as they are displayed (probably escaped),
+ and as they are executed (probably unescaped). the
+ parser does *NOT* do any unescaping, this is
+ the task of the matcher.c (which breaks up a
+ rule into condition) and the filtering.c (which
+ breaks up the rule's action). to make this
+ run happily we provide an unescaped copy of
+ crucial strings to the MatcherProp and
+ FilteringAction structures. note that the only
+ exception to this is any REGEXP string. those
+ are directly passed to regcomp() and regexp()
+ (who have much more powerful unescape functions).
+
+ for everyone else:
+
+ you can escape tab (\t), carriage return (\r),
+ linefeed (\n), form feed (\f), quote (\"),
+ single quote (\'), bell (\b) in all the entry
+ lines in the scoring & filtering dialogs.
+ as an added bonus this should not affect
+ existing filtering rules.
+
2001-12-12 [carsten] 0.6.5claws80
* src/summaryview.c
action->type = type;
action->account_id = account_id;
- if (destination)
- action->destination = g_strdup(destination);
+ if (destination) {
+ action->destination = g_strdup(destination);
+ action->unesc_destination = matcher_unescape_str(g_strdup(destination));
+ } else {
+ action->destination = NULL;
+ action->unesc_destination = NULL;
+ }
action->labelcolor = labelcolor;
return action;
}
void filteringaction_free(FilteringAction * action)
{
+ g_return_if_fail(action);
if (action->destination)
g_free(action->destination);
+ if (action->unesc_destination)
+ g_free(action->unesc_destination);
g_free(action);
}
return FALSE;
}
+#if 0
static gchar * filteringaction_execute_command(gchar * cmd, MsgInfo * info)
{
gchar * s = cmd;
}
return processed_cmd;
}
+#endif
/*
fitleringaction_apply
return FALSE;
case MATCHACTION_EXECUTE:
- cmd = matching_build_command(action->destination, info);
+ cmd = matching_build_command(action->unesc_destination, info);
if (cmd == NULL)
return FALSE;
else {
return NULL;
}
-
-
+/* matcher_unescape_str() - assumes that unescaping frees up room
+ * in the string, so it returns the unescaped string in the
+ * source */
gchar *matcher_unescape_str(gchar *str)
{
gchar *tmp = alloca(strlen(str) + 1);
else {
src++;
if (*src == '\\')
- *dst++ = '\\';
- else if (*src == 'n')
+ *dst++ = '\\'; /* insert backslash */
+ else if (*src == 'n') /* insert control characters */
*dst++ = '\n';
else if (*src == 'r')
*dst++ = '\r';
- else if (*src == '\'' || *src == '\"')
+ else if (*src == 't')
+ *dst++ = '\t';
+ else if (*src == 'r')
+ *dst++ = '\r';
+ else if (*src == 'b')
+ *dst++ = '\b';
+ else if (*src == 'f')
+ *dst++ = '\f';
+ else if (*src == '\'' || *src == '\"') /* insert \' or \" */
*dst++ = *src;
else {
+ /* FIXME: should perhaps escape character... */
src--;
*dst++ = *src;
}
prop = g_new0(MatcherProp, 1);
prop->criteria = criteria;
- if (header != NULL)
- prop->header = g_strdup(header);
- else
- prop->header = NULL;
- if (expr != NULL)
- prop->expr = g_strdup(expr);
- else
- prop->expr = NULL;
+ if (header != NULL) {
+ prop->header = g_strdup(header);
+ prop->unesc_header = matcher_unescape_str(g_strdup(header));
+ }
+ else {
+ prop->header = NULL;
+ prop->unesc_header = NULL;
+ }
+ if (expr != NULL) {
+ prop->expr = g_strdup(expr);
+ prop->unesc_expr = matcher_unescape_str(g_strdup(expr));
+ }
+ else {
+ prop->expr = NULL;
+ prop->unesc_expr = NULL;
+ }
prop->matchtype = matchtype;
prop->preg = NULL;
prop->value = value;
void matcherprop_free(MatcherProp * prop)
{
- g_free(prop->expr);
+ if (prop->expr)
+ g_free(prop->expr);
+ if (prop->unesc_expr)
+ g_free(prop->unesc_expr);
+ if (prop->header)
+ g_free(prop->header);
+ if (prop->unesc_header)
+ g_free(prop->unesc_header);
if (prop->preg != NULL) {
regfree(prop->preg);
g_free(prop->preg);
case MATCHTYPE_REGEXP:
if (!prop->preg && (prop->error == 0)) {
prop->preg = g_new0(regex_t, 1);
+ /* if regexp then don't use the escaped string */
if (regcomp(prop->preg, prop->expr,
REG_NOSUB | REG_EXTENDED
| ((prop->matchtype == MATCHTYPE_REGEXPCASE)
return FALSE;
case MATCHTYPE_MATCH:
- return (strstr(str, prop->expr) != NULL);
+ return (strstr(str, prop->unesc_expr) != NULL);
+ /* FIXME: put upper in unesc_str */
case MATCHTYPE_MATCHCASE:
- str2 = alloca(strlen(prop->expr) + 1);
- strcpy(str2, prop->expr);
+ str2 = alloca(strlen(prop->unesc_expr) + 1);
+ strcpy(str2, prop->unesc_expr);
g_strup(str2);
str1 = alloca(strlen(str) + 1);
strcpy(str1, str);
if (file == NULL)
return FALSE;
- cmd = matching_build_command(prop->expr, info);
+ cmd = matching_build_command(prop->unesc_expr, info);
if (cmd == NULL)
return FALSE;
case MATCHTYPE_MATCHCASE:
case MATCHTYPE_REGEXP:
case MATCHTYPE_REGEXPCASE:
- count = 0;
- for(p = matcher->expr; *p != 0 ; p++)
- if (*p == '\"') count ++;
-
- expr_str = g_new(char, strlen(matcher->expr) + count + 1);
-
- for(p = matcher->expr, out = expr_str ; *p != 0 ; p++, out++) {
- if (*p == '\"') {
- *out = '\\'; out++;
- *out = '\"';
- }
- else
- *out = *p;
- }
- * out = '\0';
-
if (matcher->header)
matcher_str =
g_strdup_printf("%s \"%s\" %s \"%s\"",
criteria_str, matcher->header,
- matchtype_str, expr_str);
+ matchtype_str, matcher->expr);
else
matcher_str =
g_strdup_printf("%s %s \"%s\"", criteria_str,
- matchtype_str, expr_str);
-
- g_free(expr_str);
-
- break;
-
- /*
- case MATCHTYPE_REGEXP:
- case MATCHTYPE_REGEXPCASE:
-
- if (matcher->header)
- matcher_str =
- g_strdup_printf("%s \"%s\" %s /%s/",
- criteria_str, matcher->header,
- matchtype_str, matcher->expr);
- else
- matcher_str =
- g_strdup_printf("%s %s /%s/", criteria_str,
matchtype_str, matcher->expr);
-
break;
- */
}
return matcher_str;
return result;
}
-
+/* matching_build_command() - preferably cmd should be unescaped */
gchar * matching_build_command(gchar * cmd, MsgInfo * info)
{
gchar * s = cmd;
gchar * p;
gint size;
- matcher_unescape_str(cmd);
-
size = strlen(cmd) + 1;
while (*s != '\0') {
if (*s == '%') {
BEGIN(string);
string_buf_ptr = string_buf;
}
-<string>\\n add_char('\n');
-<string>\\t add_char('\t');
-<string>\\r add_char('\r');
-<string>\\b add_char('\b');
-<string>\\f add_char('\f');
-<string>\\. add_char(yytext[1]);
+ /* alfons - OK, the new attempt is to just swallow
+ * *EVERYTHING* and make sure everything is escaped
+ * when actually performing things. */
+<string>\\\" {
+ /* take care of escaped \" because this means the
+ * quote char should be skipped */
+ add_char('\\');
+ add_char('\"');
+ }
<string>\" {
+ /* get out of the state: string ends. */
BEGIN(0);
*string_buf_ptr = '\0';
yylval.str = string_buf;
return MATCHER_STRING;
}
+ /* put everything else in the output. */
<string>. {
-add_char(yytext[0]);
-}
+ add_char(yytext[0]);
+ }
\[[^\[\]]*\] {
- BEGIN(0);
- yylval.str = yytext + 1;
- yytext[strlen(yytext) - 1] = '\0';
- return MATCHER_SECTION;
- }
+ BEGIN(0);
+ yylval.str = yytext + 1;
+ yytext[strlen(yytext) - 1] = '\0';
+ return MATCHER_SECTION;
+ }
[-+]?[0-9]+ {
yylval.str = yytext;
return MATCHER_INTEGER;