10440ff15Schris<?php 20440ff15Schris/* 30440ff15Schris * User Manager 40440ff15Schris * 50440ff15Schris * Dokuwiki Admin Plugin 60440ff15Schris * 70440ff15Schris * This version of the user manager has been modified to only work with 80440ff15Schris * objectified version of auth system 90440ff15Schris * 100440ff15Schris * @author neolao <neolao@neolao.com> 110440ff15Schris * @author Chris Smith <chris@jalakai.co.uk> 120440ff15Schris */ 130440ff15Schrisif(!defined('DOKU_PLUGIN_IMAGES')) define('DOKU_PLUGIN_IMAGES',DOKU_BASE.'lib/plugins/usermanager/images/'); 140440ff15Schris 150440ff15Schris/** 160440ff15Schris * All DokuWiki plugins to extend the admin function 170440ff15Schris * need to inherit from this class 180440ff15Schris */ 190440ff15Schrisclass admin_plugin_usermanager extends DokuWiki_Admin_Plugin { 200440ff15Schris 213712ca9aSGerrit Uitslag protected $_auth = null; // auth object 223712ca9aSGerrit Uitslag protected $_user_total = 0; // number of registered users 233712ca9aSGerrit Uitslag protected $_filter = array(); // user selection filter(s) 243712ca9aSGerrit Uitslag protected $_start = 0; // index of first user to be displayed 253712ca9aSGerrit Uitslag protected $_last = 0; // index of the last user to be displayed 263712ca9aSGerrit Uitslag protected $_pagesize = 20; // number of users to list on one page 273712ca9aSGerrit Uitslag protected $_edit_user = ''; // set to user selected for editing 283712ca9aSGerrit Uitslag protected $_edit_userdata = array(); 293712ca9aSGerrit Uitslag protected $_disabled = ''; // if disabled set to explanatory string 303712ca9aSGerrit Uitslag protected $_import_failures = array(); 31462e9e37SMichael Große protected $_lastdisabled = false; // set to true if last user is unknown and last button is hence buggy 320440ff15Schris 330440ff15Schris /** 340440ff15Schris * Constructor 350440ff15Schris */ 3626e22ab8SChristopher Smith public function __construct(){ 37c5a7c0c6SGerrit Uitslag /** @var DokuWiki_Auth_Plugin $auth */ 380440ff15Schris global $auth; 390440ff15Schris 400440ff15Schris $this->setupLocale(); 4151d94d49Schris 4251d94d49Schris if (!isset($auth)) { 43c5a7c0c6SGerrit Uitslag $this->_disabled = $this->lang['noauth']; 4482fd59b6SAndreas Gohr } else if (!$auth->canDo('getUsers')) { 45c5a7c0c6SGerrit Uitslag $this->_disabled = $this->lang['nosupport']; 4651d94d49Schris } else { 4751d94d49Schris 4851d94d49Schris // we're good to go 4951d94d49Schris $this->_auth = & $auth; 5051d94d49Schris 5151d94d49Schris } 52ae1afd2fSChristopher Smith 53ae1afd2fSChristopher Smith // attempt to retrieve any import failures from the session 540e80bb5eSChristopher Smith if (!empty($_SESSION['import_failures'])){ 55ae1afd2fSChristopher Smith $this->_import_failures = $_SESSION['import_failures']; 56ae1afd2fSChristopher Smith } 570440ff15Schris } 580440ff15Schris 590440ff15Schris /** 60c5a7c0c6SGerrit Uitslag * Return prompt for admin menu 61253d4b48SGerrit Uitslag * 62253d4b48SGerrit Uitslag * @param string $language 63253d4b48SGerrit Uitslag * @return string 640440ff15Schris */ 65c5a7c0c6SGerrit Uitslag public function getMenuText($language) { 660440ff15Schris 670440ff15Schris if (!is_null($this->_auth)) 680440ff15Schris return parent::getMenuText($language); 690440ff15Schris 70c5a7c0c6SGerrit Uitslag return $this->getLang('menu').' '.$this->_disabled; 710440ff15Schris } 720440ff15Schris 730440ff15Schris /** 740440ff15Schris * return sort order for position in admin menu 75253d4b48SGerrit Uitslag * 76253d4b48SGerrit Uitslag * @return int 770440ff15Schris */ 78c5a7c0c6SGerrit Uitslag public function getMenuSort() { 790440ff15Schris return 2; 800440ff15Schris } 810440ff15Schris 820440ff15Schris /** 8367a31a83SMichael Große * @return int current start value for pageination 8467a31a83SMichael Große */ 8567a31a83SMichael Große public function getStart() { 8667a31a83SMichael Große return $this->_start; 8767a31a83SMichael Große } 8867a31a83SMichael Große 8967a31a83SMichael Große /** 9067a31a83SMichael Große * @return int number of users per page 9167a31a83SMichael Große */ 9267a31a83SMichael Große public function getPagesize() { 9367a31a83SMichael Große return $this->_pagesize; 9467a31a83SMichael Große } 9567a31a83SMichael Große 9667a31a83SMichael Große /** 97462e9e37SMichael Große * @param boolean $lastdisabled 98462e9e37SMichael Große */ 99462e9e37SMichael Große public function setLastdisabled($lastdisabled) { 100462e9e37SMichael Große $this->_lastdisabled = $lastdisabled; 101462e9e37SMichael Große } 102462e9e37SMichael Große 103462e9e37SMichael Große /** 104c5a7c0c6SGerrit Uitslag * Handle user request 105253d4b48SGerrit Uitslag * 106253d4b48SGerrit Uitslag * @return bool 1070440ff15Schris */ 108c5a7c0c6SGerrit Uitslag public function handle() { 10900d58927SMichael Hamann global $INPUT; 1100440ff15Schris if (is_null($this->_auth)) return false; 1110440ff15Schris 1120440ff15Schris // extract the command and any specific parameters 1130440ff15Schris // submit button name is of the form - fn[cmd][param(s)] 11400d58927SMichael Hamann $fn = $INPUT->param('fn'); 1150440ff15Schris 1160440ff15Schris if (is_array($fn)) { 1170440ff15Schris $cmd = key($fn); 1180440ff15Schris $param = is_array($fn[$cmd]) ? key($fn[$cmd]) : null; 1190440ff15Schris } else { 1200440ff15Schris $cmd = $fn; 1210440ff15Schris $param = null; 1220440ff15Schris } 1230440ff15Schris 1240440ff15Schris if ($cmd != "search") { 12500d58927SMichael Hamann $this->_start = $INPUT->int('start', 0); 1260440ff15Schris $this->_filter = $this->_retrieveFilter(); 1270440ff15Schris } 1280440ff15Schris 1290440ff15Schris switch($cmd){ 1300440ff15Schris case "add" : $this->_addUser(); break; 1310440ff15Schris case "delete" : $this->_deleteUser(); break; 1320440ff15Schris case "modify" : $this->_modifyUser(); break; 13378c7c8c9Schris case "edit" : $this->_editUser($param); break; 1340440ff15Schris case "search" : $this->_setFilter($param); 1350440ff15Schris $this->_start = 0; 1360440ff15Schris break; 1375c967d3dSChristopher Smith case "export" : $this->_export(); break; 138ae1afd2fSChristopher Smith case "import" : $this->_import(); break; 139ae1afd2fSChristopher Smith case "importfails" : $this->_downloadImportFailures(); break; 1400440ff15Schris } 1410440ff15Schris 14251d94d49Schris $this->_user_total = $this->_auth->canDo('getUserCount') ? $this->_auth->getUserCount($this->_filter) : -1; 1430440ff15Schris 1440440ff15Schris // page handling 1450440ff15Schris switch($cmd){ 1460440ff15Schris case 'start' : $this->_start = 0; break; 1470440ff15Schris case 'prev' : $this->_start -= $this->_pagesize; break; 1480440ff15Schris case 'next' : $this->_start += $this->_pagesize; break; 1490440ff15Schris case 'last' : $this->_start = $this->_user_total; break; 1500440ff15Schris } 1510440ff15Schris $this->_validatePagination(); 152c5a7c0c6SGerrit Uitslag return true; 1530440ff15Schris } 1540440ff15Schris 1550440ff15Schris /** 156c5a7c0c6SGerrit Uitslag * Output appropriate html 157253d4b48SGerrit Uitslag * 158253d4b48SGerrit Uitslag * @return bool 1590440ff15Schris */ 160c5a7c0c6SGerrit Uitslag public function html() { 1610440ff15Schris global $ID; 1620440ff15Schris 1630440ff15Schris if(is_null($this->_auth)) { 1640440ff15Schris print $this->lang['badauth']; 1650440ff15Schris return false; 1660440ff15Schris } 1670440ff15Schris 1680440ff15Schris $user_list = $this->_auth->retrieveUsers($this->_start, $this->_pagesize, $this->_filter); 1690440ff15Schris 1700440ff15Schris $page_buttons = $this->_pagination(); 17182fd59b6SAndreas Gohr $delete_disable = $this->_auth->canDo('delUser') ? '' : 'disabled="disabled"'; 1720440ff15Schris 17377d19185SAndreas Gohr $editable = $this->_auth->canDo('UserMod'); 174b59cff8bSGerrit Uitslag $export_label = empty($this->_filter) ? $this->lang['export_all'] : $this->lang['export_filtered']; 1756154103cSmatthiasgrimm 1760440ff15Schris print $this->locale_xhtml('intro'); 1770440ff15Schris print $this->locale_xhtml('list'); 1780440ff15Schris 17958dde80dSAnika Henke ptln("<div id=\"user__manager\">"); 18058dde80dSAnika Henke ptln("<div class=\"level2\">"); 1810440ff15Schris 18267019d15Schris if ($this->_user_total > 0) { 183*64159a61SAndreas Gohr ptln( 184*64159a61SAndreas Gohr "<p>" . sprintf( 185*64159a61SAndreas Gohr $this->lang['summary'], 186*64159a61SAndreas Gohr $this->_start + 1, 187*64159a61SAndreas Gohr $this->_last, 188*64159a61SAndreas Gohr $this->_user_total, 189*64159a61SAndreas Gohr $this->_auth->getUserCount() 190*64159a61SAndreas Gohr ) . "</p>" 191*64159a61SAndreas Gohr ); 1920440ff15Schris } else { 193a102b175SGerrit Uitslag if($this->_user_total < 0) { 194a102b175SGerrit Uitslag $allUserTotal = 0; 195a102b175SGerrit Uitslag } else { 196a102b175SGerrit Uitslag $allUserTotal = $this->_auth->getUserCount(); 197a102b175SGerrit Uitslag } 198a102b175SGerrit Uitslag ptln("<p>".sprintf($this->lang['nonefound'], $allUserTotal)."</p>"); 1990440ff15Schris } 2000440ff15Schris ptln("<form action=\"".wl($ID)."\" method=\"post\">"); 201634d7150SAndreas Gohr formSecurityToken(); 202c7b28ffdSAnika Henke ptln(" <div class=\"table\">"); 2030440ff15Schris ptln(" <table class=\"inline\">"); 2040440ff15Schris ptln(" <thead>"); 2050440ff15Schris ptln(" <tr>"); 206*64159a61SAndreas Gohr ptln(" <th> </th> 207*64159a61SAndreas Gohr <th>".$this->lang["user_id"]."</th> 208*64159a61SAndreas Gohr <th>".$this->lang["user_name"]."</th> 209*64159a61SAndreas Gohr <th>".$this->lang["user_mail"]."</th> 210*64159a61SAndreas Gohr <th>".$this->lang["user_groups"]."</th>"); 2110440ff15Schris ptln(" </tr>"); 2120440ff15Schris 2130440ff15Schris ptln(" <tr>"); 214*64159a61SAndreas Gohr ptln(" <td class=\"rightalign\"><input type=\"image\" src=\"". 215*64159a61SAndreas Gohr DOKU_PLUGIN_IMAGES."search.png\" name=\"fn[search][new]\" title=\"". 216*64159a61SAndreas Gohr $this->lang['search_prompt']."\" alt=\"".$this->lang['search']."\" class=\"button\" /></td>"); 217*64159a61SAndreas Gohr ptln(" <td><input type=\"text\" name=\"userid\" class=\"edit\" value=\"". 218*64159a61SAndreas Gohr $this->_htmlFilter('user')."\" /></td>"); 219*64159a61SAndreas Gohr ptln(" <td><input type=\"text\" name=\"username\" class=\"edit\" value=\"". 220*64159a61SAndreas Gohr $this->_htmlFilter('name')."\" /></td>"); 221*64159a61SAndreas Gohr ptln(" <td><input type=\"text\" name=\"usermail\" class=\"edit\" value=\"". 222*64159a61SAndreas Gohr $this->_htmlFilter('mail')."\" /></td>"); 223*64159a61SAndreas Gohr ptln(" <td><input type=\"text\" name=\"usergroups\" class=\"edit\" value=\"". 224*64159a61SAndreas Gohr $this->_htmlFilter('grps')."\" /></td>"); 2250440ff15Schris ptln(" </tr>"); 2260440ff15Schris ptln(" </thead>"); 2270440ff15Schris 2280440ff15Schris if ($this->_user_total) { 2290440ff15Schris ptln(" <tbody>"); 2300440ff15Schris foreach ($user_list as $user => $userinfo) { 2310440ff15Schris extract($userinfo); 232c5a7c0c6SGerrit Uitslag /** 233c5a7c0c6SGerrit Uitslag * @var string $name 234c5a7c0c6SGerrit Uitslag * @var string $pass 235c5a7c0c6SGerrit Uitslag * @var string $mail 236c5a7c0c6SGerrit Uitslag * @var array $grps 237c5a7c0c6SGerrit Uitslag */ 2380440ff15Schris $groups = join(', ',$grps); 239a2c0246eSAnika Henke ptln(" <tr class=\"user_info\">"); 240*64159a61SAndreas Gohr ptln(" <td class=\"centeralign\"><input type=\"checkbox\" name=\"delete[".hsc($user). 241*64159a61SAndreas Gohr "]\" ".$delete_disable." /></td>"); 2422365d73dSAnika Henke if ($editable) { 243f23f9594SAndreas Gohr ptln(" <td><a href=\"".wl($ID,array('fn[edit]['.$user.']' => 1, 24477d19185SAndreas Gohr 'do' => 'admin', 24577d19185SAndreas Gohr 'page' => 'usermanager', 24677d19185SAndreas Gohr 'sectok' => getSecurityToken())). 24777d19185SAndreas Gohr "\" title=\"".$this->lang['edit_prompt']."\">".hsc($user)."</a></td>"); 2482365d73dSAnika Henke } else { 2492365d73dSAnika Henke ptln(" <td>".hsc($user)."</td>"); 2502365d73dSAnika Henke } 2512365d73dSAnika Henke ptln(" <td>".hsc($name)."</td><td>".hsc($mail)."</td><td>".hsc($groups)."</td>"); 2520440ff15Schris ptln(" </tr>"); 2530440ff15Schris } 2540440ff15Schris ptln(" </tbody>"); 2550440ff15Schris } 2560440ff15Schris 2570440ff15Schris ptln(" <tbody>"); 2582365d73dSAnika Henke ptln(" <tr><td colspan=\"5\" class=\"centeralign\">"); 259a2c0246eSAnika Henke ptln(" <span class=\"medialeft\">"); 260*64159a61SAndreas Gohr ptln(" <button type=\"submit\" name=\"fn[delete]\" id=\"usrmgr__del\" ".$delete_disable.">". 261*64159a61SAndreas Gohr $this->lang['delete_selected']."</button>"); 26276c49356SMike Wilmes ptln(" </span>"); 26376c49356SMike Wilmes ptln(" <span class=\"mediaright\">"); 264*64159a61SAndreas Gohr ptln(" <button type=\"submit\" name=\"fn[start]\" ".$page_buttons['start'].">". 265*64159a61SAndreas Gohr $this->lang['start']."</button>"); 266*64159a61SAndreas Gohr ptln(" <button type=\"submit\" name=\"fn[prev]\" ".$page_buttons['prev'].">". 267*64159a61SAndreas Gohr $this->lang['prev']."</button>"); 268*64159a61SAndreas Gohr ptln(" <button type=\"submit\" name=\"fn[next]\" ".$page_buttons['next'].">". 269*64159a61SAndreas Gohr $this->lang['next']."</button>"); 270*64159a61SAndreas Gohr ptln(" <button type=\"submit\" name=\"fn[last]\" ".$page_buttons['last'].">". 271*64159a61SAndreas Gohr $this->lang['last']."</button>"); 27276c49356SMike Wilmes ptln(" </span>"); 2735c967d3dSChristopher Smith if (!empty($this->_filter)) { 274ae614416SAnika Henke ptln(" <button type=\"submit\" name=\"fn[search][clear]\">".$this->lang['clear']."</button>"); 2755c967d3dSChristopher Smith } 276ae614416SAnika Henke ptln(" <button type=\"submit\" name=\"fn[export]\">".$export_label."</button>"); 2775164d9c9SAnika Henke ptln(" <input type=\"hidden\" name=\"do\" value=\"admin\" />"); 2785164d9c9SAnika Henke ptln(" <input type=\"hidden\" name=\"page\" value=\"usermanager\" />"); 279daf4ca4eSAnika Henke 280daf4ca4eSAnika Henke $this->_htmlFilterSettings(2); 281daf4ca4eSAnika Henke 2820440ff15Schris ptln(" </td></tr>"); 2830440ff15Schris ptln(" </tbody>"); 2840440ff15Schris ptln(" </table>"); 285c7b28ffdSAnika Henke ptln(" </div>"); 2860440ff15Schris 2870440ff15Schris ptln("</form>"); 2880440ff15Schris ptln("</div>"); 2890440ff15Schris 290a2c0246eSAnika Henke $style = $this->_edit_user ? " class=\"edit_user\"" : ""; 2910440ff15Schris 29282fd59b6SAndreas Gohr if ($this->_auth->canDo('addUser')) { 2930440ff15Schris ptln("<div".$style.">"); 2940440ff15Schris print $this->locale_xhtml('add'); 2950440ff15Schris ptln(" <div class=\"level2\">"); 2960440ff15Schris 29778c7c8c9Schris $this->_htmlUserForm('add',null,array(),4); 2980440ff15Schris 2990440ff15Schris ptln(" </div>"); 3000440ff15Schris ptln("</div>"); 3010440ff15Schris } 3020440ff15Schris 30382fd59b6SAndreas Gohr if($this->_edit_user && $this->_auth->canDo('UserMod')){ 304c632fc69SAndreas Gohr ptln("<div".$style." id=\"scroll__here\">"); 3050440ff15Schris print $this->locale_xhtml('edit'); 3060440ff15Schris ptln(" <div class=\"level2\">"); 3070440ff15Schris 30878c7c8c9Schris $this->_htmlUserForm('modify',$this->_edit_user,$this->_edit_userdata,4); 3090440ff15Schris 3100440ff15Schris ptln(" </div>"); 3110440ff15Schris ptln("</div>"); 3120440ff15Schris } 313ae1afd2fSChristopher Smith 314ae1afd2fSChristopher Smith if ($this->_auth->canDo('addUser')) { 315ae1afd2fSChristopher Smith $this->_htmlImportForm(); 316ae1afd2fSChristopher Smith } 31758dde80dSAnika Henke ptln("</div>"); 318c5a7c0c6SGerrit Uitslag return true; 3190440ff15Schris } 3200440ff15Schris 32182fd59b6SAndreas Gohr /** 322c5a7c0c6SGerrit Uitslag * Display form to add or modify a user 323c5a7c0c6SGerrit Uitslag * 324c5a7c0c6SGerrit Uitslag * @param string $cmd 'add' or 'modify' 325c5a7c0c6SGerrit Uitslag * @param string $user id of user 326c5a7c0c6SGerrit Uitslag * @param array $userdata array with name, mail, pass and grps 327c5a7c0c6SGerrit Uitslag * @param int $indent 32882fd59b6SAndreas Gohr */ 3293712ca9aSGerrit Uitslag protected function _htmlUserForm($cmd,$user='',$userdata=array(),$indent=0) { 330a6858c6aSchris global $conf; 331bb4866bdSchris global $ID; 332be9008d3SChristopher Smith global $lang; 33378c7c8c9Schris 33478c7c8c9Schris $name = $mail = $groups = ''; 335a6858c6aSchris $notes = array(); 3360440ff15Schris 3370440ff15Schris if ($user) { 33878c7c8c9Schris extract($userdata); 33978c7c8c9Schris if (!empty($grps)) $groups = join(',',$grps); 340a6858c6aSchris } else { 341a6858c6aSchris $notes[] = sprintf($this->lang['note_group'],$conf['defaultgroup']); 3420440ff15Schris } 3430440ff15Schris 3440440ff15Schris ptln("<form action=\"".wl($ID)."\" method=\"post\">",$indent); 345634d7150SAndreas Gohr formSecurityToken(); 346c7b28ffdSAnika Henke ptln(" <div class=\"table\">",$indent); 3470440ff15Schris ptln(" <table class=\"inline\">",$indent); 3480440ff15Schris ptln(" <thead>",$indent); 3490440ff15Schris ptln(" <tr><th>".$this->lang["field"]."</th><th>".$this->lang["value"]."</th></tr>",$indent); 3500440ff15Schris ptln(" </thead>",$indent); 3510440ff15Schris ptln(" <tbody>",$indent); 35226fb387bSchris 353*64159a61SAndreas Gohr $this->_htmlInputField( 354*64159a61SAndreas Gohr $cmd . "_userid", 355*64159a61SAndreas Gohr "userid", 356*64159a61SAndreas Gohr $this->lang["user_id"], 357*64159a61SAndreas Gohr $user, 358*64159a61SAndreas Gohr $this->_auth->canDo("modLogin"), 359*64159a61SAndreas Gohr true, 360*64159a61SAndreas Gohr $indent + 6 361*64159a61SAndreas Gohr ); 362*64159a61SAndreas Gohr $this->_htmlInputField( 363*64159a61SAndreas Gohr $cmd . "_userpass", 364*64159a61SAndreas Gohr "userpass", 365*64159a61SAndreas Gohr $this->lang["user_pass"], 366*64159a61SAndreas Gohr "", 367*64159a61SAndreas Gohr $this->_auth->canDo("modPass"), 368*64159a61SAndreas Gohr false, 369*64159a61SAndreas Gohr $indent + 6 370*64159a61SAndreas Gohr ); 371*64159a61SAndreas Gohr $this->_htmlInputField( 372*64159a61SAndreas Gohr $cmd . "_userpass2", 373*64159a61SAndreas Gohr "userpass2", 374*64159a61SAndreas Gohr $lang["passchk"], 375*64159a61SAndreas Gohr "", 376*64159a61SAndreas Gohr $this->_auth->canDo("modPass"), 377*64159a61SAndreas Gohr false, 378*64159a61SAndreas Gohr $indent + 6 379*64159a61SAndreas Gohr ); 380*64159a61SAndreas Gohr $this->_htmlInputField( 381*64159a61SAndreas Gohr $cmd . "_username", 382*64159a61SAndreas Gohr "username", 383*64159a61SAndreas Gohr $this->lang["user_name"], 384*64159a61SAndreas Gohr $name, 385*64159a61SAndreas Gohr $this->_auth->canDo("modName"), 386*64159a61SAndreas Gohr true, 387*64159a61SAndreas Gohr $indent + 6 388*64159a61SAndreas Gohr ); 389*64159a61SAndreas Gohr $this->_htmlInputField( 390*64159a61SAndreas Gohr $cmd . "_usermail", 391*64159a61SAndreas Gohr "usermail", 392*64159a61SAndreas Gohr $this->lang["user_mail"], 393*64159a61SAndreas Gohr $mail, 394*64159a61SAndreas Gohr $this->_auth->canDo("modMail"), 395*64159a61SAndreas Gohr true, 396*64159a61SAndreas Gohr $indent + 6 397*64159a61SAndreas Gohr ); 398*64159a61SAndreas Gohr $this->_htmlInputField( 399*64159a61SAndreas Gohr $cmd . "_usergroups", 400*64159a61SAndreas Gohr "usergroups", 401*64159a61SAndreas Gohr $this->lang["user_groups"], 402*64159a61SAndreas Gohr $groups, 403*64159a61SAndreas Gohr $this->_auth->canDo("modGroups"), 404*64159a61SAndreas Gohr false, 405*64159a61SAndreas Gohr $indent + 6 406*64159a61SAndreas Gohr ); 40726fb387bSchris 408a6858c6aSchris if ($this->_auth->canDo("modPass")) { 409ee9498f5SChristopher Smith if ($cmd == 'add') { 410c3f4fb63SGina Haeussge $notes[] = $this->lang['note_pass']; 411ee9498f5SChristopher Smith } 412a6858c6aSchris if ($user) { 413a6858c6aSchris $notes[] = $this->lang['note_notify']; 414a6858c6aSchris } 415a6858c6aSchris 416*64159a61SAndreas Gohr ptln("<tr><td><label for=\"".$cmd."_usernotify\" >". 417*64159a61SAndreas Gohr $this->lang["user_notify"].": </label></td> 418*64159a61SAndreas Gohr <td><input type=\"checkbox\" id=\"".$cmd."_usernotify\" name=\"usernotify\" value=\"1\" /> 419*64159a61SAndreas Gohr </td></tr>", $indent); 420a6858c6aSchris } 421a6858c6aSchris 4220440ff15Schris ptln(" </tbody>",$indent); 4230440ff15Schris ptln(" <tbody>",$indent); 4240440ff15Schris ptln(" <tr>",$indent); 4250440ff15Schris ptln(" <td colspan=\"2\">",$indent); 4260440ff15Schris ptln(" <input type=\"hidden\" name=\"do\" value=\"admin\" />",$indent); 4270440ff15Schris ptln(" <input type=\"hidden\" name=\"page\" value=\"usermanager\" />",$indent); 4280440ff15Schris 4290440ff15Schris // save current $user, we need this to access details if the name is changed 4300440ff15Schris if ($user) 431f23f9594SAndreas Gohr ptln(" <input type=\"hidden\" name=\"userid_old\" value=\"".hsc($user)."\" />",$indent); 4320440ff15Schris 4330440ff15Schris $this->_htmlFilterSettings($indent+10); 4340440ff15Schris 435ae614416SAnika Henke ptln(" <button type=\"submit\" name=\"fn[".$cmd."]\">".$this->lang[$cmd]."</button>",$indent); 4360440ff15Schris ptln(" </td>",$indent); 4370440ff15Schris ptln(" </tr>",$indent); 4380440ff15Schris ptln(" </tbody>",$indent); 4390440ff15Schris ptln(" </table>",$indent); 44045c19902SChristopher Smith 44145c19902SChristopher Smith if ($notes) { 44245c19902SChristopher Smith ptln(" <ul class=\"notes\">"); 44345c19902SChristopher Smith foreach ($notes as $note) { 444ae614416SAnika Henke ptln(" <li><span class=\"li\">".$note."</li>",$indent); 44545c19902SChristopher Smith } 44645c19902SChristopher Smith ptln(" </ul>"); 44745c19902SChristopher Smith } 448c7b28ffdSAnika Henke ptln(" </div>",$indent); 4490440ff15Schris ptln("</form>",$indent); 4500440ff15Schris } 4510440ff15Schris 452c5a7c0c6SGerrit Uitslag /** 453c5a7c0c6SGerrit Uitslag * Prints a inputfield 454c5a7c0c6SGerrit Uitslag * 455c5a7c0c6SGerrit Uitslag * @param string $id 456c5a7c0c6SGerrit Uitslag * @param string $name 457c5a7c0c6SGerrit Uitslag * @param string $label 458c5a7c0c6SGerrit Uitslag * @param string $value 459c5a7c0c6SGerrit Uitslag * @param bool $cando whether auth backend is capable to do this action 4609b82d43fSAndreas Gohr * @param bool $required is this field required? 461c5a7c0c6SGerrit Uitslag * @param int $indent 462c5a7c0c6SGerrit Uitslag */ 4639b82d43fSAndreas Gohr protected function _htmlInputField($id, $name, $label, $value, $cando, $required, $indent=0) { 4647de12fceSAndreas Gohr $class = $cando ? '' : ' class="disabled"'; 4657de12fceSAndreas Gohr echo str_pad('',$indent); 4667de12fceSAndreas Gohr 467359e9417SChristopher Smith if($name == 'userpass' || $name == 'userpass2'){ 468d796a891SAndreas Gohr $fieldtype = 'password'; 469d796a891SAndreas Gohr $autocomp = 'autocomplete="off"'; 4707b3674bdSChristopher Smith }elseif($name == 'usermail'){ 4717b3674bdSChristopher Smith $fieldtype = 'email'; 4727b3674bdSChristopher Smith $autocomp = ''; 473d796a891SAndreas Gohr }else{ 474d796a891SAndreas Gohr $fieldtype = 'text'; 475d796a891SAndreas Gohr $autocomp = ''; 476d796a891SAndreas Gohr } 477f23f9594SAndreas Gohr $value = hsc($value); 478d796a891SAndreas Gohr 4797de12fceSAndreas Gohr echo "<tr $class>"; 4807de12fceSAndreas Gohr echo "<td><label for=\"$id\" >$label: </label></td>"; 4817de12fceSAndreas Gohr echo "<td>"; 4827de12fceSAndreas Gohr if($cando){ 4839b82d43fSAndreas Gohr $req = ''; 4849b82d43fSAndreas Gohr if($required) $req = 'required="required"'; 485*64159a61SAndreas Gohr echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\" 486*64159a61SAndreas Gohr value=\"$value\" class=\"edit\" $autocomp $req />"; 4877de12fceSAndreas Gohr }else{ 4887de12fceSAndreas Gohr echo "<input type=\"hidden\" name=\"$name\" value=\"$value\" />"; 489*64159a61SAndreas Gohr echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\" 490*64159a61SAndreas Gohr value=\"$value\" class=\"edit disabled\" disabled=\"disabled\" />"; 4917de12fceSAndreas Gohr } 4927de12fceSAndreas Gohr echo "</td>"; 4937de12fceSAndreas Gohr echo "</tr>"; 49426fb387bSchris } 49526fb387bSchris 496c5a7c0c6SGerrit Uitslag /** 497c5a7c0c6SGerrit Uitslag * Returns htmlescaped filter value 498c5a7c0c6SGerrit Uitslag * 499c5a7c0c6SGerrit Uitslag * @param string $key name of search field 500c5a7c0c6SGerrit Uitslag * @return string html escaped value 501c5a7c0c6SGerrit Uitslag */ 5023712ca9aSGerrit Uitslag protected function _htmlFilter($key) { 5030440ff15Schris if (empty($this->_filter)) return ''; 5040440ff15Schris return (isset($this->_filter[$key]) ? hsc($this->_filter[$key]) : ''); 5050440ff15Schris } 5060440ff15Schris 507c5a7c0c6SGerrit Uitslag /** 508c5a7c0c6SGerrit Uitslag * Print hidden inputs with the current filter values 509c5a7c0c6SGerrit Uitslag * 510c5a7c0c6SGerrit Uitslag * @param int $indent 511c5a7c0c6SGerrit Uitslag */ 5123712ca9aSGerrit Uitslag protected function _htmlFilterSettings($indent=0) { 5130440ff15Schris 5140440ff15Schris ptln("<input type=\"hidden\" name=\"start\" value=\"".$this->_start."\" />",$indent); 5150440ff15Schris 5160440ff15Schris foreach ($this->_filter as $key => $filter) { 5170440ff15Schris ptln("<input type=\"hidden\" name=\"filter[".$key."]\" value=\"".hsc($filter)."\" />",$indent); 5180440ff15Schris } 5190440ff15Schris } 5200440ff15Schris 521c5a7c0c6SGerrit Uitslag /** 522c5a7c0c6SGerrit Uitslag * Print import form and summary of previous import 523c5a7c0c6SGerrit Uitslag * 524c5a7c0c6SGerrit Uitslag * @param int $indent 525c5a7c0c6SGerrit Uitslag */ 5263712ca9aSGerrit Uitslag protected function _htmlImportForm($indent=0) { 527ae1afd2fSChristopher Smith global $ID; 528ae1afd2fSChristopher Smith 529ae1afd2fSChristopher Smith $failure_download_link = wl($ID,array('do'=>'admin','page'=>'usermanager','fn[importfails]'=>1)); 530ae1afd2fSChristopher Smith 531ae1afd2fSChristopher Smith ptln('<div class="level2 import_users">',$indent); 532ae1afd2fSChristopher Smith print $this->locale_xhtml('import'); 533ae1afd2fSChristopher Smith ptln(' <form action="'.wl($ID).'" method="post" enctype="multipart/form-data">',$indent); 534ae1afd2fSChristopher Smith formSecurityToken(); 535b59cff8bSGerrit Uitslag ptln(' <label>'.$this->lang['import_userlistcsv'].'<input type="file" name="import" /></label>',$indent); 536ae614416SAnika Henke ptln(' <button type="submit" name="fn[import]">'.$this->lang['import'].'</button>',$indent); 537ae1afd2fSChristopher Smith ptln(' <input type="hidden" name="do" value="admin" />',$indent); 538ae1afd2fSChristopher Smith ptln(' <input type="hidden" name="page" value="usermanager" />',$indent); 539ae1afd2fSChristopher Smith 540ae1afd2fSChristopher Smith $this->_htmlFilterSettings($indent+4); 541ae1afd2fSChristopher Smith ptln(' </form>',$indent); 542ae1afd2fSChristopher Smith ptln('</div>'); 543ae1afd2fSChristopher Smith 544ae1afd2fSChristopher Smith // list failures from the previous import 545ae1afd2fSChristopher Smith if ($this->_import_failures) { 546ae1afd2fSChristopher Smith $digits = strlen(count($this->_import_failures)); 547ae1afd2fSChristopher Smith ptln('<div class="level3 import_failures">',$indent); 548b59cff8bSGerrit Uitslag ptln(' <h3>'.$this->lang['import_header'].'</h3>'); 549ae1afd2fSChristopher Smith ptln(' <table class="import_failures">',$indent); 550ae1afd2fSChristopher Smith ptln(' <thead>',$indent); 551ae1afd2fSChristopher Smith ptln(' <tr>',$indent); 552ae1afd2fSChristopher Smith ptln(' <th class="line">'.$this->lang['line'].'</th>',$indent); 553ae1afd2fSChristopher Smith ptln(' <th class="error">'.$this->lang['error'].'</th>',$indent); 554ae1afd2fSChristopher Smith ptln(' <th class="userid">'.$this->lang['user_id'].'</th>',$indent); 555ae1afd2fSChristopher Smith ptln(' <th class="username">'.$this->lang['user_name'].'</th>',$indent); 556ae1afd2fSChristopher Smith ptln(' <th class="usermail">'.$this->lang['user_mail'].'</th>',$indent); 557ae1afd2fSChristopher Smith ptln(' <th class="usergroups">'.$this->lang['user_groups'].'</th>',$indent); 558ae1afd2fSChristopher Smith ptln(' </tr>',$indent); 559ae1afd2fSChristopher Smith ptln(' </thead>',$indent); 560ae1afd2fSChristopher Smith ptln(' <tbody>',$indent); 561ae1afd2fSChristopher Smith foreach ($this->_import_failures as $line => $failure) { 562ae1afd2fSChristopher Smith ptln(' <tr>',$indent); 563ae1afd2fSChristopher Smith ptln(' <td class="lineno"> '.sprintf('%0'.$digits.'d',$line).' </td>',$indent); 564ae1afd2fSChristopher Smith ptln(' <td class="error">' .$failure['error'].' </td>', $indent); 565ae1afd2fSChristopher Smith ptln(' <td class="field userid"> '.hsc($failure['user'][0]).' </td>',$indent); 566ae1afd2fSChristopher Smith ptln(' <td class="field username"> '.hsc($failure['user'][2]).' </td>',$indent); 567ae1afd2fSChristopher Smith ptln(' <td class="field usermail"> '.hsc($failure['user'][3]).' </td>',$indent); 568ae1afd2fSChristopher Smith ptln(' <td class="field usergroups"> '.hsc($failure['user'][4]).' </td>',$indent); 569ae1afd2fSChristopher Smith ptln(' </tr>',$indent); 570ae1afd2fSChristopher Smith } 571ae1afd2fSChristopher Smith ptln(' </tbody>',$indent); 572ae1afd2fSChristopher Smith ptln(' </table>',$indent); 573b59cff8bSGerrit Uitslag ptln(' <p><a href="'.$failure_download_link.'">'.$this->lang['import_downloadfailures'].'</a></p>'); 574ae1afd2fSChristopher Smith ptln('</div>'); 575ae1afd2fSChristopher Smith } 576ae1afd2fSChristopher Smith 577ae1afd2fSChristopher Smith } 578ae1afd2fSChristopher Smith 579c5a7c0c6SGerrit Uitslag /** 580c5a7c0c6SGerrit Uitslag * Add an user to auth backend 581c5a7c0c6SGerrit Uitslag * 582c5a7c0c6SGerrit Uitslag * @return bool whether succesful 583c5a7c0c6SGerrit Uitslag */ 5843712ca9aSGerrit Uitslag protected function _addUser(){ 58500d58927SMichael Hamann global $INPUT; 586634d7150SAndreas Gohr if (!checkSecurityToken()) return false; 58782fd59b6SAndreas Gohr if (!$this->_auth->canDo('addUser')) return false; 5880440ff15Schris 589359e9417SChristopher Smith list($user,$pass,$name,$mail,$grps,$passconfirm) = $this->_retrieveUser(); 5900440ff15Schris if (empty($user)) return false; 5916733c4d7SChris Smith 5926733c4d7SChris Smith if ($this->_auth->canDo('modPass')){ 593c3f4fb63SGina Haeussge if (empty($pass)){ 59400d58927SMichael Hamann if($INPUT->has('usernotify')){ 5958a285f7fSAndreas Gohr $pass = auth_pwgen($user); 596c3f4fb63SGina Haeussge } else { 59760b9901bSAndreas Gohr msg($this->lang['add_fail'], -1); 59809a5dcd6SMichael Große msg($this->lang['addUser_error_missing_pass'], -1); 59960b9901bSAndreas Gohr return false; 60060b9901bSAndreas Gohr } 601359e9417SChristopher Smith } else { 602359e9417SChristopher Smith if (!$this->_verifyPassword($pass,$passconfirm)) { 60309a5dcd6SMichael Große msg($this->lang['add_fail'], -1); 60409a5dcd6SMichael Große msg($this->lang['addUser_error_pass_not_identical'], -1); 605359e9417SChristopher Smith return false; 606359e9417SChristopher Smith } 6076733c4d7SChris Smith } 6086733c4d7SChris Smith } else { 6096733c4d7SChris Smith if (!empty($pass)){ 6106733c4d7SChris Smith msg($this->lang['add_fail'], -1); 61109a5dcd6SMichael Große msg($this->lang['addUser_error_modPass_disabled'], -1); 6126733c4d7SChris Smith return false; 6136733c4d7SChris Smith } 6146733c4d7SChris Smith } 6156733c4d7SChris Smith 6166733c4d7SChris Smith if ($this->_auth->canDo('modName')){ 6176733c4d7SChris Smith if (empty($name)){ 6186733c4d7SChris Smith msg($this->lang['add_fail'], -1); 61909a5dcd6SMichael Große msg($this->lang['addUser_error_name_missing'], -1); 6206733c4d7SChris Smith return false; 6216733c4d7SChris Smith } 6226733c4d7SChris Smith } else { 6236733c4d7SChris Smith if (!empty($name)){ 62409a5dcd6SMichael Große msg($this->lang['add_fail'], -1); 62509a5dcd6SMichael Große msg($this->lang['addUser_error_modName_disabled'], -1); 6266733c4d7SChris Smith return false; 6276733c4d7SChris Smith } 6286733c4d7SChris Smith } 6296733c4d7SChris Smith 6306733c4d7SChris Smith if ($this->_auth->canDo('modMail')){ 6316733c4d7SChris Smith if (empty($mail)){ 6326733c4d7SChris Smith msg($this->lang['add_fail'], -1); 63309a5dcd6SMichael Große msg($this->lang['addUser_error_mail_missing'], -1); 6346733c4d7SChris Smith return false; 6356733c4d7SChris Smith } 6366733c4d7SChris Smith } else { 6376733c4d7SChris Smith if (!empty($mail)){ 63809a5dcd6SMichael Große msg($this->lang['add_fail'], -1); 63909a5dcd6SMichael Große msg($this->lang['addUser_error_modMail_disabled'], -1); 6406733c4d7SChris Smith return false; 6416733c4d7SChris Smith } 6426733c4d7SChris Smith } 6430440ff15Schris 6447d3c8d42SGabriel Birke if ($ok = $this->_auth->triggerUserMod('create', array($user,$pass,$name,$mail,$grps))) { 645a6858c6aSchris 646a6858c6aSchris msg($this->lang['add_ok'], 1); 647a6858c6aSchris 64800d58927SMichael Hamann if ($INPUT->has('usernotify') && $pass) { 649a6858c6aSchris $this->_notifyUser($user,$pass); 650a6858c6aSchris } 651a6858c6aSchris } else { 65260b9901bSAndreas Gohr msg($this->lang['add_fail'], -1); 65309a5dcd6SMichael Große msg($this->lang['addUser_error_create_event_failed'], -1); 654a6858c6aSchris } 655a6858c6aSchris 656a6858c6aSchris return $ok; 6570440ff15Schris } 6580440ff15Schris 6590440ff15Schris /** 660c5a7c0c6SGerrit Uitslag * Delete user from auth backend 661c5a7c0c6SGerrit Uitslag * 662c5a7c0c6SGerrit Uitslag * @return bool whether succesful 6630440ff15Schris */ 6643712ca9aSGerrit Uitslag protected function _deleteUser(){ 66500d58927SMichael Hamann global $conf, $INPUT; 6669ec82636SAndreas Gohr 667634d7150SAndreas Gohr if (!checkSecurityToken()) return false; 66882fd59b6SAndreas Gohr if (!$this->_auth->canDo('delUser')) return false; 6690440ff15Schris 67000d58927SMichael Hamann $selected = $INPUT->arr('delete'); 67100d58927SMichael Hamann if (empty($selected)) return false; 6720440ff15Schris $selected = array_keys($selected); 6730440ff15Schris 674c9a8f912SMichael Klier if(in_array($_SERVER['REMOTE_USER'], $selected)) { 675c9a8f912SMichael Klier msg("You can't delete yourself!", -1); 676c9a8f912SMichael Klier return false; 677c9a8f912SMichael Klier } 678c9a8f912SMichael Klier 6797d3c8d42SGabriel Birke $count = $this->_auth->triggerUserMod('delete', array($selected)); 6800440ff15Schris if ($count == count($selected)) { 6810440ff15Schris $text = str_replace('%d', $count, $this->lang['delete_ok']); 6820440ff15Schris msg("$text.", 1); 6830440ff15Schris } else { 6840440ff15Schris $part1 = str_replace('%d', $count, $this->lang['delete_ok']); 6850440ff15Schris $part2 = str_replace('%d', (count($selected)-$count), $this->lang['delete_fail']); 6860440ff15Schris msg("$part1, $part2",-1); 6870440ff15Schris } 68878c7c8c9Schris 6899ec82636SAndreas Gohr // invalidate all sessions 6909ec82636SAndreas Gohr io_saveFile($conf['cachedir'].'/sessionpurge',time()); 6919ec82636SAndreas Gohr 69278c7c8c9Schris return true; 69378c7c8c9Schris } 69478c7c8c9Schris 69578c7c8c9Schris /** 69678c7c8c9Schris * Edit user (a user has been selected for editing) 697c5a7c0c6SGerrit Uitslag * 698c5a7c0c6SGerrit Uitslag * @param string $param id of the user 699c5a7c0c6SGerrit Uitslag * @return bool whether succesful 70078c7c8c9Schris */ 7013712ca9aSGerrit Uitslag protected function _editUser($param) { 702634d7150SAndreas Gohr if (!checkSecurityToken()) return false; 70378c7c8c9Schris if (!$this->_auth->canDo('UserMod')) return false; 704786dfb0eSGerrit Uitslag $user = $this->_auth->cleanUser(preg_replace('/.*[:\/]/','',$param)); 70578c7c8c9Schris $userdata = $this->_auth->getUserData($user); 70678c7c8c9Schris 70778c7c8c9Schris // no user found? 70878c7c8c9Schris if (!$userdata) { 70978c7c8c9Schris msg($this->lang['edit_usermissing'],-1); 71078c7c8c9Schris return false; 71178c7c8c9Schris } 71278c7c8c9Schris 71378c7c8c9Schris $this->_edit_user = $user; 71478c7c8c9Schris $this->_edit_userdata = $userdata; 71578c7c8c9Schris 71678c7c8c9Schris return true; 7170440ff15Schris } 7180440ff15Schris 7190440ff15Schris /** 720c5a7c0c6SGerrit Uitslag * Modify user in the auth backend (modified user data has been recieved) 721c5a7c0c6SGerrit Uitslag * 722c5a7c0c6SGerrit Uitslag * @return bool whether succesful 7230440ff15Schris */ 7243712ca9aSGerrit Uitslag protected function _modifyUser(){ 72500d58927SMichael Hamann global $conf, $INPUT; 7269ec82636SAndreas Gohr 727634d7150SAndreas Gohr if (!checkSecurityToken()) return false; 72882fd59b6SAndreas Gohr if (!$this->_auth->canDo('UserMod')) return false; 7290440ff15Schris 73026fb387bSchris // get currently valid user data 731786dfb0eSGerrit Uitslag $olduser = $this->_auth->cleanUser(preg_replace('/.*[:\/]/','',$INPUT->str('userid_old'))); 732073766c6Smatthiasgrimm $oldinfo = $this->_auth->getUserData($olduser); 733073766c6Smatthiasgrimm 73426fb387bSchris // get new user data subject to change 735359e9417SChristopher Smith list($newuser,$newpass,$newname,$newmail,$newgrps,$passconfirm) = $this->_retrieveUser(); 736073766c6Smatthiasgrimm if (empty($newuser)) return false; 7370440ff15Schris 7380440ff15Schris $changes = array(); 739073766c6Smatthiasgrimm if ($newuser != $olduser) { 74026fb387bSchris 74126fb387bSchris if (!$this->_auth->canDo('modLogin')) { // sanity check, shouldn't be possible 74226fb387bSchris msg($this->lang['update_fail'],-1); 74326fb387bSchris return false; 74426fb387bSchris } 74526fb387bSchris 74626fb387bSchris // check if $newuser already exists 747073766c6Smatthiasgrimm if ($this->_auth->getUserData($newuser)) { 748073766c6Smatthiasgrimm msg(sprintf($this->lang['update_exists'],$newuser),-1); 749a6858c6aSchris $re_edit = true; 7500440ff15Schris } else { 751073766c6Smatthiasgrimm $changes['user'] = $newuser; 7520440ff15Schris } 75393eefc2fSAndreas Gohr } 754359e9417SChristopher Smith if ($this->_auth->canDo('modPass')) { 7552400ddcbSChristopher Smith if ($newpass || $passconfirm) { 756359e9417SChristopher Smith if ($this->_verifyPassword($newpass,$passconfirm)) { 757359e9417SChristopher Smith $changes['pass'] = $newpass; 758359e9417SChristopher Smith } else { 759359e9417SChristopher Smith return false; 760359e9417SChristopher Smith } 761359e9417SChristopher Smith } else { 762359e9417SChristopher Smith // no new password supplied, check if we need to generate one (or it stays unchanged) 763359e9417SChristopher Smith if ($INPUT->has('usernotify')) { 764359e9417SChristopher Smith $changes['pass'] = auth_pwgen($olduser); 765359e9417SChristopher Smith } 766359e9417SChristopher Smith } 7670440ff15Schris } 7680440ff15Schris 76940d72af6SChristopher Smith if (!empty($newname) && $this->_auth->canDo('modName') && $newname != $oldinfo['name']) { 770073766c6Smatthiasgrimm $changes['name'] = $newname; 77140d72af6SChristopher Smith } 77240d72af6SChristopher Smith if (!empty($newmail) && $this->_auth->canDo('modMail') && $newmail != $oldinfo['mail']) { 773073766c6Smatthiasgrimm $changes['mail'] = $newmail; 77440d72af6SChristopher Smith } 77540d72af6SChristopher Smith if (!empty($newgrps) && $this->_auth->canDo('modGroups') && $newgrps != $oldinfo['grps']) { 776073766c6Smatthiasgrimm $changes['grps'] = $newgrps; 77740d72af6SChristopher Smith } 7780440ff15Schris 7797d3c8d42SGabriel Birke if ($ok = $this->_auth->triggerUserMod('modify', array($olduser, $changes))) { 7800440ff15Schris msg($this->lang['update_ok'],1); 781a6858c6aSchris 7826ed3476bSChristopher Smith if ($INPUT->has('usernotify') && !empty($changes['pass'])) { 783a6858c6aSchris $notify = empty($changes['user']) ? $olduser : $newuser; 7846ed3476bSChristopher Smith $this->_notifyUser($notify,$changes['pass']); 785a6858c6aSchris } 786a6858c6aSchris 7879ec82636SAndreas Gohr // invalidate all sessions 7889ec82636SAndreas Gohr io_saveFile($conf['cachedir'].'/sessionpurge',time()); 7899ec82636SAndreas Gohr 7900440ff15Schris } else { 7910440ff15Schris msg($this->lang['update_fail'],-1); 7920440ff15Schris } 79378c7c8c9Schris 794a6858c6aSchris if (!empty($re_edit)) { 795a6858c6aSchris $this->_editUser($olduser); 7960440ff15Schris } 7970440ff15Schris 798a6858c6aSchris return $ok; 799a6858c6aSchris } 800a6858c6aSchris 801a6858c6aSchris /** 802c5a7c0c6SGerrit Uitslag * Send password change notification email 803c5a7c0c6SGerrit Uitslag * 804c5a7c0c6SGerrit Uitslag * @param string $user id of user 805c5a7c0c6SGerrit Uitslag * @param string $password plain text 806c5a7c0c6SGerrit Uitslag * @param bool $status_alert whether status alert should be shown 807c5a7c0c6SGerrit Uitslag * @return bool whether succesful 808a6858c6aSchris */ 8093712ca9aSGerrit Uitslag protected function _notifyUser($user, $password, $status_alert=true) { 810a6858c6aSchris 811a6858c6aSchris if ($sent = auth_sendPassword($user,$password)) { 812328143f8SChristopher Smith if ($status_alert) { 813a6858c6aSchris msg($this->lang['notify_ok'], 1); 814328143f8SChristopher Smith } 815a6858c6aSchris } else { 816328143f8SChristopher Smith if ($status_alert) { 817a6858c6aSchris msg($this->lang['notify_fail'], -1); 818a6858c6aSchris } 819328143f8SChristopher Smith } 820a6858c6aSchris 821a6858c6aSchris return $sent; 822a6858c6aSchris } 823a6858c6aSchris 824a6858c6aSchris /** 825359e9417SChristopher Smith * Verify password meets minimum requirements 826359e9417SChristopher Smith * :TODO: extend to support password strength 827359e9417SChristopher Smith * 828359e9417SChristopher Smith * @param string $password candidate string for new password 829359e9417SChristopher Smith * @param string $confirm repeated password for confirmation 830359e9417SChristopher Smith * @return bool true if meets requirements, false otherwise 831359e9417SChristopher Smith */ 832359e9417SChristopher Smith protected function _verifyPassword($password, $confirm) { 833be9008d3SChristopher Smith global $lang; 834359e9417SChristopher Smith 8352400ddcbSChristopher Smith if (empty($password) && empty($confirm)) { 836359e9417SChristopher Smith return false; 837359e9417SChristopher Smith } 838359e9417SChristopher Smith 839359e9417SChristopher Smith if ($password !== $confirm) { 840be9008d3SChristopher Smith msg($lang['regbadpass'], -1); 841359e9417SChristopher Smith return false; 842359e9417SChristopher Smith } 843359e9417SChristopher Smith 844359e9417SChristopher Smith // :TODO: test password for required strength 845359e9417SChristopher Smith 846359e9417SChristopher Smith // if we make it this far the password is good 847359e9417SChristopher Smith return true; 848359e9417SChristopher Smith } 849359e9417SChristopher Smith 850359e9417SChristopher Smith /** 851c5a7c0c6SGerrit Uitslag * Retrieve & clean user data from the form 852a6858c6aSchris * 853c5a7c0c6SGerrit Uitslag * @param bool $clean whether the cleanUser method of the authentication backend is applied 854a6858c6aSchris * @return array (user, password, full name, email, array(groups)) 8550440ff15Schris */ 8563712ca9aSGerrit Uitslag protected function _retrieveUser($clean=true) { 857c5a7c0c6SGerrit Uitslag /** @var DokuWiki_Auth_Plugin $auth */ 8587441e340SAndreas Gohr global $auth; 859fbfbbe8aSHakan Sandell global $INPUT; 8600440ff15Schris 86159bc3b48SGerrit Uitslag $user = array(); 862fbfbbe8aSHakan Sandell $user[0] = ($clean) ? $auth->cleanUser($INPUT->str('userid')) : $INPUT->str('userid'); 863fbfbbe8aSHakan Sandell $user[1] = $INPUT->str('userpass'); 864fbfbbe8aSHakan Sandell $user[2] = $INPUT->str('username'); 865fbfbbe8aSHakan Sandell $user[3] = $INPUT->str('usermail'); 866fbfbbe8aSHakan Sandell $user[4] = explode(',',$INPUT->str('usergroups')); 867359e9417SChristopher Smith $user[5] = $INPUT->str('userpass2'); // repeated password for confirmation 8680440ff15Schris 8697441e340SAndreas Gohr $user[4] = array_map('trim',$user[4]); 8707441e340SAndreas Gohr if($clean) $user[4] = array_map(array($auth,'cleanGroup'),$user[4]); 8717441e340SAndreas Gohr $user[4] = array_filter($user[4]); 8727441e340SAndreas Gohr $user[4] = array_unique($user[4]); 8737441e340SAndreas Gohr if(!count($user[4])) $user[4] = null; 8740440ff15Schris 8750440ff15Schris return $user; 8760440ff15Schris } 8770440ff15Schris 878c5a7c0c6SGerrit Uitslag /** 879c5a7c0c6SGerrit Uitslag * Set the filter with the current search terms or clear the filter 880c5a7c0c6SGerrit Uitslag * 881c5a7c0c6SGerrit Uitslag * @param string $op 'new' or 'clear' 882c5a7c0c6SGerrit Uitslag */ 8833712ca9aSGerrit Uitslag protected function _setFilter($op) { 8840440ff15Schris 8850440ff15Schris $this->_filter = array(); 8860440ff15Schris 8870440ff15Schris if ($op == 'new') { 88859bc3b48SGerrit Uitslag list($user,/* $pass */,$name,$mail,$grps) = $this->_retrieveUser(false); 8890440ff15Schris 8900440ff15Schris if (!empty($user)) $this->_filter['user'] = $user; 8910440ff15Schris if (!empty($name)) $this->_filter['name'] = $name; 8920440ff15Schris if (!empty($mail)) $this->_filter['mail'] = $mail; 8930440ff15Schris if (!empty($grps)) $this->_filter['grps'] = join('|',$grps); 8940440ff15Schris } 8950440ff15Schris } 8960440ff15Schris 897c5a7c0c6SGerrit Uitslag /** 898c5a7c0c6SGerrit Uitslag * Get the current search terms 899c5a7c0c6SGerrit Uitslag * 900c5a7c0c6SGerrit Uitslag * @return array 901c5a7c0c6SGerrit Uitslag */ 9023712ca9aSGerrit Uitslag protected function _retrieveFilter() { 903fbfbbe8aSHakan Sandell global $INPUT; 9040440ff15Schris 905fbfbbe8aSHakan Sandell $t_filter = $INPUT->arr('filter'); 9060440ff15Schris 9070440ff15Schris // messy, but this way we ensure we aren't getting any additional crap from malicious users 9080440ff15Schris $filter = array(); 9090440ff15Schris 9100440ff15Schris if (isset($t_filter['user'])) $filter['user'] = $t_filter['user']; 9110440ff15Schris if (isset($t_filter['name'])) $filter['name'] = $t_filter['name']; 9120440ff15Schris if (isset($t_filter['mail'])) $filter['mail'] = $t_filter['mail']; 9130440ff15Schris if (isset($t_filter['grps'])) $filter['grps'] = $t_filter['grps']; 9140440ff15Schris 9150440ff15Schris return $filter; 9160440ff15Schris } 9170440ff15Schris 918c5a7c0c6SGerrit Uitslag /** 919c5a7c0c6SGerrit Uitslag * Validate and improve the pagination values 920c5a7c0c6SGerrit Uitslag */ 9213712ca9aSGerrit Uitslag protected function _validatePagination() { 9220440ff15Schris 9230440ff15Schris if ($this->_start >= $this->_user_total) { 9240440ff15Schris $this->_start = $this->_user_total - $this->_pagesize; 9250440ff15Schris } 9260440ff15Schris if ($this->_start < 0) $this->_start = 0; 9270440ff15Schris 9280440ff15Schris $this->_last = min($this->_user_total, $this->_start + $this->_pagesize); 9290440ff15Schris } 9300440ff15Schris 931c5a7c0c6SGerrit Uitslag /** 932c5a7c0c6SGerrit Uitslag * Return an array of strings to enable/disable pagination buttons 933c5a7c0c6SGerrit Uitslag * 934c5a7c0c6SGerrit Uitslag * @return array with enable/disable attributes 9350440ff15Schris */ 9363712ca9aSGerrit Uitslag protected function _pagination() { 9370440ff15Schris 93851d94d49Schris $disabled = 'disabled="disabled"'; 93951d94d49Schris 94059bc3b48SGerrit Uitslag $buttons = array(); 94151d94d49Schris $buttons['start'] = $buttons['prev'] = ($this->_start == 0) ? $disabled : ''; 94251d94d49Schris 94351d94d49Schris if ($this->_user_total == -1) { 94451d94d49Schris $buttons['last'] = $disabled; 94551d94d49Schris $buttons['next'] = ''; 94651d94d49Schris } else { 947*64159a61SAndreas Gohr $buttons['last'] = $buttons['next'] = 948*64159a61SAndreas Gohr (($this->_start + $this->_pagesize) >= $this->_user_total) ? $disabled : ''; 94951d94d49Schris } 9500440ff15Schris 951462e9e37SMichael Große if ($this->_lastdisabled) { 952462e9e37SMichael Große $buttons['last'] = $disabled; 953462e9e37SMichael Große } 954462e9e37SMichael Große 9550440ff15Schris return $buttons; 9560440ff15Schris } 9575c967d3dSChristopher Smith 958c5a7c0c6SGerrit Uitslag /** 959c5a7c0c6SGerrit Uitslag * Export a list of users in csv format using the current filter criteria 9605c967d3dSChristopher Smith */ 9613712ca9aSGerrit Uitslag protected function _export() { 9625c967d3dSChristopher Smith // list of users for export - based on current filter criteria 9635c967d3dSChristopher Smith $user_list = $this->_auth->retrieveUsers(0, 0, $this->_filter); 9645c967d3dSChristopher Smith $column_headings = array( 9655c967d3dSChristopher Smith $this->lang["user_id"], 9665c967d3dSChristopher Smith $this->lang["user_name"], 9675c967d3dSChristopher Smith $this->lang["user_mail"], 9685c967d3dSChristopher Smith $this->lang["user_groups"] 9695c967d3dSChristopher Smith ); 9705c967d3dSChristopher Smith 9715c967d3dSChristopher Smith // ============================================================================================== 9725c967d3dSChristopher Smith // GENERATE OUTPUT 9735c967d3dSChristopher Smith // normal headers for downloading... 9745c967d3dSChristopher Smith header('Content-type: text/csv;charset=utf-8'); 9755c967d3dSChristopher Smith header('Content-Disposition: attachment; filename="wikiusers.csv"'); 9765c967d3dSChristopher Smith# // for debugging assistance, send as text plain to the browser 9775c967d3dSChristopher Smith# header('Content-type: text/plain;charset=utf-8'); 9785c967d3dSChristopher Smith 9795c967d3dSChristopher Smith // output the csv 9805c967d3dSChristopher Smith $fd = fopen('php://output','w'); 9815c967d3dSChristopher Smith fputcsv($fd, $column_headings); 9825c967d3dSChristopher Smith foreach ($user_list as $user => $info) { 9835c967d3dSChristopher Smith $line = array($user, $info['name'], $info['mail'], join(',',$info['grps'])); 9845c967d3dSChristopher Smith fputcsv($fd, $line); 9855c967d3dSChristopher Smith } 9865c967d3dSChristopher Smith fclose($fd); 987b2c01466SChristopher Smith if (defined('DOKU_UNITTEST')){ return; } 988b2c01466SChristopher Smith 9895c967d3dSChristopher Smith die; 9905c967d3dSChristopher Smith } 991ae1afd2fSChristopher Smith 992c5a7c0c6SGerrit Uitslag /** 993c5a7c0c6SGerrit Uitslag * Import a file of users in csv format 994ae1afd2fSChristopher Smith * 995ae1afd2fSChristopher Smith * csv file should have 4 columns, user_id, full name, email, groups (comma separated) 996c5a7c0c6SGerrit Uitslag * 9975ba64050SChristopher Smith * @return bool whether successful 998ae1afd2fSChristopher Smith */ 9993712ca9aSGerrit Uitslag protected function _import() { 1000ae1afd2fSChristopher Smith // check we are allowed to add users 1001ae1afd2fSChristopher Smith if (!checkSecurityToken()) return false; 1002ae1afd2fSChristopher Smith if (!$this->_auth->canDo('addUser')) return false; 1003ae1afd2fSChristopher Smith 1004ae1afd2fSChristopher Smith // check file uploaded ok. 1005*64159a61SAndreas Gohr if ( 1006*64159a61SAndreas Gohr empty($_FILES['import']['size']) || 1007*64159a61SAndreas Gohr !empty($_FILES['import']['error']) && $this->_isUploadedFile($_FILES['import']['tmp_name']) 1008*64159a61SAndreas Gohr ) { 1009ae1afd2fSChristopher Smith msg($this->lang['import_error_upload'],-1); 1010ae1afd2fSChristopher Smith return false; 1011ae1afd2fSChristopher Smith } 1012ae1afd2fSChristopher Smith // retrieve users from the file 1013ae1afd2fSChristopher Smith $this->_import_failures = array(); 1014ae1afd2fSChristopher Smith $import_success_count = 0; 1015ae1afd2fSChristopher Smith $import_fail_count = 0; 1016ae1afd2fSChristopher Smith $line = 0; 1017ae1afd2fSChristopher Smith $fd = fopen($_FILES['import']['tmp_name'],'r'); 1018ae1afd2fSChristopher Smith if ($fd) { 1019ae1afd2fSChristopher Smith while($csv = fgets($fd)){ 1020efcec72bSChristopher Smith if (!utf8_check($csv)) { 1021efcec72bSChristopher Smith $csv = utf8_encode($csv); 1022efcec72bSChristopher Smith } 1023d0c0a5c4SAnika Henke $raw = str_getcsv($csv); 1024ae1afd2fSChristopher Smith $error = ''; // clean out any errors from the previous line 1025ae1afd2fSChristopher Smith // data checks... 1026ae1afd2fSChristopher Smith if (1 == ++$line) { 1027ae1afd2fSChristopher Smith if ($raw[0] == 'user_id' || $raw[0] == $this->lang['user_id']) continue; // skip headers 1028ae1afd2fSChristopher Smith } 1029ae1afd2fSChristopher Smith if (count($raw) < 4) { // need at least four fields 1030ae1afd2fSChristopher Smith $import_fail_count++; 1031ae1afd2fSChristopher Smith $error = sprintf($this->lang['import_error_fields'], count($raw)); 1032ae1afd2fSChristopher Smith $this->_import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); 1033ae1afd2fSChristopher Smith continue; 1034ae1afd2fSChristopher Smith } 1035ae1afd2fSChristopher Smith array_splice($raw,1,0,auth_pwgen()); // splice in a generated password 1036ae1afd2fSChristopher Smith $clean = $this->_cleanImportUser($raw, $error); 1037ae1afd2fSChristopher Smith if ($clean && $this->_addImportUser($clean, $error)) { 1038328143f8SChristopher Smith $sent = $this->_notifyUser($clean[0],$clean[1],false); 1039328143f8SChristopher Smith if (!$sent){ 1040328143f8SChristopher Smith msg(sprintf($this->lang['import_notify_fail'],$clean[0],$clean[3]),-1); 1041328143f8SChristopher Smith } 1042ae1afd2fSChristopher Smith $import_success_count++; 1043ae1afd2fSChristopher Smith } else { 1044ae1afd2fSChristopher Smith $import_fail_count++; 1045e73725baSChristopher Smith array_splice($raw, 1, 1); // remove the spliced in password 1046ae1afd2fSChristopher Smith $this->_import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv); 1047ae1afd2fSChristopher Smith } 1048ae1afd2fSChristopher Smith } 1049*64159a61SAndreas Gohr msg( 1050*64159a61SAndreas Gohr sprintf( 1051*64159a61SAndreas Gohr $this->lang['import_success_count'], 1052*64159a61SAndreas Gohr ($import_success_count + $import_fail_count), 1053*64159a61SAndreas Gohr $import_success_count 1054*64159a61SAndreas Gohr ), 1055*64159a61SAndreas Gohr ($import_success_count ? 1 : -1) 1056*64159a61SAndreas Gohr ); 1057ae1afd2fSChristopher Smith if ($import_fail_count) { 1058ae1afd2fSChristopher Smith msg(sprintf($this->lang['import_failure_count'], $import_fail_count),-1); 1059ae1afd2fSChristopher Smith } 1060ae1afd2fSChristopher Smith } else { 1061ae1afd2fSChristopher Smith msg($this->lang['import_error_readfail'],-1); 1062ae1afd2fSChristopher Smith } 1063ae1afd2fSChristopher Smith 1064ae1afd2fSChristopher Smith // save import failures into the session 1065ae1afd2fSChristopher Smith if (!headers_sent()) { 1066ae1afd2fSChristopher Smith session_start(); 1067ae1afd2fSChristopher Smith $_SESSION['import_failures'] = $this->_import_failures; 1068ae1afd2fSChristopher Smith session_write_close(); 1069ae1afd2fSChristopher Smith } 1070c5a7c0c6SGerrit Uitslag return true; 1071ae1afd2fSChristopher Smith } 1072ae1afd2fSChristopher Smith 1073c5a7c0c6SGerrit Uitslag /** 1074786dfb0eSGerrit Uitslag * Returns cleaned user data 1075c5a7c0c6SGerrit Uitslag * 1076c5a7c0c6SGerrit Uitslag * @param array $candidate raw values of line from input file 1077253d4b48SGerrit Uitslag * @param string $error 1078253d4b48SGerrit Uitslag * @return array|false cleaned data or false 1079c5a7c0c6SGerrit Uitslag */ 10803712ca9aSGerrit Uitslag protected function _cleanImportUser($candidate, & $error){ 1081ae1afd2fSChristopher Smith global $INPUT; 1082ae1afd2fSChristopher Smith 1083ae1afd2fSChristopher Smith // kludgy .... 1084ae1afd2fSChristopher Smith $INPUT->set('userid', $candidate[0]); 1085ae1afd2fSChristopher Smith $INPUT->set('userpass', $candidate[1]); 1086ae1afd2fSChristopher Smith $INPUT->set('username', $candidate[2]); 1087ae1afd2fSChristopher Smith $INPUT->set('usermail', $candidate[3]); 1088ae1afd2fSChristopher Smith $INPUT->set('usergroups', $candidate[4]); 1089ae1afd2fSChristopher Smith 1090ae1afd2fSChristopher Smith $cleaned = $this->_retrieveUser(); 109159bc3b48SGerrit Uitslag list($user,/* $pass */,$name,$mail,/* $grps */) = $cleaned; 1092ae1afd2fSChristopher Smith if (empty($user)) { 1093ae1afd2fSChristopher Smith $error = $this->lang['import_error_baduserid']; 1094ae1afd2fSChristopher Smith return false; 1095ae1afd2fSChristopher Smith } 1096ae1afd2fSChristopher Smith 1097ae1afd2fSChristopher Smith // no need to check password, handled elsewhere 1098ae1afd2fSChristopher Smith 1099ae1afd2fSChristopher Smith if (!($this->_auth->canDo('modName') xor empty($name))){ 1100ae1afd2fSChristopher Smith $error = $this->lang['import_error_badname']; 1101ae1afd2fSChristopher Smith return false; 1102ae1afd2fSChristopher Smith } 1103ae1afd2fSChristopher Smith 1104328143f8SChristopher Smith if ($this->_auth->canDo('modMail')) { 1105328143f8SChristopher Smith if (empty($mail) || !mail_isvalid($mail)) { 1106ae1afd2fSChristopher Smith $error = $this->lang['import_error_badmail']; 1107ae1afd2fSChristopher Smith return false; 1108ae1afd2fSChristopher Smith } 1109328143f8SChristopher Smith } else { 1110328143f8SChristopher Smith if (!empty($mail)) { 1111328143f8SChristopher Smith $error = $this->lang['import_error_badmail']; 1112328143f8SChristopher Smith return false; 1113328143f8SChristopher Smith } 1114328143f8SChristopher Smith } 1115ae1afd2fSChristopher Smith 1116ae1afd2fSChristopher Smith return $cleaned; 1117ae1afd2fSChristopher Smith } 1118ae1afd2fSChristopher Smith 1119c5a7c0c6SGerrit Uitslag /** 1120c5a7c0c6SGerrit Uitslag * Adds imported user to auth backend 1121c5a7c0c6SGerrit Uitslag * 1122c5a7c0c6SGerrit Uitslag * Required a check of canDo('addUser') before 1123c5a7c0c6SGerrit Uitslag * 1124c5a7c0c6SGerrit Uitslag * @param array $user data of user 1125c5a7c0c6SGerrit Uitslag * @param string &$error reference catched error message 11265ba64050SChristopher Smith * @return bool whether successful 1127c5a7c0c6SGerrit Uitslag */ 11283712ca9aSGerrit Uitslag protected function _addImportUser($user, & $error){ 1129ae1afd2fSChristopher Smith if (!$this->_auth->triggerUserMod('create', $user)) { 1130ae1afd2fSChristopher Smith $error = $this->lang['import_error_create']; 1131ae1afd2fSChristopher Smith return false; 1132ae1afd2fSChristopher Smith } 1133ae1afd2fSChristopher Smith 1134ae1afd2fSChristopher Smith return true; 1135ae1afd2fSChristopher Smith } 1136ae1afd2fSChristopher Smith 1137c5a7c0c6SGerrit Uitslag /** 1138c5a7c0c6SGerrit Uitslag * Downloads failures as csv file 1139c5a7c0c6SGerrit Uitslag */ 11403712ca9aSGerrit Uitslag protected function _downloadImportFailures(){ 1141ae1afd2fSChristopher Smith 1142ae1afd2fSChristopher Smith // ============================================================================================== 1143ae1afd2fSChristopher Smith // GENERATE OUTPUT 1144ae1afd2fSChristopher Smith // normal headers for downloading... 1145ae1afd2fSChristopher Smith header('Content-type: text/csv;charset=utf-8'); 1146ae1afd2fSChristopher Smith header('Content-Disposition: attachment; filename="importfails.csv"'); 1147ae1afd2fSChristopher Smith# // for debugging assistance, send as text plain to the browser 1148ae1afd2fSChristopher Smith# header('Content-type: text/plain;charset=utf-8'); 1149ae1afd2fSChristopher Smith 1150ae1afd2fSChristopher Smith // output the csv 1151ae1afd2fSChristopher Smith $fd = fopen('php://output','w'); 1152c5a7c0c6SGerrit Uitslag foreach ($this->_import_failures as $fail) { 1153ae1afd2fSChristopher Smith fputs($fd, $fail['orig']); 1154ae1afd2fSChristopher Smith } 1155ae1afd2fSChristopher Smith fclose($fd); 1156ae1afd2fSChristopher Smith die; 1157ae1afd2fSChristopher Smith } 1158ae1afd2fSChristopher Smith 1159b2c01466SChristopher Smith /** 1160b2c01466SChristopher Smith * wrapper for is_uploaded_file to facilitate overriding by test suite 1161253d4b48SGerrit Uitslag * 1162253d4b48SGerrit Uitslag * @param string $file filename 1163253d4b48SGerrit Uitslag * @return bool 1164b2c01466SChristopher Smith */ 1165b2c01466SChristopher Smith protected function _isUploadedFile($file) { 1166b2c01466SChristopher Smith return is_uploaded_file($file); 1167b2c01466SChristopher Smith } 11680440ff15Schris} 1169