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

Detailed Description

Uniform Resource Identifiers.

Definition in file uri.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ 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 53 of file uri.c.

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

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

Referenced by parse_uristring_setting(), and uri_decode_inplace().

◆ uri_decode_inplace()

static void uri_decode_inplace ( struct uri uri,
unsigned int  field 
)
static

Decode URI field in-place.

Parameters
uriURI
fieldURI field index

Definition at line 85 of file uri.c.

85  {
86  const char *encoded = uri_field ( uri, field );
87  char *decoded = ( ( char * ) encoded );
88  size_t len;
89 
90  /* Do nothing if field is not present */
91  if ( ! encoded )
92  return;
93 
94  /* Decode field in place */
95  len = uri_decode ( encoded, decoded, strlen ( encoded ) );
96 
97  /* Terminate decoded string */
98  decoded[len] = '\0';
99 }
size_t uri_decode(const char *encoded, void *buf, size_t len)
Decode URI field.
Definition: uri.c:53
size_t strlen(const char *src)
Get length of string.
Definition: string.c:228
uint32_t len
Length.
Definition: ena.h:14
#define uri_field(uri, field)
Access URI field.
Definition: uri.h:82
A Uniform Resource Identifier.
Definition: uri.h:50

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

Referenced by parse_uri().

◆ uri_character_escaped()

static 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 108 of file uri.c.

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

References c, isprint(), strchr(), URI_FIELDS, URI_FRAGMENT, URI_HOST, URI_OPAQUE, URI_PASSWORD, URI_PATH, URI_PORT, URI_QUERY, 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 }
uint32_t c
Definition: md4.c:30
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition: vsprintf.c:420
static size_t raw_len
Definition: base16.h:50
static int uri_character_escaped(char c, unsigned int field)
Check if character should be escaped within a URI field.
Definition: uri.c:108
unsigned char uint8_t
Definition: stdint.h:10
uint32_t len
Length.
Definition: ena.h:14
__be32 raw[7]
Definition: CIB_PRM.h:28
signed long ssize_t
Definition: stdint.h:7

References c, 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
size_t strlen(const char *src)
Get length of string.
Definition: string.c:228
uint32_t len
Length.
Definition: ena.h:14

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

Referenced by format_uri(), and http_params().

◆ uri_dump()

static 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->query )
266  DBGC ( uri, " query \"%s\"", uri->query );
267  if ( uri->fragment )
268  DBGC ( uri, " fragment \"%s\"", uri->fragment );
269  if ( uri->params )
270  DBGC ( uri, " params \"%s\"", uri->params->name );
271 }
#define DBGC(...)
Definition: compiler.h:505
const char * port
Port number.
Definition: uri.h:64
const char * scheme
Scheme.
Definition: uri.h:54
const char * path
Path.
Definition: uri.h:66
struct parameters * params
Form parameters.
Definition: uri.h:72
const char * name
Name.
Definition: params.h:22
const char * host
Host name.
Definition: uri.h:62
const char * query
Query.
Definition: uri.h:68
const char * opaque
Opaque part.
Definition: uri.h:56
const char * fragment
Fragment.
Definition: uri.h:70
const char * password
Password.
Definition: uri.h:60
const char * user
User name.
Definition: uri.h:58
A Uniform Resource Identifier.
Definition: uri.h:50

References DBGC, uri::fragment, uri::host, parameters::name, uri::opaque, uri::params, uri::password, uri::path, uri::port, uri::query, uri::scheme, and uri::user.

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

◆ uri_free()

static void uri_free ( struct refcnt refcnt)
static

Free URI.

Parameters
refcntReference count

Definition at line 278 of file uri.c.

278  {
279  struct uri *uri = container_of ( refcnt, struct uri, refcnt );
280 
281  params_put ( uri->params );
282  free ( uri );
283 }
A reference counter.
Definition: refcnt.h:26
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
struct parameters * params
Form parameters.
Definition: uri.h:72
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
A Uniform Resource Identifier.
Definition: uri.h:50

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 295 of file uri.c.

295  {
296  struct uri *uri;
297  struct parameters *params;
298  char *raw;
299  char *tmp;
300  char *path;
301  char *authority;
302  size_t raw_len;
303  unsigned int field;
304 
305  /* Allocate space for URI struct and a copy of the string */
306  raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
307  uri = zalloc ( sizeof ( *uri ) + raw_len );
308  if ( ! uri )
309  return NULL;
310  ref_init ( &uri->refcnt, uri_free );
311  raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );
312 
313  /* Copy in the raw string */
314  memcpy ( raw, uri_string, raw_len );
315 
316  /* Identify the parameter list, if present */
317  if ( ( tmp = strstr ( raw, "##params" ) ) ) {
318  *tmp = '\0';
319  tmp += 8 /* "##params" */;
320  params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL );
321  if ( params ) {
322  uri->params = claim_parameters ( params );
323  } else {
324  /* Ignore non-existent submission blocks */
325  }
326  }
327 
328  /* Chop off the fragment, if it exists */
329  if ( ( tmp = strchr ( raw, '#' ) ) ) {
330  *(tmp++) = '\0';
331  uri->fragment = tmp;
332  }
333 
334  /* Identify absolute/relative URI */
335  if ( ( tmp = strchr ( raw, ':' ) ) ) {
336  /* Absolute URI: identify hierarchical/opaque */
337  uri->scheme = raw;
338  *(tmp++) = '\0';
339  if ( *tmp == '/' ) {
340  /* Absolute URI with hierarchical part */
341  path = tmp;
342  } else {
343  /* Absolute URI with opaque part */
344  uri->opaque = tmp;
345  path = NULL;
346  }
347  } else {
348  /* Relative URI */
349  path = raw;
350  }
351 
352  /* If we don't have a path (i.e. we have an absolute URI with
353  * an opaque portion, we're already finished processing
354  */
355  if ( ! path )
356  goto done;
357 
358  /* Chop off the query, if it exists */
359  if ( ( tmp = strchr ( path, '?' ) ) ) {
360  *(tmp++) = '\0';
361  uri->query = tmp;
362  }
363 
364  /* If we have no path remaining, then we're already finished
365  * processing.
366  */
367  if ( ! path[0] )
368  goto done;
369 
370  /* Identify net/absolute/relative path */
371  if ( uri->scheme && ( strncmp ( path, "//", 2 ) == 0 ) ) {
372  /* Net path. If this is terminated by the first '/'
373  * of an absolute path, then we have no space for a
374  * terminator after the authority field, so shuffle
375  * the authority down by one byte, overwriting one of
376  * the two slashes.
377  */
378  authority = ( path + 2 );
379  if ( ( tmp = strchr ( authority, '/' ) ) ) {
380  /* Shuffle down */
381  uri->path = tmp;
382  memmove ( ( authority - 1 ), authority,
383  ( tmp - authority ) );
384  authority--;
385  *(--tmp) = '\0';
386  }
387  } else {
388  /* Absolute/relative path */
389  uri->path = path;
390  authority = NULL;
391  }
392 
393  /* If we don't have an authority (i.e. we have a non-net
394  * path), we're already finished processing
395  */
396  if ( ! authority )
397  goto done;
398 
399  /* Split authority into user[:password] and host[:port] portions */
400  if ( ( tmp = strchr ( authority, '@' ) ) ) {
401  /* Has user[:password] */
402  *(tmp++) = '\0';
403  uri->host = tmp;
404  uri->user = authority;
405  if ( ( tmp = strchr ( authority, ':' ) ) ) {
406  /* Has password */
407  *(tmp++) = '\0';
408  uri->password = tmp;
409  }
410  } else {
411  /* No user:password */
412  uri->host = authority;
413  }
414 
415  /* Split host into host[:port] */
416  if ( ( tmp = strrchr ( uri->host, ':' ) ) &&
417  ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) ) {
418  *(tmp++) = '\0';
419  uri->port = tmp;
420  }
421 
422  done:
423  /* Decode fields in-place */
424  for ( field = 0 ; field < URI_FIELDS ; field++ )
425  uri_decode_inplace ( uri, field );
426 
427  DBGC ( uri, "URI parsed \"%s\" to", uri_string );
428  uri_dump ( uri );
429  DBGC ( uri, "\n" );
430 
431  return uri;
432 }
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition: uri.c:247
char * strrchr(const char *src, int character)
Find rightmost character within a string.
Definition: string.c:274
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
A form parameter list.
Definition: params.h:16
#define DBGC(...)
Definition: compiler.h:505
struct parameters * find_parameters(const char *name)
Find form parameter list by name.
Definition: params.c:68
int strncmp(const char *first, const char *second, size_t max)
Compare strings.
Definition: string.c:185
const char * port
Port number.
Definition: uri.h:64
char * strstr(const char *haystack, const char *needle)
Find substring.
Definition: string.c:294
const char * scheme
Scheme.
Definition: uri.h:54
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * path
Path.
Definition: uri.h:66
struct parameters * params
Form parameters.
Definition: uri.h:72
static size_t raw_len
Definition: base16.h:50
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
char * strchr(const char *src, int character)
Find character within a string.
Definition: string.c:256
uint8_t * tmp
Definition: entropy.h:156
size_t strlen(const char *src)
Get length of string.
Definition: string.c:228
const char * host
Host name.
Definition: uri.h:62
void * memmove(void *dest, const void *src, size_t len) __nonnull
static void uri_decode_inplace(struct uri *uri, unsigned int field)
Decode URI field in-place.
Definition: uri.c:85
const char * query
Query.
Definition: uri.h:68
const char * opaque
Opaque part.
Definition: uri.h:56
const char * fragment
Fragment.
Definition: uri.h:70
struct refcnt refcnt
Reference count.
Definition: uri.h:52
static void uri_free(struct refcnt *refcnt)
Free URI.
Definition: uri.c:278
const char * password
Password.
Definition: uri.h:60
__be32 raw[7]
Definition: CIB_PRM.h:28
const char * user
User name.
Definition: uri.h:58
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct bofm_section_header done
Definition: bofm_test.c:46

References DBGC, done, find_parameters(), uri::fragment, uri::host, memcpy(), memmove(), NULL, uri::opaque, uri::params, uri::password, uri::path, uri::port, uri::query, raw, raw_len, ref_init, uri::refcnt, uri::scheme, strchr(), strlen(), strncmp(), strrchr(), strstr(), tmp, uri_decode_inplace(), uri_dump(), URI_FIELDS, uri_free(), uri::user, and zalloc().

Referenced by 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 441 of file uri.c.

441  {
442 
443  if ( ( ! uri ) || ( ! uri->port ) )
444  return default_port;
445 
446  return ( strtoul ( uri->port, NULL, 0 ) );
447 }
unsigned long strtoul(const char *string, char **endp, int base)
Convert string to numeric value.
Definition: string.c:456
const char * port
Port number.
Definition: uri.h:64
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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 457 of file uri.c.

457  {
458  static const char prefixes[URI_FIELDS] = {
459  [URI_PASSWORD] = ':',
460  [URI_PORT] = ':',
461  [URI_QUERY] = '?',
462  [URI_FRAGMENT] = '#',
463  };
464  char prefix;
465  size_t used = 0;
466  unsigned int field;
467 
468  /* Ensure buffer is NUL-terminated */
469  if ( len )
470  buf[0] = '\0';
471 
472  /* Special-case NULL URI */
473  if ( ! uri )
474  return 0;
475 
476  /* Generate fields */
477  for ( field = 0 ; field < URI_FIELDS ; field++ ) {
478 
479  /* Skip non-existent fields */
480  if ( ! uri_field ( uri, field ) )
481  continue;
482 
483  /* Prefix this field, if applicable */
484  prefix = prefixes[field];
485  if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
486  prefix = '@';
487  if ( prefix ) {
488  used += ssnprintf ( ( buf + used ), ( len - used ),
489  "%c", prefix );
490  }
491 
492  /* Encode this field */
493  used += uri_encode_string ( field, uri_field ( uri, field ),
494  ( buf + used ), ( len - used ) );
495 
496  /* Suffix this field, if applicable */
497  if ( field == URI_SCHEME ) {
498  used += ssnprintf ( ( buf + used ), ( len - used ),
499  ":%s", ( uri->host ? "//" : "" ) );
500  }
501  }
502 
503  if ( len ) {
504  DBGC ( uri, "URI formatted" );
505  uri_dump ( uri );
506  DBGC ( uri, " to \"%s%s\"\n", buf,
507  ( ( used > len ) ? "<TRUNCATED>" : "" ) );
508  }
509 
510  return used;
511 }
Definition: uri.h:100
Definition: uri.h:96
size_t uri_encode_string(unsigned int field, const char *string, char *buf, ssize_t len)
Encode URI field string.
Definition: uri.c:236
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition: uri.c:247
#define DBGC(...)
Definition: compiler.h:505
char prefix[4]
Definition: vmconsole.c:53
Definition: uri.h:101
int ssnprintf(char *buf, ssize_t ssize, const char *fmt,...)
Version of vsnprintf() that accepts a signed buffer size.
Definition: vsprintf.c:420
const char * host
Host name.
Definition: uri.h:62
Definition: uri.h:103
uint32_t len
Length.
Definition: ena.h:14
#define uri_field(uri, field)
Access URI field.
Definition: uri.h:82
const char * user
User name.
Definition: uri.h:58
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References DBGC, uri::host, len, NULL, prefix, ssnprintf(), uri_dump(), uri_encode_string(), uri_field, URI_FIELDS, URI_FRAGMENT, URI_HOST, URI_PASSWORD, URI_PORT, URI_QUERY, URI_SCHEME, and uri::user.

Referenced by efi_block_hook(), 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 522 of file uri.c.

522  {
523  size_t len;
524  char *string;
525 
526  len = ( format_uri ( uri, NULL, 0 ) + 1 /* NUL */ );
527  string = malloc ( len );
528  if ( string )
529  format_uri ( uri, string, len );
530  return string;
531 }
uint32_t string
Definition: multiboot.h:14
size_t format_uri(const struct uri *uri, char *buf, size_t len)
Format URI.
Definition: uri.c:457
void * malloc(size_t size)
Allocate memory.
Definition: malloc.c:583
uint32_t len
Length.
Definition: ena.h:14
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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

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

◆ uri_copy_fields()

static 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 540 of file uri.c.

540  {
541  size_t len = sizeof ( *dest );
542  char *out = ( ( void * ) dest + len );
543  unsigned int field;
544  size_t field_len;
545 
546  /* Copy existent fields */
547  for ( field = 0 ; field < URI_FIELDS ; field++ ) {
548 
549  /* Skip non-existent fields */
550  if ( ! uri_field ( src, field ) )
551  continue;
552 
553  /* Calculate field length */
554  field_len = ( strlen ( uri_field ( src, field ) )
555  + 1 /* NUL */ );
556  len += field_len;
557 
558  /* Copy field, if applicable */
559  if ( dest ) {
560  memcpy ( out, uri_field ( src, field ), field_len );
561  uri_field ( dest, field ) = out;
562  out += field_len;
563  }
564  }
565  return len;
566 }
void * memcpy(void *dest, const void *src, size_t len) __nonnull
__be32 out[4]
Definition: CIB_PRM.h:36
static void * dest
Definition: strings.h:176
static __always_inline void off_t userptr_t src
Definition: efi_uaccess.h:66
size_t strlen(const char *src)
Get length of string.
Definition: string.c:228
uint32_t len
Length.
Definition: ena.h:14
#define uri_field(uri, field)
Access URI field.
Definition: uri.h:82

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 576 of file uri.c.

576  {
577  struct uri *dup;
578  size_t len;
579 
580  /* Allocate new URI */
581  len = uri_copy_fields ( uri, NULL );
582  dup = zalloc ( len );
583  if ( ! dup )
584  return NULL;
585  ref_init ( &dup->refcnt, uri_free );
586 
587  /* Copy fields */
588  uri_copy_fields ( uri, dup );
589 
590  /* Copy parameters */
591  dup->params = params_get ( uri->params );
592 
593  DBGC ( uri, "URI duplicated" );
594  uri_dump ( uri );
595  DBGC ( uri, "\n" );
596 
597  return dup;
598 }
static void uri_dump(const struct uri *uri)
Dump URI for debugging.
Definition: uri.c:247
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
#define DBGC(...)
Definition: compiler.h:505
static size_t uri_copy_fields(const struct uri *src, struct uri *dest)
Copy URI fields.
Definition: uri.c:540
struct parameters * params
Form parameters.
Definition: uri.h:72
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
uint32_t len
Length.
Definition: ena.h:14
struct refcnt refcnt
Reference count.
Definition: uri.h:52
static void uri_free(struct refcnt *refcnt)
Free URI.
Definition: uri.c:278
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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 614 of file uri.c.

615  {
616  char *base_copy;
617  char *base_tmp;
618  char *resolved;
619 
620  /* If relative path is absolute, just re-use it */
621  if ( relative_path[0] == '/' )
622  return strdup ( relative_path );
623 
624  /* Create modifiable copy of path for dirname() */
625  base_copy = strdup ( base_path );
626  if ( ! base_copy )
627  return NULL;
628 
629  /* Strip filename portion of base path */
630  base_tmp = dirname ( base_copy );
631 
632  /* Process "./" and "../" elements */
633  while ( *relative_path == '.' ) {
634  relative_path++;
635  if ( *relative_path == 0 ) {
636  /* Do nothing */
637  } else if ( *relative_path == '/' ) {
638  relative_path++;
639  } else if ( *relative_path == '.' ) {
640  relative_path++;
641  if ( *relative_path == 0 ) {
642  base_tmp = dirname ( base_tmp );
643  } else if ( *relative_path == '/' ) {
644  base_tmp = dirname ( base_tmp );
645  relative_path++;
646  } else {
647  relative_path -= 2;
648  break;
649  }
650  } else {
651  relative_path--;
652  break;
653  }
654  }
655 
656  /* Create and return new path */
657  if ( asprintf ( &resolved, "%s%s%s", base_tmp,
658  ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
659  "" : "/" ), relative_path ) < 0 )
660  resolved = NULL;
661  free ( base_copy );
662  return resolved;
663 }
char * dirname(char *path)
Return directory name from path.
Definition: basename.c:57
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:41
char * strdup(const char *src)
Duplicate string.
Definition: string.c:365
size_t strlen(const char *src)
Get length of string.
Definition: string.c:228
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

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 676 of file uri.c.

677  {
678  struct uri tmp_uri;
679  char *tmp_path = NULL;
680  struct uri *new_uri;
681 
682  /* If relative URI is absolute, just re-use it */
683  if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
684  return uri_get ( relative_uri );
685 
686  /* Mangle URI */
687  memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
688  if ( relative_uri->path ) {
689  tmp_path = resolve_path ( ( base_uri->path ?
690  base_uri->path : "/" ),
691  relative_uri->path );
692  tmp_uri.path = tmp_path;
693  tmp_uri.query = relative_uri->query;
694  tmp_uri.fragment = relative_uri->fragment;
695  tmp_uri.params = relative_uri->params;
696  } else if ( relative_uri->query ) {
697  tmp_uri.query = relative_uri->query;
698  tmp_uri.fragment = relative_uri->fragment;
699  tmp_uri.params = relative_uri->params;
700  } else if ( relative_uri->fragment ) {
701  tmp_uri.fragment = relative_uri->fragment;
702  tmp_uri.params = relative_uri->params;
703  } else if ( relative_uri->params ) {
704  tmp_uri.params = relative_uri->params;
705  }
706 
707  /* Create demangled URI */
708  new_uri = uri_dup ( &tmp_uri );
709  free ( tmp_path );
710  return new_uri;
711 }
static struct uri * uri_get(struct uri *uri)
Increment URI reference count.
Definition: uri.h:177
static int uri_is_absolute(const struct uri *uri)
URI is an absolute URI.
Definition: uri.h:118
void * memcpy(void *dest, const void *src, size_t len) __nonnull
const char * path
Path.
Definition: uri.h:66
char * resolve_path(const char *base_path, const char *relative_path)
Resolve base+relative path.
Definition: uri.c:614
struct parameters * params
Form parameters.
Definition: uri.h:72
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
struct uri * uri_dup(const struct uri *uri)
Duplicate URI.
Definition: uri.c:576
const char * query
Query.
Definition: uri.h:68
const char * fragment
Fragment.
Definition: uri.h:70
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References uri::fragment, free, memcpy(), NULL, uri::params, uri::path, uri::query, resolve_path(), uri_dup(), uri_get(), and uri_is_absolute().

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

◆ tftp_uri()

static 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 720 of file uri.c.

721  {
722  struct sockaddr_tcpip *st_server =
723  ( ( struct sockaddr_tcpip * ) sa_server );
724  char buf[ 6 /* "65535" + NUL */ ];
725  char *path;
726  struct uri tmp;
727  struct uri *uri = NULL;
728 
729  /* Initialise TFTP URI */
730  memset ( &tmp, 0, sizeof ( tmp ) );
731  tmp.scheme = "tftp";
732 
733  /* Construct TFTP server address */
734  tmp.host = sock_ntoa ( sa_server );
735  if ( ! tmp.host )
736  goto err_host;
737 
738  /* Construct TFTP server port, if applicable */
739  if ( st_server->st_port ) {
740  snprintf ( buf, sizeof ( buf ), "%d",
741  ntohs ( st_server->st_port ) );
742  tmp.port = buf;
743  }
744 
745  /* Construct TFTP path */
746  if ( asprintf ( &path, "/%s", filename ) < 0 )
747  goto err_path;
748  tmp.path = path;
749 
750  /* Demangle URI */
751  uri = uri_dup ( &tmp );
752  if ( ! uri )
753  goto err_uri;
754 
755  err_uri:
756  free ( path );
757  err_path:
758  err_host:
759  return uri;
760 }
TCP/IP socket address.
Definition: tcpip.h:75
#define ntohs(value)
Definition: byteswap.h:136
const char * path
Path.
Definition: uri.h:66
uint16_t st_port
TCP/IP port.
Definition: tcpip.h:81
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
int asprintf(char **strp, const char *fmt,...)
Write a formatted string to newly allocated memory.
Definition: asprintf.c:41
struct uri * uri_dup(const struct uri *uri)
Duplicate URI.
Definition: uri.c:576
uint8_t * tmp
Definition: entropy.h:156
const char * sock_ntoa(struct sockaddr *sa)
Transcribe socket address.
Definition: socket.c:42
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition: vsprintf.c:382
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
void * memset(void *dest, int character, size_t len) __nonnull

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 774 of file uri.c.

774  {
775  struct uri *uri;
776 
777  /* Fail if filename is empty */
778  if ( ! ( filename && filename[0] ) )
779  return NULL;
780 
781  /* If filename is a hierarchical absolute URI, then use that
782  * URI. (We accept only hierarchical absolute URIs, since PXE
783  * filenames sometimes start with DOS drive letters such as
784  * "C:\", which get misinterpreted as opaque absolute URIs.)
785  */
786  uri = parse_uri ( filename );
787  if ( uri && uri_is_absolute ( uri ) && ( ! uri->opaque ) )
788  return uri;
789  uri_put ( uri );
790 
791  /* Otherwise, construct a TFTP URI directly */
792  return tftp_uri ( sa_server, filename );
793 }
static void uri_put(struct uri *uri)
Decrement URI reference count.
Definition: uri.h:188
static int uri_is_absolute(const struct uri *uri)
URI is an absolute URI.
Definition: uri.h:118
static struct uri * tftp_uri(struct sockaddr *sa_server, const char *filename)
Construct TFTP URI from server address and filename.
Definition: uri.c:720
const char * opaque
Opaque part.
Definition: uri.h:56
A Uniform Resource Identifier.
Definition: uri.h:50
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
struct uri * parse_uri(const char *uri_string)
Parse URI.
Definition: uri.c:295

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().