diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/msg_mime.c b/libs/sofia-sip/libsofia-sip-ua/msg/msg_mime.c index 4fe75a24de..e889ceb633 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/msg_mime.c +++ b/libs/sofia-sip/libsofia-sip-ua/msg/msg_mime.c @@ -1069,28 +1069,33 @@ MSG_HEADER_CLASS(msg_, accept, "Accept", "", ac_params, apndlist, issize_t msg_accept_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { - msg_accept_t *ac = (msg_accept_t *)h; + msg_accept_t *ac; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + for(;;) { + ac = (msg_accept_t *)h; - if (*s == '\0') { - /* Empty Accept list is not an error */ - ac->ac_type = ac->ac_subtype = ""; - return 0; - } + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; - /* "Accept:" #(type/subtyp ; *(parameters))) */ - if (msg_mediatype_d(&s, &ac->ac_type) == -1) - return -1; - if (!(ac->ac_subtype = strchr(ac->ac_type, '/'))) - return -1; - ac->ac_subtype++; + if (*s == '\0') { + /* Empty Accept list is not an error */ + ac->ac_type = ac->ac_subtype = ""; + return 0; + } - if (*s == ';' && msg_params_d(home, &s, &ac->ac_params) == -1) - return -1; + /* "Accept:" #(type/subtyp ; *(parameters))) */ + if (msg_mediatype_d(&s, &ac->ac_type) == -1) + return -1; + if (!(ac->ac_subtype = strchr(ac->ac_type, '/'))) + return -1; + ac->ac_subtype++; + + if (*s == ';' && msg_params_d(home, &s, &ac->ac_params) == -1) + return -1; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } issize_t msg_accept_e(char b[], isize_t bsiz, msg_header_t const *h, int flags) @@ -1167,22 +1172,26 @@ issize_t msg_accept_any_d(su_home_t *home, char *s, isize_t slen) { /** @relatesalso msg_accept_any_s */ - msg_accept_any_t *aa = (msg_accept_any_t *)h; + msg_accept_any_t *aa; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + for(;;) { + aa = (msg_accept_any_t *)h; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; - if (*s == '\0') - return -2; /* Empty list */ + if (*s == '\0') + return -2; /* Empty list */ - /* "Accept-*:" 1#(token *(SEMI accept-param)) */ - if (msg_token_d(&s, &aa->aa_value) == -1) - return -1; + /* "Accept-*:" 1#(token *(SEMI accept-param)) */ + if (msg_token_d(&s, &aa->aa_value) == -1) + return -1; - if (*s == ';' && msg_params_d(home, &s, &aa->aa_params) == -1) - return -1; + if (*s == ';' && msg_params_d(home, &s, &aa->aa_params) == -1) + return -1; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } /** Encode an Accept-* header field. */ @@ -2071,29 +2080,33 @@ MSG_HEADER_CLASS_G(content_transfer_encoding, "Content-Transfer-Encoding", issize_t msg_warning_d(su_home_t *home, msg_header_t *h, char *s, isize_t slen) { - msg_warning_t *w = (msg_warning_t *)h; + msg_warning_t *w; char *text; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + for(;;) { + w = (msg_warning_t *)h; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; - /* Parse protocol */ - if (!IS_DIGIT(*s)) - return -1; - w->w_code = strtoul(s, &s, 10); - skip_lws(&s); + /* Parse protocol */ + if (!IS_DIGIT(*s)) + return -1; + w->w_code = strtoul(s, &s, 10); + skip_lws(&s); - /* Host (and port) */ - if (msg_hostport_d(&s, &w->w_host, &w->w_port) == -1) - return -1; - if (msg_quoted_d(&s, &text) == -1) - return -1; - if (msg_unquote(text, text) == NULL) - return -1; + /* Host (and port) */ + if (msg_hostport_d(&s, &w->w_host, &w->w_port) == -1) + return -1; + if (msg_quoted_d(&s, &text) == -1) + return -1; + if (msg_unquote(text, text) == NULL) + return -1; - w->w_text = text; + w->w_text = text; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } issize_t msg_warning_e(char b[], isize_t bsiz, msg_header_t const *h, int f) diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.c b/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.c index e4bf3debca..d75b975689 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.c +++ b/libs/sofia-sip/libsofia-sip-ua/msg/msg_parser.c @@ -1190,6 +1190,7 @@ msg_header_t *error_header_parse(msg_t *msg, msg_pub_t *mo, return h; } + /** Complete this header field and parse next header field. * * This function completes parsing a multi-field header like @Accept, @@ -1238,6 +1239,7 @@ issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev, return hc->hc_parse(home, h, s, end - s); } + /** Decode a message header. */ msg_header_t *msg_header_d(su_home_t *home, msg_t const *msg, char const *b) { diff --git a/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h b/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h index c2fc31f862..7d784b5a61 100644 --- a/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h +++ b/libs/sofia-sip/libsofia-sip-ua/msg/sofia-sip/msg_parser.h @@ -185,6 +185,34 @@ SOFIAPUBFUN issize_t msg_unquoted_e(char *b, isize_t bsiz, char const *s); SOFIAPUBFUN issize_t msg_parse_next_field(su_home_t *home, msg_header_t *prev, char *s, isize_t slen); +#define msg_parse_next_field_without_recursion() { \ + msg_header_t *prev = h; \ + msg_hclass_t *hc = prev->sh_class; \ + char *end = s + slen; \ + \ + if (*s && *s != ',') \ + return -1; \ + \ + if (msg_header_update_params(prev->sh_common, 0) < 0) \ + return -1; \ + \ + while (*s == ',') \ + *s = '\0', s += span_lws(s + 1) + 1; \ + \ + if (*s == 0) \ + return 0; \ + \ + h = msg_header_alloc(home, hc, 0); \ + if (!h) \ + return -1; \ + \ + prev->sh_succ = h, h->sh_prev = &prev->sh_succ; \ + prev->sh_next = h; \ + slen = end - s; \ + } + + + /** Terminate encoding. @HI */ #define MSG_TERM_E(p, e) ((p) < (e) ? (p)[0] = '\0' : '\0') diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c index b3dd3c396a..d2e1c0875e 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c @@ -1391,18 +1391,23 @@ issize_t sip_contact_d(su_home_t *home, char *s, isize_t slen) { - sip_contact_t *m = (sip_contact_t *)h; + sip_contact_t *m; assert(h); + for(;;) { - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + m = (sip_contact_t *)h; - if (sip_name_addr_d(home, &s, &m->m_display, m->m_url, - &m->m_params, &m->m_comment) == -1) - return -1; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; + + if (sip_name_addr_d(home, &s, &m->m_display, m->m_url, + &m->m_params, &m->m_comment) == -1) + return -1; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } @@ -2106,18 +2111,24 @@ issize_t sip_any_route_d(su_home_t *home, char *s, isize_t slen) { - sip_route_t *r = (sip_route_t *)h; + sip_route_t *r; + assert(h); + for (;;) { + r = (sip_route_t *)h; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + while (*s == ',') { /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; + } - if (sip_name_addr_d(home, &s, &r->r_display, - r->r_url, &r->r_params, NULL) < 0) - return -1; + if (sip_name_addr_d(home, &s, &r->r_display, r->r_url, &r->r_params, NULL) < 0) { + return -1; + } + + msg_parse_next_field_without_recursion(); + } - 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) @@ -2534,29 +2545,32 @@ 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 = (sip_via_t *)h; + sip_via_t *v; assert(h); + for (;;) { + v = (sip_via_t *)h; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; - /* sent-protocol sent-by *( ";" via-params ) [ comment ] */ + /* 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; - /* 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 msg_parse_next_field(home, h, s, slen); + msg_parse_next_field_without_recursion(); + } } issize_t sip_via_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_caller_prefs.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_caller_prefs.c index 9cbc5ed2ee..b2dc3d8e50 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_caller_prefs.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_caller_prefs.c @@ -194,39 +194,41 @@ static issize_t sip_caller_prefs_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { - sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h; - url_t url[1]; - char const *ignore = NULL; - int kludge = 0; + for(;;) { + sip_caller_prefs_t *cp = (sip_caller_prefs_t *)h; + url_t url[1]; + char const *ignore = NULL; + int kludge = 0; - assert(h); + assert(h); - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; - /* Kludge: support PoC IS spec with a typo... */ - if (su_casenmatch(s, "*,", 2)) - 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] == ';'); - } + /* Kludge: support PoC IS spec with a typo... */ + if (su_casenmatch(s, "*,", 2)) + 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 (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 msg_parse_next_field(home, h, s, slen); + 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; */ + msg_parse_next_field_without_recursion(); + } + } static diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c index 48cb7a6bbf..8b2913f43b 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_extra.c @@ -40,15 +40,17 @@ #define MSG_PUB_T struct sip_s #define MSG_HDR_T union sip_header_u + #include "sofia-sip/sip_parser.h" #include "sofia-sip/sip_extra.h" +#include "../su/sofia-sip/su_alloc.h" #include #include #include #include #include - +# #include /* ====================================================================== */ @@ -887,16 +889,19 @@ issize_t sip_info_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) sip_call_info_t *ci = h->sh_call_info; char *end = s + slen; - assert(h); + for(;;) { + ci = h->sh_call_info; + end = s + slen; - while (*s == ',') - s += span_lws(s + 1) + 1; + while (*s == ',') + s += span_lws(s + 1) + 1; - if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0) - return -1; + if (sip_name_addr_d(home, &s, NULL, ci->ci_url, &ci->ci_params, NULL) < 0) + return -1; - /* Recurse */ - return msg_parse_next_field(home, h, s, end - s); + slen = end - s; + msg_parse_next_field_without_recursion(); + } } isize_t sip_info_dup_xtra(sip_header_t const *h, isize_t offset) @@ -1148,18 +1153,23 @@ SIP_HEADER_CLASS(remote_party_id, "Remote-Party-ID", "", issize_t sip_remote_party_id_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { - sip_remote_party_id_t *rpid = (sip_remote_party_id_t *)h; + sip_remote_party_id_t *rpid; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + for(;;) { + rpid = (sip_remote_party_id_t *)h; - if (sip_name_addr_d(home, &s, - &rpid->rpid_display, - rpid->rpid_url, - &rpid->rpid_params, NULL) == -1) - return -1; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; + + if (sip_name_addr_d(home, &s, + &rpid->rpid_display, + rpid->rpid_url, + &rpid->rpid_params, NULL) == -1) + return -1; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } issize_t sip_remote_party_id_e(char b[], isize_t bsiz, @@ -1288,18 +1298,22 @@ SIP_HEADER_CLASS(p_asserted_identity, "P-Asserted-Identity", "", issize_t sip_p_asserted_identity_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) { - sip_p_asserted_identity_t *paid = (sip_p_asserted_identity_t *)h; + sip_p_asserted_identity_t *paid; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + for(;;) { + paid = (sip_p_asserted_identity_t *)h; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 1; - if (sip_name_addr_d(home, &s, - &paid->paid_display, - paid->paid_url, - NULL, NULL) == -1) - return -1; + if (sip_name_addr_d(home, &s, + &paid->paid_display, + paid->paid_url, + NULL, NULL) == -1) + return -1; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } issize_t sip_p_asserted_identity_e(char b[], isize_t bsiz, diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_mime.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_mime.c index 90cce374de..62286bc0fa 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_mime.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_mime.c @@ -135,24 +135,28 @@ 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_accept_disposition_t *ad = (sip_accept_disposition_t *)h; + sip_accept_disposition_t *ad; - assert(h); + assert(h); - /* Ignore empty entries (comma-whitespace) */ - while (*s == ',') - s += span_lws(s + 1) + 1; + for(;;) { + ad = (sip_accept_disposition_t *)h; + /* Ignore empty entries (comma-whitespace) */ + while (*s == ',') + s += span_lws(s + 1) + 1; - /* "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; + /* "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; - if (ad->ad_subtype) ad->ad_subtype++; + if (ad->ad_subtype) ad->ad_subtype++; + + msg_parse_next_field_without_recursion(); + } - 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) diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_reason.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_reason.c index bb7dbd068f..995fd8c816 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_reason.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_reason.c @@ -96,20 +96,25 @@ 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_reason_t *re = (sip_reason_t *)h; - size_t n; + sip_reason_t *re; + size_t n; + for (;;) { + re = (sip_reason_t *)h; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + while (*s == ',') /* Ignore empty entries (comma-whitespace) */ + *s = '\0', s += span_lws(s + 1) + 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; + + msg_parse_next_field_without_recursion(); + } - 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 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) diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_security.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_security.c index 99520b2aac..69cddff252 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_security.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_security.c @@ -458,20 +458,24 @@ 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_security_agree_t *sa = (sip_security_agree_t *)h; - isize_t n; + for (;;) { + sip_security_agree_t *sa = (sip_security_agree_t *)h; - while (*s == ',') /* Ignore empty entries (comma-whitespace) */ - *s = '\0', s += span_lws(s + 1) + 1; + isize_t n; - 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; + 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; + + msg_parse_next_field_without_recursion(); + } - return msg_parse_next_field(home, h, s, slen); } static