<?php
/**
 *  g2fa Google 2-Factor Authentication Plugin
 *
 *  Dokuwiki Admin Plugin
 *
 *  @author  Andreas Boehler <dev@aboehler.at>
 */
// must be run within Dokuwiki
if(!defined('DOKU_INC')) die();
require_once(dirname(__FILE__).'/GoogleAuthenticator.php');
require_once(dirname(__FILE__).'/TokenHelper.php');

/**
 * All DokuWiki plugins to extend the admin function
 * need to inherit from this class
 */
class admin_plugin_authg2fa extends DokuWiki_Admin_Plugin {

    protected $_auth = null;
    protected $_tokens = array();
    protected $_start = 0;
    protected $_pagesize = 20;
    protected $_filter = array();
    protected $_disabled = "";
    protected $_user_total = 0;
    protected $_tokenHelper = null;
    protected $_unhide = "";

    /**
     * Constructor
     */
    public function admin_plugin_authg2fa() {
        /** @var DokuWiki_Auth_Plugin $auth */
        global $auth;

        $this->setupLocale();

        if (!isset($auth)) {
            return;
            //$this->_disabled = $this->lang['noauth'];
        } else if (!$auth->canDo('getUsers')) {
            return;
            //$this->_disabled = $this->lang['nosupport'];
        } else {

            // we're good to go
            $this->_auth = & $auth;

        }
        $this->_tokenHelper = new TokenHelper();

        $this->_tokens = $this->_tokenHelper->getTokens();
    }

    public function handle() {
        global $INPUT;
        if(is_null($this->_auth)) return false;
        if(!isset($_REQUEST['fn']) || !checkSecurityToken()) return;

        // extract the command and any specific parameters
        // submit button name is of the form - fn[cmd][param(s)]
        $fn   = $INPUT->param('fn');

        if (is_array($fn)) {
            $cmd = key($fn);
            $param = is_array($fn[$cmd]) ? key($fn[$cmd]) : null;
        } else {
            $cmd = $fn;
            $param = null;
        }

        if ($cmd != "search") {
            $this->_start = $INPUT->int('start', 0);
            $this->_filter = $this->_retrieveFilter();
        }

        switch($cmd) {
            case "csecret"   :  $this->_tokenHelper->createTokenForUser($param); $this->_tokens = $this->_tokenHelper->getTokens(); break;
            case "nsecret"   :  $this->_createTokenForAllUsers(); break;
            case "dsecret"   :  $this->_tokenHelper->deleteTokenForUser($param); $this->_tokens = $this->_tokenHelper->getTokens(); break;
            case "ssecret"   :  $this->_unhide = $param; break;
        }


        $this->_user_total = $this->_auth->canDo('getUserCount') ? $this->_auth->getUserCount($this->_filter) : -1;

        // page handling
        switch($cmd){
            case 'start' : $this->_start = 0; break;
            case 'prev'  : $this->_start -= $this->_pagesize; break;
            case 'next'  : $this->_start += $this->_pagesize; break;
            case 'last'  : $this->_start = $this->_user_total; break;
        }
        $this->_validatePagination();

        return true;
    }

    public function html() {
        global $ID;

        $user_list = $this->_auth->retrieveUsers($this->_start, $this->_pagesize, $this->_filter);
        $page_buttons = $this->_pagination();

        if($this->_unhide != "")
        {
          if(isset($this->_tokens[$this->_unhide])) {
            $ga = new PHPGangsta_GoogleAuthenticator();
            $url = $ga->getQRCodeGoogleUrl(urlencode('DokuWiki:'.$this->_unhide), $this->_tokens[$this->_unhide]);
            ptln('Showing QR Code for user '.$this->_unhide.':<br />');
            ptln('<img src="'.$url.'" alt="Google 2FA QR Image"><br />');
          }
        }

        ptln("<form action=\"".wl($ID)."\" method=\"post\">");
        formSecurityToken();
        ptln("<div class=\"table\">");
        ptln("<table class=\"inline\">");
        ptln('<tr><th>User</th><th>Secret</th><th>Action</th></tr>');
        foreach($user_list as $user => $userinfo)
        {
            extract($userinfo);
            ptln('<tr>');
            ptln('<td>'.hsc($user).'</td>');
            if(isset($this->_tokens[$user]))
                $secret = $this->_tokens[$user];
            else
                $secret = "";
            if($this->_unhide == hsc($user)) {
              ptln('<td>'.$secret.'</td>');
              $this->_unhide = "";
            }
            else {
              if($secret != "") {
                ptln('<td>********</td>');
              }
              else {
                ptln('<td></td>');
              }
            }
            ptln("<td>");
            ptln("<input type=\"submit\" name=\"fn[ssecret][".hsc($user)."]\" class=\"button\" value=\"Show Secret/QR Code\" />");
            ptln("<input type=\"submit\" name=\"fn[csecret][".hsc($user)."]\" class=\"button\" value=\"Create new Secret\" />");
            ptln("<input type=\"submit\" name=\"fn[dsecret][".hsc($user)."]\" class=\"button\" value=\"Delete Secret\" />");
            ptln("</td>");
            ptln('</tr>');

        }
//        ptln('</table>');
        ptln("<td colspan=\"3\">");
        ptln("<span class=\"medialeft\">");
        ptln("<input type=\"submit\" name=\"fn[nsecret]\" class=\"button\" value=\"Create Secrets for all\" />");
        ptln("        <input type=\"hidden\" name=\"do\"    value=\"admin\" />");
        ptln("        <input type=\"hidden\" name=\"page\"  value=\"authg2fa\" />");
        ptln("      </span>");
        ptln("        <span class=\"mediaright\">");
        ptln("          <input type=\"submit\" name=\"fn[start]\" ".$page_buttons['start']." class=\"button\" value=\"Start\" />");
        ptln("          <input type=\"submit\" name=\"fn[prev]\" ".$page_buttons['prev']." class=\"button\" value=\"Prev\" />");
        ptln("          <input type=\"submit\" name=\"fn[next]\" ".$page_buttons['next']." class=\"button\" value=\"Next\" />");
        ptln("          <input type=\"submit\" name=\"fn[last]\" ".$page_buttons['last']." class=\"button\" value=\"Last\" />");
        ptln("        </span>");
        ptln("</td>");
        ptln("</table>");
        ptln("</form>");
        ptln("</div>");
        return true;
    }

    /**
     * Validate and improve the pagination values
     */
    protected function _validatePagination() {

        if ($this->_start >= $this->_user_total) {
            $this->_start = $this->_user_total - $this->_pagesize;
        }
        if ($this->_start < 0) $this->_start = 0;

        $this->_last = min($this->_user_total, $this->_start + $this->_pagesize);
    }

    /**
     * Get the current search terms
     *
     * @return array
     */
    protected function _retrieveFilter() {
        global $INPUT;

        $t_filter = $INPUT->arr('filter');

        // messy, but this way we ensure we aren't getting any additional crap from malicious users
        $filter = array();

        if (isset($t_filter['user'])) $filter['user'] = $t_filter['user'];
        if (isset($t_filter['name'])) $filter['name'] = $t_filter['name'];
        if (isset($t_filter['mail'])) $filter['mail'] = $t_filter['mail'];
        if (isset($t_filter['grps'])) $filter['grps'] = $t_filter['grps'];

        return $filter;
    }

    /**
     * Return an array of strings to enable/disable pagination buttons
     *
     * @return array with enable/disable attributes
     */
    protected function _pagination() {

        $disabled = 'disabled="disabled"';

        $buttons['start'] = $buttons['prev'] = ($this->_start == 0) ? $disabled : '';

        if ($this->_user_total == -1) {
            $buttons['last'] = $disabled;
            $buttons['next'] = '';
        } else {
            $buttons['last'] = $buttons['next'] = (($this->_start + $this->_pagesize) >= $this->_user_total) ? $disabled : '';
        }

        return $buttons;
    }

    protected function _createTokenForAllUsers() {
        $user_list = $this->_auth->retrieveUsers($this->_start, $this->_pagesize, $this->_filter);
        foreach($user_list as $user => $user_info)
        {
            if(!isset($this->_tokens[$user]))
               $this->_tokenHelper->createTokenForUser($user);
        }
        $this->_tokens = $this->_tokenHelper->getTokens();
    }





}
