These changes are the raw update to qemu-2.6.
[kvmfornfv.git] / qemu / roms / ipxe / src / core / uri.c
1 /*
2  * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
26 /** @file
27  *
28  * Uniform Resource Identifiers
29  *
30  */
31
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <libgen.h>
36 #include <ctype.h>
37 #include <ipxe/vsprintf.h>
38 #include <ipxe/params.h>
39 #include <ipxe/uri.h>
40
41 /**
42  * Decode URI field (in place)
43  *
44  * @v string            String
45  *
46  * URI decoding can never increase the length of a string; we can
47  * therefore safely decode in place.
48  */
49 static void uri_decode ( char *string ) {
50         char *dest = string;
51         char hexbuf[3];
52         char *hexbuf_end;
53         char c;
54         char decoded;
55         unsigned int skip;
56
57         /* Copy string, decoding escaped characters as necessary */
58         do {
59                 c = *(string++);
60                 if ( c == '%' ) {
61                         snprintf ( hexbuf, sizeof ( hexbuf ), "%s", string );
62                         decoded = strtoul ( hexbuf, &hexbuf_end, 16 );
63                         skip = ( hexbuf_end - hexbuf );
64                         string += skip;
65                         if ( skip )
66                                 c = decoded;
67                 }
68                 *(dest++) = c;
69         } while ( c );
70 }
71
72 /**
73  * Check if character should be escaped within a URI field
74  *
75  * @v c                 Character
76  * @v field             URI field index
77  * @ret escaped         Character should be escaped
78  */
79 static int uri_character_escaped ( char c, unsigned int field ) {
80
81         /* Non-printing characters and whitespace should always be
82          * escaped, since they cannot sensibly be displayed as part of
83          * a coherent URL string.  (This test also catches control
84          * characters such as CR and LF, which could affect the
85          * operation of line-based protocols such as HTTP.)
86          *
87          * We should also escape characters which would alter the
88          * interpretation of the URL if not escaped, i.e. characters
89          * which have significance to the URL parser.  We should not
90          * blindly escape all such characters, because this would lead
91          * to some very strange-looking URLs (e.g. if we were to
92          * always escape '/' as "%2F" even within the URI path).
93          *
94          * We do not need to be perfect.  Our primary role is as a
95          * consumer of URIs rather than a producer; the main situation
96          * in which we produce a URI string is for display to a human
97          * user, who can probably tolerate some variance from the
98          * formal specification.  The only situation in which we
99          * currently produce a URI string to be consumed by a computer
100          * is when constructing an HTTP request URI, which contains
101          * only the path and query fields.
102          *
103          * We can therefore sacrifice some correctness for the sake of
104          * code size.  For example, colons within the URI host should
105          * be escaped unless they form part of an IPv6 literal
106          * address; doing this correctly would require the URI
107          * formatter to be aware of whether or not the URI host
108          * contained an IPv4 address, an IPv6 address, or a host name.
109          * We choose to simplify and never escape colons within the
110          * URI host field: in the event of a pathological hostname
111          * containing colons, this could potentially produce a URI
112          * string which could not be reparsed.
113          *
114          * After excluding non-printing characters, whitespace, and
115          * '%', the full set of characters with significance to the
116          * URL parser is "/#:@?".  We choose for each URI field which
117          * of these require escaping in our use cases.
118          */
119         static const char *escaped[URI_FIELDS] = {
120                 /* Scheme: escape everything */
121                 [URI_SCHEME]    = "/#:@?",
122                 /* Opaque part: escape characters which would affect
123                  * the reparsing of the URI, allowing everything else
124                  * (e.g. ':', which will appear in iSCSI URIs).
125                  */
126                 [URI_OPAQUE]    = "/#",
127                 /* User name: escape everything */
128                 [URI_USER]      = "/#:@?",
129                 /* Password: escape everything */
130                 [URI_PASSWORD]  = "/#:@?",
131                 /* Host name: escape everything except ':', which may
132                  * appear as part of an IPv6 literal address.
133                  */
134                 [URI_HOST]      = "/#@?",
135                 /* Port number: escape everything */
136                 [URI_PORT]      = "/#:@?",
137                 /* Path: escape everything except '/', which usually
138                  * appears within paths.
139                  */
140                 [URI_PATH]      = "#:@?",
141                 /* Query: escape everything except '/', which
142                  * sometimes appears within queries.
143                  */
144                 [URI_QUERY]     = "#:@?",
145                 /* Fragment: escape everything */
146                 [URI_FRAGMENT]  = "/#:@?",
147         };
148
149         return ( /* Always escape non-printing characters and whitespace */
150                  ( ! isprint ( c ) ) || ( c == ' ' ) ||
151                  /* Always escape '%' */
152                  ( c == '%' ) ||
153                  /* Escape field-specific characters */
154                  strchr ( escaped[field], c ) );
155 }
156
157 /**
158  * Encode URI field
159  *
160  * @v uri               URI
161  * @v field             URI field index
162  * @v buf               Buffer to contain encoded string
163  * @v len               Length of buffer
164  * @ret len             Length of encoded string (excluding NUL)
165  */
166 size_t uri_encode ( const char *string, unsigned int field,
167                     char *buf, ssize_t len ) {
168         ssize_t remaining = len;
169         size_t used;
170         char c;
171
172         /* Ensure encoded string is NUL-terminated even if empty */
173         if ( len > 0 )
174                 buf[0] = '\0';
175
176         /* Copy string, escaping as necessary */
177         while ( ( c = *(string++) ) ) {
178                 if ( uri_character_escaped ( c, field ) ) {
179                         used = ssnprintf ( buf, remaining, "%%%02X", c );
180                 } else {
181                         used = ssnprintf ( buf, remaining, "%c", c );
182                 }
183                 buf += used;
184                 remaining -= used;
185         }
186
187         return ( len - remaining );
188 }
189
190 /**
191  * Dump URI for debugging
192  *
193  * @v uri               URI
194  */
195 static void uri_dump ( const struct uri *uri ) {
196
197         if ( ! uri )
198                 return;
199         if ( uri->scheme )
200                 DBGC ( uri, " scheme \"%s\"", uri->scheme );
201         if ( uri->opaque )
202                 DBGC ( uri, " opaque \"%s\"", uri->opaque );
203         if ( uri->user )
204                 DBGC ( uri, " user \"%s\"", uri->user );
205         if ( uri->password )
206                 DBGC ( uri, " password \"%s\"", uri->password );
207         if ( uri->host )
208                 DBGC ( uri, " host \"%s\"", uri->host );
209         if ( uri->port )
210                 DBGC ( uri, " port \"%s\"", uri->port );
211         if ( uri->path )
212                 DBGC ( uri, " path \"%s\"", uri->path );
213         if ( uri->query )
214                 DBGC ( uri, " query \"%s\"", uri->query );
215         if ( uri->fragment )
216                 DBGC ( uri, " fragment \"%s\"", uri->fragment );
217         if ( uri->params )
218                 DBGC ( uri, " params \"%s\"", uri->params->name );
219 }
220
221 /**
222  * Free URI
223  *
224  * @v refcnt            Reference count
225  */
226 static void uri_free ( struct refcnt *refcnt ) {
227         struct uri *uri = container_of ( refcnt, struct uri, refcnt );
228
229         params_put ( uri->params );
230         free ( uri );
231 }
232
233 /**
234  * Parse URI
235  *
236  * @v uri_string        URI as a string
237  * @ret uri             URI
238  *
239  * Splits a URI into its component parts.  The return URI structure is
240  * dynamically allocated and must eventually be freed by calling
241  * uri_put().
242  */
243 struct uri * parse_uri ( const char *uri_string ) {
244         struct uri *uri;
245         struct parameters *params;
246         char *raw;
247         char *tmp;
248         char *path;
249         char *authority;
250         size_t raw_len;
251         unsigned int field;
252
253         /* Allocate space for URI struct and a copy of the string */
254         raw_len = ( strlen ( uri_string ) + 1 /* NUL */ );
255         uri = zalloc ( sizeof ( *uri ) + raw_len );
256         if ( ! uri )
257                 return NULL;
258         ref_init ( &uri->refcnt, uri_free );
259         raw = ( ( ( void * ) uri ) + sizeof ( *uri ) );
260
261         /* Copy in the raw string */
262         memcpy ( raw, uri_string, raw_len );
263
264         /* Identify the parameter list, if present */
265         if ( ( tmp = strstr ( raw, "##params" ) ) ) {
266                 *tmp = '\0';
267                 tmp += 8 /* "##params" */;
268                 params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL );
269                 if ( params ) {
270                         uri->params = claim_parameters ( params );
271                 } else {
272                         /* Ignore non-existent submission blocks */
273                 }
274         }
275
276         /* Chop off the fragment, if it exists */
277         if ( ( tmp = strchr ( raw, '#' ) ) ) {
278                 *(tmp++) = '\0';
279                 uri->fragment = tmp;
280         }
281
282         /* Identify absolute/relative URI */
283         if ( ( tmp = strchr ( raw, ':' ) ) ) {
284                 /* Absolute URI: identify hierarchical/opaque */
285                 uri->scheme = raw;
286                 *(tmp++) = '\0';
287                 if ( *tmp == '/' ) {
288                         /* Absolute URI with hierarchical part */
289                         path = tmp;
290                 } else {
291                         /* Absolute URI with opaque part */
292                         uri->opaque = tmp;
293                         path = NULL;
294                 }
295         } else {
296                 /* Relative URI */
297                 path = raw;
298         }
299
300         /* If we don't have a path (i.e. we have an absolute URI with
301          * an opaque portion, we're already finished processing
302          */
303         if ( ! path )
304                 goto done;
305
306         /* Chop off the query, if it exists */
307         if ( ( tmp = strchr ( path, '?' ) ) ) {
308                 *(tmp++) = '\0';
309                 uri->query = tmp;
310         }
311
312         /* If we have no path remaining, then we're already finished
313          * processing.
314          */
315         if ( ! path[0] )
316                 goto done;
317
318         /* Identify net/absolute/relative path */
319         if ( strncmp ( path, "//", 2 ) == 0 ) {
320                 /* Net path.  If this is terminated by the first '/'
321                  * of an absolute path, then we have no space for a
322                  * terminator after the authority field, so shuffle
323                  * the authority down by one byte, overwriting one of
324                  * the two slashes.
325                  */
326                 authority = ( path + 2 );
327                 if ( ( tmp = strchr ( authority, '/' ) ) ) {
328                         /* Shuffle down */
329                         uri->path = tmp;
330                         memmove ( ( authority - 1 ), authority,
331                                   ( tmp - authority ) );
332                         authority--;
333                         *(--tmp) = '\0';
334                 }
335         } else {
336                 /* Absolute/relative path */
337                 uri->path = path;
338                 authority = NULL;
339         }
340
341         /* If we don't have an authority (i.e. we have a non-net
342          * path), we're already finished processing
343          */
344         if ( ! authority )
345                 goto done;
346
347         /* Split authority into user[:password] and host[:port] portions */
348         if ( ( tmp = strchr ( authority, '@' ) ) ) {
349                 /* Has user[:password] */
350                 *(tmp++) = '\0';
351                 uri->host = tmp;
352                 uri->user = authority;
353                 if ( ( tmp = strchr ( authority, ':' ) ) ) {
354                         /* Has password */
355                         *(tmp++) = '\0';
356                         uri->password = tmp;
357                 }
358         } else {
359                 /* No user:password */
360                 uri->host = authority;
361         }
362
363         /* Split host into host[:port] */
364         if ( ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) &&
365              ( tmp = strrchr ( uri->host, ':' ) ) ) {
366                 *(tmp++) = '\0';
367                 uri->port = tmp;
368         }
369
370         /* Decode fields in-place */
371         for ( field = 0 ; field < URI_FIELDS ; field++ ) {
372                 if ( uri_field ( uri, field ) )
373                         uri_decode ( ( char * ) uri_field ( uri, field ) );
374         }
375
376  done:
377         DBGC ( uri, "URI parsed \"%s\" to", uri_string );
378         uri_dump ( uri );
379         DBGC ( uri, "\n" );
380
381         return uri;
382 }
383
384 /**
385  * Get port from URI
386  *
387  * @v uri               URI, or NULL
388  * @v default_port      Default port to use if none specified in URI
389  * @ret port            Port
390  */
391 unsigned int uri_port ( const struct uri *uri, unsigned int default_port ) {
392
393         if ( ( ! uri ) || ( ! uri->port ) )
394                 return default_port;
395
396         return ( strtoul ( uri->port, NULL, 0 ) );
397 }
398
399 /**
400  * Format URI
401  *
402  * @v uri               URI
403  * @v buf               Buffer to fill with URI string
404  * @v size              Size of buffer
405  * @ret len             Length of URI string
406  */
407 size_t format_uri ( const struct uri *uri, char *buf, size_t len ) {
408         static const char prefixes[URI_FIELDS] = {
409                 [URI_OPAQUE] = ':',
410                 [URI_PASSWORD] = ':',
411                 [URI_PORT] = ':',
412                 [URI_PATH] = '/',
413                 [URI_QUERY] = '?',
414                 [URI_FRAGMENT] = '#',
415         };
416         char prefix;
417         size_t used = 0;
418         unsigned int field;
419
420         /* Ensure buffer is NUL-terminated */
421         if ( len )
422                 buf[0] = '\0';
423
424         /* Special-case NULL URI */
425         if ( ! uri )
426                 return 0;
427
428         /* Generate fields */
429         for ( field = 0 ; field < URI_FIELDS ; field++ ) {
430
431                 /* Skip non-existent fields */
432                 if ( ! uri_field ( uri, field ) )
433                         continue;
434
435                 /* Prefix this field, if applicable */
436                 prefix = prefixes[field];
437                 if ( ( field == URI_HOST ) && ( uri->user != NULL ) )
438                         prefix = '@';
439                 if ( ( field == URI_PATH ) && ( uri->path[0] == '/' ) )
440                         prefix = '\0';
441                 if ( prefix ) {
442                         used += ssnprintf ( ( buf + used ), ( len - used ),
443                                             "%c", prefix );
444                 }
445
446                 /* Encode this field */
447                 used += uri_encode ( uri_field ( uri, field ), field,
448                                      ( buf + used ), ( len - used ) );
449
450                 /* Suffix this field, if applicable */
451                 if ( ( field == URI_SCHEME ) && ( ! uri->opaque ) ) {
452                         used += ssnprintf ( ( buf + used ), ( len - used ),
453                                             "://" );
454                 }
455         }
456
457         if ( len ) {
458                 DBGC ( uri, "URI formatted" );
459                 uri_dump ( uri );
460                 DBGC ( uri, " to \"%s%s\"\n", buf,
461                        ( ( used > len ) ? "<TRUNCATED>" : "" ) );
462         }
463
464         return used;
465 }
466
467 /**
468  * Format URI
469  *
470  * @v uri               URI
471  * @ret string          URI string, or NULL on failure
472  *
473  * The caller is responsible for eventually freeing the allocated
474  * memory.
475  */
476 char * format_uri_alloc ( const struct uri *uri ) {
477         size_t len;
478         char *string;
479
480         len = ( format_uri ( uri, NULL, 0 ) + 1 /* NUL */ );
481         string = malloc ( len );
482         if ( string )
483                 format_uri ( uri, string, len );
484         return string;
485 }
486
487 /**
488  * Copy URI fields
489  *
490  * @v src               Source URI
491  * @v dest              Destination URI, or NULL to calculate length
492  * @ret len             Length of raw URI
493  */
494 static size_t uri_copy_fields ( const struct uri *src, struct uri *dest ) {
495         size_t len = sizeof ( *dest );
496         char *out = ( ( void * ) dest + len );
497         unsigned int field;
498         size_t field_len;
499
500         /* Copy existent fields */
501         for ( field = 0 ; field < URI_FIELDS ; field++ ) {
502
503                 /* Skip non-existent fields */
504                 if ( ! uri_field ( src, field ) )
505                         continue;
506
507                 /* Calculate field length */
508                 field_len = ( strlen ( uri_field ( src, field ) )
509                               + 1 /* NUL */ );
510                 len += field_len;
511
512                 /* Copy field, if applicable */
513                 if ( dest ) {
514                         memcpy ( out, uri_field ( src, field ), field_len );
515                         uri_field ( dest, field ) = out;
516                         out += field_len;
517                 }
518         }
519         return len;
520 }
521
522 /**
523  * Duplicate URI
524  *
525  * @v uri               URI
526  * @ret uri             Duplicate URI
527  *
528  * Creates a modifiable copy of a URI.
529  */
530 struct uri * uri_dup ( const struct uri *uri ) {
531         struct uri *dup;
532         size_t len;
533
534         /* Allocate new URI */
535         len = uri_copy_fields ( uri, NULL );
536         dup = zalloc ( len );
537         if ( ! dup )
538                 return NULL;
539         ref_init ( &dup->refcnt, uri_free );
540
541         /* Copy fields */
542         uri_copy_fields ( uri, dup );
543
544         /* Copy parameters */
545         dup->params = params_get ( uri->params );
546
547         DBGC ( uri, "URI duplicated" );
548         uri_dump ( uri );
549         DBGC ( uri, "\n" );
550
551         return dup;
552 }
553
554 /**
555  * Resolve base+relative path
556  *
557  * @v base_uri          Base path
558  * @v relative_uri      Relative path
559  * @ret resolved_uri    Resolved path
560  *
561  * Takes a base path (e.g. "/var/lib/tftpboot/vmlinuz" and a relative
562  * path (e.g. "initrd.gz") and produces a new path
563  * (e.g. "/var/lib/tftpboot/initrd.gz").  Note that any non-directory
564  * portion of the base path will automatically be stripped; this
565  * matches the semantics used when resolving the path component of
566  * URIs.
567  */
568 char * resolve_path ( const char *base_path,
569                       const char *relative_path ) {
570         size_t base_len = ( strlen ( base_path ) + 1 );
571         char base_path_copy[base_len];
572         char *base_tmp = base_path_copy;
573         char *resolved;
574
575         /* If relative path is absolute, just re-use it */
576         if ( relative_path[0] == '/' )
577                 return strdup ( relative_path );
578
579         /* Create modifiable copy of path for dirname() */
580         memcpy ( base_tmp, base_path, base_len );
581         base_tmp = dirname ( base_tmp );
582
583         /* Process "./" and "../" elements */
584         while ( *relative_path == '.' ) {
585                 relative_path++;
586                 if ( *relative_path == 0 ) {
587                         /* Do nothing */
588                 } else if ( *relative_path == '/' ) {
589                         relative_path++;
590                 } else if ( *relative_path == '.' ) {
591                         relative_path++;
592                         if ( *relative_path == 0 ) {
593                                 base_tmp = dirname ( base_tmp );
594                         } else if ( *relative_path == '/' ) {
595                                 base_tmp = dirname ( base_tmp );
596                                 relative_path++;
597                         } else {
598                                 relative_path -= 2;
599                                 break;
600                         }
601                 } else {
602                         relative_path--;
603                         break;
604                 }
605         }
606
607         /* Create and return new path */
608         if ( asprintf ( &resolved, "%s%s%s", base_tmp,
609                         ( ( base_tmp[ strlen ( base_tmp ) - 1 ] == '/' ) ?
610                           "" : "/" ), relative_path ) < 0 )
611                 return NULL;
612
613         return resolved;
614 }
615
616 /**
617  * Resolve base+relative URI
618  *
619  * @v base_uri          Base URI, or NULL
620  * @v relative_uri      Relative URI
621  * @ret resolved_uri    Resolved URI
622  *
623  * Takes a base URI (e.g. "http://ipxe.org/kernels/vmlinuz" and a
624  * relative URI (e.g. "../initrds/initrd.gz") and produces a new URI
625  * (e.g. "http://ipxe.org/initrds/initrd.gz").
626  */
627 struct uri * resolve_uri ( const struct uri *base_uri,
628                            struct uri *relative_uri ) {
629         struct uri tmp_uri;
630         char *tmp_path = NULL;
631         struct uri *new_uri;
632
633         /* If relative URI is absolute, just re-use it */
634         if ( uri_is_absolute ( relative_uri ) || ( ! base_uri ) )
635                 return uri_get ( relative_uri );
636
637         /* Mangle URI */
638         memcpy ( &tmp_uri, base_uri, sizeof ( tmp_uri ) );
639         if ( relative_uri->path ) {
640                 tmp_path = resolve_path ( ( base_uri->path ?
641                                             base_uri->path : "/" ),
642                                           relative_uri->path );
643                 tmp_uri.path = tmp_path;
644                 tmp_uri.query = relative_uri->query;
645                 tmp_uri.fragment = relative_uri->fragment;
646                 tmp_uri.params = relative_uri->params;
647         } else if ( relative_uri->query ) {
648                 tmp_uri.query = relative_uri->query;
649                 tmp_uri.fragment = relative_uri->fragment;
650                 tmp_uri.params = relative_uri->params;
651         } else if ( relative_uri->fragment ) {
652                 tmp_uri.fragment = relative_uri->fragment;
653                 tmp_uri.params = relative_uri->params;
654         } else if ( relative_uri->params ) {
655                 tmp_uri.params = relative_uri->params;
656         }
657
658         /* Create demangled URI */
659         new_uri = uri_dup ( &tmp_uri );
660         free ( tmp_path );
661         return new_uri;
662 }
663
664 /**
665  * Construct TFTP URI from next-server and filename
666  *
667  * @v next_server       Next-server address
668  * @v port              Port number, or zero to use the default port
669  * @v filename          Filename
670  * @ret uri             URI, or NULL on failure
671  *
672  * TFTP filenames specified via the DHCP next-server field often
673  * contain characters such as ':' or '#' which would confuse the
674  * generic URI parser.  We provide a mechanism for directly
675  * constructing a TFTP URI from the next-server and filename.
676  */
677 struct uri * tftp_uri ( struct in_addr next_server, unsigned int port,
678                         const char *filename ) {
679         char buf[ 6 /* "65535" + NUL */ ];
680         struct uri uri;
681
682         memset ( &uri, 0, sizeof ( uri ) );
683         uri.scheme = "tftp";
684         uri.host = inet_ntoa ( next_server );
685         if ( port ) {
686                 snprintf ( buf, sizeof ( buf ), "%d", port );
687                 uri.port = buf;
688         }
689         uri.path = filename;
690         return uri_dup ( &uri );
691 }