Vidalia 0.2.10

AdvancedPage.cpp

Go to the documentation of this file.
00001 /*
00002 **  This file is part of Vidalia, and is subject to the license terms in the
00003 **  LICENSE file, found in the top level directory of this distribution. If you
00004 **  did not receive the LICENSE file with this file, you may obtain it from the
00005 **  Vidalia source package distributed by the Vidalia Project at
00006 **  http://www.vidalia-project.net/. No part of Vidalia, including this file,
00007 **  may be copied, modified, propagated, or distributed except according to the
00008 **  terms described in the LICENSE file.
00009 */
00010 
00011 /*
00012 ** \file AdvancedPage.cpp
00013 ** \version $Id: AdvancedPage.cpp 4353 2010-07-14 15:50:50Z edmanm $
00014 ** \brief Advanced Tor and Vidalia configuration options
00015 */
00016 
00017 #include "AdvancedPage.h"
00018 #include "Vidalia.h"
00019 #include "VMessageBox.h"
00020 #include "IpValidator.h"
00021 #include "Local8BitStringValidator.h"
00022 
00023 #include "file.h"
00024 
00025 #if defined(Q_WS_WIN)
00026 #include "TorService.h"
00027 #endif
00028 
00029 #include <QFile>
00030 #include <QFileInfo>
00031 #include <QHostAddress>
00032 #include <QTextCodec>
00033 
00034 
00035 /** Constructor */
00036 AdvancedPage::AdvancedPage(QWidget *parent)
00037   : ConfigPage(parent, "Advanced")
00038 {
00039   /* Invoke the Qt Designer generated object setup routine */
00040   ui.setupUi(this);
00041 
00042   /* Create TorSettings object */
00043   _settings = new TorSettings(Vidalia::torControl());
00044 
00045   /* Set validators for the control port and IP address fields */
00046   ui.lineControlAddress->setValidator(new IpValidator(this));
00047   ui.lineControlPort->setValidator(new QIntValidator(1, 65535, this));
00048 
00049   /* Set encoding validators for text boxes containing values that may be
00050    * passed to Tor via the control port. */
00051   ui.lineTorConfig->setValidator(new Local8BitStringValidator(this));
00052   ui.lineTorDataDirectory->setValidator(new Local8BitStringValidator(this));
00053   ui.linePassword->setValidator(new Local8BitStringValidator(this));
00054 
00055   /* Bind event to actions */
00056   connect(ui.btnBrowseTorConfig, SIGNAL(clicked()), this, SLOT(browseTorConfig()));
00057   connect(ui.btnBrowseTorDataDirectory, SIGNAL(clicked()),
00058           this, SLOT(browseTorDataDirectory()));
00059   connect(ui.cmbAuthMethod, SIGNAL(currentIndexChanged(int)),
00060           this, SLOT(authMethodChanged(int)));
00061   connect(ui.chkRandomPassword, SIGNAL(toggled(bool)),
00062           ui.linePassword, SLOT(setDisabled(bool)));
00063 
00064   /* Hide platform specific features */
00065 #if defined(Q_WS_WIN)
00066 #if 0
00067   ui.grpService->setVisible(TorService::isSupported());
00068 #endif
00069 #endif
00070 }
00071 
00072 /** Destructor */
00073 AdvancedPage::~AdvancedPage()
00074 {
00075   delete _settings;
00076 }
00077 
00078 /** Called when the user changes the UI translation. */
00079 void
00080 AdvancedPage::retranslateUi()
00081 {
00082   ui.retranslateUi(this);
00083 }
00084 
00085 /** Applies the network configuration settings to Tor. Returns true if the
00086  * settings were applied successfully. Otherwise, <b>errmsg</b> is set
00087  * and false is returned. */
00088 bool
00089 AdvancedPage::apply(QString &errmsg)
00090 {
00091   return _settings->apply(&errmsg);
00092 }
00093 
00094 /** Reverts the Tor configuration settings to their values at the last
00095  * time they were successfully applied to Tor. */
00096 bool
00097 AdvancedPage::changedSinceLastApply()
00098 {
00099   return _settings->changedSinceLastApply();
00100 }
00101 
00102 /** Returns true if the user has changed their advanced Tor settings since
00103  * the last time they were applied to Tor. */
00104 void
00105 AdvancedPage::revert()
00106 {
00107   return _settings->revert();
00108 }
00109 
00110 /** Saves all settings for this page. */
00111 bool
00112 AdvancedPage::save(QString &errmsg)
00113 {
00114   /* Validate the control listener address */
00115   QHostAddress controlAddress(ui.lineControlAddress->text());
00116   if (controlAddress.isNull()) {
00117     errmsg = tr("'%1' is not a valid IP address.")
00118                .arg(ui.lineControlAddress->text());
00119     return false; 
00120   }
00121   
00122   /* Validate the selected authentication options */
00123   TorSettings::AuthenticationMethod authMethod = 
00124     indexToAuthMethod(ui.cmbAuthMethod->currentIndex());
00125   if (authMethod == TorSettings::PasswordAuth
00126         && ui.linePassword->text().isEmpty()
00127         && !ui.chkRandomPassword->isChecked()) {
00128     errmsg = tr("You selected 'Password' authentication, but did not "
00129                 "specify a password.");
00130     return false;
00131   }
00132 
00133   /* Ensure that the DataDirectory and torrc options only contain characters
00134    * that are valid in the local 8-bit encoding. */
00135   if (! Local8BitStringValidator::canEncode(ui.lineTorConfig->text())) {
00136     errmsg = tr("The specified Tor configuration file location contains "
00137                 "characters that cannot be represented in your system's "
00138                 "current 8-bit character encoding.");
00139     return false;
00140   }
00141   if (! Local8BitStringValidator::canEncode(ui.lineTorDataDirectory->text())) {
00142     errmsg = tr("The specified Tor data directory location contains "
00143                 "characters that cannot be represented in your system's "
00144                 "current 8-bit character encoding.");
00145     return false;
00146   }
00147 
00148   /* Only remember the torrc and datadir values if Vidalia started Tor, or
00149    * if the user changed the displayed values. */
00150   if (!Vidalia::torControl()->isVidaliaRunningTor()) {
00151     QString torrc = ui.lineTorConfig->text();
00152     if (torrc != _settings->getTorrc())
00153       _settings->setTorrc(torrc);
00154 
00155     QString dataDir = ui.lineTorDataDirectory->text();
00156     if (dataDir != _settings->getDataDirectory())
00157       _settings->setDataDirectory(dataDir);
00158   } else {
00159     _settings->setTorrc(ui.lineTorConfig->text());
00160     _settings->setDataDirectory(ui.lineTorDataDirectory->text());
00161   }
00162 
00163   _settings->setControlAddress(controlAddress);
00164   _settings->setControlPort(ui.lineControlPort->text().toUShort());
00165 
00166   _settings->setAuthenticationMethod(authMethod);
00167   _settings->setUseRandomPassword(ui.chkRandomPassword->isChecked());
00168   if (authMethod == TorSettings::PasswordAuth
00169         && !ui.chkRandomPassword->isChecked())
00170     _settings->setControlPassword(ui.linePassword->text());
00171 
00172 #if 0
00173 #if defined(Q_WS_WIN)
00174   /* Install or uninstall the Tor service as necessary */
00175   setupService(ui.chkUseService->isChecked());
00176 #endif
00177 #endif
00178 
00179   return true;
00180 }
00181 
00182 /** Loads previously saved settings. */
00183 void
00184 AdvancedPage::load()
00185 {
00186   ui.lineControlAddress->setText(_settings->getControlAddress().toString());
00187   ui.lineControlPort->setText(QString::number(_settings->getControlPort()));
00188   ui.lineTorConfig->setText(_settings->getTorrc());
00189   ui.lineTorDataDirectory->setText(_settings->getDataDirectory());
00190 
00191   ui.cmbAuthMethod->setCurrentIndex(
00192     authMethodToIndex(_settings->getAuthenticationMethod()));
00193   ui.chkRandomPassword->setChecked(_settings->useRandomPassword());
00194   if (!ui.chkRandomPassword->isChecked())
00195     ui.linePassword->setText(_settings->getControlPassword());
00196 
00197 #if 0
00198 #if defined(Q_WS_WIN)
00199   TorService s;
00200   ui.chkUseService->setChecked(s.isInstalled());
00201 #endif
00202 #endif
00203 }
00204 
00205 /** Called when the user selects a different authentication method from the
00206  * combo box. */
00207 void
00208 AdvancedPage::authMethodChanged(int index)
00209 {
00210   bool usePassword = (indexToAuthMethod(index) == TorSettings::PasswordAuth);
00211   ui.linePassword->setEnabled(usePassword && !ui.chkRandomPassword->isChecked());
00212   ui.chkRandomPassword->setEnabled(usePassword);
00213 }
00214 
00215 /** Returns the authentication method for the given <b>index</b>. */
00216 TorSettings::AuthenticationMethod
00217 AdvancedPage::indexToAuthMethod(int index)
00218 {
00219   switch (index) {
00220     case 0: return TorSettings::NullAuth;
00221     case 1: return TorSettings::CookieAuth;
00222     case 2: return TorSettings::PasswordAuth;
00223     default: break;
00224   }
00225   return TorSettings::UnknownAuth;
00226 }
00227 
00228 /** Returns the index in the authentication methods combo box for the given
00229  * authentication <b>method</b>. */
00230 int
00231 AdvancedPage::authMethodToIndex(TorSettings::AuthenticationMethod method)
00232 {
00233   switch (method) {
00234     case TorSettings::NullAuth: return 0;
00235     case TorSettings::CookieAuth: return 1;
00236     default: break;
00237   }
00238   return 2;
00239 }
00240 
00241 /** Open a QFileDialog to browse for Tor config file. */
00242 void
00243 AdvancedPage::browseTorConfig()
00244 {
00245   /* Prompt the user to select a file or create a new one */
00246   QString filename = QFileDialog::getOpenFileName(this, 
00247                        tr("Select Tor Configuration File"),
00248                        QFileInfo(ui.lineTorConfig->text()).filePath(),
00249                        tr("Tor Configuration File (torrc);;All Files (*)"));
00250 
00251   /* Make sure a filename was selected */
00252   if (filename.isEmpty()) {
00253     return;
00254   }
00255 
00256   /* Check if the file exists */
00257   QFile torrcFile(filename);
00258   if (!QFileInfo(filename).exists()) {
00259     /* The given file does not exist. Should we create it? */
00260     int response = VMessageBox::question(this,
00261                      tr("File Not Found"),
00262                      tr("%1 does not exist. Would you like to create it?")
00263                                                             .arg(filename),
00264                      VMessageBox::Yes, VMessageBox::No);
00265     
00266     if (response == VMessageBox::No) {
00267       /* Don't create it. Just bail. */
00268       return;
00269     }
00270     /* Attempt to create the specified file */
00271     QString errmsg;
00272     if (!touch_file(filename, false, &errmsg)) {
00273       VMessageBox::warning(this,
00274         tr("Failed to Create File"),
00275         tr("Unable to create %1 [%2]").arg(filename)
00276                                       .arg(errmsg),
00277         VMessageBox::Ok);
00278       return;
00279     }
00280   }
00281   ui.lineTorConfig->setText(filename);
00282 }
00283 
00284 /** Opens a QFileDialog for the user to browse to or create a directory for
00285  * Tor's DataDirectory. */
00286 void
00287 AdvancedPage::browseTorDataDirectory()
00288 {
00289   QString dataDir = QFileDialog::getExistingDirectory(this,
00290                       tr("Select a Directory to Use for Tor Data"),
00291                       ui.lineTorDataDirectory->text());
00292 
00293   if (!dataDir.isEmpty()) 
00294     ui.lineTorDataDirectory->setText(dataDir);
00295 }
00296 
00297 #if 0
00298 #if defined(Q_WS_WIN)
00299 /** Installs or removes the Tor service as necessary. */
00300 void
00301 AdvancedPage::setupService(bool useService)
00302 {
00303   TorService service;
00304   bool isInstalled = service.isInstalled();
00305 
00306   if (!useService && isInstalled) {
00307     /* Uninstall if we don't want to use it anymore */
00308     Vidalia::torControl()->stop();
00309     
00310     if (!service.remove()) {
00311       VMessageBox::critical(this,
00312                             tr("Unable to remove Tor Service"),
00313                             tr("Vidalia was unable to remove the Tor service.\n\n"
00314                                "You may need to remove it manually."), 
00315                             VMessageBox::Ok, VMessageBox::Cancel);
00316     }
00317   } else if (useService && !isInstalled) {
00318     /* Install if we want to start using a service */
00319     if (!service.install(_settings->getExecutable(),
00320                          _settings->getTorrc(),
00321                          _settings->getControlPort())) {
00322       VMessageBox::critical(this,
00323                             tr("Unable to install Tor Service"),
00324                             tr("Vidalia was unable to install the Tor service."),
00325                             VMessageBox::Ok, VMessageBox::Cancel);
00326     }
00327   }
00328 }
00329 #endif
00330 #endif
00331