[uri] Decode/encode URIs when parsing/unparsing
[people/cooldavid/gpxe.git] / src / include / gpxe / uri.h
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  */
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  */
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  */
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 *
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
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 */