about summary refs log tree commit diff stats
path: root/wiki/lib/plugins/authpgsql/auth.php
diff options
context:
space:
mode:
authorahriman <ahriman@falte.red>2018-12-03 19:22:25 -0500
committerahriman <ahriman@falte.red>2018-12-03 19:22:25 -0500
commit0ae8cbf5c0b1a198b963490985b7738392ebcb97 (patch)
treeb2c77ae72c6b717e2b97492065196ac5ffb2d9e2 /wiki/lib/plugins/authpgsql/auth.php
parentf57f6cc5a2d159f90168d292437dc4bd8cd7f934 (diff)
downloadsite-0ae8cbf5c0b1a198b963490985b7738392ebcb97.tar.gz
installed dokuwiki, added to navbar, updated news
Diffstat (limited to 'wiki/lib/plugins/authpgsql/auth.php')
-rw-r--r--wiki/lib/plugins/authpgsql/auth.php431
1 files changed, 431 insertions, 0 deletions
diff --git a/wiki/lib/plugins/authpgsql/auth.php b/wiki/lib/plugins/authpgsql/auth.php
new file mode 100644
index 0000000..7b677d3
--- /dev/null
+++ b/wiki/lib/plugins/authpgsql/auth.php
@@ -0,0 +1,431 @@
+<?php
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+/**
+ * PostgreSQL authentication backend
+ *
+ * This class inherits much functionality from the MySQL class
+ * and just reimplements the Postgres specific parts.
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <andi@splitbrain.org>
+ * @author     Chris Smith <chris@jalakai.co.uk>
+ * @author     Matthias Grimm <matthias.grimmm@sourceforge.net>
+ * @author     Jan Schumann <js@schumann-it.com>
+ */
+class auth_plugin_authpgsql extends auth_plugin_authmysql {
+
+    /**
+     * Constructor
+     *
+     * checks if the pgsql interface is available, otherwise it will
+     * set the variable $success of the basis class to false
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     * @author Andreas Gohr <andi@splitbrain.org>
+     */
+    public function __construct() {
+        // we don't want the stuff the MySQL constructor does, but the grandparent might do something
+        DokuWiki_Auth_Plugin::__construct();
+
+        if(!function_exists('pg_connect')) {
+            $this->_debug("PgSQL err: PHP Postgres extension not found.", -1, __LINE__, __FILE__);
+            $this->success = false;
+            return;
+        }
+
+        $this->loadConfig();
+
+        // set capabilities based upon config strings set
+        if(empty($this->conf['user']) ||
+            empty($this->conf['password']) || empty($this->conf['database'])
+        ) {
+            $this->_debug("PgSQL err: insufficient configuration.", -1, __LINE__, __FILE__);
+            $this->success = false;
+            return;
+        }
+
+        $this->cando['addUser']   = $this->_chkcnf(
+            array(
+                 'getUserInfo',
+                 'getGroups',
+                 'addUser',
+                 'getUserID',
+                 'getGroupID',
+                 'addGroup',
+                 'addUserGroup'
+            )
+        );
+        $this->cando['delUser']   = $this->_chkcnf(
+            array(
+                 'getUserID',
+                 'delUser',
+                 'delUserRefs'
+            )
+        );
+        $this->cando['modLogin']  = $this->_chkcnf(
+            array(
+                 'getUserID',
+                 'updateUser',
+                 'UpdateTarget'
+            )
+        );
+        $this->cando['modPass']   = $this->cando['modLogin'];
+        $this->cando['modName']   = $this->cando['modLogin'];
+        $this->cando['modMail']   = $this->cando['modLogin'];
+        $this->cando['modGroups'] = $this->_chkcnf(
+            array(
+                 'getUserID',
+                 'getGroups',
+                 'getGroupID',
+                 'addGroup',
+                 'addUserGroup',
+                 'delGroup',
+                 'getGroupID',
+                 'delUserGroup'
+            )
+        );
+        /* getGroups is not yet supported
+           $this->cando['getGroups']    = $this->_chkcnf(array('getGroups',
+           'getGroupID')); */
+        $this->cando['getUsers']     = $this->_chkcnf(
+            array(
+                 'getUsers',
+                 'getUserInfo',
+                 'getGroups'
+            )
+        );
+        $this->cando['getUserCount'] = $this->_chkcnf(array('getUsers'));
+    }
+
+    /**
+     * Check if the given config strings are set
+     *
+     * @author  Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @param   string[] $keys
+     * @param   bool  $wop
+     * @return  bool
+     */
+    protected function _chkcnf($keys, $wop = false) {
+        foreach($keys as $key) {
+            if(empty($this->conf[$key])) return false;
+        }
+        return true;
+    }
+
+    /**
+     * Counts users which meet certain $filter criteria.
+     *
+     * @author  Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @param  array  $filter  filter criteria in item/pattern pairs
+     * @return int count of found users.
+     */
+    public function getUserCount($filter = array()) {
+        $rc = 0;
+
+        if($this->_openDB()) {
+            $sql = $this->_createSQLFilter($this->conf['getUsers'], $filter);
+
+            // no equivalent of SQL_CALC_FOUND_ROWS in pgsql?
+            if(($result = $this->_queryDB($sql))) {
+                $rc = count($result);
+            }
+            $this->_closeDB();
+        }
+        return $rc;
+    }
+
+    /**
+     * Bulk retrieval of user data
+     *
+     * @author  Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @param   int   $first     index of first user to be returned
+     * @param   int   $limit     max number of users to be returned
+     * @param   array $filter    array of field/pattern pairs
+     * @return  array userinfo (refer getUserData for internal userinfo details)
+     */
+    public function retrieveUsers($first = 0, $limit = 0, $filter = array()) {
+        $out = array();
+
+        if($this->_openDB()) {
+            $this->_lockTables("READ");
+            $sql = $this->_createSQLFilter($this->conf['getUsers'], $filter);
+            $sql .= " ".$this->conf['SortOrder'];
+            if($limit) $sql .= " LIMIT $limit";
+            if($first) $sql .= " OFFSET $first";
+            $result = $this->_queryDB($sql);
+
+            foreach($result as $user) {
+                if(($info = $this->_getUserInfo($user['user']))) {
+                    $out[$user['user']] = $info;
+                }
+            }
+
+            $this->_unlockTables();
+            $this->_closeDB();
+        }
+        return $out;
+    }
+
+    // @inherit function joinGroup($user, $group)
+    // @inherit function leaveGroup($user, $group) {
+
+    /**
+     * Adds a user to a group.
+     *
+     * If $force is set to true non existing groups would be created.
+     *
+     * The database connection must already be established. Otherwise
+     * this function does nothing and returns 'false'.
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     * @author Andreas Gohr   <andi@splitbrain.org>
+     *
+     * @param   string $user    user to add to a group
+     * @param   string $group   name of the group
+     * @param   bool   $force   create missing groups
+     * @return  bool   true on success, false on error
+     */
+    protected function _addUserToGroup($user, $group, $force = false) {
+        $newgroup = 0;
+
+        if(($this->dbcon) && ($user)) {
+            $gid = $this->_getGroupID($group);
+            if(!$gid) {
+                if($force) { // create missing groups
+                    $sql = str_replace('%{group}', addslashes($group), $this->conf['addGroup']);
+                    $this->_modifyDB($sql);
+                    //group should now exists try again to fetch it
+                    $gid      = $this->_getGroupID($group);
+                    $newgroup = 1; // group newly created
+                }
+            }
+            if(!$gid) return false; // group didn't exist and can't be created
+
+            $sql = $this->conf['addUserGroup'];
+            if(strpos($sql, '%{uid}') !== false) {
+                $uid = $this->_getUserID($user);
+                $sql = str_replace('%{uid}', addslashes($uid), $sql);
+            }
+            $sql = str_replace('%{user}', addslashes($user), $sql);
+            $sql = str_replace('%{gid}', addslashes($gid), $sql);
+            $sql = str_replace('%{group}', addslashes($group), $sql);
+            if($this->_modifyDB($sql) !== false) {
+                $this->_flushUserInfoCache($user);
+                return true;
+            }
+
+            if($newgroup) { // remove previously created group on error
+                $sql = str_replace('%{gid}', addslashes($gid), $this->conf['delGroup']);
+                $sql = str_replace('%{group}', addslashes($group), $sql);
+                $this->_modifyDB($sql);
+            }
+        }
+        return false;
+    }
+
+    // @inherit function _delUserFromGroup($user $group)
+    // @inherit function _getGroups($user)
+    // @inherit function _getUserID($user)
+
+    /**
+     * Adds a new User to the database.
+     *
+     * The database connection must already be established
+     * for this function to work. Otherwise it will return
+     * 'false'.
+     *
+     * @param  string $user  login of the user
+     * @param  string $pwd   encrypted password
+     * @param  string $name  full name of the user
+     * @param  string $mail  email address
+     * @param  array  $grps  array of groups the user should become member of
+     * @return bool
+     *
+     * @author  Andreas Gohr <andi@splitbrain.org>
+     * @author  Chris Smith <chris@jalakai.co.uk>
+     * @author  Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     */
+    protected function _addUser($user, $pwd, $name, $mail, $grps) {
+        if($this->dbcon && is_array($grps)) {
+            $sql = str_replace('%{user}', addslashes($user), $this->conf['addUser']);
+            $sql = str_replace('%{pass}', addslashes($pwd), $sql);
+            $sql = str_replace('%{name}', addslashes($name), $sql);
+            $sql = str_replace('%{email}', addslashes($mail), $sql);
+            if($this->_modifyDB($sql)) {
+                $uid = $this->_getUserID($user);
+            } else {
+                return false;
+            }
+
+            $group = '';
+            $gid = false;
+
+            if($uid) {
+                foreach($grps as $group) {
+                    $gid = $this->_addUserToGroup($user, $group, true);
+                    if($gid === false) break;
+                }
+
+                if($gid !== false){
+                    $this->_flushUserInfoCache($user);
+                    return true;
+                } else {
+                    /* remove the new user and all group relations if a group can't
+                     * be assigned. Newly created groups will remain in the database
+                     * and won't be removed. This might create orphaned groups but
+                     * is not a big issue so we ignore this problem here.
+                     */
+                    $this->_delUser($user);
+                    $this->_debug("PgSQL err: Adding user '$user' to group '$group' failed.", -1, __LINE__, __FILE__);
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Opens a connection to a database and saves the handle for further
+     * usage in the object. The successful call to this functions is
+     * essential for most functions in this object.
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @return bool
+     */
+    protected function _openDB() {
+        if(!$this->dbcon) {
+            $dsn = $this->conf['server'] ? 'host='.$this->conf['server'] : '';
+            $dsn .= ' port='.$this->conf['port'];
+            $dsn .= ' dbname='.$this->conf['database'];
+            $dsn .= ' user='.$this->conf['user'];
+            $dsn .= ' password='.conf_decodeString($this->conf['password']);
+
+            $con = @pg_connect($dsn);
+            if($con) {
+                $this->dbcon = $con;
+                return true; // connection and database successfully opened
+            } else {
+                $this->_debug(
+                        "PgSQL err: Connection to {$this->conf['user']}@{$this->conf['server']} not possible.",
+                        -1, __LINE__, __FILE__
+                    );
+            }
+            return false; // connection failed
+        }
+        return true; // connection already open
+    }
+
+    /**
+     * Closes a database connection.
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     */
+    protected function _closeDB() {
+        if($this->dbcon) {
+            pg_close($this->dbcon);
+            $this->dbcon = 0;
+        }
+    }
+
+    /**
+     * Sends a SQL query to the database and transforms the result into
+     * an associative array.
+     *
+     * This function is only able to handle queries that returns a
+     * table such as SELECT.
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @param  string $query  SQL string that contains the query
+     * @return array|false the result table
+     */
+    protected function _queryDB($query) {
+        $resultarray = array();
+        if($this->dbcon) {
+            $result = @pg_query($this->dbcon, $query);
+            if($result) {
+                while(($t = pg_fetch_assoc($result)) !== false)
+                    $resultarray[] = $t;
+                pg_free_result($result);
+                return $resultarray;
+            } else{
+                $this->_debug('PgSQL err: '.pg_last_error($this->dbcon), -1, __LINE__, __FILE__);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Executes an update or insert query. This differs from the
+     * MySQL one because it does NOT return the last insertID
+     *
+     * @author Andreas Gohr <andi@splitbrain.org>
+     *
+     * @param string $query
+     * @return bool
+     */
+    protected function _modifyDB($query) {
+        if($this->dbcon) {
+            $result = @pg_query($this->dbcon, $query);
+            if($result) {
+                pg_free_result($result);
+                return true;
+            }
+            $this->_debug('PgSQL err: '.pg_last_error($this->dbcon), -1, __LINE__, __FILE__);
+        }
+        return false;
+    }
+
+    /**
+     * Start a transaction
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @param string $mode  could be 'READ' or 'WRITE'
+     * @return bool
+     */
+    protected function _lockTables($mode) {
+        if($this->dbcon) {
+            $this->_modifyDB('BEGIN');
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Commit a transaction
+     *
+     * @author Matthias Grimm <matthiasgrimm@users.sourceforge.net>
+     *
+     * @return bool
+     */
+    protected function _unlockTables() {
+        if($this->dbcon) {
+            $this->_modifyDB('COMMIT');
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Escape a string for insertion into the database
+     *
+     * @author Andreas Gohr <andi@splitbrain.org>
+     *
+     * @param  string  $string The string to escape
+     * @param  bool    $like   Escape wildcard chars as well?
+     * @return string
+     */
+    protected function _escape($string, $like = false) {
+        $string = pg_escape_string($string);
+        if($like) {
+            $string = addcslashes($string, '%_');
+        }
+        return $string;
+    }
+}