1<?php
2// must be run within Dokuwiki
3if(!defined('DOKU_INC')) die();
4//error_reporting (E_ALL | E_STRICT);
5//ini_set ('display_errors', 'On');
6/**
7 * authenticat against owncloud instance
8 *
9 * @license   GPL 2 (http://www.gnu.org/licenses/gpl.html)
10 * @author    Martin Schulte <lebowski[at]corvus[dot]uberspace[dot]de>
11 */
12class auth_plugin_authowncloud extends DokuWiki_Auth_Plugin {
13
14	public function __construct() {
15		parent::__construct();
16
17        $savedSession = session_name();
18        session_write_close();
19        // one could argue about error_reportint() .... ;) However, we
20        // simply save and restore the settings active in
21        // owncloud. Otherwise the owncloud.log will be bloated with
22        // all kind of DW warnings
23        $savedReporting = error_reporting();
24
25		require_once($this->getConf('pathtoowncloud').'/lib/base.php');
26
27        error_reporting($savedReporting);
28        error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);
29        session_write_close();
30        session_name($savedSession);
31        session_start();
32
33		// Check if ownCloud is installed or in maintenance (update) mode
34		if (!OC_Config::getValue('installed', false)) {
35			global $conf;
36			echo "Owncloud not installed!";
37			$this->success = false;
38		}else{
39			$this->cando['addUser']   = true;
40			$this->cando['modGroups'] = true;
41			$this->cando['logout']    = true;
42			$this->cando['delUser']   = true;
43			$this->cando['modLogin']  = true;
44			$this->cando['modPass']   = true;
45			$this->cando['modName']   = true;
46			$this->cando['modMail']   = true;
47			$this->cando['getUsers']  = true;
48			$this->cando['getGroups'] = true;
49            $this->cando['getUserCount'] = true;
50            $this->success = true;
51		}
52
53    }
54
55    /**
56     * Check user+password
57     *
58     * Checks if the given user exists and the given
59     * plaintext password is correct by forward it to
60     * the corresponding owncloud function.
61     *
62     * @param string $user
63     * @param string $pass
64     * @return  bool
65     */
66    public function checkPass($user, $pass) {
67         if(OC_USER::checkPassword($user,$pass)) return true;
68         return false;
69    }
70
71
72    /**
73     * Return user info
74     *
75     * name string  full name of the user
76     * mail string  email addres of the user
77     * grps array   list of groups the user is in
78     *
79     * @param   string $user the user name
80     * @return  array containing user data or false
81     */
82    public function getUserData($user) {
83		$name = OC_User::getDisplayName($user);
84		$mail = $this->getUserMail($user);
85		$grps = $this->getUserGroups($user);
86        return array('name'=>$name,'mail'=>$mail,'grps'=>$grps);
87    }
88
89
90     /**
91     * Create a new User
92     *
93     * Returns false if the user already exists, null when an error
94     * occurred and true if everything went well.
95     *
96     * The new user will be added to the default group by this
97     * function if grps are not specified (default behaviour).
98     *
99     *
100     * @param string $user
101     * @param string $pwd
102     * @param string $name
103     * @param string $mail
104     * @param array  $grps
105     * @return bool|null
106     */
107    public function createUser($user, $pwd, $name, $mail, $grps = null) {
108		global $conf;
109		if(OC_USER::userExists($user)) return false;
110		if(!OC_USER::createUser($user, $pwd)) return null;
111		if(!OC_USER::setDisplayName($user, $name)) return null;
112        if(!OC_Preferences::setValue($user, 'settings', 'email', $mail)) return null;
113        if(!OC_Group::groupExists($conf['defaultgroup'])) $this->addGroup($conf['defaultgroup']);
114        if(!is_array($grps)) $grps = array($conf['defaultgroup']);
115        foreach($grps as $grp){
116			if(!OC_Group::groupExists($grp)) $this->addGroup($grp);
117			OC_Group::addToGroup($user, $grp);
118		}
119		return true;
120    }
121
122
123    /**
124     * Modify user data
125     *
126     * @param   string $user      username
127     * @param   array  $changes   array of field/value pairs to be changed
128     * @return  bool
129     */
130    public function modifyUser($user, $changes) {
131        $return = true;
132        // password changing
133        if(isset($changes['pass'])) {
134			if(!OC_User::setPassword($user, $changes['pass'])) return false;
135        }
136        // changing user data
137        $adchanges = array();
138        if(isset($changes['name'])) {
139            if(!OC_USER::setDisplayName($user, $changes['name'])) return false;
140        }
141        if(isset($changes['grps'])) {
142			foreach($changes['grps'] as $grp){
143				if(!OC_Group::groupExists($grp)) $this->addGroup($grp);
144				OC_Group::addToGroup($user, $grp);
145			}
146        }
147        if(isset($changes['mail'])) {
148            if(!OC_Preferences::setValue($user, 'settings', 'email', $changes['mail'])) return false;
149        }
150        return true;
151    }
152
153
154        /**
155     * Remove one or more users from the owncloud database
156     *
157     * @param   array  $users   array of users to be deleted
158     * @return  int             the number of users deleted
159     */
160    public function deleteUsers($users) {
161        if(!is_array($users) || empty($users)) return 0;
162        $deleted = 0;
163        foreach($users as $user) {
164            if(OC_User::deleteUser($user)) $deleted++;
165        }
166        return $deleted;
167    }
168
169
170    /**
171     * Return db-query for filter
172     *
173     *
174     * @param array $filter
175     * @return int
176     */
177    private function getUsers($filter = array(), $start = 0, $limit = -1) {
178		$wheres = '';
179		$joins = '';
180		$selectMail = '';
181		$selectGroup = '';
182		if(!empty($filter)){
183			foreach($filter as $item => $pattern) {
184				$where = array();
185				$values = array();
186				$groupJoin = false;
187				$prefJoin = false;
188				$tmp = "%$pattern%";
189				if($item == 'user') {
190					array_push($where, '*PREFIX*users.uid LIKE ?');
191					array_push($values, $tmp);
192				}else if($item == 'name') {
193					array_push($where, '*PREFIX*users.displayname LIKE ?');
194					array_push($values, $tmp);
195				}else if($item == 'mail') {
196					array_push($where, '*PREFIX*preferences.configvalue LIKE ?');
197					array_push($values, $tmp);
198					$prefJoin = true;
199				}else if($item == 'grps') {
200					array_push($where, '*PREFIX*group_user.gid LIKE ?');
201					array_push($values, $tmp);
202					$groupJoin = true;
203				}
204			}
205			if($prefJoin){
206					array_push($where, '*PREFIX*preferences.configkey = ?');
207					array_push($values, 'email');
208					$joins .= ' JOIN *PREFIX*preferences ON *PREFIX*users.uid = *PREFIX*preferences.userid';
209					$selectMail = ', *PREFIX*preferences.configvalue AS mail ';
210			}
211			if($groupJoin){
212				$joins .= ' JOIN *PREFIX*group_user ON *PREFIX*users.uid = *PREFIX*group_user.uid';
213				$selectGroup = ', *PREFIX*group_user.gid AS `group` ';
214			}
215			if(!empty($where)) $wheres = ' WHERE '.implode(' AND ', $where);
216		}
217		$sql = "SELECT DISTINCT *PREFIX*users.uid AS user, *PREFIX*users.displayname AS name $selectMail $selectGroup FROM `*PREFIX*users`";
218		$sql .= $joins.' '.$wheres;
219		if($limit > 0) $sql .= ' LIMIT '.$start.','.$limit.' ';
220		$db = OC_DB::prepare($sql);
221		$result = $db->execute($values);
222		return $result;
223    }
224
225
226    /**
227     * Return a count of the number of user which meet $filter criteria
228     *
229     * @author  Chris Smith <chris@jalakai.co.uk>
230     *
231     * @param array $filter
232     * @return int
233     */
234    public function getUserCount($filter = array()){
235		return $this->getUsers($filter)->numRows();
236	}
237
238
239	/**
240     * Bulk retrieval of user data
241     *
242     *
243     * @param   int   $start index of first user to be returned
244     * @param   int   $limit max number of users to be returned
245     * @param   array $filter array of field/pattern pairs
246     * @return  array userinfo (refer getUserData for internal userinfo details)
247     */
248    public function retrieveUsers($start = 0, $limit = -1, $filter = array()) {
249		$result = $this->getUsers($filter, $start, $limit);
250		$ret = array();
251		$row = $result->fetchRow();
252		while($row){
253			$ret[$row['user']]['name'] =$row['name'];
254			$ret[$row['user']]['mail'] =$this->getUserMail($row['user']);
255			$ret[$row['user']]['grps'] =$this->getUserGroups($row['user']);
256			$row = $result->fetchRow();
257		}
258		return $ret;
259	}
260
261
262    /**
263     * Define a group
264     *
265     * @param   string $group
266     * @return  bool success
267     */
268    public function addGroup($group) {
269        return OC_Group::createGroup($group);
270    }
271
272
273    /**
274     * LogOff user
275     */
276    public function logOff(){
277		/* Doesn't work, i don't no why. If I run this 3 lines in an
278		 * external script, it works. Within DokuWiki not */
279        $savedSession = session_name();
280        session_write_close();
281		session_name(OC_Util::getInstanceId());
282		session_start();
283		OC_User::logout();
284        session_write_close();
285        session_name($savedSession);
286        session_start();
287	}
288
289
290	/* List all available groups
291	 *
292     * @return array|bool false or array with all groups.
293	 */
294	public function retrieveGroups($start=0,$limit=-1){
295			return OC_Group::getGroups('',$limit,$start);
296	}
297
298
299	/* List all available groups for a user
300	 *
301	 * @param string $user loginname
302     * @return array|bool false or array with all groups of this user.
303	 */
304	private function getUserGroups($user){
305		return OC_Group::getUserGroups($user);
306	}
307
308	/* Get email for a a user
309	 *
310	 * @param string $user loginname
311     * @return string|bool false or usermail
312	 */
313	private function getUserMail($user){
314		$db = OC_DB::prepare('SELECT `configvalue` FROM `*PREFIX*preferences` WHERE `userid` = ? AND `configkey` = "email"');
315		$result = $db->execute(array($user));
316		return $result->fetchOne();
317	}
318}
319