Property changes on: branches/5.2.x/LICENSE ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/LICENSE:r15957 Property changes on: branches/5.2.x/robots.txt ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/robots.txt:r15957 Index: branches/5.2.x/core/kernel/application.php =================================================================== --- branches/5.2.x/core/kernel/application.php (revision 16433) +++ branches/5.2.x/core/kernel/application.php (revision 16434) @@ -1,3100 +1,3098 @@ * The class encapsulates the main run-cycle of the script, provide access to all other objects in the framework.
*
* The class is a singleton, which means that there could be only one instance of kApplication in the script.
* This could be guaranteed by NOT calling the class constructor directly, but rather calling kApplication::Instance() method, * which returns an instance of the application. The method guarantees that it will return exactly the same instance for any call.
* See singleton pattern by GOF. */ class kApplication implements kiCacheable { /** * Location of module helper class (used in installator too) */ const MODULE_HELPER_PATH = '/../units/helpers/modules_helper.php'; /** * Is true, when Init method was called already, prevents double initialization * * @var bool */ public $InitDone = false; /** * Holds internal NParser object * * @var NParser * @access public */ public $Parser; /** * Holds parser output buffer * * @var string * @access protected */ protected $HTML = ''; /** * The main Factory used to create * almost any class of kernel and * modules * * @var kFactory * @access protected */ protected $Factory; /** * Template names, that will be used instead of regular templates * * @var Array * @access public */ public $ReplacementTemplates = Array (); /** * Mod-Rewrite listeners used during url building and parsing * * @var Array * @access public */ public $RewriteListeners = Array (); /** * Reference to debugger * * @var Debugger * @access public */ public $Debugger = null; /** * Holds all phrases used * in code and template * * @var PhrasesCache * @access public */ public $Phrases; /** * Modules table content, key - module name * * @var Array * @access public */ public $ModuleInfo = Array (); /** * Holds DBConnection * * @var IDBConnection * @access public */ public $Conn = null; /** * Reference to event log * * @var Array|kLogger * @access public */ protected $_logger = Array (); // performance needs: /** * Holds a reference to httpquery * * @var kHttpQuery * @access public */ public $HttpQuery = null; /** * Holds a reference to UnitConfigReader * * @var kUnitConfigReader * @access public */ public $UnitConfigReader = null; /** * Holds a reference to Session * * @var Session * @access public */ public $Session = null; /** * Holds a ref to kEventManager * * @var kEventManager * @access public */ public $EventManager = null; /** * Holds a ref to kUrlManager * * @var kUrlManager * @access public */ public $UrlManager = null; /** * Ref for TemplatesCache * * @var TemplatesCache * @access public */ public $TemplatesCache = null; /** * Holds current NParser tag while parsing, can be used in error messages to display template file and line * * @var _BlockTag * @access public */ public $CurrentNTag = null; /** * Object of unit caching class * * @var kCacheManager * @access public */ public $cacheManager = null; /** * Tells, that administrator has authenticated in administrative console * Should be used to manipulate data change OR data restrictions! * * @var bool * @access public */ public $isAdminUser = false; /** * Tells, that admin version of "index.php" was used, nothing more! * Should be used to manipulate data display! * * @var bool * @access public */ public $isAdmin = false; /** * Instance of site domain object * * @var kDBItem * @access public * @todo move away into separate module */ public $siteDomain = null; /** * Prevent kApplication class to be created directly, only via Instance method * * @access private */ private function __construct() { } final private function __clone() {} /** * Returns kApplication instance anywhere in the script. * * This method should be used to get single kApplication object instance anywhere in the * Kernel-based application. The method is guaranteed to return the SAME instance of kApplication. * Anywhere in the script you could write: * * $application =& kApplication::Instance(); * * or in an object: * * $this->Application =& kApplication::Instance(); * * to get the instance of kApplication. Note that we call the Instance method as STATIC - directly from the class. * To use descendant of standard kApplication class in your project you would need to define APPLICATION_CLASS constant * BEFORE calling kApplication::Instance() for the first time. If APPLICATION_CLASS is not defined the method would * create and return default KernelApplication instance. * * Pattern: Singleton * * @static * @return kApplication * @access public */ public static function &Instance() { static $instance = false; if ( !$instance ) { $class = defined('APPLICATION_CLASS') ? APPLICATION_CLASS : 'kApplication'; $instance = new $class(); } return $instance; } /** * Initializes the Application * * @param string $factory_class * @return bool Was Init actually made now or before * @access public * @see kHTTPQuery * @see Session * @see TemplatesCache */ public function Init($factory_class = 'kFactory') { if ( $this->InitDone ) { return false; } if ( preg_match('/utf-8/i', CHARSET) ) { setlocale(LC_ALL, 'en_US.UTF-8'); mb_internal_encoding('UTF-8'); } $this->isAdmin = kUtil::constOn('ADMIN'); if ( !kUtil::constOn('SKIP_OUT_COMPRESSION') ) { ob_start(); // collect any output from method (other then tags) into buffer } if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) { $this->Debugger->appendMemoryUsage('Application before Init:'); } $this->_logger = new kLogger($this->_logger); $this->Factory = new $factory_class(); $this->registerDefaultClasses(); $vars = kUtil::parseConfig(true); $db_class = isset($vars['Databases']) ? 'kDBLoadBalancer' : ($this->isDebugMode() ? 'kDBConnectionDebug' : 'kDBConnection'); $this->Conn = $this->Factory->makeClass($db_class, Array (SQL_TYPE, Array ($this->_logger, 'handleSQLError'))); $this->Conn->setup($vars); $this->cacheManager = $this->makeClass('kCacheManager'); $this->cacheManager->InitCache(); if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Before UnitConfigReader'); } // init config reader and all managers $this->UnitConfigReader = $this->makeClass('kUnitConfigReader'); $this->UnitConfigReader->scanModules(MODULES_PATH); // will also set RewriteListeners when existing cache is read $this->registerModuleConstants(); if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('After UnitConfigReader'); } define('MOD_REWRITE', $this->ConfigValue('UseModRewrite') && !$this->isAdmin ? 1 : 0); // start processing request $this->HttpQuery = $this->recallObject('HTTPQuery'); $this->HttpQuery->process(); if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed HTTPQuery initial'); } $this->Session = $this->recallObject('Session'); if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed Session'); } $this->Session->ValidateExpired(); // needs mod_rewrite url already parsed to keep user at proper template after session expiration if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed HTTPQuery AfterInit'); } $this->cacheManager->LoadApplicationCache(); $site_timezone = $this->ConfigValue('Config_Site_Time'); if ( $site_timezone ) { date_default_timezone_set($site_timezone); } if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Loaded cache and phrases'); } $this->ValidateLogin(); // must be called before AfterConfigRead, because current user should be available there $this->UnitConfigReader->AfterConfigRead(); // will set RewriteListeners when missing cache is built first time if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendTimestamp('Processed AfterConfigRead'); } if ( $this->GetVar('m_cat_id') === false ) { $this->SetVar('m_cat_id', 0); } if ( !$this->RecallVar('curr_iso') && !(defined('IS_INSTALL') && IS_INSTALL) ) { $this->StoreVar('curr_iso', $this->GetPrimaryCurrency(), true); // true for optional } $visit_id = $this->RecallVar('visit_id'); if ( $visit_id !== false ) { $this->SetVar('visits_id', $visit_id); } if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->profileFinish('kernel4_startup'); } $this->InitDone = true; if ( PHP_SAPI !== 'cli' && !$this->isAdmin ) { $this->HandleEvent(new kEvent('adm:OnStartup')); } return true; } /** * Performs initialization of manager classes, that can be overridden from unit configs * * @return void * @access public * @throws Exception */ public function InitManagers() { if ( $this->InitDone ) { throw new Exception('Duplicate call of ' . __METHOD__, E_USER_ERROR); return; } $this->UrlManager = $this->makeClass('kUrlManager'); $this->EventManager = $this->makeClass('EventManager'); $this->Phrases = $this->makeClass('kPhraseCache'); $this->RegisterDefaultBuildEvents(); } /** * Returns module information. Searches module by requested field * * @param string $field * @param mixed $value * @param string $return_field field value to returns, if not specified, then return all fields * @return Array */ public function findModule($field, $value, $return_field = null) { $found = $module_info = false; foreach ($this->ModuleInfo as $module_info) { if ( strtolower($module_info[$field]) == strtolower($value) ) { $found = true; break; } } if ( $found ) { return isset($return_field) ? $module_info[$return_field] : $module_info; } return false; } /** * Refreshes information about loaded modules * * @return void * @access public */ public function refreshModuleInfo() { if ( defined('IS_INSTALL') && IS_INSTALL && !$this->TableFound('Modules', true) ) { $this->registerModuleConstants(); return; } // use makeClass over recallObject, since used before kApplication initialization during installation $modules_helper = $this->makeClass('ModulesHelper'); /* @var $modules_helper kModulesHelper */ $this->Conn->nextQueryCachable = true; $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'Modules WHERE ' . $modules_helper->getWhereClause() . ' ORDER BY LoadOrder'; $this->ModuleInfo = $this->Conn->Query($sql, 'Name'); $this->registerModuleConstants(); } /** * Checks if passed language id if valid and sets it to primary otherwise * * @return void * @access public */ public function VerifyLanguageId() { /** @var LanguagesItem $lang */ $lang = $this->recallObject('lang.current'); if ( !$lang->isLoaded() || (!$this->isAdmin && !$lang->GetDBField('Enabled')) ) { if ( !defined('IS_INSTALL') ) { $this->ApplicationDie('Unknown or disabled language'); } } } /** * Checks if passed theme id if valid and sets it to primary otherwise * * @return void * @access public */ public function VerifyThemeId() { if ( $this->isAdmin ) { kUtil::safeDefine('THEMES_PATH', '/core/admin_templates'); return; } $path = $this->GetFrontThemePath(); if ( $path === false ) { $this->ApplicationDie('No Primary Theme Selected or Current Theme is Unknown or Disabled'); } kUtil::safeDefine('THEMES_PATH', $path); } /** * Returns relative path to current front-end theme * * @param bool $force * @return string * @access public */ public function GetFrontThemePath($force = false) { static $path = null; if ( !$force && isset($path) ) { return $path; } /** @var ThemeItem $theme */ $theme = $this->recallObject('theme.current'); if ( !$theme->isLoaded() || !$theme->GetDBField('Enabled') ) { return false; } // assign & then return, since it's static variable $path = '/themes/' . $theme->GetDBField('Name'); return $path; } /** * Returns primary front/admin language id * * @param bool $init * @return int * @access public */ public function GetDefaultLanguageId($init = false) { $cache_key = 'primary_language_info[%LangSerial%]'; $language_info = $this->getCache($cache_key); if ( $language_info === false ) { // cache primary language info first $table = $this->getUnitOption('lang', 'TableName'); $id_field = $this->getUnitOption('lang', 'IDField'); $this->Conn->nextQueryCachable = true; $sql = 'SELECT ' . $id_field . ', IF(AdminInterfaceLang, "Admin", "Front") AS LanguageKey FROM ' . $table . ' WHERE (AdminInterfaceLang = 1 OR PrimaryLang = 1) AND (Enabled = 1)'; $language_info = $this->Conn->GetCol($sql, 'LanguageKey'); if ( $language_info !== false ) { $this->setCache($cache_key, $language_info); } } $language_key = ($this->isAdmin && $init) || count($language_info) == 1 ? 'Admin' : 'Front'; if ( array_key_exists($language_key, $language_info) && $language_info[$language_key] > 0 ) { // get from cache return $language_info[$language_key]; } $language_id = $language_info && array_key_exists($language_key, $language_info) ? $language_info[$language_key] : false; if ( !$language_id && defined('IS_INSTALL') && IS_INSTALL ) { $language_id = 1; } return $language_id; } /** * Returns front-end primary theme id (even, when called from admin console) * * @param bool $force_front * @return int * @access public */ public function GetDefaultThemeId($force_front = false) { static $theme_id = 0; if ( $theme_id > 0 ) { return $theme_id; } if ( kUtil::constOn('DBG_FORCE_THEME') ) { $theme_id = DBG_FORCE_THEME; } elseif ( !$force_front && $this->isAdmin ) { $theme_id = 999; } else { $cache_key = 'primary_theme[%ThemeSerial%]'; $theme_id = $this->getCache($cache_key); if ( $theme_id === false ) { $this->Conn->nextQueryCachable = true; $sql = 'SELECT ' . $this->getUnitOption('theme', 'IDField') . ' FROM ' . $this->getUnitOption('theme', 'TableName') . ' WHERE (PrimaryTheme = 1) AND (Enabled = 1)'; $theme_id = $this->Conn->GetOne($sql); if ( $theme_id !== false ) { $this->setCache($cache_key, $theme_id); } } } return $theme_id; } /** * Returns site primary currency ISO code * * @return string * @access public * @todo Move into In-Commerce */ public function GetPrimaryCurrency() { $cache_key = 'primary_currency[%CurrSerial%][%SiteDomainSerial%]:' . $this->siteDomainField('DomainId'); $currency_iso = $this->getCache($cache_key); if ( $currency_iso === false ) { if ( $this->prefixRegistred('curr') ) { $this->Conn->nextQueryCachable = true; $currency_id = $this->siteDomainField('PrimaryCurrencyId'); $sql = 'SELECT ISO FROM ' . $this->getUnitOption('curr', 'TableName') . ' WHERE ' . ($currency_id > 0 ? 'CurrencyId = ' . $currency_id : 'IsPrimary = 1'); $currency_iso = $this->Conn->GetOne($sql); } else { $currency_iso = 'USD'; } $this->setCache($cache_key, $currency_iso); } return $currency_iso; } /** * Returns site domain field. When none of site domains are found false is returned. * * @param string $field * @param bool $formatted * @param string $format * @return mixed * @todo Move into separate module */ public function siteDomainField($field, $formatted = false, $format = null) { if ( $this->isAdmin ) { // don't apply any filtering in administrative console return false; } if ( !$this->siteDomain ) { $this->siteDomain = $this->recallObject('site-domain.current', null, Array ('live_table' => true)); /* @var $site_domain kDBItem */ } if ( $this->siteDomain->isLoaded() ) { return $formatted ? $this->siteDomain->GetField($field, $format) : $this->siteDomain->GetDBField($field); } return false; } /** * Registers default classes such as kDBEventHandler, kUrlManager * * Called automatically while initializing kApplication * * @return void * @access public */ public function RegisterDefaultClasses() { $this->registerClass('kHelper', KERNEL_PATH . '/kbase.php'); $this->registerClass('kMultipleFilter', KERNEL_PATH . '/utility/filters.php'); $this->registerClass('kiCacheable', KERNEL_PATH . '/interfaces/cacheable.php'); $this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php', 'EventManager'); $this->registerClass('kHookManager', KERNEL_PATH . '/managers/hook_manager.php'); $this->registerClass('kScheduledTaskManager', KERNEL_PATH . '/managers/scheduled_task_manager.php'); $this->registerClass('kRequestManager', KERNEL_PATH . '/managers/request_manager.php'); $this->registerClass('kSubscriptionManager', KERNEL_PATH . '/managers/subscription_manager.php'); $this->registerClass('kSubscriptionItem', KERNEL_PATH . '/managers/subscription_manager.php'); $this->registerClass('kUrlManager', KERNEL_PATH . '/managers/url_manager.php'); $this->registerClass('kUrlProcessor', KERNEL_PATH . '/managers/url_processor.php'); $this->registerClass('kPlainUrlProcessor', KERNEL_PATH . '/managers/plain_url_processor.php'); $this->registerClass('kRewriteUrlProcessor', KERNEL_PATH . '/managers/rewrite_url_processor.php'); $this->registerClass('kCacheManager', KERNEL_PATH . '/managers/cache_manager.php'); $this->registerClass('PhrasesCache', KERNEL_PATH . '/languages/phrases_cache.php', 'kPhraseCache'); $this->registerClass('kTempTablesHandler', KERNEL_PATH . '/utility/temp_handler.php'); $this->registerClass('kValidator', KERNEL_PATH . '/utility/validator.php'); $this->registerClass('kOpenerStack', KERNEL_PATH . '/utility/opener_stack.php'); $this->registerClass('kLogger', KERNEL_PATH . '/utility/logger.php'); $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php'); $this->registerClass('PasswordHash', KERNEL_PATH . '/utility/php_pass.php'); // Params class descendants $this->registerClass('kArray', KERNEL_PATH . '/utility/params.php'); $this->registerClass('Params', KERNEL_PATH . '/utility/params.php'); $this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions'); $this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php', 'kCache', 'Params'); $this->registerClass('kHTTPQuery', KERNEL_PATH . '/utility/http_query.php', 'HTTPQuery'); // session $this->registerClass('Session', KERNEL_PATH . '/session/session.php'); $this->registerClass('SessionStorage', KERNEL_PATH . '/session/session_storage.php'); $this->registerClass('InpSession', KERNEL_PATH . '/session/inp_session.php', 'Session'); $this->registerClass('InpSessionStorage', KERNEL_PATH . '/session/inp_session_storage.php', 'SessionStorage'); // template parser $this->registerClass('kTagProcessor', KERNEL_PATH . '/processors/tag_processor.php'); $this->registerClass('kMainTagProcessor', KERNEL_PATH . '/processors/main_processor.php', 'm_TagProcessor'); $this->registerClass('kDBTagProcessor', KERNEL_PATH . '/db/db_tag_processor.php'); $this->registerClass('kCatDBTagProcessor', KERNEL_PATH . '/db/cat_tag_processor.php'); $this->registerClass('NParser', KERNEL_PATH . '/nparser/nparser.php'); $this->registerClass('TemplatesCache', KERNEL_PATH . '/nparser/template_cache.php'); // database $this->registerClass('kDBConnection', KERNEL_PATH . '/db/db_connection.php'); $this->registerClass('kDBConnectionDebug', KERNEL_PATH . '/db/db_connection.php'); $this->registerClass('kDBLoadBalancer', KERNEL_PATH . '/db/db_load_balancer.php'); $this->registerClass('kDBItem', KERNEL_PATH . '/db/dbitem.php'); $this->registerClass('kCatDBItem', KERNEL_PATH . '/db/cat_dbitem.php'); $this->registerClass('kDBList', KERNEL_PATH . '/db/dblist.php'); $this->registerClass('kCatDBList', KERNEL_PATH . '/db/cat_dblist.php'); $this->registerClass('kDBEventHandler', KERNEL_PATH . '/db/db_event_handler.php'); $this->registerClass('kCatDBEventHandler', KERNEL_PATH . '/db/cat_event_handler.php'); // email sending $this->registerClass('kEmail', KERNEL_PATH . '/utility/email.php'); $this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender'); $this->registerClass('kSocket', KERNEL_PATH . '/utility/socket.php', 'Socket'); // do not move to config - this helper is used before configs are read $this->registerClass('kModulesHelper', KERNEL_PATH . self::MODULE_HELPER_PATH, 'ModulesHelper'); } /** * Registers default build events * * @return void */ public function RegisterDefaultBuildEvents() { $this->EventManager->registerBuildEvent('kTempTablesHandler', 'OnTempHandlerBuild'); } /** * Returns cached category information by given cache name. All given category * information is recached, when at least one of 4 caches is missing. * * @param int $category_id * @param string $name cache name = {filenames, category_designs, category_tree} * @return string * @access public */ public function getCategoryCache($category_id, $name) { return $this->cacheManager->getCategoryCache($category_id, $name); } /** * Returns caching type (none, memory, temporary) * * @param int $caching_type * @return bool * @access public */ public function isCachingType($caching_type) { return $this->cacheManager->isCachingType($caching_type); } /** * Increments serial based on prefix and it's ID (optional) * * @param string $prefix * @param int $id ID (value of IDField) or ForeignKeyField:ID * @param bool $increment * @return string * @access public */ public function incrementCacheSerial($prefix, $id = null, $increment = true) { return $this->cacheManager->incrementCacheSerial($prefix, $id, $increment); } /** * Returns cached $key value from cache named $cache_name * * @param int $key key name from cache * @param bool $store_locally store data locally after retrieved * @param int $max_rebuild_seconds * @return mixed * @access public */ public function getCache($key, $store_locally = true, $max_rebuild_seconds = 0) { return $this->cacheManager->getCache($key, $store_locally, $max_rebuild_seconds); } /** * Stores new $value in cache with $key name * * @param int $key key name to add to cache * @param mixed $value value of cached record * @param int $expiration when value expires (0 - doesn't expire) * @return bool * @access public */ public function setCache($key, $value, $expiration = 0) { return $this->cacheManager->setCache($key, $value, $expiration); } /** * Stores new $value in cache with $key name (only if it's not there) * * @param int $key key name to add to cache * @param mixed $value value of cached record * @param int $expiration when value expires (0 - doesn't expire) * @return bool * @access public */ public function addCache($key, $value, $expiration = 0) { return $this->cacheManager->addCache($key, $value, $expiration); } /** * Sets rebuilding mode for given cache * * @param string $name * @param int $mode * @param int $max_rebuilding_time * @return bool * @access public */ public function rebuildCache($name, $mode = null, $max_rebuilding_time = 0) { return $this->cacheManager->rebuildCache($name, $mode, $max_rebuilding_time); } /** * Deletes key from cache * * @param string $key * @return void * @access public */ public function deleteCache($key) { $this->cacheManager->deleteCache($key); } /** * Reset's all memory cache at once * * @return void * @access public */ public function resetCache() { $this->cacheManager->resetCache(); } /** * Returns value from database cache * * @param string $name key name * @param int $max_rebuild_seconds * @return mixed * @access public */ public function getDBCache($name, $max_rebuild_seconds = 0) { return $this->cacheManager->getDBCache($name, $max_rebuild_seconds); } /** * Sets value to database cache * * @param string $name * @param mixed $value * @param int|bool $expiration * @return void * @access public */ public function setDBCache($name, $value, $expiration = false) { $this->cacheManager->setDBCache($name, $value, $expiration); } /** * Sets rebuilding mode for given cache * * @param string $name * @param int $mode * @param int $max_rebuilding_time * @return bool * @access public */ public function rebuildDBCache($name, $mode = null, $max_rebuilding_time = 0) { return $this->cacheManager->rebuildDBCache($name, $mode, $max_rebuilding_time); } /** * Deletes key from database cache * * @param string $name * @return void * @access public */ public function deleteDBCache($name) { $this->cacheManager->deleteDBCache($name); } /** * Registers each module specific constants if any found * * @return bool * @access protected */ protected function registerModuleConstants() { if ( file_exists(KERNEL_PATH . '/constants.php') ) { kUtil::includeOnce(KERNEL_PATH . '/constants.php'); } if ( !$this->ModuleInfo ) { return false; } foreach ($this->ModuleInfo as $module_info) { $constants_file = FULL_PATH . '/' . $module_info['Path'] . 'constants.php'; if ( file_exists($constants_file) ) { kUtil::includeOnce($constants_file); } } return true; } /** * Performs redirect to hard maintenance template * * @return void * @access public */ public function redirectToMaintenance() { $maintenance_page = WRITEBALE_BASE . '/maintenance.html'; $query_string = ''; // $this->isAdmin ? '' : '?next_template=' . kUtil::escape($_SERVER['REQUEST_URI'], kUtil::ESCAPE_URL); if ( file_exists(FULL_PATH . $maintenance_page) ) { header('Location: ' . BASE_PATH . $maintenance_page . $query_string); exit; } } /** * Actually runs the parser against current template and stores parsing result * * This method gets 't' variable passed to the script, loads the template given in 't' variable and * parses it. The result is store in {@link $this->HTML} property. * * @return void * @access public */ public function Run() { // process maintenance mode redirect: begin $maintenance_mode = $this->getMaintenanceMode(); if ( $maintenance_mode == MaintenanceMode::HARD ) { $this->redirectToMaintenance(); } elseif ( $maintenance_mode == MaintenanceMode::SOFT ) { $maintenance_template = $this->isAdmin ? 'login' : $this->ConfigValue('SoftMaintenanceTemplate'); if ( $this->GetVar('t') != $maintenance_template ) { $redirect_params = Array (); if ( !$this->isAdmin ) { $redirect_params['next_template'] = $_SERVER['REQUEST_URI']; } $this->Redirect($maintenance_template, $redirect_params); } } // process maintenance mode redirect: end if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) { $this->Debugger->appendMemoryUsage('Application before Run:'); } if ( $this->isAdminUser ) { // for permission checking in events & templates $this->LinkVar('module'); // for common configuration templates $this->LinkVar('module_key'); // for common search templates $this->LinkVar('section'); // for common configuration templates if ( $this->GetVar('m_opener') == 'p' ) { $this->LinkVar('main_prefix'); // window prefix, that opened selector $this->LinkVar('dst_field'); // field to set value choosed in selector } if ( $this->GetVar('ajax') == 'yes' && !$this->GetVar('debug_ajax') ) { // hide debug output from ajax requests automatically kUtil::safeDefine('DBG_SKIP_REPORTING', 1); // safeDefine, because debugger also defines it } } elseif ( $this->GetVar('admin') ) { $admin_session = $this->recallObject('Session.admin'); /* @var $admin_session Session */ // store Admin Console User's ID to Front-End's session for cross-session permission checks $this->StoreVar('admin_user_id', (int)$admin_session->RecallVar('user_id')); if ( $this->CheckAdminPermission('CATEGORY.MODIFY', 0, $this->getBaseCategory()) ) { // user can edit cms blocks (when viewing front-end through admin's frame) $editing_mode = $this->GetVar('editing_mode'); define('EDITING_MODE', $editing_mode ? $editing_mode : EDITING_MODE_BROWSE); } } kUtil::safeDefine('EDITING_MODE', ''); // user can't edit anything $this->Phrases->setPhraseEditing(); $this->EventManager->ProcessRequest(); $this->InitParser(); $t = $this->GetVar('render_template', $this->GetVar('t')); if ( !$this->TemplatesCache->TemplateExists($t) && !$this->isAdmin ) { $cms_handler = $this->recallObject('st_EventHandler'); /* @var $cms_handler CategoriesEventHandler */ $t = ltrim($cms_handler->GetDesignTemplate(), '/'); if ( defined('DEBUG_MODE') && $this->isDebugMode() ) { $this->Debugger->appendHTML('Design Template: ' . $t . '; CategoryID: ' . $this->GetVar('m_cat_id')); } } /*else { $cms_handler->SetCatByTemplate(); }*/ if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) { $this->Debugger->appendMemoryUsage('Application before Parsing:'); } $this->HTML = $this->Parser->Run($t); if ( defined('DEBUG_MODE') && $this->isDebugMode() && kUtil::constOn('DBG_PROFILE_MEMORY') ) { $this->Debugger->appendMemoryUsage('Application after Parsing:'); } } /** * Replaces current rendered template with given one. * * @param string|null $template Template. * * @return void */ public function QuickRun($template) { /** @var kThemesHelper $themes_helper */ $themes_helper = $this->recallObject('ThemesHelper'); // Set Web Request variables to affect link building on template itself. $this->SetVar('t', $template); $this->SetVar('m_cat_id', $themes_helper->getPageByTemplate($template)); $this->SetVar('passed', 'm'); // Replace current page content with given template. $this->InitParser(); $this->Parser->Clear(); $this->HTML = $this->Parser->Run($template); } /** * Performs template parser/cache initialization * * @param bool|string $theme_name * @return void * @access public */ public function InitParser($theme_name = false) { if ( !is_object($this->Parser) ) { $this->Parser = $this->recallObject('NParser'); $this->TemplatesCache = $this->recallObject('TemplatesCache'); } $this->TemplatesCache->forceThemeName = $theme_name; } /** * Send the parser results to browser * * Actually send everything stored in {@link $this->HTML}, to the browser by echoing it. * * @return void * @access public */ public function Done() { $this->HandleEvent(new kEvent('adm:OnBeforeShutdown')); $debug_mode = defined('DEBUG_MODE') && $this->isDebugMode(); if ( $debug_mode ) { if ( kUtil::constOn('DBG_PROFILE_MEMORY') ) { $this->Debugger->appendMemoryUsage('Application before Done:'); } $this->Session->SaveData(); // adds session data to debugger report $this->HTML = ob_get_clean() . $this->HTML . $this->Debugger->printReport(true); } else { // send "Set-Cookie" header before any output is made $this->Session->SetSession(); $this->HTML = ob_get_clean() . $this->HTML; } $this->_outputPage(); $this->cacheManager->UpdateApplicationCache(); if ( !$debug_mode ) { $this->Session->SaveData(); } $this->EventManager->runScheduledTasks(); if ( defined('DBG_CAPTURE_STATISTICS') && DBG_CAPTURE_STATISTICS && !$this->isAdmin ) { $this->_storeStatistics(); } } /** * Outputs generated page content to end-user * * @return void * @access protected */ protected function _outputPage() { $this->setContentType(); ob_start(); if ( $this->UseOutputCompression() ) { $compression_level = $this->ConfigValue('OutputCompressionLevel'); if ( !$compression_level || $compression_level < 0 || $compression_level > 9 ) { $compression_level = 7; } header('Content-Encoding: gzip'); echo gzencode($this->HTML, $compression_level); } else { // when gzip compression not used connection won't be closed early! echo $this->HTML; } // send headers to tell the browser to close the connection header('Content-Length: ' . ob_get_length()); header('Connection: close'); // flush all output ob_end_flush(); if ( ob_get_level() ) { ob_flush(); } flush(); // close current session if ( session_id() ) { session_write_close(); } } /** * Stores script execution statistics to database * * @return void * @access protected */ protected function _storeStatistics() { global $start; $script_time = microtime(true) - $start; $query_statistics = $this->Conn->getQueryStatistics(); // time & count $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'StatisticsCapture WHERE TemplateName = ' . $this->Conn->qstr($this->GetVar('t')); $data = $this->Conn->GetRow($sql); if ( $data ) { $this->_updateAverageStatistics($data, 'ScriptTime', $script_time); $this->_updateAverageStatistics($data, 'SqlTime', $query_statistics['time']); $this->_updateAverageStatistics($data, 'SqlCount', $query_statistics['count']); $data['Hits']++; $data['LastHit'] = adodb_mktime(); $this->Conn->doUpdate($data, TABLE_PREFIX . 'StatisticsCapture', 'StatisticsId = ' . $data['StatisticsId']); } else { $data['ScriptTimeMin'] = $data['ScriptTimeAvg'] = $data['ScriptTimeMax'] = $script_time; $data['SqlTimeMin'] = $data['SqlTimeAvg'] = $data['SqlTimeMax'] = $query_statistics['time']; $data['SqlCountMin'] = $data['SqlCountAvg'] = $data['SqlCountMax'] = $query_statistics['count']; $data['TemplateName'] = $this->GetVar('t'); $data['Hits'] = 1; $data['LastHit'] = adodb_mktime(); $this->Conn->doInsert($data, TABLE_PREFIX . 'StatisticsCapture'); } } /** * Calculates average time for statistics * * @param Array $data * @param string $field_prefix * @param float $current_value * @return void * @access protected */ protected function _updateAverageStatistics(&$data, $field_prefix, $current_value) { $data[$field_prefix . 'Avg'] = (($data['Hits'] * $data[$field_prefix . 'Avg']) + $current_value) / ($data['Hits'] + 1); if ( $current_value < $data[$field_prefix . 'Min'] ) { $data[$field_prefix . 'Min'] = $current_value; } if ( $current_value > $data[$field_prefix . 'Max'] ) { $data[$field_prefix . 'Max'] = $current_value; } } /** * Remembers slow query SQL and execution time into log * * @param string $slow_sql * @param int $time * @return void * @access public */ public function logSlowQuery($slow_sql, $time) { $query_crc = kUtil::crc32($slow_sql); $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'SlowSqlCapture WHERE QueryCrc = ' . $query_crc; $data = $this->Conn->Query($sql, null, true); if ( $data ) { $this->_updateAverageStatistics($data, 'Time', $time); $template_names = explode(',', $data['TemplateNames']); array_push($template_names, $this->GetVar('t')); $data['TemplateNames'] = implode(',', array_unique($template_names)); $data['Hits']++; $data['LastHit'] = adodb_mktime(); $this->Conn->doUpdate($data, TABLE_PREFIX . 'SlowSqlCapture', 'CaptureId = ' . $data['CaptureId']); } else { $data['TimeMin'] = $data['TimeAvg'] = $data['TimeMax'] = $time; $data['SqlQuery'] = $slow_sql; $data['QueryCrc'] = $query_crc; $data['TemplateNames'] = $this->GetVar('t'); $data['Hits'] = 1; $data['LastHit'] = adodb_mktime(); $this->Conn->doInsert($data, TABLE_PREFIX . 'SlowSqlCapture'); } } /** * Checks if output compression options is available * * @return bool * @access protected */ protected function UseOutputCompression() { if ( kUtil::constOn('IS_INSTALL') || kUtil::constOn('DBG_ZEND_PRESENT') || kUtil::constOn('SKIP_OUT_COMPRESSION') ) { return false; } $accept_encoding = isset($_SERVER['HTTP_ACCEPT_ENCODING']) ? $_SERVER['HTTP_ACCEPT_ENCODING'] : ''; return $this->ConfigValue('UseOutputCompression') && function_exists('gzencode') && strstr($accept_encoding, 'gzip'); } // Facade /** * Returns current session id (SID) * * @return int * @access public */ public function GetSID() { $session = $this->recallObject('Session'); /* @var $session Session */ return $session->GetID(); } /** * Destroys current session * * @return void * @access public * @see UserHelper::logoutUser() */ public function DestroySession() { $session = $this->recallObject('Session'); /* @var $session Session */ $session->Destroy(); } /** * Returns variable passed to the script as GET/POST/COOKIE * * @param string $name Name of variable to retrieve * @param mixed $default default value returned in case if variable not present * @return mixed * @access public */ public function GetVar($name, $default = false) { return isset($this->HttpQuery->_Params[$name]) ? $this->HttpQuery->_Params[$name] : $default; } /** * Removes forceful escaping done to the variable upon Front-End submission. * * @param string|array $value Value. * * @return string|array * @see kHttpQuery::StripSlashes * @todo Temporary method for marking problematic places to take care of, when forceful escaping will be removed. */ public function unescapeRequestVariable($value) { return $this->HttpQuery->unescapeRequestVariable($value); } /** * Returns variable passed to the script as $type * * @param string $name Name of variable to retrieve * @param string $type Get/Post/Cookie * @param mixed $default default value returned in case if variable not present * @return mixed * @access public */ public function GetVarDirect($name, $type, $default = false) { // $type = ucfirst($type); $array = $this->HttpQuery->$type; return isset($array[$name]) ? $array[$name] : $default; } /** * Returns ALL variables passed to the script as GET/POST/COOKIE * * @return Array * @access public * @deprecated */ public function GetVars() { return $this->HttpQuery->GetParams(); } /** * Set the variable 'as it was passed to the script through GET/POST/COOKIE' * * This could be useful to set the variable when you know that * other objects would relay on variable passed from GET/POST/COOKIE * or you could use SetVar() / GetVar() pairs to pass the values between different objects.
* * @param string $var Variable name to set * @param mixed $val Variable value * @return void * @access public */ public function SetVar($var,$val) { $this->HttpQuery->Set($var, $val); } /** * Deletes kHTTPQuery variable * * @param string $var * @return void * @todo Think about method name */ public function DeleteVar($var) { $this->HttpQuery->Remove($var); } /** * Deletes Session variable * * @param string $var * @return void * @access public */ public function RemoveVar($var) { $this->Session->RemoveVar($var); } /** * Removes variable from persistent session * * @param string $var * @return void * @access public */ public function RemovePersistentVar($var) { $this->Session->RemovePersistentVar($var); } /** * Restores Session variable to it's db version * * @param string $var * @return void * @access public */ public function RestoreVar($var) { $this->Session->RestoreVar($var); } /** * Returns session variable value * * Return value of $var variable stored in Session. An optional default value could be passed as second parameter. * * @param string $var Variable name * @param mixed $default Default value to return if no $var variable found in session * @return mixed * @access public * @see Session::RecallVar() */ public function RecallVar($var,$default=false) { return $this->Session->RecallVar($var,$default); } /** * Returns variable value from persistent session * * @param string $var * @param mixed $default * @return mixed * @access public * @see Session::RecallPersistentVar() */ public function RecallPersistentVar($var, $default = false) { return $this->Session->RecallPersistentVar($var, $default); } /** * Stores variable $val in session under name $var * * Use this method to store variable in session. Later this variable could be recalled. * * @param string $var Variable name * @param mixed $val Variable value * @param bool $optional * @return void * @access public * @see kApplication::RecallVar() */ public function StoreVar($var, $val, $optional = false) { $session = $this->recallObject('Session'); /* @var $session Session */ $this->Session->StoreVar($var, $val, $optional); } /** * Stores variable to persistent session * * @param string $var * @param mixed $val * @param bool $optional * @return void * @access public */ public function StorePersistentVar($var, $val, $optional = false) { $this->Session->StorePersistentVar($var, $val, $optional); } /** * Stores default value for session variable * * @param string $var * @param string $val * @param bool $optional * @return void * @access public * @see Session::RecallVar() * @see Session::StoreVar() */ public function StoreVarDefault($var, $val, $optional = false) { $session = $this->recallObject('Session'); /* @var $session Session */ $this->Session->StoreVarDefault($var, $val, $optional); } /** * Links HTTP Query variable with session variable * * If variable $var is passed in HTTP Query it is stored in session for later use. If it's not passed it's recalled from session. * This method could be used for making sure that GetVar will return query or session value for given * variable, when query variable should overwrite session (and be stored there for later use).
* This could be used for passing item's ID into popup with multiple tab - * in popup script you just need to call LinkVar('id', 'current_id') before first use of GetVar('id'). * After that you can be sure that GetVar('id') will return passed id or id passed earlier and stored in session * * @param string $var HTTP Query (GPC) variable name * @param mixed $ses_var Session variable name * @param mixed $default Default variable value * @param bool $optional * @return void * @access public */ public function LinkVar($var, $ses_var = null, $default = '', $optional = false) { if ( !isset($ses_var) ) { $ses_var = $var; } if ( $this->GetVar($var) !== false ) { $this->StoreVar($ses_var, $this->GetVar($var), $optional); } else { $this->SetVar($var, $this->RecallVar($ses_var, $default)); } } /** * Returns variable from HTTP Query, or from session if not passed in HTTP Query * * The same as LinkVar, but also returns the variable value taken from HTTP Query if passed, or from session if not passed. * Returns the default value if variable does not exist in session and was not passed in HTTP Query * * @param string $var HTTP Query (GPC) variable name * @param mixed $ses_var Session variable name * @param mixed $default Default variable value * @return mixed * @access public * @see LinkVar */ public function GetLinkedVar($var, $ses_var = null, $default = '') { $this->LinkVar($var, $ses_var, $default); return $this->GetVar($var); } /** * Renders given tag and returns it's output * * @param string $prefix * @param string $tag * @param Array $params * @return mixed * @access public * @see kApplication::InitParser() */ public function ProcessParsedTag($prefix, $tag, $params) { $processor = $this->Parser->GetProcessor($prefix); /* @var $processor kDBTagProcessor */ return $processor->ProcessParsedTag($tag, $params, $prefix); } /** * Return object of IDBConnection interface * * Return object of IDBConnection interface already connected to the project database, configurable in config.php * * @return IDBConnection * @access public */ public function &GetADODBConnection() { return $this->Conn; } /** * Allows to parse given block name or include template * * @param Array $params Parameters to pass to block. Reserved parameter "name" used to specify block name. * @param bool $pass_params Forces to pass current parser params to this block/template. Use with caution, because you can accidentally pass "block_no_data" parameter. * @param bool $as_template * @return string * @access public */ public function ParseBlock($params, $pass_params = false, $as_template = false) { if ( substr($params['name'], 0, 5) == 'html:' ) { return substr($params['name'], 5); } return $this->Parser->ParseBlock($params, $pass_params, $as_template); } /** * Checks, that we have given block defined * * @param string $name * @return bool * @access public */ public function ParserBlockFound($name) { return $this->Parser->blockFound($name); } /** * Allows to include template with a given name and given parameters * * @param Array $params Parameters to pass to template. Reserved parameter "name" used to specify template name. * @return string * @access public */ public function IncludeTemplate($params) { return $this->Parser->IncludeTemplate($params, isset($params['is_silent']) ? 1 : 0); } /** * Return href for template * * @param string $t Template path * @param string $prefix index.php prefix - could be blank, 'admin' * @param Array $params * @param string $index_file * @return string */ public function HREF($t, $prefix = '', $params = Array (), $index_file = null) { return $this->UrlManager->HREF($t, $prefix, $params, $index_file); } /** * Returns theme template filename and it's corresponding page_id based on given seo template * * @param string $seo_template * @return string * @access public */ public function getPhysicalTemplate($seo_template) { return $this->UrlManager->getPhysicalTemplate($seo_template); } /** * Returns template name, that corresponds with given virtual (not physical) page id * * @param int $page_id * @return string|bool * @access public */ public function getVirtualPageTemplate($page_id) { return $this->UrlManager->getVirtualPageTemplate($page_id); } /** * Returns section template for given physical/virtual template * * @param string $template * @param int $theme_id * @return string * @access public */ public function getSectionTemplate($template, $theme_id = null) { return $this->UrlManager->getSectionTemplate($template, $theme_id); } /** * Returns variables with values that should be passed through with this link + variable list * * @param Array $params * @return Array * @access public */ public function getPassThroughVariables(&$params) { return $this->UrlManager->getPassThroughVariables($params); } /** * Builds url * * @param string $t * @param Array $params * @param string $pass * @param bool $pass_events * @param bool $env_var * @return string * @access public */ public function BuildEnv($t, $params, $pass = 'all', $pass_events = false, $env_var = true) { return $this->UrlManager->plain->build($t, $params, $pass, $pass_events, $env_var); } /** * Process QueryString only, create * events, ids, based on config * set template name and sid in * desired application variables. * * @param string $env_var environment string value * @param string $pass_name * @return Array * @access public */ public function processQueryString($env_var, $pass_name = 'passed') { return $this->UrlManager->plain->parse($env_var, $pass_name); } /** * Parses rewrite url and returns parsed variables * * @param string $url * @param string $pass_name * @return Array * @access public */ public function parseRewriteUrl($url, $pass_name = 'passed') { return $this->UrlManager->rewrite->parse($url, $pass_name); } /** * Returns base part of all urls, build on website * * @param string $prefix * @param bool $ssl * @param bool $add_port * @return string * @access public */ public function BaseURL($prefix = '', $ssl = null, $add_port = true) { if ( $ssl === null ) { // stay on same encryption level return PROTOCOL . SERVER_NAME . ($add_port && defined('PORT') ? ':' . PORT : '') . BASE_PATH . $prefix . '/'; } if ( $ssl ) { // going from http:// to https:// $base_url = $this->isAdmin ? $this->ConfigValue('AdminSSL_URL') : false; if ( !$base_url ) { $ssl_url = $this->siteDomainField('SSLUrl'); $base_url = $ssl_url !== false ? $ssl_url : $this->ConfigValue('SSL_URL'); } return rtrim($base_url, '/') . $prefix . '/'; } // going from https:// to http:// $domain = $this->siteDomainField('DomainName'); if ( $domain === false ) { $domain = DOMAIN; } return 'http://' . $domain . ($add_port && defined('PORT') ? ':' . PORT : '') . BASE_PATH . $prefix . '/'; } /** * Redirects user to url, that's build based on given parameters * * @param string $t * @param Array $params * @param string $prefix * @param string $index_file * @return void * @access public */ public function Redirect($t = '', $params = Array(), $prefix = '', $index_file = null) { $js_redirect = getArrayValue($params, 'js_redirect'); if ( $t == '' || $t === true ) { $t = $this->GetVar('t'); } // pass prefixes and special from previous url if ( array_key_exists('js_redirect', $params) ) { unset($params['js_redirect']); } // allows to send custom responce code along with redirect header if ( array_key_exists('response_code', $params) ) { $response_code = (int)$params['response_code']; unset($params['response_code']); } else { $response_code = 302; // Found } if ( !array_key_exists('pass', $params) ) { $params['pass'] = 'all'; } if ( $this->GetVar('ajax') == 'yes' && $t == $this->GetVar('t') ) { // redirects to the same template as current $params['ajax'] = 'yes'; } $location = $this->HREF($t, $prefix, $params, $index_file); if ( $this->isDebugMode() && (kUtil::constOn('DBG_REDIRECT') || (kUtil::constOn('DBG_RAISE_ON_WARNINGS') && $this->Debugger->WarningCount)) ) { $this->Debugger->appendTrace(); echo 'Debug output above !!!
' . "\n"; if ( array_key_exists('HTTP_REFERER', $_SERVER) ) { echo 'Referer: ' . kUtil::escape($_SERVER['HTTP_REFERER'], kUtil::ESCAPE_HTML) . '
' . "\n"; } echo "Proceed to redirect: {$location}
\n"; } else { if ( $js_redirect ) { // show "redirect" template instead of redirecting, // because "Set-Cookie" header won't work, when "Location" // header is used later $this->SetVar('t', 'redirect'); $this->SetVar('redirect_to', $location); // make all additional parameters available on "redirect" template too foreach ($params as $name => $value) { $this->SetVar($name, $value); } return; } else { if ( $this->GetVar('ajax') == 'yes' && ($t != $this->GetVar('t') || !$this->isSOPSafe($location, $t)) ) { // redirection to other then current template during ajax request OR SOP violation kUtil::safeDefine('DBG_SKIP_REPORTING', 1); echo '#redirect#' . $location; } elseif ( headers_sent() != '' ) { // some output occurred -> redirect using javascript echo ''; } else { // no output before -> redirect using HTTP header // header('HTTP/1.1 302 Found'); header('Location: ' . $location, true, $response_code); } } } // session expiration is called from session initialization, // that's why $this->Session may be not defined here $session = $this->recallObject('Session'); /* @var $session Session */ if ( $this->InitDone ) { // if redirect happened in the middle of application initialization don't call event, // that presumes that application was successfully initialized $this->HandleEvent(new kEvent('adm:OnBeforeShutdown')); } $session->SaveData(); ob_end_flush(); exit; } /** * Determines if real redirect should be made within AJAX request. * * @param string $url Location. * @param string $template Template. * * @return boolean * @link http://en.wikipedia.org/wiki/Same-origin_policy */ protected function isSOPSafe($url, $template) { $parsed_url = parse_url($url); if ( $parsed_url['scheme'] . '://' != PROTOCOL ) { return false; } if ( $parsed_url['host'] != SERVER_NAME ) { return false; } if ( defined('PORT') && isset($parsed_url['port']) && $parsed_url['port'] != PORT ) { return false; } return true; } /** * Returns translation of given label * * @param string $label * @param bool $allow_editing return translation link, when translation is missing on current language * @param bool $use_admin use current Admin Console language to translate phrase * @return string * @access public */ public function Phrase($label, $allow_editing = true, $use_admin = false) { return $this->Phrases->GetPhrase($label, $allow_editing, $use_admin); } /** * Replace language tags in exclamation marks found in text * * @param string $text * @param bool $force_escape force escaping, not escaping of resulting string * @return string * @access public */ public function ReplaceLanguageTags($text, $force_escape = null) { return $this->Phrases->ReplaceLanguageTags($text, $force_escape); } /** * Checks if user is logged in, and creates * user object if so. User object can be recalled * later using "u.current" prefix_special. Also you may * get user id by getting "u.current_id" variable. * * @return void * @access protected */ protected function ValidateLogin() { $session = $this->recallObject('Session'); /* @var $session Session */ $user_id = $session->GetField('PortalUserId'); if ( !$user_id && $user_id != USER_ROOT ) { $user_id = USER_GUEST; } $this->SetVar('u.current_id', $user_id); if ( !$this->isAdmin ) { // needed for "profile edit", "registration" forms ON FRONT ONLY $this->SetVar('u_id', $user_id); } $this->StoreVar('user_id', $user_id, $user_id == USER_GUEST); // storing Guest user_id (-2) is optional $this->isAdminUser = $this->isAdmin && $this->LoggedIn(); if ( $this->GetVar('expired') == 1 ) { // this parameter is set only from admin $user = $this->recallObject('u.login-admin', null, Array ('form_name' => 'login')); /* @var $user UsersItem */ $user->SetError('UserLogin', 'session_expired', 'la_text_sess_expired'); } - if ( ($user_id != USER_GUEST) && defined('DBG_REQUREST_LOG') && DBG_REQUREST_LOG ) { - $this->HttpQuery->writeRequestLog(DBG_REQUREST_LOG); - } + $this->HandleEvent(new kEvent('adm:OnLogHttpRequest')); if ( $user_id != USER_GUEST ) { // normal users + root $this->LoadPersistentVars(); } $user_timezone = $this->Session->GetField('TimeZone'); if ( $user_timezone ) { date_default_timezone_set($user_timezone); } } /** * Loads current user persistent session data * * @return void * @access public */ public function LoadPersistentVars() { $this->Session->LoadPersistentVars(); } /** * Returns configuration option value by name * * @param string $name * @return string * @access public */ public function ConfigValue($name) { return $this->cacheManager->ConfigValue($name); } /** * Changes value of individual configuration variable (+resets cache, when needed) * * @param string $name * @param string $value * @param bool $local_cache_only * @return string * @access public */ public function SetConfigValue($name, $value, $local_cache_only = false) { return $this->cacheManager->SetConfigValue($name, $value, $local_cache_only); } /** * Allows to process any type of event * * @param kEvent $event * @param Array $params * @param Array $specific_params * @return void * @access public */ public function HandleEvent($event, $params = null, $specific_params = null) { if ( isset($params) ) { $event = new kEvent($params, $specific_params); } $this->EventManager->HandleEvent($event); } /** * Notifies event subscribers, that event has occured * * @param kEvent $event * @return void */ public function notifyEventSubscribers(kEvent $event) { $this->EventManager->notifySubscribers($event); } /** * Allows to process any type of event * * @param kEvent $event * @return bool * @access public */ public function eventImplemented(kEvent $event) { return $this->EventManager->eventImplemented($event); } /** * Registers new class in the factory * * @param string $real_class Real name of class as in class declaration * @param string $file Filename in what $real_class is declared * @param string $pseudo_class Name under this class object will be accessed using getObject method * @return void * @access public */ public function registerClass($real_class, $file, $pseudo_class = null) { $this->Factory->registerClass($real_class, $file, $pseudo_class); } /** * Unregisters existing class from factory * * @param string $real_class Real name of class as in class declaration * @param string $pseudo_class Name under this class object is accessed using getObject method * @return void * @access public */ public function unregisterClass($real_class, $pseudo_class = null) { $this->Factory->unregisterClass($real_class, $pseudo_class); } /** * Finds the absolute path to the file where the class is defined. * * @param string $class The name of the class. * * @return string|false */ public function findClassFile($class) { return $this->Factory->findClassFile($class); } /** * Add new scheduled task * * @param string $short_name name to be used to store last maintenance run info * @param string $event_string * @param int $run_schedule run schedule like for Cron * @param int $status * @access public */ public function registerScheduledTask($short_name, $event_string, $run_schedule, $status = STATUS_ACTIVE) { $this->EventManager->registerScheduledTask($short_name, $event_string, $run_schedule, $status); } /** * Registers Hook from subprefix event to master prefix event * * Pattern: Observer * * @param string $hook_event * @param string $do_event * @param int $mode * @param bool $conditional * @access public */ public function registerHook($hook_event, $do_event, $mode = hAFTER, $conditional = false) { $this->EventManager->registerHook($hook_event, $do_event, $mode, $conditional); } /** * Registers build event for given pseudo class * * @param string $pseudo_class * @param string $event_name * @access public */ public function registerBuildEvent($pseudo_class, $event_name) { $this->EventManager->registerBuildEvent($pseudo_class, $event_name); } /** * Allows one TagProcessor tag act as other TagProcessor tag * * @param Array $tag_info * @return void * @access public */ public function registerAggregateTag($tag_info) { $aggregator = $this->recallObject('TagsAggregator', 'kArray'); /* @var $aggregator kArray */ $tag_data = Array ( $tag_info['LocalPrefix'], $tag_info['LocalTagName'], getArrayValue($tag_info, 'LocalSpecial') ); $aggregator->SetArrayValue($tag_info['AggregateTo'], $tag_info['AggregatedTagName'], $tag_data); } /** * Returns object using params specified, creates it if is required * * @param string $name * @param string $pseudo_class * @param Array $event_params * @param Array $arguments * @return kBase */ public function recallObject($name, $pseudo_class = null, array $event_params = array(), array $arguments = array()) { /*if ( !$this->hasObject($name) && $this->isDebugMode() && ($name == '_prefix_here_') ) { // first time, when object with "_prefix_here_" prefix is accessed $this->Debugger->appendTrace(); }*/ return $this->Factory->getObject($name, $pseudo_class, $event_params, $arguments); } /** * Returns tag processor for prefix specified * * @param string $prefix * @return kDBTagProcessor * @access public */ public function recallTagProcessor($prefix) { $this->InitParser(); // because kDBTagProcesor is in NParser dependencies return $this->recallObject($prefix . '_TagProcessor'); } /** * Checks if object with prefix passes was already created in factory * * @param string $name object pseudo_class, prefix * @return bool * @access public */ public function hasObject($name) { return $this->Factory->hasObject($name); } /** * Removes object from storage by given name * * @param string $name Object's name in the Storage * @return void * @access public */ public function removeObject($name) { $this->Factory->DestroyObject($name); } /** * Get's real class name for pseudo class, includes class file and creates class instance * * Pattern: Factory Method * * @param string $pseudo_class * @param Array $arguments * @return kBase * @access public */ public function makeClass($pseudo_class, array $arguments = array()) { return $this->Factory->makeClass($pseudo_class, $arguments); } /** * Checks if application is in debug mode * * @param bool $check_debugger check if kApplication debugger is initialized too, not only for defined DEBUG_MODE constant * @return bool * @author Alex * @access public */ public function isDebugMode($check_debugger = true) { $debug_mode = defined('DEBUG_MODE') && DEBUG_MODE; if ($check_debugger) { $debug_mode = $debug_mode && is_object($this->Debugger); } return $debug_mode; } /** * Apply url rewriting used by mod_rewrite or not * * @param bool|null $ssl Force ssl link to be build * @return bool * @access public */ public function RewriteURLs($ssl = false) { // case #1,#4: // we want to create https link from http mode // we want to create https link from https mode // conditions: ($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL') // case #2,#3: // we want to create http link from https mode // we want to create http link from http mode // conditions: !$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://') $allow_rewriting = (!$ssl && (PROTOCOL == 'https://' || PROTOCOL == 'http://')) // always allow mod_rewrite for http || // or allow rewriting for redirect TO httpS or when already in httpS (($ssl || PROTOCOL == 'https://') && $this->ConfigValue('UseModRewriteWithSSL')); // but only if it's allowed in config! return kUtil::constOn('MOD_REWRITE') && $allow_rewriting; } /** * Reads unit (specified by $prefix) * option specified by $option * * @param string $prefix * @param string $option * @param mixed $default * @return string * @access public */ public function getUnitOption($prefix, $option, $default = false) { return $this->UnitConfigReader->getUnitOption($prefix, $option, $default); } /** * Set's new unit option value * * @param string $prefix * @param string $option * @param string $value * @access public */ public function setUnitOption($prefix, $option, $value) { $this->UnitConfigReader->setUnitOption($prefix,$option,$value); } /** * Read all unit with $prefix options * * @param string $prefix * @return Array * @access public */ public function getUnitOptions($prefix) { return $this->UnitConfigReader->getUnitOptions($prefix); } /** * Returns true if config exists and is allowed for reading * * @param string $prefix * @return bool */ public function prefixRegistred($prefix) { return $this->UnitConfigReader->prefixRegistred($prefix); } /** * Splits any mixing of prefix and * special into correct ones * * @param string $prefix_special * @return Array * @access public */ public function processPrefix($prefix_special) { return $this->Factory->processPrefix($prefix_special); } /** * Set's new event for $prefix_special * passed * * @param string $prefix_special * @param string $event_name * @return void * @access public */ public function setEvent($prefix_special, $event_name) { $this->EventManager->setEvent($prefix_special, $event_name); } /** * SQL Error Handler * * @param int $code * @param string $msg * @param string $sql * @return bool * @access public * @throws Exception * @deprecated */ public function handleSQLError($code, $msg, $sql) { return $this->_logger->handleSQLError($code, $msg, $sql); } /** * Returns & blocks next ResourceId available in system * * @return int * @access public */ public function NextResourceId() { $table_name = TABLE_PREFIX . 'IdGenerator'; $this->Conn->Query('LOCK TABLES ' . $table_name . ' WRITE'); $this->Conn->Query('UPDATE ' . $table_name . ' SET lastid = lastid + 1'); $id = $this->Conn->GetOne('SELECT lastid FROM ' . $table_name); if ( $id === false ) { $this->Conn->Query('INSERT INTO ' . $table_name . ' (lastid) VALUES (2)'); $id = 2; } $this->Conn->Query('UNLOCK TABLES'); return $id - 1; } /** * Returns genealogical main prefix for sub-table prefix passes * OR prefix, that has been found in REQUEST and some how is parent of passed sub-table prefix * * @param string $current_prefix * @param bool $real_top if set to true will return real topmost prefix, regardless of its id is passed or not * @return string * @access public */ public function GetTopmostPrefix($current_prefix, $real_top = false) { // 1. get genealogical tree of $current_prefix $prefixes = Array ($current_prefix); while ($parent_prefix = $this->getUnitOption($current_prefix, 'ParentPrefix')) { if ( !$this->prefixRegistred($parent_prefix) ) { // stop searching, when parent prefix is not registered break; } $current_prefix = $parent_prefix; array_unshift($prefixes, $current_prefix); } if ( $real_top ) { return $current_prefix; } // 2. find what if parent is passed $passed = explode(',', $this->GetVar('all_passed')); foreach ($prefixes as $a_prefix) { if ( in_array($a_prefix, $passed) ) { return $a_prefix; } } return $current_prefix; } /** * Triggers email event of type Admin * * @param string $email_template_name * @param int $to_user_id * @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text * @return kEvent * @access public */ public function emailAdmin($email_template_name, $to_user_id = null, $send_params = Array ()) { return $this->_email($email_template_name, EmailTemplate::TEMPLATE_TYPE_ADMIN, $to_user_id, $send_params); } /** * Triggers email event of type User * * @param string $email_template_name * @param int $to_user_id * @param array $send_params associative array of direct send params, possible keys: to_email, to_name, from_email, from_name, message, message_text * @return kEvent * @access public */ public function emailUser($email_template_name, $to_user_id = null, $send_params = Array ()) { return $this->_email($email_template_name, EmailTemplate::TEMPLATE_TYPE_FRONTEND, $to_user_id, $send_params); } /** * Triggers general email event * * @param string $email_template_name * @param int $email_template_type (0 for User, 1 for Admin) * @param int $to_user_id * @param array $send_params associative array of direct send params, * possible keys: to_email, to_name, from_email, from_name, message, message_text * @return kEvent * @access protected */ protected function _email($email_template_name, $email_template_type, $to_user_id = null, $send_params = Array ()) { $email = $this->makeClass('kEmail'); /* @var $email kEmail */ if ( !$email->findTemplate($email_template_name, $email_template_type) ) { return false; } $email->setParams($send_params); return $email->send($to_user_id); } /** * Allows to check if user in this session is logged in or not * * @return bool * @access public */ public function LoggedIn() { // no session during expiration process return is_null($this->Session) ? false : $this->Session->LoggedIn(); } /** * Check current user permissions based on it's group permissions in specified category * * @param string $name permission name * @param int $cat_id category id, current used if not specified * @param int $type permission type {1 - system, 0 - per category} * @return int * @access public */ public function CheckPermission($name, $type = 1, $cat_id = null) { $perm_helper = $this->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ return $perm_helper->CheckPermission($name, $type, $cat_id); } /** * Check current admin permissions based on it's group permissions in specified category * * @param string $name permission name * @param int $cat_id category id, current used if not specified * @param int $type permission type {1 - system, 0 - per category} * @return int * @access public */ public function CheckAdminPermission($name, $type = 1, $cat_id = null) { $perm_helper = $this->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ return $perm_helper->CheckAdminPermission($name, $type, $cat_id); } /** * Set's any field of current visit * * @param string $field * @param mixed $value * @return void * @access public * @todo move to separate module */ public function setVisitField($field, $value) { if ( $this->isAdmin || !$this->ConfigValue('UseVisitorTracking') ) { // admin logins are not registered in visits list return; } $visit = $this->recallObject('visits', null, Array ('raise_warnings' => 0)); /* @var $visit kDBItem */ if ( $visit->isLoaded() ) { $visit->SetDBField($field, $value); $visit->Update(); } } /** * Allows to check if in-portal is installed * * @return bool * @access public */ public function isInstalled() { return $this->InitDone && (count($this->ModuleInfo) > 0); } /** * Allows to determine if module is installed & enabled * * @param string $module_name * @return bool * @access public */ public function isModuleEnabled($module_name) { return $this->findModule('Name', $module_name) !== false; } /** * Returns Window ID of passed prefix main prefix (in edit mode) * * @param string $prefix * @return int * @access public */ public function GetTopmostWid($prefix) { $top_prefix = $this->GetTopmostPrefix($prefix); $mode = $this->GetVar($top_prefix . '_mode'); return $mode != '' ? substr($mode, 1) : ''; } /** * Get temp table name * * @param string $table * @param mixed $wid * @return string * @access public */ public function GetTempName($table, $wid = '') { return $this->GetTempTablePrefix($wid) . $table; } /** * Builds temporary table prefix based on given window id * * @param string $wid * @return string * @access public */ public function GetTempTablePrefix($wid = '') { if ( preg_match('/prefix:(.*)/', $wid, $regs) ) { $wid = $this->GetTopmostWid($regs[1]); } return TABLE_PREFIX . 'ses_' . $this->GetSID() . ($wid ? '_' . $wid : '') . '_edit_'; } /** * Checks if given table is a temporary table * * @param string $table * @return bool * @access public */ public function IsTempTable($table) { static $cache = Array (); if ( !array_key_exists($table, $cache) ) { $cache[$table] = preg_match('/' . TABLE_PREFIX . 'ses_' . $this->GetSID() . '(_[\d]+){0,1}_edit_(.*)/', $table); } return (bool)$cache[$table]; } /** * Checks, that given prefix is in temp mode * * @param string $prefix * @param string $special * @return bool * @access public */ public function IsTempMode($prefix, $special = '') { $top_prefix = $this->GetTopmostPrefix($prefix); $var_names = Array ( $top_prefix, rtrim($top_prefix . '_' . $special, '_'), // from post rtrim($top_prefix . '.' . $special, '.'), // assembled locally ); $var_names = array_unique($var_names); $temp_mode = false; foreach ($var_names as $var_name) { $value = $this->GetVar($var_name . '_mode'); if ( $value && (substr($value, 0, 1) == 't') ) { $temp_mode = true; break; } } return $temp_mode; } /** * Return live table name based on temp table name * * @param string $temp_table * @return string */ public function GetLiveName($temp_table) { if ( preg_match('/' . TABLE_PREFIX . 'ses_' . $this->GetSID() . '(_[\d]+){0,1}_edit_(.*)/', $temp_table, $rets) ) { // cut wid from table end if any return $rets[2]; } else { return $temp_table; } } /** * Stops processing of user request and displays given message * * @param string $message * @access public */ public function ApplicationDie($message = '') { while ( ob_get_level() ) { ob_end_clean(); } if ( $this->isDebugMode() ) { $message .= $this->Debugger->printReport(true); } $this->HTML = $message; $this->_outputPage(); } /** * Returns comma-separated list of groups from given user * * @param int $user_id * @return string */ public function getUserGroups($user_id) { switch ($user_id) { case USER_ROOT: $user_groups = $this->ConfigValue('User_LoggedInGroup'); break; case USER_GUEST: $user_groups = $this->ConfigValue('User_LoggedInGroup') . ',' . $this->ConfigValue('User_GuestGroup'); break; default: $sql = 'SELECT GroupId FROM ' . TABLE_PREFIX . 'UserGroupRelations WHERE PortalUserId = ' . (int)$user_id; $res = $this->Conn->GetCol($sql); $user_groups = Array ($this->ConfigValue('User_LoggedInGroup')); if ( $res ) { $user_groups = array_merge($user_groups, $res); } $user_groups = implode(',', $user_groups); } return $user_groups; } /** * Allows to detect if page is browsed by spider (293 scheduled_tasks supported) * * @return bool * @access public */ /*public function IsSpider() { static $is_spider = null; if ( !isset($is_spider) ) { $user_agent = trim($_SERVER['HTTP_USER_AGENT']); $robots = file(FULL_PATH . '/core/robots_list.txt'); foreach ($robots as $robot_info) { $robot_info = explode("\t", $robot_info, 3); if ( $user_agent == trim($robot_info[2]) ) { $is_spider = true; break; } } } return $is_spider; }*/ /** * Allows to detect table's presence in database * * @param string $table_name * @param bool $force * @return bool * @access public */ public function TableFound($table_name, $force = false) { return $this->Conn->TableFound($table_name, $force); } /** * Returns counter value * * @param string $name counter name * @param Array $params counter parameters * @param string $query_name specify query name directly (don't generate from parameters) * @param bool $multiple_results * @return mixed * @access public */ public function getCounter($name, $params = Array (), $query_name = null, $multiple_results = false) { $count_helper = $this->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ return $count_helper->getCounter($name, $params, $query_name, $multiple_results); } /** * Resets counter, which are affected by one of specified tables * * @param string $tables comma separated tables list used in counting sqls * @return void * @access public */ public function resetCounters($tables) { if ( kUtil::constOn('IS_INSTALL') ) { return; } $count_helper = $this->recallObject('CountHelper'); /* @var $count_helper kCountHelper */ $count_helper->resetCounters($tables); } /** * Sends XML header + optionally displays xml heading * * @param string|bool $xml_version * @return string * @access public * @author Alex */ public function XMLHeader($xml_version = false) { $this->setContentType('text/xml'); return $xml_version ? '' : ''; } /** * Returns category tree * * @param int $category_id * @return Array * @access public */ public function getTreeIndex($category_id) { $tree_index = $this->getCategoryCache($category_id, 'category_tree'); if ( $tree_index ) { $ret = Array (); list ($ret['TreeLeft'], $ret['TreeRight']) = explode(';', $tree_index); return $ret; } return false; } /** * Base category of all categories * Usually replaced category, with ID = 0 in category-related operations. * * @return int * @access public */ public function getBaseCategory() { // same, what $this->findModule('Name', 'Core', 'RootCat') does // don't cache while IS_INSTALL, because of kInstallToolkit::createModuleCategory and upgrade return $this->ModuleInfo['Core']['RootCat']; } /** * Deletes all data, that was cached during unit config parsing (excluding unit config locations) * * @param Array $config_variables * @access public */ public function DeleteUnitCache($config_variables = null) { $this->cacheManager->DeleteUnitCache($config_variables); } /** * Deletes cached section tree, used during permission checking and admin console tree display * * @return void * @access public */ public function DeleteSectionCache() { $this->cacheManager->DeleteSectionCache(); } /** * Sets data from cache to object * * @param Array $data * @access public */ public function setFromCache(&$data) { $this->Factory->setFromCache($data); $this->UnitConfigReader->setFromCache($data); $this->EventManager->setFromCache($data); $this->ReplacementTemplates = $data['Application.ReplacementTemplates']; $this->RewriteListeners = $data['Application.RewriteListeners']; $this->ModuleInfo = $data['Application.ModuleInfo']; } /** * Gets object data for caching * The following caches should be reset based on admin interaction (adjusting config, enabling modules etc) * * @access public * @return Array */ public function getToCache() { return array_merge( $this->Factory->getToCache(), $this->UnitConfigReader->getToCache(), $this->EventManager->getToCache(), Array ( 'Application.ReplacementTemplates' => $this->ReplacementTemplates, 'Application.RewriteListeners' => $this->RewriteListeners, 'Application.ModuleInfo' => $this->ModuleInfo, ) ); } public function delayUnitProcessing($method, $params) { $this->cacheManager->delayUnitProcessing($method, $params); } /** * Returns current maintenance mode state * * @param bool $check_ips * @return int * @access public */ public function getMaintenanceMode($check_ips = true) { $exception_ips = defined('MAINTENANCE_MODE_IPS') ? MAINTENANCE_MODE_IPS : ''; $setting_name = $this->isAdmin ? 'MAINTENANCE_MODE_ADMIN' : 'MAINTENANCE_MODE_FRONT'; if ( defined($setting_name) && constant($setting_name) > MaintenanceMode::NONE ) { $exception_ip = $check_ips ? kUtil::ipMatch($exception_ips) : false; if ( !$exception_ip ) { return constant($setting_name); } } return MaintenanceMode::NONE; } /** * Sets content type of the page * * @param string $content_type * @param bool $include_charset * @return void * @access public */ public function setContentType($content_type = 'text/html', $include_charset = null) { static $already_set = false; if ( $already_set ) { return; } $header = 'Content-type: ' . $content_type; if ( !isset($include_charset) ) { $include_charset = $content_type = 'text/html' || $content_type == 'text/plain' || $content_type = 'text/xml'; } if ( $include_charset ) { $header .= '; charset=' . CHARSET; } $already_set = true; header($header); } /** * Posts message to event log * * @param string $message * @param int $code * @param bool $write_now Allows further customization of log record by returning kLog object * @return bool|int|kLogger * @access public */ public function log($message, $code = null, $write_now = false) { $log = $this->_logger->prepare($message, $code)->addSource($this->_logger->createTrace(null, 1)); if ( $write_now ) { return $log->write(); } return $log; } /** * Deletes log with given id from database or disk, when database isn't available * * @param int $unique_id * @param int $storage_medium * @return void * @access public * @throws InvalidArgumentException */ public function deleteLog($unique_id, $storage_medium = kLogger::LS_AUTOMATIC) { $this->_logger->delete($unique_id, $storage_medium); } /** * Returns the client IP address. * * @return string The client IP address * @access public */ public function getClientIp() { return $this->HttpQuery->getClientIp(); } } Index: branches/5.2.x/core/kernel/processors/main_processor.php =================================================================== --- branches/5.2.x/core/kernel/processors/main_processor.php (revision 16433) +++ branches/5.2.x/core/kernel/processors/main_processor.php (revision 16434) @@ -1,1316 +1,1293 @@ Application->recallObject('kActions'); /* @var $actions Params */ $actions->Set('t', $this->Application->GetVar('t')); $actions->Set('sid', $this->Application->GetSID()); $actions->Set('m_opener', $this->Application->GetVar('m_opener') ); } /** * Base folder for all template includes * * @param Array $params * @return string */ function TemplatesBase($params) { static $cached = Array (); $cache_key = crc32( serialize($params) ); if (!array_key_exists($cache_key, $cached)) { $module = array_key_exists('module', $params) ? $params['module'] : 'core'; if ($this->Application->isAdmin) { if ($module == 'in-portal') { $module = 'kernel'; } // remove leading slash + substitute module $module_path = $this->Application->findModule('Name', $module, 'Path'); if ($module_path !== false) { $path = $module_path . 'admin_templates'; } else { // remove leading slash + substitute module $path = preg_replace('/\/(.*?)\/(.*)/', $module . '/\\2', THEMES_PATH); } } else { $path = mb_substr(THEMES_PATH, 1); if (mb_strtolower($module) == 'in-portal') { $module_folder = 'platform'; } else { $module_folder = $this->Application->findModule('Name', $module, 'TemplatePath'); } $path .= rtrim('/' . trim($module_folder, '/'), '/') . '/'; } $cached[$cache_key] = $this->Application->BaseURL() . $path; } return $cached[$cache_key]; } /** * Creates HTML tag for all templates * affects future css, js files and href params of links * * @param Array $params * @return string * @access protected * @see kMainTagProcessor::TemplatesBase */ protected function Base_Ref($params) { // tag TemplatesBase adds trailing "/" but only on Front-End $base_href = rtrim($this->TemplatesBase($params), '/'); return ''; } /** * Returns base url for web-site * * @return string * @access public */ function BaseURL() { return $this->Application->BaseURL(); } //for compatability with K3 tags function Base($params) { return $this->TemplatesBase($params).'/'; } function ProjectBase($params) { return $this->Application->BaseURL(); } /*function Base($params) { return $this->Application->BaseURL().$params['add']; }*/ /** * Used to create link to any template. * use "pass" paramter if "t" tag to specify * prefix & special of object to be represented * in resulting url * * @param Array $params * @return string * @access public */ function T($params) { // by default link to current template $template = $this->SelectParam($params, 't,template'); $prefix = array_key_exists('prefix', $params) ? $params['prefix'] : ''; unset($params['t'], $params['template'], $params['prefix']); $no_html_escape = false; if ( isset($params['no_amp']) ) { $no_html_escape = $params['no_amp']; unset($params['no_amp']); } $ret = $this->Application->HREF($template, $prefix, $params); if ( !$no_html_escape ) { // most of the time links are placed into HTML document // TODO: in future always do escaping according to current "escape context" $ret = kUtil::escape($ret, kUtil::ESCAPE_HTML); } return $ret; } function Link($params) { // pass "m" prefix, instead of "all", that is by default on Front-End if (!array_key_exists('pass', $params)) { $params['pass'] = 'm'; } return $this->T($params); } /** * Performs redirect to provided template/url * * @param Array $params * @return string */ function Redirect($params) { // By default link to current template. $template = $this->SelectParam($params, 't,template'); $prefix = array_key_exists('prefix', $params) ? $params['prefix'] : ''; unset($params['t'], $params['template'], $params['prefix']); // Pass "m" prefix, instead of "all", that is by default on Front-End. if ( !array_key_exists('pass', $params) ) { $params['pass'] = 'm'; } $this->Application->Redirect($template, $params, $prefix); return ''; } /*function Env($params) { $t = $params['template']; unset($params['template']); return $this->Application->BuildEnv($t, $params, 'm', false, false); }*/ function FormAction($params) { if (!array_key_exists('pass', $params)) { $params['pass'] = 'all,m'; } $params['pass_category'] = 1; return $this->Application->HREF('', '', $params); } /*// NEEDS TEST function Config($params) { return $this->Application->ConfigOption($params['var']); } function Object($params) { $name = $params['name']; $method = $params['method']; $tmp = $this->Application->recallObject($name); if ($tmp != null) { if (method_exists($tmp, $method)) return $tmp->$method($params); else echo "Method $method does not exist in object ".get_class($tmp)." named $name
"; } else echo "Object $name does not exist in the appliaction
"; }*/ /** * Tag, that always returns true. * For parser testing purposes * * @param Array $params * @return bool * @access public */ function True($params) { return true; } /** * Tag, that always returns false. * For parser testing purposes * * @param Array $params * @return bool * @access public */ function False($params) { return false; } /** * Returns block parameter by name (used only as "check" parameter value for "m_if" tag!) * * @param Array $params * @return stirng * @access public */ function Param($params) { $name = $params['name']; if (array_key_exists($name, $this->Application->Parser->Captures)) { $capture_params = $params; $capture_params['name'] = '__capture_' . $name; $this->Application->Parser->SetParam($name, $this->Application->ParseBlock($capture_params)); } $res = $this->Application->Parser->GetParam($name); if ($res === false) { $res = ''; } if (array_key_exists('plus', $params)) { $res += $params['plus']; } return $res; } /** * Compares block parameter with value specified * * @param Array $params * @return bool * @access public */ function ParamEquals($params) { $name = $this->SelectParam($params, 'name,var,param'); $value = $params['value']; return ($this->Application->Parser->GetParam($name) == $value); } /*function PHP_Self($params) { return $HTTP_SERVER_VARS['PHP_SELF']; } */ /** * Returns session variable value by name * * @param Array $params * @return string * @access public */ function Recall($params) { $var_name = $this->SelectParam($params,'name,var,param'); if (isset($params['persistent']) && $params['persistent']) { $ret = $this->Application->RecallPersistentVar($var_name); } else { $ret = $this->Application->RecallVar($var_name); } $ret = ($ret === false && isset($params['no_null'])) ? '' : $ret; if (getArrayValue($params, 'special') || getArrayValue($params, 'htmlchars')) { $ret = kUtil::escape($ret, kUtil::ESCAPE_HTML); } if (getArrayValue($params, 'urlencode')) { $ret = kUtil::escape($ret, kUtil::ESCAPE_URL); } return $ret; } function RemoveVar($params) { $this->Application->RemoveVar( $this->SelectParam($params,'name,var,param') ); } // bad style to store something from template to session !!! (by Alex) // Used here only to test how session works, nothing more function Store($params) { //echo"Store $params[name]
"; $name = $params['name']; $value = $params['value']; $this->Application->StoreVar($name,$value); } /** * Links variable from request with variable from session * * @param Array $params * @return string * @access protected */ protected function LinkVar($params) { $var_name = $params['name']; $session_var_name = isset($params['session_name']) ? $params['session_name'] : $var_name; $default_value = isset($params['default']) ? $params['default'] : ''; $this->Application->LinkVar($var_name, $session_var_name, $default_value); return ''; } /** * Links variable from request with variable from session and returns it's value * * @param Array $params * @return string * @access protected */ protected function GetLinkedVar($params) { $this->LinkVar($params); return $this->Application->GetVar( $params['name'] ); } /** * Sets application variable value(-s) * * @param Array $params * @access public */ function Set($params) { foreach ($params as $param => $value) { $this->Application->SetVar($param, $value); } } /** * Increment application variable * specified by number specified * * @param Array $params * @access public */ function Inc($params) { $this->Application->SetVar($params['param'], $this->Application->GetVar($params['param']) + $params['by']); } /** * Retrieves application variable * value by name * * @param Array $params * @return string * @access public */ function Get($params) { $name = $this->SelectParam($params, 'name,var,param'); if ( strpos($name, '[') !== false ) { preg_match('/([^\[\]]+)\[(.*)\]/', $name, $regs); $function_params = explode('][', $regs[2]); $ret = $this->Application->GetVar($regs[1], array()); kUtil::array_unshift_ref($function_params, $ret); $ret = call_user_func_array('getArrayValue', $function_params); } else { $ret = $this->Application->GetVar($name, ''); } if ( array_key_exists('no_html_escape', $params) && $params['no_html_escape'] ) { return $this->Application->isAdmin ? $ret : kUtil::unescape($ret, kUtil::ESCAPE_HTML); } return kUtil::escape($ret, kUtil::ESCAPE_HTML); } /** * Retrieves application constant * value by name * * @param Array $params * @return string * @access public */ function GetConst($params) { $constant_name = $this->SelectParam($params, 'name,const'); return defined($constant_name) ? constant($constant_name) : ''; } /** * Retrieves configuration variable value by name * * @param Array $params * @return string * @access public */ function GetConfig($params) { $config_name = $this->SelectParam($params, 'name,var'); $ret = $this->Application->ConfigValue($config_name); if ( isset($params['formatted']) && $params['formatted'] ) { $sql = 'SELECT ValueList FROM ' . TABLE_PREFIX . 'SystemSettings WHERE VariableName = ' . $this->Conn->qstr($config_name) . ' AND ElementType IN ("select", "radio")'; $value_list = $this->Conn->GetOne($sql); if ( $value_list ) { $helper = $this->Application->recallObject('InpCustomFieldsHelper'); /* @var $helper InpCustomFieldsHelper */ $options = $helper->GetValuesHash($value_list); $ret = isset($options[$ret]) ? $options[$ret] : $ret; } } if ( isset($params['as_label']) && $params['as_label'] ) { $ret = $this->Application->Phrase($ret); } return $ret; } /** * Compares configuration variable to a given value * * @param Array $params * @return bool * @deprecated * @access protected */ protected function ConfigEquals($params) { $option = $this->SelectParam($params, 'name,option,var'); return $this->Application->ConfigValue($option) == $params['value']; } /** * Creates all hidden fields * needed for kernel_form * * @param Array $params * @return string * @access protected */ protected function DumpSystemInfo($params) { $actions = $this->Application->recallObject('kActions'); /* @var $actions Params */ $actions->Set('t', $this->Application->GetVar('t')); $o = ''; $params = $actions->GetParams(); foreach ($params AS $name => $val) { $o .= "\n"; } return $o; } /** * Used for search sidebox on front-end only * * @param Array $params * @return string * @access protected */ protected function GetFormHiddens($params) { $t = $this->SelectParam($params, 'template,t'); unset($params['template']); $form_fields = Array (); if ( $this->Application->RewriteURLs() ) { $session = $this->Application->recallObject('Session'); /* @var $session Session */ if ( $session->NeedQueryString() ) { $form_fields['sid'] = $this->Application->GetSID(); } } else { $form_fields['env'] = $this->Application->BuildEnv($t, $params, 'm', false, false); } if ( $this->Application->GetVar('admin') == 1 ) { $form_fields['admin'] = 1; } $ret = ''; $field_tpl = '' . "\n"; foreach ($form_fields as $form_field => $field_value) { $ret .= sprintf($field_tpl, $form_field, $field_value); } return $ret; } function Odd_Even($params) { $odd = $params['odd']; $even = $params['even']; if (!isset($params['var'])) { $var = 'odd_even'; } else { $var = $params['var']; } if ($this->Application->GetVar($var) == 'even') { if (!isset($params['readonly']) || !$params['readonly']) { $this->Application->SetVar($var, 'odd'); } return $even; } else { if (!isset($params['readonly']) || !$params['readonly']) { $this->Application->SetVar($var, 'even'); } return $odd; } } /** * Returns phrase translation by name * * @param Array $params * @return string * @access public */ function Phrase($params) { $phrase_name = $this->SelectParam($params, 'label,name,title'); $default_translation = $this->SelectParam($params, 'default'); $no_editing = isset($params['no_editing']) && $params['no_editing']; $translation = $this->Application->Phrase($phrase_name, !$no_editing); $phrase_key = mb_strtoupper($phrase_name); if ( $default_translation && strpos($translation, '!' . $phrase_key . '!') !== false ) { $phrase = $this->Application->recallObject('phrases.autocreate', null, Array ('skip_autoload' => true)); /* @var $phrase kDBItem */ if ( !$phrase->Load($phrase_key, 'PhraseKey') ) { $phrase->SetDBField('Phrase', $phrase_name); $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); /* @var $ml_helper kMultiLanguageHelper */ $languages = $ml_helper->getLanguages(); foreach ($languages AS $language_id) { $phrase->SetDBField('l' . $language_id . '_Translation', $default_translation); } if ( $phrase->Create() ) { $translation = $default_translation; } } } if ( isset($params['escape']) && $params['escape'] ) { // html escaping here is redundant $translation = kUtil::escape($translation, kUtil::ESCAPE_JS); } return $translation; } // for tabs function is_active($params) { $test_templ = $this->SelectParam($params, 'templ,template,t'); if ( !getArrayValue($params, 'allow_empty') ) { $if_true = getArrayValue($params, 'true') ? $params['true'] : 1; $if_false = getArrayValue($params, 'false') ? $params['false'] : 0; } else { $if_true = $params['true']; $if_false = $params['false']; } $physical_template = $this->Application->getPhysicalTemplate($this->Application->GetVar('t')); return preg_match('/^' . str_replace('/', '\/', $test_templ) . '/i', $physical_template) ? $if_true : $if_false; } function IsNotActive($params) { return !$this->is_active($params); } function IsActive($params) { return $this->is_active($params); } function is_t_active($params) { return $this->is_active($params); } function CurrentTemplate($params) { return $this->is_active($params); } /** * Checks if session variable * specified by name value match * value passed as parameter * * @param Array $params * @return string * @access public */ function RecallEquals($params) { $name = $this->SelectParam($params, 'name,var'); $value = $params['value']; if (isset($params['persistent']) && $params['persistent']) { return $this->Application->RecallPersistentVar($name) == $value; } return ($this->Application->RecallVar($name) == $value); } /** * Checks if application variable specified by name value match value passed as parameter * * @param Array $params * @return bool * @access protected * @deprecated */ protected function GetEquals($params) { $name = $this->SelectParam($params, 'var,name,param'); return $this->Application->GetVar($name) == $params['value']; } function ModuleInclude($params) { $ret = ''; $included = Array (); $block_params = array_merge($params, Array ('is_silent' => 2)); // don't make fatal errors in case if template is missing $current_template = $this->Application->GetVar('t'); $replace_main = isset($params['replace_m']) && $params['replace_m']; $skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array (); $cms_mode = $this->Application->GetVar('admin'); foreach ($this->Application->ModuleInfo as $module_name => $module_data) { $module_key = mb_strtolower($module_name); if ( $module_name == 'In-Portal' ) { if ( !$cms_mode && $this->Application->isAdmin ) { // don't process In-Portal templates in admin continue; } // Front-End still relies on In-Portal module $module_prefix = $module_data['TemplatePath']; } elseif ( $this->Application->isAdmin && $module_data['Path'] != 'core/' ) { $module_prefix = $module_key . '/'; // was $module_data['Path']; } else { $module_prefix = $module_data['TemplatePath']; // always have trailing "/" } if ( in_array($module_prefix, $included) ) { // template by this path was already included by other module (e.g. in-portal used core's template) continue; } $block_params['t'] = $module_prefix . $this->SelectParam($params, $module_key . '_template,' . $module_key . '_t,template,t'); $check_prefix = $module_data['Var']; if ( $check_prefix == 'adm' && $replace_main ) { $check_prefix = 'c'; } if ( $block_params['t'] == $current_template || in_array($check_prefix, $skip_prefixes) ) { continue; } $no_data = $this->SelectParam($params, $module_key . '_block_no_data,block_no_data'); if ( $no_data ) { $block_params['block_no_data'] = $module_prefix . '/' . $no_data; } $ret .= $this->Application->IncludeTemplate($block_params); $included[] = $module_prefix; } return $ret; } function ModuleEnabled($params) { return $this->Application->isModuleEnabled( $params['module'] ); } /** * Checks if debug mode is on * * @param Array $params * @return bool * @access public */ function IsDebugMode($params) { return defined('DEBUG_MODE') && $this->Application->isDebugMode(); } /*function MassParse($params) { $qty = $params['qty']; $block = $params['block']; $mode = $params['mode']; $o = ''; if ($mode == 'func') { $func = create_function('$params', ' $o = \'\'; $o.= \'a\'.$params[\'param1\'].\'\'; $o.= \'a\'.$params[\'param2\'].\'\'; $o.= \'a\'.$params[\'param3\'].\'\'; $o.= \'a\'.$params[\'param4\'].\'\'; $o.= \'\'; return $o; '); for ($i=1; $i<$qty; $i++) { $block_params['param1'] = rand(1, 10000); $block_params['param2'] = rand(1, 10000); $block_params['param3'] = rand(1, 10000); $block_params['param4'] = rand(1, 10000); $o .= $func($block_params); } return $o; } $block_params['name'] = $block; for ($i=0; $i<$qty; $i++) { $block_params['param1'] = rand(1, 10000); $block_params['param2'] = rand(1, 10000); $block_params['param3'] = rand(1, 10000); $block_params['param4'] = rand(1, 10000); $block_params['passed'] = $params['passed']; $block_params['prefix'] = 'm'; $o.= $this->Application->ParseBlock($block_params); } return $o; }*/ function LoggedIn($params) { return $this->Application->LoggedIn(); } /** * Allows to check if permission exists directly in template and perform additional actions if required * * @param Array $params * @return bool */ function CheckPermission($params) { $perm_helper = $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ return $perm_helper->TagPermissionCheck($params); } /** * Checks if user is logged in and if not redirects it to template passed * * @param Array $params */ function RequireLogin($params) { $t = $this->Application->GetVar('t'); $next_t = getArrayValue($params, 'next_template'); if ( $next_t ) { $t = $next_t; } // check by permissions: begin if ((isset($params['perm_event']) && $params['perm_event']) || (isset($params['perm_prefix']) && $params['perm_prefix']) || (isset($params['permissions']) && $params['permissions'])) { $perm_helper = $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $perm_status = $perm_helper->TagPermissionCheck($params); if (!$perm_status) { list($redirect_template, $redirect_params) = $perm_helper->getPermissionTemplate($params); $this->Application->Redirect($redirect_template, $redirect_params); } else { return ; } } // check by permissions: end // check by configuration value: begin $condition = getArrayValue($params, 'condition'); if (!$condition) { $condition = true; } else { if (substr($condition, 0, 1) == '!') { $condition = !$this->Application->ConfigValue(substr($condition, 1)); } else { $condition = $this->Application->ConfigValue($condition); } } // check by configuration value: end // check by belonging to group: begin $group = $this->SelectParam($params, 'group'); $group_access = true; if ($group) { $sql = 'SELECT GroupId FROM '.TABLE_PREFIX.'UserGroups WHERE Name = '.$this->Conn->qstr($group); $group_id = $this->Conn->GetOne($sql); if ($group_id) { $groups = explode(',', $this->Application->RecallVar('UserGroups')); $group_access = in_array($group_id, $groups); } } // check by belonging to group: end if ((!$this->Application->LoggedIn() || !$group_access) && $condition) { $redirect_params = $this->Application->HttpQuery->getRedirectParams(true); if (MOD_REWRITE) { // TODO: $next_t variable is ignored !!! (is anyone using m_RequireLogin tag with "next_template" parameter?) $redirect_params = Array ( 'm_cat_id' => 0, 'next_template' => 'external:' . $_SERVER['REQUEST_URI'], ); } else { $redirect_params['next_template'] = $t; } if (array_key_exists('pass_category', $params)) { $redirect_params['pass_category'] = $params['pass_category']; } if (array_key_exists('use_section', $params)) { $redirect_params['use_section'] = $params['use_section']; } if ( $this->Application->LoggedIn() && !$group_access) { $this->Application->Redirect($params['no_group_perm_template'], $redirect_params); } $this->Application->Redirect($params['login_template'], $redirect_params); } } /** * Checks, that user belongs to a group with a given name * * @param Array $params * @return bool */ protected function IsMember($params) { $sql = 'SELECT GroupId FROM ' . TABLE_PREFIX . 'UserGroups WHERE Name = ' . $this->Conn->qstr($params['group']); $group_id = $this->Conn->GetOne($sql); if ( $group_id ) { $groups = explode(',', $this->Application->RecallVar('UserGroups')); return in_array($group_id, $groups); } return false; } /** * Checks if SSL is on and redirects to SSL URL if needed * If SSL_URL is not defined in config - the tag does not do anything * If for_logged_in_only="1" exits if user is not logged in. * If called without params forces https right away. If called with by_config="1" checks the * Require SSL setting from General Config and if it is ON forces https * * @param Array $params */ protected function CheckSSL($params) { $ssl = $this->Application->isAdmin ? $this->Application->ConfigValue('AdminSSL_URL') : false; if ( !$ssl ) { // not in admin or admin ssl url is empty $ssl_url = $this->Application->siteDomainField('SSLUrl'); $ssl = $ssl_url !== false ? $ssl_url : $this->Application->ConfigValue('SSL_URL'); } if ( !$ssl || ($this->Application->TemplatesCache->forceThemeName !== false) ) { // SSL URL is not set - no way to require SSL // internal parsing (e.g. "TemplateParser::_parseTemplate") -> don't redirect return; } $require = false; if ( isset($params['mode']) && $params['mode'] == 'required' ) { $require = true; if ( isset($params['for_logged_in_only']) && $params['for_logged_in_only'] && !$this->Application->LoggedIn() ) { $require = false; } if ( isset($params['condition']) ) { if ( !$this->Application->ConfigValue($params['condition']) ) { $require = false; } } } if ( EDITING_MODE ) { // match SSL mode on front-end to one in administrative console, when browse modes are used $require = $this->Application->ConfigValue('Require_AdminSSL'); } $http_query = $this->Application->recallObject('HTTPQuery'); /* @var $http_query kHTTPQuery */ $pass = $http_query->getRedirectParams(); $pass['pass_events'] = 1; // to make sure all events are passed when redirect happens if ( $require ) { if ( PROTOCOL == 'https://' ) { $this->Application->SetVar('__KEEP_SSL__', 1); return; } $pass['__SSL__'] = 1; $this->Application->Redirect('', $pass); } else { if ( PROTOCOL == 'https://' && $this->Application->ConfigValue('Force_HTTP_When_SSL_Not_Required') ) { if ( $this->Application->GetVar('__KEEP_SSL__') ) { return; } // $pass_more = Array ('pass' => 'm', 'm_cat_id' => 0, '__SSL__' => 0); $pass['__SSL__'] = 0; $this->Application->Redirect('', $pass); // $pass_more } } } function ConstOn($params) { $name = $this->SelectParam($params,'name,const'); return kUtil::constOn($name); } function SetDefaultCategory($params) { $category_id = $this->Application->findModule('Name', $params['module'], 'RootCat'); $this->Application->SetVar('m_cat_id', $category_id); } function XMLTemplate($params) { $this->NoDebug($params); if ( isset($params['cache']) && $params['cache'] ) { $nextyear = intval(date('Y') + 1); $format = "D, d M Y H:i:s"; $expiration = gmdate($format, time() + $params['cache']) . ' GMT'; $last_modified = time(); header('Cache-Control: public, cache, max-age=' . $params['cache']); header("Expires: $expiration"); header('Pragma: public'); // Getting headers sent by the client. - $headers = $this->_requestHeaders(); + $headers = $this->Application->HttpQuery->getHeaders(); // Checking if the client is validating his cache and if it is current. if ( isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) > $last_modified - $params['cache']) ) { // Client's cache IS current, so we just respond '304 Not Modified'. header('Last-Modified: ' . date($format, strtotime($headers['If-Modified-Since'])) . ' GMT', true, 304); exit; } else { // Image not cached or cache outdated, we respond '200 OK' and output the image. header('Last-Modified: ' . gmdate($format, $last_modified) . ' GMT', true, 200); } } // xml documents are usually long kUtil::setResourceLimit(); if ( !$this->Application->GetVar('debug') ) { return $this->Application->XMLHeader(getArrayValue($params, 'xml_version')); } return ''; } - protected function _requestHeaders() - { - if ( function_exists('apache_request_headers') ) { - // If apache_request_headers() exists... - $headers = apache_request_headers(); - - if ($headers) { - return $headers; // And works... Use it - } - } - - $headers = Array (); - - foreach (array_keys($_SERVER) as $skey) { - if (substr($skey, 0, 5) == 'HTTP_') { - $headername = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($skey, 0, 5))))); - $headers[$headername] = $_SERVER[$skey]; - } - } - - return $headers; - } - function Header($params) { header($params['data']); } function NoDebug($params) { if ( !$this->Application->GetVar('debug') ) { kUtil::safeDefine('DBG_SKIP_REPORTING', 1); } } /** * Returns Home category name * * @param Array $params * @return string * @deprecated */ function RootCategoryName($params) { $no_editing = array_key_exists('no_editing', $params) && $params['no_editing']; return $this->Application->Phrase('la_rootcategory_name', !$no_editing); } /** * Allows to attach file directly from email event template * * @param Array $params */ function AttachFile($params) { $path = FULL_PATH . '/' . $params['path']; $pseudo = isset($params['special']) ? 'EmailSender.' . $params['special'] : 'EmailSender'; $esender = $this->Application->recallObject($pseudo); /* @var $esender kEmailSendingHelper */ if ( file_exists($path) && is_file($path) ) { $esender->AddAttachment($path); } } function CaptchaImage($params) { $this->NoDebug($params); $this->Application->SetVar('skip_last_template', 1); $captcha_helper = $this->Application->recallObject('CaptchaHelper'); /* @var $captcha_helper kCaptchaHelper */ // generate captcha code $code = $captcha_helper->prepareCode( $this->Application->GetVar('var') ); $captcha_helper->GenerateCaptchaImage($code, $this->Application->GetVar('w'), $this->Application->GetVar('h'), true); } function SID($params) { return $this->Application->GetSID(); } function ModuleInfo($params) { return $this->Application->findModule($params['key'], $params['value'], $params['return']); } function Random($params) { return rand(1, 100000000); } /** * Prints parser params, available at current deep level * * @param Array $params * @return string */ function PrintCurrentParams($params) { $current_params = $this->Application->Parser->Params; foreach ($current_params as $param_name => $param_value) { if ( is_object($param_value) && !method_exists($param_value, '__toString') ) { $param_value = 'ClassName: ' . get_class($param_value); } $current_params[$param_name] = $param_name . ' = "' . $param_value . '"'; } return '
' . implode("\n", $current_params) . '
'; } /** * Gets previously defined counter result * * @param Array $params * @return int */ function GetCounter($params) { return $this->Application->getCounter($params['name'], $params); } /** * Increments PageHit counter * * @param Array $params * @return int */ function RegisterPageHit($params) { if ($this->Application->ConfigValue('UsePageHitCounter')) { // get current counte $sql = 'SELECT VariableValue FROM '.TABLE_PREFIX.'SystemSettings WHERE VariableName = "PageHitCounter"'; $page_counter = (int)$this->Conn->GetOne($sql); $sql = 'UPDATE LOW_PRIORITY '.TABLE_PREFIX.'SystemSettings SET VariableValue = '.($page_counter + 1).' WHERE VariableName = "PageHitCounter"'; $this->Conn->Query($sql); } } function Timestamp($params) { $format = isset($params['format']) ? $params['format'] : 'd.m.Y H:i:s'; return adodb_date($format); } function GetUrlHiddenFileds($params) { $vars = Array ('page', 'per_page', 'sort_by'); $ret = ''; if (array_key_exists('skip', $params)) { $vars = array_diff($vars, $params['skip']); } foreach ($vars as $var_name) { $var_value = $this->Application->GetVar($var_name); if ($var_value) { $ret .= ''; } } return $ret; } /** * Returns current Page URL (without re-assembling it). * "skip_query" param is optional and will remove the ?QUERY part from the result. * * @param Array $params * @return string * @access protected */ protected function CurrentPageLink($params) { if ( isset($params['skip_query']) && $params['skip_query'] ) { return preg_replace('/\?' . preg_quote($_SERVER['QUERY_STRING'], '/') . '$/', '', $_SERVER['REQUEST_URI']); } return $_SERVER['REQUEST_URI']; } /** * Returns current maintenance mode state * * @param Array $params * @return int * @access protected */ protected function MaintenanceMode($params) { $check_ips = isset($params['check_ips']) ? $params['check_ips'] : true; return $this->Application->getMaintenanceMode($check_ips); } /** * Checks if element with given name is defined * * @param Array $params * @return int * @access protected */ protected function ElementDefined($params) { return $this->Application->Parser->blockFound($params['name']); } } Index: branches/5.2.x/core/kernel/utility/http_query.php =================================================================== --- branches/5.2.x/core/kernel/utility/http_query.php (revision 16433) +++ branches/5.2.x/core/kernel/utility/http_query.php (revision 16434) @@ -1,818 +1,808 @@ Order = $order; if ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // when AJAX request is made from jQuery, then create ajax variable, // so any logic based in it (like redirects) will not break down $_GET['ajax'] = 'yes'; } $vars = kUtil::getConfigVars(); $this->_trustProxy = isset($vars['TrustProxy']) ? (bool)$vars['TrustProxy'] : false; } /** * Discovers unit form request and returns it's QueryString option on success * * @param string $prefix_special * * @return Array|bool * @access public */ public function discoverUnit($prefix_special) { list($prefix) = explode('.', $prefix_special); $query_string = $this->getQueryString($prefix); if ($query_string) { // only units with QueryString option can be discovered $this->discoveredUnits[$prefix_special] = $query_string; return $query_string; } unset( $this->discoveredUnits[$prefix] ); return false; } /** * Returns units, passed in request * * @param bool $prefix_special_only * @return Array * @access protected */ public function getDiscoveredUnits($prefix_special_only = true) { return $prefix_special_only ? array_keys( $this->discoveredUnits ) : $this->discoveredUnits; } /** * Returns QueryMap for requested unit config. * In case if unit config is a clone, then get parent item's (from prefix) config to create clone * * @param string $prefix * @return Array * @access protected */ protected function getQueryString($prefix) { $ret = $this->Application->getUnitOption($prefix, 'QueryString', Array ()); if ( !$ret && preg_match('/(.*?)-(.*)/', $prefix, $regs) ) { // "#prefix" (new format), "prefix" (old format) return $this->_getQueryString('#' . $regs[2]); } return $ret; } /** * Returns query string (with safety check against missing prefixes) * * @param string $prefix * @return Array */ private function _getQueryString($prefix) { if ( $this->Application->prefixRegistred($prefix) ) { return $this->Application->getUnitOption($prefix, 'QueryString'); } return substr($prefix, 0, 1) == '#' ? $this->_getQueryString( substr($prefix, 1) ) : Array (); } /** * Removes specials from request * * @param Array $array * @return Array * @access protected */ protected function _removeSpecials($array) { $ret = Array (); $removed = false; foreach ($this->specialsToRemove as $prefix_special => $flag) { if ( $flag ) { $removed = true; list ($prefix, $special) = explode('.', $prefix_special, 2); foreach ($array as $key => $val) { $new_key = preg_match("/^" . $prefix . "[._]{1}" . $special . "(.*)/", $key, $regs) ? $prefix . $regs[1] : $key; $ret[$new_key] = is_array($val) ? $this->_removeSpecials($val) : $val; } } } return $removed ? $ret : $array; } public function process() { $this->AddAllVars(); $this->removeSpecials(); ini_set('magic_quotes_gpc', 0); $this->Application->UrlManager->LoadStructureTemplateMapping(); $this->AfterInit(); } /** * All all requested vars to * common storage place * * @return void * @access protected */ protected function AddAllVars() { for ($i = 0; $i < strlen($this->Order); $i++) { switch ($this->Order[$i]) { case 'G': $this->Get = $this->AddVars($_GET); if ( array_key_exists('sid', $_GET) ) { $this->_sidInQueryString = true; } $vars = $this->Application->processQueryString($this->Get(ENV_VAR_NAME)); if ( array_key_exists('sid', $vars) ) { // used by Session::GetPassedSIDValue $this->Get['sid'] = $vars['sid']; } $this->AddParams($vars); break; case 'P': $this->Post = $this->AddVars($_POST); $this->convertPostEvents(); $this->_processPostEnvVariables(); break; case 'C': $this->Cookie = $this->AddVars($_COOKIE); break; /*case 'E'; $this->Env = $this->AddVars($_ENV, false); //do not strip slashes! break; case 'S'; $this->Server = $this->AddVars($_SERVER, false); //do not strip slashes! break;*/ case 'F'; $this->convertFiles(); $this->Files = $this->MergeVars($_FILES); // , false); //do not strip slashes! break; } } } /** * Allow POST variables, that names were transformed by PHP ("." replaced with "_") to * override variables, that were virtually created through environment variable parsing * */ function _processPostEnvVariables() { $passed = $this->Get('passed'); if ( !$passed ) { return; } $passed = explode(',', $passed); foreach ($passed as $prefix_special) { if ( strpos($prefix_special, '.') === false ) { continue; } list ($prefix, $special) = explode('.', $prefix_special); $query_map = $this->getQueryString($prefix); $post_prefix_special = $prefix . '_' . $special; foreach ($query_map as $var_name) { if ( array_key_exists($post_prefix_special . '_' . $var_name, $this->Post) ) { $this->Set($prefix_special . '_' . $var_name, $this->Post[$post_prefix_special . '_' . $var_name]); } } } } /** * Removes requested specials from all request variables * * @return void * @access protected */ protected function removeSpecials() { $this->specialsToRemove = $this->Get('remove_specials'); if ( $this->specialsToRemove ) { foreach ($this->specialsToRemove as $prefix_special => $flag) { if ( $flag && strpos($prefix_special, '.') === false ) { unset($this->specialsToRemove[$prefix_special]); trigger_error('Incorrect usage of "remove_specials[' . $prefix_special . ']" field (no special found)', E_USER_NOTICE); } } $this->_Params = $this->_removeSpecials($this->_Params); } } /** * Finishes initialization of kHTTPQuery class * * @return void * @access protected * @todo: only uses build-in rewrite listeners, when cache is build for the first time */ protected function AfterInit() { $rewrite_url = $this->Get('_mod_rw_url_'); if ( $this->Application->RewriteURLs() || $rewrite_url ) { // maybe call onafterconfigread here $this->Application->UrlManager->initRewrite(); if ( defined('DEBUG_MODE') && $this->Application->isDebugMode() ) { $this->Application->Debugger->profileStart('url_parsing', 'Parsing MOD_REWRITE url'); $this->Application->UrlManager->rewrite->parseRewriteURL(); $description = 'Parsing MOD_REWRITE url (template: ' . $this->Get('t') . ')'; $this->Application->Debugger->profileFinish('url_parsing', $description); } else { $this->Application->UrlManager->rewrite->parseRewriteURL(); } if ( !$rewrite_url && $this->rewriteRedirectRequired() ) { // rewrite url is missing (e.g. not a script from tools folder) $url_params = $this->getRedirectParams(); // no idea about how to check, that given template require category to be passed with it, so pass anyway $url_params['pass_category'] = 1; $url_params['response_code'] = 301; // Moved Permanently trigger_error('Non mod-rewrite url "' . $_SERVER['REQUEST_URI'] . '" used', E_USER_NOTICE); $this->Application->Redirect('', $url_params); } } else { $this->Application->VerifyThemeId(); $this->Application->VerifyLanguageId(); } $virtual_template = $this->Application->getVirtualPageTemplate($this->Get('m_cat_id')); if ( ($virtual_template !== false) && preg_match('/external:(.*)/', $virtual_template) ) { trigger_error('URL of page, that has "External URL" set was accessed: "' . $_SERVER['REQUEST_URI'] . '"', E_USER_NOTICE); $this->Application->Redirect($virtual_template); } } /** * Checks, that non-rewrite url was visited and it's automatic rewrite is required * * @return bool */ function rewriteRedirectRequired() { $redirect_conditions = Array ( !$this->IsHTTPSRedirect(), // not https <-> http redirect !$this->refererIsOurSite(), // referer doesn't match ssl path or non-ssl domain (same for site domains) !defined('GW_NOTIFY'), // not in payment gateway notification script preg_match('/[\/]{0,1}index.php[\/]{0,1}/', $_SERVER['PHP_SELF']), // "index.php" was visited $this->Get('t') != 'index', // not on index page ); $perform_redirect = true; foreach ($redirect_conditions as $redirect_condition) { $perform_redirect = $perform_redirect && $redirect_condition; if (!$perform_redirect) { return false; } } return true; } /** * This is redirect from https to http or via versa * * @return bool */ function IsHTTPSRedirect() { $http_referer = array_key_exists('HTTP_REFERER', $_SERVER) ? $_SERVER['HTTP_REFERER'] : false; return ( ( PROTOCOL == 'https://' && preg_match('#http:\/\/#', $http_referer) ) || ( PROTOCOL == 'http://' && preg_match('#https:\/\/#', $http_referer) ) ); } /** * Checks, that referer is out site * * @return bool */ function refererIsOurSite() { if ( !array_key_exists('HTTP_REFERER', $_SERVER) ) { // no referer -> don't care what happens return false; } $site_helper = $this->Application->recallObject('SiteHelper'); /* @var $site_helper SiteHelper */ $found = false; $http_referer = $_SERVER['HTTP_REFERER']; preg_match('/^(.*?):\/\/(.*?)(\/|$)/', $http_referer, $regs); // 1 - protocol, 2 - domain if ($regs[1] == 'https') { $found = $site_helper->getDomainByName('SSLUrl', $http_referer) > 0; if (!$found) { // check if referer starts with our ssl url $ssl_url = $this->Application->ConfigValue('SSL_URL'); $found = $ssl_url && preg_match('/^' . preg_quote($ssl_url, '/') . '/', $http_referer); } } else { $found = $site_helper->getDomainByName('DomainName', $regs[2]) > 0; if (!$found) { $found = $regs[2] == DOMAIN; } } return $found; } function convertFiles() { if ( !$_FILES ) { return ; } $tmp = Array (); $file_keys = Array ('error', 'name', 'size', 'tmp_name', 'type'); foreach ($_FILES as $file_name => $file_info) { if ( is_array($file_info['error']) ) { $tmp[$file_name] = $this->getArrayLevel($file_info['error'], $file_name); } else { $normal_files[$file_name] = $file_info; } } if ( !$tmp ) { return ; } $files = $_FILES; $_FILES = Array (); foreach ($tmp as $prefix => $prefix_files) { $anchor =& $_FILES; foreach ($prefix_files['keys'] as $key) { $anchor =& $anchor[$key]; } foreach ($prefix_files['value'] as $field_name) { unset($inner_anchor, $copy); $work_copy = $prefix_files['keys']; foreach ($file_keys as $file_key) { $inner_anchor =& $files[$prefix][$file_key]; if ( isset($copy) ) { $work_copy = $copy; } else { $copy = $work_copy; } array_shift($work_copy); foreach ($work_copy as $prefix_file_key) { $inner_anchor =& $inner_anchor[$prefix_file_key]; } $anchor[$field_name][$file_key] = $inner_anchor[$field_name]; } } } // keys: img_temp, 0, values: LocalPath, ThumbPath } function getArrayLevel(&$level, $prefix='') { $ret['keys'] = $prefix ? Array($prefix) : Array(); $ret['value'] = Array(); foreach($level as $level_key => $level_value) { if( is_array($level_value) ) { $ret['keys'][] = $level_key; $tmp = $this->getArrayLevel($level_value); $ret['keys'] = array_merge($ret['keys'], $tmp['keys']); $ret['value'] = array_merge($ret['value'], $tmp['value']); } else { $ret['value'][] = $level_key; } } return $ret; } /** * Overwrites GET events with POST events in case if they are set and not empty * * @return void * @access protected */ protected function convertPostEvents() { $events = $this->Get('events', Array ()); /* @var $events Array */ if ( is_array($events) ) { $events = array_filter($events); foreach ($events as $prefix_special => $event_name) { $this->Set($prefix_special . '_event', $event_name); } } } function finalizeParsing($passed = Array()) { if (!$passed) { return; } foreach ($passed as $passed_prefix) { $this->discoverUnit($passed_prefix); // from mod-rewrite url parsing } $this->Set('passed', implode(',', $this->getDiscoveredUnits())); } /** * Saves variables from array specified * into common variable storage place * * @param Array $array * @param bool $strip_slashes * @return Array * @access private */ function AddVars($array, $strip_slashes = true) { if ( $strip_slashes ) { $array = $this->StripSlashes($array); } foreach ($array as $key => $value) { $this->Set($key, $value); } return $array; } function MergeVars($array, $strip_slashes = true) { if ( $strip_slashes ) { $array = $this->StripSlashes($array); } foreach ($array as $key => $value_array) { // $value_array is an array too $this->_Params = kUtil::array_merge_recursive($this->_Params, Array ($key => $value_array)); } return $array; } function StripSlashes($array) { static $magic_quotes = null; if (!isset($magic_quotes)) { $magic_quotes = get_magic_quotes_gpc(); } foreach ($array as $key => $value) { if (is_array($value)) { $array[$key] = $this->StripSlashes($value); } else { if ($magic_quotes) { $value = stripslashes($value); } if (!$this->Application->isAdmin) { // TODO: always escape output instead of input $value = kUtil::escape($value, kUtil::ESCAPE_HTML); } $array[$key] = $value; } } return $array; } /** * Removes forceful escaping done to the variable upon Front-End submission. * * @param string|array $value Value. * * @return string|array * @see StripSlashes */ public function unescapeRequestVariable($value) { if ( $this->Application->isAdmin ) { return $value; } // This allows to revert kUtil::escape() call for each field submitted on front-end. if ( is_array($value) ) { foreach ( $value as $param_name => $param_value ) { $value[$param_name] = $this->unescapeRequestVariable($param_value); } return $value; } return kUtil::unescape($value, kUtil::ESCAPE_HTML); } /** * Returns all $_GET array excluding system parameters, that are not allowed to be passed through generated urls * * @param bool $access_error Method is called during no_permission, require login, session expiration link preparation * @return Array */ function getRedirectParams($access_error = false) { $vars = $this->Get; $unset_vars = Array (ENV_VAR_NAME, 'rewrite', '_mod_rw_url_', 'Action'); if (!$this->_sidInQueryString) { $unset_vars[] = 'sid'; } // remove system variables foreach ($unset_vars as $var_name) { if (array_key_exists($var_name, $vars)) { unset($vars[$var_name]); } } if ($access_error) { // place 1 of 2 (also in UsersEventHandler::OnSessionExpire) $vars = $this->_removePassThroughVariables($vars); } return $vars; } /** * Removes all pass_though variables from redirect params * * @param Array $url_params * @return Array */ function _removePassThroughVariables($url_params) { $pass_through = array_key_exists('pass_through', $url_params) ? $url_params['pass_through'] : ''; if (!$pass_through) { return $url_params; } $pass_through = explode(',', $pass_through . ',pass_through'); foreach ($pass_through as $pass_through_var) { unset($url_params[$pass_through_var]); } $url_params['no_pass_through'] = 1; // this way kApplication::HREF won't add them again return $url_params; } - function writeRequestLog($filename) - { - $log_file = (defined('RESTRICTED') ? RESTRICTED : FULL_PATH) . '/' . $filename; - - if ( is_writable(dirname($log_file)) ) { - $fp = fopen($log_file, 'a'); - - if ( $fp ) { - $session = $this->Application->recallObject('Session'); - /* @var $session Session */ - - $user_id = $session->GetField('PortalUserId'); - $admin_mark = $this->Application->isAdmin ? 'ADMIN' : 'FRONT'; - - $data = '[' . date('D M d H:i:s Y') . '] ' . $admin_mark . '; ip: ' . $this->getClientIp() . '; user_id: ' . $user_id . '; sid: ' . $this->Application->GetSID() . '; request: ' . "\n"; - if ( $this->Get ) { - $data .= "_GET:\n" . print_r($this->Get, true); - } - - if ( $this->Post ) { - $data .= "_POST:\n" . print_r($this->Post, true); - } - - if ( $this->Cookie ) { - $data .= "_COOKIE:\n" . print_r($this->Cookie, true); - } - $data .= str_repeat('=', 100) . "\n"; - - fwrite($fp, $data); - fclose($fp); - } - else { - trigger_error('Request Log directory not writable', E_USER_WARNING); - } - } - else { - trigger_error('Request Log directory not writable', E_USER_WARNING); - } - } - /** * Checks, that url is empty * * @return bool * @access public */ public function isEmptyUrl() { if ( $this->Application->RewriteURLs() ) { return !$this->Get('_mod_rw_url_'); } return !count($this->Get); } /** * Returns the client IP address. * * @return string The client IP address * @access public */ public function getClientIp() { if ( $this->_trustProxy ) { if ( array_key_exists('HTTP_CLIENT_IP', $_SERVER) ) { return $_SERVER['HTTP_CLIENT_IP']; } if ( array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER) ) { $client_ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); foreach ($client_ip as $ip_address) { $clean_ip_address = trim($ip_address); if ( false !== filter_var($clean_ip_address, FILTER_VALIDATE_IP) ) { return $clean_ip_address; } } return ''; } } return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : ''; } + + /** + * Returns headers + * + * @return array + * @access public + */ + public function getHeaders() + { + if ( function_exists('apache_request_headers') ) { + // If apache_request_headers() exists... + $headers = apache_request_headers(); + + if ( $headers ) { + return $headers; // And works... Use it + } + } + + $headers = array(); + + foreach ( array_keys($_SERVER) as $server_key ) { + if ( substr($server_key, 0, 5) == 'HTTP_' ) { + $header_name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($server_key, 0, 5))))); + $headers[$header_name] = $_SERVER[$server_key]; + } + } + + return $headers; + } + } Index: branches/5.2.x/core/kernel/utility/logger.php =================================================================== --- branches/5.2.x/core/kernel/utility/logger.php (revision 16433) +++ branches/5.2.x/core/kernel/utility/logger.php (revision 16434) @@ -1,1401 +1,1404 @@ _debugMode = $this->Application->isDebugMode(); $this->setState(isset($vars['EnableSystemLog']) ? $vars['EnableSystemLog'] : self::STATE_DISABLED); $this->_maxLogLevel = isset($vars['SystemLogMaxLevel']) ? (int)$vars['SystemLogMaxLevel'] : self::LL_NOTICE; foreach ($methods_to_call as $method_to_call) { call_user_func_array(Array ($this, $method_to_call[0]), $method_to_call[1]); } if ( !kUtil::constOn('DBG_ZEND_PRESENT') && !$this->Application->isDebugMode() ) { // don't report error on screen if debug mode is turned off error_reporting(0); ini_set('display_errors', 0); } register_shutdown_function(Array ($this, 'catchLastError')); } /** * Sets state of the logged (enabled/user-only/disabled) * * @param $new_state * @return void * @access public */ public function setState($new_state = null) { if ( isset($new_state) ) { $this->_state = (int)$new_state; } if ( $this->_state === self::STATE_ENABLED ) { $this->_enableErrorHandling(); } elseif ( $this->_state === self::STATE_DISABLED ) { $this->_disableErrorHandling(); } } /** * Enable error/exception handling capabilities * * @return void * @access protected */ protected function _enableErrorHandling() { $this->_disableErrorHandling(); $this->_handlers[self::LL_ERROR] = new kErrorHandlerStack($this); $this->_handlers[self::LL_CRITICAL] = new kExceptionHandlerStack($this); } /** * Disables error/exception handling capabilities * * @return void * @access protected */ protected function _disableErrorHandling() { foreach ($this->_handlers as $index => $handler) { $this->_handlers[$index]->__destruct(); unset($this->_handlers[$index]); } } /** * Initializes new log record. Use "kLogger::write" to save to db/disk * * @param string $message * @param int $code * @return kLogger * @access public */ public function prepare($message = '', $code = null) { $this->_logRecord = Array ( 'LogUniqueId' => kUtil::generateId(), 'LogMessage' => $message, 'LogLevel' => self::LL_INFO, 'LogCode' => $code, 'LogType' => self::LT_OTHER, 'LogHostname' => $_SERVER['HTTP_HOST'], 'LogRequestSource' => php_sapi_name() == 'cli' ? 2 : 1, 'LogRequestURI' => php_sapi_name() == 'cli' ? implode(' ', $GLOBALS['argv']) : $_SERVER['REQUEST_URI'], 'LogUserId' => USER_GUEST, 'IpAddress' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '', 'LogSessionKey' => 0, 'LogProcessId' => getmypid(), 'LogUserData' => '', 'LogNotificationStatus' => self::LNS_DISABLED, ); if ( $this->Application->isAdmin ) { $this->_logRecord['LogInterface'] = defined('CRON') && CRON ? self::LI_CRON_ADMIN : self::LI_ADMIN; } else { $this->_logRecord['LogInterface'] = defined('CRON') && CRON ? self::LI_CRON_FRONT : self::LI_FRONT; } if ( $this->Application->InitDone ) { $this->_logRecord['LogUserId'] = $this->Application->RecallVar('user_id'); $this->_logRecord['LogSessionKey'] = $this->Application->GetSID(); $this->_logRecord['IpAddress'] = $this->Application->getClientIp(); } return $this; } /** * Sets one or more fields of log record * * @param string|Array $field_name * @param string|null $field_value * @return kLogger * @access public * @throws UnexpectedValueException */ public function setLogField($field_name, $field_value = null) { if ( isset($field_value) ) { $this->_logRecord[$field_name] = $field_value; } elseif ( is_array($field_name) ) { $this->_logRecord = array_merge($this->_logRecord, $field_name); } else { throw new UnexpectedValueException('Invalid arguments'); } return $this; } /** * Sets user data * * @param string $data * @param bool $as_array * @return kLogger * @access public */ public function setUserData($data, $as_array = false) { if ( $as_array ) { $data = serialize((array)$data); } return $this->setLogField('LogUserData', $data); } /** * Add user data * * @param string $data * @param bool $as_array * @return kLogger * @access public */ public function addUserData($data, $as_array = false) { $new_data = $this->_logRecord['LogUserData']; if ( $as_array ) { $new_data = $new_data ? unserialize($new_data) : Array (); $new_data[] = $data; $new_data = serialize($new_data); } else { $new_data .= ($new_data ? PHP_EOL : '') . $data; } return $this->setLogField('LogUserData', $new_data); } /** * Adds event to log record * * @param kEvent $event * @return kLogger * @access public */ public function addEvent(kEvent $event) { $this->_logRecord['LogEventName'] = (string)$event; return $this; } /** * Adds log source file & file to log record * * @param string|Array $file_or_trace file path * @param int $line file line * @return kLogger * @access public */ public function addSource($file_or_trace = '', $line = 0) { if ( is_array($file_or_trace) ) { $trace_info = $file_or_trace[0]; $this->_logRecord['LogSourceFilename'] = $trace_info['file']; $this->_logRecord['LogSourceFileLine'] = $trace_info['line']; } else { $this->_logRecord['LogSourceFilename'] = $file_or_trace; $this->_logRecord['LogSourceFileLine'] = $line; } return $this; } /** * Adds session contents to log record * * @param bool $include_optional Include optional session variables * @return kLogger * @access public */ public function addSessionData($include_optional = false) { if ( $this->Application->InitDone ) { $this->_logRecord['LogSessionData'] = serialize($this->Application->Session->getSessionData($include_optional)); } return $this; } /** * Adds user request information to log record * * @return kLogger * @access public */ public function addRequestData() { - $request_data = Array (); - $request_variables = Array ('_GET' => $_GET, '_POST' => $_POST, '_COOKIE' => $_COOKIE); + $request_data = array( + 'Headers' => $this->Application->HttpQuery->getHeaders(), + ); + + $request_variables = Array('_GET' => $_GET, '_POST' => $_POST, '_COOKIE' => $_COOKIE); - foreach ($request_variables as $title => $data) { + foreach ( $request_variables as $title => $data ) { if ( !$data ) { continue; } $request_data[$title] = $data; } $this->_logRecord['LogRequestData'] = serialize($request_data); return $this; } /** * Adds trace to log record * * @param Array $trace * @param int $skip_levels * @param Array $skip_files * @return kLogger * @access public */ public function addTrace($trace = null, $skip_levels = 1, $skip_files = null) { $trace = $this->createTrace($trace, $skip_levels, $skip_files); foreach ($trace as $trace_index => $trace_info) { if ( isset($trace_info['args']) ) { $trace[$trace_index]['args'] = $this->_implodeObjects($trace_info['args']); } } $this->_logRecord['LogBacktrace'] = serialize($this->_removeObjectsFromTrace($trace)); return $this; } /** * Remove objects from trace, since before PHP 5.2.5 there wasn't possible to remove them initially * * @param Array $trace * @return Array * @access protected */ protected function _removeObjectsFromTrace($trace) { if ( version_compare(PHP_VERSION, '5.3', '>=') ) { return $trace; } $trace_indexes = array_keys($trace); foreach ($trace_indexes as $trace_index) { unset($trace[$trace_index]['object']); } return $trace; } /** * Implodes object to prevent memory leaks * * @param Array $array * @return Array * @access protected */ protected function _implodeObjects($array) { $ret = Array (); foreach ($array as $key => $value) { if ( is_array($value) ) { $ret[$key] = $this->_implodeObjects($value); } elseif ( is_object($value) ) { if ( $value instanceof kEvent ) { $ret[$key] = 'Event: ' . (string)$value; } elseif ( $value instanceof kBase ) { $ret[$key] = (string)$value; } else { $ret[$key] = 'Class: ' . get_class($value); } } elseif ( strlen($value) > 200 ) { $ret[$key] = substr($value, 0, 50) . ' ...'; } else { $ret[$key] = $value; } } return $ret; } /** * Removes first N levels from trace * * @param Array $trace * @param int $levels * @param Array $files * @return Array * @access public */ public function createTrace($trace = null, $levels = null, $files = null) { if ( !isset($trace) ) { $trace = debug_backtrace(false); } if ( !$trace ) { // no trace information return $trace; } if ( isset($levels) && is_numeric($levels) ) { for ($i = 0; $i < $levels; $i++) { array_shift($trace); } } if ( isset($files) && is_array($files) ) { while (true) { $trace_info = $trace[0]; $file = isset($trace_info['file']) ? basename($trace_info['file']) : ''; if ( !in_array($file, $files) ) { break; } array_shift($trace); } } return $trace; } /** * Adds PHP error to log record * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @return kLogger * @access public */ public function addError($errno, $errstr, $errfile = null, $errline = null) { $errstr = self::expandMessage($errstr, !$this->_debugMode); $this->_logRecord['LogLevel'] = $this->_getLogLevelByErrorNo($errno); if ( $this->isLogType(self::LT_DATABASE, $errstr) ) { list ($errno, $errstr, $sql) = self::parseDatabaseError($errstr); $this->_logRecord['LogType'] = self::LT_DATABASE; $this->_logRecord['LogUserData'] = $sql; $trace = $this->createTrace(null, 4, $this->_ignoreInTrace); $this->addSource($trace); $this->addTrace($trace, 0); } else { $this->_logRecord['LogType'] = self::LT_PHP; $this->addSource((string)$errfile, $errline); $this->addTrace(null, 4); } $this->_logRecord['LogCode'] = $errno; $this->_logRecord['LogMessage'] = $errstr; return $this; } /** * Adds PHP exception to log record * * @param Exception $exception * @return kLogger * @access public */ public function addException($exception) { $errstr = self::expandMessage($exception->getMessage(), !$this->_debugMode); $this->_logRecord['LogLevel'] = self::LL_CRITICAL; $exception_trace = $exception->getTrace(); array_unshift($exception_trace, array( 'function' => '', 'file' => $exception->getFile() !== null ? $exception->getFile() : 'n/a', 'line' => $exception->getLine() !== null ? $exception->getLine() : 'n/a', 'args' => array(), )); if ( $this->isLogType(self::LT_DATABASE, $errstr) ) { list ($errno, $errstr, $sql) = self::parseDatabaseError($errstr); $this->_logRecord['LogType'] = self::LT_DATABASE; $this->_logRecord['LogUserData'] = $sql; $trace = $this->createTrace($exception_trace, null, $this->_ignoreInTrace); $this->addSource($trace); $this->addTrace($trace, 0); } else { $this->_logRecord['LogType'] = self::LT_PHP; $errno = $exception->getCode(); $this->addSource((string)$exception->getFile(), $exception->getLine()); $this->addTrace($exception_trace, 0); } $this->_logRecord['LogCode'] = $errno; $this->_logRecord['LogMessage'] = $errstr; return $this; } /** * Allows to map PHP error numbers to syslog log level * * @param int $errno * @return int * @access protected */ protected function _getLogLevelByErrorNo($errno) { $error_number_mapping = Array ( self::LL_ERROR => Array (E_RECOVERABLE_ERROR, E_USER_ERROR, E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE), self::LL_WARNING => Array (E_WARNING, E_USER_WARNING, E_CORE_WARNING, E_COMPILE_WARNING), self::LL_NOTICE => Array (E_NOTICE, E_USER_NOTICE, E_STRICT), ); if ( version_compare(PHP_VERSION, '5.3.0', '>=') ) { $error_number_mapping[self::LL_NOTICE][] = E_DEPRECATED; $error_number_mapping[self::LL_NOTICE][] = E_USER_DEPRECATED; } foreach ($error_number_mapping as $log_level => $error_numbers) { if ( in_array($errno, $error_numbers) ) { return $log_level; } } return self::LL_ERROR; } /** * Changes log level of a log record * * @param int $log_level * @return kLogger * @access public */ public function setLogLevel($log_level) { $this->_logRecord['LogLevel'] = $log_level; return $this; } /** * Writes prepared log to database or disk, when database isn't available * * @param int $storage_medium * @return bool|int * @access public * @throws InvalidArgumentException */ public function write($storage_medium = self::LS_AUTOMATIC) { if ( !$this->_logRecord || $this->_logRecord['LogLevel'] > $this->_maxLogLevel || $this->_state == self::STATE_DISABLED ) { // nothing to save OR less detailed logging requested OR disabled - return true; + return false; } $this->_logRecord['LogMemoryUsed'] = memory_get_usage(); $this->_logRecord['LogTimestamp'] = adodb_mktime(); $this->_logRecord['LogDate'] = adodb_date('Y-m-d H:i:s'); if ( $storage_medium == self::LS_AUTOMATIC ) { $storage_medium = $this->Conn->connectionOpened() ? self::LS_DATABASE : self::LS_DISK; } if ( $storage_medium == self::LS_DATABASE ) { $result = $this->Conn->doInsert($this->_logRecord, TABLE_PREFIX . 'SystemLog'); } elseif ( $storage_medium == self::LS_DISK ) { $result = $this->_saveToFile(RESTRICTED . '/system.log'); } else { throw new InvalidArgumentException('Unknown storage medium "' . $storage_medium . '"'); } $unique_id = $this->_logRecord['LogUniqueId']; if ( $this->_logRecord['LogNotificationStatus'] == self::LNS_SENT ) { $this->_sendNotification($unique_id); } $this->_logRecord = Array (); return $result ? $unique_id : false; } /** * Catches last error happened before script ended * * @return void * @access public */ public function catchLastError() { $this->write(); $last_error = error_get_last(); if ( !is_null($last_error) && isset($this->_handlers[self::LL_ERROR]) ) { $handler = $this->_handlers[self::LL_ERROR]; /* @var $handler kErrorHandlerStack */ $handler->handle($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']); } } /** * Deletes log with given id from database or disk, when database isn't available * * @param int $unique_id * @param int $storage_medium * @return void * @access public * @throws InvalidArgumentException */ public function delete($unique_id, $storage_medium = self::LS_AUTOMATIC) { if ( $storage_medium == self::LS_AUTOMATIC ) { $storage_medium = $this->Conn->connectionOpened() ? self::LS_DATABASE : self::LS_DISK; } if ( $storage_medium == self::LS_DATABASE ) { $sql = 'DELETE FROM ' . TABLE_PREFIX . 'SystemLog WHERE LogUniqueId = ' . $unique_id; $this->Conn->Query($sql); } elseif ( $storage_medium == self::LS_DISK ) { // TODO: no way to delete a line from a file } else { throw new InvalidArgumentException('Unknown storage medium "' . $storage_medium . '"'); } } /** * Send notification (delayed or instant) about log record to e-mail from configuration * * @param bool $instant * @return kLogger * @access public */ public function notify($instant = false) { $this->_logRecord['LogNotificationStatus'] = $instant ? self::LNS_SENT : self::LNS_PENDING; return $this; } /** * Sends notification e-mail about message with given $unique_id * * @param int $unique_id * @return void * @access protected */ protected function _sendNotification($unique_id) { $notification_email = $this->Application->ConfigValue('SystemLogNotificationEmail'); if ( !$notification_email ) { trigger_error('System Log notification E-mail not specified', E_USER_NOTICE); return; } $send_params = Array ( 'to_name' => $notification_email, 'to_email' => $notification_email, ); // initialize list outside of e-mail event with right settings $this->Application->recallObject('system-log.email', 'system-log_List', Array ('unique_id' => $unique_id)); $this->Application->emailAdmin('SYSTEM.LOG.NOTIFY', null, $send_params); $this->Application->removeObject('system-log.email'); } /** * Adds error/exception handler * * @param string|Array $handler * @param bool $is_exception * @return void * @access public */ public function addErrorHandler($handler, $is_exception = false) { $this->_handlers[$is_exception ? self::LL_CRITICAL : self::LL_ERROR]->add($handler); } /** * SQL Error Handler * * When not debug mode, then fatal database query won't break anything. * * @param int $code * @param string $msg * @param string $sql * @return bool * @access public * @throws RuntimeException */ public function handleSQLError($code, $msg, $sql) { $error_msg = self::shortenMessage(self::DB_ERROR_PREFIX . ' #' . $code . ' - ' . $msg . '. SQL: ' . trim($sql)); if ( isset($this->Application->Debugger) ) { if ( kUtil::constOn('DBG_SQL_FAILURE') && !defined('IS_INSTALL') ) { throw new RuntimeException($error_msg); } else { $this->Application->Debugger->appendTrace(); } } // next line also trigger attached error handlers trigger_error($error_msg, E_USER_WARNING); return true; } /** * Packs information about error into a single line * * @param string $errno * @param bool $strip_tags * @return string * @access public */ public function toString($errno = null, $strip_tags = false) { if ( !isset($errno) ) { $errno = $this->_logRecord['LogCode']; } $errstr = $this->_logRecord['LogMessage']; $errfile = $this->_logRecord['LogSourceFilename']; $errline = $this->_logRecord['LogSourceFileLine']; if ( PHP_SAPI === 'cli' ) { $result = sprintf(' [%s] ' . PHP_EOL . ' %s', $errno, $errstr); if ( $this->_logRecord['LogBacktrace'] ) { $result .= $this->printBacktrace(unserialize($this->_logRecord['LogBacktrace'])); } } else { $result = '' . $errno . ': ' . "{$errstr} in {$errfile} on line {$errline}"; } return $strip_tags ? strip_tags($result) : $result; } /** * Prints backtrace result * * @param array $trace Trace. * * @return string */ protected function printBacktrace(array $trace) { if ( !$trace ) { return ''; } $ret = PHP_EOL . PHP_EOL . PHP_EOL . 'Exception trace:' . PHP_EOL; foreach ( $trace as $trace_info ) { $class = isset($trace_info['class']) ? $trace_info['class'] : ''; $type = isset($trace_info['type']) ? $trace_info['type'] : ''; $function = $trace_info['function']; $args = isset($trace_info['args']) && $trace_info['args'] ? '...' : ''; $file = isset($trace_info['file']) ? $trace_info['file'] : 'n/a'; $line = isset($trace_info['line']) ? $trace_info['line'] : 'n/a'; $ret .= sprintf(' %s%s%s(%s) at %s:%s' . PHP_EOL, $class, $type, $function, $args, $file, $line); } return $ret; } /** * Saves log to file (e.g. when not possible to save into database) * * @param $filename * @return bool * @access protected */ protected function _saveToFile($filename) { $time = adodb_date('Y-m-d H:i:s'); $log_file = new SplFileObject($filename, 'a'); return $log_file->fwrite('[' . $time . '] #' . $this->toString(null, true) . PHP_EOL) > 0; } /** * Checks if log type of current log record matches given one * * @param int $log_type * @param string $log_message * @return bool * @access public */ public function isLogType($log_type, $log_message = null) { if ( $this->_logRecord['LogType'] == $log_type ) { return true; } if ( $log_type == self::LT_DATABASE ) { if ( !isset($log_message) ) { $log_message = $this->_logRecord['LogMessage']; } return strpos($log_message, self::DB_ERROR_PREFIX) !== false; } return false; } /** * Shortens message * * @param string $message * @return string * @access public */ public static function shortenMessage($message) { $max_len = ini_get('log_errors_max_len'); if ( strlen($message) > $max_len ) { $long_key = kUtil::generateId(); self::$_longMessages[$long_key] = $message; return mb_substr($message, 0, $max_len - strlen($long_key) - 2) . ' #' . $long_key; } return $message; } /** * Expands shortened message * * @param string $message * @param bool $clear_cache Allow debugger to expand message after it's been expanded by kLogger * @return string * @access public */ public static function expandMessage($message, $clear_cache = true) { if ( preg_match('/(.*)#([\d]+)$/', $message, $regs) ) { $long_key = $regs[2]; if ( isset(self::$_longMessages[$long_key]) ) { $message = self::$_longMessages[$long_key]; if ( $clear_cache ) { unset(self::$_longMessages[$long_key]); } } } return $message; } /** * Parses database error message into error number, error message and sql that caused that error * * @static * @param string $message * @return Array * @access public */ public static function parseDatabaseError($message) { $regexp = '/' . preg_quote(self::DB_ERROR_PREFIX) . ' #(.*?) - (.*?)\. SQL: (.*?)$/s'; if ( preg_match($regexp, $message, $regs) ) { // errno, errstr, sql return Array ($regs[1], $regs[2], $regs[3]); } return Array (0, $message, ''); } } /** * Base class for error or exception handling */ abstract class kHandlerStack extends kBase { /** * List of added handlers * * @var Array * @access protected */ protected $_handlers = Array (); /** * Reference to event log, which created this object * * @var kLogger * @access protected */ protected $_logger; /** * Remembers if handler is activated * * @var bool * @access protected */ protected $_enabled = false; public function __construct(kLogger $logger) { parent::__construct(); $this->_logger = $logger; if ( !kUtil::constOn('DBG_ZEND_PRESENT') ) { $this->attach(); $this->_enabled = true; } } /** * Detaches from error handling routines on class destruction * * @return void * @access public */ public function __destruct() { if ( !$this->_enabled ) { return; } $this->detach(); $this->_enabled = false; } /** * Attach to error handling routines * * @abstract * @return void * @access protected */ abstract protected function attach(); /** * Detach from error handling routines * * @abstract * @return void * @access protected */ abstract protected function detach(); /** * Adds new handler to the stack * * @param callable $handler * @return void * @access public */ public function add($handler) { $this->_handlers[] = $handler; } protected function _handleFatalError($errno) { $debug_mode = defined('DEBUG_MODE') && DEBUG_MODE; $skip_reporting = defined('DBG_SKIP_REPORTING') && DBG_SKIP_REPORTING; if ( !$this->_handlers || ($debug_mode && $skip_reporting) ) { // when debugger absent OR it's present, but we actually can't see it's error report (e.g. during ajax request) if ( $this->_isFatalError($errno) ) { $this->_displayFatalError($errno); } if ( !$this->_handlers ) { return true; } } return null; } /** * Determines if given error is a fatal * * @abstract * @param Exception|int $errno * @return bool */ abstract protected function _isFatalError($errno); /** * Displays div with given error message * * @param string $errno * @return void * @access protected */ protected function _displayFatalError($errno) { $errno = $this->_getFatalErrorTitle($errno); $margin = $this->Application->isAdmin ? '8px' : 'auto'; $error_msg = $this->_logger->toString($errno, PHP_SAPI === 'cli'); if ( PHP_SAPI === 'cli' ) { echo $error_msg; } else { echo '
' . $error_msg . '
'; } exit; } /** * Returns title to show for a fatal * * @abstract * @param Exception|int $errno * @return string */ abstract protected function _getFatalErrorTitle($errno); } /** * Class, that handles errors */ class kErrorHandlerStack extends kHandlerStack { /** * Attach to error handling routines * * @return void * @access protected */ protected function attach() { // set as error handler $error_handler = set_error_handler(Array ($this, 'handle')); if ( $error_handler ) { // wrap around previous error handler, if any was set $this->_handlers[] = $error_handler; } } /** * Detach from error handling routines * * @return void * @access protected */ protected function detach() { restore_error_handler(); } /** * Determines if given error is a fatal * * @param int $errno * @return bool * @access protected */ protected function _isFatalError($errno) { $fatal_errors = Array (E_USER_ERROR, E_RECOVERABLE_ERROR, E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_PARSE); return in_array($errno, $fatal_errors); } /** * Returns title to show for a fatal * * @param int $errno * @return string * @access protected */ protected function _getFatalErrorTitle($errno) { return 'Fatal Error'; } /** * Default error handler * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param Array $errcontext * @return bool * @access public */ public function handle($errno, $errstr, $errfile = null, $errline = null, $errcontext = Array ()) { $log = $this->_logger->prepare()->addError($errno, $errstr, $errfile, $errline); if ( $this->_handleFatalError($errno) ) { $log->write(); return true; } $log->write(); $res = false; foreach ($this->_handlers as $handler) { $res = call_user_func($handler, $errno, $errstr, $errfile, $errline, $errcontext); } return $res; } } /** * Class, that handles exceptions */ class kExceptionHandlerStack extends kHandlerStack { /** * Attach to error handling routines * * @return void * @access protected */ protected function attach() { // set as exception handler $exception_handler = set_exception_handler(Array ($this, 'handle')); if ( $exception_handler ) { // wrap around previous exception handler, if any was set $this->_handlers[] = $exception_handler; } } /** * Detach from error handling routines * * @return void * @access protected */ protected function detach() { restore_exception_handler(); } /** * Determines if given error is a fatal * * @param Exception $errno * @return bool */ protected function _isFatalError($errno) { return true; } /** * Returns title to show for a fatal * * @param Exception $errno * @return string */ protected function _getFatalErrorTitle($errno) { return get_class($errno); } /** * Handles exception * * @param Exception $exception * @return bool * @access public */ public function handle($exception) { $log = $this->_logger->prepare()->addException($exception); if ( $exception instanceof kRedirectException ) { /* @var $exception kRedirectException */ $exception->run(); } if ( $this->_handleFatalError($exception) ) { $log->write(); return true; } $log->write(); $res = false; foreach ($this->_handlers as $handler) { $res = call_user_func($handler, $exception); } return $res; } } Index: branches/5.2.x/core/units/admin/admin_events_handler.php =================================================================== --- branches/5.2.x/core/units/admin/admin_events_handler.php (revision 16433) +++ branches/5.2.x/core/units/admin/admin_events_handler.php (revision 16434) @@ -1,1249 +1,1267 @@ Array ('self' => true), 'OnGetPopupSize' => Array ('self' => true), 'OnClosePopup' => Array ('self' => true), 'OnSaveSetting' => Array ('self' => true), 'OnDropTempTablesByWID' => Array ('self' => true), 'OnProcessSelected' => Array ('self' => true), // allow CSV import file upload ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Checks user permission to execute given $event * * @param kEvent $event * @return bool * @access public */ public function CheckPermission(kEvent $event) { $perm_value = null; $system_events = Array ( 'OnResetModRwCache', 'OnResetSections', 'OnResetConfigsCache', 'OnResetParsedData', 'OnResetMemcache', 'OnDeleteCompiledTemplates', 'OnCompileTemplates', 'OnGenerateTableStructure', 'OnSynchronizeDBRevisions', 'OnDeploy', 'OnRebuildThemes', 'OnCheckPrefixConfig', 'OnMemoryCacheGet', 'OnMemoryCacheSet' ); if ( in_array($event->Name, $system_events) ) { // events from "Tools -> System Tools" section are controlled via that section "edit" permission $perm_value = /*$this->Application->isDebugMode() ||*/ $this->Application->CheckPermission($event->getSection() . '.edit'); } $tools_events = Array ( 'OnBackup' => 'in-portal:backup.view', 'OnBackupProgress' => 'in-portal:backup.view', 'OnDeleteBackup' => 'in-portal:backup.view', 'OnBackupCancel' => 'in-portal:backup.view', 'OnRestore' => 'in-portal:restore.view', 'OnRestoreProgress' => 'in-portal:restore.view', 'OnRestoreCancel' => 'in-portal:backup.view', 'OnSqlQuery' => 'in-portal:sql_query.view', ); if ( array_key_exists($event->Name, $tools_events) ) { $perm_value = $this->Application->CheckPermission($tools_events[$event->Name]); } if ( $event->Name == 'OnSaveMenuFrameWidth' ) { $perm_value = $this->Application->isAdminUser; } $perm_helper = $this->Application->recallObject('PermissionsHelper'); /* @var $perm_helper kPermissionsHelper */ $csv_events = Array ('OnCSVImportBegin', 'OnCSVImportStep', 'OnExportCSV', 'OnGetCSV'); if ( in_array($event->Name, $csv_events) ) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $prefix = $csv_helper->getPrefix(stripos($event->Name, 'import') !== false); $perm_mapping = Array ( 'OnCSVImportBegin' => 'OnProcessSelected', 'OnCSVImportStep' => 'OnProcessSelected', 'OnExportCSV' => 'OnLoad', 'OnGetCSV' => 'OnLoad', ); $tmp_event = new kEvent($prefix . ':' . $perm_mapping[$event->Name] ); $perm_value = $perm_helper->CheckEventPermission($tmp_event, $this->permMapping); } if ( isset($perm_value) ) { return $perm_helper->finalizePermissionCheck($event, $perm_value); } return parent::CheckPermission($event); } /** * Reset mod-rewrite url cache * * @param kEvent $event * @return void * @access protected */ protected function OnResetModRwCache(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $this->Conn->Query('DELETE FROM ' . TABLE_PREFIX . 'CachedUrls'); $event->SetRedirectParam('action_completed', 1); } /** * Resets tree section cache and refreshes admin section tree * * @param kEvent $event * @return void * @access protected */ protected function OnResetSections(kEvent $event) { if ($this->Application->GetVar('ajax') == 'yes') { $event->status = kEvent::erSTOP; } if ($this->Application->isCachingType(CACHING_TYPE_MEMORY)) { $this->Application->rebuildCache('master:sections_parsed', kCache::REBUILD_LATER, CacheSettings::$sectionsParsedRebuildTime); } else { $this->Application->rebuildDBCache('sections_parsed', kCache::REBUILD_LATER, CacheSettings::$sectionsParsedRebuildTime); } $event->SetRedirectParam('refresh_tree', 1); $event->SetRedirectParam('action_completed', 1); } /** * Resets unit config cache * * @param kEvent $event * @return void * @access protected */ protected function OnResetConfigsCache(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) { $this->Application->rebuildCache('master:config_files', kCache::REBUILD_LATER, CacheSettings::$unitCacheRebuildTime); } else { $this->Application->rebuildDBCache('config_files', kCache::REBUILD_LATER, CacheSettings::$unitCacheRebuildTime); } $this->OnResetParsedData($event); $skin_helper = $this->Application->recallObject('SkinHelper'); /* @var $skin_helper SkinHelper */ $skin_helper->deleteCompiled(); } /** * Resets parsed data from unit configs * * @param kEvent $event * @return void * @access protected */ protected function OnResetParsedData(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $this->Application->DeleteUnitCache(); if ( $this->Application->GetVar('validate_configs') ) { $event->SetRedirectParam('validate_configs', 1); } $event->SetRedirectParam('action_completed', 1); } /** * Resets memory cache * * @param kEvent $event * @return void * @access protected */ protected function OnResetMemcache(kEvent $event) { if ($this->Application->GetVar('ajax') == 'yes') { $event->status = kEvent::erSTOP; } $this->Application->resetCache(); $event->SetRedirectParam('action_completed', 1); } /** * Compiles all templates (with a progress bar) * * @param kEvent $event * @return void * @access protected */ protected function OnCompileTemplates(kEvent $event) { $compiler = $this->Application->recallObject('NParserCompiler'); /* @var $compiler NParserCompiler */ $compiler->CompileTemplatesStep(); $event->status = kEvent::erSTOP; } /** * Deletes all compiled templates * * @param kEvent $event * @return void * @access protected */ protected function OnDeleteCompiledTemplates(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $base_path = WRITEABLE . DIRECTORY_SEPARATOR . 'cache'; // delete debugger reports $debugger_reports = glob(RESTRICTED . '/debug_@*@.txt'); if ( $debugger_reports ) { foreach ($debugger_reports as $debugger_report) { unlink($debugger_report); } } $this->_deleteCompiledTemplates($base_path); $event->SetRedirectParam('action_completed', 1); } /** * Deletes compiled templates in a given folder * * @param string $folder * @param bool $unlink_folder * @return void * @access protected */ protected function _deleteCompiledTemplates($folder, $unlink_folder = false) { $sub_folders = glob($folder . '/*', GLOB_ONLYDIR); if ( is_array($sub_folders) ) { foreach ($sub_folders as $sub_folder) { $this->_deleteCompiledTemplates($sub_folder, true); } } $files = glob($folder . '/*.php'); if ( is_array($files) ) { foreach ($files as $file) { unlink($file); } } if ( $unlink_folder ) { rmdir($folder); } } /** * Generates structure for specified table * * @param kEvent $event * @return void * @access protected */ protected function OnGenerateTableStructure(kEvent $event) { $types_hash = Array ( 'string' => 'varchar|text|mediumtext|longtext|date|datetime|time|timestamp|char|year|enum|set', 'int' => 'smallint|mediumint|int|bigint|tinyint', 'float' => 'float|double|decimal', ); $table_name = $this->Application->GetVar('table_name'); if ( !$table_name ) { echo 'error: no table name specified'; return; } if ( TABLE_PREFIX && !preg_match('/^' . preg_quote(TABLE_PREFIX, '/') . '(.*)/', $table_name) && (strtolower($table_name) != $table_name) ) { // table name without prefix, then add it (don't affect K3 tables named in lowercase) $table_name = TABLE_PREFIX . $table_name; } if ( !$this->Conn->TableFound($table_name) ) { // table with prefix doesn't exist, assume that just config prefix passed -> resolve table name from it $prefix = preg_replace('/^' . preg_quote(TABLE_PREFIX, '/') . '/', '', $table_name); if ( $this->Application->prefixRegistred($prefix) ) { // when prefix is found -> use it's table (don't affect K3 tables named in lowecase) $table_name = $this->Application->getUnitOption($prefix, 'TableName'); } } $table_info = $this->Conn->Query('DESCRIBE '.$table_name); // 1. prepare config keys $grids = Array ( 'Default' => Array ( 'Icons' => Array ('default' => 'icon16_item.png'), 'Fields' => Array (), ) ); $grids_fields = Array(); $id_field = ''; $fields = Array (); $float_types = Array ('float', 'double', 'numeric'); foreach ($table_info as $field_info) { if ( preg_match('/l[\d]+_.*/', $field_info['Field']) ) { // don't put multilingual fields in config continue; } $field_options = Array (); if ( $field_info['Key'] == 'PRI' ) { if ( $field_info['Field'] == 'Id' ) { $grid_col_options = Array ('filter_block' => 'grid_range_filter', 'width' => 80); } else { $grid_col_options = Array ('title' => 'column:la_fld_Id', 'filter_block' => 'grid_range_filter', 'width' => 80); } } else { $grid_col_options = Array ('filter_block' => 'grid_like_filter'); } // 1. get php field type by mysql field type foreach ($types_hash as $php_type => $db_types) { if ( preg_match('/' . $db_types . '/', $field_info['Type']) ) { $field_options['type'] = $php_type; break; } } // 2. get field default value $default_value = $field_info['Default']; $not_null = $field_info['Null'] != 'YES'; if ( is_numeric($default_value) ) { $default_value = preg_match('/[\.,]/', $default_value) ? (float)$default_value : (int)$default_value; } if ( is_null($default_value) && $not_null ) { $default_value = $field_options['type'] == 'string' ? '' : 0; } if ( in_array($php_type, $float_types) ) { // this is float number if ( preg_match('/' . $db_types . '\([\d]+,([\d]+)\)/i', $field_info['Type'], $regs) ) { // size is described in structure -> add formatter $field_options['formatter'] = 'kFormatter'; $field_options['format'] = '%01.' . $regs[1] . 'f'; if ( $not_null ) { // null fields, will most likely have NULL as default value $default_value = 0; } } elseif ( $not_null ) { // no size information, just convert to float // null fields, will most likely have NULL as default value $default_value = (float)$default_value; } } if ( preg_match('/varchar\(([\d]+)\)/i', $field_info['Type'], $regs) ) { $field_options['max_len'] = (int)$regs[1]; } if ( preg_match('/tinyint\([\d]+\)/i', $field_info['Type']) ) { $field_options['formatter'] = 'kOptionsFormatter'; $field_options['options'] = Array (1 => 'la_Yes', 0 => 'la_No'); $field_options['use_phrases'] = 1; $grid_col_options['filter_block'] = 'grid_options_filter'; } if ( $not_null ) { $field_options['not_null'] = 1; } if ( $field_info['Key'] == 'PRI' ) { $default_value = 0; $id_field = $field_info['Field']; } if ( $php_type == 'int' && !$not_null ) { // numeric null field if ( preg_match('/(On|Date)$/', $field_info['Field']) || $field_info['Field'] == 'Modified' ) { $field_options['formatter'] = 'kDateFormatter'; $grid_col_options['filter_block'] = 'grid_date_range_filter'; $grid_col_options['width'] = 120; } else { $grid_col_options['filter_block'] = 'grid_range_filter'; $grid_col_options['width'] = 80; } } if ( $php_type == 'int' && ($not_null || is_numeric($default_value)) ) { // is integer field AND not null $field_options['default'] = (int)$default_value; } else { $field_options['default'] = $default_value; } $fields[$field_info['Field']] = $field_options; $grids_fields[$field_info['Field']] = $grid_col_options; } $grids['Default']['Fields'] = $grids_fields; $ret = Array ( 'IDField' => $id_field, 'Fields' => $fields, 'Grids' => $grids, ); $decorator = new UnitConfigDecorator(); $ret = $decorator->decorate($ret); $this->Application->InitParser(); ob_start(); echo $this->Application->ParseBlock(Array('name' => 'incs/header', 'body_properties' => 'style="background-color: #E7E7E7; margin: 8px;"')); ?> Close Window

highlightString($ret); ?>

Close Window
Application->ParseBlock(Array('name' => 'incs/footer')); echo ob_get_clean(); $event->status = kEvent::erSTOP; } /** * Refreshes ThemeFiles & Themes tables by actual content on HDD * * @param kEvent $event * @return void * @access protected */ protected function OnRebuildThemes(kEvent $event) { if ( $this->Application->GetVar('ajax') == 'yes' ) { $event->status = kEvent::erSTOP; } $themes_helper = $this->Application->recallObject('ThemesHelper'); /* @var $themes_helper kThemesHelper */ $themes_helper->refreshThemes(); $event->SetRedirectParam('action_completed', 1); } /** * Saves grid column widths after their resize by user * * @param kEvent $event * @return void * @access protected */ protected function OnSaveColumns(kEvent $event) { $picker_helper = new kColumnPickerHelper( $this->Application->GetVar('main_prefix'), $this->Application->GetLinkedVar('grid_name') ); $picked = trim($this->Application->GetVar('picked_str'), '|'); $hidden = trim($this->Application->GetVar('hidden_str'), '|'); $picker_helper->saveColumns($picked, $hidden); $this->finalizePopup($event); } /** * Saves various admin settings via ajax * * @param kEvent $event * @return void * @access protected */ protected function OnSaveSetting(kEvent $event) { if ( $this->Application->GetVar('ajax') != 'yes' ) { return; } $var_name = $this->Application->GetVar('var_name'); $var_value = $this->Application->GetVar('var_value'); $this->Application->StorePersistentVar($var_name, $var_value); $event->status = kEvent::erSTOP; } /** * Just closes popup & deletes last_template & opener_stack if popup, that is closing * * @param kEvent $event * @return void * @access protected */ protected function OnClosePopup(kEvent $event) { $event->SetRedirectParam('opener', 'u'); } /** * Occurs right after initialization of the kernel, used mainly as hook-to event * * @param kEvent $event * @return void * @access protected */ protected function OnStartup(kEvent $event) { if ( $this->Application->isAdmin ) { return; } $base_url = preg_quote($this->Application->BaseURL(), '/'); $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : ''; if ( $referrer && !preg_match('/^' . $base_url . '/', $referrer) ) { $this->Application->Session->SetCookie('original_referrer', $referrer); $this->Application->SetVar('original_referrer', $referrer); } } /** * Occurs right before echoing the output, in Done method of application, used mainly as hook-to event * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeShutdown(kEvent $event) { } /** * Is called after tree was build (when not from cache) * * @param kEvent $event * @return void * @access protected */ protected function OnAfterBuildTree(kEvent $event) { } /** * Called by AJAX to perform CSV export * * @param kEvent $event * @return void * @access protected */ protected function OnExportCSV(kEvent $event) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $csv_helper->PrefixSpecial = $csv_helper->getPrefix(false); $csv_helper->grid = $this->Application->GetVar('grid'); $csv_helper->ExportStep(); $event->status = kEvent::erSTOP; } /** * Returning created by AJAX CSV file * * @param kEvent $event * @return void * @access protected */ protected function OnGetCSV(kEvent $event) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $csv_helper->GetCSV(); } /** * Start CSV import * * @param kEvent $event * @return void * @access protected */ protected function OnCSVImportBegin(kEvent $event) { $object = $event->getObject(Array ('skip_autoload' => true)); /* @var $object kDBItem */ $object->setID(0); $field_values = $this->getSubmittedFields($event); $object->SetFieldsFromHash($field_values); $event->setEventParam('form_data', $field_values); $event->redirect = false; $result = 'required'; if ( $object->GetDBField('ImportFile') ) { $csv_helper = $this->Application->recallObject('CSVHelper'); /* @var $csv_helper kCSVHelper */ $csv_helper->PrefixSpecial = $csv_helper->getPrefix(true); $csv_helper->grid = $this->Application->GetVar('grid'); $result = $csv_helper->ImportStart($object->GetField('ImportFile', 'file_paths')); if ( $result === true ) { $event->redirect = $this->Application->GetVar('next_template'); $event->SetRedirectParam('PrefixSpecial', $this->Application->GetVar('PrefixSpecial')); $event->SetRedirectParam('grid', $this->Application->GetVar('grid')); } } if ( $event->redirect === false ) { $object->SetError('ImportFile', $result); $event->status = kEvent::erFAIL; } } /** * Performs one CSV import step * * @param kEvent $event * @return void * @access protected */ protected function OnCSVImportStep(kEvent $event) { $import_helper = $this->Application->recallObject('CSVHelper'); /* @var $import_helper kCSVHelper */ $import_helper->ImportStep(); $event->status = kEvent::erSTOP; } /** * Shows unit config filename, where requested prefix is defined * * @param kEvent $event * @return void * @access protected */ protected function OnCheckPrefixConfig(kEvent $event) { $prefix = $this->Application->GetVar('config_prefix'); $config_file = $this->Application->UnitConfigReader->prefixFiles[$prefix]; $this->Application->InitParser(); ob_start(); echo $this->Application->ParseBlock(Array('name' => 'incs/header', 'body_properties' => 'style="background-color: #E7E7E7; margin: 8px;"')); ?> Close Window

Prefix:
Unit Config: highlightString($config_file); ?>

Close Window
Application->ParseBlock(Array ('name' => 'incs/footer')); echo ob_get_clean(); $event->status = kEvent::erSTOP; } /** * Deletes temp tables, when user closes window using "x" button in top right corner * * @param kEvent $event * @return void * @access protected */ protected function OnDropTempTablesByWID(kEvent $event) { $sid = $this->Application->GetSID(); $wid = $this->Application->GetVar('m_wid'); $tables = $this->Conn->GetCol('SHOW TABLES'); $mask_edit_table = '/' . TABLE_PREFIX . 'ses_' . $sid . '_' . $wid . '_edit_(.*)$/'; foreach ($tables as $table) { if ( preg_match($mask_edit_table, $table, $rets) ) { $this->Conn->Query('DROP TABLE IF EXISTS ' . $table); } } echo 'OK'; $event->status = kEvent::erSTOP; } /** * Backup all data * * @param kEvent $event * @return void * @access protected */ protected function OnBackup(kEvent $event) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper BackupHelper */ if ( !$backup_helper->initBackup() ) { $event->status = kEvent::erFAIL; } $event->redirect = 'tools/backup2'; } /** * Perform next backup step * * @param kEvent $event * @return void * @access protected */ protected function OnBackupProgress(kEvent $event) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper BackupHelper */ $done_percent = $backup_helper->performBackup(); if ( $done_percent == 100 ) { $event->redirect = 'tools/backup3'; return; } $event->status = kEvent::erSTOP; echo $done_percent; } /** * Stops Backup & redirect to Backup template * * @param kEvent $event * @return void * @access protected */ protected function OnBackupCancel(kEvent $event) { $event->redirect = 'tools/backup1'; } /** * Starts restore process * * @param kEvent $event * @return void * @access protected */ protected function OnRestore(kEvent $event) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper BackupHelper */ $backup_helper->initRestore(); $event->redirect = 'tools/restore3'; } /** * Performs next restore step * * @param kEvent $event * @return void * @access protected */ protected function OnRestoreProgress(kEvent $event) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper BackupHelper */ $done_percent = $backup_helper->performRestore(); if ( $done_percent == BackupHelper::SQL_ERROR_DURING_RESTORE ) { $event->redirect = 'tools/restore4'; } elseif ( $done_percent == BackupHelper::FAILED_READING_BACKUP_FILE ) { $this->Application->StoreVar('adm.restore_error', 'File read error'); $event->redirect = 'tools/restore4'; } elseif ( $done_percent == 100 ) { $backup_helper->replaceRestoredFiles(); $this->Application->StoreVar('adm.restore_success', 1); $event->redirect = 'tools/restore4'; } else { $event->status = kEvent::erSTOP; echo $done_percent; } } /** * Stops Restore & redirect to Restore template * * @param kEvent $event * @return void * @access protected */ protected function OnRestoreCancel(kEvent $event) { $event->redirect = 'tools/restore1'; } /** * Deletes one backup file * * @param kEvent $event * @return void * @access protected */ protected function OnDeleteBackup(kEvent $event) { $backup_helper = $this->Application->recallObject('BackupHelper'); /* @var $backup_helper BackupHelper */ $backup_helper->delete(); } /** * Starts restore process * * @param kEvent $event * @return void * @access protected */ protected function OnSqlQuery(kEvent $event) { $sql = $this->Application->GetVar('sql'); if ( $sql ) { $start = microtime(true); $result = $this->Conn->Query($sql); $this->Application->SetVar('sql_time', round(microtime(true) - $start, 7)); if ( $result && is_array($result) ) { $this->Application->SetVar('sql_has_rows', 1); $this->Application->SetVar('sql_rows', serialize($result)); } $check_sql = trim(strtolower($sql)); if ( preg_match('/^(insert|update|replace|delete)/', $check_sql) ) { $this->Application->SetVar('sql_has_affected', 1); $this->Application->SetVar('sql_affected', $this->Conn->getAffectedRows()); } } $this->Application->SetVar('query_status', 1); $event->status = kEvent::erFAIL; } /** * Occurs after unit config cache was successfully rebuilt * * @param kEvent $event * @return void * @access protected */ protected function OnAfterCacheRebuild(kEvent $event) { } /** * Removes "Community -> Groups" section when it is not allowed * * @param kEvent $event * @return void * @access protected */ protected function OnAfterConfigRead(kEvent $event) { parent::OnAfterConfigRead($event); $section_adjustments = $this->Application->getUnitOption($event->Prefix, 'SectionAdjustments', Array()); if ( !$this->Application->ConfigValue('AdvancedUserManagement') ) { $section_adjustments['in-portal:user_groups'] = 'remove'; } $section_adjustments['in-portal:root'] = Array ( 'label' => $this->Application->ConfigValue('Site_Name') ); $this->Application->setUnitOption($event->Prefix, 'SectionAdjustments', $section_adjustments); } /** * Saves menu (tree) frame width * * @param kEvent $event * @return void * @access protected */ protected function OnSaveMenuFrameWidth(kEvent $event) { $event->status = kEvent::erSTOP; if ( !$this->Application->ConfigValue('ResizableFrames') ) { return; } $this->Application->StorePersistentVar('MenuFrameWidth', (int)$this->Application->GetVar('width')); } /** * Retrieves data from memory cache * * @param kEvent $event * @return void * @access protected */ protected function OnMemoryCacheGet(kEvent $event) { $event->status = kEvent::erSTOP; $ret = Array ('message' => '', 'code' => 0); // 0 - ok, > 0 - error $key = $this->Application->GetVar('key'); if ( !$key ) { $ret['code'] = 1; $ret['message'] = 'Key name missing'; } else { $value = $this->Application->getCache($key); $ret['value'] =& $value; $ret['size'] = is_string($value) ? kUtil::formatSize(strlen($value)) : '?'; $ret['type'] = gettype($value); if ( kUtil::IsSerialized($value) ) { $value = unserialize($value); } if ( is_array($value) ) { $ret['value'] = print_r($value, true); } if ( $ret['value'] === false ) { $ret['code'] = 2; $ret['message'] = 'Key "' . $key . '" doesn\'t exist'; } } $json_helper = $this->Application->recallObject('JSONHelper'); /* @var $json_helper JSONHelper */ echo $json_helper->encode($ret); } /** * Retrieves data from memory cache * * @param kEvent $event * @return void * @access protected */ protected function OnMemoryCacheSet(kEvent $event) { $event->status = kEvent::erSTOP; $ret = Array ('message' => '', 'code' => 0); // 0 - ok, > 0 - error $key = $this->Application->GetVar('key'); if ( !$key ) { $ret['code'] = 1; $ret['message'] = 'Key name missing'; } else { $value = $this->Application->GetVar('value'); $res = $this->Application->setCache($key, $value); $ret['result'] = $res ? 'OK' : 'FAILED'; } $json_helper = $this->Application->recallObject('JSONHelper'); /* @var $json_helper JSONHelper */ echo $json_helper->encode($ret); } /** * Deploy changes * * Usage: "php tools/run_event.php adm:OnDeploy b674006f3edb1d9cd4d838c150b0567d" * * @param kEvent $event * @return void * @access protected */ protected function OnDeploy(kEvent $event) { $this->_deploymentAction($event); } /** * Synchronizes database revisions from "project_upgrades.sql" file * * @param kEvent $event * @return void * @access protected */ protected function OnSynchronizeDBRevisions(kEvent $event) { $this->_deploymentAction($event, true); } /** * Common code to invoke deployment helper * * @param kEvent $event * @param bool $dry_run * @return void * @access protected */ protected function _deploymentAction(kEvent $event, $dry_run = false) { $deployment_helper = $this->Application->recallObject('DeploymentHelper'); /* @var $deployment_helper DeploymentHelper */ $deployment_helper->setEvent($event); if ( $deployment_helper->deployAll($dry_run) ) { $event->SetRedirectParam('action_completed', 1); if ( !$deployment_helper->isCommandLine ) { // browser invocation -> don't perform redirect $event->redirect = false; // no redirect, but deployment succeeded - set redirect params directly foreach ($event->getRedirectParams() as $param_name => $param_value) { $this->Application->SetVar($param_name, $param_value); } } } else { $event->status = kEvent::erFAIL; } } /** * [SCHEDULED TASK] * 1. Delete all Debug files from system/.restricted folder (format debug_@977827436@.txt) * 2. Run MySQL OPTIMIZE SQL one by one on all In-Portal tables (found by prefix). * * @param kEvent $event * @return void * @access protected */ protected function OnOptimizePerformance(kEvent $event) { $start_time = adodb_mktime(); $sql = 'SELECT SessionKey FROM ' . TABLE_PREFIX . 'UserSessions WHERE LastAccessed > ' . $start_time; $active_sessions = array_flip($this->Conn->GetCol($sql)); $files = scandir(RESTRICTED); $file_path = RESTRICTED . '/'; foreach ($files AS $file_name) { if ( !preg_match('#^debug_@([0-9]{9})@.txt$#', $file_name, $matches) ) { // not debug file continue; } $sid = $matches[1]; if ( isset($active_sessions[$sid]) || (filemtime($file_path . $file_name) > $start_time) ) { // debug file belongs to an active session // debug file is recently created (after sessions snapshot) continue; } unlink($file_path . $file_name); } $system_tables = $this->Conn->GetCol('SHOW TABLES LIKE "' . TABLE_PREFIX . '%"'); foreach ($system_tables AS $table_name) { $this->Conn->Query('OPTIMIZE TABLE ' . $table_name); } } /** * Returns popup size (by template), if not cached, then parse template to get value * * @param kEvent $event * @return void * @access protected */ protected function OnGetPopupSize(kEvent $event) { $event->status = kEvent::erSTOP; if ( $this->Application->GetVar('ajax') != 'yes' ) { return; } $t = $this->Application->GetVar('template_name'); $sql = 'SELECT * FROM ' . TABLE_PREFIX . 'PopupSizes WHERE TemplateName = ' . $this->Conn->qstr($t); $popup_info = $this->Conn->GetRow($sql); $this->Application->setContentType('text/plain'); if ( !$popup_info ) { // dies when SetPopupSize tag found & in ajax request $this->Application->InitParser(); $this->Application->ParseBlock(Array ('name' => $t)); // tag SetPopupSize not found in template -> use default size echo '750x400'; } else { echo $popup_info['PopupWidth'] . 'x' . $popup_info['PopupHeight']; } } + + /** + * Writes HTTP request to System Log + * + * @param kEvent $event + * @return void + * @access public + */ + public function OnLogHttpRequest(kEvent $event) + { + if ( defined('DBG_REQUEST_LOG') && DBG_REQUEST_LOG && $this->Application->LoggedIn() ) { + $log = $this->Application->log('HTTP_REQUEST')->addRequestData(); + + if ( !$log->write() ) { + trigger_error('Unable to log Http Request due disabled "System Log"', E_USER_WARNING); + } + } + } } class UnitConfigDecorator { var $parentPath = Array (); /** * Decorates given array * * @param Array $var * @param int $level * @return string */ public function decorate($var, $level = 0) { $ret = ''; $deep_level = count($this->parentPath); if ( $deep_level && ($this->parentPath[0] == 'Fields') ) { $expand = $level < 2; } elseif ( $deep_level && ($this->parentPath[0] == 'Grids') ) { if ( $deep_level == 3 && $this->parentPath[2] == 'Icons' ) { $expand = false; } else { $expand = $level < 4; } } else { $expand = $level == 0; } if ( is_array($var) ) { $ret .= 'array('; $prepend = $expand ? "\n" . str_repeat("\t", $level + 1) : ''; foreach ($var as $key => $value) { array_push($this->parentPath, $key); $ret .= $prepend . (is_string($key) ? "'" . $key . "'" : $key) . ' => ' . $this->decorate($value, $level + 1); $ret .= ',' . ($expand ? '' : ' '); array_pop($this->parentPath); } $prepend = $expand ? "\n" . str_repeat("\t", $level) : ''; if ( !$expand ) { $ret = rtrim($ret, ', '); } $ret .= $prepend . ')'; } else { if ( is_null($var) ) { $ret = 'null'; } elseif ( is_string($var) ) { $ret = "'" . $var . "'"; } else { $ret = $var; } } return $ret; } } Property changes on: branches/5.2.x/CREDITS ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/CREDITS:r15957 Property changes on: branches/5.2.x/README ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/README:r15957 Property changes on: branches/5.2.x/index.php ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/index.php:r15957 Index: branches/5.2.x/tools/debug_sample.php =================================================================== --- branches/5.2.x/tools/debug_sample.php (revision 16433) +++ branches/5.2.x/tools/debug_sample.php (revision 16434) @@ -1,60 +1,60 @@ '192.168.1.1/24;192.168.2.1/24;173.9.192.210', // !!!REQUIRED!!! Define IP addreses, which are allowed to use debugger (semicolon separated) 'DEBUG_MODE' => 1, // Debug mode is allowed/disabled (note: set DBG_IP to use this one) // 'DBG_LOCAL_BASE_PATH' => 'w:', // Folder name on mapped drive, where site resides // 'DBG_TOOLBAR_BUTTONS' => 1, // Show "Show Debugger" & "Refresh Frame" buttons (on front) // 'DBG_USE_HIGHLIGHT' => 0, // Use "highlight_string" php function for debugger output formatting // 'DBG_RAISE_ON_WARNINGS' => 1, // Show debugger output in case of any non-fatal error 'DBG_SQL_PROFILE' => defined('IS_INSTALL') && IS_INSTALL ? 0 : 1, // Profile SQL queries // 'DBG_SQL_EXPLAIN' => 1, // Explain every SQL query, that is retrieving data 'DBG_SQL_FAILURE' => isset($GLOBALS['pathtoroot']) && defined('IS_INSTALL') && IS_INSTALL ? 0 : 1, // treat sql errors as fatal errors except for installation process // 'DBG_SQL_SERVERINFO' => 1, // Display database server info next each sql query in debugger 'DBG_SHOW_HTTPQUERY' => 1, // Show http query content (parsed user submit, GPC) 'DBG_SHOW_SESSIONDATA' => 1, // Show session data (at script finish) // 'DBG_SHOW_PERSISTENTDATA' => 1, // Show persistent session data (at script finish) // 'DBG_FORCE_THEME' => 1, // Use this theme_id instead of one in url 'DBG_PHRASES' => 1, // Add ability to translate phrases on the fly // 'DBG_WINDOW_WIDTH' => 700, // Set custom debugger layer width (in pixels) // 'DBG_REDIRECT' => 1, // Show links with redirect url instead of performing it (useful in events debugging) // 'DBG_VALIDATE_CONFIGS' => 1, // Check that config fields match ones from database // 'DBG_SHOW_TAGS' => 1, // Show tags beeing processed // 'DBG_SHOW_TREE_PRIORITY'=> 1, // Show tree node priority // 'DBG_SKIP_AJAX' => 1, // Don't debug AJAX requests // 'DBG_PAYMENT_GW' => 1, // All requests to payment gateways goes in TEST MODE // 'DBG_IMAGE_RECOVERY' => 1, // Don't replace missing images with noimage.gif // 'DBG_SQL_MODE' => 'TRADITIONAL', // Extra control over sql syntax & data from MySQL server side // 'DBG_RESET_ROOT' => 1, // Shows "root" user password reset link on Admin Console login screen // 'DBG_CACHE_URLS' => 0, // Cache urls, that are build by rewrite listeners // 'DBG_SHORTCUT' => 'F12' // Defines debugger activation shortcut (any symbols or Ctrl/Alt/Shift are allowed, e.g. Ctrl+Alt+F12) ); \ No newline at end of file Property changes on: branches/5.2.x/LICENSES ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/LICENSES:r15957 Property changes on: branches/5.2.x/INSTALL ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/INSTALL:r15957 Property changes on: branches/5.2.x/COPYRIGHT ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/COPYRIGHT:r15957 Property changes on: branches/5.2.x/.htaccess ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x/.htaccess:r15957 Property changes on: branches/5.2.x ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.3.x:r15957