xref: /dokuwiki/lib/plugins/usermanager/admin.php (revision 3a97d936870170491bdd7d03d71143143b10191d)
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 */
130440ff15Schris
140440ff15Schris/**
150440ff15Schris * All DokuWiki plugins to extend the admin function
160440ff15Schris * need to inherit from this class
170440ff15Schris */
18*3a97d936SAndreas Gohrclass admin_plugin_usermanager extends DokuWiki_Admin_Plugin
19*3a97d936SAndreas Gohr{
20*3a97d936SAndreas Gohr    const IMAGE_DIR = DOKU_BASE.'lib/plugins/usermanager/images/';
210440ff15Schris
22*3a97d936SAndreas Gohr    protected $auth = null;        // auth object
23*3a97d936SAndreas Gohr    protected $users_total = 0;     // number of registered users
24*3a97d936SAndreas Gohr    protected $filter = array();   // user selection filter(s)
25*3a97d936SAndreas Gohr    protected $start = 0;          // index of first user to be displayed
26*3a97d936SAndreas Gohr    protected $last = 0;           // index of the last user to be displayed
27*3a97d936SAndreas Gohr    protected $pagesize = 20;      // number of users to list on one page
28*3a97d936SAndreas Gohr    protected $edit_user = '';     // set to user selected for editing
29*3a97d936SAndreas Gohr    protected $edit_userdata = array();
30*3a97d936SAndreas Gohr    protected $disabled = '';      // if disabled set to explanatory string
31*3a97d936SAndreas Gohr    protected $import_failures = array();
32*3a97d936SAndreas Gohr    protected $lastdisabled = false; // set to true if last user is unknown and last button is hence buggy
330440ff15Schris
340440ff15Schris    /**
350440ff15Schris     * Constructor
360440ff15Schris     */
37*3a97d936SAndreas Gohr    public function __construct()
38*3a97d936SAndreas Gohr    {
39c5a7c0c6SGerrit Uitslag        /** @var DokuWiki_Auth_Plugin $auth */
400440ff15Schris        global $auth;
410440ff15Schris
420440ff15Schris        $this->setupLocale();
4351d94d49Schris
4451d94d49Schris        if (!isset($auth)) {
45*3a97d936SAndreas Gohr            $this->disabled = $this->lang['noauth'];
4682fd59b6SAndreas Gohr        } elseif (!$auth->canDo('getUsers')) {
47*3a97d936SAndreas Gohr            $this->disabled = $this->lang['nosupport'];
4851d94d49Schris        } else {
4951d94d49Schris            // we're good to go
50*3a97d936SAndreas Gohr            $this->auth = & $auth;
5151d94d49Schris        }
52ae1afd2fSChristopher Smith
53ae1afd2fSChristopher Smith        // attempt to retrieve any import failures from the session
540e80bb5eSChristopher Smith        if (!empty($_SESSION['import_failures'])) {
55*3a97d936SAndreas Gohr            $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     */
65*3a97d936SAndreas Gohr    public function getMenuText($language)
66*3a97d936SAndreas Gohr    {
670440ff15Schris
68*3a97d936SAndreas Gohr        if (!is_null($this->auth))
690440ff15Schris          return parent::getMenuText($language);
700440ff15Schris
71*3a97d936SAndreas Gohr        return $this->getLang('menu').' '.$this->disabled;
720440ff15Schris    }
730440ff15Schris
740440ff15Schris    /**
750440ff15Schris     * return sort order for position in admin menu
76253d4b48SGerrit Uitslag     *
77253d4b48SGerrit Uitslag     * @return int
780440ff15Schris     */
79*3a97d936SAndreas Gohr    public function getMenuSort()
80*3a97d936SAndreas Gohr    {
810440ff15Schris        return 2;
820440ff15Schris    }
830440ff15Schris
840440ff15Schris    /**
8567a31a83SMichael Große     * @return int current start value for pageination
8667a31a83SMichael Große     */
87*3a97d936SAndreas Gohr    public function getStart()
88*3a97d936SAndreas Gohr    {
89*3a97d936SAndreas Gohr        return $this->start;
9067a31a83SMichael Große    }
9167a31a83SMichael Große
9267a31a83SMichael Große    /**
9367a31a83SMichael Große     * @return int number of users per page
9467a31a83SMichael Große     */
95*3a97d936SAndreas Gohr    public function getPagesize()
96*3a97d936SAndreas Gohr    {
97*3a97d936SAndreas Gohr        return $this->pagesize;
9867a31a83SMichael Große    }
9967a31a83SMichael Große
10067a31a83SMichael Große    /**
101462e9e37SMichael Große     * @param boolean $lastdisabled
102462e9e37SMichael Große     */
103*3a97d936SAndreas Gohr    public function setLastdisabled($lastdisabled)
104*3a97d936SAndreas Gohr    {
105*3a97d936SAndreas Gohr        $this->lastdisabled = $lastdisabled;
106462e9e37SMichael Große    }
107462e9e37SMichael Große
108462e9e37SMichael Große    /**
109c5a7c0c6SGerrit Uitslag     * Handle user request
110253d4b48SGerrit Uitslag     *
111253d4b48SGerrit Uitslag     * @return bool
1120440ff15Schris     */
113*3a97d936SAndreas Gohr    public function handle()
114*3a97d936SAndreas Gohr    {
11500d58927SMichael Hamann        global $INPUT;
116*3a97d936SAndreas Gohr        if (is_null($this->auth)) return false;
1170440ff15Schris
1180440ff15Schris        // extract the command and any specific parameters
1190440ff15Schris        // submit button name is of the form - fn[cmd][param(s)]
12000d58927SMichael Hamann        $fn   = $INPUT->param('fn');
1210440ff15Schris
1220440ff15Schris        if (is_array($fn)) {
1230440ff15Schris            $cmd = key($fn);
1240440ff15Schris            $param = is_array($fn[$cmd]) ? key($fn[$cmd]) : null;
1250440ff15Schris        } else {
1260440ff15Schris            $cmd = $fn;
1270440ff15Schris            $param = null;
1280440ff15Schris        }
1290440ff15Schris
1300440ff15Schris        if ($cmd != "search") {
131*3a97d936SAndreas Gohr            $this->start = $INPUT->int('start', 0);
132*3a97d936SAndreas Gohr            $this->filter = $this->retrieveFilter();
1330440ff15Schris        }
1340440ff15Schris
1350440ff15Schris        switch ($cmd) {
136*3a97d936SAndreas Gohr            case "add":
137*3a97d936SAndreas Gohr                $this->addUser();
1380440ff15Schris                break;
139*3a97d936SAndreas Gohr            case "delete":
140*3a97d936SAndreas Gohr                $this->deleteUser();
141*3a97d936SAndreas Gohr                break;
142*3a97d936SAndreas Gohr            case "modify":
143*3a97d936SAndreas Gohr                $this->modifyUser();
144*3a97d936SAndreas Gohr                break;
145*3a97d936SAndreas Gohr            case "edit":
146*3a97d936SAndreas Gohr                $this->editUser($param);
147*3a97d936SAndreas Gohr                break;
148*3a97d936SAndreas Gohr            case "search":
149*3a97d936SAndreas Gohr                $this->setFilter($param);
150*3a97d936SAndreas Gohr                            $this->start = 0;
151*3a97d936SAndreas Gohr                break;
152*3a97d936SAndreas Gohr            case "export":
153*3a97d936SAndreas Gohr                $this->exportCSV();
154*3a97d936SAndreas Gohr                break;
155*3a97d936SAndreas Gohr            case "import":
156*3a97d936SAndreas Gohr                $this->importCSV();
157*3a97d936SAndreas Gohr                break;
158*3a97d936SAndreas Gohr            case "importfails":
159*3a97d936SAndreas Gohr                $this->downloadImportFailures();
160*3a97d936SAndreas Gohr                break;
1610440ff15Schris        }
1620440ff15Schris
163*3a97d936SAndreas Gohr        $this->users_total = $this->auth->canDo('getUserCount') ? $this->auth->getUserCount($this->filter) : -1;
1640440ff15Schris
1650440ff15Schris        // page handling
1660440ff15Schris        switch ($cmd) {
167*3a97d936SAndreas Gohr            case 'start':
168*3a97d936SAndreas Gohr                $this->start = 0;
169*3a97d936SAndreas Gohr                break;
170*3a97d936SAndreas Gohr            case 'prev':
171*3a97d936SAndreas Gohr                $this->start -= $this->pagesize;
172*3a97d936SAndreas Gohr                break;
173*3a97d936SAndreas Gohr            case 'next':
174*3a97d936SAndreas Gohr                $this->start += $this->pagesize;
175*3a97d936SAndreas Gohr                break;
176*3a97d936SAndreas Gohr            case 'last':
177*3a97d936SAndreas Gohr                $this->start = $this->users_total;
178*3a97d936SAndreas Gohr                break;
1790440ff15Schris        }
180*3a97d936SAndreas Gohr        $this->validatePagination();
181c5a7c0c6SGerrit Uitslag        return true;
1820440ff15Schris    }
1830440ff15Schris
1840440ff15Schris    /**
185c5a7c0c6SGerrit Uitslag     * Output appropriate html
186253d4b48SGerrit Uitslag     *
187253d4b48SGerrit Uitslag     * @return bool
1880440ff15Schris     */
189*3a97d936SAndreas Gohr    public function html()
190*3a97d936SAndreas Gohr    {
1910440ff15Schris        global $ID;
1920440ff15Schris
193*3a97d936SAndreas Gohr        if (is_null($this->auth)) {
1940440ff15Schris            print $this->lang['badauth'];
1950440ff15Schris            return false;
1960440ff15Schris        }
1970440ff15Schris
198*3a97d936SAndreas Gohr        $user_list = $this->auth->retrieveUsers($this->start, $this->pagesize, $this->filter);
1990440ff15Schris
200*3a97d936SAndreas Gohr        $page_buttons = $this->pagination();
201*3a97d936SAndreas Gohr        $delete_disable = $this->auth->canDo('delUser') ? '' : 'disabled="disabled"';
2020440ff15Schris
203*3a97d936SAndreas Gohr        $editable = $this->auth->canDo('UserMod');
204*3a97d936SAndreas Gohr        $export_label = empty($this->filter) ? $this->lang['export_all'] : $this->lang['export_filtered'];
2056154103cSmatthiasgrimm
2060440ff15Schris        print $this->locale_xhtml('intro');
2070440ff15Schris        print $this->locale_xhtml('list');
2080440ff15Schris
20958dde80dSAnika Henke        ptln("<div id=\"user__manager\">");
21058dde80dSAnika Henke        ptln("<div class=\"level2\">");
2110440ff15Schris
212*3a97d936SAndreas Gohr        if ($this->users_total > 0) {
21364159a61SAndreas Gohr            ptln(
21464159a61SAndreas Gohr                "<p>" . sprintf(
21564159a61SAndreas Gohr                    $this->lang['summary'],
216*3a97d936SAndreas Gohr                    $this->start + 1,
217*3a97d936SAndreas Gohr                    $this->last,
218*3a97d936SAndreas Gohr                    $this->users_total,
219*3a97d936SAndreas Gohr                    $this->auth->getUserCount()
22064159a61SAndreas Gohr                ) . "</p>"
22164159a61SAndreas Gohr            );
2220440ff15Schris        } else {
223*3a97d936SAndreas Gohr            if ($this->users_total < 0) {
224a102b175SGerrit Uitslag                $allUserTotal = 0;
225a102b175SGerrit Uitslag            } else {
226*3a97d936SAndreas Gohr                $allUserTotal = $this->auth->getUserCount();
227a102b175SGerrit Uitslag            }
228a102b175SGerrit Uitslag            ptln("<p>".sprintf($this->lang['nonefound'], $allUserTotal)."</p>");
2290440ff15Schris        }
2300440ff15Schris        ptln("<form action=\"".wl($ID)."\" method=\"post\">");
231634d7150SAndreas Gohr        formSecurityToken();
232c7b28ffdSAnika Henke        ptln("  <div class=\"table\">");
2330440ff15Schris        ptln("  <table class=\"inline\">");
2340440ff15Schris        ptln("    <thead>");
2350440ff15Schris        ptln("      <tr>");
23664159a61SAndreas Gohr        ptln("        <th>&#160;</th>
23764159a61SAndreas Gohr            <th>".$this->lang["user_id"]."</th>
23864159a61SAndreas Gohr            <th>".$this->lang["user_name"]."</th>
23964159a61SAndreas Gohr            <th>".$this->lang["user_mail"]."</th>
24064159a61SAndreas Gohr            <th>".$this->lang["user_groups"]."</th>");
2410440ff15Schris        ptln("      </tr>");
2420440ff15Schris
2430440ff15Schris        ptln("      <tr>");
24464159a61SAndreas Gohr        ptln("        <td class=\"rightalign\"><input type=\"image\" src=\"".
245*3a97d936SAndreas Gohr             self::IMAGE_DIR."search.png\" name=\"fn[search][new]\" title=\"".
24664159a61SAndreas Gohr             $this->lang['search_prompt']."\" alt=\"".$this->lang['search']."\" class=\"button\" /></td>");
24764159a61SAndreas Gohr        ptln("        <td><input type=\"text\" name=\"userid\" class=\"edit\" value=\"".
248*3a97d936SAndreas Gohr             $this->htmlFilter('user')."\" /></td>");
24964159a61SAndreas Gohr        ptln("        <td><input type=\"text\" name=\"username\" class=\"edit\" value=\"".
250*3a97d936SAndreas Gohr             $this->htmlFilter('name')."\" /></td>");
25164159a61SAndreas Gohr        ptln("        <td><input type=\"text\" name=\"usermail\" class=\"edit\" value=\"".
252*3a97d936SAndreas Gohr             $this->htmlFilter('mail')."\" /></td>");
25364159a61SAndreas Gohr        ptln("        <td><input type=\"text\" name=\"usergroups\" class=\"edit\" value=\"".
254*3a97d936SAndreas Gohr             $this->htmlFilter('grps')."\" /></td>");
2550440ff15Schris        ptln("      </tr>");
2560440ff15Schris        ptln("    </thead>");
2570440ff15Schris
258*3a97d936SAndreas Gohr        if ($this->users_total) {
2590440ff15Schris            ptln("    <tbody>");
2600440ff15Schris            foreach ($user_list as $user => $userinfo) {
2610440ff15Schris                extract($userinfo);
262c5a7c0c6SGerrit Uitslag                /**
263c5a7c0c6SGerrit Uitslag                 * @var string $name
264c5a7c0c6SGerrit Uitslag                 * @var string $pass
265c5a7c0c6SGerrit Uitslag                 * @var string $mail
266c5a7c0c6SGerrit Uitslag                 * @var array  $grps
267c5a7c0c6SGerrit Uitslag                 */
2680440ff15Schris                $groups = join(', ', $grps);
269a2c0246eSAnika Henke                ptln("    <tr class=\"user_info\">");
27064159a61SAndreas Gohr                ptln("      <td class=\"centeralign\"><input type=\"checkbox\" name=\"delete[".hsc($user).
27164159a61SAndreas Gohr                     "]\" ".$delete_disable." /></td>");
2722365d73dSAnika Henke                if ($editable) {
273f23f9594SAndreas Gohr                    ptln("    <td><a href=\"".wl($ID, array('fn[edit]['.$user.']' => 1,
27477d19185SAndreas Gohr                                                           'do' => 'admin',
27577d19185SAndreas Gohr                                                           'page' => 'usermanager',
27677d19185SAndreas Gohr                                                           'sectok' => getSecurityToken())).
27777d19185SAndreas Gohr                         "\" title=\"".$this->lang['edit_prompt']."\">".hsc($user)."</a></td>");
2782365d73dSAnika Henke                } else {
2792365d73dSAnika Henke                    ptln("    <td>".hsc($user)."</td>");
2802365d73dSAnika Henke                }
2812365d73dSAnika Henke                ptln("      <td>".hsc($name)."</td><td>".hsc($mail)."</td><td>".hsc($groups)."</td>");
2820440ff15Schris                ptln("    </tr>");
2830440ff15Schris            }
2840440ff15Schris            ptln("    </tbody>");
2850440ff15Schris        }
2860440ff15Schris
2870440ff15Schris        ptln("    <tbody>");
2882365d73dSAnika Henke        ptln("      <tr><td colspan=\"5\" class=\"centeralign\">");
289a2c0246eSAnika Henke        ptln("        <span class=\"medialeft\">");
29064159a61SAndreas Gohr        ptln("          <button type=\"submit\" name=\"fn[delete]\" id=\"usrmgr__del\" ".$delete_disable.">".
29164159a61SAndreas Gohr             $this->lang['delete_selected']."</button>");
29276c49356SMike Wilmes        ptln("        </span>");
29376c49356SMike Wilmes        ptln("        <span class=\"mediaright\">");
29464159a61SAndreas Gohr        ptln("          <button type=\"submit\" name=\"fn[start]\" ".$page_buttons['start'].">".
29564159a61SAndreas Gohr             $this->lang['start']."</button>");
29664159a61SAndreas Gohr        ptln("          <button type=\"submit\" name=\"fn[prev]\" ".$page_buttons['prev'].">".
29764159a61SAndreas Gohr             $this->lang['prev']."</button>");
29864159a61SAndreas Gohr        ptln("          <button type=\"submit\" name=\"fn[next]\" ".$page_buttons['next'].">".
29964159a61SAndreas Gohr             $this->lang['next']."</button>");
30064159a61SAndreas Gohr        ptln("          <button type=\"submit\" name=\"fn[last]\" ".$page_buttons['last'].">".
30164159a61SAndreas Gohr             $this->lang['last']."</button>");
30276c49356SMike Wilmes        ptln("        </span>");
303*3a97d936SAndreas Gohr        if (!empty($this->filter)) {
304ae614416SAnika Henke            ptln("    <button type=\"submit\" name=\"fn[search][clear]\">".$this->lang['clear']."</button>");
3055c967d3dSChristopher Smith        }
306ae614416SAnika Henke        ptln("        <button type=\"submit\" name=\"fn[export]\">".$export_label."</button>");
3075164d9c9SAnika Henke        ptln("        <input type=\"hidden\" name=\"do\"    value=\"admin\" />");
3085164d9c9SAnika Henke        ptln("        <input type=\"hidden\" name=\"page\"  value=\"usermanager\" />");
309daf4ca4eSAnika Henke
310*3a97d936SAndreas Gohr        $this->htmlFilterSettings(2);
311daf4ca4eSAnika Henke
3120440ff15Schris        ptln("      </td></tr>");
3130440ff15Schris        ptln("    </tbody>");
3140440ff15Schris        ptln("  </table>");
315c7b28ffdSAnika Henke        ptln("  </div>");
3160440ff15Schris
3170440ff15Schris        ptln("</form>");
3180440ff15Schris        ptln("</div>");
3190440ff15Schris
320*3a97d936SAndreas Gohr        $style = $this->edit_user ? " class=\"edit_user\"" : "";
3210440ff15Schris
322*3a97d936SAndreas Gohr        if ($this->auth->canDo('addUser')) {
3230440ff15Schris            ptln("<div".$style.">");
3240440ff15Schris            print $this->locale_xhtml('add');
3250440ff15Schris            ptln("  <div class=\"level2\">");
3260440ff15Schris
327*3a97d936SAndreas Gohr            $this->htmlUserForm('add', null, array(), 4);
3280440ff15Schris
3290440ff15Schris            ptln("  </div>");
3300440ff15Schris            ptln("</div>");
3310440ff15Schris        }
3320440ff15Schris
333*3a97d936SAndreas Gohr        if ($this->edit_user  && $this->auth->canDo('UserMod')) {
334c632fc69SAndreas Gohr            ptln("<div".$style." id=\"scroll__here\">");
3350440ff15Schris            print $this->locale_xhtml('edit');
3360440ff15Schris            ptln("  <div class=\"level2\">");
3370440ff15Schris
338*3a97d936SAndreas Gohr            $this->htmlUserForm('modify', $this->edit_user, $this->edit_userdata, 4);
3390440ff15Schris
3400440ff15Schris            ptln("  </div>");
3410440ff15Schris            ptln("</div>");
3420440ff15Schris        }
343ae1afd2fSChristopher Smith
344*3a97d936SAndreas Gohr        if ($this->auth->canDo('addUser')) {
345*3a97d936SAndreas Gohr            $this->htmlImportForm();
346ae1afd2fSChristopher Smith        }
34758dde80dSAnika Henke        ptln("</div>");
348c5a7c0c6SGerrit Uitslag        return true;
3490440ff15Schris    }
3500440ff15Schris
35182fd59b6SAndreas Gohr    /**
352c5a7c0c6SGerrit Uitslag     * Display form to add or modify a user
353c5a7c0c6SGerrit Uitslag     *
354c5a7c0c6SGerrit Uitslag     * @param string $cmd 'add' or 'modify'
355c5a7c0c6SGerrit Uitslag     * @param string $user id of user
356c5a7c0c6SGerrit Uitslag     * @param array  $userdata array with name, mail, pass and grps
357c5a7c0c6SGerrit Uitslag     * @param int    $indent
35882fd59b6SAndreas Gohr     */
359*3a97d936SAndreas Gohr    protected function htmlUserForm($cmd, $user = '', $userdata = array(), $indent = 0)
360*3a97d936SAndreas Gohr    {
361a6858c6aSchris        global $conf;
362bb4866bdSchris        global $ID;
363be9008d3SChristopher Smith        global $lang;
36478c7c8c9Schris
36578c7c8c9Schris        $name = $mail = $groups = '';
366a6858c6aSchris        $notes = array();
3670440ff15Schris
3680440ff15Schris        if ($user) {
36978c7c8c9Schris            extract($userdata);
37078c7c8c9Schris            if (!empty($grps)) $groups = join(',', $grps);
371a6858c6aSchris        } else {
372a6858c6aSchris            $notes[] = sprintf($this->lang['note_group'], $conf['defaultgroup']);
3730440ff15Schris        }
3740440ff15Schris
3750440ff15Schris        ptln("<form action=\"".wl($ID)."\" method=\"post\">", $indent);
376634d7150SAndreas Gohr        formSecurityToken();
377c7b28ffdSAnika Henke        ptln("  <div class=\"table\">", $indent);
3780440ff15Schris        ptln("  <table class=\"inline\">", $indent);
3790440ff15Schris        ptln("    <thead>", $indent);
3800440ff15Schris        ptln("      <tr><th>".$this->lang["field"]."</th><th>".$this->lang["value"]."</th></tr>", $indent);
3810440ff15Schris        ptln("    </thead>", $indent);
3820440ff15Schris        ptln("    <tbody>", $indent);
38326fb387bSchris
384*3a97d936SAndreas Gohr        $this->htmlInputField(
38564159a61SAndreas Gohr            $cmd . "_userid",
38664159a61SAndreas Gohr            "userid",
38764159a61SAndreas Gohr            $this->lang["user_id"],
38864159a61SAndreas Gohr            $user,
389*3a97d936SAndreas Gohr            $this->auth->canDo("modLogin"),
39064159a61SAndreas Gohr            true,
39164159a61SAndreas Gohr            $indent + 6
39264159a61SAndreas Gohr        );
393*3a97d936SAndreas Gohr        $this->htmlInputField(
39464159a61SAndreas Gohr            $cmd . "_userpass",
39564159a61SAndreas Gohr            "userpass",
39664159a61SAndreas Gohr            $this->lang["user_pass"],
39764159a61SAndreas Gohr            "",
398*3a97d936SAndreas Gohr            $this->auth->canDo("modPass"),
39964159a61SAndreas Gohr            false,
40064159a61SAndreas Gohr            $indent + 6
40164159a61SAndreas Gohr        );
402*3a97d936SAndreas Gohr        $this->htmlInputField(
40364159a61SAndreas Gohr            $cmd . "_userpass2",
40464159a61SAndreas Gohr            "userpass2",
40564159a61SAndreas Gohr            $lang["passchk"],
40664159a61SAndreas Gohr            "",
407*3a97d936SAndreas Gohr            $this->auth->canDo("modPass"),
40864159a61SAndreas Gohr            false,
40964159a61SAndreas Gohr            $indent + 6
41064159a61SAndreas Gohr        );
411*3a97d936SAndreas Gohr        $this->htmlInputField(
41264159a61SAndreas Gohr            $cmd . "_username",
41364159a61SAndreas Gohr            "username",
41464159a61SAndreas Gohr            $this->lang["user_name"],
41564159a61SAndreas Gohr            $name,
416*3a97d936SAndreas Gohr            $this->auth->canDo("modName"),
41764159a61SAndreas Gohr            true,
41864159a61SAndreas Gohr            $indent + 6
41964159a61SAndreas Gohr        );
420*3a97d936SAndreas Gohr        $this->htmlInputField(
42164159a61SAndreas Gohr            $cmd . "_usermail",
42264159a61SAndreas Gohr            "usermail",
42364159a61SAndreas Gohr            $this->lang["user_mail"],
42464159a61SAndreas Gohr            $mail,
425*3a97d936SAndreas Gohr            $this->auth->canDo("modMail"),
42664159a61SAndreas Gohr            true,
42764159a61SAndreas Gohr            $indent + 6
42864159a61SAndreas Gohr        );
429*3a97d936SAndreas Gohr        $this->htmlInputField(
43064159a61SAndreas Gohr            $cmd . "_usergroups",
43164159a61SAndreas Gohr            "usergroups",
43264159a61SAndreas Gohr            $this->lang["user_groups"],
43364159a61SAndreas Gohr            $groups,
434*3a97d936SAndreas Gohr            $this->auth->canDo("modGroups"),
43564159a61SAndreas Gohr            false,
43664159a61SAndreas Gohr            $indent + 6
43764159a61SAndreas Gohr        );
43826fb387bSchris
439*3a97d936SAndreas Gohr        if ($this->auth->canDo("modPass")) {
440ee9498f5SChristopher Smith            if ($cmd == 'add') {
441c3f4fb63SGina Haeussge                $notes[] = $this->lang['note_pass'];
442ee9498f5SChristopher Smith            }
443a6858c6aSchris            if ($user) {
444a6858c6aSchris                $notes[] = $this->lang['note_notify'];
445a6858c6aSchris            }
446a6858c6aSchris
44764159a61SAndreas Gohr            ptln("<tr><td><label for=\"".$cmd."_usernotify\" >".
44864159a61SAndreas Gohr                 $this->lang["user_notify"].": </label></td>
44964159a61SAndreas Gohr                 <td><input type=\"checkbox\" id=\"".$cmd."_usernotify\" name=\"usernotify\" value=\"1\" />
45064159a61SAndreas Gohr                 </td></tr>", $indent);
451a6858c6aSchris        }
452a6858c6aSchris
4530440ff15Schris        ptln("    </tbody>", $indent);
4540440ff15Schris        ptln("    <tbody>", $indent);
4550440ff15Schris        ptln("      <tr>", $indent);
4560440ff15Schris        ptln("        <td colspan=\"2\">", $indent);
4570440ff15Schris        ptln("          <input type=\"hidden\" name=\"do\"    value=\"admin\" />", $indent);
4580440ff15Schris        ptln("          <input type=\"hidden\" name=\"page\"  value=\"usermanager\" />", $indent);
4590440ff15Schris
4600440ff15Schris        // save current $user, we need this to access details if the name is changed
4610440ff15Schris        if ($user)
462f23f9594SAndreas Gohr          ptln("          <input type=\"hidden\" name=\"userid_old\"  value=\"".hsc($user)."\" />", $indent);
4630440ff15Schris
464*3a97d936SAndreas Gohr        $this->htmlFilterSettings($indent+10);
4650440ff15Schris
466ae614416SAnika Henke        ptln("          <button type=\"submit\" name=\"fn[".$cmd."]\">".$this->lang[$cmd]."</button>", $indent);
4670440ff15Schris        ptln("        </td>", $indent);
4680440ff15Schris        ptln("      </tr>", $indent);
4690440ff15Schris        ptln("    </tbody>", $indent);
4700440ff15Schris        ptln("  </table>", $indent);
47145c19902SChristopher Smith
47245c19902SChristopher Smith        if ($notes) {
47345c19902SChristopher Smith            ptln("    <ul class=\"notes\">");
47445c19902SChristopher Smith            foreach ($notes as $note) {
475ae614416SAnika Henke                ptln("      <li><span class=\"li\">".$note."</li>", $indent);
47645c19902SChristopher Smith            }
47745c19902SChristopher Smith            ptln("    </ul>");
47845c19902SChristopher Smith        }
479c7b28ffdSAnika Henke        ptln("  </div>", $indent);
4800440ff15Schris        ptln("</form>", $indent);
4810440ff15Schris    }
4820440ff15Schris
483c5a7c0c6SGerrit Uitslag    /**
484c5a7c0c6SGerrit Uitslag     * Prints a inputfield
485c5a7c0c6SGerrit Uitslag     *
486c5a7c0c6SGerrit Uitslag     * @param string $id
487c5a7c0c6SGerrit Uitslag     * @param string $name
488c5a7c0c6SGerrit Uitslag     * @param string $label
489c5a7c0c6SGerrit Uitslag     * @param string $value
490c5a7c0c6SGerrit Uitslag     * @param bool   $cando whether auth backend is capable to do this action
4919b82d43fSAndreas Gohr     * @param bool   $required is this field required?
492c5a7c0c6SGerrit Uitslag     * @param int $indent
493c5a7c0c6SGerrit Uitslag     */
494*3a97d936SAndreas Gohr    protected function htmlInputField($id, $name, $label, $value, $cando, $required, $indent = 0)
495*3a97d936SAndreas Gohr    {
4967de12fceSAndreas Gohr        $class = $cando ? '' : ' class="disabled"';
4977de12fceSAndreas Gohr        echo str_pad('', $indent);
4987de12fceSAndreas Gohr
499359e9417SChristopher Smith        if ($name == 'userpass' || $name == 'userpass2') {
500d796a891SAndreas Gohr            $fieldtype = 'password';
501d796a891SAndreas Gohr            $autocomp  = 'autocomplete="off"';
5027b3674bdSChristopher Smith        } elseif ($name == 'usermail') {
5037b3674bdSChristopher Smith            $fieldtype = 'email';
5047b3674bdSChristopher Smith            $autocomp  = '';
505d796a891SAndreas Gohr        } else {
506d796a891SAndreas Gohr            $fieldtype = 'text';
507d796a891SAndreas Gohr            $autocomp  = '';
508d796a891SAndreas Gohr        }
509f23f9594SAndreas Gohr        $value = hsc($value);
510d796a891SAndreas Gohr
5117de12fceSAndreas Gohr        echo "<tr $class>";
5127de12fceSAndreas Gohr        echo "<td><label for=\"$id\" >$label: </label></td>";
5137de12fceSAndreas Gohr        echo "<td>";
5147de12fceSAndreas Gohr        if ($cando) {
5159b82d43fSAndreas Gohr            $req = '';
5169b82d43fSAndreas Gohr            if ($required) $req = 'required="required"';
51764159a61SAndreas Gohr            echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\"
51864159a61SAndreas Gohr                  value=\"$value\" class=\"edit\" $autocomp $req />";
5197de12fceSAndreas Gohr        } else {
5207de12fceSAndreas Gohr            echo "<input type=\"hidden\" name=\"$name\" value=\"$value\" />";
52164159a61SAndreas Gohr            echo "<input type=\"$fieldtype\" id=\"$id\" name=\"$name\"
52264159a61SAndreas Gohr                  value=\"$value\" class=\"edit disabled\" disabled=\"disabled\" />";
5237de12fceSAndreas Gohr        }
5247de12fceSAndreas Gohr        echo "</td>";
5257de12fceSAndreas Gohr        echo "</tr>";
52626fb387bSchris    }
52726fb387bSchris
528c5a7c0c6SGerrit Uitslag    /**
529c5a7c0c6SGerrit Uitslag     * Returns htmlescaped filter value
530c5a7c0c6SGerrit Uitslag     *
531c5a7c0c6SGerrit Uitslag     * @param string $key name of search field
532c5a7c0c6SGerrit Uitslag     * @return string html escaped value
533c5a7c0c6SGerrit Uitslag     */
534*3a97d936SAndreas Gohr    protected function htmlFilter($key)
535*3a97d936SAndreas Gohr    {
536*3a97d936SAndreas Gohr        if (empty($this->filter)) return '';
537*3a97d936SAndreas Gohr        return (isset($this->filter[$key]) ? hsc($this->filter[$key]) : '');
5380440ff15Schris    }
5390440ff15Schris
540c5a7c0c6SGerrit Uitslag    /**
541c5a7c0c6SGerrit Uitslag     * Print hidden inputs with the current filter values
542c5a7c0c6SGerrit Uitslag     *
543c5a7c0c6SGerrit Uitslag     * @param int $indent
544c5a7c0c6SGerrit Uitslag     */
545*3a97d936SAndreas Gohr    protected function htmlFilterSettings($indent = 0)
546*3a97d936SAndreas Gohr    {
5470440ff15Schris
548*3a97d936SAndreas Gohr        ptln("<input type=\"hidden\" name=\"start\" value=\"".$this->start."\" />", $indent);
5490440ff15Schris
550*3a97d936SAndreas Gohr        foreach ($this->filter as $key => $filter) {
5510440ff15Schris            ptln("<input type=\"hidden\" name=\"filter[".$key."]\" value=\"".hsc($filter)."\" />", $indent);
5520440ff15Schris        }
5530440ff15Schris    }
5540440ff15Schris
555c5a7c0c6SGerrit Uitslag    /**
556c5a7c0c6SGerrit Uitslag     * Print import form and summary of previous import
557c5a7c0c6SGerrit Uitslag     *
558c5a7c0c6SGerrit Uitslag     * @param int $indent
559c5a7c0c6SGerrit Uitslag     */
560*3a97d936SAndreas Gohr    protected function htmlImportForm($indent = 0)
561*3a97d936SAndreas Gohr    {
562ae1afd2fSChristopher Smith        global $ID;
563ae1afd2fSChristopher Smith
564ae1afd2fSChristopher Smith        $failure_download_link = wl($ID, array('do'=>'admin','page'=>'usermanager','fn[importfails]'=>1));
565ae1afd2fSChristopher Smith
566ae1afd2fSChristopher Smith        ptln('<div class="level2 import_users">', $indent);
567ae1afd2fSChristopher Smith        print $this->locale_xhtml('import');
568ae1afd2fSChristopher Smith        ptln('  <form action="'.wl($ID).'" method="post" enctype="multipart/form-data">', $indent);
569ae1afd2fSChristopher Smith        formSecurityToken();
570b59cff8bSGerrit Uitslag        ptln('    <label>'.$this->lang['import_userlistcsv'].'<input type="file" name="import" /></label>', $indent);
571ae614416SAnika Henke        ptln('    <button type="submit" name="fn[import]">'.$this->lang['import'].'</button>', $indent);
572ae1afd2fSChristopher Smith        ptln('    <input type="hidden" name="do"    value="admin" />', $indent);
573ae1afd2fSChristopher Smith        ptln('    <input type="hidden" name="page"  value="usermanager" />', $indent);
574ae1afd2fSChristopher Smith
575*3a97d936SAndreas Gohr        $this->htmlFilterSettings($indent+4);
576ae1afd2fSChristopher Smith        ptln('  </form>', $indent);
577ae1afd2fSChristopher Smith        ptln('</div>');
578ae1afd2fSChristopher Smith
579ae1afd2fSChristopher Smith        // list failures from the previous import
580*3a97d936SAndreas Gohr        if ($this->import_failures) {
581*3a97d936SAndreas Gohr            $digits = strlen(count($this->import_failures));
582ae1afd2fSChristopher Smith            ptln('<div class="level3 import_failures">', $indent);
583b59cff8bSGerrit Uitslag            ptln('  <h3>'.$this->lang['import_header'].'</h3>');
584ae1afd2fSChristopher Smith            ptln('  <table class="import_failures">', $indent);
585ae1afd2fSChristopher Smith            ptln('    <thead>', $indent);
586ae1afd2fSChristopher Smith            ptln('      <tr>', $indent);
587ae1afd2fSChristopher Smith            ptln('        <th class="line">'.$this->lang['line'].'</th>', $indent);
588ae1afd2fSChristopher Smith            ptln('        <th class="error">'.$this->lang['error'].'</th>', $indent);
589ae1afd2fSChristopher Smith            ptln('        <th class="userid">'.$this->lang['user_id'].'</th>', $indent);
590ae1afd2fSChristopher Smith            ptln('        <th class="username">'.$this->lang['user_name'].'</th>', $indent);
591ae1afd2fSChristopher Smith            ptln('        <th class="usermail">'.$this->lang['user_mail'].'</th>', $indent);
592ae1afd2fSChristopher Smith            ptln('        <th class="usergroups">'.$this->lang['user_groups'].'</th>', $indent);
593ae1afd2fSChristopher Smith            ptln('      </tr>', $indent);
594ae1afd2fSChristopher Smith            ptln('    </thead>', $indent);
595ae1afd2fSChristopher Smith            ptln('    <tbody>', $indent);
596*3a97d936SAndreas Gohr            foreach ($this->import_failures as $line => $failure) {
597ae1afd2fSChristopher Smith                ptln('      <tr>', $indent);
598ae1afd2fSChristopher Smith                ptln('        <td class="lineno"> '.sprintf('%0'.$digits.'d', $line).' </td>', $indent);
599ae1afd2fSChristopher Smith                ptln('        <td class="error">' .$failure['error'].' </td>', $indent);
600ae1afd2fSChristopher Smith                ptln('        <td class="field userid"> '.hsc($failure['user'][0]).' </td>', $indent);
601ae1afd2fSChristopher Smith                ptln('        <td class="field username"> '.hsc($failure['user'][2]).' </td>', $indent);
602ae1afd2fSChristopher Smith                ptln('        <td class="field usermail"> '.hsc($failure['user'][3]).' </td>', $indent);
603ae1afd2fSChristopher Smith                ptln('        <td class="field usergroups"> '.hsc($failure['user'][4]).' </td>', $indent);
604ae1afd2fSChristopher Smith                ptln('      </tr>', $indent);
605ae1afd2fSChristopher Smith            }
606ae1afd2fSChristopher Smith            ptln('    </tbody>', $indent);
607ae1afd2fSChristopher Smith            ptln('  </table>', $indent);
608b59cff8bSGerrit Uitslag            ptln('  <p><a href="'.$failure_download_link.'">'.$this->lang['import_downloadfailures'].'</a></p>');
609ae1afd2fSChristopher Smith            ptln('</div>');
610ae1afd2fSChristopher Smith        }
611ae1afd2fSChristopher Smith    }
612ae1afd2fSChristopher Smith
613c5a7c0c6SGerrit Uitslag    /**
614c5a7c0c6SGerrit Uitslag     * Add an user to auth backend
615c5a7c0c6SGerrit Uitslag     *
616c5a7c0c6SGerrit Uitslag     * @return bool whether succesful
617c5a7c0c6SGerrit Uitslag     */
618*3a97d936SAndreas Gohr    protected function addUser()
619*3a97d936SAndreas Gohr    {
62000d58927SMichael Hamann        global $INPUT;
621634d7150SAndreas Gohr        if (!checkSecurityToken()) return false;
622*3a97d936SAndreas Gohr        if (!$this->auth->canDo('addUser')) return false;
6230440ff15Schris
624*3a97d936SAndreas Gohr        list($user,$pass,$name,$mail,$grps,$passconfirm) = $this->retrieveUser();
6250440ff15Schris        if (empty($user)) return false;
6266733c4d7SChris Smith
627*3a97d936SAndreas Gohr        if ($this->auth->canDo('modPass')) {
628c3f4fb63SGina Haeussge            if (empty($pass)) {
62900d58927SMichael Hamann                if ($INPUT->has('usernotify')) {
6308a285f7fSAndreas Gohr                    $pass = auth_pwgen($user);
631c3f4fb63SGina Haeussge                } else {
63260b9901bSAndreas Gohr                    msg($this->lang['add_fail'], -1);
63309a5dcd6SMichael Große                    msg($this->lang['addUser_error_missing_pass'], -1);
63460b9901bSAndreas Gohr                    return false;
63560b9901bSAndreas Gohr                }
636359e9417SChristopher Smith            } else {
637*3a97d936SAndreas Gohr                if (!$this->verifyPassword($pass, $passconfirm)) {
63809a5dcd6SMichael Große                    msg($this->lang['add_fail'], -1);
63909a5dcd6SMichael Große                    msg($this->lang['addUser_error_pass_not_identical'], -1);
640359e9417SChristopher Smith                    return false;
641359e9417SChristopher Smith                }
6426733c4d7SChris Smith            }
6436733c4d7SChris Smith        } else {
6446733c4d7SChris Smith            if (!empty($pass)) {
6456733c4d7SChris Smith                msg($this->lang['add_fail'], -1);
64609a5dcd6SMichael Große                msg($this->lang['addUser_error_modPass_disabled'], -1);
6476733c4d7SChris Smith                return false;
6486733c4d7SChris Smith            }
6496733c4d7SChris Smith        }
6506733c4d7SChris Smith
651*3a97d936SAndreas Gohr        if ($this->auth->canDo('modName')) {
6526733c4d7SChris Smith            if (empty($name)) {
6536733c4d7SChris Smith                msg($this->lang['add_fail'], -1);
65409a5dcd6SMichael Große                msg($this->lang['addUser_error_name_missing'], -1);
6556733c4d7SChris Smith                return false;
6566733c4d7SChris Smith            }
6576733c4d7SChris Smith        } else {
6586733c4d7SChris Smith            if (!empty($name)) {
65909a5dcd6SMichael Große                msg($this->lang['add_fail'], -1);
66009a5dcd6SMichael Große                msg($this->lang['addUser_error_modName_disabled'], -1);
6616733c4d7SChris Smith                return false;
6626733c4d7SChris Smith            }
6636733c4d7SChris Smith        }
6646733c4d7SChris Smith
665*3a97d936SAndreas Gohr        if ($this->auth->canDo('modMail')) {
6666733c4d7SChris Smith            if (empty($mail)) {
6676733c4d7SChris Smith                msg($this->lang['add_fail'], -1);
66809a5dcd6SMichael Große                msg($this->lang['addUser_error_mail_missing'], -1);
6696733c4d7SChris Smith                return false;
6706733c4d7SChris Smith            }
6716733c4d7SChris Smith        } else {
6726733c4d7SChris Smith            if (!empty($mail)) {
67309a5dcd6SMichael Große                msg($this->lang['add_fail'], -1);
67409a5dcd6SMichael Große                msg($this->lang['addUser_error_modMail_disabled'], -1);
6756733c4d7SChris Smith                return false;
6766733c4d7SChris Smith            }
6776733c4d7SChris Smith        }
6780440ff15Schris
679*3a97d936SAndreas Gohr        if ($ok = $this->auth->triggerUserMod('create', array($user, $pass, $name, $mail, $grps))) {
680a6858c6aSchris            msg($this->lang['add_ok'], 1);
681a6858c6aSchris
68200d58927SMichael Hamann            if ($INPUT->has('usernotify') && $pass) {
683*3a97d936SAndreas Gohr                $this->notifyUser($user, $pass);
684a6858c6aSchris            }
685a6858c6aSchris        } else {
68660b9901bSAndreas Gohr            msg($this->lang['add_fail'], -1);
68709a5dcd6SMichael Große            msg($this->lang['addUser_error_create_event_failed'], -1);
688a6858c6aSchris        }
689a6858c6aSchris
690a6858c6aSchris        return $ok;
6910440ff15Schris    }
6920440ff15Schris
6930440ff15Schris    /**
694c5a7c0c6SGerrit Uitslag     * Delete user from auth backend
695c5a7c0c6SGerrit Uitslag     *
696c5a7c0c6SGerrit Uitslag     * @return bool whether succesful
6970440ff15Schris     */
698*3a97d936SAndreas Gohr    protected function deleteUser()
699*3a97d936SAndreas Gohr    {
70000d58927SMichael Hamann        global $conf, $INPUT;
7019ec82636SAndreas Gohr
702634d7150SAndreas Gohr        if (!checkSecurityToken()) return false;
703*3a97d936SAndreas Gohr        if (!$this->auth->canDo('delUser')) return false;
7040440ff15Schris
70500d58927SMichael Hamann        $selected = $INPUT->arr('delete');
70600d58927SMichael Hamann        if (empty($selected)) return false;
7070440ff15Schris        $selected = array_keys($selected);
7080440ff15Schris
709c9a8f912SMichael Klier        if (in_array($_SERVER['REMOTE_USER'], $selected)) {
710c9a8f912SMichael Klier            msg("You can't delete yourself!", -1);
711c9a8f912SMichael Klier            return false;
712c9a8f912SMichael Klier        }
713c9a8f912SMichael Klier
714*3a97d936SAndreas Gohr        $count = $this->auth->triggerUserMod('delete', array($selected));
7150440ff15Schris        if ($count == count($selected)) {
7160440ff15Schris            $text = str_replace('%d', $count, $this->lang['delete_ok']);
7170440ff15Schris            msg("$text.", 1);
7180440ff15Schris        } else {
7190440ff15Schris            $part1 = str_replace('%d', $count, $this->lang['delete_ok']);
7200440ff15Schris            $part2 = str_replace('%d', (count($selected)-$count), $this->lang['delete_fail']);
7210440ff15Schris            msg("$part1, $part2", -1);
7220440ff15Schris        }
72378c7c8c9Schris
7249ec82636SAndreas Gohr        // invalidate all sessions
7259ec82636SAndreas Gohr        io_saveFile($conf['cachedir'].'/sessionpurge', time());
7269ec82636SAndreas Gohr
72778c7c8c9Schris        return true;
72878c7c8c9Schris    }
72978c7c8c9Schris
73078c7c8c9Schris    /**
73178c7c8c9Schris     * Edit user (a user has been selected for editing)
732c5a7c0c6SGerrit Uitslag     *
733c5a7c0c6SGerrit Uitslag     * @param string $param id of the user
734c5a7c0c6SGerrit Uitslag     * @return bool whether succesful
73578c7c8c9Schris     */
736*3a97d936SAndreas Gohr    protected function editUser($param)
737*3a97d936SAndreas Gohr    {
738634d7150SAndreas Gohr        if (!checkSecurityToken()) return false;
739*3a97d936SAndreas Gohr        if (!$this->auth->canDo('UserMod')) return false;
740*3a97d936SAndreas Gohr        $user = $this->auth->cleanUser(preg_replace('/.*[:\/]/', '', $param));
741*3a97d936SAndreas Gohr        $userdata = $this->auth->getUserData($user);
74278c7c8c9Schris
74378c7c8c9Schris        // no user found?
74478c7c8c9Schris        if (!$userdata) {
74578c7c8c9Schris            msg($this->lang['edit_usermissing'], -1);
74678c7c8c9Schris            return false;
74778c7c8c9Schris        }
74878c7c8c9Schris
749*3a97d936SAndreas Gohr        $this->edit_user = $user;
750*3a97d936SAndreas Gohr        $this->edit_userdata = $userdata;
75178c7c8c9Schris
75278c7c8c9Schris        return true;
7530440ff15Schris    }
7540440ff15Schris
7550440ff15Schris    /**
756c5a7c0c6SGerrit Uitslag     * Modify user in the auth backend (modified user data has been recieved)
757c5a7c0c6SGerrit Uitslag     *
758c5a7c0c6SGerrit Uitslag     * @return bool whether succesful
7590440ff15Schris     */
760*3a97d936SAndreas Gohr    protected function modifyUser()
761*3a97d936SAndreas Gohr    {
76200d58927SMichael Hamann        global $conf, $INPUT;
7639ec82636SAndreas Gohr
764634d7150SAndreas Gohr        if (!checkSecurityToken()) return false;
765*3a97d936SAndreas Gohr        if (!$this->auth->canDo('UserMod')) return false;
7660440ff15Schris
76726fb387bSchris        // get currently valid  user data
768*3a97d936SAndreas Gohr        $olduser = $this->auth->cleanUser(preg_replace('/.*[:\/]/', '', $INPUT->str('userid_old')));
769*3a97d936SAndreas Gohr        $oldinfo = $this->auth->getUserData($olduser);
770073766c6Smatthiasgrimm
77126fb387bSchris        // get new user data subject to change
772*3a97d936SAndreas Gohr        list($newuser,$newpass,$newname,$newmail,$newgrps,$passconfirm) = $this->retrieveUser();
773073766c6Smatthiasgrimm        if (empty($newuser)) return false;
7740440ff15Schris
7750440ff15Schris        $changes = array();
776073766c6Smatthiasgrimm        if ($newuser != $olduser) {
777*3a97d936SAndreas Gohr            if (!$this->auth->canDo('modLogin')) {        // sanity check, shouldn't be possible
77826fb387bSchris                msg($this->lang['update_fail'], -1);
77926fb387bSchris                return false;
78026fb387bSchris            }
78126fb387bSchris
78226fb387bSchris            // check if $newuser already exists
783*3a97d936SAndreas Gohr            if ($this->auth->getUserData($newuser)) {
784073766c6Smatthiasgrimm                msg(sprintf($this->lang['update_exists'], $newuser), -1);
785a6858c6aSchris                $re_edit = true;
7860440ff15Schris            } else {
787073766c6Smatthiasgrimm                $changes['user'] = $newuser;
7880440ff15Schris            }
78993eefc2fSAndreas Gohr        }
790*3a97d936SAndreas Gohr        if ($this->auth->canDo('modPass')) {
7912400ddcbSChristopher Smith            if ($newpass || $passconfirm) {
792*3a97d936SAndreas Gohr                if ($this->verifyPassword($newpass, $passconfirm)) {
793359e9417SChristopher Smith                    $changes['pass'] = $newpass;
794359e9417SChristopher Smith                } else {
795359e9417SChristopher Smith                    return false;
796359e9417SChristopher Smith                }
797359e9417SChristopher Smith            } else {
798359e9417SChristopher Smith                // no new password supplied, check if we need to generate one (or it stays unchanged)
799359e9417SChristopher Smith                if ($INPUT->has('usernotify')) {
800359e9417SChristopher Smith                    $changes['pass'] = auth_pwgen($olduser);
801359e9417SChristopher Smith                }
802359e9417SChristopher Smith            }
8030440ff15Schris        }
8040440ff15Schris
805*3a97d936SAndreas Gohr        if (!empty($newname) && $this->auth->canDo('modName') && $newname != $oldinfo['name']) {
806073766c6Smatthiasgrimm            $changes['name'] = $newname;
80740d72af6SChristopher Smith        }
808*3a97d936SAndreas Gohr        if (!empty($newmail) && $this->auth->canDo('modMail') && $newmail != $oldinfo['mail']) {
809073766c6Smatthiasgrimm            $changes['mail'] = $newmail;
81040d72af6SChristopher Smith        }
811*3a97d936SAndreas Gohr        if (!empty($newgrps) && $this->auth->canDo('modGroups') && $newgrps != $oldinfo['grps']) {
812073766c6Smatthiasgrimm            $changes['grps'] = $newgrps;
81340d72af6SChristopher Smith        }
8140440ff15Schris
815*3a97d936SAndreas Gohr        if ($ok = $this->auth->triggerUserMod('modify', array($olduser, $changes))) {
8160440ff15Schris            msg($this->lang['update_ok'], 1);
817a6858c6aSchris
8186ed3476bSChristopher Smith            if ($INPUT->has('usernotify') && !empty($changes['pass'])) {
819a6858c6aSchris                $notify = empty($changes['user']) ? $olduser : $newuser;
820*3a97d936SAndreas Gohr                $this->notifyUser($notify, $changes['pass']);
821a6858c6aSchris            }
822a6858c6aSchris
8239ec82636SAndreas Gohr            // invalidate all sessions
8249ec82636SAndreas Gohr            io_saveFile($conf['cachedir'].'/sessionpurge', time());
8250440ff15Schris        } else {
8260440ff15Schris            msg($this->lang['update_fail'], -1);
8270440ff15Schris        }
82878c7c8c9Schris
829a6858c6aSchris        if (!empty($re_edit)) {
830*3a97d936SAndreas Gohr            $this->editUser($olduser);
8310440ff15Schris        }
8320440ff15Schris
833a6858c6aSchris        return $ok;
834a6858c6aSchris    }
835a6858c6aSchris
836a6858c6aSchris    /**
837c5a7c0c6SGerrit Uitslag     * Send password change notification email
838c5a7c0c6SGerrit Uitslag     *
839c5a7c0c6SGerrit Uitslag     * @param string $user         id of user
840c5a7c0c6SGerrit Uitslag     * @param string $password     plain text
841c5a7c0c6SGerrit Uitslag     * @param bool   $status_alert whether status alert should be shown
842c5a7c0c6SGerrit Uitslag     * @return bool whether succesful
843a6858c6aSchris     */
844*3a97d936SAndreas Gohr    protected function notifyUser($user, $password, $status_alert = true)
845*3a97d936SAndreas Gohr    {
846a6858c6aSchris
847a6858c6aSchris        if ($sent = auth_sendPassword($user, $password)) {
848328143f8SChristopher Smith            if ($status_alert) {
849a6858c6aSchris                msg($this->lang['notify_ok'], 1);
850328143f8SChristopher Smith            }
851a6858c6aSchris        } else {
852328143f8SChristopher Smith            if ($status_alert) {
853a6858c6aSchris                msg($this->lang['notify_fail'], -1);
854a6858c6aSchris            }
855328143f8SChristopher Smith        }
856a6858c6aSchris
857a6858c6aSchris        return $sent;
858a6858c6aSchris    }
859a6858c6aSchris
860a6858c6aSchris    /**
861359e9417SChristopher Smith     * Verify password meets minimum requirements
862359e9417SChristopher Smith     * :TODO: extend to support password strength
863359e9417SChristopher Smith     *
864359e9417SChristopher Smith     * @param string  $password   candidate string for new password
865359e9417SChristopher Smith     * @param string  $confirm    repeated password for confirmation
866359e9417SChristopher Smith     * @return bool   true if meets requirements, false otherwise
867359e9417SChristopher Smith     */
868*3a97d936SAndreas Gohr    protected function verifyPassword($password, $confirm)
869*3a97d936SAndreas Gohr    {
870be9008d3SChristopher Smith        global $lang;
871359e9417SChristopher Smith
8722400ddcbSChristopher Smith        if (empty($password) && empty($confirm)) {
873359e9417SChristopher Smith            return false;
874359e9417SChristopher Smith        }
875359e9417SChristopher Smith
876359e9417SChristopher Smith        if ($password !== $confirm) {
877be9008d3SChristopher Smith            msg($lang['regbadpass'], -1);
878359e9417SChristopher Smith            return false;
879359e9417SChristopher Smith        }
880359e9417SChristopher Smith
881359e9417SChristopher Smith        // :TODO: test password for required strength
882359e9417SChristopher Smith
883359e9417SChristopher Smith        // if we make it this far the password is good
884359e9417SChristopher Smith        return true;
885359e9417SChristopher Smith    }
886359e9417SChristopher Smith
887359e9417SChristopher Smith    /**
888c5a7c0c6SGerrit Uitslag     * Retrieve & clean user data from the form
889a6858c6aSchris     *
890c5a7c0c6SGerrit Uitslag     * @param bool $clean whether the cleanUser method of the authentication backend is applied
891a6858c6aSchris     * @return array (user, password, full name, email, array(groups))
8920440ff15Schris     */
893*3a97d936SAndreas Gohr    protected function retrieveUser($clean = true)
894*3a97d936SAndreas Gohr    {
895c5a7c0c6SGerrit Uitslag        /** @var DokuWiki_Auth_Plugin $auth */
8967441e340SAndreas Gohr        global $auth;
897fbfbbe8aSHakan Sandell        global $INPUT;
8980440ff15Schris
89959bc3b48SGerrit Uitslag        $user = array();
900fbfbbe8aSHakan Sandell        $user[0] = ($clean) ? $auth->cleanUser($INPUT->str('userid')) : $INPUT->str('userid');
901fbfbbe8aSHakan Sandell        $user[1] = $INPUT->str('userpass');
902fbfbbe8aSHakan Sandell        $user[2] = $INPUT->str('username');
903fbfbbe8aSHakan Sandell        $user[3] = $INPUT->str('usermail');
904fbfbbe8aSHakan Sandell        $user[4] = explode(',', $INPUT->str('usergroups'));
905359e9417SChristopher Smith        $user[5] = $INPUT->str('userpass2');                // repeated password for confirmation
9060440ff15Schris
9077441e340SAndreas Gohr        $user[4] = array_map('trim', $user[4]);
9087441e340SAndreas Gohr        if ($clean) $user[4] = array_map(array($auth,'cleanGroup'), $user[4]);
9097441e340SAndreas Gohr        $user[4] = array_filter($user[4]);
9107441e340SAndreas Gohr        $user[4] = array_unique($user[4]);
9117441e340SAndreas Gohr        if (!count($user[4])) $user[4] = null;
9120440ff15Schris
9130440ff15Schris        return $user;
9140440ff15Schris    }
9150440ff15Schris
916c5a7c0c6SGerrit Uitslag    /**
917c5a7c0c6SGerrit Uitslag     * Set the filter with the current search terms or clear the filter
918c5a7c0c6SGerrit Uitslag     *
919c5a7c0c6SGerrit Uitslag     * @param string $op 'new' or 'clear'
920c5a7c0c6SGerrit Uitslag     */
921*3a97d936SAndreas Gohr    protected function setFilter($op)
922*3a97d936SAndreas Gohr    {
9230440ff15Schris
924*3a97d936SAndreas Gohr        $this->filter = array();
9250440ff15Schris
9260440ff15Schris        if ($op == 'new') {
927*3a97d936SAndreas Gohr            list($user,/* $pass */,$name,$mail,$grps) = $this->retrieveUser(false);
9280440ff15Schris
929*3a97d936SAndreas Gohr            if (!empty($user)) $this->filter['user'] = $user;
930*3a97d936SAndreas Gohr            if (!empty($name)) $this->filter['name'] = $name;
931*3a97d936SAndreas Gohr            if (!empty($mail)) $this->filter['mail'] = $mail;
932*3a97d936SAndreas Gohr            if (!empty($grps)) $this->filter['grps'] = join('|', $grps);
9330440ff15Schris        }
9340440ff15Schris    }
9350440ff15Schris
936c5a7c0c6SGerrit Uitslag    /**
937c5a7c0c6SGerrit Uitslag     * Get the current search terms
938c5a7c0c6SGerrit Uitslag     *
939c5a7c0c6SGerrit Uitslag     * @return array
940c5a7c0c6SGerrit Uitslag     */
941*3a97d936SAndreas Gohr    protected function retrieveFilter()
942*3a97d936SAndreas Gohr    {
943fbfbbe8aSHakan Sandell        global $INPUT;
9440440ff15Schris
945fbfbbe8aSHakan Sandell        $t_filter = $INPUT->arr('filter');
9460440ff15Schris
9470440ff15Schris        // messy, but this way we ensure we aren't getting any additional crap from malicious users
9480440ff15Schris        $filter = array();
9490440ff15Schris
9500440ff15Schris        if (isset($t_filter['user'])) $filter['user'] = $t_filter['user'];
9510440ff15Schris        if (isset($t_filter['name'])) $filter['name'] = $t_filter['name'];
9520440ff15Schris        if (isset($t_filter['mail'])) $filter['mail'] = $t_filter['mail'];
9530440ff15Schris        if (isset($t_filter['grps'])) $filter['grps'] = $t_filter['grps'];
9540440ff15Schris
9550440ff15Schris        return $filter;
9560440ff15Schris    }
9570440ff15Schris
958c5a7c0c6SGerrit Uitslag    /**
959c5a7c0c6SGerrit Uitslag     * Validate and improve the pagination values
960c5a7c0c6SGerrit Uitslag     */
961*3a97d936SAndreas Gohr    protected function validatePagination()
962*3a97d936SAndreas Gohr    {
9630440ff15Schris
964*3a97d936SAndreas Gohr        if ($this->start >= $this->users_total) {
965*3a97d936SAndreas Gohr            $this->start = $this->users_total - $this->pagesize;
9660440ff15Schris        }
967*3a97d936SAndreas Gohr        if ($this->start < 0) $this->start = 0;
9680440ff15Schris
969*3a97d936SAndreas Gohr        $this->last = min($this->users_total, $this->start + $this->pagesize);
9700440ff15Schris    }
9710440ff15Schris
972c5a7c0c6SGerrit Uitslag    /**
973c5a7c0c6SGerrit Uitslag     * Return an array of strings to enable/disable pagination buttons
974c5a7c0c6SGerrit Uitslag     *
975c5a7c0c6SGerrit Uitslag     * @return array with enable/disable attributes
9760440ff15Schris     */
977*3a97d936SAndreas Gohr    protected function pagination()
978*3a97d936SAndreas Gohr    {
9790440ff15Schris
98051d94d49Schris        $disabled = 'disabled="disabled"';
98151d94d49Schris
98259bc3b48SGerrit Uitslag        $buttons = array();
983*3a97d936SAndreas Gohr        $buttons['start'] = $buttons['prev'] = ($this->start == 0) ? $disabled : '';
98451d94d49Schris
985*3a97d936SAndreas Gohr        if ($this->users_total == -1) {
98651d94d49Schris            $buttons['last'] = $disabled;
98751d94d49Schris            $buttons['next'] = '';
98851d94d49Schris        } else {
98964159a61SAndreas Gohr            $buttons['last'] = $buttons['next'] =
990*3a97d936SAndreas Gohr                (($this->start + $this->pagesize) >= $this->users_total) ? $disabled : '';
99151d94d49Schris        }
9920440ff15Schris
993*3a97d936SAndreas Gohr        if ($this->lastdisabled) {
994462e9e37SMichael Große            $buttons['last'] = $disabled;
995462e9e37SMichael Große        }
996462e9e37SMichael Große
9970440ff15Schris        return $buttons;
9980440ff15Schris    }
9995c967d3dSChristopher Smith
1000c5a7c0c6SGerrit Uitslag    /**
1001c5a7c0c6SGerrit Uitslag     * Export a list of users in csv format using the current filter criteria
10025c967d3dSChristopher Smith     */
1003*3a97d936SAndreas Gohr    protected function exportCSV()
1004*3a97d936SAndreas Gohr    {
10055c967d3dSChristopher Smith        // list of users for export - based on current filter criteria
1006*3a97d936SAndreas Gohr        $user_list = $this->auth->retrieveUsers(0, 0, $this->filter);
10075c967d3dSChristopher Smith        $column_headings = array(
10085c967d3dSChristopher Smith            $this->lang["user_id"],
10095c967d3dSChristopher Smith            $this->lang["user_name"],
10105c967d3dSChristopher Smith            $this->lang["user_mail"],
10115c967d3dSChristopher Smith            $this->lang["user_groups"]
10125c967d3dSChristopher Smith        );
10135c967d3dSChristopher Smith
10145c967d3dSChristopher Smith        // ==============================================================================================
10155c967d3dSChristopher Smith        // GENERATE OUTPUT
10165c967d3dSChristopher Smith        // normal headers for downloading...
10175c967d3dSChristopher Smith        header('Content-type: text/csv;charset=utf-8');
10185c967d3dSChristopher Smith        header('Content-Disposition: attachment; filename="wikiusers.csv"');
10195c967d3dSChristopher Smith#       // for debugging assistance, send as text plain to the browser
10205c967d3dSChristopher Smith#       header('Content-type: text/plain;charset=utf-8');
10215c967d3dSChristopher Smith
10225c967d3dSChristopher Smith        // output the csv
10235c967d3dSChristopher Smith        $fd = fopen('php://output', 'w');
10245c967d3dSChristopher Smith        fputcsv($fd, $column_headings);
10255c967d3dSChristopher Smith        foreach ($user_list as $user => $info) {
10265c967d3dSChristopher Smith            $line = array($user, $info['name'], $info['mail'], join(',', $info['grps']));
10275c967d3dSChristopher Smith            fputcsv($fd, $line);
10285c967d3dSChristopher Smith        }
10295c967d3dSChristopher Smith        fclose($fd);
1030*3a97d936SAndreas Gohr        if (defined('DOKU_UNITTEST')) {
1031*3a97d936SAndreas Gohr            return;
1032*3a97d936SAndreas Gohr        }
1033b2c01466SChristopher Smith
10345c967d3dSChristopher Smith        die;
10355c967d3dSChristopher Smith    }
1036ae1afd2fSChristopher Smith
1037c5a7c0c6SGerrit Uitslag    /**
1038c5a7c0c6SGerrit Uitslag     * Import a file of users in csv format
1039ae1afd2fSChristopher Smith     *
1040ae1afd2fSChristopher Smith     * csv file should have 4 columns, user_id, full name, email, groups (comma separated)
1041c5a7c0c6SGerrit Uitslag     *
10425ba64050SChristopher Smith     * @return bool whether successful
1043ae1afd2fSChristopher Smith     */
1044*3a97d936SAndreas Gohr    protected function importCSV()
1045*3a97d936SAndreas Gohr    {
1046ae1afd2fSChristopher Smith        // check we are allowed to add users
1047ae1afd2fSChristopher Smith        if (!checkSecurityToken()) return false;
1048*3a97d936SAndreas Gohr        if (!$this->auth->canDo('addUser')) return false;
1049ae1afd2fSChristopher Smith
1050ae1afd2fSChristopher Smith        // check file uploaded ok.
1051*3a97d936SAndreas Gohr        if (empty($_FILES['import']['size']) ||
1052*3a97d936SAndreas Gohr            !empty($_FILES['import']['error']) && $this->isUploadedFile($_FILES['import']['tmp_name'])
105364159a61SAndreas Gohr        ) {
1054ae1afd2fSChristopher Smith            msg($this->lang['import_error_upload'], -1);
1055ae1afd2fSChristopher Smith            return false;
1056ae1afd2fSChristopher Smith        }
1057ae1afd2fSChristopher Smith        // retrieve users from the file
1058*3a97d936SAndreas Gohr        $this->import_failures = array();
1059ae1afd2fSChristopher Smith        $import_success_count = 0;
1060ae1afd2fSChristopher Smith        $import_fail_count = 0;
1061ae1afd2fSChristopher Smith        $line = 0;
1062ae1afd2fSChristopher Smith        $fd = fopen($_FILES['import']['tmp_name'], 'r');
1063ae1afd2fSChristopher Smith        if ($fd) {
1064ae1afd2fSChristopher Smith            while ($csv = fgets($fd)) {
1065efcec72bSChristopher Smith                if (!utf8_check($csv)) {
1066efcec72bSChristopher Smith                    $csv = utf8_encode($csv);
1067efcec72bSChristopher Smith                }
1068d0c0a5c4SAnika Henke                $raw = str_getcsv($csv);
1069ae1afd2fSChristopher Smith                $error = '';                        // clean out any errors from the previous line
1070ae1afd2fSChristopher Smith                // data checks...
1071ae1afd2fSChristopher Smith                if (1 == ++$line) {
1072ae1afd2fSChristopher Smith                    if ($raw[0] == 'user_id' || $raw[0] == $this->lang['user_id']) continue;    // skip headers
1073ae1afd2fSChristopher Smith                }
1074ae1afd2fSChristopher Smith                if (count($raw) < 4) {                                        // need at least four fields
1075ae1afd2fSChristopher Smith                    $import_fail_count++;
1076ae1afd2fSChristopher Smith                    $error = sprintf($this->lang['import_error_fields'], count($raw));
1077*3a97d936SAndreas Gohr                    $this->import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv);
1078ae1afd2fSChristopher Smith                    continue;
1079ae1afd2fSChristopher Smith                }
1080ae1afd2fSChristopher Smith                array_splice($raw, 1, 0, auth_pwgen());                          // splice in a generated password
1081*3a97d936SAndreas Gohr                $clean = $this->cleanImportUser($raw, $error);
1082*3a97d936SAndreas Gohr                if ($clean && $this->importUser($clean, $error)) {
1083*3a97d936SAndreas Gohr                    $sent = $this->notifyUser($clean[0], $clean[1], false);
1084328143f8SChristopher Smith                    if (!$sent) {
1085328143f8SChristopher Smith                        msg(sprintf($this->lang['import_notify_fail'], $clean[0], $clean[3]), -1);
1086328143f8SChristopher Smith                    }
1087ae1afd2fSChristopher Smith                    $import_success_count++;
1088ae1afd2fSChristopher Smith                } else {
1089ae1afd2fSChristopher Smith                    $import_fail_count++;
1090e73725baSChristopher Smith                    array_splice($raw, 1, 1);                                  // remove the spliced in password
1091*3a97d936SAndreas Gohr                    $this->import_failures[$line] = array('error' => $error, 'user' => $raw, 'orig' => $csv);
1092ae1afd2fSChristopher Smith                }
1093ae1afd2fSChristopher Smith            }
109464159a61SAndreas Gohr            msg(
109564159a61SAndreas Gohr                sprintf(
109664159a61SAndreas Gohr                    $this->lang['import_success_count'],
109764159a61SAndreas Gohr                    ($import_success_count + $import_fail_count),
109864159a61SAndreas Gohr                    $import_success_count
109964159a61SAndreas Gohr                ),
110064159a61SAndreas Gohr                ($import_success_count ? 1 : -1)
110164159a61SAndreas Gohr            );
1102ae1afd2fSChristopher Smith            if ($import_fail_count) {
1103ae1afd2fSChristopher Smith                msg(sprintf($this->lang['import_failure_count'], $import_fail_count), -1);
1104ae1afd2fSChristopher Smith            }
1105ae1afd2fSChristopher Smith        } else {
1106ae1afd2fSChristopher Smith            msg($this->lang['import_error_readfail'], -1);
1107ae1afd2fSChristopher Smith        }
1108ae1afd2fSChristopher Smith
1109ae1afd2fSChristopher Smith        // save import failures into the session
1110ae1afd2fSChristopher Smith        if (!headers_sent()) {
1111ae1afd2fSChristopher Smith            session_start();
1112*3a97d936SAndreas Gohr            $_SESSION['import_failures'] = $this->import_failures;
1113ae1afd2fSChristopher Smith            session_write_close();
1114ae1afd2fSChristopher Smith        }
1115c5a7c0c6SGerrit Uitslag        return true;
1116ae1afd2fSChristopher Smith    }
1117ae1afd2fSChristopher Smith
1118c5a7c0c6SGerrit Uitslag    /**
1119786dfb0eSGerrit Uitslag     * Returns cleaned user data
1120c5a7c0c6SGerrit Uitslag     *
1121c5a7c0c6SGerrit Uitslag     * @param array $candidate raw values of line from input file
1122253d4b48SGerrit Uitslag     * @param string $error
1123253d4b48SGerrit Uitslag     * @return array|false cleaned data or false
1124c5a7c0c6SGerrit Uitslag     */
1125*3a97d936SAndreas Gohr    protected function cleanImportUser($candidate, & $error)
1126*3a97d936SAndreas Gohr    {
1127ae1afd2fSChristopher Smith        global $INPUT;
1128ae1afd2fSChristopher Smith
1129*3a97d936SAndreas Gohr        // FIXME kludgy ....
1130ae1afd2fSChristopher Smith        $INPUT->set('userid', $candidate[0]);
1131ae1afd2fSChristopher Smith        $INPUT->set('userpass', $candidate[1]);
1132ae1afd2fSChristopher Smith        $INPUT->set('username', $candidate[2]);
1133ae1afd2fSChristopher Smith        $INPUT->set('usermail', $candidate[3]);
1134ae1afd2fSChristopher Smith        $INPUT->set('usergroups', $candidate[4]);
1135ae1afd2fSChristopher Smith
1136*3a97d936SAndreas Gohr        $cleaned = $this->retrieveUser();
113759bc3b48SGerrit Uitslag        list($user,/* $pass */,$name,$mail,/* $grps */) = $cleaned;
1138ae1afd2fSChristopher Smith        if (empty($user)) {
1139ae1afd2fSChristopher Smith            $error = $this->lang['import_error_baduserid'];
1140ae1afd2fSChristopher Smith            return false;
1141ae1afd2fSChristopher Smith        }
1142ae1afd2fSChristopher Smith
1143ae1afd2fSChristopher Smith        // no need to check password, handled elsewhere
1144ae1afd2fSChristopher Smith
1145*3a97d936SAndreas Gohr        if (!($this->auth->canDo('modName') xor empty($name))) {
1146ae1afd2fSChristopher Smith            $error = $this->lang['import_error_badname'];
1147ae1afd2fSChristopher Smith            return false;
1148ae1afd2fSChristopher Smith        }
1149ae1afd2fSChristopher Smith
1150*3a97d936SAndreas Gohr        if ($this->auth->canDo('modMail')) {
1151328143f8SChristopher Smith            if (empty($mail) || !mail_isvalid($mail)) {
1152ae1afd2fSChristopher Smith                $error = $this->lang['import_error_badmail'];
1153ae1afd2fSChristopher Smith                return false;
1154ae1afd2fSChristopher Smith            }
1155328143f8SChristopher Smith        } else {
1156328143f8SChristopher Smith            if (!empty($mail)) {
1157328143f8SChristopher Smith                $error = $this->lang['import_error_badmail'];
1158328143f8SChristopher Smith                return false;
1159328143f8SChristopher Smith            }
1160328143f8SChristopher Smith        }
1161ae1afd2fSChristopher Smith
1162ae1afd2fSChristopher Smith        return $cleaned;
1163ae1afd2fSChristopher Smith    }
1164ae1afd2fSChristopher Smith
1165c5a7c0c6SGerrit Uitslag    /**
1166c5a7c0c6SGerrit Uitslag     * Adds imported user to auth backend
1167c5a7c0c6SGerrit Uitslag     *
1168c5a7c0c6SGerrit Uitslag     * Required a check of canDo('addUser') before
1169c5a7c0c6SGerrit Uitslag     *
1170c5a7c0c6SGerrit Uitslag     * @param array  $user   data of user
1171c5a7c0c6SGerrit Uitslag     * @param string &$error reference catched error message
11725ba64050SChristopher Smith     * @return bool whether successful
1173c5a7c0c6SGerrit Uitslag     */
1174*3a97d936SAndreas Gohr    protected function importUser($user, &$error)
1175*3a97d936SAndreas Gohr    {
1176*3a97d936SAndreas Gohr        if (!$this->auth->triggerUserMod('create', $user)) {
1177ae1afd2fSChristopher Smith            $error = $this->lang['import_error_create'];
1178ae1afd2fSChristopher Smith            return false;
1179ae1afd2fSChristopher Smith        }
1180ae1afd2fSChristopher Smith
1181ae1afd2fSChristopher Smith        return true;
1182ae1afd2fSChristopher Smith    }
1183ae1afd2fSChristopher Smith
1184c5a7c0c6SGerrit Uitslag    /**
1185c5a7c0c6SGerrit Uitslag     * Downloads failures as csv file
1186c5a7c0c6SGerrit Uitslag     */
1187*3a97d936SAndreas Gohr    protected function downloadImportFailures()
1188*3a97d936SAndreas Gohr    {
1189ae1afd2fSChristopher Smith
1190ae1afd2fSChristopher Smith        // ==============================================================================================
1191ae1afd2fSChristopher Smith        // GENERATE OUTPUT
1192ae1afd2fSChristopher Smith        // normal headers for downloading...
1193ae1afd2fSChristopher Smith        header('Content-type: text/csv;charset=utf-8');
1194ae1afd2fSChristopher Smith        header('Content-Disposition: attachment; filename="importfails.csv"');
1195ae1afd2fSChristopher Smith#       // for debugging assistance, send as text plain to the browser
1196ae1afd2fSChristopher Smith#       header('Content-type: text/plain;charset=utf-8');
1197ae1afd2fSChristopher Smith
1198ae1afd2fSChristopher Smith        // output the csv
1199ae1afd2fSChristopher Smith        $fd = fopen('php://output', 'w');
1200*3a97d936SAndreas Gohr        foreach ($this->import_failures as $fail) {
1201ae1afd2fSChristopher Smith            fputs($fd, $fail['orig']);
1202ae1afd2fSChristopher Smith        }
1203ae1afd2fSChristopher Smith        fclose($fd);
1204ae1afd2fSChristopher Smith        die;
1205ae1afd2fSChristopher Smith    }
1206ae1afd2fSChristopher Smith
1207b2c01466SChristopher Smith    /**
1208b2c01466SChristopher Smith     * wrapper for is_uploaded_file to facilitate overriding by test suite
1209253d4b48SGerrit Uitslag     *
1210253d4b48SGerrit Uitslag     * @param string $file filename
1211253d4b48SGerrit Uitslag     * @return bool
1212b2c01466SChristopher Smith     */
1213*3a97d936SAndreas Gohr    protected function isUploadedFile($file)
1214*3a97d936SAndreas Gohr    {
1215b2c01466SChristopher Smith        return is_uploaded_file($file);
1216b2c01466SChristopher Smith    }
12170440ff15Schris}
1218