#include #include #include #include #include //#include "md5.h" #include #include #include #include "parser.h" #include "globals.h" #include "connect.h" using namespace std; class CurledClass { public: static int writer(char *data, size_t size, size_t nmemb, std::string *buffer_in) { // Is there anything in the buffer? if (buffer_in != NULL) { // Append the data to the buffer buffer_in->append(data, size * nmemb); // How much did we write? return size * nmemb; } return 0; } }; CConnect* CConnect::getInstance() { static CConnect* instance = NULL; if(!instance) instance = new CConnect(); return instance; } CConnect::CConnect() { cpars = CParser::getInstance(); //sockfb = 0; query_logic = 0; loginLUA = 0; debug = 1; } CConnect::~CConnect() { // } #if 0 /****************************************************************************** * functions ******************************************************************************/ #endif std::string CConnect::post2fritz(const char* url, const std::string data, const std::string curlOutFile) { CURL *curl; CURLcode result; // multipart post struct curl_httppost *formpost=NULL; struct curl_httppost *lastptr=NULL; struct curl_slist *headerlist=NULL; static const char buf[] = "Expect:"; if(!multipart.empty()) { curl_global_init(CURL_GLOBAL_ALL); // add all map values for (vector::iterator it = multipart.begin(); it != multipart.end(); ++it) { // extract the name value string::size_type begin = (*it).find_first_not_of(" \f\t\v"); string::size_type end = (*it).find('='); string key = (*it).substr(begin, end - begin); // extract the contents value begin = (*it).find_first_not_of(" \f\n\r\t\v", end); end = (*it).find_last_not_of(" \f\n\r\t\v"); string value = (*it).substr(begin + 1, end - begin); //cout << key << "='" << value << "'" << endl; curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, key.c_str(), CURLFORM_COPYCONTENTS, value.c_str(), CURLFORM_END); } } // Create our curl handle curl = curl_easy_init(); if(!multipart.empty()) { // initialize custom header list (stating that Expect: 100-continue is not wanted headerlist = curl_slist_append(headerlist, buf); } //errors char errorBuffer[CURL_ERROR_SIZE]; // Write all expected data in here std::string buffer; if(!curl){ std::cerr << "Error init Curl!" << std::endl; return std::string(); } curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorBuffer); curl_easy_setopt(curl, CURLOPT_URL, url); curl_easy_setopt(curl, CURLOPT_HEADER, 0); curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0"); curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); curl_easy_setopt(curl, CURLOPT_VERBOSE, debug?1:0); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); if(!multipart.empty()) curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); if(!data.empty()) { curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); // print CURLOPT_POSTFIELDS if(debug > 1 && !data.empty()) {cout << '[' << BASENAME << "] - CURLOPT_POSTFIELDS: " << data << endl;} } FILE *tmpFile = fopen(curlOutFile.c_str(), "w"); if (tmpFile) { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL); curl_easy_setopt(curl, CURLOPT_WRITEDATA, tmpFile); } else { curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurledClass::writer); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); } // Attempt to retrieve the remote page result = curl_easy_perform(curl); // Always cleanup curl_easy_cleanup(curl); if (tmpFile) fclose(tmpFile); if(!multipart.empty()) multipart.clear(); if(debug > 1){ if(curlOutFile.empty()) cout << "DEBUG-OUT" << ">>" << buffer << "<<" << "DEBUG-OUT END" << endl; else cout << "DEBUG-OUT" << ">>" << curlOutFile << "<<" << "DEBUG-OUT END" << endl; } if(result == CURLE_OK) return(buffer); return std::string(); } int CConnect::get_challenge(bool lua) { ostringstream url; log(1,"%s(%s)\n", __FUNCTION__, lua?"lua":"xml"); //if(mysockfb <= 0){ // printf("[%s] - CConnect::get_challenge(): ERR connect2Host\n", BASENAME); // return 0; //} if(lua){ url << cpars->getFritzAdr() << "/login_sid.lua"; // OS 5.50 } else { url << cpars->getFritzAdr() << "/cgi-bin/webcm?getpage=../html/login_sid.xml"; // Firmwareversion xx.04.74 } string s = post2fritz(url.str().c_str(), ""); //search string s1 = ""; string s2 = ""; string token; size_t pos = 0; if((pos = s.find(s1)) != string::npos) { s.erase(0, pos + s1.length()); pos = 0; if((pos = s.find(s2)) != string::npos) { s.erase(pos, s.length()); if(!s.empty()) { strncpy(challenge,s.c_str(),sizeof(challenge)); if(debug) {printf("[%s] - CHALLENGE %s \n", BASENAME, challenge);} return 1; } } } if(lua) { log(0,"%s(%s) - NO CHALLENGE found\n", __FUNCTION__, lua?"lua":"xml"); return(get_challenge(false/*xml*/)); } else { log(0,"%s(%s) - failed to get CHALLENGE\n", __FUNCTION__, lua?"lua":"xml"); } return 0; } int CConnect::get_md5(const char *challenge, char *fritzPW) { //convert to utf16 //http://www.avm.de/de/Extern/Technical_Note_Session_ID.pdf unsigned int i; int y = 0; std::string utf8_str = (std::string) challenge + "-" + (std::string) UTF8toISO(fritzPW); std::string utf16_str = (""); log(2,"Challenge-Password = \"%s-%s\"\n",challenge, UTF8toISO(fritzPW)); log(1,"Binary for hash = "); for (i=0; i < utf8_str.length(); i++) { y = i*2; // change UNICODE > 255 in 46 (".") if (utf8_str[i] > 0xAD) { utf16_str += '\x2E'; utf16_str += '\x00'; } else { utf16_str += utf8_str[i]; utf16_str += '\x00'; } if (debug) printf("%02x%02x",utf16_str[y],utf16_str[y+1]); } if (debug) printf("\n"); //get md5sum from utf16 binary hash MD5_CTX ctx; //struct MD5Context ctx; /*md5.h"*/ MD5_Init(&ctx); MD5_Update(&ctx, utf16_str.c_str(), strlen(utf8_str.c_str())*2)/*size*/; MD5_Final(digest, &ctx); strcpy((char *)md5sum,""); for (i = 0; i < 16; i++) { char fdigest[5]; sprintf(fdigest,"%02x", digest[i]); strcat((char *)md5sum, fdigest); } log(2,"MD5 hash = %s (%d)\n",md5sum, strlen((char *)md5sum)); return(strlen((char *)md5sum)); } int CConnect::get_sid(const char *challenge, const unsigned char *md5) { ostringstream url,command; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "login:command/response=" << challenge << '-' << md5 << "&getpage=../html/login_sid.xml"; if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;} string s = post2fritz(url.str().c_str(), command.str()); //search string s1 = ""; string s2 = ""; string token; size_t pos = 0; if((pos = s.find(s1)) != string::npos) { s.erase(0, pos + s1.length()); pos = 0; if((pos = s.find(s2)) != string::npos) { s.erase(pos, s.length()); if(s != "0000000000000000" && !s.empty()) { strncpy(sid,s.c_str(),sizeof(sid)); if(debug) {printf("[%s] - SID %s \n", BASENAME, sid);} return 1; } } } printf("[%s] - failed to get SID\n", BASENAME); return(0); } int CConnect::get_sid_LUA(const char *challenge, const unsigned char *md5) { ostringstream url, command; url << cpars->getFritzAdr() << "/login_sid.lua"; command << "response=" << challenge << '-' << md5; if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;} string s = post2fritz(url.str().c_str(), command.str()); //search string s1 = ""; string s2 = ""; string token; size_t pos = 0; if((pos = s.find(s1)) != string::npos) { s.erase(0, pos + s1.length()); pos = 0; if((pos = s.find(s2)) != string::npos) { s.erase(pos, s.length()); if(s != "0000000000000000" && !s.empty()) { strncpy(sid,s.c_str(),sizeof(sid)); if(debug) {printf("[%s] - SID %s \n", BASENAME, sid);} return 1; } } } /* //split into line string delimiter = "\n"; string token; size_t pos = 0; while ((pos = s.find(delimiter)) != string::npos) { i++; token = s.substr(0, pos); if(debug) {cout << "rec[" << i << "]" << token << endl;} s.erase(0, pos + delimiter.length()); } */ printf("[%s] - failed to get SID\n", BASENAME); return(0); } #if 0 /****************************************************************************** * tools ******************************************************************************/ #endif char *CConnect::trim(char *txt) { register int l; register char *p1, *p2; if (*txt==' ') { for (p1=p2=txt; (*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r'); p1++); while (*p1) *p2++=*p1++; *p2='\0'; } if ((l=strlen(txt))>0) for (p1=txt+l-1; (*p1==' ') || (*p1=='\t') || (*p1=='\n') || (*p1=='\r'); *p1--='\0'); return(txt); } char *CConnect::UTF8toISO(char *txt) { //http://www.lingua-systems.de/knowledge/unicode-mappings/iso-8859-1-to-unicode.html //'ä','ö','ü','Ä','Ö','Ü','ß','é' const unsigned iso[]={'\xe4','\xf6','\xfc','\xc4','\xd6','\xdc','\xdf','\xe9'}, //ISO-8859-1 ö = 0xf6 utf[]={'\xa4','\xb6','\xbc','\x84','\x96','\x9c','\x9f','\xa9'}; //UTF-8 ö = 0xc3 0xb6 int i,found,quota=0; char *rptr=txt,*tptr=txt; while(*rptr != '\0') { if(*rptr=='\'') { quota^=1; } if (!quota && *rptr=='\xc3' && *(rptr+1)) { found=0; for(i=0; i<(int)sizeof(utf) && !found; i++) { if(*(rptr+1)==utf[i]) { found=1; *tptr=iso[i]; ++rptr; } } if(!found) { *tptr=*rptr; } } else if (!quota && *rptr=='\xc2' && *(rptr+1)) { *tptr=*(rptr+1); ++rptr; } else { *tptr=*rptr; } tptr++; rptr++; } *tptr=0; return(txt); } void CConnect::log(const int& dlevel, const char *ftxt,...) { if(debug >= dlevel) { va_list params; va_start(params, ftxt); printf("[%s] - ", BASENAME); vprintf(ftxt, params); fflush(stdout); va_end(params); } } #if 0 /****************************************************************************** * get login to Fritz!Box ******************************************************************************/ #endif int CConnect::get_login(const char* fritzPW) { log(1,"%s()\n", __FUNCTION__); int ret=get_challenge(); if (ret < 0) return 0; if(!ret) { if(!send_old_login(fritzPW)) { log(0,"ERROR send_old_login\n"); return 0; } } else { get_md5(challenge,(char*)fritzPW); if(!get_sid_LUA(challenge,md5sum)) { log(0,"login_sid.lua not found\n"); if(!get_sid(challenge,md5sum)) { log(0,"ERROR get SID\n"); return 0; } } else loginLUA = 1; } query_logic = get_query_logic(sid,0); if(!query_logic) { if(get_OLDquery_logic(sid,1)) { query_logic=2; //old logic } else { log(0,"ERROR get query logic\n"); return 0; } } log(1,"query_logic = %i\n", query_logic); return(query_logic); } #if 0 /****************************************************************************** * send logout to Fritz!Box ******************************************************************************/ #endif int CConnect::send_logout(const char *sid) { ostringstream url, command; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "sid=" << sid << "&security:command/logout=&getpage=../html/confirm_logout.htlm"; if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;} //(w_fritz, "GET /home/home.lua?sid=%s&logout=1 HTTP/1.1\r\nHost: 192.168.99.254\r\n\r\n", sid); post2fritz(url.str().c_str(), command.str().c_str()); return(1); } #if 0 /****************************************************************************** * send old logic password to Fritz!Box ******************************************************************************/ #endif int CConnect::send_old_login(const char *fritzPW) { ostringstream url, command; size_t pos = 0; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "getpage=../html/de/menus/menu2.html&var%3Alang=de&var%3Amenu=home&var%3Apagename=home&login%3Acommand%2Fpassword=" << fritzPW << "&sid=" << sid; if(debug) {cout << '[' << BASENAME << "] - " << __FUNCTION__ << "()" << endl;} string s = post2fritz(url.str().c_str(), command.str().c_str()); if((pos= s.find("class=\"errorMessage\"")) != std::string::npos) { log(0,"failed to get old login\n"); return 0; } return 1; } #if 0 /****************************************************************************** * send query's to Fritz!Box ******************************************************************************/ #endif int CConnect::get_query_logic(const char *sid, int logic) { if(!loginLUA) { return (get_OLDquery_logic(sid, logic)); } size_t pos; std::ostringstream url; log(1,"%s()\n", __FUNCTION__); url << cpars->getFritzAdr() << "/query.lua?sid=" << sid << "&ver=logic:status/nspver"; string s = post2fritz(url.str().c_str(), ""); string res = cpars->parseString("ver", s); if(!res.empty() && (pos = res.find('.')) != string::npos) { log(0,"Firmwareversion (%s)\n", res.c_str()); cpars->setNspver(res); query_logic = 3; return (query_logic); } else { return (get_OLDquery_logic(sid, logic)); } } int CConnect::get_OLDquery_logic(const char *sid, int logic) { ostringstream url, command; std::string output ="/tmp/fim.out"; char *line; ssize_t read; size_t len; FILE* fd; int i = 0; int res = 0; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; if(logic) { command << "getpage=../html/query.txt&var:cnt=1&var:n0=logic:status/nspver" //old << "&sid=" << sid; } else { command << "getpage=../html/query.txt&var:n[0]=logic:status/nspver" //new << "&sid=" << sid; } log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str(),output); line=NULL; if((fd = fopen(output.c_str(), "r"))) { while ((read = getline(&line, &len, fd)) != -1) { i++; if(debug){cout << "rec " << '[' << i << ']' << line;} if(i==1) { if(strlen(trim(line))!=0 && strlen(trim(line))<35) { log(0,"Firmwareversion (%s)\n", (trim(line))); cpars->setNspver(trim(line)); res=1; } } } fclose(fd); } if(line) free(line); return (res); } int CConnect::send_refresh(const char *sid) { if(query_logic == 3) { return(0); } std::ostringstream url, command; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "getpage=../html/query.txt" << (query_logic==2 /*old logic*/ ? "&var:cnt=2" : "") << "&var:n" << (query_logic==1 ? "[" : "") << 0 << (query_logic==1 ? "]" : "") << "=telcfg:settings/RefreshJournal&var:n" << (query_logic==1 ? "]" : "") << 1 << (query_logic==1 ? "]" : "") << "=telcfg:settings/Journal/count" << "&sid=" << sid; log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str()); return 0; } /****************************************************************************** * FritzInfoMonitor ******************************************************************************/ #if 0 void send_query(char *sid, char *searchquery) { /* -- query.lua -- -- Liest Werte von Control-Manager Variablen aus und gibt diese in einer JSON Struktur zur├╝ck. -- -- Jeder GET Parameter wird als = gedeutet. kann dabei relativ frei gew├ñhlt werden. -- ist der Querystring f├╝r eine Control-Manager Variable. -- -- Beispiel: http://fritz.box/query.lua?fw=logic:status/nspver&ld=landevice:settings/landevice/list(name,ip,mac) -- -- Ja, normale Queries k├Ânnen mit Multiqueries gemischt werden. -- -- Multiqueries werden am Vorhandensein von "list(...)" in der Query erkannt. Da alte emu-Module dieses Kommando -- nicht kennen, kann alternativ der Pr├ñfix "mq_" vor den Namen der Query gesetzt werden. Beispiel: -- http://fritz.box/query.lua?mq_log=logger:status/log -- Nur bei einer "mq_" Liste wird der Knotennamen ("landevice0") mit ausgegeben. -- -- Und nicht die Session-ID vergessen! Wenn die Box mit einem Passwort gesichert ist, sieht ein Request in -- Wahrheit so aus: -- http://fritz.box/query.lua?sid=bc0c3998a520f93c&fw=logic:status/nspver -- -- Wenn auf der Box kein Passwort gesetzt ist, kann die Session-ID entfallen. Das Skript sorgt dann selbst f├╝r -- eine g├╝ltige Session-ID. -- */ int i; int y=0; int inx=-1; char *ptr; char line[BUFFERSIZE]; connect2fritz(); if(debug) printf("GET /query.lua?sid=%s&mq_result=%s HTTP/1.1\n", sid, searchquery); fprintf(w_fritz, "GET /query.lua?sid=%s&mq_result=%s HTTP/1.1\r\n\r\n", sid, searchquery); fflush(w_fritz); for (i=1; 1; i+=1) { char *s=fgets(line, sizeof(line), r_fritz); if(debug) printf("Line %d/[%d]%d: %s",i,inx,y,line); if (s==NULL) { break; } else if (strstr(line, "Journal")) { y=0; inx++; } else if(inx >= 0) { /* Line 1/[-1]0: HTTP/1.0 200 OK Line 2/[-1]1: Content-type: application/json Line 3/[-1]2: Expires: -1 Line 4/[-1]3: Line 5/[-1]4: { Line 6/[-1]5: "mq_result" : [ Line 7/[-1]6: { Line 8/[-1]7: "_node" : "Journal0", Line 9/[0]1: "0" : "3", Line 10/[0]2: "5" : "07.09.11 20:48", Line 11/[0]3: "Type" : "caller number", Line 12/[0]4: "Date" : "4", Line 13/[0]5: "Number" : "0:03", Line 14/[0]6: "Port" : "my number", Line 15/[0]7: "Duration" : "0", Line 16/[0]8: "Route" : "Name", Line 17/[0]9: "RouteType" : "my home", Line 18/[0]10: "Name" : "" Line 19/[0]11: }, Line 20/[0]12: { Line 21/[0]13: "_node" : "Journal1", */ switch (y) { case 1: sscanf(line + 8, "%[^\"]", (char *) &caller[inx].call_type); case 2: sscanf(line + 8, "%[^\"]", (char *) &caller[inx].call_date); case 3: sscanf(line +11, "%[^\"]", (char *) &caller[inx].call_numr); if(strlen(caller[inx].call_numr) == 0) { // strcpy(caller[inx].call_numr, "keine Rufnummer"); } case 8: sscanf(line +12, "%[^\"]", (char *) &caller[inx].call_name); if(strlen(caller[inx].call_name) == 0) { // strcpy(caller[inx].call_name, "unbekannt"); } } } y++; } if(debug) { for (i=0; i < MAXCALLER; i++) printf("inx[%i] %s %s %s %s\n",i,caller[i].call_type, caller[i].call_date, caller[i].call_numr, caller[i].call_name); } // When finished send all lingering transmissions and close the connection quitfritz(); } #endif int CConnect::send_query_info(const char *sid) { if(query_logic == 3) { return(get_QueryInfos(sid)); } char *line; ssize_t read; size_t len; string output ="/tmp/fim.out"; FILE* fd; int i = 0; ostringstream url, command; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; if(query_logic==2) { command << "getpage=../html/query.txt" << "&var:cnt=6" << "&var:n0=ddns:settings/account0/state" << "&var:n1=ddns:settings/account0/domain" << "&var:n2=tam:settings/TAM0/Active" << "&var:n3=tam:settings/TAM0/NumNewMessages" << "&var:n4=sip:settings/sip0/displayname" << "&var:n5=sip:settings/sip1/displayname" << "&var:n6=connection0:pppoe:status/ip" << "&sid=" << sid; } else { command << "getpage=../html/query.txt" << "&var:n[0]=ddns:settings/account0/state" << "&var:n[1]=ddns:settings/account0/domain" << "&var:n[2]=tam:settings/TAM0/Active" << "&var:n[3]=tam:settings/TAM0/NumNewMessages" << "&var:n[4]=sip:settings/sip0/displayname" << "&var:n[5]=sip:settings/sip1/displayname" << "&var:n[6]=connection0:pppoe:status/ip" << "&sid=" << sid; } log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str(),output); line=NULL; if((fd = fopen(output.c_str(), "r"))) { while ((read = getline(&line, &len, fd)) != -1) { i++; if(debug>1){cout << "rec " << '[' << i << ']' << line;} switch(i) { case 1: cpars->setDdns_state(trim(line));break; case 2: cpars->setDdns_domain(trim(line)); break; case 3: cpars->setTam0_active(trim(line));break; case 4: cpars->setTam0_NumNewMessages(trim(line));break; case 5: cpars->setSip0Nr(trim(line));break; case 6: cpars->setSip1Nr(trim(line));break; case 7: cpars->setPppoe_ip(trim(line));break; } } fclose(fd); log(1,"ddns_state=%i ddns_domain=%s tam0_active=%i tam0_NumNewMessages=%i sip0nr=%s sip1nr=%s pppoe_ip=%s\n", atoi(cpars->getDdns_state().c_str()), cpars->getDdns_domain().c_str(), atoi(cpars->getTam0_active().c_str()), atoi(cpars->getTam0_NumNewMessages().c_str()), cpars->getSip0Nr().c_str(),cpars->getSip1Nr().c_str(), cpars->getPppoe_ip().c_str()); } if(line) free(line); return 0; } int CConnect::get_QueryInfos(const char *sid) { ostringstream url,command; int i = 0; url << cpars->getFritzAdr() << "/query.lua?sid=" << sid << "&var0=ddns:settings/account0/state" << "&var1=ddns:settings/account0/domain" << "&var2=tam:settings/TAM0/Active" << "&var3=tam:settings/TAM0/NumNewMessages" << "&var4=sip:settings/sip0/displayname" << "&var5=sip:settings/sip1/displayname" << "&var6=connection0:pppoe:status/ip"; log(1,"%s()\n", __FUNCTION__); string s = post2fritz(url.str().c_str(), ""); StringReplace(s," ",""); for (i=0; i <= 6; i++) { stringstream ss; ss << "var" << i; string res = cpars->parseString(ss.str().c_str(), s); switch(i) { case 0: cpars->setDdns_state(res);break; case 1: cpars->setDdns_domain(res); break; case 2: cpars->setTam0_active(res);break; case 3: cpars->setTam0_NumNewMessages(res);break; case 4: cpars->setSip0Nr(res);break; case 5: cpars->setSip1Nr(res);break; case 6: cpars->setPppoe_ip(res);break; } } return 0; } int CConnect::send_query_caller(const char *sid, int s, int max) { if(loginLUA) { return (get_caller_LUA(sid, s, max)); } std::ostringstream url, command; int i=0; char *line; ssize_t read; size_t len; int inx=0; int inxx=0; int items=9; char c1[2] = "["; char c2[2] = "]"; string output ="/tmp/fim.out"; FILE* fd; log(1,"%s()\n", __FUNCTION__); cpars->init_caller(); url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "getpage=../html/query.txt"; if(query_logic==2) //old logic { strcpy(c1,""); strcpy(c2,""); items=7; command << "&var:cnt=" << items * max; } inx=0; log(0,"hole Eintrag %d bis %d\n",s+1,s+max); for (i=s; i <= s+max; i++) { command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Type"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Date"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Number"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Port"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Duration"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Route"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/Name"; inx++; if(query_logic==1) { command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/RouteType"; inx++; command << "&var:n" << c1 << inx << c2 << "=telcfg:settings/Journal" << i << "/PortName"; inx++; } } command << "&sid=" << sid; post2fritz(url.str().c_str(), command.str().c_str(), output); i=0; inx=0; inxx=0; line=NULL; if((fd = fopen(output.c_str(), "r"))) { while ((read = getline(&line, &len, fd)) != -1) { i++; inx++; if(debug>1){cout << "rec" << '[' << inxx << ']' << '[' << inx << ']' << '[' << i << ']' << line;} /* 1="Type"; 2="Date"; 3="Number"; 4="Port"; 5="Duration"; 6="Route"; 7="Name"; 8="RouteType"; 9="PortName" */ switch(inx) { case 1: strcpy(cpars->caller[inxx].call_type, trim(line)); break; case 2: strcpy(cpars->caller[inxx].call_date, trim(line)); break; case 3: strcpy(cpars->caller[inxx].call_numr, trim(line)); break; case 5: strcpy(cpars->caller[inxx].call_time, trim(line));break; case 6: strcpy(cpars->caller[inxx].port_rout, trim(line));break; case 7: strcpy(cpars->caller[inxx].call_name, UTF8toISO(trim(line))); if(query_logic != 1) { inx=0; inxx++; } break; case 9: strcpy(cpars->caller[inx].port_name, UTF8toISO(trim(line))); inx=0; inxx++; break; } if (inxx==max) { break; } } fclose(fd); } if(debug) { for (i=0; i < max; i++) log(1,"inxx[%i] %s(%i) %s(%i) %s(%i) %s(%i) %s(%i) %s(%i) %s(%i)\n",i, cpars->caller[i].call_type, strlen(cpars->caller[i].call_type), cpars->caller[i].call_date, strlen(cpars->caller[i].call_date), cpars->caller[i].call_numr, strlen(cpars->caller[i].call_numr), cpars->caller[i].call_name, strlen(cpars->caller[i].call_name), cpars->caller[i].port_rout, strlen(cpars->caller[i].port_rout), cpars->caller[i].port_name, strlen(cpars->caller[i].port_name), cpars->caller[i].call_time, strlen(cpars->caller[i].call_time)); } if(line) free(line); return(0); } int CConnect::get_caller_LUA(const char *sid, int s, int max) { ostringstream url,command; string output = "/tmp/fim.out"; int i = 0; int inx = 0; int skip = 1; url << cpars->getFritzAdr() << "/fon_num/foncalls_list.lua?csv="; command << "refresh=&sid=" << sid; log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str(), cpars->getListfile()); cpars->init_caller(); ifstream fh(cpars->getListfile()); if ( fh.is_open() ) { string line; while (getline(fh,line)) { string Typ; string Datum; string Name; string Rufnummer; string Nebenstelle; string Eigene_Rufnummer; string Dauer; istringstream in(line); // select data if(inx <= skip+s) { inx++; continue; } else if(inx > skip+s+max) { break; } if( getline(in, Typ, ';') && getline(in, Datum, ';') && getline(in, Name, ';') && getline(in, Rufnummer, ';') && getline(in, Nebenstelle, ';') && getline(in, Eigene_Rufnummer, ';') && getline(in, Dauer, ';') ) { size_t found; if((found = Eigene_Rufnummer.find("Internet")) != std::string::npos) Eigene_Rufnummer.replace(found,8,"@"); //this is ugly, better use vector!!! strcpy(cpars->caller[i].call_type, Typ.c_str()); strcpy(cpars->caller[i].call_date, Datum.c_str()); strcpy(cpars->caller[i].call_numr, Rufnummer.c_str()); strcpy(cpars->caller[i].call_time, Dauer.c_str()); strcpy(cpars->caller[i].port_rout, Eigene_Rufnummer.c_str()); strcpy(cpars->caller[i].call_name, UTF8toISO((char*)Name.c_str())); strcpy(cpars->caller[i].port_name, UTF8toISO((char*)Nebenstelle.c_str())); if(debug>1) { cout << " rec[" << inx << "]" << line << endl; cout << "array[" << i << "]" << Typ << ";" << Datum << ";" << Name << ";" << Rufnummer << ";" << Nebenstelle << ";" << Eigene_Rufnummer << ";" << Dauer << endl; } i++; } else { cerr << '[' << BASENAME << "] - " << __FILE__ << " could not parse line [" << inx << "]" << line << endl; } inx++; } fh.close(); } else { cerr << '[' << BASENAME << "] - " << __FILE__ << "error open file" << endl; } return(0); } int CConnect::get_phonebooks(const char *sid, int phonebook) { char *line; ssize_t read; size_t len; ostringstream url, command; string output ="/tmp/fim.out"; FILE* fd; int i = 0; log(1,"%s()\n", __FUNCTION__); if(loginLUA) { return(get_phonebooks_LUA(sid, phonebook)); } cpars->init_address(); url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "telcfg:settings/Phonebook/Books/Select=" << phonebook-1 << "&getpage=../html/de/menus/menu2.html" << "&var:lang=de" << "&var:pagename=fonbuch" << "&var:menu=fon" << "&sid=" << sid; post2fritz(url.str().c_str(), command.str().c_str(), output); line=NULL; if((fd = fopen(output.c_str(), "r"))) { while ((read = getline(&line, &len, fd)) != -1) { char *ptr; char buffer[50]; i++; if(debug>1){cout << "rec " << '[' << i << ']' << line;} if ((ptr = strstr(line, ">TrFonName("))) { sscanf(ptr + 11, "\"%*[^\"]\", \"%[^\"]", (char *) &cpars->address.name); } else if ((ptr = strstr(line, ">TrFonNr("))) { sscanf(ptr + 9, "\"%49[^\"]\", \"%[^\"]", (char *) &buffer,(char *) &cpars->address.number); if(!strstr(buffer,"intern")) //no "intern" type { if(cpars->address.number[0] != '0' && strlen(cpars->getCityprefix()) > 0) { sprintf(buffer,"%s%s",cpars->getCityprefix(),cpars->address.number); strcpy(cpars->address.number,buffer); } if (cpars->search_AddrBook(cpars->address.number)) { log(1,"[existing]\t%s %s\n",cpars->address.number,cpars->address.name); } else { cpars->add_AddrBook(cpars->address.number); log(1,"[add]\t\t%s %s\n",cpars->address.number,cpars->address.name); } } } else if (strstr(line, "document.write(TrFon1())")) { cpars->init_address(); } } fclose(fd); } if(line) free(line); return(0); } int CConnect::get_phonebooks_LUA(const char *sid, int phonebook) { std::ostringstream url,command, vsid, bookID; string output ="/tmp/fim.out"; ifstream fh; string str, line; size_t pos; size_t begin = 0; log(1,"%s()\n", __FUNCTION__); // create multipart vector vsid << "sid=" << sid; bookID << "PhonebookId=" << phonebook; multipart.push_back(vsid.str()); multipart.push_back(bookID.str()); multipart.push_back("PhonebookExportName=Telefonbuch"); multipart.push_back("PhonebookExport="); //get phonebook url.str(""); url << cpars->getFritzAdr() << "/cgi-bin/firmwarecfg"; post2fritz(url.str().c_str(), "", output); // parse output fh.open(output.c_str(), std::ios::in); if(fh.is_open()) { while (!fh.eof()) { getline(fh, str); // get the whole Data in one line line += str; } fh.close(); // loop search bool stop = false; do { str = ""; if((pos=line.find(str, begin)) != string::npos) { size_t name_ende = line.find("", pos); string tmp = line.substr(pos+str.length(), name_ende - (pos+str.length())); strcpy(cpars->address.name, tmp.c_str()); cout << " name - " << cpars->address.name << endl; } str = "", number_start); tmp = line.substr(number_start+str.length(), number_ende - (number_start+str.length())); strcpy(cpars->address.number, tmp.c_str()); cout << " number - " << cpars->address.number << endl; } if(pos == string::npos) stop = true; else { //add to AddrBook if(strlen(cpars->address.number) != 0) { if(cpars->address.number[0] != '0' && strlen(cpars->getCityprefix()) > 0) { char buffer[50]; sprintf(buffer,"%s%s",cpars->getCityprefix(),cpars->address.number); strcpy(cpars->address.number,buffer); } if(cpars->search_AddrBook(cpars->address.number)) { cout << '[' << BASENAME << "] - [existing]\t"; } else { cpars->add_AddrBook(cpars->address.number); cout << '[' << BASENAME << "] - [add]\t"; } cout << cpars->address.number << ' ' << cpars->address.name << endl; } } begin = pos +1; } while (!stop); } /* line=NULL; if((fd = fopen(output.c_str(), "r"))) { while ((read = getline(&line, &len, fd)) != -1) { char *ptr; cpars->init_address(); i++; if(debug>1){cout << "rec " << '[' << i << ']' << line;} if((ptr = strstr(line, ""))) { sscanf(ptr + 18, "%[^<]", (char *) &cpars->address.name); cout << cpars->address.name << endl; } if((ptr = strstr(line, ""))) { sscanf(ptr + 36, "%[^<]", (char *) &cpars->address.number); cout << cpars->address.number << endl; //add to AddrBook if(strlen(cpars->address.number) != 0) { if(cpars->address.number[0] != '0' && strlen(cpars->getCityprefix()) > 0) { char buffer[50]; sprintf(buffer,"%s%s",cpars->getCityprefix(),cpars->address.number); strcpy(cpars->address.number,buffer); } if(cpars->search_AddrBook(cpars->address.number)) { cout << '[' << BASENAME << "] - [existing]\t"; } else { cpars->add_AddrBook(cpars->address.number); cout << '[' << BASENAME << "] - [add]\t"; } cout << cpars->address.number << ' ' << cpars->address.name << endl; } } } fclose(fd); } if(line) free(line); */ return(0); } int CConnect::dial(const char *sid, int port, const char *number) { std::ostringstream url,command; if(query_logic == 3) { url << cpars->getFritzAdr() << "/fon_num/fonbook_list.lua?" << "dial=" << number << "&orig_port=" << port << "&sid=" << sid; } else { url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "getpage=../html/de/menus/menu2.html" << "&telcfg:settings/UseClickToDial=1" << "&telcfg:settings/DialPort=" << port << "&telcfg:command/Dial=" << number << "&sid=" << sid; } log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str()); return(0); } int CConnect::hangup(const char *sid, int port) { std::ostringstream url,command; url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "getpage=../html/de/menus/menu2.html" << "&telcfg:settings/UseClickToDial=1" << "&telcfg:settings/DialPort=" << port << "&telcfg:command/Hangup=" << "&sid=" << sid; log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str()); return(0); } int CConnect::reconnect(const char *sid) { std::ostringstream url,command; if(query_logic == 3) { url << cpars->getFritzAdr() << "/internet/inetstat_monitor.lua?sid=" << sid << "&useajax=1&action=disconnect&xhr=1"; } else { url << cpars->getFritzAdr() << "/cgi-bin/webcm"; command << "sid=" << sid << "&connection0%3Asettings%2Fcmd_disconnect="; } log(1,"%s()\n", __FUNCTION__); post2fritz(url.str().c_str(), command.str().c_str()); return(0); } /****************************************************************************** * reverse search ******************************************************************************/ int CConnect::rsearch(const char *searchNO) { char *found; char *line; ssize_t read; size_t len; ostringstream url; string sstr; string output ="/tmp/fim.out"; FILE* fd; log(1,"%s()\n", __FUNCTION__); cpars->init_address(); if(searchNO[0] != '0') sstr = (std::string) (strlen(cpars->getCityprefix())>0 ? cpars->getCityprefix() : "") + (std::string) searchNO; else sstr = searchNO; url << cpars->getSearchAdr() << "/suche/" << sstr << "/-"; post2fritz(url.str().c_str(),"", output); line=NULL; if((fd = fopen(output.c_str(), "r"))) { while ((read = getline(&line, &len, fd)) != -1) { if ((found = strstr(line, "target=\"_self\" title=\"Zur Detailseite von "))) { sscanf(found + 47, "%255[^\"]", (char *) &cpars->address.name); } else if ((found = strstr(line, "\"postalCode\" content=\""))) { sscanf(found + 22, "%5[^\"]", (char *) &cpars->address.code); } else if((found = strstr(line, "\"addressLocality\" content=\""))) { sscanf(found + 27, "%127[^\"]", (char *) &cpars->address.locality); } else if((found = strstr(line, "\"streetAddress\" content=\""))) { sscanf(found + 25, "%127[^\"]", (char *) &cpars->address.street); } } fclose(fd); } if(line) free(line); if(strlen(cpars->address.name)!=0) { log(1,"(%s) = %s, %s, %s %s\n",sstr.c_str(), cpars->address.name, cpars->address.street, cpars->address.code, cpars->address.locality); return(1); } else { log(0,"no results for %s\n", sstr.c_str()); } return(0); } void CConnect::StringReplace(string &str, const string search, const string rstr) { stringstream f(search); // stringstream f("string1;string2;stringX"); string s; while (getline(f, s, ';')) { string::size_type ptr = 0; string::size_type pos = 0; while((ptr = str.find(s,pos)) != string::npos) { str.replace(ptr,s.length(),rstr); pos = ptr + rstr.length(); } } }