FILTER command
authorChristian Thaeter <ct@pipapo.org>
Mon, 29 Oct 2007 05:27:34 +0000 (06:27 +0100)
committerChristian Thaeter <ct@pipapo.org>
Mon, 29 Oct 2007 05:27:34 +0000 (06:27 +0100)
src/rxpd.h
src/rxpd_connection_cmd.c
tests/20simplecommands.tests
tests/30listmanipulation.tests

index f4c0db0..5c51138 100644 (file)
@@ -57,6 +57,7 @@
   RXPD_CMD(UPDATE,      "atimes from other lists")              \
   RXPD_CMD(MERGE,       "new rules from from other lists")      \
   RXPD_CMD(EXPIRE,      "aged rules from a list")               \
+  RXPD_CMD(FILTER,      "rules in a list")                      \
   RXPD_CMD(DUMP,        "rules in a list")                      \
   RXPD_CMD(LIST,        "all existing lists")                   \
   RXPD_CMD(VERSION,     "of this rxpd is "PACKAGE_VERSION)      \
index f4e0261..f88f7e3 100644 (file)
@@ -625,6 +625,88 @@ rxpd_connection_cmd_MERGE (struct rxpd_connection* self)
   rxpd_buffer_printf (&self->out, "#OK:\n");
 }
 
+void
+rxpd_connection_cmd_FILTER (struct rxpd_connection* self)
+{
+  RXPD_FILENAME_REQUIRED;
+
+  /* Filter processes the target list by checking its rules against other lists */
+  /* The outcome of this check is used to decide how to process with a rule */
+  /* DELETE: delete rule from list */
+  /* ACTIVATE: try to reactivate a rule which was commented out */
+  /* any other: comment the rule out by using 'any other' as hint*/
+
+  struct rxpd_base* base = self->socket->base;
+
+  pth_rwlock_acquire (&self->file->lock, PTH_RWLOCK_RW, FALSE, NULL);
+
+  char* line;
+  while ((line = rxpd_buffer_readline (&self->in)))
+    {
+      if (*line && !RXPD_PREFIXCMP (line, "#EXIT:"))
+        {
+
+          /* for each line which is a listname */
+          struct rxpd_file* source;
+          source = (struct rxpd_file*) psplay_find (&base->files, line);
+          if (source)
+            {
+              pth_rwlock_acquire (&source->lock, PTH_RWLOCK_RD, FALSE, NULL);
+
+              LLIST_FOREACH (&self->file->rules, n)
+                {
+                  LLIST_FOREACH (&source->rules, m)
+                    {
+                      struct rxpd_rule* rule_n = (struct rxpd_rule*)n;
+                      struct rxpd_rule* rule_m = (struct rxpd_rule*)m;
+                      if (rule_m->string[0] != '#')
+                        {
+                          if (regexec (&rule_m->rx, rule_n->string, 0, NULL, 0) == 0)
+                            {
+                              if (rule_m->atime != (time_t) -1)
+                                time (&rule_m->atime);
+
+                              if (RXPD_PREFIXCMP (rule_m->string, "DELETE:"))
+                                {
+                                  n = llist_prev (n);
+                                  rxpd_log (base, LOG_DEBUG, "deleting rule '%s' from list '%s'\n",
+                                            rule_n->string, (const char*) self->file->node.key);
+                                  rxpd_rule_delete (rule_n);
+                                }
+                              else if (RXPD_PREFIXCMP (rule_m->string, "ACTIVATE:"))
+                                {
+                                  if (!rxpd_rule_activate (rule_n))
+                                    rxpd_buffer_printf (&self->out, "#ERROR: cant activate rule '%s'\n", rule_n->string);
+                                  else
+                                    rxpd_log (base, LOG_DEBUG, "activated rule '%s' in list '%s'\n",
+                                              rule_n->string, (const char*) self->file->node.key);
+                                }
+                              else
+                                {
+                                  char* c = strndupa (rule_m->string, strchr (rule_m->string, ':') - rule_m->string);
+                                  rxpd_log (base, LOG_DEBUG, "commenting rule '%s' as '%s', in list '%s'\n",
+                                            rule_n->string, c, (const char*) self->file->node.key);
+
+                                  rxpd_rule_comment (rule_n, c);
+                                }
+                            }
+                        }
+                    }
+                }
+              pth_rwlock_release (&source->lock);
+            }
+          else
+            rxpd_buffer_printf (&self->out, "#ERROR: unknown file '%s'\n", line);
+        }
+      else
+        break;  /* exit at empty line, error or whatever */
+    }
+
+  pth_rwlock_release (&self->file->lock);
+
+  rxpd_buffer_printf (&self->out, "#OK:\n");
+}
+
 /* Template
 void
 rxpd_connection_cmd_ (struct rxpd_connection* self)
index 37101f9..e771fd3 100644 (file)
@@ -46,6 +46,7 @@ out: # FETCH a list from a remote server.
 out: # UPDATE atimes from other lists.
 out: # MERGE new rules from from other lists.
 out: # EXPIRE aged rules from a list.
+out: # FILTER rules in a list.
 out: # DUMP rules in a list.
 out: # LIST all existing lists.
 out: # VERSION of this rxpd is $version.
index d85357f..aad3be1 100644 (file)
@@ -4,7 +4,7 @@
 cp -rf $srcdir/files ./
 chmod -R +w files
 port=$((RANDOM+1500))
-./rxpd -L $LC_CTYPE -dq -b files -p policy -t $port example
+./rxpd -L $LC_CTYPE -Dvvv -b files -p policy -t $port example &>,${TESTS##*/}.log &
 
 function rxpd_client()
 {
@@ -174,6 +174,38 @@ out: # test list line 3
 out: # test list line 4
 END
 
+TEST "filter, add activateable rule" <<END
+in: APPEND:test
+in: #something: # test list line 5
+in: #EXIT:
+out: #OK:
+END
+
+TEST "filter, create" <<END
+in: APPEND:filter
+in: :DELETE:line .*1
+in: :ACTIVATE:line 5
+in: :something:line 4
+in: #EXIT:
+out: #OK:
+END
+
+TEST "filter, run" <<END
+in: FILTER:test
+in: filter
+in: #EXIT:
+out: #OK:
+END
+
+TEST "filter, check" <<END
+in: DUMP:test
+out: # test list line -4
+out: # test list line -3
+out: # test list line -2
+out: # test list line 3
+out: #something: # test list line 4
+out: # test list line 5
+END
 
 TEST "daemon shutdown" <<END
 in: SHUTDOWN: