MT#56321 HeaderFilter: add multi-line headers parsing

We have to add multi-line headers parsing support, to be able
to properly detect and apply filters to such headers.

Since the SEMS prefers to work with single line values,
multi-line values are getting converted into signle line, like that:

  Accept: application/sdp,
    application/isup,
    multipart/mixed

gets converted into:

  Accept: application/sdp,  application/isup,  multipart/mixed

Additionally:
Support of spaces detection in hf names has been added.
We do not consider spaces as part of the hf name, if they are added.

Original ticket number: 56354

Change-Id: I6adda8218ee6b88035fa9297187187d868f4eb60
mr11.4.1
Donat Zenichev 3 years ago
parent 29400e4a97
commit d7db3e433d

@ -90,7 +90,7 @@ bool readFilter(AmConfigReader& cfg, const char* cfg_key_filter, const char* cfg
return true;
}
int skip_header(const std::string& hdr, size_t start_pos,
int skip_header(std::string& hdr, size_t start_pos,
size_t& name_end, size_t& val_begin,
size_t& val_end, size_t& hdr_end) {
/* adapted from sip/parse_header.cpp */
@ -111,8 +111,11 @@ int skip_header(const std::string& hdr, size_t start_pos,
int st = H_NAME;
int saved_st = 0;
/* iterate till actual name, if space(s)/tab(s) in front of hf name */
bool iteration_till_name = true;
size_t p = start_pos;
for (; p<hdr.length() && st != ST_LF && st != ST_CRLF; p++)
for ( ; p < hdr.length() && st != ST_LF && st != ST_CRLF; p++)
{
switch (st)
{
@ -128,9 +131,20 @@ int skip_header(const std::string& hdr, size_t start_pos,
case SP:
case HTAB:
st = H_HCOLON;
name_end = p;
/* skip spaces/tabs at the beginning of the line (if now expected hf name) */
if (!iteration_till_name) {
st = H_HCOLON;
name_end = p;
} else {
/* remove space from the name */
hdr.erase(p--, 1);
}
break;
/* other letters apart space, tab and colon */
default:
/* means - no spaces at the beginning of hf name found, start reading the name */
iteration_till_name = false;
}
break;
@ -156,9 +170,52 @@ int skip_header(const std::string& hdr, size_t start_pos,
case_CR_LF;
};
if (st==ST_CR || st==ST_LF)
val_end = p;
/* trying to guess, if this is a multi-line header */
if (st == ST_CR || st == ST_LF) {
/* if next line of SIP message begins with a space, then we should check for a multi-value */
if (hdr[p] == CR && hdr[p+1] == LF && (hdr[p+2] == SP || hdr[p+2] == HTAB))
{
printf("Checking whether the value is multi-line\n");
/* next line must not contain colon. No colon - is a clear sign of multi-line value */
size_t tmp = p;
tmp += 2;
bool colon_found = false;
for ( ; tmp < hdr.length() && hdr[tmp] != CR && hdr[tmp] != LF; tmp++)
{
if (hdr[tmp] == HCOLON) {
colon_found = true;
break;
}
}
if (colon_found) {
/* next line is definitely another header, stop parsing as a value */
val_end = p;
} else {
/* next line is a part of multi-line value */
hdr.erase(p, 2); /* remove CR and LF from the string */
st = H_VALUE;
}
break;
/* definitely not a multi-value */
} else {
val_end = p;
}
}
/* Beginning of the next part of multi-line value.
* By RFC3261 (section 7.4.1), as well as by RFC2616, multi-line value of hf,
* must begin either with at least one space or tab.
*/
if (hdr[p] == SP || hdr[p] == HTAB) {
while (hdr[p] == SP || hdr[p] == HTAB)
p++;
}
break;
case H_HCOLON:
@ -188,7 +245,7 @@ int skip_header(const std::string& hdr, size_t start_pos,
}
hdr_end = p;
if (p==hdr.length() && st==H_VALUE) {
if (p == hdr.length() && st == H_VALUE) {
val_end = p;
}
@ -213,7 +270,7 @@ int inplaceHeaderFilter(string& hdrs, const vector<FilterEntry>& filter_list) {
/* todo: multi-line header support */
size_t start_pos = 0;
while (start_pos<hdrs.length())
while (start_pos < hdrs.length())
{
size_t name_end, val_begin, val_end, hdr_end;
int res;
@ -223,10 +280,15 @@ int inplaceHeaderFilter(string& hdrs, const vector<FilterEntry>& filter_list) {
return res;
}
string hdr_name = hdrs.substr(start_pos, name_end-start_pos);
string hdr_name = hdrs.substr(start_pos, name_end - start_pos);
std::transform(hdr_name.begin(), hdr_name.end(), hdr_name.begin(), ::tolower);
bool erase = (f_type == Whitelist);
string hdr_value = hdrs.substr(val_begin, val_end - val_begin);
DBG("hdr name parsed: '%s'\n", hdr_name.c_str());
DBG("hdr value parsed: '%s'\n", hdr_value.c_str());
for (set<string>::iterator it = headerfilter_list.begin();
it != headerfilter_list.end(); ++it)
{
@ -237,9 +299,10 @@ int inplaceHeaderFilter(string& hdrs, const vector<FilterEntry>& filter_list) {
}
if (erase) {
DBG("erasing header '%s' by %s\n", hdr_name.c_str(), FilterType2String(f_type));
DBG("erasing header '%s' by filter '%s'\n", hdr_name.c_str(), FilterType2String(f_type));
hdrs.erase(start_pos, hdr_end-start_pos);
} else {
DBG("header accepted '%s' by filter '%s'\n", hdr_name.c_str(), FilterType2String(f_type));
start_pos = hdr_end;
}
}

Loading…
Cancel
Save