/**************************************************************************** ** $Id: torclient.cpp,v 1.138 2009/10/13 20:19:51 hoganrobert Exp $ * Copyright (C) 2006 - 2008 Robert Hogan * * robert@roberthogan.net * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include #include #include #include "torclient.h" #include "tork.h" #include "torkconfig.h" #include "dndlistview.h" #include "functions.h" #include #include #include #include #include #include #include #include #include #include #include #include "crypto.h" #ifndef EXTERNAL_GEOIP # include "GeoIP-1.4.0/libGeoIP/GeoIP.h" #else # include #endif /* Linux-specific includes */ #include #include using namespace tk; TorClient::TorClient( const TQString &host, TQ_UINT16 port ) { // create the socket and connect various of its signals socket = new TQSocket( this ); connect( socket, SIGNAL(connected()), SLOT(socketConnected()) ); connect( socket, SIGNAL(connectionClosed()), SLOT(socketConnectionClosed()) ); connect( socket, SIGNAL(readyRead()), SLOT(socketReadyRead()) ); connect( socket, SIGNAL(error(int)), SLOT(socketError(int)) ); // connect to the server //infoText->append( tr("Trying to connect to the server\n") ); socket->connectToHost( host, port ); m_expectingCircuitInfo= false; m_expectingStreamInfo= false; m_expectingOrconnInfo= false; m_expectingGuardsInfo= false; m_expectingDirStatus= false; m_expectingServerInfo= false; m_controllerWorking= false; m_firstloadcomplete = false; m_resolvingServerAddress = false; clearServers(); serverReport.append("Status Not Known"); clientReport.append("Status Not Known"); serverStatus["DANGEROUS_VERSION"] = "Server Requires Upgrade"; serverStatus["TOO_MANY_CONNECTIONS"] = "Recently Exceeded Local Connection Limit. Check Local System"; serverStatus["CLOCK_SKEW"] = "Your Local Clock Is Skewed. Check Local System."; serverStatus["BAD_LIBEVENT"] = "Libevent Installation Requires Upgrade"; serverStatus["DIR_ALL_UNREACHABLE"] = "Tor Network Unreachable."; // serverStatus["NAMESERVER_ALL_DOWN"] = "Your DNS Servers are down."; serverStatus["DNS_HIJACKED"] = "Your Provider is Hijacking DNS Requests."; serverStatus["DNS_USELESS"] = "Your Provider is Hijacking DNS Requests."; serverStatus["EXTERNAL_ADDRESS"] = "Using Address ADDRESS"; serverStatus["REACHABILITY_SUCCEEDED"] = "Reachable By Tor Network"; serverStatus["REACHABILITY_FAILED"] = "Reachability Tests Failed. Trying again.."; serverStatus["BAD_SERVER_DESCRIPTOR"] = "Server Not Accepted By Tor Network Yet."; serverStatus["GOOD_SERVER_DESCRIPTOR"] = "Accepted By Tor Network"; serverStatusIcon["REACHABILITY_SUCCEEDED"] = "tork_green"; serverStatusIcon["REACHABILITY_FAILED"] = "tork_orange"; serverStatusIcon["BAD_SERVER_DESCRIPTOR"] = "tork_little"; serverStatusIcon["GOOD_SERVER_DESCRIPTOR"] = "tork_green"; serverStatusIcon["DIR_ALL_UNREACHABLE"] = "tork_red"; clientStatus["NOT_ENOUGH_DIR_INFO"] = "Not Enough Info To Try Network Yet"; clientStatus["ENOUGH_DIR_INFO"] = "Enough Info To Try Network"; clientStatus["CIRCUIT_ESTABLISHED"] = "Connected to Network."; clientStatus["CIRCUIT_NOT_ESTABLISHED"] = "Still Trying Network"; clientStatusIcon[clientStatus["NOT_ENOUGH_DIR_INFO"]] = "tork_red"; clientStatusIcon[clientStatus["ENOUGH_DIR_INFO"]] = "tork_little"; clientStatusIcon[clientStatus["CIRCUIT_ESTABLISHED"]] = "tork_green"; clientStatusIcon[clientStatus["CIRCUIT_NOT_ESTABLISHED"]] = "tork_orange"; portMessage["23"] = " Port 23 is used by telnet, which transmits usernames " "and passwords unencrypted."; portMessage["110"] = " Port 110 is used to download email, so your login " "details can be transmitted unencrypted."; portMessage["109"] = " Port 109 is used to download email, so your login " "details can be transmitted unencrypted."; portMessage["143"] = " Port 143 is used to download email, so your login " "details can be transmitted unencrypted."; statusMessage["DANGEROUS_PORT"] = "QUESTIONMESSAGETraffic on Port PORT " "has been rejected by Tor."; statusMessage["DANGEROUS_VERSION"] = "QUESTIONMESSAGEYou are using Tor CURRENT." " This version is REASON. " "You should use Tor RECOMMENDED instead"; statusMessage["TOO_MANY_CONNECTIONS"] = "MESSAGETor has reached its native" " limit on file descriptors: CURRENT. "; statusMessage["BUG"] = "WARNINGMESSAGETor encountered an unexpected error: REASON. "; statusMessage["CLOCK_SKEW"] = "WARNINGMESSAGEYour local clock is skewed by SKEW seconds. "; statusMessage["BAD_LIBEVENT"] = "WARNINGMESSAGEYour version of libevent, VERSION, is BADNESS. "; statusMessage["DIR_ALL_UNREACHABLE"] = "WARNINGMESSAGEAll known directory servers are unreachable. "; statusMessage["ENOUGH_DIR_INFO"] = "WARNINGMESSAGETor has gathered enough info to start working. "; statusMessage["NOT_ENOUGH_DIR_INFO"] = "WARNINGMESSAGETor does not have enough info to work. "; statusMessage["CIRCUIT_ESTABLISHED"] = "WARNINGMESSAGETor has gathered enough info to start working. "; statusMessage["CIRCUIT_NOT_ESTABLISHED"] = "WARNINGMESSAGETor does not have enough info to work. "; statusMessage["SOCKS_BAD_HOSTNAME"] = "WARNINGMESSAGESome application gave us" " a funny-looking hostname." "Perhaps it is broken?"; statusMessage["NAMESERVER_ALL_DOWN"] = "WARNINGMESSAGEAll your configured nameservers appear to be down."; statusMessage["DNS_HIJACKED"] = "WARNINGMESSAGEYour DNS requests are being hijacked by your provider."; statusMessage["DNS_USELESS"] = "WARNINGMESSAGEYour DNS requests are being hijacked by your provider."; statusMessage["BAD_SERVER_DESCRIPTOR"] = "WARNINGMESSAGEYour descriptor was rejected by DIRAUTH " "because of REASON."; m_statustip = i18n("Name: $SERVERNAME
" "IP: $IP ($HOSTNAME) Port: $PORT
" "Country: $COUNTRY
" "Version: $VERSION OS: $OS
" "Published: $PUBLISHED Up Time: $UPTIME minutes
" "
Avg BW up to $INTERVALTIME
" "      " "      " "      24 hrs" "   " // 1 space "   " // 1 space "   " // 1 space "   " // 1 space "   12 hrs" "   " // 1 space "   " // 1 space "   " // 1 space "   " // 1 space "   6 hrs" "   " // 1 space "   " // 1 space "   " // 1 space "   " // 1 space "   " // 1 space "   1 hr
" "Up" "    " // 1 space "    " // 1 space "    " // 1 space "$BWUP
" "Down" "   " // 1 space "   " // 1 space "$BWDN
" ); } void TorClient::configureServer( int orPort, int dirPort) { sendToServer(TQString("SETCONF ContactInfo=%1").arg(TorkConfig::contactInfo())) ; sendToServer(TQString("SETCONF ClientOnly=%1").arg(TorkConfig::clientOnly())) ; if (TorkConfig::middleMan()) ( sendToServer(TQString("SETCONF ExitPolicy=%1").arg(("\"reject *:*\"")))) ; else ( sendToServer(TQString("SETCONF ExitPolicy=\"%2\"").arg( TorkConfig::exitPolicy().join(",")))); sendToServer(TQString("SETCONF NickName=%1").arg(TorkConfig::nickName())) ; if (!TorkConfig::clientOnly()){ //We send the orport configs together to avoid error messages from Tor //telling us that one cannot be set without the other. sendToServer(TQString("SETCONF ORPort=%1 " "ORListenAddress=0.0.0.0:%2") .arg(orPort) .arg(TorkConfig::oRListenAddress())) ; //We send the dirport configs together to avoid error messages from Tor //telling us that one cannot be set without the other. sendToServer(TQString("SETCONF DIRPort=%1 " "DIRListenAddress=0.0.0.0:%2") .arg(dirPort) .arg(TorkConfig::dirListenAddress())) ; sendToServer(TQString("SETCONF BridgeRelay=%1").arg(TorkConfig::bridgeRelay())) ; setBandwidth(TQString("%1").arg(TorkConfig::bandwidthRate()), TQString("%1").arg(TorkConfig::bandwidthBurst()), TQString("%1").arg(TorkConfig::maxAdvertisedBandwidth())); }else{ sendToServer(TQString("SETCONF ORPort= ORListenAddress=")) ; sendToServer(TQString("SETCONF DirPort= DirListenAddress=")) ; sendToServer(TQString("SETCONF BridgeRelay=")) ; } if (TorkConfig::clientOnly()) resetClientReport(); TorkConfig::writeConfig(); } void TorClient::clearNodes( ) { sendToServer("SETCONF ExcludeNodes="); sendToServer("SETCONF ExitNodes="); sendToServer("SETCONF EntryNodes="); TorkConfig::setCurrentExcludeNodes(""); TorkConfig::setCurrentEntryNodes(""); TorkConfig::setCurrentExitNodes(""); emit copyOldConfig(); } void TorClient::updateExcludeNodes( ) { ////kdDebug() << "SETCONF ExcludeNodes=" + TorkConfig::currentExcludeNodes().join(",") << endl; sendToServer("SETCONF ExcludeNodes=" + TorkConfig::currentExcludeNodes().join(",")); sendToServer("GETCONF ExcludeNodes"); sendToServer("signal newnym"); } void TorClient::updateExitNodes( ) { ////kdDebug() << "SETCONF ExitNodes=" + TorkConfig::currentExitNodes().join(",") << endl; sendToServer("SETCONF ExitNodes=" + TorkConfig::currentExitNodes().join(",")); sendToServer("GETCONF ExitNodes"); sendToServer("signal newnym"); } void TorClient::strictExitNodes( bool strict ) { if (strict) sendToServer("SETCONF StrictExitNodes=1"); else sendToServer("SETCONF StrictExitNodes=0"); } void TorClient::safeLogging( bool safe ) { if (safe) sendToServer("SETCONF SafeLogging=1"); else sendToServer("SETCONF SafeLogging=0"); } void TorClient::updateEntryNodes( ) { ////kdDebug() << "SETCONF EntryNodes=" + TorkConfig::currentEntryNodes().join(",") << endl; sendToServer("SETCONF EntryNodes=" + TorkConfig::currentEntryNodes().join(",")); sendToServer("GETCONF EntryNodes"); sendToServer("signal newnym"); } void TorClient::enableDNS( bool set ) { if (set) sendToServer("SETCONF DNSPort=9999"); else sendToServer("SETCONF DNSPort="); } void TorClient::enableTransPort( bool set ) { if (set) sendToServer("SETCONF TransPort=9040"); else sendToServer("SETCONF TransPort="); } void TorClient::fetchServerInfo( const TQString & server) { TQString fp = getFPFromFPDigest(server); fp.replace("$",""); kdDebug() << fp << endl; // emit showServerBW(fp); sendToServer("GETINFO dir/server/fp/" + fp); } void TorClient::fetchServerInfoByNick( const TQString & server) { TQString fp = getFPFromNickName(server); fp.replace("$",""); sendToServer("GETINFO dir/server/fp/" + fp); } void TorClient::slotCheckTorNet() { sendToServer("GETINFO ns/all"); } void TorClient::slotCheckGuards() { sendToServer("GETINFO entry-guards"); } void TorClient::terminateTor() { sendToServer("SIGNAL SHUTDOWN"); } void TorClient::createService(const TQString &dir, const TQString &port) { sendToServer(TQString("setconf hiddenservicedir=\"%1\" hiddenserviceport=\"%2\"").arg(dir).arg(port)); } void TorClient::authenticate() { // if (TorkConfig::defaultRunningNormalOptions()){ // sendToServer("AUTHENTICATE"); // return; // } if (TorkConfig::cookieAuthentication()){ if (!readCookie()){ emit processQuestion("cookienotfound", TQString("Couldn't find authentication" " cookie in %1/.tor!").arg(getenv("HOME"))); emit fatalError(); } }else if (!TorkConfig::hashedControlPassword().isEmpty()) sendToServer(TQString("AUTHENTICATE \"%1\"").arg(TorkConfig::hashedControlPassword())); else{ sendToServer("AUTHENTICATE"); /* Lock the control port */ if (TorkConfig::generateRandomPassword()){ crypto_seed_rng(); sendToServer(TQString("setconf HashedControlPassword=16:%2") .arg(hashPassword(crypto_rand_string(16)))); } } } bool TorClient::readCookie() { TQString hex; char hx[2]; TQStringList cookieCandidates; cookieCandidates << TQString("%1/.tor/control_auth_cookie").arg(getenv("HOME")); cookieCandidates << TQString("/var/lib/tor/control_auth_cookie"); for ( TQStringList::Iterator it = cookieCandidates.begin(); it != cookieCandidates.end(); ++it ) { TQFile inf((*it)); if ( inf.open(IO_ReadOnly) ) { TQByteArray array = inf.readAll(); inf.close(); if (array.size() != 32) continue; for ( unsigned int i = 0; i < array.size(); i++ ) { sprintf(hx,"%02x",array[i]); hex += TQString(hx).right(2); } sendToServer(TQString("AUTHENTICATE %1").arg(hex)); return true; } } return false; } void TorClient::readRouters() { TQFile inf(TQString("%1/.tor/cached-status/7EA6EAD6FD83083C538F44038BBFA077587DD755").arg(getenv("HOME"))); if ( inf.open(IO_ReadOnly) ) { TQTextStream stream( &inf ); TQString line; while ( !stream.atEnd() ) { line = stream.readLine(); // line of text excluding '\n' parseDirStatus(line); } inf.close(); } } void TorClient::newIdentity() { kdDebug() << "changing id" << endl; sendToServer("signal newnym"); } void TorClient::bandwidth() { sendToServer("usefeature verbose_names"); sendToServer("usefeature extended_events"); sendToServer("GETINFO ns/all"); sendToServer("GETINFO circuit-status"); sendToServer("GETINFO stream-status"); sendToServer("GETINFO orconn-status"); sendToServer("GETINFO version"); sendToServer("GETINFO status/enough-dir-info"); sendToServer("GETINFO status/good-server-descriptor"); sendToServer("GETINFO status/reachability-succeeded/or"); //Always enable for each session, user can disable through yes/no //interface when warned - but only for that session. m_portsToReject.clear(); m_portsToReject << "23" << "109" << "110" << "143"; sendToServer(TQString("SETCONF WarnPlainTextPorts=%1") .arg(m_portsToReject.join(","))); sendToServer(TQString("SETCONF RejectPlainTextPorts=%1") .arg(m_portsToReject.join(","))); sendToServer("SETEVENTS EXTENDED CIRC STREAM ORCONN NOTICE " "WARN ERR ADDRMAP BW STREAM_BW NS STATUS_GENERAL " "STATUS_CLIENT STATUS_SERVER GUARD"); sendToServer(TQString("SETCONF __ReloadTorrcOnSIGHUP=0")); } void TorClient::handle250(const TQString &lin) { TQString line = lin; if ((line.contains("250-circuit-status="))){ if (line != ".") parseEvent("CIRC",line.replace("250-circuit-status=","")); else m_expectingCircuitInfo = false; }else if ((line.contains("250-orconn-status="))){ if (line != ".") parseEvent("ORCONN",line.replace("250-orconn-status=","")); else m_expectingOrconnInfo = false; }else if ((line.contains("250-stream-status="))){ if (line != ".") parseEvent("STREAM",line.replace("250-stream-status=","")); else m_expectingStreamInfo = false; }else if (line.contains("250+circuit-status=")) m_expectingCircuitInfo= true; else if (line.contains("250+orconn-status=")) m_expectingOrconnInfo= true; else if (line.contains("250+stream-status=")) m_expectingStreamInfo= true; else if (line.contains("250+entry-guards=")) m_expectingGuardsInfo= true; else if (line.contains("250+dir/server/fp/")) m_expectingServerInfo= true; else if (line.contains("250+extra-info/digest/")) m_expectingServerInfo= true; else if (line.contains("250+ns/all=")){ m_expectingDirStatus= true; emit whatImDoing("Inspecting the Tor network.."); }else if (line.contains("250-ns/all=")){ emit warnNoServerInfo(); emit shouldIApplySettings(); }else if (line.contains("250-version=")) handleTorVersion(line.section("=",1,1)); else if (line.contains("250 BandwidthRate=")) m_CurBandwidthRate = line.section("=",1,1).toInt(); else if (line.contains("250 BandwidthBurst=")) m_CurBandwidthBurst = line.section("=",1,1).toInt(); else if (line.contains("250 MaxAdvertisedBandwidth=")) m_CurMaxAdvertisedBandwidth = line.section("=",1,1).toInt(); else if (line.contains("250 ExcludeNodes=")) TorkConfig::setCurrentExcludeNodes(TQStringList::split(",",line.replace("250 ExcludeNodes=",""))); else if (line.contains("250 EntryNodes=")) TorkConfig::setCurrentEntryNodes(TQStringList::split(",",line.replace("250 EntryNodes=",""))); else if (line.contains("250 ExitNodes=")) TorkConfig::setCurrentExitNodes(TQStringList::split(",",line.replace("250 ExitNodes=",""))); else if (line.contains("250-status/circuit-established=1")) updateClientReport("CIRCUIT_ESTABLISHED"); else if (line.contains("250-status/circuit-established=0")) updateClientReport("CIRCUIT_NOT_ESTABLISHED"); else if (line.contains("250-status/enough-dir-info=1")){ updateClientReport("ENOUGH_DIR_INFO"); sendToServer("GETINFO status/circuit-established"); }else if (line.contains("250-status/enough-dir-info=0")) updateClientReport("NOT_ENOUGH_DIR_INFO"); else if (line.contains("250-status/good-server-descriptor=1")) updateServerReport("GOOD_SERVER_DESCRIPTOR", TQString()); else if (line.contains("250-status/good-server-descriptor=0")) updateServerReport("BAD_SERVER_DESCRIPTOR", TQString()); else if (line.contains("250-status/reachability-succeeded/or=1")) updateServerReport("REACHABILITY_SUCCEEDED", TQString()); else if (line.contains("250-status/reachability-succeeded/or=0")) updateServerReport("REACHABILITY_FAILED", TQString()); } void TorClient::socketReadyRead() { TQString line; // read from the server while ( socket->canReadLine() ) { line = (socket->readLine()).stripWhiteSpace(); if (line.contains("250 OK")){ if (!m_controllerWorking){ bandwidth(); emit authenticated(); m_controllerWorking = true; } continue; } if (m_expectingDirStatus){ if (!(line == ".")){ parseDirStatus(line); }else{ m_expectingDirStatus = false; sendToServer("GETINFO entry-guards"); if (!m_firstloadcomplete) emit shouldIApplySettings(); m_firstloadcomplete = true; } continue; }else if ((m_expectingCircuitInfo)){ if (line != "."){ parseEvent("CIRC",line); }else m_expectingCircuitInfo = false; continue; }else if ((m_expectingOrconnInfo)){ if (line != "."){ parseEvent("ORCONN",line); }else m_expectingOrconnInfo = false; continue; }else if ((m_expectingStreamInfo)){ if (line != "."){ parseEvent("STREAM",line); }else m_expectingStreamInfo = false; continue; }else if (m_expectingServerInfo){ if (line != "."){ parseEvent("SERVER",line); }else m_expectingServerInfo = false; continue; }else if (m_expectingGuardsInfo){ if (line != "."){ parseEvent("GUARDS",line); emit whatImDoing(i18n("Ready for use.")); }else{ m_expectingGuardsInfo = false; } continue; } if (line.contains("552 Unrecognized key \"ns/all\"")){ emit needAlphaVersion(); emit shouldIApplySettings(); continue; } TQString code = line.left(3); if (code == "250") handle250(line); else if (code == "650"){ if (line.contains("650+NS")){ m_expectingDirStatus= true; continue; } TQString eventType = line.section(" ",1,1); TQString eventInfo = line.section(" ",2); if (eventInfo.contains("circuit_testing_failed")) emit serverError(); parseEvent(eventType,eventInfo); }else if (code == "552"){ TQString eventInfo = line.section(" ",1); emit displayError("Sorry!", eventInfo); }else if (code == "514"){ TQString eventInfo = line.section(" ",1); emit processWarning("authenticationrequired", eventInfo); emit fatalError(); }else if (code == "515"){ TQString eventInfo = line.section(" ",1); if (eventInfo.contains("Wrong length")) emit processQuestion("cookierequired", eventInfo); else{ if (TorkConfig::generateRandomPassword()) emit processQuestion("passwordlost", eventInfo); else emit processWarning("authenticationfailed", eventInfo); } //Only used by the first-run wizard emit authenticationFailed(); } } } void TorClient::parseEvent(const TQString &type, const TQString &info) { if (info.isEmpty()) return; if (type == "STREAM") parseStream(info); else if (type == "ORCONN") parseORConn(info); else if (type == "CIRC") parseCircuit(info); else if (type == "GUARDS") parseGuards(info); else if (type == "GUARD") parseGuards(info.section(" ",1)); else if (type == "SERVER") parseServer(info); else if (type == "DIRSTATUS") parseDirStatus(info); else if (type == "BW") parseBW(info); else if (type == "STREAM_BW") parseStreamBW(info); else if (type.contains( "STATUS_")) parseStatusGeneral(info); else if (type == "ADDRMAP") parseAddrmap(info); /* else if (type == "STREAM_PORT") parseStreamPort(info);*/ else if ((type == "WARN") || (type == "NOTICE") || (type == "ERR")) parseInfo(type,info); } void TorClient::parseStatusGeneral(const TQString &info) { TQString severity = info.section(" ",0,0); TQString action = info.section(" ",1,1); TQString message = statusMessage[action]; if (!serverStatus[action].isEmpty()) updateServerReport(action, info); if (!clientStatus[action].isEmpty()) updateClientReport(action); /* kdDebug() << info << endl; kdDebug() << info.section(" ",2) << endl;*/ populateMessageFromStatusDetail(info.section(" ",2), message); if (message.left(14) == "WARNINGMESSAGE"){ message.replace("WARNINGMESSAGE",""); emit processWarning(action, message); }else{ message.replace("QUESTIONMESSAGE",""); emit processQuestion(action, message); } } void TorClient::populateMessageFromStatusDetail(const TQString &line, TQString &message) { TQRegExp rx("[\\sA-Z0-9]+[=]([\\-\\:\\.\\(\\)a-zA-Z0-9]+|\\\"[\\-\\.\\,a-zA-Z0-9\\s]+\\\")"); int pos = 0; while ( (pos = rx.search(line, pos)) != -1 ) { /* kdDebug() << rx.cap(0) << endl;*/ TQString keyword = rx.cap(0).section("=",0,0).stripWhiteSpace(); TQString value = rx.cap(0).section("=",1,1).stripWhiteSpace(); message.replace(keyword,value); pos += rx.matchedLength(); if (keyword=="PORT"){ m_WarnedPorts << value; message.append(portMessage[value]); } } } void TorClient::updateServerReport(const TQString &message, const TQString &info) { // kdDebug() << serverStatusIcon[message] << endl; // kdDebug() << message << endl; //If we're back to being a client, ensure the server symbol is removed from the tray icon if (TorkConfig::clientOnly()){ emit updateTrayIcon(serverStatusIcon[message].replace("server","")); return; } if (!serverStatusIcon[message].isEmpty()) emit updateTrayIcon(serverStatusIcon[message]); serverReport.remove("Status Not Known"); TQString msg = serverStatus[message]; if (message.contains("EXTERNAL_ADDRESS")){ for ( TQStringList::Iterator it = serverReport.begin(); it != serverReport.end(); ++it ) { // XXX Fixme if ((*it).contains("Using Address")){ serverReport.remove((*it)); break; } } populateMessageFromStatusDetail(info.section(" ",2),msg); }else if (message.contains("REACHABILITY")){ serverReport.remove(serverStatus["REACHABILITY_FAILED"]); serverReport.remove(serverStatus["REACHABILITY_SUCCEEDED"]); }else if (message.contains("SERVER_DESCRIPTOR")){ serverReport.remove(serverStatus["DIR_ALL_UNREACHABLE"]); serverReport.remove(serverStatus["BAD_SERVER_DESCRIPTOR"]); serverReport.remove(serverStatus["GOOD_SERVER_DESCRIPTOR"]); }else // Prevent multiple reports serverReport.remove(msg); serverReport.append(msg); } void TorClient::updateClientReport(const TQString &message) { if (!clientStatusIcon[message].isEmpty() && (TorkConfig::clientOnly())) emit updateTrayIcon(clientStatusIcon[clientStatus[message]]); clientReport.clear(); clientReport.append(clientStatus[message]); } void TorClient::resetClientReport() { emit updateTrayIcon(clientStatusIcon[clientReport.first()]); } void TorClient::parseBW(const TQString &info) { TQString in = info.section(" ",0,0); TQString out = info.section(" ",1,1); emit bwUpdate(in, out); } void TorClient::parseStreamBW(const TQString &info) { TQString stream = info.section(" ",0,0); /* Tor spec had it wrong way round! */ TQString out = info.section(" ",1,1); TQString in = info.section(" ",2,2); emit streamBwUpdate(stream, in, out); } void TorClient::parseStream(const TQString &info) { TQString streamID = info.section(" ",0,0); TQString status = info.section(" ",1,1); TQString circID = info.section(" ",2,2); TQString Target = info.section(" ",3,3); //We ignore REMAPs because we don't do anything with them if (status == "REMAP") return; emit streamStatusUpdate(streamID, status, circID, Target, info); } void TorClient::parseServer(const TQString &info) { kdDebug() << "server info " << info << endl; if (info.left(7) == "router "){ TQString ip = info.section(" ",2,2); TQString cc; GeoIP * gi = 0; if (geoip_db) #ifndef EXTERNAL_GEOIP gi = GeoIP_open(locate("data", "tork/geoip/GeoIP.dat").ascii(),0); #else gi = GeoIP_new(GEOIP_STANDARD); #endif if (gi){ int country_id = 0; country_id = GeoIP_id_by_name(gi, ip); cc = GeoIP_country_name[country_id]; GeoIP_delete(gi); }else cc = "a1"; m_statustiptmp = m_statustip; m_statustipIP = ip; m_statustiptmp.replace("$SERVERNAME",info.section(" ",1,1)); m_statustiptmp.replace("$IP",ip); m_statustiptmp.replace("$PORT",info.section(" ",3,3)); m_statustiptmp.replace("$COUNTRY",cc); }else if (info.left(8) == "platform"){ m_statustiptmp.replace("$VERSION",info.section(" ",1,2)); m_statustiptmp.replace("$OS",info.section(" ",4).section("{",0,0)); }else if (info.left(9) == "published"){ m_statustiptmp.replace("$PUBLISHED",info.section(" ",1)); }else if (info.left(6) == "uptime"){ //from the clever ktorrent TDELocale* loc = TDEGlobal::locale(); TQTime t; int nsecs = info.section(" ",1).toInt(); int ndays = (nsecs) / 86400; t = t.addSecs(nsecs % 86400); TQString s = loc->formatTime(t,true,true); if (ndays > 0) s = i18n("1 day ","%n days ",ndays) + s; m_statustiptmp.replace("$UPTIME",s); }else if (info.left(20).contains("write-history")){ TQStringList bwlist = TQStringList::split(",",info.section(" ",-1)); TQValueList bws; bws << 4 << 24 << 48 << bwlist.count(); TQString bwup; TQString avgbw; for ( TQValueList::Iterator it = bws.begin(); it != bws.end(); ++it ){ avgbw = calcBW(bwlist, (*it)); for (int i = avgbw.length(); i < 14; i++) avgbw.append("  "); bwup.append(avgbw); } m_statustiptmp.replace("$BWUP",bwup); m_statustiptmp.replace("$INTERVALTIME", info.section(" ",2,3)); }else if (info.left(20).contains("read-history")){ TQStringList bwlist = TQStringList::split(",",info.section(" ",-1)); TQValueList bws; bws << 4 << 24 << 48 << bwlist.count(); TQString bwup; TQString avgbw; for ( TQValueList::Iterator it = bws.begin(); it != bws.end(); ++it ){ avgbw = calcBW(bwlist, (*it)); for (int i = avgbw.length(); i < 14; i++) avgbw.append("  "); bwup.append(avgbw); } m_statustiptmp.replace("$BWDN",bwup); if (m_currentTorVersion.left(3) == "0.2"){ m_resolvingServerAddress=true; sendToServer("RESOLVE mode=reverse " + m_statustipIP); }else{ m_statustiptmp.replace("($HOSTNAME)",""); emit displayServer("Server Info", m_statustiptmp); } }else if (info.left(25).contains("opt extra-info-digest")){ if (m_currentTorVersion.left(3) == "0.2"){ sendToServer("GETINFO extra-info/digest/" + info.section(" ",2)); }else{ m_statustiptmp.replace("($HOSTNAME)",""); m_statustiptmp.replace("$BWDN","Unavailable"); m_statustiptmp.replace("$BWUP","Unavailable"); m_statustiptmp.replace("$INTERVALTIME", "Unavailable"); emit displayServer("Server Info", m_statustiptmp); } } } void TorClient::parseAddrmap(const TQString &info) { TQString type = info.section(" ",0,0); TQString address = info.section(" ",1,1); // If this is a request to resolve a hostname/address from the traffic // logs if (logResolveList.contains(type)){ emit resolvedAddress(info); logResolveList.remove(logResolveList.find(type)); return; } if (!m_resolvingServerAddress) return; // If this is a request to resolve a node name from the server list if (type.startsWith("REVERSE")){ m_statustiptmp.replace("$HOSTNAME",address); }else m_statustiptmp.replace("$HOSTNAME","Cannot Resolve Hostname."); emit displayServer("Server Info", m_statustiptmp); m_resolvingServerAddress = false; } void TorClient::parseGuards(const TQString &info) { TQString fp_identity = info.section(" ",0,0); TQString status = info.section(" ",1,1); TQRegExp rx("(\\$[A-Z0-9]{40})"); rx.search(fp_identity); TQString server = getNickNameFromFP(rx.cap(0)); if (!server.isEmpty()){ emit guardStatusUpdate(server, status); } } void TorClient::parseCircuit(const TQString &info) { if (info.contains("FAILED")) emit displayError("Circuit Failed - "+info.section(" ",3,3).replace("REASON=",""), "Circuit: " + info.section(" ",2,2)); TQString circuitID = info.section(" ",0,0).stripWhiteSpace(); TQString status = info.section(" ",1,1).stripWhiteSpace(); TQString path = info.section(" ",2,2).stripWhiteSpace(); //Get the FP Digest (if any) of the last server in the circuit TQString exit; TQRegExp rx("(\\$[A-Z0-9]{40})"); int count = 0; int pos = 0; while ( (pos = rx.search(path, pos)) != -1 ) { count++; pos += rx.matchedLength(); exit = rx.cap(0); } if (!exit.isEmpty()) exit = getFPDigestFromFP(exit); //Strip out the FPs from the circuit, if any path.replace(TQRegExp("(\\$[A-Z0-9]{40})(~|=)"),""); emit circuitStatusUpdate(circuitID, status, path, exit); } void TorClient::parseORConn(const TQString &info) { TQString serverID = info.section(" ",0,0); TQString status = info.section(" ",1,1); if (serverID.startsWith("$")){ TQString server = getNickNameFromFP(serverID); if (!server.isEmpty()) serverID = server; } if (!status.contains("NEW")){ serverID.replace(TQRegExp("^[A-Z0-9$=~]{42}"),""); emit ORStatusUpdate(serverID, status); } } void TorClient::parseInfo(const TQString &type,const TQString &info) { TQString message = info; message.replace(TQRegExp("^[a-zA-Z0-9_]+\\(\\):"),""); // TQString summary = info.section(":",0,0); // TQString data = info.section(":",1); if (info.contains("Servers unavailable")) emit displayServer("Server Info", "Server appears to be down!"); emit infoUpdate(type, message, TQString()); } void TorClient::updateCandidateServers(const TQString &path) { TQStringList servers = TQStringList::split(",", path); TQStringList existingServers = TorkConfig::serversHistory(); for ( TQStringList::Iterator it = servers.begin(); it != servers.end(); ++it ) { if ((*it).isEmpty()) continue; if (existingServers.find(*it) == existingServers.end()) existingServers.append(*it); } TorkConfig::setServersHistory(existingServers); TorkConfig::writeConfig(); } void TorClient::attemptAttach(const TQString &circid, const TQString &streamid) { TQStringList streams = TQStringList::split( " ", streamid); for ( TQStringList::Iterator it = streams.begin(); it != streams.end(); ++it ) { if ((*it).isEmpty()) continue; sendToServer(TQString("ATTACHSTREAM %1 %2").arg(*it).arg(circid)); } } void TorClient::attemptExtendCircuit(const TQString &circid, const TQString &serverlist, bool usefp) { TQStringList servers = TQStringList::split( " ", serverlist); TQStringList circuitlist; for ( TQStringList::Iterator it = servers.begin(); it != servers.end(); ++it ) { if ((*it).isEmpty()) continue; if (usefp) circuitlist.append(getFPFromFPDigest((*it))); else circuitlist.append((*it)); } TQString circuit = circuitlist.join(","); sendToServer(TQString("EXTENDCIRCUIT %1 %2").arg(circid).arg(circuit)); } void TorClient::attemptCreateCircuit(const TQString &serverlist, bool usefp) { TQStringList servers = TQStringList::split( " ", serverlist); TQStringList circuitlist; for ( TQStringList::Iterator it = servers.begin(); it != servers.end(); ++it ) { if ((*it).isEmpty()) continue; if (usefp) circuitlist.append(getFPFromFPDigest((*it))); else circuitlist.append((*it)); } TQString circuit = circuitlist.join(","); sendToServer(TQString("EXTENDCIRCUIT 0 %1").arg(circuit)); } void TorClient::attemptCloseStream(const TQString &streamid) { sendToServer(TQString("CLOSESTREAM %1 1").arg(streamid)); } void TorClient::attemptAttachStreams( bool attachStreams) { sendToServer(TQString("SETCONF __LeaveStreamsUnattached=%1").arg(attachStreams)); } void TorClient::attemptCloseCircuit(const TQString &circuitid) { sendToServer(TQString("CLOSECIRCUIT %1").arg(circuitid)); } void TorClient::updatePrevConfig(PrevConfig::PrevConfigList prevlist) { m_previtems = prevlist; } void TorClient::applySettingsToRunningTor() { //FIXME: use function pointers and a list to do this switch (TorkConfig::quickConfigure()) { case 0 : //Tor client and server with default settings return; case 1 : //Tor client with default settings return; case 2 : //Tor server with default settings return; case 3 : //Tor server with default settings return; case 4 : //Tor server with default settings return; default: break; } // kdDebug() << "1" << endl; TDEConfigSkeletonItem::List items = TorkConfig::self()->items(); TDEConfigSkeletonItem::List::ConstIterator it; for( it = items.begin(); it != items.end(); ++it ) { if (elementShouldBeUsed((*it))){ if (noSpecialProcessing((*it))){ PrevConfig::PrevConfigList::iterator mit; TQVariant oldvalue; for( mit = m_previtems.begin(); mit != m_previtems.end(); ++mit ) { if ((*mit).name() == (*it)->name()){ oldvalue = (*mit).property(); continue; } } if ( (*it)->property().type() == TQVariant::String ) { if ((oldvalue !=(*it)->property())){ ( sendToServer(TQString("SETCONF %1=%2").arg((*it)->name()).arg((*it)->property().toString()))); } }else if ( (*it)->property().type() == TQVariant::StringList ) { if ((oldvalue !=(*it)->property())){ ( sendToServer(TQString("SETCONF %1=\"%2\"").arg((*it)->name()).arg( (*it)->property().toStringList().join(",")))); } }else if ( (*it)->property().type() == TQVariant::Int ) { if ((oldvalue !=(*it)->property())){ ( sendToServer(TQString("SETCONF %1=%2").arg((*it)->name()).arg( (*it)->property().toString()))); } }else if ( (*it)->property().type() == TQVariant::Bool ) { if ((oldvalue !=(*it)->property())){ ( sendToServer(TQString("SETCONF %1=%2").arg((*it)->name()).arg( (*it)->property().toInt()))); } } } } } if (TorkConfig::useProxy()){ if ((TorkConfig::httpProxyPort() > 0) && (!TorkConfig::httpProxyHost().isEmpty())) ( sendToServer(TQString("SETCONF HttpProxy=%1:%2").arg(TorkConfig::httpProxyHost()).arg(TorkConfig::httpProxyPort()))) ; if ((TorkConfig::httpsProxyPort() > 0) && (!TorkConfig::httpsProxyHost().isEmpty())) ( sendToServer(TQString("SETCONF HttpsProxy=%1:%2").arg(TorkConfig::httpsProxyHost()).arg(TorkConfig::httpsProxyPort()))) ; if ((!TorkConfig::httpProxyAuthenticatorUserName().isEmpty()) && (!TorkConfig::httpProxyAuthenticatorPassword().isEmpty())) ( sendToServer(TQString("SETCONF HttpProxyAuthenticator=%1:%2").arg(TorkConfig::httpProxyAuthenticatorUserName()).arg(TorkConfig::httpProxyAuthenticatorPassword()))); if ((!TorkConfig::httpsProxyAuthenticatorUserName().isEmpty()) && (!TorkConfig::httpsProxyAuthenticatorPassword().isEmpty())) ( sendToServer(TQString("SETCONF HttpsProxyAuthenticator=%1:%2").arg(TorkConfig::httpsProxyAuthenticatorUserName() ).arg(TorkConfig::httpsProxyAuthenticatorPassword()))); }else{ ( sendToServer(TQString("SETCONF HttpProxy="))); ( sendToServer(TQString("SETCONF HttpsProxy="))); ( sendToServer(TQString("SETCONF HttpProxyAuthenticator="))); ( sendToServer(TQString("SETCONF HttpsProxyAuthenticator="))); } if ((!TorkConfig::sOCKSBindAddressHost().isEmpty()) && (TorkConfig::sOCKSBindAddressPort() > -1)) ( sendToServer(TQString("SETCONF SOCKSListenAddress=%1:%2").arg(TorkConfig::sOCKSBindAddressHost()).arg( TorkConfig::sOCKSBindAddressPort()))) ; if ((TorkConfig::sOCKSBindAddressHost().isEmpty()) && (TorkConfig::sOCKSBindAddressPort() > -1)) ( sendToServer(TQString("SETCONF SOCKSPort=%2").arg(TorkConfig::sOCKSBindAddressPort()))) ; emit copyOldConfig(); emit makeTorkStoppable(); sendToServer(TQString("GETCONF ExcludeNodes")) ; sendToServer(TQString("GETCONF ExitNodes")) ; sendToServer(TQString("GETCONF EntryNodes")) ; } bool TorClient::elementShouldBeUsed(const TDEConfigSkeletonItem* it) { //Maxmin Settings are always applied, defaults if 'let Tor decide' selected. if (((*it).group() == "MaxMin") || ((!(TorkConfig::clientOnly())) && ((*it).group() == "DefaultServerAddress")) || ((*it).group() == "FirewallEvasion") || ((*it).group() == "Censorship") || (((*it).group() == "RunningSpecial")) || (((*it).group() == "Servers")) || // Server settings are applied by calling configureServer() later //(((*it).group() == "MyServer")) || (((*it).group() == "Usability")) || (((*it).group() == "UsingTor")) || (((*it).group() == "MyHiddenServices")) || //Serverperformance Settings are always applied, defaults if 'let Tor decide' selected. (((*it).group() == "ServerPerformance"))) return true; //Excluded: //((*it).group() == "RunningNormal")) - Because they aren't appropriate for a running Tor return false; } bool TorClient::noSpecialProcessing(const TDEConfigSkeletonItem* it) { if (((*it).name() == "PublishServerDescriptor") && (TorkConfig::bridgeRelay())){ sendToServer(TQString("setconf PublishServerDescriptor=bridge")); return false; } if ((*it).name() == "HashedControlPassword"){ if ((*it).property().toString().isEmpty() && (!TorkConfig::cookieAuthentication()) && TorkConfig::generateRandomPassword()){ crypto_seed_rng(); sendToServer(TQString("setconf %1=16:%2") .arg((*it).name()) .arg(hashPassword(crypto_rand_string(16)))); return false; } return true; } if ((*it).group() == "DefaultServerAddress"){ if ((*it).name() == "ORPort") ( sendToServer(TQString("SETCONF %1=%2").arg((*it).name()) .arg( (*it).property().toString()))); return false; } if (((*it).name() == "BandwidthBurst") || ((*it).name() == "BandwidthRate")){ ( sendToServer(TQString("SETCONF BandwidthBurst=%1KB BandwidthRate=%2KB") .arg(TorkConfig::bandwidthBurst()).arg(TorkConfig::bandwidthRate()))); getBandwidth(); return false; } if ((*it).name() == "MaxAdvertisedBandwidth"){ ( sendToServer(TQString("SETCONF %1=%2KB").arg((*it).name()).arg( (*it).property().toString()))); getBandwidth(); return false; } if ((*it).name() == "AccountingMax"){ ( sendToServer(TQString("SETCONF %1=\"%2 bytes\"").arg((*it).name()).arg( ((*it).property().toInt() * 1024 * 1024)))); return false; } if ((*it).name() == "AccountingStart"){ if ((*it).property().toString() == "day") ( sendToServer(TQString("SETCONF %1=\"%2 00:00\"").arg((*it).name()).arg( (*it).property().toString()))); else ( sendToServer(TQString("SETCONF %1=\"%2 1 00:00\"").arg((*it).name()).arg( (*it).property().toString()))); return false; } if ((*it).name() == "KeepalivePeriod"){ if (!TorkConfig::reachableAddresses().isEmpty()){ ( sendToServer(TQString("SETCONF %1=%2").arg((*it).name()).arg( ((*it).property().toInt() * 60)))) ; } return false; } if ((*it).name() == "TrackHostExits"){ if (!TorkConfig::trackHostExits().isEmpty()){ ( sendToServer(TQString("SETCONF %1=%2").arg((*it).name()).arg( ((*it).property().toStringList().join(","))))) ; if (TorkConfig::trackHostExitsExpire() > 0) ( sendToServer(TQString("SETCONF TrackHostExitsExpire=%2").arg((TorkConfig::trackHostExitsExpire() * 60)))) ; } return false; } if ((*it).name() == "SOCKSBindAddressMany"){ if (!TorkConfig::sOCKSBindAddressMany().isEmpty()){ TQStringList socksbind = TorkConfig::sOCKSBindAddressMany(); for ( TQStringList::Iterator it = (socksbind).begin(); it != (socksbind).end(); it++ ) { if ((*it).isEmpty()) continue; ( sendToServer(TQString("SETCONF SOCKSListenAddress=%2").arg((*it)))) ; } } return false; } if ((*it).name() == "ExitPolicy"){ if (TorkConfig::middleMan()) ( sendToServer(TQString("SETCONF ExitPolicy=%1").arg(("\"reject *:*\"")))) ; else ( sendToServer(TQString("SETCONF %1=\"%2\"").arg((*it).name()).arg( (*it).property().toStringList().join(",")))); return false; } if ((*it).name() == "HiddenServices"){ TQStringList hiddenServices = TorkConfig::hiddenServices(); TQString allservices; for ( TQStringList::Iterator it = (hiddenServices).begin(); it != (hiddenServices).end(); it++ ) { if ((*it).isEmpty()) continue; allservices += (TQString("HiddenServiceDir=\"%1\" HiddenServicePort=\"%2 %3\" ").arg((*it).section("\n",-1)).arg((*it).section("\n",-4,-4)).arg((*it).section("\n",-3,-3))) ; } if (!allservices.isEmpty()) ( sendToServer(TQString("SETCONF %1").arg(allservices))) ; else ( sendToServer(TQString("SETCONF HiddenServiceDir= HiddenServicePort="))) ; return false; } if ((TorkConfig::useBridges()) && ((*it).name() == "Bridge")){ TQStringList bridges = TorkConfig::bridge(); TQString allbridges; for ( TQStringList::Iterator it = (bridges).begin(); it != (bridges).end(); it++ ) { if ((*it).isEmpty()) continue; allbridges += (TQString("Bridge=\"%1\" ") .arg((*it))) ; } if (!allbridges.isEmpty()) ( sendToServer(TQString("SETCONF %1").arg(allbridges))) ; else ( sendToServer(TQString("SETCONF Bridge="))) ; return false; } if ((*it).name() == "MyFamily"){ TQStringList family = TorkConfig::myFamily(); TQStringList allfamily; for ( TQStringList::Iterator it = (family).begin(); it != (family).end(); it++ ) { if ((*it).isEmpty()) continue; TQString node = "$"+getFPFromFPDigest((*it).section("-",1,1)); allfamily.append(node) ; } if (!allfamily.isEmpty()) ( sendToServer(TQString("SETCONF MyFamily=%1").arg(allfamily.join(",")))) ; else ( sendToServer(TQString("SETCONF MyFamily="))) ; return false; } if ((*it).name() == "MapAddress"){ TQStringList maps = TorkConfig::mapAddress(); for ( TQStringList::Iterator it = (maps).begin(); it != (maps).end(); it++ ) { if ((*it).isEmpty()) continue; ( sendToServer(TQString("SETCONF MapAddress=%2").arg((*it)))) ; } return false; } if ((!TorkConfig::fascistFirewall()) && ((*it).name() == "ReachableAddresses")){ ( sendToServer(TQString("SETCONF ReachableAddresses="))) ; return false; } return true; } void TorClient::cleanUp() { if (TorkConfig::hashedControlPassword().isEmpty() && (!TorkConfig::cookieAuthentication()) && TorkConfig::generateRandomPassword()){ sendToServer(TQString("setconf HashedControlPassword=")); socket->flush(); } } TorClient::~TorClient() { } void TorClient::parseDirStatus(const TQString &info) { if (info.left(2) == "r "){ ds_identity = info.section(" ",2,2); ds_ip = info.section(" ",6,6); ds_server = info.section(" ",1,1); ds_date = info.section(" ",4,4); return; } if (info.left(2) == "s "){ if (TQDate::currentDate().daysTo(TQDate(ds_date.left(4).toInt(), ds_date.mid(5,2).toInt(),ds_date.right(2).toInt())) > -30) { if (server(ds_identity).isEmpty()) storeServer(ds_server,ds_identity); ds_statuses = info; emit updateServerStatus(ds_ip, ds_identity, ds_server, ds_statuses); } } } bool TorClient::isControllerWorking() { return m_controllerWorking; } void TorClient::setBandwidth(const TQString &rate, const TQString &burst, const TQString &max) { ( sendToServer(TQString("SETCONF BandwidthRate=%2KB BandwidthBurst=%2KB") .arg(rate).arg(burst))); if (!max.isEmpty()) ( sendToServer(TQString("SETCONF MaxAdvertisedBandwidth=%2KB").arg(max))); getBandwidth(); } void TorClient::getBandwidth() { ( sendToServer(TQString("GETCONF BandwidthRate"))); ( sendToServer(TQString("GETCONF BandwidthBurst"))); ( sendToServer(TQString("GETCONF MaxAdvertisedBandwidth"))); } void TorClient::handleTorVersion( const TQString &caption) { m_currentTorVersion = caption; if (m_currentTorVersion.left(3) == "0.2") sendToServer("SETCONF DownloadExtraInfo=1"); emit setTorCaption(caption); } void TorClient::closeAllCircuits( TQListView* &circuitList) { TQListViewItemIterator cit(circuitList); while ( cit.current() ) { attemptCloseCircuit(cit.current()->text(0)); ++cit; } } void TorClient::assignPortToRemove() { //called by the warning message to get the port to remove in case // user requests it. if (m_WarnedPorts[0].isNull()) return; kdDebug() << "warnedports " << m_WarnedPorts[0] << endl; m_portToRemove = m_WarnedPorts[0]; kdDebug() << "porttoremove" << m_portToRemove << endl; m_WarnedPorts.pop_front(); kdDebug() << "porttoremove" << m_portToRemove << endl; } void TorClient::allowPlainTextPorts() { kdDebug() << "m_portsToReject " << m_portsToReject << endl; m_portsToReject.remove(m_portsToReject.find(m_portToRemove)); sendToServer(TQString("SETCONF WarnPlainTextPorts=%1") .arg(m_portsToReject.join(","))); sendToServer(TQString("SETCONF RejectPlainTextPorts=%1") .arg(m_portsToReject.join(","))); } void TorClient::resolveAddress(const TQString &address) { TQRegExp rx("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); rx.search(address); TQString tmp = rx.cap(0); if (tmp.isEmpty()) { sendToServer("RESOLVE " + address); logResolveList << address; }else{ sendToServer("RESOLVE mode=reverse " + tmp); logResolveList << TQString("REVERSE[%1]").arg(tmp); } } #include "torclient.moc"