| [0] | 1 | <?php | 
|---|
|  | 2 | # -- BEGIN LICENSE BLOCK --------------------------------------- | 
|---|
|  | 3 | # | 
|---|
|  | 4 | # This file is part of Dotclear 2. | 
|---|
|  | 5 | # | 
|---|
| [1179] | 6 | # Copyright (c) 2003-2013 Olivier Meunier & Association Dotclear | 
|---|
| [0] | 7 | # Licensed under the GPL version 2.0 license. | 
|---|
|  | 8 | # See LICENSE file or | 
|---|
|  | 9 | # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html | 
|---|
|  | 10 | # | 
|---|
|  | 11 | # -- END LICENSE BLOCK ----------------------------------------- | 
|---|
|  | 12 | if (!defined('DC_RC_PATH')) { return; } | 
|---|
|  | 13 |  | 
|---|
|  | 14 | /** | 
|---|
| [333] | 15 | * @ingroup DC_CORE | 
|---|
|  | 16 | * @nosubgrouping | 
|---|
|  | 17 | * @brief Authentication and user credentials management | 
|---|
| [2566] | 18 | * | 
|---|
| [333] | 19 | * dcAuth is a class used to handle everything related to user authentication | 
|---|
|  | 20 | * and credentials. Object is provided by dcCore $auth property. | 
|---|
| [0] | 21 | */ | 
|---|
|  | 22 | class dcAuth | 
|---|
|  | 23 | { | 
|---|
| [333] | 24 | /** @var dcCore dcCore instance */ | 
|---|
|  | 25 | protected $core; | 
|---|
|  | 26 | /** @var connection Database connection object */ | 
|---|
|  | 27 | protected $con; | 
|---|
| [2566] | 28 |  | 
|---|
| [333] | 29 | /** @var string User table name */ | 
|---|
|  | 30 | protected $user_table; | 
|---|
|  | 31 | /** @var string Perm table name */ | 
|---|
|  | 32 | protected $perm_table; | 
|---|
| [2566] | 33 |  | 
|---|
| [333] | 34 | /** @var string Current user ID */ | 
|---|
|  | 35 | protected $user_id; | 
|---|
|  | 36 | /** @var array Array with user information */ | 
|---|
|  | 37 | protected $user_info = array(); | 
|---|
|  | 38 | /** @var array Array with user options */ | 
|---|
|  | 39 | protected $user_options = array(); | 
|---|
|  | 40 | /** @var boolean User must change his password after login */ | 
|---|
|  | 41 | protected $user_change_pwd; | 
|---|
|  | 42 | /** @var boolean User is super admin */ | 
|---|
|  | 43 | protected $user_admin; | 
|---|
|  | 44 | /** @var array Permissions for each blog */ | 
|---|
|  | 45 | protected $permissions = array(); | 
|---|
|  | 46 | /** @var boolean User can change its password */ | 
|---|
|  | 47 | protected $allow_pass_change = true; | 
|---|
|  | 48 | /** @var array List of blogs on which the user has permissions */ | 
|---|
|  | 49 | protected $blogs = array(); | 
|---|
|  | 50 | /** @var integer Count of user blogs */ | 
|---|
|  | 51 | public $blog_count = null; | 
|---|
| [2566] | 52 |  | 
|---|
| [333] | 53 | /** @var array Permission types */ | 
|---|
|  | 54 | protected $perm_types; | 
|---|
| [2566] | 55 |  | 
|---|
| [333] | 56 | /** @var dcPrefs dcPrefs object */ | 
|---|
|  | 57 | public $user_prefs; | 
|---|
| [2566] | 58 |  | 
|---|
| [0] | 59 | /** | 
|---|
| [333] | 60 | * Class constructor. Takes dcCore object as single argument. | 
|---|
| [2566] | 61 | * | 
|---|
| [333] | 62 | * @param dcCore     $core          dcCore object | 
|---|
| [0] | 63 | */ | 
|---|
|  | 64 | public function __construct($core) | 
|---|
|  | 65 | { | 
|---|
|  | 66 | $this->core =& $core; | 
|---|
|  | 67 | $this->con =& $core->con; | 
|---|
|  | 68 | $this->blog_table = $core->prefix.'blog'; | 
|---|
|  | 69 | $this->user_table = $core->prefix.'user'; | 
|---|
|  | 70 | $this->perm_table = $core->prefix.'permissions'; | 
|---|
| [2566] | 71 |  | 
|---|
| [0] | 72 | $this->perm_types = array( | 
|---|
|  | 73 | 'admin' => __('administrator'), | 
|---|
|  | 74 | 'usage' => __('manage their own entries and comments'), | 
|---|
|  | 75 | 'publish' => __('publish entries and comments'), | 
|---|
|  | 76 | 'delete' => __('delete entries and comments'), | 
|---|
|  | 77 | 'contentadmin' => __('manage all entries and comments'), | 
|---|
|  | 78 | 'categories' => __('manage categories'), | 
|---|
|  | 79 | 'media' => __('manage their own media items'), | 
|---|
|  | 80 | 'media_admin' => __('manage all media items') | 
|---|
|  | 81 | ); | 
|---|
|  | 82 | } | 
|---|
| [2566] | 83 |  | 
|---|
| [0] | 84 | /// @name Credentials and user permissions | 
|---|
|  | 85 | //@{ | 
|---|
|  | 86 | /** | 
|---|
| [333] | 87 | * Checks if user exists and can log in. <var>$pwd</var> argument is optionnal | 
|---|
|  | 88 | * while you may need to check user without password. This method will create | 
|---|
|  | 89 | * credentials and populate all needed object properties. | 
|---|
| [2566] | 90 | * | 
|---|
| [333] | 91 | * @param string     $user_id       User ID | 
|---|
|  | 92 | * @param string     $pwd           User password | 
|---|
|  | 93 | * @param string     $user_key      User key check | 
|---|
|  | 94 | * @param boolean    $check_blog    checks if user is associated to a blog or not. | 
|---|
|  | 95 | * @return boolean | 
|---|
| [0] | 96 | */ | 
|---|
| [312] | 97 | public function checkUser($user_id, $pwd=null, $user_key=null, $check_blog=true) | 
|---|
| [0] | 98 | { | 
|---|
|  | 99 | # Check user and password | 
|---|
|  | 100 | $strReq = 'SELECT user_id, user_super, user_pwd, user_change_pwd, '. | 
|---|
|  | 101 | 'user_name, user_firstname, user_displayname, user_email, '. | 
|---|
|  | 102 | 'user_url, user_default_blog, user_options, '. | 
|---|
|  | 103 | 'user_lang, user_tz, user_post_status, user_creadt, user_upddt '. | 
|---|
|  | 104 | 'FROM '.$this->con->escapeSystem($this->user_table).' '. | 
|---|
|  | 105 | "WHERE user_id = '".$this->con->escape($user_id)."' "; | 
|---|
| [2566] | 106 |  | 
|---|
| [0] | 107 | try { | 
|---|
|  | 108 | $rs = $this->con->select($strReq); | 
|---|
|  | 109 | } catch (Exception $e) { | 
|---|
|  | 110 | $err = $e->getMessage(); | 
|---|
|  | 111 | return false; | 
|---|
| [2566] | 112 | } | 
|---|
|  | 113 |  | 
|---|
| [0] | 114 | if ($rs->isEmpty()) { | 
|---|
| [2311] | 115 | sleep(rand(2,5)); | 
|---|
| [0] | 116 | return false; | 
|---|
|  | 117 | } | 
|---|
| [2566] | 118 |  | 
|---|
| [0] | 119 | $rs->extend('rsExtUser'); | 
|---|
| [2566] | 120 |  | 
|---|
| [0] | 121 | if ($pwd != '') | 
|---|
|  | 122 | { | 
|---|
| [3627] | 123 | $rehash = false; | 
|---|
|  | 124 | if (password_verify($pwd,$rs->user_pwd)) { | 
|---|
|  | 125 | // User password ok | 
|---|
|  | 126 | if (password_needs_rehash($rs->user_pwd,PASSWORD_DEFAULT)) { | 
|---|
|  | 127 | $rs->user_pwd = $this->crypt($pwd); | 
|---|
|  | 128 | $rehash = true; | 
|---|
|  | 129 | } | 
|---|
|  | 130 | } else { | 
|---|
|  | 131 | // Check if pwd still stored in old fashion way | 
|---|
|  | 132 | $ret = password_get_info($rs->user_pwd); | 
|---|
|  | 133 | if (is_array($ret) && isset($ret['algo']) && $ret['algo'] == 0) { | 
|---|
|  | 134 | // hash not done with password_hash() function, check by old fashion way | 
|---|
|  | 135 | if (crypt::hmac(DC_MASTER_KEY,$pwd,DC_CRYPT_ALGO) == $rs->user_pwd) { | 
|---|
|  | 136 | // Password Ok, need to store it in new fashion way | 
|---|
|  | 137 | $rs->user_pwd = $this->crypt($pwd); | 
|---|
|  | 138 | $rehash = true; | 
|---|
|  | 139 | } else { | 
|---|
|  | 140 | // Password KO | 
|---|
|  | 141 | sleep(rand(2,5)); | 
|---|
|  | 142 | return false; | 
|---|
|  | 143 | } | 
|---|
|  | 144 | } else { | 
|---|
|  | 145 | // Password KO | 
|---|
|  | 146 | sleep(rand(2,5)); | 
|---|
|  | 147 | return false; | 
|---|
|  | 148 | } | 
|---|
|  | 149 | } | 
|---|
|  | 150 | if ($rehash) { | 
|---|
|  | 151 | // Store new hash in DB | 
|---|
|  | 152 | $cur = $this->con->openCursor($this->user_table); | 
|---|
|  | 153 | $cur->user_pwd = (string) $rs->user_pwd; | 
|---|
|  | 154 | $cur->update("WHERE user_id = '".$rs->user_id."'"); | 
|---|
| [0] | 155 | } | 
|---|
|  | 156 | } | 
|---|
|  | 157 | elseif ($user_key != '') | 
|---|
|  | 158 | { | 
|---|
| [3627] | 159 | if (http::browserUID(DC_MASTER_KEY.$rs->user_id.$this->cryptLegacy($rs->user_id)) != $user_key) { | 
|---|
| [0] | 160 | return false; | 
|---|
|  | 161 | } | 
|---|
|  | 162 | } | 
|---|
| [2566] | 163 |  | 
|---|
| [0] | 164 | $this->user_id = $rs->user_id; | 
|---|
|  | 165 | $this->user_change_pwd = (boolean) $rs->user_change_pwd; | 
|---|
|  | 166 | $this->user_admin = (boolean) $rs->user_super; | 
|---|
| [2566] | 167 |  | 
|---|
| [0] | 168 | $this->user_info['user_pwd'] = $rs->user_pwd; | 
|---|
|  | 169 | $this->user_info['user_name'] = $rs->user_name; | 
|---|
|  | 170 | $this->user_info['user_firstname'] = $rs->user_firstname; | 
|---|
|  | 171 | $this->user_info['user_displayname'] = $rs->user_displayname; | 
|---|
|  | 172 | $this->user_info['user_email'] = $rs->user_email; | 
|---|
|  | 173 | $this->user_info['user_url'] = $rs->user_url; | 
|---|
|  | 174 | $this->user_info['user_default_blog'] = $rs->user_default_blog; | 
|---|
|  | 175 | $this->user_info['user_lang'] = $rs->user_lang; | 
|---|
|  | 176 | $this->user_info['user_tz'] = $rs->user_tz; | 
|---|
|  | 177 | $this->user_info['user_post_status'] = $rs->user_post_status; | 
|---|
|  | 178 | $this->user_info['user_creadt'] = $rs->user_creadt; | 
|---|
|  | 179 | $this->user_info['user_upddt'] = $rs->user_upddt; | 
|---|
| [2566] | 180 |  | 
|---|
| [0] | 181 | $this->user_info['user_cn'] = dcUtils::getUserCN($rs->user_id, $rs->user_name, | 
|---|
|  | 182 | $rs->user_firstname, $rs->user_displayname); | 
|---|
| [2566] | 183 |  | 
|---|
| [0] | 184 | $this->user_options = array_merge($this->core->userDefaults(),$rs->options()); | 
|---|
| [2566] | 185 |  | 
|---|
| [3] | 186 | $this->user_prefs = new dcPrefs($this->core,$this->user_id); | 
|---|
| [2566] | 187 |  | 
|---|
| [0] | 188 | # Get permissions on blogs | 
|---|
| [312] | 189 | if ($check_blog && ($this->findUserBlog() === false)) { | 
|---|
| [0] | 190 | return false; | 
|---|
|  | 191 | } | 
|---|
|  | 192 | return true; | 
|---|
|  | 193 | } | 
|---|
| [2566] | 194 |  | 
|---|
| [0] | 195 | /** | 
|---|
| [3036] | 196 | * This method crypt given string (password, session_id, …). | 
|---|
|  | 197 | * | 
|---|
|  | 198 | * @param string $pwd string to be crypted | 
|---|
|  | 199 | * @return string crypted value | 
|---|
|  | 200 | */ | 
|---|
|  | 201 | public function crypt($pwd) | 
|---|
|  | 202 | { | 
|---|
| [3627] | 203 | return password_hash($pwd,PASSWORD_DEFAULT); | 
|---|
|  | 204 | } | 
|---|
|  | 205 |  | 
|---|
|  | 206 | /** | 
|---|
|  | 207 | * This method crypt given string (password, session_id, …). | 
|---|
|  | 208 | * | 
|---|
|  | 209 | * @param string $pwd string to be crypted | 
|---|
|  | 210 | * @return string crypted value | 
|---|
|  | 211 | */ | 
|---|
|  | 212 | public function cryptLegacy($pwd) | 
|---|
|  | 213 | { | 
|---|
| [3231] | 214 | return crypt::hmac(DC_MASTER_KEY,$pwd,DC_CRYPT_ALGO); | 
|---|
| [3036] | 215 | } | 
|---|
|  | 216 |  | 
|---|
|  | 217 | /** | 
|---|
| [333] | 218 | * This method only check current user password. | 
|---|
| [2566] | 219 | * | 
|---|
| [333] | 220 | * @param string     $pwd           User password | 
|---|
|  | 221 | * @return boolean | 
|---|
| [0] | 222 | */ | 
|---|
|  | 223 | public function checkPassword($pwd) | 
|---|
|  | 224 | { | 
|---|
|  | 225 | if (!empty($this->user_info['user_pwd'])) { | 
|---|
| [3627] | 226 | return password_verify($pwd,$this->user_info['user_pwd']); | 
|---|
| [0] | 227 | } | 
|---|
| [2566] | 228 |  | 
|---|
| [0] | 229 | return false; | 
|---|
|  | 230 | } | 
|---|
| [2566] | 231 |  | 
|---|
| [0] | 232 | /** | 
|---|
| [333] | 233 | * This method checks if user session cookie exists | 
|---|
| [2566] | 234 | * | 
|---|
| [333] | 235 | * @return boolean | 
|---|
| [0] | 236 | */ | 
|---|
|  | 237 | public function sessionExists() | 
|---|
|  | 238 | { | 
|---|
|  | 239 | return isset($_COOKIE[DC_SESSION_NAME]); | 
|---|
|  | 240 | } | 
|---|
| [2566] | 241 |  | 
|---|
| [0] | 242 | /** | 
|---|
| [333] | 243 | * This method checks user session validity. | 
|---|
| [2566] | 244 | * | 
|---|
| [333] | 245 | * @return boolean | 
|---|
| [0] | 246 | */ | 
|---|
|  | 247 | public function checkSession($uid=null) | 
|---|
|  | 248 | { | 
|---|
|  | 249 | $this->core->session->start(); | 
|---|
| [2566] | 250 |  | 
|---|
| [0] | 251 | # If session does not exist, logout. | 
|---|
|  | 252 | if (!isset($_SESSION['sess_user_id'])) { | 
|---|
|  | 253 | $this->core->session->destroy(); | 
|---|
|  | 254 | return false; | 
|---|
|  | 255 | } | 
|---|
| [2566] | 256 |  | 
|---|
| [0] | 257 | # Check here for user and IP address | 
|---|
|  | 258 | $this->checkUser($_SESSION['sess_user_id']); | 
|---|
| [3340] | 259 | $uid = $uid ?: http::browserUID(DC_MASTER_KEY); | 
|---|
| [2566] | 260 |  | 
|---|
| [0] | 261 | $user_can_log = $this->userID() !== null && $uid == $_SESSION['sess_browser_uid']; | 
|---|
| [2566] | 262 |  | 
|---|
| [0] | 263 | if (!$user_can_log) { | 
|---|
|  | 264 | $this->core->session->destroy(); | 
|---|
|  | 265 | return false; | 
|---|
|  | 266 | } | 
|---|
| [2566] | 267 |  | 
|---|
| [0] | 268 | return true; | 
|---|
|  | 269 | } | 
|---|
| [2566] | 270 |  | 
|---|
| [0] | 271 | /** | 
|---|
|  | 272 | * Checks if user must change his password in order to login. | 
|---|
|  | 273 | * | 
|---|
|  | 274 | * @return boolean | 
|---|
|  | 275 | */ | 
|---|
|  | 276 | public function mustChangePassword() | 
|---|
|  | 277 | { | 
|---|
|  | 278 | return $this->user_change_pwd; | 
|---|
|  | 279 | } | 
|---|
| [2566] | 280 |  | 
|---|
| [0] | 281 | /** | 
|---|
| [333] | 282 | * Checks if user is super admin | 
|---|
| [2566] | 283 | * | 
|---|
| [333] | 284 | * @return boolean | 
|---|
| [0] | 285 | */ | 
|---|
|  | 286 | public function isSuperAdmin() | 
|---|
|  | 287 | { | 
|---|
|  | 288 | return $this->user_admin; | 
|---|
|  | 289 | } | 
|---|
| [2566] | 290 |  | 
|---|
| [0] | 291 | /** | 
|---|
| [333] | 292 | * Checks if user has permissions given in <var>$permissions</var> for blog | 
|---|
|  | 293 | * <var>$blog_id</var>. <var>$permissions</var> is a coma separated list of | 
|---|
|  | 294 | * permissions. | 
|---|
| [2566] | 295 | * | 
|---|
| [333] | 296 | * @param string     $permissions   Permissions list | 
|---|
|  | 297 | * @param string     $blog_id       Blog ID | 
|---|
|  | 298 | * @return boolean | 
|---|
| [0] | 299 | */ | 
|---|
|  | 300 | public function check($permissions,$blog_id) | 
|---|
|  | 301 | { | 
|---|
|  | 302 | if ($this->user_admin) { | 
|---|
|  | 303 | return true; | 
|---|
|  | 304 | } | 
|---|
| [2566] | 305 |  | 
|---|
| [3298] | 306 | $p = array_map('trim',explode(',',$permissions)); | 
|---|
| [0] | 307 | $b = $this->getPermissions($blog_id); | 
|---|
| [2566] | 308 |  | 
|---|
| [0] | 309 | if ($b != false) | 
|---|
|  | 310 | { | 
|---|
|  | 311 | if (isset($b['admin'])) { | 
|---|
|  | 312 | return true; | 
|---|
|  | 313 | } | 
|---|
| [2566] | 314 |  | 
|---|
| [0] | 315 | foreach ($p as $v) | 
|---|
|  | 316 | { | 
|---|
|  | 317 | if (isset($b[$v])) { | 
|---|
|  | 318 | return true; | 
|---|
|  | 319 | } | 
|---|
|  | 320 | } | 
|---|
|  | 321 | } | 
|---|
| [2566] | 322 |  | 
|---|
| [0] | 323 | return false; | 
|---|
|  | 324 | } | 
|---|
| [2566] | 325 |  | 
|---|
| [0] | 326 | /** | 
|---|
| [333] | 327 | * Returns true if user is allowed to change its password. | 
|---|
| [2566] | 328 | * | 
|---|
| [333] | 329 | * @return boolean | 
|---|
| [0] | 330 | */ | 
|---|
|  | 331 | public function allowPassChange() | 
|---|
|  | 332 | { | 
|---|
|  | 333 | return $this->allow_pass_change; | 
|---|
|  | 334 | } | 
|---|
|  | 335 | //@} | 
|---|
| [2566] | 336 |  | 
|---|
| [0] | 337 | /// @name User code handlers | 
|---|
|  | 338 | //@{ | 
|---|
|  | 339 | public function getUserCode() | 
|---|
|  | 340 | { | 
|---|
|  | 341 | $code = | 
|---|
|  | 342 | pack('a32',$this->userID()). | 
|---|
| [3036] | 343 | pack('H*',$this->crypt($this->getInfo('user_pwd'))); | 
|---|
| [0] | 344 | return bin2hex($code); | 
|---|
|  | 345 | } | 
|---|
| [2566] | 346 |  | 
|---|
| [0] | 347 | public function checkUserCode($code) | 
|---|
|  | 348 | { | 
|---|
|  | 349 | $code = @pack('H*',$code); | 
|---|
| [2566] | 350 |  | 
|---|
| [0] | 351 | $user_id = trim(@pack('a32',substr($code,0,32))); | 
|---|
| [3231] | 352 | $pwd = @unpack('H*hex',substr($code,32)); | 
|---|
| [2566] | 353 |  | 
|---|
| [0] | 354 | if ($user_id === false || $pwd === false) { | 
|---|
|  | 355 | return false; | 
|---|
|  | 356 | } | 
|---|
| [2566] | 357 |  | 
|---|
| [0] | 358 | $pwd = $pwd['hex']; | 
|---|
| [2566] | 359 |  | 
|---|
| [0] | 360 | $strReq = 'SELECT user_id, user_pwd '. | 
|---|
|  | 361 | 'FROM '.$this->user_table.' '. | 
|---|
|  | 362 | "WHERE user_id = '".$this->con->escape($user_id)."' "; | 
|---|
| [2566] | 363 |  | 
|---|
| [0] | 364 | $rs = $this->con->select($strReq); | 
|---|
| [2566] | 365 |  | 
|---|
| [0] | 366 | if ($rs->isEmpty()) { | 
|---|
|  | 367 | return false; | 
|---|
|  | 368 | } | 
|---|
| [2566] | 369 |  | 
|---|
| [3036] | 370 | if ($this->crypt($rs->user_pwd) != $pwd) { | 
|---|
| [0] | 371 | return false; | 
|---|
|  | 372 | } | 
|---|
| [2566] | 373 |  | 
|---|
| [0] | 374 | return $rs->user_id; | 
|---|
|  | 375 | } | 
|---|
|  | 376 | //@} | 
|---|
| [2566] | 377 |  | 
|---|
|  | 378 |  | 
|---|
| [0] | 379 | /// @name Sudo | 
|---|
|  | 380 | //@{ | 
|---|
|  | 381 | /** | 
|---|
| [333] | 382 | * Calls $f function with super admin rights. | 
|---|
|  | 383 | * Returns the function result. | 
|---|
| [2566] | 384 | * | 
|---|
| [333] | 385 | * @param callback   $f             Callback function | 
|---|
|  | 386 | * @return mixed | 
|---|
| [0] | 387 | */ | 
|---|
|  | 388 | public function sudo($f) | 
|---|
|  | 389 | { | 
|---|
|  | 390 | if (!is_callable($f)) { | 
|---|
|  | 391 | throw new Exception($f.' function doest not exist'); | 
|---|
|  | 392 | } | 
|---|
| [2566] | 393 |  | 
|---|
| [0] | 394 | $args = func_get_args(); | 
|---|
|  | 395 | array_shift($args); | 
|---|
| [2566] | 396 |  | 
|---|
| [0] | 397 | if ($this->user_admin) { | 
|---|
|  | 398 | $res = call_user_func_array($f,$args); | 
|---|
|  | 399 | } else { | 
|---|
|  | 400 | $this->user_admin = true; | 
|---|
|  | 401 | try { | 
|---|
|  | 402 | $res = call_user_func_array($f,$args); | 
|---|
|  | 403 | $this->user_admin = false; | 
|---|
|  | 404 | } catch (Exception $e) { | 
|---|
|  | 405 | $this->user_admin = false; | 
|---|
|  | 406 | throw $e; | 
|---|
|  | 407 | } | 
|---|
|  | 408 | } | 
|---|
| [2566] | 409 |  | 
|---|
| [0] | 410 | return $res; | 
|---|
|  | 411 | } | 
|---|
|  | 412 | //@} | 
|---|
| [2566] | 413 |  | 
|---|
| [0] | 414 | /// @name User information and options | 
|---|
|  | 415 | //@{ | 
|---|
|  | 416 | /** | 
|---|
| [333] | 417 | * Returns user permissions for a blog as an array which looks like: | 
|---|
| [2566] | 418 | * | 
|---|
| [333] | 419 | *  - [blog_id] | 
|---|
|  | 420 | *    - [permission] => true | 
|---|
|  | 421 | *    - ... | 
|---|
| [2566] | 422 | * | 
|---|
| [333] | 423 | * @param string     $blog_id       Blog ID | 
|---|
|  | 424 | * @return array | 
|---|
| [0] | 425 | */ | 
|---|
|  | 426 | public function getPermissions($blog_id) | 
|---|
|  | 427 | { | 
|---|
|  | 428 | if (isset($this->blogs[$blog_id])) { | 
|---|
|  | 429 | return $this->blogs[$blog_id]; | 
|---|
|  | 430 | } | 
|---|
| [2159] | 431 |  | 
|---|
| [0] | 432 | if ($this->user_admin) { | 
|---|
|  | 433 | $strReq = 'SELECT blog_id '. | 
|---|
|  | 434 | 'from '.$this->blog_table.' '. | 
|---|
|  | 435 | "WHERE blog_id = '".$this->con->escape($blog_id)."' "; | 
|---|
|  | 436 | $rs = $this->con->select($strReq); | 
|---|
| [2566] | 437 |  | 
|---|
| [0] | 438 | $this->blogs[$blog_id] = $rs->isEmpty() ? false : array('admin' => true); | 
|---|
| [2566] | 439 |  | 
|---|
| [0] | 440 | return $this->blogs[$blog_id]; | 
|---|
|  | 441 | } | 
|---|
| [2566] | 442 |  | 
|---|
| [0] | 443 | $strReq = 'SELECT permissions '. | 
|---|
|  | 444 | 'FROM '.$this->perm_table.' '. | 
|---|
|  | 445 | "WHERE user_id = '".$this->con->escape($this->user_id)."' ". | 
|---|
|  | 446 | "AND blog_id = '".$this->con->escape($blog_id)."' ". | 
|---|
|  | 447 | "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') "; | 
|---|
|  | 448 | $rs = $this->con->select($strReq); | 
|---|
| [2566] | 449 |  | 
|---|
| [0] | 450 | $this->blogs[$blog_id] = $rs->isEmpty() ? false : $this->parsePermissions($rs->permissions); | 
|---|
| [2566] | 451 |  | 
|---|
| [0] | 452 | return $this->blogs[$blog_id]; | 
|---|
|  | 453 | } | 
|---|
| [2159] | 454 |  | 
|---|
|  | 455 | public function getBlogCount() { | 
|---|
|  | 456 | if ($this->blog_count === null) { | 
|---|
|  | 457 | $this->blog_count = $this->core->getBlogs(array(),true)->f(0); | 
|---|
|  | 458 | } | 
|---|
|  | 459 |  | 
|---|
|  | 460 | return $this->blog_count; | 
|---|
|  | 461 | } | 
|---|
| [2566] | 462 |  | 
|---|
| [0] | 463 | public function findUserBlog($blog_id=null) | 
|---|
|  | 464 | { | 
|---|
|  | 465 | if ($blog_id && $this->getPermissions($blog_id) !== false) | 
|---|
|  | 466 | { | 
|---|
|  | 467 | return $blog_id; | 
|---|
|  | 468 | } | 
|---|
|  | 469 | else | 
|---|
|  | 470 | { | 
|---|
|  | 471 | if ($this->user_admin) | 
|---|
|  | 472 | { | 
|---|
|  | 473 | $strReq = 'SELECT blog_id '. | 
|---|
|  | 474 | 'FROM '.$this->blog_table.' '. | 
|---|
|  | 475 | 'ORDER BY blog_id ASC '. | 
|---|
|  | 476 | $this->con->limit(1); | 
|---|
|  | 477 | } | 
|---|
|  | 478 | else | 
|---|
|  | 479 | { | 
|---|
| [3399] | 480 | $strReq = 'SELECT P.blog_id '. | 
|---|
|  | 481 | 'FROM '.$this->perm_table.' P, '.$this->blog_table.' B '. | 
|---|
| [0] | 482 | "WHERE user_id = '".$this->con->escape($this->user_id)."' ". | 
|---|
| [3399] | 483 | "AND P.blog_id = B.blog_id ". | 
|---|
| [0] | 484 | "AND (permissions LIKE '%|usage|%' OR permissions LIKE '%|admin|%' OR permissions LIKE '%|contentadmin|%') ". | 
|---|
| [3399] | 485 | "AND blog_status >= 0 ". | 
|---|
|  | 486 | 'ORDER BY P.blog_id ASC '. | 
|---|
| [0] | 487 | $this->con->limit(1); | 
|---|
|  | 488 | } | 
|---|
| [2566] | 489 |  | 
|---|
| [0] | 490 | $rs = $this->con->select($strReq); | 
|---|
|  | 491 | if (!$rs->isEmpty()) { | 
|---|
|  | 492 | return $rs->blog_id; | 
|---|
|  | 493 | } | 
|---|
|  | 494 | } | 
|---|
| [2566] | 495 |  | 
|---|
| [0] | 496 | return false; | 
|---|
|  | 497 | } | 
|---|
| [2566] | 498 |  | 
|---|
| [0] | 499 | /** | 
|---|
| [333] | 500 | * Returns current user ID | 
|---|
| [2566] | 501 | * | 
|---|
| [333] | 502 | * @return string | 
|---|
| [0] | 503 | */ | 
|---|
|  | 504 | public function userID() | 
|---|
|  | 505 | { | 
|---|
|  | 506 | return $this->user_id; | 
|---|
|  | 507 | } | 
|---|
| [2566] | 508 |  | 
|---|
| [0] | 509 | /** | 
|---|
| [333] | 510 | * Returns information about a user . | 
|---|
| [2566] | 511 | * | 
|---|
| [333] | 512 | * @param string     $n             Information name | 
|---|
|  | 513 | * @return string | 
|---|
| [0] | 514 | */ | 
|---|
|  | 515 | public function getInfo($n) | 
|---|
|  | 516 | { | 
|---|
|  | 517 | if (isset($this->user_info[$n])) { | 
|---|
|  | 518 | return $this->user_info[$n]; | 
|---|
|  | 519 | } | 
|---|
| [2566] | 520 |  | 
|---|
| [0] | 521 | return null; | 
|---|
|  | 522 | } | 
|---|
| [2566] | 523 |  | 
|---|
| [0] | 524 | /** | 
|---|
| [333] | 525 | * Returns a specific user option | 
|---|
| [2566] | 526 | * | 
|---|
| [333] | 527 | * @param string     $n             Option name | 
|---|
|  | 528 | * @return string | 
|---|
| [0] | 529 | */ | 
|---|
|  | 530 | public function getOption($n) | 
|---|
|  | 531 | { | 
|---|
|  | 532 | if (isset($this->user_options[$n])) { | 
|---|
|  | 533 | return $this->user_options[$n]; | 
|---|
|  | 534 | } | 
|---|
|  | 535 | return null; | 
|---|
|  | 536 | } | 
|---|
| [2566] | 537 |  | 
|---|
| [0] | 538 | /** | 
|---|
| [333] | 539 | * Returns all user options in an associative array. | 
|---|
| [2566] | 540 | * | 
|---|
| [333] | 541 | * @return array | 
|---|
| [0] | 542 | */ | 
|---|
|  | 543 | public function getOptions() | 
|---|
|  | 544 | { | 
|---|
|  | 545 | return $this->user_options; | 
|---|
|  | 546 | } | 
|---|
|  | 547 | //@} | 
|---|
| [2566] | 548 |  | 
|---|
| [0] | 549 | /// @name Permissions | 
|---|
|  | 550 | //@{ | 
|---|
|  | 551 | /** | 
|---|
| [333] | 552 | * Returns an array with permissions parsed from the string <var>$level</var> | 
|---|
| [2566] | 553 | * | 
|---|
| [333] | 554 | * @param string     $level         Permissions string | 
|---|
|  | 555 | * @return array | 
|---|
| [0] | 556 | */ | 
|---|
|  | 557 | public function parsePermissions($level) | 
|---|
|  | 558 | { | 
|---|
|  | 559 | $level = preg_replace('/^\|/','',$level); | 
|---|
|  | 560 | $level = preg_replace('/\|$/','',$level); | 
|---|
| [2566] | 561 |  | 
|---|
| [0] | 562 | $res = array(); | 
|---|
|  | 563 | foreach (explode('|',$level) as $v) { | 
|---|
|  | 564 | $res[$v] = true; | 
|---|
|  | 565 | } | 
|---|
|  | 566 | return $res; | 
|---|
|  | 567 | } | 
|---|
| [2566] | 568 |  | 
|---|
| [0] | 569 | /** | 
|---|
| [333] | 570 | * Returns <var>perm_types</var> property content. | 
|---|
| [2566] | 571 | * | 
|---|
| [333] | 572 | * @return array | 
|---|
| [0] | 573 | */ | 
|---|
|  | 574 | public function getPermissionsTypes() | 
|---|
|  | 575 | { | 
|---|
|  | 576 | return $this->perm_types; | 
|---|
|  | 577 | } | 
|---|
| [2566] | 578 |  | 
|---|
| [0] | 579 | /** | 
|---|
| [333] | 580 | * Adds a new permission type. | 
|---|
| [2566] | 581 | * | 
|---|
| [333] | 582 | * @param string     $name          Permission name | 
|---|
|  | 583 | * @param string     $title         Permission title | 
|---|
| [0] | 584 | */ | 
|---|
|  | 585 | public function setPermissionType($name,$title) | 
|---|
|  | 586 | { | 
|---|
|  | 587 | $this->perm_types[$name] = $title; | 
|---|
|  | 588 | } | 
|---|
|  | 589 | //@} | 
|---|
| [2566] | 590 |  | 
|---|
| [0] | 591 | /// @name Password recovery | 
|---|
|  | 592 | //@{ | 
|---|
|  | 593 | /** | 
|---|
| [333] | 594 | * Add a recover key to a specific user identified by its email and | 
|---|
|  | 595 | * password. | 
|---|
| [2566] | 596 | * | 
|---|
| [333] | 597 | * @param string     $user_id       User ID | 
|---|
|  | 598 | * @param string     $user_email    User Email | 
|---|
|  | 599 | * @return string | 
|---|
| [0] | 600 | */ | 
|---|
|  | 601 | public function setRecoverKey($user_id,$user_email) | 
|---|
|  | 602 | { | 
|---|
|  | 603 | $strReq = 'SELECT user_id '. | 
|---|
|  | 604 | 'FROM '.$this->user_table.' '. | 
|---|
|  | 605 | "WHERE user_id = '".$this->con->escape($user_id)."' ". | 
|---|
|  | 606 | "AND user_email = '".$this->con->escape($user_email)."' "; | 
|---|
| [2566] | 607 |  | 
|---|
| [0] | 608 | $rs = $this->con->select($strReq); | 
|---|
| [2566] | 609 |  | 
|---|
| [0] | 610 | if ($rs->isEmpty()) { | 
|---|
|  | 611 | throw new Exception(__('That user does not exist in the database.')); | 
|---|
|  | 612 | } | 
|---|
| [2566] | 613 |  | 
|---|
| [3512] | 614 | $key = md5(uniqid('',true)); | 
|---|
| [2566] | 615 |  | 
|---|
| [0] | 616 | $cur = $this->con->openCursor($this->user_table); | 
|---|
|  | 617 | $cur->user_recover_key = $key; | 
|---|
| [2566] | 618 |  | 
|---|
| [0] | 619 | $cur->update("WHERE user_id = '".$this->con->escape($user_id)."'"); | 
|---|
| [2566] | 620 |  | 
|---|
| [0] | 621 | return $key; | 
|---|
|  | 622 | } | 
|---|
| [2566] | 623 |  | 
|---|
| [0] | 624 | /** | 
|---|
| [333] | 625 | * Creates a new user password using recovery key. Returns an array: | 
|---|
| [2566] | 626 | * | 
|---|
| [333] | 627 | * - user_email | 
|---|
|  | 628 | * - user_id | 
|---|
|  | 629 | * - new_pass | 
|---|
| [2566] | 630 | * | 
|---|
| [333] | 631 | * @param string     $recover_key   Recovery key | 
|---|
|  | 632 | * @return array | 
|---|
| [0] | 633 | */ | 
|---|
|  | 634 | public function recoverUserPassword($recover_key) | 
|---|
|  | 635 | { | 
|---|
|  | 636 | $strReq = 'SELECT user_id, user_email '. | 
|---|
|  | 637 | 'FROM '.$this->user_table.' '. | 
|---|
|  | 638 | "WHERE user_recover_key = '".$this->con->escape($recover_key)."' "; | 
|---|
| [2566] | 639 |  | 
|---|
| [0] | 640 | $rs = $this->con->select($strReq); | 
|---|
| [2566] | 641 |  | 
|---|
| [0] | 642 | if ($rs->isEmpty()) { | 
|---|
|  | 643 | throw new Exception(__('That key does not exist in the database.')); | 
|---|
|  | 644 | } | 
|---|
| [2566] | 645 |  | 
|---|
| [0] | 646 | $new_pass = crypt::createPassword(); | 
|---|
| [2566] | 647 |  | 
|---|
| [0] | 648 | $cur = $this->con->openCursor($this->user_table); | 
|---|
| [3036] | 649 | $cur->user_pwd = $this->crypt($new_pass); | 
|---|
| [0] | 650 | $cur->user_recover_key = null; | 
|---|
| [3535] | 651 | $cur->user_change_pwd = 1;         // User will have to change this temporary password at next login | 
|---|
| [2566] | 652 |  | 
|---|
| [0] | 653 | $cur->update("WHERE user_recover_key = '".$this->con->escape($recover_key)."'"); | 
|---|
| [2566] | 654 |  | 
|---|
| [0] | 655 | return array('user_email' => $rs->user_email, 'user_id' => $rs->user_id, 'new_pass' => $new_pass); | 
|---|
|  | 656 | } | 
|---|
|  | 657 | //@} | 
|---|
| [2566] | 658 |  | 
|---|
| [0] | 659 | /** @name User management callbacks | 
|---|
|  | 660 | This 3 functions only matter if you extend this class and use | 
|---|
|  | 661 | DC_AUTH_CLASS constant. | 
|---|
|  | 662 | These are called after core user management functions. | 
|---|
|  | 663 | Could be useful if you need to add/update/remove stuff in your | 
|---|
|  | 664 | LDAP directory or other third party authentication database. | 
|---|
|  | 665 | */ | 
|---|
|  | 666 | //@{ | 
|---|
| [2566] | 667 |  | 
|---|
| [0] | 668 | /** | 
|---|
| [333] | 669 | * Called after core->addUser | 
|---|
|  | 670 | * @see dcCore::addUser | 
|---|
|  | 671 | * @param cursor     $cur           User cursor | 
|---|
| [0] | 672 | */ | 
|---|
|  | 673 | public function afterAddUser($cur) {} | 
|---|
| [2566] | 674 |  | 
|---|
| [0] | 675 | /** | 
|---|
| [333] | 676 | * Called after core->updUser | 
|---|
|  | 677 | * @see dcCore::updUser | 
|---|
|  | 678 | * @param string     $id            User ID | 
|---|
|  | 679 | * @param cursor     $cur           User cursor | 
|---|
| [0] | 680 | */ | 
|---|
|  | 681 | public function afterUpdUser($id,$cur) {} | 
|---|
| [2566] | 682 |  | 
|---|
| [0] | 683 | /** | 
|---|
| [333] | 684 | * Called after core->delUser | 
|---|
|  | 685 | * @see dcCore::delUser | 
|---|
|  | 686 | * @param string     $id            User ID | 
|---|
| [0] | 687 | */ | 
|---|
|  | 688 | public function afterDelUser($id) {} | 
|---|
|  | 689 | //@} | 
|---|
|  | 690 | } | 
|---|