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 /**@CFILE torture_url.c Test functions for url parser
26  *
27  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
28  *
29  * @date Created: Tue Aug 21 15:18:26 2001 ppessi
30  */
31 
32 #include "config.h"
33 
34 #include <stddef.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <limits.h>
38 #include <stdio.h>
39 #include <assert.h>
40 
41 #include "sofia-sip/url.h"
42 #include "sofia-sip/url_tag.h"
43 
44 static int tstflags = 0;
45 
46 #define TSTFLAGS tstflags
47 
48 #include <sofia-sip/tstdef.h>
49 
50 char const name[] = "torture_url";
51 
52 unsigned char hash1[16], hash2[16];
53 
54 /* test unquoting and canonizing */
test_quote(void)55 int test_quote(void)
56 {
57   su_home_t home[1] = { SU_HOME_INIT(home) };
58   url_t *u;
59   char s[] = "%73ip:q%74est%01:%01%02%00@host%2enokia.com;%70aram=%01%02";
60   char c[] = "sip:qtest%01:%01%02%00@host.nokia.com;param=%01%02";
61   char *d;
62 
63 #define RESERVED        ";/?:@&=+$,"
64 #define DELIMS          "<>#%\""
65 #define UNWISE		"{}|\\^[]`"
66 #define EXCLUDED	RESERVED DELIMS UNWISE
67 
68   char escaped[1 + 3 * 23 + 1];
69 
70 #define UNRESERVED    "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
71                       "abcdefghijklmnopqrstuvwxyz" \
72                       "0123456789" \
73                       "-_.!~*'()"
74 
75   char unreserved[26 + 26 + 10 + 9 + 1];
76 
77   BEGIN();
78 
79   d = url_as_string(home, (url_t *)"sip:joe@example.com");
80   TEST_S(d, "sip:joe@example.com");
81 
82   TEST(strlen(EXCLUDED), 23);
83   TEST(strlen(UNRESERVED), 71);
84 
85   TEST_1(!url_reserved_p("foo"));
86   TEST_1(!url_reserved_p(""));
87   TEST_1(url_reserved_p("foobar:bar"));
88 
89   TEST_SIZE(url_esclen("a" EXCLUDED, ""),
90 	    1 + strlen(RESERVED) + 3 * strlen(DELIMS UNWISE));
91   TEST_SIZE(url_esclen("a" EXCLUDED, DELIMS UNWISE),
92 	    1 + strlen(RESERVED) + 3 * strlen(DELIMS UNWISE));
93   TEST_SIZE(url_esclen("a" EXCLUDED, EXCLUDED), 1 + 3 * strlen(EXCLUDED));
94   TEST_SIZE(url_esclen("a" EXCLUDED, NULL), 1 + 3 * strlen(EXCLUDED));
95 
96   TEST_S(url_escape(escaped, "a" EXCLUDED, NULL),
97 	 "a%3B%2F%3F%3A%40%26%3D%2B%24%2C"
98 	 "%3C%3E%23%25%22"
99 	 "%7B%7D%7C%5C%5E%5B%5D%60");
100   TEST_S(url_unescape(escaped, escaped), "a" EXCLUDED);
101 
102   TEST_SIZE(url_esclen(UNRESERVED, NULL), strlen(UNRESERVED));
103   TEST_S(url_escape(unreserved, UNRESERVED, NULL), UNRESERVED);
104   TEST_S(url_unescape(unreserved, UNRESERVED), UNRESERVED);
105 
106   d = "%53ip:%75@%48";		/* Sip:u@H */
107   u = url_hdup(home, (url_t *)d); TEST_1(u);
108   url_digest(hash1, sizeof(hash1), u, NULL);
109   url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
110   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
111 
112   d = "sip:u@h";
113   u = url_hdup(home, (url_t *)d); TEST_1(u);
114   url_digest(hash1, sizeof(hash1), u, NULL);
115   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
116   url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
117   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
118 
119   u = url_hdup(home, (url_t *)s); TEST_1(u);
120   d = url_as_string(home, u); TEST_1(d);
121   TEST_S(d, c);
122 
123   d = "sip:&=+$,;?/:&=+$,@[::1]:56001;param=+$,/:@&;another=@%40%2F"
124     "?header=" RESERVED "&%3b%2f%3f%3a%40%26%3d%2b%24%2c";
125   u = url_hdup(home, (url_t *)d); TEST_1(u);
126   TEST_S(u->url_user, "&=+$,;?/");
127   TEST_S(u->url_host, "[::1]");
128   TEST_S(u->url_params, "param=+$,/:@&;another=@%40/");
129   TEST_S(u->url_headers, "header=" RESERVED "&%3B%2F%3F%3A%40%26%3D%2B%24%2C");
130   url_digest(hash1, sizeof(hash1), u, NULL);
131   url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
132   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
133 
134   u = url_hdup(home, (url_t *)s); TEST_1(u);
135   d = url_as_string(home, u); TEST_1(d);
136   TEST_S(d, c);
137 
138   d = "http://&=+$,;:&=+$,;@host:8080/foo%2F%3B%3D"
139     ";param=+$,%2f%3b%3d/bar;param=:@&;another=@"
140     "?query=" RESERVED;
141   u = url_hdup(home, (url_t *)d); TEST_1(u);
142   TEST_S(u->url_user, "&=+$,;"); TEST_S(u->url_password, "&=+$,;");
143   TEST_S(u->url_path, "foo%2F%3B%3D;param=+$,%2F%3B%3D/bar;param=:@&;another=@");
144   url_digest(hash1, sizeof(hash1), u, NULL);
145   url_digest(hash2, sizeof(hash2), (url_t const *)d, NULL);
146   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
147 
148   u = url_hdup(home, (url_t *)s); TEST_1(u);
149   d = url_as_string(home, u); TEST_1(d);
150   TEST_S(d, c);
151 
152   url_digest(hash1, sizeof(hash1), u, NULL);
153   url_digest(hash2, sizeof(hash2), (url_t const *)s, NULL);
154   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
155 
156   url_digest(hash2, sizeof(hash2), (url_t const *)c, NULL);
157   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
158 
159   END();
160 }
161 
162 
test_any(void)163 int test_any(void)
164 {
165   /* Test any (*) urls */
166   url_t any[1] = { URL_INIT_AS(any) };
167   su_home_t home[1] = { SU_HOME_INIT(home) };
168   url_t *u, url[1];
169   char *tst;
170 
171   BEGIN();
172 
173   TEST_S(url_scheme(url_any), "*");
174   TEST_S(url_scheme(url_mailto), "mailto");
175   TEST_S(url_scheme(url_im), "im");
176   TEST_S(url_scheme(url_cid), "cid");
177   TEST_S(url_scheme(url_msrp), "msrp");
178   TEST_S(url_scheme(url_msrps), "msrps");
179 
180   TEST_1(tst = su_strdup(home, "*"));
181   TEST(url_d(url, tst), 0);
182   TEST(url_cmp(any, url), 0);
183   TEST(url->url_type, url_any);
184   TEST_1(u = url_hdup(home, url));
185   TEST(u->url_type, url_any);
186   TEST(url_cmp(any, u), 0);
187 
188   url_digest(hash1, sizeof(hash1), url, NULL);
189   url_digest(hash2, sizeof(hash2), (url_t *)"*", NULL);
190   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
191 
192   {
193     char buf[6];
194 
195     TEST_1(u = url_hdup(home, (void *)"error"));
196     TEST_SIZE(url_xtra(u), 6);
197     TEST_SIZE(url_dup(buf, 6, url, u), 6);
198     TEST_S(buf, "error");
199   }
200 
201   {
202     TEST_1(u = url_hdup(home, (void *)"scheme:test"));
203     TEST(u->url_type, url_unknown);
204   }
205 
206   {
207     TEST_1(u = url_hdup(home, (void *)"*;param=foo?query=bar"));
208     TEST(u->url_type, url_unknown);
209     TEST_S(u->url_host, "*");
210     TEST_S(u->url_params, "param=foo");
211     TEST_S(u->url_headers, "query=bar");
212   }
213 
214   {
215     TEST_1(u = url_hdup(home, (void *)"#foo"));
216     TEST(u->url_type, url_unknown);
217     TEST_S(u->url_fragment, "foo");
218   }
219 
220   {
221     url_t u[1];
222     char b2[6] = "";
223 
224     memset(u, 0xff, sizeof u);
225     TEST(url_d(u, b2), 0);
226     TEST(u->url_type, url_unknown);
227   }
228 
229   su_home_deinit(home);
230 
231   END();
232 }
233 
test_sip(void)234 int test_sip(void)
235 {
236   /* sip urls */
237   su_home_t home[1] = { SU_HOME_INIT(home) };
238   url_t sip[1] = { URL_INIT_AS(sip) };
239   url_t *u, url[1];
240   char *tst, *s;
241   char sipurl0[] =
242     "sip:pekka%2Epessi@nokia%2Ecom;method=%4D%45%53%53%41%47%45"
243     "?body=CANNED%20MSG";
244   char sipurl[] =
245     "sip:user:pass@host:32;param=1"
246     "?From=foo@bar&To=bar@baz#unf";
247   char sip2url[] =
248     "sip:user/path;tel-param:pass@host:32;param=1%3d%3d1"
249     "?From=foo@bar&To=bar@baz#unf";
250   char sip2[sizeof(sipurl) + 32];
251   char sipsurl[] =
252     "sips:user:pass@host:32;param=1"
253     "?From=foo@bar&To=bar@baz#unf";
254   size_t i, j;
255   url_t *a, *b;
256 
257   BEGIN();
258 
259   TEST_S(url_scheme(url_sip), "sip");
260   TEST_S(url_scheme(url_urn), "urn");
261   TEST_S(url_scheme(url_sips), "sips");
262 
263   memset(url, 255, sizeof url);
264 
265   TEST(url_d(url, sipurl0), 0);
266 
267   TEST(url->url_type, url_sip);
268   TEST(url->url_root, 0);
269   TEST_S(url->url_scheme, "sip");
270   TEST_S(url->url_user, "pekka.pessi");
271   TEST_P(url->url_password, NULL);
272   TEST_S(url->url_host, "nokia.com");
273   TEST_P(url->url_port, NULL);
274   TEST_P(url->url_path, NULL);
275   TEST_S(url->url_params, "method=MESSAGE");
276   TEST_S(url->url_headers, "body=CANNED%20MSG");
277   TEST_P(url->url_fragment, NULL);
278 
279   TEST_S(url_query_as_header_string(home, url->url_headers),
280 	 "\n\nCANNED MSG");
281 
282   sip->url_user = "user";
283   sip->url_password = "pass";
284   sip->url_host = "host";
285   sip->url_port = "32";
286   sip->url_params = "param=1";
287   sip->url_headers = "From=foo@bar&To=bar@baz";
288   sip->url_fragment = "unf";
289 
290   memset(url, 255, sizeof url);
291 
292   TEST_1(tst = su_strdup(home, sipurl));
293   TEST_1(url_d(url, tst) == 0);
294   TEST_1(url_cmp(sip, url) == 0);
295   TEST(url->url_type, url_sip);
296   TEST_1(u = url_hdup(home, url));
297   TEST(u->url_type, url_sip);
298   TEST_1(url_cmp(sip, u) == 0);
299   TEST(url_e(sip2, sizeof(sip2), u), strlen(sipurl));
300   TEST_1(strcmp(sip2, sipurl) == 0);
301   TEST_SIZE(snprintf(sip2, sizeof(sip2), URL_PRINT_FORMAT,
302 		     URL_PRINT_ARGS(sip)), strlen(sipurl));
303   TEST_1(strcmp(sip2, sipurl) == 0);
304 
305   url_digest(hash1, sizeof(hash1), url, NULL);
306   url_digest(hash2, sizeof(hash2), (url_t const *)sipurl, NULL);
307   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
308 
309   TEST_1(tst = su_strdup(home, sip2url));
310   TEST_1(url_d(url, tst) == 0);
311   TEST_S(url->url_user, "user/path;tel-param");
312   TEST_S(url->url_params, "param=1%3D%3D1");
313 
314   TEST_S(url_query_as_header_string(home, url->url_headers),
315 	 "From:foo@bar\nTo:bar@baz");
316 
317   url_digest(hash1, sizeof(hash1), url, NULL);
318   url_digest(hash2, sizeof(hash2), (url_t *)sip2url, NULL);
319   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
320 
321   sip->url_type = url_sips; sip->url_scheme = "sips";
322 
323   TEST_1(tst = su_strdup(home, sipsurl));
324   TEST_1(url_d(url, tst) == 0);
325   TEST_1(url_cmp(sip, url) == 0);
326   TEST(url->url_type, url_sips);
327 
328   /* Test url_dup() */
329   for (i = 0; i <= sizeof(sipsurl); i++) {
330     char buf[sizeof(sipsurl) + 1];
331     url_t dst[1];
332 
333     buf[i] = '\377';
334     TEST_SIZE(url_dup(buf, i, dst, url), sizeof(sipsurl) - 1 - strlen("sips"));
335     TEST(buf[i], '\377');
336   }
337 
338   url_digest(hash1, sizeof(hash1), url, NULL);
339   url_digest(hash2, sizeof(hash2), (url_t *)sipsurl, NULL);
340   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
341 
342   u = url_hdup(home, (url_t*)"SIP:test@127.0.0.1:55"); TEST_1(u);
343   TEST(u->url_type, url_sip);
344 
345   u = url_hdup(home, (url_t*)"SIP:test@127.0.0.1:"); TEST_1(u);
346   TEST(u->url_type, url_sip);
347 
348   TEST_P(url_hdup(home, (url_t*)"sip:test@127.0.0.1::55"), NULL);
349   TEST_P(url_hdup(home, (url_t*)"sip:test@127.0.0.1:55:"), NULL);
350   TEST_P(url_hdup(home, (url_t*)"sip:test@127.0.0.1:sip"), NULL);
351 
352   u = url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar@127.0.0.1"); TEST_1(u);
353   TEST(u->url_type, url_sip);
354   TEST_S(u->url_user, "#**00**#;foo=/bar");
355 
356   TEST_1(!url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar@#127.0.0.1"));
357   TEST_1(!url_hdup(home, (url_t*)"SIP:#**00**#;foo=/bar;127.0.0.1"));
358 
359   for (i = 32; i <= 256; i++) {
360     char pu[512];
361     char param[512];
362 
363     for (j = 0; j < i; j++)
364       param[j] = 'x';
365     param[j] = '\0';
366     memcpy(param, "x=", 2);
367 
368     snprintf(pu, sizeof(pu), "sip:test@host;%s", param);
369     u = url_hdup(home, (url_t*)pu); TEST_1(u);
370     s = url_as_string(home, u);
371     TEST_S(pu, s);
372   }
373 
374   s = su_strdup(home, "ttl;transport=tcp;ttl=15;ttl=;method=INVITE;ttl");
375   TEST_1(s);
376   s = url_strip_param_string(s, "ttl");
377   TEST_S(s, "transport=tcp;method=INVITE");
378 
379   u = url_hdup(home, (void*)"sip:u:p@host:5060;maddr=127.0.0.1;transport=tcp");
380   TEST_1(u);
381   TEST_1(url_have_transport(u));
382   TEST_1(url_strip_transport(u));
383   TEST_P(u->url_params, NULL);
384   TEST_1(!url_have_transport(u));
385 
386   u = url_hdup(home, (void*)"sip:u:p@host:5060;user=phone;ttl=1;isfocus");
387   TEST_1(u);
388   TEST_1(url_have_transport(u));
389   TEST_1(url_strip_transport(u));
390   TEST_S(u->url_params, "user=phone;isfocus");
391   TEST_1(!url_have_transport(u));
392 
393   u = url_hdup(home, (void*)"sip:u:p@host:5060;maddr=127.0.0.1;user=phone");
394   TEST_1(u);
395   TEST_1(url_have_transport(u));
396   TEST_1(url_strip_transport(u));
397   TEST_S(u->url_params, "user=phone");
398   TEST_1(!url_have_transport(u));
399 
400   u = url_hdup(home, (void*)"sip:u:p@host:5060;user=phone;transport=tcp");
401   TEST_1(u);
402   TEST_1(url_have_transport(u));
403   TEST_1(url_strip_transport(u));
404   TEST_S(u->url_params, "user=phone");
405   TEST_1(!url_have_transport(u));
406 
407   u = url_hdup(home, (void*)"sip:u:p@host;user=phone;;");
408   TEST_1(u);
409   /* We don't have transport params */
410   TEST_1(!url_have_transport(u));
411   /* ...but we still strip empty params */
412   TEST_1(url_strip_transport(u));
413   TEST_S(u->url_params, "user=phone");
414   TEST_1(!url_have_transport(u));
415 
416   u = url_hdup(home, (void*)"sip:u:p@host:5060;ttl=1;isfocus;transport=udp;");
417   TEST_1(u);
418   TEST_1(url_have_transport(u));
419   TEST_1(url_strip_transport(u));
420   TEST_S(u->url_params, "isfocus");
421   TEST_1(!url_have_transport(u));
422 
423   u = url_hdup(home, (void *)"sip:%22foo%22@172.21.55.55:5060");
424   TEST_1(u);
425   TEST_S(u->url_user, "%22foo%22");
426 
427   a = url_hdup(home, (void *)"sip:172.21.55.55:5060");
428   b = url_hdup(home, (void *)"sip:172.21.55.55");
429   TEST_1(a); TEST_1(b);
430   TEST_1(url_cmp(a, b) == 0);
431   TEST(url_cmp_all(a, b), 0);
432 
433   a = url_hdup(home, (void *)"sips:172.21.55.55:5060");
434   b = url_hdup(home, (void *)"sips:172.21.55.55");
435   TEST_1(a); TEST_1(b);
436   TEST_1(url_cmp(a, b) != 0);
437   TEST_1(url_cmp_all(a, b) < 0);
438 
439   a = url_hdup(home, (void *)"sips:172.21.55.55:5061");
440   b = url_hdup(home, (void *)"sips:172.21.55.55");
441   TEST_1(a); TEST_1(b);
442   TEST_1(url_cmp(a, b) == 0);
443   TEST(url_cmp_all(a, b), 0);
444 
445   a = url_hdup(home, (void *)"sip:my.domain:5060");
446   b = url_hdup(home, (void *)"sip:my.domain");
447   TEST_1(a); TEST_1(b);
448   TEST_1(url_cmp(a, b) > 0);
449   TEST_1(url_cmp_all(a, b) > 0);
450 
451   a = url_hdup(home, (void *)"sips:my.domain:5061");
452   b = url_hdup(home, (void *)"sips:my.domain");
453   TEST_1(a); TEST_1(b);
454   TEST_1(url_cmp(a, b) > 0);
455   TEST_1(url_cmp_all(a, b) > 0);
456 
457   a = url_hdup(home, (void *)"sip:my.domain");
458   b = url_hdup(home, (void *)"SIP:MY.DOMAIN");
459   TEST_1(a); TEST_1(b);
460   TEST_1(url_cmp(a, b) == 0);
461   TEST_1(url_cmp_all(a, b) == 0);
462 
463   su_home_deinit(home);
464 
465   END();
466 }
467 
test_wv(void)468 int test_wv(void)
469 {
470   /* wv urls */
471   su_home_t home[1] = { SU_HOME_INIT(home) };
472   url_t wv[1] = { URL_INIT_AS(wv) };
473   url_t *u, url[1];
474   char *tst;
475   char wvurl[] = "wv:+12345678@imps.com";
476   char wv2[sizeof(wvurl) + 32];
477 
478   BEGIN();
479 
480   TEST_S(url_scheme(url_wv), "wv");
481 
482   wv->url_user = "+12345678";
483   wv->url_host = "imps.com";
484 
485   TEST_1(tst = su_strdup(home, wvurl));
486   TEST_1(url_d(url, tst) == 0);
487   TEST_1(url_cmp(wv, url) == 0);
488   TEST_1(url_cmp(url_hdup(home, (void *)"wv:+12345678@imps.com"), url) == 0);
489   TEST(url->url_type, url_wv);
490   TEST_1(u = url_hdup(home, url));
491   TEST(u->url_type, url_wv);
492   TEST_1(url_cmp(wv, u) == 0);
493   TEST_SIZE(url_e(wv2, sizeof(wv2), u), strlen(wvurl));
494   TEST_1(strcmp(wv2, wvurl) == 0);
495   TEST_SIZE(snprintf(wv2, sizeof(wv2), URL_PRINT_FORMAT,
496 		     URL_PRINT_ARGS(wv)), strlen(wvurl));
497   TEST_1(strcmp(wv2, wvurl) == 0);
498 
499   url_digest(hash1, sizeof(hash1), url, NULL);
500   url_digest(hash2, sizeof(hash2), (url_t *)wvurl, NULL);
501   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
502 
503   TEST_1(u = url_hdup(home, (void*)"wv:/managers@imps.com"));
504   TEST_S(u->url_user, "/managers");
505 
506   su_home_deinit(home);
507 
508   END();
509 }
510 
511 
test_tel(void)512 int test_tel(void)
513 {
514   /* tel urls: RFC 3906 */
515   su_home_t home[1] = { SU_HOME_INIT(home) };
516   url_t tel[1] = { URL_INIT_AS(tel) };
517   url_t *u, url[1];
518   char *tst;
519   char telurl[] =
520     "tel:+12345678"
521     ";param=1;param=2"
522     "?From=foo@bar&To=bar@baz#unf";
523   char tel2[sizeof(telurl) + 32];
524   url_t *a, *b;
525 
526   BEGIN();
527 
528   TEST_S(url_scheme(url_tel), "tel");
529 
530   tel->url_user = "+12345678";
531   tel->url_params = "param=1;param=2";
532   tel->url_headers = "From=foo@bar&To=bar@baz";
533   tel->url_fragment = "unf";
534 
535   TEST_1(tst = su_strdup(home, telurl));
536   TEST_1(url_d(url, tst) == 0);
537   TEST_1(url_cmp(tel, url) == 0);
538   TEST_1(url_cmp(url_hdup(home, (url_t const *)"tel:+12345678"
539 			  ";param=1;param=2"
540 			  "?From=foo@bar&To=bar@baz#unf"), url) == 0);
541   TEST(url->url_type, url_tel);
542   TEST_1(u = url_hdup(home, url));
543   TEST(u->url_type, url_tel);
544   TEST_1(url_cmp(tel, u) == 0);
545   TEST_SIZE(url_e(tel2, sizeof(tel2), u), strlen(telurl));
546   TEST_1(strcmp(tel2, telurl) == 0);
547   TEST_SIZE(snprintf(tel2, sizeof(tel2), URL_PRINT_FORMAT,
548 		     URL_PRINT_ARGS(tel)), strlen(telurl));
549   TEST_1(strcmp(tel2, telurl) == 0);
550 
551   url_digest(hash1, sizeof(hash1), url, NULL);
552   url_digest(hash2, sizeof(hash2), (url_t *)telurl, NULL);
553   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
554 
555   a = url_hdup(home, (void *)"tel:+1.245.62357");
556   b = url_hdup(home, (void *)"tel:+(1).245.62357");
557   TEST_1(a); TEST_1(b);
558   TEST_1(url_cmp(a, b) == 0);
559   TEST_1(url_cmp_all(a, b) == 0);
560 
561   su_home_deinit(home);
562 
563   END();
564 }
565 
test_fax(void)566 int test_fax(void)
567 {
568   /* fax urls */
569   su_home_t home[1] = { SU_HOME_INIT(home) };
570   url_t fax[1] = { URL_INIT_AS(fax) };
571   url_t *u, url[1];
572   char *tst;
573   char faxurl[] =
574     "fax:+12345678"
575     ";param=1;param=2"
576     "?From=foo@bar&To=bar@baz#unf";
577   char fax2[sizeof(faxurl) + 32];
578 
579   BEGIN();
580 
581   TEST_S(url_scheme(url_fax), "fax");
582 
583   fax->url_user = "+12345678";
584   fax->url_params = "param=1;param=2";
585   fax->url_headers = "From=foo@bar&To=bar@baz";
586   fax->url_fragment = "unf";
587 
588   TEST_1(tst = su_strdup(home, faxurl));
589   TEST_1(url_d(url, tst) == 0);
590   TEST_1(url_cmp(fax, url) == 0);
591   TEST(url->url_type, url_fax);
592   TEST_1(u = url_hdup(home, url));
593   TEST(u->url_type, url_fax);
594   TEST_1(url_cmp(fax, u) == 0);
595   TEST_SIZE(url_e(fax2, sizeof(fax2), u), strlen(faxurl));
596   TEST_1(strcmp(fax2, faxurl) == 0);
597   TEST_SIZE(snprintf(fax2, sizeof(fax2), URL_PRINT_FORMAT,
598 		     URL_PRINT_ARGS(fax)), strlen(faxurl));
599   TEST_1(strcmp(fax2, faxurl) == 0);
600 
601 
602   url_digest(hash1, sizeof(hash1), url, NULL);
603   url_digest(hash2, sizeof(hash2), (url_t *)faxurl, NULL);
604   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
605 
606   su_home_deinit(home);
607 
608   END();
609 }
610 
test_modem(void)611 int test_modem(void)
612 {
613   /* modem urls */
614   su_home_t home[1] = { SU_HOME_INIT(home) };
615   url_t modem[1] = { URL_INIT_AS(modem) };
616   url_t *u, url[1];
617   char *tst;
618   char modemurl[] =
619     "modem:+12345678"
620     ";param=1;param=2"
621     "?From=foo@bar&To=bar@baz#unf";
622   char modem2[sizeof(modemurl) + 32];
623 
624   BEGIN();
625 
626   TEST_S(url_scheme(url_modem), "modem");
627 
628   modem->url_user = "+12345678";
629   modem->url_params = "param=1;param=2";
630   modem->url_headers = "From=foo@bar&To=bar@baz";
631   modem->url_fragment = "unf";
632 
633   TEST_1(tst = su_strdup(home, modemurl));
634   TEST_1(url_d(url, tst) == 0);
635   TEST_1(url_cmp(modem, url) == 0);
636   TEST(url->url_type, url_modem);
637   TEST_1(u = url_hdup(home, url));
638   TEST(u->url_type, url_modem);
639   TEST_1(url_cmp(modem, u) == 0);
640   TEST_SIZE(url_e(modem2, sizeof(modem2), u), strlen(modemurl));
641   TEST_1(strcmp(modem2, modemurl) == 0);
642   TEST_SIZE(snprintf(modem2, sizeof(modem2), URL_PRINT_FORMAT,
643 		     URL_PRINT_ARGS(modem)), strlen(modemurl));
644   TEST_1(strcmp(modem2, modemurl) == 0);
645 
646   url_digest(hash1, sizeof(hash1), url, NULL);
647   url_digest(hash2, sizeof(hash2), (url_t *)modemurl, NULL);
648   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
649 
650   su_home_deinit(home);
651 
652   END();
653 }
654 
test_file(void)655 int test_file(void)
656 {
657   /* Test a url with path like file:/foo/bar  */
658   char fileurl[] = "file:///foo/bar";
659   url_t file[1] = { URL_INIT_AS(file) };
660   su_home_t home[1] = { SU_HOME_INIT(home) };
661   char *tst;
662   url_t *u, url[1];
663   char buf1[sizeof(fileurl) + 32];
664   char buf2[sizeof(fileurl) + 32];
665 
666   BEGIN();
667 
668   TEST_S(url_scheme(url_file), "file");
669 
670   TEST_1(tst = su_strdup(home, fileurl));
671   TEST(url_d(url, tst), 0);
672   TEST_S(url->url_host, "");
673   file->url_root = '/';
674   file->url_host = "";
675   file->url_path = "foo/bar";
676   TEST(url_cmp(file, url), 0);
677   TEST(url->url_type, url_file);
678   TEST_1(u = url_hdup(home, url));
679   TEST(u->url_type, url_file);
680   TEST(url_cmp(file, u), 0);
681   TEST_SIZE(url_e(buf1, sizeof(buf1), u), strlen(fileurl));
682   TEST_S(buf1, fileurl);
683   TEST_SIZE(snprintf(buf2, sizeof(buf2), URL_PRINT_FORMAT, URL_PRINT_ARGS(u)),
684 	    strlen(fileurl));
685   TEST_S(buf2, fileurl);
686 
687   url_digest(hash1, sizeof(hash1), url, NULL);
688   url_digest(hash2, sizeof(hash2), (url_t *)fileurl, NULL);
689   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
690 
691   su_home_deinit(home);
692 
693   END();
694 }
695 
test_ldap(void)696 int test_ldap(void)
697 {
698   /* Test a LDAP url  */
699   char ldapurl[] = "ldap://cn=Manager,o=nokia:secret@localhost:389/ou=devices,o=nokia";
700   url_t ldap[1] = { URL_INIT_AS(file) };
701   su_home_t home[1] = { SU_HOME_INIT(home) };
702   char *tst;
703   url_t *u, url[1];
704   char buf1[sizeof(ldapurl) + 32];
705   char buf2[sizeof(ldapurl) + 32];
706 
707   BEGIN();
708 
709   ldap->url_type = url_unknown;
710   ldap->url_scheme = "ldap";
711 
712   /* TEST_S(url_scheme(url_ldap), "ldap"); */
713 
714   TEST_1(tst = su_strdup(home, ldapurl));
715   TEST(url_d(url, tst), 0);
716 
717   TEST_S(url->url_user, "cn=Manager,o=nokia:secret");
718   /* TEST_S(url->url_password, "secret"); */
719   TEST_S(url->url_host, "localhost");
720   TEST_S(url->url_port, "389");
721   TEST_S(url->url_path, "ou=devices,o=nokia");
722 
723   ldap->url_user = "cn=Manager,o=nokia";
724   ldap->url_password = "secret";
725   ldap->url_user = "cn=Manager,o=nokia:secret", ldap->url_password = NULL;
726   ldap->url_host = "localhost";
727   ldap->url_port = "389";
728   ldap->url_path = "ou=devices,o=nokia";
729 
730   TEST(url_cmp(ldap, url), 0);
731   TEST(url->url_type, url_unknown);
732   TEST_S(url->url_scheme, "ldap");
733   TEST_1(u = url_hdup(home, url));
734   TEST(u->url_type, url_unknown);
735   TEST_S(u->url_scheme, "ldap");
736   TEST(url_cmp(ldap, u), 0);
737   TEST_SIZE(url_e(buf1, sizeof(buf1), u), strlen(ldapurl));
738   TEST_S(buf1, ldapurl);
739   TEST_SIZE(snprintf(buf2, sizeof(buf2), URL_PRINT_FORMAT, URL_PRINT_ARGS(u)),
740 	    strlen(ldapurl));
741   TEST_S(buf2, ldapurl);
742 
743   url_digest(hash1, sizeof(hash1), url, NULL);
744   url_digest(hash2, sizeof(hash2), (url_t *)ldapurl, NULL);
745   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
746 
747   su_home_deinit(home);
748 
749   END();
750 }
751 
test_rtsp(void)752 int test_rtsp(void)
753 {
754   /* RTSP urls */
755   su_home_t home[1] = { SU_HOME_INIT(home) };
756   url_t rtsp[1] = { URL_INIT_AS(rtsp) };
757   url_t *u, url[1];
758   char *tst;
759   char rtspurl[] = "rtsp://example.com:42/barfoo.rm";
760   char rtspuurl[] = "rtspu://example.com:42/barfoo.rm";
761   char rtsp2[sizeof(rtspurl) + 32];
762 
763   BEGIN();
764 
765   TEST_S(url_scheme(url_rtsp), "rtsp");
766   TEST_S(url_scheme(url_rtspu), "rtspu");
767 
768   rtsp->url_root = 1;
769   rtsp->url_host = "example.com";
770   rtsp->url_port = "42";
771   rtsp->url_path = "barfoo.rm";
772 
773   TEST_1(tst = su_strdup(home, rtspurl));
774   TEST_1(url_d(url, tst) == 0);
775   TEST_1(url_cmp(rtsp, url) == 0);
776   TEST(url->url_type, url_rtsp);
777   TEST_1(u = url_hdup(home, url));
778   TEST(u->url_type, url_rtsp);
779   TEST_1(url_cmp(rtsp, u) == 0);
780   TEST(url_e(rtsp2, sizeof(rtsp2), u), strlen(rtspurl));
781   TEST_1(strcmp(rtsp2, rtspurl) == 0);
782   TEST_SIZE(snprintf(rtsp2, sizeof(rtsp2), URL_PRINT_FORMAT,
783 		     URL_PRINT_ARGS(rtsp)), strlen(rtspurl));
784   TEST_1(strcmp(rtsp2, rtspurl) == 0);
785 
786   url_digest(hash1, sizeof(hash1), url, NULL);
787   url_digest(hash2, sizeof(hash2), (url_t *)rtspurl, NULL);
788   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
789 
790   su_home_deinit(home);
791   rtsp->url_type = url_rtspu, rtsp->url_scheme = "rtspu";
792 
793   TEST_1(tst = su_strdup(home, rtspuurl));
794   TEST_1(url_d(url, tst) == 0);
795   TEST_1(url_cmp(rtsp, url) == 0);
796   TEST(url->url_type, url_rtspu);
797 
798   url_digest(hash1, sizeof(hash1), url, NULL);
799   url_digest(hash2, sizeof(hash2), (url_t *)rtspuurl, NULL);
800   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
801 
802   su_home_deinit(home);
803 
804   END();
805 }
806 
test_http(void)807 int test_http(void)
808 {
809   /* http urls */
810   su_home_t home[1] = { SU_HOME_INIT(home) };
811   url_t http[1] = { URL_INIT_AS(http) };
812   url_t *u, url[1];
813   char *tst;
814   char httpurl[] =
815     "http://user:pass@host:32/foo;param=1/bar;param=3"
816     "?From=foo@bar&To=bar@baz#unf";
817   char http2[sizeof(httpurl) + 32];
818 
819   char queryonly[] =
820     "http://some.host?query";
821 
822   BEGIN();
823 
824   TEST_S(url_scheme(url_http), "http");
825   TEST_S(url_scheme(url_https), "https");
826 
827   http->url_root = '/';
828   http->url_user = "user";
829   http->url_password = "pass";
830   http->url_host = "host";
831   http->url_port = "32";
832   http->url_path = "foo;param=1/bar;param=3";
833   http->url_headers = "From=foo@bar&To=bar@baz";
834   http->url_fragment = "unf";
835 
836   TEST_1(tst = su_strdup(home, httpurl));
837   TEST_1(url_d(url, tst) == 0);
838   TEST_1(url_cmp(http, url) == 0);
839   TEST(url->url_type, url_http);
840   TEST_1(u = url_hdup(home, url));
841   TEST(u->url_type, url_http);
842   TEST_1(url_cmp(http, u) == 0);
843   TEST_SIZE(url_e(http2, sizeof(http2), u), strlen(httpurl));
844   TEST_1(strcmp(http2, httpurl) == 0);
845   TEST_SIZE(snprintf(http2, sizeof(http2), URL_PRINT_FORMAT,
846 		     URL_PRINT_ARGS(http)), strlen(httpurl));
847   TEST_1(strcmp(http2, httpurl) == 0);
848 
849   url_digest(hash1, sizeof(hash1), http, NULL);
850   url_digest(hash2, sizeof(hash2), (url_t *)httpurl, NULL);
851   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
852 
853   memset(url, 0, sizeof url);
854   TEST_1(tst = su_strdup(home, queryonly));
855   TEST(url_d(url, tst), 0);
856   TEST_S(url->url_host, "some.host");
857   TEST_S(url->url_headers, "query");
858   TEST_S(url->url_params, NULL);
859 
860   TEST_1(u = url_hdup(home, (void *)"http://[::1]/test;ing?here"));
861   TEST_S(u->url_host, "[::1]");
862   TEST_S(u->url_path, "test;ing");
863   TEST_S(u->url_headers, "here");
864 
865   url_digest(hash1, sizeof(hash1), u, NULL);
866   url_digest(hash2, sizeof(hash2), (url_t *)"http://[::1]/test;ing?here",
867 	     NULL);
868   TEST(memcmp(hash1, hash2, sizeof(hash1)), 0);
869 
870   su_home_deinit(home);
871 
872   END();
873 }
874 
test_sanitizing(void)875 int test_sanitizing(void)
876 {
877   url_t url[1];
878   char www[] = "www.hut.fi";
879   char ftp[] = "ftp.hut.fi";
880   char www2[] = "iptel.hut.fi/humppa";
881   char sip[] = "test.host";
882   char buf[64];
883 
884   BEGIN();
885 
886   TEST_1(url_d(url, www) == 0);
887   TEST_1(url_sanitize(url) == 0);
888   TEST(url->url_type, url_http);
889   snprintf(buf, sizeof(buf), URL_PRINT_FORMAT, URL_PRINT_ARGS(url));
890   TEST_S(buf, "http://www.hut.fi");
891 
892   TEST_1(url_d(url, ftp) == 0);
893   TEST_1(url_sanitize(url) == 0);
894   TEST(url->url_type, url_ftp);
895   snprintf(buf, sizeof(buf), URL_PRINT_FORMAT, URL_PRINT_ARGS(url));
896   TEST_S(buf, "ftp://ftp.hut.fi");
897 
898   TEST_1(url_d(url, www2) == 0);
899   TEST_1(url_sanitize(url) == 0);
900   TEST(url->url_type, url_http);
901   snprintf(buf, sizeof(buf), URL_PRINT_FORMAT, URL_PRINT_ARGS(url));
902   TEST_S(buf, "http://iptel.hut.fi/humppa");
903 
904   TEST_1(url_d(url, sip) == 0);
905   TEST_1(url_sanitize(url) == 0);
906   TEST(url->url_type, url_sip);
907   snprintf(buf, sizeof(buf), URL_PRINT_FORMAT, URL_PRINT_ARGS(url));
908   TEST_S(buf, "sip:test.host");
909 
910   END();
911 }
912 
913 
test_tags(void)914 int test_tags(void)
915 {
916   url_t u0[1];
917   url_t *u1 = NULL;
918   url_t const *u2 = (void *)-1;
919   url_t const u3[1] = { URL_INIT_AS(sip) };
920   char c0[] = "http://www.nokia.com";
921   char const *c1 = "http://goodfeel.nokia.com";
922   char *c2 = "http://forum.nokia.com";
923   char const c3[] = "http://www.research.nokia.com";
924   url_string_t *us0 = NULL;
925 
926   tagi_t *lst, *dup;
927 
928   tag_value_t value;
929   char *s;
930   su_home_t home[1] = { SU_HOME_INIT(home) };
931 
932   BEGIN();
933 
934   TEST(t_scan(urltag_url, home, c0, &value), 0);
935   TEST_S(s = url_as_string(home, (url_t *)value), c0);
936 
937   TEST(t_scan(urltag_url, home, c3, &value), 0);
938   TEST_S(s = url_as_string(home, (url_t *)value), c3);
939 
940   TEST_1(url_d(u0, c0) == 0);
941 
942   lst = tl_list(URLTAG_URL(u0),
943 		URLTAG_URL(u1),
944 		URLTAG_URL(u2),
945 		URLTAG_URL(u3),
946 		URLTAG_URL(c0),
947 		URLTAG_URL(c1),
948 		URLTAG_URL(c2),
949 		URLTAG_URL(c3),
950 		URLTAG_URL(us0),
951 		TAG_NULL());
952 
953   TEST_1(lst);
954 
955   dup = tl_adup(home, lst);
956 
957   tl_vfree(lst);
958 
959   su_free(home, dup);
960 
961   su_home_deinit(home);
962 
963   END();
964 }
965 
966 #include <sofia-sip/su_tag_class.h>
967 
test_tag_filter(void)968 int test_tag_filter(void)
969 {
970   BEGIN();
971 
972 #undef TAG_NAMESPACE
973 #define TAG_NAMESPACE "test"
974   tag_typedef_t tag_a = STRTAG_TYPEDEF(a);
975 #define TAG_A(s)      tag_a, tag_str_v((s))
976   tag_typedef_t tag_b = STRTAG_TYPEDEF(b);
977 #define TAG_B(s)      tag_b, tag_str_v((s))
978 
979   tagi_t filter[2] = {{ URLTAG_ANY() }, { TAG_END() }};
980 
981   tagi_t *lst, *result;
982 
983   lst = tl_list(TAG_A("X"),
984 		TAG_SKIP(2),
985 		URLTAG_URL((void *)"urn:foo"),
986 		TAG_B("Y"),
987 		URLTAG_URL((void *)"urn:bar"),
988 		TAG_NULL());
989 
990   TEST_1(lst);
991 
992   result = tl_afilter(NULL, filter, lst);
993 
994   TEST_1(result);
995   TEST_P(result[0].t_tag, urltag_url);
996   TEST_P(result[1].t_tag, urltag_url);
997 
998   tl_vfree(lst);
999   free(result);
1000 
1001   END();
1002 }
1003 
1004 #if 0
1005 /* This is just a spike. How we can get
1006  *   register_printf_function('U', printf_url, printf_url_info)
1007  * run while initializing?
1008  */
1009 #include <printf.h>
1010 
1011 int printf_url(FILE *fp,
1012 	       const struct printf_info *info,
1013 	       const void * const *args)
1014 {
1015   url_t const *url = *(url_t **)args[0];
1016 
1017   return fprintf(fp, URL_PRINT_FORMAT, URL_PRINT_ARGS(url));
1018 }
1019 
1020 /* This is the appropriate argument information function for `printf_url'.  */
1021 int printf_url_info(const struct printf_info *info,
1022 		    size_t n, int *argtypes)
1023 {
1024   if (n > 0) {
1025     argtypes[0] = PA_POINTER;
1026     return 1;
1027   }
1028   return 0;
1029 }
1030 #endif
1031 
test_print(void)1032 int test_print(void)
1033 {
1034 #if 0
1035   url_t u0[1];
1036   url_t *u1 = NULL;
1037   url_t const *u2 = (void *)-1;
1038   url_t const u3[1] = { URL_INIT_AS(sip) };
1039   char c0[] = "http://www.nokia.com/";
1040   char c1[] = "http://goodfeel.nokia.com/test";
1041   char c2[] = "/test2/";
1042   char c3[] = "///file/";
1043 
1044   tagi_t *lst;
1045 
1046   BEGIN();
1047 
1048   TEST(register_printf_function('U', printf_url, printf_url_info), 0);
1049 
1050   TEST(url_d(u0, c0), 0);
1051   printf("URL is %U\n", u0);
1052 
1053   TEST(url_d(u0, c1), 0);
1054   printf("URL is %U\n", u0);
1055 
1056   TEST(url_d(u0, c2), 0);
1057   printf("URL is %U\n", u0);
1058 
1059   TEST(url_d(u0, c3), 0);
1060   printf("URL is %U\n", u0);
1061 #else
1062   BEGIN();
1063 #endif
1064 
1065   END();
1066 }
1067 
usage(int exitcode)1068 void usage(int exitcode)
1069 {
1070   fprintf(stderr, "usage: %s [-v] [-a]\n", name);
1071   exit(exitcode);
1072 }
1073 
main(int argc,char * argv[])1074 int main(int argc, char *argv[])
1075 {
1076   int retval = 0;
1077   int i;
1078 
1079   for (i = 1; argv[i]; i++) {
1080     if (strcmp(argv[i], "-v") == 0)
1081       tstflags |= tst_verbatim;
1082     else if (strcmp(argv[i], "-a") == 0)
1083       tstflags |= tst_abort;
1084     else
1085       usage(1);
1086   }
1087 
1088 #if HAVE_OPEN_C
1089   tstflags |= tst_verbatim;
1090 #endif
1091 
1092   retval |= test_quote(); fflush(stdout);
1093   retval |= test_any(); fflush(stdout);
1094   retval |= test_sip(); fflush(stdout);
1095   retval |= test_wv(); fflush(stdout);
1096   retval |= test_tel(); fflush(stdout);
1097   retval |= test_fax(); fflush(stdout);
1098   retval |= test_modem(); fflush(stdout);
1099   retval |= test_file(); fflush(stdout);
1100   retval |= test_ldap(); fflush(stdout);
1101   retval |= test_rtsp(); fflush(stdout);
1102   retval |= test_http(); fflush(stdout);
1103   retval |= test_sanitizing(); fflush(stdout);
1104   retval |= test_tags(); fflush(stdout);
1105   retval |= test_print(); fflush(stdout);
1106   retval |= test_tag_filter(); fflush(stdout);
1107 
1108   return retval;
1109 }
1110 
1111