00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <unistd.h>
00022
00023 #include <tqwidget.h>
00024 #include <tqlineedit.h>
00025 #include <tqlabel.h>
00026 #include <tqlayout.h>
00027 #include <tqsize.h>
00028 #include <tqevent.h>
00029 #include <tqkeycode.h>
00030 #include <tqcheckbox.h>
00031 #include <tqregexp.h>
00032 #include <tqhbox.h>
00033 #include <tqwhatsthis.h>
00034 #include <tqptrdict.h>
00035 #include <tqtimer.h>
00036
00037 #include <tdeglobal.h>
00038 #include <kdebug.h>
00039 #include <tdeapplication.h>
00040 #include <tdelocale.h>
00041 #include <kiconloader.h>
00042 #include <tdemessagebox.h>
00043 #include <tdeaboutdialog.h>
00044 #include <tdeconfig.h>
00045 #include <kstandarddirs.h>
00046 #include <kprogress.h>
00047
00048 #include <sys/time.h>
00049 #include <sys/resource.h>
00050
00051 #include "kpassdlg.h"
00052
00053 #include "../tdesu/defaults.h"
00054
00055
00056
00057
00058
00059 const int KPasswordEdit::PassLen = 200;
00060
00061 class KPasswordDialog::KPasswordDialogPrivate
00062 {
00063 public:
00064 KPasswordDialogPrivate()
00065 : m_MatchLabel( 0 ), iconName( 0 ), allowEmptyPasswords( false ),
00066 minimumPasswordLength(0), maximumPasswordLength(KPasswordEdit::PassLen - 1),
00067 passwordStrengthWarningLevel(1), m_strengthBar(0),
00068 reasonablePasswordLength(8)
00069 {}
00070 TQLabel *m_MatchLabel;
00071 TQString iconName;
00072 bool allowEmptyPasswords;
00073 int minimumPasswordLength;
00074 int maximumPasswordLength;
00075 int passwordStrengthWarningLevel;
00076 KProgress* m_strengthBar;
00077 int reasonablePasswordLength;
00078 };
00079
00080
00081 KPasswordEdit::KPasswordEdit(TQWidget *parent, const char *name)
00082 : TQLineEdit(parent, name)
00083 {
00084 init();
00085
00086 TDEConfig* const cfg = TDEGlobal::config();
00087 TDEConfigGroupSaver saver(cfg, "Passwords");
00088
00089 const TQString val = cfg->readEntry("EchoMode", "OneStar");
00090 if (val == "ThreeStars") {
00091 setEchoMode(PasswordThreeStars);
00092 }
00093 else if (val == "NoEcho") {
00094 setEchoMode(TQLineEdit::NoEcho);
00095 }
00096 else {
00097 setEchoMode(TQLineEdit::Password);
00098 }
00099
00100 setInputMethodEnabled( true );
00101 }
00102
00103 KPasswordEdit::KPasswordEdit(TQWidget *parent, const char *name, int echoMode)
00104 : TQLineEdit(parent, name)
00105 {
00106 setEchoMode((TQLineEdit::EchoMode)echoMode);
00107 init();
00108 }
00109
00110 KPasswordEdit::KPasswordEdit(EchoMode echoMode, TQWidget *parent, const char *name)
00111 : TQLineEdit(parent, name)
00112 {
00113 setEchoMode(echoMode);
00114 init();
00115 }
00116
00117 KPasswordEdit::KPasswordEdit(EchoModes echoMode, TQWidget *parent, const char *name)
00118 : TQLineEdit(parent, name)
00119 {
00120 if (echoMode == KPasswordEdit::NoEcho) {
00121 setEchoMode(TQLineEdit::NoEcho);
00122 }
00123 else if (echoMode == KPasswordEdit::ThreeStars) {
00124 setEchoMode(TQLineEdit::PasswordThreeStars);
00125 }
00126 else if (echoMode == KPasswordEdit::OneStar) {
00127 setEchoMode(TQLineEdit::Password);
00128 }
00129 init();
00130 }
00131
00132 void KPasswordEdit::init()
00133 {
00134 setAcceptDrops(false);
00135 }
00136
00137 KPasswordEdit::~KPasswordEdit()
00138 {
00139 }
00140
00141 TQString KPasswordEdit::password() const {
00142 return text();
00143 }
00144
00145 void KPasswordEdit::erase()
00146 {
00147 setText("");
00148 }
00149
00150 void KPasswordEdit::setMaxPasswordLength(int newLength)
00151 {
00152 setMaxLength(newLength);
00153 }
00154
00155 int KPasswordEdit::maxPasswordLength() const
00156 {
00157 return maxLength();
00158 }
00159
00160 void KPasswordEdit::insert( const TQString &str) {
00161 TQLineEdit::insert(str);
00162 }
00163
00164 void KPasswordEdit::keyPressEvent(TQKeyEvent *e) {
00165 TQLineEdit::keyPressEvent(e);
00166 }
00167
00168 void KPasswordEdit::focusInEvent(TQFocusEvent *e) {
00169 TQLineEdit::focusInEvent(e);
00170 }
00171
00172 bool KPasswordEdit::event(TQEvent *e) {
00173 return TQLineEdit::event(e);
00174 }
00175
00176
00177
00178
00179
00180 KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn,
00181 TQWidget *parent, const char *name)
00182 : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn,
00183 Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), m_keepWarnLbl(0), d(new KPasswordDialogPrivate)
00184 {
00185 d->iconName = "password";
00186 init();
00187 }
00188
00189 KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn, const TQString& icon,
00190 TQWidget *parent, const char *name )
00191 : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn,
00192 Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), m_keepWarnLbl(0), d(new KPasswordDialogPrivate)
00193 {
00194 if ( icon.stripWhiteSpace().isEmpty() )
00195 d->iconName = "password";
00196 else
00197 d->iconName = icon;
00198 init();
00199 }
00200
00201 KPasswordDialog::KPasswordDialog(int type, TQString prompt, bool enableKeep,
00202 int extraBttn)
00203 : KDialogBase(0L, "Password Dialog", true, "", Ok|Cancel|extraBttn,
00204 Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), m_keepWarnLbl(0), d(new KPasswordDialogPrivate)
00205 {
00206 d->iconName = "password";
00207 init();
00208 setPrompt(prompt);
00209 }
00210
00211 void KPasswordDialog::init()
00212 {
00213 m_Row = 0;
00214
00215 TDEConfig* const cfg = TDEGlobal::config();
00216 const TDEConfigGroupSaver saver(cfg, "Passwords");
00217 bool def = ( qstrcmp( tqAppName(), "tdesu" ) == 0 ? defKeep : false );
00218 if (m_Keep && cfg->readBoolEntry("Keep", def))
00219 ++m_Keep;
00220
00221 m_pMain = new TQWidget(this);
00222 setMainWidget(m_pMain);
00223 m_pGrid = new TQGridLayout(m_pMain, 10, 3, 0, 0);
00224 m_pGrid->addColSpacing(1, 10);
00225
00226
00227 TQLabel *lbl;
00228 const TQPixmap pix( TDEGlobal::iconLoader()->loadIcon( d->iconName, TDEIcon::NoGroup, TDEIcon::SizeHuge, 0, 0, true));
00229 if (!pix.isNull()) {
00230 lbl = new TQLabel(m_pMain);
00231 lbl->setPixmap(pix);
00232 lbl->setAlignment(AlignHCenter|AlignVCenter);
00233 lbl->setFixedSize(lbl->sizeHint());
00234 m_pGrid->addWidget(lbl, 0, 0, (TQ_Alignment)AlignCenter);
00235 }
00236
00237 m_pHelpLbl = new TQLabel(m_pMain);
00238 m_pHelpLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak);
00239 m_pGrid->addWidget(m_pHelpLbl, 0, 2, (TQ_Alignment)AlignLeft);
00240 m_pGrid->addRowSpacing(1, 10);
00241 m_pGrid->setRowStretch(1, 12);
00242
00243
00244 m_pGrid->addRowSpacing(6, 5);
00245 m_pGrid->setRowStretch(6, 12);
00246
00247
00248 lbl = new TQLabel(m_pMain);
00249 lbl->setAlignment(AlignLeft|AlignVCenter);
00250 lbl->setText(i18n("&Password:"));
00251 lbl->setFixedSize(lbl->sizeHint());
00252 m_pGrid->addWidget(lbl, 7, 0, (TQ_Alignment)AlignLeft);
00253
00254 TQHBoxLayout *h_lay = new TQHBoxLayout();
00255 m_pGrid->addLayout(h_lay, 7, 2);
00256 m_pEdit = new KPasswordEdit(m_pMain);
00257 m_pEdit2 = 0;
00258 lbl->setBuddy(m_pEdit);
00259 TQSize size = m_pEdit->sizeHint();
00260 m_pEdit->setFixedHeight(size.height());
00261 m_pEdit->setMinimumWidth(size.width());
00262 h_lay->addWidget(m_pEdit);
00263
00264
00265
00266 if ((m_Type == Password) && m_Keep) {
00267 m_pGrid->addRowSpacing(8, 10);
00268 m_pGrid->setRowStretch(8, 12);
00269 TQCheckBox* const cb = new TQCheckBox(i18n("&Keep password"), m_pMain);
00270 cb->setFixedSize(cb->sizeHint());
00271 m_keepWarnLbl = new TQLabel(m_pMain);
00272 m_keepWarnLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak);
00273 if (m_Keep > 1) {
00274 cb->setChecked(true);
00275 m_keepWarnLbl->show();
00276 }
00277 else {
00278 m_Keep = 0;
00279 m_keepWarnLbl->hide();
00280 }
00281 connect(cb, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotKeep(bool)));
00282 m_pGrid->addWidget(cb, 9, 2, (TQ_Alignment)(AlignLeft|AlignVCenter));
00283
00284 m_pGrid->addMultiCellWidget(m_keepWarnLbl, 13, 13, 0, 3);
00285 } else if (m_Type == NewPassword) {
00286 m_pGrid->addRowSpacing(8, 10);
00287 lbl = new TQLabel(m_pMain);
00288 lbl->setAlignment(AlignLeft|AlignVCenter);
00289 lbl->setText(i18n("&Verify:"));
00290 lbl->setFixedSize(lbl->sizeHint());
00291 m_pGrid->addWidget(lbl, 9, 0, (TQ_Alignment)AlignLeft);
00292
00293 h_lay = new TQHBoxLayout();
00294 m_pGrid->addLayout(h_lay, 9, 2);
00295 m_pEdit2 = new KPasswordEdit(m_pMain);
00296 lbl->setBuddy(m_pEdit2);
00297 size = m_pEdit2->sizeHint();
00298 m_pEdit2->setFixedHeight(size.height());
00299 m_pEdit2->setMinimumWidth(size.width());
00300 h_lay->addWidget(m_pEdit2);
00301
00302
00303 m_pGrid->addRowSpacing(10, 10);
00304 m_pGrid->setRowStretch(10, 12);
00305
00306 TQHBox* const strengthBox = new TQHBox(m_pMain);
00307 strengthBox->setSpacing(10);
00308 m_pGrid->addMultiCellWidget(strengthBox, 11, 11, 0, 2);
00309 TQLabel* const passStrengthLabel = new TQLabel(strengthBox);
00310 passStrengthLabel->setAlignment(AlignLeft|AlignVCenter);
00311 passStrengthLabel->setText(i18n("Password strength meter:"));
00312 d->m_strengthBar = new KProgress(100, strengthBox, "PasswordStrengthMeter");
00313 d->m_strengthBar->setPercentageVisible(false);
00314
00315 const TQString strengthBarWhatsThis(i18n("The password strength meter gives an indication of the security "
00316 "of the password you have entered. To improve the strength of "
00317 "the password, try:\n"
00318 " - using a longer password;\n"
00319 " - using a mixture of upper- and lower-case letters;\n"
00320 " - using numbers or symbols, such as #, as well as letters."));
00321 TQWhatsThis::add(passStrengthLabel, strengthBarWhatsThis);
00322 TQWhatsThis::add(d->m_strengthBar, strengthBarWhatsThis);
00323
00324
00325 m_pGrid->addRowSpacing(12, 10);
00326 m_pGrid->setRowStretch(12, 12);
00327
00328 d->m_MatchLabel = new TQLabel(m_pMain);
00329 d->m_MatchLabel->setAlignment(AlignLeft|AlignVCenter|WordBreak);
00330 m_pGrid->addMultiCellWidget(d->m_MatchLabel, 13, 13, 0, 2);
00331 d->m_MatchLabel->setText(i18n("Passwords do not match"));
00332
00333
00334 connect( m_pEdit, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(enableOkBtn()) );
00335 connect( m_pEdit2, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(enableOkBtn()) );
00336 enableOkBtn();
00337 }
00338
00339 erase();
00340 }
00341
00342
00343 KPasswordDialog::~KPasswordDialog()
00344 {
00345 delete d;
00346 }
00347
00348
00349 void KPasswordDialog::clearPassword()
00350 {
00351 m_pEdit->erase();
00352 }
00353
00354
00355 void KPasswordDialog::setPrompt(TQString prompt)
00356 {
00357 m_pHelpLbl->setText(prompt);
00358 m_pHelpLbl->setFixedSize(275, m_pHelpLbl->heightForWidth(275));
00359 }
00360
00361 void KPasswordDialog::setKeepWarning(TQString warn)
00362 {
00363 if (m_keepWarnLbl) {
00364 m_keepWarnLbl->setText(warn);
00365 }
00366 }
00367
00368
00369 TQString KPasswordDialog::prompt() const
00370
00371 {
00372 return m_pHelpLbl->text();
00373 }
00374
00375
00376
00377 void KPasswordDialog::addLine(TQString key, TQString value)
00378 {
00379 if (m_Row > 3)
00380 return;
00381
00382 TQLabel *lbl = new TQLabel(key, m_pMain);
00383 lbl->setAlignment(AlignLeft|AlignTop);
00384 lbl->setFixedSize(lbl->sizeHint());
00385 m_pGrid->addWidget(lbl, m_Row+2, 0, (TQ_Alignment)AlignLeft);
00386
00387 lbl = new TQLabel(value, m_pMain);
00388 lbl->setAlignment(AlignTop|WordBreak);
00389 lbl->setFixedSize(275, lbl->heightForWidth(275));
00390 m_pGrid->addWidget(lbl, m_Row+2, 2, (TQ_Alignment)AlignLeft);
00391 ++m_Row;
00392 }
00393
00394
00395 void KPasswordDialog::erase()
00396 {
00397 m_pEdit->erase();
00398 m_pEdit->setFocus();
00399 if (m_Type == NewPassword)
00400 m_pEdit2->erase();
00401 }
00402
00403
00404 void KPasswordDialog::slotOk()
00405 {
00406 if (m_Type == NewPassword) {
00407 if (m_pEdit->password() != m_pEdit2->password()) {
00408 KMessageBox::sorry(this, i18n("You entered two different "
00409 "passwords. Please try again."));
00410 erase();
00411 return;
00412 }
00413 if (d->m_strengthBar && d->m_strengthBar->progress() < d->passwordStrengthWarningLevel) {
00414 int retVal = KMessageBox::warningContinueCancel(this,
00415 i18n( "The password you have entered has a low strength. "
00416 "To improve the strength of "
00417 "the password, try:\n"
00418 " - using a longer password;\n"
00419 " - using a mixture of upper- and lower-case letters;\n"
00420 " - using numbers or symbols as well as letters.\n"
00421 "\n"
00422 "Would you like to use this password anyway?"),
00423 i18n("Low Password Strength"));
00424 if (retVal == KMessageBox::Cancel) return;
00425 }
00426 }
00427 if (!checkPassword(m_pEdit->password())) {
00428 erase();
00429 return;
00430 }
00431 accept();
00432 }
00433
00434
00435 void KPasswordDialog::slotCancel()
00436 {
00437 reject();
00438 }
00439
00440
00441 void KPasswordDialog::slotKeep(bool keep)
00442 {
00443 if (m_keepWarnLbl->text() != "") {
00444 if (keep) {
00445 m_keepWarnLbl->show();
00446 }
00447 else {
00448 m_keepWarnLbl->hide();
00449 }
00450 TQTimer::singleShot(0, this, SLOT(slotLayout()));
00451 }
00452
00453 m_Keep = keep;
00454 }
00455
00456 void KPasswordDialog::slotLayout()
00457 {
00458 resize(sizeHint());
00459 }
00460
00461
00462 int KPasswordDialog::getPassword(TQString &password, TQString prompt,
00463 int *keep)
00464 {
00465 const bool enableKeep = (keep && *keep);
00466 KPasswordDialog* const dlg = new KPasswordDialog(int(Password), prompt, enableKeep);
00467 const int ret = dlg->exec();
00468 if (ret == Accepted) {
00469 password = dlg->password();
00470 if (enableKeep)
00471 *keep = dlg->keep();
00472 }
00473 delete dlg;
00474 return ret;
00475 }
00476
00477
00478
00479 int KPasswordDialog::getNewPassword(TQString &password, TQString prompt)
00480 {
00481 KPasswordDialog* const dlg = new KPasswordDialog(NewPassword, prompt);
00482 const int ret = dlg->exec();
00483 if (ret == Accepted)
00484 password = dlg->password();
00485 delete dlg;
00486 return ret;
00487 }
00488
00489
00490
00491 void KPasswordDialog::disableCoreDumps()
00492 {
00493 struct rlimit rlim;
00494 rlim.rlim_cur = rlim.rlim_max = 0;
00495 setrlimit(RLIMIT_CORE, &rlim);
00496 }
00497
00498 void KPasswordDialog::virtual_hook( int id, void* data )
00499 { KDialogBase::virtual_hook( id, data ); }
00500
00501 void KPasswordDialog::enableOkBtn()
00502 {
00503 if (m_Type == NewPassword) {
00504 const bool match = (m_pEdit->password() == m_pEdit2->password())
00505 && (d->allowEmptyPasswords || !m_pEdit->password().isEmpty());
00506
00507 const TQString pass(m_pEdit->password());
00508
00509 const int minPasswordLength = minimumPasswordLength();
00510
00511 if ((int) pass.length() < minPasswordLength) {
00512 enableButtonOK(false);
00513 } else {
00514 enableButtonOK( match );
00515 }
00516
00517 if ( match && d->allowEmptyPasswords && m_pEdit->password().isEmpty() ) {
00518 d->m_MatchLabel->setText( i18n("Password is empty") );
00519 } else {
00520 if ((int) pass.length() < minPasswordLength) {
00521 d->m_MatchLabel->setText(i18n("Password must be at least 1 character long", "Password must be at least %n characters long", minPasswordLength));
00522 } else {
00523 d->m_MatchLabel->setText( match? i18n("Passwords match")
00524 :i18n("Passwords do not match") );
00525 }
00526 }
00527
00528
00529
00530
00531
00532
00533
00534 const double lengthFactor = d->reasonablePasswordLength / 8.0;
00535
00536
00537 int pwlength = (int) (pass.length() / lengthFactor);
00538 if (pwlength > 5) pwlength = 5;
00539
00540 const TQRegExp numRxp("[0-9]", true, false);
00541 int numeric = (int) (pass.contains(numRxp) / lengthFactor);
00542 if (numeric > 3) numeric = 3;
00543
00544 const TQRegExp symbRxp("\\W", false, false);
00545 int numsymbols = (int) (pass.contains(symbRxp) / lengthFactor);
00546 if (numsymbols > 3) numsymbols = 3;
00547
00548 const TQRegExp upperRxp("[A-Z]", true, false);
00549 int upper = (int) (pass.contains(upperRxp) / lengthFactor);
00550 if (upper > 3) upper = 3;
00551
00552 int pwstrength=((pwlength*10)-20) + (numeric*10) + (numsymbols*15) + (upper*10);
00553
00554 if ( pwstrength < 0 ) {
00555 pwstrength = 0;
00556 }
00557
00558 if ( pwstrength > 100 ) {
00559 pwstrength = 100;
00560 }
00561 d->m_strengthBar->setProgress(pwstrength);
00562
00563 }
00564 }
00565
00566
00567 void KPasswordDialog::setAllowEmptyPasswords(bool allowed) {
00568 d->allowEmptyPasswords = allowed;
00569 enableOkBtn();
00570 }
00571
00572
00573 bool KPasswordDialog::allowEmptyPasswords() const {
00574 return d->allowEmptyPasswords;
00575 }
00576
00577 void KPasswordDialog::setMinimumPasswordLength(int minLength) {
00578 d->minimumPasswordLength = minLength;
00579 enableOkBtn();
00580 }
00581
00582 int KPasswordDialog::minimumPasswordLength() const {
00583 return d->minimumPasswordLength;
00584 }
00585
00586 void KPasswordDialog::setMaximumPasswordLength(int maxLength) {
00587
00588 if (maxLength < 0) maxLength = 0;
00589 if (maxLength >= KPasswordEdit::PassLen) maxLength = KPasswordEdit::PassLen - 1;
00590
00591 d->maximumPasswordLength = maxLength;
00592
00593 m_pEdit->setMaxPasswordLength(maxLength);
00594 if (m_pEdit2) m_pEdit2->setMaxPasswordLength(maxLength);
00595
00596 }
00597
00598 int KPasswordDialog::maximumPasswordLength() const {
00599 return d->maximumPasswordLength;
00600 }
00601
00602
00603
00604 void KPasswordDialog::setReasonablePasswordLength(int reasonableLength) {
00605
00606 if (reasonableLength < 1) reasonableLength = 1;
00607 if (reasonableLength >= maximumPasswordLength()) reasonableLength = maximumPasswordLength();
00608
00609 d->reasonablePasswordLength = reasonableLength;
00610
00611 }
00612
00613 int KPasswordDialog::reasonablePasswordLength() const {
00614 return d->reasonablePasswordLength;
00615 }
00616
00617
00618 void KPasswordDialog::setPasswordStrengthWarningLevel(int warningLevel) {
00619 if (warningLevel < 0) warningLevel = 0;
00620 if (warningLevel > 99) warningLevel = 99;
00621 d->passwordStrengthWarningLevel = warningLevel;
00622 }
00623
00624 int KPasswordDialog::passwordStrengthWarningLevel() const {
00625 return d->passwordStrengthWarningLevel;
00626 }
00627
00628 #include "kpassdlg.moc"