Introduce negative tag patterns NO-REQUEST-TAG and NO-RESPONSE-TAG
authorFabian Keil <fk@fabiankeil.de>
Sun, 24 Nov 2013 14:24:18 +0000 (14:24 +0000)
committerFabian Keil <fk@fabiankeil.de>
Sun, 24 Nov 2013 14:24:18 +0000 (14:24 +0000)
They apply if no matching tag is found after parsing client
or server headers.

actions.c
actions.h
parsers.c
project.h
urlmatch.c

index acd3d7c..b07d8bc 100644 (file)
--- a/actions.c
+++ b/actions.c
@@ -1,4 +1,4 @@
-const char actions_rcs[] = "$Id: actions.c,v 1.87 2012/11/24 13:59:00 fabiankeil Exp $";
+const char actions_rcs[] = "$Id: actions.c,v 1.88 2013/11/24 14:22:51 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/actions.c,v $
@@ -810,8 +810,8 @@ int update_action_bits_for_tag(struct client_state *csp, const char *tag)
       /* and through all the action patterns, */
       for (b = b->next; NULL != b; b = b->next)
       {
-         /* skip the URL patterns, */
-         if (NULL == b->url->pattern.tag_regex)
+         /* skip everything but TAG patterns, */
+         if (!(b->url->flags & PATTERN_SPEC_TAG_PATTERN))
          {
             continue;
          }
@@ -835,6 +835,76 @@ int update_action_bits_for_tag(struct client_state *csp, const char *tag)
 }
 
 
+/*********************************************************************
+ *
+ * Function    :  check_negative_tag_patterns
+ *
+ * Description :  Updates the action bits based on NO-*-TAG patterns.
+ *
+ * Parameters  :
+ *          1  :  csp = Current client state (buffers, headers, etc...)
+ *          2  :  flag = The tag pattern type
+ *
+ * Returns     :  JB_ERR_OK in case off success, or
+ *                JB_ERR_MEMORY on out-of-memory error.
+ *
+ *********************************************************************/
+jb_err check_negative_tag_patterns(struct client_state *csp, unsigned int flag)
+{
+   struct list_entry *tag;
+   struct file_list *fl;
+   struct url_actions *b = NULL;
+   int i;
+
+   for (i = 0; i < MAX_AF_FILES; i++)
+   {
+      fl = csp->actions_list[i];
+      if ((fl == NULL) || ((b = fl->f) == NULL))
+      {
+         continue;
+      }
+      for (b = b->next; NULL != b; b = b->next)
+      {
+         int tag_found = 0;
+         if (0 == (b->url->flags & flag))
+         {
+            continue;
+         }
+         for (tag = csp->tags->first; NULL != tag; tag = tag->next)
+         {
+            if (0 == regexec(b->url->pattern.tag_regex, tag->str, 0, NULL, 0))
+            {
+               /*
+                * The pattern matches at least one tag, thus the action
+                * section doesn't apply and we don't need to look at the
+                * other tags.
+                */
+               tag_found = 1;
+               break;
+            }
+         }
+         if (!tag_found)
+         {
+            /*
+             * The pattern doesn't match any tags,
+             * thus the action section applies.
+             */
+            if (merge_current_action(csp->action, b->action))
+            {
+               log_error(LOG_LEVEL_ERROR,
+                  "Out of memory while changing action bits");
+               return JB_ERR_MEMORY;
+            }
+            log_error(LOG_LEVEL_HEADER, "Updated action bits based on: %s",
+               b->url->spec);
+         }
+      }
+   }
+
+   return JB_ERR_OK;
+}
+
+
 /*********************************************************************
  *
  * Function    :  free_current_action
index be9f02c..5b9e7dc 100644 (file)
--- a/actions.h
+++ b/actions.h
@@ -1,6 +1,6 @@
 #ifndef ACTIONS_H_INCLUDED
 #define ACTIONS_H_INCLUDED
-#define ACTIONS_H_VERSION "$Id: actions.h,v 1.21 2012/07/27 17:39:57 fabiankeil Exp $"
+#define ACTIONS_H_VERSION "$Id: actions.h,v 1.22 2013/11/24 14:23:28 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/actions.h,v $
@@ -64,6 +64,7 @@ extern jb_err merge_actions (struct action_spec *dest,
 extern int update_action_bits_for_all_tags(struct client_state *csp);
 #endif
 extern int update_action_bits_for_tag(struct client_state *csp, const char *tag);
+extern jb_err check_negative_tag_patterns(struct client_state *csp, unsigned int flag);
 extern jb_err copy_action (struct action_spec *dest,
                            const struct action_spec *src);
 extern char * actions_to_text     (const struct action_spec *action);
index bd5d33d..0e58c11 100644 (file)
--- a/parsers.c
+++ b/parsers.c
@@ -1,4 +1,4 @@
-const char parsers_rcs[] = "$Id: parsers.c,v 1.278 2013/08/06 12:58:28 fabiankeil Exp $";
+const char parsers_rcs[] = "$Id: parsers.c,v 1.279 2013/08/06 12:59:34 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/parsers.c,v $
@@ -1097,6 +1097,7 @@ static void enforce_header_order(struct list *headers, const struct list *ordere
    return;
 }
 
+
 /*********************************************************************
  *
  * Function    :  sed
@@ -1126,19 +1127,21 @@ jb_err sed(struct client_state *csp, int filter_server_headers)
    const add_header_func_ptr *f;
    jb_err err = JB_ERR_OK;
 
+   scan_headers(csp);
+
    if (filter_server_headers)
    {
       v = server_patterns;
       f = add_server_headers;
+      check_negative_tag_patterns(csp, PATTERN_SPEC_NO_RESPONSE_TAG_PATTERN);
    }
    else
    {
       v = client_patterns;
       f = add_client_headers;
+      check_negative_tag_patterns(csp, PATTERN_SPEC_NO_REQUEST_TAG_PATTERN);
    }
 
-   scan_headers(csp);
-
    while ((err == JB_ERR_OK) && (v->str != NULL))
    {
       for (p = csp->headers->first; (err == JB_ERR_OK) && (p != NULL); p = p->next)
index efcb456..8e0e937 100644 (file)
--- a/project.h
+++ b/project.h
@@ -1,7 +1,7 @@
 #ifndef PROJECT_H_INCLUDED
 #define PROJECT_H_INCLUDED
 /** Version string. */
-#define PROJECT_H_VERSION "$Id: project.h,v 1.198 2013/11/24 14:22:51 fabiankeil Exp $"
+#define PROJECT_H_VERSION "$Id: project.h,v 1.199 2013/11/24 14:23:28 fabiankeil Exp $"
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/project.h,v $
@@ -393,6 +393,17 @@ struct pattern_spec
  */
 #define ANCHOR_RIGHT 2
 
+/** Pattern spec bitmap: It's an URL pattern. */
+#define PATTERN_SPEC_URL_PATTERN          0x00000001UL
+
+/** Pattern spec bitmap: It's a TAG pattern. */
+#define PATTERN_SPEC_TAG_PATTERN          0x00000002UL
+
+/** Pattern spec bitmap: It's a NO-REQUEST-TAG pattern. */
+#define PATTERN_SPEC_NO_REQUEST_TAG_PATTERN 0x00000004UL
+
+/** Pattern spec bitmap: It's a NO-RESPONSE-TAG pattern. */
+#define PATTERN_SPEC_NO_RESPONSE_TAG_PATTERN 0x00000008UL
 
 /**
  * An I/O buffer.  Holds a string which can be appended to, and can have data
index 3e807bb..092ae0f 100644 (file)
@@ -1,4 +1,4 @@
-const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.75 2012/12/07 12:49:47 fabiankeil Exp $";
+const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.76 2013/11/24 14:22:51 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/urlmatch.c,v $
@@ -1114,13 +1114,31 @@ jb_err create_url_spec(struct pattern_spec *url, char *buf)
    /* Remember the original specification for the CGI pages. */
    url->spec = strdup_or_die(buf);
 
-   /* Is it a tag pattern? */
+   /* Is it a positive tag pattern? */
    if (0 == strncmpic(url->spec, "TAG:", 4))
    {
       /* The pattern starts with the first character after "TAG:" */
       const char *tag_pattern = buf + 4;
+      url->flags |= PATTERN_SPEC_TAG_PATTERN;
       return compile_pattern(tag_pattern, NO_ANCHORING, url, &url->pattern.tag_regex);
    }
+   /* Is it a negative tag pattern? */
+   if (0 == strncmpic(url->spec, "NO-REQUEST-TAG:", 15))
+   {
+      /* The pattern starts with the first character after "NO-REQUEST-TAG:" */
+      const char *tag_pattern = buf + 15;
+      url->flags |= PATTERN_SPEC_NO_REQUEST_TAG_PATTERN;
+      return compile_pattern(tag_pattern, NO_ANCHORING, url, &url->pattern.tag_regex);
+   }
+   if (0 == strncmpic(url->spec, "NO-RESPONSE-TAG:", 16))
+   {
+      /* The pattern starts with the first character after "NO-RESPONSE-TAG:" */
+      const char *tag_pattern = buf + 16;
+      url->flags |= PATTERN_SPEC_NO_RESPONSE_TAG_PATTERN;
+      return compile_pattern(tag_pattern, NO_ANCHORING, url, &url->pattern.tag_regex);
+   }
+
+   url->flags |= PATTERN_SPEC_URL_PATTERN;
 
    /* If it isn't a tag pattern it must be an URL pattern. */
    return compile_url_pattern(url, buf);
@@ -1250,9 +1268,9 @@ static int path_matches(const char *path, const struct pattern_spec *pattern)
 int url_match(const struct pattern_spec *pattern,
               const struct http_request *http)
 {
-   if (pattern->pattern.tag_regex != NULL)
+   if (!(pattern->flags & PATTERN_SPEC_URL_PATTERN))
    {
-      /* It's a tag pattern and shouldn't be matched against URLs */
+      /* It's not an URL pattern and thus shouldn't be matched against URLs */
       return 0;
    }