pfix-srsd: add a -I option
[apps/pfixtools.git] / postlicyd / filter.c
index d145f42..0a9cef9 100644 (file)
 /*     products derived from this software without specific prior written     */
 /*     permission.                                                            */
 /*                                                                            */
-/*  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND   */
-/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE     */
-/*  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        */
-/*  PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS    */
-/*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR    */
-/*  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF      */
-/*  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  */
-/*  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN   */
-/*  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   */
-/*  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF    */
-/*  THE POSSIBILITY OF SUCH DAMAGE.                                           */
+/*  THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS   */
+/*  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED         */
+/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE    */
+/*  DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY         */
+/*  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        */
+/*  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS   */
+/*  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)     */
+/*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       */
+/*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  */
+/*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
+/*  POSSIBILITY OF SUCH DAMAGE.                                               */
+/*                                                                            */
+/*   Copyright (c) 2006-2008 the Authors                                      */
+/*   see AUTHORS and source files for details                                 */
 /******************************************************************************/
 
 /*
@@ -50,6 +53,8 @@ static filter_async_handler_t       async_handler = NULL;
 static const filter_hook_t default_hook = {
     .type      = 0,
     .value     = (char*)"DUNNO",
+    .counter   = -1,
+    .cost      = 0,
     .postfix   = true,
     .async     = false,
     .filter_id = 0
@@ -58,6 +63,8 @@ static const filter_hook_t default_hook = {
 static const filter_hook_t async_hook = {
     .type      = 0,
     .value     = NULL,
+    .counter   = -1,
+    .cost      = 0,
     .postfix   = false,
     .async     = true,
     .filter_id = 0
@@ -277,6 +284,7 @@ bool filter_add_hook(filter_t *filter, const char *name, int name_len,
                      const char *value, int value_len)
 {
     filter_hook_t hook;
+    hook.filter_id = -1;
     hook.type  = hook_tokenize(name, name_len);
     if (hook.type == HTK_UNKNOWN) {
         err("unknown hook type %.*s", name_len, name);
@@ -288,13 +296,42 @@ bool filter_add_hook(filter_t *filter, const char *name, int name_len,
         return false;
     }
     hook.async   = false;
+
+    /* Value format is (counter:id:incr)?(postfix:reply|filter_name)
+     */
+    hook.value = NULL;
+    if (strncmp(value, "counter:", 8) == 0) {
+        char *end = NULL;
+        value += 8;
+        hook.counter = strtol(value, &end, 10);
+        if (end == value || *end != ':') {
+              err("hook %s, cannot read counter id", htokens[hook.type]);
+              return false;
+        } else if (hook.counter < 0 || hook.counter >= MAX_COUNTERS) {
+            err("hook %s, invalid counter id %d", htokens[hook.type], hook.counter);
+            return false;
+        }
+        value = end + 1;
+        hook.cost = strtol(value, &end, 10);
+        if (end == value || *end != ':') {
+            err("hook %s, cannot read counter increment", htokens[hook.type]);
+            return false;
+        } else if (hook.cost < 0) {
+            err("hook %s, invalid counter increment value %d", htokens[hook.type],
+                hook.cost);
+            return false;
+        }
+        value = end + 1;
+    } else {
+        hook.counter = -1;
+        hook.cost    = 0;
+    }
     hook.postfix = (strncmp(value, "postfix:", 8) == 0);
-    if (hook.postfix && query_format(NULL, 0, value + 8, NULL) == -1) {
+    if (hook.postfix && !query_format_check(value + 8)) {
         err("invalid formatted text \"%s\"", value + 8);
         return false;
     }
     hook.value = m_strdup(hook.postfix ? value + 8 : value);
-    hook.filter_id = -1;
     array_add(filter->hooks, hook);
     return true;
 }
@@ -319,6 +356,12 @@ void filter_context_wipe(filter_context_t *context)
     }
 }
 
+void filter_context_clean(filter_context_t *context)
+{
+    p_clear(&context->counters, 1);
+    context->instance[0] = '\0';
+}
+
 void filter_post_async_result(filter_context_t *context, filter_result_t result)
 {
     const filter_t *filter = context->current_filter;