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 43*5de3a6a5SAndreas 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 * May be ommited if trustExternal is used. 74f64dbc90SAndreas Gohr * 75f64dbc90SAndreas Gohr * @param string $user the user name 76f64dbc90SAndreas Gohr * @param string $pass the clear text password 77f64dbc90SAndreas Gohr * @return bool 78f64dbc90SAndreas Gohr */ 79f64dbc90SAndreas Gohr public function checkPass($user, $pass) { 80f64dbc90SAndreas Gohr 81f64dbc90SAndreas Gohr $data = $this->_selectUser($user); 82f64dbc90SAndreas Gohr if($data == false) return false; 83f64dbc90SAndreas Gohr 84f64dbc90SAndreas Gohr if(isset($data['hash'])) { 85f64dbc90SAndreas Gohr // hashed password 86f64dbc90SAndreas Gohr $passhash = new PassHash(); 87f64dbc90SAndreas Gohr return $passhash->verify_hash($pass, $data['hash']); 88f64dbc90SAndreas Gohr } else { 89f64dbc90SAndreas Gohr // clear text password in the database O_o 90f64dbc90SAndreas Gohr return ($pass == $data['clear']); 91f64dbc90SAndreas Gohr } 92f64dbc90SAndreas Gohr } 93f64dbc90SAndreas Gohr 94f64dbc90SAndreas Gohr /** 95f64dbc90SAndreas Gohr * Return user info 96f64dbc90SAndreas Gohr * 97f64dbc90SAndreas Gohr * Returns info about the given user needs to contain 98f64dbc90SAndreas Gohr * at least these fields: 99f64dbc90SAndreas Gohr * 100f64dbc90SAndreas Gohr * name string full name of the user 101f64dbc90SAndreas Gohr * mail string email addres of the user 102f64dbc90SAndreas Gohr * grps array list of groups the user is in 103f64dbc90SAndreas Gohr * 104f64dbc90SAndreas Gohr * @param string $user the user name 105f64dbc90SAndreas Gohr * @param bool $requireGroups whether or not the returned data must include groups 106f64dbc90SAndreas Gohr * @return array containing user data or false 107f64dbc90SAndreas Gohr */ 108f64dbc90SAndreas Gohr public function getUserData($user, $requireGroups = true) { 109f64dbc90SAndreas Gohr $data = $this->_selectUser($user); 110f64dbc90SAndreas Gohr if($data == false) return false; 111f64dbc90SAndreas Gohr 11270a89417SAndreas Gohr if(isset($data['hash'])) unset($data['hash']); 11370a89417SAndreas Gohr if(isset($data['clean'])) unset($data['clean']); 114f64dbc90SAndreas Gohr 11570a89417SAndreas Gohr if($requireGroups) { 11670a89417SAndreas Gohr $data['grps'] = $this->_selectUserGroups($data); 117*5de3a6a5SAndreas Gohr if($data['grps'] === false) return false; 118f64dbc90SAndreas Gohr } 119f64dbc90SAndreas Gohr 120f64dbc90SAndreas Gohr return $data; 121f64dbc90SAndreas Gohr } 122f64dbc90SAndreas Gohr 123f64dbc90SAndreas Gohr /** 124f64dbc90SAndreas Gohr * Create a new User [implement only where required/possible] 125f64dbc90SAndreas Gohr * 126f64dbc90SAndreas Gohr * Returns false if the user already exists, null when an error 127f64dbc90SAndreas Gohr * occurred and true if everything went well. 128f64dbc90SAndreas Gohr * 129f64dbc90SAndreas Gohr * The new user HAS TO be added to the default group by this 130f64dbc90SAndreas Gohr * function! 131f64dbc90SAndreas Gohr * 132f64dbc90SAndreas Gohr * Set addUser capability when implemented 133f64dbc90SAndreas Gohr * 134f64dbc90SAndreas Gohr * @param string $user 135*5de3a6a5SAndreas Gohr * @param string $clear 136f64dbc90SAndreas Gohr * @param string $name 137f64dbc90SAndreas Gohr * @param string $mail 138f64dbc90SAndreas Gohr * @param null|array $grps 139f64dbc90SAndreas Gohr * @return bool|null 140f64dbc90SAndreas Gohr */ 141*5de3a6a5SAndreas Gohr public function createUser($user, $clear, $name, $mail, $grps = null) { 142*5de3a6a5SAndreas Gohr global $conf; 143*5de3a6a5SAndreas Gohr 144*5de3a6a5SAndreas Gohr if(($info = $this->getUserData($user, false)) !== false) { 145*5de3a6a5SAndreas Gohr msg($this->getLang('userexists'), -1); 146*5de3a6a5SAndreas Gohr return false; // user already exists 147*5de3a6a5SAndreas Gohr } 148*5de3a6a5SAndreas Gohr 149*5de3a6a5SAndreas Gohr // prepare data 150*5de3a6a5SAndreas Gohr if($grps == null) $grps = array(); 151*5de3a6a5SAndreas Gohr $grps[] = $conf['defaultgroup']; 152*5de3a6a5SAndreas Gohr $grps = array_unique($grps); 153*5de3a6a5SAndreas Gohr $hash = auth_cryptPassword($clear); 154*5de3a6a5SAndreas Gohr $userdata = compact('user', 'clear', 'hash', 'name', 'mail'); 155*5de3a6a5SAndreas Gohr 156*5de3a6a5SAndreas Gohr // action protected by transaction 157*5de3a6a5SAndreas Gohr $this->pdo->beginTransaction(); 158*5de3a6a5SAndreas Gohr { 159*5de3a6a5SAndreas Gohr // insert the user 160*5de3a6a5SAndreas Gohr $ok = $this->_query($this->getConf('insert-user'), $userdata); 161*5de3a6a5SAndreas Gohr if($ok === false) goto FAIL; 162*5de3a6a5SAndreas Gohr $userdata = $this->getUserData($user, false); 163*5de3a6a5SAndreas Gohr if($userdata === false) goto FAIL; 164*5de3a6a5SAndreas Gohr 165*5de3a6a5SAndreas Gohr // create all groups that do not exist, the refetch the groups 166*5de3a6a5SAndreas Gohr $allgroups = $this->_selectGroups(); 167*5de3a6a5SAndreas Gohr foreach($grps as $group) { 168*5de3a6a5SAndreas Gohr if(!isset($allgroups[$group])) { 169*5de3a6a5SAndreas Gohr $ok = $this->_insertGroup($group); 170*5de3a6a5SAndreas Gohr if($ok === false) goto FAIL; 171*5de3a6a5SAndreas Gohr } 172*5de3a6a5SAndreas Gohr } 173*5de3a6a5SAndreas Gohr $allgroups = $this->_selectGroups(); 174*5de3a6a5SAndreas Gohr 175*5de3a6a5SAndreas Gohr // add user to the groups 176*5de3a6a5SAndreas Gohr foreach($grps as $group) { 177*5de3a6a5SAndreas Gohr $ok = $this->_joinGroup($userdata, $allgroups[$group]); 178*5de3a6a5SAndreas Gohr if($ok === false) goto FAIL; 179*5de3a6a5SAndreas Gohr } 180*5de3a6a5SAndreas Gohr } 181*5de3a6a5SAndreas Gohr $this->pdo->commit(); 182*5de3a6a5SAndreas Gohr return true; 183*5de3a6a5SAndreas Gohr 184*5de3a6a5SAndreas Gohr // something went wrong, rollback 185*5de3a6a5SAndreas Gohr FAIL: 186*5de3a6a5SAndreas Gohr $this->pdo->rollBack(); 187*5de3a6a5SAndreas Gohr $this->_debug('Transaction rolled back', 0, __LINE__); 188*5de3a6a5SAndreas Gohr return null; // return error 189*5de3a6a5SAndreas Gohr } 190f64dbc90SAndreas Gohr 191f64dbc90SAndreas Gohr /** 192f64dbc90SAndreas Gohr * Modify user data [implement only where required/possible] 193f64dbc90SAndreas Gohr * 194f64dbc90SAndreas Gohr * Set the mod* capabilities according to the implemented features 195f64dbc90SAndreas Gohr * 196f64dbc90SAndreas Gohr * @param string $user nick of the user to be changed 197f64dbc90SAndreas Gohr * @param array $changes array of field/value pairs to be changed (password will be clear text) 198f64dbc90SAndreas Gohr * @return bool 199f64dbc90SAndreas Gohr */ 200f64dbc90SAndreas Gohr //public function modifyUser($user, $changes) { 201f64dbc90SAndreas Gohr // FIXME implement 202f64dbc90SAndreas Gohr // return false; 203f64dbc90SAndreas Gohr //} 204f64dbc90SAndreas Gohr 205f64dbc90SAndreas Gohr /** 206f64dbc90SAndreas Gohr * Delete one or more users [implement only where required/possible] 207f64dbc90SAndreas Gohr * 208f64dbc90SAndreas Gohr * Set delUser capability when implemented 209f64dbc90SAndreas Gohr * 210f64dbc90SAndreas Gohr * @param array $users 211f64dbc90SAndreas Gohr * @return int number of users deleted 212f64dbc90SAndreas Gohr */ 213f64dbc90SAndreas Gohr //public function deleteUsers($users) { 214f64dbc90SAndreas Gohr // FIXME implement 215f64dbc90SAndreas Gohr // return false; 216f64dbc90SAndreas Gohr //} 217f64dbc90SAndreas Gohr 218f64dbc90SAndreas Gohr /** 219f64dbc90SAndreas Gohr * Bulk retrieval of user data [implement only where required/possible] 220f64dbc90SAndreas Gohr * 221f64dbc90SAndreas Gohr * Set getUsers capability when implemented 222f64dbc90SAndreas Gohr * 223f64dbc90SAndreas Gohr * @param int $start index of first user to be returned 224f64dbc90SAndreas Gohr * @param int $limit max number of users to be returned 225f64dbc90SAndreas Gohr * @param array $filter array of field/pattern pairs, null for no filter 226f64dbc90SAndreas Gohr * @return array list of userinfo (refer getUserData for internal userinfo details) 227f64dbc90SAndreas Gohr */ 228f64dbc90SAndreas Gohr //public function retrieveUsers($start = 0, $limit = -1, $filter = null) { 229f64dbc90SAndreas Gohr // FIXME implement 230f64dbc90SAndreas Gohr // return array(); 231f64dbc90SAndreas Gohr //} 232f64dbc90SAndreas Gohr 233f64dbc90SAndreas Gohr /** 234f64dbc90SAndreas Gohr * Return a count of the number of user which meet $filter criteria 235f64dbc90SAndreas Gohr * [should be implemented whenever retrieveUsers is implemented] 236f64dbc90SAndreas Gohr * 237f64dbc90SAndreas Gohr * Set getUserCount capability when implemented 238f64dbc90SAndreas Gohr * 239f64dbc90SAndreas Gohr * @param array $filter array of field/pattern pairs, empty array for no filter 240f64dbc90SAndreas Gohr * @return int 241f64dbc90SAndreas Gohr */ 242f64dbc90SAndreas Gohr //public function getUserCount($filter = array()) { 243f64dbc90SAndreas Gohr // FIXME implement 244f64dbc90SAndreas Gohr // return 0; 245f64dbc90SAndreas Gohr //} 246f64dbc90SAndreas Gohr 247f64dbc90SAndreas Gohr /** 248f64dbc90SAndreas Gohr * Define a group [implement only where required/possible] 249f64dbc90SAndreas Gohr * 250f64dbc90SAndreas Gohr * Set addGroup capability when implemented 251f64dbc90SAndreas Gohr * 252f64dbc90SAndreas Gohr * @param string $group 253f64dbc90SAndreas Gohr * @return bool 254f64dbc90SAndreas Gohr */ 255f64dbc90SAndreas Gohr //public function addGroup($group) { 256f64dbc90SAndreas Gohr // FIXME implement 257f64dbc90SAndreas Gohr // return false; 258f64dbc90SAndreas Gohr //} 259f64dbc90SAndreas Gohr 260f64dbc90SAndreas Gohr /** 261*5de3a6a5SAndreas Gohr * Retrieve groups 262f64dbc90SAndreas Gohr * 263f64dbc90SAndreas Gohr * Set getGroups capability when implemented 264f64dbc90SAndreas Gohr * 265f64dbc90SAndreas Gohr * @param int $start 266f64dbc90SAndreas Gohr * @param int $limit 267f64dbc90SAndreas Gohr * @return array 268f64dbc90SAndreas Gohr */ 269*5de3a6a5SAndreas Gohr public function retrieveGroups($start = 0, $limit = 0) { 270*5de3a6a5SAndreas Gohr $groups = array_keys($this->_selectGroups()); 271*5de3a6a5SAndreas Gohr if($groups === false) return array(); 272f64dbc90SAndreas Gohr 273*5de3a6a5SAndreas Gohr if(!$limit) { 274*5de3a6a5SAndreas Gohr return array_splice($groups, $start); 275*5de3a6a5SAndreas Gohr } else { 276*5de3a6a5SAndreas Gohr return array_splice($groups, $start, $limit); 277f64dbc90SAndreas Gohr } 278f64dbc90SAndreas Gohr } 279f64dbc90SAndreas Gohr 280f64dbc90SAndreas Gohr /** 281f64dbc90SAndreas Gohr * Select data of a specified user 282f64dbc90SAndreas Gohr * 283*5de3a6a5SAndreas Gohr * @param string $user the user name 284*5de3a6a5SAndreas Gohr * @return bool|array user data, false on error 285f64dbc90SAndreas Gohr */ 286f64dbc90SAndreas Gohr protected function _selectUser($user) { 287f64dbc90SAndreas Gohr $sql = $this->getConf('select-user'); 288f64dbc90SAndreas Gohr 289*5de3a6a5SAndreas Gohr $result = $this->_query($sql, array(':user' => $user)); 29070a89417SAndreas Gohr if(!$result) return false; 291f64dbc90SAndreas Gohr 29270a89417SAndreas Gohr if(count($result) > 1) { 293f64dbc90SAndreas Gohr $this->_debug('Found more than one matching user', -1, __LINE__); 294f64dbc90SAndreas Gohr return false; 295f64dbc90SAndreas Gohr } 296f64dbc90SAndreas Gohr 297f64dbc90SAndreas Gohr $data = array_shift($result); 298f64dbc90SAndreas Gohr $dataok = true; 299f64dbc90SAndreas Gohr 300f64dbc90SAndreas Gohr if(!isset($data['user'])) { 301f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'user' attribute", -1, __LINE__); 302f64dbc90SAndreas Gohr $dataok = false; 303f64dbc90SAndreas Gohr } 304f64dbc90SAndreas Gohr if(!isset($data['hash']) && !isset($data['clear'])) { 305f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'clear' or 'hash' attribute", -1, __LINE__); 306f64dbc90SAndreas Gohr $dataok = false; 307f64dbc90SAndreas Gohr } 308f64dbc90SAndreas Gohr if(!isset($data['name'])) { 309f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'name' attribute", -1, __LINE__); 310f64dbc90SAndreas Gohr $dataok = false; 311f64dbc90SAndreas Gohr } 312f64dbc90SAndreas Gohr if(!isset($data['mail'])) { 313f64dbc90SAndreas Gohr $this->_debug("Statement did not return 'mail' attribute", -1, __LINE__); 314f64dbc90SAndreas Gohr $dataok = false; 315f64dbc90SAndreas Gohr } 316f64dbc90SAndreas Gohr 317f64dbc90SAndreas Gohr if(!$dataok) return false; 318f64dbc90SAndreas Gohr return $data; 319f64dbc90SAndreas Gohr } 320f64dbc90SAndreas Gohr 321f64dbc90SAndreas Gohr /** 32270a89417SAndreas Gohr * Select all groups of a user 32370a89417SAndreas Gohr * 32470a89417SAndreas Gohr * @param array $userdata The userdata as returned by _selectUser() 325*5de3a6a5SAndreas Gohr * @return array|bool list of group names, false on error 32670a89417SAndreas Gohr */ 32770a89417SAndreas Gohr protected function _selectUserGroups($userdata) { 32870a89417SAndreas Gohr global $conf; 32970a89417SAndreas Gohr $sql = $this->getConf('select-user-groups'); 330*5de3a6a5SAndreas Gohr $result = $this->_query($sql, $userdata); 331*5de3a6a5SAndreas Gohr if($result === false) return false; 33270a89417SAndreas Gohr 33370a89417SAndreas Gohr $groups = array($conf['defaultgroup']); // always add default config 334*5de3a6a5SAndreas Gohr foreach($result as $row) { 335*5de3a6a5SAndreas Gohr if(!isset($row['group'])) { 336*5de3a6a5SAndreas Gohr $this->_debug("No 'group' field returned in select-user-groups statement"); 337*5de3a6a5SAndreas Gohr return false; 338*5de3a6a5SAndreas Gohr } 33970a89417SAndreas Gohr $groups[] = $row['group']; 34070a89417SAndreas Gohr } 34170a89417SAndreas Gohr 34270a89417SAndreas Gohr $groups = array_unique($groups); 34370a89417SAndreas Gohr sort($groups); 34470a89417SAndreas Gohr return $groups; 34570a89417SAndreas Gohr } 34670a89417SAndreas Gohr 34770a89417SAndreas Gohr /** 348*5de3a6a5SAndreas Gohr * Select all available groups 349*5de3a6a5SAndreas Gohr * 350*5de3a6a5SAndreas Gohr * @todo this should be cached 351*5de3a6a5SAndreas Gohr * @return array|bool list of all available groups and their properties 352*5de3a6a5SAndreas Gohr */ 353*5de3a6a5SAndreas Gohr protected function _selectGroups() { 354*5de3a6a5SAndreas Gohr $sql = $this->getConf('select-groups'); 355*5de3a6a5SAndreas Gohr $result = $this->_query($sql); 356*5de3a6a5SAndreas Gohr if($result === false) return false; 357*5de3a6a5SAndreas Gohr 358*5de3a6a5SAndreas Gohr $groups = array(); 359*5de3a6a5SAndreas Gohr foreach($result as $row) { 360*5de3a6a5SAndreas Gohr if(!isset($row['group'])) { 361*5de3a6a5SAndreas Gohr $this->_debug("No 'group' field returned from select-groups statement", -1, __LINE__); 362*5de3a6a5SAndreas Gohr return false; 363*5de3a6a5SAndreas Gohr } 364*5de3a6a5SAndreas Gohr 365*5de3a6a5SAndreas Gohr // relayout result with group name as key 366*5de3a6a5SAndreas Gohr $group = $row['group']; 367*5de3a6a5SAndreas Gohr $groups[$group] = $row; 368*5de3a6a5SAndreas Gohr } 369*5de3a6a5SAndreas Gohr 370*5de3a6a5SAndreas Gohr ksort($groups); 371*5de3a6a5SAndreas Gohr return $groups; 372*5de3a6a5SAndreas Gohr } 373*5de3a6a5SAndreas Gohr 374*5de3a6a5SAndreas Gohr /** 375*5de3a6a5SAndreas Gohr * Create a new group with the given name 376*5de3a6a5SAndreas Gohr * 377*5de3a6a5SAndreas Gohr * @param string $group 378*5de3a6a5SAndreas Gohr * @return bool 379*5de3a6a5SAndreas Gohr */ 380*5de3a6a5SAndreas Gohr protected function _insertGroup($group) { 381*5de3a6a5SAndreas Gohr $sql = $this->getConf('insert-group'); 382*5de3a6a5SAndreas Gohr 383*5de3a6a5SAndreas Gohr $result = $this->_query($sql, array(':group' => $group)); 384*5de3a6a5SAndreas Gohr if($result === false) return false; 385*5de3a6a5SAndreas Gohr return true; 386*5de3a6a5SAndreas Gohr } 387*5de3a6a5SAndreas Gohr 388*5de3a6a5SAndreas Gohr /** 389*5de3a6a5SAndreas Gohr * Enters the user to the group 390*5de3a6a5SAndreas Gohr * 391*5de3a6a5SAndreas Gohr * @param array $userdata all the user data 392*5de3a6a5SAndreas Gohr * @param array $groupdata all the group data 393*5de3a6a5SAndreas Gohr * @return bool 394*5de3a6a5SAndreas Gohr */ 395*5de3a6a5SAndreas Gohr protected function _joinGroup($userdata, $groupdata) { 396*5de3a6a5SAndreas Gohr $data = array_merge($userdata, $groupdata); 397*5de3a6a5SAndreas Gohr $sql = $this->getConf('join-group'); 398*5de3a6a5SAndreas Gohr $result = $this->_query($sql, $data); 399*5de3a6a5SAndreas Gohr if($result === false) return false; 400*5de3a6a5SAndreas Gohr return true; 401*5de3a6a5SAndreas Gohr } 402*5de3a6a5SAndreas Gohr 403*5de3a6a5SAndreas Gohr /** 40470a89417SAndreas Gohr * Executes a query 40570a89417SAndreas Gohr * 40670a89417SAndreas Gohr * @param string $sql The SQL statement to execute 40770a89417SAndreas Gohr * @param array $arguments Named parameters to be used in the statement 408*5de3a6a5SAndreas Gohr * @return array|bool The result as associative array, false on error 40970a89417SAndreas Gohr */ 410*5de3a6a5SAndreas Gohr protected function _query($sql, $arguments = array()) { 411*5de3a6a5SAndreas Gohr if(empty($sql)) { 412*5de3a6a5SAndreas Gohr $this->_debug('No SQL query given', -1, __LINE__); 413*5de3a6a5SAndreas Gohr return false; 414*5de3a6a5SAndreas Gohr } 415*5de3a6a5SAndreas Gohr 41670a89417SAndreas Gohr // prepare parameters - we only use those that exist in the SQL 41770a89417SAndreas Gohr $params = array(); 41870a89417SAndreas Gohr foreach($arguments as $key => $value) { 41970a89417SAndreas Gohr if(is_array($value)) continue; 42070a89417SAndreas Gohr if(is_object($value)) continue; 42170a89417SAndreas Gohr if($key[0] != ':') $key = ":$key"; // prefix with colon if needed 42270a89417SAndreas Gohr if(strpos($sql, $key) !== false) $params[$key] = $value; 42370a89417SAndreas Gohr } 42470a89417SAndreas Gohr 42570a89417SAndreas Gohr // execute 42670a89417SAndreas Gohr $sth = $this->pdo->prepare($sql); 427*5de3a6a5SAndreas Gohr try { 42870a89417SAndreas Gohr $sth->execute($params); 42970a89417SAndreas Gohr $result = $sth->fetchAll(); 430*5de3a6a5SAndreas Gohr } catch(Exception $e) { 431*5de3a6a5SAndreas Gohr $dsql = $this->_debugSQL($sql, $params, !defined('DOKU_UNITTEST')); 432*5de3a6a5SAndreas Gohr $this->_debug($e); 433*5de3a6a5SAndreas Gohr $this->_debug("SQL: <pre>$dsql</pre>", -1, $e->getLine()); 43470a89417SAndreas Gohr $result = false; 435*5de3a6a5SAndreas Gohr } finally { 43670a89417SAndreas Gohr $sth->closeCursor(); 43770a89417SAndreas Gohr $sth = null; 43870a89417SAndreas Gohr } 43970a89417SAndreas Gohr 440*5de3a6a5SAndreas Gohr return $result; 441*5de3a6a5SAndreas Gohr } 44270a89417SAndreas Gohr 44370a89417SAndreas Gohr /** 444f64dbc90SAndreas Gohr * Wrapper around msg() but outputs only when debug is enabled 445f64dbc90SAndreas Gohr * 446f64dbc90SAndreas Gohr * @param string|Exception $message 447f64dbc90SAndreas Gohr * @param int $err 448f64dbc90SAndreas Gohr * @param int $line 449f64dbc90SAndreas Gohr */ 450f64dbc90SAndreas Gohr protected function _debug($message, $err = 0, $line = 0) { 451f64dbc90SAndreas Gohr if(!$this->getConf('debug')) return; 452f64dbc90SAndreas Gohr if(is_a($message, 'Exception')) { 453f64dbc90SAndreas Gohr $err = -1; 454f64dbc90SAndreas Gohr $line = $message->getLine(); 455f64dbc90SAndreas Gohr $msg = $message->getMessage(); 456f64dbc90SAndreas Gohr } else { 457f64dbc90SAndreas Gohr $msg = $message; 458f64dbc90SAndreas Gohr } 459f64dbc90SAndreas Gohr 460f64dbc90SAndreas Gohr if(defined('DOKU_UNITTEST')) { 461f64dbc90SAndreas Gohr printf("\n%s, %s:%d\n", $msg, __FILE__, $line); 462f64dbc90SAndreas Gohr } else { 463f64dbc90SAndreas Gohr msg('authpdo: ' . $msg, $err, $line, __FILE__); 464f64dbc90SAndreas Gohr } 465f64dbc90SAndreas Gohr } 466*5de3a6a5SAndreas Gohr 467*5de3a6a5SAndreas Gohr /** 468*5de3a6a5SAndreas Gohr * Check if the given config strings are set 469*5de3a6a5SAndreas Gohr * 470*5de3a6a5SAndreas Gohr * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net> 471*5de3a6a5SAndreas Gohr * 472*5de3a6a5SAndreas Gohr * @param string[] $keys 473*5de3a6a5SAndreas Gohr * @return bool 474*5de3a6a5SAndreas Gohr */ 475*5de3a6a5SAndreas Gohr protected function _chkcnf($keys) { 476*5de3a6a5SAndreas Gohr foreach($keys as $key) { 477*5de3a6a5SAndreas Gohr if(!$this->getConf($key)) return false; 478*5de3a6a5SAndreas Gohr } 479*5de3a6a5SAndreas Gohr 480*5de3a6a5SAndreas Gohr return true; 481*5de3a6a5SAndreas Gohr } 482*5de3a6a5SAndreas Gohr 483*5de3a6a5SAndreas Gohr /** 484*5de3a6a5SAndreas Gohr * create an approximation of the SQL string with parameters replaced 485*5de3a6a5SAndreas Gohr * 486*5de3a6a5SAndreas Gohr * @param string $sql 487*5de3a6a5SAndreas Gohr * @param array $params 488*5de3a6a5SAndreas Gohr * @param bool $htmlescape Should the result be escaped for output in HTML? 489*5de3a6a5SAndreas Gohr * @return string 490*5de3a6a5SAndreas Gohr */ 491*5de3a6a5SAndreas Gohr protected function _debugSQL($sql, $params, $htmlescape=true) { 492*5de3a6a5SAndreas Gohr foreach($params as $key => $val) { 493*5de3a6a5SAndreas Gohr if(is_int($val)) { 494*5de3a6a5SAndreas Gohr $val = $this->pdo->quote($val, PDO::PARAM_INT); 495*5de3a6a5SAndreas Gohr } elseif(is_bool($val)) { 496*5de3a6a5SAndreas Gohr $val = $this->pdo->quote($val, PDO::PARAM_BOOL); 497*5de3a6a5SAndreas Gohr } elseif(is_null($val)) { 498*5de3a6a5SAndreas Gohr $val = 'NULL'; 499*5de3a6a5SAndreas Gohr } else { 500*5de3a6a5SAndreas Gohr $val = $this->pdo->quote($val); 501*5de3a6a5SAndreas Gohr } 502*5de3a6a5SAndreas Gohr $sql = str_replace($key, $val, $sql); 503*5de3a6a5SAndreas Gohr } 504*5de3a6a5SAndreas Gohr if($htmlescape) $sql = hsc($sql); 505*5de3a6a5SAndreas Gohr return $sql; 506*5de3a6a5SAndreas Gohr } 507f64dbc90SAndreas Gohr} 508f64dbc90SAndreas Gohr 509f64dbc90SAndreas Gohr// vim:ts=4:sw=4:et: 510