PageRenderTime 90ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/elgg/mod/dokuwiki/lib/dokuwiki/inc/auth/plain.class.php

https://bitbucket.org/rhizomatik/lorea_production/
PHP | 324 lines | 166 code | 53 blank | 105 comment | 41 complexity | b5bf116dfdc7b6e7b0363e50f4dd9a12 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * Plaintext authentication backend
  4. *
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Andreas Gohr <andi@splitbrain.org>
  7. * @author Chris Smith <chris@jalakai.co.uk>
  8. */
  9. define('DOKU_AUTH', dirname(__FILE__));
  10. require_once(DOKU_AUTH.'/basic.class.php');
  11. define('AUTH_USERFILE',DOKU_CONF.'users.auth.php');
  12. class auth_plain extends auth_basic {
  13. var $users = null;
  14. var $_pattern = array();
  15. /**
  16. * Constructor
  17. *
  18. * Carry out sanity checks to ensure the object is
  19. * able to operate. Set capabilities.
  20. *
  21. * @author Christopher Smith <chris@jalakai.co.uk>
  22. */
  23. function auth_plain() {
  24. if (!@is_readable(AUTH_USERFILE)){
  25. $this->success = false;
  26. }else{
  27. if(@is_writable(AUTH_USERFILE)){
  28. $this->cando['addUser'] = true;
  29. $this->cando['delUser'] = true;
  30. $this->cando['modLogin'] = true;
  31. $this->cando['modPass'] = true;
  32. $this->cando['modName'] = true;
  33. $this->cando['modMail'] = true;
  34. $this->cando['modGroups'] = true;
  35. }
  36. $this->cando['getUsers'] = true;
  37. $this->cando['getUserCount'] = true;
  38. }
  39. }
  40. /**
  41. * Check user+password [required auth function]
  42. *
  43. * Checks if the given user exists and the given
  44. * plaintext password is correct
  45. *
  46. * @author Andreas Gohr <andi@splitbrain.org>
  47. * @return bool
  48. */
  49. function checkPass($user,$pass){
  50. $userinfo = $this->getUserData($user);
  51. if ($userinfo === false) return false;
  52. return auth_verifyPassword($pass,$this->users[$user]['pass']);
  53. }
  54. /**
  55. * Return user info
  56. *
  57. * Returns info about the given user needs to contain
  58. * at least these fields:
  59. *
  60. * name string full name of the user
  61. * mail string email addres of the user
  62. * grps array list of groups the user is in
  63. *
  64. * @author Andreas Gohr <andi@splitbrain.org>
  65. */
  66. function getUserData($user){
  67. if($this->users === null) $this->_loadUserData();
  68. return isset($this->users[$user]) ? $this->users[$user] : false;
  69. }
  70. /**
  71. * Create a new User
  72. *
  73. * Returns false if the user already exists, null when an error
  74. * occurred and true if everything went well.
  75. *
  76. * The new user will be added to the default group by this
  77. * function if grps are not specified (default behaviour).
  78. *
  79. * @author Andreas Gohr <andi@splitbrain.org>
  80. * @author Chris Smith <chris@jalakai.co.uk>
  81. */
  82. function createUser($user,$pwd,$name,$mail,$grps=null){
  83. global $conf;
  84. // user mustn't already exist
  85. if ($this->getUserData($user) !== false) return false;
  86. $pass = auth_cryptPassword($pwd);
  87. // set default group if no groups specified
  88. if (!is_array($grps)) $grps = array($conf['defaultgroup']);
  89. // prepare user line
  90. $groups = join(',',$grps);
  91. $userline = join(':',array($user,$pass,$name,$mail,$groups))."\n";
  92. if (io_saveFile(AUTH_USERFILE,$userline,true)) {
  93. $this->users[$user] = compact('pass','name','mail','grps');
  94. return $pwd;
  95. }
  96. msg('The '.AUTH_USERFILE.' file is not writable. Please inform the Wiki-Admin',-1);
  97. return null;
  98. }
  99. /**
  100. * Modify user data
  101. *
  102. * @author Chris Smith <chris@jalakai.co.uk>
  103. * @param $user nick of the user to be changed
  104. * @param $changes array of field/value pairs to be changed (password will be clear text)
  105. * @return bool
  106. */
  107. function modifyUser($user, $changes) {
  108. global $conf;
  109. global $ACT;
  110. global $INFO;
  111. // sanity checks, user must already exist and there must be something to change
  112. if (($userinfo = $this->getUserData($user)) === false) return false;
  113. if (!is_array($changes) || !count($changes)) return true;
  114. // update userinfo with new data, remembering to encrypt any password
  115. $newuser = $user;
  116. foreach ($changes as $field => $value) {
  117. if ($field == 'user') {
  118. $newuser = $value;
  119. continue;
  120. }
  121. if ($field == 'pass') $value = auth_cryptPassword($value);
  122. $userinfo[$field] = $value;
  123. }
  124. $groups = join(',',$userinfo['grps']);
  125. $userline = join(':',array($newuser, $userinfo['pass'], $userinfo['name'], $userinfo['mail'], $groups))."\n";
  126. if (!$this->deleteUsers(array($user))) {
  127. msg('Unable to modify user data. Please inform the Wiki-Admin',-1);
  128. return false;
  129. }
  130. if (!io_saveFile(AUTH_USERFILE,$userline,true)) {
  131. msg('There was an error modifying your user data. You should register again.',-1);
  132. // FIXME, user has been deleted but not recreated, should force a logout and redirect to login page
  133. $ACT == 'register';
  134. return false;
  135. }
  136. $this->users[$newuser] = $userinfo;
  137. return true;
  138. }
  139. /**
  140. * Remove one or more users from the list of registered users
  141. *
  142. * @author Christopher Smith <chris@jalakai.co.uk>
  143. * @param array $users array of users to be deleted
  144. * @return int the number of users deleted
  145. */
  146. function deleteUsers($users) {
  147. if (!is_array($users) || empty($users)) return 0;
  148. if ($this->users === null) $this->_loadUserData();
  149. $deleted = array();
  150. foreach ($users as $user) {
  151. if (isset($this->users[$user])) $deleted[] = preg_quote($user,'/');
  152. }
  153. if (empty($deleted)) return 0;
  154. $pattern = '/^('.join('|',$deleted).'):/';
  155. if (io_deleteFromFile(AUTH_USERFILE,$pattern,true)) {
  156. foreach ($deleted as $user) unset($this->users[$user]);
  157. return count($deleted);
  158. }
  159. // problem deleting, reload the user list and count the difference
  160. $count = count($this->users);
  161. $this->_loadUserData();
  162. $count -= count($this->users);
  163. return $count;
  164. }
  165. /**
  166. * Return a count of the number of user which meet $filter criteria
  167. *
  168. * @author Chris Smith <chris@jalakai.co.uk>
  169. */
  170. function getUserCount($filter=array()) {
  171. if($this->users === null) $this->_loadUserData();
  172. if (!count($filter)) return count($this->users);
  173. $count = 0;
  174. $this->_constructPattern($filter);
  175. foreach ($this->users as $user => $info) {
  176. $count += $this->_filter($user, $info);
  177. }
  178. return $count;
  179. }
  180. /**
  181. * Bulk retrieval of user data
  182. *
  183. * @author Chris Smith <chris@jalakai.co.uk>
  184. * @param start index of first user to be returned
  185. * @param limit max number of users to be returned
  186. * @param filter array of field/pattern pairs
  187. * @return array of userinfo (refer getUserData for internal userinfo details)
  188. */
  189. function retrieveUsers($start=0,$limit=0,$filter=array()) {
  190. if ($this->users === null) $this->_loadUserData();
  191. ksort($this->users);
  192. $i = 0;
  193. $count = 0;
  194. $out = array();
  195. $this->_constructPattern($filter);
  196. foreach ($this->users as $user => $info) {
  197. if ($this->_filter($user, $info)) {
  198. if ($i >= $start) {
  199. $out[$user] = $info;
  200. $count++;
  201. if (($limit > 0) && ($count >= $limit)) break;
  202. }
  203. $i++;
  204. }
  205. }
  206. return $out;
  207. }
  208. /**
  209. * Only valid pageid's (no namespaces) for usernames
  210. */
  211. function cleanUser($user){
  212. global $conf;
  213. return cleanID(str_replace(':',$conf['sepchar'],$user));
  214. }
  215. /**
  216. * Only valid pageid's (no namespaces) for groupnames
  217. */
  218. function cleanGroup($group){
  219. global $conf;
  220. return cleanID(str_replace(':',$conf['sepchar'],$group));
  221. }
  222. /**
  223. * Load all user data
  224. *
  225. * loads the user file into a datastructure
  226. *
  227. * @author Andreas Gohr <andi@splitbrain.org>
  228. */
  229. function _loadUserData(){
  230. $this->users = array();
  231. if(!@file_exists(AUTH_USERFILE)) return;
  232. $lines = file(AUTH_USERFILE);
  233. foreach($lines as $line){
  234. $line = preg_replace('/#.*$/','',$line); //ignore comments
  235. $line = trim($line);
  236. if(empty($line)) continue;
  237. $row = explode(":",$line,5);
  238. $groups = array_values(array_filter(explode(",",$row[4])));
  239. $this->users[$row[0]]['pass'] = $row[1];
  240. $this->users[$row[0]]['name'] = urldecode($row[2]);
  241. $this->users[$row[0]]['mail'] = $row[3];
  242. $this->users[$row[0]]['grps'] = $groups;
  243. }
  244. }
  245. /**
  246. * return 1 if $user + $info match $filter criteria, 0 otherwise
  247. *
  248. * @author Chris Smith <chris@jalakai.co.uk>
  249. */
  250. function _filter($user, $info) {
  251. // FIXME
  252. foreach ($this->_pattern as $item => $pattern) {
  253. if ($item == 'user') {
  254. if (!preg_match($pattern, $user)) return 0;
  255. } else if ($item == 'grps') {
  256. if (!count(preg_grep($pattern, $info['grps']))) return 0;
  257. } else {
  258. if (!preg_match($pattern, $info[$item])) return 0;
  259. }
  260. }
  261. return 1;
  262. }
  263. function _constructPattern($filter) {
  264. $this->_pattern = array();
  265. foreach ($filter as $item => $pattern) {
  266. // $this->_pattern[$item] = '/'.preg_quote($pattern,"/").'/i'; // don't allow regex characters
  267. $this->_pattern[$item] = '/'.str_replace('/','\/',$pattern).'/i'; // allow regex characters
  268. }
  269. }
  270. }
  271. //Setup VIM: ex: et ts=2 enc=utf-8 :