summaryrefslogtreecommitdiff
path: root/it_user.class
diff options
context:
space:
mode:
authorChristian Schneider2007-10-11 00:39:30 +0000
committerChristian Schneider2007-10-11 00:39:30 +0000
commit35fe33f7364329dacf415c950bff01b6de9ef88e (patch)
treeb0e6b018b50038ca20266723c53750268f508df5 /it_user.class
parent1f95711ff3e9697cd85a54545ab42e5fd3611317 (diff)
downloaditools-35fe33f7364329dacf415c950bff01b6de9ef88e.tar.gz
itools-35fe33f7364329dacf415c950bff01b6de9ef88e.tar.bz2
itools-35fe33f7364329dacf415c950bff01b6de9ef88e.zip
Populated release branch
Diffstat (limited to 'it_user.class')
-rw-r--r--it_user.class505
1 files changed, 505 insertions, 0 deletions
diff --git a/it_user.class b/it_user.class
new file mode 100644
index 0000000..b0bb05b
--- /dev/null
+++ b/it_user.class
@@ -0,0 +1,505 @@
+<?php
+/*
+** $Id$
+**
+** Copyright (C) 1995-2007 by the ITools Authors.
+** This file is part of ITools - the Internet Tools Library
+**
+** ITools is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 3 of the License, or
+** (at your option) any later version.
+**
+** ITools is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program. If not, see <http://www.gnu.org/licenses/>.
+**
+** it_user.class - User management and authentication
+*/
+
+/* PUBLIC and guaranteed to stay in same order (but not value) forever */
+define('IT_USER_STATUS_FAILED', 1); /* Wrong password given */
+define('IT_USER_STATUS_UNKNOWN', 2); /* Not logged in, no UID */
+define('IT_USER_STATUS_ANONYMOUS', 3); /* Not logged in, UID known */
+define('IT_USER_STATUS_KNOWN', 4); /* Not logged in, UID,username known */
+define('IT_USER_STATUS_SESSION', 5); /* Has a valid session */
+
+/* PRIVATE */
+define('_IT_USER_UID_COOKIE', 'UID');
+define('_IT_USER_UID_COOKIE_LIFETIME', 0x7FFFFFFF); /* Forever :-) */
+define('_IT_USER_STATUS_INVALID', 0); /* INTERNAL: Not yet evaluated */
+
+class it_user extends it_dbi
+{
+ /* PRIVATE */
+ var $status; # Current status (IT_USER_STATUS_...)
+ var $session; # Session object
+ var $sessioninitialized = false;
+
+ var $login_identifier_required = false;
+ var $login_identifier;
+ var $domain;
+ var $lifetime;
+ var $secret;
+ var $urlauthenticationcode = 'uac'; # Name of UAC url parameter
+
+ var $uid;
+ var $username;
+
+ /*
+ * Used by login(), contains unvalidated user data to give overloading
+ * functions a way of accessing it.
+ */
+ var $workrecord;
+
+
+/**
+ * Constructor
+ * @param $p array(key => value) of configuration data
+ */
+function it_user($p)
+{
+ $this->p = $p + array(
+ 'uid_field' => 'ID',
+ 'table' => 'T_Users',
+ 'username_field' => 'Username',
+ 'password_field' => 'Password',
+ 'uidcookiename' => _IT_USER_UID_COOKIE,
+ 'sessioncookiename' => null
+ );
+
+ # Default to uid being primary key, may change later
+ $this->it_dbi(array('table' => $this->p['table'], 'keyfield' => $this->p['uid_field']));
+
+ $this->session = new it_session;
+ $this->status = _IT_USER_STATUS_INVALID;
+}
+
+
+/**
+ * Post processing, called by ITools after reading a database record
+ * @access private
+ */
+function _read_post_process()
+{
+ parent::_read_post_process();
+
+ # If read succeeded, get UID. This is necessary because it's only set if a cookie is present (i.e. in web-context)
+ if (isset($this->{$this->p['uid_field']}))
+ $this->uid = $this->{$this->p['uid_field']};
+
+ # Get username from database field (shortcut)
+ $this->username = $this->{$this->p['username_field']};
+}
+
+
+function set_session_cookie_name($sessioncookiename)
+{
+ $this->p['sessioncookiename'] = $sessioncookiename;
+}
+
+
+function set_uid_cookie_name($uidcookiename)
+{
+ $this->p['uidcookiename'] = $uidcookiename;
+}
+
+
+function set_domain($domain)
+{
+ $this->domain = $domain;
+}
+
+
+function set_session_lifetime($lifetime)
+{
+ $this->lifetime = $lifetime;
+}
+
+
+function set_login_identifier($login_identifier)
+{
+ $this->login_identifier_required = true;
+ $this->login_identifier = $login_identifier;
+}
+
+
+function _init_session()
+{
+ if (!$this->sessioninitialized)
+ {
+ # Using non-standard values for session?
+ if ($this->p['sessioncookiename'])
+ $this->session->set_cookiename($this->p['sessioncookiename']);
+
+ if (isset($this->domain))
+ $this->session->set_domain($this->domain);
+
+ if (isset($this->lifetime))
+ $this->session->set_lifetime($this->lifetime);
+
+ if (isset($this->secret))
+ $this->session->set_secret($this->secret);
+
+ $this->session->init();
+ $this->sessioninitialized = true;
+ }
+}
+
+
+function get_status()
+{
+ if ($this->status == _IT_USER_STATUS_INVALID)
+ {
+ $this->_init_session();
+
+ if ($this->session->is_valid())
+ {
+ $this->status = IT_USER_STATUS_SESSION;
+ $this->_set_uid($this->session->get_uid());
+ $this->read($this->uid);
+
+ # username == uid means we don't have a username yet
+ if ($this->username == $this->uid)
+ $this->username = "";
+ }
+ else if (isset($_COOKIE[$this->p['uidcookiename']]) && ($this->uid = substr($_COOKIE[$this->p['uidcookiename']], 0, 32)))
+ {
+ $this->read($this->uid);
+
+ if ($this->username == $this->uid)
+ $this->username = "";
+
+ $this->status = $this->username ? IT_USER_STATUS_KNOWN : IT_USER_STATUS_ANONYMOUS;
+ }
+ else
+ {
+ $this->status = IT_USER_STATUS_UNKNOWN;
+ $this->username = '';
+
+ if ($this->p['uid_field'])
+ $this->_set_uid($this->create_uid());
+ }
+ }
+
+ return $this->status;
+}
+
+
+function get_username()
+{
+ return $this->username;
+}
+
+
+function get_uid()
+{
+ return $this->uid;
+}
+
+
+function _set_uid($uid)
+{
+ $this->uid = $uid;
+
+ if (!isset($_COOKIE[$this->p['uidcookiename']]) || ($_COOKIE[$this->p['uidcookiename']] != $uid))
+ {
+ @setcookie($this->p['uidcookiename'], $uid, _IT_USER_UID_COOKIE_LIFETIME, "/", $this->domain);
+ $_COOKIE[$this->p['uidcookiename']] = $uid;
+ }
+}
+
+
+/* Return session status of this user: Is she logged in? */
+function is_logged_in()
+{
+ return $this->status == IT_USER_STATUS_SESSION;
+}
+
+
+/**
+ * Try to log in user. Use get_status() to check result.
+ * NOTE: Must not be called AFTER get_status() has been used.
+ * @param $username User ID to login
+ * @param $password Password to authenticate login
+ * @param $ignorepassword True if you want to login anyway (e.g. 'su')
+ * @return non-false if successful, false on error
+ */
+function login($username, $password, $ignorepassword = false, $withsession = true)
+{
+ $result = false;
+
+ $this->_init_session();
+ $this->workrecord = new it_dbi(array('table' => $this->p['table'], 'keyfield' => $this->p['username_field']));
+
+ if ($this->workrecord->read($username))
+ {
+ if ($ignorepassword || $this->check_password($password, $this->workrecord->{$this->p['password_field']}))
+ {
+ $this->session->set_uid($this->workrecord->{$this->p['uid_field']});
+ if ($withsession)
+ $result = $this->session->set_valid(true, $this->login_identifier_required, $this->login_identifier);
+ else
+ $result = $_COOKIE[$this->p['uidcookiename']] = $this->session->get_uid();
+ }
+ }
+
+ if ($result && ($this->session->get_uid() == $this->workrecord->{$this->p['uid_field']}))
+ $this->username = $this->workrecord->{$this->p['username_field']};
+
+ $this->status = $result ? _IT_USER_STATUS_INVALID : IT_USER_STATUS_FAILED;
+
+ return $result;
+}
+
+
+/*
+ * Logout user.
+ * NOTE: Must not be called AFTER get_status() has been used.
+ */
+function logout()
+{
+ $this->_init_session();
+ $this->session->set_valid(false);
+}
+
+
+/*
+ * Throw away all user information and restart from scratch...
+ */
+function purge()
+{
+ $this->status = _IT_USER_STATUS_INVALID;
+ $this->_set_uid($this->create_uid());
+ $this->username = "";
+ $this->session->purge();
+}
+
+
+/*
+ * Create user database record.
+ * @param $tags Fields to set (uid and username are optional)
+ * @see it_dbi::insert()
+ */
+function create($tags)
+{
+ # Make sure UID is always set in database records
+ if ($this->p['uid_field'])
+ {
+ if (!$this->uid)
+ $this->_set_uid($this->create_uid());
+
+ $tags[$this->p['uid_field']] = $this->uid;
+ }
+
+ # Create dummy but unique username if none given
+ if (!$tags[$this->p['username_field']] && !$this->{$this->p['username_field']})
+ $tags[$this->p['username_field']] = $this->uid;
+
+ if ($result = $this->insert($tags))
+ $this->_set_uid($this->{$this->p['uid_field']});
+
+ return $result;
+}
+
+
+/*
+ * Create unique identifier used for anonymously users, Override if you want
+ * different type of UIDs.
+ * Returns newly created uid
+ */
+function create_uid()
+{
+ return md5(uniqid(rand())); /* random garbage */
+}
+
+
+/*
+ * Create a login identifier and set session to login identifier 'secret' value
+ * Returns a value to be put into the login <form> which has to be passed to
+ * login() to create a valid session
+ */
+function create_login_identifier()
+{
+ return $this->session->create_login_identifier();
+}
+
+
+/*
+ * Create a random password with given length.
+ */
+function create_password($length = 8, $charset = 'abcdefghjkpqrstuvwxyz23456789ABCDEFGHJKPRSTUVWXYZ')
+{
+ $result = "";
+
+ mt_srand((double)microtime() * 1000000);
+
+ for ($i = 0; $i < $length; $i++)
+ $result .= substr($charset, mt_rand(0, strlen($charset) - 1), 1);
+
+ return $result;
+}
+
+
+/*
+ * Crypt the password, same function is used in check_login_status
+ * You can use unencrypted passwords if you extend the user class and
+ * override this function.
+ */
+function crypt_password($password)
+{
+ $result = $this->query("SELECT PASSWORD('" . mysql_real_escape_string($password) . "')");
+ list($pw) = mysql_fetch_array($result);
+
+ return $pw;
+}
+
+
+/*
+ * Crypt the password and compare it to cryptedpassword.
+ */
+function check_password($password, $cryptedpassword)
+{
+ return $this->crypt_password($password) == $cryptedpassword;
+}
+
+
+/*
+ * Check if cookies are enabled.
+ * NOTE: Only works if you used create_login_identifier() on previous page
+ */
+function has_cookies()
+{
+ return $this->session->has_cookies();
+}
+
+
+/*
+ * Check if $name would be an acceptable username
+ */
+function is_valid_username($name)
+{
+ if ((strlen($name) >= 2) && (strlen($name) <= 32))
+ {
+ if (!ereg('["\'\\&\$+]', $name))
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ * Check if $word would be an acceptable password
+ */
+function is_valid_password($word)
+{
+ if ((strlen($word) >= 2) && (strlen($word) <= 32))
+ {
+ if (!ereg('["\'\\&\$+]', $word))
+ return true;
+ }
+ return false;
+}
+
+
+/*
+ * Sign string with current user id or session
+ * @param $text Text to be signed
+ * @param $withsession Sign with session if true, with uid if false
+ * @return Signature for $text
+ */
+function create_signature($text, $withsession = true)
+{
+ if ($withsession)
+ {
+ switch ($this->get_status())
+ {
+ case IT_USER_STATUS_SESSION:
+ $result = $this->session->create_signature($text);
+ break;
+
+ default:
+ $result = md5("$this->secret,$text,$this->secret");
+ break;
+ }
+ }
+ else
+ {
+ /* Sign with UID only */
+ $result = md5("$this->secret,$this->uid,$text,$this->secret");
+ }
+
+ return $result;
+}
+
+/*
+ * Check signature for string with current user id or session
+ * @param $text Text which was signed
+ * @param $signature Signature to be checked
+ * @param $withsession Signed with session if true, with uid if false
+ * @return True if signature ok, false otherwise
+ */
+function check_signature($text, $signature, $withsession = true)
+{
+ if ($withsession)
+ {
+ switch ($this->get_status())
+ {
+ case IT_USER_STATUS_SESSION:
+ $result = $this->session->check_signature($text, $signature);
+ break;
+
+ default:
+ $result = (md5("$this->secret,$text,$this->secret") == $signature);
+ break;
+ }
+ }
+ else
+ {
+ /* Sign with UID only */
+ $result = ($this->create_signature($text, false) == $signature);
+ }
+
+ return $result;
+}
+
+/*
+ * Sign an url with parameters
+ * @param $url URL to sign
+ * @param $withsession Signed with session if true, with uid if false
+ * @return Signed url
+ */
+function sign_url($url, $withsession = false)
+{
+ if (strstr($url, '?'))
+ $url .= "&amp;$this->urlauthenticationcode=" . $this->create_signature(str_replace('&amp;', '&', $url), $withsession);
+
+ return $url;
+}
+
+/*
+ * Check if url GET parameters are properly signed and not modified
+ * @param $withsession Signed with session if true, with uid if false
+ * @return False if url was modified
+ */
+function check_url($withsession = false)
+{
+ $result = true; /* Default to true for url without parameters */
+
+ if (!empty($_SERVER['QUERY_STRING']))
+ {
+ $url = ereg_replace("&?$this->urlauthenticationcode=[a-zA-Z0-9]*", '', $_SERVER['REQUEST_URI']);
+
+ $result = $this->check_signature($url, $GLOBALS[$this->urlauthenticationcode], $withsession);
+ }
+
+ return $result;
+}
+
+} /* End class it_user */
+
+?>