-const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.54 2009/06/03 16:42:49 fabiankeil Exp $";
+const char urlmatch_rcs[] = "$Id: urlmatch.c,v 1.62 2011/09/04 11:10:56 fabiankeil Exp $";
/*********************************************************************
*
* File : $Source: /cvsroot/ijbswa/current/urlmatch.c,v $
const char urlmatch_h_rcs[] = URLMATCH_H_VERSION;
-enum regex_anchoring {NO_ANCHORING, LEFT_ANCHORED, RIGHT_ANCHORED};
+enum regex_anchoring
+{
+ NO_ANCHORING,
+ LEFT_ANCHORED,
+ RIGHT_ANCHORED,
+ RIGHT_ANCHORED_HOST
+};
static jb_err compile_host_pattern(struct url_spec *url, const char *host_pattern);
/*********************************************************************
/*
* Check for * URI. If found, we're done.
- */
+ */
if (*http->url == '*')
{
if ( NULL == (http->path = strdup("*"))
- || NULL == (http->hostport = strdup("")) )
+ || NULL == (http->hostport = strdup("")) )
{
return JB_ERR_MEMORY;
}
*********************************************************************/
static int unknown_method(const char *method)
{
- static const char *known_http_methods[] = {
+ static const char * const known_http_methods[] = {
/* Basic HTTP request type */
"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS", "TRACE", "CONNECT",
/* webDAV extensions (RFC2518) */
* Microsoft webDAV extension for Exchange 2000. See:
* http://lists.w3.org/Archives/Public/w3c-dist-auth/2002JanMar/0001.html
* http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_methods.asp
- */
+ */
"BCOPY", "BMOVE", "BDELETE", "BPROPFIND", "BPROPPATCH",
/*
* Another Microsoft webDAV extension for Exchange 2000. See:
* http://systems.cs.colorado.edu/grunwald/MobileComputing/Papers/draft-cohen-gena-p-base-00.txt
* http://lists.w3.org/Archives/Public/w3c-dist-auth/2002JanMar/0001.html
* http://msdn.microsoft.com/library/en-us/wss/wss/_webdav_methods.asp
- */
+ */
"SUBSCRIBE", "UNSUBSCRIBE", "NOTIFY", "POLL",
/*
* Yet another WebDAV extension, this time for
*
* Parameters :
* 1 : pattern = The pattern to compile.
- * 2 : anchoring = How the regex should be anchored.
- * Can be either one of NO_ANCHORING,
- * LEFT_ANCHORED or RIGHT_ANCHORED.
+ * 2 : anchoring = How the regex should be modified
+ * before compilation. Can be either
+ * one of NO_ANCHORING, LEFT_ANCHORED,
+ * RIGHT_ANCHORED or RIGHT_ANCHORED_HOST.
* 3 : url = In case of failures, the spec member is
* logged and the structure freed.
* 4 : regex = Where the compiled regex should be stored.
case RIGHT_ANCHORED:
fmt = "%s$";
break;
+ case RIGHT_ANCHORED_HOST:
+ fmt = "%s\\.?$";
+ break;
case LEFT_ANCHORED:
fmt = "^%s";
break;
*********************************************************************/
static jb_err compile_host_pattern(struct url_spec *url, const char *host_pattern)
{
- return compile_pattern(host_pattern, RIGHT_ANCHORED, url, &url->host_regex);
+ return compile_pattern(host_pattern, RIGHT_ANCHORED_HOST, url, &url->host_regex);
}
#else
url->unanchored |= ANCHOR_LEFT;
}
- /*
+ /*
* Split domain into components
*/
url->dbuffer = strdup(host_pattern);
return JB_ERR_MEMORY;
}
- /*
+ /*
* Map to lower case
*/
for (p = url->dbuffer; *p ; p++)
*p = (char)tolower((int)(unsigned char)*p);
}
- /*
+ /*
* Split the domain name into components
*/
url->dcount = ssplit(url->dbuffer, ".", v, SZ(v), 1, 1);
}
else if (url->dcount != 0)
{
- /*
+ /*
* Save a copy of the pointers in dvec
*/
size = (size_t)url->dcount * sizeof(*url->dvec);
-
+
url->dvec = (char **)malloc(size);
if (NULL == url->dvec)
{
{
const unsigned char *pat = (const unsigned char *)pattern;
const unsigned char *txt = (const unsigned char *)text;
- const unsigned char *fallback = pat;
+ const unsigned char *fallback = pat;
int wildcard = 0;
-
+
unsigned char lastchar = 'a';
unsigned i;
unsigned char charmap[32];
-
+
while (*txt)
{
}
/* '*' in the pattern? */
- if (*pat == '*')
+ if (*pat == '*')
{
-
+
/* The pattern ends afterwards? Speed up the return. */
if (*++pat == '\0')
{
return 0;
}
-
+
/* Else, set wildcard mode and remember position after '*' */
wildcard = 1;
fallback = pat;
while (*++pat != ']')
{
if (!*pat)
- {
+ {
return 1;
}
else if (*pat == '-')
for (i = lastchar; i <= *pat; i++)
{
charmap[i / 8] |= (unsigned char)(1 << (i % 8));
- }
+ }
}
else
{
} /* -END- if Character range specification */
- /*
- * Char match, or char range match?
+ /*
+ * Char match, or char range match?
*/
if ( (*pat == *txt)
|| (*pat == '?')
|| ((*pat == ']') && (charmap[*txt / 8] & (1 << (*txt % 8)))) )
{
- /*
- * Sucess: Go ahead
+ /*
+ * Success: Go ahead
*/
pat++;
}
else if (!wildcard)
{
- /*
+ /*
* No match && no wildcard: No luck
*/
return 1;
}
/* Is it a tag pattern? */
- if (0 == strncmpic("TAG:", url->spec, 4))
+ if (0 == strncmpic(url->spec, "TAG:", 4))
{
/* The pattern starts with the first character after "TAG:" */
const char *tag_pattern = buf + 4;
}
+/*********************************************************************
+ *
+ * Function : port_matches
+ *
+ * Description : Compares a port against a port list.
+ *
+ * Parameters :
+ * 1 : port = The port to check.
+ * 2 : port_list = The list of port to compare with.
+ *
+ * Returns : TRUE for yes, FALSE otherwise.
+ *
+ *********************************************************************/
+static int port_matches(const int port, const char *port_list)
+{
+ return ((NULL == port_list) || match_portlist(port_list, port));
+}
+
+
+/*********************************************************************
+ *
+ * Function : host_matches
+ *
+ * Description : Compares a host against a host pattern.
+ *
+ * Parameters :
+ * 1 : url = The URL to match
+ * 2 : pattern = The URL pattern
+ *
+ * Returns : TRUE for yes, FALSE otherwise.
+ *
+ *********************************************************************/
+static int host_matches(const struct http_request *http,
+ const struct url_spec *pattern)
+{
+#ifdef FEATURE_EXTENDED_HOST_PATTERNS
+ return ((NULL == pattern->host_regex)
+ || (0 == regexec(pattern->host_regex, http->host, 0, NULL, 0)));
+#else
+ return ((NULL == pattern->dbuffer) || (0 == domain_match(pattern, http)));
+#endif
+}
+
+
+/*********************************************************************
+ *
+ * Function : path_matches
+ *
+ * Description : Compares a path against a path pattern.
+ *
+ * Parameters :
+ * 1 : path = The path to match
+ * 2 : pattern = The URL pattern
+ *
+ * Returns : TRUE for yes, FALSE otherwise.
+ *
+ *********************************************************************/
+static int path_matches(const char *path, const struct url_spec *pattern)
+{
+ return ((NULL == pattern->preg)
+ || (0 == regexec(pattern->preg, path, 0, NULL, 0)));
+}
+
+
/*********************************************************************
*
* Function : url_match
int url_match(const struct url_spec *pattern,
const struct http_request *http)
{
- /* XXX: these should probably be functions. */
-#define PORT_MATCHES ((NULL == pattern->port_list) || match_portlist(pattern->port_list, http->port))
-#ifdef FEATURE_EXTENDED_HOST_PATTERNS
-#define DOMAIN_MATCHES ((NULL == pattern->host_regex) || (0 == regexec(pattern->host_regex, http->host, 0, NULL, 0)))
-#else
-#define DOMAIN_MATCHES ((NULL == pattern->dbuffer) || (0 == domain_match(pattern, http)))
-#endif
-#define PATH_MATCHES ((NULL == pattern->preg) || (0 == regexec(pattern->preg, http->path, 0, NULL, 0)))
-
if (pattern->tag_regex != NULL)
{
/* It's a tag pattern and shouldn't be matched against URLs */
return 0;
- }
+ }
- return (PORT_MATCHES && DOMAIN_MATCHES && PATH_MATCHES);
+ return (port_matches(http->port, pattern->port_list)
+ && host_matches(http, pattern) && path_matches(http->path, pattern));
}