You are viewing a plain text version of this content. The canonical link for it is here.
Posted to mod_python-commits@quetz.apache.org by gr...@apache.org on 2006/10/24 05:41:55 UTC

svn commit: r467228 - in /httpd/mod_python/trunk: Doc/ lib/python/mod_python/ src/ src/include/

Author: grahamd
Date: Mon Oct 23 20:41:54 2006
New Revision: 467228

URL: http://svn.apache.org/viewvc?view=rev&rev=467228
Log:
(MODPYTHON-193) Added new req.hlist.location attribute so that value to a
Location/LocationMatch directive can be determined. Also fixed crash when
req.hlist is accessed from inside a filter and do some restructuring of how
errors are logged and displayed back to browser.

Modified:
    httpd/mod_python/trunk/Doc/appendixc.tex
    httpd/mod_python/trunk/lib/python/mod_python/apache.py
    httpd/mod_python/trunk/lib/python/mod_python/importer.py
    httpd/mod_python/trunk/src/hlist.c
    httpd/mod_python/trunk/src/hlistobject.c
    httpd/mod_python/trunk/src/include/hlist.h
    httpd/mod_python/trunk/src/include/mod_python.h
    httpd/mod_python/trunk/src/include/mod_python.h.in
    httpd/mod_python/trunk/src/mod_python.c
    httpd/mod_python/trunk/src/requestobject.c

Modified: httpd/mod_python/trunk/Doc/appendixc.tex
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/Doc/appendixc.tex?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/Doc/appendixc.tex (original)
+++ httpd/mod_python/trunk/Doc/appendixc.tex Mon Oct 23 20:41:54 2006
@@ -75,6 +75,14 @@
       those other modules to access the mechanics of how mod_python creates
       interpreters, thereby allowing other modules to also embed Python
       and for there not to be a conflict with mod_python.
+    \item
+      (\citetitle[http://issues.apache.org/jira/browse/MODPYTHON-193]{MODPYTHON-193})
+      Added new attribute available as \code{req.hlist.location}. For a
+      handler executed directly as the result of a handler directive
+      within a \code{Location} directive, this will be set to the value
+      of the \code{Location} directive. If \code{LocationMatch}, or
+      wildcards or regular expressions are used with \code{Location},
+      the value will be the matched value in the URL and not the pattern.
   \end{itemize}
 
   Improvements

Modified: httpd/mod_python/trunk/lib/python/mod_python/apache.py
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/lib/python/mod_python/apache.py?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/apache.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/apache.py Mon Oct 23 20:41:54 2006
@@ -564,6 +564,7 @@
             except:
                 # last try
                 traceback.print_exc()
+                sys.stderr.flush()
 
         finally:
             # erase the traceback

Modified: httpd/mod_python/trunk/lib/python/mod_python/importer.py
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/lib/python/mod_python/importer.py?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/lib/python/mod_python/importer.py (original)
+++ httpd/mod_python/trunk/lib/python/mod_python/importer.py Mon Oct 23 20:41:54 2006
@@ -337,29 +337,27 @@
     def _log_notice(self, msg):
         pid = os.getpid()
         name = apache.interpreter
-        server = apache.main_server
         flags = apache.APLOG_NOERRNO|apache.APLOG_NOTICE
-        text = "mod_python (pid=%d,interpreter=%s): %s" % (pid, `name`, msg)
-        apache.log_error(text, flags, server)
+        text = "mod_python (pid=%d, interpreter=%s): %s" % (pid, `name`, msg)
+        apache.main_server.log_error(text, flags)
 
     def _log_warning(self, msg):
         pid = os.getpid()
         name = apache.interpreter
-        server = apache.main_server
         flags = apache.APLOG_NOERRNO|apache.APLOG_WARNING
-        text = "mod_python (pid=%d,interpreter=%s): %s" % (pid, `name`, msg)
-        apache.log_error(text, flags, server)
+        text = "mod_python (pid=%d, interpreter=%s): %s" % (pid, `name`, msg)
+        apache.main_server.log_error(text, flags)
 
     def _log_exception(self):
         pid = os.getpid()
         name = apache.interpreter
-        server = apache.main_server
         flags = apache.APLOG_NOERRNO|apache.APLOG_ERR
-        prefix = "mod_python (pid=%d,interpreter=%s)" % (pid, `name`)
+        msg = 'Application error'
+        text = "mod_python (pid=%d, interpreter=%s): %s" % (pid, `name`, msg)
+        apache.main_server.log_error(text, flags)
         etype, evalue, etb = sys.exc_info()
-        for msg in traceback.format_exception(etype, evalue, etb):
-            text = "%s: %s" % (prefix, msg[:-1])
-            apache.log_error(text, flags, server)
+        for text in traceback.format_exception(etype, evalue, etb):
+            apache.main_server.log_error(text[:-1], flags)
         etb = None
 
     def cached_modules(self):
@@ -1264,7 +1262,7 @@
         try:
             (exc_type, exc_value, exc_traceback) = traceblock
             result = self.ReportError(exc_type, exc_value, exc_traceback,
-                    srv=conn.base_server, phase="ConnectionHandler",
+                    conn=conn, phase="ConnectionHandler",
                     hname=conn.hlist.handler, debug=debug)
 
         finally:
@@ -1279,7 +1277,7 @@
         try:    
             exc_type, exc_value, exc_traceback = sys.exc_info()
             result = self.ReportError(exc_type, exc_value, exc_traceback,
-                    srv=conn.base_server, phase="ConnectionHandler",
+                    conn=conn, phase="ConnectionHandler",
                     hname=conn.hlist.handler, debug=debug)
         finally:
             exc_traceback = None
@@ -1425,13 +1423,28 @@
     options = req.get_options()
 
     try:
+        (aborted, hlist) = False, req.hlist
+
+	# The actual handler root is the directory
+	# associated with the handler first in the
+	# chain. This may be a handler which was called
+	# in an earlier phase if the req.add_handler()
+	# method was used. The directory for those that
+	# follow the first may have been overridden by
+	# directory supplied to the req.add_handler()
+	# method.
+
+        root = hlist.directory
+        parent = hlist.parent
+        while parent is not None:
+            root = parent.directory
+            parent = parent.parent
+
         # Iterate over the handlers defined for the
         # current phase and execute each in turn
         # until the last is reached or prematurely
         # aborted.
 
-        (aborted, hlist) = False, req.hlist
-
         while not aborted and hlist.handler is not None:
 
             try:
@@ -1443,6 +1456,11 @@
                 # If directory for handler is not set,
                 # then search back through parents and
                 # inherit value from parent if found.
+                # This directory is that where modules
+                # are searched for first and may not be
+                # the same as the handler root if it
+                # was supplied explicitly to the method
+                # req.add_handler().
 
                 if directory is None:
                     parent = hlist.parent
@@ -1468,7 +1486,7 @@
                 # current request so that it will be
                 # available from within 'import_module()'.
 
-                cache = _setup_current_cache(config, options, directory)
+                cache = _setup_current_cache(config, options, root)
 
                 (aborted, result) = _process_target(config=config, req=req,
                         directory=directory, handler=handler,
@@ -1583,8 +1601,7 @@
             exc_type, exc_value, exc_traceback = sys.exc_info()
             result = self.ReportError(exc_type, exc_value, exc_traceback,
                                       filter=filter, phase=filter.name,
-                                      hname=filter.req.filename,
-                                      debug=debug)
+                                      hname=filter.req.filename, debug=debug)
         finally:
             exc_traceback = None
 
@@ -1647,8 +1664,8 @@
 _callback.ImportDispatch = new.instancemethod(
         ImportDispatch, _callback, apache.CallBack)
 
-def ReportError(self, etype, evalue, etb, req=None, filter=None,
-                srv=None, phase="N/A", hname="N/A", debug=0):
+def ReportError(self, etype, evalue, etb, conn=None, req=None, filter=None,
+                phase="N/A", hname="N/A", debug=0):
 
     try:
         try:
@@ -1668,22 +1685,54 @@
 
                 debug = 0
 
+            # Determine which log function we are going
+            # to use to output any messages.
+
+            if filter and not req:
+                req = filter.req
+
+            if req:
+                log_error = req.log_error
+            elif conn:
+                log_error = conn.log_error
+            else:
+                log_error = apache.main_server.log_error
+
             # Always log the details of any exception.
 
             pid = os.getpid()
             iname = apache.interpreter
             flags = apache.APLOG_NOERRNO|apache.APLOG_ERR
-            details = "(pid=%d,interpreter=%s,phase=%s,handler=%s)" % \
-                    (pid, `iname`, `phase`, `hname`)
+
+            text = "mod_python (pid=%d, interpreter=%s, " % (pid, `iname`)
+            text = text + "phase=%s, handler=%s)" % (`phase`, `hname`)
+            text = text + ": Application error"
+
+            log_error(text, flags)
+
+            if req:
+                location = None
+                directory = None
+
+                context = req.hlist
+
+                if context:
+                    while context.parent != None:
+                        context = context.parent
+
+                    location = context.location
+                    directory = context.directory
+
+                log_error('URI: %s' % `req.uri`, flags)
+                log_error('Location: %s' % `location`, flags)
+                log_error('Directory: %s' % `directory`, flags)
+                log_error('Filename: %s' % `req.filename`, flags)
+                log_error('PathInfo: %s' % `req.path_info`, flags)
 
             tb = traceback.format_exception(etype, evalue, etb)
 
             for line in tb:
-                text = "mod_python %s: %s" % (details, line[:-1])
-                if req:
-                    req.log_error(text, flags)
-                else:
-                    apache.log_error(text, flags, srv)
+                log_error(line[:-1], flags)
 
             if not debug or not req:
                 return apache.HTTP_INTERNAL_SERVER_ERROR
@@ -1695,12 +1744,16 @@
                 text = text + 'PID: %s\n' % pid
                 text = text + 'Interpreter: %s\n' % `iname`
                 text = text + 'Phase: %s\n' % `phase`
+
                 if req:
-                    context = req.hlist
-                    while context.parent != None:
-                        context = context.parent
-                    text = text + 'HandlerRoot: %s\n' % `context.directory`
-                    text = text + 'HandlerPath: %s\n' % `req.hlist.directory`
+                    text = text + '\n'
+                    text = text + 'URI: %s\n' % `req.uri`
+                    text = text + 'Location: %s\n' % `location`
+                    text = text + 'Directory: %s\n' % `directory`
+                    text = text + 'Filename: %s\n' % `req.filename`
+                    text = text + 'PathInfo: %s\n' % `req.path_info`
+
+                text = text + '\n'
                 text = text + 'Handler: %s\n' % cgi.escape(repr(hname))
                 text = text + '\n'
 

Modified: httpd/mod_python/trunk/src/hlist.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/hlist.c?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/hlist.c (original)
+++ httpd/mod_python/trunk/src/hlist.c Mon Oct 23 20:41:54 2006
@@ -33,9 +33,10 @@
  *  Start a new list.
  */
 
-hl_entry *hlist_new(apr_pool_t *p, const char *h, PyObject *o, const char *d, 
-                    int d_is_fnmatch, ap_regex_t *regex, const int s,
-                    hl_entry* parent)
+hl_entry *hlist_new(apr_pool_t *p, const char *h, PyObject *o,
+                    const char *d, int d_is_fnmatch, ap_regex_t *d_regex,
+                    const char *l, int l_is_fnmatch, ap_regex_t *l_regex,
+                    const int s, hl_entry* parent)
 {
     hl_entry *hle;
 
@@ -45,7 +46,10 @@
     hle->callable = o;
     hle->directory = d;
     hle->d_is_fnmatch = d_is_fnmatch;
-    hle->regex = regex;
+    hle->d_regex = d_regex;
+    hle->location = l;
+    hle->l_is_fnmatch = l_is_fnmatch;
+    hle->l_regex = l_regex;
     hle->silent = s;
     hle->parent = parent;
 
@@ -61,9 +65,10 @@
  *  If hle is NULL, a new list is created.
  */
 
-hl_entry *hlist_append(apr_pool_t *p, hl_entry *hle, const char * h,
-                       PyObject *o, const char *d, int d_is_fnmatch,
-                       ap_regex_t *regex, const int s, hl_entry *parent)
+hl_entry *hlist_append(apr_pool_t *p, hl_entry *hle, const char * h, PyObject *o,
+                       const char *d, int d_is_fnmatch, ap_regex_t *d_regex,
+                       const char *l, int l_is_fnmatch, ap_regex_t *l_regex,
+                       const int s, hl_entry *parent)
 {
     hl_entry *nhle;
 
@@ -77,7 +82,10 @@
     nhle->callable = o;
     nhle->directory = d;
     nhle->d_is_fnmatch = d_is_fnmatch;
-    nhle->regex = regex;
+    nhle->d_regex = d_regex;
+    nhle->location = l;
+    nhle->l_is_fnmatch = l_is_fnmatch;
+    nhle->l_regex = l_regex;
     nhle->silent = s;
     nhle->parent = parent;
 
@@ -102,7 +110,10 @@
     head->callable = hle->callable;
     head->directory = hle->directory;
     head->d_is_fnmatch = hle->d_is_fnmatch;
-    head->regex = hle->regex;
+    head->d_regex = hle->d_regex;
+    head->location = hle->location;
+    head->l_is_fnmatch = hle->l_is_fnmatch;
+    head->l_regex = hle->l_regex;
     head->silent = hle->silent;
     head->parent = hle->parent;
 
@@ -115,7 +126,10 @@
         nhle->callable = hle->callable;
         nhle->directory = hle->directory;
         nhle->d_is_fnmatch = hle->d_is_fnmatch;
-        nhle->regex = hle->regex;
+        nhle->d_regex = hle->d_regex;
+        nhle->location = hle->location;
+        nhle->l_is_fnmatch = hle->l_is_fnmatch;
+        nhle->l_regex = hle->l_regex;
         nhle->silent = hle->silent;
         nhle->parent = hle->parent;
         hle = hle->next;
@@ -146,7 +160,10 @@
         hle1->callable = hle2->callable;
         hle1->directory = hle2->directory;
         hle1->d_is_fnmatch = hle2->d_is_fnmatch;
-        hle1->regex = hle2->regex;
+        hle1->d_regex = hle2->d_regex;
+        hle1->location = hle2->location;
+        hle1->l_is_fnmatch = hle2->l_is_fnmatch;
+        hle1->l_regex = hle2->l_regex;
         hle1->silent = hle2->silent;
         hle1->parent = hle2->parent;
         hle2 = hle2->next;

Modified: httpd/mod_python/trunk/src/hlistobject.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/hlistobject.c?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/hlistobject.c (original)
+++ httpd/mod_python/trunk/src/hlistobject.c Mon Oct 23 20:41:54 2006
@@ -53,6 +53,11 @@
 
 static PyObject *hlist_next(hlistobject *self, PyObject *args)
 {
+    if (! self->head) {
+        Py_INCREF(Py_None);
+        return Py_None;
+    }
+
     self->head = self->head->next;
 
     Py_INCREF(Py_None);
@@ -68,6 +73,7 @@
 
 static struct memberlist hlist_memberlist[] = {
     {"directory",          T_STRING,    OFF(directory),            RO},
+    {"location",           T_STRING,    OFF(location),             RO},
     {"silent",             T_INT,       OFF(silent),               RO},
     {NULL}  /* Sentinel */
 };
@@ -137,7 +143,14 @@
 static PyObject *hlist_repr(hlistobject *self)
 {
     PyObject *t;
-    PyObject *s = PyString_FromString("{");
+    PyObject *s;
+
+    if (! self->head) {
+        s = PyString_FromString("None");
+        return s;
+    }
+
+    s = PyString_FromString("{");
     if (self->head->handler) {
         PyString_ConcatAndDel(&s, PyString_FromString("'handler':"));
         t = PyString_FromString(self->head->handler);
@@ -150,6 +163,12 @@
     if (self->head->directory) {
         PyString_ConcatAndDel(&s, PyString_FromString(",'directory':"));
         t = PyString_FromString(self->head->directory);
+        PyString_ConcatAndDel(&s, PyObject_Repr(t));
+        Py_XDECREF(t);
+    }
+    if (self->head->location) {
+        PyString_ConcatAndDel(&s, PyString_FromString(",'location':"));
+        t = PyString_FromString(self->head->location);
         PyString_ConcatAndDel(&s, PyObject_Repr(t));
         Py_XDECREF(t);
     }

Modified: httpd/mod_python/trunk/src/include/hlist.h
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/hlist.h?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/include/hlist.h (original)
+++ httpd/mod_python/trunk/src/include/hlist.h Mon Oct 23 20:41:54 2006
@@ -37,7 +37,10 @@
         PyObject *callable;
         const char *directory;
         int d_is_fnmatch;
-        ap_regex_t *regex;
+        ap_regex_t *d_regex;
+        const char *location;
+        int l_is_fnmatch;
+        ap_regex_t *l_regex;
         int silent;  /* 1 for PythonHandlerModule, where
                         if a handler is not found in a module,
                         no error should be reported */
@@ -46,11 +49,13 @@
     } hl_entry;
     
     hl_entry *hlist_new(apr_pool_t *p, const char *h, PyObject* o,
-                        const char *d, int d_is_fnmatch, ap_regex_t *regex,
+                        const char *d, int d_is_fnmatch, ap_regex_t *d_regex,
+                        const char *l, int l_is_fnmatch, ap_regex_t *l_regex,
                         const int s, hl_entry* parent);
-    hl_entry *hlist_append(apr_pool_t *p, hl_entry *hle, const char * h,
-                           PyObject* o, const char *d, int d_is_fnmatch,
-                           ap_regex_t *regex, const int s, hl_entry* parent);
+    hl_entry *hlist_append(apr_pool_t *p, hl_entry *hle, const char * h, PyObject* o,
+                           const char *d, int d_is_fnmatch, ap_regex_t *d_regex,
+                           const char *l, int l_is_fnmatch, ap_regex_t *l_regex,
+                           const int s, hl_entry* parent);
 
     hl_entry *hlist_copy(apr_pool_t *p, const hl_entry *hle);
     void hlist_extend(apr_pool_t *p, hl_entry *hle1, const hl_entry *hle2);

Modified: httpd/mod_python/trunk/src/include/mod_python.h
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/mod_python.h?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/include/mod_python.h (original)
+++ httpd/mod_python/trunk/src/include/mod_python.h Mon Oct 23 20:41:54 2006
@@ -200,7 +200,10 @@
     PyObject *callable;
     char *directory;
     int d_is_fnmatch;
-    ap_regex_t *regex;
+    ap_regex_t *d_regex;
+    char *location;
+    int l_is_fnmatch;
+    ap_regex_t *l_regex;
     hl_entry *parent;
 } py_handler;
 

Modified: httpd/mod_python/trunk/src/include/mod_python.h.in
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/include/mod_python.h.in?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/include/mod_python.h.in (original)
+++ httpd/mod_python/trunk/src/include/mod_python.h.in Mon Oct 23 20:41:54 2006
@@ -200,7 +200,10 @@
     PyObject *callable;
     char *directory;
     int d_is_fnmatch;
-    ap_regex_t *regex;
+    ap_regex_t *d_regex;
+    char *location;
+    int l_is_fnmatch;
+    ap_regex_t *l_regex;
     hl_entry *parent;
 } py_handler;
 

Modified: httpd/mod_python/trunk/src/mod_python.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/mod_python.c?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/mod_python.c (original)
+++ httpd/mod_python/trunk/src/mod_python.c Mon Oct 23 20:41:54 2006
@@ -1012,7 +1012,8 @@
 #endif
 
 static void determine_context(apr_pool_t *p, const cmd_parms* cmd,
-                             char **dp, int *gx, ap_regex_t **rx)
+                              char **d, int *d_gx, ap_regex_t **d_rx,
+                              char **l, int *l_gx, ap_regex_t **l_rx)
 {
     const ap_directive_t *context = 0;
     const ap_directive_t *directive = 0;
@@ -1020,7 +1021,11 @@
 
     char *directory = 0;
     int d_is_fnmatch = 0;
-    ap_regex_t *regex = 0;
+    ap_regex_t *d_regex = 0;
+
+    char *location = 0;
+    int l_is_fnmatch = 0;
+    ap_regex_t *l_regex = 0;
 
     directive = cmd->directive;
 
@@ -1041,7 +1046,7 @@
 
         if (!strcmp(directory, "~")) {
             directory = ap_getword_conf(p, &arg);
-            regex = ap_pregcomp(p, cmd->path, AP_REG_EXTENDED|USE_ICASE);
+            d_regex = ap_pregcomp(p, cmd->path, AP_REG_EXTENDED|USE_ICASE);
         } else if (ap_is_matchexp(directory)) {
             d_is_fnmatch = 1;
         }
@@ -1051,9 +1056,28 @@
         arg = apr_pstrndup(p, arg, endp - arg);
 
         directory = ap_getword_conf(p, &arg);
-        regex = ap_pregcomp(p, directory, AP_REG_EXTENDED|USE_ICASE);
-    }
-    else if (cmd->config_file != NULL) {
+        d_regex = ap_pregcomp(p, directory, AP_REG_EXTENDED|USE_ICASE);
+    } else if ((context = find_parent(directive, "<Location"))) {
+        arg = context->args;
+        endp = ap_strrchr_c(arg, '>');
+        arg = apr_pstrndup(p, arg, endp - arg);
+
+        location = ap_getword_conf(p, &arg);
+
+        if (!strcmp(location, "~")) {
+            location = ap_getword_conf(p, &arg);
+            l_regex = ap_pregcomp(p, cmd->path, AP_REG_EXTENDED|USE_ICASE);
+        } else if (ap_is_matchexp(location)) {
+            l_is_fnmatch = 1;
+        }
+    } else if ((context = find_parent(directive, "<LocationMatch"))) {
+        arg = context->args;
+        endp = ap_strrchr_c(arg, '>');
+        arg = apr_pstrndup(p, arg, endp - arg);
+
+        location = ap_getword_conf(p, &arg);
+        l_regex = ap_pregcomp(p, location, AP_REG_EXTENDED|USE_ICASE);
+    } else if (cmd->config_file != NULL) {
         /* cmd->config_file is NULL when in main Apache
          * configuration file as the file is completely
          * read in before the directive is processed as
@@ -1068,7 +1092,7 @@
      * this point if no pattern matching to be done at
      * a later time. */
 
-    if (!d_is_fnmatch && !regex) {
+    if (directory && !d_is_fnmatch && !d_regex) {
 
         char *newpath = 0;
         apr_status_t rv;
@@ -1088,9 +1112,13 @@
         }
     }
 
-    *dp = directory;
-    *gx = d_is_fnmatch;
-    *rx = regex;
+    *d = directory;
+    *d_gx = d_is_fnmatch;
+    *d_rx = d_regex;
+
+    *l = location;
+    *l_gx = l_is_fnmatch;
+    *l_rx = l_regex;
 }
 
 static void python_directive_hl_add(apr_pool_t *p, apr_hash_t *hlists, 
@@ -1102,9 +1130,14 @@
 
     char *directory = 0;
     int d_is_fnmatch = 0;
-    ap_regex_t *regex = 0;
+    ap_regex_t *d_regex = 0;
 
-    determine_context(p, cmd, &directory, &d_is_fnmatch, &regex);
+    char *location = 0;
+    int l_is_fnmatch = 0;
+    ap_regex_t *l_regex = 0;
+
+    determine_context(p, cmd, &directory, &d_is_fnmatch, &d_regex,
+                      &location, &l_is_fnmatch, &l_regex);
 
     head = (hl_entry *)apr_hash_get(hlists, phase, APR_HASH_KEY_STRING);
 
@@ -1113,11 +1146,13 @@
 
     while (*(h = ap_getword_white(p, &handler)) != '\0') {
         if (!head) {
-            head = hlist_new(p, h, 0, directory, d_is_fnmatch, regex, silent, 0);
+            head = hlist_new(p, h, 0, directory, d_is_fnmatch, d_regex,
+                             location, l_is_fnmatch, l_regex, silent, 0);
             apr_hash_set(hlists, phase, APR_HASH_KEY_STRING, head);
         }
         else {
-            hlist_append(p, head, h, 0, directory, d_is_fnmatch, regex, silent, 0);
+            hlist_append(p, head, h, 0, directory, d_is_fnmatch, d_regex,
+                         location, l_is_fnmatch, l_regex, silent, 0);
         }
     }
 }
@@ -1283,20 +1318,22 @@
  */
 
 static const char *resolve_directory(request_rec *req, const char *directory,
-                                     int d_is_fnmatch, ap_regex_t *regex)
+                                     int d_is_fnmatch, ap_regex_t *d_regex)
 {
     char *prefix;
     int len, dirs, i;
 
-    if (!req || !req->filename || (!d_is_fnmatch && !regex))
+    if (!req || !req->filename || (!d_is_fnmatch && !d_regex))
         return directory;
 
     dirs = ap_count_dirs(req->filename) + 1;
     len = strlen(req->filename);
-    prefix = (char*)apr_palloc(req->pool, len+1);
+    prefix = (char*)apr_palloc(req->pool, len+2);
 
     for (i=0; i<=dirs; i++) {
         ap_make_dirstr_prefix(prefix, req->filename, i);
+
+        /* Match with trailing slash first. */
 #ifdef WIN32
         if (d_is_fnmatch && apr_fnmatch(directory, prefix,
             APR_FNM_PATHNAME|APR_FNM_CASE_BLIND) == 0) {
@@ -1306,12 +1343,14 @@
 #endif
             return prefix;
         }
-        else if (regex && ap_regexec(regex, prefix, 0, NULL, 0) == 0) {
+        else if (d_regex && ap_regexec(d_regex, prefix, 0, NULL, 0) == 0) {
             return prefix;
         }
 
         if (strcmp(prefix, "/") != 0) {
             prefix[strlen(prefix)-1] = '\0';
+
+            /* Match without trailing slash. */
 #ifdef WIN32
             if (d_is_fnmatch && apr_fnmatch(directory, prefix,
                 APR_FNM_PATHNAME|APR_FNM_CASE_BLIND) == 0) {
@@ -1322,7 +1361,7 @@
                 prefix[strlen(prefix)] = '/';
                 return prefix;
             }
-            else if (regex && ap_regexec(regex, prefix, 0, NULL, 0) == 0) {
+            else if (d_regex && ap_regexec(d_regex, prefix, 0, NULL, 0) == 0) {
                 prefix[strlen(prefix)] = '/';
                 return prefix;
             }
@@ -1333,6 +1372,60 @@
 }
 
 /**
+ ** resolve_location
+ **
+ *      resolve any location match returning the matched location
+ */
+
+static const char *resolve_location(request_rec *req, const char *location,
+                                     int l_is_fnmatch, ap_regex_t *l_regex)
+{
+    char *prefix;
+    int len, dirs, i;
+
+    if (!req || !req->uri || (!l_is_fnmatch && !l_regex))
+        return location;
+
+    dirs = ap_count_dirs(req->uri) + 1;
+    len = strlen(req->uri);
+    prefix = (char*)apr_palloc(req->pool, len+2);
+
+    for (i=0; i<=dirs; i++) {
+        int match = 0;
+        ap_make_dirstr_prefix(prefix, req->uri, i);
+
+        /* Match with trailing slash first. */
+        if (l_is_fnmatch && apr_fnmatch(location, prefix,
+            APR_FNM_PATHNAME) == 0) {
+            match = 1;
+        }
+        else if (l_regex && ap_regexec(l_regex, prefix, 0, NULL, 0) == 0) {
+            match = 1;
+        }
+
+        if (strcmp(prefix, "/") != 0) {
+            prefix[strlen(prefix)-1] = '\0';
+
+            /* Match without trailing slash. */
+            if (l_is_fnmatch && apr_fnmatch(location, prefix,
+                APR_FNM_PATHNAME) == 0) {
+                return prefix;
+            }
+            else if (l_regex && ap_regexec(l_regex, prefix, 0, NULL, 0) == 0) {
+                return prefix;
+            }
+
+            if (match) {
+                prefix[strlen(prefix)] = '/';
+                return prefix;
+            }
+        }
+    }
+
+    return location;
+}
+
+/**
  ** select_interp_name
  **
  *      (internal)
@@ -1498,11 +1591,17 @@
     /* resolve wildcard or regex directory patterns */
     hle = hlohle;
     while (hle) {
-        if (hle->d_is_fnmatch || hle->regex) {
+        if (hle->d_is_fnmatch || hle->d_regex) {
             hle->directory = resolve_directory(req, hle->directory,
-                                               hle->d_is_fnmatch, hle->regex);
+                                               hle->d_is_fnmatch, hle->d_regex);
             hle->d_is_fnmatch = 0;
-            hle->regex = NULL;
+            hle->d_regex = NULL;
+        }
+        if (hle->l_is_fnmatch || hle->l_regex) {
+            hle->location = resolve_location(req, hle->location,
+                                               hle->l_is_fnmatch, hle->l_regex);
+            hle->l_is_fnmatch = 0;
+            hle->l_regex = NULL;
         }
 
         hle = hle->next;
@@ -2505,7 +2604,11 @@
 
     char *directory = 0;
     int d_is_fnmatch = 0;
-    ap_regex_t *regex = 0;
+    ap_regex_t *d_regex = 0;
+
+    char *location = 0;
+    int l_is_fnmatch = 0;
+    ap_regex_t *l_regex = 0;
 
     if (!name)
         name = apr_pstrdup(cmd->pool, handler);
@@ -2517,13 +2620,19 @@
  
     conf = (py_config *) mconfig;
 
-    determine_context(cmd->pool, cmd, &directory, &d_is_fnmatch, &regex);
+    determine_context(cmd->pool, cmd, &directory, &d_is_fnmatch, &d_regex,
+                      &location, &l_is_fnmatch, &l_regex);
 
     fh = (py_handler *) apr_pcalloc(cmd->pool, sizeof(py_handler));
     fh->handler = (char *)handler;
+
     fh->directory = directory;
     fh->d_is_fnmatch = d_is_fnmatch;
-    fh->regex = regex;
+    fh->d_regex = d_regex;
+
+    fh->location = location;
+    fh->l_is_fnmatch = l_is_fnmatch;
+    fh->l_regex = l_regex;
 
     apr_hash_set(conf->in_filters, frec->name, APR_HASH_KEY_STRING, fh);
 
@@ -2538,8 +2647,12 @@
 
     char *directory = 0;
     int d_is_fnmatch = 0;
-    ap_regex_t *regex = 0;
- 
+    ap_regex_t *d_regex = 0;
+
+    char *location = 0;
+    int l_is_fnmatch = 0;
+    ap_regex_t *l_regex = 0;
+
     if (!name)
         name = apr_pstrdup(cmd->pool, handler);
 
@@ -2548,15 +2661,21 @@
        would have to make sure not to duplicate this */
     frec = ap_register_output_filter(name, python_output_filter, NULL, AP_FTYPE_RESOURCE);
 
-    determine_context(cmd->pool, cmd, &directory, &d_is_fnmatch, &regex);
+    determine_context(cmd->pool, cmd, &directory, &d_is_fnmatch, &d_regex,
+                      &location, &l_is_fnmatch, &l_regex);
 
     conf = (py_config *) mconfig;
     
     fh = (py_handler *) apr_pcalloc(cmd->pool, sizeof(py_handler));
     fh->handler = (char *)handler;
+
     fh->directory = directory;
     fh->d_is_fnmatch = d_is_fnmatch;
-    fh->regex = regex;
+    fh->d_regex = d_regex;
+
+    fh->location = location;
+    fh->l_is_fnmatch = l_is_fnmatch;
+    fh->l_regex = l_regex;
 
     apr_hash_set(conf->out_filters, frec->name, APR_HASH_KEY_STRING, fh);
 

Modified: httpd/mod_python/trunk/src/requestobject.c
URL: http://svn.apache.org/viewvc/httpd/mod_python/trunk/src/requestobject.c?view=diff&rev=467228&r1=467227&r2=467228
==============================================================================
--- httpd/mod_python/trunk/src/requestobject.c (original)
+++ httpd/mod_python/trunk/src/requestobject.c Mon Oct 23 20:41:54 2006
@@ -214,7 +214,7 @@
 
         /* then just append to hlist */
         hlist_append(self->request_rec->pool, self->hlo->head,
-                     handler, callable, dir, 0, NULL, NOTSILENT,
+                     handler, callable, dir, 0, NULL, NULL, 0, NULL, NOTSILENT,
                      self->hlo->head);
     }
     else {
@@ -232,12 +232,12 @@
 
         if (! hle) {
             hle = hlist_new(self->request_rec->pool, handler, callable, dir,
-                            0, NULL, NOTSILENT, self->hlo->head);
+                            0, NULL, NULL, 0, NULL, NOTSILENT, self->hlo->head);
             apr_hash_set(req_config->dynhls, phase, APR_HASH_KEY_STRING, hle);
         }
         else {
             hlist_append(self->request_rec->pool, hle, handler, callable, dir,
-                         0, NULL, NOTSILENT, self->hlo->head);
+                         0, NULL, NULL, 0, NULL, NOTSILENT, self->hlo->head);
         }
     }