1<?php
2  /*
3   +-----------------------------------------------------------------------------+
4   | ILIAS open source                                                           |
5   +-----------------------------------------------------------------------------+
6   | Copyright (c) 1998-2009 ILIAS open source, University of Cologne            |
7   |                                                                             |
8   | This program is free software; you can redistribute it and/or               |
9   | modify it under the terms of the GNU General Public License                 |
10   | as published by the Free Software Foundation; either version 2              |
11   | of the License, or (at your option) any later version.                      |
12   |                                                                             |
13   | This program is distributed in the hope that it will be useful,             |
14   | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
15   | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
16   | GNU General Public License for more details.                                |
17   |                                                                             |
18   | You should have received a copy of the GNU General Public License           |
19   | along with this program; if not, write to the Free Software                 |
20   | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. |
21   +-----------------------------------------------------------------------------+
22  */
23
24
25  /**
26   * Soap user administration methods
27   *
28   * @author Stefan Meyer <meyer@leifos.com>
29   * @version $Id$
30   *
31   * @package ilias
32   */
33include_once './webservice/soap/classes/class.ilSoapAdministration.php';
34
35class ilSoapUserAdministration extends ilSoapAdministration
36{
37
38    /**
39     * Soap login
40     * @global type $ilUser
41     * @param type $client
42     * @param type $username
43     * @param type $password
44     * @return type
45     */
46    public function login($client, $username, $password)
47    {
48        unset($_COOKIE[session_name()]);
49        $_COOKIE['ilClientId'] = $client;
50
51        try {
52            $this->initIlias();
53        } catch (Exception $e) {
54            return $this->__raiseError($e->getMessage(), 'Server');
55        }
56
57        // now try authentication
58        include_once './Services/Authentication/classes/Frontend/class.ilAuthFrontendCredentials.php';
59        $credentials = new ilAuthFrontendCredentials();
60        $credentials->setUsername($username);
61        $credentials->setPassword($password);
62
63        include_once './Services/Authentication/classes/Provider/class.ilAuthProviderFactory.php';
64        $provider_factory = new ilAuthProviderFactory();
65        $providers = $provider_factory->getProviders($credentials);
66
67        include_once './Services/Authentication/classes/class.ilAuthStatus.php';
68        $status = ilAuthStatus::getInstance();
69
70        include_once './Services/Authentication/classes/Frontend/class.ilAuthFrontendFactory.php';
71        $frontend_factory = new ilAuthFrontendFactory();
72        $frontend_factory->setContext(ilAuthFrontendFactory::CONTEXT_CLI);
73        $frontend = $frontend_factory->getFrontend(
74            $GLOBALS['DIC']['ilAuthSession'],
75            $status,
76            $credentials,
77            $providers
78        );
79
80        $frontend->authenticate();
81
82        switch ($status->getStatus()) {
83            case ilAuthStatus::STATUS_AUTHENTICATED:
84                ilLoggerFactory::getLogger('auth')->debug('Authentication successful.');
85                return $GLOBALS['DIC']['ilAuthSession']->getId() . '::' . $client;
86
87
88            default:
89            case ilAuthStatus::STATUS_AUTHENTICATION_FAILED:
90                return $this->__raiseError(
91                    $status->getReason(),
92                    'Server'
93                );
94        }
95        return true;
96    }
97
98    // Service methods
99    public function loginCAS($client, $PT, $username)
100    {
101        $this->__initAuthenticationObject(AUTH_CAS);
102        $this->sauth->setClient($client);
103        $this->sauth->setUsername($username);
104        $this->sauth->setPT($PT);
105        $authenticated = true;
106        if (!$this->sauth->authenticate()) {
107            $authenticated = false;
108        }
109        if (!$authenticated) {
110            return $this->__raiseError($this->sauth->getMessage(), $this->sauth->getMessageCode());
111        }
112        return $this->sauth->getSid() . '::' . $client;
113    }
114
115    // Service methods
116    /**
117     * Not required anymode. This method is a simple alias for login()
118     * @param type $client
119     * @param type $username
120     * @param type $password
121     * @return type
122     * @deprecated since version 5.2
123     */
124    public function loginLDAP($client, $username, $password)
125    {
126        return $this->login($client, $username, $password);
127    }
128
129    /**
130     * login as user from Stud.IP
131     * @deprecated
132     * @param string $sid
133     * @param int $user_id
134     * @return string $sid
135     */
136    public function loginStudipUser($sid, $user_id)
137    {
138        global $DIC;
139
140        $rbacreview = $DIC['rbacreview'];
141        $ilUser = $DIC['ilUser'];
142        $ilIliasIniFile = $DIC['ilIliasIniFile'];
143
144        $this->initAuth($sid);
145        $this->initIlias();
146        list($admin_sid, $client) = $this->__explodeSid($sid);
147
148        if (!$this->__checkSession($sid)) {
149            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
150        }
151
152        if (!$ilIliasIniFile->readVariable('server', 'studip')) {
153            return $this->__raiseError('Stud.IP mode not active.', 'Server');
154        }
155
156        if (!$rbacreview->isAssigned($ilUser->getId(), SYSTEM_ROLE_ID)) {
157            return $this->__raiseError('No permission to initialize user session.', 'Server');
158        }
159
160        if ($ilUser->getLoginByUserId($user_id)) {
161            // logout admin
162            include_once './Services/Authentication/classes/class.ilSession.php';
163            ilSession::setClosingContext(ilSession::SESSION_CLOSE_USER);
164            $GLOBALS['DIC']['ilAuthSession']->logout();
165            unset($_COOKIE[session_name()]);
166
167            // init session and set user as authenticated
168            $_COOKIE['ilClientId'] = $client;
169            $GLOBALS['DIC']['ilAuthSession']->init();
170            $GLOBALS['DIC']['ilAuthSession']->setAuthenticated(true, $user_id);
171            return (session_id() . '::' . $client);
172        }
173        return $this->__raiseError('User does not exist', 'Client');
174    }
175
176    /**
177     * Logout user destroy session
178     * @param string $sid
179     * @return type
180     */
181    public function logout($sid)
182    {
183        $this->initAuth($sid);
184        $this->initIlias();
185
186        if (!$this->__checkSession($sid)) {
187            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
188        }
189
190        include_once './Services/Authentication/classes/class.ilSession.php';
191        ilSession::setClosingContext(ilSession::SESSION_CLOSE_USER);
192        $GLOBALS['DIC']['ilAuthSession']->logout();
193        return true;
194    }
195
196    /**
197     * @param $sid
198     * @param $user_name
199     * @return int|\soap_fault|\SoapFault|string
200     */
201    public function lookupUser($sid, $user_name)
202    {
203        $this->initAuth($sid);
204        $this->initIlias();
205
206        if (!$this->__checkSession($sid)) {
207            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
208        }
209
210        $user_name = trim($user_name);
211
212        if (!strlen($user_name)) {
213            return $this->__raiseError('No username given. Aborting', 'Client');
214        }
215
216        global $DIC;
217
218        $ilUser = $DIC->user();
219        $access = $DIC->access();
220
221        if (
222            strcasecmp($ilUser->getLogin(), $user_name) !== 0 &&
223            !$access->checkAccess(
224                'read_users',
225                '',
226                USER_FOLDER_ID
227            )
228        ) {
229            return $this->__raiseError('Check access failed. ' . USER_FOLDER_ID, 'Server');
230        }
231
232        $user_id = ilObjUser::getUserIdByLogin($user_name);
233
234
235        return $user_id ? $user_id : "0";
236    }
237
238    /**
239     * @param $sid
240     * @param $user_id
241     * @return mixed|\soap_fault|\SoapFault
242     * @throws \ilDatabaseException
243     * @throws \ilObjectNotFoundException
244     */
245    public function getUser($sid, $user_id)
246    {
247        $this->initAuth($sid);
248        $this->initIlias();
249
250        if (!$this->__checkSession($sid)) {
251            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
252        }
253
254        global $DIC;
255
256        $access = $DIC->access();
257        $ilUser = $DIC->user();
258
259        if (
260            !$access->checkAccess(
261                'read_users',
262                '',
263                USER_FOLDER_ID
264            )
265        ) {
266            return $this->__raiseError('Check access failed.', 'Server');
267        }
268
269        if ($ilUser->getLoginByUserId($user_id)) {
270            $tmp_user =&ilObjectFactory::getInstanceByObjId($user_id);
271            $usr_data = $this->__readUserData($tmp_user);
272
273            return $usr_data;
274        }
275        return $this->__raiseError('User does not exist', 'Client');
276    }
277
278
279    /**
280     * @deprecated
281     */
282    public function deleteUser($sid, $user_id)
283    {
284        $this->initAuth($sid);
285        $this->initIlias();
286
287        if (!$this->__checkSession($sid)) {
288            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
289        }
290
291        if (!isset($user_id)) {
292            return $this->__raiseError('No user_id given. Aborting', 'Client');
293        }
294
295        global $DIC;
296
297        $rbacsystem = $DIC['rbacsystem'];
298        $ilUser = $DIC['ilUser'];
299        $log = $DIC['log'];
300
301        if (!$rbacsystem->checkAccess('delete', USER_FOLDER_ID)) {
302            return $this->__raiseError('Check access failed.', 'Server');
303        }
304
305        if (!$ilUser->getLoginByUserId($user_id)) {
306            return $this->__raiseError('User id: ' . $user_id . ' is not a valid identifier. Aborting', 'Client');
307        }
308        if ($ilUser->getId() == $user_id) {
309            return $this->__raiseError('Cannot delete myself. Aborting', 'Client');
310        }
311        if ($user_id == SYSTEM_USER_ID) {
312            return $this->__raiseError('Cannot delete root account. Aborting', 'Client');
313        }
314        // Delete him
315        $log->write('SOAP: deleteUser()');
316        $delete_user =&ilObjectFactory::getInstanceByObjId($user_id, false);
317        $delete_user->delete();
318
319        return true;
320    }
321
322    public function __readUserData(\ilObjUser &$usr_obj)
323    {
324        $usr_data['usr_id'] = $usr_obj->getId();
325        $usr_data['login'] = $usr_obj->getLogin();
326        $usr_data['passwd'] = $usr_obj->getPasswd();
327        $usr_data['passwd_type'] = $usr_obj->getPasswdType();
328        $usr_data['firstname'] = $usr_obj->getFirstname();
329        $usr_data['lastname'] = $usr_obj->getLastname();
330        $usr_data['title'] = $usr_obj->getUTitle();
331        $usr_data['gender'] = $usr_obj->getGender();
332        $usr_data['email'] = $usr_obj->getEmail();
333        $usr_data['second_email'] = $usr_obj->getSecondEmail();
334        $usr_data['institution'] = $usr_obj->getInstitution();
335        $usr_data['street'] = $usr_obj->getStreet();
336        $usr_data['city'] = $usr_obj->getCity();
337        $usr_data['zipcode'] = $usr_obj->getZipcode();
338        $usr_data['country'] = $usr_obj->getCountry();
339        $usr_data['phone_office'] = $usr_obj->getPhoneOffice();
340        $usr_data['last_login'] = $usr_obj->getLastLogin();
341        $usr_data['last_update'] = $usr_obj->getLastUpdate();
342        $usr_data['create_date'] = $usr_obj->getCreateDate();
343        $usr_data['hobby'] = $usr_obj->getHobby();
344        $usr_data['department'] = $usr_obj->getDepartment();
345        $usr_data['phone_home'] = $usr_obj->getPhoneHome();
346        $usr_data['phone_mobile'] = $usr_obj->getPhoneMobile();
347        $usr_data['fax'] = $usr_obj->getFax();
348        $usr_data['time_limit_owner'] = $usr_obj->getTimeLimitOwner();
349        $usr_data['time_limit_unlimited'] = $usr_obj->getTimeLimitUnlimited();
350        $usr_data['time_limit_from'] = $usr_obj->getTimeLimitFrom();
351        $usr_data['time_limit_until'] = $usr_obj->getTimeLimitUntil();
352        $usr_data['time_limit_message'] = $usr_obj->getTimeLimitMessage();
353        $usr_data['referral_comment'] = $usr_obj->getComment();
354        $usr_data['matriculation'] = $usr_obj->getMatriculation();
355        $usr_data['active'] = $usr_obj->getActive();
356        $usr_data['approve_date'] = $usr_obj->getApproveDate();
357        $usr_data['user_skin'] = $usr_obj->getPref('skin');
358        $usr_data['user_style'] = $usr_obj->getPref('style');
359        $usr_data['user_language'] = $usr_obj->getLanguage();
360        $usr_data['auth_mode'] = $usr_obj->getAuthMode();
361        $usr_data['accepted_agreement'] = !$usr_obj->hasToAcceptTermsOfService();
362        $usr_data['import_id'] = $usr_obj->getImportId();
363
364        return $usr_data;
365    }
366
367    /**
368    *
369    * define ("IL_FAIL_ON_CONFLICT", 1);
370    * define ("IL_UPDATE_ON_CONFLICT", 2);
371    * define ("IL_IGNORE_ON_CONFLICT", 3);
372    */
373    public function importUsers($sid, $folder_id, $usr_xml, $conflict_rule, $send_account_mail)
374    {
375        $this->initAuth($sid);
376        $this->initIlias();
377
378        if (!$this->__checkSession($sid)) {
379            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
380        }
381
382
383        include_once './Services/User/classes/class.ilUserImportParser.php';
384        include_once './Services/AccessControl/classes/class.ilObjRole.php';
385        include_once './Services/Object/classes/class.ilObjectFactory.php';
386        global $DIC;
387
388        $rbacreview = $DIC['rbacreview'];
389        $rbacsystem = $DIC['rbacsystem'];
390        $access = $DIC->access();
391        $tree = $DIC['tree'];
392        $lng = $DIC['lng'];
393        $ilUser = $DIC['ilUser'];
394        $ilLog = $DIC['ilLog'];
395
396        // this takes time but is nescessary
397        $error = false;
398
399
400        // validate to prevent wrong XMLs
401        $this->dom = @domxml_open_mem($usr_xml, DOMXML_LOAD_VALIDATING, $error);
402        if ($error) {
403            $msg = array();
404            if (is_array($error)) {
405                foreach ($error as $err) {
406                    $msg []= "(" . $err["line"] . "," . $err["col"] . "): " . $err["errormessage"];
407                }
408            } else {
409                $msg[] = $error;
410            }
411            $msg = join("\n", $msg);
412            return $this->__raiseError($msg, "Client");
413        }
414
415
416        switch ($conflict_rule) {
417            case 2:
418                $conflict_rule = IL_UPDATE_ON_CONFLICT;
419                break;
420            case 3:
421                $conflict_rule = IL_IGNORE_ON_CONFLICT;
422                break;
423            default:
424                $conflict_rule = IL_FAIL_ON_CONFLICT;
425        }
426        if ($folder_id == 0) {
427            if (!$access->checkAccess('create_usr', '', USER_FOLDER_ID)) {
428                return $this->__raiseError('Missing permission for creating/modifying users accounts' . USER_FOLDER_ID . ' ' . $ilUser->getId(), 'Server');
429            }
430        }
431
432        // folder id 0, means to check permission on user basis!
433        // must have create user right in time_limit_owner property (which is ref_id of container)
434        if ($folder_id != 0) {
435            // determine where to import
436            if ($folder_id == -1) {
437                $folder_id = USER_FOLDER_ID;
438            }
439
440            // get folder
441            $import_folder = ilObjectFactory::getInstanceByRefId($folder_id, false);
442            // id does not exist
443            if (!$import_folder) {
444                return $this->__raiseError('Wrong reference id.', 'Server');
445            }
446
447            // folder is not a folder, can also be a category
448            if ($import_folder->getType() != "usrf" && $import_folder->getType() != "cat") {
449                return $this->__raiseError('Folder must be a usr folder or a category.', 'Server');
450            }
451
452            // check access to folder
453            if (!$rbacsystem->checkAccess('create_usr', $folder_id)) {
454                return $this->__raiseError('Missing permission for creating users within ' . $import_folder->getTitle(), 'Server');
455            }
456        }
457
458        // first verify
459        $importParser = new ilUserImportParser("", IL_VERIFY, $conflict_rule);
460        $importParser->setUserMappingMode(IL_USER_MAPPING_ID);
461        $importParser->setXMLContent($usr_xml);
462        $importParser->startParsing();
463
464        switch ($importParser->getErrorLevel()) {
465            case IL_IMPORT_SUCCESS:
466                break;
467            case IL_IMPORT_WARNING:
468                return $this->__getImportProtocolAsXML($importParser->getProtocol("User Import Log - Warning"));
469                break;
470            case IL_IMPORT_FAILURE:
471                return $this->__getImportProtocolAsXML($importParser->getProtocol("User Import Log - Failure"));
472        }
473
474        // verify is ok, so get role assignments
475
476        $importParser = new ilUserImportParser("", IL_EXTRACT_ROLES, $conflict_rule);
477        $importParser->setXMLContent($usr_xml);
478        $importParser->setUserMappingMode(IL_USER_MAPPING_ID);
479        $importParser->startParsing();
480
481        $roles = $importParser->getCollectedRoles();
482
483        //print_r($roles);
484
485
486
487        // roles to be assigned, skip if one is not allowed!
488        $permitted_roles = array();
489        foreach ($roles as $role_id => $role) {
490            if (!is_numeric($role_id)) {
491                // check if internal id
492                $internalId = ilUtil::__extractId($role_id, IL_INST_ID);
493
494                if (is_numeric($internalId)) {
495                    $role_id = $internalId;
496                    $role_name = $role_id;
497                }
498                /*				else // perhaps it is a rolename
499                                {
500                                    $role  = ilSoapUserAdministration::__getRoleForRolename ($role_id);
501                                    $role_name = $role->title;
502                                    $role_id = $role->role_id;
503                                }*/
504            }
505
506            if ($this->isPermittedRole($folder_id, $role_id)) {
507                $permitted_roles[$role_id] = $role_id;
508            } else {
509                $role_name = ilObject::_lookupTitle($role_id);
510                return $this->__raiseError("Could not find role " . $role_name . ". Either you use an invalid/deleted role " .
511                    "or you try to assign a local role into the non-standard user folder and this role is not in its subtree.", 'Server');
512            }
513        }
514
515        $global_roles = $rbacreview->getGlobalRoles();
516
517        //print_r ($global_roles);
518
519
520
521        foreach ($permitted_roles as $role_id => $role_name) {
522            if ($role_id != "") {
523                if (in_array($role_id, $global_roles)) {
524                    if ($role_id == SYSTEM_ROLE_ID && !in_array(SYSTEM_ROLE_ID, $rbacreview->assignedRoles($ilUser->getId()))
525                        || ($folder_id != USER_FOLDER_ID && $folder_id != 0 && !ilObjRole::_getAssignUsersStatus($role_id))
526                        ) {
527                        return $this->__raiseError($lng->txt("usrimport_with_specified_role_not_permitted") . " $role_name ($role_id)", 'Server');
528                    }
529                } else {
530                    $rolf = $rbacreview->getFoldersAssignedToRole($role_id, true);
531                    if ($rbacreview->isDeleted($rolf[0])
532                                || !$rbacsystem->checkAccess('write', $rolf[0])) {
533                        return $this->__raiseError($lng->txt("usrimport_with_specified_role_not_permitted") . " $role_name ($role_id)", "Server");
534                    }
535                }
536            }
537        }
538
539        //print_r ($permitted_roles);
540
541        $importParser = new ilUserImportParser("", IL_USER_IMPORT, $conflict_rule);
542        $importParser->setSendMail($send_account_mail);
543        $importParser->setUserMappingMode(IL_USER_MAPPING_ID);
544        $importParser->setFolderId($folder_id);
545        $importParser->setXMLContent($usr_xml);
546
547        $importParser->setRoleAssignment($permitted_roles);
548
549        $importParser->startParsing();
550
551        if ($importParser->getErrorLevel() != IL_IMPORT_FAILURE) {
552            return $this->__getUserMappingAsXML($importParser->getUserMapping());
553        }
554        return $this->__getImportProtocolAsXML($importParser->getProtocol());
555    }
556
557    /**
558     * check if assignment is allowed
559     *
560     * @access protected
561     * @param
562     * @return
563     */
564    protected function isPermittedRole($a_folder, $a_role)
565    {
566        static $checked_roles = array();
567        static $global_roles = null;
568
569
570        if (isset($checked_roles[$a_role])) {
571            return $checked_roles[$a_role];
572        }
573
574        global $DIC;
575
576        $rbacsystem = $DIC['rbacsystem'];
577        $rbacreview = $DIC['rbacreview'];
578        $ilUser = $DIC['ilUser'];
579        $tree = $DIC['tree'];
580        $ilLog = $DIC['ilLog'];
581
582        $locations = $rbacreview->getFoldersAssignedToRole($a_role, true);
583        $location = $locations[0];
584
585        // global role
586        if ($location == ROLE_FOLDER_ID) {
587            $ilLog->write(__METHOD__ . ': Check global role');
588            // check assignment permission if called from local admin
589
590
591            if ($a_folder != USER_FOLDER_ID and $a_folder != 0) {
592                $ilLog->write(__METHOD__ . ': ' . $a_folder);
593                include_once './Services/AccessControl/classes/class.ilObjRole.php';
594                if (!ilObjRole::_getAssignUsersStatus($a_role)) {
595                    $ilLog->write(__METHOD__ . ': No assignment allowed');
596                    $checked_roles[$a_role] = false;
597                    return false;
598                }
599            }
600            // exclude anonymous role from list
601            if ($a_role == ANONYMOUS_ROLE_ID) {
602                $ilLog->write(__METHOD__ . ': Anonymous role chosen.');
603                $checked_roles[$a_role] = false;
604                return false;
605            }
606            // do not allow to assign users to administrator role if current user does not has SYSTEM_ROLE_ID
607            if ($a_role == SYSTEM_ROLE_ID and !in_array(SYSTEM_ROLE_ID, $rbacreview->assignedRoles($ilUser->getId()))) {
608                $ilLog->write(__METHOD__ . ': System role assignment forbidden.');
609                $checked_roles[$a_role] = false;
610                return false;
611            }
612
613            // Global role assignment ok
614            $ilLog->write(__METHOD__ . ': Assignment allowed.');
615            $checked_roles[$a_role] = true;
616            return true;
617        } elseif ($location) {
618            $ilLog->write(__METHOD__ . ': Check local role.');
619
620            // It's a local role
621            $rolfs = $rbacreview->getFoldersAssignedToRole($a_role, true);
622            $rolf = $rolfs[0];
623
624
625            // only process role folders that are not set to status "deleted"
626            // and for which the user has write permissions.
627            // We also don't show the roles which are in the ROLE_FOLDER_ID folder.
628            // (The ROLE_FOLDER_ID folder contains the global roles).
629            if ($rbacreview->isDeleted($rolf)
630                || !$rbacsystem->checkAccess('edit_permission', $rolf)) {
631                $ilLog->write(__METHOD__ . ': Role deleted or no permission.');
632                $checked_roles[$a_role] = false;
633                return false;
634            }
635            // A local role is only displayed, if it is contained in the subtree of
636            // the localy administrated category. If the import function has been
637            // invoked from the user folder object, we show all local roles, because
638            // the user folder object is considered the parent of all local roles.
639            // Thus, if we start from the user folder object, we initializ$isInSubtree = $folder_id == USER_FOLDER_ID || $folder_id == 0;e the
640            // isInSubtree variable with true. In all other cases it is initialized
641            // with false, and only set to true if we find the object id of the
642            // locally administrated category in the tree path to the local role.
643            if ($a_folder != USER_FOLDER_ID and $a_folder != 0 and !$tree->isGrandChild($a_folder, $rolf)) {
644                $ilLog->write(__METHOD__ . ': Not in path of category.');
645                $checked_roles[$a_role] = false;
646                return false;
647            }
648            $ilLog->write(__METHOD__ . ': Assignment allowed.');
649            $checked_roles[$a_role] = true;
650            return true;
651        }
652    }
653
654
655    /**
656    * return list of users following dtd users_3_7
657    */
658    public function getUsersForContainer($sid, $ref_id, $attachRoles, $active)
659    {
660        $this->initAuth($sid);
661        $this->initIlias();
662
663        if (!$this->__checkSession($sid)) {
664            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
665        }
666
667        global $DIC;
668
669        $ilDB = $DIC['ilDB'];
670        $tree = $DIC['tree'];
671        $rbacreview = $DIC['rbacreview'];
672        $rbacsystem = $DIC['rbacsystem'];
673        $access = $DIC->access();
674
675        if ($ref_id == -1) {
676            $ref_id = USER_FOLDER_ID;
677        }
678
679        if (
680            $ref_id == USER_FOLDER_ID &&
681            !$access->checkAccess('read_users', '', USER_FOLDER_ID)
682        ) {
683            return $this->__raiseError('Access denied', "Client");
684        }
685
686
687        $object = $this->checkObjectAccess($ref_id, array("crs","cat","grp","usrf","sess"), "read", true);
688        if ($this->isFault($object)) {
689            return $object;
690        }
691
692        $data = array();
693        switch ($object->getType()) {
694            case "usrf":
695                $data = ilObjUser::_getUsersForFolder(USER_FOLDER_ID, $active);
696                break;
697            case "cat":
698                $data =  ilObjUser::_getUsersForFolder($ref_id, $active);
699                break;
700            case "crs":
701            {
702                // GET ALL MEMBERS
703                $roles = $object->__getLocalRoles();
704
705                foreach ($roles as $role_id) {
706                    $data = array_merge($rbacreview->assignedUsers($role_id), $data);
707                }
708
709                break;
710            }
711            case "grp":
712                $member_ids = $object->getGroupMemberIds();
713                $data = ilObjUser::_getUsersForGroup($member_ids, $active);
714                break;
715            case "sess":
716                $course_ref_id = $tree->checkForParentType($ref_id, 'crs');
717                if (!$course_ref_id) {
718                    return $this->__raiseError("No course for session", "Client");
719                }
720
721                $event_obj_id = ilObject::_lookupObjId($ref_id);
722                include_once 'Modules/Session/classes/class.ilEventParticipants.php';
723                $event_part = new ilEventParticipants($event_obj_id);
724                $member_ids = array_keys($event_part->getParticipants());
725                $data = ilObjUser::_getUsersForIds($member_ids, $active);
726                break;
727        }
728
729        if (is_array($data)) {
730            include_once './Services/User/classes/class.ilUserXMLWriter.php';
731
732            $xmlWriter = new ilUserXMLWriter();
733            $xmlWriter->setObjects($data);
734            $xmlWriter->setAttachRoles($attachRoles);
735
736            if ($xmlWriter->start()) {
737                return $xmlWriter->getXML();
738            }
739        }
740        return $this->__raiseError('Error in processing information. This is likely a bug.', 'Server');
741    }
742
743
744    /**
745    * @return list of users of a specific role, following dtd users_3_7
746    */
747    public function getUserForRole($sid, $role_id, $attachRoles, $active)
748    {
749        $this->initAuth($sid);
750        $this->initIlias();
751
752        if (!$this->__checkSession($sid)) {
753            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
754        }
755
756        include_once './Services/AccessControl/classes/class.ilObjRole.php';
757        global $DIC;
758
759        $ilDB = $DIC['ilDB'];
760        $rbacreview = $DIC['rbacreview'];
761        $tree = $DIC->repositoryTree();
762        $ilUser = $DIC->user();
763        $access = $DIC->access();
764
765
766        $global_roles = $rbacreview->getGlobalRoles();
767
768
769        if (in_array($role_id, $global_roles)) {
770            // global roles
771            if ($role_id == SYSTEM_ROLE_ID && !in_array(SYSTEM_ROLE_ID, $rbacreview->assignedRoles($ilUser->getId()))
772            ) {
773                return $this->__raiseError("Role access not permitted. ($role_id)", "Server");
774            }
775        } else {
776            // local roles
777            $rolfs = $rbacreview->getFoldersAssignedToRole($role_id, true);
778            $access_granted = true;
779            foreach ($rolfs as $rolf) {
780                if ($tree->isDeleted($rolf)) {
781                    $access_granted = false;
782                }
783                $type = \ilObject::_lookupType($rolf, true);
784                switch ($type) {
785                    case 'crs':
786                    case 'grp':
787                        if (!$access->checkAccess('manage_members', '', $rolf)) {
788                            $access_granted = false;
789                        }
790                        break;
791                    default:
792                        if (!$access->checkAccess('edit_permission', '', $rolf)) {
793                            $access_granted = false;
794                        }
795                        break;
796                }
797            }
798            // read user data must be granted
799            if (!$access->checkAccess('read_users', '', USER_FOLDER_ID)) {
800                $access_granted = false;
801            }
802            if (!$access_granted || !count($rolfs)) {
803                return $this->__raiseError('Role access not permitted. ' . '(' . $role_id .')', 'Server');
804            }
805        }
806
807        $data = ilObjUser::_getUsersForRole($role_id, $active);
808        include_once './Services/User/classes/class.ilUserXMLWriter.php';
809
810        $xmlWriter = new ilUserXMLWriter();
811        $xmlWriter->setAttachRoles($attachRoles);
812
813        $xmlWriter->setObjects($data);
814
815        if ($xmlWriter->start()) {
816            return $xmlWriter->getXML();
817        }
818        return $this->__raiseError('Error in getUsersForRole', 'Server');
819    }
820
821
822
823    /**
824    *	Create XML ResultSet
825    *
826    **/
827    public function __getImportProtocolAsXML($a_array)
828    {
829        include_once './webservice/soap/classes/class.ilXMLResultSet.php';
830        include_once './webservice/soap/classes/class.ilXMLResultSetWriter.php';
831
832        $xmlResultSet = new ilXMLResultSet();
833        $xmlResultSet->addColumn("userid");
834        $xmlResultSet->addColumn("login");
835        $xmlResultSet->addColumn("action");
836        $xmlResultSet->addColumn("message");
837
838        foreach ($a_array as $username => $messages) {
839            foreach ($messages as $message) {
840                $xmlRow = new ilXMLResultSetRow();
841                $xmlRow->setValue(0, 0);
842                $xmlRow->setValue(1, $username);
843                $xmlRow->setValue(2, "");
844                $xmlRow->setValue(3, $message);
845
846                $xmlResultSet->addRow($xmlRow);
847            }
848        }
849
850        $xml_writer = new ilXMLResultSetWriter($xmlResultSet);
851
852        if ($xml_writer->start()) {
853            return $xml_writer->getXML();
854        }
855
856        return $this->__raiseError('Error in __getImportProtocolAsXML', 'Server');
857    }
858
859    /**
860     * return user  mapping as xml
861     *
862     * @param array (user_id => login) $a_array
863     * @return XML String, following resultset.dtd
864     */
865    public function __getUserMappingAsXML($a_array)
866    {
867        include_once './webservice/soap/classes/class.ilXMLResultSet.php';
868        include_once './webservice/soap/classes/class.ilXMLResultSetWriter.php';
869
870        $xmlResultSet = new ilXMLResultSet();
871        $xmlResultSet->addColumn("userid");
872        $xmlResultSet->addColumn("login");
873        $xmlResultSet->addColumn("action");
874        $xmlResultSet->addColumn("message");
875
876        if (count($a_array)) {
877            foreach ($a_array as $username => $message) {
878                $xmlRow = new ilXMLResultSetRow();
879                $xmlRow->setValue(0, $username);
880                $xmlRow->setValue(1, $message["login"]);
881                $xmlRow->setValue(2, $message["action"]);
882                $xmlRow->setValue(3, $message["message"]);
883
884                $xmlResultSet->addRow($xmlRow);
885            }
886        }
887
888        $xml_writer = new ilXMLResultSetWriter($xmlResultSet);
889
890        if ($xml_writer->start()) {
891            return $xml_writer->getXML();
892        }
893
894        return $this->__raiseError('Error in __getUserMappingAsXML', 'Server');
895    }
896
897    /**
898     * return user xml following dtd 3.7
899     *
900     * @param String $sid    session id
901     * @param String array $a_keyfields    array of user fieldname, following dtd 3.7
902     * @param String $queryOperator  any logical operator
903     * @param String array $a_keyValues  values separated by space, at least 3 chars per search term
904     */
905    public function searchUser($sid, $a_keyfields, $query_operator, $a_keyvalues, $attach_roles, $active)
906    {
907        $this->initAuth($sid);
908        $this->initIlias();
909
910        if (!$this->__checkSession($sid)) {
911            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
912        }
913
914        global $DIC;
915
916        $ilDB = $DIC['ilDB'];
917        $access = $DIC->access();
918
919        if (!$access->checkAccess('read_users', '', USER_FOLDER_ID)) {
920            return $this->__raiseError('Check access failed.', 'Server');
921        }
922        if (!count($a_keyfields)) {
923            $this->__raiseError('At least one keyfield is needed', 'Client');
924        }
925
926        if (!count($a_keyvalues)) {
927            $this->__raiseError('At least one keyvalue is needed', 'Client');
928        }
929
930        if (!strcasecmp($query_operator, "and")==0 || !strcasecmp($query_operator, "or") == 0) {
931            $this->__raiseError('Query operator must be either \'and\' or \'or\'', 'Client');
932        }
933
934
935        $query = $this->__buildSearchQuery($a_keyfields, $query_operator, $a_keyvalues);
936
937        $query = "SELECT usr_data.*, usr_pref.value AS language
938		          FROM usr_data
939		          LEFT JOIN usr_pref
940		          ON usr_pref.usr_id = usr_data.usr_id AND usr_pref.keyword = " .
941                  $ilDB->quote("language", "text") .
942                  "'language'
943		          WHERE 1 = 1 " . $query;
944
945        if (is_numeric($active) && $active > -1) {
946            $query .= " AND active = " . $ilDB->quote($active);
947        }
948
949        $query .= " ORDER BY usr_data.lastname, usr_data.firstname ";
950
951        //echo $query;
952
953        $r = $ilDB->query($query);
954
955        $data = array();
956
957        while ($row = $ilDB->fetchAssoc($r)) {
958            $data[] = $row;
959        }
960
961        include_once './Services/User/classes/class.ilUserXMLWriter.php';
962
963        $xmlWriter = new ilUserXMLWriter();
964        $xmlWriter->setAttachRoles($attach_roles);
965
966        $xmlWriter->setObjects($data);
967
968        if ($xmlWriter->start()) {
969            return $xmlWriter->getXML();
970        }
971        return $this->__raiseError('Error in searchUser', 'Server');
972    }
973
974    /**
975     * create search term according to parameters
976     *
977     * @param array of string $a_keyfields
978     * @param string $queryOperator
979     * @param array of string $a_keyValues
980     */
981
982    public function __buildSearchQuery($a_keyfields, $queryOperator, $a_keyvalues)
983    {
984        global $DIC;
985
986        $ilDB = $DIC['ilDB'];
987        $query = array();
988
989        $allowed_fields = array("firstname","lastname","email","login","matriculation","institution","department","title","ext_account");
990
991        foreach ($a_keyfields as $keyfield) {
992            $keyfield = strtolower($keyfield);
993
994            if (!in_array($keyfield, $allowed_fields)) {
995                continue;
996            }
997
998            $field_query = array();
999            foreach ($a_keyvalues as $keyvalue) {
1000                if (strlen($keyvalue) >= 3) {
1001                    $field_query []= $keyfield . " like '%" . $keyvalue . "%'";
1002                }
1003            }
1004            if (count($field_query)) {
1005                $query [] = join(" " . strtoupper($queryOperator) . " ", $field_query);
1006            }
1007        }
1008
1009        return count($query) ? " AND ((" . join(") OR (", $query) . "))" : "AND 0";
1010    }
1011
1012
1013    /**
1014    *	return user xmls for given user ids (csv separated ids) as xml based on usr dtd.
1015    *	@param string sid	session id
1016    *	@param string a_userids array of user ids, may be numeric or ilias ids
1017    *	@param boolean attachRoles	if true, role assignments will be attached, nothing will be done otherwise
1018    *	@return	string	xml string based on usr dtd
1019    */
1020    public function getUserXML($sid, $a_user_ids, $attach_roles)
1021    {
1022        $this->initAuth($sid);
1023        $this->initIlias();
1024
1025        if (!$this->__checkSession($sid)) {
1026            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1027        }
1028
1029        global $DIC;
1030
1031        $rbacsystem = $DIC['rbacsystem'];
1032        $access = $DIC->access();
1033        $ilUser = $DIC['ilUser'];
1034        $ilDB = $DIC['ilDB'];
1035
1036        // check if own account
1037        $is_self = false;
1038        if (is_array($a_user_ids) and count($a_user_ids) == 1) {
1039            if (end($a_user_ids) == $ilUser->getId()) {
1040                $is_self = true;
1041            }
1042        } elseif (is_numeric($a_user_ids)) {
1043            if ($a_user_ids == $ilUser->getId()) {
1044                $is_self = true;
1045            }
1046        }
1047
1048        if (!$access->checkAccess('read_users', '', USER_FOLDER_ID) && !$is_self) {
1049            return $this->__raiseError('Check access failed.', 'Server');
1050        }
1051
1052
1053        // begin-patch filemanager
1054        $data = ilObjUser::_getUserData((array) $a_user_ids);
1055        // end-patch filemanager
1056
1057        include_once './Services/User/classes/class.ilUserXMLWriter.php';
1058        $xmlWriter = new ilUserXMLWriter();
1059        $xmlWriter->setAttachRoles($attach_roles);
1060        $xmlWriter->setObjects($data);
1061
1062        if ($xmlWriter->start()) {
1063            return $xmlWriter->getXML();
1064        }
1065
1066        return $this->__raiseError('User does not exist', 'Client');
1067    }
1068
1069
1070    // has new mail
1071    public function hasNewMail($sid)
1072    {
1073        $this->initAuth($sid);
1074        $this->initIlias();
1075
1076        if (!$this->__checkSession($sid)) {
1077            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1078        }
1079
1080        global $DIC;
1081
1082        $ilUser = $DIC['ilUser'];
1083
1084        if (ilMailGlobalServices::getNewMailsData((int) $ilUser->getId())['count'] > 0) {
1085            return true;
1086        } else {
1087            return false;
1088        }
1089    }
1090
1091    public function getUserIdBySid($sid)
1092    {
1093        $this->initAuth($sid);
1094        $this->initIlias();
1095
1096        if (!$this->__checkSession($sid)) {
1097            return $this->__raiseError($this->__getMessage(), $this->__getMessageCode());
1098        }
1099
1100        global $DIC;
1101
1102        $ilDB = $DIC['ilDB'];
1103
1104        $parts = explode('::', $sid);
1105        $query = "SELECT usr_id FROM usr_session "
1106               . "INNER JOIN usr_data ON usr_id = user_id WHERE session_id = %s";
1107        $res = $ilDB->queryF($query, array('text'), array($parts[0]));
1108        $data = $ilDB->fetchAssoc($res);
1109
1110        if (!(int) $data['usr_id']) {
1111            $this->__raiseError('User does not exist', 'Client');
1112        }
1113
1114        return (int) $data['usr_id'];
1115    }
1116}
1117