summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/include/ipxe/uri.h
blob: 00e5a24c42991c4d6042e3a9fcf700f76f9d3f35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#ifndef _IPXE_URI_H
#define _IPXE_URI_H

/** @file
 *
 * Uniform Resource Identifiers
 *
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

#include <stddef.h>
#include <stdlib.h>
#include <ipxe/refcnt.h>
#include <ipxe/in.h>

struct parameters;

/** A Uniform Resource Identifier
 *
 * Terminology for this data structure is as per uri(7), except that
 * "path" is defined to include the leading '/' for an absolute path.
 *
 * Note that all fields within a URI are optional and may be NULL.
 *
 * The pointers to the various fields are packed together so they can
 * be accessed in array fashion in some places in uri.c where doing so
 * saves significant code size.
 *
 * Some examples are probably helpful:
 *
 *   http://www.ipxe.org/wiki :
 *
 *   scheme = "http", host = "www.ipxe.org", path = "/wiki"
 *
 *   /var/lib/tftpboot :
 *
 *   path = "/var/lib/tftpboot"
 *
 *   mailto:bob@nowhere.com :
 *
 *   scheme = "mailto", opaque = "bob@nowhere.com"
 *
 *   ftp://joe:secret@insecure.org:8081/hidden/path/to?what=is#this
 *
 *   scheme = "ftp", user = "joe", password = "secret",
 *   host = "insecure.org", port = "8081", path = "/hidden/path/to",
 *   query = "what=is", fragment = "this"
 */
struct uri {
	/** Reference count */
	struct refcnt refcnt;
	/** Scheme */
	const char *scheme;
	/** Opaque part */
	const char *opaque;
	/** User name */
	const char *user;
	/** Password */
	const char *password;
	/** Host name */
	const char *host;
	/** Port number */
	const char *port;
	/** Path */
	const char *path;
	/** Query */
	const char *query;
	/** Fragment */
	const char *fragment;
	/** Form parameters */
	struct parameters *params;
} __attribute__ (( packed ));

/**
 * Access URI field
 *
 * @v uri		URI
 * @v field		URI field index
 * @ret field		URI field (as an lvalue)
 */
#define uri_field( uri, field ) (&uri->scheme)[field]

/**
 * Calculate index of a URI field
 *
 * @v name		URI field name
 * @ret field		URI field index
 */
#define URI_FIELD( name )						\
	( ( offsetof ( struct uri, name ) -				\
	    offsetof ( struct uri, scheme ) ) / sizeof ( void * ) )

/** URI fields */
enum uri_fields {
	URI_SCHEME = URI_FIELD ( scheme ),
	URI_OPAQUE = URI_FIELD ( opaque ),
	URI_USER = URI_FIELD ( user ),
	URI_PASSWORD = URI_FIELD ( password ),
	URI_HOST = URI_FIELD ( host ),
	URI_PORT = URI_FIELD ( port ),
	URI_PATH = URI_FIELD ( path ),
	URI_QUERY = URI_FIELD ( query ),
	URI_FRAGMENT = URI_FIELD ( fragment ),
	URI_FIELDS
};

/**
 * URI is an absolute URI
 *
 * @v uri			URI
 * @ret is_absolute		URI is absolute
 *
 * An absolute URI begins with a scheme, e.g. "http:" or "mailto:".
 * Note that this is a separate concept from a URI with an absolute
 * path.
 */
static inline int uri_is_absolute ( const struct uri *uri ) {
	return ( uri->scheme != NULL );
}

/**
 * URI has an opaque part
 *
 * @v uri			URI
 * @ret has_opaque		URI has an opaque part
 */
static inline int uri_has_opaque ( const struct uri *uri ) {
	return ( uri->opaque && ( uri->opaque[0] != '\0' ) );
}

/**
 * URI has a path
 *
 * @v uri			URI
 * @ret has_path		URI has a path
 */
static inline int uri_has_path ( const struct uri *uri ) {
	return ( uri->path && ( uri->path[0] != '\0' ) );
}

/**
 * URI has an absolute path
 *
 * @v uri			URI
 * @ret has_absolute_path	URI has an absolute path
 *
 * An absolute path begins with a '/'.  Note that this is a separate
 * concept from an absolute URI.  Note also that a URI may not have a
 * path at all.
 */
static inline int uri_has_absolute_path ( const struct uri *uri ) {
	return ( uri->path && ( uri->path[0] == '/' ) );
}

/**
 * URI has a relative path
 *
 * @v uri			URI
 * @ret has_relative_path	URI has a relative path
 *
 * A relative path begins with something other than a '/'.  Note that
 * this is a separate concept from a relative URI.  Note also that a
 * URI may not have a path at all.
 */
static inline int uri_has_relative_path ( const struct uri *uri ) {
	return ( uri->path && ( uri->path[0] != '/' ) );
}

/**
 * Increment URI reference count
 *
 * @v uri		URI, or NULL
 * @ret uri		URI as passed in
 */
static inline __attribute__ (( always_inline )) struct uri *
uri_get ( struct uri *uri ) {
	ref_get ( &uri->refcnt );
	return uri;
}

/**
 * Decrement URI reference count
 *
 * @v uri		URI, or NULL
 */
static inline __attribute__ (( always_inline )) void
uri_put ( struct uri *uri ) {
	ref_put ( &uri->refcnt );
}

extern struct uri *cwuri;

extern size_t uri_encode ( const char *string, unsigned int field,
			   char *buf, ssize_t len );
extern struct uri * parse_uri ( const char *uri_string );
extern size_t format_uri ( const struct uri *uri, char *buf, size_t len );
extern char * format_uri_alloc ( const struct uri *uri );
extern unsigned int uri_port ( const struct uri *uri,
			       unsigned int default_port );
extern struct uri * uri_dup ( const struct uri *uri );
extern char * resolve_path ( const char *base_path,
			     const char *relative_path );
extern struct uri * resolve_uri ( const struct uri *base_uri,
				  struct uri *relative_uri );
extern struct uri * tftp_uri ( struct in_addr next_server, unsigned int port,
			       const char *filename );
extern void churi ( struct uri *uri );

#endif /* _IPXE_URI_H */