Set CODE_STATUS to stable.
[privoxy.git] / urlmatch.c
index 74287ff..3e4e621 100644 (file)
@@ -1,4 +1,4 @@
-const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.17 2007/04/15 16:39:21 fabiankeil Exp $";
+const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.20 2007/09/02 15:31:20 fabiankeil Exp $";
 /*********************************************************************
  *
  * File        :  $Source: /cvsroot/ijbswa/current/urlmatch.c,v $
@@ -33,6 +33,19 @@ const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.17 2007/04/15 16:39:21 fabianke
  *
  * Revisions   :
  *    $Log: urlmatch.c,v $
+ *    Revision 1.20  2007/09/02 15:31:20  fabiankeil
+ *    Move match_portlist() from filter.c to urlmatch.c.
+ *    It's used for url matching, not for filtering.
+ *
+ *    Revision 1.19  2007/09/02 13:42:11  fabiankeil
+ *    - Allow port lists in url patterns.
+ *    - Ditch unused url_spec member pathlen.
+ *
+ *    Revision 1.18  2007/07/30 16:42:21  fabiankeil
+ *    Move the method check into unknown_method()
+ *    and loop through the known methods instead
+ *    of using a screen-long OR chain.
+ *
  *    Revision 1.17  2007/04/15 16:39:21  fabiankeil
  *    Introduce tags as alternative way to specify which
  *    actions apply to a request. At the moment tags can be
@@ -807,20 +820,20 @@ jb_err create_url_spec(struct url_spec * url, const char * buf)
    }
 
    /* Only reached for URL patterns */
-   if ((p = strchr(buf, '/')) != NULL)
+   p = strchr(buf, '/');
+   if (NULL != p)
    {
-      if (NULL == (url->path = strdup(p)))
+      url->path = strdup(p);
+      if (NULL == url->path)
       {
          freez(url->spec);
          return JB_ERR_MEMORY;
       }
-      url->pathlen = strlen(url->path);
       *p = '\0';
    }
    else
    {
-      url->path    = NULL;
-      url->pathlen = 0;
+      url->path = NULL;
    }
    if (url->path)
    {
@@ -856,14 +869,20 @@ jb_err create_url_spec(struct url_spec * url, const char * buf)
          return JB_ERR_PARSE;
       }
    }
-   if ((p = strchr(buf, ':')) == NULL)
+
+   p = strchr(buf, ':');
+   if (NULL != p)
    {
-      url->port = 0;
+      *p++ = '\0';
+      url->port_list = strdup(p);
+      if (NULL == url->port_list)
+      {
+         return JB_ERR_MEMORY;
+      }
    }
    else
    {
-      *p++ = '\0';
-      url->port = atoi(p);
+      url->port_list = NULL;
    }
 
    if (buf[0] != '\0')
@@ -974,6 +993,7 @@ void free_url_spec(struct url_spec *url)
    freez(url->dbuffer);
    freez(url->dvec);
    freez(url->path);
+   freez(url->port_list);
    if (url->preg)
    {
       regfree(url->preg);
@@ -1003,17 +1023,99 @@ void free_url_spec(struct url_spec *url)
 int url_match(const struct url_spec *pattern,
               const struct http_request *url)
 {
+   /* XXX: these should probably be functions. */
+#define PORT_MATCHES ((NULL == pattern->port_list) || match_portlist(pattern->port_list, url->port))
+#define DOMAIN_MATCHES ((NULL == pattern->dbuffer) || (0 == domain_match(pattern, url)))
+#define PATH_MATCHES ((NULL == pattern->path) || (0 == regexec(pattern->preg, url->path, 0, NULL, 0)))
+
    if (pattern->tag_regex != NULL)
    {
       /* It's a tag pattern and shouldn't be matched against URLs */
       return 0;
    } 
 
-   return ((pattern->port == 0) || (pattern->port == url->port))
-       && ((pattern->dbuffer == NULL) || (domain_match(pattern, url) == 0))
-       && ((pattern->path == NULL) ||
-            (regexec(pattern->preg, url->path, 0, NULL, 0) == 0)
-      );
+   return (PORT_MATCHES && DOMAIN_MATCHES && PATH_MATCHES);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function    :  match_portlist
+ *
+ * Description :  Check if a given number is covered by a comma
+ *                separated list of numbers and ranges (a,b-c,d,..)
+ *
+ * Parameters  :
+ *          1  :  portlist = String with list
+ *          2  :  port = port to check
+ *
+ * Returns     :  0 => no match
+ *                1 => match
+ *
+ *********************************************************************/
+int match_portlist(const char *portlist, int port)
+{
+   char *min, *max, *next, *portlist_copy;
+
+   min = next = portlist_copy = strdup(portlist);
+
+   /*
+    * Zero-terminate first item and remember offset for next
+    */
+   if (NULL != (next = strchr(portlist_copy, (int) ',')))
+   {
+      *next++ = '\0';
+   }
+
+   /*
+    * Loop through all items, checking for match
+    */
+   while(min)
+   {
+      if (NULL == (max = strchr(min, (int) '-')))
+      {
+         /*
+          * No dash, check for equality
+          */
+         if (port == atoi(min))
+         {
+            free(portlist_copy);
+            return(1);
+         }
+      }
+      else
+      {
+         /*
+          * This is a range, so check if between min and max,
+          * or, if max was omitted, between min and 65K
+          */
+         *max++ = '\0';
+         if(port >= atoi(min) && port <= (atoi(max) ? atoi(max) : 65535))
+         {
+            free(portlist_copy);
+            return(1);
+         }
+
+      }
+
+      /*
+       * Jump to next item
+       */
+      min = next;
+
+      /*
+       * Zero-terminate next item and remember offset for n+1
+       */
+      if ((NULL != next) && (NULL != (next = strchr(next, (int) ','))))
+      {
+         *next++ = '\0';
+      }
+   }
+
+   free(portlist_copy);
+   return 0;
+
 }