1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 /**@file sofia-sip/url.h
26  *
27  * URL struct and helper functions.
28  *
29  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
30  *
31  * @date Created: Thu Jun  8 19:28:55 2000 ppessi
32  */
33 
34 #ifndef URL_H_TYPES
35 #define URL_H_TYPES
36 
37 /** Recognized URL schemes (value of url_t.url_type).
38  *
39  * @sa &lt;<a href="http://www.iana.org/assignments/uri-schemes.html">http://www.iana.org/assignments/uri-schemes.html</a>&gt;
40  */
41 enum url_type_e {
42   url_invalid = -2,	/**< Invalid url. */
43   url_unknown = -1,	/**< Unknown scheme. */
44   url_any = 0,		/**< "*" */
45   url_sip,		/**< "sip:". @sa @RFC3261 */
46   url_sips,		/**< "sips:". @sa @RFC3261 */
47   url_urn,		/**< "urn:". @sa @RFC6061 */
48   url_tel,		/**< "tel:" @sa RFC3966 */
49   url_fax,		/**< "fax:". @note Obsolete. @sa @RFC2806 */
50   url_modem,		/**< "modem:". @note Obsolete. @sa @RFC2806  */
51   url_http,		/**< "http:". @sa @RFC2616, @RFC3986 */
52   url_https,		/**< "https:". @sa @RFC2618, @RFC3986 */
53   url_ftp,		/**< "ftp:". @sa @RFC1738 */
54   url_file,		/**< "file:" @sa @RFC1738 */
55   url_rtsp,		/**< "rtsp:" @sa @RFC2326 */
56   url_rtspu,		/**< "rtspu:" @sa @RFC2326 */
57   url_mailto,		/**< "mailto:" @sa @RFC2368 */
58   url_im,		/**< "im:" (simple instant messaging). @sa @RFC3860 */
59   url_pres,		/**< "pres:" (simple presence). @sa @RFC3859  */
60   url_cid,		/**< "cid:" (Content-ID). @sa @RFC2392 */
61   url_msrp,		/**< "msrp:" (message session relay)  */
62   url_msrps,		/**< "msrps:" (new in @VERSION_1_12_2) */
63   url_wv,		/**< "wv:" (Wireless village) */
64   _url_none
65 };
66 
67 /** URL structure.
68  *
69  * This structure is used to present a parsed URL.
70  */
71 typedef struct {
72   char                url_pad[sizeof(void *) - 2];
73 				    /**< Zero pad for URL_STRING_P(). */
74   signed char         url_type;	    /**< URL type (url_type_e). */
75   char                url_root;	    /**< Nonzero if root "//" */
76   char const         *url_scheme;   /**< URL type as string. */
77   char const         *url_user;	    /**< User part */
78   char const         *url_password; /**< Password */
79   char const         *url_host;     /**< Host part */
80   char const         *url_port;     /**< Port */
81   char const         *url_path;     /**< Path part, starts with "/" */
82   char const         *url_params;   /**< Parameters (separated by ;) */
83   char const         *url_headers;  /**< Headers (separated by ? and &) */
84   char const         *url_fragment; /**< Fragment (separated by #) */
85 } url_t;
86 
87 enum {
88   /** Maximum size of a URL. */
89   URL_MAXLEN = 65536
90 };
91 
92 /** Type to present either a parsed URL or string.
93  *
94  * The union type url_string_t is used to pass a parsed URL or string as a
95  * parameter. The URL_STRING_P() checks if a passed pointer points to a
96  * string or a parsed URL. Testing requires that the first character of the
97  * string is nonzero. Use URL_STRING_MAKE() to properly cast a string
98  * pointer as a pointer to url_string_t.
99  */
100 typedef union {
101   char  us_str[URL_MAXLEN];	/**< URL as a string. */
102   url_t us_url[1];		/**< Parsed URL. */
103 } url_string_t;
104 
105 #endif
106 
107 #ifndef URL_H
108 /** Defined when <sofia-sip/url.h> has been included. */
109 #define URL_H
110 
111 #ifndef SU_ALLOC_H
112 #include <sofia-sip/su_alloc.h>
113 #endif
114 
115 SOFIA_BEGIN_DECLS
116 
117 /** Convert a string to a url struct. */
118 SOFIAPUBFUN url_t *url_make(su_home_t *h, char const *str);
119 
120 /** Convert a string formatting result to a url struct. */
121 SOFIAPUBFUN url_t *url_format(su_home_t *h, char const *fmt, ...);
122 
123 /** Convert #url_t to a string allocated from @a home */
124 SOFIAPUBFUN char *url_as_string(su_home_t *home, url_t const *url);
125 
126 /** Duplicate the url to memory allocated via home */
127 SOFIAPUBFUN url_t *url_hdup(su_home_t *h, url_t const *src);
128 
129 /** Sanitize a URL. */
130 SOFIAPUBFUN int url_sanitize(url_t *u);
131 
132 /** Get URL scheme by type. */
133 SOFIAPUBFUN char const *url_scheme(enum url_type_e type);
134 
135 /* ---------------------------------------------------------------------- */
136 /* URL comparison */
137 
138 /** Compare two URLs lazily. */
139 SOFIAPUBFUN int url_cmp(url_t const *a, url_t const *b);
140 
141 /** Compare two URLs conservatively. */
142 SOFIAPUBFUN int url_cmp_all(url_t const *a, url_t const *b);
143 
144 /* ---------------------------------------------------------------------- */
145 /* Parameter handling */
146 
147 /** Search for a parameter. */
148 SOFIAPUBFUN isize_t url_param(char const *params, char const *tag,
149 			      char value[], isize_t vlen);
150 
151 /** Check for a parameter. */
152 SOFIAPUBFUN int url_has_param(url_t const *url, char const *name);
153 
154 /** Check for a presence of a parameter in string. */
155 SOFIAPUBFUN isize_t url_have_param(char const *params, char const *tag);
156 
157 /** Add a parameter. */
158 SOFIAPUBFUN int url_param_add(su_home_t *h, url_t *url, char const *param);
159 
160 /** Strip transport-specific stuff away from URI. */
161 SOFIAPUBFUN int url_strip_transport(url_t *u);
162 
163 /** Strip parameter away from URI. */
164 SOFIAPUBFUN char *url_strip_param_string(char *params, char const *name);
165 
166 /** Test if url has any transport-specific stuff. */
167 SOFIAPUBFUN int url_have_transport(url_t const *u);
168 
169 /* ---------------------------------------------------------------------- */
170 /* Query handling */
171 
172 /** Convert a URL query to a header string. */
173 SOFIAPUBFUN char *url_query_as_header_string(su_home_t *home,
174 					     char const *query);
175 
176 /* ---------------------------------------------------------------------- */
177 /* Handling url-escque strings */
178 
179 /** Test if string contains url-reserved characters. */
180 SOFIAPUBFUN int url_reserved_p(char const *s);
181 
182 /** Escape a string. */
183 SOFIAPUBFUN char *url_escape(char *d, char const *s, char const reserved[]);
184 
185 /** Calculate length of string when escaped. */
186 SOFIAPUBFUN isize_t url_esclen(char const *s, char const reserved[]);
187 
188 /** Unescape characters from string */
189 SOFIAPUBFUN size_t url_unescape_to(char *d, char const *s, size_t n);
190 
191 /** Unescape a string */
192 SOFIAPUBFUN char *url_unescape(char *d, char const *s);
193 
194 #define URL_RESERVED_CHARS ";/?:@&=+$,"
195 
196 /* ---------------------------------------------------------------------- */
197 /* Initializing */
198 
199 /** Initializer for an #url_t structure. @HI
200  *
201  * The macro URL_INIT_AS() is used to initialize a #url_t structure with a
202  * known url type:
203  * @code
204  *   url_t urls[2] = { URL_INIT_AS(sip), URL_INIT_AS(http) };
205  * @endcode
206  */
207 #define URL_INIT_AS(type)  \
208   { "\0", url_##type, 0, url_##type != url_any ? #type : "*" }
209 
210 /** Init a url structure as given type */
211 SOFIAPUBFUN void url_init(url_t *url, enum url_type_e type);
212 
213 /* ---------------------------------------------------------------------- */
214 /* Resolving helpers */
215 
216 /** Return default port number corresponding to the url type. */
217 SOFIAPUBFUN char const *url_port_default(enum url_type_e url_type);
218 
219 /** Return default transport name corresponding to the url type */
220 SOFIAPUBFUN char const *url_tport_default(enum url_type_e url_type);
221 
222 /** Return the URL port string, using default port if not present. */
223 SOFIAPUBFUN char const *url_port(url_t const *u);
224 
225 /** Return the URL port string, using default port if none present. */
226 #define URL_PORT(u) \
227   ((u) && (u)->url_port ? (u)->url_port : \
228   url_port_default((u) ? (enum url_type_e)(u)->url_type : url_any))
229 
230 /* ---------------------------------------------------------------------- */
231 /* url_string_t handling */
232 
233 /** Test if a pointer to #url_string_t is a string
234  * (not a pointer to a #url_t structure). */
235 #define URL_STRING_P(u) ((u) && *((url_string_t*)(u))->us_str != 0)
236 
237 /** Test if a pointer to #url_string_t is a string
238  * (not a pointer to a #url_t structure). */
239 #define URL_IS_STRING(u) ((u) && *((url_string_t*)(u))->us_str != 0)
240 
241 /** Test if a pointer to #url_string_t is a string
242  * (not a pointer to a #url_t structure). */
243 SOFIAPUBFUN int url_string_p(url_string_t const * url);
244 
245 /** Test if a pointer to #url_string_t is a string
246  * (not a pointer to a #url_t structure). */
247 SOFIAPUBFUN int url_is_string(url_string_t const * url);
248 
249 /** Cast a string to a #url_string_t. @HI */
250 #define URL_STRING_MAKE(s) \
251   ((url_string_t *)((s) && *((char *)(s)) ? (s) : NULL))
252 
253 /* ---------------------------------------------------------------------- */
254 /* Printing URL */
255 
256 /** Format string used when printing url with printf(). @HI */
257 #define URL_PRINT_FORMAT "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"
258 #define URL_FORMAT_STRING URL_PRINT_FORMAT
259 
260 /** Argument list used when printing url with printf(). @HI */
261 #define URL_PRINT_ARGS(u) \
262   (u)->url_scheme ? (u)->url_scheme : "",	\
263   (u)->url_type != url_any && (u)->url_scheme && (u)->url_scheme[0] \
264     ? ":" : "", \
265   (u)->url_root && ((u)->url_host || (u)->url_user) ? "//" : "", \
266   (u)->url_user ? (u)->url_user : "", \
267   (u)->url_user && (u)->url_password ? ":" : "", \
268   (u)->url_user && (u)->url_password ? (u)->url_password : "", \
269   (u)->url_user && (u)->url_host ? "@" : "", \
270   (u)->url_host ? (u)->url_host : "", \
271   (u)->url_host && (u)->url_port ? ":" : "", \
272   (u)->url_host && (u)->url_port ? (u)->url_port : "", \
273   (u)->url_root && (u)->url_path ? "/" : "", \
274   (u)->url_path ? (u)->url_path : "", \
275   (u)->url_params ? ";" : "", (u)->url_params ? (u)->url_params : "", \
276   (u)->url_headers ? "?" : "", (u)->url_headers ? (u)->url_headers : "", \
277   (u)->url_fragment ? "#" : "", (u)->url_fragment ? (u)->url_fragment : ""
278 
279 /* ---------------------------------------------------------------------- */
280 /* URL digests */
281 
282 struct su_md5_t;
283 
284 /** Update MD5 sum with URL contents. */
285 SOFIAPUBFUN void url_update(struct su_md5_t *md5, url_t const *url);
286 
287 /** Calculate a digest from URL contents. */
288 SOFIAPUBFUN void url_digest(void *hash, int hsize,
289 			    url_t const *, char const *key);
290 
291 /* ---------------------------------------------------------------------- */
292 /* Parsing and manipulating URLs */
293 
294 /** Decode a URL. */
295 SOFIAPUBFUN int url_d(url_t *url, char *s);
296 
297 /** Calculate the encoding length of URL. */
298 SOFIAPUBFUN isize_t url_len(url_t const * url);
299 
300 /** Encode a URL. */
301 SOFIAPUBFUN issize_t url_e(char buffer[], isize_t n, url_t const *url);
302 
303 /** Encode a URL: use @a buf up to @a end. @HI */
304 #define URL_E(buf, end, url) \
305   (buf) += url_e((buf), (buf) < (end) ? (end) - (buf) : 0, (url))
306 
307 /** Calculate the size of srings attached to the url. */
308 SOFIAPUBFUN isize_t url_xtra(url_t const * url);
309 
310 /** Duplicate the url in the provided memory area. */
311 SOFIAPUBFUN issize_t url_dup(char *, isize_t , url_t *dst, url_t const *src);
312 
313 /** Duplicate the url: use @a buf up to @a end. @HI */
314 #define URL_DUP(buf, end, dst, src) \
315   (buf) += url_dup((buf), (isize_t)((buf) < (end) ? (end) - (buf) : 0), (dst), (src))
316 
317 SOFIA_END_DECLS
318 #endif
319 
320