📄 uri.c
字号:
remove_escaped_chars( INOUT char *in, INOUT int *size ){ int i = 0; for( i = 0; i < *size; i++ ) { replace_escaped( in, i, size ); } return UPNP_E_SUCCESS;}/************************************************************************* Function : remove_dots** Parameters :* char *in ; string of characters from which "dots" have to be * removed* int size ; size limit for the number of characters** Description : Removes ".", and ".." from a path. If a ".." can not* be resolved (i.e. the .. would go past the root of the path) an * error is returned. The input IS modified in place.)** Return : int ;* UPNP_E_SUCCESS - On Success* UPNP_E_OUTOF_MEMORY - On failure to allocate memory* UPNP_E_INVALID_URL - Failure to resolve URL** Note :* Examples* char path[30]="/../hello";* remove_dots(path, strlen(path)) -> UPNP_E_INVALID_URL* char path[30]="/./hello";* remove_dots(path, strlen(path)) -> UPNP_E_SUCCESS, * in = "/hello"* char path[30]="/./hello/foo/../goodbye" -> * UPNP_E_SUCCESS, in = "/hello/goodbye"************************************************************************/intremove_dots( char *in, int size ){ char *copyTo = in; char *copyFrom = in; char *max = in + size; char **Segments = NULL; int lastSegment = -1; Segments = malloc( sizeof( char * ) * size ); if( Segments == NULL ) return UPNP_E_OUTOF_MEMORY; Segments[0] = NULL; DBGONLY( UpnpPrintf ( UPNP_ALL, API, __FILE__, __LINE__, "REMOVE_DOTS: before: %s\n", in ) ); while( ( copyFrom < max ) && ( *copyFrom != '?' ) && ( *copyFrom != '#' ) ) { if( ( ( *copyFrom ) == '.' ) && ( ( copyFrom == in ) || ( *( copyFrom - 1 ) == '/' ) ) ) { if( ( copyFrom + 1 == max ) || ( *( copyFrom + 1 ) == '/' ) ) { copyFrom += 2; continue; } else if( ( *( copyFrom + 1 ) == '.' ) && ( ( copyFrom + 2 == max ) || ( *( copyFrom + 2 ) == '/' ) ) ) { copyFrom += 3; if( lastSegment > 0 ) { copyTo = Segments[--lastSegment]; } else { free( Segments ); //TRACE("ERROR RESOLVING URL, ../ at ROOT"); return UPNP_E_INVALID_URL; } continue; } } if( ( *copyFrom ) == '/' ) { lastSegment++; Segments[lastSegment] = copyTo + 1; } ( *copyTo ) = ( *copyFrom ); copyTo++; copyFrom++; } if( copyFrom < max ) { while( copyFrom < max ) { ( *copyTo ) = ( *copyFrom ); copyTo++; copyFrom++; } } ( *copyTo ) = 0; free( Segments ); DBGONLY( UpnpPrintf ( UPNP_ALL, API, __FILE__, __LINE__, "REMOVE_DOTS: after: %s\n", in ) ); return UPNP_E_SUCCESS;}/************************************************************************* Function : resolve_rel_url** Parameters :* char * base_url ; Base URL* char * rel_url ; Relative URL** Description : resolves a relative url with a base url returning a NEW * (dynamically allocated with malloc) full url. If the base_url is * NULL, then a copy of the rel_url is passed back if the rel_url * is absolute then a copy of the rel_url is passed back if neither * the base nor the rel_url are Absolute then NULL is returned.* otherwise it tries and resolves the relative url with the base * as described in: http://www.ietf.org/rfc/rfc2396.txt (RFCs * explaining URIs) * : resolution of '..' is NOT implemented, but '.' is resolved ** Return : char * ;** Note :************************************************************************/char *resolve_rel_url( char *base_url, char *rel_url ){ uri_type base; uri_type rel; char temp_path = '/'; int i = 0; char *finger = NULL; char *last_slash = NULL; char *out = NULL; char *out_finger = NULL; if( base_url && rel_url ) { out = ( char * )malloc( strlen( base_url ) + strlen( rel_url ) + 2 ); out_finger = out; } else { if( rel_url ) return strdup( rel_url ); else return NULL; } if( out == NULL ) { return NULL; } if( ( parse_uri( rel_url, strlen( rel_url ), &rel ) ) == HTTP_SUCCESS ) { if( rel.type == ABSOLUTE ) { strcpy( out, rel_url ); } else { if( ( parse_uri( base_url, strlen( base_url ), &base ) == HTTP_SUCCESS ) && ( base.type == ABSOLUTE ) ) { if( strlen( rel_url ) == 0 ) { strcpy( out, base_url ); } else { memcpy( out, base.scheme.buff, base.scheme.size ); out_finger += base.scheme.size; ( *out_finger ) = ':'; out_finger++; if( rel.hostport.text.size > 0 ) { sprintf( out_finger, "%s", rel_url ); } else { if( base.hostport.text.size > 0 ) { memcpy( out_finger, "//", 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 == ABS_PATH ) { strcpy( out_finger, rel_url ); } else { if( base.pathquery.size == 0 ) { base.pathquery.size = 1; base.pathquery.buff = &temp_path; } finger = out_finger; last_slash = finger; i = 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++; } i = 0; strcpy( last_slash, 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 { free( out ); //free(rel_url); return NULL; } //free(rel_url); return out;}/************************************************************************* Function : parse_uri** Parameters :* char * in ; character string containing uri information to be * parsed* int max ; maximum limit on the number of characters* uri_type * out ; out parameter which will have the parsed uri* information ** Description : parses a uri as defined in http://www.ietf.org/rfc/* rfc2396.txt (RFC explaining URIs)* Handles absolute, relative, and opaque uris. Parses into the * following pieces: scheme, hostport, pathquery, fragment (path and* query are treated as one token)* Caller should check for the pieces they require.** Return : int ;** Note :************************************************************************/intparse_uri( char *in, int max, uri_type * out ){ int begin_path = 0; int begin_hostport = 0; int begin_fragment = 0; if( ( begin_hostport = parse_scheme( in, max, &out->scheme ) ) ) { out->type = ABSOLUTE; out->path_type = OPAQUE_PART; begin_hostport++; } else { out->type = RELATIVE; out->path_type = REL_PATH; } if( ( ( begin_hostport + 1 ) < max ) && ( in[begin_hostport] == '/' ) && ( in[begin_hostport + 1] == '/' ) ) { begin_hostport += 2; if( ( begin_path = parse_hostport( &in[begin_hostport], max - begin_hostport, &out->hostport ) ) >= 0 ) { begin_path += begin_hostport; } else return begin_path; } else { out->hostport.IPv4address.sin_port = 0; out->hostport.IPv4address.sin_addr.s_addr = 0; out->hostport.text.size = 0; out->hostport.text.buff = 0; begin_path = begin_hostport; } begin_fragment = parse_uric( &in[begin_path], max - begin_path, &out->pathquery ) + begin_path; if( ( out->pathquery.size ) && ( out->pathquery.buff[0] == '/' ) ) { out->path_type = ABS_PATH; } if( ( begin_fragment < max ) && ( in[begin_fragment] == '#' ) ) { begin_fragment++; parse_uric( &in[begin_fragment], max - begin_fragment, &out->fragment ); } else { out->fragment.buff = NULL; out->fragment.size = 0; } return HTTP_SUCCESS;}/************************************************************************* Function : parse_uri_and_unescape** Parameters :* char * in ; * int max ; * uri_type * out ; ** Description : Same as parse_uri, except that all strings are * unescaped (%XX replaced by chars)** Return : int ;** Note: This modifies 'pathquery' and 'fragment' parts of the input************************************************************************/intparse_uri_and_unescape( char *in, int max, uri_type * out ){ int ret; if( ( ret = parse_uri( in, max, out ) ) != HTTP_SUCCESS ) return ret; if( out->pathquery.size > 0 ) remove_escaped_chars( out->pathquery.buff, &out->pathquery.size ); if( out->fragment.size > 0 ) remove_escaped_chars( out->fragment.buff, &out->fragment.size ); return HTTP_SUCCESS;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -