1f64dbc90SAndreas Gohr<?php 2f64dbc90SAndreas Gohr/** 3f64dbc90SAndreas Gohr * DokuWiki Plugin authpdo (Auth Component) 4f64dbc90SAndreas Gohr * 5f64dbc90SAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6f64dbc90SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 7f64dbc90SAndreas Gohr */ 8f64dbc90SAndreas Gohr 9f64dbc90SAndreas Gohr// must be run within Dokuwiki 10f64dbc90SAndreas Gohrif(!defined('DOKU_INC')) die(); 11f64dbc90SAndreas Gohr 12f64dbc90SAndreas Gohrclass auth_plugin_authpdo extends DokuWiki_Auth_Plugin { 13f64dbc90SAndreas Gohr 14f64dbc90SAndreas Gohr /** @var PDO */ 15f64dbc90SAndreas Gohr protected $pdo; 16f64dbc90SAndreas Gohr 17f64dbc90SAndreas Gohr /** 18f64dbc90SAndreas Gohr * Constructor. 19f64dbc90SAndreas Gohr */ 20f64dbc90SAndreas Gohr public function __construct() { 21f64dbc90SAndreas Gohr parent::__construct(); // for compatibility 22f64dbc90SAndreas Gohr 23f64dbc90SAndreas Gohr if(!class_exists('PDO')) { 24f64dbc90SAndreas Gohr $this->_debug('PDO extension for PHP not found.', -1, __LINE__); 25f64dbc90SAndreas Gohr $this->success = false; 26f64dbc90SAndreas Gohr return; 27f64dbc90SAndreas Gohr } 28f64dbc90SAndreas Gohr 29f64dbc90SAndreas Gohr if(!$this->getConf('dsn')) { 30f64dbc90SAndreas Gohr $this->_debug('No DSN specified', -1, __LINE__); 31f64dbc90SAndreas Gohr $this->success = false; 32f64dbc90SAndreas Gohr return; 33f64dbc90SAndreas Gohr } 34f64dbc90SAndreas Gohr 35f64dbc90SAndreas Gohr try { 36f64dbc90SAndreas Gohr $this->pdo = new PDO( 37f64dbc90SAndreas Gohr $this->getConf('dsn'), 38f64dbc90SAndreas Gohr $this->getConf('user'), 39f64dbc90SAndreas Gohr $this->getConf('pass'), 40f64dbc90SAndreas Gohr array( 4170a89417SAndreas Gohr PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, // always fetch as array 4270a89417SAndreas Gohr PDO::ATTR_EMULATE_PREPARES => true, // emulating prepares allows us to reuse param names 435de3a6a5SAndreas Gohr PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, // we want exceptions, not error codes 44f64dbc90SAndreas Gohr ) 45f64dbc90SAndreas Gohr ); 46f64dbc90SAndreas Gohr } catch(PDOException $e) { 47f64dbc90SAndreas Gohr $this->_debug($e); 48f64dbc90SAndreas Gohr $this->success = false; 49f64dbc90SAndreas Gohr return; 50f64dbc90SAndreas Gohr } 51f64dbc90SAndreas Gohr 52f64dbc90SAndreas Gohr // FIXME set capabilities accordingly 53f64dbc90SAndreas Gohr //$this->cando['addUser'] = false; // can Users be created? 54f64dbc90SAndreas Gohr //$this->cando['delUser'] = false; // can Users be deleted? 55f64dbc90SAndreas Gohr //$this->cando['modLogin'] = false; // can login names be changed? 56f64dbc90SAndreas Gohr //$this->cando['modPass'] = false; // can passwords be changed? 57f64dbc90SAndreas Gohr //$this->cando['modName'] = false; // can real names be changed? 58f64dbc90SAndreas Gohr //$this->cando['modMail'] = false; // can emails be changed? 59f64dbc90SAndreas Gohr //$this->cando['modGroups'] = false; // can groups be changed? 60f64dbc90SAndreas Gohr //$this->cando['getUsers'] = false; // can a (filtered) list of users be retrieved? 61f64dbc90SAndreas Gohr //$this->cando['getUserCount']= false; // can the number of users be retrieved? 62f64dbc90SAndreas Gohr //$this->cando['getGroups'] = false; // can a list of available groups be retrieved? 63f64dbc90SAndreas Gohr //$this->cando['external'] = false; // does the module do external auth checking? 64f64dbc90SAndreas Gohr //$this->cando['logout'] = true; // can the user logout again? (eg. not possible with HTTP auth) 65f64dbc90SAndreas Gohr 66f64dbc90SAndreas Gohr // FIXME intialize your auth system and set success to true, if successful 67f64dbc90SAndreas Gohr $this->success = true; 68f64dbc90SAndreas Gohr } 69f64dbc90SAndreas Gohr 70f64dbc90SAndreas Gohr /** 71f64dbc90SAndreas Gohr * Check user+password 72f64dbc90SAndreas Gohr * 73f64dbc90SAndreas Gohr * @param string $user the user name 74f64dbc90SAndreas Gohr * @param string $pass the clear text password 75f64dbc90SAndreas Gohr * @return bool 76f64dbc90SAndreas Gohr */ 77f64dbc90SAndreas Gohr public function checkPass($user, $pass) { 78f64dbc90SAndreas Gohr 79f64dbc90SAndreas Gohr $data = $this->_selectUser($user); 80f64dbc90SAndreas Gohr if($data == false) return false; 81f64dbc90SAndreas Gohr 82f64dbc90SAndreas Gohr if(isset($data['hash'])) { 83f64dbc90SAndreas Gohr // hashed password 84f64dbc90SAndreas Gohr $passhash = new PassHash(); 85f64dbc90SAndreas Gohr return $passhash->verify_hash($pass, $data['hash']); 86f64dbc90SAndreas Gohr } else { 87f64dbc90SAndreas Gohr // clear text password in the database O_o 88f64dbc90SAndreas Gohr return ($pass == $data['clear']); 89f64dbc90SAndreas Gohr } 90f64dbc90SAndreas Gohr } 91f64dbc90SAndreas Gohr 92f64dbc90SAndreas Gohr /** 93f64dbc90SAndreas Gohr * Return user info 94f64dbc90SAndreas Gohr * 95f64dbc90SAndreas Gohr * Returns info about the given user needs to contain 96f64dbc90SAndreas Gohr * at least these fields: 97f64dbc90SAndreas Gohr * 98f64dbc90SAndreas Gohr * name string full name of the user 99f64dbc90SAndreas Gohr * mail string email addres of the user 100f64dbc90SAndreas Gohr * grps array list of groups the user is in 101f64dbc90SAndreas Gohr * 102f64dbc90SAndreas Gohr * @param string $user the user name 103f64dbc90SAndreas Gohr * @param bool $requireGroups whether or not the returned data must include groups 104f64dbc90SAndreas Gohr * @return array containing user data or false 105f64dbc90SAndreas Gohr */ 106f64dbc90SAndreas Gohr public function getUserData($user, $requireGroups = true) { 107f64dbc90SAndreas Gohr $data = $this->_selectUser($user); 108f64dbc90SAndreas Gohr if($data == false) return false; 109f64dbc90SAndreas Gohr 11070a89417SAndreas Gohr if(isset($data['hash'])) unset($data['hash']); 11170a89417SAndreas Gohr if(isset($data['clean'])) unset($data['clean']); 112f64dbc90SAndreas Gohr 11370a89417SAndreas Gohr if($requireGroups) { 11470a89417SAndreas Gohr $data['grps'] = $this->_selectUserGroups($data); 1155de3a6a5SAndreas Gohr if($data['grps'] === false) return false; 116f64dbc90SAndreas Gohr } 117f64dbc90SAndreas Gohr 118f64dbc90SAndreas Gohr return $data; 119f64dbc90SAndreas Gohr } 120f64dbc90SAndreas Gohr 121f64dbc90SAndreas Gohr /** 122f64dbc90SAndreas Gohr * Create a new User [implement only where required/possible] 123f64dbc90SAndreas Gohr * 124f64dbc90SAndreas Gohr * Returns false if the user already exists, null when an error 125f64dbc90SAndreas Gohr * occurred and true if everything went well. 126f64dbc90SAndreas Gohr * 127f64dbc90SAndreas Gohr * The new user HAS TO be added to the default group by this 128f64dbc90SAndreas Gohr * function! 129f64dbc90SAndreas Gohr * 130f64dbc90SAndreas Gohr * Set addUser capability when implemented 131f64dbc90SAndreas Gohr * 132f64dbc90SAndreas Gohr * @param string $user 1335de3a6a5SAndreas Gohr * @param string $clear 134f64dbc90SAndreas Gohr * @param string $name 135f64dbc90SAndreas Gohr * @param string $mail 136f64dbc90SAndreas Gohr * @param null|array $grps 137f64dbc90SAndreas Gohr * @return bool|null 138f64dbc90SAndreas Gohr */ 1395de3a6a5SAndreas Gohr public function createUser($user, $clear, $name, $mail, $grps = null) { 1405de3a6a5SAndreas Gohr global $conf; 1415de3a6a5SAndreas Gohr 1425de3a6a5SAndreas Gohr if(($info = $this->getUserData($user, false)) !== false) { 1435de3a6a5SAndreas Gohr msg($this->getLang('userexists'), -1); 1445de3a6a5SAndreas Gohr return false; // user already exists 1455de3a6a5SAndreas Gohr } 1465de3a6a5SAndreas Gohr 1475de3a6a5SAndreas Gohr // prepare data 1485de3a6a5SAndreas Gohr if($grps == null) $grps = array(); 1495de3a6a5SAndreas Gohr $grps[] = $conf['defaultgroup']; 1505de3a6a5SAndreas Gohr $grps = array_unique($grps); 1515de3a6a5SAndreas Gohr $hash = auth_cryptPassword($clear); 1525de3a6a5SAndreas Gohr $userdata = compact('user', 'clear', 'hash', 'name', 'mail'); 1535de3a6a5SAndreas Gohr 1545de3a6a5SAndreas Gohr // action protected by transaction 1555de3a6a5SAndreas Gohr $this->pdo->beginTransaction(); 1565de3a6a5SAndreas Gohr { 1575de3a6a5SAndreas Gohr // insert the user 1585de3a6a5SAndreas Gohr $ok = $this->_query($this->getConf('insert-user'), $userdata); 1595de3a6a5SAndreas Gohr if($ok === false) goto FAIL; 1605de3a6a5SAndreas Gohr $userdata = $this->getUserData($user, false); 1615de3a6a5SAndreas Gohr if($userdata === false) goto FAIL; 1625de3a6a5SAndreas Gohr 1635de3a6a5SAndreas Gohr // create all groups that do not exist, the refetch the groups 1645de3a6a5SAndreas Gohr $allgroups = $this->_selectGroups(); 1655de3a6a5SAndreas Gohr foreach($grps as $group) { 1665de3a6a5SAndreas Gohr if(!isset($allgroups[$group])) { 1675de3a6a5SAndreas Gohr $ok = $this->_insertGroup($group); 1685de3a6a5SAndreas Gohr if($ok === false) goto FAIL; 1695de3a6a5SAndreas Gohr } 1705de3a6a5SAndreas Gohr } 1715de3a6a5SAndreas Gohr $allgroups = $this->_selectGroups(); 1725de3a6a5SAndreas Gohr 1735de3a6a5SAndreas Gohr // add user to the groups 1745de3a6a5SAndreas Gohr foreach($grps as $group) { 1755de3a6a5SAndreas Gohr $ok = $this->_joinGroup($userdata, $allgroups[$group]); 1765de3a6a5SAndreas Gohr if($ok === false) goto FAIL; 1775de3a6a5SAndreas Gohr } 1785de3a6a5SAndreas Gohr } 1795de3a6a5SAndreas Gohr $this->pdo->commit(); 1805de3a6a5SAndreas Gohr return true; 1815de3a6a5SAndreas Gohr 1825de3a6a5SAndreas Gohr // something went wrong, rollback 1835de3a6a5SAndreas Gohr FAIL: 1845de3a6a5SAndreas Gohr $this->pdo->rollBack(); 1855de3a6a5SAndreas Gohr $this->_debug('Transaction rolled back', 0, __LINE__); 1865de3a6a5SAndreas Gohr return null; // return error 1875de3a6a5SAndreas Gohr } 188f64dbc90SAndreas Gohr 189f64dbc90SAndreas Gohr /** 190*4fb8dfabSAndreas Gohr * Modify user data 191f64dbc90SAndreas Gohr * 192f64dbc90SAndreas Gohr * @param string $user nick of the user to be changed 193f64dbc90SAndreas Gohr * @param array $changes array of field/value pairs to be changed (password will be clear text) 194f64dbc90SAndreas Gohr * @return bool 195f64dbc90SAndreas Gohr */ 196*4fb8dfabSAndreas Gohr public function modifyUser($user, $changes) { 197*4fb8dfabSAndreas Gohr // secure everything in transaction 198*4fb8dfabSAndreas Gohr $this->pdo->beginTransaction(); 199*4fb8dfabSAndreas Gohr { 200*4fb8dfabSAndreas Gohr $olddata = $this->getUserData($user); 201*4fb8dfabSAndreas Gohr $oldgroups = $olddata['grps']; 202*4fb8dfabSAndreas Gohr unset($olddata['grps']); 203*4fb8dfabSAndreas Gohr 204*4fb8dfabSAndreas Gohr // changing the user name? 205*4fb8dfabSAndreas Gohr if(isset($changes['user'])) { 206*4fb8dfabSAndreas Gohr if($this->getUserData($changes['user'], false)) goto FAIL; 207*4fb8dfabSAndreas Gohr $params = $olddata; 208*4fb8dfabSAndreas Gohr $params['newlogin'] = $changes['user']; 209*4fb8dfabSAndreas Gohr 210*4fb8dfabSAndreas Gohr $ok = $this->_query($this->getConf('update-user-login'), $params); 211*4fb8dfabSAndreas Gohr if($ok === false) goto FAIL; 212*4fb8dfabSAndreas Gohr } 213*4fb8dfabSAndreas Gohr 214*4fb8dfabSAndreas Gohr // changing the password? 215*4fb8dfabSAndreas Gohr if(isset($changes['pass'])) { 216*4fb8dfabSAndreas Gohr $params = $olddata; 217*4fb8dfabSAndreas Gohr $params['clear'] = $changes['pass']; 218*4fb8dfabSAndreas Gohr $params['hash'] = auth_cryptPassword($changes['pass']); 219*4fb8dfabSAndreas Gohr 220*4fb8dfabSAndreas Gohr $ok = $this->_query($this->getConf('update-user-pass'), $params); 221*4fb8dfabSAndreas Gohr if($ok === false) goto FAIL; 222*4fb8dfabSAndreas Gohr } 223*4fb8dfabSAndreas Gohr 224*4fb8dfabSAndreas Gohr // changing info? 225*4fb8dfabSAndreas Gohr if(isset($changes['mail']) || isset($changes['name'])) { 226*4fb8dfabSAndreas Gohr $params = $olddata; 227*4fb8dfabSAndreas Gohr if(isset($changes['mail'])) $params['mail'] = $changes['mail']; 228*4fb8dfabSAndreas Gohr if(isset($changes['name'])) $params['name'] = $changes['name']; 229*4fb8dfabSAndreas Gohr 230*4fb8dfabSAndreas Gohr $ok = $this->_query($this->getConf('update-user-info'), $params); 231*4fb8dfabSAndreas Gohr if($ok === false) goto FAIL; 232*4fb8dfabSAndreas Gohr } 233*4fb8dfabSAndreas Gohr 234*4fb8dfabSAndreas Gohr // changing groups? 235*4fb8dfabSAndreas Gohr if(isset($changes['grps'])) { 236*4fb8dfabSAndreas Gohr $allgroups = $this->_selectGroups(); 237*4fb8dfabSAndreas Gohr 238*4fb8dfabSAndreas Gohr // remove membership for previous groups 239*4fb8dfabSAndreas Gohr foreach($oldgroups as $group) { 240*4fb8dfabSAndreas Gohr if(!in_array($group, $changes['grps'])) { 241*4fb8dfabSAndreas Gohr $ok = $this->_leaveGroup($olddata, $allgroups[$group]); 242*4fb8dfabSAndreas Gohr if($ok === false) goto FAIL; 243*4fb8dfabSAndreas Gohr } 244*4fb8dfabSAndreas Gohr } 245*4fb8dfabSAndreas Gohr 246*4fb8dfabSAndreas Gohr // create all new groups that are missing 247*4fb8dfabSAndreas Gohr $added = 0; 248*4fb8dfabSAndreas Gohr foreach($changes['grps'] as $group) { 249*4fb8dfabSAndreas Gohr if(!isset($allgroups[$group])) { 250*4fb8dfabSAndreas Gohr $ok = $this->_insertGroup($group); 251*4fb8dfabSAndreas Gohr if($ok === false) goto FAIL; 252*4fb8dfabSAndreas Gohr $added++; 253*4fb8dfabSAndreas Gohr } 254*4fb8dfabSAndreas Gohr } 255*4fb8dfabSAndreas Gohr // reload group info 256*4fb8dfabSAndreas Gohr if($added > 0) $allgroups = $this->_selectGroups(); 257*4fb8dfabSAndreas Gohr 258*4fb8dfabSAndreas Gohr // add membership for new groups 259*4fb8dfabSAndreas Gohr foreach($changes['grps'] as $group) { 260*4fb8dfabSAndreas Gohr if(!in_array($group, $oldgroups)) { 261*4fb8dfabSAndreas Gohr $ok = $this->_joinGroup($olddata, $allgroups[$group]); 262*4fb8dfabSAndreas Gohr if($ok === false) goto FAIL; 263*4fb8dfabSAndreas Gohr } 264*4fb8dfabSAndreas Gohr } 265*4fb8dfabSAndreas Gohr } 266*4fb8dfabSAndreas Gohr 267*4fb8dfabSAndreas Gohr } 268*4fb8dfabSAndreas Gohr $this->pdo->commit(); 269*4fb8dfabSAndreas Gohr return true; 270*4fb8dfabSAndreas Gohr 271*4fb8dfabSAndreas Gohr // something went wrong, rollback 272*4fb8dfabSAndreas Gohr FAIL: 273*4fb8dfabSAndreas Gohr $this->pdo->rollBack(); 274*4fb8dfabSAndreas Gohr $this->_debug('Transaction rolled back', 0, __LINE__); 275*4fb8dfabSAndreas Gohr return false; // return error 276*4fb8dfabSAndreas Gohr } 277f64dbc90SAndreas Gohr 278f64dbc90SAndreas Gohr /** 279f64dbc90SAndreas Gohr * Delete one or more users [implement only where required/possible] 280f64dbc90SAndreas Gohr * 281f64dbc90SAndreas Gohr * Set delUser capability when implemented 282f64dbc90SAndreas Gohr * 283f64dbc90SAndreas Gohr * @param array $users 284f64dbc90SAndreas Gohr * @return int number of users deleted 285f64dbc90SAndreas Gohr */ 286f64dbc90SAndreas Gohr //public function deleteUsers($users) { 287f64dbc90SAndreas Gohr // FIXME implement 288f64dbc90SAndreas Gohr // return false; 289f64dbc90SAndreas Gohr //} 290f64dbc90SAndreas Gohr 291f64dbc90SAndreas Gohr /** 292f64dbc90SAndreas Gohr * Bulk retrieval of user data [implement only where required/possible] 293f64dbc90SAndreas Gohr * 294f64dbc90SAndreas Gohr * Set getUsers capability when implemented 295f64dbc90SAndreas Gohr * 296f64dbc90SAndreas Gohr * @param int $start index of first user to be returned 297f64dbc90SAndreas Gohr * @param int $limit max number of users to be returned 298f64dbc90SAndreas Gohr * @param array $filter array of field/pattern pairs, null for no filter 299f64dbc90SAndreas Gohr * @return array list of userinfo (refer getUserData for internal userinfo details) 300f64dbc90SAndreas Gohr */ 301f64dbc90SAndreas Gohr //public function retrieveUsers($start = 0, $limit = -1, $filter = null) { 302f64dbc90SAndreas Gohr // FIXME implement 303f64dbc90SAndreas Gohr // return array(); 304f64dbc90SAndreas Gohr //} 305f64dbc90SAndreas Gohr 306f64dbc90SAndreas Gohr /** 307f64dbc90SAndreas Gohr * Return a count of the number of user which meet $filter criteria 308f64dbc90SAndreas Gohr * [should be implemented whenever retrieveUsers is implemented] 309f64dbc90SAndreas Gohr * 310f64dbc90SAndreas Gohr * Set getUserCount capability when implemented 311f64dbc90SAndreas Gohr * 312f64dbc90SAndreas Gohr * @param array $filter array of field/pattern pairs, empty array for no filter 313f64dbc90SAndreas Gohr * @return int 314f64dbc90SAndreas Gohr */ 315f64dbc90SAndreas Gohr //public function getUserCount($filter = array()) { 316f64dbc90SAndreas Gohr // FIXME implement 317f64dbc90SAndreas Gohr // return 0; 318f64dbc90SAndreas Gohr //} 319f64dbc90SAndreas Gohr 320f64dbc90SAndreas Gohr /** 321f64dbc90SAndreas Gohr * Define a group [implement only where required/possible] 322f64dbc90SAndreas Gohr * 323f64dbc90SAndreas Gohr * Set addGroup capability when implemented 324f64dbc90SAndreas Gohr * 325f64dbc90SAndreas Gohr * @param string $group 326f64dbc90SAndreas Gohr * @return bool 327f64dbc90SAndreas Gohr */ 328f64dbc90SAndreas Gohr //public function addGroup($group) { 329f64dbc90SAndreas Gohr // FIXME implement 330f64dbc90SAndreas Gohr // return false; 331f64dbc90SAndreas Gohr //} 332f64dbc90SAndreas Gohr 333f64dbc90SAndreas Gohr /** 3345de3a6a5SAndreas Gohr * Retrieve groups 335f64dbc90SAndreas Gohr * 336f64dbc90SAndreas Gohr * Set getGroups capability when implemented 337f64dbc90SAndreas Gohr * 338f64dbc90SAndreas Gohr * @param int $start 339f64dbc90SAndreas Gohr * @param int $limit 340f64dbc90SAndreas Gohr * @return array 341f64dbc90SAndreas Gohr */ 3425de3a6a5SAndreas Gohr public function retrieveGroups($start = 0, $limit = 0) { 3435de3a6a5SAndreas Gohr $groups = array_keys($this->_selectGroups()); 3445de3a6a5SAndreas Gohr if($groups === false) return array(); 345f64dbc90SAndreas Gohr 3465de3a6a5SAndreas Gohr if(!$limit) { 3475de3a6a5SAndreas Gohr return array_splice($groups, $start); 3485de3a6a5SAndreas Gohr } else { 3495de3a6a5SAndreas Gohr return array_splice($groups, $start, $limit); 350f64dbc90SAndreas Gohr } 351f64dbc90SAndreas Gohr } 352f64dbc90SAndreas Gohr 353f64dbc90SAndreas Gohr /** 354f64dbc90SAndreas Gohr * Select data of a specified user 355f64dbc90SAndreas Gohr * 3565de3a6a5SAndreas Gohr * @param string $user the user name 3575de3a6a5SAndreas Gohr * @return bool|array user data, false on error 358f64dbc90SAndreas Gohr */ 359f64dbc90SAndreas Gohr protected function _selectUser($user) { 360f64dbc90SAndreas Gohr $sql = $this->getConf('select-user'); 361f64dbc90SAndreas Gohr 3625de3a6a5SAndreas Gohr $result = $this->_query($sql, array(':user' => $user)); 36370a89417SAndreas Gohr if(!$result) return false; 364f64dbc90SAndreas Gohr 36570a89417SAndreas Gohr if(count($result) > 1) { 366f64dbc90SAndreas Gohr $this->_debug('Found more than one matching user', -1, __LINE__); 367f64dbc90SAndreas Gohr return false; 368f64dbc90SAndreas Gohr } 369f64dbc90SAndreas Gohr 370f64dbc90SAndreas Gohr $data = array_shift($result); 371f64dbc90SAndreas Gohr $dataok = true; 372f64dbc90SAndreas Gohr 373f64dbc90SAndreas Gohr if(!isset($data['user'])) { 374f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'user' attribute", -1, __LINE__); 375f64dbc90SAndreas Gohr $dataok = false; 376f64dbc90SAndreas Gohr } 377f64dbc90SAndreas Gohr if(!isset($data['hash']) && !isset($data['clear'])) { 378f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'clear' or 'hash' attribute", -1, __LINE__); 379f64dbc90SAndreas Gohr $dataok = false; 380f64dbc90SAndreas Gohr } 381f64dbc90SAndreas Gohr if(!isset($data['name'])) { 382f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'name' attribute", -1, __LINE__); 383f64dbc90SAndreas Gohr $dataok = false; 384f64dbc90SAndreas Gohr } 385f64dbc90SAndreas Gohr if(!isset($data['mail'])) { 386f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'mail' attribute", -1, __LINE__); 387f64dbc90SAndreas Gohr $dataok = false; 388f64dbc90SAndreas Gohr } 389f64dbc90SAndreas Gohr 390f64dbc90SAndreas Gohr if(!$dataok) return false; 391f64dbc90SAndreas Gohr return $data; 392f64dbc90SAndreas Gohr } 393f64dbc90SAndreas Gohr 394f64dbc90SAndreas Gohr /** 39570a89417SAndreas Gohr * Select all groups of a user 39670a89417SAndreas Gohr * 39770a89417SAndreas Gohr * @param array $userdata The userdata as returned by _selectUser() 3985de3a6a5SAndreas Gohr * @return array|bool list of group names, false on error 39970a89417SAndreas Gohr */ 40070a89417SAndreas Gohr protected function _selectUserGroups($userdata) { 40170a89417SAndreas Gohr global $conf; 40270a89417SAndreas Gohr $sql = $this->getConf('select-user-groups'); 4035de3a6a5SAndreas Gohr $result = $this->_query($sql, $userdata); 4045de3a6a5SAndreas Gohr if($result === false) return false; 40570a89417SAndreas Gohr 40670a89417SAndreas Gohr $groups = array($conf['defaultgroup']); // always add default config 4075de3a6a5SAndreas Gohr foreach($result as $row) { 4085de3a6a5SAndreas Gohr if(!isset($row['group'])) { 4095de3a6a5SAndreas Gohr $this->_debug("No 'group' field returned in select-user-groups statement"); 4105de3a6a5SAndreas Gohr return false; 4115de3a6a5SAndreas Gohr } 41270a89417SAndreas Gohr $groups[] = $row['group']; 41370a89417SAndreas Gohr } 41470a89417SAndreas Gohr 41570a89417SAndreas Gohr $groups = array_unique($groups); 41670a89417SAndreas Gohr sort($groups); 41770a89417SAndreas Gohr return $groups; 41870a89417SAndreas Gohr } 41970a89417SAndreas Gohr 42070a89417SAndreas Gohr /** 4215de3a6a5SAndreas Gohr * Select all available groups 4225de3a6a5SAndreas Gohr * 4235de3a6a5SAndreas Gohr * @todo this should be cached 4245de3a6a5SAndreas Gohr * @return array|bool list of all available groups and their properties 4255de3a6a5SAndreas Gohr */ 4265de3a6a5SAndreas Gohr protected function _selectGroups() { 4275de3a6a5SAndreas Gohr $sql = $this->getConf('select-groups'); 4285de3a6a5SAndreas Gohr $result = $this->_query($sql); 4295de3a6a5SAndreas Gohr if($result === false) return false; 4305de3a6a5SAndreas Gohr 4315de3a6a5SAndreas Gohr $groups = array(); 4325de3a6a5SAndreas Gohr foreach($result as $row) { 4335de3a6a5SAndreas Gohr if(!isset($row['group'])) { 4345de3a6a5SAndreas Gohr $this->_debug("No 'group' field returned from select-groups statement", -1, __LINE__); 4355de3a6a5SAndreas Gohr return false; 4365de3a6a5SAndreas Gohr } 4375de3a6a5SAndreas Gohr 4385de3a6a5SAndreas Gohr // relayout result with group name as key 4395de3a6a5SAndreas Gohr $group = $row['group']; 4405de3a6a5SAndreas Gohr $groups[$group] = $row; 4415de3a6a5SAndreas Gohr } 4425de3a6a5SAndreas Gohr 4435de3a6a5SAndreas Gohr ksort($groups); 4445de3a6a5SAndreas Gohr return $groups; 4455de3a6a5SAndreas Gohr } 4465de3a6a5SAndreas Gohr 4475de3a6a5SAndreas Gohr /** 4485de3a6a5SAndreas Gohr * Create a new group with the given name 4495de3a6a5SAndreas Gohr * 4505de3a6a5SAndreas Gohr * @param string $group 4515de3a6a5SAndreas Gohr * @return bool 4525de3a6a5SAndreas Gohr */ 4535de3a6a5SAndreas Gohr protected function _insertGroup($group) { 4545de3a6a5SAndreas Gohr $sql = $this->getConf('insert-group'); 4555de3a6a5SAndreas Gohr 4565de3a6a5SAndreas Gohr $result = $this->_query($sql, array(':group' => $group)); 4575de3a6a5SAndreas Gohr if($result === false) return false; 4585de3a6a5SAndreas Gohr return true; 4595de3a6a5SAndreas Gohr } 4605de3a6a5SAndreas Gohr 4615de3a6a5SAndreas Gohr /** 462*4fb8dfabSAndreas Gohr * Adds the user to the group 4635de3a6a5SAndreas Gohr * 4645de3a6a5SAndreas Gohr * @param array $userdata all the user data 4655de3a6a5SAndreas Gohr * @param array $groupdata all the group data 4665de3a6a5SAndreas Gohr * @return bool 4675de3a6a5SAndreas Gohr */ 4685de3a6a5SAndreas Gohr protected function _joinGroup($userdata, $groupdata) { 4695de3a6a5SAndreas Gohr $data = array_merge($userdata, $groupdata); 4705de3a6a5SAndreas Gohr $sql = $this->getConf('join-group'); 4715de3a6a5SAndreas Gohr $result = $this->_query($sql, $data); 4725de3a6a5SAndreas Gohr if($result === false) return false; 4735de3a6a5SAndreas Gohr return true; 4745de3a6a5SAndreas Gohr } 4755de3a6a5SAndreas Gohr 4765de3a6a5SAndreas Gohr /** 477*4fb8dfabSAndreas Gohr * Removes the user from the group 478*4fb8dfabSAndreas Gohr * 479*4fb8dfabSAndreas Gohr * @param array $userdata all the user data 480*4fb8dfabSAndreas Gohr * @param array $groupdata all the group data 481*4fb8dfabSAndreas Gohr * @return bool 482*4fb8dfabSAndreas Gohr */ 483*4fb8dfabSAndreas Gohr protected function _leaveGroup($userdata, $groupdata) { 484*4fb8dfabSAndreas Gohr $data = array_merge($userdata, $groupdata); 485*4fb8dfabSAndreas Gohr $sql = $this->getConf('leave-group'); 486*4fb8dfabSAndreas Gohr $result = $this->_query($sql, $data); 487*4fb8dfabSAndreas Gohr if($result === false) return false; 488*4fb8dfabSAndreas Gohr return true; 489*4fb8dfabSAndreas Gohr } 490*4fb8dfabSAndreas Gohr 491*4fb8dfabSAndreas Gohr /** 49270a89417SAndreas Gohr * Executes a query 49370a89417SAndreas Gohr * 49470a89417SAndreas Gohr * @param string $sql The SQL statement to execute 49570a89417SAndreas Gohr * @param array $arguments Named parameters to be used in the statement 4965de3a6a5SAndreas Gohr * @return array|bool The result as associative array, false on error 49770a89417SAndreas Gohr */ 4985de3a6a5SAndreas Gohr protected function _query($sql, $arguments = array()) { 4995de3a6a5SAndreas Gohr if(empty($sql)) { 5005de3a6a5SAndreas Gohr $this->_debug('No SQL query given', -1, __LINE__); 5015de3a6a5SAndreas Gohr return false; 5025de3a6a5SAndreas Gohr } 5035de3a6a5SAndreas Gohr 50470a89417SAndreas Gohr // prepare parameters - we only use those that exist in the SQL 50570a89417SAndreas Gohr $params = array(); 50670a89417SAndreas Gohr foreach($arguments as $key => $value) { 50770a89417SAndreas Gohr if(is_array($value)) continue; 50870a89417SAndreas Gohr if(is_object($value)) continue; 50970a89417SAndreas Gohr if($key[0] != ':') $key = ":$key"; // prefix with colon if needed 51070a89417SAndreas Gohr if(strpos($sql, $key) !== false) $params[$key] = $value; 51170a89417SAndreas Gohr } 51270a89417SAndreas Gohr 51370a89417SAndreas Gohr // execute 51470a89417SAndreas Gohr $sth = $this->pdo->prepare($sql); 5155de3a6a5SAndreas Gohr try { 51670a89417SAndreas Gohr $sth->execute($params); 51770a89417SAndreas Gohr $result = $sth->fetchAll(); 5185de3a6a5SAndreas Gohr } catch(Exception $e) { 519*4fb8dfabSAndreas Gohr // report the caller's line 520*4fb8dfabSAndreas Gohr $trace = debug_backtrace(); 521*4fb8dfabSAndreas Gohr $line = $trace[0]['line']; 5225de3a6a5SAndreas Gohr $dsql = $this->_debugSQL($sql, $params, !defined('DOKU_UNITTEST')); 523*4fb8dfabSAndreas Gohr $this->_debug($e, -1, $line); 524*4fb8dfabSAndreas Gohr $this->_debug("SQL: <pre>$dsql</pre>", -1, $line); 52570a89417SAndreas Gohr $result = false; 5265de3a6a5SAndreas Gohr } finally { 52770a89417SAndreas Gohr $sth->closeCursor(); 52870a89417SAndreas Gohr $sth = null; 52970a89417SAndreas Gohr } 53070a89417SAndreas Gohr 5315de3a6a5SAndreas Gohr return $result; 5325de3a6a5SAndreas Gohr } 53370a89417SAndreas Gohr 53470a89417SAndreas Gohr /** 535f64dbc90SAndreas Gohr * Wrapper around msg() but outputs only when debug is enabled 536f64dbc90SAndreas Gohr * 537f64dbc90SAndreas Gohr * @param string|Exception $message 538f64dbc90SAndreas Gohr * @param int $err 539f64dbc90SAndreas Gohr * @param int $line 540f64dbc90SAndreas Gohr */ 541f64dbc90SAndreas Gohr protected function _debug($message, $err = 0, $line = 0) { 542f64dbc90SAndreas Gohr if(!$this->getConf('debug')) return; 543f64dbc90SAndreas Gohr if(is_a($message, 'Exception')) { 544f64dbc90SAndreas Gohr $err = -1; 545f64dbc90SAndreas Gohr $msg = $message->getMessage(); 546*4fb8dfabSAndreas Gohr if(!$line) $line = $message->getLine(); 547f64dbc90SAndreas Gohr } else { 548f64dbc90SAndreas Gohr $msg = $message; 549f64dbc90SAndreas Gohr } 550f64dbc90SAndreas Gohr 551f64dbc90SAndreas Gohr if(defined('DOKU_UNITTEST')) { 552f64dbc90SAndreas Gohr printf("\n%s, %s:%d\n", $msg, __FILE__, $line); 553f64dbc90SAndreas Gohr } else { 554f64dbc90SAndreas Gohr msg('authpdo: ' . $msg, $err, $line, __FILE__); 555f64dbc90SAndreas Gohr } 556f64dbc90SAndreas Gohr } 5575de3a6a5SAndreas Gohr 5585de3a6a5SAndreas Gohr /** 5595de3a6a5SAndreas Gohr * Check if the given config strings are set 5605de3a6a5SAndreas Gohr * 5615de3a6a5SAndreas Gohr * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 5625de3a6a5SAndreas Gohr * 5635de3a6a5SAndreas Gohr * @param string[] $keys 5645de3a6a5SAndreas Gohr * @return bool 5655de3a6a5SAndreas Gohr */ 5665de3a6a5SAndreas Gohr protected function _chkcnf($keys) { 5675de3a6a5SAndreas Gohr foreach($keys as $key) { 5685de3a6a5SAndreas Gohr if(!$this->getConf($key)) return false; 5695de3a6a5SAndreas Gohr } 5705de3a6a5SAndreas Gohr 5715de3a6a5SAndreas Gohr return true; 5725de3a6a5SAndreas Gohr } 5735de3a6a5SAndreas Gohr 5745de3a6a5SAndreas Gohr /** 5755de3a6a5SAndreas Gohr * create an approximation of the SQL string with parameters replaced 5765de3a6a5SAndreas Gohr * 5775de3a6a5SAndreas Gohr * @param string $sql 5785de3a6a5SAndreas Gohr * @param array $params 5795de3a6a5SAndreas Gohr * @param bool $htmlescape Should the result be escaped for output in HTML? 5805de3a6a5SAndreas Gohr * @return string 5815de3a6a5SAndreas Gohr */ 5825de3a6a5SAndreas Gohr protected function _debugSQL($sql, $params, $htmlescape = true) { 5835de3a6a5SAndreas Gohr foreach($params as $key => $val) { 5845de3a6a5SAndreas Gohr if(is_int($val)) { 5855de3a6a5SAndreas Gohr $val = $this->pdo->quote($val, PDO::PARAM_INT); 5865de3a6a5SAndreas Gohr } elseif(is_bool($val)) { 5875de3a6a5SAndreas Gohr $val = $this->pdo->quote($val, PDO::PARAM_BOOL); 5885de3a6a5SAndreas Gohr } elseif(is_null($val)) { 5895de3a6a5SAndreas Gohr $val = 'NULL'; 5905de3a6a5SAndreas Gohr } else { 5915de3a6a5SAndreas Gohr $val = $this->pdo->quote($val); 5925de3a6a5SAndreas Gohr } 5935de3a6a5SAndreas Gohr $sql = str_replace($key, $val, $sql); 5945de3a6a5SAndreas Gohr } 5955de3a6a5SAndreas Gohr if($htmlescape) $sql = hsc($sql); 5965de3a6a5SAndreas Gohr return $sql; 5975de3a6a5SAndreas Gohr } 598f64dbc90SAndreas Gohr} 599f64dbc90SAndreas Gohr 600f64dbc90SAndreas Gohr// vim:ts=4:sw=4:et: 601