|
From: Florin C B. <ory...@us...> - 2013-06-26 09:15:27
|
Update of /cvsroot/mxbb/core/includes In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv24985/includes Modified Files: mx_functions.php mx_functions_admincp.php mx_functions_core.php mx_functions_style.php Log Message: Index: mx_functions_core.php =================================================================== RCS file: /cvsroot/mxbb/core/includes/mx_functions_core.php,v retrieving revision 1.135 retrieving revision 1.136 diff -C2 -d -r1.135 -r1.136 *** mx_functions_core.php 25 Jun 2013 20:05:03 -0000 1.135 --- mx_functions_core.php 26 Jun 2013 09:15:23 -0000 1.136 *************** *** 180,186 **** global $db; ! if ( ($config = $this->get('mxbb_config')) && ($use_cache) ) { ! return $config; } else --- 180,186 ---- global $db; ! if ( ($portal_config = $this->get('mx_config')) && ($use_cache) ) { ! return $portal_config; } else *************** *** 204,213 **** foreach ($row as $config_name => $config_value) { ! $config[$config_name] = trim($config_value); } $db->sql_freeresult($result); ! $this->put('mxbb_config', $config); ! return ($config); } } --- 204,213 ---- foreach ($row as $config_name => $config_value) { ! $portal_config[$config_name] = trim($config_value); } $db->sql_freeresult($result); ! $this->put('mx_config', $portal_config); ! return ($portal_config); } } *************** *** 634,638 **** WHERE portal_id = 1"; ! if ( !( $result = $db->sql_query( $sql, BEGIN_TRANSACTION ) ) ) { mx_message_die( GENERAL_ERROR, "Could not update portal cache time.", "", __LINE__, __FILE__, $sql ); --- 634,638 ---- WHERE portal_id = 1"; ! if (!($result = $db->sql_query($sql, BEGIN_TRANSACTION))) { mx_message_die( GENERAL_ERROR, "Could not update portal cache time.", "", __LINE__, __FILE__, $sql ); *************** *** 781,785 **** @closedir($dir); } ! } /** --- 781,1066 ---- @closedir($dir); } ! /** ! * Read cached data from a specified file ! * ! * @access private ! * @param string $filename Filename to write ! * @return mixed False if an error was encountered, otherwise the data type of the cached data ! */ ! function _read($filename) ! { ! global $phpEx; ! ! $file = "{$this->cache_dir}$filename.$phpEx"; ! ! $type = substr($filename, 0, strpos($filename, '_')); ! ! if (!file_exists($file)) ! { ! return false; ! } ! ! if (!($handle = @fopen($file, 'rb'))) ! { ! return false; ! } ! ! // Skip the PHP header ! fgets($handle); ! ! if ($filename == 'data_global') ! { ! $this->vars = $this->var_expires = array(); ! ! $time = time(); ! ! while (($expires = (int) fgets($handle)) && !feof($handle)) ! { ! // Number of bytes of data ! $bytes = substr(fgets($handle), 0, -1); ! ! if (!is_numeric($bytes) || ($bytes = (int) $bytes) === 0) ! { ! // We cannot process the file without a valid number of bytes ! // so we discard it ! fclose($handle); ! ! $this->vars = $this->var_expires = array(); ! $this->is_modified = false; ! ! $this->remove_file($file); ! ! return false; ! } ! ! if ($time >= $expires) ! { ! fseek($handle, $bytes, SEEK_CUR); ! ! continue; ! } ! ! $var_name = substr(fgets($handle), 0, -1); ! ! // Read the length of bytes that consists of data. ! $data = fread($handle, $bytes - strlen($var_name)); ! $data = @unserialize($data); ! ! // Don't use the data if it was invalid ! if ($data !== false) ! { ! $this->vars[$var_name] = $data; ! $this->var_expires[$var_name] = $expires; ! } ! ! // Absorb the LF ! fgets($handle); ! } ! ! fclose($handle); ! ! $this->is_modified = false; ! ! return true; ! } ! else ! { ! $data = false; ! $line = 0; ! ! while (($buffer = fgets($handle)) && !feof($handle)) ! { ! $buffer = substr($buffer, 0, -1); // Remove the LF ! ! // $buffer is only used to read integers ! // if it is non numeric we have an invalid ! // cache file, which we will now remove. ! if (!is_numeric($buffer)) ! { ! break; ! } ! ! if ($line == 0) ! { ! $expires = (int) $buffer; ! ! if (time() >= $expires) ! { ! break; ! } ! ! if ($type == 'sql') ! { ! // Skip the query ! fgets($handle); ! } ! } ! else if ($line == 1) ! { ! $bytes = (int) $buffer; ! ! // Never should have 0 bytes ! if (!$bytes) ! { ! break; ! } ! ! // Grab the serialized data ! $data = fread($handle, $bytes); ! ! // Read 1 byte, to trigger EOF ! fread($handle, 1); ! ! if (!feof($handle)) ! { ! // Somebody tampered with our data ! $data = false; ! } ! break; ! } ! else ! { ! // Something went wrong ! break; ! } ! $line++; ! } ! fclose($handle); ! ! // unserialize if we got some data ! $data = ($data !== false) ? @unserialize($data) : $data; ! ! if ($data === false) ! { ! $this->remove_file($file); ! return false; ! } ! ! return $data; ! } ! } ! ! /** ! * Write cache data to a specified file ! * ! * 'data_global' is a special case and the generated format is different for this file: ! * <code> ! * <?php exit; ?> ! * (expiration) ! * (length of var and serialised data) ! * (var) ! * (serialised data) ! * ... (repeat) ! * </code> ! * ! * The other files have a similar format: ! * <code> ! * <?php exit; ?> ! * (expiration) ! * (query) [SQL files only] ! * (length of serialised data) ! * (serialised data) ! * </code> ! * ! * @access private ! * @param string $filename Filename to write ! * @param mixed $data Data to store ! * @param int $expires Timestamp when the data expires ! * @param string $query Query when caching SQL queries ! * @return bool True if the file was successfully created, otherwise false ! */ ! function _write($filename, $data = null, $expires = 0, $query = '') ! { ! global $phpEx; ! ! $file = "{$this->cache_dir}$filename.$phpEx"; ! ! $lock = new mx_lock_flock($file); ! $lock->acquire(); ! ! if ($handle = @fopen($file, 'wb')) ! { ! // File header ! fwrite($handle, '<' . '?php exit; ?' . '>'); ! ! if ($filename == 'data_global') ! { ! // Global data is a different format ! foreach ($this->vars as $var => $data) ! { ! if (strpos($var, "\r") !== false || strpos($var, "\n") !== false) ! { ! // CR/LF would cause fgets() to read the cache file incorrectly ! // do not cache test entries, they probably won't be read back ! // the cache keys should really be alphanumeric with a few symbols. ! continue; ! } ! $data = serialize($data); ! ! // Write out the expiration time ! fwrite($handle, "\n" . $this->var_expires[$var] . "\n"); ! ! // Length of the remaining data for this var (ignoring two LF's) ! fwrite($handle, strlen($data . $var) . "\n"); ! fwrite($handle, $var . "\n"); ! fwrite($handle, $data); ! } ! } ! else ! { ! fwrite($handle, "\n" . $expires . "\n"); ! ! if (strpos($filename, 'sql_') === 0) ! { ! fwrite($handle, $query . "\n"); ! } ! $data = serialize($data); ! ! fwrite($handle, strlen($data) . "\n"); ! fwrite($handle, $data); ! } ! ! fclose($handle); ! ! if (!function_exists('mx_chmod')) ! { ! global $mx_root_path; ! include($mx_root_path . 'includes/mx_functions.' . $phpEx); ! } ! ! mx_chmod($file, CHMOD_READ | CHMOD_WRITE); ! ! $return_value = true; ! } ! else ! { ! $return_value = false; ! } ! ! $lock->release(); ! ! return $return_value; ! } ! ! /** ! * Removes/unlinks file ! */ ! function remove_file($filename, $check = false) ! { ! if (!function_exists('phpbb_is_writable')) ! { ! global $phpbb_root_path, $phpEx; ! include($phpbb_root_path . 'includes/functions.' . $phpEx); ! } ! ! if ($check && !phpbb_is_writable($this->cache_dir)) ! { ! // E_USER_ERROR - not using language entry - intended. ! trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); ! } ! ! return @unlink($filename); ! } ! } /** *************** *** 813,816 **** --- 1094,1122 ---- var $is_modified = false; var $sql_rowset = array('1' => '1'); // Cache fix. Now also FIRST query can be cached. Unsolved phpBB bug...i think ;) + + /** + * Cache driver. + * + * @var mx_cache_driver_interface + */ + var $driver = true; + + /** @var mx_page */ + protected $mx_page; + + /** + * Root path. + * + * @var string + */ + protected $mx_root_path; + + /** + * PHP extension. + * + * @var string + */ + protected $phpEx; + /**#@-*/ *************** *** 818,835 **** // Private Methods // ! // /** ! * Constructor. ! * ! * @return cache ! */ ! function cache() { ! global $mx_root_path; $this->cache_dir = $mx_root_path . 'cache/'; } /** * Load. * --- 1124,1164 ---- // Private Methods // ! // /** ! * Creates a cache service around a cache driver ! * ! * @return cache ! */ ! public function cache() { ! global $mx_root_path, $phpEx; ! ! $this->mx_root_path = $mx_root_path; ! $this->php_ext = $phpEx; $this->cache_dir = $mx_root_path . 'cache/'; } /** + * Returns the cache driver used by this cache service. + * + * @return mx_cache_driver_interface The cache driver + */ + public function get_driver() + { + return $this->driver; + } + + /** + * Replaces the cache driver used by this cache service. + * + * @param mx_cache_driver_interface $driver The cache driver + */ + public function set_driver($driver) + { + $this->driver = $driver; + } + + /** * Load. * *************** *** 952,956 **** // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); ! $query_id = sizeof($this->sql_rowset); if (!file_exists($this->cache_dir . 'sql_' . md5($query) . ".$phpEx")) --- 1281,1285 ---- // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); ! $query_id = isset($this->sql_rowset) ? sizeof($this->sql_rowset) : 0; if (!file_exists($this->cache_dir . 'sql_' . md5($query) . ".$phpEx")) *************** *** 972,975 **** --- 1301,1393 ---- return $query_id; } + + /** + * {@inheritDoc}. + * + * @access private + * @param unknown_type $query + * @param unknown_type $query_result + * @param unknown_type $ttl + */ + function sql_save($query, &$query_result, $ttl) + { + global $db, $phpEx; + + // Remove extra spaces and tabs + $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); + $hash = md5($query); + + // determine which tables this query belongs to + // Some queries use backticks, namely the get_database_size() query + // don't check for conformity, the SQL would error and not reach here. + if (!preg_match('/FROM \\(?(`?\\w+`?(?: \\w+)?(?:, ?`?\\w+`?(?: \\w+)?)*)\\)?/', $query, $regs)) + { + // Bail out if the match fails. + return $query_result; + } + $tables = array_map('trim', explode(',', $regs[1])); + + $fp = @fopen($this->cache_dir . 'sql_' . md5($query) . '.' . $phpEx, 'wb'); + @flock($fp, LOCK_EX); + foreach ($tables as $table_name) + { + // Remove backticks + $table_name = ($table_name[0] == '`') ? substr($table_name, 1, -1) : $table_name; + + if (($pos = strpos($table_name, ' ')) !== false) + { + $table_name = substr($table_name, 0, $pos); + } + + $temp = $this->_read('sql_' . $table_name); + + if ($temp === false) + { + $temp = array(); + } + + $temp[$hash] = true; + + // This must never expire + if ($fp === false) + { + $this->_write('sql_' . $table_name, $temp, 0); + } + else + { + fwrite($fp, "<?php\n\n/*\n$query\n*/\n\n\$temp[\$hash] = " . true . "; ?>"); + @flock($fp, LOCK_UN); + fclose($fp); + } + } + + // store them in the right place + $lines = array(); + $query_id = sizeof($this->sql_rowset); + $query_id = !empty($query_id) ? $query_id : 1; + $this->sql_rowset[$query_id] = array(); + $this->sql_row_pointer[$query_id] = 0; + + while ($row = $db->sql_fetchrow($query_result)) + { + $this->sql_rowset[$query_id][] = $row; + $lines[] = "unserialize('" . str_replace("'", "\\'", str_replace('\\', '\\\\', serialize($row))) . "')"; + } + $db->sql_freeresult($query_result); + + if ($fp === false) + { + $this->_write('sql_' . $hash, $this->sql_rowset[$query_id], $ttl); + } + else + { + @fwrite($fp, "<?php\n\n/*\n$query\n*/\n\n\$expired = (time() > " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\n\$this->sql_rowset[\$query_id] = array(" . implode(',', $lines) . '); ?>'); + @flock($fp, LOCK_UN); + @fclose($fp); + } + $query_result = $query_id; + + return $query_id; + } /** *************** *** 981,985 **** * @param unknown_type $ttl */ ! function sql_save($query, &$query_result, $ttl) { global $db, $phpEx; --- 1399,1403 ---- * @param unknown_type $ttl */ ! function sql_save2($query, &$query_result, $ttl) { global $db, $phpEx; *************** *** 987,990 **** --- 1405,1409 ---- // Remove extra spaces and tabs $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); + $hash = md5($query); if ($fp = @fopen($this->cache_dir . 'sql_' . md5($query) . '.' . $phpEx, 'wb')) *************** *** 994,997 **** --- 1413,1417 ---- $lines = array(); $query_id = sizeof($this->sql_rowset); + $query_id = !empty($query_id) ? $query_id : 1; $this->sql_rowset[$query_id] = array(); *************** *** 1225,1229 **** $fp = fopen($this->cache_dir . $entry, 'rb'); ! $file = fread($fp, filesize($this->cache_dir . $entry)); @fclose($fp); --- 1645,1649 ---- $fp = fopen($this->cache_dir . $entry, 'rb'); ! $file = @fread($fp, @filesize($this->cache_dir . $entry)); @fclose($fp); Index: mx_functions_style.php =================================================================== RCS file: /cvsroot/mxbb/core/includes/mx_functions_style.php,v retrieving revision 1.133 retrieving revision 1.134 diff -C2 -d -r1.133 -r1.134 *** mx_functions_style.php 25 Jun 2013 17:14:48 -0000 1.133 --- mx_functions_style.php 26 Jun 2013 09:15:23 -0000 1.134 *************** *** 1193,1197 **** $this->theme['fontcolor2'] = $theme['fontcolor2']; */ ! $this->theme = is_array($this->theme) ? array_merge($this->theme, $theme) : $theme; /* Removed since in 3.0.x+ our default template is no style --- 1193,1197 ---- $this->theme['fontcolor2'] = $theme['fontcolor2']; */ ! $this->theme = is_array($this->theme) ? array_merge($this->theme, @$theme) : @$theme; /* Removed since in 3.0.x+ our default template is no style *************** *** 1453,1464 **** @define('TEMPLATE_CONFIG', TRUE); ! // We include common temlate config file here to not load it every time a module template config file is included ! $this->theme = &$theme; break; } ! // ! // We have no template to use - die ! // if ( !defined('TEMPLATE_CONFIG') ) { --- 1453,1465 ---- @define('TEMPLATE_CONFIG', TRUE); ! // We include common temlate config file here to not load it every time a module template config file is included ! //$this->theme = is_array($this->theme) ? array_merge($this->theme, $theme) : $theme; ! //$this->theme = &$theme; break; } ! /* ! * We have no template to use - die ! */ if ( !defined('TEMPLATE_CONFIG') ) { *************** *** 1468,1474 **** $img_lang = ( file_exists($phpbb_root_path . $this->current_template_path . '/images/lang_' . $this->encode_lang($this->lang['default_lang'])) ) ? $this->encode_lang($this->lang['default_lang']) : 'english'; ! // ! // Import phpBB Graphics, prefix with PHPBB_URL, and apply LANG info ! // while( list($key, $value) = @each($images) ) { --- 1469,1475 ---- $img_lang = ( file_exists($phpbb_root_path . $this->current_template_path . '/images/lang_' . $this->encode_lang($this->lang['default_lang'])) ) ? $this->encode_lang($this->lang['default_lang']) : 'english'; ! /* ! * Import phpBB Graphics, prefix with PHPBB_URL, and apply LANG info ! */ while( list($key, $value) = @each($images) ) { *************** *** 1762,1768 **** } ! // ! // If use default template intead ! // if (!$mx_template_config) { --- 1763,1769 ---- } ! /* ! * If use default template intead ! */ if (!$mx_template_config) { *************** *** 1794,1800 **** } ! // ! // We have no template to use - die ! // if (!$mx_template_config) { --- 1795,1801 ---- } ! /* ! * We have no template to use - die ! */ if (!$mx_template_config) { *************** *** 1829,1834 **** // We include common temlate config file here to not load it every time a module template config file is included ! $this->theme = is_array($this->theme) ? array_merge($this->theme, $theme) : $theme; ! //$this->theme = &$theme; unset($mx_images); } --- 1830,1835 ---- // We include common temlate config file here to not load it every time a module template config file is included ! //$this->theme = is_array($this->theme) ? array_merge($this->theme, $theme) : $theme; ! $this->theme = &$theme; unset($mx_images); } Index: mx_functions_admincp.php =================================================================== RCS file: /cvsroot/mxbb/core/includes/mx_functions_admincp.php,v retrieving revision 1.71 retrieving revision 1.72 diff -C2 -d -r1.71 -r1.72 *** mx_functions_admincp.php 25 Jun 2013 20:05:03 -0000 1.71 --- mx_functions_admincp.php 26 Jun 2013 09:15:23 -0000 1.72 *************** *** 3925,3929 **** $i = ($j > 0) ? abs($j - 1) : 0; ! if( $row[$j]['module_id'] != $row[$k]['module_id'] ) { $module_desc_tmp = str_replace("\n", '', $row[$j]['module_desc']); --- 3925,3929 ---- $i = ($j > 0) ? abs($j - 1) : 0; ! if( $row[$j]['module_id'] != $row[$i]['module_id'] ) { $module_desc_tmp = str_replace("\n", '', $row[$j]['module_desc']); Index: mx_functions.php =================================================================== RCS file: /cvsroot/mxbb/core/includes/mx_functions.php,v retrieving revision 1.119 retrieving revision 1.120 diff -C2 -d -r1.119 -r1.120 *** mx_functions.php 25 Jun 2013 20:05:03 -0000 1.119 --- mx_functions.php 26 Jun 2013 09:15:22 -0000 1.120 *************** *** 668,671 **** --- 668,906 ---- /** + * Global function for chmodding directories and files for internal use + * + * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. + * The function determines owner and group from common.php file and sets the same to the provided file. + * The function uses bit fields to build the permissions. + * The function sets the appropiate execute bit on directories. + * + * Supported constants representing bit fields are: + * + * CHMOD_ALL - all permissions (7) + * CHMOD_READ - read permission (4) + * CHMOD_WRITE - write permission (2) + * CHMOD_EXECUTE - execute permission (1) + * + * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. + * + * @param string $filename The file/directory to be chmodded + * @param int $perms Permissions to set + * + * @return bool true on success, otherwise false + * @author faw, phpBB Group + */ + function mx_chmod($filename, $perms = CHMOD_READ) + { + static $_chmod_info; + + // Return if the file no longer exists. + if (!file_exists($filename)) + { + return false; + } + + // Determine some common vars + if (empty($_chmod_info)) + { + if (!function_exists('fileowner') || !function_exists('filegroup')) + { + // No need to further determine owner/group - it is unknown + $_chmod_info['process'] = false; + } + else + { + global $mx_root_path, $phpEx; + + // Determine owner/group of common.php file and the filename we want to change here + $common_php_owner = @fileowner($mx_root_path . 'common.' . $phpEx); + $common_php_group = @filegroup($mx_root_path . 'common.' . $phpEx); + + // And the owner and the groups PHP is running under. + $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; + $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; + + // If we are unable to get owner/group, then do not try to set them by guessing + if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) + { + $_chmod_info['process'] = false; + } + else + { + $_chmod_info = array( + 'process' => true, + 'common_owner' => $common_php_owner, + 'common_group' => $common_php_group, + 'php_uid' => $php_uid, + 'php_gids' => $php_gids, + ); + } + } + } + + if ($_chmod_info['process']) + { + $file_uid = @fileowner($filename); + $file_gid = @filegroup($filename); + + // Change owner + if (@chown($filename, $_chmod_info['common_owner'])) + { + clearstatcache(); + $file_uid = @fileowner($filename); + } + + // Change group + if (@chgrp($filename, $_chmod_info['common_group'])) + { + clearstatcache(); + $file_gid = @filegroup($filename); + } + + // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something + if ($file_uid != $_chmod_info['common_owner'] || $file_gid != $_chmod_info['common_group']) + { + $_chmod_info['process'] = false; + } + } + + // Still able to process? + if ($_chmod_info['process']) + { + if ($file_uid == $_chmod_info['php_uid']) + { + $php = 'owner'; + } + else if (in_array($file_gid, $_chmod_info['php_gids'])) + { + $php = 'group'; + } + else + { + // Since we are setting the everyone bit anyway, no need to do expensive operations + $_chmod_info['process'] = false; + } + } + + // We are not able to determine or change something + if (!$_chmod_info['process']) + { + $php = 'other'; + } + + // Owner always has read/write permission + $owner = CHMOD_READ | CHMOD_WRITE; + if (is_dir($filename)) + { + $owner |= CHMOD_EXECUTE; + + // Only add execute bit to the permission if the dir needs to be readable + if ($perms & CHMOD_READ) + { + $perms |= CHMOD_EXECUTE; + } + } + + switch ($php) + { + case 'owner': + $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); + + clearstatcache(); + + if (is_readable($filename) && mx_is_writable($filename)) + { + break; + } + + case 'group': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); + + clearstatcache(); + + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || mx_is_writable($filename))) + { + break; + } + + case 'other': + $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); + + clearstatcache(); + + if ((!($perms & CHMOD_READ) || is_readable($filename)) && (!($perms & CHMOD_WRITE) || mx_is_writable($filename))) + { + break; + } + + default: + return false; + break; + } + + return $result; + } + + /** + * Test if a file/directory is writable + * + * This function calls the native is_writable() when not running under + * Windows and it is not disabled. + * + * @param string $file Path to perform write test on + * @return bool True when the path is writable, otherwise false. + */ + function mx_is_writable($file) + { + if (strtolower(substr(PHP_OS, 0, 3)) === 'win' || !function_exists('is_writable')) + { + if (file_exists($file)) + { + // Canonicalise path to absolute path + $file = mx_realpath($file); + + if (is_dir($file)) + { + // Test directory by creating a file inside the directory + $result = @tempnam($file, 'i_w'); + + if (is_string($result) && file_exists($result)) + { + unlink($result); + + // Ensure the file is actually in the directory (returned realpathed) + return (strpos($result, $file) === 0) ? true : false; + } + } + else + { + $handle = @fopen($file, 'r+'); + + if (is_resource($handle)) + { + fclose($handle); + return true; + } + } + } + else + { + // file does not exist test if we can write to the directory + $dir = dirname($file); + + if (file_exists($dir) && is_dir($dir) && mx_is_writable($dir)) + { + return true; + } + } + + return false; + } + else + { + return is_writable($file); + } + } + + /** * Generate portal 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) *************** *** 2080,2084 **** $page_id_array['page_name'] = $p_row['page_name']; $page_id_array['page_desc'] = $p_row['page_desc']; ! $page_id_array['block_id'] = $p_row['block_id']; } unset($p_row); --- 2315,2319 ---- $page_id_array['page_name'] = $p_row['page_name']; $page_id_array['page_desc'] = $p_row['page_desc']; ! $page_id_array['block_id'] = isset($p_row['block_id']) ? $p_row['block_id'] : 0; } unset($p_row); *************** *** 2500,2511 **** /** * Borrowed from phpBB * */ function mx_phpbb_realpath($path) { global $mx_root_path, $phpEx; ! return (!@function_exists('realpath') || !@realpath($mx_root_path . 'includes/mx_functions.'.$phpEx)) ? $path : @realpath($path); } --- 2735,2953 ---- /** + * Checks if a path ($path) is absolute or relative + * + * @param string $path Path to check absoluteness of + * @return boolean + */ + function mx_is_absolute($path) + { + return (isset($path[0]) && $path[0] == '/' || preg_match('#^[a-z]:[/\\\]#i', $path)) ? true : false; + } + + /** * Borrowed from phpBB * + * @author Chris Smith <ch...@pr...> + * @copyright 2006 Project Minerva Team + * @param string $path The path which we should attempt to resolve. + * @return mixed */ + function mx_own_realpath($path) + { + global $request; + + // 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 (mx_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 ($request->server('SCRIPT_FILENAME')) + { + // Warning: If chdir() has been used this will lie! + // Warning: This has some problems sometime (CLI can create them easily) + $filename = htmlspecialchars_decode($request->server('SCRIPT_FILENAME')); + $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($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! + } + + function mx_phpbb_realpath($path) { global $mx_root_path, $phpEx; + + return mx_realpath($path); + } ! if (!function_exists('realpath')) ! { ! /** ! * A wrapper for realpath ! * @ignore ! */ ! function mx_realpath($path) ! { ! return mx_own_realpath($path); ! } ! } ! else ! { ! /** ! * A wrapper for realpath ! */ ! function mx_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) ! { ! return mx_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; ! } } |