source: documentation/trunk/packages/dokuwiki-2011-05-25a/inc/auth/pgsql.class.php@ 25027

Last change on this file since 25027 was 25027, checked in by jmt12, 12 years ago

Adding the packages directory, and within it a configured version of dokuwiki all ready to run

File size: 13.8 KB
Line 
1<?php
2/**
3 * PgSQL authentication backend
4 *
5 * This class inherits much functionality from the MySQL class
6 * and just reimplements the Postgres specific parts.
7 *
8 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
9 * @author Andreas Gohr <[email protected]>
10 * @author Chris Smith <[email protected]>
11 * @author Matthias Grimm <[email protected]>
12*/
13
14require_once(DOKU_INC.'inc/auth/mysql.class.php');
15
16class auth_pgsql extends auth_mysql {
17
18 /**
19 * Constructor
20 *
21 * checks if the pgsql interface is available, otherwise it will
22 * set the variable $success of the basis class to false
23 *
24 * @author Matthias Grimm <[email protected]>
25 * @author Andreas Gohr <[email protected]>
26 */
27 function auth_pgsql() {
28 global $conf;
29 $this->cnf = $conf['auth']['pgsql'];
30 if(!$this->cnf['port']) $this->cnf['port'] = 5432;
31
32 if (method_exists($this, 'auth_basic'))
33 parent::auth_basic();
34
35 if(!function_exists('pg_connect')) {
36 if ($this->cnf['debug'])
37 msg("PgSQL err: PHP Postgres extension not found.",-1);
38 $this->success = false;
39 return;
40 }
41
42 $this->defaultgroup = $conf['defaultgroup'];
43
44 // set capabilities based upon config strings set
45 if (empty($this->cnf['user']) ||
46 empty($this->cnf['password']) || empty($this->cnf['database'])){
47 if ($this->cnf['debug'])
48 msg("PgSQL err: insufficient configuration.",-1,__LINE__,__FILE__);
49 $this->success = false;
50 return;
51 }
52
53 $this->cando['addUser'] = $this->_chkcnf(array('getUserInfo',
54 'getGroups',
55 'addUser',
56 'getUserID',
57 'getGroupID',
58 'addGroup',
59 'addUserGroup'));
60 $this->cando['delUser'] = $this->_chkcnf(array('getUserID',
61 'delUser',
62 'delUserRefs'));
63 $this->cando['modLogin'] = $this->_chkcnf(array('getUserID',
64 'updateUser',
65 'UpdateTarget'));
66 $this->cando['modPass'] = $this->cando['modLogin'];
67 $this->cando['modName'] = $this->cando['modLogin'];
68 $this->cando['modMail'] = $this->cando['modLogin'];
69 $this->cando['modGroups'] = $this->_chkcnf(array('getUserID',
70 'getGroups',
71 'getGroupID',
72 'addGroup',
73 'addUserGroup',
74 'delGroup',
75 'getGroupID',
76 'delUserGroup'));
77 /* getGroups is not yet supported
78 $this->cando['getGroups'] = $this->_chkcnf(array('getGroups',
79 'getGroupID')); */
80 $this->cando['getUsers'] = $this->_chkcnf(array('getUsers',
81 'getUserInfo',
82 'getGroups'));
83 $this->cando['getUserCount'] = $this->_chkcnf(array('getUsers'));
84 }
85
86 /**
87 * Check if the given config strings are set
88 *
89 * @author Matthias Grimm <[email protected]>
90 * @return bool
91 */
92 function _chkcnf($keys, $wop=false){
93 foreach ($keys as $key){
94 if (empty($this->cnf[$key])) return false;
95 }
96 return true;
97 }
98
99 // @inherit function checkPass($user,$pass)
100 // @inherit function getUserData($user)
101 // @inherit function createUser($user,$pwd,$name,$mail,$grps=null)
102 // @inherit function modifyUser($user, $changes)
103 // @inherit function deleteUsers($users)
104
105
106 /**
107 * [public function]
108 *
109 * Counts users which meet certain $filter criteria.
110 *
111 * @param array $filter filter criteria in item/pattern pairs
112 * @return count of found users.
113 *
114 * @author Matthias Grimm <[email protected]>
115 */
116 function getUserCount($filter=array()) {
117 $rc = 0;
118
119 if($this->_openDB()) {
120 $sql = $this->_createSQLFilter($this->cnf['getUsers'], $filter);
121
122 // no equivalent of SQL_CALC_FOUND_ROWS in pgsql?
123 if (($result = $this->_queryDB($sql))){
124 $rc = count($result);
125 }
126 $this->_closeDB();
127 }
128 return $rc;
129 }
130
131 /**
132 * Bulk retrieval of user data. [public function]
133 *
134 * @param first index of first user to be returned
135 * @param limit max number of users to be returned
136 * @param filter array of field/pattern pairs
137 * @return array of userinfo (refer getUserData for internal userinfo details)
138 *
139 * @author Matthias Grimm <[email protected]>
140 */
141 function retrieveUsers($first=0,$limit=10,$filter=array()) {
142 $out = array();
143
144 if($this->_openDB()) {
145 $this->_lockTables("READ");
146 $sql = $this->_createSQLFilter($this->cnf['getUsers'], $filter);
147 $sql .= " ".$this->cnf['SortOrder']." LIMIT $limit OFFSET $first";
148 $result = $this->_queryDB($sql);
149
150 foreach ($result as $user)
151 if (($info = $this->_getUserInfo($user['user'])))
152 $out[$user['user']] = $info;
153
154 $this->_unlockTables();
155 $this->_closeDB();
156 }
157 return $out;
158 }
159
160 // @inherit function joinGroup($user, $group)
161 // @inherit function leaveGroup($user, $group) {
162
163 /**
164 * Adds a user to a group.
165 *
166 * If $force is set to '1' non existing groups would be created.
167 *
168 * The database connection must already be established. Otherwise
169 * this function does nothing and returns 'false'.
170 *
171 * @param $user user to add to a group
172 * @param $group name of the group
173 * @param $force '1' create missing groups
174 * @return bool 'true' on success, 'false' on error
175 *
176 * @author Matthias Grimm <[email protected]>
177 * @author Andreas Gohr <[email protected]>
178 */
179 function _addUserToGroup($user, $group, $force=0) {
180 $newgroup = 0;
181
182 if (($this->dbcon) && ($user)) {
183 $gid = $this->_getGroupID($group);
184 if (!$gid) {
185 if ($force) { // create missing groups
186 $sql = str_replace('%{group}',addslashes($group),$this->cnf['addGroup']);
187 $this->_modifyDB($sql);
188 //group should now exists try again to fetch it
189 $gid = $this->_getGroupID($group);
190 $newgroup = 1; // group newly created
191 }
192 }
193 if (!$gid) return false; // group didn't exist and can't be created
194
195 $sql = $this->cnf['addUserGroup'];
196 if(strpos($sql,'%{uid}') !== false){
197 $uid = $this->_getUserID($user);
198 $sql = str_replace('%{uid}', addslashes($uid), $sql);
199 }
200 $sql = str_replace('%{user}', addslashes($user),$sql);
201 $sql = str_replace('%{gid}', addslashes($gid),$sql);
202 $sql = str_replace('%{group}',addslashes($group),$sql);
203 if ($this->_modifyDB($sql) !== false) return true;
204
205 if ($newgroup) { // remove previously created group on error
206 $sql = str_replace('%{gid}', addslashes($gid),$this->cnf['delGroup']);
207 $sql = str_replace('%{group}',addslashes($group),$sql);
208 $this->_modifyDB($sql);
209 }
210 }
211 return false;
212 }
213
214 // @inherit function _delUserFromGroup($user $group)
215 // @inherit function _getGroups($user)
216 // @inherit function _getUserID($user)
217
218 /**
219 * Adds a new User to the database.
220 *
221 * The database connection must already be established
222 * for this function to work. Otherwise it will return
223 * 'false'.
224 *
225 * @param $user login of the user
226 * @param $pwd encrypted password
227 * @param $name full name of the user
228 * @param $mail email address
229 * @param $grps array of groups the user should become member of
230 * @return bool
231 *
232 * @author Andreas Gohr <[email protected]>
233 * @author Chris Smith <[email protected]>
234 * @author Matthias Grimm <[email protected]>
235 */
236 function _addUser($user,$pwd,$name,$mail,$grps){
237 if($this->dbcon && is_array($grps)) {
238 $sql = str_replace('%{user}', addslashes($user),$this->cnf['addUser']);
239 $sql = str_replace('%{pass}', addslashes($pwd),$sql);
240 $sql = str_replace('%{name}', addslashes($name),$sql);
241 $sql = str_replace('%{email}',addslashes($mail),$sql);
242 if($this->_modifyDB($sql)){
243 $uid = $this->_getUserID($user);
244 }else{
245 return false;
246 }
247
248 if ($uid) {
249 foreach($grps as $group) {
250 $gid = $this->_addUserToGroup($user, $group, 1);
251 if ($gid === false) break;
252 }
253
254 if ($gid) return true;
255 else {
256 /* remove the new user and all group relations if a group can't
257 * be assigned. Newly created groups will remain in the database
258 * and won't be removed. This might create orphaned groups but
259 * is not a big issue so we ignore this problem here.
260 */
261 $this->_delUser($user);
262 if ($this->cnf['debug'])
263 msg("PgSQL err: Adding user '$user' to group '$group' failed.",-1,__LINE__,__FILE__);
264 }
265 }
266 }
267 return false;
268 }
269
270 // @inherit function _delUser($user)
271 // @inherit function _getUserInfo($user)
272 // @inherit function _updateUserInfo($changes, $uid)
273 // @inherit function _getGroupID($group)
274
275 /**
276 * Opens a connection to a database and saves the handle for further
277 * usage in the object. The successful call to this functions is
278 * essential for most functions in this object.
279 *
280 * @return bool
281 *
282 * @author Matthias Grimm <[email protected]>
283 */
284 function _openDB() {
285 if (!$this->dbcon) {
286 $dsn = $this->cnf['server'] ? 'host='.$this->cnf['server'] : '';
287 $dsn .= ' port='.$this->cnf['port'];
288 $dsn .= ' dbname='.$this->cnf['database'];
289 $dsn .= ' user='.$this->cnf['user'];
290 $dsn .= ' password='.$this->cnf['password'];
291
292 $con = @pg_connect($dsn);
293 if ($con) {
294 $this->dbcon = $con;
295 return true; // connection and database successfully opened
296 } else if ($this->cnf['debug']){
297 msg ("PgSQL err: Connection to {$this->cnf['user']}@{$this->cnf['server']} not possible.",
298 -1,__LINE__,__FILE__);
299 }
300 return false; // connection failed
301 }
302 return true; // connection already open
303 }
304
305 /**
306 * Closes a database connection.
307 *
308 * @author Matthias Grimm <[email protected]>
309 */
310 function _closeDB() {
311 if ($this->dbcon) {
312 pg_close ($this->dbcon);
313 $this->dbcon = 0;
314 }
315 }
316
317 /**
318 * Sends a SQL query to the database and transforms the result into
319 * an associative array.
320 *
321 * This function is only able to handle queries that returns a
322 * table such as SELECT.
323 *
324 * @param $query SQL string that contains the query
325 * @return array with the result table
326 *
327 * @author Matthias Grimm <[email protected]>
328 */
329 function _queryDB($query) {
330 if ($this->dbcon) {
331 $result = @pg_query($this->dbcon,$query);
332 if ($result) {
333 while (($t = pg_fetch_assoc($result)) !== false)
334 $resultarray[]=$t;
335 pg_free_result ($result);
336 return $resultarray;
337 }elseif ($this->cnf['debug'])
338 msg('PgSQL err: '.pg_last_error($this->dbcon),-1,__LINE__,__FILE__);
339 }
340 return false;
341 }
342
343 /**
344 * Executes an update or insert query. This differs from the
345 * MySQL one because it does NOT return the last insertID
346 *
347 * @author Andreas Gohr
348 */
349 function _modifyDB($query) {
350 if ($this->dbcon) {
351 $result = @pg_query($this->dbcon,$query);
352 if ($result) {
353 pg_free_result ($result);
354 return true;
355 }
356 if ($this->cnf['debug']){
357 msg('PgSQL err: '.pg_last_error($this->dbcon),-1,__LINE__,__FILE__);
358 }
359 }
360 return false;
361 }
362
363 /**
364 * Start a transaction
365 *
366 * @param $mode could be 'READ' or 'WRITE'
367 * @author Matthias Grimm <[email protected]>
368 */
369 function _lockTables($mode) {
370 if ($this->dbcon) {
371 $this->_modifyDB('BEGIN');
372 return true;
373 }
374 return false;
375 }
376
377 /**
378 * Commit a transaction
379 *
380 * @author Matthias Grimm <[email protected]>
381 */
382 function _unlockTables() {
383 if ($this->dbcon) {
384 $this->_modifyDB('COMMIT');
385 return true;
386 }
387 return false;
388 }
389
390 // @inherit function _createSQLFilter($sql, $filter)
391
392
393 /**
394 * Escape a string for insertion into the database
395 *
396 * @author Andreas Gohr <[email protected]>
397 * @param string $string The string to escape
398 * @param boolean $like Escape wildcard chars as well?
399 */
400 function _escape($string,$like=false){
401 $string = pg_escape_string($string);
402 if($like){
403 $string = addcslashes($string,'%_');
404 }
405 return $string;
406 }
407
408}
409
410//Setup VIM: ex: et ts=2 :
Note: See TracBrowser for help on using the repository browser.