Blame view

sources/lib/private/user/database.php 7.63 KB
03e52840d   Kload   Init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
  <?php
  
  /**
   * ownCloud
   *
   * @author Frank Karlitschek
   * @copyright 2012 Frank Karlitschek frank@owncloud.org
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
   * License as published by the Free Software Foundation; either
   * version 3 of the License, or any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
   *
   * You should have received a copy of the GNU Affero General Public
   * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
   *
   */
  /*
   *
   * The following SQL statement is just a help for developers and will not be
   * executed!
   *
   * CREATE TABLE `users` (
   *   `uid` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
   *   `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
   *   PRIMARY KEY (`uid`)
   * ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
   *
   */
  
  require_once 'phpass/PasswordHash.php';
  
  /**
   * Class for user management in a SQL Database (e.g. MySQL, SQLite)
   */
  class OC_User_Database extends OC_User_Backend {
  	/**
  	 * @var PasswordHash
  	 */
6d9380f96   Cédric Dupont   Update sources OC...
45
46
47
  	private static $hasher = null;
  
  	private $cache = array();
03e52840d   Kload   Init
48
49
  
  	private function getHasher() {
a293d369c   Kload   Update sources to...
50
  		if (!self::$hasher) {
31b7f2792   Kload   Upgrade to ownclo...
51
  			//we don't want to use DES based crypt(), since it doesn't return a hash with a recognisable prefix
a293d369c   Kload   Update sources to...
52
53
  			$forcePortable = (CRYPT_BLOWFISH != 1);
  			self::$hasher = new PasswordHash(8, $forcePortable);
03e52840d   Kload   Init
54
55
  		}
  		return self::$hasher;
03e52840d   Kload   Init
56
57
58
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
59
60
61
62
  	 * Create a new user
  	 * @param string $uid The username of the user to create
  	 * @param string $password The password of the new user
  	 * @return bool
03e52840d   Kload   Init
63
64
65
66
  	 *
  	 * Creates a new user. Basic checking of username is done in OC_User
  	 * itself, not in its subclasses.
  	 */
a293d369c   Kload   Update sources to...
67
  	public function createUser($uid, $password) {
6d9380f96   Cédric Dupont   Update sources OC...
68
  		if (!$this->userExists($uid)) {
a293d369c   Kload   Update sources to...
69
70
71
72
  			$hasher = $this->getHasher();
  			$hash = $hasher->HashPassword($password . OC_Config::getValue('passwordsalt', ''));
  			$query = OC_DB::prepare('INSERT INTO `*PREFIX*users` ( `uid`, `password` ) VALUES( ?, ? )');
  			$result = $query->execute(array($uid, $hash));
03e52840d   Kload   Init
73
74
75
  
  			return $result ? true : false;
  		}
6d9380f96   Cédric Dupont   Update sources OC...
76
77
  
  		return false;
03e52840d   Kload   Init
78
79
80
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
81
82
83
  	 * delete a user
  	 * @param string $uid The username of the user to delete
  	 * @return bool
03e52840d   Kload   Init
84
85
86
  	 *
  	 * Deletes a user
  	 */
a293d369c   Kload   Update sources to...
87
  	public function deleteUser($uid) {
03e52840d   Kload   Init
88
  		// Delete user-group-relation
a293d369c   Kload   Update sources to...
89
  		$query = OC_DB::prepare('DELETE FROM `*PREFIX*users` WHERE `uid` = ?');
6d9380f96   Cédric Dupont   Update sources OC...
90
91
92
93
94
95
96
  		$result = $query->execute(array($uid));
  
  		if (isset($this->cache[$uid])) {
  			unset($this->cache[$uid]);
  		}
  
  		return $result ? true : false;
03e52840d   Kload   Init
97
98
99
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
100
101
102
103
  	 * Set password
  	 * @param string $uid The username
  	 * @param string $password The new password
  	 * @return bool
03e52840d   Kload   Init
104
105
106
  	 *
  	 * Change the password of a user
  	 */
a293d369c   Kload   Update sources to...
107
108
109
110
111
  	public function setPassword($uid, $password) {
  		if ($this->userExists($uid)) {
  			$hasher = $this->getHasher();
  			$hash = $hasher->HashPassword($password . OC_Config::getValue('passwordsalt', ''));
  			$query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `password` = ? WHERE `uid` = ?');
6d9380f96   Cédric Dupont   Update sources OC...
112
  			$result = $query->execute(array($hash, $uid));
03e52840d   Kload   Init
113

6d9380f96   Cédric Dupont   Update sources OC...
114
  			return $result ? true : false;
03e52840d   Kload   Init
115
  		}
6d9380f96   Cédric Dupont   Update sources OC...
116
117
  
  		return false;
03e52840d   Kload   Init
118
119
120
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
121
122
123
124
  	 * Set display name
  	 * @param string $uid The username
  	 * @param string $displayName The new display name
  	 * @return bool
03e52840d   Kload   Init
125
126
127
  	 *
  	 * Change the display name of a user
  	 */
a293d369c   Kload   Update sources to...
128
129
  	public function setDisplayName($uid, $displayName) {
  		if ($this->userExists($uid)) {
6d9380f96   Cédric Dupont   Update sources OC...
130
  			$query = OC_DB::prepare('UPDATE `*PREFIX*users` SET `displayname` = ? WHERE LOWER(`uid`) = LOWER(?)');
a293d369c   Kload   Update sources to...
131
  			$query->execute(array($displayName, $uid));
6d9380f96   Cédric Dupont   Update sources OC...
132
  			$this->cache[$uid]['displayname'] = $displayName;
03e52840d   Kload   Init
133
  			return true;
03e52840d   Kload   Init
134
  		}
6d9380f96   Cédric Dupont   Update sources OC...
135
136
  
  		return false;
03e52840d   Kload   Init
137
138
139
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
140
141
  	 * get display name of the user
  	 * @param string $uid user ID of the user
a293d369c   Kload   Update sources to...
142
  	 * @return string display name
03e52840d   Kload   Init
143
144
  	 */
  	public function getDisplayName($uid) {
6d9380f96   Cédric Dupont   Update sources OC...
145
146
  		$this->loadUser($uid);
  		return empty($this->cache[$uid]['displayname']) ? $uid : $this->cache[$uid]['displayname'];
03e52840d   Kload   Init
147
148
149
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
150
151
  	 * Get a list of all display names
  	 * @return array an array of  all displayNames (value) and the correspondig uids (key)
03e52840d   Kload   Init
152
153
154
155
156
157
  	 *
  	 * Get a list of all display names and user ids.
  	 */
  	public function getDisplayNames($search = '', $limit = null, $offset = null) {
  		$displayNames = array();
  		$query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users`'
a293d369c   Kload   Update sources to...
158
159
  			. ' WHERE LOWER(`displayname`) LIKE LOWER(?) OR '
  			. 'LOWER(`uid`) LIKE LOWER(?)', $limit, $offset);
6d9380f96   Cédric Dupont   Update sources OC...
160
  		$result = $query->execute(array('%' . $search . '%', '%' . $search . '%'));
03e52840d   Kload   Init
161
162
163
164
  		$users = array();
  		while ($row = $result->fetchRow()) {
  			$displayNames[$row['uid']] = $row['displayname'];
  		}
03e52840d   Kload   Init
165
166
167
168
  		return $displayNames;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
169
170
171
172
  	 * Check if the password is correct
  	 * @param string $uid The username
  	 * @param string $password The password
  	 * @return string
03e52840d   Kload   Init
173
174
175
176
  	 *
  	 * Check if the password is correct without logging in the user
  	 * returns the user id or false
  	 */
a293d369c   Kload   Update sources to...
177
178
179
  	public function checkPassword($uid, $password) {
  		$query = OC_DB::prepare('SELECT `uid`, `password` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)');
  		$result = $query->execute(array($uid));
03e52840d   Kload   Init
180

a293d369c   Kload   Update sources to...
181
182
183
  		$row = $result->fetchRow();
  		if ($row) {
  			$storedHash = $row['password'];
6d9380f96   Cédric Dupont   Update sources OC...
184
  			if ($storedHash[0] === '$') { //the new phpass based hashing
a293d369c   Kload   Update sources to...
185
186
  				$hasher = $this->getHasher();
  				if ($hasher->CheckPassword($password . OC_Config::getValue('passwordsalt', ''), $storedHash)) {
03e52840d   Kload   Init
187
  					return $row['uid'];
03e52840d   Kload   Init
188
  				}
6d9380f96   Cédric Dupont   Update sources OC...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  
  			//old sha1 based hashing
  			} elseif (sha1($password) === $storedHash) {
  				//upgrade to new hashing
  				$this->setPassword($row['uid'], $password);
  				return $row['uid'];
  			}
  		}
  
  		return false;
  	}
  
  	/**
  	 * Load an user in the cache
  	 * @param string $uid the username
  	 * @return boolean
  	 */
  	private function loadUser($uid) {
  		if (empty($this->cache[$uid])) {
  			$query = OC_DB::prepare('SELECT `uid`, `displayname` FROM `*PREFIX*users` WHERE LOWER(`uid`) = LOWER(?)');
  			$result = $query->execute(array($uid));
  
  			if (OC_DB::isError($result)) {
  				OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR);
  				return false;
  			}
  
  			while ($row = $result->fetchRow()) {
  				$this->cache[$uid]['uid'] = $row['uid'];
  				$this->cache[$uid]['displayname'] = $row['displayname'];
03e52840d   Kload   Init
219
  			}
03e52840d   Kload   Init
220
  		}
6d9380f96   Cédric Dupont   Update sources OC...
221
222
  
  		return true;
03e52840d   Kload   Init
223
224
225
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
226
227
  	 * Get a list of all users
  	 * @return array an array of all uids
03e52840d   Kload   Init
228
229
230
231
232
  	 *
  	 * Get a list of all users.
  	 */
  	public function getUsers($search = '', $limit = null, $offset = null) {
  		$query = OC_DB::prepare('SELECT `uid` FROM `*PREFIX*users` WHERE LOWER(`uid`) LIKE LOWER(?)', $limit, $offset);
6d9380f96   Cédric Dupont   Update sources OC...
233
  		$result = $query->execute(array('%' . $search . '%'));
03e52840d   Kload   Init
234
235
236
237
238
239
240
241
  		$users = array();
  		while ($row = $result->fetchRow()) {
  			$users[] = $row['uid'];
  		}
  		return $users;
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
242
  	 * check if a user exists
03e52840d   Kload   Init
243
244
245
246
  	 * @param string $uid the username
  	 * @return boolean
  	 */
  	public function userExists($uid) {
6d9380f96   Cédric Dupont   Update sources OC...
247
248
  		$this->loadUser($uid);
  		return !empty($this->cache[$uid]);
03e52840d   Kload   Init
249
250
251
  	}
  
  	/**
6d9380f96   Cédric Dupont   Update sources OC...
252
  	 * get the user's home directory
a293d369c   Kload   Update sources to...
253
  	 * @param string $uid the username
6d9380f96   Cédric Dupont   Update sources OC...
254
  	 * @return string|false
a293d369c   Kload   Update sources to...
255
  	 */
03e52840d   Kload   Init
256
  	public function getHome($uid) {
a293d369c   Kload   Update sources to...
257
258
  		if ($this->userExists($uid)) {
  			return OC_Config::getValue("datadirectory", OC::$SERVERROOT . "/data") . '/' . $uid;
03e52840d   Kload   Init
259
  		}
6d9380f96   Cédric Dupont   Update sources OC...
260
261
  
  		return false;
03e52840d   Kload   Init
262
263
264
265
266
267
268
269
  	}
  
  	/**
  	 * @return bool
  	 */
  	public function hasUserListings() {
  		return true;
  	}
a293d369c   Kload   Update sources to...
270
271
272
  	/**
  	 * counts the users in the database
  	 *
6d9380f96   Cédric Dupont   Update sources OC...
273
  	 * @return int|bool
a293d369c   Kload   Update sources to...
274
275
276
277
278
279
280
281
282
283
  	 */
  	public function countUsers() {
  		$query = OC_DB::prepare('SELECT COUNT(*) FROM `*PREFIX*users`');
  		$result = $query->execute();
  		if (OC_DB::isError($result)) {
  			OC_Log::write('core', OC_DB::getErrorMessage($result), OC_Log::ERROR);
  			return false;
  		}
  		return $result->fetchOne();
  	}
03e52840d   Kload   Init
284
  }