Vidalia 0.3.1
AdvancedPage.cpp
Go to the documentation of this file.
1/*
2** This file is part of Vidalia, and is subject to the license terms in the
3** LICENSE file, found in the top level directory of this distribution. If you
4** did not receive the LICENSE file with this file, you may obtain it from the
5** Vidalia source package distributed by the Vidalia Project at
6** http://www.torproject.org/projects/vidalia.html. No part of Vidalia,
7** including this file, may be copied, modified, propagated, or distributed
8** except according to the terms described in the LICENSE file.
9*/
10
11/*
12** \file AdvancedPage.cpp
13** \brief Advanced Tor and Vidalia configuration options
14*/
15
16#include "AdvancedPage.h"
17#include "TorrcDialog.h"
18#include "Vidalia.h"
19#include "VMessageBox.h"
20#include "IpValidator.h"
22
23#include "file.h"
24
25#if defined(Q_WS_WIN)
26#include "TorService.h"
27#endif
28
29#include <QFile>
30#include <QFileInfo>
31#include <QHostAddress>
32#include <QTextCodec>
33
34
35/** Constructor */
37 : ConfigPage(parent, "Advanced")
38{
39 /* Invoke the Qt Designer generated object setup routine */
40 ui.setupUi(this);
41
42 /* Create TorSettings object */
44
45 /* Set validators for the control port and IP address fields */
46 ui.lineControlAddress->setValidator(new IpValidator(this));
47 ui.lineControlPort->setValidator(new QIntValidator(1, 65535, this));
48
49 /* Set encoding validators for text boxes containing values that may be
50 * passed to Tor via the control port. */
51 ui.lineTorConfig->setValidator(new Local8BitStringValidator(this));
52 ui.lineTorDataDirectory->setValidator(new Local8BitStringValidator(this));
53 ui.linePassword->setValidator(new Local8BitStringValidator(this));
54
55 /* Bind event to actions */
56 connect(ui.btnBrowseTorConfig, SIGNAL(clicked()), this, SLOT(browseTorConfig()));
57 connect(ui.btnBrowseTorDataDirectory, SIGNAL(clicked()),
58 this, SLOT(browseTorDataDirectory()));
59 connect(ui.cmbAuthMethod, SIGNAL(currentIndexChanged(int)),
60 this, SLOT(authMethodChanged(int)));
61 connect(ui.chkRandomPassword, SIGNAL(toggled(bool)),
62 ui.linePassword, SLOT(setDisabled(bool)));
63 connect(ui.chkRandomPassword, SIGNAL(toggled(bool)),
64 this, SLOT(displayWarning(bool)));
65 connect(ui.btnEditTorConfig, SIGNAL(clicked()),
66 this, SLOT(displayTorrcDialog()));
67 connect(ui.rdoControlPort, SIGNAL(toggled(bool)), this, SLOT(toggleControl(bool)));
68 connect(ui.btnBrowseSocketPath, SIGNAL(clicked()), this, SLOT(browseSocketPath()));
69 connect(ui.chkAuto, SIGNAL(toggled(bool)), this, SLOT(toggleAuto(bool)));
70
71 /* Hide platform specific features */
72#if defined(Q_WS_WIN)
73#if 0
74 ui.grpService->setVisible(TorService::isSupported());
75#endif
76 /* Disable ControlSocket */
77 ui.rdoControlSocket->setEnabled(false);
78#endif
79}
80
81/** Destructor */
83{
84 delete _settings;
85}
86
87/** Called when the user changes the UI translation. */
88void
90{
91 ui.retranslateUi(this);
92}
93
94/** Applies the network configuration settings to Tor. Returns true if the
95 * settings were applied successfully. Otherwise, <b>errmsg</b> is set
96 * and false is returned. */
97bool
98AdvancedPage::apply(QString &errmsg)
99{
100 return _settings->apply(&errmsg);
101}
102
103/** Reverts the Tor configuration settings to their values at the last
104 * time they were successfully applied to Tor. */
105bool
107{
109}
110
111/** Returns true if the user has changed their advanced Tor settings since
112 * the last time they were applied to Tor. */
113void
115{
116 return _settings->revert();
117}
118
119/** Saves all settings for this page. */
120bool
121AdvancedPage::save(QString &errmsg)
122{
123 QHostAddress controlAddress(ui.lineControlAddress->text());
124 QString path(ui.lineSocketPath->text());
125
126 if(ui.chkAuto->isChecked()) {
127 if(ui.lineTorDataDirectory->text().isEmpty()) {
128 errmsg = tr("You've checked the autoconfiguration option for the ControlPort, but"
129 " provided no Data Directory. Please add one, or uncheck the"
130 " \"Configure ControlPort automatically\" option.");
131 return false;
132 }
134 }
135
136 /* Validate the control settings */
137 if(ui.rdoControlPort->isChecked()) {
138 if (controlAddress.isNull()) {
139 errmsg = tr("'%1' is not a valid IP address.")
140 .arg(ui.lineControlAddress->text());
141 return false;
142 }
144 } else {
145 QFileInfo finfo(path);
146 if(!finfo.exists()) {
147 errmsg = tr("ControlSocket path doesn't exist.");
148 return false;
149 }
151 }
152
153 /* Validate the selected authentication options */
155 indexToAuthMethod(ui.cmbAuthMethod->currentIndex());
156 if (authMethod == TorSettings::PasswordAuth
157 && ui.linePassword->text().isEmpty()
158 && !ui.chkRandomPassword->isChecked()) {
159 errmsg = tr("You selected 'Password' authentication, but did not "
160 "specify a password.");
161 return false;
162 }
163
164 /* Ensure that the DataDirectory and torrc options only contain characters
165 * that are valid in the local 8-bit encoding. */
166 if (! Local8BitStringValidator::canEncode(ui.lineTorConfig->text())) {
167 errmsg = tr("The specified Tor configuration file location contains "
168 "characters that cannot be represented in your system's "
169 "current 8-bit character encoding.");
170 return false;
171 }
172 if (! Local8BitStringValidator::canEncode(ui.lineTorDataDirectory->text())) {
173 errmsg = tr("The specified Tor data directory location contains "
174 "characters that cannot be represented in your system's "
175 "current 8-bit character encoding.");
176 return false;
177 }
178
179 /* Only remember the torrc and datadir values if Vidalia started Tor, or
180 * if the user changed the displayed values. */
183 QString torrc = ui.lineTorConfig->text();
184 if (torrc != _settings->getTorrc()) {
185 _settings->setTorrc(torrc);
187 QMessageBox::StandardButtons res = QMessageBox::question(this, tr("Warning"),
188 tr("You changed torrc path, would you like to restart Tor?"),
189 QMessageBox::Yes | QMessageBox::No);
190 if(res == QMessageBox::Yes)
191 emit restartTor();
192 }
193 }
194
195 QString dataDir = ui.lineTorDataDirectory->text();
196 if (dataDir != _settings->getDataDirectory())
197 _settings->setDataDirectory(dataDir);
198 }
199
200 if(!ui.chkAuto->isChecked()) {
201 _settings->setControlAddress(controlAddress);
202 _settings->setControlPort(ui.lineControlPort->text().toUShort());
204 }
205 _settings->setSocketPath(ui.lineSocketPath->text());
206
208 _settings->setUseRandomPassword(ui.chkRandomPassword->isChecked());
209 if (authMethod == TorSettings::PasswordAuth
210 && !ui.chkRandomPassword->isChecked())
211 _settings->setControlPassword(ui.linePassword->text());
212
213#if 0
214#if defined(Q_WS_WIN)
215 /* Install or uninstall the Tor service as necessary */
216 setupService(ui.chkUseService->isChecked());
217#endif
218#endif
219
220 return true;
221}
222
223/** Loads previously saved settings. */
224void
226{
227 ui.lineControlAddress->setText(_settings->getControlAddress().toString());
228 ui.lineControlPort->setText(QString::number(_settings->getControlPort()));
229 ui.lineTorConfig->setText(_settings->getTorrc());
230 ui.lineTorDataDirectory->setText(_settings->getDataDirectory());
231 ui.chkAuto->setChecked(_settings->autoControlPort());
232
233 ui.cmbAuthMethod->setCurrentIndex(
235 ui.chkRandomPassword->setChecked(_settings->useRandomPassword());
236 if (!ui.chkRandomPassword->isChecked())
237 ui.linePassword->setText(_settings->getControlPassword());
238 ui.rdoControlPort->setChecked(_settings->getControlMethod() == ControlMethod::Port);
239 ui.rdoControlSocket->setChecked(_settings->getControlMethod() == ControlMethod::Socket);
240 ui.lineSocketPath->setText(_settings->getSocketPath());
241
242#if 0
243#if defined(Q_WS_WIN)
244 TorService s;
245 ui.chkUseService->setChecked(s.isInstalled());
246#endif
247#endif
248 if(Vidalia::torControl()->getTorVersion() < 0x2021a) { // 0x2021a == 0.2.2.26
249 ui.chkAuto->setChecked(false);
250 ui.chkAuto->setVisible(false);
251 }
252}
253
254/** Called when the user selects a different authentication method from the
255 * combo box. */
256void
258{
259 bool usePassword = (indexToAuthMethod(index) == TorSettings::PasswordAuth);
260 ui.linePassword->setEnabled(usePassword && !ui.chkRandomPassword->isChecked());
261 ui.chkRandomPassword->setEnabled(usePassword);
262 ui.lblWarn->setVisible((ui.chkRandomPassword->checkState() == Qt::Unchecked) and usePassword);
263}
264
265/** Returns the authentication method for the given <b>index</b>. */
268{
269 switch (index) {
270 case 0: return TorSettings::NullAuth;
271 case 1: return TorSettings::CookieAuth;
272 case 2: return TorSettings::PasswordAuth;
273 default: break;
274 }
276}
277
278/** Returns the index in the authentication methods combo box for the given
279 * authentication <b>method</b>. */
280int
282{
283 switch (method) {
284 case TorSettings::NullAuth: return 0;
285 case TorSettings::CookieAuth: return 1;
286 default: break;
287 }
288 return 2;
289}
290
291/** Open a QFileDialog to browse for Tor config file. */
292void
294{
295 /* Prompt the user to select a file or create a new one */
296 QString filename = QFileDialog::getOpenFileName(this,
297 tr("Select Tor Configuration File"),
298 QFileInfo(ui.lineTorConfig->text()).filePath(),
299 tr("Tor Configuration File (torrc);;All Files (*)"));
300
301 /* Make sure a filename was selected */
302 if (filename.isEmpty()) {
303 return;
304 }
305
306 /* Check if the file exists */
307 QFile torrcFile(filename);
308 if (!QFileInfo(filename).exists()) {
309 /* The given file does not exist. Should we create it? */
310 int response = VMessageBox::question(this,
311 tr("File Not Found"),
312 tr("%1 does not exist. Would you like to create it?")
313 .arg(filename),
315
316 if (response == VMessageBox::No) {
317 /* Don't create it. Just bail. */
318 return;
319 }
320 /* Attempt to create the specified file */
321 QString errmsg;
322 if (!touch_file(filename, false, &errmsg)) {
324 tr("Failed to Create File"),
325 tr("Unable to create %1 [%2]").arg(filename)
326 .arg(errmsg),
328 return;
329 }
330 }
331 ui.lineTorConfig->setText(filename);
332}
333
334/** Opens a QFileDialog for the user to browse to or create a directory for
335 * Tor's DataDirectory. */
336void
338{
339 QString dataDir = QFileDialog::getExistingDirectory(this,
340 tr("Select a Directory to Use for Tor Data"),
341 ui.lineTorDataDirectory->text());
342
343 if (!dataDir.isEmpty())
344 ui.lineTorDataDirectory->setText(dataDir);
345}
346
347/** Opens a QFileDialog for the user to browse to or create a socket path to
348 * communicate to Tor */
349void
351{
352 QString start = QDir::currentPath();
353 if(!ui.lineSocketPath->text().isEmpty())
354 start = ui.lineSocketPath->text();
355 QString socketPath = QFileDialog::getOpenFileName(this,
356 tr("Select a file to use for Tor socket path"),
357 start);
358
359 if (!socketPath.isEmpty())
360 ui.lineSocketPath->setText(socketPath);
361}
362
363#if 0
364#if defined(Q_WS_WIN)
365/** Installs or removes the Tor service as necessary. */
366void
367AdvancedPage::setupService(bool useService)
368{
369 TorService service;
370 bool isInstalled = service.isInstalled();
371
372 if (!useService && isInstalled) {
373 /* Uninstall if we don't want to use it anymore */
375
376 if (!service.remove()) {
378 tr("Unable to remove Tor Service"),
379 tr("Vidalia was unable to remove the Tor service.\n\n"
380 "You may need to remove it manually."),
382 }
383 } else if (useService && !isInstalled) {
384 /* Install if we want to start using a service */
385 if (!service.install(_settings->getExecutable(),
389 tr("Unable to install Tor Service"),
390 tr("Vidalia was unable to install the Tor service."),
392 }
393 }
394}
395#endif
396#endif
397
398/** Called when the user presses the Edit current torrc button */
399void
401{
402 TorrcDialog rcdialog(this);
403 rcdialog.exec();
404}
405
406void
408{
409 if(ui.rdoControlPort->isChecked()) {
410 ui.lblAddress->setEnabled(true);
411 ui.lineControlAddress->setEnabled(true);
412 ui.lineControlPort->setEnabled(true);
413 ui.lblPath->setEnabled(false);
414 ui.lineSocketPath->setEnabled(false);
415 ui.btnBrowseSocketPath->setEnabled(false);
416 ui.chkAuto->setEnabled(true);
417 } else {
418#if !defined(Q_OS_WIN32)
419 ui.lblAddress->setEnabled(false);
420 ui.lineControlAddress->setEnabled(false);
421 ui.lineControlPort->setEnabled(false);
422 ui.lblPath->setEnabled(true);
423 ui.lineSocketPath->setEnabled(true);
424 ui.btnBrowseSocketPath->setEnabled(true);
425 ui.chkAuto->setEnabled(false);
426#endif
427 }
428}
429
430void
432{
433 ui.lblAddress->setVisible(!ui.chkAuto->isChecked());
434 ui.lineControlAddress->setVisible(!ui.chkAuto->isChecked());
435 ui.label->setVisible(!ui.chkAuto->isChecked());
436 ui.lineControlPort->setVisible(!ui.chkAuto->isChecked());
437}
438
439void
441{
442 ui.lblWarn->setVisible(!checked and
443 indexToAuthMethod(ui.cmbAuthMethod->currentIndex()) ==
445}
stop errmsg connect(const QHostAddress &address, quint16 port)
stop errmsg isConnected()
getTorVersion()
stop errmsg isVidaliaRunningTor()
virtual bool changedSinceLastApply() const
void restartTor()
TorSettings * _settings
Definition: AdvancedPage.h:99
void toggleControl(bool)
Ui::AdvancedPage ui
Definition: AdvancedPage.h:101
AdvancedPage(QWidget *parent=0)
void browseTorDataDirectory()
void browseTorConfig()
TorSettings::AuthenticationMethod indexToAuthMethod(int index)
void browseSocketPath()
int authMethodToIndex(TorSettings::AuthenticationMethod method)
bool changedSinceLastApply()
bool apply(QString &errmsg)
void toggleAuto(bool)
virtual void retranslateUi()
void authMethodChanged(int index)
void displayTorrcDialog()
bool save(QString &errmsg)
void displayWarning(bool)
static bool canEncode(const QString &input)
bool stop(QString *errmsg=0)
Definition: TorControl.cpp:131
bool remove()
Definition: TorService.cpp:280
bool isInstalled()
Definition: TorService.cpp:119
bool install(const QString &torPath, const QString &torrc, quint16 controlPort)
Definition: TorService.cpp:239
static bool isSupported()
Definition: TorService.cpp:48
void setControlPassword(const QString &password)
bool apply(QString *errmsg=0)
QString getExecutable() const
bool useRandomPassword() const
void setUseRandomPassword(bool useRandomPassword)
QString getControlPassword() const
void setControlAddress(const QHostAddress &addr)
quint16 getControlPort() const
QHostAddress getControlAddress() const
void setTorrc(const QString &torrc)
void setAuthenticationMethod(AuthenticationMethod method)
QString getDataDirectory() const
void setControlMethod(ControlMethod::Method method)
void setSocketPath(const QString &path)
QString getTorrc() const
void setDataDirectory(const QString &dataDir)
void setControlPort(quint16 port)
QString getSocketPath() const
ControlMethod::Method getControlMethod() const
bool autoControlPort() const
void setAutoControlPort(const bool autoControl)
AuthenticationMethod getAuthenticationMethod() const
static int critical(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
static int warning(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton)
static int question(QWidget *parent, QString caption, QString text, int button0, int button1=NoButton, int button2=NoButton, QString remember=QString(), VSettings *settings=0, QString key=QString())
static TorControl * torControl()
Definition: Vidalia.h:76
bool touch_file(const QString &filename, bool createdir, QString *errmsg)
Definition: file.cpp:31