/* returns -1 on error. */ int osip_message_set_header(osip_message_t * sip, const char *hname, const char *hvalue) { osip_header_t *h; int i; if (sip == NULL || hname == NULL) return OSIP_BADPARAMETER; i = osip_header_init(&h); if (i != 0) return i; h->hname = (char *) osip_malloc(strlen(hname) + 1); if (h->hname == NULL) { osip_header_free(h); return OSIP_NOMEM; } osip_clrncpy(h->hname, hname, strlen(hname)); if (hvalue != NULL) { /* some headers can be null ("subject:") */ h->hvalue = (char *) osip_malloc(strlen(hvalue) + 1); if (h->hvalue == NULL) { osip_header_free(h); return OSIP_NOMEM; } osip_clrncpy(h->hvalue, hvalue, strlen(hvalue)); } else h->hvalue = NULL; sip->message_property = 2; osip_list_add(&sip->headers, h, -1); return OSIP_SUCCESS; /* ok */ }
/* returns -1 on error. */ int osip_cseq_parse (osip_cseq_t * cseq, const char *hvalue) { char *method = NULL; const char *end = NULL; cseq->number = NULL; cseq->method = NULL; method = strchr (hvalue, ' '); /* SEARCH FOR SPACE */ end = hvalue + strlen (hvalue); if (method == NULL) return -1; if (method - hvalue + 1 < 2) return -1; cseq->number = (char *) osip_malloc (method - hvalue + 1); if (cseq->number == NULL) return -1; osip_clrncpy (cseq->number, hvalue, method - hvalue); if (end - method + 1 < 2) return -1; cseq->method = (char *) osip_malloc (end - method + 1); if (cseq->method == NULL) return -1; osip_clrncpy (cseq->method, method + 1, end - method); return 0; /* ok */ }
/* returns -1 on error. */ int osip_cseq_parse(osip_cseq_t * cseq, const char *hvalue) { char *method = NULL; const char *end = NULL; if (cseq == NULL || hvalue == NULL) return OSIP_BADPARAMETER; cseq->number = NULL; cseq->method = NULL; method = strchr(hvalue, ' '); /* SEARCH FOR SPACE */ if (method == NULL) return OSIP_SYNTAXERROR; end = hvalue + strlen(hvalue); if (method - hvalue + 1 < 2) return OSIP_SYNTAXERROR; cseq->number = (char *) osip_malloc(method - hvalue + 1); if (cseq->number == NULL) return OSIP_NOMEM; osip_clrncpy(cseq->number, hvalue, method - hvalue); if (end - method + 1 < 2) return OSIP_SYNTAXERROR; cseq->method = (char *) osip_malloc(end - method + 1); if (cseq->method == NULL) return OSIP_NOMEM; osip_clrncpy(cseq->method, method + 1, end - method); return OSIP_SUCCESS; /* ok */ }
/* returns -1 on error. */ int osip_content_type_parse(osip_content_type_t * content_type, const char *hvalue) { char *subtype; char *osip_content_type_params; int i; /* How to parse: we'll place the pointers: subtype => beginning of subtype osip_content_type_params => beginning of params examples: application/multipart ; boundary= ^ ^ */ if (hvalue == NULL || hvalue[0] == '\0') return OSIP_SUCCESS; /* It's valid to add empty Accept header! */ subtype = strchr(hvalue, '/'); osip_content_type_params = strchr(hvalue, ';'); if (subtype == NULL) return OSIP_SYNTAXERROR; /* do we really mind such an error */ if (osip_content_type_params != NULL) { i = __osip_generic_param_parseall(&content_type->gen_params, osip_content_type_params); if (i != 0) return i; } else osip_content_type_params = subtype + strlen(subtype); if (subtype - hvalue + 1 < 2) return OSIP_SYNTAXERROR; content_type->type = (char *) osip_malloc(subtype - hvalue + 1); if (content_type->type == NULL) return OSIP_NOMEM; osip_clrncpy(content_type->type, hvalue, subtype - hvalue); if (osip_content_type_params - subtype < 2) return OSIP_SYNTAXERROR; content_type->subtype = (char *) osip_malloc(osip_content_type_params - subtype); if (content_type->subtype == NULL) return OSIP_NOMEM; osip_clrncpy(content_type->subtype, subtype + 1, osip_content_type_params - subtype - 1); return OSIP_SUCCESS; }
int osip_call_info_parse (osip_call_info_t * call_info, const char *hvalue) { const char *osip_call_info_params; osip_call_info_params = strchr (hvalue, '<'); if (osip_call_info_params == NULL) return -1; osip_call_info_params = strchr (osip_call_info_params + 1, '>'); if (osip_call_info_params == NULL) return -1; osip_call_info_params = strchr (osip_call_info_params + 1, ';'); if (osip_call_info_params != NULL) { if (__osip_generic_param_parseall (call_info->gen_params, osip_call_info_params) == -1) return -1; } else osip_call_info_params = hvalue + strlen (hvalue); if (osip_call_info_params - hvalue + 1 < 2) return -1; call_info->element = (char *) osip_malloc (osip_call_info_params - hvalue + 1); if (call_info->element == NULL) return -1; osip_clrncpy (call_info->element, hvalue, osip_call_info_params - hvalue); return 0; }
int osip_accept_encoding_parse (osip_accept_encoding_t * accept_encoding, const char *hvalue) { const char *osip_accept_encoding_params; osip_accept_encoding_params = strchr (hvalue, ';'); if (osip_accept_encoding_params != NULL) { if (__osip_generic_param_parseall (&accept_encoding->gen_params, osip_accept_encoding_params) == -1) return -1; } else osip_accept_encoding_params = hvalue + strlen (hvalue); if (osip_accept_encoding_params - hvalue + 1 < 2) return -1; accept_encoding->element = (char *) osip_malloc (osip_accept_encoding_params - hvalue + 1); if (accept_encoding->element == NULL) return -1; osip_clrncpy (accept_encoding->element, hvalue, osip_accept_encoding_params - hvalue); return 0; }
int osip_accept_encoding_parse(osip_accept_encoding_t * accept_encoding, const char *hvalue) { int i; const char *osip_accept_encoding_params; osip_accept_encoding_params = strchr(hvalue, ';'); if (osip_accept_encoding_params != NULL) { i = __osip_generic_param_parseall(&accept_encoding->gen_params, osip_accept_encoding_params); if (i != 0) return i; } else osip_accept_encoding_params = hvalue + strlen(hvalue); if (osip_accept_encoding_params - hvalue + 1 < 2) return OSIP_SYNTAXERROR; accept_encoding->element = (char *) osip_malloc(osip_accept_encoding_params - hvalue + 1); if (accept_encoding->element == NULL) return OSIP_NOMEM; osip_clrncpy(accept_encoding->element, hvalue, osip_accept_encoding_params - hvalue); return OSIP_SUCCESS; }
int osip_call_info_parse (osip_call_info_t * call_info, const char *hvalue) { const char *osip_call_info_params; int i; osip_call_info_params = strchr (hvalue, '<'); if (osip_call_info_params == NULL) return OSIP_SYNTAXERROR; osip_call_info_params = strchr (osip_call_info_params + 1, '>'); if (osip_call_info_params == NULL) return OSIP_SYNTAXERROR; osip_call_info_params = strchr (osip_call_info_params + 1, ';'); if (osip_call_info_params != NULL) { i = __osip_generic_param_parseall(&call_info->gen_params, osip_call_info_params); if (i != 0) return i; } else osip_call_info_params = hvalue + strlen (hvalue); if (osip_call_info_params - hvalue + 1 < 2) return OSIP_SYNTAXERROR; call_info->element = (char *) osip_malloc (osip_call_info_params - hvalue + 1); if (call_info->element == NULL) return OSIP_NOMEM; osip_clrncpy (call_info->element, hvalue, osip_call_info_params - hvalue); return OSIP_SUCCESS; }
/* returns -1 on error. */ int osip_message_replace_header (osip_message_t * sip, const char *hname, const char *hvalue) { osip_header_t *h, *oldh; int i, oldpos = -1; if (sip == NULL || hname == NULL) return OSIP_BADPARAMETER; oldpos = osip_message_header_get_byname(sip, hname, 0, &oldh); i = osip_header_init (&h); if (i != 0) return i; h->hname = (char *) osip_malloc (strlen (hname) + 1); if (h->hname == NULL) { osip_header_free (h); return OSIP_NOMEM; } osip_clrncpy (h->hname, hname, strlen (hname)); if (hvalue != NULL) { /* some headers can be null ("subject:") */ h->hvalue = (char *) osip_malloc (strlen (hvalue) + 1); if (h->hvalue == NULL) { osip_header_free (h); return OSIP_NOMEM; } osip_clrncpy (h->hvalue, hvalue, strlen (hvalue)); } else h->hvalue = NULL; if (oldpos != -1) { osip_list_remove(&sip->headers, oldpos); osip_header_free(oldh); } sip->message_property = 2; osip_list_add (&sip->headers, h, -1); return OSIP_SUCCESS; /* ok */ }
int osip_content_disposition_parse (osip_content_disposition_t * cd, const char *hvalue) { const char *cd_params; cd_params = strchr (hvalue, ';'); if (cd_params != NULL) { if (__osip_generic_param_parseall (&cd->gen_params, cd_params) == -1) return -1; } else cd_params = hvalue + strlen (hvalue); if (cd_params - hvalue + 1 < 2) return -1; cd->element = (char *) osip_malloc (cd_params - hvalue + 1); if (cd->element == NULL) return -1; osip_clrncpy (cd->element, hvalue, cd_params - hvalue); return 0; }
int __osip_token_set (const char *name, const char *str, char **result, const char **next) { const char *beg; const char *tmp; *next = str; if (*result != NULL) return OSIP_SUCCESS; /* already parsed */ *next = NULL; beg = strchr (str, '='); if (beg == NULL) return OSIP_SYNTAXERROR; /* bad header format... */ if (strlen (str) < 6) return OSIP_SUCCESS; /* end of header... */ while ((' ' == *str) || ('\t' == *str) || (',' == *str)) if (*str) str++; else return OSIP_SYNTAXERROR; /* bad header format */ if (osip_strncasecmp (name, str, strlen (name)) == 0) { const char *end; end = strchr (str, ','); if (end == NULL) end = str + strlen (str); /* This is the end of the header */ if (end - beg < 2) return OSIP_SYNTAXERROR; *result = (char *) osip_malloc (end - beg); if (*result == NULL) return OSIP_NOMEM; osip_clrncpy (*result, beg + 1, end - beg - 1); /* make sure the element does not contain more parameter */ tmp = (*end) ? (end + 1) : end; for (; *tmp == ' ' || *tmp == '\t'; tmp++) { } for (; *tmp == '\n' || *tmp == '\r'; tmp++) { } /* skip LWS */ *next = NULL; if (*tmp == '\0') /* end of header detected */ return OSIP_SUCCESS; if (*tmp != '\t' && *tmp != ' ') /* LWS here ? */ *next = tmp; else { /* it is: skip it... */ for (; *tmp == ' ' || *tmp == '\t'; tmp++) { } if (*tmp == '\0') /* end of header detected */ return OSIP_SUCCESS; *next = tmp; } } else *next = str; /* next element start here */ return OSIP_SUCCESS; }
int osip_message_set_multiple_header(osip_message_t * sip, char *hname, char *hvalue) { int i; char *ptr; /* current location of the search */ char *comma; /* This is the separator we are elooking for */ char *beg; /* beg of a header */ char *end; /* end of a header */ char *quote1; /* first quote of a pair of quotes */ char *quote2; /* second quuote of a pair of quotes */ size_t hname_len; /* Find header based upon lowercase comparison */ osip_tolower(hname); if (hvalue == NULL) { i = osip_message_set__header(sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } ptr = hvalue; comma = strchr(ptr, ','); hname_len = strlen(hname); if (comma == NULL || (hname_len == 4 && strncmp(hname, "date", 4) == 0) || (hname_len == 2 && strncmp(hname, "to", 2) == 0) || (hname_len == 4 && strncmp(hname, "from", 4) == 0) || (hname_len == 7 && strncmp(hname, "call-id", 7) == 0) || (hname_len == 4 && strncmp(hname, "cseq", 4) == 0) || (hname_len == 7 && strncmp(hname, "subject", 7) == 0) || (hname_len == 7 && strncmp(hname, "expires", 7) == 0) || (hname_len == 6 && strncmp(hname, "server", 6) == 0) || (hname_len == 10 && strncmp(hname, "user-agent", 10) == 0) || (hname_len == 16 && strncmp(hname, "www-authenticate", 16) == 0) || (hname_len == 19 && strncmp(hname, "authentication-info", 19) == 0) || (hname_len == 18 && strncmp(hname, "proxy-authenticate", 18) == 0) || (hname_len == 19 && strncmp(hname, "proxy-authorization", 19) == 0) || (hname_len == 25 && strncmp(hname, "proxy-authentication-info", 25) == 0) || (hname_len == 12 && strncmp(hname, "organization", 12) == 0) || (hname_len == 13 && strncmp(hname, "authorization", 13) == 0)) /* there is no multiple header! likely */ /* to happen most of the time... */ /* or hname is a TEXT-UTF8-TRIM and may */ /* contain a comma. this is not a separator */ /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */ { i = osip_message_set__header(sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } beg = hvalue; end = NULL; quote2 = NULL; while (comma != NULL) { quote1 = __osip_quote_find(ptr); if (quote1 != NULL) { quote2 = __osip_quote_find(quote1 + 1); if (quote2 == NULL) return OSIP_SYNTAXERROR; /* quotes comes by pair */ ptr = quote2 + 1; } if ((quote1 == NULL) || (quote1 > comma)) { /* We must search for the next comma which is not within quotes! */ end = comma; if (quote1 != NULL && quote1 > comma) { /* comma may be within the quotes */ /* ,<sip:[email protected]>;methods=\"INVITE,BYE,OPTIONS,ACK,CANCEL\",<sip:[email protected]> */ /* we want the next comma after the quotes */ char *tmp_comma; char *tmp_quote1; char *tmp_quote2; tmp_quote1 = quote1; tmp_quote2 = quote2; tmp_comma = strchr(comma + 1, ','); while (1) { if (tmp_comma < tmp_quote1) break; /* ok (before to quotes) */ if (tmp_comma < tmp_quote2) { tmp_comma = strchr(tmp_quote2 + 1, ','); } tmp_quote1 = __osip_quote_find(tmp_quote2 + 1); if (tmp_quote1 == NULL) break; tmp_quote2 = __osip_quote_find(tmp_quote1 + 1); if (tmp_quote2 == NULL) break; /* probably a malformed message? */ } comma = tmp_comma; /* this one is not enclosed within quotes */ } else comma = strchr(comma + 1, ','); if (comma != NULL) ptr = comma + 1; } else if ((quote1 < comma) && (quote2 < comma)) { /* quotes are located before the comma, */ /* continue the search for next quotes */ ptr = quote2 + 1; } else if ((quote1 < comma) && (comma < quote2)) { /* if comma is inside the quotes... */ /* continue with the next comma. */ ptr = quote2 + 1; comma = strchr(ptr, ','); if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ #if 0 if (strlen(beg) < 2) return OSIP_SUCCESS; /* empty header */ #else if (beg[0] == '\0' || beg[1] == '\0') return OSIP_SUCCESS; /* empty header */ #endif osip_clrspace(beg); i = osip_message_set__header(sip, hname, beg); if (i != 0) return i; return OSIP_SUCCESS; } } if (end != NULL) { char *avalue; if (end - beg + 1 < 2) return OSIP_SYNTAXERROR; avalue = (char *) osip_malloc(end - beg + 1); if (avalue == NULL) return OSIP_NOMEM; osip_clrncpy(avalue, beg, end - beg); /* really store the header in the sip structure */ i = osip_message_set__header(sip, hname, avalue); osip_free(avalue); if (i != 0) return i; beg = end + 1; end = NULL; if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ #if 0 if (strlen(beg) < 2) return OSIP_SUCCESS; /* empty header */ #else if (beg[0] == '\0' || beg[1] == '\0') return OSIP_SUCCESS; /* empty header */ #endif osip_clrspace(beg); i = osip_message_set__header(sip, hname, beg); if (i != 0) return i; return OSIP_SUCCESS; } } } return OSIP_SYNTAXERROR; /* if comma is NULL, we should have already return 0 */ }
/* set all headers */ static int msg_headers_parse(osip_message_t * sip, const char *start_of_header, const char **body) { const char *colon_index; /* index of ':' */ char *hname; char *hvalue; const char *end_of_header; int i; for (;;) { if (start_of_header[0] == '\0') { /* final CRLF is missing */ OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "SIP message does not end with CRLFCRLF\n")); return OSIP_SUCCESS; } i = __osip_find_next_crlf(start_of_header, &end_of_header); if (i == -2) { } else if (i != 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "End of header Not found\n")); return i; /* this is an error case! */ } /* the list of headers MUST always end with */ /* CRLFCRLF (also CRCR and LFLF are allowed) */ if ((start_of_header[0] == '\r') || (start_of_header[0] == '\n')) { *body = start_of_header; return OSIP_SUCCESS; /* end of header found */ } /* find the header name */ colon_index = strchr(start_of_header, ':'); if (colon_index == NULL) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "End of header Not found\n")); return OSIP_SYNTAXERROR; /* this is also an error case */ } if (colon_index - start_of_header + 1 < 2) return OSIP_SYNTAXERROR; if (end_of_header <= colon_index) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Malformed message\n")); return OSIP_SYNTAXERROR; } hname = (char *) osip_malloc(colon_index - start_of_header + 1); if (hname == NULL) return OSIP_NOMEM; osip_clrncpy(hname, start_of_header, colon_index - start_of_header); { const char *end; /* END of header is (end_of_header-2) if header separation is CRLF */ /* END of header is (end_of_header-1) if header separation is CR or LF */ if ((end_of_header[-2] == '\r') || (end_of_header[-2] == '\n')) end = end_of_header - 2; else end = end_of_header - 1; if ((end) - colon_index < 2) hvalue = NULL; /* some headers (subject) can be empty */ else { hvalue = (char *) osip_malloc((end) - colon_index + 1); if (hvalue == NULL) { osip_free(hname); return OSIP_NOMEM; } osip_clrncpy(hvalue, colon_index + 1, (end) - colon_index - 1); } } /* hvalue MAY contains multiple value. In this case, they */ /* are separated by commas. But, a comma may be part of a */ /* quoted-string ("here, and there" is an example where the */ /* comma is not a separator!) */ i = osip_message_set_multiple_header(sip, hname, hvalue); osip_free(hname); if (hvalue != NULL) osip_free(hvalue); if (i != 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "End of header Not found\n")); return OSIP_SYNTAXERROR; } /* continue on the next header */ start_of_header = end_of_header; } /* Unreachable code OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_BUG, NULL, "This code cannot be reached\n")); */ return OSIP_SYNTAXERROR; }
static int __osip_message_startline_parsereq(osip_message_t * dest, const char *buf, const char **headers) { const char *p1; const char *p2; char *requesturi; int i; dest->sip_method = NULL; dest->status_code = 0; dest->reason_phrase = NULL; *headers = buf; /* The first token is the method name: */ p2 = strchr(buf, ' '); if (p2 == NULL) return OSIP_SYNTAXERROR; if (*(p2 + 1) == '\0' || *(p2 + 2) == '\0') return OSIP_SYNTAXERROR; if (p2 - buf == 0) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "No space allowed here\n")); return OSIP_SYNTAXERROR; } dest->sip_method = (char *) osip_malloc(p2 - buf + 1); if (dest->sip_method == NULL) return OSIP_NOMEM; osip_strncpy(dest->sip_method, buf, p2 - buf); /* The second token is a sip-url or a uri: */ p1 = strchr(p2 + 2, ' '); /* no space allowed inside sip-url */ if (p1 == NULL) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Uncompliant request-uri\n")); osip_free(dest->sip_method); dest->sip_method = NULL; return OSIP_SYNTAXERROR; } if (p1 - p2 < 2) { osip_free(dest->sip_method); dest->sip_method = NULL; return OSIP_SYNTAXERROR; } requesturi = (char *) osip_malloc(p1 - p2); if (requesturi == NULL) { osip_free(dest->sip_method); dest->sip_method = NULL; return OSIP_NOMEM; } osip_clrncpy(requesturi, p2 + 1, (p1 - p2 - 1)); i = osip_uri_init(&(dest->req_uri)); if (i != 0) { osip_free(requesturi); requesturi = NULL; osip_free(dest->sip_method); dest->sip_method = NULL; return OSIP_NOMEM; } i = osip_uri_parse(dest->req_uri, requesturi); osip_free(requesturi); if (i != 0) { osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return OSIP_SYNTAXERROR; } /* find the the version and the beginning of headers */ { const char *hp = p1; while ((*hp != '\r') && (*hp != '\n')) { if (*hp) hp++; else { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "No crlf found\n")); osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return OSIP_SYNTAXERROR; } } if (hp - p1 < 2) { osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return OSIP_SYNTAXERROR; } dest->sip_version = (char *) osip_malloc(hp - p1); if (dest->sip_version == NULL) { osip_free(dest->sip_method); dest->sip_method = NULL; osip_uri_free(dest->req_uri); dest->req_uri = NULL; return OSIP_NOMEM; } osip_strncpy(dest->sip_version, p1 + 1, (hp - p1 - 1)); if (0 != osip_strcasecmp(dest->sip_version, "SIP/2.0")) { OSIP_TRACE(osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "Wrong version number\n")); } hp++; if ((*hp) && ('\r' == hp[-1]) && ('\n' == hp[0])) hp++; (*headers) = hp; } return OSIP_SUCCESS; }
/* returns -1 on error. */ int osip_from_parse (osip_from_t * from, const char *hvalue) { const char *displayname; const char *url; const char *url_end; const char *gen_params; /* How to parse: we'll place the pointers: displayname => beginning of displayname url => beginning of url url_end => end of url gen_params => beginning of params examples: jack <sip:[email protected]>;tag=34erZ ^ ^ ^ ^ sip:[email protected];tag=34erZ ^ ^^ */ displayname = strchr (hvalue, '"'); url = strchr (hvalue, '<'); if (url != NULL) { url_end = strchr (url, '>'); if (url_end == NULL) return -1; } /* SIPit day2: this case was not supported first '"' is placed after '<' and after '>' <sip:[email protected];method=INVITE>;description="OPEN";expires=28800 if the fisrt quote is after '<' then this is not a quote for a displayname. */ if (displayname != NULL) { if (displayname > url) displayname = NULL; } if ((displayname == NULL) && (url != NULL)) { /* displayname IS A '*token' (not a quoted-string) */ if (hvalue != url) /* displayname exists */ { if (url - hvalue + 1 < 2) return -1; from->displayname = (char *) osip_malloc (url - hvalue + 1); if (from->displayname == NULL) return -1; osip_clrncpy (from->displayname, hvalue, url - hvalue); } url++; /* place pointer on the beginning of url */ } else { if ((displayname != NULL) && (url != NULL)) { /* displayname IS A quoted-string (not a '*token') */ const char *first; const char *second=NULL; /* search for quotes */ first = __osip_quote_find (hvalue); if (first == NULL) return -1; /* missing quote */ second = __osip_quote_find (first + 1); if (second == NULL) return -1; /* missing quote */ if ((first > url)) return -1; if (second - first + 2 >= 2) { from->displayname = (char *) osip_malloc (second - first + 2); if (from->displayname == NULL) return -1; osip_strncpy (from->displayname, first, second - first + 1); /* osip_clrspace(from->displayname); *//*should we do that? */ /* special case: "<sip:[email protected]>" <sip:[email protected]> */ } /* else displayname is empty? */ url = strchr (second + 1, '<'); if (url == NULL) return -1; /* '<' MUST exist */ url++; } else url = hvalue; /* field does not contains '<' and '>' */ } /* DISPLAY-NAME SET */ /* START of URL KNOWN */ url_end = strchr (url, '>'); if (url_end == NULL) /* sip:[email protected];tag=023 */ { /* We are sure ';' is the delimiter for from-parameters */ char *host = strchr (url, '@'); if (host != NULL) gen_params = strchr (host, ';'); else gen_params = strchr (url, ';'); if (gen_params != NULL) url_end = gen_params - 1; else url_end = url + strlen (url); } else /* jack <sip:[email protected];user=phone>;tag=azer */ { gen_params = strchr (url_end, ';'); url_end--; /* place pointer on the beginning of url */ } if (gen_params != NULL) /* now we are sure a param exist */ if (__osip_generic_param_parseall (&from->gen_params, gen_params) == -1) { return -1; } /* set the url */ { char *tmp; int i; if (url_end - url + 2 < 7) return -1; i = osip_uri_init (&(from->url)); if (i != 0) return -1; tmp = (char *) osip_malloc (url_end - url + 2); if (tmp == NULL) return -1; osip_strncpy (tmp, url, url_end - url + 1); i = osip_uri_parse (from->url, tmp); osip_free (tmp); if (i != 0) return -1; } return 0; }
int osip_via_parse (osip_via_t * via, const char *hvalue) { const char *version; const char *protocol; const char *host; const char *ipv6host; const char *port; const char *via_params; const char *comment; version = strchr (hvalue, '/'); if (version == NULL) return -1; protocol = strchr (version + 1, '/'); if (protocol == NULL) return -1; /* set the version */ if (protocol - version < 2) return -1; via->version = (char *) osip_malloc (protocol - version); if (via->version == NULL) return -1; osip_clrncpy (via->version, version + 1, protocol - version - 1); /* Here: we avoid matching an additionnal space */ host = strchr (protocol + 1, ' '); if (host == NULL) return -1; /* fixed in 0.8.4 */ if (host == protocol + 1) /* there are extra SPACE characters */ { while (0 == strncmp (host, " ", 1)) { host++; if (strlen (host) == 1) return -1; /* via is malformed */ } /* here, we match the real space located after the protocol name */ host = strchr (host + 1, ' '); if (host == NULL) return -1; /* fixed in 0.8.4 */ } /* set the protocol */ if (host - protocol < 2) return -1; via->protocol = (char *) osip_malloc (host - protocol); if (via->protocol == NULL) return -1; osip_clrncpy (via->protocol, protocol + 1, host - protocol - 1); /* comments in Via are not allowed any more in the latest draft (09) */ comment = strchr (host, '('); if (comment != NULL) { char *end_comment; end_comment = strchr (host, ')'); if (end_comment == NULL) return -1; /* if '(' exist ')' MUST exist */ if (end_comment - comment < 2) return -1; via->comment = (char *) osip_malloc (end_comment - comment); if (via->comment == NULL) return -1; osip_strncpy (via->comment, comment + 1, end_comment - comment - 1); comment--; } else comment = host + strlen (host); via_params = strchr (host, ';'); if ((via_params != NULL) && (via_params < comment)) /* via params exist */ { char *tmp; if (comment - via_params + 1 < 2) return -1; tmp = (char *) osip_malloc (comment - via_params + 1); if (tmp == NULL) return -1; osip_strncpy (tmp, via_params, comment - via_params); if (__osip_generic_param_parseall (&via->via_params, tmp)) { osip_free (tmp); return -1; } osip_free (tmp); } if (via_params == NULL) via_params = comment; /* add ipv6 support (0.8.4) */ /* Via: SIP/2.0/UDP [mlke::zeezf:ezfz:zef:zefzf]:port;.... */ ipv6host = strchr (host, '['); if (ipv6host != NULL && ipv6host < via_params) { port = strchr (ipv6host, ']'); if (port == NULL || port > via_params) return -1; if (port - ipv6host < 2) return -1; via->host = (char *) osip_malloc (port - ipv6host); if (via->host == NULL) return -1; osip_clrncpy (via->host, ipv6host + 1, port - ipv6host - 1); port = strchr (port, ':'); } else { port = strchr (host, ':'); ipv6host = NULL; } if ((port != NULL) && (port < via_params)) { if (via_params - port < 2) return -1; via->port = (char *) osip_malloc (via_params - port); if (via->port == NULL) return -1; osip_clrncpy (via->port, port + 1, via_params - port - 1); } else port = via_params; /* host is already set in the case of ipv6 */ if (ipv6host != NULL) return 0; if (port - host < 2) return -1; via->host = (char *) osip_malloc (port - host); if (via->host == NULL) return -1; osip_clrncpy (via->host, host + 1, port - host - 1); return 0; }
/* return -1 on error */ int osip_uri_parse (osip_uri_t * url, const char *buf) { char *username; char *password; char *host; const char *port; const char *params; const char *headers; const char *tmp; /* basic tests */ if (buf == NULL || buf[0] == '\0') return -1; tmp = strchr (buf, ':'); if (tmp == NULL) return -1; if (tmp - buf < 2) return -1; url->scheme = (char *) osip_malloc (tmp - buf + 1); if (url->scheme == NULL) return -1; osip_strncpy (url->scheme, buf, tmp - buf); if (strlen (url->scheme) < 3 || (0 != osip_strncasecmp (url->scheme, "sip", 3) && 0 != osip_strncasecmp (url->scheme, "sips", 4))) { /* Is not a sipurl ! */ size_t i = strlen (tmp + 1); if (i < 2) return -1; url->string = (char *) osip_malloc (i + 1); if (url->string == NULL) return -1; osip_strncpy (url->string, tmp + 1, i); return 0; } /* law number 1: if ('?' exists && is_located_after '@') or if ('?' exists && '@' is not there -no username-) =====> HEADER_PARAM EXIST =====> start at index(?) =====> end at the end of url */ /* find the beginning of host */ username = strchr (buf, ':'); /* if ':' does not exist, the url is not valid */ if (username == NULL) return -1; host = strchr (buf, '@'); if (host == NULL) host = username; else if (username[1] == '@') /* username is empty */ host = username + 1; else /* username exists */ { password = next_separator (username + 1, ':', '@'); if (password == NULL) password = host; else /* password exists */ { if (host - password < 2) return -1; url->password = (char *) osip_malloc (host - password); if (url->password == NULL) return -1; osip_strncpy (url->password, password + 1, host - password - 1); __osip_uri_unescape (url->password); } if (password - username < 2) return -1; { url->username = (char *) osip_malloc (password - username); if (url->username == NULL) return -1; osip_strncpy (url->username, username + 1, password - username - 1); __osip_uri_unescape (url->username); } } /* search for header after host */ headers = strchr (host, '?'); if (headers == NULL) headers = buf + strlen (buf); else /* headers exist */ osip_uri_parse_headers (url, headers); /* search for params after host */ params = strchr (host, ';'); /* search for params after host */ if (params == NULL) params = headers; else /* params exist */ { char *tmpbuf; if (headers - params + 1 < 2) return -1; tmpbuf = osip_malloc (headers - params + 1); if (tmpbuf == NULL) return -1; tmpbuf = osip_strncpy (tmpbuf, params, headers - params); osip_uri_parse_params (url, tmpbuf); osip_free (tmpbuf); } port = params - 1; while (port > host && *port != ']' && *port != ':') port--; if (*port == ':') { if (host == port) port = params; else { if ((params - port < 2) || (params - port > 8)) return -1; /* error cases */ url->port = (char *) osip_malloc (params - port); if (url->port == NULL) return -1; osip_clrncpy (url->port, port + 1, params - port - 1); } } else port = params; /* adjust port for ipv6 address */ tmp = port; while (tmp > host && *tmp != ']') tmp--; if (*tmp == ']') { port = tmp; while (host < port && *host != '[') host++; if (host >= port) return -1; } if (port - host < 2) return -1; url->host = (char *) osip_malloc (port - host); if (url->host == NULL) return -1; osip_clrncpy (url->host, host + 1, port - host - 1); return 0; }
int osip_message_set_multiple_header (osip_message_t * sip, char *hname, char *hvalue) { int i; char *ptr, *p; /* current location of the search */ char *comma; /* This is the separator we are elooking for */ char *beg; /* beg of a header */ char *end; /* end of a header */ int inquotes, inuri; /* state for inside/outside of double-qoutes or URI */ size_t hname_len; /* Find header based upon lowercase comparison */ osip_tolower (hname); if (hvalue == NULL) { i = osip_message_set__header (sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } ptr = hvalue; comma = strchr (ptr, ','); hname_len = strlen (hname); if (comma == NULL || (hname_len == 4 && strncmp (hname, "date", 4) == 0) || (hname_len == 1 && strncmp (hname, "t", 1) == 0) || (hname_len == 2 && strncmp (hname, "to", 2) == 0) || (hname_len == 1 && strncmp (hname, "f", 1) == 0) || (hname_len == 4 && strncmp (hname, "from", 4) == 0) || (hname_len == 1 && strncmp (hname, "i", 1) == 0) || (hname_len == 7 && strncmp (hname, "call-id", 7) == 0) || (hname_len == 4 && strncmp (hname, "cseq", 4) == 0) || (hname_len == 1 && strncmp (hname, "s", 1) == 0) || (hname_len == 7 && strncmp (hname, "subject", 7) == 0) || (hname_len == 7 && strncmp (hname, "expires", 7) == 0) || (hname_len == 6 && strncmp (hname, "server", 6) == 0) || (hname_len == 10 && strncmp (hname, "user-agent", 10) == 0) || (hname_len == 16 && strncmp (hname, "www-authenticate", 16) == 0) || (hname_len == 19 && strncmp (hname, "authentication-info", 19) == 0) || (hname_len == 18 && strncmp (hname, "proxy-authenticate", 18) == 0) || (hname_len == 19 && strncmp (hname, "proxy-authorization", 19) == 0) || (hname_len == 25 && strncmp (hname, "proxy-authentication-info", 25) == 0) || (hname_len == 12 && strncmp (hname, "organization", 12) == 0) || (hname_len == 13 && strncmp (hname, "authorization", 13) == 0) || (hname_len == 1 && strncmp (hname, "r", 1) == 0) /* refer-to */ || (hname_len == 8 && strncmp (hname, "refer-to", 8) == 0) || (hname_len == 1 && strncmp (hname, "b", 1) == 0) /* referred-by */ || (hname_len == 11 && strncmp (hname, "referred-by", 11) == 0)) /* there is no multiple header! likely */ /* to happen most of the time... */ /* or hname is a TEXT-UTF8-TRIM and may */ /* contain a comma. this is not a separator */ /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */ { i = osip_message_set__header (sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } beg = hvalue; inquotes = 0; inuri = 0; /* Seach for a comma that is not within quotes or a URI */ for (;; ptr++) { switch (*ptr) { case '"': /* Check that the '"' is not escaped */ for (i = 0, p = ptr; p >= beg && *p == '\\'; p--, i++); if (i % 2 == 0) inquotes = !inquotes; /* the '"' was not escaped */ break; case '<': if (!inquotes) { if (!inuri) { if((osip_strncasecmp(ptr+1, "sip:", 4) == 0 || osip_strncasecmp(ptr+1, "sips:", 5) == 0 || osip_strncasecmp(ptr+1, "http:", 5) == 0 || osip_strncasecmp(ptr+1, "https:", 6) == 0 || osip_strncasecmp(ptr+1, "tel:", 4) == 0) && strchr(ptr, '>')) inuri = 1; } /* else { if we found such sequence: "<sip:" "<sip:" ">" It might be a valid header containing data and not URIs. Thus, we ignore inuri } */ } break; case '>': if (!inquotes) { if (inuri) inuri = 0; } break; case '\0': /* we discard any validation we tried: no valid uri detected */ inquotes=0; inuri=0; case ',': if (!inquotes && !inuri) { char *avalue; if (beg[0] == '\0') return OSIP_SUCCESS; /* empty header */ end = ptr; if (end - beg + 1 < 2) { beg=end+1; break; /* skip empty header */ } avalue = (char *) osip_malloc (end - beg + 1); if (avalue==NULL) return OSIP_NOMEM; osip_clrncpy (avalue, beg, end - beg); /* really store the header in the sip structure */ i = osip_message_set__header (sip, hname, avalue); osip_free (avalue); if (i != 0) return i; beg = end + 1; } if (*ptr == '\0') return OSIP_SUCCESS; break; default: break; } } }