#include <stddef.h>
#include <stdlib.h>
#include <gpxe/refcnt.h>
Go to the source code of this file.
Data Structures | |
| struct | uri |
| A Uniform Resource Identifier. More... | |
Defines | |
| #define | uri_get_field(uri, field) (&uri->scheme)[field] |
| Extract field from URI. | |
| #define | URI_ALL |
| All URI fields. | |
| #define | URI_ENCODED |
| URI fields that should be decoded on storage. | |
Enumerations | |
| enum | { URI_SCHEME = 0, URI_SCHEME_BIT = ( 1 << URI_SCHEME ), URI_OPAQUE = 1, URI_OPAQUE_BIT = ( 1 << URI_OPAQUE ), URI_USER = 2, URI_USER_BIT = ( 1 << URI_USER ), URI_PASSWORD = 3, URI_PASSWORD_BIT = ( 1 << URI_PASSWORD ), URI_HOST = 4, URI_HOST_BIT = ( 1 << URI_HOST ), URI_PORT = 5, URI_PORT_BIT = ( 1 << URI_PORT ), URI_PATH = 6, URI_PATH_BIT = ( 1 << URI_PATH ), URI_QUERY = 7, URI_QUERY_BIT = ( 1 << URI_QUERY ), URI_FRAGMENT = 8, URI_FRAGMENT_BIT = ( 1 << URI_FRAGMENT ), URI_FIRST_FIELD = URI_SCHEME, URI_LAST_FIELD = URI_FRAGMENT } |
| A field in a URI. More... | |
Functions | |
| FILE_LICENCE (GPL2_OR_LATER) | |
| static int | uri_is_absolute (struct uri *uri) |
| URI is an absolute URI. | |
| static int | uri_has_absolute_path (struct uri *uri) |
| URI has an absolute path. | |
| static int | uri_has_relative_path (struct uri *uri) |
| URI has a relative path. | |
| static | __attribute__ ((always_inline)) struct uri *uri_get(struct uri *uri) |
| Increment URI reference count. | |
| struct uri * | parse_uri (const char *uri_string) |
| Parse URI. | |
| unsigned int | uri_port (struct uri *uri, unsigned int default_port) |
| Get port from URI. | |
| int | unparse_uri (char *buf, size_t size, struct uri *uri, unsigned int fields) |
| Unparse URI. | |
| struct uri * | uri_dup (struct uri *uri) |
| Duplicate URI. | |
| char * | resolve_path (const char *base_path, const char *relative_path) |
| Resolve base+relative path. | |
| struct uri * | resolve_uri (struct uri *base_uri, struct uri *relative_uri) |
| Resolve base+relative URI. | |
| void | churi (struct uri *uri) |
| Change working URI. | |
| size_t | uri_encode (const char *raw_string, char *buf, ssize_t len, int field) |
| URI-encode string. | |
| size_t | uri_decode (const char *encoded_string, char *buf, ssize_t len) |
| Decode URI-encoded string. | |
Variables | |
| struct uri | packed |
| A Uniform Resource Identifier. | |
| struct uri * | cwuri |
| Current working URI. | |
Definition in file uri.h.
Extract field from URI.
Definition at line 91 of file uri.h.
Referenced by parse_uri(), and unparse_uri().
| #define URI_ALL |
Value:
( URI_SCHEME_BIT | URI_OPAQUE_BIT | URI_USER_BIT | \ URI_PASSWORD_BIT | URI_HOST_BIT | URI_PORT_BIT | \ URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT )
Definition at line 94 of file uri.h.
Referenced by imgfetch(), test_parse_unparse(), test_resolve(), and uri_dup().
| #define URI_ENCODED |
Value:
( URI_USER_BIT | URI_PASSWORD_BIT | URI_HOST_BIT | \ URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT )
Definition at line 99 of file uri.h.
Referenced by parse_uri(), and unparse_uri().
| anonymous enum |
A field in a URI.
The order of the indices in this enumeration must match the order of the fields in the URI structure.
Definition at line 75 of file uri.h.
00075 { 00076 URI_SCHEME = 0, URI_SCHEME_BIT = ( 1 << URI_SCHEME ), 00077 URI_OPAQUE = 1, URI_OPAQUE_BIT = ( 1 << URI_OPAQUE ), 00078 URI_USER = 2, URI_USER_BIT = ( 1 << URI_USER ), 00079 URI_PASSWORD = 3, URI_PASSWORD_BIT = ( 1 << URI_PASSWORD ), 00080 URI_HOST = 4, URI_HOST_BIT = ( 1 << URI_HOST ), 00081 URI_PORT = 5, URI_PORT_BIT = ( 1 << URI_PORT ), 00082 URI_PATH = 6, URI_PATH_BIT = ( 1 << URI_PATH ), 00083 URI_QUERY = 7, URI_QUERY_BIT = ( 1 << URI_QUERY ), 00084 URI_FRAGMENT = 8, URI_FRAGMENT_BIT = ( 1 << URI_FRAGMENT ), 00085 00086 URI_FIRST_FIELD = URI_SCHEME, 00087 URI_LAST_FIELD = URI_FRAGMENT, 00088 };
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| static int uri_is_absolute | ( | struct uri * | uri | ) | [inline, static] |
URI is an absolute URI.
| uri | URI |
| is_absolute | URI is absolute |
Definition at line 112 of file uri.h.
References NULL, and uri::scheme.
Referenced by boot_next_server_and_filename(), and resolve_uri().
| static int uri_has_absolute_path | ( | struct uri * | uri | ) | [inline, static] |
URI has an absolute path.
| uri | URI |
| has_absolute_path | URI has an absolute path |
Definition at line 126 of file uri.h.
References uri::path.
| static int uri_has_relative_path | ( | struct uri * | uri | ) | [inline, static] |
URI has a relative path.
| uri | URI |
| has_relative_path | URI has a relative path |
Definition at line 140 of file uri.h.
References uri::path.
| static __attribute__ | ( | (always_inline) | ) | [inline, static] |
| struct uri* parse_uri | ( | const char * | uri_string | ) | [read] |
Parse URI.
| uri_string | URI as a string |
| uri | URI |
Definition at line 73 of file uri.c.
References DBG, dump_uri(), uri::fragment, uri::host, memcpy, memmove(), NULL, uri::opaque, uri::password, uri::path, uri::port, uri::query, raw(), uri::scheme, strchr(), strlen(), strncmp(), uri_decode(), URI_ENCODED, URI_FIRST_FIELD, uri_get_field, URI_LAST_FIELD, uri::user, and zalloc().
Referenced by boot_next_server_and_filename(), imgfetch(), test_parse_unparse(), test_resolve(), tftp_apply_settings(), uri_dup(), and xfer_open_uri_string().
00073 { 00074 struct uri *uri; 00075 char *raw; 00076 char *tmp; 00077 char *path = NULL; 00078 char *authority = NULL; 00079 int i; 00080 size_t raw_len; 00081 00082 /* Allocate space for URI struct and a copy of the string */ 00083 raw_len = ( strlen ( uri_string ) + 1 /* NUL */ ); 00084 uri = zalloc ( sizeof ( *uri ) + raw_len ); 00085 if ( ! uri ) 00086 return NULL; 00087 raw = ( ( ( char * ) uri ) + sizeof ( *uri ) ); 00088 00089 /* Copy in the raw string */ 00090 memcpy ( raw, uri_string, raw_len ); 00091 00092 /* Start by chopping off the fragment, if it exists */ 00093 if ( ( tmp = strchr ( raw, '#' ) ) ) { 00094 *(tmp++) = '\0'; 00095 uri->fragment = tmp; 00096 } 00097 00098 /* Identify absolute/relative URI. We ignore schemes that are 00099 * apparently only a single character long, since otherwise we 00100 * misinterpret a DOS-style path name ("C:\path\to\file") as a 00101 * URI with scheme="C",opaque="\path\to\file". 00102 */ 00103 if ( ( tmp = strchr ( raw, ':' ) ) && ( tmp > ( raw + 1 ) ) ) { 00104 /* Absolute URI: identify hierarchical/opaque */ 00105 uri->scheme = raw; 00106 *(tmp++) = '\0'; 00107 if ( *tmp == '/' ) { 00108 /* Absolute URI with hierarchical part */ 00109 path = tmp; 00110 } else { 00111 /* Absolute URI with opaque part */ 00112 uri->opaque = tmp; 00113 } 00114 } else { 00115 /* Relative URI */ 00116 path = raw; 00117 } 00118 00119 /* If we don't have a path (i.e. we have an absolute URI with 00120 * an opaque portion, we're already finished processing 00121 */ 00122 if ( ! path ) 00123 goto done; 00124 00125 /* Chop off the query, if it exists */ 00126 if ( ( tmp = strchr ( path, '?' ) ) ) { 00127 *(tmp++) = '\0'; 00128 uri->query = tmp; 00129 } 00130 00131 /* Identify net/absolute/relative path */ 00132 if ( strncmp ( path, "//", 2 ) == 0 ) { 00133 /* Net path. If this is terminated by the first '/' 00134 * of an absolute path, then we have no space for a 00135 * terminator after the authority field, so shuffle 00136 * the authority down by one byte, overwriting one of 00137 * the two slashes. 00138 */ 00139 authority = ( path + 2 ); 00140 if ( ( tmp = strchr ( authority, '/' ) ) ) { 00141 /* Shuffle down */ 00142 uri->path = tmp; 00143 memmove ( ( authority - 1 ), authority, 00144 ( tmp - authority ) ); 00145 authority--; 00146 *(--tmp) = '\0'; 00147 } 00148 } else { 00149 /* Absolute/relative path */ 00150 uri->path = path; 00151 } 00152 00153 /* Split authority into user[:password] and host[:port] portions */ 00154 if ( ( tmp = strchr ( authority, '@' ) ) ) { 00155 /* Has user[:password] */ 00156 *(tmp++) = '\0'; 00157 uri->host = tmp; 00158 uri->user = authority; 00159 if ( ( tmp = strchr ( authority, ':' ) ) ) { 00160 /* Has password */ 00161 *(tmp++) = '\0'; 00162 uri->password = tmp; 00163 } 00164 } else { 00165 /* No user:password */ 00166 uri->host = authority; 00167 } 00168 00169 /* Split host into host[:port] */ 00170 if ( ( tmp = strchr ( uri->host, ':' ) ) ) { 00171 *(tmp++) = '\0'; 00172 uri->port = tmp; 00173 } 00174 00175 /* Decode fields that should be decoded */ 00176 for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { 00177 const char *field = uri_get_field ( uri, i ); 00178 if ( field && ( URI_ENCODED & ( 1 << i ) ) ) 00179 uri_decode ( field, ( char * ) field, 00180 strlen ( field ) + 1 /* NUL */ ); 00181 } 00182 00183 done: 00184 DBG ( "URI \"%s\" split into", uri_string ); 00185 dump_uri ( uri ); 00186 DBG ( "\n" ); 00187 00188 return uri; 00189 }
| unsigned int uri_port | ( | struct uri * | uri, | |
| unsigned int | default_port | |||
| ) |
Get port from URI.
| uri | URI, or NULL | |
| default_port | Default port to use if none specified in URI |
| port | Port |
Definition at line 198 of file uri.c.
References NULL, uri::port, and strtoul().
Referenced by ftp_open(), http_open_filter(), slam_open(), tcp_open_uri(), tftp_core_open(), and udp_open_uri().
00198 { 00199 if ( ( ! uri ) || ( ! uri->port ) ) 00200 return default_port; 00201 return ( strtoul ( uri->port, NULL, 0 ) ); 00202 }
Unparse URI.
| buf | Buffer to fill with URI string | |
| size | Size of buffer | |
| uri | URI to write into buffer, or NULL | |
| fields | Bitmask of fields to include in URI string, or URI_ALL |
| len | Length of URI string |
Definition at line 213 of file uri.c.
References DBG, dump_uri(), ssnprintf(), uri_encode(), URI_ENCODED, URI_FIRST_FIELD, uri_get_field, URI_LAST_FIELD, URI_OPAQUE, and URI_SCHEME_BIT.
Referenced by http_step(), imgfetch(), test_parse_unparse(), test_resolve(), and uri_dup().
00214 { 00215 /* List of characters that typically go before certain fields */ 00216 static char separators[] = { /* scheme */ 0, /* opaque */ ':', 00217 /* user */ 0, /* password */ ':', 00218 /* host */ '@', /* port */ ':', 00219 /* path */ 0, /* query */ '?', 00220 /* fragment */ '#' }; 00221 int used = 0; 00222 int i; 00223 00224 DBG ( "URI unparsing" ); 00225 dump_uri ( uri ); 00226 DBG ( "\n" ); 00227 00228 /* Ensure buffer is NUL-terminated */ 00229 if ( size ) 00230 buf[0] = '\0'; 00231 00232 /* Special-case NULL URI */ 00233 if ( ! uri ) 00234 return 0; 00235 00236 /* Iterate through requested fields */ 00237 for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { 00238 const char *field = uri_get_field ( uri, i ); 00239 char sep = separators[i]; 00240 00241 /* Ensure `fields' only contains bits for fields that exist */ 00242 if ( ! field ) 00243 fields &= ~( 1 << i ); 00244 00245 /* Store this field if we were asked to */ 00246 if ( fields & ( 1 << i ) ) { 00247 /* Print :// if we're non-opaque and had a scheme */ 00248 if ( ( fields & URI_SCHEME_BIT ) && 00249 ( i > URI_OPAQUE ) ) { 00250 used += ssnprintf ( buf + used, size - used, 00251 "://" ); 00252 /* Only print :// once */ 00253 fields &= ~URI_SCHEME_BIT; 00254 } 00255 00256 /* Only print separator if an earlier field exists */ 00257 if ( sep && ( fields & ( ( 1 << i ) - 1 ) ) ) 00258 used += ssnprintf ( buf + used, size - used, 00259 "%c", sep ); 00260 00261 /* Print contents of field, possibly encoded */ 00262 if ( URI_ENCODED & ( 1 << i ) ) 00263 used += uri_encode ( field, buf + used, 00264 size - used, i ); 00265 else 00266 used += ssnprintf ( buf + used, size - used, 00267 "%s", field ); 00268 } 00269 } 00270 00271 return used; 00272 }
Duplicate URI.
| uri | URI |
| uri | Duplicate URI |
Definition at line 282 of file uri.c.
References NULL, parse_uri(), unparse_uri(), and URI_ALL.
Referenced by resolve_uri().
00282 { 00283 size_t len = ( unparse_uri ( NULL, 0, uri, URI_ALL ) + 1 ); 00284 char buf[len]; 00285 00286 unparse_uri ( buf, len, uri, URI_ALL ); 00287 return parse_uri ( buf ); 00288 }
| char* resolve_path | ( | const char * | base_path, | |
| const char * | relative_path | |||
| ) |
Resolve base+relative path.
| base_uri | Base path | |
| relative_uri | Relative path |
| resolved_uri | Resolved path |
Definition at line 304 of file uri.c.
References asprintf(), dirname(), memcpy, NULL, strdup(), and strlen().
Referenced by resolve_uri().
00305 { 00306 size_t base_len = ( strlen ( base_path ) + 1 ); 00307 char base_path_copy[base_len]; 00308 char *base_tmp = base_path_copy; 00309 char *resolved; 00310 00311 /* If relative path is absolute, just re-use it */ 00312 if ( relative_path[0] == '/' ) 00313 return strdup ( relative_path ); 00314 00315 /* Create modifiable copy of path for dirname() */ 00316 memcpy ( base_tmp, base_path, base_len ); 00317 base_tmp = dirname ( base_tmp ); 00318 00319 /* Process "./" and "../" elements */ 00320 while ( *relative_path == '.' ) { 00321 relative_path++; 00322 if ( *relative_path == 0 ) { 00323 /* Do nothing */ 00324 } else if ( *relative_path == '/' ) { 00325 relative_path++; 00326 } else if ( *relative_path == '.' ) { 00327 relative_path++; 00328 if ( *relative_path == 0 ) { 00329 base_tmp = dirname ( base_tmp ); 00330 } else if ( *relative_path == '/' ) { 00331 base_tmp = dirname ( base_tmp ); 00332 relative_path++; 00333 } else { 00334 relative_path -= 2; 00335 break; 00336 } 00337 } else { 00338 relative_path--; 00339 break; 00340 } 00341 } 00342 00343 /* Create and return new path */ 00344 if ( asprintf ( &resolved, "%s%s%s", base_tmp, 00345 ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ? 00346 "" : "/" ), relative_path ) < 0 ) 00347 return NULL; 00348 00349 return resolved; 00350 }
Resolve base+relative URI.
| base_uri | Base URI, or NULL | |
| relative_uri | Relative URI |
| resolved_uri | Resolved URI |
Definition at line 363 of file uri.c.
References uri::fragment, free(), memcpy, NULL, uri::path, uri::query, resolve_path(), uri_dup(), and uri_is_absolute().
Referenced by churi(), test_resolve(), and xfer_open_uri().
00364 { 00365 struct uri tmp_uri; 00366 char *tmp_path = NULL; 00367 struct uri *new_uri; 00368 00369 /* If relative URI is absolute, just re-use it */ 00370 if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) ) 00371 return uri_get ( relative_uri ); 00372 00373 /* Mangle URI */ 00374 memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) ); 00375 if ( relative_uri->path ) { 00376 tmp_path = resolve_path ( ( base_uri->path ? 00377 base_uri->path : "/" ), 00378 relative_uri->path ); 00379 tmp_uri.path = tmp_path; 00380 tmp_uri.query = relative_uri->query; 00381 tmp_uri.fragment = relative_uri->fragment; 00382 } else if ( relative_uri->query ) { 00383 tmp_uri.query = relative_uri->query; 00384 tmp_uri.fragment = relative_uri->fragment; 00385 } else if ( relative_uri->fragment ) { 00386 tmp_uri.fragment = relative_uri->fragment; 00387 } 00388 00389 /* Create demangled URI */ 00390 new_uri = uri_dup ( &tmp_uri ); 00391 free ( tmp_path ); 00392 return new_uri; 00393 }
| void churi | ( | struct uri * | uri | ) |
Change working URI.
| uri | New working URI, or NULL |
Definition at line 40 of file cwuri.c.
References resolve_uri().
Referenced by image_exec(), and tftp_apply_settings().
00040 { 00041 struct uri *new_uri; 00042 00043 new_uri = resolve_uri ( cwuri, uri ); 00044 uri_put ( cwuri ); 00045 cwuri = new_uri; 00046 }
URI-encode string.
| raw_string | String to be URI-encoded | |
| buf | Buffer to contain encoded string | |
| len | Length of buffer | |
| field | Field of URI in which string lies |
| len | Length of encoded string (excluding NUL) |
Definition at line 435 of file uri.c.
References is_unreserved_uri_char(), and ssnprintf().
Referenced by boot_next_server_and_filename(), fetchf_uristring(), and unparse_uri().
00436 { 00437 ssize_t remaining = len; 00438 size_t used; 00439 unsigned char c; 00440 00441 if ( len > 0 ) 00442 buf[0] = '\0'; 00443 00444 while ( ( c = *(raw_string++) ) ) { 00445 if ( is_unreserved_uri_char ( c, field ) ) { 00446 used = ssnprintf ( buf, remaining, "%c", c ); 00447 } else { 00448 used = ssnprintf ( buf, remaining, "%%%02X", c ); 00449 } 00450 buf += used; 00451 remaining -= used; 00452 } 00453 00454 return ( len - remaining ); 00455 }
Decode URI-encoded string.
| encoded_string | URI-encoded string | |
| buf | Buffer to contain decoded string | |
| len | Length of buffer |
| len | Length of decoded string (excluding NUL) |
Definition at line 468 of file uri.c.
References snprintf(), and strtoul().
Referenced by parse_uri(), and storef_uristring().
00468 { 00469 ssize_t remaining; 00470 char hexbuf[3]; 00471 char *hexbuf_end; 00472 unsigned char c; 00473 00474 for ( remaining = len; *encoded_string; remaining-- ) { 00475 if ( *encoded_string == '%' ) { 00476 encoded_string++; 00477 snprintf ( hexbuf, sizeof ( hexbuf ), "%s", 00478 encoded_string ); 00479 c = strtoul ( hexbuf, &hexbuf_end, 16 ); 00480 encoded_string += ( hexbuf_end - hexbuf ); 00481 } else { 00482 c = *(encoded_string++); 00483 } 00484 if ( remaining > 1 ) 00485 *buf++ = c; 00486 } 00487 00488 if ( len ) 00489 *buf = 0; 00490 00491 return ( len - remaining ); 00492 }
A Uniform Resource Identifier.
Terminology for this data structure is as per uri(7), except that "path" is defined to include the leading '/' for an absolute path.
Note that all fields within a URI are optional and may be NULL.
The pointers to the various fields are packed together so they can be accessed in array fashion in some places in uri.c where doing so saves significant code size.
Some examples are probably helpful:
http://www.etherboot.org/wiki :
scheme = "http", host = "www.etherboot.org", path = "/wiki"
/var/lib/tftpboot :
path = "/var/lib/tftpboot"
mailto:bob@nowhere.com :
scheme = "mailto", opaque = "bob@nowhere.com"
ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this
scheme = "ftp", user = "joe", password = "secret", host = "insecure.org", port = "8081", path = "/hidden/path/to", query = "what=is", fragment = "this"
Current working URI.
Definition at line 33 of file cwuri.c.
Referenced by image_exec(), and xfer_open_uri().
1.5.7.1