Proof-reading - fixed one usage of the i18n plural form (it wasn't doing before,...
[kdeadmin.git] / kuser / ku_user.cpp
blob8f1d47266189f8bd3d7a46da11078cb12084f94c
1 /*
2 * Copyright (c) 1998 Denis Perchine <dyp@perchine.com>
3 * Copyright (c) 2004 Szombathelyi GyĂśrgy <gyurco@freemail.hu>
4 * Former maintainer: Adriaan de Groot <groot@kde.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public
8 * License version 2 as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 **/
21 #include "globals.h"
23 #include <ku_config.h>
24 #include <errno.h>
25 #include <sys/types.h>
26 #include <sys/file.h>
27 #include <stdlib.h>
28 #ifdef HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31 #ifdef HAVE_SYS_STAT_H
32 #include <sys/stat.h>
33 #endif
34 #include <fcntl.h>
36 #include <QDir>
37 #include <QSharedData>
39 #include <kstandarddirs.h>
40 #include <kmessagebox.h>
41 #include <kshell.h>
42 #include <kdebug.h>
43 #include <kio/netaccess.h>
44 #include <kurl.h>
45 #include <klocale.h>
47 #include "ku_user.h"
48 #include "ku_misc.h"
50 KU_User_Private::KU_User_Private()
52 LastChange = 0;
53 Expire = -1;
54 UID = 0;
55 GID = 100;
57 Min = 0;
58 Max = 99999;
59 Warn = 7;
60 Inactive= -1;
61 // s_flag = 0;
62 Caps = 0;
63 CreateHome = false;
64 CreateMailBox = false;
65 CopySkel = false;
66 DeleteHome = false;
67 DeleteMailBox = false;
69 Disabled = true;
72 // class KU_User
74 KU_User::KU_User()
76 d = new KU_User_Private;
79 KU_User::KU_User(const KU_User *user)
81 d = new KU_User_Private;
82 copy(user);
85 void KU_User::copy(const KU_User *user)
87 if ( user != this ) {
88 *this = *user;
92 bool KU_User::operator ==(const KU_User &other) const
94 if ( getUID() == other.getUID() &&
95 getName() == other.getName() )
96 return true;
97 else
98 return false;
101 KU_User::~KU_User()
105 KU_PROPERTY_IMPL(KU_User,int,Caps)
106 KU_PROPERTY_IMPL(KU_User,QString,Name)
107 KU_PROPERTY_IMPL(KU_User,QString,Surname)
108 KU_PROPERTY_IMPL(KU_User,QString,Email)
109 KU_PROPERTY_IMPL(KU_User,QString,Pwd)
110 KU_PROPERTY_IMPL(KU_User,QString,HomeDir)
111 KU_PROPERTY_IMPL(KU_User,QString,Shell)
112 KU_PROPERTY_IMPL(KU_User,QString,FullName)
113 KU_PROPERTY_IMPL(KU_User,uid_t,UID)
114 KU_PROPERTY_IMPL(KU_User,uid_t,GID)
115 KU_PROPERTY_IMPL(KU_User,bool,Disabled)
117 //gecos
118 //--BSD gecos
119 KU_PROPERTY_IMPL(KU_User,QString,Office)
120 KU_PROPERTY_IMPL(KU_User,QString,WorkPhone)
121 KU_PROPERTY_IMPL(KU_User,QString,HomePhone)
122 KU_PROPERTY_IMPL(KU_User,QString,Class)
123 //--BSD end
124 KU_PROPERTY_IMPL(KU_User,QString,Office1)
125 KU_PROPERTY_IMPL(KU_User,QString,Office2)
126 KU_PROPERTY_IMPL(KU_User,QString,Address)
128 //shadow
129 KU_PROPERTY_IMPL(KU_User,QString,SPwd)
130 KU_PROPERTY_IMPL(KU_User,time_t,Expire)
131 KU_PROPERTY_IMPL(KU_User,time_t,LastChange)
132 KU_PROPERTY_IMPL(KU_User,int,Min)
133 KU_PROPERTY_IMPL(KU_User,int,Max)
134 KU_PROPERTY_IMPL(KU_User,int,Warn)
135 KU_PROPERTY_IMPL(KU_User,int,Inactive)
136 KU_PROPERTY_IMPL(KU_User,int,Flag)
138 //samba
139 KU_PROPERTY_IMPL(KU_User,QString, LMPwd)
140 KU_PROPERTY_IMPL(KU_User,QString, NTPwd)
141 KU_PROPERTY_IMPL(KU_User,QString, LoginScript)
142 KU_PROPERTY_IMPL(KU_User,QString, ProfilePath)
143 KU_PROPERTY_IMPL(KU_User,QString, HomeDrive)
144 KU_PROPERTY_IMPL(KU_User,QString, HomePath)
145 KU_PROPERTY_IMPL(KU_User,QString, Workstations)
146 KU_PROPERTY_IMPL(KU_User,QString, Domain)
147 KU_PROPERTY_IMPL(KU_User,SID, SID)
148 KU_PROPERTY_IMPL(KU_User,SID, PGSID)
150 //Administrative
151 KU_PROPERTY_IMPL(KU_User,bool, CreateHome)
152 KU_PROPERTY_IMPL(KU_User,bool, CreateMailBox)
153 KU_PROPERTY_IMPL(KU_User,bool, CopySkel)
154 KU_PROPERTY_IMPL(KU_User,bool, DeleteHome)
155 KU_PROPERTY_IMPL(KU_User,bool, DeleteMailBox)
157 int KU_User::createHome()
160 if(d->HomeDir.isNull() || d->HomeDir.isEmpty()) {
161 KMessageBox::sorry( 0, i18n("Cannot create home folder for %1: it is null or empty.", d->Name) );
162 return(0);
164 if (mkdir(QFile::encodeName(d->HomeDir), 0700) != 0) {
165 if (errno != EEXIST)
167 KMessageBox::error( 0, i18n("Cannot create home folder %1.\nError: %2", d->HomeDir, QString::fromLocal8Bit(strerror(errno))) );
168 return(0);
172 if (chown(QFile::encodeName(d->HomeDir), d->UID, d->GID) != 0) {
173 KMessageBox::error( 0, i18n("Cannot change owner of home folder %1.\nError: %2", d->HomeDir, QString::fromLocal8Bit(strerror(errno))) );
174 return(1);
177 if (chmod(QFile::encodeName(d->HomeDir), KU_HOMEDIR_PERM) != 0) {
178 KMessageBox::error( 0, i18n("Cannot change permissions on home folder %1.\nError: %2", d->HomeDir, QString::fromLocal8Bit(strerror(errno))) );
179 return(1);
181 return(1);
184 int KU_User::tryCreate(const QString &dir)
186 struct stat sb;
187 int rc = 0;
189 rc = stat(QFile::encodeName(dir), &sb);
190 if (rc == 0) {
191 if (S_ISDIR(sb.st_mode)) {
192 if (KMessageBox::warningContinueCancel( 0,
193 i18n("Folder %1 already exists.\nWill make %2 owner and change permissions.\nDo you want to continue?", dir, d->Name),
194 QString(), KStandardGuiItem::cont() ) == KMessageBox::Continue) {
196 if (chown(QFile::encodeName(dir), d->UID, d->GID) != 0) {
197 KMessageBox::error( 0, i18n("Cannot change owner of %1 folder.\nError: %2" , dir, QString::fromLocal8Bit(strerror(errno))) );
199 return(0);
200 } else {
201 KMessageBox::information( 0, i18n("Folder %1 left 'as is'.\nVerify ownership and permissions for user %2 who may not be able to log in.", dir, d->Name) );
202 return(-1);
204 } else {
205 KMessageBox::information( 0, i18n("%1 exists and is not a folder. User %2 will not be able to log in.", dir, d->Name) );
206 return(-1);
208 } else {
209 if (errno == ENOENT) {
210 if (mkdir(QFile::encodeName(dir), 0700) != 0) {
211 KMessageBox::error( 0, i18n("Cannot create %1 folder.\nError: %2", dir, QString::fromLocal8Bit(strerror(errno))));
212 return(-1);
214 if (chown(QFile::encodeName(dir), d->UID, d->GID) != 0) {
215 KMessageBox::error( 0, i18n("Cannot change owner of %1 folder.\nError: %2", dir, QString::fromLocal8Bit(strerror(errno))) );
217 return(0);
218 } else {
219 KMessageBox::error( 0, i18n("stat call on %1 failed.\nError: %2", dir, QString::fromLocal8Bit(strerror(errno))) );
220 return(-1);
225 int KU_User::createMailBox()
227 QString mailboxpath;
228 int fd;
229 mailboxpath = QFile::decodeName(MAIL_SPOOL_DIR) + '/' + d->Name;
230 if((fd = open(QFile::encodeName(mailboxpath), O_CREAT|O_EXCL|O_WRONLY,
231 S_IRUSR|S_IWUSR)) < 0) {
232 if (errno != EEXIST)
234 KMessageBox::error( 0, i18n("Cannot create %1: %2",
235 mailboxpath,
236 QString::fromLocal8Bit(strerror(errno))) );
237 return -1;
241 close(fd);
243 if (chown(QFile::encodeName(mailboxpath), d->UID, KU_MAILBOX_GID) != 0) {
244 KMessageBox::error( 0, i18n("Cannot change owner on mailbox: %1\nError: %2",
245 mailboxpath, QString::fromLocal8Bit(strerror(errno))) );
246 return -1;
249 if (chmod(QFile::encodeName(mailboxpath), KU_MAILBOX_PERM) != 0) {
250 KMessageBox::error( 0, i18n("Cannot change permissions on mailbox: %1\nError: %2",
251 mailboxpath, QString::fromLocal8Bit(strerror(errno))) );
252 return -1;
255 return 0;
258 int KU_User::copySkel()
260 QDir source(QFile::decodeName(SKELDIR));
261 QDir dest(d->HomeDir);
262 mode_t mode;
264 if (!source.exists()) {
265 KMessageBox::error( 0, i18n("Folder %1 does not exist, cannot copy skeleton for %2.", source.absolutePath(), d->Name) );
266 return (-1);
269 if (!dest.exists()) {
270 KMessageBox::error( 0, i18n("Folder %1 does not exist, cannot copy skeleton.", dest.absolutePath()) );
271 return (-1);
274 mode = umask(0007);
275 copyDir(source.absolutePath(), dest.absolutePath(), d->UID, d->GID);
276 umask( mode );
278 return 0;
281 int KU_User::removeHome()
283 struct stat sb;
285 if (!stat(QFile::encodeName(d->HomeDir), &sb))
286 if (S_ISDIR(sb.st_mode) && sb.st_uid == d->UID) {
287 if (!KIO::NetAccess::del(KUrl(d->HomeDir),0L)) {
288 KMessageBox::error( 0, i18n("Cannot remove home folder %1.\nError: %2",
289 d->HomeDir, KIO::NetAccess::lastErrorString()) );
291 } else {
292 KMessageBox::error( 0, i18n("Removal of home folder %1 failed (uid = %2, gid = %3).", d->HomeDir, sb.st_uid, sb.st_gid) );
294 else {
295 KMessageBox::error( 0, i18n("stat call on file %1 failed.\nError: %2",
296 d->HomeDir, QString::fromLocal8Bit(strerror(errno))) );
299 return 0;
302 //TODO: remove at jobs too.
304 int KU_User::removeCrontabs()
306 QString file;
307 QString command;
309 file = QFile::decodeName(CRONTAB_DIR) + '/' + d->Name;
310 if ( access(QFile::encodeName(file), F_OK) == 0 ) {
311 command = QString::fromLatin1("crontab -u %1 -r").arg(KShell::quoteArg(d->Name));
312 if ( system(QFile::encodeName(command)) != 0 ) {
313 KMessageBox::error( 0, i18n("Cannot remove crontab %1.\nError: %2",
314 command, QString::fromLocal8Bit(strerror(errno))) );
318 return 0;
321 int KU_User::removeMailBox()
323 QString file;
325 file = QFile::decodeName(MAIL_SPOOL_DIR) + '/' + d->Name;
326 if (remove(QFile::encodeName(file)) != 0) {
327 KMessageBox::error( 0, i18n("Cannot remove mailbox %1.\nError: %2",
328 file, QString::fromLocal8Bit(strerror(errno))) );
331 return 0;
334 KU_Users::KU_Users(KU_PrefsBase *cfg)
336 mCfg = cfg;
339 KU_Users::~KU_Users()
343 const QString &KU_Users::getDOMSID() const
345 return domsid;
348 void KU_Users::parseGecos( const char *gecos, QString &name,
349 QString &field1, QString &field2, QString &field3 )
351 int no = 0;
352 const char *s = gecos;
353 const char *pos = NULL;
354 // At least one part of the string exists
355 for(;;) {
356 pos = strchr(s, ',');
357 QString val;
358 if(pos == NULL)
359 val = QString::fromLocal8Bit(s);
360 else
361 val = QString::fromLocal8Bit(s, (int)(pos-s));
363 switch(no) {
364 case 0: name = val; break;
365 case 1: field1 = val; break;
366 case 2: field2 = val; break;
367 case 3: field3 = val; break;
369 if(pos == NULL) break;
370 s = pos+1;
371 no++;
375 void KU_Users::fillGecos(KU_User &user, const char *gecos)
377 QString name,field1,field2,field3;
378 parseGecos( gecos, name, field1, field2, field3 );
379 user.setFullName( name );
380 caps & Cap_BSD ? user.setOffice( field1 ) : user.setOffice1( field1 );
381 caps & Cap_BSD ? user.setWorkPhone( field2 ) : user.setOffice2( field2 );
382 caps & Cap_BSD ? user.setHomePhone( field3 ) : user.setAddress( field3 );
385 bool KU_Users::doCreate(KU_User *user)
387 QString h_dir;
389 if(user->getCreateMailBox()) {
390 user->createMailBox();
391 user->setCreateMailBox(false);
394 if(user->getCreateHome()) {
395 if(user->createHome()) {
396 user->setCreateHome(false);
397 } else {
398 return false; // if createHome fails, copySkel is irrelevant!
401 if(user->getCopySkel()) {
402 if((user->copySkel()) == 0) {
403 user->setCopySkel(false);
408 return true;
411 bool KU_Users::doDelete( KU_User *user )
413 kDebug() << "delete user: " << user->getName() << " uid: " << user->getUID();
414 if ( user->getDeleteHome() ) {
415 user->removeHome();
416 user->removeCrontabs();
418 if ( user->getDeleteMailBox() )
419 user->removeMailBox();
421 return true;
424 int KU_Users::lookup(const QString & name) const
426 for ( int i = 0; i<count(); i++ ) {
427 if ( at(i).getName() == name ) return i;
429 return -1;
432 int KU_Users::lookup(uid_t uid) const
434 for ( int i = 0; i<count(); i++ ) {
435 if ( at(i).getUID() == uid ) return i;
437 return -1;
440 int KU_Users::lookup_sam( const SID &sid ) const
442 for ( int i = 0; i<count(); i++ ) {
443 if ( at(i).getSID() == sid ) return i;
445 return -1;
448 int KU_Users::lookup_sam( const QString &sid ) const
450 for ( int i = 0; i<count(); i++ ) {
451 if ( at(i).getSID().getSID() == sid ) return i;
453 return -1;
456 int KU_Users::lookup_sam( uint rid ) const
458 for ( int i = 0; i<count(); i++ ) {
459 if ( at(i).getSID().getRID() == rid ) return i;
461 return -1;
464 uid_t KU_Users::first_free() const
466 uid_t t;
468 for (t = mCfg->firstUID() ; t<65534; t++)
469 if (lookup(t) == -1)
470 return t;
472 return NO_FREE;
475 uint KU_Users::first_free_sam() const
477 uint t;
479 for (t = 1000; t<65534; t++)
480 if (lookup_sam(t) == -1)
481 return t;
483 return 0;
486 void KU_Users::add(const KU_User &user)
488 mAdd.append( user );
491 void KU_Users::del( int index)
493 mDel.append( index );
496 void KU_Users::mod(int index, const KU_User &newuser)
498 mMod.insert( index, newuser );
501 void KU_Users::commit()
503 kDebug() << "KU_Users::commit()";
505 for ( ModList::Iterator it = mModSucc.begin(); it != mModSucc.end(); ++it ) {
506 replace(it.key(),*it);
508 for ( AddList::Iterator it = mAddSucc.begin(); it != mAddSucc.end(); ++it ) {
509 append(*it);
511 for ( DelList::Iterator it = mDelSucc.begin(); it != mDelSucc.end(); ++it ) {
512 removeAt(*it);
514 cancelMods();
517 void KU_Users::cancelMods()
519 mAdd.clear();
520 mDel.clear();
521 mMod.clear();
522 mAddSucc.clear();
523 mDelSucc.clear();
524 mModSucc.clear();