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> |
52 | void parseargs(char* buf, char** args); |
53 | |
54 | AccountWidget::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 | |
187 | void 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 | |
216 | void 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 | |
232 | void 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 | |
251 | void 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 | |
264 | void 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 | |
309 | void 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 | |
328 | void 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 | |
347 | int 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 | |
445 | QString 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 | ///////////////////////////////////////////////////////////////////////////// |
471 | QueryReset::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 | |
516 | void 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 | |