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