Revert "Revert "and added files""
[bcm963xx.git] / userapps / opensource / libosip2 / src / osipparser2 / osip_from.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 /* HISTORY:
21
22    v0.5.0: created.
23
24    v0.6.0: 16/07/2001 complete support for from:
25    new structure
26    new osip_from_parse() method
27 */
28
29 #include <stdlib.h>
30 #include <stdio.h>
31
32 #include <osipparser2/osip_port.h>
33 #include <osipparser2/osip_message.h>
34 #include <osipparser2/osip_parser.h>
35 #include "parser.h"
36
37 /* adds the from header to message.              */
38 /* INPUT : char *hvalue | value of header.    */
39 /* OUTPUT: osip_message_t *sip | structure to save results.  */
40 /* returns -1 on error. */
41 int
42 osip_message_set_from (osip_message_t * sip, const char *hvalue)
43 {
44   int i;
45
46   if (hvalue == NULL || hvalue[0] == '\0')
47     return 0;
48
49   if (sip->from != NULL)
50     return -1;
51   i = osip_from_init (&(sip->from));
52   if (i != 0)
53     return -1;
54   sip->message_property = 2;
55   i = osip_from_parse (sip->from, hvalue);
56   if (i != 0)
57     {
58       osip_from_free (sip->from);
59       sip->from = NULL;
60       return -1;
61     }
62   return 0;
63 }
64
65
66 /* returns the from header.            */
67 /* INPUT : osip_message_t *sip | sip message.   */
68 /* returns null on error. */
69 osip_from_t *
70 osip_message_get_from (const osip_message_t * sip)
71 {
72   return sip->from;
73 }
74
75 int
76 osip_from_init (osip_from_t ** from)
77 {
78   *from = (osip_from_t *) osip_malloc (sizeof (osip_from_t));
79   if (*from == NULL)
80     return -1;
81   (*from)->displayname = NULL;
82   (*from)->url = NULL;
83
84   (*from)->gen_params = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
85   if ((*from)->gen_params == NULL)
86     {
87       osip_free (*from);
88       *from = NULL;
89     }
90   osip_list_init ((*from)->gen_params);
91
92   return 0;
93 }
94
95 /* deallocates a osip_from_t structure.  */
96 /* INPUT : osip_from_t *from | from. */
97 void
98 osip_from_free (osip_from_t * from)
99 {
100   if (from == NULL)
101     return;
102   if (from->url != NULL)
103     {
104       osip_uri_free (from->url);
105     }
106   osip_free (from->displayname);
107
108   osip_generic_param_freelist (from->gen_params);
109
110   osip_free (from);
111 }
112
113 /* parses the string as a from header.                   */
114 /* INPUT : const char *string | pointer to a from string.*/
115 /* OUTPUT: osip_from_t *from | structure to save results.     */
116 /* returns -1 on error. */
117 int
118 osip_from_parse (osip_from_t * from, const char *hvalue)
119 {
120   const char *displayname;
121   const char *url;
122   const char *url_end;
123   const char *gen_params;
124
125   /* How to parse:
126
127      we'll place the pointers:
128      displayname  =>  beginning of displayname
129      url          =>  beginning of url
130      url_end      =>  end       of url
131      gen_params  =>  beginning of params
132
133      examples:
134
135      jack <sip:jack@atosc.org>;tag=34erZ
136      ^     ^                ^ ^
137
138      sip:jack@atosc.org;tag=34erZ
139      ^                ^^      
140    */
141
142   displayname = strchr (hvalue, '"');
143
144   url = strchr (hvalue, '<');
145   if (url != NULL)
146     {
147       url_end = strchr (url, '>');
148       if (url_end == NULL)
149         return -1;
150     }
151
152   /* SIPit day2: this case was not supported
153      first '"' is placed after '<' and after '>'
154      <sip:ixion@62.254.248.117;method=INVITE>;description="OPEN";expires=28800
155      if the fisrt quote is after '<' then
156      this is not a quote for a displayname.
157    */
158   if (displayname > url)
159     displayname = NULL;
160
161   if ((displayname == NULL) && (url != NULL))
162     {                           /* displayname IS A '*token' (not a quoted-string) */
163       if (hvalue != url)        /* displayname exists */
164         {
165           if (url - hvalue + 1 < 2)
166             return -1;
167           from->displayname = (char *) osip_malloc (url - hvalue + 1);
168           if (from->displayname == NULL)
169             return -1;
170           osip_strncpy (from->displayname, hvalue, url - hvalue);
171           osip_clrspace (from->displayname);
172         }
173       url++;                    /* place pointer on the beginning of url */
174     }
175   else
176     {
177       if ((displayname != NULL) && (url != NULL))
178         {                       /* displayname IS A quoted-string (not a '*token') */
179           const char *first;
180           const char *second;
181
182           /* search for quotes */
183           first = __osip_quote_find (hvalue);
184           second = __osip_quote_find (first + 1);
185           if (second == NULL)
186             return -1;          /* if there is only 1 quote: failure */
187           if ((first > url))
188             return -1;
189
190           if (second - first + 2 >= 2)
191             {
192               from->displayname = (char *) osip_malloc (second - first + 2);
193               if (from->displayname == NULL)
194                 return -1;
195               osip_strncpy (from->displayname, first, second - first + 1);
196               /* osip_clrspace(from->displayname); *//*should we do that? */
197
198               /* special case: "<sip:joe@big.org>" <sip:joe@really.big.com> */
199             }                   /* else displayname is empty? */
200           url = strchr (second + 1, '<');
201           if (url == NULL)
202             return -1;          /* '<' MUST exist */
203           url++;
204         }
205       else
206         url = hvalue;           /* field does not contains '<' and '>' */
207     }
208
209   /* DISPLAY-NAME SET   */
210   /* START of URL KNOWN */
211
212   url_end = strchr (url, '>');
213
214   if (url_end == NULL)          /* sip:jack@atosc.org;tag=023 */
215     {                           /* We are sure ';' is the delimiter for from-parameters */
216       char *host = strchr (url, '@');
217
218       if (host != NULL)
219         gen_params = strchr (host, ';');
220       else
221         gen_params = strchr (url, ';');
222       if (gen_params != NULL)
223         url_end = gen_params - 1;
224       else
225         url_end = url + strlen (url);
226     }
227   else                          /* jack <sip:jack@atosc.org;user=phone>;tag=azer */
228     {
229       gen_params = strchr (url_end, ';');
230       url_end--;                /* place pointer on the beginning of url */
231     }
232
233   if (gen_params != NULL)       /* now we are sure a param exist */
234     if (__osip_generic_param_parseall (from->gen_params, gen_params) == -1)
235       {
236         return -1;
237       }
238
239   /* set the url */
240   {
241     char *tmp;
242     int i;
243
244     if (url_end - url + 2 < 7)
245       return -1;
246     i = osip_uri_init (&(from->url));
247     if (i != 0)
248       return -1;
249     tmp = (char *) osip_malloc (url_end - url + 2);
250     if (tmp == NULL)
251       return -1;
252     osip_strncpy (tmp, url, url_end - url + 1);
253     i = osip_uri_parse (from->url, tmp);
254     osip_free (tmp);
255     if (i != 0)
256       return -1;
257   }
258   return 0;
259 }
260
261
262 /* returns the from header as a string.  */
263 /* INPUT : osip_from_t *from | from header.   */
264 /* returns -1 on error. */
265 int
266 osip_from_to_str (const osip_from_t * from, char **dest)
267 {
268   char *url;
269   char *buf;
270   int i;
271   size_t len;
272
273   *dest = NULL;
274   if ((from == NULL) || (from->url == NULL))
275     return -1;
276
277   i = osip_uri_to_str (from->url, &url);
278   if (i != 0)
279     return -1;
280
281   if (from->displayname == NULL)
282     len = strlen (url) + 5;
283   else
284     len = strlen (url) + strlen (from->displayname) + 5;
285
286   buf = (char *) osip_malloc (len);
287   if (buf == NULL)
288     {
289       osip_free (url);
290       return -1;
291     }
292
293   if (from->displayname != NULL)
294     sprintf (buf, "%s <%s>", from->displayname, url);
295   else
296     /* from rfc2543bis-04: for authentication related issue!
297        "The To and From header fields always include the < and >
298        delimiters even if the display-name is empty." */
299     sprintf (buf, "<%s>", url);
300   osip_free (url);
301
302   {
303     int pos = 0;
304     osip_generic_param_t *u_param;
305     size_t plen;
306     char *tmp;
307
308     while (!osip_list_eol (from->gen_params, pos))
309       {
310         u_param =
311           (osip_generic_param_t *) osip_list_get (from->gen_params, pos);
312
313         if (u_param->gvalue == NULL)
314           plen = strlen (u_param->gname) + 2;
315         else
316           plen = strlen (u_param->gname) + strlen (u_param->gvalue) + 3;
317         len = len + plen;
318         buf = (char *) realloc (buf, len);
319         tmp = buf;
320         tmp = tmp + strlen (tmp);
321         if (u_param->gvalue == NULL)
322           sprintf (tmp, ";%s", u_param->gname);
323         else
324           sprintf (tmp, ";%s=%s", u_param->gname, u_param->gvalue);
325         pos++;
326       }
327   }
328   *dest = buf;
329   return 0;
330 }
331
332 char *
333 osip_from_get_displayname (osip_from_t * from)
334 {
335   if (from == NULL)
336     return NULL;
337   return from->displayname;
338 }
339
340 void
341 osip_from_set_displayname (osip_from_t * from, char *displayname)
342 {
343   from->displayname = displayname;
344 }
345
346 osip_uri_t *
347 osip_from_get_url (osip_from_t * from)
348 {
349   if (from == NULL)
350     return NULL;
351   return from->url;
352 }
353
354 void
355 osip_from_set_url (osip_from_t * from, osip_uri_t * url)
356 {
357   from->url = url;
358 }
359
360 int
361 osip_from_param_get (osip_from_t * from, int pos,
362                      osip_generic_param_t ** fparam)
363 {
364   *fparam = NULL;
365   if (from == NULL)
366     return -1;
367   if (osip_list_size (from->gen_params) <= pos)
368     return -1;                  /* does not exist */
369   *fparam = (osip_generic_param_t *) osip_list_get (from->gen_params, pos);
370   return pos;
371 }
372
373 int
374 osip_from_clone (const osip_from_t * from, osip_from_t ** dest)
375 {
376   int i;
377   osip_from_t *fr;
378
379   *dest = NULL;
380   if (from == NULL)
381     return -1;
382
383   i = osip_from_init (&fr);
384   if (i != 0)                   /* allocation failed */
385     return -1;
386   if (from->displayname != NULL)
387     fr->displayname = osip_strdup (from->displayname);
388
389   if (from->url != NULL)
390     {
391       i = osip_uri_clone (from->url, &(fr->url));
392       if (i != 0)
393         {
394           osip_from_free (fr);
395           return -1;
396         }
397     }
398
399   {
400     int pos = 0;
401     osip_generic_param_t *u_param;
402     osip_generic_param_t *dest_param;
403
404     while (!osip_list_eol (from->gen_params, pos))
405       {
406         u_param =
407           (osip_generic_param_t *) osip_list_get (from->gen_params, pos);
408         i = osip_generic_param_clone (u_param, &dest_param);
409         if (i != 0)
410           {
411             osip_from_free (fr);
412             return -1;
413           }
414         osip_list_add (fr->gen_params, dest_param, -1);
415         pos++;
416       }
417   }
418   *dest = fr;
419   return 0;
420 }
421
422 int
423 osip_from_compare (osip_from_t * from1, osip_from_t * from2)
424 {
425   char *tag1;
426   char *tag2;
427
428   if (from1 == NULL || from2 == NULL)
429     return -1;
430   if (from1->url == NULL || from2->url == NULL)
431     return -1;
432
433   /* we could have a sip or sips url, but if string!=NULL,
434      host part will be NULL. */
435   if (from1->url->host == NULL && from2->url->host == NULL)
436     {
437       if (from1->url->string == NULL || from2->url->string == NULL)
438         return -1;
439       if (0 == strcmp (from1->url->string, from2->url->string))
440         return 0;
441     }
442   if (from1->url->host == NULL || from2->url->host == NULL)
443     return -1;
444
445   /* compare url including tag */
446   if (0 != strcmp (from1->url->host, from2->url->host))
447     return -1;
448   if (from1->url->username != NULL && from2->url->username != NULL)
449     if (0 != strcmp (from1->url->username, from2->url->username))
450       return -1;
451
452   tag1 = NULL;
453   tag2 = NULL;
454   {
455     int pos = 0;
456     osip_generic_param_t *u_param;
457
458     while (!osip_list_eol (from1->gen_params, pos))
459       {
460         u_param =
461           (osip_generic_param_t *) osip_list_get (from1->gen_params, pos);
462         if (0 == strncmp (u_param->gname, "tag", 3))
463           {
464             tag1 = u_param->gvalue;
465             break;
466           }
467         pos++;
468       }
469   }
470   {
471     int pos = 0;
472     osip_generic_param_t *u_param;
473
474     while (!osip_list_eol (from2->gen_params, pos))
475       {
476         u_param =
477           (osip_generic_param_t *) osip_list_get (from2->gen_params, pos);
478         if (0 == strncmp (u_param->gname, "tag", 3))
479           {
480             tag2 = u_param->gvalue;
481             break;
482           }
483         pos++;
484       }
485   }
486
487   /* sounds like a BUG!
488      if tag2 exists and tag1 does not, then it will
489      return 0;
490      in the first request, (INVITE) the To field does not
491      contain any tag. The response contains one! and the
492      response must match the request....
493    */
494   /* so we test the tags only when both exist! */
495   if (tag1 != NULL && tag2 != NULL)
496     if (0 != strcmp (tag1, tag2))
497       return -1;
498
499   /* We could return a special case, when */
500   /* only one tag exists?? */
501
502   return 0;                     /* return code changed to 0 from release 0.6.1 */
503 }
504
505 int
506 __osip_generic_param_parseall (osip_list_t * gen_params, const char *params)
507 {
508   char *pname;
509   char *pvalue;
510
511   const char *comma;
512   const char *equal;
513
514   /* find '=' wich is the separator for one param */
515   /* find ';' wich is the separator for multiple params */
516
517   equal = next_separator (params + 1, '=', ';');
518   comma = strchr (params + 1, ';');
519
520   while (comma != NULL)
521     {
522
523       if (equal == NULL)
524         {
525           equal = comma;
526           pvalue = NULL;
527         }
528       else
529         {
530           const char *tmp;
531           /* check for NULL param with an '=' character */
532           tmp = equal + 1;
533           for (; *tmp == '\t' || *tmp == ' '; tmp++)
534             {
535             }
536           pvalue = NULL;
537           if (*tmp != ',' && *tmp != '\0')
538             {
539               if (comma - equal < 2)
540                 return -1;
541               pvalue = (char *) osip_malloc (comma - equal);
542               if (pvalue == NULL)
543                 return -1;
544               osip_strncpy (pvalue, equal + 1, comma - equal - 1);
545             }
546         }
547
548       if (equal - params < 2)
549         {
550           osip_free (pvalue);
551           return -1;
552         }
553       pname = (char *) osip_malloc (equal - params);
554       if (pname == NULL)
555         {
556           osip_free (pvalue);
557           return -1;
558         }
559       osip_strncpy (pname, params + 1, equal - params - 1);
560
561       osip_generic_param_add (gen_params, pname, pvalue);
562
563       params = comma;
564       equal = next_separator (params + 1, '=', ';');
565       comma = strchr (params + 1, ';');
566     }
567
568   /* this is the last header (comma==NULL) */
569   comma = params + strlen (params);
570
571   if (equal == NULL)
572     {
573       equal = comma;            /* at the end */
574       pvalue = NULL;
575     }
576   else
577     {
578       const char *tmp;
579       /* check for NULL param with an '=' character */
580       tmp = equal + 1;
581       for (; *tmp == '\t' || *tmp == ' '; tmp++)
582         {
583         }
584       pvalue = NULL;
585       if (*tmp != ',' && *tmp != '\0')
586         {
587           if (comma - equal < 2)
588             return -1;
589           pvalue = (char *) osip_malloc (comma - equal);
590           if (pvalue == NULL)
591             return -1;
592           osip_strncpy (pvalue, equal + 1, comma - equal - 1);
593         }
594     }
595
596   if (equal - params < 2)
597     {
598       osip_free (pvalue);
599       return -1;
600     }
601   pname = (char *) osip_malloc (equal - params);
602   if (pname == NULL)
603     return -1;
604   osip_strncpy (pname, params + 1, equal - params - 1);
605
606   osip_generic_param_add (gen_params, pname, pvalue);
607
608   return 0;
609 }
610
611
612 void
613 osip_generic_param_set_value (osip_generic_param_t * fparam, char *value)
614 {
615   fparam->gvalue = value;
616 }
617
618 char *
619 osip_generic_param_get_name (const osip_generic_param_t * fparam)
620 {
621   if (fparam == NULL)
622     return NULL;
623   return fparam->gname;
624 }
625
626 void
627 osip_generic_param_set_name (osip_generic_param_t * fparam, char *name)
628 {
629   fparam->gname = name;
630 }
631
632 char *
633 osip_generic_param_get_value (const osip_generic_param_t * fparam)
634 {
635   if (fparam == NULL)
636     return NULL;
637   if (fparam->gname == NULL)
638     return NULL;                /* name is mandatory */
639   return fparam->gvalue;
640 }
641
642 int
643 osip_from_tag_match (osip_from_t * from1, osip_from_t * from2)
644 {
645   osip_generic_param_t *tag_from1;
646   osip_generic_param_t *tag_from2;
647
648   osip_from_param_get_byname (from1, "tag", &tag_from1);
649   osip_from_param_get_byname (from2, "tag", &tag_from2);
650   if (tag_from1 == NULL && tag_from2 == NULL)
651     return 0;
652   if ((tag_from1 != NULL && tag_from2 == NULL)
653       || (tag_from1 == NULL && tag_from2 != NULL))
654     return -1;
655   if (tag_from1->gvalue == NULL || tag_from2->gvalue == NULL)
656     return -1;
657   if (0 != strcmp (tag_from1->gvalue, tag_from2->gvalue))
658     return -1;
659   return 0;
660 }