[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [vidalia/alpha] Add the torrc parser and the torrc abstraction class
commit 15cf1838fcaa1456d9e69f2fa8fc2364133547de
Author: Tomás Touceda <chiiph@xxxxxxxxxxxxxx>
Date: Fri Feb 3 17:30:10 2012 -0300
Add the torrc parser and the torrc abstraction class
---
src/vidalia/CMakeLists.txt | 3 +
src/vidalia/config/torrc/Torrc.cpp | 247 +++++++++++++++++
src/vidalia/config/torrc/Torrc.h | 75 ++++++
src/vidalia/config/torrc/TorrcParser.cpp | 428 ++++++++++++++++++++++++++++++
src/vidalia/config/torrc/TorrcParser.h | 189 +++++++++++++
5 files changed, 942 insertions(+), 0 deletions(-)
diff --git a/src/vidalia/CMakeLists.txt b/src/vidalia/CMakeLists.txt
index 3277bf0..5b4d2a2 100644
--- a/src/vidalia/CMakeLists.txt
+++ b/src/vidalia/CMakeLists.txt
@@ -17,6 +17,7 @@ include_directories(
${CMAKE_CURRENT_SOURCE_DIR}/about
${CMAKE_CURRENT_SOURCE_DIR}/bwgraph
${CMAKE_CURRENT_SOURCE_DIR}/config
+ ${CMAKE_CURRENT_SOURCE_DIR}/config/torrc
${CMAKE_CURRENT_SOURCE_DIR}/help/browser
${CMAKE_CURRENT_SOURCE_DIR}/log
${CMAKE_CURRENT_SOURCE_DIR}/network
@@ -126,6 +127,8 @@ set(vidalia_SRCS ${vidalia_SRCS}
config/TorSettings.cpp
config/VidaliaSettings.cpp
config/VSettings.cpp
+ config/torrc/TorrcParser.cpp
+ config/torrc/Torrc.cpp
)
qt4_wrap_cpp(vidalia_SRCS
config/AbstractTorSettings.h
diff --git a/src/vidalia/config/torrc/Torrc.cpp b/src/vidalia/config/torrc/Torrc.cpp
new file mode 100644
index 0000000..7d2ad6c
--- /dev/null
+++ b/src/vidalia/config/torrc/Torrc.cpp
@@ -0,0 +1,247 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+** including this file, may be copied, modified, propagated, or distributed
+** except according to the terms described in the LICENSE file.
+*/
+
+/*
+** \file Torrc.cpp
+** \brief Handles the interaction with the torrc file
+*/
+
+#include "Torrc.h"
+#include "Vidalia.h"
+
+#include <QtGlobal>
+
+Torrc::Torrc(const QString &torrcPath, const QString &defaultsPath) :
+ _torrcPath(torrcPath), changed(false)
+{
+ load(torrcPath, defaultsPath);
+}
+
+void
+Torrc::load(const QString &torrcPath, const QString &defaultsPath)
+{
+ _lines = _parser.parse(torrcPath, _torrcMap);
+
+ if(not defaultsPath.isEmpty())
+ _parser.parse(defaultsPath, _defaultsMap);
+}
+
+bool
+Torrc::apply(TorControl *tc, QString *errmsg)
+{
+ if(not changed)
+ return true;
+
+ QFile torrc(_torrcPath);
+ QFileInfo torrc_info(torrc);
+
+ if(!torrc.open(QIODevice::WriteOnly)) {
+ *errmsg = "Couldn't open torrc file";
+ return false;
+ }
+
+ QString torrc_contents = "";
+ QString current_line;
+
+ foreach(TorrcLine *line, _lines) {
+ torrc_contents += QString("%1 %2")
+ .arg(line->content())
+ .arg(line->comment()).trimmed();
+ torrc_contents += "\n";
+ }
+
+ if(torrc_info.isWritable())
+ torrc.write(torrc_contents.trimmed().toLatin1());
+ torrc.close();
+
+ clearAll();
+ load(_torrcPath);
+
+ changed = false;
+
+ bool ret = true;
+ if(tc && tc->isConnected()) {
+ if(!tc->loadConf(torrc_contents, errmsg)) {
+ vWarn(QObject::tr("There were some settings that Vidalia "
+ "wasn't able to apply together"));
+ vWarn("Trying to apply them one at a time...");
+ QPair<QString, TorOpt> value;
+ QString ferrmsg;
+ ControlReply reply;
+ bool somefailed = false;
+ foreach(QString key, _torrcMap.keys()) {
+ foreach(value, _torrcMap.values(key)) {
+ if(not tc->setConf(key, value.first, &ferrmsg, &reply)) {
+ if(reply.getStatus() == "553") {
+ vWarn(QObject::tr("Failed to set %1:\nReason: %2")
+ .arg(key).arg(ferrmsg));
+ somefailed = true;
+ } else {
+ *errmsg = ferrmsg;
+ return false;
+ }
+ }
+ }
+ }
+ if(somefailed) {
+ if(torrc_info.isWritable())
+ vWarn(QObject::tr("The failed options were saved in your torrc "
+ "and will be applied when you restart."));
+ else
+ vWarn(QObject::tr("The failed options were NOT saved in your torrc "
+ "and will be applied when you restart."));
+ }
+ if(not torrc_info.isWritable())
+ vWarn(QObject::tr("Vidalia was unable to save the options to the torrc file."));
+ }
+ }
+ return true;
+}
+
+QStringList
+Torrc::value(const QString &key) const
+{
+ QStringList ret;
+ QPair<QString,TorOpt> value;
+ if(_torrcMap.contains(key)) {
+ foreach(value, _torrcMap.values(key))
+ ret << value.first;
+ return ret;
+ }
+
+ if(_defaultsMap.contains(key)) {
+ foreach(value, _defaultsMap.values(key))
+ ret << value.first;
+ return ret;
+ }
+
+ return ret;
+}
+
+void
+Torrc::setValue(const QString &key, const QString &value, const QString &comment)
+{
+ // Prevent possible bugs
+ if(not key.isEmpty() and value.isEmpty())
+ return;
+
+ if(_defaultsMap.contains(key)) {
+ QPair<QString,TorOpt> defvalue;
+ foreach(defvalue, _defaultsMap.values(key)) {
+ if(defvalue.first == value)
+ return;
+ }
+ }
+
+ if(_torrcMap.contains(key)) {
+ QPair<QString,TorOpt> val;
+ foreach(val, _torrcMap.values(key)) {
+ if(not val.second.isMultilined() and val.first != value) {
+ val.second.line()->setContent(QString("%1 %2")
+ .arg(key)
+ .arg(value));
+ if(not comment.isEmpty() and val.second.line()->comment().isEmpty())
+ val.second.line()->setComment(comment);
+ changed = true;
+ return;
+ } else if(not val.second.isMultilined() and val.first == value) {
+ // if it's the same, leave it like that
+ return;
+ } // else it's multilined, in which case we just add a new entry
+ }
+ }
+
+ changed = true;
+
+ TorOpt opt(_parser.getTorOpt(key));
+ TorrcLine *line = new TorrcLine(QString("%1 %2")
+ .arg(key)
+ .arg(value).trimmed(),
+ comment.trimmed());
+
+ if(key.isEmpty()) {
+ _lines << line;
+ return;
+ }
+
+ if(opt.isMultivalued()) {
+ bool found = false;
+ QPair<QString,TorOpt> val;
+ foreach(val, _torrcMap.values(key)) {
+ if(val.first == value) {
+ found = true;
+ break;
+ }
+ }
+
+ opt.setLine(line);
+
+ if(!found)
+ _torrcMap.insertMulti(key, QPair<QString,TorOpt>(value, opt));
+ else
+ return;
+ } else
+ _torrcMap.insert(key, QPair<QString,TorOpt>(value, opt));
+
+ _lines << line;
+}
+
+void
+Torrc::clear(QStringList &keys)
+{
+ QPair<QString, TorOpt> value;
+ foreach(const QString key, keys) {
+ foreach(value, _torrcMap.values(key)) {
+ if(value.second.line()) {
+ value.second.line()->setContent("");
+ if(value.second.line()->comment().isEmpty())
+ _lines.removeAll(value.second.line());
+ }
+ }
+ _torrcMap.remove(key);
+ }
+}
+
+bool
+Torrc::isValid(const QString &key, const QString &value)
+{
+ if(not _parser.getTorOpt(key).isNull())
+ return true;
+ // TODO: check value
+ return false;
+}
+
+void
+Torrc::clearAll()
+{
+ _torrcMap.clear();
+ _lines.clear();
+}
+
+bool
+Torrc::setRawContents(const QString &contents, QString *errmsg, TorControl *tc)
+{
+ clearAll();
+
+ QFile torrc(_torrcPath);
+ if(!torrc.open(QIODevice::WriteOnly)) {
+ *errmsg = "Couldn't open torrc file";
+ return false;
+ }
+
+ torrc.write(contents.trimmed().toLatin1());
+ torrc.close();
+
+ load(_torrcPath);
+
+ if(tc && tc->isConnected())
+ return tc->signal(TorSignal::Reload, errmsg);
+ return true;
+}
diff --git a/src/vidalia/config/torrc/Torrc.h b/src/vidalia/config/torrc/Torrc.h
new file mode 100644
index 0000000..6ab7d08
--- /dev/null
+++ b/src/vidalia/config/torrc/Torrc.h
@@ -0,0 +1,75 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+** including this file, may be copied, modified, propagated, or distributed
+** except according to the terms described in the LICENSE file.
+*/
+
+/*
+** \file Torrc.h
+** \brief Handles the interaction with the torrc file
+*/
+
+#ifndef TORRC_H
+#define TORRC_H
+
+#include <QtCore>
+
+#include "TorControl.h"
+#include "TorrcParser.h"
+
+class Torrc {
+ public:
+ /** Constructor */
+ Torrc(const QString &torrcPath, const QString &defaultsPath = "");
+
+ /** Loads the torrc from the path provided and its defaults if provided */
+ void load(const QString &torrcPath, const QString &defaultsPath = "");
+
+ /** Applies the changes in configuration to the torrc file */
+ bool apply(TorControl *tc = 0, QString *errmsg = 0);
+ /** Clears the keys provided in the list */
+ void clear(QStringList &keys);
+ /** Clears the _torrcMap and _lines values */
+ void clearAll();
+
+ /** Returns a list of values associated with the given key */
+ QStringList value(const QString &key) const;
+ /** Sets the value to the given key with a optional
+ * comment that will appear in the file */
+ void setValue(const QString &key, const QString &value, const QString &comment = "");
+
+ /** Returns the used torrc path */
+ QString getTorrcPath() const
+ { return _torrcPath; }
+
+ /** Returns true if the key=value is a valid config option */
+ bool isValid(const QString &key, const QString &value);
+
+ /** Resets the config values as if the torrc file contained the
+ * string in contents, and applies it. */
+ bool setRawContents(const QString &contents, QString *errmsg, TorControl *tc = 0);
+
+ private:
+ /** Map that contains the key=value config options and a
+ representation to the actual line in the torrc file */
+ QMap<QString, QPair<QString,TorOpt> > _torrcMap;
+ /** Map that contains the key=value config options and a
+ representation to the actual line in the defaults torrc file */
+ QMap<QString, QPair<QString,TorOpt> > _defaultsMap;
+ /** List of torrc lines */
+ QList<TorrcLine *> _lines;
+ /** Parser used to analyze the torrc and defaults files */
+ TorrcParser _parser;
+
+ /** Path to the used torrc file */
+ QString _torrcPath;
+
+ /** True if the config options have been changed */
+ bool changed;
+};
+
+#endif
diff --git a/src/vidalia/config/torrc/TorrcParser.cpp b/src/vidalia/config/torrc/TorrcParser.cpp
new file mode 100644
index 0000000..ed21e8e
--- /dev/null
+++ b/src/vidalia/config/torrc/TorrcParser.cpp
@@ -0,0 +1,428 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+** including this file, may be copied, modified, propagated, or distributed
+** except according to the terms described in the LICENSE file.
+*/
+
+/*
+** \file TorrcParser.cpp
+** \brief Parser for the torrc file and other data representations for the file
+*/
+
+#include "TorrcParser.h"
+#include "Vidalia.h"
+
+TorrcParser::TorrcParser()
+{
+ _torOpts << TorOpt("AccountingMax", TorOpt::DataSize, "0 bytes");
+ _torOpts << TorOpt("AccountingStart", TorOpt::String, "");
+ _torOpts << TorOpt("Address", TorOpt::String, "");
+ _torOpts << TorOpt("AllowDotExit", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AllowInvalidNodes", TorOpt::CommaList, "middle,rendezvous");
+ _torOpts << TorOpt("AllowNonRFC953Hostnames", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AllowSingleHopCircuits", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AllowSingleHopExits", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AlternateBridgeAuthority", TorOpt::LineList, "");
+ _torOpts << TorOpt("AlternateDirAuthority", TorOpt::LineList, "");
+ _torOpts << TorOpt("AlternateHSAuthority", TorOpt::LineList, "");
+ _torOpts << TorOpt("AssumeReachable", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AuthDirBadDir", TorOpt::LineList, "");
+ _torOpts << TorOpt("AuthDirBadExit", TorOpt::LineList, "");
+ _torOpts << TorOpt("AuthDirInvalid", TorOpt::LineList, "");
+ _torOpts << TorOpt("AuthDirReject", TorOpt::LineList, "");
+ _torOpts << TorOpt("AuthDirRejectUnlisted", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AuthDirListBadDirs", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AuthDirListBadExits", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AuthDirMaxServersPerAddr", TorOpt::Integer, "2");
+ _torOpts << TorOpt("AuthDirMaxServersPerAuthAddr", TorOpt::Integer, "5");
+ _torOpts << TorOpt("AuthoritativeDirectory", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AutomapHostsOnResolve", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("AutomapHostsSuffixes", TorOpt::CommaList, ".onion,.exit");
+ _torOpts << TorOpt("AvoidDiskWrites", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("BandwidthBurst", TorOpt::DataSize, "10 MB");
+ _torOpts << TorOpt("BandwidthRate", TorOpt::DataSize, "5 MB");
+ _torOpts << TorOpt("BridgeAuthoritativeDir", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("Bridge", TorOpt::LineList, "");
+ _torOpts << TorOpt("BridgePassword", TorOpt::String, "");
+ _torOpts << TorOpt("BridgeRecordUsageByCountry", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("BridgeRelay", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("CellStatistics", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("LearnCircuitBuildTimeout", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("CircuitBuildTimeout", TorOpt::TimeInterval, "0");
+ _torOpts << TorOpt("CircuitIdleTimeout", TorOpt::TimeInterval, "1 hour");
+ _torOpts << TorOpt("CircuitStreamTimeout", TorOpt::TimeInterval, "0");
+ _torOpts << TorOpt("CircuitPriorityHalflife", TorOpt::Float, "-100.0");
+ _torOpts << TorOpt("ClientDNSRejectInternalAddresses", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ClientOnly", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ClientRejectInternalAddresses", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ClientTransportPlugin", TorOpt::LineList, "");
+ _torOpts << TorOpt("ConsensusParams", TorOpt::String, "");
+ _torOpts << TorOpt("ConnLimit", TorOpt::Integer, "1000");
+ _torOpts << TorOpt("ConnDirectionStatistics", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ConstrainedSockets", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ConstrainedSockSize", TorOpt::DataSize, "8192");
+ _torOpts << TorOpt("ContactInfo", TorOpt::String, "");
+ _torOpts << TorOpt("ControlListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("ControlPort", TorOpt::Port, "0");
+ _torOpts << TorOpt("ControlPortFileGroupReadable", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ControlPortWriteToFile", TorOpt::Filename, "");
+ _torOpts << TorOpt("ControlSocket", TorOpt::LineList, "");
+ _torOpts << TorOpt("ControlSocketsGroupWritable", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("CookieAuthentication", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("CookieAuthFileGroupReadable", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("CookieAuthFile", TorOpt::String, "");
+ _torOpts << TorOpt("CountPrivateBandwidth", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("DataDirectory", TorOpt::Filename, "");
+ _torOpts << TorOpt("DirAllowPrivateAddresses", TorOpt::Boolean, "");
+ _torOpts << TorOpt("TestingAuthDirTimeToLearnReachability", TorOpt::TimeInterval, "30 minutes");
+ _torOpts << TorOpt("DirListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("DirPolicy", TorOpt::LineList, "");
+ _torOpts << TorOpt("DirPort", TorOpt::Port, "0");
+ _torOpts << TorOpt("DirPortFrontPage", TorOpt::Filename, "");
+ _torOpts << TorOpt("DirReqStatistics", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("DirServer", TorOpt::LineList, "");
+ _torOpts << TorOpt("DisableAllSwap", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("DisableIOCP", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("DNSPort", TorOpt::LineList, "");
+ _torOpts << TorOpt("DNSListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("DownloadExtraInfo", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("EnforceDistinctSubnets", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("EntryNodes", TorOpt::RouterList, "");
+ _torOpts << TorOpt("EntryStatistics", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("TestingEstimatedDescriptorPropagationTime", TorOpt::TimeInterval, "10 minutes");
+ _torOpts << TorOpt("ExcludeNodes", TorOpt::RouterList, "");
+ _torOpts << TorOpt("ExcludeExitNodes", TorOpt::RouterList, "");
+ _torOpts << TorOpt("ExcludeSingleHopRelays", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ExitNodes", TorOpt::RouterList, "");
+ _torOpts << TorOpt("ExitPolicy", TorOpt::LineList, "");
+ _torOpts << TorOpt("ExitPolicyRejectPrivate", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ExitPortStatistics", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ExtraInfoStatistics", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("FallbackNetworkstatusFile", TorOpt::Filename, "/usr/local/share/tor/fallback-consensus");
+ _torOpts << TorOpt("FascistFirewall", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("FirewallPorts", TorOpt::CommaList, "");
+ _torOpts << TorOpt("FastFirstHopPK", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("FetchDirInfoEarly", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("FetchDirInfoExtraEarly", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("FetchServerDescriptors", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("FetchHidServDescriptors", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("FetchUselessDescriptors", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("FetchV2Networkstatus", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("GeoIPFile", TorOpt::Filename, "/usr/local/share/tor/geoip");
+ _torOpts << TorOpt("GiveGuardFlagTo_CVE_2011_2768_VulnerableRelays", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("HardwareAccel", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("HeartbeatPeriod", TorOpt::TimeInterval, "6 hours");
+ _torOpts << TorOpt("AccelName", TorOpt::String, "");
+ _torOpts << TorOpt("AccelDir", TorOpt::Filename, "");
+ // HashedControlPassword will only use one value, the salt prevents
+ // treat it like the rest of the LineLists
+ _torOpts << TorOpt("HashedControlPassword", TorOpt::String, "");
+ _torOpts << TorOpt("HidServDirectoryV2", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("HiddenServiceDir", TorOpt::Dependant, "");
+ _torOpts << TorOpt("HiddenServiceOptions", TorOpt::Virtual, "");
+ _torOpts << TorOpt("HiddenServicePort", TorOpt::Dependant, "");
+ _torOpts << TorOpt("HiddenServiceVersion", TorOpt::Dependant, "");
+ _torOpts << TorOpt("HiddenServiceAuthorizeClient", TorOpt::Dependant, "");
+ _torOpts << TorOpt("HidServAuth", TorOpt::LineList, "");
+ _torOpts << TorOpt("HSAuthoritativeDir", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("HTTPProxy", TorOpt::String, "");
+ _torOpts << TorOpt("HTTPProxyAuthenticator", TorOpt::String, "");
+ _torOpts << TorOpt("HTTPSProxy", TorOpt::String, "");
+ _torOpts << TorOpt("HTTPSProxyAuthenticator", TorOpt::String, "");
+ _torOpts << TorOpt("ServerTransportPlugin", TorOpt::LineList, "");
+ _torOpts << TorOpt("Socks4Proxy", TorOpt::String, "");
+ _torOpts << TorOpt("Socks5Proxy", TorOpt::String, "");
+ _torOpts << TorOpt("Socks5ProxyUsername", TorOpt::String, "");
+ _torOpts << TorOpt("Socks5ProxyPassword", TorOpt::String, "");
+ _torOpts << TorOpt("KeepalivePeriod", TorOpt::TimeInterval, "5 minutes");
+ _torOpts << TorOpt("Log", TorOpt::LineList, "");
+ _torOpts << TorOpt("LogMessageDomains", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("LogTimeGranularity", TorOpt::TimeMsecInterval, "1 second");
+ _torOpts << TorOpt("LongLivedPorts", TorOpt::CommaList, "21,22,706,1863,5050,5190,5222,5223,6523,6667,6697,8300");
+ _torOpts << TorOpt("MapAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("MaxAdvertisedBandwidth", TorOpt::DataSize, "1 GB");
+ _torOpts << TorOpt("MaxCircuitDirtiness", TorOpt::TimeInterval, "10 minutes");
+ _torOpts << TorOpt("MaxClientCircuitsPending", TorOpt::Integer, "32");
+ _torOpts << TorOpt("MaxOnionsPending", TorOpt::Integer, "100");
+ _torOpts << TorOpt("MyFamily", TorOpt::String, "");
+ _torOpts << TorOpt("NewCircuitPeriod", TorOpt::TimeInterval, "30 seconds");
+ _torOpts << TorOpt("NamingAuthoritativeDirectory", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("NATDListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("NATDPort", TorOpt::LineList, "");
+ _torOpts << TorOpt("Nickname", TorOpt::String, "");
+ _torOpts << TorOpt("WarnUnsafeSocks", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("NodeFamily", TorOpt::LineList, "");
+ _torOpts << TorOpt("NumCPUs", TorOpt::Integer, "0");
+ _torOpts << TorOpt("NumEntryGuards", TorOpt::Integer, "3");
+ _torOpts << TorOpt("ORListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("ORPort", TorOpt::Port, "0");
+ _torOpts << TorOpt("OutboundBindAddress", TorOpt::String, "");
+ _torOpts << TorOpt("PerConnBWBurst", TorOpt::DataSize, "0");
+ _torOpts << TorOpt("PerConnBWRate", TorOpt::DataSize, "0");
+ _torOpts << TorOpt("PidFile", TorOpt::String, "");
+ _torOpts << TorOpt("TestingTorNetwork", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("OptimisticData", TorOpt::BooleanAuto, "auto");
+ _torOpts << TorOpt("PortForwarding", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("PortForwardingHelper", TorOpt::Filename, "tor-fw-helper");
+ _torOpts << TorOpt("PreferTunneledDirConns", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ProtocolWarnings", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("PublishServerDescriptor", TorOpt::CommaList, "1");
+ _torOpts << TorOpt("PublishHidServDescriptors", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ReachableAddresses", TorOpt::LineList, "");
+ _torOpts << TorOpt("ReachableDirAddresses", TorOpt::LineList, "");
+ _torOpts << TorOpt("ReachableORAddresses", TorOpt::LineList, "");
+ _torOpts << TorOpt("RecommendedVersions", TorOpt::LineList, "");
+ _torOpts << TorOpt("RecommendedClientVersions", TorOpt::LineList, "");
+ _torOpts << TorOpt("RecommendedServerVersions", TorOpt::LineList, "");
+ _torOpts << TorOpt("RefuseUnknownExits", TorOpt::BooleanAuto, "auto");
+ _torOpts << TorOpt("RejectPlaintextPorts", TorOpt::CommaList, "");
+ _torOpts << TorOpt("RelayBandwidthBurst", TorOpt::DataSize, "0");
+ _torOpts << TorOpt("RelayBandwidthRate", TorOpt::DataSize, "0");
+ _torOpts << TorOpt("RendPostPeriod", TorOpt::TimeInterval, "1 hour");
+ _torOpts << TorOpt("RephistTrackTime", TorOpt::TimeInterval, "24 hours");
+ _torOpts << TorOpt("RunAsDaemon", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("SafeLogging", TorOpt::String, "1");
+ _torOpts << TorOpt("SafeSocks", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ServerDNSAllowBrokenConfig", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ServerDNSAllowNonRFC953Hostnames", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ServerDNSDetectHijacking", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ServerDNSRandomizeCase", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("ServerDNSResolvConfFile", TorOpt::String, "");
+ _torOpts << TorOpt("ServerDNSSearchDomains", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("ServerDNSTestAddresses", TorOpt::CommaList, "www.google.com,www.mit.edu,www.yahoo.com,www.slashdot.org");
+ _torOpts << TorOpt("ShutdownWaitLength", TorOpt::TimeInterval, "30 seconds");
+ _torOpts << TorOpt("SocksListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("SocksPolicy", TorOpt::LineList, "");
+ _torOpts << TorOpt("SocksPort", TorOpt::LineList, "");
+ _torOpts << TorOpt("SocksTimeout", TorOpt::TimeInterval, "2 minutes");
+ _torOpts << TorOpt("StrictNodes", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("TestSocks", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("TokenBucketRefillInterval", TorOpt::TimeMsecInterval, "100 msec");
+ _torOpts << TorOpt("TrackHostExits", TorOpt::CommaList, "");
+ _torOpts << TorOpt("TrackHostExitsExpire", TorOpt::TimeInterval, "30 minutes");
+ _torOpts << TorOpt("TransListenAddress", TorOpt::LineList, "");
+ _torOpts << TorOpt("TransPort", TorOpt::LineList, "");
+ _torOpts << TorOpt("TunnelDirConns", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("UpdateBridgesFromAuthority", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("UseBridges", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("UseEntryGuards", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("UseMicrodescriptors", TorOpt::BooleanAuto, "auto");
+ _torOpts << TorOpt("User", TorOpt::String, "");
+ _torOpts << TorOpt("V1AuthoritativeDirectory", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("V2AuthoritativeDirectory", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("V3AuthoritativeDirectory", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("TestingV3AuthInitialVotingInterval", TorOpt::TimeInterval, "30 minutes");
+ _torOpts << TorOpt("TestingV3AuthInitialVoteDelay", TorOpt::TimeInterval, "5 minutes");
+ _torOpts << TorOpt("TestingV3AuthInitialDistDelay", TorOpt::TimeInterval, "5 minutes");
+ _torOpts << TorOpt("V3AuthVotingInterval", TorOpt::TimeInterval, "1 hour");
+ _torOpts << TorOpt("V3AuthVoteDelay", TorOpt::TimeInterval, "5 minutes");
+ _torOpts << TorOpt("V3AuthDistDelay", TorOpt::TimeInterval, "5 minutes");
+ _torOpts << TorOpt("V3AuthNIntervalsValid", TorOpt::Integer, "3");
+ _torOpts << TorOpt("V3AuthUseLegacyKey", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("V3BandwidthsFile", TorOpt::Filename, "");
+ _torOpts << TorOpt("VersioningAuthoritativeDirectory", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("VirtualAddrNetwork", TorOpt::String, "127.192.0.0/10");
+ _torOpts << TorOpt("WarnPlaintextPorts", TorOpt::CommaList, "23,109,110,143");
+ _torOpts << TorOpt("_UseFilteringSSLBufferevents", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("__ReloadTorrcOnSIGHUP", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("__AllDirActionsPrivate", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("__DisablePredictedCircuits", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("__LeaveStreamsUnattached", TorOpt::Boolean, "0");
+ _torOpts << TorOpt("__HashedControlSessionPassword", TorOpt::LineList, "");
+ _torOpts << TorOpt("__OwningControllerProcess", TorOpt::String, "");
+ _torOpts << TorOpt("MinUptimeHidServDirectoryV2", TorOpt::TimeInterval, "25 hours");
+ _torOpts << TorOpt("VoteOnHidServDirectoriesV2", TorOpt::Boolean, "1");
+ _torOpts << TorOpt("_UsingTestNetworkDefaults", TorOpt::Boolean, "0");
+
+ _regexp = createRegExp();
+}
+
+QRegExp
+TorrcParser::createRegExp()
+{
+ QString reg = "";
+ foreach(TorOpt opt, _torOpts) {
+ reg += opt.name();
+ reg += "|";
+ }
+ reg = reg.remove(reg.size() - 1, 1);
+
+ return QRegExp(reg, Qt::CaseInsensitive);
+}
+
+TorOpt
+TorrcParser::getTorOpt(const QString &name)
+{
+ foreach(const TorOpt &opt, _torOpts) {
+ if(opt.name() == name)
+ return opt;
+ }
+
+ return TorOpt::null();
+}
+
+QList<TorrcLine *>
+TorrcParser::parse(const QString &path,
+ QMap<QString, QPair<QString, TorOpt> > &map)
+{
+ QFile torrc(path);
+ QFileInfo torrc_info;
+ QList<TorrcLine *> lines;
+ torrc_info.setFile(torrc);
+
+ if(not torrc_info.isReadable()) {
+ vWarn("Can't read torrc file, aborting parsing.");
+ return lines;
+ }
+
+ if(not torrc.open(QIODevice::ReadOnly)) {
+ vWarn("Can't open torrc file, aborting parsing.");
+ return lines;
+ }
+
+ QString raw_contents(torrc.readAll());
+ torrc.close();
+
+ lines = toTorrcLines(raw_contents);
+
+ QString key, value;
+ int sp_pos = -1;
+
+ foreach(TorrcLine *line, lines) {
+ sp_pos = line->content().indexOf(" ");
+ if(sp_pos == -1)
+ continue;
+
+ key = line->content().mid(0, sp_pos);
+ value = "";
+ if(line->isMultilined()) {
+ QList<TorrcLine *> valueLines = findValueLines(line, lines);
+ foreach(TorrcLine *valueLine, valueLines) {
+ if(valueLine->isMultilined()) {
+ value += valueLine->content().remove(valueLine->content().lastIndexOf("\\"), 1);
+ } else
+ // Last line, doesn't have \ at the end
+ value += valueLine->content();
+ // remove the contents, since they will live in the first line only
+ valueLine->setContent("");
+ }
+ line->setContent(QString("%1 %2").arg(key).arg(value));
+ } else {
+ value = line->content().mid(sp_pos+1, line->content().size());
+ }
+
+ TorOpt opt(getTorOpt(key));
+ opt.setLine(line);
+ if(map.contains(key) and opt.isMultivalued())
+ map.insertMulti(key, QPair<QString, TorOpt>(value, opt));
+ else
+ map.insert(key, QPair<QString, TorOpt>(value, opt));
+ }
+
+ return lines;
+}
+
+QString
+TorrcParser::stripContents(QString contents)
+{
+ QString stripped_contents = "", current_line = "";
+ int comment_pos = -1;
+
+ foreach(QString line, contents.split("\n")) {
+ comment_pos = line.indexOf("#");
+ if(comment_pos == -1) {
+ stripped_contents += line.trimmed();
+ stripped_contents += "\n";
+ continue;
+ }
+
+ current_line = line.mid(0, comment_pos).trimmed();
+ if(current_line.size() == 0)
+ continue;
+ stripped_contents += current_line;
+ stripped_contents += "\n";
+ }
+
+ return stripped_contents.replace("\t", " ");
+}
+
+QList<TorrcLine *>
+TorrcParser::toTorrcLines(QString contents)
+{
+ QList<TorrcLine *> lines;
+ QString stripped_contents = "", current_line = "";
+ int comment_pos = -1;
+
+ foreach(QString line, contents.split("\n")) {
+ comment_pos = line.indexOf("#");
+ if(comment_pos == -1) {
+ lines << new TorrcLine(line.trimmed());
+ continue;
+ }
+
+ current_line = line.mid(0, comment_pos).trimmed().replace("\t", " ");
+ if(current_line.size() == 0) {
+ // The line is just a comment
+ lines << new TorrcLine("", line.trimmed());
+ continue;
+ }
+ lines << new TorrcLine(current_line, line.mid(comment_pos, line.size()).trimmed());
+ }
+
+ return lines;
+}
+
+QList<TorrcLine *>
+TorrcParser::findValueLines(TorrcLine *line,
+ const QList<TorrcLine *> &lines) const
+{
+ QList<TorrcLine *> collected;
+
+ int index = -1;
+ index = lines.indexOf(line) + 1;
+ if(index >= lines.size())
+ return collected;
+
+ for(int i = index; i<lines.size(); i++) {
+ if(lines.at(i)->isMultilined())
+ collected << lines.at(i);
+ else {
+ collected << lines.at(i);
+ break;
+ }
+ }
+
+ return collected;
+}
+
+bool
+TorrcParser::isKeyword(const QString &contents, int pos)
+{
+ while(contents.at(pos) != '\n') {
+ pos--;
+ if(pos < 0 or contents.at(pos) == '\n')
+ return true;
+ if(contents.at(pos) != ' ')
+ return false;
+ }
+ return true;
+}
+
+QDebug
+operator<<(QDebug dbg, const TorOpt &opt) {
+ dbg.nospace() << qPrintable(QString("TorOpt(%1)")
+ .arg(opt.name()));
+ return dbg;
+}
+
+QDebug
+operator<<(QDebug dbg, TorrcLine *line) {
+ dbg.nospace() << qPrintable(QString("TorLine(%1, %2)")
+ .arg(line->content())
+ .arg(line->comment()));
+ return dbg;
+}
diff --git a/src/vidalia/config/torrc/TorrcParser.h b/src/vidalia/config/torrc/TorrcParser.h
new file mode 100644
index 0000000..83572bb
--- /dev/null
+++ b/src/vidalia/config/torrc/TorrcParser.h
@@ -0,0 +1,189 @@
+/*
+** This file is part of Vidalia, and is subject to the license terms in the
+** LICENSE file, found in the top level directory of this distribution. If you
+** did not receive the LICENSE file with this file, you may obtain it from the
+** Vidalia source package distributed by the Vidalia Project at
+** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
+** including this file, may be copied, modified, propagated, or distributed
+** except according to the terms described in the LICENSE file.
+*/
+
+/*
+** \file TorrcParser.h
+** \brief Parser for the torrc file and other data representations for the file
+*/
+
+#ifndef TORRCPARSER_H
+#define TORRCPARSER_H
+
+#include <QtCore>
+
+/** Rpresents a line in the torrc file that respects the formatting
+ * the user gave it */
+class TorrcLine
+{
+ public:
+ /** Constructor */
+ TorrcLine(const QString &content = "", const QString &comment = "")
+ : _content(content), _comment(comment) {}
+
+ /** Returns the content for this line */
+ QString content()
+ { return _content; }
+ /** Sets the contents for this line */
+ void setContent(const QString &content)
+ { _content = content; }
+
+ /** Returns the comment for this line */
+ QString comment()
+ { return _comment; }
+ /** Sets the comment for this line */
+ void setComment(const QString &comment)
+ { _comment = comment; }
+
+ /** Returns true if the line's content is divided into other
+ * subsequent lines */
+ bool isMultilined()
+ {
+ int index = -1;
+ index = _content.lastIndexOf("\\") + 1;
+ if(index == -1)
+ return false;
+ for(int i = index; i<_content.size(); i++) {
+ if(_content.at(i) != ' ')
+ return false;
+ }
+ return true;
+ }
+
+ private:
+ /** Strings that hold the content and comment for the line */
+ QString _content, _comment;
+};
+
+/** Represents an possible option in the torrc file. This is used to
+ * handle the different type of values that may be associated with
+ * each option */
+class TorOpt
+{
+ public:
+ /** Possible value types */
+ enum OptType {
+ TimeInterval = 0,
+ TimeMsecInterval,
+ String,
+ RouterList,
+ LineList,
+ Float,
+ Dependant,
+ Virtual,
+ Filename,
+ CommaList,
+ Boolean,
+ BooleanAuto,
+ Integer,
+ DataSize,
+ Port,
+ NIL
+ };
+
+ /** Default constructor */
+ TorOpt()
+ { TorOpt("", NIL); }
+ /** Constructor */
+ TorOpt(const QString &name, OptType type, QString defaultValue = "")
+ : _name(name), _type(type), _default(defaultValue), _line(0) {}
+ /** Copy constructor */
+ TorOpt(const TorOpt &opt)
+ : _name(opt.name()), _type(opt.type()), _default(opt.defaultValue()), _line(opt.line()) {}
+
+ /** Returns true if this option can be defined with multiple lines */
+ bool isMultilined()
+ { return _type == LineList or _type == Dependant or _type == Virtual; }
+
+ /** Returns true if this option can be defined multiple times with
+ * different values */
+ bool isMultivalued()
+ { return _type == LineList; }
+
+ /** Returns the name for this option */
+ QString name() const
+ { return _name; }
+
+ /** Returns the type for this option*/
+ OptType type() const
+ { return _type; }
+
+ /** Returns the default value that tor assumes for this option */
+ QString defaultValue() const
+ { return _default; }
+
+ /** Returns a pointer to the TorrcLine for this option */
+ TorrcLine *line() const
+ { return _line; }
+
+ /** Sets the line for this option */
+ void setLine(TorrcLine *line)
+ { _line = line; }
+
+ /** Returns true if it's a null TorOpt */
+ bool isNull() const
+ { return _type == NIL; }
+
+ /** Creates a null TorOpt*/
+ static TorOpt null()
+ { return TorOpt("Nil", NIL); }
+
+ private:
+ /** Name for this option */
+ QString _name;
+ /** Type for this option */
+ OptType _type;
+ /** Default value for this option */
+ QString _default;
+ /** Pointer to the line that represents this option */
+ TorrcLine *_line;
+};
+
+/** Parser for the torrc file and any other torrc structured file */
+class TorrcParser
+{
+ public:
+ /** Default constructor */
+ TorrcParser();
+
+ /** Parses the torrc file provided in the path and returns the
+ * TorrcLine list for the file and the map of key=value */
+ QList<TorrcLine *> parse(const QString &path,
+ QMap<QString, QPair<QString, TorOpt> > &map);
+ /** Returns the TorOpt for a given option name */
+ TorOpt getTorOpt(const QString &name);
+
+ private:
+ /** List with all the current valid options for the torrc */
+ QList<TorOpt> _torOpts;
+ /** Regular expression used in the parsing based on _torOpts */
+ QRegExp _regexp;
+
+ /** Strips the torrc contents passed from comments an empty lines */
+ QString stripContents(QString contents);
+ /** Given the contents of a torrc file, it returns a list of
+ * TorrcLines representing it */
+ QList<TorrcLine *> toTorrcLines(QString contents);
+ /** Given a TorrcLine and the line list where it belongs, it returns
+ * the set of lines that define the multilined value */
+ QList<TorrcLine *> findValueLines(TorrcLine *line,
+ const QList<TorrcLine *> &lines) const;
+ /** Creates the regular expression used in parsing */
+ QRegExp createRegExp();
+ /** Returns true if there's a keyword in the contents at the given
+ * pos */
+ bool isKeyword(const QString &contents, int pos);
+};
+
+/** Debug output methods */
+QDebug operator<<(QDebug dbg, const TorOpt &opt);
+QDebug operator<<(QDebug dbg, TorrcLine *line);
+
+#endif
+
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits