1/*
2 * kPPP: A pppd front end for the KDE project
3 *
4 * $Id$
5 *
6 * Copyright (C) 1997 Bernd Johannes Wuebben
7 * wuebben@math.cornell.edu
8 *
9 * based on EzPPP:
10 * Copyright (C) 1997 Jay Painter
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Library General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with this program; if not, write to the Free
24 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25 */
26
27#include <qdir.h>
28//Added by qt3to4:
29#include <QLabel>
30#include <QVBoxLayout>
31#include <QHBoxLayout>
32#include <stdlib.h>
33#include <qlayout.h>
34#include <q3tabdialog.h>
35
36#include <qmessagebox.h>
37#include <QApplication>
38#include <kmessagebox.h>
39#include <klocale.h>
40#include <kglobal.h>
41#include <kwindowsystem.h>
42#include <kpagedialog.h>
43#include <KStandardGuiItem>
44//#include <qvgroupbox.h>
45#include <kiconloader.h>
46#include "pppdata.h"
47#include "accounts.h"
48#include "accounting.h"
49#include "providerdb.h"
50#include "edit.h"
51#include <errno.h>
52void parseargs(char* buf, char** args);
53
54AccountWidget::AccountWidget( QWidget *parent, const char *name )
55 : QWidget( parent )
56{
57 setObjectName( name );
58 int min = 0;
59 QVBoxLayout *l1 = new QVBoxLayout(parent);
60 l1->setSpacing(10);
61 l1->setMargin(10);
62
63 // add a hbox
64 QHBoxLayout *l11 = new QHBoxLayout;
65 l1->addLayout(l11);
66
67 accountlist_l = new Q3ListBox(parent);
68 accountlist_l->setMinimumSize(160, 128);
69 connect(accountlist_l, SIGNAL(highlighted(int)),
70 this, SLOT(slotListBoxSelect(int)));
71 connect(accountlist_l, SIGNAL(selected(int)),
72 this, SLOT(editaccount()));
73 l11->addWidget(accountlist_l, 10);
74
75 QVBoxLayout *l111 = new QVBoxLayout;
76 l11->addLayout(l111, 1);
77 edit_b = new QPushButton(i18n("&Edit..."), parent);
78 connect(edit_b, SIGNAL(clicked()), SLOT(editaccount()));
79 edit_b->setWhatsThis( i18n("Allows you to modify the selected account"));
80
81 min = edit_b->sizeHint().width();
82 min = qMax(70,min);
83 edit_b->setMinimumWidth(min);
84
85 l111->addWidget(edit_b);
86
87 new_b = new QPushButton(i18n("&New..."), parent);
88 connect(new_b, SIGNAL(clicked()), SLOT(newaccount()));
89 l111->addWidget(new_b);
90 new_b->setWhatsThis( i18n("Create a new dialup connection\n"
91 "to the Internet"));
92
93 copy_b = new QPushButton(i18n("Co&py"), parent);
94 connect(copy_b, SIGNAL(clicked()), SLOT(copyaccount()));
95 l111->addWidget(copy_b);
96 copy_b->setWhatsThis(
97 i18n("Makes a copy of the selected account. All\n"
98 "settings of the selected account are copied\n"
99 "to a new account that you can modify to fit your\n"
100 "needs"));
101
102 delete_b = new QPushButton(i18n("De&lete"), parent);
103 connect(delete_b, SIGNAL(clicked()), SLOT(deleteaccount()));
104 l111->addWidget(delete_b);
105 delete_b->setWhatsThis(
106 i18n("<p>Deletes the selected account\n\n"
107 "<font color=\"red\"><b>Use with care!</b></font>"));
108
109 QHBoxLayout *l12 = new QHBoxLayout;
110 l1->addStretch(1);
111 l1->addLayout(l12);
112
113 QVBoxLayout *l121 = new QVBoxLayout;
114 l12->addLayout(l121);
115 l121->addStretch(1);
116 costlabel = new QLabel(i18n("Phone costs:"), parent);
117 costlabel->setEnabled(false);
118 l121->addWidget(costlabel);
119
120 costedit = new QLineEdit(parent);
121 costedit->setFocusPolicy(Qt::NoFocus);
122 costedit->setFixedHeight(costedit->sizeHint().height());
123 costedit->setEnabled(false);
124 l121->addWidget(costedit);
125 l121->addStretch(1);
126 QString tmp = i18n("<p>This shows the accumulated phone costs\n"
127 "for the selected account.\n"
128 "\n"
129 "<b>Important</b>: If you have more than one \n"
130 "account - beware, this is <b>NOT</b> the sum \n"
131 "of the phone costs of all your accounts!");
132 costlabel->setWhatsThis( tmp);
133 costedit->setWhatsThis( tmp);
134
135 vollabel = new QLabel(i18n("Volume:"), parent);
136 vollabel->setEnabled(false);
137 l121->addWidget(vollabel);
138
139 voledit = new QLineEdit(parent);
140 voledit->setObjectName( "voledit" );
141 voledit->setFocusPolicy(Qt::NoFocus);
142 voledit->setFixedHeight(voledit->sizeHint().height());
143 voledit->setEnabled(false);
144 l121->addWidget(voledit);
145 tmp = i18n("<p>This shows the number of bytes transferred\n"
146 "for the selected account (not for all of your\n"
147 "accounts. You can select what to display in\n"
148 "the accounting dialog.\n"
149 "\n"
150 "<a href=\"#volaccounting\">More on volume accounting</a>");
151
152 vollabel->setWhatsThis(tmp);
153 voledit->setWhatsThis( tmp);
154
155 QVBoxLayout *l122 = new QVBoxLayout;
156 l12->addStretch(1);
157 l12->addLayout(l122);
158
159 l122->addStretch(1);
160 reset = new QPushButton(i18n("&Reset..."), parent);
161 reset->setEnabled(false);
162 connect(reset, SIGNAL(clicked()),
163 this, SLOT(resetClicked()));
164 l122->addWidget(reset);
165
166 log = new QPushButton(i18n("&View Logs"), parent);
167 connect(log, SIGNAL(clicked()),
168 this, SLOT(viewLogClicked()));
169 l122->addWidget(log);
170 l122->addStretch(1);
171
172 //load up account list from gppdata to the list box
173 if(gpppdata.accountCount() > 0) {
174 for(int i=0; i <= gpppdata.accountCount()-1; i++) {
175 gpppdata.setAccountByIndex(i);
176 accountlist_l->insertItem(gpppdata.accname());
177 }
178 }
179
180 slotListBoxSelect(accountlist_l->currentItem());
181
182 l1->activate();
183}
184
185
186
187void AccountWidget::slotListBoxSelect(int idx) {
188 delete_b->setEnabled((bool)(idx != -1));
189 edit_b->setEnabled((bool)(idx != -1));
190 copy_b->setEnabled((bool)(idx != -1));
191 if(idx!=-1) {
192 QString account = gpppdata.accname();
193 gpppdata.setAccountByIndex(accountlist_l->currentItem());
194 reset->setEnabled(true);
195 costlabel->setEnabled(true);
196 costedit->setEnabled(true);
197 costedit->setText(AccountingBase::getCosts(accountlist_l->text(accountlist_l->currentItem())));
198
199 vollabel->setEnabled(true);
200 voledit->setEnabled(true);
201 int bytes = gpppdata.totalBytes();
202 voledit->setText(prettyPrintVolume(bytes));
203 gpppdata.setAccount(account);
204 } else{
205 reset->setEnabled(false);
206 costlabel->setEnabled(false);
207 costedit->setText("");
208 costedit->setEnabled(false);
209 vollabel->setEnabled(false);
210 voledit->setText("");
211 voledit->setEnabled(false);
212 }
213}
214
215
216void AccountWidget::viewLogClicked(){
217
218 QApplication::flush();
219 if(fork() == 0) {
220 if (setgid(getgid()) < 0 && errno != EPERM)
221 _exit(2);
222 setuid(getuid());
223 if( geteuid() != getuid() )
224 _exit(1);
225 // TODO: use execvp
226 system("kppplogview -kppp");
227 _exit(0);
228 }
229}
230
231
232void AccountWidget::resetClicked(){
233 if(accountlist_l->currentItem() == -1)
234 return;
235
236 QueryReset dlg(this);
237 int what = dlg.exec();
238
239 if((what & QueryReset::COSTS)) {
240 emit resetCosts(accountlist_l->text(accountlist_l->currentItem()));
241 costedit->setText("0");
242 }
243
244 if((what & QueryReset::VOLUME)) {
245 emit resetVolume(accountlist_l->text(accountlist_l->currentItem()));
246 voledit->setText(prettyPrintVolume(0));
247 }
248}
249
250
251void AccountWidget::editaccount() {
252 gpppdata.setAccount(accountlist_l->text(accountlist_l->currentItem()));
253
254 int result = doTab();
255
256 if(result == QDialog::Accepted) {
257 accountlist_l->changeItem(gpppdata.accname(),accountlist_l->currentItem());
258 emit resetaccounts();
259 gpppdata.save();
260 }
261}
262
263
264void AccountWidget::newaccount() {
265 if(accountlist_l->count() == MAX_ACCOUNTS) {
266 KMessageBox::sorry(this, i18n("Maximum number of accounts reached."));
267 return;
268 }
269
270 int result;
271 int query = KMessageBox::questionYesNoCancel(this,
272 i18n("Do you want to use the wizard to create the new account or the "
273 "standard, dialog-based setup?\n"
274 "The wizard is easier and sufficient in most cases. If you need "
275 "very special settings, you might want to try the standard, "
276 "dialog-based setup."),
277 i18n("Create New Account"),
278 KGuiItem(i18n("&Wizard")), KGuiItem(i18n("&Manual Setup")));
279
280 switch(query) {
281 case KMessageBox::Yes:
282 {
283 if (gpppdata.newaccount() == -1)
284 return;
285 ProviderDB pdb(this);
286 result = pdb.exec();
287 break;
288 }
289 case KMessageBox::No:
290 if (gpppdata.newaccount() == -1)
291 return;
292 result = doTab();
293 break;
294 default:
295 return;
296 }
297
298 if(result == QDialog::Accepted) {
299 accountlist_l->insertItem(gpppdata.accname());
300 accountlist_l->setSelected(accountlist_l->findItem(gpppdata.accname()),
301 true);
302 emit resetaccounts();
303 gpppdata.save();
304 } else
305 gpppdata.deleteAccount();
306}
307
308
309void AccountWidget::copyaccount() {
310 if(accountlist_l->count() == MAX_ACCOUNTS) {
311 KMessageBox::sorry(this, i18n("Maximum number of accounts reached."));
312 return;
313 }
314
315 if(accountlist_l->currentItem()<0) {
316 KMessageBox::sorry(this, i18n("No account selected."));
317 return;
318 }
319
320 gpppdata.copyaccount(accountlist_l->currentItem());
321
322 accountlist_l->insertItem(gpppdata.accname());
323 emit resetaccounts();
324 gpppdata.save();
325}
326
327
328void AccountWidget::deleteaccount() {
329
330 QString s = i18n("Are you sure you want to delete\nthe account \"%1\"?",
331 accountlist_l->text(accountlist_l->currentItem()));
332
333 if(KMessageBox::warningYesNo(this, s, i18n("Confirm"), KGuiItem(i18n("Delete"), "edit-delete"), KStandardGuiItem::cancel()) != KMessageBox::Yes)
334 return;
335
336 if(gpppdata.deleteAccount(accountlist_l->text(accountlist_l->currentItem())))
337 accountlist_l->removeItem(accountlist_l->currentItem());
338
339 emit resetaccounts();
340 gpppdata.save();
341
342 slotListBoxSelect(accountlist_l->currentItem());
343
344}
345
346
347int AccountWidget::doTab(){
348 tabWindow = new KPageDialog( this );
349 tabWindow->setFaceType( KPageDialog::Tabbed );
350 tabWindow->setButtons( KDialog::Ok|KDialog::Cancel );
351 tabWindow->setDefaultButton( KDialog::Ok );
352 tabWindow->setModal( true );
353 KWindowSystem::setIcons(tabWindow->winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
354 bool isnewaccount;
355
356 if(gpppdata.accname().isEmpty()) {
357 tabWindow->setCaption(i18n("New Account"));
358 isnewaccount = true;
359 } else {
360 QString tit = i18n("Edit Account: ");
361 tit += gpppdata.accname();
362 tabWindow->setCaption(tit);
363 isnewaccount = false;
364 }
365
366 QFrame * frame = new QFrame();
367 KPageWidgetItem *pageItem = new KPageWidgetItem( frame, i18n("Dial") );
368 pageItem->setHeader( i18n("Dial Setup") );
369 tabWindow->addPage( pageItem );
370 dial_w = new DialWidget(frame, isnewaccount);
371
372
373 frame = new QFrame();
374 pageItem = new KPageWidgetItem( frame, i18n("IP") );
375 pageItem->setHeader( i18n("IP Setup") );
376 tabWindow->addPage( pageItem );
377 ip_w = new IPWidget(frame, isnewaccount);
378
379 frame = new QFrame();
380 pageItem = new KPageWidgetItem( frame, i18n("Gateway") );
381 pageItem->setHeader( i18n("Gateway Setup") );
382 tabWindow->addPage( pageItem );
383 gateway_w = new GatewayWidget(frame, isnewaccount);
384
385 frame = new QFrame();
386 pageItem = new KPageWidgetItem( frame, i18n("DNS") );
387 pageItem->setHeader( i18n("DNS Servers") );
388 tabWindow->addPage( pageItem );
389 dns_w = new DNSWidget(frame, isnewaccount);
390
391 frame = new QFrame();
392 pageItem = new KPageWidgetItem( frame, i18n("Login Script") );
393 pageItem->setHeader( i18n("Edit Login Script") );
394 tabWindow->addPage( pageItem );
395 script_w = new ScriptWidget(frame, isnewaccount);
396
397
398 frame = new QFrame();
399 pageItem = new KPageWidgetItem( frame, i18n("Execute") );
400 pageItem->setHeader( i18n("Execute Programs") );
401 tabWindow->addPage( pageItem );
402 ExecWidget *exec_w = new ExecWidget(frame, isnewaccount);
403
404 frame = new QFrame();
405 pageItem = new KPageWidgetItem( frame, i18n("Accounting") );
406 tabWindow->addPage( pageItem );
407
408 acct = new AccountingSelector(frame, isnewaccount);
409
410 int result = 0;
411 bool ok = false;
412 while (!ok){
413
414 result = tabWindow->exec();
415 ok = true;
416
417 if(result == QDialog::Accepted) {
418 if (script_w->check()) {
419 if(dial_w->save()) {
420 ip_w->save();
421 dns_w->save();
422 gateway_w->save();
423 script_w->save();
424 exec_w->save();
425 acct->save();
426 } else {
427 // ### add: "and valid"
428 KMessageBox::error(this, i18n( "You must enter a unique\n"
429 "account name"));
430 ok = false;
431 }
432 } else {
433 KMessageBox::error(this, i18n("Login script has unbalanced "
434 "loop Start/End"));
435 ok = false;
436 }
437 }
438 }
439
440 delete tabWindow;
441 return result;
442}
443
444
445QString AccountWidget::prettyPrintVolume(unsigned int n) {
446 int idx = 0;
447 const QString quant[] = {i18n("Byte"), i18n("KiB"),
448 i18n("MiB"), i18n("GiB"), QString()};
449
450 float n1 = n;
451 while(n >= 1024 && !quant[idx].isNull()) {
452 idx++;
453 n /= 1024;
454 }
455
456 int i = idx;
457 while(i--)
458 n1 = n1 / 1024.0;
459
460 QString s = KGlobal::locale()->formatNumber( n1, idx==0 ? 0 : 1 );
461 s += ' ' + quant[idx];
462 return s;
463}
464
465
466/////////////////////////////////////////////////////////////////////////////
467//
468// Queries the user what to reset: costs, volume or both
469//
470/////////////////////////////////////////////////////////////////////////////
471QueryReset::QueryReset(QWidget *parent) : KDialog(parent) {
472 KWindowSystem::setIcons(winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
473 setWindowTitle(i18n("Reset Accounting"));
474
475 QWidget *w = new QWidget(this);
476 setMainWidget(w);
477 QVBoxLayout *tl = new QVBoxLayout;
478 w->setLayout(tl);
479 tl->setSpacing(0);
480 tl->setMargin(0);
481
482 QGroupBox *f = new QGroupBox(i18n("What to Reset"));
483 tl->addWidget(f);
484
485 QVBoxLayout *l1 = new QVBoxLayout;
486 f->setLayout(l1);
487
488 costs = new QCheckBox(i18n("Reset the accumulated p&hone costs"));
489 costs->setChecked(true);
490 l1->addWidget(costs);
491 costs->setWhatsThis( i18n("Check this to set the phone costs\n"
492 "to zero. Typically you will want to\n"
493 "do this once a month."));
494
495 volume = new QCheckBox(i18n("Reset &volume accounting"), f);
496 volume->setChecked(true);
497 l1->addWidget(volume);
498 volume->setWhatsThis( i18n("Check this to set the volume accounting\n"
499 "to zero. Typically you will want to do this\n"
500 "once a month."));
501
502 l1->activate();
503
504 // this activates the f-layout and sets minimumSize()
505 f->show();
506
507 tl->addWidget(f);
508
509 setButtons(Ok|Cancel);
510
511 // TODO: activate if KGroupBox is fixed
512 // setFixedSize(sizeHint());
513}
514
515
516void QueryReset::accepted() {
517 int result = costs->isChecked() ? COSTS : 0;
518 result += volume->isChecked() ? VOLUME : 0;
519
520 done(result);
521}
522
523#include "accounts.moc"
524