00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <QHostAddress>
00018 #include <file.h>
00019 #include <stringutil.h>
00020 #include "torcontrol.h"
00021
00022
00023
00024 TorControl::TorControl()
00025 {
00026
00027
00028 _controlConn = new ControlConnection(&_torEvents);
00029 QObject::connect(_controlConn, SIGNAL(connected()),
00030 this, SLOT(onConnected()));
00031 QObject::connect(_controlConn, SIGNAL(connectFailed(QString)),
00032 this, SLOT(onConnectFailed(QString)));
00033 QObject::connect(_controlConn, SIGNAL(disconnected()),
00034 this, SLOT(onDisconnected()));
00035
00036
00037 _torProcess = new TorProcess(this);
00038 QObject::connect(_torProcess, SIGNAL(started()),
00039 this, SLOT(onStarted()));
00040 QObject::connect(_torProcess, SIGNAL(finished(int, QProcess::ExitStatus)),
00041 this, SLOT(onStopped(int, QProcess::ExitStatus)));
00042 QObject::connect(_torProcess, SIGNAL(startFailed(QString)),
00043 this, SLOT(onStartFailed(QString)));
00044 QObject::connect(_torProcess, SIGNAL(log(QString, QString)),
00045 this, SLOT(onLogStdout(QString, QString)));
00046
00047 #if defined(Q_OS_WIN32)
00048 _torService = new TorService(this);
00049 QObject::connect(_torService, SIGNAL(started()), this, SLOT(onStarted()));
00050 QObject::connect(_torService, SIGNAL(finished(int, QProcess::ExitStatus)),
00051 this, SLOT(onStopped(int, QProcess::ExitStatus)));
00052 QObject::connect(_torService, SIGNAL(startFailed(QString)),
00053 this, SLOT(onStartFailed(QString)));
00054 #endif
00055 }
00056
00057
00058 TorControl::~TorControl()
00059 {
00060
00061 if (isConnected()) {
00062 disconnect();
00063 }
00064
00065 if (isVidaliaRunningTor()) {
00066 stop();
00067 }
00068 delete _controlConn;
00069 }
00070
00071
00072
00073 void
00074 TorControl::start(const QString &tor, const QStringList &args)
00075 {
00076 if (isRunning()) {
00077 emit started();
00078 } else {
00079 #if defined(Q_OS_WIN32)
00080
00081
00082 if (TorService::isSupported() && _torService->isInstalled())
00083 _torService->start();
00084 else
00085 _torProcess->start(expand_filename(tor), args);
00086 #else
00087
00088 _torProcess->start(expand_filename(tor), args);
00089 #endif
00090 }
00091 }
00092
00093
00094 void
00095 TorControl::onStarted()
00096 {
00097 emit started();
00098 }
00099
00100
00101
00102 void
00103 TorControl::onStartFailed(QString errmsg)
00104 {
00105 emit startFailed(errmsg);
00106 }
00107
00108
00109 bool
00110 TorControl::stop(QString *errmsg)
00111 {
00112 bool rc = false;
00113 if (_controlConn->isConnected())
00114 rc = signal(TorSignal::Halt, errmsg);
00115 if (!rc)
00116 rc = _torProcess->stop(errmsg);
00117 return rc;
00118 }
00119
00120
00121 void
00122 TorControl::onStopped(int exitCode, QProcess::ExitStatus exitStatus)
00123 {
00124 if (_controlConn->status() == ControlConnection::Connecting)
00125 _controlConn->cancelConnect();
00126
00127 emit stopped();
00128 emit stopped(exitCode, exitStatus);
00129 }
00130
00131
00132
00133 bool
00134 TorControl::isVidaliaRunningTor()
00135 {
00136 return (_torProcess->state() != QProcess::NotRunning);
00137 }
00138
00139
00140 bool
00141 TorControl::isRunning()
00142 {
00143 return (_torProcess->state() != QProcess::NotRunning
00144 || _controlConn->isConnected());
00145 }
00146
00147
00148 void
00149 TorControl::onLogStdout(QString severity, QString message)
00150 {
00151 LogEvent::Severity s = LogEvent::toSeverity(severity);
00152 _torEvents.dispatch(TorEvents::toTorEvent(s), new LogEvent(s, message));
00153 }
00154
00155
00156
00157 void
00158 TorControl::connect(const QHostAddress &address, quint16 port)
00159 {
00160 _controlConn->connect(address, port);
00161 }
00162
00163
00164
00165 void
00166 TorControl::onConnected()
00167 {
00168
00169 emit connected();
00170 }
00171
00172
00173 void
00174 TorControl::onConnectFailed(QString errmsg)
00175 {
00176 emit connectFailed(errmsg);
00177 }
00178
00179
00180 void
00181 TorControl::disconnect()
00182 {
00183 if (isConnected())
00184 _controlConn->disconnect();
00185 }
00186
00187
00188 void
00189 TorControl::onDisconnected()
00190 {
00191 if (_torProcess) {
00192
00193
00194
00195 _torProcess->openStdout();
00196 }
00197
00198 _torVersion = QString();
00199
00200
00201 emit disconnected();
00202 }
00203
00204
00205 bool
00206 TorControl::isConnected()
00207 {
00208 return _controlConn->isConnected();
00209 }
00210
00211
00212
00213
00214
00215 bool
00216 TorControl::send(ControlCommand cmd, ControlReply &reply, QString *errmsg)
00217 {
00218 if (_controlConn->send(cmd, reply, errmsg)) {
00219 if (reply.getStatus() == "250") {
00220 return true;
00221 }
00222 if (errmsg) {
00223 *errmsg = reply.getMessage();
00224 }
00225 }
00226 return false;
00227 }
00228
00229
00230 bool
00231 TorControl::send(ControlCommand cmd, QString *errmsg)
00232 {
00233 ControlReply reply;
00234 return send(cmd, reply, errmsg);
00235 }
00236
00237
00238
00239
00240
00241 bool
00242 TorControl::authenticate(const QByteArray cookie, QString *errmsg)
00243 {
00244 ControlCommand cmd("AUTHENTICATE", base16_encode(cookie));
00245 ControlReply reply;
00246 QString str;
00247
00248 if (!send(cmd, reply, &str)) {
00249 emit authenticationFailed(str);
00250 return err(errmsg, str);
00251 }
00252 onAuthenticated();
00253 return true;
00254 }
00255
00256
00257
00258
00259
00260 bool
00261 TorControl::authenticate(const QString password, QString *errmsg)
00262 {
00263 ControlCommand cmd("AUTHENTICATE", QString("%1")
00264 .arg(string_escape(password)));
00265 ControlReply reply;
00266 QString str;
00267
00268 if (!send(cmd, reply, &str)) {
00269 emit authenticationFailed(str);
00270 return err(errmsg, str);
00271 }
00272 onAuthenticated();
00273 return true;
00274 }
00275
00276
00277 void
00278 TorControl::onAuthenticated()
00279 {
00280
00281
00282 getInfo("version", _torVersion);
00283
00284 useFeature("VERBOSE_NAMES");
00285
00286
00287 if (_torProcess)
00288 _torProcess->closeStdout();
00289
00290 emit authenticated();
00291 }
00292
00293
00294 ProtocolInfo
00295 TorControl::protocolInfo(QString *errmsg)
00296 {
00297 ControlCommand cmd("PROTOCOLINFO", "1");
00298 ControlReply reply;
00299 ProtocolInfo pi;
00300 QString msg, topic;
00301 QHash<QString,QString> keyvals;
00302 int idx;
00303 bool ok;
00304
00305 if (!send(cmd, reply, errmsg))
00306 return ProtocolInfo();
00307
00308 foreach (ReplyLine line, reply.getLines()) {
00309 if (line.getStatus() != "250")
00310 continue;
00311
00312 msg = line.getMessage().trimmed();
00313 idx = msg.indexOf(" ");
00314 topic = msg.mid(0, idx).toUpper();
00315
00316 if (idx > 0) {
00317 keyvals = string_parse_keyvals(msg.mid(idx+1), &ok);
00318 if (!ok)
00319 continue;
00320 } else {
00321 keyvals = QHash<QString,QString>();
00322 }
00323
00324 if (topic == "AUTH") {
00325 if (keyvals.contains("METHODS"))
00326 pi.setAuthMethods(keyvals.value("METHODS"));
00327 if (keyvals.contains("COOKIEFILE"))
00328 pi.setCookieAuthFile(keyvals.value("COOKIEFILE"));
00329 } else if (topic == "VERSION") {
00330 if (keyvals.contains("Tor"))
00331 pi.setTorVersion(keyvals.value("Tor"));
00332 }
00333 }
00334 return pi;
00335 }
00336
00337
00338
00339
00340 bool
00341 TorControl::useFeature(const QString &feature, QString *errmsg)
00342 {
00343 ControlCommand cmd("USEFEATURE", feature);
00344 return send(cmd, errmsg);
00345 }
00346
00347 BootstrapStatus
00348 TorControl::bootstrapStatus(QString *errmsg)
00349 {
00350 QString str = getInfo("status/bootstrap-phase").toString();
00351 if (!str.isEmpty()) {
00352 tc::Severity severity = tc::toSeverity(str.section(' ', 0, 0));
00353 QHash<QString,QString> args = string_parse_keyvals(str);
00354 return BootstrapStatus(severity,
00355 BootstrapStatus::statusFromString(args.value("TAG")),
00356 args.value("PROGRESS").toInt(),
00357 args.value("SUMMARY"),
00358 args.value("WARNING"),
00359 tc::toConnectionStatusReason(args.value("REASON")),
00360 BootstrapStatus::actionFromString(
00361 args.value("RECOMMENDATION")));
00362 }
00363 return BootstrapStatus();
00364 }
00365
00366
00367
00368 bool
00369 TorControl::circuitEstablished()
00370 {
00371
00372
00373 if (getTorVersion() >= 0x020001) {
00374 QString tmp;
00375 if (getInfo("status/circuit-established", tmp))
00376 return (tmp == "1");
00377 }
00378
00379
00380
00381 CircuitList circs = getCircuits();
00382 foreach (Circuit circ, circs) {
00383 if (circ.status() == Circuit::Built)
00384 return true;
00385 }
00386 return false;
00387 }
00388
00389
00390
00391
00392
00393
00394 bool
00395 TorControl::getInfo(QHash<QString,QString> &map, QString *errmsg)
00396 {
00397 ControlCommand cmd("GETINFO");
00398 ControlReply reply;
00399
00400
00401 foreach (QString key, map.keys()) {
00402 cmd.addArgument(key);
00403 }
00404
00405
00406 if (send(cmd, reply, errmsg)) {
00407
00408 foreach (ReplyLine line, reply.getLines()) {
00409
00410 QStringList keyval = line.getMessage().split("=");
00411 if (keyval.size() == 2) {
00412 map.insert(keyval.at(0), keyval.at(1));
00413 }
00414 }
00415 return true;
00416 }
00417 return false;
00418 }
00419
00420
00421
00422
00423 QVariantMap
00424 TorControl::getInfo(const QStringList &keys, QString *errmsg)
00425 {
00426 ControlCommand cmd("GETINFO");
00427 ControlReply reply;
00428 QVariantMap infoMap;
00429
00430 cmd.addArguments(keys);
00431 if (!send(cmd, reply, errmsg))
00432 return QVariantMap();
00433
00434 foreach (ReplyLine line, reply.getLines()) {
00435 QString msg = line.getMessage();
00436 int index = msg.indexOf("=");
00437 QString key = msg.mid(0, index);
00438 QStringList val;
00439
00440 if (index > 0 && index < msg.length()-1)
00441 val << msg.mid(index+1);
00442 if (line.hasData())
00443 val << line.getData();
00444
00445 if (infoMap.contains(key)) {
00446 QStringList values = infoMap.value(key).toStringList();
00447 values << val;
00448 infoMap.insert(key, values);
00449 } else {
00450 infoMap.insert(key, val);
00451 }
00452 }
00453 return infoMap;
00454 }
00455
00456
00457
00458
00459 QVariant
00460 TorControl::getInfo(const QString &key, QString *errmsg)
00461 {
00462 QVariantMap map = getInfo(QStringList() << key, errmsg);
00463 return map.value(key);
00464 }
00465
00466
00467 bool
00468 TorControl::getInfo(QString key, QString &val, QString *errmsg)
00469 {
00470 QHash<QString,QString> map;
00471 map.insert(key, "");
00472
00473 if (getInfo(map, errmsg)) {
00474 val = map.value(key);
00475 return true;
00476 }
00477 return false;
00478 }
00479
00480
00481 bool
00482 TorControl::signal(TorSignal::Signal sig, QString *errmsg)
00483 {
00484 ControlCommand cmd("SIGNAL");
00485 cmd.addArgument(TorSignal::toString(sig));
00486
00487 if (sig == TorSignal::Shutdown || sig == TorSignal::Halt) {
00488
00489
00490 return _controlConn->send(cmd, errmsg);
00491 }
00492 return send(cmd, errmsg);
00493 }
00494
00495
00496
00497 QHostAddress
00498 TorControl::getSocksAddress(QString *errmsg)
00499 {
00500 QHostAddress socksAddr;
00501
00502
00503 if (getSocksPort() == 0) {
00504 return QHostAddress::Null;
00505 }
00506
00507
00508
00509 QStringList addrList = getSocksAddressList(errmsg);
00510 foreach (QString addr, addrList) {
00511 addr = addr.mid(0, addr.indexOf(":"));
00512 if (socksAddr.setAddress(addr)) {
00513 return socksAddr;
00514 }
00515 }
00516
00517 return QHostAddress::LocalHost;
00518 }
00519
00520
00521
00522 QStringList
00523 TorControl::getSocksAddressList(QString *errmsg)
00524 {
00525 QStringList addrList;
00526 if (getConf("SocksListenAddress", addrList, errmsg)) {
00527 return addrList;
00528 }
00529 return QStringList();
00530 }
00531
00532
00533
00534 quint16
00535 TorControl::getSocksPort(QString *errmsg)
00536 {
00537 QList<quint16> portList = getSocksPortList(errmsg);
00538 if (portList.size() > 0) {
00539 return portList.at(0);
00540 }
00541 return 0;
00542 }
00543
00544
00545
00546 QList<quint16>
00547 TorControl::getSocksPortList(QString *errmsg)
00548 {
00549 bool valid;
00550 quint16 port, socksPort;
00551 QString portString;
00552 QList<quint16> portList;
00553
00554
00555 if (getConf("SocksPort", portString, errmsg)) {
00556 socksPort = (quint16)portString.toUInt(&valid);
00557 if (valid) {
00558 if (socksPort == 0) {
00559
00560
00561 return QList<quint16>();
00562 }
00563 }
00564 }
00565
00566 QStringList addrList = getSocksAddressList(errmsg);
00567 foreach (QString addr, addrList) {
00568 if (addr.contains(":")) {
00569 portString = addr.mid(addr.indexOf(":")+1);
00570 port = (quint16)portString.toUInt(&valid);
00571 if (valid) {
00572 portList << port;
00573 }
00574 }
00575 }
00576
00577
00578 if (!portList.size() || (portList.size() != addrList.size())) {
00579 portList << socksPort;
00580 }
00581 return portList;
00582 }
00583
00584
00585 QString
00586 TorControl::getTorVersionString()
00587 {
00588 return _torVersion;
00589 }
00590
00591
00592
00593 quint32
00594 TorControl::getTorVersion()
00595 {
00596 static QString versionString;
00597 static quint32 version = 0;
00598 quint8 major, minor, micro, patch;
00599
00600
00601 if (versionString == _torVersion)
00602 return version;
00603 versionString = _torVersion;
00604
00605
00606 QStringList parts = versionString.split(QRegExp("\\.|-|\\ "));
00607 if (parts.size() >= 4) {
00608 major = (quint8)parts.at(0).toUInt();
00609 minor = (quint8)parts.at(1).toUInt();
00610 micro = (quint8)parts.at(2).toUInt();
00611 patch = (quint8)parts.at(3).toUInt();
00612 version = ((major << 24) | (minor << 16) | (micro << 8) | patch);
00613 } else {
00614
00615 version = 0;
00616 }
00617 return version;
00618 }
00619
00620
00621
00622
00623 bool
00624 TorControl::setEvent(TorEvents::TorEvent e, QObject *obj,
00625 bool add, bool set, QString *errmsg)
00626 {
00627 if (add) {
00628 _torEvents.add(e, obj);
00629 } else {
00630 _torEvents.remove(e, obj);
00631 }
00632 if (set && isConnected()) {
00633 return setEvents(errmsg);
00634 }
00635 return true;
00636 }
00637
00638
00639
00640
00641 bool
00642 TorControl::setLogEvents(uint filter, QObject *obj, QString *errmsg)
00643 {
00644 setEvent(TorEvents::LogError , obj, filter & LogEvent::Error , false);
00645 setEvent(TorEvents::LogWarn , obj, filter & LogEvent::Warn , false);
00646 setEvent(TorEvents::LogNotice, obj, filter & LogEvent::Notice, false);
00647 setEvent(TorEvents::LogInfo , obj, filter & LogEvent::Info , false);
00648 setEvent(TorEvents::LogDebug , obj, filter & LogEvent::Debug , false);
00649 return (isConnected() ? setEvents(errmsg) : true);
00650 }
00651
00652
00653 bool
00654 TorControl::setEvents(QString *errmsg)
00655 {
00656 ControlCommand cmd("SETEVENTS");
00657 quint32 torVersion = getTorVersion();
00658
00659
00660 foreach (TorEvents::TorEvent e, _torEvents.eventList()) {
00661 if (torVersion < 0x010203
00662 && (e == TorEvents::GeneralStatus
00663 || e == TorEvents::ClientStatus
00664 || e == TorEvents::ServerStatus)) {
00665
00666
00667 continue;
00668 }
00669 cmd.addArgument(TorEvents::toString(e));
00670 }
00671 return send(cmd, errmsg);
00672 }
00673
00674
00675
00676 bool
00677 TorControl::setConf(QHash<QString,QString> map, QString *errmsg)
00678 {
00679 ControlCommand cmd("SETCONF");
00680
00681
00682 foreach (QString key, map.uniqueKeys()) {
00683 foreach (QString value, map.values(key)) {
00684 if (value.length() > 0)
00685 cmd.addArgument(key + "=" + string_escape(value));
00686 else
00687 cmd.addArgument(key);
00688 }
00689 }
00690 return send(cmd, errmsg);
00691 }
00692
00693
00694 bool
00695 TorControl::setConf(QString key, QString value, QString *errmsg)
00696 {
00697 QHash<QString,QString> map;
00698 map.insert(key, value);
00699 return setConf(map, errmsg);
00700 }
00701
00702
00703 bool
00704 TorControl::setConf(QString keyAndValue, QString *errmsg)
00705 {
00706 QHash<QString,QString> map;
00707 map.insert(keyAndValue, "");
00708 return setConf(map, errmsg);
00709 }
00710
00711
00712
00713 bool
00714 TorControl::getConf(QHash<QString,QString> &map, QString *errmsg)
00715 {
00716 QHash<QString,QStringList> multiMap;
00717 foreach (QString key, map.keys()) {
00718 multiMap.insert(key, QStringList());
00719 }
00720 if (getConf(multiMap, errmsg)) {
00721 foreach (QString key, multiMap.keys()) {
00722 if (map.contains(key)) {
00723 map.insert(key, multiMap.value(key).join("\n"));
00724 }
00725 }
00726 }
00727 return false;
00728 }
00729
00730
00731 bool
00732 TorControl::getConf(QHash<QString,QStringList> &map, QString *errmsg)
00733 {
00734 ControlCommand cmd("GETCONF");
00735 ControlReply reply;
00736 QStringList confValue;
00737 QString confKey;
00738
00739
00740 foreach (QString key, map.keys()) {
00741 cmd.addArgument(key);
00742 }
00743
00744
00745 if (send(cmd, reply, errmsg)) {
00746
00747 foreach (ReplyLine line, reply.getLines()) {
00748
00749 QStringList keyval = line.getMessage().split("=");
00750 if (keyval.size() == 2) {
00751 confKey = keyval.at(0);
00752
00753 if (map.contains(confKey)) {
00754
00755
00756 confValue = map.value(confKey);
00757 }
00758 confValue << keyval.at(1);
00759 map.insert(keyval.at(0), confValue);
00760 }
00761 }
00762 return true;
00763 }
00764 return false;
00765 }
00766
00767
00768 bool
00769 TorControl::getConf(QString key, QString &value, QString *errmsg)
00770 {
00771 QStringList confValues;
00772 if (getConf(key, confValues, errmsg)) {
00773 value = confValues.join("\n");
00774 return true;
00775 }
00776 return false;
00777 }
00778
00779
00780 bool
00781 TorControl::getConf(QString key, QStringList &value, QString *errmsg)
00782 {
00783 QHash<QString,QStringList> map;
00784 map.insert(key, QStringList());
00785
00786 if (getConf(map, errmsg)) {
00787 value = map.value(key);
00788 return true;
00789 }
00790 return false;
00791 }
00792
00793
00794
00795
00796 QVariantMap
00797 TorControl::getConf(const QStringList &keys, QString *errmsg)
00798 {
00799 ControlCommand cmd("GETCONF");
00800 ControlReply reply;
00801 QVariantMap confMap;
00802
00803 cmd.addArguments(keys);
00804 if (!send(cmd, reply, errmsg))
00805 return QVariantMap();
00806
00807 foreach (ReplyLine line, reply.getLines()) {
00808 QString msg = line.getMessage();
00809 int index = msg.indexOf("=");
00810 QString key = msg.mid(0, index);
00811 QString val;
00812
00813 if (index > 0 && index < msg.length()-1)
00814 val = msg.mid(index+1);
00815
00816 if (confMap.contains(key)) {
00817 QStringList values = confMap.value(key).toStringList();
00818 values << val;
00819 confMap.insert(key, values);
00820 } else {
00821 confMap.insert(key, val);
00822 }
00823 }
00824 return confMap;
00825 }
00826
00827
00828
00829
00830 QVariant
00831 TorControl::getConf(const QString &key, QString *errmsg)
00832 {
00833 QVariantMap map = getConf(QStringList() << key, errmsg);
00834 return map.value(key);
00835 }
00836
00837
00838
00839 QString
00840 TorControl::getHiddenServiceConf(const QString &key, QString *errmsg)
00841 {
00842 ControlCommand cmd("GETCONF");
00843 ControlReply reply;
00844 QVariantMap confMap;
00845
00846 cmd.addArgument(key);
00847 if (!send(cmd, reply, errmsg))
00848 return "";
00849
00850 return reply.toString();
00851 }
00852
00853
00854 bool
00855 TorControl::saveConf(QString *errmsg)
00856 {
00857 ControlCommand cmd("SAVECONF");
00858 return send(cmd, errmsg);
00859 }
00860
00861
00862 bool
00863 TorControl::resetConf(QStringList keys, QString *errmsg)
00864 {
00865 ControlCommand cmd("RESETCONF");
00866
00867
00868 foreach (QString key, keys) {
00869 cmd.addArgument(key);
00870 }
00871 return send(cmd, errmsg);
00872 }
00873
00874
00875
00876 bool
00877 TorControl::resetConf(QString key, QString *errmsg)
00878 {
00879 return resetConf(QStringList() << key, errmsg);
00880 }
00881
00882
00883
00884
00885 RouterDescriptor
00886 TorControl::getRouterDescriptor(const QString &id, QString *errmsg)
00887 {
00888 QStringList descriptor = getInfo("desc/id/" + id, errmsg).toStringList();
00889 return RouterDescriptor(descriptor);
00890 }
00891
00892
00893
00894
00895 RouterStatus
00896 TorControl::getRouterStatus(const QString &id, QString *errmsg)
00897 {
00898 QStringList status = getInfo("ns/id/" + id, errmsg).toStringList();
00899 return RouterStatus(status);
00900 }
00901
00902
00903
00904
00905 NetworkStatus
00906 TorControl::getNetworkStatus(QString *errmsg)
00907 {
00908 QStringList networkStatusLines = getInfo("ns/all", errmsg).toStringList();
00909 QList<RouterStatus> networkStatus;
00910 int len = networkStatusLines.size();
00911 int i = 0;
00912
00913 while (i < len) {
00914
00915 QStringList routerStatusLines;
00916 do {
00917 routerStatusLines << networkStatusLines.at(i);
00918 } while (++i < len && ! networkStatusLines.at(i).startsWith("r "));
00919
00920
00921
00922 RouterStatus routerStatus(routerStatusLines);
00923 if (routerStatus.isValid())
00924 networkStatus << routerStatus;
00925 }
00926 return networkStatus;
00927 }
00928
00929
00930
00931
00932
00933 DescriptorAnnotations
00934 TorControl::getDescriptorAnnotations(const QString &id, QString *errmsg)
00935 {
00936 QStringList lines = getInfo("desc-annotations/id/"+id, errmsg).toStringList();
00937 DescriptorAnnotations annotations;
00938 QString key, value;
00939
00940 foreach (QString line, lines) {
00941 int idx = line.indexOf(" ");
00942
00943
00944 key = line.mid(0, idx);
00945 if (key.startsWith("@"))
00946 key = key.remove(0, 1);
00947
00948
00949 if (idx > 0 && idx < line.length()-1)
00950 annotations.insert(key, line.mid(idx + 1).trimmed());
00951 else
00952 annotations.insert(key, QString());
00953 }
00954 return annotations;
00955 }
00956
00957
00958 QList<Circuit>
00959 TorControl::getCircuits(QString *errmsg)
00960 {
00961 ControlCommand cmd("GETINFO", "circuit-status");
00962 ControlReply reply;
00963 CircuitList circuits;
00964
00965 if (!send(cmd, reply, errmsg))
00966 return CircuitList();
00967
00968
00969 foreach(QString line, reply.getData()) {
00970 Circuit circ(line);
00971 if (circ.isValid())
00972 circuits << circ;
00973 }
00974 return circuits;
00975 }
00976
00977
00978
00979 bool
00980 TorControl::closeCircuit(const CircuitId &circId, bool ifUnused, QString *errmsg)
00981 {
00982 ControlCommand cmd("CLOSECIRCUIT", circId);
00983 if (ifUnused) {
00984 cmd.addArgument("IfUnused");
00985 }
00986 return send(cmd, errmsg);
00987 }
00988
00989
00990 QList<Stream>
00991 TorControl::getStreams(QString *errmsg)
00992 {
00993 ControlCommand cmd("GETINFO", "stream-status");
00994 ControlReply reply;
00995 QList<Stream> streams;
00996 Stream s;
00997
00998 if (send(cmd, reply, errmsg)) {
00999
01000 QString msg = reply.getMessage();
01001 s = Stream::fromString(msg.mid(msg.indexOf("=")+1));
01002 if (s.isValid())
01003 streams << s;
01004
01005
01006 foreach (QString line, reply.getData()) {
01007 s = Stream::fromString(line);
01008 if (s.isValid())
01009 streams << s;
01010 }
01011 }
01012 return streams;
01013 }
01014
01015
01016 bool
01017 TorControl::closeStream(const StreamId &streamId, QString *errmsg)
01018 {
01019 ControlCommand cmd("CLOSESTREAM", streamId);
01020 cmd.addArgument("1");
01021 return send(cmd, errmsg);
01022 }
01023
01024
01025
01026 AddressMap
01027 TorControl::getAddressMap(AddressMap::AddressMapType type, QString *errmsg)
01028 {
01029 ControlCommand cmd("GETINFO");
01030 ControlReply reply;
01031 AddressMap addressMap;
01032
01033 switch (type) {
01034 case AddressMap::AddressMapConfig:
01035 cmd.addArgument("addr-mappings/config");
01036 break;
01037 case AddressMap::AddressMapCache:
01038 cmd.addArgument("addr-mappings/cache");
01039 break;
01040 case AddressMap::AddressMapControl:
01041 cmd.addArgument("addr-mappings/control");
01042 break;
01043 default:
01044 cmd.addArgument("addr-mappings/all");
01045 }
01046
01047 if (send(cmd, reply, errmsg)) {
01048 foreach (QString mapping, reply.getData()) {
01049 addressMap.add(mapping);
01050 }
01051 }
01052 return addressMap;
01053 }
01054