1 /***************************************************************************
2 *                                                                         *
3 *   This program is free software; you can redistribute it and/or modify  *
4 *   it under the terms of the GNU General Public License as published by  *
5 *   the Free Software Foundation; either version 3 of the License, or     *
6 *   (at your option) any later version.                                   *
7 *                                                                         *
8 ***************************************************************************/
9 
10 #include "SettingsConnection.h"
11 #include "MainWindow.h"
12 #include "WulforSettings.h"
13 #include "WulforUtil.h"
14 
15 #include "dcpp/stdinc.h"
16 #include "dcpp/SettingsManager.h"
17 #include "dcpp/Socket.h"
18 
19 #include <QLineEdit>
20 #include <QRadioButton>
21 #include <QList>
22 #include <QMessageBox>
23 //#define DEBUG_CONNECTION
24 #ifdef DEBUG_CONNECTION
25 #include <QtDebug>
26 #endif
27 using namespace dcpp;
28 
29 #ifndef IPTOS_TOS_MASK
30 #define	IPTOS_TOS_MASK		0x1E
31 #endif
32 #ifndef IPTOS_TOS
33 #define	IPTOS_TOS(tos)		((tos) & IPTOS_TOS_MASK)
34 #endif
35 #ifndef IPTOS_LOWDELAY
36 #define	IPTOS_LOWDELAY		0x10
37 #endif
38 #ifndef IPTOS_THROUGHPUT
39 #define	IPTOS_THROUGHPUT	0x08
40 #endif
41 #ifndef IPTOS_RELIABILITY
42 #define	IPTOS_RELIABILITY	0x04
43 #endif
44 #ifndef IPTOS_LOWCOST
45 #define	IPTOS_LOWCOST		0x02
46 #endif
47 #ifndef IPTOS_MINCOST
48 #define	IPTOS_MINCOST		IPTOS_LOWCOST
49 #endif
50 
51 
SettingsConnection(QWidget * parent)52 SettingsConnection::SettingsConnection( QWidget *parent):
53         QWidget(parent),
54         dirty(false)
55 {
56     setupUi(this);
57 
58     init();
59 }
60 
eventFilter(QObject * obj,QEvent * e)61 bool SettingsConnection::eventFilter(QObject *obj, QEvent *e){
62     if ((e->type() == QEvent::KeyRelease) || (e->type() == QEvent::MouseButtonRelease))//May be some settings has been changed
63         dirty = true;
64 
65     return QWidget::eventFilter(obj, e);
66 }
67 
ok()68 void SettingsConnection::ok(){
69 
70     bool active = !radioButton_PASSIVE->isChecked();
71     SettingsManager *SM = SettingsManager::getInstance();
72 
73     int old_mode = SETTING(INCOMING_CONNECTIONS);
74     SM->set(SettingsManager::AUTO_DETECT_CONNECTION, checkBox_AUTO_DETECT_CONNECTION->isChecked());
75     if (active){
76         if (radioButton_ACTIVE->isChecked())
77             SM->set(SettingsManager::INCOMING_CONNECTIONS, SettingsManager::INCOMING_DIRECT);
78         else if (radioButton_PORT->isChecked())
79             SM->set(SettingsManager::INCOMING_CONNECTIONS, SettingsManager::INCOMING_FIREWALL_NAT);
80 #if (defined USE_MINIUPNP)
81         else
82             SM->set(SettingsManager::INCOMING_CONNECTIONS, SettingsManager::INCOMING_FIREWALL_UPNP);
83 #endif
84         SM->set(SettingsManager::TCP_PORT, spinBox_TCP->value());
85         SM->set(SettingsManager::UDP_PORT, spinBox_UDP->value());
86 
87         if (spinBox_TLS->value() != SETTING(TCP_PORT))
88             SM->set(SettingsManager::TLS_PORT, spinBox_TLS->value());
89         else
90             SM->set(SettingsManager::TLS_PORT, spinBox_TLS->value()+1);
91 
92         SM->set(SettingsManager::EXTERNAL_IP, lineEdit_WANIP->text().toStdString());
93         QString bind_ip=lineEdit_BIND_ADDRESS->text();
94         if (validateIp(bind_ip))
95             SM->set(SettingsManager::BIND_ADDRESS, lineEdit_BIND_ADDRESS->text().toStdString());
96         SM->set(SettingsManager::NO_IP_OVERRIDE, checkBox_DONTOVERRIDE->checkState() == Qt::Checked);
97     }
98     else {
99         SM->set(SettingsManager::INCOMING_CONNECTIONS, SettingsManager::INCOMING_FIREWALL_PASSIVE);
100     }
101 
102     bool use_socks = !radioButton_DC->isChecked();
103     int type = SETTING(OUTGOING_CONNECTIONS);
104 
105     SM->set(SettingsManager::BIND_IFACE, radioButton_BIND_IFACE->isChecked());
106     SM->set(SettingsManager::BIND_IFACE_NAME, _tq(comboBox_IFACES->currentText()));
107 
108     if (use_socks){
109         QString ip = lineEdit_SIP->text();
110 
111         if (!validateIp(ip)){
112             showMsg(tr("No valid SOCKS5 server IP found!"), NULL);
113 
114             return;
115         }
116 
117         int port = lineEdit_SPORT->text().toInt();
118 
119         SM->set(SettingsManager::SOCKS_SERVER, lineEdit_SIP->text().toStdString());
120         SM->set(SettingsManager::SOCKS_USER, lineEdit_SUSR->text().toStdString());
121         SM->set(SettingsManager::SOCKS_PASSWORD, lineEdit_SPSWD->text().toStdString());
122         SM->set(SettingsManager::SOCKS_RESOLVE, checkBox_RESOLVE->checkState() == Qt::Checked);
123         SM->set(SettingsManager::OUTGOING_CONNECTIONS, SettingsManager::OUTGOING_SOCKS5);
124 
125         if (port > 0 && port <= 65535)
126             SM->set(SettingsManager::SOCKS_PORT, port);
127     }
128     else{
129         SM->set(SettingsManager::OUTGOING_CONNECTIONS, SettingsManager::OUTGOING_DIRECT);
130     }
131 
132     if (SETTING(OUTGOING_CONNECTIONS) != type)
133         Socket::socksUpdated();
134 
135     SM->set(SettingsManager::THROTTLE_ENABLE, checkBox_THROTTLE_ENABLE->isChecked());
136     SM->set(SettingsManager::TIME_DEPENDENT_THROTTLE, checkBox_TIME_DEPENDENT_THROTTLE->isChecked());
137     SM->set(SettingsManager::MAX_DOWNLOAD_SPEED_MAIN, spinBox_DOWN_LIMIT_NORMAL->value());
138     SM->set(SettingsManager::MAX_UPLOAD_SPEED_MAIN, spinBox_UP_LIMIT_NORMAL->value());
139     SM->set(SettingsManager::MAX_DOWNLOAD_SPEED_ALTERNATE, spinBox_DOWN_LIMIT_TIME->value());
140     SM->set(SettingsManager::MAX_UPLOAD_SPEED_ALTERNATE, spinBox_UP_LIMIT_TIME->value());
141     SM->set(SettingsManager::BANDWIDTH_LIMIT_START, spinBox_BANDWIDTH_LIMIT_START->value());
142     SM->set(SettingsManager::BANDWIDTH_LIMIT_END, spinBox_BANDWIDTH_LIMIT_END->value());
143     SM->set(SettingsManager::SLOTS_ALTERNATE_LIMITING, spinBox_ALTERNATE_SLOTS->value());
144     SM->set(SettingsManager::RECONNECT_DELAY, spinBox_RECONNECT_DELAY->value());
145     SM->set(SettingsManager::IP_TOS_VALUE, comboBox_TOS->itemData(comboBox_TOS->currentIndex()).toInt());
146     SM->set(SettingsManager::DYNDNS_SERVER, lineEdit_DYNDNS_SERVER->text().toStdString());
147     SM->set(SettingsManager::DYNDNS_ENABLE, checkBox_DYNDNS->isChecked());
148 
149 #ifdef WITH_DHT
150     SM->set(SettingsManager::USE_DHT, groupBox_DHT->isChecked());
151     if (spinBox_DHT->value() != SETTING(UDP_PORT))
152         SM->set(SettingsManager::DHT_PORT, spinBox_DHT->value());
153     else
154         SM->set(SettingsManager::DHT_PORT, spinBox_DHT->value()+1);
155 
156     if (!(old_dht < 1024) && (SETTING(DHT_PORT) < 1024))
157         showMsg(tr("Program need root privileges to open ports less than 1024"), NULL);
158 #endif
159     SM->set(SettingsManager::ALLOW_UNTRUSTED_CLIENTS, checkBox_UNTRUSTED_CLIENTS->isChecked());
160     SM->set(SettingsManager::ALLOW_UNTRUSTED_HUBS, checkBox_UNTRUSTED_HUBS->isChecked());
161 
162     SM->set(SettingsManager::USE_TLS, (comboBox_TLS->currentIndex() == 1) || (comboBox_TLS->currentIndex() == 2));
163     SM->set(SettingsManager::REQUIRE_TLS, (comboBox_TLS->currentIndex() == 2));
164 
165     if (old_mode != SETTING(INCOMING_CONNECTIONS) || old_tcp != (SETTING(TCP_PORT))
166         || old_udp != (SETTING(UDP_PORT)) || old_tls != (SETTING(TLS_PORT)))
167     {
168         if (!(old_tcp < 1024 || old_tls < 1024 || old_udp < 1024) &&
169             (SETTING(TCP_PORT) < 1024 || SETTING(UDP_PORT) < 1024 || SETTING(TLS_PORT) < 1024))
170             showMsg(tr("Program need root privileges to open ports less than 1024"), NULL);
171 
172         MainWindow::getInstance()->startSocket(true);
173     }
174 }
175 
init()176 void SettingsConnection::init(){
177     lineEdit_WANIP->setText(QString::fromStdString(SETTING(EXTERNAL_IP)));
178     lineEdit_BIND_ADDRESS->setText(QString::fromStdString(SETTING(BIND_ADDRESS)));
179 
180     spinBox_TCP->setValue(old_tcp = SETTING(TCP_PORT));
181     spinBox_UDP->setValue(old_udp = SETTING(UDP_PORT));
182     spinBox_TLS->setValue(old_tls = SETTING(TLS_PORT));
183     checkBox_AUTO_DETECT_CONNECTION->setChecked(BOOLSETTING(AUTO_DETECT_CONNECTION));
184     checkBox_THROTTLE_ENABLE->setChecked(BOOLSETTING(THROTTLE_ENABLE));
185     checkBox_TIME_DEPENDENT_THROTTLE->setChecked(BOOLSETTING(TIME_DEPENDENT_THROTTLE));
186     spinBox_DOWN_LIMIT_NORMAL->setValue(SETTING(MAX_DOWNLOAD_SPEED_MAIN));
187     spinBox_UP_LIMIT_NORMAL->setValue(SETTING(MAX_UPLOAD_SPEED_MAIN));
188     spinBox_DOWN_LIMIT_TIME->setValue(SETTING(MAX_DOWNLOAD_SPEED_ALTERNATE));
189     spinBox_UP_LIMIT_TIME->setValue(SETTING(MAX_UPLOAD_SPEED_ALTERNATE));
190     spinBox_BANDWIDTH_LIMIT_START->setValue(SETTING(BANDWIDTH_LIMIT_START));
191     spinBox_BANDWIDTH_LIMIT_END->setValue(SETTING(BANDWIDTH_LIMIT_END));
192     spinBox_ALTERNATE_SLOTS->setValue(SETTING(SLOTS_ALTERNATE_LIMITING));
193     spinBox_RECONNECT_DELAY->setValue(SETTING(RECONNECT_DELAY));
194     checkBox_DONTOVERRIDE->setCheckState( SETTING(NO_IP_OVERRIDE)? Qt::Checked : Qt::Unchecked );
195     checkBox_DYNDNS->setCheckState( BOOLSETTING(DYNDNS_ENABLE) ? Qt::Checked : Qt::Unchecked );
196     lineEdit_DYNDNS_SERVER->setText(QString::fromStdString(SETTING(DYNDNS_SERVER)));
197 
198 #ifdef WITH_DHT
199     groupBox_DHT->setChecked(BOOLSETTING(USE_DHT));
200     spinBox_DHT->setValue(old_dht = SETTING(DHT_PORT));
201 #else
202     groupBox_DHT->hide();
203 #endif
204 
205     checkBox_UNTRUSTED_CLIENTS->setChecked(SETTING(ALLOW_UNTRUSTED_CLIENTS));
206     checkBox_UNTRUSTED_HUBS->setChecked(SETTING(ALLOW_UNTRUSTED_HUBS));
207 
208     comboBox_TLS->setCurrentIndex(0);
209     if (SETTING(USE_TLS)) {
210         comboBox_TLS->setCurrentIndex(1);
211     }
212     if (SETTING(REQUIRE_TLS)) {
213         comboBox_TLS->setCurrentIndex(2);
214     }
215 
216     QStringList ifaces = WulforUtil::getInstance()->getLocalIfaces();
217 
218     if (!ifaces.isEmpty())
219         comboBox_IFACES->addItems(ifaces);
220 
221     comboBox_IFACES->addItem("");
222 
223     if (SETTING(BIND_IFACE)){
224         radioButton_BIND_IFACE->toggle();
225 
226         if (ifaces.contains(_q(SETTING(BIND_IFACE_NAME))))
227             comboBox_IFACES->setCurrentIndex(ifaces.indexOf(_q(SETTING(BIND_IFACE_NAME))));
228         else
229             comboBox_IFACES->setCurrentIndex(comboBox_IFACES->count()-1);
230     }
231     else
232         radioButton_BIND_ADDR->toggle();
233 
234     switch (SETTING(INCOMING_CONNECTIONS)){
235     case SettingsManager::INCOMING_DIRECT:
236         {
237             radioButton_ACTIVE->setChecked(true);
238 
239             break;
240         }
241     case SettingsManager::INCOMING_FIREWALL_NAT:
242         {
243             radioButton_PORT->setChecked(true);
244 
245             break;
246         }
247     case SettingsManager::INCOMING_FIREWALL_PASSIVE:
248         {
249             radioButton_PASSIVE->setChecked(true);
250 
251             break;
252         }
253 #if (defined USE_MINIUPNP)
254     case SettingsManager::INCOMING_FIREWALL_UPNP:
255         {
256             radioButton_UPNP->setChecked(true);
257 
258             break;
259         }
260 #endif
261     }
262 #if (!defined USE_MINIUPNP)
263     radioButton_UPNP->setEnabled(false);
264 #endif
265 
266     lineEdit_SIP->setText(QString::fromStdString(SETTING(SOCKS_SERVER)));
267     lineEdit_SUSR->setText(QString::fromStdString(SETTING(SOCKS_USER)));
268     lineEdit_SPORT->setText(QString().setNum(SETTING(SOCKS_PORT)));
269     lineEdit_SPSWD->setText(QString::fromStdString(SETTING(SOCKS_PASSWORD)));
270 
271     checkBox_RESOLVE->setCheckState( SETTING(SOCKS_RESOLVE)? Qt::Checked : Qt::Unchecked );
272 
273     switch (SETTING(OUTGOING_CONNECTIONS)){
274     case SettingsManager::OUTGOING_DIRECT:
275         {
276             radioButton_DC->toggle();
277 
278             break;
279         }
280     case SettingsManager::OUTGOING_SOCKS5:
281         {
282             radioButton_SOCKS->toggle();
283 
284             break;
285         }
286     }
287 
288     comboBox_TOS->setItemData(0, -1);
289     comboBox_TOS->setItemData(1, IPTOS_LOWDELAY);
290     comboBox_TOS->setItemData(2, IPTOS_THROUGHPUT);
291     comboBox_TOS->setItemData(3, IPTOS_RELIABILITY);
292     comboBox_TOS->setItemData(4, IPTOS_MINCOST);
293 
294     for (int i = 0; i < comboBox_TOS->count(); i++){
295         if (comboBox_TOS->itemData(i).toInt() == SETTING(IP_TOS_VALUE)){
296             comboBox_TOS->setCurrentIndex(i);
297 
298             break;
299         }
300     }
301 
302     slotToggleIncomming();
303     slotToggleOutgoing();
304 
305     connect(radioButton_ACTIVE, SIGNAL(toggled(bool)), this, SLOT(slotToggleIncomming()));
306     connect(radioButton_PORT, SIGNAL(toggled(bool)), this, SLOT(slotToggleIncomming()));
307     connect(radioButton_PASSIVE, SIGNAL(toggled(bool)), this, SLOT(slotToggleIncomming()));
308 #if (defined USE_MINIUPNP)
309     connect(radioButton_UPNP, SIGNAL(toggled(bool)), this, SLOT(slotToggleIncomming()));
310 #endif
311     connect(radioButton_DC, SIGNAL(toggled(bool)), this, SLOT(slotToggleOutgoing()));
312     connect(radioButton_SOCKS, SIGNAL(toggled(bool)), this, SLOT(slotToggleOutgoing()));
313 
314     lineEdit_SIP->installEventFilter(this);
315     lineEdit_SPORT->installEventFilter(this);
316     lineEdit_SPSWD->installEventFilter(this);
317     lineEdit_SUSR->installEventFilter(this);
318     lineEdit_WANIP->installEventFilter(this);
319 
320     spinBox_TCP->installEventFilter(this);
321     spinBox_UDP->installEventFilter(this);
322     spinBox_TLS->installEventFilter(this);
323 
324     radioButton_ACTIVE->installEventFilter(this);
325     radioButton_DC->installEventFilter(this);
326     radioButton_PASSIVE->installEventFilter(this);
327     radioButton_PORT->installEventFilter(this);
328     radioButton_SOCKS->installEventFilter(this);
329 #if (defined USE_MINIUPNP)
330     radioButton_UPNP->installEventFilter(this);
331 #endif
332     checkBox_DONTOVERRIDE->installEventFilter(this);
333     checkBox_RESOLVE->installEventFilter(this);
334 }
335 
slotToggleIncomming()336 void SettingsConnection::slotToggleIncomming(){
337     bool b = !radioButton_PASSIVE->isChecked();
338 
339     frame->setEnabled(b);
340 }
341 
slotToggleOutgoing()342 void SettingsConnection::slotToggleOutgoing(){
343     bool b = !radioButton_DC->isChecked();
344 
345     frame_2->setEnabled(b);
346 }
validateIp(QString & ip)347 bool SettingsConnection::validateIp(QString &ip){
348     if (ip.isEmpty() || ip.isNull())
349         return false;
350 
351     QStringList l = ip.split(".", QString::SkipEmptyParts);
352 
353     if (l.size() != 4)
354         return false;
355 
356     QIntValidator v(0, 255, this);
357 
358     bool valid = true;
359     int pos = 0;
360 
361     for (QString s : l)
362         valid = valid && (v.validate(s, pos) == QValidator::Acceptable);
363 
364     return valid;
365 }
366 
showMsg(QString msg,QWidget * focusTo)367 void SettingsConnection::showMsg(QString msg, QWidget *focusTo){
368     QMessageBox::warning(this, tr("Warning"), msg);
369 
370     if (focusTo)
371         focusTo->setFocus();
372 }
373