1 /*******************************************************************************
2  *
3  * Copyright (c) 2000-2003 Intel Corporation
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * - Redistributions of source code must retain the above copyright notice,
10  * this list of conditions and the following disclaimer.
11  * - Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  * - Neither name of Intel Corporation nor the names of its contributors
15  * may be used to endorse or promote products derived from this software
16  * without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *
30  ******************************************************************************/
31 
32 #ifndef GENLIB_NET_URI_H
33 #define GENLIB_NET_URI_H
34 
35 /*!
36  * \file
37  */
38 
39 #if !defined(_WIN32)
40 	#include <sys/param.h>
41 #endif
42 
43 #include "UpnpGlobal.h" /* for */
44 #include "UpnpInet.h"
45 
46 #include <ctype.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <sys/types.h>
52 #include <time.h>
53 
54 #ifdef _WIN32
55 	#if !defined(UPNP_USE_MSVCPP) && !defined(UPNP_USE_BCBPP)
56 		/* VC Winsocks2 includes these functions */
57 		#include "inet_pton.h"
58 	#endif
59 #else
60 	#include <netdb.h>      /* for struct addrinfo */
61 #endif
62 
63 #ifdef _WIN32
64 	#define strncasecmp strnicmp
65 #else
66 	/* Other systems have strncasecmp */
67 #endif
68 
69 #ifdef __cplusplus
70 extern "C" {
71 #endif
72 
73 #define MARK "-_.!~*'()"
74 
75 /*! added {} for compatibility */
76 #define RESERVED ";/?:@&=+$,{}"
77 
78 #define HTTP_SUCCESS 1
79 
80 enum hostType {
81 	HOSTNAME,
82 	IPv4address
83 };
84 
85 enum pathType {
86 	ABS_PATH,
87 	REL_PATH,
88 	OPAQUE_PART
89 };
90 
91 #ifdef _WIN32
92 	/* there is a conflict in windows with other symbols. */
93 	enum uriType  {
94 		absolute,
95 		relative
96 	};
97 #else
98 	enum uriType  {
99 		ABSOLUTE,
100 		RELATIVE
101 	};
102 #endif
103 
104 /*!
105  * \brief Buffer used in parsinghttp messages, urls, etc. generally this simply
106  * holds a pointer into a larger array.
107  */
108 typedef struct TOKEN {
109 	const char *buff;
110 	size_t size;
111 } token;
112 
113 /*!
114  * \brief Represents a host port: e.g. "127.127.0.1:80" text is a token
115  * pointing to the full string representation.
116  */
117 typedef struct HOSTPORT {
118 	/*! Full host port. */
119 	token text;
120 	/* Network Byte Order */
121 	struct sockaddr_storage IPaddress;
122 } hostport_type;
123 
124 /*!
125  * \brief Represents a URI used in parse_uri and elsewhere
126  */
127 typedef struct URI{
128 	enum uriType type;
129 	token scheme;
130 	enum pathType path_type;
131 	token pathquery;
132 	token fragment;
133 	hostport_type hostport;
134 } uri_type;
135 
136 /*!
137  * \brief Represents a list of URLs as in the "callback" header of SUBSCRIBE
138  * message in GENA. "char *" URLs holds dynamic memory.
139  */
140 typedef struct URL_LIST {
141 	/*! */
142 	size_t size;
143 	/*! All the urls, delimited by <> */
144 	char *URLs;
145 	/*! */
146 	uri_type *parsedURLs;
147 } URL_list;
148 
149 /*!
150  * \brief Replaces an escaped sequence with its unescaped version as in
151  * http://www.ietf.org/rfc/rfc2396.txt  (RFC explaining URIs)
152  *
153  * Size of array is NOT checked (MUST be checked by caller)
154  *
155  * \note This function modifies the string. If the sequence is an escaped
156  * sequence it is replaced, the other characters in the string are shifted
157  * over, and NULL characters are placed at the end of the string.
158  *
159  * \return
160  */
161 int replace_escaped(
162 	/*! [in,out] String of characters. */
163 	char *in,
164 	/*! [in] Index at which to start checking the characters. */
165 	size_t index,
166 	/*! [out] . */
167 	size_t *max);
168 
169 /*!
170  * \brief Copies one URL_list into another.
171  *
172  * This includes dynamically allocating the out->URLs field (the full string),
173  * and the structures used to hold the parsedURLs. This memory MUST be freed
174  * by the caller through: free_URL_list(&out).
175  *
176  * \return
177  * 	\li HTTP_SUCCESS - On Success.
178  * 	\li UPNP_E_OUTOF_MEMORY - On Failure to allocate memory.
179  */
180 int copy_URL_list(
181 	/*! [in] Source URL list. */
182 	URL_list *in,
183 	/*! [out] Destination URL list. */
184 	URL_list *out);
185 
186 /*!
187  * \brief Frees the memory associated with a URL_list.
188  *
189  * Frees the dynamically allocated members of of list. Does NOT free the
190  * pointer to the list itself ( i.e. does NOT free(list)).
191  */
192 void free_URL_list(
193 	/*! [in] URL list object. */
194 	URL_list *list);
195 
196 /*!
197  * \brief Function useful in debugging for printing a parsed uri.
198  */
199 #ifdef DEBUG
200 void print_uri(
201 	/*! [in] URI object to print. */
202 	uri_type *in);
203 #else
204 #define print_uri(in) do {} while (0)
205 #endif
206 
207 /*!
208  * \brief Function useful in debugging for printing a token.
209  */
210 #ifdef DEBUG
211 void print_token(
212 	/*! [in] Token object to print. */
213 	token *in);
214 #else
215 #define print_token(in) do {} while (0)
216 #endif
217 
218 /*!
219  * \brief Compares buffer in the token object with the buffer in in2.
220  *
221  * \return
222  * 	\li < 0, if string1 is less than string2.
223  * 	\li == 0, if string1 is identical to string2 .
224  * 	\li > 0, if string1 is greater than string2.
225  */
226 int token_string_casecmp(
227 	/*! [in] Token object whose buffer is to be compared. */
228 	token *in1,
229 	/*! [in] String of characters to compare with. */
230 	const char *in2);
231 
232 /*!
233  * \brief Compares two tokens.
234  *
235  * \return
236  * 	\li < 0, if string1 is less than string2.
237  * 	\li == 0, if string1 is identical to string2 .
238  * 	\li > 0, if string1 is greater than string2.
239  */
240 int token_cmp(
241 	/*! [in] First token object whose buffer is to be compared. */
242 	token *in1,
243 	/*! [in] Second token object used for the comparison. */
244 	token *in2);
245 
246 /*!
247  * \brief Removes http escaped characters such as: "%20" and replaces them with
248  * their character representation. i.e. "hello%20foo" -> "hello foo".
249  *
250  * The input IS MODIFIED in place (shortened). Extra characters are replaced
251  * with \b NULL.
252  *
253  * \return UPNP_E_SUCCESS.
254  */
255 int remove_escaped_chars(
256 	/*! [in,out] String of characters to be modified. */
257 	char *in,
258 	/*! [in,out] Size limit for the number of characters. */
259 	size_t *size);
260 
261 /*!
262  * \brief Removes ".", and ".." from a path.
263  *
264  * If a ".." can not be resolved (i.e. the .. would go past the root of the
265  * path) an error is returned.
266  *
267  * The input IS modified in place.)
268  *
269  * \note Examples
270  * 	char path[30]="/../hello";
271  * 	remove_dots(path, strlen(path)) -> UPNP_E_INVALID_URL
272  * 	char path[30]="/./hello";
273  * 	remove_dots(path, strlen(path)) -> UPNP_E_SUCCESS,
274  * 	in = "/hello"
275  * 	char path[30]="/./hello/foo/../goodbye" ->
276  * 	UPNP_E_SUCCESS, in = "/hello/goodbye"
277  *
278  * \return
279  * 	\li UPNP_E_SUCCESS - On Success.
280  * 	\li UPNP_E_OUTOF_MEMORY - On failure to allocate memory.
281  * 	\li UPNP_E_INVALID_URL - Failure to resolve URL.
282  */
283 int remove_dots(
284 	/*! [in] String of characters from which "dots" have to be removed. */
285 	char *in,
286 	/*! [in] Size limit for the number of characters. */
287 	size_t size);
288 
289 /*!
290  * \brief resolves a relative url with a base url returning a NEW (dynamically
291  * allocated with malloc) full url.
292  *
293  * If the base_url is \b NULL, then a copy of the  rel_url is passed back if
294  * the rel_url is absolute then a copy of the rel_url is passed back if neither
295  * the base nor the rel_url are Absolute then NULL is returned. Otherwise it
296  * tries and resolves the relative url with the base as described in
297  * http://www.ietf.org/rfc/rfc2396.txt (RFCs explaining URIs).
298  *
299  * The resolution of '..' is NOT implemented, but '.' is resolved.
300  *
301  * \return
302  */
303 char *resolve_rel_url(
304 	/*! [in] Base URL. */
305 	char *base_url,
306 	/*! [in] Relative URL. */
307 	char *rel_url);
308 
309 /*!
310  * \brief Parses a uri as defined in http://www.ietf.org/rfc/rfc2396.txt
311  * (RFC explaining URIs).
312  *
313  * Handles absolute, relative, and opaque uris. Parses into the following
314  * pieces: scheme, hostport, pathquery, fragment (path and query are treated
315  * as one token)
316  *
317  * Caller should check for the pieces they require.
318  *
319  * \return
320  */
321 int parse_uri(
322 	/*! [in] Character string containing uri information to be parsed. */
323 	const char *in,
324 	/*! [in] Maximum limit on the number of characters. */
325 	size_t max,
326 	/*! [out] Output parameter which will have the parsed uri information. */
327 	uri_type *out);
328 
329 /*!
330  * \brief
331  *
332  * \return
333  */
334 int parse_token(
335 	/*! [in] . */
336 	char *in,
337 	/*! [out] . */
338 	token *out,
339 	/*! [in] . */
340 	int max_size);
341 
342 #ifdef __cplusplus
343 }
344 #endif
345 
346 
347 #endif /* GENLIB_NET_URI_H */
348 
349