• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _GPXE_URI_H
2 #define _GPXE_URI_H
3 
4 /** @file
5  *
6  * Uniform Resource Identifiers
7  *
8  */
9 
10 FILE_LICENCE ( GPL2_OR_LATER );
11 
12 #include <stddef.h>
13 #include <stdlib.h>
14 #include <gpxe/refcnt.h>
15 
16 /** A Uniform Resource Identifier
17  *
18  * Terminology for this data structure is as per uri(7), except that
19  * "path" is defined to include the leading '/' for an absolute path.
20  *
21  * Note that all fields within a URI are optional and may be NULL.
22  *
23  * The pointers to the various fields are packed together so they can
24  * be accessed in array fashion in some places in uri.c where doing so
25  * saves significant code size.
26  *
27  * Some examples are probably helpful:
28  *
29  *   http://www.etherboot.org/wiki :
30  *
31  *   scheme = "http", host = "www.etherboot.org", path = "/wiki"
32  *
33  *   /var/lib/tftpboot :
34  *
35  *   path = "/var/lib/tftpboot"
36  *
37  *   mailto:bob@nowhere.com :
38  *
39  *   scheme = "mailto", opaque = "bob@nowhere.com"
40  *
41  *   ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this
42  *
43  *   scheme = "ftp", user = "joe", password = "secret",
44  *   host = "insecure.org", port = "8081", path = "/hidden/path/to",
45  *   query = "what=is", fragment = "this"
46  */
47 struct uri {
48 	/** Reference count */
49 	struct refcnt refcnt;
50 	/** Scheme */
51 	const char *scheme;
52 	/** Opaque part */
53 	const char *opaque;
54 	/** User name */
55 	const char *user;
56 	/** Password */
57 	const char *password;
58 	/** Host name */
59 	const char *host;
60 	/** Port number */
61 	const char *port;
62 	/** Path */
63 	const char *path;
64 	/** Query */
65 	const char *query;
66 	/** Fragment */
67 	const char *fragment;
68 } __attribute__ (( packed ));
69 
70 /** A field in a URI
71  *
72  * The order of the indices in this enumeration must match the order
73  * of the fields in the URI structure.
74  */
75 enum {
76 	URI_SCHEME = 0,		URI_SCHEME_BIT = ( 1 << URI_SCHEME ),
77 	URI_OPAQUE = 1,		URI_OPAQUE_BIT = ( 1 << URI_OPAQUE ),
78 	URI_USER = 2,		URI_USER_BIT = ( 1 << URI_USER ),
79 	URI_PASSWORD = 3,	URI_PASSWORD_BIT = ( 1 << URI_PASSWORD ),
80 	URI_HOST = 4,		URI_HOST_BIT = ( 1 << URI_HOST ),
81 	URI_PORT = 5,		URI_PORT_BIT = ( 1 << URI_PORT ),
82 	URI_PATH = 6,		URI_PATH_BIT = ( 1 << URI_PATH ),
83 	URI_QUERY = 7,		URI_QUERY_BIT = ( 1 << URI_QUERY ),
84 	URI_FRAGMENT = 8,	URI_FRAGMENT_BIT = ( 1 << URI_FRAGMENT ),
85 
86 	URI_FIRST_FIELD = URI_SCHEME,
87 	URI_LAST_FIELD = URI_FRAGMENT,
88 };
89 
90 /** Extract field from URI */
91 #define uri_get_field( uri, field )	(&uri->scheme)[field]
92 
93 /** All URI fields */
94 #define URI_ALL		( URI_SCHEME_BIT | URI_OPAQUE_BIT | URI_USER_BIT | \
95 			  URI_PASSWORD_BIT | URI_HOST_BIT | URI_PORT_BIT | \
96 			  URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT )
97 
98 /** URI fields that should be decoded on storage */
99 #define URI_ENCODED	( URI_USER_BIT | URI_PASSWORD_BIT | URI_HOST_BIT | \
100 			  URI_PATH_BIT | URI_QUERY_BIT | URI_FRAGMENT_BIT )
101 
102 /**
103  * URI is an absolute URI
104  *
105  * @v uri			URI
106  * @ret is_absolute		URI is absolute
107  *
108  * An absolute URI begins with a scheme, e.g. "http:" or "mailto:".
109  * Note that this is a separate concept from a URI with an absolute
110  * path.
111  */
uri_is_absolute(struct uri * uri)112 static inline int uri_is_absolute ( struct uri *uri ) {
113 	return ( uri->scheme != NULL );
114 }
115 
116 /**
117  * URI has an absolute path
118  *
119  * @v uri			URI
120  * @ret has_absolute_path	URI has an absolute path
121  *
122  * An absolute path begins with a '/'.  Note that this is a separate
123  * concept from an absolute URI.  Note also that a URI may not have a
124  * path at all.
125  */
uri_has_absolute_path(struct uri * uri)126 static inline int uri_has_absolute_path ( struct uri *uri ) {
127 	return ( uri->path && ( uri->path[0] == '/' ) );
128 }
129 
130 /**
131  * URI has a relative path
132  *
133  * @v uri			URI
134  * @ret has_relative_path	URI has a relative path
135  *
136  * A relative path begins with something other than a '/'.  Note that
137  * this is a separate concept from a relative URI.  Note also that a
138  * URI may not have a path at all.
139  */
uri_has_relative_path(struct uri * uri)140 static inline int uri_has_relative_path ( struct uri *uri ) {
141 	return ( uri->path && ( uri->path[0] != '/' ) );
142 }
143 
144 /**
145  * Increment URI reference count
146  *
147  * @v uri		URI, or NULL
148  * @ret uri		URI as passed in
149  */
150 static inline __attribute__ (( always_inline )) struct uri *
uri_get(struct uri * uri)151 uri_get ( struct uri *uri ) {
152 	ref_get ( &uri->refcnt );
153 	return uri;
154 }
155 
156 /**
157  * Decrement URI reference count
158  *
159  * @v uri		URI, or NULL
160  */
161 static inline __attribute__ (( always_inline )) void
uri_put(struct uri * uri)162 uri_put ( struct uri *uri ) {
163 	ref_put ( &uri->refcnt );
164 }
165 
166 extern struct uri *cwuri;
167 
168 extern struct uri * parse_uri ( const char *uri_string );
169 extern unsigned int uri_port ( struct uri *uri, unsigned int default_port );
170 extern int unparse_uri ( char *buf, size_t size, struct uri *uri,
171 			 unsigned int fields );
172 extern struct uri * uri_dup ( struct uri *uri );
173 extern char * resolve_path ( const char *base_path,
174 			     const char *relative_path );
175 extern struct uri * resolve_uri ( struct uri *base_uri,
176 				  struct uri *relative_uri );
177 extern void churi ( struct uri *uri );
178 extern size_t uri_encode ( const char *raw_string, char *buf, ssize_t len,
179 			   int field );
180 extern size_t uri_decode ( const char *encoded_string, char *buf, ssize_t len );
181 
182 #endif /* _GPXE_URI_H */
183