Vidalia 0.2.10
|
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