|
|
|
|
@ -61,217 +61,230 @@ string replaceParameters(const string& s,
|
|
|
|
|
string res;
|
|
|
|
|
bool is_replaced = false;
|
|
|
|
|
size_t p = 0;
|
|
|
|
|
char last_char=' ';
|
|
|
|
|
bool is_escaped = false;
|
|
|
|
|
|
|
|
|
|
// char last_char=' ';
|
|
|
|
|
|
|
|
|
|
while (p<s.length()) {
|
|
|
|
|
size_t skip_chars = 1;
|
|
|
|
|
if (last_char=='\\') {
|
|
|
|
|
res += s[p];
|
|
|
|
|
is_replaced = true;
|
|
|
|
|
} else if (s[p]=='\\') {
|
|
|
|
|
if (p==s.length()-1)
|
|
|
|
|
res += s[p];
|
|
|
|
|
} else if ((s[p]=='$') && (s.length() >= p+1)) {
|
|
|
|
|
is_replaced = true;
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
if (is_escaped) {
|
|
|
|
|
switch (s[p]) {
|
|
|
|
|
case 'f': { // from
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) {
|
|
|
|
|
res += req.from;
|
|
|
|
|
break;
|
|
|
|
|
case 'r': res += '\r'; break;
|
|
|
|
|
case 'n': res += '\n'; break;
|
|
|
|
|
case 't': res += '\t'; break;
|
|
|
|
|
default: res += s[p]; break;
|
|
|
|
|
}
|
|
|
|
|
is_escaped = false;
|
|
|
|
|
} else { // not escaped
|
|
|
|
|
if (s[p]=='\\') {
|
|
|
|
|
if (p==s.length()-1) {
|
|
|
|
|
res += '\\'; // add single \ at the end
|
|
|
|
|
} else {
|
|
|
|
|
is_escaped = true;
|
|
|
|
|
is_replaced = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (from_parser.uri.empty()) {
|
|
|
|
|
from_parser.uri = req.from;
|
|
|
|
|
if (!from_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing From URI '%s'\n", req.from.c_str());
|
|
|
|
|
} else if ((s[p]=='$') && (s.length() >= p+1)) {
|
|
|
|
|
is_replaced = true;
|
|
|
|
|
p++;
|
|
|
|
|
switch (s[p]) {
|
|
|
|
|
case 'f': { // from
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) {
|
|
|
|
|
res += req.from;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
replaceParsedParam(s, p, from_parser, res);
|
|
|
|
|
if (from_parser.uri.empty()) {
|
|
|
|
|
from_parser.uri = req.from;
|
|
|
|
|
if (!from_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing From URI '%s'\n", req.from.c_str());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}; break;
|
|
|
|
|
replaceParsedParam(s, p, from_parser, res);
|
|
|
|
|
|
|
|
|
|
case 't': { // to
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) {
|
|
|
|
|
res += req.to;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
if (to_parser.uri.empty()) {
|
|
|
|
|
to_parser.uri = req.to;
|
|
|
|
|
if (!to_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing To URI '%s'\n", req.to.c_str());
|
|
|
|
|
case 't': { // to
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) {
|
|
|
|
|
res += req.to;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
replaceParsedParam(s, p, to_parser, res);
|
|
|
|
|
if (to_parser.uri.empty()) {
|
|
|
|
|
to_parser.uri = req.to;
|
|
|
|
|
if (!to_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing To URI '%s'\n", req.to.c_str());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}; break;
|
|
|
|
|
replaceParsedParam(s, p, to_parser, res);
|
|
|
|
|
|
|
|
|
|
case 'r': { // r-uri
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) {
|
|
|
|
|
res += req.r_uri;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (ruri_parser.uri.empty()) {
|
|
|
|
|
ruri_parser.uri = req.r_uri;
|
|
|
|
|
if (!ruri_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing R-URI '%s'\n", req.r_uri.c_str());
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
case 'r': { // r-uri
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) {
|
|
|
|
|
res += req.r_uri;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
replaceParsedParam(s, p, ruri_parser, res);
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
case 'c': { // call-id
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == 'i')) {
|
|
|
|
|
res += req.callid;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
WARN("unknown replacement $c%c\n", s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
if (ruri_parser.uri.empty()) {
|
|
|
|
|
ruri_parser.uri = req.r_uri;
|
|
|
|
|
if (!ruri_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing R-URI '%s'\n", req.r_uri.c_str());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
replaceParsedParam(s, p, ruri_parser, res);
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
case 's': { // source (remote)
|
|
|
|
|
if (s.length() < p+1) {
|
|
|
|
|
WARN("unknown replacement $s\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 'c': { // call-id
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == 'i')) {
|
|
|
|
|
res += req.callid;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
WARN("unknown replacement $c%c\n", s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
if (s[p+1] == 'i') { // $si source IP address
|
|
|
|
|
res += req.remote_ip.c_str();
|
|
|
|
|
break;
|
|
|
|
|
} else if (s[p+1] == 'p') { // $sp source port
|
|
|
|
|
res += int2str(req.remote_port);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 's': { // source (remote)
|
|
|
|
|
if (s.length() < p+1) {
|
|
|
|
|
WARN("unknown replacement $s\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WARN("unknown replacement $s%c\n", s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
if (s[p+1] == 'i') { // $si source IP address
|
|
|
|
|
res += req.remote_ip.c_str();
|
|
|
|
|
break;
|
|
|
|
|
} else if (s[p+1] == 'p') { // $sp source port
|
|
|
|
|
res += int2str(req.remote_port);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case 'R': { // received (local)
|
|
|
|
|
if (s.length() < p+1) {
|
|
|
|
|
WARN("unknown replacement $R\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
WARN("unknown replacement $s%c\n", s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
if (s[p+1] == 'i') { // $si source IP address
|
|
|
|
|
res += req.local_ip.c_str();
|
|
|
|
|
break;
|
|
|
|
|
} else if (s[p+1] == 'p') { // $sp source port
|
|
|
|
|
res += int2str(req.local_port);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
WARN("unknown replacement $R%c\n", s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
case 'R': { // received (local)
|
|
|
|
|
if (s.length() < p+1) {
|
|
|
|
|
WARN("unknown replacement $R\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (s[p+1] == 'i') { // $si source IP address
|
|
|
|
|
res += req.local_ip.c_str();
|
|
|
|
|
break;
|
|
|
|
|
} else if (s[p+1] == 'p') { // $sp source port
|
|
|
|
|
res += int2str(req.local_port);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
WARN("unknown replacement $R%c\n", s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define case_HDR(pv_char, pv_name, hdr_name) \
|
|
|
|
|
case pv_char: { \
|
|
|
|
|
AmUriParser uri_parser; \
|
|
|
|
|
uri_parser.uri = getHeader(req.hdrs, hdr_name); \
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) { \
|
|
|
|
|
res += uri_parser.uri; \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
case pv_char: { \
|
|
|
|
|
AmUriParser uri_parser; \
|
|
|
|
|
uri_parser.uri = getHeader(req.hdrs, hdr_name); \
|
|
|
|
|
if ((s.length() == p+1) || (s[p+1] == '.')) { \
|
|
|
|
|
res += uri_parser.uri; \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
\
|
|
|
|
|
if (!uri_parser.parse_uri()) { \
|
|
|
|
|
WARN("Error parsing " pv_name " URI '%s'\n", uri_parser.uri.c_str()); \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
if (s[p+1] == 'i') { \
|
|
|
|
|
res+=uri_parser.uri_user+"@"+uri_parser.uri_host; \
|
|
|
|
|
if (!uri_parser.uri_port.empty()) \
|
|
|
|
|
res+=":"+uri_parser.uri_port; \
|
|
|
|
|
} else { \
|
|
|
|
|
replaceParsedParam(s, p, uri_parser, res); \
|
|
|
|
|
} \
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
case_HDR('a', "PAI", SIP_HDR_P_ASSERTED_IDENTITY); // P-Asserted-Identity
|
|
|
|
|
case_HDR('p', "PPI", SIP_HDR_P_PREFERRED_IDENTITY); // P-Preferred-Identity
|
|
|
|
|
|
|
|
|
|
case 'P': { // app-params
|
|
|
|
|
if (s[p+1] != '(') {
|
|
|
|
|
WARN("Error parsing P param replacement (missing '(')\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (s.length()<p+3) {
|
|
|
|
|
WARN("Error parsing P param replacement (short string)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (!uri_parser.parse_uri()) { \
|
|
|
|
|
WARN("Error parsing " pv_name " URI '%s'\n", uri_parser.uri.c_str()); \
|
|
|
|
|
break; \
|
|
|
|
|
} \
|
|
|
|
|
if (s[p+1] == 'i') { \
|
|
|
|
|
res+=uri_parser.uri_user+"@"+uri_parser.uri_host; \
|
|
|
|
|
if (!uri_parser.uri_port.empty()) \
|
|
|
|
|
res+=":"+uri_parser.uri_port; \
|
|
|
|
|
} else { \
|
|
|
|
|
replaceParsedParam(s, p, uri_parser, res); \
|
|
|
|
|
} \
|
|
|
|
|
}; break;
|
|
|
|
|
|
|
|
|
|
size_t skip_p = p+2;
|
|
|
|
|
for (;skip_p<s.length() && s[skip_p] != ')';skip_p++) { }
|
|
|
|
|
if (skip_p==s.length()) {
|
|
|
|
|
WARN("Error parsing P param replacement (unclosed brackets)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
string param_name = s.substr(p+2, skip_p-p-2);
|
|
|
|
|
// DBG("param_name = '%s' (skip-p - p = %d)\n", param_name.c_str(), skip_p-p);
|
|
|
|
|
res += get_header_keyvalue(app_param, param_name);
|
|
|
|
|
skip_chars = skip_p-p;
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case 'H': { // header
|
|
|
|
|
size_t name_offset = 2;
|
|
|
|
|
if (s[p+1] != '(') {
|
|
|
|
|
if (s[p+2] != '(') {
|
|
|
|
|
WARN("Error parsing H header replacement (missing '(')\n");
|
|
|
|
|
case_HDR('a', "PAI", SIP_HDR_P_ASSERTED_IDENTITY); // P-Asserted-Identity
|
|
|
|
|
case_HDR('p', "PPI", SIP_HDR_P_PREFERRED_IDENTITY); // P-Preferred-Identity
|
|
|
|
|
|
|
|
|
|
case 'P': { // app-params
|
|
|
|
|
if (s[p+1] != '(') {
|
|
|
|
|
WARN("Error parsing P param replacement (missing '(')\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (s.length()<p+3) {
|
|
|
|
|
WARN("Error parsing P param replacement (short string)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
name_offset = 3;
|
|
|
|
|
}
|
|
|
|
|
if (s.length()<name_offset+1) {
|
|
|
|
|
WARN("Error parsing H header replacement (short string)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t skip_p = p+name_offset;
|
|
|
|
|
for (;skip_p<s.length() && s[skip_p] != ')';skip_p++) { }
|
|
|
|
|
if (skip_p==s.length()) {
|
|
|
|
|
WARN("Error parsing H header replacement (unclosed brackets)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
string hdr_name = s.substr(p+name_offset, skip_p-p-name_offset);
|
|
|
|
|
// DBG("param_name = '%s' (skip-p - p = %d)\n", param_name.c_str(), skip_p-p);
|
|
|
|
|
if (name_offset == 2) {
|
|
|
|
|
// full header
|
|
|
|
|
res += getHeader(req.hdrs, hdr_name);
|
|
|
|
|
} else {
|
|
|
|
|
// parse URI and use component
|
|
|
|
|
AmUriParser uri_parser;
|
|
|
|
|
uri_parser.uri = getHeader(req.hdrs, hdr_name);
|
|
|
|
|
if ((s[p+1] == '.')) {
|
|
|
|
|
res += uri_parser.uri;
|
|
|
|
|
size_t skip_p = p+2;
|
|
|
|
|
for (;skip_p<s.length() && s[skip_p] != ')';skip_p++) { }
|
|
|
|
|
if (skip_p==s.length()) {
|
|
|
|
|
WARN("Error parsing P param replacement (unclosed brackets)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
string param_name = s.substr(p+2, skip_p-p-2);
|
|
|
|
|
// DBG("param_name = '%s' (skip-p - p = %d)\n", param_name.c_str(), skip_p-p);
|
|
|
|
|
res += get_header_keyvalue(app_param, param_name);
|
|
|
|
|
skip_chars = skip_p-p;
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
if (!uri_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing header %s URI '%s'\n",
|
|
|
|
|
hdr_name.c_str(), uri_parser.uri.c_str());
|
|
|
|
|
case 'H': { // header
|
|
|
|
|
size_t name_offset = 2;
|
|
|
|
|
if (s[p+1] != '(') {
|
|
|
|
|
if (s[p+2] != '(') {
|
|
|
|
|
WARN("Error parsing H header replacement (missing '(')\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
name_offset = 3;
|
|
|
|
|
}
|
|
|
|
|
if (s.length()<name_offset+1) {
|
|
|
|
|
WARN("Error parsing H header replacement (short string)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
replaceParsedParam(s, p, uri_parser, res);
|
|
|
|
|
}
|
|
|
|
|
skip_chars = skip_p-p;
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
default: {
|
|
|
|
|
WARN("unknown replace pattern $%c%c\n",
|
|
|
|
|
s[p], s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
};
|
|
|
|
|
size_t skip_p = p+name_offset;
|
|
|
|
|
for (;skip_p<s.length() && s[skip_p] != ')';skip_p++) { }
|
|
|
|
|
if (skip_p==s.length()) {
|
|
|
|
|
WARN("Error parsing H header replacement (unclosed brackets)\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
string hdr_name = s.substr(p+name_offset, skip_p-p-name_offset);
|
|
|
|
|
// DBG("param_name = '%s' (skip-p - p = %d)\n", param_name.c_str(), skip_p-p);
|
|
|
|
|
if (name_offset == 2) {
|
|
|
|
|
// full header
|
|
|
|
|
res += getHeader(req.hdrs, hdr_name);
|
|
|
|
|
} else {
|
|
|
|
|
// parse URI and use component
|
|
|
|
|
AmUriParser uri_parser;
|
|
|
|
|
uri_parser.uri = getHeader(req.hdrs, hdr_name);
|
|
|
|
|
if ((s[p+1] == '.')) {
|
|
|
|
|
res += uri_parser.uri;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!uri_parser.parse_uri()) {
|
|
|
|
|
WARN("Error parsing header %s URI '%s'\n",
|
|
|
|
|
hdr_name.c_str(), uri_parser.uri.c_str());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
replaceParsedParam(s, p, uri_parser, res);
|
|
|
|
|
}
|
|
|
|
|
skip_chars = skip_p-p;
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
default: {
|
|
|
|
|
WARN("unknown replace pattern $%c%c\n",
|
|
|
|
|
s[p], s[p+1]);
|
|
|
|
|
}; break;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
p+=skip_chars; // skip $.X
|
|
|
|
|
} else {
|
|
|
|
|
res += s[p];
|
|
|
|
|
}
|
|
|
|
|
p+=skip_chars; // skip $.X
|
|
|
|
|
} else {
|
|
|
|
|
res += s[p];
|
|
|
|
|
}
|
|
|
|
|
} // end not escaped
|
|
|
|
|
|
|
|
|
|
last_char = s[p];
|
|
|
|
|
p++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|