iPXE
uri.c File Reference

Uniform Resource Identifiers. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <libgen.h>
#include <ctype.h>
#include <ipxe/vsprintf.h>
#include <ipxe/params.h>
#include <ipxe/tcpip.h>
#include <ipxe/uri.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
size_t uri_decode (const char *encoded, void *buf, size_t len)
 Decode URI field.
static void uri_decode_inplace (char *encoded)
 Decode URI field in-place.
static int uri_character_escaped (char c, unsigned int field)
 Check if character should be escaped within a URI field.
size_t uri_encode (unsigned int field, const void *raw, size_t raw_len, char *buf, ssize_t len)
 Encode URI field.
size_t uri_encode_string (unsigned int field, const char *string, char *buf, ssize_t len)
 Encode URI field string.
static void uri_dump (const struct uri *uri)
 Dump URI for debugging.
static void uri_free (struct refcnt *refcnt)
 Free URI.
struct uriparse_uri (const char *uri_string)
 Parse URI.
unsigned int uri_port (const struct uri *uri, unsigned int default_port)
 Get port from URI.
size_t format_uri (const struct uri *uri, char *buf, size_t len)
 Format URI.
char * format_uri_alloc (const struct uri *uri)
 Format URI.
static size_t uri_copy_fields (const struct uri *src, struct uri *dest)
 Copy URI fields.
struct uriuri_dup (const struct uri *uri)
 Duplicate URI.
char * resolve_path (const char *base_path, const char *relative_path)
 Resolve base+relative path.
struct uriresolve_uri (const struct uri *base_uri, struct uri *relative_uri)
 Resolve base+relative URI.
static struct uritftp_uri (struct sockaddr *sa_server, const char *filename)
 Construct TFTP URI from server address and filename.
struct uripxe_uri (struct sockaddr *sa_server, const char *filename)
 Construct URI from server address and filename.

Detailed Description

Uniform Resource Identifiers.

Definition in file uri.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ uri_decode()

size_t uri_decode ( const char * encoded,
void * buf,
size_t len )

Decode URI field.

Parameters
encodedEncoded field
bufData buffer
lenLength
Return values
lenLength of data

URI decoding can never increase the length of a string; we can therefore safely decode in place.

Definition at line 54 of file uri.c.

54 {
55 uint8_t *out = buf;
56 unsigned int count = 0;
57 char hexbuf[3];
58 char *hexbuf_end;
59 char c;
60 char decoded;
61 unsigned int skip;
62
63 /* Copy string, decoding escaped characters as necessary */
64 while ( ( c = *(encoded++) ) ) {
65 if ( c == '%' ) {
66 snprintf ( hexbuf, sizeof ( hexbuf ), "%s", encoded );
67 decoded = strtoul ( hexbuf, &hexbuf_end, 16 );
68 skip = ( hexbuf_end - hexbuf );
69 encoded += skip;
70 if ( skip )
71 c = decoded;
72 }
73 if ( count < len )
74 out[count] = c;
75 count++;
76 }
77 return count;
78}
__be32 out[4]
Definition CIB_PRM.h:8
unsigned char uint8_t
Definition stdint.h:10
ring len
Length.
Definition dwmac.h:226
static unsigned int count
Number of entries.
Definition dwmac.h:220
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition string.c:485
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References count, len, out, snprintf(), and strtoul().

Referenced by parse_uristring_setting(), and uri_decode_inplace().

◆ uri_decode_inplace()

void uri_decode_inplace ( char * encoded)
static

Decode URI field in-place.

Parameters
encodedEncoded field, or NULL

Definition at line 85 of file uri.c.

85 {
86 char *decoded = encoded;
87 size_t len;
88
89 /* Do nothing if field is not present */
90 if ( ! encoded )
91 return;
92
93 /* Decode field in place */
94 len = uri_decode ( encoded, decoded, strlen ( encoded ) );
95
96 /* Terminate decoded string */
97 decoded[len] = '\0';
98}
size_t strlen(const char *src)
Get length of string.
Definition string.c:244
size_t uri_decode(const char *encoded, void *buf, size_t len)
Decode URI field.
Definition uri.c:54

References len, strlen(), and uri_decode().

Referenced by parse_uri(), and resolve_uri().

◆ uri_character_escaped()

int uri_character_escaped ( char c,
unsigned int field )
static

Check if character should be escaped within a URI field.

Parameters
cCharacter
fieldURI field index
Return values
escapedCharacter should be escaped

Definition at line 107 of file uri.c.

107 {
108
109 /* Non-printing characters and whitespace should always be
110 * escaped, since they cannot sensibly be displayed as part of
111 * a coherent URL string. (This test also catches control
112 * characters such as CR and LF, which could affect the
113 * operation of line-based protocols such as HTTP.)
114 *
115 * We should also escape characters which would alter the
116 * interpretation of the URL if not escaped, i.e. characters
117 * which have significance to the URL parser. We should not
118 * blindly escape all such characters, because this would lead
119 * to some very strange-looking URLs (e.g. if we were to
120 * always escape '/' as "%2F" even within the URI path).
121 *
122 * We do not need to be perfect. Our primary role is as a
123 * consumer of URIs rather than a producer; the main situation
124 * in which we produce a URI string is for display to a human
125 * user, who can probably tolerate some variance from the
126 * formal specification. The only situation in which we
127 * currently produce a URI string to be consumed by a computer
128 * is when constructing an HTTP request URI, which contains
129 * only the path and query fields.
130 *
131 * We can therefore sacrifice some correctness for the sake of
132 * code size. For example, colons within the URI host should
133 * be escaped unless they form part of an IPv6 literal
134 * address; doing this correctly would require the URI
135 * formatter to be aware of whether or not the URI host
136 * contained an IPv4 address, an IPv6 address, or a host name.
137 * We choose to simplify and never escape colons within the
138 * URI host field: in the event of a pathological hostname
139 * containing colons, this could potentially produce a URI
140 * string which could not be reparsed.
141 *
142 * After excluding non-printing characters, whitespace, and
143 * '%', the full set of characters with significance to the
144 * URL parser is "/#:@?". We choose for each URI field which
145 * of these require escaping in our use cases.
146 *
147 * For the scheme field (equivalently, if field is zero), we
148 * escape anything that has significance not just for our URI
149 * parser but for any other URI parsers (e.g. HTTP query
150 * string parsers, which care about '=' and '&').
151 */
152 static const char *escaped[URI_EPATH] = {
153 /* Scheme or default: escape everything */
154 [URI_SCHEME] = "/#:@?=&",
155 /* Opaque part: escape characters which would affect
156 * the reparsing of the URI, allowing everything else
157 * (e.g. ':', which will appear in iSCSI URIs).
158 */
159 [URI_OPAQUE] = "#",
160 /* User name: escape everything */
161 [URI_USER] = "/#:@?",
162 /* Password: escape everything */
163 [URI_PASSWORD] = "/#:@?",
164 /* Host name: escape everything except ':', which may
165 * appear as part of an IPv6 literal address.
166 */
167 [URI_HOST] = "/#@?",
168 /* Port number: escape everything */
169 [URI_PORT] = "/#:@?",
170 /* Path: escape everything except '/', which usually
171 * appears within paths.
172 */
173 [URI_PATH] = "#:@?",
174 };
175
176 /* Always escape non-printing characters and whitespace */
177 if ( ( ! isprint ( c ) ) || ( c == ' ' ) )
178 return 1;
179
180 /* Escape nothing else in already-escaped fields */
181 if ( field >= URI_EPATH )
182 return 0;
183
184 /* Escape '%' and any field-specific characters */
185 if ( ( c == '%' ) || strchr ( escaped[field], c ) )
186 return 1;
187
188 return 0;
189}
static int isprint(int character)
Check if character is printable.
Definition ctype.h:98
char * strchr(const char *src, int character)
Find character within a string.
Definition string.c:272
@ URI_PATH
Definition uri.h:119
@ URI_EPATH
Definition uri.h:120
@ URI_SCHEME
Definition uri.h:113
@ URI_PORT
Definition uri.h:118
@ URI_USER
Definition uri.h:115
@ URI_HOST
Definition uri.h:117
@ URI_OPAQUE
Definition uri.h:114
@ URI_PASSWORD
Definition uri.h:116

References isprint(), strchr(), URI_EPATH, URI_HOST, URI_OPAQUE, URI_PASSWORD, URI_PATH, URI_PORT, URI_SCHEME, and URI_USER.

Referenced by uri_encode().

◆ uri_encode()

size_t uri_encode ( unsigned int field,
const void * raw,
size_t raw_len,
char * buf,
ssize_t len )

Encode URI field.

Parameters
fieldURI field index
rawRaw data
raw_lenLength of raw data
bufBuffer
lenLength of buffer
Return values
lenLength of encoded string (excluding NUL)

Definition at line 201 of file uri.c.

202 {
203 const uint8_t *raw_bytes = ( ( const uint8_t * ) raw );
204 ssize_t remaining = len;
205 size_t used;
206 char c;
207
208 /* Ensure encoded string is NUL-terminated even if empty */
209 if ( len > 0 )
210 buf[0] = '\0';
211
212 /* Copy string, escaping as necessary */
213 while ( raw_len-- ) {
214 c = *(raw_bytes++);
215 if ( uri_character_escaped ( c, field ) ) {
216 used = ssnprintf ( buf, remaining, "%%%02X", c );
217 } else {
218 used = ssnprintf ( buf, remaining, "%c", c );
219 }
220 buf += used;
221 remaining -= used;
222 }
223
224 return ( len - remaining );
225}
__be32 raw[7]
Definition CIB_PRM.h:0
signed long ssize_t
Definition stdint.h:7
static size_t raw_len
Definition base16.h:54
static int uri_character_escaped(char c, unsigned int field)
Check if character should be escaped within a URI field.
Definition uri.c:107
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition vsprintf.c:421

References len, raw, raw_len, ssnprintf(), and uri_character_escaped().

Referenced by format_uristring_setting(), ocsp_uri_string(), and uri_encode_string().

◆ uri_encode_string()

size_t uri_encode_string ( unsigned int field,
const char * string,
char * buf,
ssize_t len )

Encode URI field string.

Parameters
fieldURI field index
stringString
bufBuffer
lenLength of buffer
Return values
lenLength of encoded string (excluding NUL)

Definition at line 236 of file uri.c.

237 {
238
239 return uri_encode ( field, string, strlen ( string ), buf, len );
240}
size_t uri_encode(unsigned int field, const void *raw, size_t raw_len, char *buf, ssize_t len)
Encode URI field.
Definition uri.c:201

References len, strlen(), and uri_encode().

Referenced by format_uri(), and http_form_params().

◆ uri_dump()

void uri_dump ( const struct uri * uri)
static

Dump URI for debugging.

Parameters
uriURI

Definition at line 247 of file uri.c.

247 {
248
249 if ( ! uri )
250 return;
251 if ( uri->scheme )
252 DBGC ( uri, " scheme \"%s\"", uri->scheme );
253 if ( uri->opaque )
254 DBGC ( uri, " opaque \"%s\"", uri->opaque );
255 if ( uri->user )
256 DBGC ( uri, " user \"%s\"", uri->user );
257 if ( uri->password )
258 DBGC ( uri, " password \"%s\"", uri->password );
259 if ( uri->host )
260 DBGC ( uri, " host \"%s\"", uri->host );
261 if ( uri->port )
262 DBGC ( uri, " port \"%s\"", uri->port );
263 if ( uri->path )
264 DBGC ( uri, " path \"%s\"", uri->path );
265 if ( uri->epath )
266 DBGC ( uri, " epath \"%s\"", uri->epath );
267 if ( uri->equery )
268 DBGC ( uri, " equery \"%s\"", uri->equery );
269 if ( uri->efragment )
270 DBGC ( uri, " efragment \"%s\"", uri->efragment );
271 if ( uri->params )
272 DBGC ( uri, " params \"%s\"", uri->params->name );
273}
#define DBGC(...)
Definition compiler.h:505
const char * name
Name.
Definition params.h:23
A Uniform Resource Identifier.
Definition uri.h:65
const char * epath
Path (with original URI encoding)
Definition uri.h:83
const char * path
Path (after URI decoding)
Definition uri.h:81
const char * user
User name.
Definition uri.h:73
struct parameters * params
Request parameters.
Definition uri.h:89
const char * host
Host name.
Definition uri.h:77
const char * password
Password.
Definition uri.h:75
const char * efragment
Fragment (with original URI encoding)
Definition uri.h:87
const char * scheme
Scheme.
Definition uri.h:69
const char * equery
Query (with original URI encoding)
Definition uri.h:85
const char * port
Port number.
Definition uri.h:79
const char * opaque
Opaque part.
Definition uri.h:71

References DBGC, uri::efragment, uri::epath, uri::equery, uri::host, parameters::name, uri::opaque, uri::params, uri::password, uri::path, uri::port, uri::scheme, and uri::user.

Referenced by format_uri(), parse_uri(), and uri_dup().

◆ uri_free()

void uri_free ( struct refcnt * refcnt)
static

Free URI.

Parameters
refcntReference count

Definition at line 280 of file uri.c.

280 {
281 struct uri *uri = container_of ( refcnt, struct uri, refcnt );
282
283 params_put ( uri->params );
284 free ( uri );
285}
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
A reference counter.
Definition refcnt.h:27

References container_of, free, and uri::params.

Referenced by parse_uri(), and uri_dup().

◆ parse_uri()

struct uri * parse_uri ( const char * uri_string)

Parse URI.

Parameters
uri_stringURI as a string
Return values
uriURI

Splits a URI into its component parts. The return URI structure is dynamically allocated and must eventually be freed by calling uri_put().

Definition at line 297 of file uri.c.

297 {
298 struct uri *uri;
299 struct parameters *params;
300 char *raw;
301 char *tmp;
302 char *path;
303 char *epath;
304 char *authority;
305 size_t raw_len;
306 unsigned int field;
307
308 /* Allocate space for URI struct and two copies of the string */
309 raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
310 uri = zalloc ( sizeof ( *uri ) + ( 2 * raw_len ) );
311 if ( ! uri )
312 return NULL;
314 raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );
315 path = ( raw + raw_len );
316
317 /* Copy in the raw string */
318 memcpy ( raw, uri_string, raw_len );
319
320 /* Identify the parameter list, if present */
321 if ( ( tmp = strstr ( raw, "##params" ) ) ) {
322 *tmp = '\0';
323 tmp += 8 /* "##params" */;
324 params = find_parameters ( ( *tmp == '=' ) ?
325 ( tmp + 1 ) : NULL );
326 if ( params ) {
327 uri->params = claim_parameters ( params );
328 } else {
329 /* Ignore non-existent submission blocks */
330 }
331 }
332
333 /* Chop off the fragment, if it exists */
334 if ( ( tmp = strchr ( raw, '#' ) ) ) {
335 *(tmp++) = '\0';
336 uri->efragment = tmp;
337 }
338
339 /* Identify absolute URIs */
340 epath = raw;
341 for ( tmp = raw ; ; tmp++ ) {
342 /* Possible scheme character (for our URI schemes) */
343 if ( isalpha ( *tmp ) || ( *tmp == '-' ) || ( *tmp == '_' ) )
344 continue;
345 /* Invalid scheme character or NUL: is a relative URI */
346 if ( *tmp != ':' )
347 break;
348 /* Absolute URI: identify hierarchical/opaque */
349 uri->scheme = raw;
350 *(tmp++) = '\0';
351 if ( *tmp == '/' ) {
352 /* Absolute URI with hierarchical part */
353 epath = tmp;
354 } else {
355 /* Absolute URI with opaque part */
356 uri->opaque = tmp;
357 epath = NULL;
358 }
359 break;
360 }
361
362 /* If we don't have a path (i.e. we have an absolute URI with
363 * an opaque portion, we're already finished processing
364 */
365 if ( ! epath )
366 goto done;
367
368 /* Chop off the query, if it exists */
369 if ( ( tmp = strchr ( epath, '?' ) ) ) {
370 *(tmp++) = '\0';
371 uri->equery = tmp;
372 }
373
374 /* If we have no path remaining, then we're already finished
375 * processing.
376 */
377 if ( ! epath[0] )
378 goto done;
379
380 /* Identify net/absolute/relative path */
381 if ( uri->scheme && ( strncmp ( epath, "//", 2 ) == 0 ) ) {
382 /* Net path. If this is terminated by the first '/'
383 * of an absolute path, then we have no space for a
384 * terminator after the authority field, so shuffle
385 * the authority down by one byte, overwriting one of
386 * the two slashes.
387 */
388 authority = ( epath + 2 );
389 if ( ( tmp = strchr ( authority, '/' ) ) ) {
390 /* Shuffle down */
391 uri->epath = tmp;
392 memmove ( ( authority - 1 ), authority,
393 ( tmp - authority ) );
394 authority--;
395 *(--tmp) = '\0';
396 }
397 } else {
398 /* Absolute/relative path */
399 uri->epath = epath;
400 authority = NULL;
401 }
402
403 /* Create copy of path for decoding */
404 if ( uri->epath ) {
405 strcpy ( path, uri->epath );
406 uri->path = path;
407 }
408
409 /* If we don't have an authority (i.e. we have a non-net
410 * path), we're already finished processing
411 */
412 if ( ! authority )
413 goto done;
414
415 /* Split authority into user[:password] and host[:port] portions */
416 if ( ( tmp = strchr ( authority, '@' ) ) ) {
417 /* Has user[:password] */
418 *(tmp++) = '\0';
419 uri->host = tmp;
420 uri->user = authority;
421 if ( ( tmp = strchr ( authority, ':' ) ) ) {
422 /* Has password */
423 *(tmp++) = '\0';
424 uri->password = tmp;
425 }
426 } else {
427 /* No user:password */
428 uri->host = authority;
429 }
430
431 /* Split host into host[:port] */
432 if ( ( tmp = strrchr ( uri->host, ':' ) ) &&
433 ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) ) {
434 *(tmp++) = '\0';
435 uri->port = tmp;
436 }
437
438 done:
439 /* Decode fields in-place */
440 for ( field = 0 ; field < URI_EPATH ; field++ )
441 uri_decode_inplace ( ( char * ) uri_field ( uri, field ) );
442
443 DBGC ( uri, "URI parsed \"%s\" to", uri_string );
444 uri_dump ( uri );
445 DBGC ( uri, "\n" );
446
447 return uri;
448}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct bofm_section_header done
Definition bofm_test.c:46
static int isalpha(int character)
Check if character is alphabetic.
Definition ctype.h:76
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * memmove(void *dest, const void *src, size_t len) __nonnull
unsigned long tmp
Definition linux_pci.h:65
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
struct parameters * find_parameters(const char *name)
Find request parameter list by name.
Definition params.c:69
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition string.c:187
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition string.c:310
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition string.c:290
char * strcpy(char *dest, const char *src)
Copy string.
Definition string.c:347
A request parameter list.
Definition params.h:17
struct refcnt refcnt
Reference count.
Definition uri.h:67
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition uri.c:247
static void uri_free(struct refcnt *refcnt)
Free URI.
Definition uri.c:280
static void uri_decode_inplace(char *encoded)
Decode URI field in-place.
Definition uri.c:85
#define uri_field(uri, field)
Access URI field.
Definition uri.h:99

References DBGC, done, uri::efragment, uri::epath, uri::equery, find_parameters(), uri::host, isalpha(), memcpy(), memmove(), NULL, uri::opaque, uri::params, uri::password, uri::path, uri::port, raw, raw_len, ref_init, uri::refcnt, uri::scheme, strchr(), strcpy(), strlen(), strncmp(), strrchr(), strstr(), tmp, uri_decode_inplace(), uri_dump(), URI_EPATH, uri_field, uri_free(), uri::user, and zalloc().

Referenced by cwuri_fetch_uri(), efi_path_uri(), fetch_root_path(), http_redirect(), imgdownload_string(), peerblk_retrieval_uri(), pxe_uri(), sanboot_core_exec(), tftp_apply_settings(), uri_churi_okx(), uri_params_okx(), uri_parse_okx(), uri_port_okx(), uri_resolve_okx(), and xfer_open_uri_string().

◆ uri_port()

unsigned int uri_port ( const struct uri * uri,
unsigned int default_port )

Get port from URI.

Parameters
uriURI, or NULL
default_portDefault port to use if none specified in URI
Return values
portPort

Definition at line 457 of file uri.c.

457 {
458
459 if ( ( ! uri ) || ( ! uri->port ) )
460 return default_port;
461
462 return ( strtoul ( uri->port, NULL, 0 ) );
463}

References NULL, uri::port, and strtoul().

Referenced by ftp_open(), http_connect(), slam_open(), tcp_open_uri(), tftp_core_open(), udp_open_uri(), and uri_port_okx().

◆ format_uri()

size_t format_uri ( const struct uri * uri,
char * buf,
size_t len )

Format URI.

Parameters
uriURI
bufBuffer to fill with URI string
sizeSize of buffer
Return values
lenLength of URI string

Definition at line 473 of file uri.c.

473 {
474 static const char prefixes[URI_FIELDS] = {
475 [URI_PASSWORD] = ':',
476 [URI_PORT] = ':',
477 [URI_EQUERY] = '?',
478 [URI_EFRAGMENT] = '#',
479 };
480 char prefix;
481 size_t used = 0;
482 unsigned int field;
483
484 /* Ensure buffer is NUL-terminated */
485 if ( len )
486 buf[0] = '\0';
487
488 /* Special-case NULL URI */
489 if ( ! uri )
490 return 0;
491
492 /* Generate fields */
493 for ( field = 0 ; field < URI_FIELDS ; field++ ) {
494
495 /* Skip non-existent fields */
496 if ( ! uri_field ( uri, field ) )
497 continue;
498
499 /* Skip path field if encoded path is present */
500 if ( ( field == URI_PATH ) && uri->epath )
501 continue;
502
503 /* Prefix this field, if applicable */
504 prefix = prefixes[field];
505 if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
506 prefix = '@';
507 if ( prefix ) {
508 used += ssnprintf ( ( buf + used ), ( len - used ),
509 "%c", prefix );
510 }
511
512 /* Encode this field */
513 used += uri_encode_string ( field, uri_field ( uri, field ),
514 ( buf + used ), ( len - used ) );
515
516 /* Suffix this field, if applicable */
517 if ( field == URI_SCHEME ) {
518 used += ssnprintf ( ( buf + used ), ( len - used ),
519 ":%s", ( uri->host ? "//" : "" ) );
520 }
521 }
522
523 if ( len ) {
524 DBGC ( uri, "URI formatted" );
525 uri_dump ( uri );
526 DBGC ( uri, " to \"%s%s\"\n", buf,
527 ( ( used > len ) ? "<TRUNCATED>" : "" ) );
528 }
529
530 return used;
531}
size_t uri_encode_string(unsigned int field, const char *string, char *buf, ssize_t len)
Encode URI field string.
Definition uri.c:236
@ URI_FIELDS
Definition uri.h:123
@ URI_EFRAGMENT
Definition uri.h:122
@ URI_EQUERY
Definition uri.h:121
char prefix[4]
Definition vmconsole.c:53

References DBGC, uri::epath, uri::host, len, NULL, prefix, ssnprintf(), uri_dump(), URI_EFRAGMENT, uri_encode_string(), URI_EQUERY, uri_field, URI_FIELDS, URI_HOST, URI_PASSWORD, URI_PATH, URI_PORT, URI_SCHEME, and uri::user.

Referenced by efi_uri_path(), format_uri_alloc(), http_open(), multiboot_add_cmdline(), uri_format_okx(), and uri_pxe_okx().

◆ format_uri_alloc()

char * format_uri_alloc ( const struct uri * uri)

Format URI.

Parameters
uriURI
Return values
stringURI string, or NULL on failure

The caller is responsible for eventually freeing the allocated memory.

Definition at line 542 of file uri.c.

542 {
543 size_t len;
544 char *string;
545
546 len = ( format_uri ( uri, NULL, 0 ) + 1 /* NUL */ );
547 string = malloc ( len );
548 if ( string )
549 format_uri ( uri, string, len );
550 return string;
551}
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
uint32_t string
Definition multiboot.h:2
size_t format_uri(const struct uri *uri, char *buf, size_t len)
Format URI.
Definition uri.c:473

References format_uri(), len, malloc(), NULL, and string.

Referenced by cwuri_fetch_uri(), imgdownload(), uri_churi_okx(), uri_format_okx(), and uri_resolve_okx().

◆ uri_copy_fields()

size_t uri_copy_fields ( const struct uri * src,
struct uri * dest )
static

Copy URI fields.

Parameters
srcSource URI
destDestination URI, or NULL to calculate length
Return values
lenLength of raw URI

Definition at line 560 of file uri.c.

560 {
561 size_t len = sizeof ( *dest );
562 char *out = ( ( void * ) dest + len );
563 unsigned int field;
564 size_t field_len;
565
566 /* Copy existent fields */
567 for ( field = 0 ; field < URI_FIELDS ; field++ ) {
568
569 /* Skip non-existent fields */
570 if ( ! uri_field ( src, field ) )
571 continue;
572
573 /* Calculate field length */
574 field_len = ( strlen ( uri_field ( src, field ) )
575 + 1 /* NUL */ );
576 len += field_len;
577
578 /* Copy field, if applicable */
579 if ( dest ) {
580 memcpy ( out, uri_field ( src, field ), field_len );
581 uri_field ( dest, field ) = out;
582 out += field_len;
583 }
584 }
585 return len;
586}
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" retur dest)
Definition string.h:151
static const void * src
Definition string.h:48

References dest, len, memcpy(), out, src, strlen(), uri_field, and URI_FIELDS.

Referenced by uri_dup().

◆ uri_dup()

struct uri * uri_dup ( const struct uri * uri)

Duplicate URI.

Parameters
uriURI
Return values
uriDuplicate URI

Creates a modifiable copy of a URI.

Definition at line 596 of file uri.c.

596 {
597 struct uri *dup;
598 size_t len;
599
600 /* Allocate new URI */
602 dup = zalloc ( len );
603 if ( ! dup )
604 return NULL;
605 ref_init ( &dup->refcnt, uri_free );
606
607 /* Copy fields */
608 uri_copy_fields ( uri, dup );
609
610 /* Copy parameters */
611 dup->params = params_get ( uri->params );
612
613 DBGC ( uri, "URI duplicated" );
614 uri_dump ( uri );
615 DBGC ( uri, "\n" );
616
617 return dup;
618}
static size_t uri_copy_fields(const struct uri *src, struct uri *dest)
Copy URI fields.
Definition uri.c:560

References DBGC, len, NULL, uri::params, ref_init, uri::refcnt, uri_copy_fields(), uri_dump(), uri_free(), and zalloc().

Referenced by resolve_uri(), tftp_uri(), uri_dup_okx(), and uri_params_okx().

◆ resolve_path()

char * resolve_path ( const char * base_path,
const char * relative_path )

Resolve base+relative path.

Parameters
base_uriBase path
relative_uriRelative path
Return values
resolved_uriResolved path, or NULL on failure

Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative path (e.g. "initrd.gz") and produces a new path (e.g. "/var/lib/tftpboot/initrd.gz"). Note that any non-directory portion of the base path will automatically be stripped; this matches the semantics used when resolving the path component of URIs.

Definition at line 634 of file uri.c.

635 {
636 char *base_copy;
637 char *base_tmp;
638 char *resolved;
639
640 /* If relative path is absolute, just re-use it */
641 if ( relative_path[0] == '/' )
642 return strdup ( relative_path );
643
644 /* Create modifiable copy of path for dirname() */
645 base_copy = strdup ( base_path );
646 if ( ! base_copy )
647 return NULL;
648
649 /* Strip filename portion of base path */
650 base_tmp = dirname ( base_copy );
651
652 /* Process "./" and "../" elements */
653 while ( *relative_path == '.' ) {
654 relative_path++;
655 if ( *relative_path == 0 ) {
656 /* Do nothing */
657 } else if ( *relative_path == '/' ) {
658 relative_path++;
659 } else if ( *relative_path == '.' ) {
660 relative_path++;
661 if ( *relative_path == 0 ) {
662 base_tmp = dirname ( base_tmp );
663 } else if ( *relative_path == '/' ) {
664 base_tmp = dirname ( base_tmp );
665 relative_path++;
666 } else {
667 relative_path -= 2;
668 break;
669 }
670 } else {
671 relative_path--;
672 break;
673 }
674 }
675
676 /* Create and return new path */
677 if ( asprintf ( &resolved, "%s%s%s", base_tmp,
678 ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
679 "" : "/" ), relative_path ) < 0 )
680 resolved = NULL;
681 free ( base_copy );
682 return resolved;
683}
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition asprintf.c:42
char * dirname(char *path)
Return directory name from path.
Definition basename.c:58
char * strdup(const char *src)
Duplicate string.
Definition string.c:394

References asprintf(), dirname(), free, NULL, strdup(), and strlen().

Referenced by efi_local_open_path(), resolve_uri(), and uri_resolve_path_okx().

◆ resolve_uri()

struct uri * resolve_uri ( const struct uri * base_uri,
struct uri * relative_uri )

Resolve base+relative URI.

Parameters
base_uriBase URI, or NULL
relative_uriRelative URI
Return values
resolved_uriResolved URI, or NULL on failure

Takes a base URI (e.g. "http://ipxe.org/kernels/vmlinuz" and a relative URI (e.g. "../initrds/initrd.gz") and produces a new URI (e.g. "http://ipxe.org/initrds/initrd.gz").

Definition at line 696 of file uri.c.

697 {
698 struct uri tmp_uri;
699 char *tmp_epath = NULL;
700 char *tmp_path = NULL;
701 struct uri *new_uri;
702
703 /* If relative URI is absolute, just re-use it */
704 if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
705 return uri_get ( relative_uri );
706
707 /* Mangle URI */
708 memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
709 if ( relative_uri->epath ) {
710 tmp_epath = resolve_path ( ( base_uri->epath ?
711 base_uri->epath : "/" ),
712 relative_uri->epath );
713 if ( ! tmp_epath )
714 goto err_epath;
715 tmp_path = strdup ( tmp_epath );
716 if ( ! tmp_path )
717 goto err_path;
718 uri_decode_inplace ( tmp_path );
719 tmp_uri.epath = tmp_epath;
720 tmp_uri.path = tmp_path;
721 tmp_uri.equery = relative_uri->equery;
722 tmp_uri.efragment = relative_uri->efragment;
723 tmp_uri.params = relative_uri->params;
724 } else if ( relative_uri->equery ) {
725 tmp_uri.equery = relative_uri->equery;
726 tmp_uri.efragment = relative_uri->efragment;
727 tmp_uri.params = relative_uri->params;
728 } else if ( relative_uri->efragment ) {
729 tmp_uri.efragment = relative_uri->efragment;
730 tmp_uri.params = relative_uri->params;
731 } else if ( relative_uri->params ) {
732 tmp_uri.params = relative_uri->params;
733 }
734
735 /* Create demangled URI */
736 new_uri = uri_dup ( &tmp_uri );
737 free ( tmp_path );
738 free ( tmp_epath );
739 return new_uri;
740
741 free ( tmp_path );
742 err_path:
743 free ( tmp_epath );
744 err_epath:
745 return NULL;
746}
struct uri * uri_dup(const struct uri *uri)
Duplicate URI.
Definition uri.c:596
char * resolve_path(const char *base_path, const char *relative_path)
Resolve base+relative path.
Definition uri.c:634
static int uri_is_absolute(const struct uri *uri)
URI is an absolute URI.
Definition uri.h:136
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition uri.h:195

References uri::efragment, uri::epath, uri::equery, free, memcpy(), NULL, uri::params, uri::path, resolve_path(), strdup(), uri_decode_inplace(), uri_dup(), uri_get(), and uri_is_absolute().

Referenced by churi(), cwuri_fetch_uri(), http_redirect(), imgdownload(), uri_resolve_okx(), and xfer_open_uri().

◆ tftp_uri()

struct uri * tftp_uri ( struct sockaddr * sa_server,
const char * filename )
static

Construct TFTP URI from server address and filename.

Parameters
sa_serverServer address
filenameFilename
Return values
uriURI, or NULL on failure

Definition at line 755 of file uri.c.

756 {
757 struct sockaddr_tcpip *st_server =
758 ( ( struct sockaddr_tcpip * ) sa_server );
759 char buf[ 6 /* "65535" + NUL */ ];
760 char *path;
761 struct uri tmp;
762 struct uri *uri = NULL;
763
764 /* Initialise TFTP URI */
765 memset ( &tmp, 0, sizeof ( tmp ) );
766 tmp.scheme = "tftp";
767
768 /* Construct TFTP server address */
769 tmp.host = sock_ntoa ( sa_server );
770 if ( ! tmp.host )
771 goto err_host;
772
773 /* Construct TFTP server port, if applicable */
774 if ( st_server->st_port ) {
775 snprintf ( buf, sizeof ( buf ), "%d",
776 ntohs ( st_server->st_port ) );
777 tmp.port = buf;
778 }
779
780 /* Construct TFTP path */
781 if ( asprintf ( &path, "/%s", filename ) < 0 )
782 goto err_path;
783 tmp.path = path;
784 tmp.epath = path;
785
786 /* Demangle URI */
787 uri = uri_dup ( &tmp );
788 if ( ! uri )
789 goto err_uri;
790
791 err_uri:
792 free ( path );
793 err_path:
794 err_host:
795 return uri;
796}
#define ntohs(value)
Definition byteswap.h:137
void * memset(void *dest, int character, size_t len) __nonnull
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition socket.c:43
TCP/IP socket address.
Definition tcpip.h:76
uint16_t st_port
TCP/IP port.
Definition tcpip.h:82

References asprintf(), free, memset(), ntohs, NULL, uri::path, snprintf(), sock_ntoa(), sockaddr_tcpip::st_port, tmp, and uri_dup().

Referenced by pxe_uri().

◆ pxe_uri()

struct uri * pxe_uri ( struct sockaddr * sa_server,
const char * filename )

Construct URI from server address and filename.

Parameters
sa_serverServer address
filenameFilename
Return values
uriURI, or NULL on failure

PXE TFTP filenames specified via the DHCP next-server field often contain characters such as ':' or '#' which would confuse the generic URI parser. We provide a mechanism for directly constructing a TFTP URI from the next-server and filename.

Definition at line 810 of file uri.c.

810 {
811 struct uri *uri;
812
813 /* Fail if filename is empty */
814 if ( ! ( filename && filename[0] ) )
815 return NULL;
816
817 /* If filename is a hierarchical absolute URI, then use that
818 * URI. (We accept only hierarchical absolute URIs, since PXE
819 * filenames sometimes start with DOS drive letters such as
820 * "C:\", which get misinterpreted as opaque absolute URIs.)
821 */
822 uri = parse_uri ( filename );
823 if ( uri && uri_is_absolute ( uri ) && ( ! uri->opaque ) )
824 return uri;
825 uri_put ( uri );
826
827 /* Otherwise, construct a TFTP URI directly */
828 return tftp_uri ( sa_server, filename );
829}
struct uri * parse_uri(const char *uri_string)
Parse URI.
Definition uri.c:297
static struct uri * tftp_uri(struct sockaddr *sa_server, const char *filename)
Construct TFTP URI from server address and filename.
Definition uri.c:755
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition uri.h:206

References NULL, uri::opaque, parse_uri(), tftp_uri(), uri_is_absolute(), and uri_put().

Referenced by efi_pxe_tftp_open(), fetch_next_server_and_filename(), pxe_tftp_open(), and uri_pxe_okx().