// incoming calls AmSession* VoiceboxFactory::onInvite(const AmSipRequest& req, const string& app_name, const map<string,string>& app_params) { string user; string pin; string domain; string language; string uid; string did; if(SimpleMode){ AmUriParser p; p.uri = req.from_uri; if (!p.parse_uri()) { DBG("parsing From-URI '%s' failed\n", p.uri.c_str()); throw AmSession::Exception(500, APP_NAME ": could not parse From-URI"); } user = p.uri_user; //domain = p.uri_domain; domain = "default"; } else { string iptel_app_param = getHeader(req.hdrs, PARAM_HDR, true); if (!iptel_app_param.length()) { throw AmSession::Exception(500, APP_NAME ": parameters not found"); } // consistently with voicemail application: // uid overrides user user = get_header_keyvalue(iptel_app_param, "uid", "UserID"); if (user.empty()) user = get_header_keyvalue(iptel_app_param, "usr", "User"); // did overrides domain domain = get_header_keyvalue(iptel_app_param, "did", "DomainID"); if (domain.empty()) domain = get_header_keyvalue(iptel_app_param, "dom", "Domain"); pin = get_header_keyvalue(iptel_app_param, "pin", "PIN"); language = get_header_keyvalue(iptel_app_param,"lng", "Language"); } // checks if (user.empty()) throw AmSession::Exception(500, APP_NAME ": user missing"); if (language.empty()) language = default_language; PromptOptions po(false, false); AmPromptCollection* pc = findPrompts(domain, language, po); if (NULL == pc) throw AmSession::Exception(500, APP_NAME ": no menu for domain/language"); return new VoiceboxDialog(user, domain, pin, pc, po); }
string replaceParameters(const string& s, const char* r_type, const AmSipRequest& req, const string& app_param, AmUriParser& ruri_parser, AmUriParser& from_parser, AmUriParser& to_parser) { string res; bool is_replaced = false; size_t p = 0; bool is_escaped = false; // char last_char=' '; while (p<s.length()) { size_t skip_chars = 1; if (is_escaped) { switch (s[p]) { 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; } } 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; } if (s[p+1]=='t') { // $ft - from tag res += req.from_tag; break; } if (from_parser.uri.empty()) { size_t end; if (!from_parser.parse_contact(req.from, 0, end)) { WARN("Error parsing From URI '%s'\n", req.from.c_str()); break; } from_parser.dump(); } replaceParsedParam(s, p, from_parser, res); }; break; case 't': { // to if ((s.length() == p+1) || (s[p+1] == '.')) { res += req.to; break; } if (to_parser.uri.empty()) { size_t end; if (!to_parser.parse_contact(req.to, 0, end)) { WARN("Error parsing To URI '%s'\n", req.to.c_str()); break; } } replaceParsedParam(s, p, to_parser, res); }; break; 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; } } 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; case 's': { // source (remote) if (s.length() < p+1) { WARN("unknown replacement $s\n"); 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; } WARN("unknown replacement $s%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') { // $Ri received IP address res += req.local_ip.c_str(); break; } else if (s[p+1] == 'p') { // $Rp received port res += int2str(req.local_port); break; } else if (s[p+1] == 'f') { // $Rf received interface id res += int2str(req.local_if); } else if (s[p+1] == 'n') { // $Rn received interface name if ((req.local_if >= 0) && req.local_if < AmConfig::Ifs.size()) { res += AmConfig::Ifs[req.local_if].name; } } else if (s[p+1] == 'I') { // $RI received interface public IP if ((req.local_if >= 0) && req.local_if < AmConfig::Ifs.size()) { res += AmConfig::Ifs[req.local_if].PublicIP; } } 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; \ string m_uri = getHeader(req.hdrs, hdr_name); \ if ((s.length() == p+1) || (s[p+1] == '.')) { \ res += m_uri; \ break; \ } \ size_t end; \ if (!uri_parser.parse_contact(m_uri, 0, end)) { \ WARN("Error parsing " pv_name " URI '%s'\n", m_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; } 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"); 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; string m_uri = getHeader(req.hdrs, hdr_name); if ((s[p+1] == '.')) { res += m_uri; break; } size_t end; if (!uri_parser.parse_contact(m_uri, 0, end)) { WARN("Error parsing header %s URI '%s'\n", hdr_name.c_str(), m_uri.c_str()); break; } replaceParsedParam(s, p, uri_parser, res); } skip_chars = skip_p-p; } break; case 'M': { // regex map if (s[p+1] != '(') { WARN("Error parsing $M regex map replacement (missing '(')\n"); break; } if (s.length()<p+3) { WARN("Error parsing $M regex map replacement (short string)\n"); break; } size_t skip_p = p+2; skip_p = skip_to_end_of_brackets(s, skip_p); if (skip_p==s.length()) { WARN("Error parsing $M regex map replacement (unclosed brackets)\n"); skip_chars = skip_p-p; break; } string map_str = s.substr(p+2, skip_p-p-2); size_t spos = map_str.rfind("=>"); if (spos == string::npos) { skip_chars = skip_p-p; WARN("Error parsing $M regex map replacement: no => found in '%s'\n", map_str.c_str()); break; } string map_val = map_str.substr(0, spos); string map_val_replaced = replaceParameters(map_val, r_type, req, app_param, ruri_parser, from_parser, to_parser); string mapping_name = map_str.substr(spos+2); string map_res; if (SBCFactory::regex_mappings. mapRegex(mapping_name, map_val_replaced.c_str(), map_res)) { DBG("matched regex mapping '%s' (orig '%s) in '%s'\n", map_val_replaced.c_str(), map_val.c_str(), mapping_name.c_str()); res+=map_res; } else { DBG("no match in regex mapping '%s' (orig '%s') in '%s'\n", map_val_replaced.c_str(), map_val.c_str(), mapping_name.c_str()); } skip_chars = skip_p-p; } break; case '_': { // modify if (s.length()<p+4) { // $_O() WARN("Error parsing $_ modifier replacement (short string)\n"); break; } char operation = s[p+1]; if (operation != 'U' && operation != 'l' && operation != 's' && operation != '5') { WARN("Error parsing $_%c string modifier: unknown operator '%c'\n", operation, operation); } if (s[p+2] != '(') { WARN("Error parsing $U upcase replacement (missing '(')\n"); break; } size_t skip_p = p+3; skip_p = skip_to_end_of_brackets(s, skip_p); if (skip_p==s.length()) { WARN("Error parsing $_ modifier (unclosed brackets)\n"); skip_chars = skip_p-p; break; } string br_str = s.substr(p+3, skip_p-p-3); string br_str_replaced = replaceParameters(br_str, "$_*(...)", req, app_param, ruri_parser, from_parser, to_parser); br_str = br_str_replaced; switch(operation) { case 'u': // uppercase transform(br_str_replaced.begin(), br_str_replaced.end(), br_str_replaced.begin(), ::toupper); break; case 'l': // lowercase transform(br_str_replaced.begin(), br_str_replaced.end(), br_str_replaced.begin(), ::tolower); break; case 's': // size (string length) br_str_replaced = int2str((unsigned int)br_str.length()); break; case '5': // md5 br_str_replaced = calculateMD5(br_str); break; default: break; } DBG("applied operator '%c': '%s' => '%s'\n", operation, br_str.c_str(), br_str_replaced.c_str()); res+=br_str_replaced; 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]; } } // end not escaped p++; } if (is_replaced) { DBG("%s pattern replace: '%s' -> '%s'\n", r_type, s.c_str(), res.c_str()); } return res; }
void AnnRecorderFactory::getAppParams(const AmSipRequest& req, map<string, string>& params) { string language; string domain; string user; string typ; if (SimpleMode){ AmUriParser p; p.uri = req.from_uri; if (!p.parse_uri()) { DBG("parsing From-URI '%s' failed\n", p.uri.c_str()); throw AmSession::Exception(500, MOD_NAME ": could not parse From-URI"); } user = p.uri_user; //domain = p.uri_domain; domain = "default"; typ = DEFAULT_TYPE; } else { string iptel_app_param = getHeader(req.hdrs, PARAM_HDR, true); if (!iptel_app_param.length()) { throw AmSession::Exception(500, MOD_NAME ": parameters not found"); } language = get_header_keyvalue(iptel_app_param, "lng", "Language"); user = get_header_keyvalue(iptel_app_param,"uid", "UserID"); if (user.empty()) { user = get_header_keyvalue(iptel_app_param,"usr", "User"); if (!user.length()) user = req.user; } domain = get_header_keyvalue(iptel_app_param, "did", "DomainID"); if (domain.empty()){ domain = get_header_keyvalue(iptel_app_param, "dom", "Domain"); if (domain.empty()) domain = req.domain; } typ = get_header_keyvalue(iptel_app_param, "typ", "Type"); if (!typ.length()) typ = DEFAULT_TYPE; } // checks if (user.empty()) throw AmSession::Exception(500, MOD_NAME ": user missing"); string announce_file = add2path(AnnouncePath,2, domain.c_str(), (user + ".wav").c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,3, domain.c_str(), language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,2, domain.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; if (!language.empty()) { announce_file = add2path(AnnouncePath,2, language.c_str(), DefaultAnnounce.c_str()); if (file_exists(announce_file)) goto announce_found; } announce_file = add2path(AnnouncePath,1, DefaultAnnounce.c_str()); if (!file_exists(announce_file)) announce_file = ""; announce_found: DBG(MOD_NAME " invocation parameters: \n"); DBG(" User: <%s> \n", user.c_str()); DBG(" Domain: <%s> \n", domain.c_str()); DBG(" Language: <%s> \n", language.c_str()); DBG(" Type: <%s> \n", typ.c_str()); DBG(" Def. File:<%s> \n", announce_file.c_str()); params["domain"] = domain; params["user"] = user; params["defaultfile"] = announce_file; params["type"] = typ; }