summaryrefslogtreecommitdiff
authorzecke <zecke>2004-07-09 21:36:37 (UTC)
committer zecke <zecke>2004-07-09 21:36:37 (UTC)
commit944adb8bf2741a16cf627d19e08f51c08920ad89 (patch) (side-by-side diff)
tree5f9edc9784e0268a00fe68ec74d7151900c5183a
parentc5d3262afd775bce81b99c5dc06e74c4686cee2a (diff)
downloadopie-944adb8bf2741a16cf627d19e08f51c08920ad89.zip
opie-944adb8bf2741a16cf627d19e08f51c08920ad89.tar.gz
opie-944adb8bf2741a16cf627d19e08f51c08920ad89.tar.bz2
Add setting a root password if none is set to opie-login
If you directly start Opie-Taskbar or use AutoLogin you will not be presented by a set root password gui
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--core/opie-login/.cvsignore2
-rw-r--r--core/opie-login/loginwindowimpl.cpp14
-rw-r--r--core/opie-login/loginwindowimpl.h5
-rw-r--r--core/opie-login/opie-login.pro8
-rw-r--r--core/opie-login/passworddialog.ui225
-rw-r--r--core/opie-login/passworddialogimpl.cpp232
-rw-r--r--core/opie-login/passworddialogimpl.h65
7 files changed, 545 insertions, 6 deletions
diff --git a/core/opie-login/.cvsignore b/core/opie-login/.cvsignore
index 0c3cc62..b80bdc4 100644
--- a/core/opie-login/.cvsignore
+++ b/core/opie-login/.cvsignore
@@ -1,7 +1,9 @@
*.moc
Makefile*
loginwindow.cpp
loginwindow.h
+passworddialog.h
+passworddialog.cpp
moc_*
.moc
.obj
diff --git a/core/opie-login/loginwindowimpl.cpp b/core/opie-login/loginwindowimpl.cpp
index 32f98f3..73c2cbe 100644
--- a/core/opie-login/loginwindowimpl.cpp
+++ b/core/opie-login/loginwindowimpl.cpp
@@ -34,32 +34,33 @@
#include <qpopupmenu.h>
#include <qmessagebox.h>
#if QT_VERSION < 300
#include <qgfx_qws.h>
#endif
#include <qwindowsystem_qws.h>
#include <qpe/resource.h>
#include <qpe/qcopenvelope_qws.h>
#include <qpe/config.h>
#include <opie2/odevice.h>
#include <stdio.h>
#include <stdlib.h>
+#include "passworddialogimpl.h"
#include "loginwindowimpl.h"
#include "loginapplication.h"
#include "inputmethods.h"
using namespace Opie::Core;
LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_Customize | WStyle_NoBorder | WDestructiveClose )
{
QPopupMenu *pop = new QPopupMenu ( this );
pop-> insertItem ( tr( "Restart" ), this, SLOT( restart()));
pop-> insertItem ( tr( "Quit" ), this, SLOT( quit()));
m_menu-> setPopup ( pop );
QCopChannel *channel = new QCopChannel ( "QPE/TaskBar", this );
connect ( channel, SIGNAL( received(const QCString&,const QByteArray&)), this, SLOT( receive(const QCString&,const QByteArray&)));
@@ -77,42 +78,47 @@ LoginWindowImpl::LoginWindowImpl ( ) : LoginWindow ( 0, "LOGIN-WINDOW", WStyle_C
//there is no point in displaying the IM for a zaurus
if (ODevice::inst ( )-> series ( ) != Model_Zaurus){
QTimer::singleShot ( 0, this, SLOT( showIM()));
}
QString opiedir = ::getenv ( "OPIEDIR" );
QPixmap bgpix ( opiedir + "/pics/launcher/opie-background.jpg" );
if ( !bgpix. isNull ( )) {
setBackgroundPixmap ( bgpix );
m_caption-> setBackgroundPixmap ( bgpix);
TextLabel1-> setBackgroundPixmap ( bgpix);
TextLabel2-> setBackgroundPixmap ( bgpix);
}
- m_caption-> setText ( tr("<center>Welcome to OPIE %1</center><center>& %2 %3</center>"). arg(QPE_VERSION). arg ( ODevice::inst ( )-> systemString ( )). arg ( ODevice::inst ( )-> systemVersionString ( )));
+// m_caption-> setText ( tr("<center>Welcome to OPIE %1</center><center>& %2 %3</center>"). arg(QPE_VERSION). arg ( ODevice::inst ( )-> systemString ( )). arg ( ODevice::inst ( )-> systemVersionString ( )));
Config cfg ( "opie-login" );
cfg. setGroup ( "General" );
QString last = cfg. readEntry ( "LastLogin" );
if ( !last. isEmpty ( ))
m_user-> setEditText ( last );
calcMaxWindowRect ( );
+
+ if ( PasswordDialogImpl::needDialog() )
+ QTimer::singleShot(10, this, SLOT(showPasswordDialog()) );
+
+
}
LoginWindowImpl::~LoginWindowImpl ( )
{
}
void LoginWindowImpl::receive ( const QCString &msg, const QByteArray &data )
{
QDataStream stream ( data, IO_ReadOnly );
if ( msg == "hideInputMethod()" )
m_input-> hideInputMethod ( );
else if ( msg == "showInputMethod()" )
m_input-> showInputMethod ( );
else if ( msg == "reloadInputMethods()" )
@@ -235,16 +241,22 @@ void LoginWindowImpl::login ( )
cfg. setGroup ( "General" );
cfg. writeEntry ( "LastLogin", user );
cfg. write ( );
lApp-> setLoginAs ( user );
// Draw a big wait icon, the image can be altered in later revisions
m_input-> hideInputMethod ( );
new WaitLogo ( );
// WaitLogo::showEvent() calls qApp-> quit()
}
else {
QMessageBox::warning ( this, tr( "Wrong password" ), tr( "The given password is incorrect." ));
m_password-> clear ( );
}
}
+
+void LoginWindowImpl::showPasswordDialog() {
+ PasswordDialogImpl dia( this );
+ dia.showMaximized();
+ dia.exec();
+}
diff --git a/core/opie-login/loginwindowimpl.h b/core/opie-login/loginwindowimpl.h
index df8dbbb..1de212c 100644
--- a/core/opie-login/loginwindowimpl.h
+++ b/core/opie-login/loginwindowimpl.h
@@ -21,43 +21,44 @@
  -_. . .   )=.  = see the file COPYING. If not, write to the
    --        :-=` Free Software Foundation, Inc.,
59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#ifndef __OPIE_LOGINWINDOW_IMPL_H__
#define __OPIE_LOGINWINDOW_IMPL_H__
#include "loginwindow.h"
class InputMethods;
class LoginWindowImpl : public LoginWindow {
Q_OBJECT
-
+
public:
LoginWindowImpl ( );
- virtual ~LoginWindowImpl ( );
+ virtual ~LoginWindowImpl ( );
protected slots:
void restart ( );
void quit ( );
void showIM ( );
void suspend ( );
void backlight ( );
void login ( );
void toggleEchoMode ( bool );
void calcMaxWindowRect ( );
void receive ( const QCString &, const QByteArray & );
+ void showPasswordDialog();
protected:
virtual void keyPressEvent ( QKeyEvent *e );
QStringList getAllUsers ( );
bool changeIdentity ( const char *user );
private:
InputMethods *m_input;
};
#endif
diff --git a/core/opie-login/opie-login.pro b/core/opie-login/opie-login.pro
index 63d4481..175d0b6 100644
--- a/core/opie-login/opie-login.pro
+++ b/core/opie-login/opie-login.pro
@@ -1,28 +1,30 @@
TEMPLATE = app
CONFIG = qt warn_on usepam
-HEADERS = loginwindowimpl.h \
+HEADERS = loginwindowimpl.h \
loginapplication.h \
+ passworddialogimpl.h \
../launcher/inputmethods.h \
../apps/calibrate/calibrate.h
-SOURCES = loginwindowimpl.cpp \
+SOURCES = loginwindowimpl.cpp \
loginapplication.cpp \
+ passworddialogimpl.cpp \
../launcher/inputmethods.cpp \
../apps/calibrate/calibrate.cpp \
main.cpp
-INTERFACES = loginwindow.ui
+INTERFACES = loginwindow.ui passworddialog.ui
INCLUDEPATH += $(OPIEDIR)/include ../launcher ../apps/calibrate
DEPENDPATH += $(OPIEDIR)/include ../launcher ../apps/calibrate
LIBS += -lqpe -lopiecore2
usepam:LIBS += -lpam
usepam:DEFINES += USEPAM
DESTDIR = $(OPIEDIR)/bin
TARGET = opie-login
include ( $(OPIEDIR)/include.pro )
diff --git a/core/opie-login/passworddialog.ui b/core/opie-login/passworddialog.ui
new file mode 100644
index 0000000..f2b2c88
--- a/dev/null
+++ b/core/opie-login/passworddialog.ui
@@ -0,0 +1,225 @@
+<!DOCTYPE UI><UI>
+<class>PasswordDialog</class>
+<widget>
+ <class>QDialog</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>PasswordDialog</cstring>
+ </property>
+ <property stdset="1">
+ <name>geometry</name>
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>625</width>
+ <height>277</height>
+ </rect>
+ </property>
+ <property stdset="1">
+ <name>caption</name>
+ <string>Set Password</string>
+ <comment>Caption of the password dialog</comment>
+ </property>
+ <property>
+ <name>layoutMargin</name>
+ </property>
+ <property>
+ <name>layoutSpacing</name>
+ </property>
+ <grid>
+ <property stdset="1">
+ <name>margin</name>
+ <number>4</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>4</number>
+ </property>
+ <widget row="0" column="0" >
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>m_header</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&lt;qt&gt;&lt;h2&gt;Please set a password for the Superuser.&lt;/h2&gt;&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget row="1" column="0" >
+ <class>QLayoutWidget</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>Layout5</cstring>
+ </property>
+ <grid>
+ <property stdset="1">
+ <name>margin</name>
+ <number>0</number>
+ </property>
+ <property stdset="1">
+ <name>spacing</name>
+ <number>6</number>
+ </property>
+ <widget row="0" column="1" >
+ <class>QLineEdit</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>m_pass</cstring>
+ </property>
+ <property stdset="1">
+ <name>echoMode</name>
+ <enum>Password</enum>
+ </property>
+ </widget>
+ <widget row="0" column="0" >
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>m_passLabel</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&lt;b&gt;Password:&lt;/b&gt;</string>
+ </property>
+ <property>
+ <name>buddy</name>
+ <cstring>m_pass</cstring>
+ </property>
+ </widget>
+ <widget row="0" column="2" >
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>ToolButton3</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string></string>
+ </property>
+ <property stdset="1">
+ <name>pixmap</name>
+ <pixmap>image0</pixmap>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ <property stdset="1">
+ <name>toggleButton</name>
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget row="1" column="3" >
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>ToolButton1_2</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string></string>
+ </property>
+ <property stdset="1">
+ <name>pixmap</name>
+ <pixmap>image1</pixmap>
+ </property>
+ </widget>
+ <widget row="1" column="1" >
+ <class>QLineEdit</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>m_confirm</cstring>
+ </property>
+ <property stdset="1">
+ <name>echoMode</name>
+ <enum>Password</enum>
+ </property>
+ </widget>
+ <widget row="0" column="3" >
+ <class>QToolButton</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>ToolButton1</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string></string>
+ </property>
+ <property stdset="1">
+ <name>pixmap</name>
+ <pixmap>image1</pixmap>
+ </property>
+ </widget>
+ <widget row="1" column="0" >
+ <class>QLabel</class>
+ <property stdset="1">
+ <name>name</name>
+ <cstring>m_confirmLbl</cstring>
+ </property>
+ <property stdset="1">
+ <name>text</name>
+ <string>&lt;b&gt;Confirm:&lt;/b&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="2" column="0" >
+ <property>
+ <name>name</name>
+ <cstring>Spacer2</cstring>
+ </property>
+ <property stdset="1">
+ <name>orientation</name>
+ <enum>Vertical</enum>
+ </property>
+ <property stdset="1">
+ <name>sizeType</name>
+ <enum>Expanding</enum>
+ </property>
+ <property>
+ <name>sizeHint</name>
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<images>
+ <image>
+ <name>image0</name>
+ <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141a808a2983b03284848a298304c108240e15033141045829580cac07ac4e590f5d0c22a4876caf32d45898797a48044caf32c22948e629c39d0457a78ce60f65b8f104ec50d6c366af1e865eb4b0aab5e602008bcd444d</data>
+ </image>
+ <image>
+ <name>image1</name>
+ <data format="XPM.GZ" length="341">789c558fcd0a02310c84ef7d8ad0b915c9bae84d7c04c5a3201e4275d1c32ab8eb41c477b73fa96e43a1f30d4d266d1ced771b728d194619af9efc451ee44ecfbe7f1d8eebb7b1ed92c259506b67c63279dade6fe7a81134e6a9224ac4ae2bc85565075004901c8820731069a648b490effc26eac4a25dcc195373c94231b87a8349fabf894b7a3d27a76af8cf01eb0e534757d70da1bf8a933f2bf30509e84b68</data>
+ </image>
+</images>
+<connections>
+ <connection>
+ <sender>ToolButton3</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>PasswordDialog</receiver>
+ <slot>slotToggleEcho(bool)</slot>
+ </connection>
+ <connection>
+ <sender>ToolButton1</sender>
+ <signal>clicked()</signal>
+ <receiver>m_pass</receiver>
+ <slot>clear()</slot>
+ </connection>
+ <connection>
+ <sender>ToolButton1_2</sender>
+ <signal>clicked()</signal>
+ <receiver>m_confirm</receiver>
+ <slot>clear()</slot>
+ </connection>
+ <slot access="protected">slotToggleEcho(bool)</slot>
+</connections>
+<tabstops>
+ <tabstop>m_pass</tabstop>
+ <tabstop>m_confirm</tabstop>
+</tabstops>
+</UI>
diff --git a/core/opie-login/passworddialogimpl.cpp b/core/opie-login/passworddialogimpl.cpp
new file mode 100644
index 0000000..aeb7516
--- a/dev/null
+++ b/core/opie-login/passworddialogimpl.cpp
@@ -0,0 +1,232 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2004 Holger Hans Peter Freyther <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This file is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This file 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 file;
+  -_. . .   )=.  = see the file COPYING. If not, write to the
+    --        :-=` Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qlineedit.h>
+#include <qvalidator.h>
+#include <qmessagebox.h>
+#include <qhbox.h>
+#include <qtoolbutton.h>
+
+#include <sys/types.h>
+#include <pwd.h>
+#include <shadow.h>
+#include <stdio.h>
+#include <time.h>
+#include <unistd.h>
+
+
+#include "passworddialogimpl.h"
+
+
+// This function is taken from 'busybox'.
+static int i64c(int i) {
+ if (i <= 0)
+ return ('.');
+ if (i == 1)
+ return ('/');
+ if (i >= 2 && i < 12)
+ return ('0' - 2 + i);
+ if (i >= 12 && i < 38)
+ return ('A' - 12 + i);
+ if (i >= 38 && i < 63)
+ return ('a' - 38 + i);
+ return ('z');
+}
+
+// This function is taken from 'busybox'.
+static char *crypt_make_salt() {
+ time_t now;
+ static unsigned long x;
+ static char result[3];
+
+ ::time(&now);
+ x += now + getpid() + clock();
+ result[0] = i64c(((x >> 18) ^ (x >> 6)) & 077);
+ result[1] = i64c(((x >> 12) ^ x) & 077);
+ result[2] = '\0';
+ return result;
+}
+
+/*
+ * Modal dialog to force root password. It is quite hard as it only leave
+ * when a password is set.
+ * Also it prevalidates the password...
+ */
+PasswordDialogImpl::PasswordDialogImpl( QWidget* parent )
+ : PasswordDialog( parent, 0, true ), m_isSet( PasswordDialogImpl::needDialog() ) {
+}
+
+PasswordDialogImpl::~PasswordDialogImpl() {
+ /* qt does the stuff for us */
+}
+
+void PasswordDialogImpl::done(int res) {
+ m_isSet = true;
+
+ /*
+ * The user hit 'Ok' see if we can safe the file
+ * if not an error will be raised and m_isSet altered.
+ * On cancel we will see if it is now ok...
+ */
+ if ( res == Accepted )
+ writePassword();
+ else if(PasswordDialogImpl::needDialog() ) {
+ switch( QMessageBox::warning(this,tr("Trying to leave without password set") ,
+ tr("<qt>No password was set. This could lead to you not beeing"
+ "able to remotely connect to your machine."
+ "Do you want to continue not setting a password?</qt>" ),
+ QMessageBox::Ok, QMessageBox::Cancel ) ) {
+ case QMessageBox::Cancel:
+ m_isSet = false;
+ break;
+ case QMessageBox::Ok:
+ default:
+ break;
+ }
+
+ }
+
+ if(m_isSet)
+ PasswordDialog::done( res );
+}
+
+/*
+ * Lets see if we can write either shadow
+ *
+ */
+/**
+ * CRYPT the password and then tries to write it either to the shadow password
+ * or to the plain /etc/passwd
+ */
+void PasswordDialogImpl::writePassword() {
+ /*
+ * Check if both texts are the same
+ */
+ if ( m_pass->text() != m_confirm->text() )
+ return error( tr("Passwords don't match"),
+ tr("<qt>The two passwords don't match. Please try again.</qt>") );
+
+
+ /*
+ * Now crypt the password so we can write it later
+ */
+ char* password = ::crypt( m_pass->text().latin1(), crypt_make_salt() );
+
+ if ( !password )
+ return error( tr("Password not legal" ),
+ tr("<qt>The entered password is not a valid password."
+ "Please try entering a valid password.</qt>" ) );
+
+ /* rewind and rewrite the password file */
+ ::setpwent();
+
+ FILE* file = ::fopen( "/etc/passwd.new", "w" );
+ struct passwd* pass;
+ while ( (pass = ::getpwent()) != 0l ) {
+ /* no shadow password support */
+ if ( pass->pw_uid == 0 )
+ pass->pw_passwd = password;
+
+ ::putpwent( pass, file );
+ }
+
+ ::fclose( file );
+ ::endpwent();
+ ::unlink("/etc/passwd");
+ ::rename("/etc/passwd.new","/etc/passwd" );
+
+ /* should be done now */
+#ifdef OPIE_LOGIN_SHADOW_PW
+ #error "Can't write Shadow Passwords fixme"
+#endif
+}
+
+/**
+ * Raise an error. Delete input and set the focus after showing
+ * the error to the user
+ */
+void PasswordDialogImpl::error( const QString& caption, const QString& text ) {
+ m_isSet = false;
+ QMessageBox::critical(this,caption, text,
+ QMessageBox::Ok, QMessageBox::NoButton );
+
+ m_pass->setText("");
+ m_pass->setFocus();
+
+ m_confirm->setText("");
+}
+
+void PasswordDialogImpl::slotToggleEcho( bool b ) {
+ m_pass-> setEchoMode( b ? QLineEdit::Normal : QLineEdit::Password );
+ m_confirm->setEchoMode( b ? QLineEdit::Normal : QLineEdit::Password );
+}
+
+/////////////////////////
+/// static functions
+///
+
+/**
+ * Ask whether or not we need to show the dialog. It returns true if
+ * no root password is set so that the user will be able to set one.
+ */
+bool PasswordDialogImpl::needDialog() {
+ /*
+ * This can cope with no password and shadow passwords
+ * Let us go through the user database until we find 'root' and then
+ * see if it is 'shadow' and see if shadow is empty or see if the password is empty
+ */
+ bool need = false;
+ struct passwd *pwd;
+ ::setpwent();
+
+ while((pwd = ::getpwent() ) ) {
+ /* found root */
+ if( pwd->pw_uid == 0 ) {
+ QString str = QString::fromLatin1(pwd->pw_passwd );
+
+ /*
+ * If str is really empty it is passwordless anyway...
+ * else it is shadow based
+ */
+ if(str.isEmpty() )
+ need = true;
+ else if ( str == '*' || str == 'x' )
+#ifdef OPIE_LOGIN_SHADOW_PW
+ need = QString::fromLatin1( ::getspnam( pwd->pw_name )->sp_pwdp ).isEmpty();
+#else
+ ;
+#endif
+ break;
+ }
+ }
+ ::endpwent();
+
+ return need;
+}
diff --git a/core/opie-login/passworddialogimpl.h b/core/opie-login/passworddialogimpl.h
new file mode 100644
index 0000000..f8953dd
--- a/dev/null
+++ b/core/opie-login/passworddialogimpl.h
@@ -0,0 +1,65 @@
+/*
+               =. This file is part of the OPIE Project
+             .=l. Copyright (c) 2004 Holger Hans Peter Freyther <zecke@handhelds.org>
+           .>+-=
+ _;:,     .>    :=|. This file is free software; you can
+.> <`_,   >  .   <= redistribute it and/or modify it under
+:`=1 )Y*s>-.--   : the terms of the GNU General Public
+.="- .-=="i,     .._ License as published by the Free Software
+ - .   .-<_>     .<> Foundation; either version 2 of the License,
+     ._= =}       : or (at your option) any later version.
+    .%`+i>       _;_.
+    .i_,=:_.      -<s. This file 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 file;
+  -_. . .   )=.  = see the file COPYING. If not, write to the
+    --        :-=` Free Software Foundation, Inc.,
+ 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+*/
+
+
+#ifndef OPIE_LOGIN_PASSWORDIMPL_DIALOG_H
+#define OPIE_LOGIN_PASSWORDIMPL_DIALOG_H
+
+#include "passworddialog.h"
+
+
+class QLineEdit;
+/**
+ * Small Dialog and Class to set the root password if it
+ * is not empty.
+ * \code
+ * if(PasswordDialogImpl::needDialog()) {
+ * PasswordDialogImpl *dia = new PasswordDialogImpl()
+ * dia->exec();
+ * dia->delete();
+ * }
+ */
+class PasswordDialogImpl : public PasswordDialog {
+ Q_OBJECT
+public:
+ PasswordDialogImpl( QWidget *parent );
+ ~PasswordDialogImpl();
+ static bool needDialog();
+
+protected slots:
+ void done( int );
+ void slotToggleEcho( bool );
+
+private:
+ void writePassword();
+ void writeShadow();
+ void error( const QString&, const QString& );
+ bool m_isSet : 1;
+};
+
+
+#endif