Fix resolve_rel_url()
This reworks commit 0edaf3361d
, which
broke resolving relative url, where the relative URL is shorter than the
absolute URL:
"http://127.0.0.1:6544/getDeviceDesc" + "CDS_Event"
Wrong: "http://127.0.0.1:6544/CDS_EventDesc"
Right: "http://127.0.0.1:6544/CDS_Event"
While reviewing that commit, improve code by:
1. Move the simple cases to the beginning of the function.
2. Keep track of the remaining target buffer size.
3. Fix URI concatenation with queries.
4. Fix URI concatenation with fragments.
Signed-off-by: Marcelo Roberto Jimenez <mroberto@users.sourceforge.net>
This commit is contained in:
parent
848d66e69d
commit
0508fb0d6e
@ -580,115 +580,113 @@ char *resolve_rel_url(char *base_url, char *rel_url)
|
|||||||
{
|
{
|
||||||
uri_type base;
|
uri_type base;
|
||||||
uri_type rel;
|
uri_type rel;
|
||||||
|
int rv;
|
||||||
|
|
||||||
size_t i = (size_t)0;
|
if (!base_url) {
|
||||||
char *finger = NULL;
|
if (!rel_url)
|
||||||
|
|
||||||
char *last_slash = NULL;
|
|
||||||
|
|
||||||
char *out = NULL;
|
|
||||||
|
|
||||||
if( base_url && rel_url ) {
|
|
||||||
out =
|
|
||||||
( char * )malloc( strlen( base_url ) + strlen( rel_url ) + (size_t)2 );
|
|
||||||
} else {
|
|
||||||
if( rel_url )
|
|
||||||
return strdup( rel_url );
|
|
||||||
else
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
return strdup(rel_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
if( out == NULL ) {
|
size_t len_rel = strlen(rel_url);
|
||||||
|
if (parse_uri(rel_url, len_rel, &rel) != HTTP_SUCCESS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
if (rel.type == (enum uriType)ABSOLUTE)
|
||||||
|
return strdup(rel_url);
|
||||||
|
|
||||||
|
size_t len_base = strlen(base_url);
|
||||||
|
if ((parse_uri(base_url, len_base, &base) != HTTP_SUCCESS)
|
||||||
|
|| (base.type != (enum uriType)ABSOLUTE))
|
||||||
|
return NULL;
|
||||||
|
if (len_rel == (size_t)0)
|
||||||
|
return strdup(base_url);
|
||||||
|
|
||||||
|
size_t len = len_base + len_rel + (size_t)2;
|
||||||
|
char *out = (char *)malloc(len);
|
||||||
|
if (out == NULL)
|
||||||
|
return NULL;
|
||||||
|
memset(out, 0, len);
|
||||||
|
char *out_finger = out;
|
||||||
|
|
||||||
|
/* scheme */
|
||||||
|
rv = snprintf(out_finger, len, "%.*s:", (int)base.scheme.size, base.scheme.buff);
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
|
|
||||||
|
/* authority */
|
||||||
|
if (rel.hostport.text.size > (size_t)0) {
|
||||||
|
rv = snprintf(out_finger, len, "%s", rel_url);
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
if (base.hostport.text.size > (size_t)0) {
|
||||||
|
rv = snprintf(out_finger, len, "//%.*s", (int)base.hostport.text.size, base.hostport.text.buff);
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
}
|
}
|
||||||
memset( out, 0, strlen( base_url ) + strlen( rel_url ) + (size_t)2 );
|
|
||||||
|
|
||||||
if( ( parse_uri( rel_url, strlen( rel_url ), &rel ) ) == HTTP_SUCCESS ) {
|
/* path */
|
||||||
|
char *path = out_finger;
|
||||||
if( rel.type == ( enum uriType) ABSOLUTE ) {
|
if (rel.path_type == (enum pathType)ABS_PATH) {
|
||||||
|
rv = snprintf(out_finger, len, "%s", rel_url);
|
||||||
strncpy( out, rel_url, strlen ( rel_url ) );
|
} else if (base.pathquery.size == (size_t)0) {
|
||||||
} else {
|
rv = snprintf(out_finger, len, "/%s", rel_url);
|
||||||
|
|
||||||
if( ( parse_uri( base_url, strlen( base_url ), &base ) ==
|
|
||||||
HTTP_SUCCESS )
|
|
||||||
&& ( base.type == ( enum uriType ) ABSOLUTE ) ) {
|
|
||||||
|
|
||||||
if( strlen( rel_url ) == (size_t)0 ) {
|
|
||||||
strncpy( out, base_url, strlen ( base_url ) );
|
|
||||||
} else {
|
|
||||||
char *out_finger = out;
|
|
||||||
assert( base.scheme.size + (size_t)1 /* ':' */ <= strlen ( base_url ) );
|
|
||||||
memcpy( out, base.scheme.buff, base.scheme.size );
|
|
||||||
out_finger += base.scheme.size;
|
|
||||||
( *out_finger ) = ':';
|
|
||||||
out_finger++;
|
|
||||||
|
|
||||||
if( rel.hostport.text.size > (size_t)0 ) {
|
|
||||||
snprintf( out_finger, strlen( rel_url ) + (size_t)1,
|
|
||||||
"%s", rel_url );
|
|
||||||
} else {
|
|
||||||
if( base.hostport.text.size > (size_t)0 ) {
|
|
||||||
assert( base.scheme.size + (size_t)1
|
|
||||||
+ base.hostport.text.size + (size_t)2 /* "//" */ <= strlen ( base_url ) );
|
|
||||||
memcpy( out_finger, "//", (size_t)2 );
|
|
||||||
out_finger += 2;
|
|
||||||
memcpy( out_finger, base.hostport.text.buff,
|
|
||||||
base.hostport.text.size );
|
|
||||||
out_finger += base.hostport.text.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( rel.path_type == ( enum pathType ) ABS_PATH ) {
|
|
||||||
strncpy( out_finger, rel_url, strlen ( rel_url ) );
|
|
||||||
|
|
||||||
} else {
|
|
||||||
char temp_path = '/';
|
|
||||||
|
|
||||||
if( base.pathquery.size == (size_t)0 ) {
|
|
||||||
base.pathquery.size = (size_t)1;
|
|
||||||
base.pathquery.buff = &temp_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert( base.scheme.size + (size_t)1 + base.hostport.text.size + (size_t)2
|
|
||||||
+ base.pathquery.size <= strlen ( base_url ) + (size_t)1 /* temp_path */);
|
|
||||||
finger = out_finger;
|
|
||||||
last_slash = finger;
|
|
||||||
i = (size_t)0;
|
|
||||||
while( ( i < base.pathquery.size ) &&
|
|
||||||
( base.pathquery.buff[i] != '?' ) ) {
|
|
||||||
( *finger ) = base.pathquery.buff[i];
|
|
||||||
if( base.pathquery.buff[i] == '/' )
|
|
||||||
last_slash = finger + 1;
|
|
||||||
i++;
|
|
||||||
finger++;
|
|
||||||
|
|
||||||
}
|
|
||||||
strncpy( last_slash, rel_url, strlen ( rel_url ) );
|
|
||||||
if( remove_dots( out_finger,
|
|
||||||
strlen( out_finger ) ) !=
|
|
||||||
UPNP_E_SUCCESS ) {
|
|
||||||
free(out);
|
|
||||||
/* free(rel_url); */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
free(out);
|
|
||||||
/* free(rel_url); */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
free(out);
|
if (rel.pathquery.size == (size_t)0) {
|
||||||
/* free(rel_url); */
|
rv = snprintf(out_finger, len, "%.*s", (int)base.pathquery.size, base.pathquery.buff);
|
||||||
return NULL;
|
} else {
|
||||||
}
|
if (len < base.pathquery.size)
|
||||||
|
goto error;
|
||||||
|
size_t i = (size_t)0, prefix = (size_t)1;
|
||||||
|
while (i < base.pathquery.size) {
|
||||||
|
out_finger[i] = base.pathquery.buff[i];
|
||||||
|
switch (base.pathquery.buff[i++]) {
|
||||||
|
case '/':
|
||||||
|
prefix = i;
|
||||||
|
/* fall-through */
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
case '?': /* query */
|
||||||
|
if (rel.pathquery.buff[0] == '?')
|
||||||
|
prefix = --i;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out_finger += prefix;
|
||||||
|
len -= prefix;
|
||||||
|
rv = snprintf(out_finger, len, "%.*s", (int)rel.pathquery.size, rel.pathquery.buff);
|
||||||
|
}
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
|
|
||||||
|
/* fragment */
|
||||||
|
if (rel.fragment.size > (size_t)0)
|
||||||
|
rv = snprintf(out_finger, len, "#%.*s", (int)rel.fragment.size, rel.fragment.buff);
|
||||||
|
else if (base.fragment.size > (size_t)0)
|
||||||
|
rv = snprintf(out_finger, len, "#%.*s", (int)base.fragment.size, base.fragment.buff);
|
||||||
|
else
|
||||||
|
rv = 0;
|
||||||
|
}
|
||||||
|
if (rv < 0 || rv >= len)
|
||||||
|
goto error;
|
||||||
|
out_finger += rv;
|
||||||
|
len -= rv;
|
||||||
|
|
||||||
|
if (remove_dots(path, out_finger - path) != UPNP_E_SUCCESS)
|
||||||
|
goto error;
|
||||||
|
|
||||||
/* free(rel_url); */
|
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
|
error:
|
||||||
|
free(out);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user