On Sat, 17 Feb 2001, Martin Kraemer wrote:
> On Wed, Feb 14, 2001 at 07:56:05AM -0800, Jeffrey W. Baker wrote:
> > > It looks good, although in the line
> > > 29 uptr->scheme = DEFAULT_URI_SCHEME;
> > > you assign to a "const" structure, and some compilers dislike that.
> >
> > Ah, you are right I meant to remove that but my versions got out of sync.
>
> Does that mean: your patch, minus exactly this one line?
> But that breaks the check for the default port further down.
> (uptr->port == ap_default_port_for_scheme(uptr->scheme)))
> although if no scheme is set, the port and per_str are probably
> unset as well?!
>
> I am unsure, could you please re-submit the cleaned patch?
Attached. I replaced the loop initializer with memset, and avoided
modifying the const argument by holding the scheme in a local
variable. Passes local tests and mod_test_util_uri.c.
-jwb
Index: util_uri.c
===================================================================
RCS file: /home/cvspublic/apache-1.3/src/main/util_uri.c,v
retrieving revision 1.30
diff -u -r1.30 util_uri.c
--- util_uri.c 2001/02/17 14:07:04 1.30
+++ util_uri.c 2001/02/17 18:47:49
@@ -170,61 +170,118 @@
/* Unparse a uri_components structure to an URI string.
* Optionally suppress the password for security reasons.
+ * See also RFC 2396.
*/
API_EXPORT(char *) ap_unparse_uri_components(pool *p,
const uri_components * uptr,
unsigned flags)
{
- char *ret = "";
-
- /* If suppressing the site part, omit both user name & scheme://hostname */
+ char *parts[16]; /* 16 distinct parts of a URI */
+ char *scheme = NULL; /* to hold the scheme without modifying const args */
+ int j = 0; /* an index into parts */
+
+ memset(parts, 0, sizeof(parts));
+
+ /* If suppressing the site part, omit all of scheme://user:pass@host:port */
if (!(flags & UNP_OMITSITEPART)) {
- /* Construct a "user:password@" string, honoring the passed UNP_ flags: */
- if (uptr->user || uptr->password)
- ret = ap_pstrcat(p,
- (uptr->user
- && !(flags & UNP_OMITUSER)) ? uptr->user : "",
- (uptr->password
- && !(flags & UNP_OMITPASSWORD)) ? ":" : "",
- (uptr->password && !(flags & UNP_OMITPASSWORD))
- ? ((flags & UNP_REVEALPASSWORD) ? uptr->
- password : "XXXXXXXX")
- : "", "@", NULL);
-
- /* Construct scheme://site string */
- if (uptr->hostname) {
- int is_default_port;
-
- is_default_port =
- (uptr->port_str == NULL ||
- uptr->port == 0 ||
- uptr->port == ap_default_port_for_scheme(uptr->scheme));
-
- ret = ap_pstrcat(p,
- uptr->scheme, "://", ret,
- uptr->hostname ? uptr->hostname : "",
- is_default_port ? "" : ":",
- is_default_port ? "" : uptr->port_str, NULL);
+ /* if the user passes in a scheme, we'll assume an absoluteURI */
+ if (uptr->scheme) {
+ scheme = uptr->scheme;
+
+ parts[j++] = uptr->scheme;
+ parts[j++] = ":";
+ }
+
+ /* handle the hier_part */
+ if (uptr->user || uptr->password || uptr->hostname) {
+
+ /* this stuff requires absoluteURI, so we have to add the scheme */
+ if (!uptr->scheme) {
+ scheme = DEFAULT_URI_SCHEME;
+
+ parts[j++] = DEFAULT_URI_SCHEME;
+ parts[j++] = ":";
+ }
+
+ parts[j++] = "//";
+
+ /* userinfo requires hostport */
+ if (uptr->hostname && (uptr->user || uptr->password)) {
+ if (uptr->user && !(flags & UNP_OMITUSER))
+ parts[j++] = uptr->user;
+
+ if (uptr->password && !(flags & UNP_OMITPASSWORD)) {
+ parts[j++] = ":";
+
+ if (flags & UNP_REVEALPASSWORD)
+ parts[j++] = uptr->password;
+ else
+ parts[j++] = "XXXXXXXX";
+ }
+
+ parts[j++] = "@";
+ }
+
+ /* If we get here, there must be a hostname. */
+ parts[j++] = uptr->hostname;
+
+ /* Emit the port. A small beautification
+ * prevents http://host:80/ and similar visual blight.
+ */
+ if (uptr->port_str &&
+ !(uptr->port &&
+ scheme &&
+ uptr->port == ap_default_port_for_scheme(scheme))) {
+
+ parts[j++] = ":";
+ parts[j++] = uptr->port_str;
+ }
}
}
-
- /* Should we suppress all path info? */
+
if (!(flags & UNP_OMITPATHINFO)) {
- /* Append path, query and fragment strings: */
- ret = ap_pstrcat(p,
- ret,
- uptr->path ? uptr->path : "",
- (uptr->query && !(flags & UNP_OMITQUERY)) ? "?" : "",
- (uptr->query
- && !(flags & UNP_OMITQUERY)) ? uptr->query : "",
- (uptr->fragment
- && !(flags & UNP_OMITQUERY)) ? "#" : NULL,
- (uptr->fragment
- && !(flags & UNP_OMITQUERY)) ? uptr->
- fragment : NULL, NULL);
+
+
+ /* We must ensure we don't put out a hier_part and a rel_path */
+ if (j && uptr->path && *uptr->path != '/')
+ parts[j++] = "/";
+
+ parts[j++] = uptr->path;
+
+ if (!(flags & UNP_OMITQUERY)) {
+ if (uptr->query) {
+ parts[j++] = "?";
+ parts[j++] = uptr->query;
+ }
+
+ if (uptr->fragment) {
+ parts[j++] = "#";
+ parts[j++] = uptr->fragment;
+ }
+ }
}
- return ret;
+
+ /* Ugly, but correct and probably faster than ap_vsnprintf. */
+ return ap_pstrcat(p,
+ parts[0],
+ parts[1],
+ parts[2],
+ parts[3],
+ parts[4],
+ parts[5],
+ parts[6],
+ parts[7],
+ parts[8],
+ parts[9],
+ parts[10],
+ parts[11],
+ parts[12],
+ parts[13],
+ parts[14],
+ parts[15],
+ NULL
+ );
}
/* The regex version of parse_uri_components has the advantage that it is
Index: util_uri.h
===================================================================
RCS file: /home/cvspublic/apache-1.3/src/include/util_uri.h,v
retrieving revision 1.15
diff -u -r1.15 util_uri.h
--- util_uri.h 2001/01/15 17:04:41 1.15
+++ util_uri.h 2001/02/17 18:48:13
@@ -80,6 +80,8 @@
#define DEFAULT_SNEWS_PORT 563
#define DEFAULT_PROSPERO_PORT 1525 /* WARNING: conflict w/Oracle */
+#define DEFAULT_URI_SCHEME "http"
+
/* Flags passed to unparse_uri_components(): */
#define UNP_OMITSITEPART (1U<<0) /* suppress "scheme://user@site:port" */
#define UNP_OMITUSER (1U<<1) /* Just omit user */