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