2 The oSIP library implements the Session Initiation Protocol (SIP -rfc3261-)
3 Copyright (C) 2001,2002,2003 Aymeric MOIZARD jack@atosc.org
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.
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.
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
24 v0.6.0: 16/07/2001 complete support for from:
26 new osip_from_parse() method
32 #include <osipparser2/osip_port.h>
33 #include <osipparser2/osip_message.h>
34 #include <osipparser2/osip_parser.h>
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. */
42 osip_message_set_from (osip_message_t * sip, const char *hvalue)
46 if (hvalue == NULL || hvalue[0] == '\0')
49 if (sip->from != NULL)
51 i = osip_from_init (&(sip->from));
54 sip->message_property = 2;
55 i = osip_from_parse (sip->from, hvalue);
58 osip_from_free (sip->from);
66 /* returns the from header. */
67 /* INPUT : osip_message_t *sip | sip message. */
68 /* returns null on error. */
70 osip_message_get_from (const osip_message_t * sip)
76 osip_from_init (osip_from_t ** from)
78 *from = (osip_from_t *) osip_malloc (sizeof (osip_from_t));
81 (*from)->displayname = NULL;
84 (*from)->gen_params = (osip_list_t *) osip_malloc (sizeof (osip_list_t));
85 if ((*from)->gen_params == NULL)
90 osip_list_init ((*from)->gen_params);
95 /* deallocates a osip_from_t structure. */
96 /* INPUT : osip_from_t *from | from. */
98 osip_from_free (osip_from_t * from)
102 if (from->url != NULL)
104 osip_uri_free (from->url);
106 osip_free (from->displayname);
108 osip_generic_param_freelist (from->gen_params);
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. */
118 osip_from_parse (osip_from_t * from, const char *hvalue)
120 const char *displayname;
123 const char *gen_params;
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
135 jack <sip:jack@atosc.org>;tag=34erZ
138 sip:jack@atosc.org;tag=34erZ
142 displayname = strchr (hvalue, '"');
144 url = strchr (hvalue, '<');
147 url_end = strchr (url, '>');
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.
158 if (displayname > url)
161 if ((displayname == NULL) && (url != NULL))
162 { /* displayname IS A '*token' (not a quoted-string) */
163 if (hvalue != url) /* displayname exists */
165 if (url - hvalue + 1 < 2)
167 from->displayname = (char *) osip_malloc (url - hvalue + 1);
168 if (from->displayname == NULL)
170 osip_strncpy (from->displayname, hvalue, url - hvalue);
171 osip_clrspace (from->displayname);
173 url++; /* place pointer on the beginning of url */
177 if ((displayname != NULL) && (url != NULL))
178 { /* displayname IS A quoted-string (not a '*token') */
182 /* search for quotes */
183 first = __osip_quote_find (hvalue);
184 second = __osip_quote_find (first + 1);
186 return -1; /* if there is only 1 quote: failure */
190 if (second - first + 2 >= 2)
192 from->displayname = (char *) osip_malloc (second - first + 2);
193 if (from->displayname == NULL)
195 osip_strncpy (from->displayname, first, second - first + 1);
196 /* osip_clrspace(from->displayname); *//*should we do that? */
198 /* special case: "<sip:joe@big.org>" <sip:joe@really.big.com> */
199 } /* else displayname is empty? */
200 url = strchr (second + 1, '<');
202 return -1; /* '<' MUST exist */
206 url = hvalue; /* field does not contains '<' and '>' */
209 /* DISPLAY-NAME SET */
210 /* START of URL KNOWN */
212 url_end = strchr (url, '>');
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, '@');
219 gen_params = strchr (host, ';');
221 gen_params = strchr (url, ';');
222 if (gen_params != NULL)
223 url_end = gen_params - 1;
225 url_end = url + strlen (url);
227 else /* jack <sip:jack@atosc.org;user=phone>;tag=azer */
229 gen_params = strchr (url_end, ';');
230 url_end--; /* place pointer on the beginning of url */
233 if (gen_params != NULL) /* now we are sure a param exist */
234 if (__osip_generic_param_parseall (from->gen_params, gen_params) == -1)
244 if (url_end - url + 2 < 7)
246 i = osip_uri_init (&(from->url));
249 tmp = (char *) osip_malloc (url_end - url + 2);
252 osip_strncpy (tmp, url, url_end - url + 1);
253 i = osip_uri_parse (from->url, tmp);
262 /* returns the from header as a string. */
263 /* INPUT : osip_from_t *from | from header. */
264 /* returns -1 on error. */
266 osip_from_to_str (const osip_from_t * from, char **dest)
274 if ((from == NULL) || (from->url == NULL))
277 i = osip_uri_to_str (from->url, &url);
281 if (from->displayname == NULL)
282 len = strlen (url) + 5;
284 len = strlen (url) + strlen (from->displayname) + 5;
286 buf = (char *) osip_malloc (len);
293 if (from->displayname != NULL)
294 sprintf (buf, "%s <%s>", from->displayname, url);
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);
304 osip_generic_param_t *u_param;
308 while (!osip_list_eol (from->gen_params, pos))
311 (osip_generic_param_t *) osip_list_get (from->gen_params, pos);
313 if (u_param->gvalue == NULL)
314 plen = strlen (u_param->gname) + 2;
316 plen = strlen (u_param->gname) + strlen (u_param->gvalue) + 3;
318 buf = (char *) realloc (buf, len);
320 tmp = tmp + strlen (tmp);
321 if (u_param->gvalue == NULL)
322 sprintf (tmp, ";%s", u_param->gname);
324 sprintf (tmp, ";%s=%s", u_param->gname, u_param->gvalue);
333 osip_from_get_displayname (osip_from_t * from)
337 return from->displayname;
341 osip_from_set_displayname (osip_from_t * from, char *displayname)
343 from->displayname = displayname;
347 osip_from_get_url (osip_from_t * from)
355 osip_from_set_url (osip_from_t * from, osip_uri_t * url)
361 osip_from_param_get (osip_from_t * from, int pos,
362 osip_generic_param_t ** fparam)
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);
374 osip_from_clone (const osip_from_t * from, osip_from_t ** dest)
383 i = osip_from_init (&fr);
384 if (i != 0) /* allocation failed */
386 if (from->displayname != NULL)
387 fr->displayname = osip_strdup (from->displayname);
389 if (from->url != NULL)
391 i = osip_uri_clone (from->url, &(fr->url));
401 osip_generic_param_t *u_param;
402 osip_generic_param_t *dest_param;
404 while (!osip_list_eol (from->gen_params, pos))
407 (osip_generic_param_t *) osip_list_get (from->gen_params, pos);
408 i = osip_generic_param_clone (u_param, &dest_param);
414 osip_list_add (fr->gen_params, dest_param, -1);
423 osip_from_compare (osip_from_t * from1, osip_from_t * from2)
428 if (from1 == NULL || from2 == NULL)
430 if (from1->url == NULL || from2->url == NULL)
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)
437 if (from1->url->string == NULL || from2->url->string == NULL)
439 if (0 == strcmp (from1->url->string, from2->url->string))
442 if (from1->url->host == NULL || from2->url->host == NULL)
445 /* compare url including tag */
446 if (0 != strcmp (from1->url->host, from2->url->host))
448 if (from1->url->username != NULL && from2->url->username != NULL)
449 if (0 != strcmp (from1->url->username, from2->url->username))
456 osip_generic_param_t *u_param;
458 while (!osip_list_eol (from1->gen_params, pos))
461 (osip_generic_param_t *) osip_list_get (from1->gen_params, pos);
462 if (0 == strncmp (u_param->gname, "tag", 3))
464 tag1 = u_param->gvalue;
472 osip_generic_param_t *u_param;
474 while (!osip_list_eol (from2->gen_params, pos))
477 (osip_generic_param_t *) osip_list_get (from2->gen_params, pos);
478 if (0 == strncmp (u_param->gname, "tag", 3))
480 tag2 = u_param->gvalue;
487 /* sounds like a BUG!
488 if tag2 exists and tag1 does not, then it will
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....
494 /* so we test the tags only when both exist! */
495 if (tag1 != NULL && tag2 != NULL)
496 if (0 != strcmp (tag1, tag2))
499 /* We could return a special case, when */
500 /* only one tag exists?? */
502 return 0; /* return code changed to 0 from release 0.6.1 */
506 __osip_generic_param_parseall (osip_list_t * gen_params, const char *params)
514 /* find '=' wich is the separator for one param */
515 /* find ';' wich is the separator for multiple params */
517 equal = next_separator (params + 1, '=', ';');
518 comma = strchr (params + 1, ';');
520 while (comma != NULL)
531 /* check for NULL param with an '=' character */
533 for (; *tmp == '\t' || *tmp == ' '; tmp++)
537 if (*tmp != ',' && *tmp != '\0')
539 if (comma - equal < 2)
541 pvalue = (char *) osip_malloc (comma - equal);
544 osip_strncpy (pvalue, equal + 1, comma - equal - 1);
548 if (equal - params < 2)
553 pname = (char *) osip_malloc (equal - params);
559 osip_strncpy (pname, params + 1, equal - params - 1);
561 osip_generic_param_add (gen_params, pname, pvalue);
564 equal = next_separator (params + 1, '=', ';');
565 comma = strchr (params + 1, ';');
568 /* this is the last header (comma==NULL) */
569 comma = params + strlen (params);
573 equal = comma; /* at the end */
579 /* check for NULL param with an '=' character */
581 for (; *tmp == '\t' || *tmp == ' '; tmp++)
585 if (*tmp != ',' && *tmp != '\0')
587 if (comma - equal < 2)
589 pvalue = (char *) osip_malloc (comma - equal);
592 osip_strncpy (pvalue, equal + 1, comma - equal - 1);
596 if (equal - params < 2)
601 pname = (char *) osip_malloc (equal - params);
604 osip_strncpy (pname, params + 1, equal - params - 1);
606 osip_generic_param_add (gen_params, pname, pvalue);
613 osip_generic_param_set_value (osip_generic_param_t * fparam, char *value)
615 fparam->gvalue = value;
619 osip_generic_param_get_name (const osip_generic_param_t * fparam)
623 return fparam->gname;
627 osip_generic_param_set_name (osip_generic_param_t * fparam, char *name)
629 fparam->gname = name;
633 osip_generic_param_get_value (const osip_generic_param_t * fparam)
637 if (fparam->gname == NULL)
638 return NULL; /* name is mandatory */
639 return fparam->gvalue;
643 osip_from_tag_match (osip_from_t * from1, osip_from_t * from2)
645 osip_generic_param_t *tag_from1;
646 osip_generic_param_t *tag_from2;
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)
652 if ((tag_from1 != NULL && tag_from2 == NULL)
653 || (tag_from1 == NULL && tag_from2 != NULL))
655 if (tag_from1->gvalue == NULL || tag_from2->gvalue == NULL)
657 if (0 != strcmp (tag_from1->gvalue, tag_from2->gvalue))