00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include <QMenu>
00018 #include <QIntValidator>
00019 #include <QClipboard>
00020 #include <QHostAddress>
00021 #include <networksettings.h>
00022 #include <vmessagebox.h>
00023 #include <vidalia.h>
00024 #include <stringutil.h>
00025
00026 #include "networkpage.h"
00027 #include "domainvalidator.h"
00028
00029 #define IMG_COPY ":/images/22x22/edit-copy.png"
00030
00031
00032
00033 NetworkPage::NetworkPage(QWidget *parent)
00034 : ConfigPage(parent, tr("Network"))
00035 {
00036
00037 ui.setupUi(this);
00038
00039 connect(ui.btnAddBridge, SIGNAL(clicked()), this, SLOT(addBridge()));
00040 connect(ui.btnRemoveBridge, SIGNAL(clicked()), this, SLOT(removeBridge()));
00041 connect(ui.btnCopyBridge, SIGNAL(clicked()),
00042 this, SLOT(copySelectedBridgesToClipboard()));
00043 connect(ui.listBridges, SIGNAL(customContextMenuRequested(QPoint)),
00044 this, SLOT(bridgeContextMenuRequested(QPoint)));
00045 connect(ui.listBridges, SIGNAL(itemSelectionChanged()),
00046 this, SLOT(bridgeSelectionChanged()));
00047 connect(ui.lineBridge, SIGNAL(returnPressed()), this, SLOT(addBridge()));
00048 connect(Vidalia::torControl(), SIGNAL(authenticated()),
00049 this, SLOT(onAuthenticated()));
00050 connect(Vidalia::torControl(), SIGNAL(disconnected()),
00051 this, SLOT(onDisconnected()));
00052 connect(ui.lblHelpFindBridges, SIGNAL(linkActivated(QString)),
00053 this, SLOT(onLinkActivated(QString)));
00054
00055 ui.lblNoBridgeSupport->setVisible(false);
00056 ui.lineHttpProxyAddress->setValidator(new DomainValidator(this));
00057 ui.lineHttpProxyPort->setValidator(new QIntValidator(1, 65535, this));
00058
00059 vApp->createShortcut(QKeySequence(QKeySequence::Copy),
00060 ui.listBridges, this,
00061 SLOT(copySelectedBridgesToClipboard()));
00062
00063 #if defined(Q_WS_MAC)
00064
00065
00066 ui.grpProxySettings->setTitle("");
00067 ui.grpFirewallSettings->setTitle("");
00068 ui.grpBridgeSettings->setTitle("");
00069 #endif
00070 }
00071
00072
00073
00074
00075 bool
00076 NetworkPage::apply(QString &errmsg)
00077 {
00078 return NetworkSettings(Vidalia::torControl()).apply(&errmsg);
00079 }
00080
00081
00082
00083 bool
00084 NetworkPage::changedSinceLastApply()
00085 {
00086 return NetworkSettings(Vidalia::torControl()).changedSinceLastApply();
00087 }
00088
00089
00090
00091 void
00092 NetworkPage::revert()
00093 {
00094 NetworkSettings settings(Vidalia::torControl());
00095 settings.revert();
00096 }
00097
00098
00099
00100
00101 void
00102 NetworkPage::onAuthenticated()
00103 {
00104 quint32 torVersion = Vidalia::torControl()->getTorVersion();
00105 if (torVersion < 0x020003) {
00106 ui.grpBridgeSettings->setEnabled(false);
00107 ui.lblNoBridgeSupport->setVisible(true);
00108 }
00109 }
00110
00111
00112
00113
00114 void
00115 NetworkPage::onDisconnected()
00116 {
00117 ui.grpBridgeSettings->setEnabled(true);
00118 ui.lblNoBridgeSupport->setVisible(false);
00119 }
00120
00121
00122
00123 void
00124 NetworkPage::onLinkActivated(const QString &url)
00125 {
00126 emit helpRequested(url);
00127 }
00128
00129
00130
00131
00132
00133
00134 bool
00135 NetworkPage::validateBridge(const QString &bridge, QString *out)
00136 {
00137 QString temp = bridge;
00138 if (temp.startsWith("bridge ", Qt::CaseInsensitive))
00139 temp = temp.remove(0, 7);
00140
00141 QStringList parts = temp.split(" ", QString::SkipEmptyParts);
00142 if (parts.isEmpty())
00143 return false;
00144
00145 QString s = parts.at(0);
00146 if (s.contains(":")) {
00147 if (s.endsWith(":"))
00148 return false;
00149
00150 int index = s.indexOf(":");
00151 QString host = s.mid(0, index);
00152 QString port = s.mid(index + 1);
00153 if (QHostAddress(host).isNull()
00154 || QHostAddress(host).protocol() != QAbstractSocket::IPv4Protocol
00155 || port.toUInt() < 1
00156 || port.toUInt() > 65535)
00157 return false;
00158 temp = s;
00159 if (parts.size() > 1) {
00160 QString fp = static_cast<QStringList>(parts.mid(1)).join("");
00161 if (fp.length() != 40 || !string_is_hex(fp))
00162 return false;
00163 temp += " " + fp.toUpper();
00164 }
00165 } else {
00166 QString fp = parts.join("");
00167 if (fp.length() != 40 || !string_is_hex(fp))
00168 return false;
00169 temp = fp.toUpper();
00170 }
00171 *out = temp;
00172 return true;
00173 }
00174
00175
00176 void
00177 NetworkPage::addBridge()
00178 {
00179 QString bridge;
00180 QString input = ui.lineBridge->text().trimmed();
00181
00182 if (input.isEmpty())
00183 return;
00184 if (!validateBridge(input, &bridge)) {
00185 VMessageBox::warning(this,
00186 tr("Invalid Bridge"),
00187 tr("The specified bridge identifier is not valid."),
00188 VMessageBox::Ok|VMessageBox::Default);
00189 return;
00190 }
00191 if (!ui.listBridges->findItems(bridge, Qt::MatchFixedString).isEmpty())
00192 return;
00193
00194 ui.listBridges->addItem(bridge);
00195 ui.lineBridge->clear();
00196 }
00197
00198
00199 void
00200 NetworkPage::removeBridge()
00201 {
00202 qDeleteAll(ui.listBridges->selectedItems());
00203 }
00204
00205
00206 void
00207 NetworkPage::copySelectedBridgesToClipboard()
00208 {
00209 QString contents;
00210
00211 foreach (QListWidgetItem *item, ui.listBridges->selectedItems()) {
00212 #if defined(Q_WS_WIN)
00213 contents += item->text() + "\r\n";
00214 #else
00215 contents += item->text() + "\n";
00216 #endif
00217 }
00218 if (!contents.isEmpty())
00219 vApp->clipboard()->setText(contents.trimmed());
00220 }
00221
00222
00223
00224 void
00225 NetworkPage::bridgeContextMenuRequested(const QPoint &pos)
00226 {
00227 QMenu menu(this);
00228
00229 QListWidgetItem *item = ui.listBridges->itemAt(pos);
00230 if (!item)
00231 return;
00232
00233 QAction *copyAction =
00234 new QAction(QIcon(IMG_COPY), tr("Copy (Ctrl+C)"), &menu);
00235 connect(copyAction, SIGNAL(triggered()),
00236 this, SLOT(copySelectedBridgesToClipboard()));
00237
00238 menu.addAction(copyAction);
00239 menu.exec(ui.listBridges->mapToGlobal(pos));
00240 }
00241
00242
00243 void
00244 NetworkPage::bridgeSelectionChanged()
00245 {
00246 bool enabled = !ui.listBridges->selectedItems().isEmpty();
00247 ui.btnCopyBridge->setEnabled(enabled);
00248 ui.btnRemoveBridge->setEnabled(enabled);
00249 }
00250
00251
00252 bool
00253 NetworkPage::save(QString &errmsg)
00254 {
00255 NetworkSettings settings(Vidalia::torControl());
00256 QStringList bridgeList;
00257 QList<quint16> reachablePorts;
00258 bool ok;
00259
00260 if (ui.chkUseProxy->isChecked()
00261 && (ui.lineHttpProxyAddress->text().isEmpty()
00262 || ui.lineHttpProxyPort->text().isEmpty())) {
00263 errmsg = tr("You must specify both an IP address or hostname and a "
00264 "port number to configure Tor to use a proxy to access "
00265 "the Internet.");
00266 return false;
00267 }
00268 if (ui.chkFascistFirewall->isChecked()
00269 && ui.lineReachablePorts->text().isEmpty()) {
00270 errmsg = tr("You must specify one or more ports to which your "
00271 "firewall allows you to connect.");
00272 return false;
00273 }
00274
00275
00276 settings.setUseHttpProxy(ui.chkUseProxy->isChecked());
00277 settings.setUseHttpsProxy(ui.chkProxyUseHttps->isChecked());
00278 if (!ui.lineHttpProxyAddress->text().isEmpty()) {
00279 QString proxy = ui.lineHttpProxyAddress->text();
00280 if (!ui.lineHttpProxyPort->text().isEmpty())
00281 proxy += ":" + ui.lineHttpProxyPort->text();
00282
00283 settings.setHttpProxy(proxy);
00284 settings.setHttpsProxy(proxy);
00285 } else {
00286 settings.setHttpProxy("");
00287 settings.setHttpsProxy("");
00288 }
00289
00290 if (!ui.lineHttpProxyUsername->text().isEmpty() ||
00291 !ui.lineHttpProxyPassword->text().isEmpty()) {
00292 QString auth = ui.lineHttpProxyUsername->text() + ":" +
00293 ui.lineHttpProxyPassword->text();
00294 settings.setHttpProxyAuthenticator(auth);
00295 settings.setHttpsProxyAuthenticator(auth);
00296 } else {
00297 settings.setHttpProxyAuthenticator("");
00298 settings.setHttpsProxyAuthenticator("");
00299 }
00300
00301
00302 settings.setFascistFirewall(ui.chkFascistFirewall->isChecked());
00303 foreach (QString portString,
00304 ui.lineReachablePorts->text().split(",", QString::SkipEmptyParts)) {
00305 quint32 port = portString.toUInt(&ok);
00306 if (!ok || port < 1 || port > 65535) {
00307 errmsg = tr("'%1' is not a valid port number.").arg(portString);
00308 return false;
00309 }
00310 reachablePorts << (quint16)port;
00311 }
00312 settings.setReachablePorts(reachablePorts);
00313
00314
00315 settings.setUseBridges(ui.chkUseBridges->isChecked());
00316 for (int i = 0; i < ui.listBridges->count(); i++)
00317 bridgeList << ui.listBridges->item(i)->text();
00318 settings.setBridgeList(bridgeList);
00319
00320 return true;
00321 }
00322
00323
00324 void
00325 NetworkPage::load()
00326 {
00327 NetworkSettings settings(Vidalia::torControl());
00328 QStringList reachablePortStrings;
00329
00330
00331 ui.chkUseProxy->setChecked(settings.getUseHttpProxy());
00332 ui.chkProxyUseHttps->setChecked(settings.getUseHttpsProxy());
00333 QStringList proxy = settings.getHttpProxy().split(":");
00334 QStringList proxyAuth = settings.getHttpProxyAuthenticator().split(":");
00335 if (proxy.size() >= 1)
00336 ui.lineHttpProxyAddress->setText(proxy.at(0));
00337 if (proxy.size() >= 2)
00338 ui.lineHttpProxyPort->setText(proxy.at(1));
00339 if (proxyAuth.size() >= 1)
00340 ui.lineHttpProxyUsername->setText(proxyAuth.at(0));
00341 if (proxyAuth.size() >= 2)
00342 ui.lineHttpProxyPassword->setText(proxyAuth.at(1));
00343
00344
00345 ui.chkFascistFirewall->setChecked(settings.getFascistFirewall());
00346 QList<quint16> reachablePorts = settings.getReachablePorts();
00347 foreach (quint16 port, reachablePorts) {
00348 reachablePortStrings << QString::number(port);
00349 }
00350 ui.lineReachablePorts->setText(reachablePortStrings.join(","));
00351
00352
00353 ui.chkUseBridges->setChecked(settings.getUseBridges());
00354 ui.listBridges->clear();
00355 ui.listBridges->addItems(settings.getBridgeList());
00356 }
00357