source: psi/trunk/src/proxy.cpp@ 59

Last change on this file since 59 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 15.5 KB
Line 
1/*
2 * proxy.cpp - classes for handling proxy profiles
3 * Copyright (C) 2003 Justin Karneges
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include"proxy.h"
22
23#include<qlabel.h>
24#include<qlineedit.h>
25#include<qcheckbox.h>
26#include<qvgroupbox.h>
27#include<qlayout.h>
28#include<qgrid.h>
29#include<qhbox.h>
30#include<qvbox.h>
31#include<qcombobox.h>
32#include<qpushbutton.h>
33#include<qlistbox.h>
34#include<qdom.h>
35#include<qguardedptr.h>
36#include<qwhatsthis.h>
37#include<qapplication.h>
38#include"common.h"
39#include"iconwidget.h"
40
41static QDomElement textTag(QDomDocument &doc, const QString &name, const QString &content)
42{
43 QDomElement tag = doc.createElement(name);
44 QDomText text = doc.createTextNode(content);
45 tag.appendChild(text);
46
47 return tag;
48}
49
50static QDomElement textTag(QDomDocument &doc, const QString &name, bool content)
51{
52 QDomElement tag = doc.createElement(name);
53 QDomText text = doc.createTextNode(content ? "true" : "false");
54 tag.appendChild(text);
55
56 return tag;
57}
58
59static QDomElement findSubTag(const QDomElement &e, const QString &name)
60{
61 for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
62 QDomElement i = n.toElement();
63 if(i.isNull())
64 continue;
65 if(i.tagName() == name)
66 return i;
67 }
68
69 return QDomElement();
70}
71
72//----------------------------------------------------------------------------
73// HostPortEdit
74//----------------------------------------------------------------------------
75class HostPortEdit::Private
76{
77public:
78 Private() {}
79
80 QLineEdit *le_host, *le_port;
81};
82
83HostPortEdit::HostPortEdit(QWidget *parent, const char *name)
84:QWidget(parent, name)
85{
86 d = new Private;
87
88 QLabel *l;
89 QHBoxLayout *hb = new QHBoxLayout(this, 0, 4);
90 l = new QLabel(tr("Host:"), this);
91 hb->addWidget(l);
92 d->le_host = new QLineEdit(this);
93 d->le_host->setMinimumWidth(128);
94 hb->addWidget(d->le_host);
95 l = new QLabel(tr("Port:"), this);
96 hb->addWidget(l);
97 d->le_port = new QLineEdit(this);
98 d->le_port->setFixedWidth(64);
99 hb->addWidget(d->le_port);
100 setPort(0);
101}
102
103HostPortEdit::~HostPortEdit()
104{
105 delete d;
106}
107
108QString HostPortEdit::host() const
109{
110 return d->le_host->text();
111}
112
113int HostPortEdit::port() const
114{
115 return d->le_port->text().toInt();
116}
117
118void HostPortEdit::setHost(const QString &s)
119{
120 d->le_host->setText(s);
121}
122
123void HostPortEdit::setPort(int x)
124{
125 d->le_port->setText(QString::number(x));
126}
127
128void HostPortEdit::fixTabbing(QWidget *a, QWidget *b)
129{
130 setTabOrder(a, d->le_host);
131 setTabOrder(d->le_host, d->le_port);
132 setTabOrder(d->le_port, b);
133}
134
135
136//----------------------------------------------------------------------------
137// ProxySettings
138//----------------------------------------------------------------------------
139ProxySettings::ProxySettings()
140{
141 port = 0;
142 useAuth = false;
143}
144
145QDomElement ProxySettings::toXml(QDomDocument *doc) const
146{
147 QDomElement e = doc->createElement("proxySettings");
148 e.appendChild(textTag(*doc, "host", host));
149 e.appendChild(textTag(*doc, "port", QString::number(port)));
150 e.appendChild(textTag(*doc, "url", url));
151 e.appendChild(textTag(*doc, "useAuth", useAuth));
152 e.appendChild(textTag(*doc, "user", user));
153 e.appendChild(textTag(*doc, "pass", pass));
154 return e;
155}
156
157bool ProxySettings::fromXml(const QDomElement &e)
158{
159 host = findSubTag(e, "host").text();
160 port = findSubTag(e, "port").text().toInt();
161 url = findSubTag(e, "url").text();
162 useAuth = (findSubTag(e, "useAuth").text() == "true") ? true: false;
163 user = findSubTag(e, "user").text();
164 pass = findSubTag(e, "pass").text();
165 return true;
166}
167
168
169//----------------------------------------------------------------------------
170// ProxyEdit
171//----------------------------------------------------------------------------
172class ProxyEdit::Private
173{
174public:
175 Private() {}
176
177 HostPortEdit *hp_host;
178 QCheckBox *ck_auth;
179 QLabel *lb_url;
180 QLineEdit *le_url, *le_user, *le_pass;
181 QGrid *gr_auth;
182};
183
184ProxyEdit::ProxyEdit(QWidget *parent, const char *name)
185:QGroupBox(1, Horizontal, tr("Settings"), parent, name)
186{
187 d = new Private;
188
189 //QVBoxLayout *vb = new QVBoxLayout(this);
190 //QVBox *gb = new QVBox(this);
191 //gb->setSpacing(4);
192 //vb->addWidget(gb);
193
194 QLabel *l;
195
196 d->hp_host = new HostPortEdit(this);
197
198 QHBox *hb = new QHBox(this);
199 d->lb_url = new QLabel(tr("Polling URL:"), hb);
200 d->le_url = new QLineEdit(hb);
201
202 d->ck_auth = new QCheckBox(tr("Use authentication"), this);
203 connect(d->ck_auth, SIGNAL(toggled(bool)), SLOT(ck_toggled(bool)));
204
205 d->gr_auth = new QGrid(2, Horizontal, this);
206 d->gr_auth->setSpacing(4);
207 l = new QLabel(tr("Username:"), d->gr_auth);
208 d->le_user = new QLineEdit(d->gr_auth);
209 l = new QLabel(tr("Password:"), d->gr_auth);
210 d->le_pass = new QLineEdit(d->gr_auth);
211 d->le_pass->setEchoMode(QLineEdit::Password);
212 d->gr_auth->setEnabled(false);
213
214 QWhatsThis::add(d->hp_host,
215 tr("Enter the hostname and port of your proxy server.") + " " +
216 tr("Consult your network administrator if necessary."));
217 QWhatsThis::add(d->le_user,
218 tr("Enter your proxy server login (username) "
219 "or leave this field blank if the proxy server does not require it.") + " " +
220 tr("Consult your network administrator if necessary."));
221 QWhatsThis::add(d->le_pass,
222 tr("Enter your proxy server password "
223 "or leave this field blank if the proxy server does not require it.") + " " +
224 tr("Consult your network administrator if necessary."));
225}
226
227ProxyEdit::~ProxyEdit()
228{
229 delete d;
230}
231
232void ProxyEdit::reset()
233{
234 d->hp_host->setHost("");
235 d->hp_host->setPort(0);
236 d->le_url->setText("");
237 d->ck_auth->setChecked(false);
238 d->le_user->setText("");
239 d->le_pass->setText("");
240}
241
242void ProxyEdit::setType(const QString &s)
243{
244 if(s == "poll") {
245 d->lb_url->setEnabled(true);
246 d->le_url->setEnabled(true);
247 }
248 else {
249 d->lb_url->setEnabled(false);
250 d->le_url->setEnabled(false);
251 }
252}
253
254ProxySettings ProxyEdit::proxySettings() const
255{
256 ProxySettings s;
257 s.host = d->hp_host->host();
258 s.port = d->hp_host->port();
259 if(d->le_url->isEnabled())
260 s.url = d->le_url->text();
261 s.useAuth = d->ck_auth->isChecked();
262 s.user = d->le_user->text();
263 s.pass = d->le_pass->text();
264 return s;
265}
266
267void ProxyEdit::setProxySettings(const ProxySettings &s)
268{
269 d->hp_host->setHost(s.host);
270 d->hp_host->setPort(s.port);
271 d->le_url->setText(s.url);
272 d->ck_auth->setChecked(s.useAuth);
273 d->le_user->setText(s.user);
274 d->le_pass->setText(s.pass);
275}
276
277void ProxyEdit::ck_toggled(bool b)
278{
279 d->gr_auth->setEnabled(b);
280}
281
282void ProxyEdit::fixTabbing(QWidget *a, QWidget *b)
283{
284 d->hp_host->fixTabbing(a, d->le_url);
285 setTabOrder(d->le_url, d->ck_auth);
286 setTabOrder(d->ck_auth, d->le_user);
287 setTabOrder(d->le_user, d->le_pass);
288 setTabOrder(d->le_pass, b);
289}
290
291
292//----------------------------------------------------------------------------
293// ProxyDlg
294//----------------------------------------------------------------------------
295class ProxyDlg::Private
296{
297public:
298 Private() {}
299
300 ProxyEdit *pe_settings;
301 ProxyItemList list;
302 int last;
303};
304
305ProxyDlg::ProxyDlg(const ProxyItemList &list, const QStringList &methods, int def, QWidget *parent, const char *name)
306:ProxyUI(parent, name, QApplication::activeModalWidget() ? true: false, WDestructiveClose)
307{
308 d = new Private;
309 setCaption(CAP(caption()));
310
311 d->list = list;
312 d->last = -1;
313 d->pe_settings = new ProxyEdit(gb_prop);
314 replaceWidget(lb_proxyedit, d->pe_settings);
315 d->pe_settings->fixTabbing(cb_type, pb_close);
316
317 hookEdit();
318
319 connect(pb_new, SIGNAL(clicked()), SLOT(proxy_new()));
320 connect(pb_remove, SIGNAL(clicked()), SLOT(proxy_remove()));
321 connect(pb_save, SIGNAL(clicked()), SLOT(doSave()));
322 connect(pb_close, SIGNAL(clicked()), SLOT(reject()));
323 gb_prop->setEnabled(false);
324 pb_remove->setEnabled(false);
325 pb_save->setDefault(true);
326
327 cb_type->insertStringList(methods);
328 connect(cb_type, SIGNAL(activated(int)), SLOT(cb_activated(int)));
329
330 for(ProxyItemList::ConstIterator it = d->list.begin(); it != d->list.end(); ++it)
331 lbx_proxy->insertItem((*it).name);
332 if(!list.isEmpty()) {
333 if(def < 0)
334 def = 0;
335 lbx_proxy->setCurrentItem(def);
336 selectCurrent();
337 }
338
339 QWhatsThis::add(cb_type,
340 tr("If you require a proxy server to connect, select the type of proxy here.") + " " +
341 tr("Consult your network administrator if necessary."));
342 // TODO: whatsthis for name
343}
344
345ProxyDlg::~ProxyDlg()
346{
347 delete d;
348}
349
350void ProxyDlg::proxy_new()
351{
352 ProxyItem s;
353 s.id = -1; // id of -1 means 'new'
354 s.name = getUniqueName();
355 d->list += s;
356
357 lbx_proxy->insertItem(s.name);
358 lbx_proxy->setCurrentItem(lbx_proxy->count()-1);
359 selectCurrent();
360}
361
362void ProxyDlg::proxy_remove()
363{
364 int x = lbx_proxy->currentItem();
365 if(x != -1) {
366 ProxyItemList::Iterator it = d->list.begin();
367 for(int n = 0; n < x; ++n)
368 ++it;
369 d->list.remove(it);
370
371 d->last = -1;
372 lbx_proxy->removeItem(x);
373 selectCurrent();
374 }
375}
376
377void ProxyDlg::cb_activated(int x)
378{
379 if(x == 0)
380 d->pe_settings->setType("http");
381 else if(x == 1)
382 d->pe_settings->setType("socks");
383 else if(x == 2)
384 d->pe_settings->setType("poll");
385}
386
387void ProxyDlg::selectCurrent()
388{
389 int x = lbx_proxy->currentItem();
390 if(x != -1)
391 lbx_proxy->setSelected(x, true);
392}
393
394QString ProxyDlg::getUniqueName() const
395{
396 QString str;
397 int x = 0;
398 bool found;
399 do {
400 str = QString("Proxy %1").arg(++x);
401 found = false;
402 for(ProxyItemList::ConstIterator it = d->list.begin(); it != d->list.end(); ++it) {
403 if(str == (*it).name) {
404 found = true;
405 break;
406 }
407 }
408 } while(found);
409 return str;
410}
411
412void ProxyDlg::saveIntoItem(int x)
413{
414 ProxyItem &s = d->list[x];
415 s.name = le_name->text();
416 int i = cb_type->currentItem();
417 s.type = "http";
418 if(i == 0)
419 s.type = "http";
420 else if(i == 1)
421 s.type = "socks";
422 else if(i == 2)
423 s.type = "poll";
424 s.settings = d->pe_settings->proxySettings();
425}
426
427void ProxyDlg::qlbx_highlighted(int x)
428{
429 // if we are moving off of another item, save its content
430 if(d->last != -1)
431 saveIntoItem(d->last);
432 d->last = x;
433
434 // display the new item's content
435 if(x == -1) {
436 le_name->setText("");
437 cb_type->setCurrentItem(0);
438 d->pe_settings->reset();
439 gb_prop->setEnabled(false);
440 pb_remove->setEnabled(false);
441 }
442 else {
443 ProxyItem &s = d->list[x];
444 le_name->setText(s.name);
445 int i = 0;
446 if(s.type == "http")
447 i = 0;
448 else if(s.type == "socks")
449 i = 1;
450 else if(s.type == "poll")
451 i = 2;
452 cb_type->setCurrentItem(i);
453 d->pe_settings->setProxySettings(s.settings);
454 cb_activated(i);
455 gb_prop->setEnabled(true);
456 pb_remove->setEnabled(true);
457 }
458}
459
460void ProxyDlg::qle_textChanged(const QString &s)
461{
462 int x = lbx_proxy->currentItem();
463 if(x != -1) {
464 unhookEdit();
465 lbx_proxy->changeItem(s, x);
466 hookEdit();
467 }
468}
469
470// hookEdit / unhookEdit - disconnect some signals to prevent recursion
471void ProxyDlg::hookEdit()
472{
473 connect(lbx_proxy, SIGNAL(highlighted(int)), this, SLOT(qlbx_highlighted(int)));
474 connect(le_name, SIGNAL(textChanged(const QString &)), this, SLOT(qle_textChanged(const QString &)));
475}
476
477void ProxyDlg::unhookEdit()
478{
479 disconnect(lbx_proxy, SIGNAL(highlighted(int)), this, SLOT(qlbx_highlighted(int)));
480 disconnect(le_name, SIGNAL(textChanged(const QString &)), this, SLOT(qle_textChanged(const QString &)));
481}
482
483void ProxyDlg::doSave()
484{
485 int x = lbx_proxy->currentItem();
486 if(x != -1)
487 saveIntoItem(x);
488 applyList(d->list, x);
489 accept();
490}
491
492
493//----------------------------------------------------------------------------
494// ProxyChooser
495//----------------------------------------------------------------------------
496class ProxyChooser::Private
497{
498public:
499 Private() {}
500
501 QComboBox *cb_proxy;
502 QPushButton *pb_edit;
503 ProxyManager *m;
504};
505
506ProxyChooser::ProxyChooser(ProxyManager *m, QWidget *parent, const char *name)
507:QWidget(parent, name)
508{
509 d = new Private;
510 d->m = m;
511 connect(m, SIGNAL(settingsChanged()), SLOT(pm_settingsChanged()));
512 QHBoxLayout *hb = new QHBoxLayout(this, 0, 4);
513 d->cb_proxy = new QComboBox(this);
514 QSizePolicy sp = d->cb_proxy->sizePolicy();
515 d->cb_proxy->setSizePolicy( QSizePolicy(QSizePolicy::Expanding, sp.verData()) );
516 hb->addWidget(d->cb_proxy);
517 d->pb_edit = new QPushButton(tr("Edit..."), this);
518 connect(d->pb_edit, SIGNAL(clicked()), SLOT(doOpen()));
519 hb->addWidget(d->pb_edit);
520
521 buildComboBox();
522}
523
524ProxyChooser::~ProxyChooser()
525{
526 delete d;
527}
528
529int ProxyChooser::currentItem() const
530{
531 return d->cb_proxy->currentItem();
532}
533
534void ProxyChooser::setCurrentItem(int x)
535{
536 d->cb_proxy->setCurrentItem(x);
537}
538
539void ProxyChooser::pm_settingsChanged()
540{
541 int x = d->cb_proxy->currentItem();
542 buildComboBox();
543 if(x >= 1) {
544 x = d->m->findOldIndex(x-1);
545 if(x == -1)
546 d->cb_proxy->setCurrentItem(0);
547 else
548 d->cb_proxy->setCurrentItem(x+1);
549 }
550 else {
551 x = d->m->lastEdited();
552 if(x != -1)
553 d->cb_proxy->setCurrentItem(x+1);
554 }
555}
556
557void ProxyChooser::buildComboBox()
558{
559 d->cb_proxy->clear();
560 d->cb_proxy->insertItem(tr("None"));
561 ProxyItemList list = d->m->itemList();
562 for(ProxyItemList::ConstIterator it = list.begin(); it != list.end(); ++it)
563 d->cb_proxy->insertItem((*it).name);
564}
565
566void ProxyChooser::doOpen()
567{
568 int x = d->cb_proxy->currentItem();
569 if(x < 1)
570 x = -1;
571 else
572 --x;
573 d->m->openDialog(x);
574}
575
576void ProxyChooser::fixTabbing(QWidget *a, QWidget *b)
577{
578 setTabOrder(a, d->cb_proxy);
579 setTabOrder(d->cb_proxy, d->pb_edit);
580 setTabOrder(d->pb_edit, b);
581}
582
583
584//----------------------------------------------------------------------------
585// ProxyManager
586//----------------------------------------------------------------------------
587class ProxyManager::Private
588{
589public:
590 Private() {}
591
592 ProxyItemList list;
593 QGuardedPtr<ProxyDlg> pd;
594 QValueList<int> prevMap;
595 int lastEdited;
596};
597
598ProxyManager::ProxyManager(QObject *parent)
599:QObject(parent)
600{
601 d = new Private;
602}
603
604ProxyManager::~ProxyManager()
605{
606 delete d;
607}
608
609ProxyChooser *ProxyManager::createProxyChooser(QWidget *parent)
610{
611 return new ProxyChooser(this, parent);
612}
613
614ProxyItemList ProxyManager::itemList() const
615{
616 return d->list;
617}
618
619const ProxyItem & ProxyManager::getItem(int x) const
620{
621 return d->list[x];
622}
623
624int ProxyManager::lastEdited() const
625{
626 return d->lastEdited;
627}
628
629void ProxyManager::setItemList(const ProxyItemList &list)
630{
631 d->list = list;
632 assignIds();
633}
634
635QStringList ProxyManager::methodList() const
636{
637 QStringList list;
638 list += "HTTP \"Connect\"";
639 list += "SOCKS Version 5";
640 list += "HTTP Polling";
641 return list;
642}
643
644void ProxyManager::openDialog(int def)
645{
646 if(d->pd)
647 bringToFront(d->pd);
648 else {
649 d->pd = new ProxyDlg(d->list, methodList(), def, 0);
650 connect(d->pd, SIGNAL(applyList(const ProxyItemList &, int)), SLOT(pd_applyList(const ProxyItemList &, int)));
651 d->pd->show();
652 }
653}
654
655void ProxyManager::pd_applyList(const ProxyItemList &list, int x)
656{
657 d->list = list;
658 d->lastEdited = x;
659
660 // grab old id list
661 d->prevMap.clear();
662 for(ProxyItemList::ConstIterator it = d->list.begin(); it != d->list.end(); ++it)
663 d->prevMap += (*it).id;
664 assignIds(); // re-assign proper ids
665
666 settingsChanged();
667}
668
669void ProxyManager::assignIds()
670{
671 int n = 0;
672 for(ProxyItemList::Iterator it = d->list.begin(); it != d->list.end(); ++it)
673 (*it).id = n++;
674}
675
676int ProxyManager::findOldIndex(int x) const
677{
678 int newPos = 0;
679 bool found = false;
680 for(QValueList<int>::ConstIterator it = d->prevMap.begin(); it != d->prevMap.end(); ++it) {
681 if(*it == x) {
682 found = true;
683 break;
684 }
685 ++newPos;
686 }
687 if(found)
688 return newPos;
689 else
690 return -1;
691}
Note: See TracBrowser for help on using the repository browser.