aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2015-03-19 17:19:43 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2015-03-19 17:19:43 +0000
commita0b33ff3bab1fa9ef2a24008d63eaeb9b35d79ee (patch)
treec1d7f4e4dbfe82b7e78a6c9a40693f60ae2dfdb4
parent943734997a929e3d952be693ff7b202a9314680b (diff)
downloadrspamd-a0b33ff3bab1fa9ef2a24008d63eaeb9b35d79ee.tar.gz
rspamd-a0b33ff3bab1fa9ef2a24008d63eaeb9b35d79ee.zip
Implement parsing of internal functions.
-rw-r--r--src/libmime/mime_expressions.c118
-rw-r--r--src/libmime/mime_expressions.h3
2 files changed, 115 insertions, 6 deletions
diff --git a/src/libmime/mime_expressions.c b/src/libmime/mime_expressions.c
index 84e5037a8..bbe411f01 100644
--- a/src/libmime/mime_expressions.c
+++ b/src/libmime/mime_expressions.c
@@ -99,7 +99,7 @@ struct rspamd_regexp_atom {
*/
struct rspamd_function_atom {
gchar *name; /**< name of function */
- GList *args; /**< its args */
+ GArray *args; /**< its args */
};
struct rspamd_mime_atom {
@@ -163,7 +163,7 @@ rspamd_mime_expr_quark (void)
* Rspamd regexp utility functions
*/
static struct rspamd_regexp_atom *
-rspamd_parse_regexp_atom (rspamd_mempool_t * pool, const gchar *line)
+rspamd_mime_expr_parse_regexp_atom (rspamd_mempool_t * pool, const gchar *line)
{
const gchar *begin, *end, *p, *src, *start;
gchar *dbegin, *dend;
@@ -178,11 +178,11 @@ rspamd_parse_regexp_atom (rspamd_mempool_t * pool, const gchar *line)
}
if ((re = rspamd_regexp_cache_query (NULL, line, NULL)) != NULL) {
- return ((struct rspamd_regexp_element *)rspamd_regexp_get_ud (re));
+ return ((struct rspamd_regexp_atom *)rspamd_regexp_get_ud (re));
}
src = line;
- result = rspamd_mempool_alloc0 (pool, sizeof (struct rspamd_regexp_element));
+ result = rspamd_mempool_alloc0 (pool, sizeof (struct rspamd_regexp_atom));
/* Skip whitespaces */
while (g_ascii_isspace (*line)) {
line++;
@@ -339,6 +339,105 @@ rspamd_parse_regexp_atom (rspamd_mempool_t * pool, const gchar *line)
return result;
}
+struct rspamd_function_atom *
+rspamd_mime_expr_parse_function_atom (const gchar *input)
+{
+ const gchar *obrace, *ebrace, *p, *c;
+ gchar t, *databuf;
+ struct rspamd_function_atom *res;
+ struct expression_argument arg;
+ GError *err = NULL;
+ enum {
+ start_read_argument = 0,
+ in_string,
+ in_regexp,
+ got_backslash,
+ got_comma
+ } state, prev_state = 0;
+
+ obrace = strchr (input, '(');
+ ebrace = strrchr (input, ')');
+
+ g_assert (obrace != NULL && ebrace != NULL);
+
+ res = g_slice_alloc0 (sizeof (*res));
+ res->name = g_malloc (obrace - input + 1);
+ rspamd_strlcpy (res->name, input, obrace - input + 1);
+ res->args = g_array_new (FALSE, FALSE, sizeof (struct expression_argument));
+
+ p = obrace + 1;
+ c = p;
+ state = start_read_argument;
+
+ /* Read arguments */
+ while (p <= ebrace) {
+ t = *p;
+ switch (state) {
+ case start_read_argument:
+ if (t == '/') {
+ state = in_regexp;
+ c = p;
+ }
+ else if (!g_ascii_isspace (t)) {
+ state = in_string;
+ c = p;
+ }
+ p ++;
+ break;
+ case in_regexp:
+ if (t == '\\') {
+ state = got_backslash;
+ prev_state = in_regexp;
+ }
+ else if (t == ',' || p == ebrace) {
+ databuf = g_malloc (p - c + 1);
+ rspamd_strlcpy (databuf, c, p - c + 1);
+ arg.type = EXPRESSION_ARGUMENT_REGEXP;
+ arg.data = rspamd_regexp_cache_create (NULL, databuf, NULL, &err);
+
+ if (arg.data == NULL) {
+ /* Fallback to string */
+ msg_warn ("cannot parse slashed argument %s as regexp: %s",
+ databuf, err->message);
+ g_error_free (err);
+ arg.type = EXPRESSION_ARGUMENT_NORMAL;
+ arg.data = databuf;
+ }
+ else {
+ g_free (databuf);
+ }
+
+ g_array_append_val (res->args, arg);
+ }
+ p ++;
+ break;
+ case in_string:
+ if (t == '\\') {
+ state = got_backslash;
+ prev_state = in_string;
+ }
+ else if (t == ',' || p == ebrace) {
+ databuf = g_malloc (p - c + 1);
+ rspamd_strlcpy (databuf, c, p - c + 1);
+ arg.type = EXPRESSION_ARGUMENT_NORMAL;
+ arg.data = databuf;
+ g_array_append_val (res->args, arg);
+ }
+ p ++;
+ break;
+ case got_backslash:
+ state = prev_state;
+ p ++;
+ break;
+ case got_comma:
+ state = start_read_argument;
+ break;
+ }
+ }
+
+ return res;
+}
+
static rspamd_expression_atom_t *
rspamd_mime_expr_parse (const gchar *line, gsize len,
rspamd_mempool_t *pool, gpointer ud, GError **err)
@@ -451,13 +550,22 @@ set:
rspamd_strlcpy (mime_atom->str, line, p - line + 1);
if (!is_function) {
- mime_atom->d.re = rspamd_parse_regexp_atom (pool, mime_atom->str);
+ mime_atom->d.re = rspamd_mime_expr_parse_regexp_atom (pool,
+ mime_atom->str);
if (mime_atom->d.re == NULL) {
g_set_error (err, rspamd_mime_expr_quark(), 200, "cannot parse regexp '%s'",
mime_atom->str);
goto err;
}
}
+ else {
+ mime_atom->d.func = rspamd_mime_expr_parse_function_atom (mime_atom->str);
+ if (mime_atom->d.func == NULL) {
+ g_set_error (err, rspamd_mime_expr_quark(), 200, "cannot parse function '%s'",
+ mime_atom->str);
+ goto err;
+ }
+ }
a = rspamd_mempool_alloc (pool, sizeof (*a));
a->len = p - line;
diff --git a/src/libmime/mime_expressions.h b/src/libmime/mime_expressions.h
index b8a240f3e..ea00bc278 100644
--- a/src/libmime/mime_expressions.h
+++ b/src/libmime/mime_expressions.h
@@ -18,8 +18,9 @@ extern const struct rspamd_atom_subr mime_expr_subr;
*/
struct expression_argument {
enum {
- EXPRESSION_ARGUMENT_NORMAL,
+ EXPRESSION_ARGUMENT_NORMAL = 0,
EXPRESSION_ARGUMENT_BOOL,
+ EXPRESSION_ARGUMENT_REGEXP
} type; /**< type of argument (text or other function) */
void *data; /**< pointer to its data */
};