|
From: Meik S. <acy...@ph...> - 2008-12-11 17:42:31
|
Author: acydburn
Date: Thu Dec 11 17:39:51 2008
New Revision: 9185
Log:
add/remove some files. Since this branch is only a playground i do not want to preserve history for most files.
Put some functions from functions.php into core-relevant classes (security and url)
splitted session.php into session and user
added login to user class
call auth directly from session/user
added the acm abstract
Added:
branches/acydburn/phpBB/includes/acm/index.php (with props)
branches/acydburn/phpBB/includes/auth/db.php (with props)
branches/acydburn/phpBB/includes/classes/acl.php (with props)
branches/acydburn/phpBB/includes/classes/acl_admin.php (with props)
branches/acydburn/phpBB/includes/classes/session.php (with props)
branches/acydburn/phpBB/includes/classes/user.php (with props)
branches/acydburn/phpBB/includes/core/core_security.php (with props)
branches/acydburn/phpBB/includes/core/core_url.php (with props)
Removed:
branches/acydburn/phpBB/includes/acp/auth.php
branches/acydburn/phpBB/includes/auth.php
branches/acydburn/phpBB/includes/auth/auth_db.php
branches/acydburn/phpBB/includes/session.php
Added: branches/acydburn/phpBB/includes/acm/index.php
==============================================================================
*** branches/acydburn/phpBB/includes/acm/index.php (added)
--- branches/acydburn/phpBB/includes/acm/index.php Thu Dec 11 17:39:51 2008
***************
*** 0 ****
--- 1,434 ----
+ <?php
+ /**
+ *
+ * @package acm
+ * @version $Id$
+ * @copyright (c) 2008 phpBB Group
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
+ *
+ */
+
+ /**
+ * ACM call schema for developer
+ *
+ * Base Class: phpbb_acm
+ * Abstract: phpbb_acm_abstract
+ * Type-specific class: phpbb_acm_[object] extends abstract
+ *
+ * Pre-defined cache types:
+ * data => data files
+ * sql => sql files
+ * tpl => template files
+ * ctpl => custom template files
+ *
+ * Main Class used for calls is phpbb_acm
+ * Methods to be called for cache data handling:
+ * get(): Get cached data. For global data, prefix name with #
+ * put(): Put data in cache. For global data, prefix name with #
+ * tidy(): Tidy complete cache and remove expired entries.
+ * purge(): Purge complete cache and remove all entries.
+ * unload(): Unload complete cache (called on __destruct)
+ * __call(): for calling methods only defined in phpbb_acm_[object]; the cache type must be the first parameter
+ * example: [acm]->call_custom_method([type], [additional parameter]);
+ *
+ * Methods for handling cache types
+ * register(), supported()
+ *
+ * If you add a new cache object (shm for example), then these are the phpbb_acm_[object] methods you must (or can) define (based on the abstract):
+ * Required: get_local(), put_local(), destroy_local(), load(), save(), exists(), _purge()
+ * Optional: get_global(), put_global(), destroy_global(), _tidy()
+ *
+ */
+
+
+ /**
+ * @ignore
+ */
+ if (!defined('IN_PHPBB'))
+ {
+ exit;
+ }
+
+ /**
+ * Define missing ACM config variable... if not initialized yet
+ * @ignore
+ */
+ if (!defined('CONFIG_ACM_TYPE'))
+ {
+ define('CONFIG_ACM_TYPE', 'file');
+ }
+
+ /**
+ * Base, accessible ACM class. All ACM calls are directed to this class
+ * @package acm
+ */
+ class phpbb_acm
+ {
+ /**
+ * Currently registered core acm types
+ */
+ private $cache_types = array('data' => NULL, 'sql' => NULL, 'tpl' => NULL, 'ctpl' => NULL);
+
+ /**
+ * Constructor
+ */
+ public function __construct() { }
+
+ /**
+ * In case someone wants to access a public function for the acm plugin not defined within the phpbb_acm class,
+ * we use this magic method. We expect the cache type for those calls as the *first* argument
+ */
+ public function __call($method, $arguments)
+ {
+ // Get cache type
+ $cache_type = $arguments[0];
+ array_shift($arguments);
+
+ // Check if the cache type is initialized and exist
+ if (!$this->type_exists($cache_type))
+ {
+ return false;
+ }
+
+ // $this->cache_types[$cache_type]->$method($arguments);
+ return call_user_func_array(array($this->cache_types[$cache_type], $method), $arguments);
+ }
+
+ /**
+ * Get data from cache
+ *
+ * @param string $var_name The variable name. If prefixed with #, then the global cache will be used.
+ * @param string $cache_type The cache type to use. Default is 'data'.
+ *
+ * @return mixed false if no data was stored within the cache, else the dataset.
+ */
+ public function get($var_name, $cache_type = 'data')
+ {
+ return $this->__call('get', array($cache_type, $var_name));
+ }
+
+ /**
+ * Store data in cache
+ *
+ * @param string $var_name The variable name. If prefixed with #, then the global cache will be used.
+ * @param mixed $data The data to store, usually an array.
+ * @param int $ttl The time the cache should be valid in seconds.
+ * @param string $cache_type The cache type to use. Default is 'data'.
+ *
+ * @return mixed The dataset stored.
+ */
+ public function put($var_name, $data, $ttl = 31536000, $cache_type = 'data')
+ {
+ return $this->__call('put', array($cache_type, $var_name, $data, $ttl));
+ }
+
+ /**
+ * Tidy cache.
+ * This removes all expired cache files
+ */
+ public function tidy()
+ {
+ foreach ($this->cache_types as $cache_type => $object)
+ {
+ if ($object === NULL)
+ {
+ continue;
+ }
+
+ $this->cache_types[$cache_type]->tidy();
+ }
+ }
+
+ /**
+ * Purge cache.
+ * This removes all cache files from currently registered cache objects
+ */
+ public function purge()
+ {
+ foreach ($this->cache_types as $cache_type => $object)
+ {
+ if ($object === NULL)
+ {
+ continue;
+ }
+
+ $this->cache_types[$cache_type]->purge();
+ }
+ }
+
+ /**
+ * Register a custom cache type/class
+ *
+ * @param string $cache_type The cache type to register/set
+ * @param string $cache_append String to append to the cached data as identifier (if the coder has different types to distinct from)
+ * @param string $cache_object The exact name of the cache class to load.
+ * The filename must be: <code>includes/acm/acm_{$cache_object}.php</code>
+ * The class definition must be: <code>class phpbb_acm_{$cache_object} extends phpbb_acm_abstract
+ *
+ */
+ public function register($cache_type, $cache_append = false, $cache_object = CONFIG_ACM_TYPE)
+ {
+ // We need to init every cache type...
+ if (!isset($this->cache_types[$cache_type]))
+ {
+ $this->cache_types[$cache_type] = NULL;
+ }
+
+ // Unregister if already registered
+ if ($this->cache_types[$cache_type] !== NULL)
+ {
+ $this->cache_types[$cache_type] = NULL;
+ }
+
+ if ($this->cache_types[$cache_type] === NULL)
+ {
+ $class_name = 'phpbb_acm_' . $cache_object;
+
+ if (!class_exists($class_name))
+ {
+ if (!file_exists(PHPBB_ROOT_PATH . 'includes/acm/acm_' . $cache_object . '.' . PHP_EXT))
+ {
+ return false;
+ }
+ require_once(PHPBB_ROOT_PATH . 'includes/acm/acm_' . $cache_object . '.' . PHP_EXT);
+ }
+
+ // Set cache prefix, for example ctpl_prosilver
+ $cache_prefix = ($cache_append === false) ? $cache_type : $cache_type . '_' . $cache_append;
+
+ $this->cache_types[$cache_type] = new $class_name($cache_prefix);
+
+ if (!$this->supported($cache_type))
+ {
+ $this->cache_types[$cache_type] = NULL;
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Unload everything from cache and make sure non-stored cache items are properly saved.
+ */
+ public function unload()
+ {
+ foreach ($this->cache_types as $cache_type => $object)
+ {
+ if ($object === NULL)
+ {
+ continue;
+ }
+
+ $this->cache_types[$cache_type]->unload();
+ }
+ }
+
+ /**
+ * Check if a specific cache type is supported with the ACM class
+ *
+ * @param string $cache_type The cache type to check.
+ *
+ * @return bool True if the type is supported, else false.
+ */
+ public function supported($cache_type)
+ {
+ if (!$this->type_exists($cache_type))
+ {
+ return false;
+ }
+
+ return !empty($this->cache_types[$cache_type]->supported[$cache_type]);
+ }
+
+ /**
+ * Check if the cache type exists. Sometimes some types do not exist if the relevant files are not there or do not support the given cache type.
+ *
+ * @param string $cache_type The cache type to check.
+ *
+ * @return bool True if the type exist, else false.
+ * @access private
+ */
+ private function type_exists($cache_type)
+ {
+ if (!isset($this->cache_types[$cache_type]) || $this->cache_types[$cache_type] === NULL)
+ {
+ $this->register($cache_type);
+ }
+
+ return ($this->cache_types[$cache_type] !== NULL);
+ }
+ }
+
+ /**
+ * The abstract class all ACM plugins must extend. This abstract defines an object to be filled, with some functions pre-filled and some which must be filled.
+ * @package acm
+ */
+ abstract class phpbb_acm_abstract
+ {
+ protected $vars = array();
+ protected $var_expires = array();
+ protected $is_modified = false;
+
+ public $cache_prefix = '';
+
+ abstract protected function get_local($var_name);
+ abstract protected function put_local($var_name, $data, $ttl = 31536000);
+ abstract protected function destroy_local($var_name, $additional_data = false);
+ abstract public function load();
+ abstract public function save();
+ abstract public function exists($var_name);
+
+ abstract protected function _purge();
+
+ public function get($var_name)
+ {
+ // A global variable, use the internal arrays
+ if ($var_name[0] === '#')
+ {
+ $var_name = substr($var_name, 1);
+ return $this->get_global($var_name);
+ }
+ else
+ {
+ return $this->get_local($var_name);
+ }
+ }
+
+ public function put($var_name, $data, $ttl = 31536000)
+ {
+ if ($var_name[0] === '#')
+ {
+ $var_name = substr($var_name, 1);
+ return $this->put_global($var_name, $data, $ttl);
+ }
+ else
+ {
+ return $this->put_local($var_name, $data, $ttl);
+ }
+ }
+
+ public function destroy($var_name, $additional_data = false)
+ {
+ if ($var_name[0] === '#')
+ {
+ $var_name = substr($var_name, 1);
+ $this->destroy_global($var_name, $additional_data);
+ }
+ else
+ {
+ $this->destroy_local($var_name, $additional_data);
+ }
+ }
+
+ public function unload()
+ {
+ $this->save();
+ unset($this->vars);
+ unset($this->var_expires);
+
+ $this->vars = array();
+ $this->var_expires = array();
+ }
+
+ protected function get_global($var_name)
+ {
+ // Check if we have all variables
+ if (!sizeof($this->vars))
+ {
+ $this->load();
+ }
+
+ if (!isset($this->var_expires[$var_name]))
+ {
+ return false;
+ }
+
+ // If expired... we remove this entry now...
+ if (time() > $this->var_expires[$var_name])
+ {
+ $this->destroy_global($var_name);
+ return false;
+ }
+
+ if (isset($this->vars[$var_name]))
+ {
+ return $this->vars[$var_name];
+ }
+
+ return false;
+ }
+
+ protected function put_global($var_name, $data, $ttl = 31536000)
+ {
+ $this->vars[$var_name] = $data;
+ $this->var_expires[$var_name] = time() + $ttl;
+ $this->is_modified = true;
+
+ return $data;
+ }
+
+ protected function destroy_global($var_name, $additional_data = false)
+ {
+ $this->is_modified = true;
+
+ unset($this->vars[$var_name]);
+ unset($this->var_expires[$var_name]);
+
+ // We save here to let the following cache hits succeed
+ $this->save();
+ }
+
+ /**
+ * Tidy cache
+ */
+ public function tidy()
+ {
+ // If cache has no auto-gc, we call the _tidy function here
+ if (method_exists($this, '_tidy'))
+ {
+ $this->_tidy();
+ }
+
+ // Now tidy global settings
+ if (!sizeof($this->vars))
+ {
+ $this->load();
+ }
+
+ foreach ($this->var_expires as $var_name => $expires)
+ {
+ if (time() > $expires)
+ {
+ // We only unset, then save later
+ unset($this->vars[$var_name]);
+ unset($this->var_expires[$var_name]);
+ }
+ }
+
+ $this->is_modified = true;
+ $this->save();
+
+ set_config('cache_last_gc', time(), true);
+ }
+
+ /**
+ * Purge Cache
+ */
+ public function purge()
+ {
+ $this->_purge();
+
+ // Now purge global settings
+ unset($this->vars);
+ unset($this->var_expires);
+
+ $this->vars = array();
+ $this->var_expires = array();
+
+ $this->is_modified = true;
+ $this->save();
+ }
+ }
+
+ ?>
\ No newline at end of file
Propchange: branches/acydburn/phpBB/includes/acm/index.php
------------------------------------------------------------------------------
svn:eol-style = LF
Propchange: branches/acydburn/phpBB/includes/acm/index.php
------------------------------------------------------------------------------
svn:keywords = "Author Date Id Revision"
Removed: branches/acydburn/phpBB/includes/acp/auth.php
==============================================================================
*** branches/acydburn/phpBB/includes/acp/auth.php (original)
--- branches/acydburn/phpBB/includes/acp/auth.php (removed)
***************
*** 1,1260 ****
- <?php
- /**
- *
- * @package phpBB3
- * @version $Id$
- * @copyright (c) 2005 phpBB Group
- * @license http://opensource.org/licenses/gpl-license.php GNU Public License
- *
- */
-
- /**
- * @ignore
- */
- if (!defined('IN_PHPBB'))
- {
- exit;
- }
-
- /**
- * ACP Permission/Auth class
- * @package phpBB3
- */
- class auth_admin extends auth
- {
- /**
- * Init auth settings
- */
- function __construct()
- {
- global $db, $cache;
-
- if (($this->acl_options = $cache->get('_acl_options')) === false)
- {
- $sql = 'SELECT auth_option_id, auth_option, is_global, is_local
- FROM ' . ACL_OPTIONS_TABLE . '
- ORDER BY auth_option_id';
- $result = $db->sql_query($sql);
-
- $global = $local = 0;
- $this->acl_options = array();
- while ($row = $db->sql_fetchrow($result))
- {
- if ($row['is_global'])
- {
- $this->acl_options['global'][$row['auth_option']] = $global++;
- }
-
- if ($row['is_local'])
- {
- $this->acl_options['local'][$row['auth_option']] = $local++;
- }
-
- $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id'];
- $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option'];
- }
- $db->sql_freeresult($result);
-
- $cache->put('_acl_options', $this->acl_options);
- }
- }
-
- /**
- * Get permission mask
- * This function only supports getting permissions of one type (for example a_)
- *
- * @param set|view $mode defines the permissions we get, view gets effective permissions (checking user AND group permissions), set only gets the user or group permission set alone
- * @param mixed $user_id user ids to search for (a user_id or a group_id has to be specified at least)
- * @param mixed $group_id group ids to search for, return group related settings (a user_id or a group_id has to be specified at least)
- * @param mixed $forum_id forum_ids to search for. Defining a forum id also means getting local settings
- * @param string $auth_option the auth_option defines the permission setting to look for (a_ for example)
- * @param local|global $scope the scope defines the permission scope. If local, a forum_id is additionally required
- * @param ACL_NEVER|ACL_NO|ACL_YES $acl_fill defines the mode those permissions not set are getting filled with
- */
- public function get_mask($mode, $user_id = false, $group_id = false, $forum_id = false, $auth_option = false, $scope = false, $acl_fill = ACL_NEVER)
- {
- global $db, $user;
-
- $hold_ary = array();
- $view_user_mask = ($mode == 'view' && $group_id === false) ? true : false;
-
- if ($auth_option === false || $scope === false)
- {
- return array();
- }
-
- $acl_user_function = ($mode == 'set') ? 'acl_user_raw_data' : 'acl_raw_data';
-
- if (!$view_user_mask)
- {
- if ($forum_id !== false)
- {
- $hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', $forum_id) : $this->$acl_user_function($user_id, $auth_option . '%', $forum_id);
- }
- else
- {
- $hold_ary = ($group_id !== false) ? $this->acl_group_raw_data($group_id, $auth_option . '%', ($scope == 'global') ? 0 : false) : $this->$acl_user_function($user_id, $auth_option . '%', ($scope == 'global') ? 0 : false);
- }
- }
-
- // Make sure hold_ary is filled with every setting (prevents missing forums/users/groups)
- $ug_id = ($group_id !== false) ? ((!is_array($group_id)) ? array($group_id) : $group_id) : ((!is_array($user_id)) ? array($user_id) : $user_id);
- $forum_ids = ($forum_id !== false) ? ((!is_array($forum_id)) ? array($forum_id) : $forum_id) : (($scope == 'global') ? array(0) : array());
-
- // Only those options we need
- $compare_options = array_diff(preg_replace('/^((?!' . $auth_option . ').+)|(' . $auth_option . ')$/', '', array_keys($this->acl_options[$scope])), array(''));
-
- // If forum_ids is false and the scope is local we actually want to have all forums within the array
- if ($scope == 'local' && !sizeof($forum_ids))
- {
- $sql = 'SELECT forum_id
- FROM ' . FORUMS_TABLE;
- $result = $db->sql_query($sql, 120);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $forum_ids[] = (int) $row['forum_id'];
- }
- $db->sql_freeresult($result);
- }
-
- if ($view_user_mask)
- {
- $auth2 = null;
-
- $sql = 'SELECT user_id, user_permissions, user_type
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', $ug_id);
- $result = $db->sql_query($sql);
-
- while ($userdata = $db->sql_fetchrow($result))
- {
- if ($user->data['user_id'] != $userdata['user_id'])
- {
- $auth2 = new auth();
- $auth2->acl($userdata);
- }
- else
- {
- global $auth;
- $auth2 = &$auth;
- }
-
-
- $hold_ary[$userdata['user_id']] = array();
- foreach ($forum_ids as $f_id)
- {
- $hold_ary[$userdata['user_id']][$f_id] = array();
- foreach ($compare_options as $option)
- {
- $hold_ary[$userdata['user_id']][$f_id][$option] = $auth2->acl_get($option, $f_id);
- }
- }
- }
- $db->sql_freeresult($result);
-
- unset($userdata);
- unset($auth2);
- }
-
- foreach ($ug_id as $_id)
- {
- if (!isset($hold_ary[$_id]))
- {
- $hold_ary[$_id] = array();
- }
-
- foreach ($forum_ids as $f_id)
- {
- if (!isset($hold_ary[$_id][$f_id]))
- {
- $hold_ary[$_id][$f_id] = array();
- }
- }
- }
-
- // Now, we need to fill the gaps with $acl_fill. ;)
-
- // Now switch back to keys
- if (sizeof($compare_options))
- {
- $compare_options = array_combine($compare_options, array_fill(1, sizeof($compare_options), $acl_fill));
- }
-
- // Defining the user-function here to save some memory
- $return_acl_fill = create_function('$value', 'return ' . $acl_fill . ';');
-
- // Actually fill the gaps
- if (sizeof($hold_ary))
- {
- foreach ($hold_ary as $ug_id => $row)
- {
- foreach ($row as $id => $options)
- {
- // Do not include the global auth_option
- unset($options[$auth_option]);
-
- // Not a "fine" solution, but at all it's a 1-dimensional
- // array_diff_key function filling the resulting array values with zeros
- // The differences get merged into $hold_ary (all permissions having $acl_fill set)
- $hold_ary[$ug_id][$id] = array_merge($options,
-
- array_map($return_acl_fill,
- array_flip(
- array_diff(
- array_keys($compare_options), array_keys($options)
- )
- )
- )
- );
- }
- }
- }
- else
- {
- $hold_ary[($group_id !== false) ? $group_id : $user_id][(int) $forum_id] = $compare_options;
- }
-
- return $hold_ary;
- }
-
- /**
- * Get permission mask for roles
- * This function only supports getting masks for one role
- */
- public function get_role_mask($role_id)
- {
- global $db;
-
- $hold_ary = array();
-
- // Get users having this role set...
- $sql = 'SELECT user_id, forum_id
- FROM ' . ACL_USERS_TABLE . '
- WHERE auth_role_id = ' . $role_id . '
- ORDER BY forum_id';
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $hold_ary[$row['forum_id']]['users'][] = $row['user_id'];
- }
- $db->sql_freeresult($result);
-
- // Now grab groups...
- $sql = 'SELECT group_id, forum_id
- FROM ' . ACL_GROUPS_TABLE . '
- WHERE auth_role_id = ' . $role_id . '
- ORDER BY forum_id';
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $hold_ary[$row['forum_id']]['groups'][] = $row['group_id'];
- }
- $db->sql_freeresult($result);
-
- return $hold_ary;
- }
-
- /**
- * Display permission mask (assign to template)
- */
- public function display_mask($mode, $permission_type, array $hold_ary, $user_mode = 'user', $local = false, $group_display = true)
- {
- global $template, $user, $db;
-
- // Define names for template loops, might be able to be set
- $tpl_pmask = 'p_mask';
- $tpl_fmask = 'f_mask';
- $tpl_category = 'category';
- $tpl_mask = 'mask';
-
- $l_acl_type = (isset($user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)])) ? $user->lang['ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type)] : 'ACL_TYPE_' . (($local) ? 'LOCAL' : 'GLOBAL') . '_' . strtoupper($permission_type);
-
- // Allow trace for viewing permissions and in user mode
- $show_trace = ($mode == 'view' && $user_mode == 'user') ? true : false;
-
- // Get names
- if ($user_mode == 'user')
- {
- $sql = 'SELECT user_id as ug_id, username as ug_name
- FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', array_keys($hold_ary)) . '
- ORDER BY username_clean ASC';
- }
- else
- {
- $sql = 'SELECT group_id as ug_id, group_name as ug_name, group_type
- FROM ' . GROUPS_TABLE . '
- WHERE ' . $db->sql_in_set('group_id', array_keys($hold_ary)) . '
- ORDER BY group_type DESC, group_name ASC';
- }
- $result = $db->sql_query($sql);
-
- $ug_names_ary = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $ug_names_ary[$row['ug_id']] = ($user_mode == 'user') ? $row['ug_name'] : (($row['group_type'] == GROUP_SPECIAL) ? $user->lang['G_' . $row['ug_name']] : $row['ug_name']);
- }
- $db->sql_freeresult($result);
-
- // Get used forums
- $forum_ids = array();
- foreach ($hold_ary as $ug_id => $row)
- {
- $forum_ids = array_merge($forum_ids, array_keys($row));
- }
- $forum_ids = array_unique($forum_ids);
-
- $forum_names_ary = array();
- if ($local)
- {
- $forum_names_ary = make_forum_select(false, false, true, false, false, false, true);
-
- // Remove the disabled ones, since we do not create an option field here...
- foreach ($forum_names_ary as $key => $value)
- {
- if (!$value['disabled'])
- {
- continue;
- }
- unset($forum_names_ary[$key]);
- }
- }
- else
- {
- $forum_names_ary[0] = $l_acl_type;
- }
-
- // Get available roles
- $sql = 'SELECT *
- FROM ' . ACL_ROLES_TABLE . "
- WHERE role_type = '" . $db->sql_escape($permission_type) . "'
- ORDER BY role_order ASC";
- $result = $db->sql_query($sql);
-
- $roles = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $roles[$row['role_id']] = $row;
- }
- $db->sql_freeresult($result);
-
- $cur_roles = $this->acl_role_data($user_mode, $permission_type, array_keys($hold_ary));
-
- // Build js roles array (role data assignments)
- $s_role_js_array = '';
-
- if (sizeof($roles))
- {
- $s_role_js_array = array();
-
- // Make sure every role (even if empty) has its array defined
- foreach ($roles as $_role_id => $null)
- {
- $s_role_js_array[$_role_id] = "\n" . 'role_options[' . $_role_id . '] = new Array();' . "\n";
- }
-
- $sql = 'SELECT r.role_id, o.auth_option, r.auth_setting
- FROM ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' o
- WHERE o.auth_option_id = r.auth_option_id
- AND ' . $db->sql_in_set('r.role_id', array_keys($roles));
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
- {
- $flag = substr($row['auth_option'], 0, strpos($row['auth_option'], '_') + 1);
- if ($flag == $row['auth_option'])
- {
- continue;
- }
-
- $s_role_js_array[$row['role_id']] .= 'role_options[' . $row['role_id'] . '][\'' . addslashes($row['auth_option']) . '\'] = ' . $row['auth_setting'] . '; ';
- }
- $db->sql_freeresult($result);
-
- $s_role_js_array = implode('', $s_role_js_array);
- }
-
- $template->assign_var('S_ROLE_JS_ARRAY', $s_role_js_array);
- unset($s_role_js_array);
-
- // Now obtain memberships
- $user_groups_default = $user_groups_custom = array();
- if ($user_mode == 'user' && $group_display)
- {
- $sql = 'SELECT group_id, group_name, group_type
- FROM ' . GROUPS_TABLE . '
- ORDER BY group_type DESC, group_name ASC';
- $result = $db->sql_query($sql);
-
- $groups = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $groups[$row['group_id']] = $row;
- }
- $db->sql_freeresult($result);
-
- $memberships = group_memberships(false, array_keys($hold_ary), false);
-
- // User is not a member of any group? Bad admin, bad bad admin...
- if ($memberships)
- {
- foreach ($memberships as $row)
- {
- if ($groups[$row['group_id']]['group_type'] == GROUP_SPECIAL)
- {
- $user_groups_default[$row['user_id']][] = $user->lang['G_' . $groups[$row['group_id']]['group_name']];
- }
- else
- {
- $user_groups_custom[$row['user_id']][] = $groups[$row['group_id']]['group_name'];
- }
- }
- }
- unset($memberships, $groups);
- }
-
- // If we only have one forum id to display or being in local mode and more than one user/group to display,
- // we switch the complete interface to group by user/usergroup instead of grouping by forum
- // To achieve this, we need to switch the array a bit
- if (sizeof($forum_ids) == 1 || ($local && sizeof($ug_names_ary) > 1))
- {
- $hold_ary_temp = $hold_ary;
- $hold_ary = array();
- foreach ($hold_ary_temp as $ug_id => $row)
- {
- foreach ($forum_names_ary as $forum_id => $forum_row)
- {
- if (isset($row[$forum_id]))
- {
- $hold_ary[$forum_id][$ug_id] = $row[$forum_id];
- }
- }
- }
- unset($hold_ary_temp);
-
- foreach ($hold_ary as $forum_id => $forum_array)
- {
- $content_array = $categories = array();
- self::build_permission_array($hold_ary[$forum_id], $content_array, $categories, array_keys($ug_names_ary));
-
- $template->assign_block_vars($tpl_pmask, array(
- 'NAME' => ($forum_id == 0) ? $forum_names_ary[0] : $forum_names_ary[$forum_id]['forum_name'],
- 'PADDING' => ($forum_id == 0) ? '' : $forum_names_ary[$forum_id]['padding'],
-
- 'CATEGORIES' => implode('</th><th>', $categories),
-
- 'L_ACL_TYPE' => $l_acl_type,
-
- 'S_LOCAL' => ($local) ? true : false,
- 'S_GLOBAL' => (!$local) ? true : false,
- 'S_NUM_CATS' => sizeof($categories),
- 'S_VIEW' => ($mode == 'view') ? true : false,
- 'S_NUM_OBJECTS' => sizeof($content_array),
- 'S_USER_MODE' => ($user_mode == 'user') ? true : false,
- 'S_GROUP_MODE' => ($user_mode == 'group') ? true : false)
- );
-
- @reset($content_array);
- while (list($ug_id, $ug_array) = each($content_array))
- {
- // Build role dropdown options
- $current_role_id = (isset($cur_roles[$ug_id][$forum_id])) ? $cur_roles[$ug_id][$forum_id] : 0;
-
- $s_role_options = '';
-
- @reset($roles);
- while (list($role_id, $role_row) = each($roles))
- {
- $role_description = (!empty($user->lang[$role_row['role_description']])) ? $user->lang[$role_row['role_description']] : nl2br($role_row['role_description']);
- $role_name = (!empty($user->lang[$role_row['role_name']])) ? $user->lang[$role_row['role_name']] : $role_row['role_name'];
-
- $title = ($role_description) ? ' title="' . $role_description . '"' : '';
- $s_role_options .= '<option value="' . $role_id . '"' . (($role_id == $current_role_id) ? ' selected="selected"' : '') . $title . '>' . $role_name . '</option>';
- }
-
- if ($s_role_options)
- {
- $s_role_options = '<option value="0"' . ((!$current_role_id) ? ' selected="selected"' : '') . ' title="' . htmlspecialchars($user->lang['NO_ROLE_ASSIGNED_EXPLAIN']) . '">' . $user->lang['NO_ROLE_ASSIGNED'] . '</option>' . $s_role_options;
- }
-
- if (!$current_role_id && $mode != 'view')
- {
- $s_custom_permissions = false;
-
- foreach ($ug_array as $key => $value)
- {
- if ($value['S_NEVER'] || $value['S_YES'])
- {
- $s_custom_permissions = true;
- break;
- }
- }
- }
- else
- {
- $s_custom_permissions = false;
- }
-
- $template->assign_block_vars($tpl_pmask . '.' . $tpl_fmask, array(
- 'NAME' => $ug_names_ary[$ug_id],
- 'S_ROLE_OPTIONS' => $s_role_options,
- 'UG_ID' => $ug_id,
- 'S_CUSTOM' => $s_custom_permissions,
- 'FORUM_ID' => $forum_id)
- );
-
- self::assign_cat_array($ug_array, $tpl_pmask . '.' . $tpl_fmask . '.' . $tpl_category, $tpl_mask, $ug_id, $forum_id, $show_trace, ($mode == 'view'));
-
- unset($content_array[$ug_id]);
- }
-
- unset($hold_ary[$forum_id]);
- }
- }
- else
- {
- foreach ($ug_names_ary as $ug_id => $ug_name)
- {
- if (!isset($hold_ary[$ug_id]))
- {
- continue;
- }
-
- $content_array = $categories = array();
- self::build_permission_array($hold_ary[$ug_id], $content_array, $categories, array_keys($forum_names_ary));
-
- $template->assign_block_vars($tpl_pmask, array(
- 'NAME' => $ug_name,
- 'CATEGO...
[truncated message content] |
|
From: Meik S. <acy...@ph...> - 2008-12-11 17:42:53
|
Added: branches/acydburn/phpBB/includes/classes/acl.php ============================================================================== *** branches/acydburn/phpBB/includes/classes/acl.php (added) --- branches/acydburn/phpBB/includes/classes/acl.php Thu Dec 11 17:39:51 2008 *************** *** 0 **** --- 1,924 ---- + <?php + /** + * + * @package phpBB3 + * @version $Id$ + * @copyright (c) 2005 phpBB Group + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + * + */ + + /** + * @ignore + */ + if (!defined('IN_PHPBB')) + { + exit; + } + + /** + * Permission/ACL class + * @package phpBB3 + */ + class phpbb_acl + { + private $acl = array(); + private $cache = array(); + public $acl_options = array(); + private $acl_element_ids = false; + private $recache = false; + + public function __construct() + { + $this->acl = $this->cache = $this->acl_options = array(); + $this->acl_element_ids = false; + + if (($this->acl_options = phpbb::$acm->get('acl_options')) === false) + { + $sql = 'SELECT auth_option_id, auth_option, is_global, is_local + FROM ' . ACL_OPTIONS_TABLE . ' + ORDER BY auth_option_id'; + $result = phpbb::$db->sql_query($sql); + + $global = $local = 0; + $this->acl_options = array(); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + if ($row['is_global']) + { + $this->acl_options['global'][$row['auth_option']] = $global++; + } + + if ($row['is_local']) + { + $this->acl_options['local'][$row['auth_option']] = $local++; + } + + $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id']; + $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option']; + } + phpbb::$db->sql_freeresult($result); + + phpbb::$acm->put('acl_options', $this->acl_options); + $this->recache = true; + } + } + + /** + * Init permissions + */ + public function init(array &$userdata) + { + if (!trim($userdata['user_permissions']) || $this->recache) + { + $this->acl_cache($userdata); + } + + // Fill ACL array + $this->_fill_acl($userdata['user_permissions']); + + // Verify bitstring length with options provided... + $renew = false; + $global_length = sizeof($this->acl_options['global']); + $local_length = sizeof($this->acl_options['local']); + + // Specify comparing length (bitstring is padded to 31 bits) + $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length; + $local_length = ($local_length % 31) ? ($local_length - ($local_length % 31) + 31) : $local_length; + + // You thought we are finished now? Noooo... now compare them. + foreach ($this->acl as $forum_id => $bitstring) + { + if (($forum_id && strlen($bitstring) != $local_length) || (!$forum_id && strlen($bitstring) != $global_length)) + { + $renew = true; + break; + } + } + + // If a bitstring within the list does not match the options, we have a user with incorrect permissions set and need to renew them + if ($renew) + { + $this->acl_cache($userdata); + $this->_fill_acl($userdata['user_permissions']); + } + + return; + } + + /** + * Fill ACL array with relevant bitstrings from user_permissions column + * @access private + */ + private function _fill_acl($user_permissions) + { + $this->acl = array(); + $user_permissions = explode("\n", $user_permissions); + + foreach ($user_permissions as $f => $seq) + { + if ($seq) + { + $i = 0; + + if (!isset($this->acl[$f])) + { + $this->acl[$f] = ''; + } + + while ($subseq = substr($seq, $i, 6)) + { + // We put the original bitstring into the acl array + $this->acl[$f] .= str_pad(base_convert($subseq, 36, 2), 31, 0, STR_PAD_LEFT); + $i += 6; + } + } + } + } + + /** + * Look up an option + * if the option is prefixed with !, then the result becomes negated + * + * If a forum id is specified the local option will be combined with a global option if one exist. + * If a forum id is not specified, only the global option will be checked. + */ + public function acl_get($opt, $f = 0) + { + $negate = false; + + if (strpos($opt, '!') === 0) + { + $negate = true; + $opt = substr($opt, 1); + } + + if (!isset($this->cache[$f][$opt])) + { + // We combine the global/local option with an OR because some options are global and local. + // If the user has the global permission the local one is true too and vice versa + $this->cache[$f][$opt] = false; + + // Is this option a global permission setting? + if (isset($this->acl_options['global'][$opt])) + { + if (isset($this->acl[0])) + { + $this->cache[$f][$opt] = $this->acl[0][$this->acl_options['global'][$opt]]; + } + } + + // Is this option a local permission setting? + // But if we check for a global option only, we won't combine the options... + if ($f != 0 && isset($this->acl_options['local'][$opt])) + { + if (isset($this->acl[$f]) && isset($this->acl[$f][$this->acl_options['local'][$opt]])) + { + $this->cache[$f][$opt] |= $this->acl[$f][$this->acl_options['local'][$opt]]; + } + } + } + + // Founder always has all global options set to true... + return $negate xor $this->cache[$f][$opt]; + } + + /** + * Get forums with the specified permission setting + * if the option is prefixed with !, then the result becomes negated + * + * @param bool $clean set to true if only values needs to be returned which are set/unset + */ + public function acl_getf($opt, $clean = false) + { + $acl_f = array(); + $negate = false; + + if (strpos($opt, '!') === 0) + { + $negate = true; + $opt = substr($opt, 1); + } + + // If we retrieve a list of forums not having permissions in, we need to get every forum_id + if ($negate) + { + if ($this->acl_forum_ids === false) + { + $sql = 'SELECT forum_id + FROM ' . FORUMS_TABLE; + + if (sizeof($this->acl)) + { + $sql .= ' WHERE ' . phpbb::$db->sql_in_set('forum_id', array_keys($this->acl), true); + } + $result = phpbb::$db->sql_query($sql); + + $this->acl_forum_ids = array(); + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $this->acl_forum_ids[] = $row['forum_id']; + } + phpbb::$db->sql_freeresult($result); + } + } + + if (isset($this->acl_options['local'][$opt])) + { + foreach ($this->acl as $f => $bitstring) + { + // Skip global settings + if (!$f) + { + continue; + } + + $allowed = (!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt]; + + if (!$clean) + { + $acl_f[$f][$opt] = $negate xor $allowed; + } + else if ($negate xor $allowed) + { + $acl_f[$f][$opt] = 1; + } + } + } + + // If we get forum_ids not having this permission, we need to fill the remaining parts + if ($negate && sizeof($this->acl_forum_ids)) + { + foreach ($this->acl_forum_ids as $f) + { + $acl_f[$f][$opt] = 1; + } + } + + return $acl_f; + } + + /** + * Get local permission state for any forum. + * + * Returns true if user has the permission in one or more forums, false if in no forum. + * If global option is checked it returns the global state (same as acl_get($opt)) + * Local option has precedence... + */ + public function acl_getf_global($opt) + { + if (is_array($opt)) + { + // evaluates to true as soon as acl_getf_global is true for one option + foreach ($opt as $check_option) + { + if ($this->acl_getf_global($check_option)) + { + return true; + } + } + + return false; + } + + if (isset($this->acl_options['local'][$opt])) + { + foreach ($this->acl as $f => $bitstring) + { + // Skip global settings + if (!$f) + { + continue; + } + + // as soon as the user has any permission we're done so return true + if ((!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt]) + { + return true; + } + } + } + else if (isset($this->acl_options['global'][$opt])) + { + return $this->acl_get($opt); + } + + return false; + } + + /** + * Get permission settings (more than one) + */ + public function acl_gets() + { + $args = func_get_args(); + $f = array_pop($args); + + if (!is_numeric($f)) + { + $args[] = $f; + $f = 0; + } + + // alternate syntax: acl_gets(array('m_', 'a_'), $forum_id) + if (is_array($args[0])) + { + $args = $args[0]; + } + + $acl = 0; + foreach ($args as $opt) + { + $acl |= $this->acl_get($opt, $f); + } + + return $acl; + } + + /** + * Get permission listing based on user_id/options/forum_ids + */ + public function acl_get_list($user_id = false, $opts = false, $forum_id = false) + { + if ($user_id !== false && !is_array($user_id) && $opts === false && $forum_id === false) + { + $hold_ary = array($user_id => $this->acl_raw_data_single_user($user_id)); + } + else + { + $hold_ary = $this->acl_raw_data($user_id, $opts, $forum_id); + } + + $auth_ary = array(); + foreach ($hold_ary as $user_id => $forum_ary) + { + foreach ($forum_ary as $forum_id => $auth_option_ary) + { + foreach ($auth_option_ary as $auth_option => $auth_setting) + { + if ($auth_setting) + { + $auth_ary[$forum_id][$auth_option][] = $user_id; + } + } + } + } + + return $auth_ary; + } + + /** + * Cache data to user_permissions row + */ + public function acl_cache(array &$userdata) + { + // Empty user_permissions + $userdata['user_permissions'] = ''; + + $hold_ary = $this->acl_raw_data_single_user($userdata['user_id']); + + // Key 0 in $hold_ary are global options, all others are forum_ids + + // If this user is founder we're going to force fill the admin options ... + if ($userdata['user_type'] == USER_FOUNDER) + { + foreach ($this->acl_options['global'] as $opt => $id) + { + if (strpos($opt, 'a_') === 0) + { + $hold_ary[0][$this->acl_options['id'][$opt]] = ACL_YES; + } + } + } + + $hold_str = $this->build_bitstring($hold_ary); + + if ($hold_str) + { + $userdata['user_permissions'] = $hold_str; + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_permissions = '" . phpbb::$db->sql_escape($userdata['user_permissions']) . "', + user_perm_from = 0 + WHERE user_id = " . $userdata['user_id']; + phpbb::$db->sql_query($sql); + } + + return; + } + + /** + * Build bitstring from permission set + */ + protected function build_bitstring(&$hold_ary) + { + $hold_str = ''; + + if (sizeof($hold_ary)) + { + ksort($hold_ary); + + $last_f = 0; + + foreach ($hold_ary as $f => $auth_ary) + { + $ary_key = (!$f) ? 'global' : 'local'; + + $bitstring = array(); + foreach ($this->acl_options[$ary_key] as $opt => $id) + { + if (isset($auth_ary[$this->acl_options['id'][$opt]])) + { + $bitstring[$id] = $auth_ary[$this->acl_options['id'][$opt]]; + + $option_key = substr($opt, 0, strpos($opt, '_') + 1); + + // If one option is allowed, the global permission for this option has to be allowed too + // example: if the user has the a_ permission this means he has one or more a_* permissions + if ($auth_ary[$this->acl_options['id'][$opt]] == ACL_YES && (!isset($bitstring[$this->acl_options[$ary_key][$option_key]]) || $bitstring[$this->acl_options[$ary_key][$option_key]] == ACL_NEVER)) + { + $bitstring[$this->acl_options[$ary_key][$option_key]] = ACL_YES; + } + } + else + { + $bitstring[$id] = ACL_NEVER; + } + } + + // Now this bitstring defines the permission setting for the current forum $f (or global setting) + $bitstring = implode('', $bitstring); + + // The line number indicates the id, therefore we have to add empty lines for those ids not present + $hold_str .= str_repeat("\n", $f - $last_f); + + // Convert bitstring for storage - we do not use binary/bytes because PHP's string functions are not fully binary safe + for ($i = 0, $bit_length = strlen($bitstring); $i < $bit_length; $i += 31) + { + $hold_str .= str_pad(base_convert(str_pad(substr($bitstring, $i, 31), 31, 0, STR_PAD_RIGHT), 2, 36), 6, 0, STR_PAD_LEFT); + } + + $last_f = $f; + } + unset($bitstring); + + $hold_str = rtrim($hold_str); + } + + return $hold_str; + } + + /** + * Clear one or all users cached permission settings + */ + public function acl_clear_prefetch($user_id = false) + { + // Rebuild options cache + phpbb::$acm->destroy('role_cache'); + + $sql = 'SELECT * + FROM ' . ACL_ROLES_DATA_TABLE . ' + ORDER BY role_id ASC'; + $result = phpbb::$db->sql_query($sql); + + $this->role_cache = array(); + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting']; + } + phpbb::$db->sql_freeresult($result); + + foreach ($this->role_cache as $role_id => $role_options) + { + $this->role_cache[$role_id] = serialize($role_options); + } + + phpbb::$acm->put('role_cache', $this->role_cache); + + // Now empty user permissions + $where_sql = ''; + + if ($user_id !== false) + { + $user_id = (!is_array($user_id)) ? $user_id = array((int) $user_id) : array_map('intval', $user_id); + $where_sql = ' WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id); + } + + $sql = 'UPDATE ' . USERS_TABLE . " + SET user_permissions = '', + user_perm_from = 0 + $where_sql"; + phpbb::$db->sql_query($sql); + + return; + } + + /** + * Get assigned roles + * @todo: protected or public? + */ + public function acl_role_data($user_type, $role_type, $ug_id = false, $forum_id = false) + { + $roles = array(); + + $sql_id = ($user_type == 'user') ? 'user_id' : 'group_id'; + + $sql_ug = ($ug_id !== false) ? ((!is_array($ug_id)) ? "AND a.$sql_id = $ug_id" : 'AND ' . phpbb::$db->sql_in_set("a.$sql_id", $ug_id)) : ''; + $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', $forum_id)) : ''; + + // Grab assigned roles... + $sql = 'SELECT a.auth_role_id, a.' . $sql_id . ', a.forum_id + FROM ' . (($user_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE) . ' a, ' . ACL_ROLES_TABLE . " r + WHERE a.auth_role_id = r.role_id + AND r.role_type = '" . phpbb::$db->sql_escape($role_type) . "' + $sql_ug + $sql_forum + ORDER BY r.role_order ASC"; + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $roles[$row[$sql_id]][$row['forum_id']] = $row['auth_role_id']; + } + phpbb::$db->sql_freeresult($result); + + return $roles; + } + + /** + * Get raw acl data based on user/option/forum + * @todo: protected or public? + */ + public function acl_raw_data($user_id = false, $opts = false, $forum_id = false) + { + $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : phpbb::$db->sql_in_set('user_id', array_map('intval', $user_id))) : ''; + $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : ''; + + $sql_opts = $sql_opts_select = $sql_opts_from = ''; + $hold_ary = array(); + + if ($opts !== false) + { + $sql_opts_select = ', ao.auth_option'; + $sql_opts_from = ', ' . ACL_OPTIONS_TABLE . ' ao'; + $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts); + } + + $sql_ary = array(); + + // Grab non-role settings - user-specific + $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . ' + FROM ' . ACL_USERS_TABLE . ' a' . $sql_opts_from . ' + WHERE a.auth_role_id = 0 ' . + (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . + (($sql_user) ? 'AND a.' . $sql_user : '') . " + $sql_forum + $sql_opts"; + + // Now the role settings - user-specific + $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . ' + FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . ' + WHERE a.auth_role_id = r.role_id ' . + (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . + (($sql_user) ? 'AND a.' . $sql_user : '') . " + $sql_forum + $sql_opts"; + + foreach ($sql_ary as $sql) + { + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']]; + $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting']; + } + phpbb::$db->sql_freeresult($result); + } + + $sql_ary = array(); + + // Now grab group settings - non-role specific... + $sql_ary[] = 'SELECT ug.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . ' + FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug' . $sql_opts_from . ' + WHERE a.auth_role_id = 0 ' . + (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . ' + AND a.group_id = ug.group_id + AND ug.user_pending = 0 + ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . " + $sql_forum + $sql_opts"; + + // Now grab group settings - role specific... + $sql_ary[] = 'SELECT ug.user_id, a.forum_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . ' + FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . ' + WHERE a.auth_role_id = r.role_id ' . + (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . ' + AND a.group_id = ug.group_id + AND ug.user_pending = 0 + ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . " + $sql_forum + $sql_opts"; + + foreach ($sql_ary as $sql) + { + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']]; + + // @todo: use the ref technique to reduce opcode generation + if (!isset($hold_ary[$row['user_id']][$row['forum_id']][$option]) || (isset($hold_ary[$row['user_id']][$row['forum_id']][$option]) && $hold_ary[$row['user_id']][$row['forum_id']][$option] != ACL_NEVER)) + { + $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting']; + + // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again) + if ($row['auth_setting'] == ACL_NEVER) + { + $flag = substr($option, 0, strpos($option, '_') + 1); + + if (isset($hold_ary[$row['user_id']][$row['forum_id']][$flag]) && $hold_ary[$row['user_id']][$row['forum_id']][$flag] == ACL_YES) + { + unset($hold_ary[$row['user_id']][$row['forum_id']][$flag]); + + /* if (in_array(ACL_YES, $hold_ary[$row['user_id']][$row['forum_id']])) + { + $hold_ary[$row['user_id']][$row['forum_id']][$flag] = ACL_YES; + } + */ + } + } + } + } + phpbb::$db->sql_freeresult($result); + } + + return $hold_ary; + } + + /** + * Get raw user based permission settings + */ + public function acl_user_raw_data($user_id = false, $opts = false, $forum_id = false) + { + $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : phpbb::$db->sql_in_set('user_id', array_map('intval', $user_id))) : ''; + $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : ''; + + $sql_opts = ''; + $hold_ary = $sql_ary = array(); + + if ($opts !== false) + { + $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts); + } + + // Grab user settings - non-role specific... + $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option + FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao + WHERE a.auth_role_id = 0 + AND a.auth_option_id = ao.auth_option_id ' . + (($sql_user) ? 'AND a.' . $sql_user : '') . " + $sql_forum + $sql_opts + ORDER BY a.forum_id, ao.auth_option"; + + // Now the role settings - user-specific + $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id, ao.auth_option + FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao + WHERE a.auth_role_id = r.role_id + AND r.auth_option_id = ao.auth_option_id ' . + (($sql_user) ? 'AND a.' . $sql_user : '') . " + $sql_forum + $sql_opts + ORDER BY a.forum_id, ao.auth_option"; + + foreach ($sql_ary as $sql) + { + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting']; + } + phpbb::$db->sql_freeresult($result); + } + + return $hold_ary; + } + + /** + * Get raw group based permission settings + */ + public function acl_group_raw_data($group_id = false, $opts = false, $forum_id = false) + { + $sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? 'group_id = ' . (int) $group_id : phpbb::$db->sql_in_set('group_id', array_map('intval', $group_id))) : ''; + $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : ''; + + $sql_opts = ''; + $hold_ary = $sql_ary = array(); + + if ($opts !== false) + { + $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts); + } + + // Grab group settings - non-role specific... + $sql_ary[] = 'SELECT a.group_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option + FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao + WHERE a.auth_role_id = 0 + AND a.auth_option_id = ao.auth_option_id ' . + (($sql_group) ? 'AND a.' . $sql_group : '') . " + $sql_forum + $sql_opts + ORDER BY a.forum_id, ao.auth_option"; + + // Now grab group settings - role specific... + $sql_ary[] = 'SELECT a.group_id, a.forum_id, r.auth_setting, r.auth_option_id, ao.auth_option + FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao + WHERE a.auth_role_id = r.role_id + AND r.auth_option_id = ao.auth_option_id ' . + (($sql_group) ? 'AND a.' . $sql_group : '') . " + $sql_forum + $sql_opts + ORDER BY a.forum_id, ao.auth_option"; + + foreach ($sql_ary as $sql) + { + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $hold_ary[$row['group_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting']; + } + phpbb::$db->sql_freeresult($result); + } + + return $hold_ary; + } + + /** + * Get raw acl data based on user for caching user_permissions + * This function returns the same data as acl_raw_data(), but without the user id as the first key within the array. + */ + public function acl_raw_data_single_user($user_id) + { + // Check if the role-cache is there + if (($this->role_cache = phpbb::$acm->get('role_cache')) === false) + { + $this->role_cache = array(); + + // We pre-fetch roles + $sql = 'SELECT * + FROM ' . ACL_ROLES_DATA_TABLE . ' + ORDER BY role_id ASC'; + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting']; + } + phpbb::$db->sql_freeresult($result); + + foreach ($this->role_cache as $role_id => $role_options) + { + $this->role_cache[$role_id] = serialize($role_options); + } + + phpbb::$acm->put('role_cache', $this->role_cache); + } + + $hold_ary = array(); + + // Grab user-specific permission settings + $sql = 'SELECT forum_id, auth_option_id, auth_role_id, auth_setting + FROM ' . ACL_USERS_TABLE . ' + WHERE user_id = ' . $user_id; + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + // If a role is assigned, assign all options included within this role. Else, only set this one option. + if ($row['auth_role_id']) + { + $hold_ary[$row['forum_id']] = (empty($hold_ary[$row['forum_id']])) ? unserialize($this->role_cache[$row['auth_role_id']]) : $hold_ary[$row['forum_id']] + unserialize($this->role_cache[$row['auth_role_id']]); + } + else + { + $hold_ary[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting']; + } + } + phpbb::$db->sql_freeresult($result); + + // Now grab group-specific permission settings + $sql = 'SELECT a.forum_id, a.auth_option_id, a.auth_role_id, a.auth_setting + FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug + WHERE a.group_id = ug.group_id + AND ug.user_pending = 0 + AND ug.user_id = ' . $user_id; + $result = phpbb::$db->sql_query($sql); + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + if (!$row['auth_role_id']) + { + $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $row['auth_option_id'], $row['auth_setting']); + } + else if (!empty($this->role_cache[$row['auth_role_id']])) + { + foreach (unserialize($this->role_cache[$row['auth_role_id']]) as $option_id => $setting) + { + $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $option_id, $setting); + } + } + } + phpbb::$db->sql_freeresult($result); + + return $hold_ary; + } + + /** + * Private function snippet for setting a specific piece of the hold_ary + */ + private function _set_group_hold_ary(&$hold_ary, $option_id, $setting) + { + if (!isset($hold_ary[$option_id]) || (isset($hold_ary[$option_id]) && $hold_ary[$option_id] != ACL_NEVER)) + { + $hold_ary[$option_id] = $setting; + + // If we detect ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again) + if ($setting == ACL_NEVER) + { + $flag = substr($this->acl_options['option'][$option_id], 0, strpos($this->acl_options['option'][$option_id], '_') + 1); + $flag = (int) $this->acl_options['id'][$flag]; + + if (isset($hold_ary[$flag]) && $hold_ary[$flag] == ACL_YES) + { + unset($hold_ary[$flag]); + + /* This is uncommented, because i suspect this being slightly wrong due to mixed permission classes being possible + if (in_array(ACL_YES, $hold_ary)) + { + $hold_ary[$flag] = ACL_YES; + }*/ + } + } + } + } + + /** + * Fill auth_option statement for later querying based on the supplied options + */ + private function build_auth_option_statement($key, $auth_options, &$sql_opts) + { + if (!is_array($auth_options)) + { + if (strpos($auth_options, '%') !== false) + { + $sql_opts = "AND $key " . phpbb::$db->sql_like_expression(str_replace('%', phpbb::$db->any_char, $auth_options)); + } + else + { + $sql_opts = "AND $key = '" . phpbb::$db->sql_escape($auth_options) . "'"; + } + } + else + { + $is_like_expression = false; + + foreach ($auth_options as $option) + { + if (strpos($option, '%') !== false) + { + $is_like_expression = true; + } + } + + if (!$is_like_expression) + { + $sql_opts = 'AND ' . phpbb::$db->sql_in_set($key, $auth_options); + } + else + { + $sql = array(); + + foreach ($auth_options as $option) + { + if (strpos($option, '%') !== false) + { + $sql[] = $key . ' ' . phpbb::$db->sql_like_expression(str_replace('%', phpbb::$db->any_char, $option)); + } + else + { + $sql[] = $key . " = '" . phpbb::$db->sql_escape($option) . "'"; + } + } + + $sql_opts = 'AND (' . implode(' OR ', $sql) . ')'; + } + } + } + } + + ?> \ No newline at end of file Propchange: branches/acydburn/phpBB/includes/classes/acl.php ------------------------------------------------------------------------------ svn:eol-style = LF Propchange: branches/acydburn/phpBB/includes/classes/acl.php ------------------------------------------------------------------------------ svn:keywords = "Author Date Id Revision" Added: branches/acydburn/phpBB/includes/classes/acl_admin.php ============================================================================== *** branches/acydburn/phpBB/includes/classes/acl_admin.php (added) --- branches/acydburn/phpBB/includes/classes/acl_admin.php Thu Dec 11 17:39:51 2008 *************** *** 0 **** --- 1,1225 ---- + <?php + /** + * + * @package phpBB3 + * @version $Id$ + * @copyright (c) 2005 phpBB Group + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + * + */ + + /** + * @ignore + */ + if (!defined('IN_PHPBB')) + { + exit; + } + + /** + * ACP Permission/Auth class + * @package phpBB3 + */ + class phpbb_acl_admin extends acl + { + function __construct() { parent::__construct(); } + + /** + * Get permission mask + * This function only supports getting permissions of one type (for example a_) + * + * @param set|view $mode defines the permissions we get, view gets effective permissions (checking user AND group permissions), set only gets the user or group permission set alone + * @param mixed $user_id user ids to search for (a user_id or a group_id has to be specified at least) + * @param mixed $group_id group ids to search for, return group related settings (a user_id or a group_id has to be specified at least) + * @param mixed $forum_id forum_ids to search ... [truncated message content] |
|
From: Meik S. <acy...@ph...> - 2008-12-11 17:43:12
|
Added: branches/acydburn/phpBB/includes/classes/session.php ============================================================================== *** branches/acydburn/phpBB/includes/classes/session.php (added) --- branches/acydburn/phpBB/includes/classes/session.php Thu Dec 11 17:39:51 2008 *************** *** 0 **** --- 1,1423 ---- + <?php + /** + * + * @package phpBB3 + * @version $Id$ + * @copyright (c) 2005 phpBB Group + * @license http://opensource.org/licenses/gpl-license.php GNU Public License + * + */ + + /** + * @ignore + */ + if (!defined('IN_PHPBB')) + { + exit; + } + + class phpbb_server + { + /** + * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present. + */ + public static function get_host() + { + // Get hostname + $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); + + // Should be a string and lowered + $host = (string) strtolower($host); + + // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid + if ((isset(phpbb::$config['cookie_domain']) && $host === phpbb::$config['cookie_domain']) || (isset(phpbb::$config['server_name']) && $host === phpbb::$config['server_name'])) + { + return $host; + } + + // Is the host actually a IP? If so, we use the IP... (IPv4) + if (long2ip(ip2long($host)) === $host) + { + return $host; + } + + // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned + $host = @parse_url('http://' . $host, PHP_URL_HOST); + + // Remove any portions not removed by parse_url (#) + $host = str_replace('#', '', $host); + + // If, by any means, the host is now empty, we will use a "best approach" way to guess one + if (empty($host)) + { + if (!empty(phpbb::$config['server_name'])) + { + $host = phpbb::$config['server_name']; + } + else if (!empty(phpbb::$config['cookie_domain'])) + { + $host = (strpos(phpbb::$config['cookie_domain'], '.') === 0) ? substr(phpbb::$config['cookie_domain'], 1) : phpbb::$config['cookie_domain']; + } + else + { + // Set to OS hostname or localhost + $host = (function_exists('php_uname')) ? php_uname('n') : 'localhost'; + } + } + + // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set) + return $host; + } + + /** + * Extract current session page, relative from current root path (PHPBB_ROOT_PATH) + */ + public static function get_page() + { + $page_array = array(); + + // First of all, get the request uri... + $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF'); + $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING')); + + // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support... + if (!$script_name) + { + $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI'); + $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name; + $page_array['failover'] = 1; + } + + // Replace backslashes and doubled slashes (could happen on some proxy setups) + $script_name = str_replace(array('\\', '//'), '/', $script_name); + + // Now, remove the sid and let us get a clean query string... + $use_args = array(); + + // Since some browser do not encode correctly we need to do this with some "special" characters... + // " -> %22, ' => %27, < -> %3C, > -> %3E + $find = array('"', "'", '<', '>'); + $replace = array('%22', '%27', '%3C', '%3E'); + + foreach ($args as $argument) + { + if (strpos($argument, 'sid=') === 0) + { + continue; + } + + $use_args[] = str_replace($find, $replace, $argument); + } + unset($args); + + // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2 + + // The current query string + $query_string = trim(implode('&', $use_args)); + + // basenamed page name (for example: index.php) + $page_name = basename($script_name); + $page_name = urlencode(htmlspecialchars($page_name)); + + // current directory within the phpBB root (for example: adm) + $root_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath(PHPBB_ROOT_PATH))); + $page_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath('./'))); + $intersection = array_intersect_assoc($root_dirs, $page_dirs); + + $root_dirs = array_diff_assoc($root_dirs, $intersection); + $page_dirs = array_diff_assoc($page_dirs, $intersection); + + $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs); + + if ($page_dir && substr($page_dir, -1, 1) == '/') + { + $page_dir = substr($page_dir, 0, -1); + } + + // Current page from phpBB root (for example: adm/index.php?i=10&b=2) + $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : ''); + + // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in / + $script_path = trim(str_replace('\\', '/', dirname($script_name))); + + // The script path from the webroot to the phpBB root (for example: /phpBB3/) + $script_dirs = explode('/', $script_path); + array_splice($script_dirs, -sizeof($page_dirs)); + $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : ''); + + // We are on the base level (phpBB root == webroot), lets adjust the variables a bit... + if (!$root_script_path) + { + $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path; + } + + $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/'; + $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/'; + + $page_array += array( + 'page_name' => $page_name, + 'page_dir' => $page_dir, + + 'query_string' => $query_string, + 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)), + 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)), + + 'page' => $page, + 'forum' => request_var('f', 0), + ); + + return $page_array; + } + + public static function get_browser() + { + return (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; + } + + public static function get_referer() + { + return (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; + } + + public static function get_port() + { + return (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); + } + + public static function get_forwarded_for() + { + $forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; + + // if the forwarded for header shall be checked we have to validate its contents + if (phpbb::$config['forwarded_for_check']) + { + $forwarded_for = preg_replace('#, +#', ', ', $forwarded_for); + + // split the list of IPs + $ips = explode(', ', $forwarded_for); + foreach ($ips as $ip) + { + // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly + if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip)) + { + // contains invalid data, don't use the forwarded for header + return ''; + } + } + } + else + { + return ''; + } + } + + public static function get_ip() + { + // Why no forwarded_for et al? Well, too easily spoofed. With the results of my recent requests + // it's pretty clear that in the majority of cases you'll at least be left with a proxy/cache ip. + return (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : ''; + } + + public static function get_load() + { + $load = false; + + // Load limit check (if applicable) + if (phpbb::$config['limit_load'] || phpbb::$config['limit_search_load']) + { + if ((function_exists('sys_getloadavg') && $load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg')))) + { + $load = array_slice($load, 0, 1); + $load = floatval($load[0]); + } + else + { + set_config('limit_load', '0'); + set_config('limit_search_load', '0'); + } + } + + return $load; + } + + public static function get_request_method() + { + return (isset($_SERVER['REQUEST_METHOD'])) ? strtolower(htmlspecialchars((string) $_SERVER['REQUEST_METHOD'])) : ''; + } + } + + /** + * Session class + * @package phpBB3 + */ + class phpbb_session + { + private $cookie_data = array(); + + public $data = array(); + public $server = array(); + public $session_id = ''; + public $time_now = 0; + public $update_session_page = true; + + public $auth = NULL; + + public $is_registered = false; + public $is_bot = false; + + public function __construct() + { + // Reset data array ;) + $this->data = array(); + + // Init auth object + $method = basename(trim(phpbb::$config['auth_method'])); + $class = 'phpbb_auth_' . $method; + $this->auth = new $class(); + } + + /** + * Start session management + * + * This is where all session activity begins. We gather various pieces of + * information from the client and server. We test to see if a session already + * exists. If it does, fine and dandy. If it doesn't we'll go on to create a + * new one ... pretty logical heh? We also examine the system load (if we're + * running on a system which makes such information readily available) and + * halt if it's above an admin definable limit. + * + * @param bool $update_session_page if true the session page gets updated. + * This can be set to circumvent certain scripts to update the users last visited page. + */ + public function session_begin($update_session_page = true) + { + global $SID, $_SID, $_EXTRA_URL; + + // Give us some basic information + $this->time_now = time(); + $this->cookie_data = array('u' => 0, 'k' => ''); + $this->update_session_page = $update_session_page; + + // Some server variables, directly generated by phpbb_server methods + $this->server = array(); + + foreach (get_class_methods('phpbb_server') as $method) + { + if (strpos($method, 'get_') !== 0) + { + continue; + } + + $this->server[substr($method, 4)] = phpbb_server::$method(); + } + + if (request::is_set(phpbb::$config['cookie_name'] . '_sid', request::COOKIE) || request::is_set(phpbb::$config['cookie_name'] . '_u', request::COOKIE)) + { + $this->cookie_data['u'] = request_var(phpbb::$config['cookie_name'] . '_u', 0, false, true); + $this->cookie_data['k'] = request_var(phpbb::$config['cookie_name'] . '_k', '', false, true); + $this->session_id = request_var(phpbb::$config['cookie_name'] . '_sid', '', false, true); + + $SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid='; + $_SID = (defined('NEED_SID')) ? $this->session_id : ''; + + if (empty($this->session_id)) + { + $this->session_id = $_SID = request_var('sid', ''); + $SID = '?sid=' . $this->session_id; + $this->cookie_data = array('u' => 0, 'k' => ''); + } + } + else + { + $this->session_id = $_SID = request_var('sid', ''); + $SID = '?sid=' . $this->session_id; + } + + $_EXTRA_URL = array(); + + // Now check for an existing session + if ($this->session_exist()) + { + return true; + } + + // If we reach here then no (valid) session exists. So we'll create a new one + return $this->session_create(); + } + + /** + * Create a new session + * + * If upon trying to start a session we discover there is nothing existing we + * jump here. Additionally this method is called directly during login to regenerate + * the session for the specific user. In this method we carry out a number of tasks; + * garbage collection, (search)bot checking, banned user comparison. Basically + * though this method will result in a new session for a specific user. + */ + public function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true) + { + global $SID, $_SID; + + // There is one case where we need to add a "failsafe" user... when we are not able to query the database + if (!phpbb::registered('db')) + { + $this->data = $this->default_data(); + return true; + } + + // If the data array is filled, chances are high that there was a different session active + if (sizeof($this->data)) + { + // Kill the session and do not create a new one + $this->session_kill(false); + } + + $this->data = array(); + + /* Garbage collection ... remove old sessions updating user information + // if necessary. It means (potentially) 11 queries but only infrequently + if ($this->time_now > phpbb::$config['session_last_gc'] + phpbb::$config['session_gc']) + { + $this->session_gc(); + }*/ + + // Do we allow autologin on this board? No? Then override anything + // that may be requested here + if (!phpbb::$config['allow_autologin']) + { + $this->cookie_data['k'] = $persist_login = false; + } + + // Check for autologin key. ;) + if (method_exists($this->auth, 'autologin')) + { + $this->data = $this->auth->autologin(); + + if (sizeof($this->data)) + { + $this->cookie_data['k'] = ''; + $this->cookie_data['u'] = $this->data['user_id']; + } + } + + // NULL indicates we need to check for a bot later. Sometimes it is apparant that it is not a bot. ;) No need to always check this. + $bot = NULL; + + // If we're presented with an autologin key we'll join against it. + // Else if we've been passed a user_id we'll grab data based on that + if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && !sizeof($this->data)) + { + $sql = 'SELECT u.* + FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k + WHERE u.user_id = ' . (int) $this->cookie_data['u'] . ' + AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ") + AND k.user_id = u.user_id + AND k.key_id = '" . phpbb::$db->sql_escape(md5($this->cookie_data['k'])) . "'"; + $result = phpbb::$db->sql_query($sql); + $this->data = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + $bot = false; + } + else if ($user_id !== false && !sizeof($this->data)) + { + $this->cookie_data['k'] = ''; + $this->cookie_data['u'] = $user_id; + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . (int) $this->cookie_data['u'] . ' + AND user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')'; + $result = phpbb::$db->sql_query($sql); + $this->data = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + $bot = false; + } + + /** + * Here we do a bot check, oh er saucy! No, not that kind of bot + * check. We loop through the list of bots defined by the admin and + * see if we have any useragent and/or IP matches. If we do, this is a + * bot, act accordingly + */ + if ($bot === NULL) + { + $bot = $this->check_bot(); + } + + // If no data was returned one or more of the following occurred: + // Key didn't match one in the DB + // User does not exist + // User is inactive + // User is bot + if (!sizeof($this->data) || !is_array($this->data)) + { + $this->cookie_data['k'] = ''; + $this->cookie_data['u'] = ($bot) ? $bot : ANONYMOUS; + + if (!$bot) + { + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . (int) $this->cookie_data['u']; + } + else + { + // We give bots always the same session if it is not yet expired. + $sql = 'SELECT u.*, s.* + FROM ' . USERS_TABLE . ' u + LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id) + WHERE u.user_id = ' . (int) $bot; + } + + $result = phpbb::$db->sql_query($sql); + $this->data = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + $this->is_registered = false; + } + else + { + $this->is_registered = true; + } + + // Force user id to be integer... + $this->data['user_id'] = (int) $this->data['user_id']; + + // Code for ANONYMOUS user, INACTIVE user and BOTS + if (!$this->is_registered) + { + // Set last visit date to 'now' + $this->data['session_last_visit'] = $this->time_now; + $this->is_bot = ($bot) ? true : false; + + // If our friend is a bot, we re-assign a previously assigned session + if ($this->is_bot && $bot == $this->data['user_id'] && $this->data['session_id']) + { + if ($this->session_valid(false)) + { + $this->session_id = $this->data['session_id']; + + // Only update session DB a minute or so after last update or if page changes + if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->server['page']['page'])) + { + $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now; + $sql_ary = array('session_time' => $this->time_now, 'session_last_visit' => $this->time_now, 'session_admin' => 0); + + if ($this->update_session_page) + { + $sql_ary['session_page'] = substr($this->server['page']['page'], 0, 199); + } + + $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . " + WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "'"; + phpbb::$db->sql_query($sql); + + // Update the last visit time + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_lastvisit = ' . (int) $this->data['session_time'] . ' + WHERE user_id = ' . (int) $this->data['user_id']; + phpbb::$db->sql_query($sql); + } + + $SID = '?sid='; + $_SID = ''; + + return true; + } + else + { + // If the ip and browser does not match make sure we only have one bot assigned to one session + phpbb::$db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']); + } + } + } + else + { + // Code for registered users + $this->data['session_last_visit'] = (!empty($this->data['session_time'])) ? $this->data['session_time'] : (($this->data['user_lastvisit']) ? $this->data['user_lastvisit'] : $this->time_now); + $this->is_bot = false; + } + + // At this stage we should have a filled data array, defined cookie u and k data. + // data array should contain recent session info if we're a real user and a recent + // session exists in which case session_id will also be set + + // Is user banned? Are they excluded? Won't return on ban, exists within method + if ($this->data['user_type'] != USER_FOUNDER) + { + if (!phpbb::$config['forwarded_for_check']) + { + $this->check_ban($this->data['user_id'], $this->server['ip']); + } + else + { + $ips = explode(', ', $this->forwarded_for); + $ips[] = $this->server['ip']; + $this->check_ban($this->data['user_id'], $ips); + } + } + + $session_autologin = (($this->cookie_data['k'] || $persist_login) && $this->is_registered) ? true : false; + $set_admin = ($set_admin && $this->is_registered) ? true : false; + + // Create or update the session + $sql_ary = array( + 'session_user_id' => (int) $this->data['user_id'], + 'session_start' => (int) $this->time_now, + 'session_last_visit' => (int) $this->data['session_last_visit'], + 'session_time' => (int) $this->time_now, + 'session_browser' => (string) trim(substr($this->server['browser'], 0, 149)), + 'session_forwarded_for' => (string) $this->server['forwarded_for'], + 'session_ip' => (string) $this->server['ip'], + 'session_autologin' => ($session_autologin) ? 1 : 0, + 'session_admin' => ($set_admin) ? 1 : 0, + 'session_viewonline' => ($viewonline) ? 1 : 0, + ); + + if ($this->update_session_page) + { + $sql_ary['session_page'] = (string) substr($this->server['page']['page'], 0, 199); + } + + phpbb::$db->sql_return_on_error(true); + + // Delete old session, if user id now different from anonymous + if (!defined('IN_ERROR_HANDLER')) + { + // We do not care about the user id, because we assign a new session later + $sql = 'DELETE + FROM ' . SESSIONS_TABLE . " + WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "'"; + $result = phpbb::$db->sql_query($sql); + + // If there were no sessions or the session id empty (then the affected rows will be empty too), then we have a brand new session and can check the active sessions limit + if ((!$result || !phpbb::$db->sql_affectedrows()) && (empty($this->data['session_time']) && phpbb::$config['active_sessions'])) + { + $sql = 'SELECT COUNT(session_id) AS sessions + FROM ' . SESSIONS_TABLE . ' + WHERE session_time >= ' . ($this->time_now - 60); + $result = phpbb::$db->sql_query($sql); + $row = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + if ((int) $row['sessions'] > (int) phpbb::$config['active_sessions']) + { + header('HTTP/1.1 503 Service Unavailable'); + trigger_error('BOARD_UNAVAILABLE'); + } + } + } + + $this->session_id = $this->data['session_id'] = md5(phpbb::$security->unique_id()); + + $sql_ary['session_id'] = (string) $this->session_id; + + $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary); + phpbb::$db->sql_query($sql); + + phpbb::$db->sql_return_on_error(false); + + // Regenerate autologin/persistent login key + if ($session_autologin) + { + $this->set_login_key(); + } + + // refresh data + $SID = '?sid=' . $this->session_id; + $_SID = $this->session_id; + $this->data = array_merge($this->data, $sql_ary); + + if (!$bot) + { + $cookie_expire = $this->time_now + ((phpbb::$config['max_autologin_time']) ? 86400 * (int) phpbb::$config['max_autologin_time'] : 31536000); + + $this->set_cookie('u', $this->cookie_data['u'], $cookie_expire); + $this->set_cookie('k', $this->cookie_data['k'], $cookie_expire); + $this->set_cookie('sid', $this->session_id, $cookie_expire); + + unset($cookie_expire); + + // Only one session entry present... + $sql = 'SELECT COUNT(session_id) AS sessions + FROM ' . SESSIONS_TABLE . ' + WHERE session_user_id = ' . (int) $this->data['user_id'] . ' + AND session_time >= ' . (int) ($this->time_now - (max(phpbb::$config['session_length'], phpbb::$config['form_token_lifetime']))); + $result = phpbb::$db->sql_query($sql); + $row = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + + if ((int) $row['sessions'] <= 1 || empty($this->data['user_form_salt'])) + { + $this->data['user_form_salt'] = phpbb::$security->unique_id(); + + // Update the form key + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_form_salt = \'' . phpbb::$db->sql_escape($this->data['user_form_salt']) . '\' + WHERE user_id = ' . (int) $this->data['user_id']; + phpbb::$db->sql_query($sql); + } + } + else + { + $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now; + + // Update the last visit time + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_lastvisit = ' . (int) $this->data['session_time'] . ' + WHERE user_id = ' . (int) $this->data['user_id']; + phpbb::$db->sql_query($sql); + + $SID = '?sid='; + $_SID = ''; + } + + return true; + } + + /** + * Kills a session + * + * This method does what it says on the tin. It will delete a pre-existing session. + * It resets cookie information (destroying any autologin key within that cookie data) + * and update the users information from the relevant session data. It will then + * grab guest user information. + */ + public function session_kill($new_session = true) + { + global $SID, $_SID; + + $sql = 'DELETE FROM ' . SESSIONS_TABLE . " + WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "' + AND session_user_id = " . (int) $this->data['user_id']; + phpbb::$db->sql_query($sql); + + // Allow connecting logout with external auth method logout + if (method_exists($this->auth, 'logout')) + { + $this->auth->logout($this, $new_session); + } + + if ($this->data['user_id'] != ANONYMOUS) + { + // Delete existing session, update last visit info first! + if (!isset($this->data['session_time'])) + { + $this->data['session_time'] = time(); + } + + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_lastvisit = ' . (int) $this->data['session_time'] . ' + WHERE user_id = ' . (int) $this->data['user_id']; + phpbb::$db->sql_query($sql); + + if ($this->cookie_data['k']) + { + $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' + WHERE user_id = ' . (int) $this->data['user_id'] . " + AND key_id = '" . phpbb::$db->sql_escape(md5($this->cookie_data['k'])) . "'"; + phpbb::$db->sql_query($sql); + } + + // Reset the data array + $this->data = array(); + + $sql = 'SELECT * + FROM ' . USERS_TABLE . ' + WHERE user_id = ' . ANONYMOUS; + $result = phpbb::$db->sql_query($sql); + $this->data = phpbb::$db->sql_fetchrow($result); + phpbb::$db->sql_freeresult($result); + } + + $cookie_expire = $this->time_now - 31536000; + $this->set_cookie('u', '', $cookie_expire); + $this->set_cookie('k', '', $cookie_expire); + $this->set_cookie('sid', '', $cookie_expire); + unset($cookie_expire); + + $SID = '?sid='; + $this->session_id = $_SID = ''; + + // To make sure a valid session is created we create one for the anonymous user + if ($new_session) + { + $this->session_create(ANONYMOUS); + } + + return true; + } + + /** + * Session garbage collection + * + * This looks a lot more complex than it really is. Effectively we are + * deleting any sessions older than an admin definable limit. Due to the + * way in which we maintain session data we have to ensure we update user + * data before those sessions are destroyed. In addition this method + * removes autologin key information that is older than an admin defined + * limit. + */ + public function session_gc() + { + $batch_size = 10; + + if (!$this->time_now) + { + $this->time_now = time(); + } + + // Firstly, delete guest sessions + $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' + WHERE session_user_id = ' . ANONYMOUS . ' + AND session_time < ' . (int) ($this->time_now - phpbb::$config['session_length']); + phpbb::$db->sql_query($sql); + + // Get expired sessions, only most recent for each user + $sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time + FROM ' . SESSIONS_TABLE . ' + WHERE session_time < ' . ($this->time_now - phpbb::$config['session_length']) . ' + GROUP BY session_user_id, session_page'; + $result = phpbb::$db->sql_query_limit($sql, $batch_size); + + $del_user_id = array(); + $del_sessions = 0; + + while ($row = phpbb::$db->sql_fetchrow($result)) + { + $sql = 'UPDATE ' . USERS_TABLE . ' + SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . phpbb::$db->sql_escape($row['session_page']) . "' + WHERE user_id = " . (int) $row['session_user_id']; + phpbb::$db->sql_query($sql); + + $del_user_id[] = (int) $row['session_user_id']; + $del_sessions++; + } + phpbb::$db->sql_freeresult($result); + + if (sizeof($del_user_id)) + { + // Delete expired sessions + $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' + WHERE ' . phpbb::$db->sql_in_set('session_user_id', $del_user_id) . ' + AND session_time < ' . ($this->time_now - phpbb::$config['session_length']); + phpbb::$db->sql_query($sql); + } + + if ($del_sessions < $batch_size) + { + // Less than 10 users, update gc timer ... else we want gc + // called again to delete other sessions + set_config('session_last_gc', $this->time_now, true); + + if (phpbb::$config['max_autologin_time']) + { + $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' + WHERE last_login < ' . (time() - (86400 * (int) phpbb::$config['max_autologin_time'])); + phpbb::$db->sql_query($sql); + } + + // only called from CRON; should be a safe workaround until the infrastructure gets going + if (!class_exists('captcha_factory')) + { + include(PHPBB_ROOT_PATH . "includes/captcha/captcha_factory." . PHP_EXT); + } + captcha_factory::garbage_collect(phpbb::$config['captcha_plugin']); + } + + return; + } + + + /** + * Sets a cookie + * + * Sets a cookie of the given name with the specified data for the given length of time. If no time is specified, a session cookie will be set. + * + * @param string $name Name of the cookie, will be automatically prefixed with the phpBB cookie name. track becomes [cookie_name]_track then. + * @param string $cookiedata The data to hold within the cookie + * @param int $cookietime The expiration time as UNIX timestamp. If 0 is provided, a session cookie is set. + */ + public function set_cookie($name, $cookiedata, $cookietime) + { + $name_data = rawurlencode(phpbb::$config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata); + $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime); + $domain = (!phpbb::$config['cookie_domain'] || phpbb::$config['cookie_domain'] == 'localhost' || phpbb::$config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . phpbb::$config['cookie_domain']; + + header('Set-Cookie: ' . $name_data . (($cookietime) ? '; expires=' .... [truncated message content] |
|
From: Meik S. <acy...@ph...> - 2008-12-11 17:43:29
|
Added: branches/acydburn/phpBB/includes/core/core_url.php
==============================================================================
*** branches/acydburn/phpBB/includes/core/core_url.php (added)
--- branches/acydburn/phpBB/includes/core/core_url.php Thu Dec 11 17:39:51 2008
***************
*** 0 ****
--- 1,662 ----
+ <?php
+ // Server functions (building urls, redirecting...)
+ class phpbb_url
+ {
+ public function __construct() { }
+
+ /*
+ * Checks if a path ($path) is absolute or relative
+ *
+ * @param string $path Path to check absoluteness of
+ * @return boolean
+ */
+ function is_absolute($path)
+ {
+ return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:/#i', $path))) ? true : false;
+ }
+
+ /**
+ * @author Chris Smith <ch...@pr...>
+ * @copyright 2006 Project Minerva Team
+ * @param string $path The path which we should attempt to resolve.
+ * @return mixed
+ */
+ private function own_realpath($path)
+ {
+ // Now to perform funky shizzle
+
+ // Switch to use UNIX slashes
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', $path);
+ $path_prefix = '';
+
+ // Determine what sort of path we have
+ if (is_absolute($path))
+ {
+ $absolute = true;
+
+ if ($path[0] == '/')
+ {
+ // Absolute path, *NIX style
+ $path_prefix = '';
+ }
+ else
+ {
+ // Absolute path, Windows style
+ // Remove the drive letter and colon
+ $path_prefix = $path[0] . ':';
+ $path = substr($path, 2);
+ }
+ }
+ else
+ {
+ // Relative Path
+ // Prepend the current working directory
+ if (function_exists('getcwd'))
+ {
+ // This is the best method, hopefully it is enabled!
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path;
+ $absolute = true;
+ if (preg_match('#^[a-z]:#i', $path))
+ {
+ $path_prefix = $path[0] . ':';
+ $path = substr($path, 2);
+ }
+ else
+ {
+ $path_prefix = '';
+ }
+ }
+ else if (isset($_SERVER['SCRIPT_FILENAME']) && !empty($_SERVER['SCRIPT_FILENAME']))
+ {
+ // Warning: If chdir() has been used this will lie!
+ // Warning: This has some problems sometime (CLI can create them easily)
+ $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path;
+ $absolute = true;
+ $path_prefix = '';
+ }
+ else
+ {
+ // We have no way of getting the absolute path, just run on using relative ones.
+ $absolute = false;
+ $path_prefix = '.';
+ }
+ }
+
+ // Remove any repeated slashes
+ $path = preg_replace('#/{2,}#', '/', $path);
+
+ // Remove the slashes from the start and end of the path
+ $path = trim($path, '/');
+
+ // Break the string into little bits for us to nibble on
+ $bits = explode('/', $path);
+
+ // Remove any . in the path, renumber array for the loop below
+ $bits = array_values(array_diff($bits, array('.')));
+
+ // Lets get looping, run over and resolve any .. (up directory)
+ for ($i = 0, $max = sizeof($bits); $i < $max; $i++)
+ {
+ // @todo Optimise
+ if ($bits[$i] == '..' )
+ {
+ if (isset($bits[$i - 1]))
+ {
+ if ($bits[$i - 1] != '..')
+ {
+ // We found a .. and we are able to traverse upwards, lets do it!
+ unset($bits[$i]);
+ unset($bits[$i - 1]);
+ $i -= 2;
+ $max -= 2;
+ $bits = array_values($bits);
+ }
+ }
+ else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute
+ {
+ // We have an absolute path trying to descend above the root of the filesystem
+ // ... Error!
+ return false;
+ }
+ }
+ }
+
+ // Prepend the path prefix
+ array_unshift($bits, $path_prefix);
+
+ $resolved = '';
+
+ $max = sizeof($bits) - 1;
+
+ // Check if we are able to resolve symlinks, Windows cannot.
+ $symlink_resolve = (function_exists('readlink')) ? true : false;
+
+ foreach ($bits as $i => $bit)
+ {
+ if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit")))
+ {
+ // Path Exists
+ if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit")))
+ {
+ // Resolved a symlink.
+ $resolved = $link . (($i == $max) ? '' : '/');
+ continue;
+ }
+ }
+ else
+ {
+ // Something doesn't exist here!
+ // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic
+ // return false;
+ }
+ $resolved .= $bit . (($i == $max) ? '' : '/');
+ }
+
+ // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it
+ // because we must be inside that basedir, the question is where...
+ // @internal The slash in is_dir() gets around an open_basedir restriction
+ if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved)))
+ {
+ return false;
+ }
+
+ // Put the slashes back to the native operating systems slashes
+ $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved);
+
+ // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
+ if (substr($resolved, -1) == DIRECTORY_SEPARATOR)
+ {
+ return substr($resolved, 0, -1);
+ }
+
+ return $resolved; // We got here, in the end!
+ }
+
+ /**
+ * A wrapper for realpath
+ */
+ function realpath($path)
+ {
+ static $_phpbb_realpath_exist;
+
+ if (!isset($_phpbb_realpath_exist))
+ {
+ $_phpbb_realpath_exist = (!function_exists('realpath')) ? false : true;
+ }
+
+ if (!$_phpbb_realpath_exist)
+ {
+ return $this->own_realpath($path);
+ }
+
+ $realpath = realpath($path);
+
+ // Strangely there are provider not disabling realpath but returning strange values. :o
+ // We at least try to cope with them.
+ if ($realpath === $path || $realpath === false)
+ {
+ $_phpbb_realpath_exist = false;
+ return $this->own_realpath($path);
+ }
+
+ // Check for DIRECTORY_SEPARATOR at the end (and remove it!)
+ if (substr($realpath, -1) == DIRECTORY_SEPARATOR)
+ {
+ $realpath = substr($realpath, 0, -1);
+ }
+
+ return $realpath;
+ }
+
+ /**
+ * URL wrapper, hookable, all urls are run through this... either after append_sid() or not
+ */
+ public function get($url)
+ {
+ //if ($_fnc = array(__CLASS__, __FUNCTION__) && phpbb::$hooks->call($_fnc, $url) && phpbb::$hooks->return($_fnc)) return phpbb::$hooks->return_result($_fnc);
+ return $url;
+ }
+
+ /**
+ * Append session id to url.
+ * This function supports hooks.
+ *
+ * @param string $url The url the session id needs to be appended to (can have params)
+ * @param mixed $params String or array of additional url parameters
+ * @param bool $is_amp Is url using & (true) or & (false)
+ * @param string $session_id Possibility to use a custom session id instead of the global one
+ *
+ * Examples:
+ * <code>
+ * append_sid(PHPBB_ROOT_PATH . 'viewtopic.' . PHP_EXT . '?t=1&f=2');
+ * append_sid(PHPBB_ROOT_PATH . 'viewtopic.' . PHP_EXT, 't=1&f=2');
+ * append_sid('viewtopic', 't=1&f=2'); // short notation of the above example
+ * append_sid('viewtopic', 't=1&f=2', false);
+ * append_sid('viewtopic', array('t' => 1, 'f' => 2));
+ * </code>
+ *
+ */
+ public function append_sid($url, $params = false, $is_amp = true, $session_id = false)
+ {
+ global $_SID, $_EXTRA_URL;
+ static $parsed_urls = array();
+
+ // The following code is used to make sure such calls like append_sid('viewtopic') (ommitting phpbb_root_path and php_ext) work as intended
+ if (isset($parsed_urls[$url]))
+ {
+ // Set an url like 'viewtopic' to PHPBB_ROOT_PATH . 'viewtopic.' . PHP_EXT
+ $url = $parsed_urls[$url];
+ }
+ else
+ {
+ // If we detect an url without root path and extension, and also not a relative or absolute path, we add it and put it to the parsed urls
+ if (strpos($url, '.' . PHP_EXT) === false && $url[0] != '.' && $url[0] != '/')
+ {
+ $parsed_urls[$url] = $url = PHPBB_ROOT_PATH . $url . '.' . PHP_EXT;
+ }
+ }
+
+ if (empty($params))
+ {
+ $params = false;
+ }
+
+ $params_is_array = is_array($params);
+
+ // Get anchor
+ $anchor = '';
+ if (strpos($url, '#') !== false)
+ {
+ list($url, $anchor) = explode('#', $url, 2);
+ $anchor = '#' . $anchor;
+ }
+ else if (!$params_is_array && strpos($params, '#') !== false)
+ {
+ list($params, $anchor) = explode('#', $params, 2);
+ $anchor = '#' . $anchor;
+ }
+
+ // Handle really simple cases quickly
+ if ($_SID == '' && $session_id === false && empty($_EXTRA_URL) && !$params_is_array && !$anchor)
+ {
+ if ($params === false)
+ {
+ return $this->get($url);
+ }
+
+ $url_delim = (strpos($url, '?') === false) ? '?' : (($is_amp) ? '&' : '&');
+ return $this->get($url . ($params !== false ? $url_delim. $params : ''));
+ }
+
+ // Assign sid if session id is not specified
+ if ($session_id === false)
+ {
+ $session_id = $_SID;
+ }
+
+ $amp_delim = ($is_amp) ? '&' : '&';
+ $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim;
+
+ // Appending custom url parameter?
+ $append_url = (!empty($_EXTRA_URL)) ? implode($amp_delim, $_EXTRA_URL) : '';
+
+ // Use the short variant if possible ;)
+ if ($params === false)
+ {
+ // Append session id
+ if (!$session_id)
+ {
+ return $this->get($url . (($append_url) ? $url_delim . $append_url : '') . $anchor);
+ }
+ else
+ {
+ return $this->get($url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor);
+ }
+ }
+
+ // Build string if parameters are specified as array
+ if (is_array($params))
+ {
+ $output = array();
+
+ foreach ($params as $key => $item)
+ {
+ if ($item === NULL)
+ {
+ continue;
+ }
+
+ if ($key == '#')
+ {
+ $anchor = '#' . $item;
+ continue;
+ }
+
+ $output[] = $key . '=' . $item;
+ }
+
+ $params = implode($amp_delim, $output);
+ }
+
+ // Append session id and parameters (even if they are empty)
+ // If parameters are empty, the developer can still append his/her parameters without caring about the delimiter
+ return $this->get($url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . $params . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor);
+ }
+
+ /**
+ * Generate board url (example: http://www.example.com/phpBB)
+ * @param bool $without_script_path if set to true the script path gets not appended (example: http://www.example.com)
+ */
+ public function generate_board_url($without_script_path = false)
+ {
+ $server_name = phpbb::$user->server['host'];
+ $server_port = phpbb::$user->server['port'];
+
+ // Forcing server vars is the only way to specify/override the protocol
+ if ($config['force_server_vars'] || !$server_name)
+ {
+ $server_protocol = ($config['server_protocol']) ? $config['server_protocol'] : (($config['cookie_secure']) ? 'https://' : 'http://');
+ $server_name = $config['server_name'];
+ $server_port = (int) $config['server_port'];
+ $script_path = $config['script_path'];
+
+ $url = $server_protocol . $server_name;
+ $cookie_secure = $config['cookie_secure'];
+ }
+ else
+ {
+ // Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection
+ $cookie_secure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 1 : 0;
+ $url = (($cookie_secure) ? 'https://' : 'http://') . $server_name;
+
+ $script_path = $user->page['root_script_path'];
+ }
+
+ if ($server_port && (($cookie_secure && $server_port <> 443) || (!$cookie_secure && $server_port <> 80)))
+ {
+ // HTTP HOST can carry a port number (we fetch $user->host, but for old versions this may be true)
+ if (strpos($server_name, ':') === false)
+ {
+ $url .= ':' . $server_port;
+ }
+ }
+
+ if (!$without_script_path)
+ {
+ $url .= $script_path;
+ }
+
+ // Strip / from the end
+ if (substr($url, -1, 1) == '/')
+ {
+ $url = substr($url, 0, -1);
+ }
+
+ return $url;
+ }
+
+ /**
+ * Redirects the user to another page then exits the script nicely
+ * This function is intended for urls within the board. It's not meant to redirect to cross-domains.
+ *
+ * @param string $url The url to redirect to
+ * @param bool $return If true, do not redirect but return the sanitized URL. Default is no return.
+ * @param bool $disable_cd_check If true, redirect() will redirect to an external domain. If false, the redirect point to the boards url if it does not match the current domain. Default is false.
+ */
+ function redirect($url, $return = false, $disable_cd_check = false)
+ {
+ global $db, $cache, $config, $user;
+
+ if (empty($user->lang))
+ {
+ $user->add_lang('common');
+ }
+
+ if (!$return)
+ {
+ garbage_collection();
+ }
+
+ // Make sure no &'s are in, this will break the redirect
+ $url = str_replace('&', '&', $url);
+
+ // Determine which type of redirect we need to handle...
+ $url_parts = parse_url($url);
+
+ if ($url_parts === false)
+ {
+ // Malformed url, redirect to current page...
+ $url = generate_board_url() . '/' . $user->page['page'];
+ }
+ else if (!empty($url_parts['scheme']) && !empty($url_parts['host']))
+ {
+ // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work)
+ if (!$disable_cd_check && $url_parts['host'] !== $user->host)
+ {
+ $url = generate_board_url();
+ }
+ }
+ else if ($url[0] == '/')
+ {
+ // Absolute uri, prepend direct url...
+ $url = generate_board_url(true) . $url;
+ }
+ else
+ {
+ // Relative uri
+ $pathinfo = pathinfo($url);
+
+ // Is the uri pointing to the current directory?
+ if ($pathinfo['dirname'] == '.')
+ {
+ $url = str_replace('./', '', $url);
+
+ // Strip / from the beginning
+ if ($url && substr($url, 0, 1) == '/')
+ {
+ $url = substr($url, 1);
+ }
+
+ if ($user->page['page_dir'])
+ {
+ $url = generate_board_url() . '/' . $user->page['page_dir'] . '/' . $url;
+ }
+ else
+ {
+ $url = generate_board_url() . '/' . $url;
+ }
+ }
+ else
+ {
+ // Used ./ before, but PHPBB_ROOT_PATH is working better with urls within another root path
+ $root_dirs = explode('/', str_replace('\\', '/', $this->realpath(PHPBB_ROOT_PATH)));
+ $page_dirs = explode('/', str_replace('\\', '/', $this->realpath($pathinfo['dirname'])));
+ $intersection = array_intersect_assoc($root_dirs, $page_dirs);
+
+ $root_dirs = array_diff_assoc($root_dirs, $intersection);
+ $page_dirs = array_diff_assoc($page_dirs, $intersection);
+
+ $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
+
+ // Strip / from the end
+ if ($dir && substr($dir, -1, 1) == '/')
+ {
+ $dir = substr($dir, 0, -1);
+ }
+
+ // Strip / from the beginning
+ if ($dir && substr($dir, 0, 1) == '/')
+ {
+ $dir = substr($dir, 1);
+ }
+
+ $url = str_replace($pathinfo['dirname'] . '/', '', $url);
+
+ // Strip / from the beginning
+ if (substr($url, 0, 1) == '/')
+ {
+ $url = substr($url, 1);
+ }
+
+ $url = (!empty($dir) ? $dir . '/' : '') . $url;
+ $url = generate_board_url() . '/' . $url;
+ }
+ }
+
+ // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2
+ if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false)
+ {
+ trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
+ }
+
+ // Now, also check the protocol and for a valid url the last time...
+ $allowed_protocols = array('http', 'https', 'ftp', 'ftps');
+ $url_parts = parse_url($url);
+
+ if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols))
+ {
+ trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR);
+ }
+
+ if ($return)
+ {
+ return $url;
+ }
+
+ // Redirect via an HTML form for PITA webservers
+ if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE')))
+ {
+ header('Refresh: 0; URL=' . $url);
+
+ echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
+ echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . $user->lang['DIRECTION'] . '" lang="' . $user->lang['USER_LANG'] . '" xml:lang="' . $user->lang['USER_LANG'] . '">';
+ echo '<head>';
+ echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />';
+ echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&', $url) . '" />';
+ echo '<title>' . $user->lang['REDIRECT'] . '</title>';
+ echo '</head>';
+ echo '<body>';
+ echo '<div style="text-align: center;">' . sprintf($user->lang['URL_REDIRECT'], '<a href="' . str_replace('&', '&', $url) . '">', '</a>') . '</div>';
+ echo '</body>';
+ echo '</html>';
+
+ exit;
+ }
+
+ // Behave as per HTTP/1.1 spec for others
+ header('Location: ' . $url);
+ exit;
+ }
+
+ /**
+ * Re-Apply session id after page reloads
+ */
+ function reapply_sid($url)
+ {
+ if ($url === 'index.' . PHP_EXT)
+ {
+ return append_sid('index.' . PHP_EXT);
+ }
+ else if ($url === PHPBB_ROOT_PATH . 'index.' . PHP_EXT)
+ {
+ return append_sid('index');
+ }
+
+ // Remove previously added sid
+ if (strpos($url, '?sid=') !== false)
+ {
+ $url = preg_replace('/(\?)sid=[a-z0-9]+(&|&)?/', '\1', $url);
+ }
+ else if (strpos($url, '&sid=') !== false)
+ {
+ $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url);
+ }
+ else if (strpos($url, '&sid=') !== false)
+ {
+ $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url);
+ }
+
+ return append_sid($url);
+ }
+
+ /**
+ * Returns url from the session/current page with an re-appended SID with optionally stripping vars from the url
+ */
+ function build_url($strip_vars = false)
+ {
+ global $user;
+
+ // Append SID
+ $redirect = append_sid($user->page['page'], false, false);
+
+ // Add delimiter if not there...
+ if (strpos($redirect, '?') === false)
+ {
+ $redirect .= '?';
+ }
+
+ // Strip vars...
+ if ($strip_vars !== false && strpos($redirect, '?') !== false)
+ {
+ if (!is_array($strip_vars))
+ {
+ $strip_vars = array($strip_vars);
+ }
+
+ $query = $_query = array();
+
+ $args = substr($redirect, strpos($redirect, '?') + 1);
+ $args = ($args) ? explode('&', $args) : array();
+ $redirect = substr($redirect, 0, strpos($redirect, '?'));
+
+ foreach ($args as $argument)
+ {
+ $arguments = explode('=', $argument);
+ $key = $arguments[0];
+ unset($arguments[0]);
+
+ $query[$key] = implode('=', $arguments);
+ }
+
+ // Strip the vars off
+ foreach ($strip_vars as $strip)
+ {
+ if (isset($query[$strip]))
+ {
+ unset($query[$strip]);
+ }
+ }
+
+ // Glue the remaining parts together... already urlencoded
+ foreach ($query as $key => $value)
+ {
+ $_query[] = $key . '=' . $value;
+ }
+ $query = implode('&', $_query);
+
+ $redirect .= ($query) ? '?' . $query : '';
+ }
+
+ return PHPBB_ROOT_PATH . str_replace('&', '&', $redirect);
+ }
+
+ /**
+ * Meta refresh assignment
+ */
+ function meta_refresh($time, $url)
+ {
+ global $template;
+
+ $url = redirect($url, true);
+ $url = str_replace('&', '&', $url);
+
+ // For XHTML compatibility we change back & to &
+ $template->assign_vars(array(
+ 'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />')
+ );
+
+ return $url;
+ }
+ }
+
+ ?>
\ No newline at end of file
Propchange: branches/acydburn/phpBB/includes/core/core_url.php
------------------------------------------------------------------------------
svn:eol-style = LF
Propchange: branches/acydburn/phpBB/includes/core/core_url.php
------------------------------------------------------------------------------
svn:keywords = "Author Date Id Revision"
Removed: branches/acydburn/phpBB/includes/session.php
==============================================================================
*** branches/acydburn/phpBB/includes/session.php (original)
--- branches/acydburn/phpBB/includes/session.php (removed)
***************
*** 1,2146 ****
- <?php
- /**
- *
- * @package phpBB3
- * @version $Id$
- * @copyright (c) 2005 phpBB Group
- * @license http://opensource.org/licenses/gpl-license.php GNU Public License
- *
- */
-
- /**
- * @ignore
- */
- if (!defined('IN_PHPBB'))
- {
- exit;
- }
-
- /**
- * Session class
- * @package phpBB3
- */
- class session
- {
- var $cookie_data = array();
- var $page = array();
- var $data = array();
- var $browser = '';
- var $forwarded_for = '';
- var $host = '';
- var $session_id = '';
- var $ip = '';
- var $load = 0;
- var $time_now = 0;
- var $update_session_page = true;
-
- /**
- * Extract current session page
- *
- * @param string $root_path current root path (phpbb_root_path)
- */
- public static function extract_current_page($root_path)
- {
- $page_array = array();
-
- // First of all, get the request uri...
- $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF');
- $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING'));
-
- // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support...
- if (!$script_name)
- {
- $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI');
- $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name;
- $page_array['failover'] = 1;
- }
-
- // Replace backslashes and doubled slashes (could happen on some proxy setups)
- $script_name = str_replace(array('\\', '//'), '/', $script_name);
-
- // Now, remove the sid and let us get a clean query string...
- $use_args = array();
-
- // Since some browser do not encode correctly we need to do this with some "special" characters...
- // " -> %22, ' => %27, < -> %3C, > -> %3E
- $find = array('"', "'", '<', '>');
- $replace = array('%22', '%27', '%3C', '%3E');
-
- foreach ($args as $argument)
- {
- if (strpos($argument, 'sid=') === 0)
- {
- continue;
- }
-
- $use_args[] = str_replace($find, $replace, $argument);
- }
- unset($args);
-
- // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2
-
- // The current query string
- $query_string = trim(implode('&', $use_args));
-
- // basenamed page name (for example: index.php)
- $page_name = basename($script_name);
- $page_name = urlencode(htmlspecialchars($page_name));
-
- // current directory within the phpBB root (for example: adm)
- $root_dirs = explode('/', str_replace('\\', '/', phpbb_realpath($root_path)));
- $page_dirs = explode('/', str_replace('\\', '/', phpbb_realpath('./')));
- $intersection = array_intersect_assoc($root_dirs, $page_dirs);
-
- $root_dirs = array_diff_assoc($root_dirs, $intersection);
- $page_dirs = array_diff_assoc($page_dirs, $intersection);
-
- $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs);
-
- if ($page_dir && substr($page_dir, -1, 1) == '/')
- {
- $page_dir = substr($page_dir, 0, -1);
- }
-
- // Current page from phpBB root (for example: adm/index.php?i=10&b=2)
- $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : '');
-
- // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in /
- $script_path = trim(str_replace('\\', '/', dirname($script_name)));
-
- // The script path from the webroot to the phpBB root (for example: /phpBB3/)
- $script_dirs = explode('/', $script_path);
- array_splice($script_dirs, -sizeof($page_dirs));
- $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : '');
-
- // We are on the base level (phpBB root == webroot), lets adjust the variables a bit...
- if (!$root_script_path)
- {
- $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path;
- }
-
- $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/';
- $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/';
-
- $page_array += array(
- 'page_name' => $page_name,
- 'page_dir' => $page_dir,
-
- 'query_string' => $query_string,
- 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)),
- 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)),
-
- 'page' => $page
- );
-
- return $page_array;
- }
-
- /**
- * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present.
- */
- function extract_current_hostname()
- {
- global $config;
-
- // Get hostname
- $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME'));
-
- // Should be a string and lowered
- $host = (string) strtolower($host);
-
- // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid
- if ((isset($config['cookie_domain']) && $host === $config['cookie_domain']) || (isset($config['server_name']) && $host === $config['server_name']))
- {
- return $host;
- }
-
- // Is the host actually a IP? If so, we use the IP... (IPv4)
- if (long2ip(ip2long($host)) === $host)
- {
- return $host;
- }
-
- // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned
- $host = @parse_url('http://' . $host, PHP_URL_HOST);
-
- // Remove any portions not removed by parse_url (#)
- $host = str_replace('#', '', $host);
-
- // If, by any means, the host is now empty, we will use a "best approach" way to guess one
- if (empty($host))
- {
- if (!empty($config['server_name']))
- {
- $host = $config['server_name'];
- }
- else if (!empty($config['cookie_domain']))
- {
- $host = (strpos($config['cookie_domain'], '.') === 0) ? substr($config['cookie_domain'], 1) : $config['cookie_domain'];
- }
- else
- {
- // Set to OS hostname or localhost
- $host = (function_exists('php_uname')) ? php_uname('n') : 'localhost';
- }
- }
-
- // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set)
- return $host;
- }
-
- /**
- * Start session management
- *
- * This is where all session activity begins. We gather various pieces of
- * information from the client and server. We test to see if a session already
- * exists. If it does, fine and dandy. If it doesn't we'll go on to create a
- * new one ... pretty logical heh? We also examine the system load (if we're
- * running on a system which makes such information readily available) and
- * halt if it's above an admin definable limit.
- *
- * @param bool $update_session_page if true the session page gets updated.
- * This can be set to circumvent certain scripts to update the users last visited page.
- */
- function session_begin($update_session_page = true)
- {
- global $SID, $_SID, $_EXTRA_URL, $db, $config;
-
- // Give us some basic information
- $this->time_now = time();
- $this->cookie_data = array('u' => 0, 'k' => '');
- $this->update_session_page = $update_session_page;
- $this->browser = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : '';
- $this->referer = (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : '';
- $this->forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : '';
-
- $this->host = self::extract_current_hostname();
- $this->page = self::extract_current_page(PHPBB_ROOT_PATH);
-
- // if the forwarded for header shall be checked we have to validate its contents
- if ($config['forwarded_for_check'])
- {
- $this->forwarded_for = preg_replace('#, +#', ', ', $this->forwarded_for);
-
- // split the list of IPs
- $ips = explode(', ', $this->forwarded_for);
- foreach ($ips as $ip)
- {
- // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly
- if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip))
- {
- // contains invalid data, don't use the forwarded for header
- $this->forwarded_for = '';
- break;
- }
- }
- }
- else
- {
- $this->forwarded_for = '';
- }
-
- // Add forum to the page for tracking online users - also adding a "x" to the end to properly identify the number
- $forum = request_var('f', 0);
- $this->page['page'] .= ($forum) ? ((strpos($this->page['page'], '?') !== false) ? '&' : '?') . '_f_=' . $forum . 'x' : '';
-
- if (request::is_set($config['cookie_name'] . '_sid', request::COOKIE) || request::is_set($config['cookie_name'] . '_u', request::COOKIE))
- {
- $this->cookie_data['u'] = request_var($config['cookie_name'] . '_u', 0, false, true);
- $this->cookie_data['k'] = request_var($config['cookie_name'] . '_k', '', false, true);
- $this->session_id = request_var($config['cookie_name'] . '_sid', '', false, true);
-
- $SID = (defined('NEED_SID')) ? '?sid=' . $this->session_id : '?sid=';
- $_SID = (defined('NEED_SID')) ? $this->session_id : '';
-
- if (empty($this->se...
[truncated message content] |