On Thu, 30 Oct 2003, Nick Kew wrote:
> I've just hacked a couple of patches that fill gaps in Apache's
> URI manipulation, sufficient to construct HTTP requests for external
> resources. May I submit these for inclusion?
The only response to this was "where is it?", so here goes.
See attached.
--
Nick Kew
--- server/protocol.c 2003-09-10 13:13:51.000000000 +0100
+++ server/protocol.c.new 2003-11-01 14:57:20.000000000 +0000
@@ -555,8 +555,10 @@
}
r->args = r->parsed_uri.query;
- r->uri = r->parsed_uri.path ? r->parsed_uri.path
- : apr_pstrdup(r->pool, "/");
+ if ( ! r->parsed_uri.path ) {
+ r->parsed_uri.path = apr_pstrdup(r->pool, "/");
+ }
+ r->uri = r->parsed_uri.path ;
#if defined(OS2) || defined(WIN32)
/* Handle path translations for OS/2 and plug security hole.
@@ -578,6 +580,21 @@
r->uri = apr_pstrdup(r->pool, uri);
}
}
+/* Fill in fields of parsed_uri even where not required by httpd core.
+ Assumes ap_parse_uri has already been run
+
+ Would best be merged into ap_parse_uri if that doesn't risk
+ breaking something obscure
+*/
+AP_CORE_DECLARE(void) ap_fill_parsed_uri(request_rec *r)
+{
+ r->parsed_uri.scheme = r->parsed_uri.scheme ? r->parsed_uri.scheme :
apr_pstrdup(r->pool, "http") ;
+ r->parsed_uri.user = r->parsed_uri.user ? r->parsed_uri.user : r->user ;
+ r->parsed_uri.hostname = r->parsed_uri.hostname ? r->parsed_uri.hostname :
(char*)r->hostname ;
+ r->parsed_uri.port = r->parsed_uri.port ? r->parsed_uri.port :
r->connection->local_addr->port ;
+ r->parsed_uri.port_str = r->parsed_uri.port_str ? r->parsed_uri.port_str :
apr_psprintf(r->pool, "%d", r->parsed_uri.port) ;
+/* r->parsed_uri.path = r->parsed_uri.path ? r->parsed_uri.path : r->uri ?
r->uri : apr_pstrdup(r->pool, "/") ;*/
+}
static int read_request_line(request_rec *r, apr_bucket_brigade *bb)
{
--- include/http_protocol.h 2003-02-03 17:31:29.000000000 +0000
+++ include/http_protocol.h.new 2003-11-01 14:53:41.000000000 +0000
@@ -552,6 +552,15 @@
AP_CORE_DECLARE(void) ap_parse_uri(request_rec *r, const char *uri);
/**
+ * fill_parsed_uri: fill in fields available in request that parse_uri
+ * may have left null. Saves making too many special cases when
+ * using the parsed_uri.
+ * @param r The current request
+ * @deffunc void ap_fill_parsed_uri(request_rec *r)
+ */
+AP_CORE_DECLARE(void) ap_fill_parsed_uri(request_rec *r) ;
+
+/**
* Get the next line of input for the request
* @param s The buffer into which to read the line
* @param n The size of the buffer
--- 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