/* Conversation widget for kdm greeter Copyright (C) 1997, 1998, 2000 Steffen Hansen Copyright (C) 2000-2003 Oswald Buddenhagen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kgreet_classic.h" #include #include #include #include #include #include #include static int echoMode; class KDMPasswordEdit : public KLineEdit { public: KDMPasswordEdit(QWidget *parent) : KLineEdit(parent) { if (::echoMode == -1) setPasswordMode(true); else setEchoMode(::echoMode ? Password : NoEcho); setContextMenuPolicy(Qt::NoContextMenu); } }; KClassicGreeter::KClassicGreeter(KGreeterPluginHandler *_handler, QWidget *parent, const QString &_fixedEntity, Function _func, Context _ctx) : QObject(), KGreeterPlugin(_handler), fixedUser(_fixedEntity), func(_func), ctx(_ctx), exp(-1), pExp(-1), running(false) { QFormLayout *formLay = 0; if (!_handler->gplugHasNode("user-entry") || !_handler->gplugHasNode("pw-entry")) { parent = new QWidget(parent); parent->setObjectName("talker"); widgetList << parent; formLay = new QFormLayout(parent); formLay->setMargin(0); } loginLabel = passwdLabel = passwd1Label = passwd2Label = 0; loginEdit = 0; passwdEdit = passwd1Edit = passwd2Edit = 0; if (ctx == ExUnlock || ctx == ExChangeTok) fixedUser = KUser().loginName(); if (func != ChAuthTok) { if (fixedUser.isEmpty()) { loginEdit = new KLineEdit(parent); loginEdit->setContextMenuPolicy(Qt::NoContextMenu); connect(loginEdit, SIGNAL(editingFinished()), SLOT(slotLoginLostFocus())); connect(loginEdit, SIGNAL(editingFinished()), SLOT(slotChanged())); connect(loginEdit, SIGNAL(textChanged(QString)), SLOT(slotChanged())); connect(loginEdit, SIGNAL(selectionChanged()), SLOT(slotChanged())); if (!formLay) { loginEdit->setObjectName("user-entry"); widgetList << loginEdit; } else { loginLabel = new QLabel(i18n("&Username:"), parent); loginLabel->setBuddy(loginEdit); formLay->addRow(loginLabel, loginEdit); } } else if (ctx != Login && ctx != Shutdown && formLay) { loginLabel = new QLabel(i18n("Username:"), parent); formLay->addRow(loginLabel, new QLabel(fixedUser, parent)); } passwdEdit = new KDMPasswordEdit(parent); connect(passwdEdit, SIGNAL(textChanged(QString)), SLOT(slotChanged())); connect(passwdEdit, SIGNAL(editingFinished()), SLOT(slotChanged())); if (!formLay) { passwdEdit->setObjectName("pw-entry"); widgetList << passwdEdit; } else { passwdLabel = new QLabel(func == Authenticate ? i18n("&Password:") : i18n("Current &password:"), parent); passwdLabel->setBuddy(passwdEdit); formLay->addRow(passwdLabel, passwdEdit); } if (loginEdit) loginEdit->setFocus(); else passwdEdit->setFocus(); } if (func != Authenticate) { passwd1Edit = new KDMPasswordEdit(parent); passwd1Label = new QLabel(i18n("&New password:"), parent); passwd1Label->setBuddy(passwd1Edit); passwd2Edit = new KDMPasswordEdit(parent); passwd2Label = new QLabel(i18n("Con&firm password:"), parent); passwd2Label->setBuddy(passwd2Edit); if (formLay) { formLay->addRow(passwd1Label, passwd1Edit); formLay->addRow(passwd2Label, passwd2Edit); } if (!passwdEdit) passwd1Edit->setFocus(); } } // virtual KClassicGreeter::~KClassicGreeter() { abort(); qDeleteAll(widgetList); } void // virtual KClassicGreeter::loadUsers(const QStringList &users) { KCompletion *userNamesCompletion = new KCompletion; userNamesCompletion->setItems(users); loginEdit->setCompletionObject(userNamesCompletion); loginEdit->setAutoDeleteCompletionObject(true); loginEdit->setCompletionMode(KGlobalSettings::CompletionAuto); } void // virtual KClassicGreeter::presetEntity(const QString &entity, int field) { loginEdit->setText(entity); if (field == 1) { passwdEdit->setFocus(); } else { loginEdit->setFocus(); loginEdit->selectAll(); if (field == -1) { passwdEdit->setText(" "); passwdEdit->setEnabled(false); authTok = false; } } curUser = entity; } QString // virtual KClassicGreeter::getEntity() const { return fixedUser.isEmpty() ? loginEdit->text() : fixedUser; } void // virtual KClassicGreeter::setUser(const QString &user) { // assert(fixedUser.isEmpty()); curUser = user; loginEdit->setText(user); passwdEdit->setFocus(); passwdEdit->selectAll(); } void // virtual KClassicGreeter::setEnabled(bool enable) { // assert(!passwd1Label); // assert(func == Authenticate && ctx == Shutdown); // if (loginLabel) // loginLabel->setEnabled(enable); passwdLabel->setEnabled(enable); setActive(enable); if (enable) passwdEdit->setFocus(); } void // private KClassicGreeter::returnData() { switch (exp) { case 0: handler->gplugReturnText((loginEdit ? loginEdit->text() : fixedUser).toLocal8Bit(), KGreeterPluginHandler::IsUser); break; case 1: Q_ASSERT(passwdEdit); handler->gplugReturnText(passwdEdit->text().toLocal8Bit() , KGreeterPluginHandler::IsPassword | KGreeterPluginHandler::IsSecret); break; case 2: Q_ASSERT(passwd1Edit); handler->gplugReturnText(passwd1Edit->text().toLocal8Bit(), KGreeterPluginHandler::IsSecret); break; default: // case 3: Q_ASSERT(passwd2Edit); handler->gplugReturnText(passwd2Edit->text().toLocal8Bit(), KGreeterPluginHandler::IsNewPassword | KGreeterPluginHandler::IsSecret); break; } } bool // virtual KClassicGreeter::textMessage(const char *text, bool err) { if (!err && QString(text).indexOf(QRegExp("^Changing password for [^ ]+$")) >= 0) return true; return false; } void // virtual KClassicGreeter::textPrompt(const char *prompt, bool echo, bool nonBlocking) { pExp = exp; if (echo) { exp = 0; } else if (!authTok) { exp = 1; } else { QString pr(prompt); if (pr.indexOf(QRegExp("\\bpassword\\b", Qt::CaseInsensitive)) >= 0) { if (pr.indexOf(QRegExp("\\b(re-?(enter|type)|again|confirm|repeat)\\b", Qt::CaseInsensitive)) >= 0) { exp = 3; } else if (pr.indexOf(QRegExp("\\bnew\\b", Qt::CaseInsensitive)) >= 0) { exp = 2; } else { // QRegExp("\\b(old|current)\\b", Qt::CaseInsensitive) is too strict handler->gplugReturnText("", KGreeterPluginHandler::IsOldPassword | KGreeterPluginHandler::IsSecret); return; } } else { handler->gplugMsgBox(QMessageBox::Critical, i18n("Unrecognized prompt \"%1\"", prompt)); handler->gplugReturnText(0, 0); exp = -1; return; } } if (pExp >= 0 && pExp >= exp) { revive(); has = -1; } if (has >= exp || nonBlocking) returnData(); } bool // virtual KClassicGreeter::binaryPrompt(const char *, bool) { // this simply cannot happen ... :} return true; } void // virtual KClassicGreeter::start() { authTok = !(passwdEdit && passwdEdit->isEnabled()); exp = has = -1; running = true; } void // virtual KClassicGreeter::suspend() { } void // virtual KClassicGreeter::resume() { } void // virtual KClassicGreeter::next() { // assert(running); int pHas = has; if (loginEdit && loginEdit->hasFocus()) { passwdEdit->setFocus(); // will cancel running login if necessary has = 0; } else if (passwdEdit && passwdEdit->hasFocus()) { if (passwd1Edit) passwd1Edit->setFocus(); has = 1; } else if (passwd1Edit) { if (passwd1Edit->hasFocus()) { passwd2Edit->setFocus(); has = 1; // sic! } else { has = 3; } } else { has = 1; } if (exp < 0) handler->gplugStart(); else if (has >= exp && has > pHas) returnData(); } void // virtual KClassicGreeter::abort() { running = false; if (exp >= 0) { exp = -1; handler->gplugReturnText(0, 0); } } void // virtual KClassicGreeter::succeeded() { // assert(running || timed_login); if (!authTok) { setActive(false); if (passwd1Edit) { authTok = true; return; } } else { setActive2(false); } exp = -1; running = false; } void // virtual KClassicGreeter::failed() { // assert(running || timed_login); setActive(false); setActive2(false); exp = -1; running = false; } void // virtual KClassicGreeter::revive() { // assert(!running); setActive2(true); if (authTok) { passwd1Edit->clear(); passwd2Edit->clear(); passwd1Edit->setFocus(); } else { passwdEdit->clear(); if (loginEdit && loginEdit->isEnabled()) { passwdEdit->setEnabled(true); } else { setActive(true); if (loginEdit && loginEdit->text().isEmpty()) loginEdit->setFocus(); else passwdEdit->setFocus(); } } } void // virtual KClassicGreeter::clear() { // assert(!running && !passwd1Edit); passwdEdit->clear(); if (loginEdit) { loginEdit->clear(); loginEdit->setFocus(); curUser.clear(); } else { passwdEdit->setFocus(); } } // private void KClassicGreeter::setActive(bool enable) { if (loginEdit) loginEdit->setEnabled(enable); if (passwdEdit) passwdEdit->setEnabled(enable); } void KClassicGreeter::setActive2(bool enable) { if (passwd1Edit) { passwd1Edit->setEnabled(enable); passwd2Edit->setEnabled(enable); } } void KClassicGreeter::slotLoginLostFocus() { if (!running) return; loginEdit->setText(loginEdit->text().trimmed()); if (exp > 0) { if (curUser == loginEdit->text()) return; exp = -1; handler->gplugReturnText(0, 0); } curUser = loginEdit->text(); handler->gplugSetUser(curUser); } void KClassicGreeter::slotChanged() { if (running) handler->gplugChanged(); } // factory static bool init(const QString &, QVariant(*getConf)(void *, const char *, const QVariant &), void *ctx) { echoMode = getConf(ctx, "EchoPasswd", QVariant(-1)).toInt(); KGlobal::locale()->insertCatalog("kgreet_classic"); return true; } static void done(void) { KGlobal::locale()->removeCatalog("kgreet_classic"); } static KGreeterPlugin * create(KGreeterPluginHandler *handler, QWidget *parent, const QString &fixedEntity, KGreeterPlugin::Function func, KGreeterPlugin::Context ctx) { return new KClassicGreeter(handler, parent, fixedEntity, func, ctx); } KDE_EXPORT KGreeterPluginInfo kgreeterplugin_info = { I18N_NOOP2("@item:inmenu authentication method", "Username + password (classic)"), "classic", KGreeterPluginInfo::Local | KGreeterPluginInfo::Presettable, init, done, create }; #include "moc_kgreet_classic.cpp"