Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / osip_uri.c
1 /*
2   The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3   Copyright (C) 2001,2002,2003  Aymeric MOIZARD jack@atosc.org
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10   This library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14   
15   You should have received a copy of the GNU Lesser General Public
16   License along with this library; if not, write to the Free Software
17   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19
20 #include <osipparser2/osip_port.h>
21 #include <osipparser2/osip_message.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24
25 /* allocate a new url structure */
26 /* OUTPUT: osip_uri_t *url | structure to save results.   */
27 /* OUTPUT: err_t *err | structure to store error.   */
28 /* return -1 on error */
29 int
30 osip_uri_init (osip_uri_t ** url)
31 {
32   *url = (osip_uri_t *) osip_malloc (sizeof (osip_uri_t));
33   if (*url == NULL)
34     return -1;
35   (*url)->scheme = NULL;
36   (*url)->username = NULL;
37   (*url)->password = NULL;
38   (*url)->host = NULL;
39   (*url)->port = NULL;
40
41   (*url)->url_params = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
42   if ((*url)->url_params == NULL)
43     {
44       osip_free (*url);
45       *url = NULL;
46       return -1;
47     }
48   osip_list_init ((*url)->url_params);
49
50   (*url)->url_headers = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
51   if ((*url)->url_headers == NULL)
52     {
53       osip_free ((*url)->url_params);
54       osip_free (*url);
55       *url = NULL;
56       return -1;
57     }
58   osip_list_init ((*url)->url_headers);
59
60   (*url)->string = NULL;
61   return 0;
62 }
63
64 /* examples:
65    sip:j.doe@big.com;maddr=239.255.255.1;ttl=15
66    sip:j.doe@big.com
67    sip:j.doe:secret@big.com;transport=tcp
68    sip:j.doe@big.com?subject=project
69    sip:+1-212-555-1212:1234@gateway.com;user=phone
70    sip:1212@gateway.com
71    sip:alice@10.1.2.3
72    sip:alice@example.com
73    sip:alice@registrar.com;method=REGISTER
74
75    NOT EQUIVALENT:
76    SIP:JUSER@ExAmPlE.CoM;Transport=udp
77    sip:juser@ExAmPlE.CoM;Transport=UDP
78 */
79
80 /* this method search for the separator and   */
81 /* return it only if it is located before the */
82 /* second separator. */
83 char *
84 next_separator (const char *ch, int separator_osip_to_find,
85                 int before_separator)
86 {
87   char *ind;
88   char *tmp;
89
90   ind = strchr (ch, separator_osip_to_find);
91   if (ind == NULL)
92     return NULL;
93
94   tmp = NULL;
95   if (before_separator != 0)
96     tmp = strchr (ch, before_separator);
97
98   if (tmp != NULL)
99     {
100       if (ind < tmp)
101         return ind;
102     }
103   else
104     return ind;
105
106   return NULL;
107 }
108
109 /* parse the sip url.                                */
110 /* INPUT : char *buf | url to be parsed.*/
111 /* OUTPUT: osip_uri_t *url | structure to save results.   */
112 /* OUTPUT: err_t *err | structure to store error.   */
113 /* return -1 on error */
114 int
115 osip_uri_parse (osip_uri_t * url, const char *buf)
116 {
117   char *username;
118   char *password;
119   char *host;
120   const char *port;
121   const char *params;
122   const char *headers;
123   const char *tmp;
124
125   /* basic tests */
126   if (buf == NULL || buf[0] == '\0')
127     return -1;
128
129   tmp = strchr (buf, ':');
130   if (tmp == NULL)
131     return -1;
132
133   if (tmp - buf < 2)
134     return -1;
135   url->scheme = (char *) osip_malloc (tmp - buf + 1);
136   if (url->scheme == NULL)
137     return -1;
138   osip_strncpy (url->scheme, buf, tmp - buf);
139
140   if (strlen (url->scheme) < 3 ||
141       (0 != osip_strncasecmp (url->scheme, "sip", 3)
142        && 0 != osip_strncasecmp (url->scheme, "sips", 4)))
143     {                           /* Is not a sipurl ! */
144       size_t i = strlen (tmp + 1);
145
146       if (i < 2)
147         return -1;
148       url->string = (char *) osip_malloc (i + 1);
149       if (url->string == NULL)
150         return -1;
151       osip_strncpy (url->string, tmp + 1, i);
152       return 0;
153     }
154
155   /*  law number 1:
156      if ('?' exists && is_located_after '@')
157      or   if ('?' exists && '@' is not there -no username-)
158      =====>  HEADER_PARAM EXIST
159      =====>  start at index(?)
160      =====>  end at the end of url
161    */
162
163   /* find the beginning of host */
164   username = strchr (buf, ':');
165   /* if ':' does not exist, the url is not valid */
166   if (username == NULL)
167     return -1;
168
169   host = strchr (buf, '@');
170
171   if (host == NULL)
172     host = username;
173   else
174     /* username exists */
175     {
176       password = next_separator (username + 1, ':', '@');
177       if (password == NULL)
178         password = host;
179       else
180         /* password exists */
181         {
182           if (host - password < 2)
183             return -1;
184           url->password = (char *) osip_malloc (host - password);
185           if (url->password == NULL)
186             return -1;
187           osip_strncpy (url->password, password + 1, host - password - 1);
188           __osip_uri_unescape (url->password);
189         }
190       if (password - username < 2)
191         return -1;
192       {
193         url->username = (char *) osip_malloc (password - username);
194         if (url->username == NULL)
195           return -1;
196         osip_strncpy (url->username, username + 1, password - username - 1);
197         __osip_uri_unescape (url->username);
198       }
199     }
200
201
202   /* search for header after host */
203   headers = strchr (host, '?');
204
205   if (headers == NULL)
206     headers = buf + strlen (buf);
207   else
208     /* headers exist */
209     osip_uri_parse_headers (url, headers);
210
211
212   /* search for params after host */
213   params = strchr (host, ';');  /* search for params after host */
214   if (params == NULL)
215     params = headers;
216   else
217     /* params exist */
218     {
219       char *tmpbuf;
220       if (headers - params + 1 < 2)
221         return -1;
222       tmpbuf = osip_malloc (headers - params + 1);
223       if (tmpbuf == NULL)
224         return -1;
225       tmpbuf = osip_strncpy (tmpbuf, params, headers - params);
226       osip_uri_parse_params (url, tmpbuf);
227       osip_free (tmpbuf);
228     }
229
230   port = params - 1;
231   while (port > host && *port != ']' && *port != ':')
232     port--;
233   if (*port == ':')
234     {
235       if (host == port)
236         port = params;
237       else
238         {
239           if ((params - port < 2) || (params - port > 8))
240             return -1;          /* error cases */
241           url->port = (char *) osip_malloc (params - port);
242           if (url->port == NULL)
243             return -1;
244           osip_strncpy (url->port, port + 1, params - port - 1);
245           osip_clrspace (url->port);
246         }
247     }
248   else
249     port = params;
250   /* adjust port for ipv6 address */
251   tmp = port;
252   while (tmp > host && *tmp != ']')
253     tmp--;
254   if (*tmp == ']')
255     {
256       port = tmp;
257       while (host < port && *host != '[')
258         host++;
259       if (host >= port)
260         return -1;
261     }
262
263   if (port - host < 2)
264     return -1;
265   url->host = (char *) osip_malloc (port - host);
266   if (url->host == NULL)
267     return -1;
268   osip_strncpy (url->host, host + 1, port - host - 1);
269   osip_clrspace (url->host);
270
271   return 0;
272 }
273
274 void
275 osip_uri_set_scheme (osip_uri_t * url, char *scheme)
276 {
277   url->scheme = scheme;
278 }
279
280 char *
281 osip_uri_get_scheme (osip_uri_t * url)
282 {
283   if (url == NULL)
284     return NULL;
285   return url->scheme;
286 }
287
288 void
289 osip_uri_set_username (osip_uri_t * url, char *username)
290 {
291   url->username = username;
292 }
293
294 char *
295 osip_uri_get_username (osip_uri_t * url)
296 {
297   if (url == NULL)
298     return NULL;
299   return url->username;
300 }
301
302 void
303 osip_uri_set_password (osip_uri_t * url, char *password)
304 {
305   url->password = password;
306 }
307
308 char *
309 osip_uri_get_password (osip_uri_t * url)
310 {
311   if (url == NULL)
312     return NULL;
313   return url->password;
314 }
315
316 void
317 osip_uri_set_host (osip_uri_t * url, char *host)
318 {
319   url->host = host;
320 }
321
322 char *
323 osip_uri_get_host (osip_uri_t * url)
324 {
325   if (url == NULL)
326     return NULL;
327   return url->host;
328 }
329
330 void
331 osip_uri_set_port (osip_uri_t * url, char *port)
332 {
333   url->port = port;
334 }
335
336 char *
337 osip_uri_get_port (osip_uri_t * url)
338 {
339   if (url == NULL)
340     return NULL;
341   return url->port;
342 }
343
344
345 int
346 osip_uri_parse_headers (osip_uri_t * url, const char *headers)
347 {
348   char *and;
349   char *equal;
350
351   /* find '=' wich is the separator for one header */
352   /* find ';' wich is the separator for multiple headers */
353
354   equal = strchr (headers, '=');
355   and = strchr (headers + 1, '&');
356
357   if (equal == NULL)            /* each header MUST have a value */
358     return -1;
359
360   do
361     {
362       char *hname;
363       char *hvalue;
364
365       hname = (char *) osip_malloc (equal - headers);
366       if (hname == NULL)
367         return -1;
368       osip_strncpy (hname, headers + 1, equal - headers - 1);
369       __osip_uri_unescape (hname);
370
371       if (and != NULL)
372         {
373           if (and - equal < 2)
374             {
375               osip_free (hname);
376               return -1;
377             }
378           hvalue = (char *) osip_malloc (and - equal);
379           if (hvalue == NULL)
380             {
381               osip_free (hname);
382               return -1;
383             }
384           osip_strncpy (hvalue, equal + 1, and - equal - 1);
385           __osip_uri_unescape (hvalue);
386         }
387       else
388         {                       /* this is for the last header (no and...) */
389           if (headers + strlen (headers) - equal + 1 < 2)
390             {
391               osip_free (hname);
392               return -1;
393             }
394           hvalue =
395             (char *) osip_malloc (headers + strlen (headers) - equal + 1);
396           if (hvalue == NULL)
397             {
398               osip_free (hname);
399               return -1;
400             }
401           osip_strncpy (hvalue, equal + 1,
402                         headers + strlen (headers) - equal);
403           __osip_uri_unescape (hvalue);
404         }
405
406       osip_uri_uheader_add (url, hname, hvalue);
407
408       if (and == NULL)          /* we just set the last header */
409         equal = NULL;
410       else                      /* continue on next header */
411         {
412           headers = and;
413           equal = strchr (headers, '=');
414           and = strchr (headers + 1, '&');
415           if (equal == NULL)    /* each header MUST have a value */
416             return -1;
417         }
418     }
419   while (equal != NULL);
420   return 0;
421 }
422
423 int
424 osip_uri_parse_params (osip_uri_t * url, const char *params)
425 {
426   char *pname;
427   char *pvalue;
428
429   const char *comma;
430   const char *equal;
431
432   /* find '=' wich is the separator for one param */
433   /* find ';' wich is the separator for multiple params */
434
435   equal = next_separator (params + 1, '=', ';');
436   comma = strchr (params + 1, ';');
437
438   while (comma != NULL)
439     {
440       if (equal == NULL)
441         {
442           equal = comma;
443           pvalue = NULL;
444         }
445       else
446         {
447           if (comma - equal < 2)
448             return -1;
449           pvalue = (char *) osip_malloc (comma - equal);
450           if (pvalue == NULL)
451             return -1;
452           osip_strncpy (pvalue, equal + 1, comma - equal - 1);
453           __osip_uri_unescape (pvalue);
454         }
455
456       if (equal - params < 2)
457         {
458           osip_free (pvalue);
459           return -1;
460         }
461       pname = (char *) osip_malloc (equal - params);
462       if (pname == NULL)
463         {
464           osip_free (pvalue);
465           return -1;
466         }
467       osip_strncpy (pname, params + 1, equal - params - 1);
468       __osip_uri_unescape (pname);
469
470       osip_uri_uparam_add (url, pname, pvalue);
471
472       params = comma;
473       equal = next_separator (params + 1, '=', ';');
474       comma = strchr (params + 1, ';');
475     }
476
477   /* this is the last header (comma==NULL) */
478   comma = params + strlen (params);
479
480   if (equal == NULL)
481     {
482       equal = comma;            /* at the end */
483       pvalue = NULL;
484     }
485   else
486     {
487       if (comma - equal < 2)
488         return -1;
489       pvalue = (char *) osip_malloc (comma - equal);
490       if (pvalue == NULL)
491         return -1;
492       osip_strncpy (pvalue, equal + 1, comma - equal - 1);
493     }
494
495   if (equal - params < 2)
496     {
497       osip_free (pvalue);
498       return -1;
499     }
500   pname = (char *) osip_malloc (equal - params);
501   if (pname == NULL)
502     {
503       osip_free (pvalue);
504       return -1;
505     }
506   osip_strncpy (pname, params + 1, equal - params - 1);
507
508   osip_uri_uparam_add (url, pname, pvalue);
509
510   return 0;
511 }
512
513 int
514 osip_uri_to_str (const osip_uri_t * url, char **dest)
515 {
516   char *buf;
517   size_t len;
518   size_t plen;
519   char *tmp;
520   const char *scheme;
521
522   *dest = NULL;
523   if (url == NULL)
524     return -1;
525   if (url->host == NULL && url->string == NULL)
526     return -1;
527   if (url->scheme == NULL && url->string != NULL)
528     return -1;
529   if (url->string == NULL && url->scheme == NULL)
530     scheme = "sip";             /* default is sipurl */
531   else
532     scheme = url->scheme;
533
534   if (url->string != NULL)
535     {
536       buf = (char *) osip_malloc (strlen (scheme) + strlen (url->string) + 3);
537       if (buf == NULL)
538         return -1;
539       *dest = buf;
540       sprintf (buf, "%s:", scheme);
541       buf = buf + strlen (scheme) + 1;
542       sprintf (buf, "%s", url->string);
543       buf = buf + strlen (url->string);
544       return 0;
545     }
546
547   len = strlen (scheme) + 1 + strlen (url->host) + 5;
548   if (url->username != NULL)
549     len = len + (strlen (url->username) * 3) + 1;    /* count escaped char */
550   if (url->password != NULL)
551     len = len + (strlen (url->password) * 3) + 1;
552   if (url->port != NULL)
553     len = len + strlen (url->port) + 3;
554
555   buf = (char *) osip_malloc (len);
556   if (buf == NULL)
557     return -1;
558   tmp = buf;
559
560   sprintf (tmp, "%s:", scheme);
561   tmp = tmp + strlen (tmp);
562
563   if (url->username != NULL)
564     {
565       char *tmp2 = __osip_uri_escape_userinfo (url->username);
566
567       sprintf (tmp, "%s", tmp2);
568       osip_free (tmp2);
569       tmp = tmp + strlen (tmp);
570     }
571   if ((url->password != NULL) && (url->username != NULL))
572     {                           /* be sure that when a password is given, a username is also given */
573       char *tmp2 = __osip_uri_escape_password (url->password);
574
575       sprintf (tmp, ":%s", tmp2);
576       osip_free (tmp2);
577       tmp = tmp + strlen (tmp);
578     }
579   if (url->username != NULL)
580     {                           /* we add a '@' only when username is present... */
581       sprintf (tmp, "@");
582       tmp++;
583     }
584   if (strchr (url->host, ':') != NULL)
585     {
586       sprintf (tmp, "[%s]", url->host);
587       tmp = tmp + strlen (tmp);
588     }
589   else
590     {
591       sprintf (tmp, "%s", url->host);
592       tmp = tmp + strlen (tmp);
593     }
594   if (url->port != NULL)
595     {
596       sprintf (tmp, ":%s", url->port);
597       tmp = tmp + strlen (tmp);
598     }
599
600   {
601     int pos = 0;
602     osip_uri_param_t *u_param;
603
604     while (!osip_list_eol (url->url_params, pos))
605       {
606         char *tmp1;
607         char *tmp2 = NULL;
608
609         u_param = (osip_uri_param_t *) osip_list_get (url->url_params, pos);
610
611         tmp1 = __osip_uri_escape_uri_param (u_param->gname);
612         if (u_param->gvalue == NULL)
613           plen = strlen (tmp1) + 2;
614         else
615           {
616             tmp2 = __osip_uri_escape_uri_param (u_param->gvalue);
617             plen = strlen (tmp1) + strlen (tmp2) + 3;
618           }
619         len = len + plen;
620         buf = (char *) realloc (buf, len);
621         tmp = buf;
622         tmp = tmp + strlen (tmp);
623         if (u_param->gvalue == NULL)
624           sprintf (tmp, ";%s", tmp1);
625         else
626           {
627             sprintf (tmp, ";%s=%s", tmp1, tmp2);
628             osip_free (tmp2);
629           }
630         osip_free (tmp1);
631         pos++;
632       }
633   }
634
635   {
636     int pos = 0;
637     osip_uri_header_t *u_header;
638
639     while (!osip_list_eol (url->url_headers, pos))
640       {
641         char *tmp1;
642         char *tmp2;
643
644         u_header =
645           (osip_uri_header_t *) osip_list_get (url->url_headers, pos);
646         tmp1 = __osip_uri_escape_header_param (u_header->gname);
647         tmp2 = __osip_uri_escape_header_param (u_header->gvalue);
648
649         if (tmp1 == NULL || tmp2 == NULL)
650           {
651             osip_free (buf);
652             return -1;
653           }
654         plen = strlen (tmp1) + strlen (tmp2) + 4;
655
656         len = len + plen;
657         buf = (char *) realloc (buf, len);
658         tmp = buf;
659         tmp = tmp + strlen (tmp);
660         if (pos == 0)
661           {
662             sprintf (tmp, "?%s=%s", u_header->gname, u_header->gvalue);
663           }
664         else
665           sprintf (tmp, "&%s=%s", u_header->gname, u_header->gvalue);
666         osip_free (tmp1);
667         osip_free (tmp2);
668         pos++;
669       }
670   }
671
672   *dest = buf;
673   return 0;
674 }
675
676
677 void
678 osip_uri_free (osip_uri_t * url)
679 {
680   int pos = 0;
681
682   if (url == NULL)
683     return;
684   osip_free (url->scheme);
685   osip_free (url->username);
686   osip_free (url->password);
687   osip_free (url->host);
688   osip_free (url->port);
689
690   osip_uri_param_freelist (url->url_params);
691
692   {
693     osip_uri_header_t *u_header;
694
695     while (!osip_list_eol (url->url_headers, pos))
696       {
697         u_header =
698           (osip_uri_header_t *) osip_list_get (url->url_headers, pos);
699         osip_list_remove (url->url_headers, pos);
700         osip_uri_header_free (u_header);
701       }
702     osip_free (url->url_headers);
703   }
704
705   osip_free (url->string);
706
707   osip_free (url);
708 }
709
710 int
711 osip_uri_clone (const osip_uri_t * url, osip_uri_t ** dest)
712 {
713   int i;
714   osip_uri_t *ur;
715
716   *dest = NULL;
717   if (url == NULL)
718     return -1;
719   if (url->host == NULL && url->string == NULL)
720     return -1;
721
722   i = osip_uri_init (&ur);
723   if (i == -1)                  /* allocation failed */
724     return -1;
725   if (url->scheme != NULL)
726     ur->scheme = osip_strdup (url->scheme);
727   if (url->username != NULL)
728     ur->username = osip_strdup (url->username);
729   if (url->password != NULL)
730     ur->password = osip_strdup (url->password);
731   if (url->host != NULL)
732     ur->host = osip_strdup (url->host);
733   if (url->port != NULL)
734     ur->port = osip_strdup (url->port);
735   if (url->string != NULL)
736     ur->string = osip_strdup (url->string);
737
738   {
739     int pos = 0;
740     osip_uri_param_t *u_param;
741     osip_uri_param_t *dest_param;
742
743     while (!osip_list_eol (url->url_params, pos))
744       {
745         u_param = (osip_uri_param_t *) osip_list_get (url->url_params, pos);
746         i = osip_uri_param_clone (u_param, &dest_param);
747         if (i != 0)
748           return -1;
749         osip_list_add (ur->url_params, dest_param, -1);
750         pos++;
751       }
752   }
753   {
754     int pos = 0;
755     osip_uri_param_t *u_param;
756     osip_uri_param_t *dest_param;
757
758     while (!osip_list_eol (url->url_headers, pos))
759       {
760         u_param = (osip_uri_param_t *) osip_list_get (url->url_headers, pos);
761         i = osip_uri_param_clone (u_param, &dest_param);
762         if (i != 0)
763           return -1;
764         osip_list_add (ur->url_headers, dest_param, -1);
765         pos++;
766       }
767   }
768
769   *dest = ur;
770   return 0;
771 }
772
773 int
774 osip_uri_param_init (osip_uri_param_t ** url_param)
775 {
776   *url_param = (osip_uri_param_t *) osip_malloc (sizeof (osip_uri_param_t));
777   (*url_param)->gname = NULL;
778   (*url_param)->gvalue = NULL;
779   return 0;
780 }
781
782 void
783 osip_uri_param_free (osip_uri_param_t * url_param)
784 {
785   osip_free (url_param->gname);
786   osip_free (url_param->gvalue);
787   osip_free (url_param);
788 }
789
790 int
791 osip_uri_param_set (osip_uri_param_t * url_param, char *pname, char *pvalue)
792 {
793   url_param->gname = pname;
794   /* not needed for url, but for all other generic params */
795   osip_clrspace (url_param->gname);
796   url_param->gvalue = pvalue;
797   if (url_param->gvalue != NULL)
798     osip_clrspace (url_param->gvalue);
799   return 0;
800 }
801
802 int
803 osip_uri_param_add (osip_list_t * url_params, char *pname, char *pvalue)
804 {
805   int i;
806   osip_uri_param_t *url_param;
807
808   i = osip_uri_param_init (&url_param);
809   if (i != 0)
810     return -1;
811   i = osip_uri_param_set (url_param, pname, pvalue);
812   if (i != 0)
813     {
814       osip_uri_param_free (url_param);
815       return -1;
816     }
817   osip_list_add (url_params, url_param, -1);
818   return 0;
819 }
820
821 void
822 osip_uri_param_freelist (osip_list_t * params)
823 {
824   osip_uri_param_t *u_param;
825
826   while (!osip_list_eol (params, 0))
827     {
828       u_param = (osip_uri_param_t *) osip_list_get (params, 0);
829       osip_list_remove (params, 0);
830       osip_uri_param_free (u_param);
831     }
832   osip_free (params);
833 }
834
835 int
836 osip_uri_param_get_byname (osip_list_t * params, char *pname,
837                            osip_uri_param_t ** url_param)
838 {
839   int pos = 0;
840   int pname_len;
841   osip_uri_param_t *u_param;
842   *url_param = NULL;
843   if (pname==NULL)
844     return -1;
845   pname_len = strlen(pname);
846   if (pname_len<=0)
847     return -1;
848   while (!osip_list_eol (params, pos))
849     {
850       int len;
851       u_param = (osip_uri_param_t *) osip_list_get (params, pos);
852       len = strlen(u_param->gname);
853       if (pname_len == len && osip_strncasecmp (u_param->gname, pname, strlen (pname)) == 0)
854         {
855           *url_param = u_param;
856           return 0;
857         }
858       pos++;
859     }
860   return -1;
861 }
862
863 int
864 osip_uri_param_clone (const osip_uri_param_t * uparam,
865                       osip_uri_param_t ** dest)
866 {
867   int i;
868   osip_uri_param_t *up;
869
870   *dest = NULL;
871   if (uparam == NULL)
872     return -1;
873   if (uparam->gname == NULL)
874     return -1;                  /* name is mandatory */
875
876   i = osip_uri_param_init (&up);
877   if (i != 0)                   /* allocation failed */
878     return -1;
879   up->gname = osip_strdup (uparam->gname);
880   if (uparam->gvalue != NULL)
881     up->gvalue = osip_strdup (uparam->gvalue);
882   else
883     up->gvalue = NULL;
884   *dest = up;
885   return 0;
886 }
887
888
889 #define _ALPHANUM_ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890\0"
890 #define _RESERVED_ ";/?:@&=+$\0"
891 #define _MARK_ "-_.!~*'()\0"
892
893 #define _MARK__USER_UNRESERVED_ "-_.!~*'()&=+$,;?/\0"
894 #define _MARK__PWORD_UNRESERVED_ "-_.!~*'()&=+$,\0"
895 #define _MARK__URI_PARAM_UNRESERVED_ "-_.!~*'()[]/:&+$\0"
896 #define _MARK__HEADER_PARAM_UNRESERVED_ "-_.!~*'()[]/?:+$\0"
897
898 #define osip_is_alphanum(in) (  \
899        (in >= 'a' && in <= 'z') || \
900        (in >= 'A' && in <= 'Z') || \
901        (in >= '0' && in <= '9'))
902
903 char *
904 __osip_uri_escape_nonascii_and_nondef (const char *string, const char *def)
905 {
906   size_t alloc = strlen (string) + 1;
907   size_t length;
908   char *ns = osip_malloc (alloc);
909   unsigned char in;
910   size_t newlen = alloc;
911   int index = 0;
912   const char *tmp;
913   int i;
914
915   length = alloc - 1;
916   while (length--)
917     {
918       in = *string;
919
920       i = 0;
921       tmp = NULL;
922       if (osip_is_alphanum (in))
923         tmp = string;
924       else
925         {
926           for (; def[i] != '\0' && def[i] != in; i++)
927             {
928             }
929           if (def[i] != '\0')
930             tmp = string;
931         }
932       if (tmp == NULL)
933         {
934           /* encode it */
935           newlen += 2;          /* the size grows with two, since this'll become a %XX */
936           if (newlen > alloc)
937             {
938               alloc *= 2;
939               ns = realloc (ns, alloc);
940               if (!ns)
941                 return NULL;
942             }
943           sprintf (&ns[index], "%%%02X", in);
944           index += 3;
945         }
946       else
947         {
948           /* just copy this */
949           ns[index++] = in;
950         }
951       string++;
952     }
953   ns[index] = 0;                /* terminate it */
954   return ns;
955 }
956
957 /* user =  *( unreserved / escaped / user-unreserved ) */
958 const char *userinfo_def = /* implied _ALPHANUM_ */ _MARK__USER_UNRESERVED_;
959 char *
960 __osip_uri_escape_userinfo (const char *string)
961 {
962   return __osip_uri_escape_nonascii_and_nondef (string, userinfo_def);
963 }
964
965 /* user =  *( unreserved / escaped / user-unreserved ) */
966 const char *password_def = _MARK__PWORD_UNRESERVED_;
967 char *
968 __osip_uri_escape_password (const char *string)
969 {
970   return __osip_uri_escape_nonascii_and_nondef (string, password_def);
971 }
972
973 const char *uri_param_def = _MARK__URI_PARAM_UNRESERVED_;
974 char *
975 __osip_uri_escape_uri_param (char *string)
976 {
977   return __osip_uri_escape_nonascii_and_nondef (string, uri_param_def);
978 }
979
980 const char *header_param_def = _MARK__HEADER_PARAM_UNRESERVED_;
981 char *
982 __osip_uri_escape_header_param (char *string)
983 {
984   return __osip_uri_escape_nonascii_and_nondef (string, header_param_def);
985 }
986
987 void
988 __osip_uri_unescape (char *string)
989 {
990   size_t alloc = strlen (string) + 1;
991   unsigned char in;
992   int index = 0;
993   unsigned int hex;
994   char *ptr;
995
996   ptr = string;
997   while (--alloc > 0)
998     {
999       in = *ptr;
1000       if ('%' == in)
1001         {
1002           /* encoded part */
1003           if (sscanf (ptr + 1, "%02X", &hex))
1004             {
1005               in = (unsigned char) hex;
1006               ptr += 2;
1007               alloc -= 2;
1008             }
1009         }
1010
1011       string[index++] = in;
1012       ptr++;
1013     }
1014   string[index] = 0;            /* terminate it */
1015 }
1016
1017 /* 
1018    Robin Nayathodan <roooot@softhome.net> 
1019    N.K Electronics INDIA
1020
1021    RFC3261 16.5 
1022  */
1023
1024 int
1025 osip_uri_to_str_canonical (const osip_uri_t * url, char **dest)
1026 {
1027   int result;
1028   *dest = NULL;
1029   result = osip_uri_to_str (url, dest);
1030   if (result == 0)
1031     {
1032       /*
1033          tmp = strchr(*dest, ";");
1034          if (tmp !=NULL) {
1035          buf=strndup(*dest, tmp-(*dest));
1036          osip_free(*dest);
1037          *dest=buf;
1038          }
1039        */
1040       __osip_uri_unescape (*dest);
1041     }
1042   return result;
1043 }