diff --git a/channels/chan_sip.c b/channels/chan_sip.c index f013d7406c61c08722ff8ff9d50fc204feee5cf5..d52221f0e101d0e2577d07fb24b0767c234311e7 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2138,47 +2138,65 @@ static int send_request(struct sip_pvt *p, struct sip_request *req, enum xmittyp return res; } +/*! \brief Locate closing quote in a string, skipping escaped quotes. + * optionally with a limit on the search. + * start must be past the first quote. + */ +static const char *find_closing_quote(const char *start, const char *lim) +{ + char last_char = '\0'; + const char *s; + for (s = start; *s && s != lim; last_char = *s++) { + if (*s == '"' && last_char != '\\') + break; + } + return s; +} + /*! \brief Pick out text in brackets from character string \return pointer to terminated stripped string - \param tmp input string that will be modified */ + \param tmp input string that will be modified + Examples: + + "foo" <bar> valid input, returns bar + foo returns the whole string + < "foo ... > returns the string between brackets + < "foo... bogus (missing closing bracket), returns the whole string + XXX maybe should still skip the opening bracket + */ static char *get_in_brackets(char *tmp) { - char *parse; - char *first_quote; + const char *parse = tmp; char *first_bracket; - char *second_bracket; - char last_char; - parse = tmp; - for (;;) { - first_quote = strchr(parse, '"'); - first_bracket = strchr(parse, '<'); - if (first_quote && first_bracket && (first_quote < first_bracket)) { - last_char = '\0'; - for (parse = first_quote + 1; *parse; parse++) { - if ((*parse == '"') && (last_char != '\\')) - break; - last_char = *parse; - } - if (!*parse) { - ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); - return tmp; - } - parse++; - continue; + /* + * Skip any quoted text until we find the part in brackets. + * On any error give up and return the full string. + */ + while ( (first_bracket = strchr(parse, '<')) ) { + char *first_quote = strchr(parse, '"'); + + if (!first_quote || first_quote > first_bracket) + break; /* no need to look at quoted part */ + /* the bracket is within quotes, so ignore it */ + parse = find_closing_quote(first_quote + 1, NULL); + if (!*parse) { /* not found, return full string ? */ + /* XXX or be robust and return in-bracket part ? */ + ast_log(LOG_WARNING, "No closing quote found in '%s'\n", tmp); + break; } - if (first_bracket) { - second_bracket = strchr(first_bracket + 1, '>'); - if (second_bracket) { - *second_bracket = '\0'; - return first_bracket + 1; - } else { - ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); - return tmp; - } + parse++; + } + if (first_bracket) { + char *second_bracket = strchr(first_bracket + 1, '>'); + if (second_bracket) { + *second_bracket = '\0'; + tmp = first_bracket + 1; + } else { + ast_log(LOG_WARNING, "No closing bracket found in '%s'\n", tmp); } - return tmp; } + return tmp; } /*! \brief Send SIP MESSAGE text within a call