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 (at) nowhere.com : 38 * 39 * scheme = "mailto", opaque = "bob (at) 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 */ 183