[ first submitted in November; folks @apachecon suggested resubmitting ]

-- 
Nick Kew
--- srclib/apr-util/uri/apr_uri.c       2003-03-03 18:31:58.000000000 +0000
+++ srclib/apr-util/uri/apr_uri.c.new   2003-11-01 14:58:31.000000000 +0000
@@ -448,3 +448,94 @@
     }
     return APR_EGENERAL;
 }
+/* Resolve relative to a base.  This means host/etc, and (crucially) path */
+APU_DECLARE(int) apr_uri_resolve_relative(apr_pool_t* pool,
+                                         const apr_uri_t* base,
+                                         apr_uri_t* uptr)
+{
+  if ( uptr == NULL
+       || base == NULL
+       || ! base->is_initialized
+       || ! uptr->is_initialized ) {
+       return APR_EGENERAL;
+  }
+/* The interesting bit is the path.  */
+  if ( uptr->path == NULL ) {
+    if ( uptr->hostname == NULL ) {
+       /* is this compatible with is_initialised?  Harmless in any case */
+       uptr->path = base->path ? base->path : apr_pstrdup(pool, "/") ;
+    }
+    else {
+       /* deal with the idiosyncracy of APR allowing path==NULL
+       ** without risk of breaking back-compatibility
+       */
+       uptr->path = apr_pstrdup(pool, "/") ;
+    }
+  }
+  else if ( uptr->path[0] != '/' ) {
+    size_t baselen ;
+    const char* basepath = base->path ? base->path :"/" ;
+    const char* path = uptr->path ;
+    const char* base_end = strrchr(basepath, '/') ;
+
+    /* if base is nonsensical, bail out */
+    if ( basepath[0] != '/' ) {
+       return APR_EGENERAL;
+    }
+    /* munch "up" components at the start, and chop them from base path */
+    while ( !strncmp(path, "../", 3) ) {
+      while ( base_end > basepath ) {
+       if ( *--base_end == '/' ) {
+         break ;
+       }
+      }
+      path += 3 ;
+    }
+    /* munch "here" components at the start */
+    while ( !strncmp(path, "./", 2) ) {
+      path += 2 ;
+    }
+    baselen = base_end-basepath+1 ;
+    uptr->path = apr_palloc(pool, baselen + strlen(path) + 1 ) ;
+    memcpy(uptr->path, basepath, baselen) ;
+    strcpy(uptr->path+baselen, path) ;
+  }
+
+/* The trivial bits are everything-but-path */
+  if ( uptr->scheme == NULL ) {
+       uptr->scheme = base->scheme ;
+  }
+  if ( uptr->hostinfo == NULL ) {
+       uptr->hostinfo = base->hostinfo ;
+  }
+  if ( uptr->user == NULL ) {
+       uptr->user = base->user ;
+  }
+  if ( uptr->password == NULL ) {
+       uptr->password = base->password ;
+  }
+  if ( uptr->hostname == NULL ) {
+       uptr->hostname = base->hostname ;
+  }
+  if ( uptr->port_str == NULL ) {
+       uptr->port_str = base->port_str ;
+  }
+  if ( uptr->hostent == NULL ) {
+       uptr->hostent = base->hostent ;
+  }
+  if ( ! uptr->port ) {
+       uptr->port = base->port ;
+  }
+  return APR_SUCCESS ;
+}
+APU_DECLARE(int) apr_uri_parse_relative(apr_pool_t* p,
+                                       const apr_uri_t* base,
+                                       const char* uri,
+                                       apr_uri_t* uptr)
+{
+  int ret = apr_uri_parse(p, uri, uptr) ;
+  if ( ret != APR_SUCCESS ) {
+       return ret ;
+  }
+  return apr_uri_resolve_relative(p, base, uptr) ;
+}
--- srclib/apr-util/include/apr_uri.h   2003-03-03 23:41:11.000000000 +0000
+++ srclib/apr-util/include/apr_uri.h.new       2003-11-01 15:00:12.000000000
+0000
@@ -205,6 +205,33 @@
                                apr_uri_t *uptr);
 
 /**
+ * Resolve an already-initialised but possibly-relative URL
+ * against a given base URL.
+ * @param p The pool to allocate out of
+ * @param base The base to resolve against
+ * @param uptr The apr_uri_t to resolve
+ * @return An HTTP status code
+ */
+APU_DECLARE(int) apr_uri_resolve_relative(apr_pool_t *p,
+                                         const apr_uri_t *base,
+                                         apr_uri_t *uptr);
+
+/**
+ * Parse a given URI, fill in all supplied fields of a apr_uri_t structure.
+ * If the given URI is relative, then resolve it using a supplied base
+ * @param p The pool to allocate out of
+ * @param base The base to resolve against
+ * @param uri The uri to parse
+ * @param uptr The apr_uri_t to fill out
+ * @return An HTTP status code
+ */
+APU_DECLARE(int) apr_uri_parse_relative(apr_pool_t *p,
+                                       const apr_uri_t *base,
+                                       const char* uri,
+                                       apr_uri_t* uptr);
+
+
+/**
  * Special case for CONNECT parsing: it comes with the hostinfo part only
  * @param p The pool to allocate out of
  * @param hostinfo The hostinfo string to parse

Reply via email to