Commit 785b358f authored by Pekka Pessi's avatar Pekka Pessi

sip: usign msg_parse_next_field() when parsing headers with multiple fields

darcs-hash:20061031171730-65a35-f909e8449089e646ecdd1a47ef34356ce9df396d.gz
parent 3cf3a2f3
......@@ -655,6 +655,9 @@ issize_t sip_name_addr_d(su_home_t *home,
char *display = NULL, *addr_spec = NULL;
size_t n;
if (*s == '\0') /* Empty string */
return -1;
if (return_display && *s == '"') {
/* Quoted string */
if (msg_quoted_d(&s, &display) == -1)
......@@ -1332,40 +1335,18 @@ issize_t sip_contact_d(su_home_t *home,
char *s,
isize_t slen)
{
sip_header_t **hh = &h->sh_succ, *h0 = h;
sip_contact_t *m = h->sh_contact;
sip_contact_t *m = (sip_contact_t *)h;
assert(h);
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; }
if (!h) {
/* If there are multiple contacts on one line
* we must allocate next header structure */
if (!(h = sip_header_alloc(home, h0->sh_class, 0)))
return -1;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ;
m = m->m_next = h->sh_contact;
}
if (sip_name_addr_d(home, &s, &m->m_display, m->m_url,
&m->m_params, &m->m_comment) == -1)
return -1;
if (*s != '\0' && *s != ',')
return -1;
if (m->m_params)
msg_header_update_params(m->m_common, 0);
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
*s = '\0', s += span_lws(s + 1) + 1;
h = NULL;
}
if (h) /* Empty list is an error */
if (sip_name_addr_d(home, &s, &m->m_display, m->m_url,
&m->m_params, &m->m_comment) == -1)
return -1;
return 0;
return msg_parse_next_field(home, h, s, slen);
}
......@@ -1373,6 +1354,7 @@ issize_t sip_contact_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
{
sip_contact_t const *m = h->sh_contact;
int always_lt_gt = MSG_IS_CANONIC(flags) && m->m_url->url_type != url_any;
assert(sip_is_contact(h));
return sip_name_addr_e(b, bsiz, flags,
......@@ -2066,39 +2048,18 @@ issize_t sip_any_route_d(su_home_t *home,
char *s,
isize_t slen)
{
sip_header_t **hh = &h->sh_succ, *h0 = h;
sip_route_t *r = h->sh_route;
sip_route_t *r = (sip_route_t *)h;
assert(h);
/* Loop through comma-separated list of route headers.. */
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; }
if (!h) {
if (!(h = sip_header_alloc(home, h0->sh_class, 0)))
break;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ;
r = r->r_next = h->sh_route;
}
r = h->sh_route;
if (sip_name_addr_d(home, &s, &r->r_display,
r->r_url, &r->r_params, NULL) < 0)
return -1;
if (*s != '\0' && *s != ',')
return -1;
h = NULL;
}
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
*s = '\0', s += span_lws(s + 1) + 1;
if (h) /* Empty list is an error */
if (sip_name_addr_d(home, &s, &r->r_display,
r->r_url, &r->r_params, NULL) < 0)
return -1;
return 0;
return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_any_route_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
......@@ -2522,49 +2483,29 @@ SIP_HEADER_CLASS(via, "Via", "v", v_params, prepend, via);
issize_t sip_via_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
sip_via_t *v = h->sh_via;
sip_header_t *h0 = h;
sip_header_t **hh = &h->sh_succ;
sip_via_t *v = (sip_via_t *)h;
assert(h);
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; }
if (!h) { /* Allocate next header structure */
if (!(h = sip_header_alloc(home, h0->sh_class, 0)))
return -1;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ;
v = v->v_next = h->sh_via;
}
/* sent-protocol sent-by *( ";" via-params ) [ comment ] */
/* Parse protocol */
if (sip_transport_d(&s, &v->v_protocol) == -1)
return -1;
/* Host (and port) */
if (msg_hostport_d(&s, &v->v_host, &v->v_port) == -1)
return -1;
/* Parameters */
if (*s == ';' && msg_params_d(home, &s, &v->v_params) == -1)
return -1;
/* Comment */
if (*s == '(' && msg_comment_d(&s, &v->v_comment) == -1)
return -1;
if (*s != '\0' && *s != ',')
return -1;
if (v->v_params)
msg_header_update_params(v->v_common, 0);
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
*s = '\0', s += span_lws(s + 1) + 1;
h = NULL;
}
/* sent-protocol sent-by *( ";" via-params ) [ comment ] */
if (h) /* Empty list */
/* Parse protocol */
if (sip_transport_d(&s, &v->v_protocol) == -1)
return -1;
/* Host (and port) */
if (msg_hostport_d(&s, &v->v_host, &v->v_port) == -1)
return -1;
/* Parameters */
if (*s == ';' && msg_params_d(home, &s, &v->v_params) == -1)
return -1;
/* Comment */
if (*s == '(' && msg_comment_d(&s, &v->v_comment) == -1)
return -1;
return 0;
return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_via_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
......
......@@ -191,63 +191,42 @@ size_t span_attribute_value(char *s)
}
static
issize_t sip_caller_prefs_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
issize_t sip_caller_prefs_d(su_home_t *home, sip_header_t *h,
char *s, isize_t slen)
{
sip_header_t **hh = &h->sh_succ, *h0 = h;
sip_caller_prefs_t *cp = h->sh_caller_prefs;
sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h;
url_t url[1];
char const *ignore = NULL;
int kludge;
int kludge = 0;
assert(h);
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; }
if (!h) {
if (!(h = sip_header_alloc(home, h0->sh_class, 0)))
return -1;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ;
cp = cp->cp_next = h->sh_caller_prefs;
}
kludge = 0;
/* Kludge: support PoC IS spec with a typo... */
if (strncasecmp(s, "*,", 2) == 0)
s[1] = ';';
else if (s[0] != '*' && s[0] != '<') {
/* Kludge: missing URL - */
size_t n = span_attribute_value(s);
kludge = n > 0 && (s[n] == '\0' || s[n] == ',' || s[n] == ';');
}
if (kludge) {
if (msg_any_list_d(home, &s, (msg_param_t **)&cp->cp_params,
msg_attribute_value_scanner, ';') == -1)
return -1;
}
/* Parse params (and ignore display name and url) */
else if (sip_name_addr_d(home, &s, &ignore, url, &cp->cp_params, NULL)
== -1)
return -1;
/* Be liberal... */
/* if (url->url_type != url_any)
return -1; */
if (*s != '\0' && *s != ',')
return -1;
if (cp->cp_params)
msg_header_update_params(cp->cp_common, 0);
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
*s = '\0', s += span_lws(s + 1) + 1;
h = NULL;
/* Kludge: support PoC IS spec with a typo... */
if (strncasecmp(s, "*,", 2) == 0)
s[1] = ';', kludge = 0;
else if (s[0] != '*' && s[0] != '<') {
/* Kludge: missing URL - */
size_t n = span_attribute_value(s);
kludge = n > 0 && (s[n] == '\0' || s[n] == ',' || s[n] == ';');
}
if (h) /* Empty list is an error */
if (kludge) {
if (msg_any_list_d(home, &s, (msg_param_t **)&cp->cp_params,
msg_attribute_value_scanner, ';') == -1)
return -1;
}
/* Parse params (and ignore display name and url) */
else if (sip_name_addr_d(home, &s, &ignore, url, &cp->cp_params, NULL)
== -1)
return -1;
/* Be liberal... */
/* if (url->url_type != url_any)
return -1; */
return 0;
return msg_parse_next_field(home, h, s, slen);
}
static
......
......@@ -175,7 +175,6 @@ static int sip_event_update(msg_common_t *h,
* Allow-Events = ( "Allow-Events" | "u" ) ":" 1#event-type
* @endcode
*
*
* The parsed Allow-Events header is stored in #sip_allow_events_t structure.
*/
......@@ -295,12 +294,12 @@ issize_t sip_subscription_state_d(su_home_t *home, sip_header_t *h,
sip_subscription_state_t *ss = h->sh_subscription_state;
ss->ss_substate = s;
skip_token(&s); /* forwards the pointer to the end of substate-value */
s += span_token(s); /* forwards the pointer to the end of substate-value */
if (s == ss->ss_substate)
return -1;
if (IS_LWS(*s))
*s++ = '\0';/* NUL-terminate substate */
skip_lws(&s); /* Skip any extra white space (advance pointer) */
if (IS_LWS(*s)) {
*s = '\0'; s += span_lws(s + 1) + 1;
}
/* check if parameters are present and if so parse them */
if (*s == ';') {
......
......@@ -495,18 +495,18 @@ SIP_HEADER_CLASS(timestamp, "Timestamp", "", ts_common, single,
issize_t sip_timestamp_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
sip_timestamp_t *ts = (sip_timestamp_t*)h;
ts->ts_stamp = s;
skip_digit(&s);
s += span_digit(s);
if (s == ts->ts_stamp)
return -1;
if (*s == '.') { s++; skip_digit(&s); }
if (*s == '.') { s += span_digit(s + 1) + 1; }
if (IS_LWS(*s)) {
*s++ = '\0';
skip_lws(&s);
*s = '\0';
s += span_lws(s + 1) + 1;
ts->ts_delay = s;
skip_digit(&s); if (*s == '.') { s++; skip_digit(&s); }
s += span_digit(s); if (*s == '.') { s += span_digit(s + 1) + 1; }
}
if (!*s || IS_LWS(*s))
......@@ -718,28 +718,13 @@ issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
assert(h);
while (*s == ',')
s++, skip_lws(&s);
if (sip_name_addr_d(home, &s,
NULL,
ci->ci_url,
&ci->ci_params,
NULL) < 0)
return -1;
if (*s && *s != ',')
return -1;
while (*s == ',')
*s++ = '\0', skip_lws(&s); /* Skip comma and following whitespace */
if (*s == 0)
return 0;
s += span_lws(s + 1) + 1;
if (!(h = sip_header_alloc(home, h->sh_class, 0)))
if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0)
return -1;
return sip_info_d(home, h, s, end - s);
/* Recurse */
return msg_parse_next_field(home, h, s, end - s);
}
isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset)
......
......@@ -133,42 +133,24 @@ SIP_HEADER_CLASS(accept_disposition, "Accept-Disposition", "",
issize_t sip_accept_disposition_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
sip_header_t **hh = &h->sh_succ, *h0 = h;
sip_accept_disposition_t *ad = h->sh_accept_disposition;
sip_accept_disposition_t *ad = (sip_accept_disposition_t *)h;
assert(h);
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') { *s++ = '\0'; skip_lws(&s); continue; }
/* Ignore empty entries (comma-whitespace) */
while (*s == ',')
s += span_lws(s + 1) + 1;
if (!h) { /* Allocate next header structure */
if (!(h = sip_header_alloc(home, sip_accept_disposition_class, 0)))
return -1;
*hh = h, hh = &h->sh_succ;
m = ad->ad_next = h->sh_accept_disposition;
}
/* "Accept:" #(type/subtyp ; *(parameters))) */
if (/* Parse protocol */
sip_version_d(&s, &ad->ad_type) == -1 ||
(ad->ad_subtype = strchr(ad->ad_type, '/')) == NULL ||
(*s == ';' && msg_params_d(home, &s, &ad->ad_params) == -1) ||
(*s != '\0' && *s != ','))
goto error;
if (ad->ad_subtype) ad->ad_subtype++;
if (ad->ad_params)
sip_accept_disposition_update(ad);
h = NULL;
}
if (h)
/* "Accept:" #(type/subtyp ; *(parameters))) */
if (/* Parse protocol */
sip_version_d(&s, &ad->ad_type) == -1 ||
(ad->ad_subtype = strchr(ad->ad_type, '/')) == NULL ||
(*s == ';' && msg_params_d(home, &s, &ad->ad_params) == -1))
return -1;
return 0;
if (ad->ad_subtype) ad->ad_subtype++;
return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_accept_disposition_e(char b[], isize_t bsiz, sip_header_t const *h, int flags)
......@@ -233,11 +215,12 @@ SIP_HEADER_CLASS(accept_encoding, "Accept-Encoding", "",
issize_t sip_accept_encoding_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
int retval = msg_accept_encoding_d(home, h, s, slen);
issize_t retval = msg_accept_encoding_d(home, h, s, slen);
if (retval == -2) {
/* Empty Accept-Encoding list is not an error */
((sip_accept_encoding_t *)h)->aa_value = "";
sip_accept_encoding_t *aa = (sip_accept_encoding_t *)h;
aa->aa_value = "";
retval = 0;
}
......
......@@ -93,43 +93,20 @@ SIP_HEADER_CLASS(reason, "Reason", "", re_params, append, reason);
issize_t sip_reason_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
sip_header_t **hh = &h->sh_succ, *h0 = h;
sip_reason_t *re = h->sh_reason;
sip_reason_t *re = (sip_reason_t *)h;
size_t n;
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') {
*s++ = '\0'; skip_lws(&s);
continue;
}
if (!h) { /* Allocate next header structure */
if (!(h = sip_header_alloc(home, h0->sh_class, 0)))
return -1;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ;
re = re->re_next = h->sh_reason;
}
if ((n = span_token(s)) == 0)
return -1;
re->re_protocol = s; s += n; while (IS_LWS(*s)) *s++ = '\0';
if (*s == ';' && msg_params_d(home, &s, &re->re_params) < 0)
return -1;
if (*s != '\0' && *s != ',')
return -1;
if (re->re_params)
msg_header_update_params(re->re_common, 0);
h = NULL;
}
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
*s = '\0', s += span_lws(s + 1) + 1;
if (h) /* Empty list -> error */
return -1;
re->re_protocol = s;
if ((n = span_token(s)) == 0)
return -1;
s += n; while (IS_LWS(*s)) *s++ = '\0';
if (*s == ';' && msg_params_d(home, &s, &re->re_params) < 0)
return -1;
return 0;
return msg_parse_next_field(home, h, s, slen);
}
issize_t sip_reason_e(char b[], isize_t bsiz, sip_header_t const *h, int f)
......
......@@ -456,45 +456,20 @@ typedef struct sip_security_agree_s sip_security_agree_t;
static
issize_t sip_security_agree_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen)
{
sip_header_t **hh = &h->sh_succ, *h0 = h;
sip_security_agree_t *sa = h->sh_security_agree;
sip_security_agree_t *sa = (sip_security_agree_t *)h;
isize_t n;
for (;*s;) {
/* Ignore empty entries (comma-whitespace) */
if (*s == ',') {
*s++ = '\0'; skip_lws(&s);
continue;
}
if (!h) { /* Allocate next header structure */
if (!(h = sip_header_alloc(home, h0->sh_class, 0)))
return -1;
*hh = h; h->sh_prev = hh; hh = &h->sh_succ;
sa = sa->sa_next = h->sh_security_agree;
}
sa = h->sh_security_agree;
while (*s == ',') /* Ignore empty entries (comma-whitespace) */
*s = '\0', s += span_lws(s + 1) + 1;
if ((n = span_token(s)) == 0)
return -1;
sa->sa_mec = s; s += n; while (IS_LWS(*s)) *s++ = '\0';
if (*s == ';' && msg_params_d(home, &s, &sa->sa_params) < 0)
return -1;
if (*s != '\0' && *s != ',')
return -1;
if (sa->sa_params)
msg_header_update_params(sa->sa_common, 0);
h = NULL;
}
if (h) /* Empty list -> error */
return -1;
if ((n = span_token(s)) == 0)
return -1;
sa->sa_mec = s; s += n; while (IS_LWS(*s)) *s++ = '\0';
if (*s == ';' && msg_params_d(home, &s, &sa->sa_params) < 0)
return -1;
return 0;
return msg_parse_next_field(home, h, s, slen);
}
static
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment