[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[vidalia-svn] r2504: Initial patch from Domenik Bork to add an interface for sett (in vidalia/trunk/src: torcontrol vidalia vidalia/config vidalia/help/content vidalia/help/content/en vidalia/i18n vidalia/res vidalia/res/22x22)
Author: edmanm
Date: 2008-04-12 14:23:28 -0400 (Sat, 12 Apr 2008)
New Revision: 2504
Added:
vidalia/trunk/src/vidalia/config/service.cpp
vidalia/trunk/src/vidalia/config/service.h
vidalia/trunk/src/vidalia/config/servicelist.cpp
vidalia/trunk/src/vidalia/config/servicelist.h
vidalia/trunk/src/vidalia/config/servicepage.cpp
vidalia/trunk/src/vidalia/config/servicepage.h
vidalia/trunk/src/vidalia/config/servicepage.ui
vidalia/trunk/src/vidalia/config/servicesettings.cpp
vidalia/trunk/src/vidalia/config/servicesettings.h
vidalia/trunk/src/vidalia/help/content/en/services.html
vidalia/trunk/src/vidalia/res/22x22/folder.png
vidalia/trunk/src/vidalia/res/22x22/service.png
Modified:
vidalia/trunk/src/torcontrol/torcontrol.cpp
vidalia/trunk/src/torcontrol/torcontrol.h
vidalia/trunk/src/vidalia/CMakeLists.txt
vidalia/trunk/src/vidalia/config/configdialog.cpp
vidalia/trunk/src/vidalia/config/configdialog.h
vidalia/trunk/src/vidalia/help/content/content.qrc
vidalia/trunk/src/vidalia/help/content/en/config.html
vidalia/trunk/src/vidalia/help/content/en/contents.xml
vidalia/trunk/src/vidalia/i18n/vidalia_de.ts
vidalia/trunk/src/vidalia/i18n/vidalia_en.ts
vidalia/trunk/src/vidalia/res/vidalia_common.qrc
Log:
Initial patch from Domenik Bork to add an interface for setting up hidden
services. This patch just includes the backend code to handle getting and
setting the hidden service options and the new config page, but does not
modify existing code to display the new interface bits yet.
Modified: vidalia/trunk/src/torcontrol/torcontrol.cpp
===================================================================
--- vidalia/trunk/src/torcontrol/torcontrol.cpp 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/torcontrol/torcontrol.cpp 2008-04-12 18:23:28 UTC (rev 2504)
@@ -668,6 +668,15 @@
return setConf(map, errmsg);
}
+/** Sets a single configuration string that is formatted <key=escaped value>.*/
+bool
+TorControl::setConf(QString keyAndValue, QString *errmsg)
+{
+ QHash<QString,QString> map;
+ map.insert(keyAndValue, "");
+ return setConf(map, errmsg);
+}
+
/** Gets values for a set of configuration keys, each of which has a single
* value. */
bool
@@ -794,6 +803,22 @@
return map.value(key);
}
+/** Sends a GETCONF message to Tor with the single key and returns a QString
+ * containing the value returned by Tor */
+QString
+TorControl::getHiddenServiceConf(const QString &key, QString *errmsg)
+{
+ ControlCommand cmd("GETCONF");
+ ControlReply reply;
+ QVariantMap confMap;
+
+ cmd.addArgument(key);
+ if (!send(cmd, reply, errmsg))
+ return "";
+
+ return reply.toString();
+}
+
/** Asks Tor to save the current configuration to its torrc. */
bool
TorControl::saveConf(QString *errmsg)
Modified: vidalia/trunk/src/torcontrol/torcontrol.h
===================================================================
--- vidalia/trunk/src/torcontrol/torcontrol.h 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/torcontrol/torcontrol.h 2008-04-12 18:23:28 UTC (rev 2504)
@@ -124,6 +124,8 @@
bool setConf(QHash<QString,QString> map, QString *errmsg = 0);
/** Sets a single configuration key to the given value. */
bool setConf(QString key, QString value, QString *errmsg = 0);
+ /** Sets a single configuration string that is formatted <key=escaped value>. */
+ bool setConf(QString keyAndValue, QString *errmsg = 0);
/** Gets values for a set of configuration keys, each of which has a single
* value. */
bool getConf(QHash<QString,QString> &map, QString *errmsg = 0);
@@ -142,6 +144,9 @@
* QVariant containing the value returned by Tor. Returns a default
* constructed QVariant on failure. */
QVariant getConf(const QString &key, QString *errmsg = 0);
+ /** Sends a GETCONF message to Tor with the single key and returns a QString
+ * containing the value returned by Tor */
+ QString getHiddenServiceConf(const QString &key, QString *errmsg = 0);
/** Asks Tor to save the current configuration to its torrc */
bool saveConf(QString *errmsg = 0);
Modified: vidalia/trunk/src/vidalia/CMakeLists.txt
===================================================================
--- vidalia/trunk/src/vidalia/CMakeLists.txt 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/CMakeLists.txt 2008-04-12 18:23:28 UTC (rev 2504)
@@ -61,6 +61,10 @@
config/portvalidator.cpp
config/serverpage.cpp
config/serversettings.cpp
+ config/service.cpp
+ config/servicelist.cpp
+ config/servicepage.cpp
+ config/servicesettings.cpp
config/torsettings.cpp
config/vidaliasettings.cpp
config/vsettings.cpp
@@ -80,6 +84,7 @@
config/portvalidator.h
config/serverpage.h
config/serversettings.h
+ config/servicepage.h
config/torsettings.h
config/vidaliasettings.h
config/vsettings.h
@@ -192,6 +197,7 @@
config/generalpage.ui
config/networkpage.ui
config/serverpage.ui
+ config/servicepage.ui
help/browser/helpbrowser.ui
log/messagelog.ui
network/netviewer.ui
Modified: vidalia/trunk/src/vidalia/config/configdialog.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/configdialog.cpp 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/config/configdialog.cpp 2008-04-12 18:23:28 UTC (rev 2504)
@@ -42,8 +42,8 @@
#define IMAGE_SAVE ":/images/22x22/media-floppy.png"
#define IMAGE_CANCEL ":/images/22x22/emblem-unreadable.png"
#define IMAGE_HELP ":/images/22x22/help-browser.png"
+#define IMAGE_SERVICE ":/images/22x22/service.png"
-
/** Constructor */
ConfigDialog::ConfigDialog(QWidget* parent)
: VidaliaWindow("ConfigDialog", parent)
@@ -88,6 +88,10 @@
ui.stackPages->add(new AdvancedPage(ui.stackPages),
createPageAction(QIcon(IMAGE_ADVANCED),
tr("Advanced"), grp));
+
+ ui.stackPages->add(new ServicePage(ui.stackPages),
+ createPageAction(QIcon(IMAGE_SERVICE),
+ tr("Services"), grp));
foreach (ConfigPage *page, ui.stackPages->pages()) {
connect(page, SIGNAL(helpRequested(QString)),
this, SLOT(help(QString)));
@@ -250,6 +254,8 @@
help("config.appearance"); break;
case Advanced:
help("config.advanced"); break;
+ case Service:
+ help("config.services"); break;
default:
help("config.general"); break;
}
Modified: vidalia/trunk/src/vidalia/config/configdialog.h
===================================================================
--- vidalia/trunk/src/vidalia/config/configdialog.h 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/config/configdialog.h 2008-04-12 18:23:28 UTC (rev 2504)
@@ -26,6 +26,7 @@
#include "serverpage.h"
#include "advancedpage.h"
#include "appearancepage.h"
+#include "servicepage.h"
#include "ui_configdialog.h"
@@ -41,7 +42,8 @@
Network, /** Network configuration page. */
Server, /** Server configuration page. */
Appearance, /** Appearance configuration page. */
- Advanced /** Advanced configuration page. */
+ Advanced, /** Advanced configuration page. */
+ Service /** Service Configuration page */
};
/** Default Constructor */
@@ -76,7 +78,7 @@
QAction* createPageAction(QIcon img, QString text, QActionGroup *group);
/** Adds a new action to the toolbar. */
void addAction(QAction *action, const char *slot = 0);
-
+
/** Qt Designer generated object */
Ui::ConfigDialog ui;
};
Added: vidalia/trunk/src/vidalia/config/service.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/service.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/config/service.cpp 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,117 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#include "service.h"
+
+/** Default Constructor */
+Service::Service() {
+}
+
+/** Constructor to create a new Service with initial settings */
+Service::Service(QString serviceAddress, QString virtualPort,
+ QString physicalAddressPort, QString serviceDirectory, bool enabled)
+{
+
+ _serviceAddress = serviceAddress;
+ _virtualPort = virtualPort;
+ _physicalAddressPort = physicalAddressPort;
+ _serviceDirectory = serviceDirectory;
+ _enabled = enabled;
+}
+
+/** Destructor */
+Service::~Service()
+{
+}
+
+/** Sets the deploy status of a service */
+void Service::setEnabled(bool enabled)
+{
+ _enabled = enabled;
+}
+
+/** Sets the adress of a service */
+void Service::setServiceAddress(QString serviceAddress)
+{
+ _serviceAddress = serviceAddress;
+}
+
+/** Sets the virtualPort of a service */
+void Service::setVirtualPort(QString virtualPort)
+{
+ _virtualPort = virtualPort;
+}
+
+/** Sets the physical Adress and the local port of a service */
+void Service::setPhysicalAddressPort(QString physicalAddressPort)
+{
+ _physicalAddressPort = physicalAddressPort;
+}
+
+/** Sets the service directory of a service */
+void Service::setServiceDirectory(QString serviceDirectory)
+{
+ _serviceDirectory = serviceDirectory;
+}
+
+/** Sets the additional options of a service e.g. excludeNodes */
+void Service::setAdditionalServiceOptions(QString options)
+{
+ _additionalServiceOptions = options;
+}
+
+/** Writes service class data from <b>myObj</b> to the QDataStream
+ * <b>out</b>. */
+QDataStream&operator<<(QDataStream &out, const Service &myObj)
+{
+ out << myObj.serviceAddress();
+ out << myObj.virtualPort();
+ out << myObj.physicalAddressPort();
+ out << myObj.serviceDirectory();
+ out << myObj.enabled();
+ out << myObj.additionalServiceOptions();
+
+ return out;
+}
+
+/** Reads service class data in from the QDataStream <b>in</b> and
+ populates * the <b>myObj</b> object accordingly. */
+QDataStream&operator>>(QDataStream &in, Service &myObj)
+{
+ QString serviceAddress;
+ QString virtualPort;
+ QString physicalAddressPort;
+ QString serviceDirectory;
+ bool enabled;
+ QString additionalServiceOptions;
+
+ /* Read in from the data stream */
+ in >> serviceAddress >> virtualPort >> physicalAddressPort
+ >> serviceDirectory >> enabled >> additionalServiceOptions;
+
+ /* Set the appropriate class member variables */
+ myObj.setServiceAddress(serviceAddress);
+ myObj.setVirtualPort(virtualPort);
+ myObj.setPhysicalAddressPort(physicalAddressPort);
+ myObj.setServiceDirectory(serviceDirectory);
+ myObj.setEnabled(enabled);
+ myObj.setAdditionalServiceOptions(additionalServiceOptions);
+
+ /* Return the updated data stream */
+ return in;
+}
+
+QString
+Service::toString()
+{
+ return _serviceAddress +"#"+ _virtualPort +"#"+ _physicalAddressPort +
+ "#"+ _serviceDirectory +"#"+ _enabled + "#"+ _additionalServiceOptions;
+}
+
Added: vidalia/trunk/src/vidalia/config/service.h
===================================================================
--- vidalia/trunk/src/vidalia/config/service.h (rev 0)
+++ vidalia/trunk/src/vidalia/config/service.h 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,80 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#ifndef SERVICE_H_
+#define SERVICE_H_
+
+#include <QString>
+#include <QList>
+#include <QMetaType>
+
+class Service
+{
+public:
+
+ /** Default constructor. */
+ Service();
+ /** Constructor to create a new Service with initial settings */
+ Service(QString serviceAddress, QString virtualPort,
+ QString physicalAddressPort, QString serviceDirectory, bool enabled);
+ /** Destructor */
+ virtual ~Service();
+ /** Returns the service Adress of the service */
+ QString serviceAddress() const { return _serviceAddress; }
+ /** Returns the listeningPort of the service */
+ QString virtualPort() const { return _virtualPort; }
+ /** Returns the physical Adresse and the local Port of the service */
+ QString physicalAddressPort() const { return _physicalAddressPort; }
+ /** Returns the service directory of the service */
+ QString serviceDirectory() const { return _serviceDirectory; }
+ /** Returns the deployed status of a service */
+ bool enabled() const { return _enabled; }
+ /** Returns the additional options of a service e.g. excludeNodes */
+ QString additionalServiceOptions() const
+ { return _additionalServiceOptions; }
+ /** Sets the adress of a service */
+ void setServiceAddress(QString serviceAddress);
+ /** Sets the listening port of a service */
+ void setVirtualPort(QString virtualPort);
+ /** Sets the physical Adress and the local Port of a service */
+ void setPhysicalAddressPort(QString physicalAddressPort);
+ /** Sets the service directory of a service */
+ void setServiceDirectory(QString serviceDirectory);
+ /** Sets the deployed status a service */
+ void setEnabled(bool enabled);
+ /** Sets the additional options of a service e.g. excludeNodes */
+ void setAdditionalServiceOptions(QString options);
+ /** Writes service class data from <b>myObj</b> to the QDataStream
+ * <b>out</b>. */
+ friend QDataStream& operator<<(QDataStream &out, const Service &myObj);
+ /** Reads service class data in from the QDataStream <b>in</b> and
+ populates * the <b>myObj</b> object accordingly. */
+ friend QDataStream& operator>>(QDataStream &in, Service &myObj);
+
+ QString toString();
+
+private:
+ /** The adress of the service */
+ QString _serviceAddress;
+ /** The listening Port of the service */
+ QString _virtualPort;
+ /** The physical Adress and the local port of teh service */
+ QString _physicalAddressPort;
+ /** the directory of the service */
+ QString _serviceDirectory;
+ /** The Enabled status of the service */
+ bool _enabled;
+ /** Some additional service options, not configured/displayed by Vidalia */
+ QString _additionalServiceOptions;
+
+};
+Q_DECLARE_METATYPE(Service);
+#endif /*SERIVCE_H_*/
+
Added: vidalia/trunk/src/vidalia/config/servicelist.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/servicelist.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicelist.cpp 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,55 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#include "servicelist.h"
+
+/** Default constructor. */
+ServiceList::ServiceList()
+{
+}
+
+/** Constructor to create a new Servicelist with initial settings */
+void ServiceList::addService(Service service)
+{
+ _services.append(service);
+}
+
+/** Destructor */
+ServiceList::~ServiceList()
+{
+}
+
+/* Sets the serviceList */
+void ServiceList::setServices(QList<Service> services)
+{
+ _services = services;
+}
+
+/** Writes ServiceList class data from <b>myObj</b> to the QDataStream
+ * <b>out</b>. */
+QDataStream&operator<<(QDataStream &out, const ServiceList &myObj)
+{
+ out << myObj.services(); /* Write the services*/
+ return out;
+}
+
+/** Reads ServiceList class data in from the QDataStream <b>in</b> and
+ populates * the <b>myObj</b> object accordingly. */
+QDataStream&operator>>(QDataStream &in, ServiceList &myObj)
+{
+ QList<Service> services;
+ /* Read in from the data stream */
+ in >> services;
+ /* Set the appropriate class member variables */
+ myObj.setServices(services);
+ /* Return the updated data stream */
+ return in;
+}
+
Added: vidalia/trunk/src/vidalia/config/servicelist.h
===================================================================
--- vidalia/trunk/src/vidalia/config/servicelist.h (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicelist.h 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,46 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#ifndef SERVICELIST_H_
+#define SERVICELIST_H_
+#include <QList>
+#include <service.h>
+class ServiceList
+{
+public:
+
+ /** Default constructor. */
+ ServiceList();
+ /** Destructor */
+ virtual ~ServiceList();
+ /** Returns the list of services */
+ void addService(Service service);
+ /** Sets the lists of services */
+ void setServices(QList<Service> services);
+ /** Returns the list of services */
+ QList<Service> services() const {
+ return _services;
+ }
+ /** Writes ServiceList class data from <b>myObj</b> to the QDataStream
+ * <b>out</b>. */
+ friend QDataStream& operator<<(QDataStream &out, const ServiceList &myObj);
+ /** Reads ServiceList class data in from the QDataStream <b>in</b> and
+ populates * the <b>myObj</b> object accordingly. */
+ friend QDataStream& operator>>(QDataStream &in, ServiceList &myObj);
+
+private:
+
+ /** The list of Services */
+ QList<Service> _services;
+
+};
+Q_DECLARE_METATYPE(ServiceList);
+#endif /*SERVICELIST_H_*/
+
Added: vidalia/trunk/src/vidalia/config/servicepage.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/servicepage.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicepage.cpp 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,599 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#include <util/stringutil.h>
+#include <vmessagebox.h>
+#include <qheaderview.h>
+#include <qclipboard.h>
+#include <QFile>
+#include <QTextStream>
+#include <file.h>
+#include "configdialog.h"
+#include "ipvalidator.h"
+#include "service.h"
+#include "servicelist.h"
+#include "domainvalidator.h"
+#include "ipvalidator.h"
+
+/** Constructor */
+ServicePage::ServicePage(QWidget *parent)
+: ConfigPage(parent, tr("Services"))
+{
+ /* Invoke the Qt Designer generated object setup routine */
+ ui.setupUi(this);
+ /* Keep a pointer to the TorControl object used to talk to Tor */
+ _torControl = Vidalia::torControl();
+ /* Create Tor settings objects */
+ _torSettings = new TorSettings;
+ /* Keep a pointer to the ServiceSettings object used to store
+ * the configuration */
+ _serviceSettings = new ServiceSettings(_torControl);
+ /* A QMap, mapping from the row number to the Entity for
+ * all services */
+ _services = new QMap<int, Service>();
+ /* A QMap, mapping from the directory path to the Entity for
+ * all Tor services */
+ _torServices = new QMap<QString, Service>();
+
+ ui.serviceWidget->horizontalHeader()->resizeSection(0, 150);
+ ui.serviceWidget->horizontalHeader()->resizeSection(1, 89);
+ ui.serviceWidget->horizontalHeader()->resizeSection(2, 100);
+ ui.serviceWidget->horizontalHeader()->resizeSection(3, 120);
+ ui.serviceWidget->horizontalHeader()->resizeSection(4, 60);
+ ui.serviceWidget->verticalHeader()->hide();
+
+ connect(ui.addButton, SIGNAL(clicked()), this, SLOT(addService()));
+ connect(ui.removeButton, SIGNAL(clicked()), this, SLOT(removeService()));
+ connect(ui.copyButton, SIGNAL(clicked()), this, SLOT(copyToClipboard()));
+ connect(ui.browseButton, SIGNAL(clicked()), this, SLOT(browseDirectory()));
+ connect(ui.serviceWidget, SIGNAL(itemClicked(QTableWidgetItem*)), this,
+ SLOT(serviceSelectionChanged()));
+ connect(ui.serviceWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this,
+ SLOT(valueChanged()));
+}
+
+/** Destructor */
+ServicePage::~ServicePage()
+{
+ delete _serviceSettings;
+}
+
+/** Saves changes made to settings on the Server settings page. */
+bool
+ServicePage::save(QString &errmsg)
+{
+ QList<Service> serviceList;
+ QList<Service> publishedServices;
+ int index = 0;
+ while(index < ui.serviceWidget->rowCount()) {
+ QString address = ui.serviceWidget->item(index,0)->text();
+ QString virtualPort = ui.serviceWidget->item(index,1)->text();
+ QString physicalAddress = ui.serviceWidget->item(index,2)->text();
+ QString directoryPath = ui.serviceWidget->item(index,3)->text();
+ bool enabled = _services->value(index).enabled();
+ Service temp(address, virtualPort, physicalAddress, directoryPath,
+ enabled);
+ temp.setAdditionalServiceOptions(_services->value(ui.serviceWidget->
+ currentRow()).additionalServiceOptions());
+ serviceList.push_back(temp);
+ if(enabled) {
+ publishedServices.push_back(temp);
+ }
+ index++;
+ }
+ bool save;
+ save = checkBeforeSaving(serviceList);
+ if(save) {
+ ServiceList sList;
+ if(serviceList.size() > 0) {
+ sList.setServices(serviceList);
+ } else {
+ _services = new QMap<int, Service>();
+ sList.setServices(_services->values());
+ }
+ _serviceSettings->setServices(sList);
+ if(publishedServices.size() > 0) {
+ startServicesInTor(publishedServices);
+ } else {
+ QString errmsg1 = tr("Error while trying to unpublish all services");
+ QString &errmsg = errmsg1;
+ _serviceSettings->unpublishAllServices(&errmsg);
+ }
+ return true;
+ } else {
+ errmsg = tr("Please configure at least a service directory and a virtual\
+ port for each service you want to save. Remove the other ones.");
+ return false;
+ }
+}
+
+/** this method checks if either all services have minimal
+ * configuration or not */
+bool
+ServicePage::checkBeforeSaving(QList<Service> serviceList)
+{
+ bool result = true;
+ foreach(Service s, serviceList) {
+ if(s.serviceDirectory().isEmpty() || s.virtualPort().isEmpty()) {
+ result = false;
+ break;
+ }
+ }
+ return result;
+}
+
+/** this method generates the configuration string for a list of services */
+void
+ServicePage::startServicesInTor(QList<Service> services)
+{
+ QString serviceConfString;
+ QString errmsg = "Error while trying to publish services.";
+ QListIterator<Service> it(services);
+ bool first = true;
+ while(it.hasNext()) {
+ Service temp = it.next();
+ serviceConfString.append("hiddenservicedir=" +
+ string_escape(temp.serviceDirectory()) + " ");
+ serviceConfString.append("hiddenserviceport=" +
+ string_escape(temp.virtualPort() +
+ (temp.physicalAddressPort().isEmpty() ? "" : " " +
+ temp.physicalAddressPort())));
+ serviceConfString.append(" "+ temp.additionalServiceOptions());
+ }
+ _serviceSettings->applyServices(serviceConfString, &errmsg);
+}
+
+/** Loads previously saved settings */
+void
+ServicePage::load()
+{
+ ui.removeButton->setEnabled(false);
+ ui.copyButton->setEnabled(false);
+ ui.browseButton->setEnabled(false);
+ // get all services
+ _services = new QMap<int, Service>();
+ _torServices = new QMap<QString, Service>();
+ QList<Service> torServiceList;
+
+ QString torConfigurationString = _serviceSettings->
+ getHiddenServiceDirectories();
+ torServiceList = extractSingleServices(torConfigurationString);
+ QList<Service> completeList = torServiceList;
+ // the services stored with vidalia
+ ServiceList serviceList = _serviceSettings->getServices();
+ QList<Service> serviceSettingsList = serviceList.services();
+ QListIterator<Service> it(serviceSettingsList);
+ // check whether a service is already in the list because he is published
+ while(it.hasNext()) {
+ Service temp = it.next();
+ if(isServicePublished(temp, torServiceList) == false) {
+ completeList.push_back(temp);
+ }
+ }
+ // generate the _services data structure used during vidalia session
+ QListIterator<Service> it2(completeList);
+ int index = 0;
+ while (it2.hasNext()) {
+ Service tempService = it2.next();
+ _services->insert(index, tempService);
+ index++;
+ }
+ initServiceTable(_services);
+}
+
+/** this method returns a list of services by parsing the configuration
+ * string given by the tor controller */
+QList<Service>
+ServicePage::extractSingleServices(QString conf)
+{
+ QList<Service> list;
+ QStringList strList = conf.split("250 HiddenServiceDir");
+ strList.removeFirst();
+ QListIterator<QString> it(strList);
+ //for each service directory splitted string = service
+ while(it.hasNext()) {
+ QString temp = it.next();
+ list.push_back(generateService(temp));
+ }
+ return list;
+}
+
+/** this return a Service by parseing the configuration string
+ * of Tor and storeing its values into the object */
+Service
+ServicePage::generateService(QString s)
+{
+ QString additionalOptions = s;
+ // remove directory
+ int index = additionalOptions.indexOf("250",1);
+ additionalOptions.remove(0, index+4);
+ // remove the first appearance of the port
+ int startindex = additionalOptions.indexOf("hiddenserviceport",
+ 0, Qt::CaseInsensitive);
+ int endindex = additionalOptions.indexOf("250", startindex);
+ if(endindex != -1) {
+ additionalOptions.remove(startindex, (endindex-startindex)+4);
+ //remove all appearances of "250"
+ while(additionalOptions.contains("250")) {
+ int i = additionalOptions.indexOf("250", 0);
+ additionalOptions.remove(i, 4);
+ }
+ // prepare for correct quotation
+ if (!additionalOptions.endsWith('\n')) {
+ additionalOptions.append("\n");
+ }
+ //quote the values
+ int j = additionalOptions.indexOf("=", 0);
+ while(j != -1) {
+ additionalOptions.insert(j+1, "\"");
+ int end = additionalOptions.indexOf("\n", j);
+ additionalOptions.insert(end, "\"");
+ j = additionalOptions.indexOf("=", end);
+ }
+ //replace the line brakes with a space and create one single line
+ additionalOptions.replace(QString("\n"), QString(" "));
+ } else {
+ additionalOptions = "";
+ }
+
+ QString address, virtualPort, physAddressPort, serviceDir;
+ // service directory
+ QStringList strList = s.split("\n");
+ QString tempServiceDir = strList.first().trimmed();
+ serviceDir = tempServiceDir.remove(0, 1);
+ //virtual port
+ QStringList strList2 = s.split("HiddenServicePort");
+ strList2.removeFirst();
+ QStringList strList3 = strList2.first().split("\n");
+ QStringList strList4 = strList3.first().split(" ");
+ if(strList4.size() > 0) {
+ QString tempVirtualPort = strList4.first();
+ virtualPort = tempVirtualPort.remove(0, 1);
+ strList4.removeFirst();
+ //physical address:port
+ if(!strList4.isEmpty()) {
+ physAddressPort = strList4.first().trimmed();
+ }
+ } else {
+ QString tempVirtualPort = strList3.first();
+ virtualPort = tempVirtualPort.remove(0, 1);
+ }
+ //get .onion address
+ QString serviceHostnameDir = serviceDir;
+ serviceHostnameDir.append("/");
+ serviceHostnameDir.append("hostname");
+ QFile file(serviceHostnameDir);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ address = "[Directory not found]";
+ } else {
+ QTextStream in(&file);
+ QString hostname;
+ while (!in.atEnd()) {
+ hostname.append(in.readLine());
+ }
+ address = hostname;
+ }
+ Service service(address, virtualPort, physAddressPort, serviceDir, true);
+ service.setAdditionalServiceOptions(additionalOptions);
+ _torServices->insert(serviceDir, service);
+ return service;
+}
+
+/** this method checks either a service is published or not */
+bool
+ServicePage::isServicePublished(Service service, QList<Service> torServices)
+{
+ QListIterator<Service> it(torServices);
+ while(it.hasNext()) {
+ Service temp = it.next();
+ if(temp.serviceDirectory().compare(service.serviceDirectory()) == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/** this method creates/displays the values for each service
+ * shown in the service listing */
+void
+ServicePage::initServiceTable(QMap<int, Service>* _services)
+{
+ // clean the widget
+ int rows = ui.serviceWidget->rowCount();
+ for(int i = 0; i < rows; i++) {
+ ui.serviceWidget->removeRow(0);
+ }
+ //for each service
+ int index = 0;
+ while(index < _services->size()) {
+ Service tempService = _services->value(index);
+ ui.serviceWidget->insertRow(index);
+ QTableWidgetItem *cboxitem = new QTableWidgetItem();
+ cboxitem->setFlags(Qt::ItemIsSelectable);
+ QTableWidgetItem *addressitem = new QTableWidgetItem();
+ addressitem->setFlags(Qt::ItemIsSelectable);
+ if(tempService.serviceAddress().length() < 0) {
+ addressitem->setText(tempService.serviceAddress());
+ } else {
+ QString serviceHostnameDir = tempService.serviceDirectory();
+ serviceHostnameDir.append("/");
+ serviceHostnameDir.append("hostname");
+ QFile file(serviceHostnameDir);
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ addressitem->setText("[Directory not found]");
+ } else {
+ QTextStream in(&file);
+ QString hostname;
+ while (!in.atEnd()) {
+ hostname.append(in.readLine());
+ }
+ addressitem->setText(hostname);
+ tempService.setServiceAddress(hostname);
+ }
+ }
+ addressitem->setData(32, addressitem->text());
+ QTableWidgetItem *serviceDir =
+ new QTableWidgetItem(tempService.serviceDirectory(), 0);
+ serviceDir->setData(32, tempService.serviceDirectory());
+ QTableWidgetItem* virtualportitem =
+ new QTableWidgetItem(tempService.virtualPort(), 0);
+ virtualportitem->setData(32, tempService.virtualPort());
+ QTableWidgetItem* targetitem =
+ new QTableWidgetItem(tempService.physicalAddressPort(),0);
+ targetitem->setData(32, tempService.physicalAddressPort());
+ if(tempService.enabled()) {
+ cboxitem->setCheckState(Qt::Checked);
+ serviceDir->setFlags(Qt::ItemIsSelectable);
+ } else {
+ cboxitem->setCheckState(Qt::Unchecked);
+ }
+ cboxitem->setTextAlignment(Qt::AlignCenter);
+ ui.serviceWidget->setItem(index, 0, addressitem);
+ ui.serviceWidget->setItem(index, 1, virtualportitem);
+ ui.serviceWidget->setItem(index, 2, targetitem);
+ ui.serviceWidget->setItem(index, 3, serviceDir);
+ ui.serviceWidget->setItem(index, 4, cboxitem);
+ index++;
+ }
+}
+
+/** this method is called when the user clicks the "Add"-Button
+ * it generates a new empty table entrie(row) */
+void
+ServicePage::addService()
+{
+ int rows = ui.serviceWidget->rowCount();
+ ui.serviceWidget->insertRow(rows);
+ QTableWidgetItem *address = new QTableWidgetItem("[Created by Tor]");
+ address->setFlags(Qt::ItemIsSelectable);
+ QTableWidgetItem *dummy = new QTableWidgetItem();
+ QTableWidgetItem *dummy2 = new QTableWidgetItem();
+ QTableWidgetItem *dummy3 = new QTableWidgetItem();
+ QTableWidgetItem *cboxitem = new QTableWidgetItem();
+ cboxitem->setFlags(Qt::ItemIsSelectable);
+ cboxitem->setCheckState(Qt::Checked);
+ ui.serviceWidget->setItem(rows, 0, address);
+ ui.serviceWidget->setItem(rows, 1, dummy);
+ ui.serviceWidget->setItem(rows, 2, dummy2);
+ ui.serviceWidget->setItem(rows, 3, dummy3);
+ ui.serviceWidget->setItem(rows, 4, cboxitem);
+ Service s;
+ s.setEnabled(true);
+ _services->insert(rows, s);
+}
+
+/** this method is called when the user clicks the "Remove"-Button
+ * it removes a service/row of the service listing */
+void
+ServicePage::removeService()
+{
+ int rows = ui.serviceWidget->rowCount();
+ int selrow = ui.serviceWidget->currentRow();
+ if(selrow < 0 || selrow >= _services->size()) {
+ VMessageBox::warning(this, tr("Error"), tr("Please select a Service."),
+ VMessageBox::Ok);
+ return;
+ } else {
+ ui.serviceWidget->removeRow(selrow);
+ //decrease all other service keys
+ for(int i = 0; i < (rows-selrow-1); i++) {
+ int index = i+selrow;
+ Service s = _services->take(index+1);
+ _services->insert(index, s);
+ }
+ }
+ serviceSelectionChanged();
+}
+
+/** this method is called when the user clicks on the "Copy"-Button, it
+ * copies the .onion-Address of the selected service into the clipboard */
+void
+ServicePage::copyToClipboard()
+{
+ int selrow = ui.serviceWidget->currentRow();
+ if(selrow < 0 || selrow >= _services->size()) {
+ VMessageBox::warning(this, tr("Error"), tr("Please select a Service."),
+ VMessageBox::Ok);
+ return;
+ } else {
+ QString onionAddress = ui.serviceWidget->item(selrow,0)->text();
+ QClipboard *clipboard = QApplication::clipboard();
+ QString clipboardText;
+ QTableWidgetItem* selectedItem = ui.serviceWidget->item(selrow,0);
+ clipboardText.append(selectedItem->text());
+ clipboard->setText(clipboardText);
+ }
+}
+
+/** this method is called when the user clicks on the "Brows"-Button it opens
+ * a QFileDialog to choose a service directory */
+void
+ServicePage::browseDirectory()
+{
+ int selrow = ui.serviceWidget->currentRow();
+ if(selrow < 0 || selrow >= _services->size()) {
+ VMessageBox::warning(this, tr("Error"), tr("Please select a Service."),
+ VMessageBox::Ok);
+ return;
+ } else {
+ QString dirname = QFileDialog::getExistingDirectory(this,
+ tr("Select Service Directory"), "",
+ QFileDialog::ShowDirsOnly|QFileDialog::DontResolveSymlinks);
+
+ if (dirname.isEmpty()) {
+ return;
+ }
+ ui.serviceWidget->item(selrow,3)->setText(dirname);
+ Service s = _services->take(selrow);
+ s.setServiceDirectory(dirname);
+ _services->insert(selrow, s);
+ }
+}
+
+/** this method is called when the selects an other tablewidgetitem */
+void
+ServicePage::serviceSelectionChanged()
+{
+ bool emptyTable = false;
+ if(ui.serviceWidget->rowCount() > 0) {
+ ui.removeButton->setEnabled(true);
+ ui.copyButton->setEnabled(true);
+ ui.browseButton->setEnabled(true);
+ } else {
+ ui.removeButton->setEnabled(false);
+ ui.copyButton->setEnabled(false);
+ ui.browseButton->setEnabled(false);
+ emptyTable = true;
+ }
+ int currentRow = ui.serviceWidget->currentRow();
+ if(emptyTable == false) {
+ QTableWidgetItem* item = ui.serviceWidget->item(currentRow, 0);
+ if(item != NULL) {
+ bool b = item->text().contains(".onion");
+ ui.copyButton->setEnabled(b);
+ }
+ }
+ QTableWidgetItem* item = ui.serviceWidget->item(ui.serviceWidget->
+ currentRow(), 3);
+ QString selDir = _services->value(ui.serviceWidget->currentRow()).
+ serviceDirectory();
+ QList<QString> strList = _torServices->keys();
+ if(selDir.length() > 0) {
+ QListIterator<QString> it(strList);
+ while(it.hasNext()) {
+ QString temp = it.next();
+ if(selDir.compare(temp) == 0) {
+ ui.browseButton->setEnabled(false);
+ break;
+ }
+ }
+ }
+ // if the user has clicked on the checkbox cell
+ if(ui.serviceWidget->currentColumn() == 4) {
+ Service service = _services->take(currentRow);
+ QTableWidgetItem* item = ui.serviceWidget->item(currentRow,4);
+ if(service.enabled()) {
+ item->setCheckState(Qt::Unchecked);
+ service.setEnabled(false);
+ } else {
+ item->setCheckState(Qt::Checked);
+ service.setEnabled(true);
+ }
+ _services->insert(currentRow, service);
+ }
+}
+
+/** this method is called when the user finished editing a cell and it provides
+ * that only valid values are set */
+void
+ServicePage::valueChanged()
+{
+ int pos = 0;
+ QIntValidator* portValidator = new QIntValidator(1, 65535, this);
+ DomainValidator* domainValidator = new DomainValidator(this);
+ IPValidator* ipValidator = new IPValidator(this);
+ QTableWidgetItem* item = ui.serviceWidget->currentItem();
+ if (item == NULL || item->text() == NULL || item->text().length() == 0) {
+ // nothing to validate here
+ return;
+ }
+ QString text = item->text();
+ switch (item->column()) {
+ case 1: // virtual port
+ if(portValidator->validate(text, pos) == QValidator::Acceptable) {
+ // correct data; buffer value in user role 32
+ item->setData(32, text);
+ } else {
+ //incorrect data; restore value from user role 32
+ VMessageBox::warning(this, tr("Error"),
+ tr("Virtual Port may only contain valid port numbers [1..65535]."),
+ VMessageBox::Ok);
+ item->setText(item->data(32).toString());
+ }
+ break;
+ case 2: // target
+ if(text.contains(":")) {
+ // check for <address>:<port>
+ QStringList strList = text.split(":");
+ if (strList.size() != 2) {
+ goto invalid;
+ }
+ QString address = strList.at(0);
+ QString port = strList.at(1);
+ if((address.compare("localhost") != 0 &&
+ ipValidator->validate(address, pos) != QValidator::Acceptable &&
+ domainValidator->validate(address, pos) != QValidator::Acceptable) ||
+ portValidator->validate(port, pos) != QValidator::Acceptable) {
+ goto invalid;
+ }
+ } else { // either <address> or <port>
+ if (text.compare("localhost") != 0 &&
+ ipValidator->validate(text, pos) != QValidator::Acceptable &&
+ domainValidator->validate(text, pos) != QValidator::Acceptable &&
+ portValidator->validate(text, pos) != QValidator::Acceptable) {
+ goto invalid;
+ }
+ }
+ goto valid;
+ invalid:
+ VMessageBox::warning(this, tr("Error"),
+ tr("Target may only contain address:port, address, or port."),
+ VMessageBox::Ok);
+ item->setText(item->data(32).toString());
+ break;
+ valid:
+ item->setData(32, text);
+ break;
+ case 3: // service directory
+ // compare with directories of other enabled services
+ for (int index = 0; index < ui.serviceWidget->rowCount(); index++) {
+ // skip own row
+ if(index == item->row()) {
+ continue;
+ }
+ QTableWidgetItem* compareWith = ui.serviceWidget->item(index, 3);
+ if(compareWith != NULL) {
+ QString actualDir = compareWith->text();
+ if(actualDir.length() > 0 && text.compare(actualDir) == 0) {
+ // service directory already in use
+ VMessageBox::warning(this, tr("Error"),
+ tr("Directory already in use by another service."),
+ VMessageBox::Ok);
+ item->setText(item->data(32).toString());
+ return;
+ }
+ }
+ }
+ // correct data; buffer value in user role 32
+ item->setData(32, text);
+ break;
+ }
+}
+
Added: vidalia/trunk/src/vidalia/config/servicepage.h
===================================================================
--- vidalia/trunk/src/vidalia/config/servicepage.h (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicepage.h 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,85 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#ifndef _SERVICEPAGE_H
+#define _SERVICEPAGE_H
+
+#include <torcontrol.h>
+#include <torsettings.h>
+#include <servicesettings.h>
+#include <exitpolicy.h>
+#include <helpbrowser.h>
+#include "configpage.h"
+#include "ui_servicepage.h"
+
+class ServicePage : public ConfigPage
+{
+ Q_OBJECT
+
+public:
+
+ /** Default Constructor */
+ ServicePage(QWidget *parent = 0);
+ /** Default Destructor */
+ ~ServicePage();
+ /** Saves the changes on this page */
+ bool save(QString &errmsg);
+ /** Loads the settings for this page */
+ void load();
+ /** Initialize the service table */
+ void initServiceTable(QMap<int, Service>* _services);
+
+private slots:
+
+ /** this method is called whenefer the user clicks on the 'add' Button*/
+ void addService();
+ /** this method is called whenefer the user clicks on the 'remove' Button*/
+ void removeService();
+ /** this method is called whenefer the user clicks on the 'copy' Button*/
+ void copyToClipboard();
+ /** this method is called whenefer the user clicks on the 'browse' Button*/
+ void browseDirectory();
+ /** this method is called whenefer the selects a different service*/
+ void serviceSelectionChanged();
+ /** this method returns a list of services by parsing the configuration
+ * string given by the tor controller */
+ QList<Service> extractSingleServices(QString conf);
+ /** this return a Service by parseing the configuration string
+ * of Tor and storeing its values into the object */
+ Service generateService(QString serviceString);
+ /** this method checks either a service is published or not */
+ void startServicesInTor(QList<Service> services);
+ /** this method checks either a service is published or not */
+ bool isServicePublished(Service service, QList<Service> torServices);
+ /** this method checks if either all services have minimal
+ * configuration or not */
+ bool checkBeforeSaving(QList<Service> services);
+ /** this method is called when the user finished editing a cell and
+ * it provides that only valid values are set */
+ void valueChanged();
+
+private:
+
+ /** A TorControl object used to talk to Tor. */
+ TorControl* _torControl;
+ /** A TorSettings object used for saving/loading the Tor settings */
+ TorSettings *_torSettings;
+ /** A ServiceSettings object used to load/save the services. */
+ ServiceSettings* _serviceSettings;
+ /* A QMap, mapping from QString servicename to the Entity service */
+ QMap<int, Service>* _services;
+ /* A QList, consisting of all running services before vidalia starts*/
+ QMap<QString, Service>* _torServices;
+ /** Qt Designer generated object */
+ Ui::ServicePage ui;
+};
+
+#endif
+
Added: vidalia/trunk/src/vidalia/config/servicepage.ui
===================================================================
--- vidalia/trunk/src/vidalia/config/servicepage.ui (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicepage.ui 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,166 @@
+<ui version="4.0" >
+ <class>ServicePage</class>
+ <widget class="QWidget" name="ServicePage" >
+ <property name="geometry" >
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>600</width>
+ <height>400</height>
+ </rect>
+ </property>
+ <property name="minimumSize" >
+ <size>
+ <width>600</width>
+ <height>400</height>
+ </size>
+ </property>
+ <property name="windowTitle" >
+ <string>Form</string>
+ </property>
+ <layout class="QVBoxLayout" >
+ <item>
+ <widget class="QGroupBox" name="groupBox" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Fixed" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="title" >
+ <string>Provided Hidden Services</string>
+ </property>
+ <layout class="QGridLayout" >
+ <item rowspan="5" row="0" column="0" >
+ <widget class="QTableWidget" name="serviceWidget" >
+ <property name="sizePolicy" >
+ <sizepolicy vsizetype="Preferred" hsizetype="Preferred" >
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode" >
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior" >
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="textElideMode" >
+ <enum>Qt::ElideLeft</enum>
+ </property>
+ <property name="showGrid" >
+ <bool>true</bool>
+ </property>
+ <column>
+ <property name="text" >
+ <string>Onion Address</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Virtual Port</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Target</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Directory Path</string>
+ </property>
+ </column>
+ <column>
+ <property name="text" >
+ <string>Enabled</string>
+ </property>
+ </column>
+ </widget>
+ </item>
+ <item row="0" column="1" >
+ <widget class="QToolButton" name="addButton" >
+ <property name="toolTip" >
+ <string>Add new service to list</string>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="icon" >
+ <iconset resource="../res/vidalia_common.qrc" >:/images/22x22/list-add.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1" >
+ <widget class="QToolButton" name="removeButton" >
+ <property name="toolTip" >
+ <string>Remove selected service from list</string>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="icon" >
+ <iconset resource="../res/vidalia_common.qrc" >:/images/22x22/list-remove.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1" >
+ <widget class="QToolButton" name="copyButton" >
+ <property name="toolTip" >
+ <string>Copy onion address of selected service to clipboard</string>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="icon" >
+ <iconset resource="../res/vidalia_common.qrc" >:/images/22x22/edit-copy.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1" >
+ <widget class="QToolButton" name="browseButton" >
+ <property name="toolTip" >
+ <string>Browse in local file system and choose directory for selected service</string>
+ </property>
+ <property name="text" >
+ <string/>
+ </property>
+ <property name="icon" >
+ <iconset resource="../res/vidalia_common.qrc" >:/images/22x22/folder.png</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1" >
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>21</width>
+ <height>46</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation" >
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" >
+ <size>
+ <width>20</width>
+ <height>141</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Added: vidalia/trunk/src/vidalia/config/servicesettings.cpp
===================================================================
--- vidalia/trunk/src/vidalia/config/servicesettings.cpp (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicesettings.cpp 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,164 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#include <stringutil.h>
+#include "servicesettings.h"
+#include "torsettings.h"
+
+/* Service Settings */
+#define SETTING_SERVICE_VIRTUAL_PORT "Service/VirtualPort"
+#define SETTING_SERVICE_ADDRESS "Service/ServiceAddress"
+#define SETTING_SERVICE_PHYSICAL_ADDRESS "Service/ServicePhysicalAddress"
+#define SETTING_SERVICE_ENABLED "Service/Enabled"
+#define SETTING_TOR_SERVICES "Service/Services"
+
+/** Constructor.
+ * \param torControl a TorControl object used to read and apply the Service
+ * configuration settings.
+ */
+ServiceSettings::ServiceSettings(TorControl *torControl)
+{
+ _torControl = torControl;
+ setDefault(SETTING_SERVICE_VIRTUAL_PORT , 0);
+ setDefault(SETTING_SERVICE_PHYSICAL_ADDRESS, "127.0.0.1:0");
+ setDefault(SETTING_SERVICE_ENABLED, "true");
+}
+
+/** Set ServiceList to serialise it */
+void
+ServiceSettings::setServices(ServiceList service)
+{
+ QStringList serviceList;
+ if(service.services().size() > 0) {
+ QList<Service> services = service.services();
+ foreach (Service tempService, services) {
+ serviceList << tempService.toString();
+ }
+ }
+ setValue(SETTING_TOR_SERVICES, serviceList);
+}
+
+/** Get serialised ServiceList */
+ServiceList
+ServiceSettings::getServices()
+{
+ QString address,virtualPort,physAddrPort,serviceDir,enabledS,additionalData;
+ bool enabled = false;
+ QStringList stringList;
+ ServiceList services;
+
+ stringList = value(SETTING_TOR_SERVICES).toStringList();
+ foreach (QString s, stringList) {
+ QStringList skippedList = s.split("#");
+ address = skippedList.first();
+ skippedList.removeFirst();
+ virtualPort = skippedList.first();
+ skippedList.removeFirst();
+ physAddrPort = skippedList.first();
+ skippedList.removeFirst();
+ serviceDir = skippedList.first();
+ skippedList.removeFirst();
+ enabledS = skippedList.first();
+ skippedList.removeFirst();
+ additionalData = skippedList.first();
+ if(enabledS.compare("x1") == 0) {
+ enabled = true;
+ }
+ Service s(address, virtualPort, physAddrPort, serviceDir, enabled);
+ s.setAdditionalServiceOptions(additionalData);
+ services.addService(s);
+ }
+ return services;
+}
+
+/** Returns the virtual port for a specififc service*/
+QString
+ServiceSettings::getVirtualPort()
+{
+ QString port = value(SETTING_SERVICE_VIRTUAL_PORT).toString();
+ return port;
+}
+
+/** Set the virtual port for a specififc service*/
+void
+ServiceSettings::setVirtualPort(QString servicePort)
+{
+ setValue(SETTING_SERVICE_VIRTUAL_PORT, servicePort);
+}
+
+/** Returns the .onion - service address for a specific service */
+QString
+ServiceSettings::getServiceAddress()
+{
+ QString addr = value(SETTING_SERVICE_ADDRESS).toString();
+ return addr;
+}
+
+/** Set the .onion - service address or hostname for a specific service */
+void
+ServiceSettings::setServiceAddress(QString addr)
+{
+ setValue(SETTING_SERVICE_ADDRESS, addr);
+}
+
+/** Returns the physical address for a specific service */
+QString
+ServiceSettings::getPhysicalAddressPort()
+{
+ QString addr = value(SETTING_SERVICE_PHYSICAL_ADDRESS).toString();
+ return addr;
+}
+
+/** Set the physical address or hostname for a specific service */
+void
+ServiceSettings::setPhysicalAddressPort(QString addr)
+{
+ setValue(SETTING_SERVICE_PHYSICAL_ADDRESS, addr);
+}
+
+/** Returns if the Service is enabled */
+bool
+ServiceSettings::isEnabled()
+{
+ return value(SETTING_SERVICE_ENABLED).toBool();
+}
+
+/** Set the service enabled */
+void
+ServiceSettings::setEnabled(bool boolean)
+{
+ setValue(SETTING_SERVICE_ENABLED, boolean);
+}
+
+/** Get all service directories from Tor */
+QString
+ServiceSettings::getHiddenServiceDirectories()
+{
+ QString value = _torControl->getHiddenServiceConf("hiddenserviceoptions");
+ return value;
+}
+
+/** Set all services the user wants to start and send it to the
+ * Tor Controller*/
+void
+ServiceSettings::applyServices(QString value, QString *errmsg)
+{
+ _torControl->setConf(value, errmsg);
+ _torControl->saveConf(errmsg);
+}
+
+/** Unpublish all HiddenServices */
+void
+ServiceSettings::unpublishAllServices(QString *errmsg)
+{
+ _torControl->resetConf("HiddenServiceDir", errmsg);
+ _torControl->saveConf(errmsg);
+}
+
Added: vidalia/trunk/src/vidalia/config/servicesettings.h
===================================================================
--- vidalia/trunk/src/vidalia/config/servicesettings.h (rev 0)
+++ vidalia/trunk/src/vidalia/config/servicesettings.h 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,61 @@
+/*
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to the
+** terms described in the LICENSE file.
+*/
+
+#ifndef _SERVICESETTINGS_H
+#define _SERVICESETTINGS_H
+
+#include <torcontrol.h>
+#include <servicelist.h>
+#include "vidaliasettings.h"
+#include "exitpolicy.h"
+
+class ServiceSettings : private VidaliaSettings
+{
+
+public:
+
+ /** Constructor */
+ ServiceSettings(TorControl *torControl);
+ /** Returns the service port for a specififc service*/
+ QString getVirtualPort();
+ /** Set the service port for a specififc service*/
+ void setVirtualPort(QString servicePort);
+ /** Returns the .onion - service address for a specific service */
+ QString getServiceAddress();
+ /** Set the .onion - service address for a specific service */
+ void setServiceAddress(QString serviceAddress);
+ /** Returns the service address or hostname for a specific service */
+ QString getPhysicalAddressPort();
+ /** Set the service address or hostname for a specific service */
+ void setPhysicalAddressPort(QString physicalAddress);
+ /** Returns if the Service is enabled */
+ bool isEnabled();
+ /** Set the service enabled */
+ void setEnabled(bool enabled);
+ /** Returns a ServiceList containing all services */
+ ServiceList getServices();
+ /** Set ServiceList to serialise it */
+ void setServices(ServiceList services);
+ /** Get Service Directories */
+ QString getHiddenServiceDirectories();
+ /** Set all services the user wants to start and send it to the
+ * Tor Controller */
+ void applyServices(QString value, QString *errmsg);
+ /** Unpublish all services */
+ void unpublishAllServices(QString *errmsg);
+
+private:
+
+ /** A TorControl object used to talk to Tor. */
+ TorControl* _torControl;
+};
+
+#endif
+
Modified: vidalia/trunk/src/vidalia/help/content/content.qrc
===================================================================
--- vidalia/trunk/src/vidalia/help/content/content.qrc 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/help/content/content.qrc 2008-04-12 18:23:28 UTC (rev 2504)
@@ -11,6 +11,7 @@
<file>en/netview.html</file>
<file>en/links.html</file>
<file>en/bridges.html</file>
+ <file>en/services.html</file>
<!-- Finnish -->
<file>fi/contents.xml</file>
<file>fi/index.html</file>
Modified: vidalia/trunk/src/vidalia/help/content/en/config.html
===================================================================
--- vidalia/trunk/src/vidalia/help/content/en/config.html 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/help/content/en/config.html 2008-04-12 18:23:28 UTC (rev 2504)
@@ -186,6 +186,13 @@
</li>
</ul>
+<a name="services"/>
+<h3>Hidden Service Settings</h3>
+<p>
+Hidden services allow you to provide any kind of TCP-based service, e.g.
+an HTTP service, to others without revealing your IP address.
+</p>
+
</body>
</html>
Modified: vidalia/trunk/src/vidalia/help/content/en/contents.xml
===================================================================
--- vidalia/trunk/src/vidalia/help/content/en/contents.xml 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/help/content/en/contents.xml 2008-04-12 18:23:28 UTC (rev 2504)
@@ -32,6 +32,7 @@
<Topic id="server" name="Relay Settings" html="config.html" section="server"/>
<Topic id="appearance" name="Appearance Settings" html="config.html" section="appearance"/>
<Topic id="advanced" name="Advanced Settings" html="config.html" section="advanced"/>
+ <Topic id="services" name="Hidden Services" html="config.html" section="services"/>
</Topic>
<Topic id="server" name="Setting Up a Tor Relay" html="server.html">
<Topic id="basic" name="Basic Setup" html="server.html" section="basic"/>
@@ -42,6 +43,14 @@
<Topic id="about" name="What are bridge relays?" html="bridges.html" section="about"/>
<Topic id="finding" name="How do I find a bridge relay?" html="bridges.html" section="finding"/>
</Topic>
+ <Topic id="services" name="Hidden Services" html="services.html">
+ <Topic id="about" name="What is a hidden service?" html="services.html" section="about"/>
+ <Topic id="provide" name="How do I provide a hidden service?" html="services.html" section="provide"/>
+ <Topic id="data" name="What data do I need to provide?" html="services.html" section="data"/>
+ <Topic id="buttons" name="What are the five buttons used for?" html="services.html" section="buttons"/>
+ <Topic id="advanced" name="How can I configure advanced hidden service settings?" html="services.html" section="advanced"/>
+ <Topic id="client" name="How does Vidalia help me to access other hidden services?" html="services.html" section="client"/>
+ </Topic>
<Topic id="troubleshooting" name="Troubleshooting" html="troubleshooting.html">
<Topic id="start" name="I Can't Start Tor" html="troubleshooting.html" section="start"/>
<Topic id="connect" name="Vidalia Can't Connect to Tor" html="troubleshooting.html" section="connect"/>
Added: vidalia/trunk/src/vidalia/help/content/en/services.html
===================================================================
--- vidalia/trunk/src/vidalia/help/content/en/services.html (rev 0)
+++ vidalia/trunk/src/vidalia/help/content/en/services.html 2008-04-12 18:23:28 UTC (rev 2504)
@@ -0,0 +1,146 @@
+<!--
+** $Id $
+**
+** 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.vidalia-project.net/. No part of Vidalia, including this file,
+** may be copied, modified, propagated, or distributed except according to
+** the terms described in the LICENSE file.
+-->
+
+<html>
+<body>
+
+<h1>Hidden Services</h1>
+<hr />
+
+Remark: Support for hidden services is new in Vidalia. You should expect it
+to have bugs, some of which possibly corrupting your hidden service
+configuration. So, don't rely on it, or rather, don't blame us if something
+goes wrong. If you find bugs or have comments on this new feature, please
+let us know! We need your feedback.
+
+<a name="about"/>
+<h3>What is a hidden service?</h3>
+<p>
+Hidden services allow you to provide any kind of TCP-based service, e.g. an
+HTTP service, to others without revealing your IP address. The protocol
+to provide a hidden service is built on top of the same circuits that Tor
+uses for anonymous browsing and roughly has similar anonymity properties.
+</p>
+
+<p>
+For more information on hidden service you may want to read section 5 of
+Tor's design paper (doc/design-paper/tor-design.pdf) or the Rendezvous
+Specification (doc/spec/rend-spec.txt).
+</p>
+
+<a name="provide"/>
+<h3>How do I provide a hidden service?</h3>
+<p>
+Providing a hidden service consists of at least two steps:
+<ol>
+ <li>Install a web server locally (or a server for whatever service you
+ want to provide, e.g. IRC) to listen for local requests.</li>
+ <li>Configure your hidden service, so that Tor relays requests coming
+ from Tor users to your local server.</li>
+</ol>
+There is a fine tutorial on the Tor website
+(https://www.torproject.org/docs/tor-hidden-service.html) that describes
+these steps in more detail.
+</p>
+
+<a name="data"/>
+<h3>What data do I need to provide?</h3>
+<p>
+The services table contains five columns containing data about configured
+hidden services:
+<ul>
+ <li>Onion Address (generated): The service (or onion) address is
+ generated by Tor to uniquely identify your service. Give this onion
+ address to the people who shall be able to access your service. You
+ may use the "Copy to clipboard" button for that to avoid typos. If
+ you have just created a hidden service, the field says "[Created by
+ Tor]"; in order to make it display the real onion address, you need
+ to save your configuration and re-open the settings window.</li>
+ <li>Virtual Port (required): This is the TCP port that clients will need
+ to know in order to access your service. Typically, you will want to
+ use the service-specific port here, e.g. port 80 for HTTP. Note that
+ the virtual port usually has nothing to do with firewall settings,
+ because it is only used Tor-internally.</li>
+ <li>Target (optional): Usually you want Tor to relay connection requests
+ to localhost on a different port than the one you specified in
+ "Virtual Port". Therefore, you can specify a target consisting of
+ physical address and port to which requests to your hidden service
+ are redirected, e.g. to localhost:5222 (or on whatever port your
+ server is listening). If you don't specify any target, Tor will
+ redirect requests to the port specified in "Virtual Port" on
+ localhost.</li>
+ <li>Service Directory (required): Tor needs to store some hidden-service
+ specific files in a separate directory, e.g. a private key and a
+ hostname file containing the onion address. This directory should be
+ distinct from a directory containing content that the service
+ provides. A good place for a service directory might be a sub
+ directory in Tor's data directory. -- Note that you cannot change the
+ directory of a running service (it wouldn't make much sense to allow
+ it, because Vidalia is not supposed to move directories on your hard
+ disk!). If you want to move a hidden service to another directory,
+ please proceed as follows: Start by disabling the service in Vidalia
+ and save the configuration. Then move the directory on your hard disk
+ to the new place. Finally, change the directory in Vidalia to the new
+ location, enable the service again, and save the new
+ configuration.</li>
+ <li>Enabled: If this checkbox is disabled, Vidalia will not configure the
+ given hidden service in Tor. This can be useful for keeping the
+ configuration of a currently unused service for later use. All
+ non-enabled services are stored in the Vidalia-specific configuration
+ file vidalia.conf.</li>
+</ul>
+</p>
+
+<a name="buttons"/>
+<h3>What are the five buttons used for?</h3>
+<p>
+<ul>
+ <li>Add service: Creates a new empty service configuration.</li>
+ <li>Remove service: Permanently removes a hidden service configuration.
+ (If you want to temporarily remove a service, uncheck its Enabled
+ checkbox.)</li>
+ <li>Copy to clipboard: Copies the onion address to the clipboard, so
+ that you can tell it to whoever shall be able to use your
+ service.</li>
+ <li>Browse: Lets you browse to find a local hidden service
+ directory.</li>
+</ul>
+</p>
+
+<a name="advanced"/>
+<h3>How can I configure advanced hidden service settings?</h3>
+<p>
+Tor allows configuration of more specific settings for hidden services,
+e.g. forcing to use (or avoiding) certain nodes as introduction points, or
+providing multiple virtual ports for the same service.
+</p>
+
+<p>
+However, we decided to simplify things in Vidalia and provide only the most
+common settings. If you want to configure advanced settings, you need to do
+so in Tor's torrc file. Vidalia will not remove those settings even when
+you are editing your hidden services. If you specify more than one virtual
+port, only the first will be displayed and be editable.
+</p>
+
+<a name="client"/>
+<h3>How does Vidalia help me to access other hidden services?</h3>
+<p>
+Not at all. There is no need to do so. If you want to access another hidden
+service, type the service's onion address in your browser (or appropriate
+client application if it's not a web service), and Tor does the rest for
+you. There is no need to specifically configure Tor for that.
+</p>
+
+</body>
+</html>
+
Modified: vidalia/trunk/src/vidalia/i18n/vidalia_de.ts
===================================================================
--- vidalia/trunk/src/vidalia/i18n/vidalia_de.ts 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/i18n/vidalia_de.ts 2008-04-12 18:23:28 UTC (rev 2504)
@@ -2229,6 +2229,119 @@
</message>
</context>
<context>
+ <name>ServicePage</name>
+ <message>
+ <location filename="../config/servicepage.ui" line="31"/>
+ <source>Provided Hidden Services</source>
+ <translation>Versteckte Dienste</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="56"/>
+ <source>Onion Address</source>
+ <translation>Onion Adresse</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="61"/>
+ <source>Virtua Port</source>
+ <translation>Virtueller Port</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="66"/>
+ <source>Target</source>
+ <translation>Ziel</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="71"/>
+ <source>Directory Path</source>
+ <translation>Verzeichnispfad</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="76"/>
+ <source>Enabled</source>
+ <translation>Gestartet</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="84"/>
+ <source>Add new service to list</source>
+ <translation>Füge einen neuen Service hinzu</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="97"/>
+ <source>Remove selected service from list</source>
+ <translation>Entferne den gewählten Service</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="110"/>
+ <source>Copy onion address of selected service to clipboard</source>
+ <translation>Kopiere die Onion Adresse in die Zwischenablage</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="123"/>
+ <source>Browse in local file system and choose directory for selected service</source>
+ <translation>Durchsuchen Sie ihr lokales Dateisystem um ein Verzeichnis auszuwählen</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="27"/>
+ <source>Services</source>
+ <translation>Dienste</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="105"/>
+ <source>Error while trying to unpublish all services</source>
+ <translation>Fehler beim Versuch alle Dienste zu stoppen</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="137"/>
+ <source>Error while trying to publish services</source>
+ <translation>Fehler beim Versuch Dienste zu starten</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="274"/>
+ <source>Directory not found</source>
+ <translation>Verzeichnis nicht gefunden</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="330"/>
+ <source>Directory not found</source>
+ <translation>Verzeichnis nicht gefunden</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="374"/>
+ <source>Created by Tor</source>
+ <translation>Generiert von Tor</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="400"/>
+ <source>Error</source>
+ <translation>Fehler</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="400"/>
+ <source>Please select a Service</source>
+ <translation>Bitte einen Dienst wählen</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="447"/>
+ <source>Select Service Directory</source>
+ <translation>Verzeichnis auswählen</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="536"/>
+ <source>Virtual Port may only contain valid port numbers</source>
+ <translation>Virtueller Port ist nicht gültig, nur Werte aus dem Bereich</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="567"/>
+ <source>Target may only contain address:port, address, or port</source>
+ <translation>Ziel darf nur aus Adresse:Port, Adresse oder Port bestehen</translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="587"/>
+ <source>Directory already in use by another service</source>
+ <translation>Verzeichnis bereits von einem anderen Dienst benutzt</translation>
+ </message>
+</context>
+<context>
<name>Stream</name>
<message>
<location filename="../../torcontrol/stream.cpp" line="129"/>
Modified: vidalia/trunk/src/vidalia/i18n/vidalia_en.ts
===================================================================
--- vidalia/trunk/src/vidalia/i18n/vidalia_en.ts 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/i18n/vidalia_en.ts 2008-04-12 18:23:28 UTC (rev 2504)
@@ -2198,6 +2198,119 @@
</message>
</context>
<context>
+ <name>ServicePage</name>
+ <message>
+ <location filename="../config/servicepage.ui" line="31"/>
+ <source>Provided Hidden Services</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="56"/>
+ <source>Onion Address</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="61"/>
+ <source>Virtua Port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="66"/>
+ <source>Target</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="71"/>
+ <source>Directory Path</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="76"/>
+ <source>Enabled</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="84"/>
+ <source>Add new service to list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="97"/>
+ <source>Remove selected service from list</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="110"/>
+ <source>Copy onion address of selected service to clipboard</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.ui" line="123"/>
+ <source>Browse in local file system and choose directory for selected service</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="27"/>
+ <source>Services</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="105"/>
+ <source>Error while trying to unpublish all services</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="137"/>
+ <source>Error while trying to publish services</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="274"/>
+ <source>Directory not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="330"/>
+ <source>Directory not found</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="374"/>
+ <source>Created by Tor</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="400"/>
+ <source>Error</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="400"/>
+ <source>Please select a Service</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="447"/>
+ <source>Select Service Directory</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="536"/>
+ <source>Virtual Port may only contain valid port numbers</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="567"/>
+ <source>Target may only contain address:port, address, or port</source>
+ <translation type="unfinished"></translation>
+ </message>
+ <message>
+ <location filename="../config/servicepage.cpp" line="587"/>
+ <source>Directory already in use by another service</source>
+ <translation type="unfinished"></translation>
+ </message>
+</context>
+<context>
<name>Stream</name>
<message>
<location filename="../../torcontrol/stream.cpp" line="129"/>
Added: vidalia/trunk/src/vidalia/res/22x22/folder.png
===================================================================
(Binary files differ)
Property changes on: vidalia/trunk/src/vidalia/res/22x22/folder.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Added: vidalia/trunk/src/vidalia/res/22x22/service.png
===================================================================
(Binary files differ)
Property changes on: vidalia/trunk/src/vidalia/res/22x22/service.png
___________________________________________________________________
Name: svn:mime-type
+ application/octet-stream
Modified: vidalia/trunk/src/vidalia/res/vidalia_common.qrc
===================================================================
--- vidalia/trunk/src/vidalia/res/vidalia_common.qrc 2008-04-12 17:38:48 UTC (rev 2503)
+++ vidalia/trunk/src/vidalia/res/vidalia_common.qrc 2008-04-12 18:23:28 UTC (rev 2504)
@@ -39,6 +39,7 @@
<file>22x22/edit-select-all.png</file>
<file>22x22/emblem-system.png</file>
<file>22x22/emblem-unreadable.png</file>
+ <file>22x22/folder.png</file>
<file>22x22/format-justify-fill.png</file>
<file>22x22/go-down.png</file>
<file>22x22/go-home.png</file>
@@ -55,6 +56,7 @@
<file>22x22/preferences-desktop-locale.png</file>
<file>22x22/preferences-system.png</file>
<file>22x22/save-all.png</file>
+ <file>22x22/service.png</file>
<file>22x22/system-search.png</file>
<file>22x22/utilities-system-monitor.png</file>
<file>22x22/view-refresh.png</file>