author | umopapisdn <umopapisdn> | 2002-09-24 21:21:55 (UTC) |
---|---|---|
committer | umopapisdn <umopapisdn> | 2002-09-24 21:21:55 (UTC) |
commit | 8854c1688dfc388e3621b7494f6338008173b20c (patch) (side-by-side diff) | |
tree | 3e6db427b24423b847d7e594f2fc9c865e0cc2ec /noncore/settings/usermanager | |
parent | 93be75ceab687091f76a459eb34bfd4859986116 (diff) | |
download | opie-8854c1688dfc388e3621b7494f6338008173b20c.zip opie-8854c1688dfc388e3621b7494f6338008173b20c.tar.gz opie-8854c1688dfc388e3621b7494f6338008173b20c.tar.bz2 |
New Application OPIE-UserManager added.
-rw-r--r-- | noncore/settings/usermanager/groupdialog.cpp | 106 | ||||
-rw-r--r-- | noncore/settings/usermanager/groupdialog.h | 36 | ||||
-rw-r--r-- | noncore/settings/usermanager/main.cpp | 19 | ||||
-rw-r--r-- | noncore/settings/usermanager/opie-usermanager.control | 10 | ||||
-rw-r--r-- | noncore/settings/usermanager/passwd.cpp | 271 | ||||
-rw-r--r-- | noncore/settings/usermanager/passwd.h | 85 | ||||
-rw-r--r-- | noncore/settings/usermanager/userdialog.cpp | 319 | ||||
-rw-r--r-- | noncore/settings/usermanager/userdialog.h | 55 | ||||
-rw-r--r-- | noncore/settings/usermanager/usermanager.cpp | 242 | ||||
-rw-r--r-- | noncore/settings/usermanager/usermanager.h | 65 | ||||
-rw-r--r-- | noncore/settings/usermanager/usermanager.pro | 10 |
11 files changed, 1218 insertions, 0 deletions
diff --git a/noncore/settings/usermanager/groupdialog.cpp b/noncore/settings/usermanager/groupdialog.cpp new file mode 100644 index 0000000..b595d31 --- a/dev/null +++ b/noncore/settings/usermanager/groupdialog.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "groupdialog.h" + +#include <qlabel.h> +#include <qlayout.h> +#include <qmessagebox.h> + +#include <stdlib.h> + +#include "passwd.h" + +GroupDialog::GroupDialog(QWidget* parent, const char* name, bool modal, WFlags fl) : QDialog(parent, name, modal, fl) { + // GID + QLabel *gidLabel=new QLabel(this,"gid: "); + gidLabel->setText("GroupID: "); + gidLineEdit=new QLineEdit(this,"gid: "); + gidLineEdit->setEnabled(false); + + // Groupname + QLabel *groupnameLabel=new QLabel(this,"groupname"); + groupnameLabel->setText("Groupname: "); + groupnameLineEdit=new QLineEdit(this,"groupname"); + + // Widget layout + QVBoxLayout *layout=new QVBoxLayout(this); + layout->setMargin(5); + QHBoxLayout *hlayout=new QHBoxLayout(-1,"hlayout"); + layout->addLayout(hlayout); + QVBoxLayout *vlayout1=new QVBoxLayout(-1,"vlayout1"); + QVBoxLayout *vlayout2=new QVBoxLayout(-1,"vlayout2"); + // First column, labels + vlayout1->addWidget(gidLabel); + vlayout1->addWidget(groupnameLabel); + // Second column, data + vlayout2->addWidget(gidLineEdit); + vlayout2->addWidget(groupnameLineEdit); + hlayout->addLayout(vlayout1); + hlayout->addLayout(vlayout2); + layout->addSpacing(5); + +// showMaximized(); +} + +GroupDialog::~GroupDialog() { +} + +bool GroupDialog::addGroup(int gid) { + GroupDialog *addgroupDialog=new GroupDialog(); // Make a groupinfo dialog. + addgroupDialog->setCaption(tr("Add Group")); // Set the caption. + addgroupDialog->gidLineEdit->setText(QString::number(gid)); // Set the next available gid. + if(!(addgroupDialog->exec())) return false; // View the dialog, and only continue if 'ok' was pressed. + if(!(accounts->addGroup(addgroupDialog->groupnameLineEdit->text(),addgroupDialog->gidLineEdit->text().toInt()))) { // Try to add the group. + QMessageBox::information(0,"Ooops!","Something went wrong.\nUnable to add group."); + return false; + } + return true; +} + +bool GroupDialog::editGroup(int gid) { + GroupDialog *addgroupDialog=new GroupDialog(); // Create the groupinfo dialog. + accounts->findGroup(gid); // Locate the group in the database, and fill out the variables in 'accounts'. + // Fill out the widgets with previous data for this group. + addgroupDialog->setCaption(tr("Edit Group")); + addgroupDialog->gidLineEdit->setText(QString::number(accounts->gr_gid)); + addgroupDialog->groupnameLineEdit->setText(accounts->gr_name); + if(!(addgroupDialog->exec())) return false; // View the dialog, and only continue if 'ok' was pressed. + accounts->findGroup(gid); // Locate the group, and fill out the variables in 'accounts' with all info about the group. + accounts->gr_name=addgroupDialog->groupnameLineEdit->text(); // Change the name + accounts->gr_gid=addgroupDialog->gidLineEdit->text().toInt(); // Change the GID. (Unneeded as its disabled right now.) + accounts->updateGroup(gid); // Update the database with the variables (gr_name,gr_gid,gr_mem) in 'accounts'. + return true; +} + +bool GroupDialog::delGroup(const char *groupname) { + if((accounts->findGroup(groupname))) { // Does this group exist? + if(!(accounts->delGroup(groupname))) { // Try to delete it. + QMessageBox::information(0,"Ooops!","Something went wrong\nUnable to delete group: "+QString(groupname)+"."); + } + } else { + QMessageBox::information(0,"Invalid Groupname","That groupname ("+QString(groupname)+")does not exist."); + return false; + } + return true; +} + +void GroupDialog::accept() { + // Check if gid is already taken. +// if((accounts->findGroup(gidLineEdit->text().toInt()))) { +// QMessageBox::information(this,"GroupID taken","That GroupID is already taken."); +// return; +// } + // Check if groupname is already taken. + if((accounts->findGroup(groupnameLineEdit->text()))) { + QMessageBox::information(0,"Groupname taken","That groupname is already taken."); + return; // Don't close the dialog. + } + QDialog::accept(); +} diff --git a/noncore/settings/usermanager/groupdialog.h b/noncore/settings/usermanager/groupdialog.h new file mode 100644 index 0000000..8b37039 --- a/dev/null +++ b/noncore/settings/usermanager/groupdialog.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef GROUPDIALOG_H +#define GROUPDIALOG_H + +#include <qdialog.h> +#include <qlineedit.h> + +class GroupDialog : public QDialog +{ + Q_OBJECT +private: + QString gid; + QString groupname; + QLineEdit *gidLineEdit; + QLineEdit *groupnameLineEdit; + int execStatus; + + void accept(void); + +public: + GroupDialog( QWidget* parent = 0, const char* name = 0, bool modal=true, WFlags fl = 0 ); + ~GroupDialog(); + static bool addGroup(int gid); + static bool delGroup(const char *groupname); + static bool editGroup(int gid); +}; + +#endif diff --git a/noncore/settings/usermanager/main.cpp b/noncore/settings/usermanager/main.cpp new file mode 100644 index 0000000..aa78286 --- a/dev/null +++ b/noncore/settings/usermanager/main.cpp @@ -0,0 +1,19 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "usermanager.h" +#include <qpe/qpeapplication.h> + +int main( int argc, char ** argv ) +{ + QPEApplication a( argc, argv ); + UserConfig mw(0,0,0); + a.showMainWidget( &mw ); + return a.exec(); +} diff --git a/noncore/settings/usermanager/opie-usermanager.control b/noncore/settings/usermanager/opie-usermanager.control new file mode 100644 index 0000000..956d98e --- a/dev/null +++ b/noncore/settings/usermanager/opie-usermanager.control @@ -0,0 +1,10 @@ +Package: userconfig +Files: bin/usermanager apps/Settings/usermanager.desktop pics/userconfig/* +Priority: optional +Section: opie/settings +Version: $QPE_VERSION-$SUB_VERSION-0.9 +Depends: opie-base ($QPE_VERSION) +Architecture: arm +Maintainer: Ted Parnefors <zaurus@bredband.net> +License: GPL +Description: User/Group manager for OPIE. diff --git a/noncore/settings/usermanager/passwd.cpp b/noncore/settings/usermanager/passwd.cpp new file mode 100644 index 0000000..310cef8 --- a/dev/null +++ b/noncore/settings/usermanager/passwd.cpp @@ -0,0 +1,271 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "passwd.h" + +// Needed for crypt_make_salt(); +#include <sys/types.h> +#include <unistd.h> +#include <time.h> + +Passwd::Passwd() { +} + +Passwd::~Passwd() { +} + +// This function is taken from 'busybox'. +int Passwd::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'. +char *Passwd::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; +} + +bool Passwd::open() { + int returnvalue=false; + + QFile passwd_file("/etc/passwd"); + QFile group_file("/etc/group"); + passwdStringList.clear(); + groupStringList.clear(); + if((passwd_file.open(IO_ReadOnly))) { + if((group_file.open(IO_ReadOnly))) { + QTextStream ts_passwd(&passwd_file); + while(!(ts_passwd.eof())) { + passwdStringList << ts_passwd.readLine(); + } + QTextStream ts_group(&group_file); + while(!(ts_group.eof())) { + groupStringList << ts_group.readLine(); + } + returnvalue=true; + group_file.close(); + } + passwd_file.close(); + } + return returnvalue; +} + +bool Passwd::close() { + int returnvalue=false; + QFile passwd_file("/etc/passwd"); + QFile group_file("/etc/group"); + if((passwd_file.open(IO_WriteOnly))) { + if((group_file.open(IO_WriteOnly))) { + QTextStream ts_passwd(&passwd_file); + for(QStringList::Iterator it=passwdStringList.begin(); it!=passwdStringList.end(); ++it) { + ts_passwd << (*it) + "\n"; + } + QTextStream ts_group(&group_file); + for(QStringList::Iterator it=groupStringList.begin(); it!=groupStringList.end(); ++it) { + ts_group << (*it) + "\n"; + } + returnvalue=true; + group_file.close(); + } + passwd_file.close(); + } + return returnvalue; +} + +void Passwd::splitPasswdEntry(QString &userString) { + userdataStringList=QStringList::split(":",userString,true); + QStringList::Iterator it=userdataStringList.begin(); + pw_name=(*it++); + pw_passwd=(*it++); + pw_uid=(*it++).toInt(); + pw_gid=(*it++).toInt(); + pw_gecos=(*it++); + pw_dir=(*it++); + pw_shell=(*it++); +} + +void Passwd::splitGroupEntry(QString &groupString) { + groupdataStringList=QStringList::split(":",groupString,true); + QStringList::Iterator it=groupdataStringList.begin(); + gr_name=(*it++); + it++; + gr_gid=(*it++).toInt(); + gr_mem=QStringList::split(" ",(*it++)); +} + +bool Passwd::searchUser(QRegExp &userRegExp) { + QStringList tempStringList(passwdStringList.grep(userRegExp)); + if((tempStringList.isEmpty())) { + return false; + } else { + userString=(*(tempStringList.begin())); + splitPasswdEntry(userString); + } + return true; +} + +bool Passwd::findUser(const char *username) { + QRegExp userRegExp(QString("^%1\\:").arg(username)); + return searchUser(userRegExp); +} + +bool Passwd::findUser(int uid) { + QRegExp userRegExp(QString(":%1\\:").arg(uid)); + return searchUser(userRegExp); +} + +bool Passwd::addUser(QString pw_name, QString pw_passwd, int pw_uid, int pw_gid, QString pw_gecos,QString pw_dir, QString pw_shell, bool createGroup=true) { + QString tempString; + if((createGroup) && (!(findGroup(pw_gid)))) addGroup(pw_name,pw_gid); + pw_passwd = crypt(pw_passwd, crypt_make_salt()); + tempString=pw_name+":"+pw_passwd+":"+QString::number(pw_uid)+":"+QString::number(pw_gid)+":"+pw_gecos+":"+pw_dir+":"+pw_shell; + passwdStringList.append(tempString); + // Make home dir. + QDir d; + if(!(d.exists(pw_dir))) { + d.mkdir(pw_dir); + } + return 1; +} + +bool Passwd::updateUser(QString login) { + QRegExp userRegExp(QString("^%1\\:").arg(login)); + for(QStringList::Iterator it=passwdStringList.begin(); it!=passwdStringList.end(); ++it) { + if(userRegExp.find((*it),0)!=-1) { + *it=QString(pw_name+":"+pw_passwd+":"+QString::number(pw_uid)+":"+QString::number(pw_gid)+":"+pw_gecos+":"+pw_dir+":"+pw_shell); + return true; + } + } + return false; +} + +bool Passwd::deleteUser(QRegExp &userRegExp, bool delGroup) { + for(QStringList::Iterator it=passwdStringList.begin(); it!=passwdStringList.end(); ++it) { + if(userRegExp.find((*it),0)!=-1) { + splitPasswdEntry(*it); + if(delGroup) this->delGroup(pw_gid); + passwdStringList.remove(it); + return true; + } + } + return false; +} + +bool Passwd::delUser(const char *username, bool delGroup) { + QRegExp userRegExp(QString("^%1\\:").arg(username)); + return deleteUser(userRegExp,delGroup); +} + +bool Passwd::delUser(int uid, bool delGroup) { + QRegExp userRegExp(QString(":%1\\:").arg(uid)); + return deleteUser(userRegExp,delGroup); +} + +bool Passwd::searchGroup(QRegExp &groupRegExp) { + QStringList tempStringList(groupStringList.grep(groupRegExp)); + if((tempStringList.isEmpty())) { + return false; + } else { + groupString=(*(tempStringList.begin())); + splitGroupEntry(groupString); + } + return true; +} + +bool Passwd::findGroup(const char *groupname) { + QRegExp groupRegExp(QString("^%1\\:").arg(groupname)); + return searchGroup(groupRegExp); +} + +bool Passwd::findGroup(int gid) { + QRegExp groupRegExp(QString(":%1\\:").arg(gid)); + return searchGroup(groupRegExp); +} + +bool Passwd::addGroup(QString gr_name, int gr_gid) { + QString tempString; + tempString=gr_name+":*:"+QString::number(gr_gid)+":"; + groupStringList.append(tempString); + return 1; +} + +bool Passwd::updateGroup(int gid) { + QRegExp groupRegExp(QString(":%1\\:").arg(QString::number(gid))); + for(QStringList::Iterator it=groupStringList.begin(); it!=groupStringList.end(); ++it) { + if(groupRegExp.find((*it),0)!=-1) { + *it=QString(gr_name+":*:"+QString::number(gr_gid)+":"); + for(QStringList::Iterator member=gr_mem.begin(); member!=gr_mem.end(); ++member) { + *it+=*member; + *it+=" "; + } + return true; + } + } + return false; +} + +bool Passwd::deleteGroup(QRegExp &groupRegExp) { + for(QStringList::Iterator it=groupStringList.begin(); it!=groupStringList.end(); ++it) { + if(groupRegExp.find((*it),0)!=-1) { + groupStringList.remove(it); + return true; + } + } + return false; +} + +bool Passwd::delGroup(const char *groupname) { + QRegExp groupRegExp(QString("^%1\\:").arg(groupname)); + return deleteGroup(groupRegExp); +} + +bool Passwd::delGroup(int gid) { + QRegExp groupRegExp(QString(":%1\\:").arg(gid)); + return deleteGroup(groupRegExp); +} + +bool Passwd::addGroupMember(QString groupname, QString member) { + if(!(findGroup(groupname))) return false; + gr_mem << member; + if(!(updateGroup(gr_gid))) return false; + return true; +} + +bool Passwd::delGroupMember(QString groupname, QString member) { + if(!(findGroup(groupname))) return false; + for(QStringList::Iterator it=gr_mem.begin(); it!=gr_mem.end(); ++it) { + if(*it==member) { + gr_mem.remove(it); + it=gr_mem.end(); + } + } + if(!(updateGroup(gr_gid))) return false; + return true; +} + +Passwd *accounts; diff --git a/noncore/settings/usermanager/passwd.h b/noncore/settings/usermanager/passwd.h new file mode 100644 index 0000000..37c41dc --- a/dev/null +++ b/noncore/settings/usermanager/passwd.h @@ -0,0 +1,85 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef PASSWD_H +#define PASSWD_H + +#include <qobject.h> +#include <qfile.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qtextstream.h> +#include <qregexp.h> +#include <qdir.h> + +#include <crypt.h> +#include <pwd.h> +#include <grp.h> + +class Passwd +{ +public: + QStringList passwdStringList; // List of all users (name,passwd,uid,gid,gecos,dir,shell) + QStringList groupStringList; // List of all groups (name,gid,mem) + + // pwentry + QString pw_name; + QString pw_passwd; + int pw_uid; + int pw_gid; + QString pw_gecos; + QString pw_dir; + QString pw_shell; + + // grentry + QString gr_name; + int gr_gid; + QStringList gr_mem; + + Passwd(void); + ~Passwd(void); + bool open(void); + bool close(void); + char *crypt_make_salt(void); + void splitPasswdEntry(QString &userString); + void splitGroupEntry(QString &groupString); + bool findUser(const char *username); + bool findUser(int uid); + bool addUser(QString pw_name, QString pw_passwd, int pw_uid, int pw_gid, QString pw_gecos, QString pw_dir, QString pw_shell, bool createGroup=true); + bool updateUser(QString login); + bool delUser(const char *username, bool delGroup=true); + bool delUser(int uid, bool delGroup=true); + bool findGroup(const char *groupname); + bool findGroup(int gid); + bool addGroup(QString gr_name, int gr_gid); + bool updateGroup(int gid); + bool delGroup(const char *groupname); + bool delGroup(int gid); + bool addGroupMember(QString groupname,QString member); + bool delGroupMember(QString groupname,QString member); + +private: + QString userString; + QString groupString; + + int i64c(int i); + bool searchUser(QRegExp &userRegExp); + bool deleteUser(QRegExp &userRegExp, bool delGroup); + bool searchGroup(QRegExp &groupRegExp); + bool deleteGroup(QRegExp &groupRegExp); + QStringList userdataStringList; + QStringList groupdataStringList; + + QFile *passwd_file; + QFile *group_file; +}; + +extern Passwd *accounts; // Create a global object. + +#endif diff --git a/noncore/settings/usermanager/userdialog.cpp b/noncore/settings/usermanager/userdialog.cpp new file mode 100644 index 0000000..892fc8a --- a/dev/null +++ b/noncore/settings/usermanager/userdialog.cpp @@ -0,0 +1,319 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "userdialog.h" + +#include <qlayout.h> +#include <qlabel.h> +#include <qmessagebox.h> + +#include <stdlib.h> + +#include <stdio.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <signal.h> + +#include "passwd.h" + +/** + * UserDialog constructor. Setup the dialog, fill the groupComboBox & groupsListView with all groups. + * + */ +UserDialog::UserDialog(QWidget* parent, const char* name, bool modal, WFlags fl) : QDialog(parent, name, modal, fl) { + QVBoxLayout *layout = new QVBoxLayout(this); + myTabWidget=new QTabWidget(this,"User Tab Widget"); + layout->addWidget(myTabWidget); + setupTab1(); + setupTab2(); + + // And also fill the listview & the combobox with all available groups. + for( QStringList::Iterator it = accounts->groupStringList.begin(); it!=accounts->groupStringList.end(); ++it) { + accounts->splitGroupEntry(*it); + new QListViewItem(groupsListView,accounts->gr_name); + groupComboBox->insertItem(accounts->gr_name); + } + + showMaximized(); +} + +/** + * Empty destructor. + * + */ +UserDialog::~UserDialog() { +} + +/** + * Creates the first tab, all userinfo is here. + * + */ +void UserDialog::setupTab1() { + QPixmap mypixmap; + QWidget *tabpage = new QWidget(myTabWidget,"page1"); + QVBoxLayout *layout = new QVBoxLayout(tabpage); + layout->setMargin(5); + + // Picture + picturePushButton = new QPushButton(tabpage,"Label"); + picturePushButton->setMinimumSize(48,48); + picturePushButton->setMaximumSize(48,48); + picturePushButton->setPixmap(Resource::loadPixmap("userconfig/usericon")); // Load default usericon. + connect(picturePushButton,SIGNAL(clicked()),this,SLOT(clickedPicture())); // Clicking the picture should invoke pictureselector. + + // Login + QLabel *loginLabel=new QLabel(tabpage,"Login: "); + loginLabel->setText("Login: "); + loginLineEdit=new QLineEdit(tabpage,"Login: "); + + // UID + QLabel *uidLabel=new QLabel(tabpage,"uid: "); + uidLabel->setText("UserID: "); + uidLineEdit=new QLineEdit(tabpage,"uid: "); + uidLineEdit->setEnabled(false); + + // Username (gecos) + QLabel *gecosLabel=new QLabel(tabpage,"gecos"); + gecosLabel->setText("Username: "); + gecosLineEdit=new QLineEdit(tabpage,"gecos"); + + // Password + QLabel *passwordLabel=new QLabel(tabpage,"password"); + passwordLabel->setText("Password: "); + passwordLineEdit=new QLineEdit(tabpage,"password"); + passwordLineEdit->setEchoMode(QLineEdit::Password); + + // Shell + QLabel *shellLabel=new QLabel(tabpage,"shell"); + shellLabel->setText("Shell: "); + shellComboBox=new QComboBox(tabpage,"shell"); + shellComboBox->setEditable(true); + shellComboBox->insertItem("/bin/sh"); + shellComboBox->insertItem("/bin/ash"); + shellComboBox->insertItem("/bin/false"); + + // Primary Group + QLabel *groupLabel=new QLabel(tabpage,"group"); + groupLabel->setText("Primary group: "); + groupComboBox=new QComboBox(tabpage,"PrimaryGroup"); + + // Widget layout + QHBoxLayout *hlayout=new QHBoxLayout(-1,"hlayout"); + layout->addWidget(picturePushButton); + layout->addSpacing(5); + layout->addLayout(hlayout); + QVBoxLayout *vlayout1=new QVBoxLayout(-1,"vlayout1"); + QVBoxLayout *vlayout2=new QVBoxLayout(-1,"vlayout2"); + // First column, labels + vlayout1->addWidget(loginLabel); + vlayout1->addSpacing(5); + vlayout1->addWidget(uidLabel); + vlayout1->addSpacing(5); + vlayout1->addWidget(gecosLabel); + vlayout1->addSpacing(5); + vlayout1->addWidget(passwordLabel); + vlayout1->addSpacing(5); + vlayout1->addWidget(shellLabel); + vlayout1->addSpacing(5); + vlayout1->addWidget(groupLabel); + // Second column, data + vlayout2->addWidget(loginLineEdit); + vlayout2->addSpacing(5); + vlayout2->addWidget(uidLineEdit); + vlayout2->addSpacing(5); + vlayout2->addWidget(gecosLineEdit); + vlayout2->addSpacing(5); + vlayout2->addWidget(passwordLineEdit); + vlayout2->addSpacing(5); + vlayout2->addWidget(shellComboBox); + vlayout2->addSpacing(5); + vlayout2->addWidget(groupComboBox); + hlayout->addLayout(vlayout1); + hlayout->addLayout(vlayout2); + + myTabWidget->addTab(tabpage,"User Info"); +} + +/** + * Creates the second tab containing additional groups for the user. + * + */ +void UserDialog::setupTab2() { + QWidget *tabpage = new QWidget(myTabWidget,"page2"); + QVBoxLayout *layout = new QVBoxLayout(tabpage); + layout->setMargin(5); + + // Additional groups + groupsListView=new QListView(tabpage,"groups"); + groupsListView->addColumn("Additional groups"); + groupsListView->setColumnWidthMode(0,QListView::Maximum); + groupsListView->setMultiSelection(true); + + layout->addSpacing(5); + // Grouplist + layout->addWidget(groupsListView); + + myTabWidget->addTab(tabpage,"User Groups"); +} + +/** + * Static function that creates the userinfo dialog. + * The user will be prompted to add a user. + * + * @param uid This is a suggested available UID. + * @param gid This is a suggested available GID. + * + * @return <code>true</code> if the user was successfully added, otherwise <code>false</code>. + * + */ +bool UserDialog::addUser(int uid, int gid) { + UserDialog *adduserDialog=new UserDialog(); + adduserDialog->setCaption(tr("Add User")); + adduserDialog->userID=uid; // Set next available UID as default uid. + adduserDialog->groupID=gid; // Set next available GID as default gid. + // Insert default group into groupComboBox + adduserDialog->groupComboBox->insertItem("<create new group>",0); + adduserDialog->uidLineEdit->setText(QString::number(uid)); + // Show the dialog! + if(!(adduserDialog->exec())) return false; + if((adduserDialog->groupComboBox->currentItem()!=0)) { + accounts->findGroup(adduserDialog->groupComboBox->currentText()); + adduserDialog->groupID=accounts->gr_gid; + qWarning(QString::number(accounts->gr_gid)); + } + if(!(accounts->addUser(adduserDialog->loginLineEdit->text(), adduserDialog->passwordLineEdit->text(), + adduserDialog->uidLineEdit->text().toInt(), adduserDialog->groupID, adduserDialog->gecosLineEdit->text(), + QString("/home/")+adduserDialog->loginLineEdit->text() , adduserDialog->shellComboBox->currentText()))) { + QMessageBox::information(0,"Ooops!","Something went wrong!\nUnable to add user."); + return false; + } + + // Add User to additional groups. + QListViewItemIterator it( adduserDialog->groupsListView ); + for ( ; it.current(); ++it ) { + if ( it.current()->isSelected() ) + accounts->addGroupMember(it.current()->text(0),adduserDialog->loginLineEdit->text()); + } + return true; +} + +/** + * Deletes the user account. + * + * @param username User to be deleted. + * + * @return <code>true</code> if the user was successfully deleted, otherwise <code>false</code>. + * + */ +bool UserDialog::delUser(const char *username) { + if((accounts->findUser(username))) { // Does that user exist? + if(!(accounts->delUser(username))) { // Delete the user. + QMessageBox::information(0,"Ooops!","Something went wrong\nUnable to delete user: "+QString(username)+"."); + } + } else { + QMessageBox::information(0,"Invalid Username","That username ("+QString(username)+")does not exist."); + return false; + } + return true; +} + +/** + * This displays a confirmation dialog wether a user should be deleted or not. + * (And also deletes the account) + * + * @param username User to be deleted. + * + * @return <code>true</code> if the user was successfully deleted, otherwise <code>false</code>. + * + */ +bool UserDialog::editUser(const char *username) { + UserDialog *edituserDialog=new UserDialog(); // Create Dialog + edituserDialog->setCaption(tr("Edit User")); + accounts->findUser(username); // Locate user in database and fill variables in 'accounts' object. + accounts->findGroup(accounts->pw_gid); // Locate the user's primary group, and fill group variables in 'accounts' object. + // Fill widgets with userinfo. + edituserDialog->loginLineEdit->setText(accounts->pw_name); + edituserDialog->uidLineEdit->setText(QString::number(accounts->pw_uid)); + edituserDialog->gecosLineEdit->setText(accounts->pw_gecos); + // Set password to '........', we will later check if this still is the contents, if not, the password has been changed. + edituserDialog->passwordLineEdit->setText("........"); + // If this user is not using /bin/sh,/bin/ash or /bin/false as shell, add that entry to the shell-combobox. + if(accounts->pw_shell!="/bin/sh" && accounts->pw_shell!="/bin/ash" && accounts->pw_shell!="/bin/false") { + edituserDialog->shellComboBox->insertItem(accounts->pw_shell,0); + edituserDialog->shellComboBox->setCurrentItem(0); + } + // Select the primary group for this user. + for(int i=0;i<edituserDialog->groupComboBox->count();++i) { + if(accounts->gr_name==edituserDialog->groupComboBox->text(i)) { + edituserDialog->groupComboBox->setCurrentItem(i); + } + } + // Select the groups in the listview, to which the user belongs. + QRegExp userRegExp(QString("[:\\s]%1\\s").arg(username)); + QStringList tempList=accounts->groupStringList.grep(userRegExp); // Find all entries in the group database, that the user is a member of. + for(QStringList::Iterator it=tempList.begin(); it!=tempList.end(); ++it) { // Iterate over all of them. + QListViewItemIterator lvit( edituserDialog->groupsListView ); // Compare to all groups. + for ( ; lvit.current(); ++lvit ) { + if(lvit.current()->text(0)==(*it).left((*it).find(":"))) { + lvit.current()->setSelected(true); // If we find a line with that groupname, select it.; + } + } + } + + if(!(edituserDialog->exec())) return false; // SHOW THE DIALOG! + + accounts->findUser(username); // Fill user variables in 'acccounts' object. + accounts->pw_name=edituserDialog->loginLineEdit->text(); + // Has the password been changed ? Make a new "crypt":ed password. + if(edituserDialog->passwordLineEdit->text()!="........") accounts->pw_passwd=crypt(edituserDialog->passwordLineEdit->text(), accounts->crypt_make_salt()); + + // Set all variables in accounts object, that will be used when calling 'updateUser()' + accounts->pw_uid=edituserDialog->uidLineEdit->text().toInt(); + accounts->findGroup(edituserDialog->groupComboBox->currentText()); // Fill all group variables in 'accounts' object. + accounts->pw_gid=accounts->gr_gid; + accounts->pw_gecos=edituserDialog->gecosLineEdit->text(); + accounts->pw_shell=edituserDialog->shellComboBox->currentText(); + // Update userinfo, using the information stored in the user variables stored in the accounts object. + accounts->updateUser(username); + + // Remove user from all groups he/she is a member of. (could be done in a better way I guess, this was simple though.) + for(QStringList::Iterator it=tempList.begin(); it!=tempList.end(); ++it) { + accounts->delGroupMember((*it).left((*it).find(":")),username); + } + + // Add User to additional groups that he/she is a member of. + QListViewItemIterator it( edituserDialog->groupsListView ); + for ( ; it.current(); ++it ) { + if ( it.current()->isSelected() ) + accounts->addGroupMember(it.current()->text(0),edituserDialog->loginLineEdit->text()); + } + return true; +} + +/** + * "OK" has been clicked. Verify some information before closing the dialog. + * + */ +void UserDialog::accept() { + // Add checking... valid username? username taken? + if(loginLineEdit->text().isEmpty()) { + QMessageBox::information(0,"Empty Login","Please enter a login."); + return; + } + QDialog::accept(); +} + +/** + * This slot is called when the usericon is clicked, this loads (should) the iconselector. + * + */ +void UserDialog::clickedPicture() { + QMessageBox::information(0,"Sorry!","Icon selection not yet implemented.\nComming real soon now! (tm)"); +} diff --git a/noncore/settings/usermanager/userdialog.h b/noncore/settings/usermanager/userdialog.h new file mode 100644 index 0000000..b44de9e --- a/dev/null +++ b/noncore/settings/usermanager/userdialog.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef USERDIALOG_H +#define USERDIALOG_H + +#include <qdialog.h> +#include <qlineedit.h> +#include <qcombobox.h> +#include <qlistview.h> +#include <qtabwidget.h> +#include <qpushbutton.h> + +#include <qpe/resource.h> + +class UserDialog : public QDialog +{ + Q_OBJECT +private: + QTabWidget *myTabWidget; + QPushButton *picturePushButton; + QLineEdit *loginLineEdit; + QLineEdit *uidLineEdit; + QLineEdit *gecosLineEdit; + QLineEdit *passwordLineEdit; + QComboBox *shellComboBox; + QComboBox *groupComboBox; + QListView *groupsListView; + + QStringList groupMembers; + QString pictureLocation; + int groupID; + int userID; + + void setupTab1(void); + void setupTab2(void); + void accept(void); + +private slots: + void clickedPicture(void); + +public: + UserDialog( QWidget* parent = 0, const char* name = 0, bool modal=true, WFlags fl = 0 ); + ~UserDialog(); + static bool addUser(int uid, int gid); + static bool editUser(const char *username); + static bool delUser(const char *username); +}; + +#endif diff --git a/noncore/settings/usermanager/usermanager.cpp b/noncore/settings/usermanager/usermanager.cpp new file mode 100644 index 0000000..883e5d7 --- a/dev/null +++ b/noncore/settings/usermanager/usermanager.cpp @@ -0,0 +1,242 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include "usermanager.h" + +#include <qlayout.h> +#include <stdio.h> + +#include <qmessagebox.h> +#include <qfile.h> +#include <qpe/resource.h> + +#include <qregexp.h> + +/** + * The mainwindow constructor. + * + * @param QWidget *parent + * @param const char *name + * @ param WFlags fl + * + */ +UserConfig::UserConfig(QWidget* parent, const char* name, WFlags fl) : QMainWindow(parent, name, fl) { + setCaption(tr("OPIE User Manager")); + + // Create an instance of the global object 'accounts'. This holds all user/group info, and functions to modify them. + accounts=new Passwd(); + accounts->open(); // This actually loads the files /etc/passwd & /etc/group into memory. + + // Create the toolbar. + QPEToolBar *toolbar = new QPEToolBar(this,"Toolbar"); + toolbar->setHorizontalStretchable(1); // Is there any other way to get the toolbar to stretch of the full screen!? + adduserToolButton = new QToolButton(Resource::loadPixmap("userconfig/adduser"),"Add User",0,this,SLOT(addUser()),toolbar,"Add User"); + edituserToolButton = new QToolButton(Resource::loadPixmap("userconfig/edituser"),"Edit User",0,this,SLOT(editUser()),toolbar,"Edit User"); + deleteuserToolButton = new QToolButton(Resource::loadPixmap("userconfig/deleteuser"),"Delete User",0,this,SLOT(delUser()),toolbar,"Delete User"); + QToolButton *userstext = new QToolButton(0,"User",0,0,0,toolbar,"User"); + userstext->setUsesTextLabel(true); + toolbar->addSeparator(); + addgroupToolButton = new QToolButton(Resource::loadPixmap("userconfig/addgroup"),"Add Group",0,this,SLOT(addGroup()),toolbar,"Add Group"); + editgroupToolButton = new QToolButton(Resource::loadPixmap("userconfig/editgroup"),"Edit Group",0,this,SLOT(editGroup()),toolbar,"Edit Group"); + deletegroupToolButton = new QToolButton(Resource::loadPixmap("userconfig/deletegroup"),"Delete Group",0,this,SLOT(delGroup()),toolbar,"Delete Group"); + QToolButton *groupstext = new QToolButton(0,"Group",0,0,0,toolbar,"Group"); + groupstext->setUsesTextLabel(true); + addToolBar(toolbar,"myToolBar"); + + // Add a tabwidget and all the tabs. + myTabWidget = new QTabWidget(this,"My Tab Widget"); + setupTabAccounts(); + setupTabAllUsers(); + setupTabAllGroups(); + + getUsers(); // Fill out the iconview & listview with all users. + getGroups(); // Fill out the group listview with all groups. + + setCentralWidget(myTabWidget); +} + +UserConfig::~UserConfig() { + accounts->close(); + delete accounts; +} + +void UserConfig::setupTabAccounts() { + QWidget *tabpage = new QWidget(this); + QVBoxLayout *layout = new QVBoxLayout(tabpage); + layout->setMargin(5); + + usersIconView=new QIconView(tabpage,"users"); + usersIconView->setItemTextPos(QIconView::Right); + layout->addWidget(usersIconView); + + myTabWidget->addTab(tabpage,"Users"); +} + +void UserConfig::setupTabAllUsers() { + QWidget *tabpage = new QWidget(this); + QVBoxLayout *layout = new QVBoxLayout(tabpage); + layout->setMargin(5); + + usersListView=new QListView(tabpage,"allusers"); + usersListView->addColumn("UID"); + usersListView->addColumn("Login"); + usersListView->addColumn("Username"); + layout->addWidget(usersListView); + usersListView->setSorting(1,1); + usersListView->setAllColumnsShowFocus(true); + + myTabWidget->addTab(tabpage,"All Users"); +} + +void UserConfig::setupTabAllGroups() { + QWidget *tabpage = new QWidget(this); + QVBoxLayout *layout = new QVBoxLayout(tabpage); + layout->setMargin(5); + + groupsListView=new QListView(tabpage,"groups"); + groupsListView->addColumn("GID"); + groupsListView->addColumn("Groupname"); + layout->addWidget(groupsListView); + groupsListView->setSorting(1,1); + groupsListView->setAllColumnsShowFocus(true); + + myTabWidget->addTab(tabpage,"All Groups"); +} +void UserConfig::getUsers() { + QString mytext; + QPixmap mypixmap; + + // Empty the iconview & the listview. + usersIconView->clear(); + usersListView->clear(); + + // availableUID is used as a deposite for the next available UID on the system, this should start at an ID over 500. + availableUID=500; + for(QStringList::Iterator it=accounts->passwdStringList.begin(); it!=accounts->passwdStringList.end(); ++it) { + accounts->splitPasswdEntry(*it); // Split the string into it's components and store in variables in the accounts object. ("pr_name" and so on.) + new QListViewItem(usersListView,QString::number(accounts->pw_uid),accounts->pw_name,accounts->pw_gecos); + if((accounts->pw_uid>=500) && (accounts->pw_uid<65000)) { // Is this user a "normal" user ? + mytext=QString(accounts->pw_name)+" - ("+QString(accounts->pw_gecos)+")"; // The string displayed next to the icon. + mypixmap=Resource::loadPixmap(QString("users/"+accounts->pw_name)); // Is there an icon for this user? + if(mypixmap.isNull()) { + mypixmap=Resource::loadPixmap(QString("userconfig/usericon")); // If this user has no icon, load the default icon. + } + new QIconViewItem(usersIconView,mytext,mypixmap); // Add the icon+text to the qiconview. + } + if((accounts->pw_uid>=availableUID) && (accounts->pw_uid<65000)) availableUID=accounts->pw_uid+1; // Increase 1 to the latest know UID to get a free uid. + } +} + +void UserConfig::addUser() { + if(UserDialog::addUser(availableUID,availableGID)) { // Add the user to the system, also send next available UID and GID. + getUsers(); // Update users views. + getGroups(); // Update groups view. + } +} + +void UserConfig::editUser() { + QString username; + if(myTabWidget->currentPageIndex()==0) { // Users + if(usersIconView->currentItem()) { // Any icon selected? + username=usersIconView->currentItem()->text(); // Get the text associated with the icon. + username=username.left(username.find(" - (",0,true)); // Strip out the username. + if(UserDialog::editUser(username)) { // Bring up the userinfo dialog. + // If there were any changed also update the views. + getUsers(); + getGroups(); + } + } else { + QMessageBox::information(this,"No selection.","No user has been selected."); + } + } + if(myTabWidget->currentPageIndex()==1) { // All users + if(usersListView->currentItem()) { // Anything changed!? + username=usersListView->currentItem()->text(1); // Get the username. + if(UserDialog::editUser(username)) { // Bring up the userinfo dialog. + // And again update the views if there were any changes. + getUsers(); + getGroups(); + } + } else { + QMessageBox::information(this,"No selection.","No user has been selected."); + } + } +} + +void UserConfig::delUser() { + QString username; + + if(myTabWidget->currentPageIndex()==0) { // Users, Iconview. + if(usersIconView->currentItem()) { // Anything selected? + username=usersIconView->currentItem()->text(); // Get string associated with icon. + username=username.left(username.find(" - (",0,true)); // Strip out the username. + if(QMessageBox::warning(this,"Delete user","Are you sure you want to\ndelete this user? \""+QString(username)+"\" ?","&No","&Yes",0,0,1)) { + if(UserDialog::delUser(username)) { // Delete the user if possible. + // Update views. + getUsers(); + getGroups(); + } + } + } else { + QMessageBox::information(this,"No selection","No user has been selected."); + } + } + if(myTabWidget->currentPageIndex()==1) { // All users + if(usersListView->currentItem()) { // Anything changed!? + username=usersListView->currentItem()->text(1); // Get the username. + if(QMessageBox::warning(this,"Delete user","Are you sure you want to\ndelete this user? \""+QString(username)+"\" ?","&No","&Yes",0,0,1)) { + if(UserDialog::delUser(username)) { // Try to delete the user. + // Update views. + getUsers(); + getGroups(); + } + } + } else { + QMessageBox::information(this,"No selection","No user has been selected."); + } + } + +} + +void UserConfig::getGroups() { + groupsListView->clear(); // Empty the listview. + availableGID=500; // We need to find the next free GID, and are only interested in values between 500 & 65000. + for(QStringList::Iterator it=accounts->groupStringList.begin(); it!=accounts->groupStringList.end(); ++it) { // Split the list into lines. + accounts->splitGroupEntry(*it); // Split the line into its components and fill the variables of 'accounts'. (gr_name, gr_uid & gr_mem). + new QListViewItem(groupsListView,QString::number(accounts->gr_gid),accounts->gr_name); + if((accounts->gr_gid>=availableGID) && (accounts->gr_gid<65000)) availableGID=accounts->gr_gid+1; // Maybe a new free GID. + } +} + +void UserConfig::addGroup() { + if(GroupDialog::addGroup(availableGID)) getGroups(); // Bring up the add group dialog. +} + +void UserConfig::editGroup() { + int gid; + if(groupsListView->currentItem()) { // Any group selected? + gid=groupsListView->currentItem()->text(0).toInt(); // Get the GID from the listview. + if(GroupDialog::editGroup(gid)) getGroups(); // Bring up the edit group dialog. + } else { + QMessageBox::information(this,"No selection","No group has been selected."); + } +} + +void UserConfig::delGroup() { + const char *groupname; + if(groupsListView->currentItem()) { // Any group selected? + groupname=groupsListView->currentItem()->text(1); // Get the groupname from the listview. + if(QMessageBox::warning(this,"Delete group","Are you sure you want to\ndelete the group \""+QString(groupname)+"\" ?","&No","&Yes",0,0,1)) { + // If confirmed, try to delete the group. + if(GroupDialog::delGroup(groupname)) getGroups(); // And also update the view afterwards if the user was deleted. + } + } else { + QMessageBox::information(this,"No selection","No group has been selected."); + } +} diff --git a/noncore/settings/usermanager/usermanager.h b/noncore/settings/usermanager/usermanager.h new file mode 100644 index 0000000..bb5d04f --- a/dev/null +++ b/noncore/settings/usermanager/usermanager.h @@ -0,0 +1,65 @@ +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#ifndef USERCONFIG_H +#define USERCONFIG_H + +#include <qmainwindow.h> +#include <qtabwidget.h> +#include <qlistview.h> +#include <qiconview.h> + +#include <qpe/qpemenubar.h> +#include <qpopupmenu.h> +#include <qpe/qpetoolbar.h> +#include <qtoolbutton.h> + +#include "userdialog.h" +#include "groupdialog.h" +#include "passwd.h" + +class UserConfig : public QMainWindow +{ + Q_OBJECT + +public: + UserConfig( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~UserConfig(); + +private: + QToolButton *adduserToolButton; + QToolButton *edituserToolButton; + QToolButton *deleteuserToolButton; + QToolButton *addgroupToolButton; + QToolButton *editgroupToolButton; + QToolButton *deletegroupToolButton; + QTabWidget *myTabWidget; + QIconView *usersIconView; + QListView *usersListView; + QListView *groupsListView; + int availableUID; + int availableGID; + void setupTabAccounts(); + void setupTabAllUsers(); + void setupTabAllGroups(); + void setupTabPrefs(); + void setupTabAbout(); + void getUsers(); + void getGroups(); + +private slots: + void addUser(); + void editUser(); + void delUser(); + void addGroup(); + void editGroup(); + void delGroup(); +}; + +#endif // USERCONFIG_H diff --git a/noncore/settings/usermanager/usermanager.pro b/noncore/settings/usermanager/usermanager.pro new file mode 100644 index 0000000..956d98e --- a/dev/null +++ b/noncore/settings/usermanager/usermanager.pro @@ -0,0 +1,10 @@ +Package: userconfig +Files: bin/usermanager apps/Settings/usermanager.desktop pics/userconfig/* +Priority: optional +Section: opie/settings +Version: $QPE_VERSION-$SUB_VERSION-0.9 +Depends: opie-base ($QPE_VERSION) +Architecture: arm +Maintainer: Ted Parnefors <zaurus@bredband.net> +License: GPL +Description: User/Group manager for OPIE. |