kpassdlg.cpp
00001 // vi: ts=8 sts=4 sw=4 00002 /* This file is part of the KDE libraries 00003 Copyright (C) 1998 Pietro Iglio <iglio@fub.it> 00004 Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org> 00005 Copyright (C) 2004,2005 Andrew Coles <andrew_coles@yahoo.co.uk> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 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 <kglobal.h> 00038 #include <kdebug.h> 00039 #include <kapplication.h> 00040 #include <klocale.h> 00041 #include <kiconloader.h> 00042 #include <kmessagebox.h> 00043 #include <kaboutdialog.h> 00044 #include <kconfig.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 "../kdesu/defaults.h" 00054 00055 /* 00056 * Password line editor. 00057 */ 00058 00059 // BCI: Add a real d-pointer and put the int into that 00060 00061 static TQPtrDict<int>* d_ptr = 0; 00062 00063 static void cleanup_d_ptr() { 00064 delete d_ptr; 00065 } 00066 00067 static int * ourMaxLength( const KPasswordEdit* const e ) { 00068 if ( !d_ptr ) { 00069 d_ptr = new TQPtrDict<int>; 00070 d_ptr->setAutoDelete(true); 00071 qAddPostRoutine( cleanup_d_ptr ); 00072 } 00073 int* ret = d_ptr->find( (void*) e ); 00074 if ( ! ret ) { 00075 ret = new int; 00076 d_ptr->replace( (void*) e, ret ); 00077 } 00078 return ret; 00079 } 00080 00081 static void delete_d( const KPasswordEdit* const e ) { 00082 if ( d_ptr ) 00083 d_ptr->remove( (void*) e ); 00084 } 00085 00086 const int KPasswordEdit::PassLen = 200; 00087 00088 class KPasswordDialog::KPasswordDialogPrivate 00089 { 00090 public: 00091 KPasswordDialogPrivate() 00092 : m_MatchLabel( 0 ), iconName( 0 ), allowEmptyPasswords( false ), 00093 minimumPasswordLength(0), maximumPasswordLength(KPasswordEdit::PassLen - 1), 00094 passwordStrengthWarningLevel(1), m_strengthBar(0), 00095 reasonablePasswordLength(8) 00096 {} 00097 TQLabel *m_MatchLabel; 00098 TQString iconName; 00099 bool allowEmptyPasswords; 00100 int minimumPasswordLength; 00101 int maximumPasswordLength; 00102 int passwordStrengthWarningLevel; 00103 KProgress* m_strengthBar; 00104 int reasonablePasswordLength; 00105 }; 00106 00107 00108 KPasswordEdit::KPasswordEdit(TQWidget *parent, const char *name) 00109 : TQLineEdit(parent, name) 00110 { 00111 init(); 00112 00113 KConfig* const cfg = KGlobal::config(); 00114 KConfigGroupSaver saver(cfg, "Passwords"); 00115 00116 const TQString val = cfg->readEntry("EchoMode", "OneStar"); 00117 if (val == "ThreeStars") 00118 m_EchoMode = ThreeStars; 00119 else if (val == "NoEcho") 00120 m_EchoMode = NoEcho; 00121 else 00122 m_EchoMode = OneStar; 00123 00124 setInputMethodEnabled( true ); 00125 } 00126 00127 KPasswordEdit::KPasswordEdit(TQWidget *parent, const char *name, int echoMode) 00128 : TQLineEdit(parent, name), m_EchoMode(echoMode) 00129 { 00130 init(); 00131 } 00132 00133 KPasswordEdit::KPasswordEdit(EchoModes echoMode, TQWidget *parent, const char *name) 00134 : TQLineEdit(parent, name), m_EchoMode(echoMode) 00135 { 00136 init(); 00137 } 00138 00139 KPasswordEdit::KPasswordEdit(EchoMode echoMode, TQWidget *parent, const char *name) 00140 : TQLineEdit(parent, name) 00141 , m_EchoMode( echoMode == TQLineEdit::NoEcho ? NoEcho : OneStar ) 00142 { 00143 init(); 00144 } 00145 00146 void KPasswordEdit::init() 00147 { 00148 setEchoMode(TQLineEdit::Password); // Just in case 00149 setAcceptDrops(false); 00150 int* t = ourMaxLength(this); 00151 *t = (PassLen - 1); // the internal max length 00152 m_Password = new char[PassLen]; 00153 m_Password[0] = '\000'; 00154 m_Length = 0; 00155 } 00156 00157 KPasswordEdit::~KPasswordEdit() 00158 { 00159 memset(m_Password, 0, PassLen * sizeof(char)); 00160 delete[] m_Password; 00161 delete_d(this); 00162 } 00163 00164 void KPasswordEdit::insert(const TQString &txt) 00165 { 00166 const TQCString localTxt = txt.local8Bit(); 00167 const unsigned int lim = localTxt.length(); 00168 const int m_MaxLength = maxPasswordLength(); 00169 for(unsigned int i=0; i < lim; ++i) 00170 { 00171 const unsigned char ke = localTxt[i]; 00172 if (m_Length < m_MaxLength) 00173 { 00174 m_Password[m_Length] = ke; 00175 m_Password[++m_Length] = '\000'; 00176 } 00177 } 00178 showPass(); 00179 } 00180 00181 void KPasswordEdit::erase() 00182 { 00183 m_Length = 0; 00184 memset(m_Password, 0, PassLen * sizeof(char)); 00185 setText(""); 00186 } 00187 00188 void KPasswordEdit::focusInEvent(TQFocusEvent *e) 00189 { 00190 const TQString txt = text(); 00191 setUpdatesEnabled(false); 00192 TQLineEdit::focusInEvent(e); 00193 setUpdatesEnabled(true); 00194 setText(txt); 00195 } 00196 00197 00198 void KPasswordEdit::keyPressEvent(TQKeyEvent *e) 00199 { 00200 switch (e->key()) { 00201 case Key_Return: 00202 case Key_Enter: 00203 case Key_Escape: 00204 e->ignore(); 00205 break; 00206 case Key_Backspace: 00207 case Key_Delete: 00208 case 0x7f: // Delete 00209 if (e->state() & (ControlButton | AltButton)) 00210 e->ignore(); 00211 else if (m_Length) { 00212 m_Password[--m_Length] = '\000'; 00213 showPass(); 00214 } 00215 break; 00216 default: 00217 const unsigned char ke = TQString(e->text()).local8Bit()[0]; 00218 if (ke >= 32) { 00219 insert(e->text()); 00220 } else 00221 e->ignore(); 00222 break; 00223 } 00224 } 00225 00226 bool KPasswordEdit::event(TQEvent *e) { 00227 switch(e->type()) { 00228 00229 case TQEvent::MouseButtonPress: 00230 case TQEvent::MouseButtonRelease: 00231 case TQEvent::MouseButtonDblClick: 00232 case TQEvent::MouseMove: 00233 case TQEvent::IMStart: 00234 case TQEvent::IMCompose: 00235 return true; //Ignore 00236 00237 case TQEvent::IMEnd: 00238 { 00239 TQIMEvent* const ie = (TQIMEvent*) e; 00240 if (!ie->text().isEmpty()) 00241 insert( ie->text() ); 00242 return true; 00243 } 00244 00245 case TQEvent::AccelOverride: 00246 { 00247 TQKeyEvent* const k = (TQKeyEvent*) e; 00248 switch (k->key()) { 00249 case Key_U: 00250 if (k->state() & ControlButton) { 00251 m_Length = 0; 00252 m_Password[m_Length] = '\000'; 00253 showPass(); 00254 } 00255 } 00256 return true; // stop bubbling 00257 } 00258 00259 default: 00260 // Do nothing 00261 break; 00262 } 00263 return TQLineEdit::event(e); 00264 } 00265 00266 void KPasswordEdit::showPass() 00267 { 00268 TQString tmp; 00269 00270 switch (m_EchoMode) { 00271 case OneStar: 00272 tmp.fill('*', m_Length); 00273 setText(tmp); 00274 break; 00275 case ThreeStars: 00276 tmp.fill('*', m_Length*3); 00277 setText(tmp); 00278 break; 00279 case NoEcho: default: 00280 emit textChanged(TQString::null); //To update the password comparison if need be. 00281 break; 00282 } 00283 } 00284 00285 void KPasswordEdit::setMaxPasswordLength(int newLength) 00286 { 00287 if (newLength >= PassLen) newLength = PassLen - 1; // belt and braces 00288 if (newLength < 0) newLength = 0; 00289 int* t = ourMaxLength(this); 00290 *t = newLength; 00291 while (m_Length > newLength) { 00292 m_Password[m_Length] = '\000'; 00293 --m_Length; 00294 } 00295 showPass(); 00296 } 00297 00298 int KPasswordEdit::maxPasswordLength() const 00299 { 00300 return *(ourMaxLength(this)); 00301 } 00302 /* 00303 * Password dialog. 00304 */ 00305 00306 KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn, 00307 TQWidget *parent, const char *name) 00308 : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn, 00309 Ok, true), m_Keep(enableKeep? 1 : 0), m_keepWarnLbl(0), m_Type(type), d(new KPasswordDialogPrivate) 00310 { 00311 d->iconName = "password"; 00312 init(); 00313 } 00314 00315 KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn, const TQString& icon, 00316 TQWidget *parent, const char *name ) 00317 : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn, 00318 Ok, true), m_Keep(enableKeep? 1 : 0), m_keepWarnLbl(0), m_Type(type), d(new KPasswordDialogPrivate) 00319 { 00320 if ( icon.stripWhiteSpace().isEmpty() ) 00321 d->iconName = "password"; 00322 else 00323 d->iconName = icon; 00324 init(); 00325 } 00326 00327 KPasswordDialog::KPasswordDialog(int type, TQString prompt, bool enableKeep, 00328 int extraBttn) 00329 : KDialogBase(0L, "Password Dialog", true, "", Ok|Cancel|extraBttn, 00330 Ok, true), m_Keep(enableKeep? 1 : 0), m_keepWarnLbl(0), m_Type(type), d(new KPasswordDialogPrivate) 00331 { 00332 d->iconName = "password"; 00333 init(); 00334 setPrompt(prompt); 00335 } 00336 00337 void KPasswordDialog::init() 00338 { 00339 m_Row = 0; 00340 00341 KConfig* const cfg = KGlobal::config(); 00342 const KConfigGroupSaver saver(cfg, "Passwords"); 00343 bool def = ( qstrcmp( tqAppName(), "kdesu" ) == 0 ? defKeep : false ); 00344 if (m_Keep && cfg->readBoolEntry("Keep", def)) 00345 ++m_Keep; 00346 00347 m_pMain = new TQWidget(this); 00348 setMainWidget(m_pMain); 00349 m_pGrid = new TQGridLayout(m_pMain, 10, 3, 0, 0); 00350 m_pGrid->addColSpacing(1, 10); 00351 00352 // Row 1: pixmap + prompt 00353 TQLabel *lbl; 00354 const TQPixmap pix( KGlobal::iconLoader()->loadIcon( d->iconName, KIcon::NoGroup, KIcon::SizeHuge, 0, 0, true)); 00355 if (!pix.isNull()) { 00356 lbl = new TQLabel(m_pMain); 00357 lbl->setPixmap(pix); 00358 lbl->setAlignment(AlignHCenter|AlignVCenter); 00359 lbl->setFixedSize(lbl->sizeHint()); 00360 m_pGrid->addWidget(lbl, 0, 0, (TQ_Alignment)AlignCenter); 00361 } 00362 00363 m_pHelpLbl = new TQLabel(m_pMain); 00364 m_pHelpLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak); 00365 m_pGrid->addWidget(m_pHelpLbl, 0, 2, (TQ_Alignment)AlignLeft); 00366 m_pGrid->addRowSpacing(1, 10); 00367 m_pGrid->setRowStretch(1, 12); 00368 00369 // Row 2+: space for 4 extra info lines 00370 m_pGrid->addRowSpacing(6, 5); 00371 m_pGrid->setRowStretch(6, 12); 00372 00373 // Row 3: Password editor #1 00374 lbl = new TQLabel(m_pMain); 00375 lbl->setAlignment(AlignLeft|AlignVCenter); 00376 lbl->setText(i18n("&Password:")); 00377 lbl->setFixedSize(lbl->sizeHint()); 00378 m_pGrid->addWidget(lbl, 7, 0, (TQ_Alignment)AlignLeft); 00379 00380 TQHBoxLayout *h_lay = new TQHBoxLayout(); 00381 m_pGrid->addLayout(h_lay, 7, 2); 00382 m_pEdit = new KPasswordEdit(m_pMain); 00383 m_pEdit2 = 0; 00384 lbl->setBuddy(m_pEdit); 00385 TQSize size = m_pEdit->sizeHint(); 00386 m_pEdit->setFixedHeight(size.height()); 00387 m_pEdit->setMinimumWidth(size.width()); 00388 h_lay->addWidget(m_pEdit); 00389 00390 // Row 4: Password editor #2 or keep password checkbox 00391 00392 if ((m_Type == Password) && m_Keep) { 00393 m_pGrid->addRowSpacing(8, 10); 00394 m_pGrid->setRowStretch(8, 12); 00395 TQCheckBox* const cb = new TQCheckBox(i18n("&Keep password"), m_pMain); 00396 cb->setFixedSize(cb->sizeHint()); 00397 m_keepWarnLbl = new TQLabel(m_pMain); 00398 m_keepWarnLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak); 00399 if (m_Keep > 1) { 00400 cb->setChecked(true); 00401 m_keepWarnLbl->show(); 00402 } 00403 else { 00404 m_Keep = 0; 00405 m_keepWarnLbl->hide(); 00406 } 00407 connect(cb, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotKeep(bool))); 00408 m_pGrid->addWidget(cb, 9, 2, (TQ_Alignment)(AlignLeft|AlignVCenter)); 00409 // m_pGrid->addWidget(m_keepWarnLbl, 13, 2, (TQ_Alignment)(AlignLeft|AlignVCenter)); 00410 m_pGrid->addMultiCellWidget(m_keepWarnLbl, 13, 13, 0, 3); 00411 } else if (m_Type == NewPassword) { 00412 m_pGrid->addRowSpacing(8, 10); 00413 lbl = new TQLabel(m_pMain); 00414 lbl->setAlignment(AlignLeft|AlignVCenter); 00415 lbl->setText(i18n("&Verify:")); 00416 lbl->setFixedSize(lbl->sizeHint()); 00417 m_pGrid->addWidget(lbl, 9, 0, (TQ_Alignment)AlignLeft); 00418 00419 h_lay = new TQHBoxLayout(); 00420 m_pGrid->addLayout(h_lay, 9, 2); 00421 m_pEdit2 = new KPasswordEdit(m_pMain); 00422 lbl->setBuddy(m_pEdit2); 00423 size = m_pEdit2->sizeHint(); 00424 m_pEdit2->setFixedHeight(size.height()); 00425 m_pEdit2->setMinimumWidth(size.width()); 00426 h_lay->addWidget(m_pEdit2); 00427 00428 // Row 6: Password strength meter 00429 m_pGrid->addRowSpacing(10, 10); 00430 m_pGrid->setRowStretch(10, 12); 00431 00432 TQHBox* const strengthBox = new TQHBox(m_pMain); 00433 strengthBox->setSpacing(10); 00434 m_pGrid->addMultiCellWidget(strengthBox, 11, 11, 0, 2); 00435 TQLabel* const passStrengthLabel = new TQLabel(strengthBox); 00436 passStrengthLabel->setAlignment(AlignLeft|AlignVCenter); 00437 passStrengthLabel->setText(i18n("Password strength meter:")); 00438 d->m_strengthBar = new KProgress(100, strengthBox, "PasswordStrengthMeter"); 00439 d->m_strengthBar->setPercentageVisible(false); 00440 00441 const TQString strengthBarWhatsThis(i18n("The password strength meter gives an indication of the security " 00442 "of the password you have entered. To improve the strength of " 00443 "the password, try:\n" 00444 " - using a longer password;\n" 00445 " - using a mixture of upper- and lower-case letters;\n" 00446 " - using numbers or symbols, such as #, as well as letters.")); 00447 TQWhatsThis::add(passStrengthLabel, strengthBarWhatsThis); 00448 TQWhatsThis::add(d->m_strengthBar, strengthBarWhatsThis); 00449 00450 // Row 6: Label saying whether the passwords match 00451 m_pGrid->addRowSpacing(12, 10); 00452 m_pGrid->setRowStretch(12, 12); 00453 00454 d->m_MatchLabel = new TQLabel(m_pMain); 00455 d->m_MatchLabel->setAlignment(AlignLeft|AlignVCenter|WordBreak); 00456 m_pGrid->addMultiCellWidget(d->m_MatchLabel, 13, 13, 0, 2); 00457 d->m_MatchLabel->setText(i18n("Passwords do not match")); 00458 00459 00460 connect( m_pEdit, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(enableOkBtn()) ); 00461 connect( m_pEdit2, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(enableOkBtn()) ); 00462 enableOkBtn(); 00463 } 00464 00465 erase(); 00466 } 00467 00468 00469 KPasswordDialog::~KPasswordDialog() 00470 { 00471 delete d; 00472 } 00473 00474 00475 void KPasswordDialog::clearPassword() 00476 { 00477 m_pEdit->erase(); 00478 } 00479 00480 /* KDE 4: Make it const TQString & */ 00481 void KPasswordDialog::setPrompt(TQString prompt) 00482 { 00483 m_pHelpLbl->setText(prompt); 00484 m_pHelpLbl->setFixedSize(275, m_pHelpLbl->heightForWidth(275)); 00485 } 00486 00487 void KPasswordDialog::setKeepWarning(TQString warn) 00488 { 00489 if (m_keepWarnLbl) { 00490 m_keepWarnLbl->setText(warn); 00491 } 00492 } 00493 00494 00495 TQString KPasswordDialog::prompt() const 00496 00497 { 00498 return m_pHelpLbl->text(); 00499 } 00500 00501 00502 /* KDE 4: Make them const TQString & */ 00503 void KPasswordDialog::addLine(TQString key, TQString value) 00504 { 00505 if (m_Row > 3) 00506 return; 00507 00508 TQLabel *lbl = new TQLabel(key, m_pMain); 00509 lbl->setAlignment(AlignLeft|AlignTop); 00510 lbl->setFixedSize(lbl->sizeHint()); 00511 m_pGrid->addWidget(lbl, m_Row+2, 0, (TQ_Alignment)AlignLeft); 00512 00513 lbl = new TQLabel(value, m_pMain); 00514 lbl->setAlignment(AlignTop|WordBreak); 00515 lbl->setFixedSize(275, lbl->heightForWidth(275)); 00516 m_pGrid->addWidget(lbl, m_Row+2, 2, (TQ_Alignment)AlignLeft); 00517 ++m_Row; 00518 } 00519 00520 00521 void KPasswordDialog::erase() 00522 { 00523 m_pEdit->erase(); 00524 m_pEdit->setFocus(); 00525 if (m_Type == NewPassword) 00526 m_pEdit2->erase(); 00527 } 00528 00529 00530 void KPasswordDialog::slotOk() 00531 { 00532 if (m_Type == NewPassword) { 00533 if (strcmp(m_pEdit->password(), m_pEdit2->password())) { 00534 KMessageBox::sorry(this, i18n("You entered two different " 00535 "passwords. Please try again.")); 00536 erase(); 00537 return; 00538 } 00539 if (d->m_strengthBar && d->m_strengthBar->progress() < d->passwordStrengthWarningLevel) { 00540 int retVal = KMessageBox::warningContinueCancel(this, 00541 i18n( "The password you have entered has a low strength. " 00542 "To improve the strength of " 00543 "the password, try:\n" 00544 " - using a longer password;\n" 00545 " - using a mixture of upper- and lower-case letters;\n" 00546 " - using numbers or symbols as well as letters.\n" 00547 "\n" 00548 "Would you like to use this password anyway?"), 00549 i18n("Low Password Strength")); 00550 if (retVal == KMessageBox::Cancel) return; 00551 } 00552 } 00553 if (!checkPassword(m_pEdit->password())) { 00554 erase(); 00555 return; 00556 } 00557 accept(); 00558 } 00559 00560 00561 void KPasswordDialog::slotCancel() 00562 { 00563 reject(); 00564 } 00565 00566 00567 void KPasswordDialog::slotKeep(bool keep) 00568 { 00569 if (m_keepWarnLbl->text() != "") { 00570 if (keep) { 00571 m_keepWarnLbl->show(); 00572 } 00573 else { 00574 m_keepWarnLbl->hide(); 00575 } 00576 TQTimer::singleShot(0, this, SLOT(slotLayout())); 00577 } 00578 00579 m_Keep = keep; 00580 } 00581 00582 void KPasswordDialog::slotLayout() 00583 { 00584 resize(sizeHint()); 00585 } 00586 00587 00588 // static . antlarr: KDE 4: Make it const TQString & prompt 00589 int KPasswordDialog::getPassword(TQCString &password, TQString prompt, 00590 int *keep) 00591 { 00592 const bool enableKeep = (keep && *keep); 00593 KPasswordDialog* const dlg = new KPasswordDialog(int(Password), prompt, enableKeep); 00594 const int ret = dlg->exec(); 00595 if (ret == Accepted) { 00596 password = dlg->password(); 00597 if (enableKeep) 00598 *keep = dlg->keep(); 00599 } 00600 delete dlg; 00601 return ret; 00602 } 00603 00604 00605 // static . antlarr: KDE 4: Make it const TQString & prompt 00606 int KPasswordDialog::getNewPassword(TQCString &password, TQString prompt) 00607 { 00608 KPasswordDialog* const dlg = new KPasswordDialog(NewPassword, prompt); 00609 const int ret = dlg->exec(); 00610 if (ret == Accepted) 00611 password = dlg->password(); 00612 delete dlg; 00613 return ret; 00614 } 00615 00616 00617 // static 00618 void KPasswordDialog::disableCoreDumps() 00619 { 00620 struct rlimit rlim; 00621 rlim.rlim_cur = rlim.rlim_max = 0; 00622 setrlimit(RLIMIT_CORE, &rlim); 00623 } 00624 00625 void KPasswordDialog::virtual_hook( int id, void* data ) 00626 { KDialogBase::virtual_hook( id, data ); } 00627 00628 void KPasswordDialog::enableOkBtn() 00629 { 00630 if (m_Type == NewPassword) { 00631 const bool match = strcmp(m_pEdit->password(), m_pEdit2->password()) == 0 00632 && (d->allowEmptyPasswords || m_pEdit->password()[0]); 00633 00634 const TQString pass(m_pEdit->password()); 00635 00636 const int minPasswordLength = minimumPasswordLength(); 00637 00638 if ((int) pass.length() < minPasswordLength) { 00639 enableButtonOK(false); 00640 } else { 00641 enableButtonOK( match ); 00642 } 00643 00644 if ( match && d->allowEmptyPasswords && m_pEdit->password()[0] == 0 ) { 00645 d->m_MatchLabel->setText( i18n("Password is empty") ); 00646 } else { 00647 if ((int) pass.length() < minPasswordLength) { 00648 d->m_MatchLabel->setText(i18n("Password must be at least 1 character long", "Password must be at least %n characters long", minPasswordLength)); 00649 } else { 00650 d->m_MatchLabel->setText( match? i18n("Passwords match") 00651 :i18n("Passwords do not match") ); 00652 } 00653 } 00654 00655 // Password strength calculator 00656 // Based on code in the Master Password dialog in Firefox 00657 // (pref-masterpass.js) 00658 // Original code triple-licensed under the MPL, GPL, and LGPL 00659 // so is license-compatible with this file 00660 00661 const double lengthFactor = d->reasonablePasswordLength / 8.0; 00662 00663 00664 int pwlength = (int) (pass.length() / lengthFactor); 00665 if (pwlength > 5) pwlength = 5; 00666 00667 const TQRegExp numRxp("[0-9]", true, false); 00668 int numeric = (int) (pass.contains(numRxp) / lengthFactor); 00669 if (numeric > 3) numeric = 3; 00670 00671 const TQRegExp symbRxp("\\W", false, false); 00672 int numsymbols = (int) (pass.contains(symbRxp) / lengthFactor); 00673 if (numsymbols > 3) numsymbols = 3; 00674 00675 const TQRegExp upperRxp("[A-Z]", true, false); 00676 int upper = (int) (pass.contains(upperRxp) / lengthFactor); 00677 if (upper > 3) upper = 3; 00678 00679 int pwstrength=((pwlength*10)-20) + (numeric*10) + (numsymbols*15) + (upper*10); 00680 00681 if ( pwstrength < 0 ) { 00682 pwstrength = 0; 00683 } 00684 00685 if ( pwstrength > 100 ) { 00686 pwstrength = 100; 00687 } 00688 d->m_strengthBar->setProgress(pwstrength); 00689 00690 } 00691 } 00692 00693 00694 void KPasswordDialog::setAllowEmptyPasswords(bool allowed) { 00695 d->allowEmptyPasswords = allowed; 00696 enableOkBtn(); 00697 } 00698 00699 00700 bool KPasswordDialog::allowEmptyPasswords() const { 00701 return d->allowEmptyPasswords; 00702 } 00703 00704 void KPasswordDialog::setMinimumPasswordLength(int minLength) { 00705 d->minimumPasswordLength = minLength; 00706 enableOkBtn(); 00707 } 00708 00709 int KPasswordDialog::minimumPasswordLength() const { 00710 return d->minimumPasswordLength; 00711 } 00712 00713 void KPasswordDialog::setMaximumPasswordLength(int maxLength) { 00714 00715 if (maxLength < 0) maxLength = 0; 00716 if (maxLength >= KPasswordEdit::PassLen) maxLength = KPasswordEdit::PassLen - 1; 00717 00718 d->maximumPasswordLength = maxLength; 00719 00720 m_pEdit->setMaxPasswordLength(maxLength); 00721 if (m_pEdit2) m_pEdit2->setMaxPasswordLength(maxLength); 00722 00723 } 00724 00725 int KPasswordDialog::maximumPasswordLength() const { 00726 return d->maximumPasswordLength; 00727 } 00728 00729 // reasonable password length code contributed by Steffen Mthing 00730 00731 void KPasswordDialog::setReasonablePasswordLength(int reasonableLength) { 00732 00733 if (reasonableLength < 1) reasonableLength = 1; 00734 if (reasonableLength >= maximumPasswordLength()) reasonableLength = maximumPasswordLength(); 00735 00736 d->reasonablePasswordLength = reasonableLength; 00737 00738 } 00739 00740 int KPasswordDialog::reasonablePasswordLength() const { 00741 return d->reasonablePasswordLength; 00742 } 00743 00744 00745 void KPasswordDialog::setPasswordStrengthWarningLevel(int warningLevel) { 00746 if (warningLevel < 0) warningLevel = 0; 00747 if (warningLevel > 99) warningLevel = 99; 00748 d->passwordStrengthWarningLevel = warningLevel; 00749 } 00750 00751 int KPasswordDialog::passwordStrengthWarningLevel() const { 00752 return d->passwordStrengthWarningLevel; 00753 } 00754 00755 #include "kpassdlg.moc"