Index: branches/5.3.x/core/kernel/application.php =================================================================== --- branches/5.3.x/core/kernel/application.php (revision 16722) +++ branches/5.3.x/core/kernel/application.php (revision 16723) @@ -1,3095 +1,3100 @@ * 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 (); /** * Registered routers, that are used during url building and parsing. * * @var array */ public $routers = array(); /** * Reference to debugger * * @var Debugger * @access public */ public $Debugger = null; /** * Holds all phrases used * in code and template * * @var kPhraseCache * @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(); $system_config = new kSystemConfig(true); $vars = $system_config->getData(); $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 routers. $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('kHTTPQuery'); $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(); 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); } $this->UrlManager = $this->makeClass('kUrlManager'); $this->EventManager = $this->makeClass('kEventManager'); $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(); $this->Factory->configureAutoloader(); return; } // use makeClass over recallObject, since used before kApplication initialization during installation /** @var kModulesHelper $modules_helper */ $modules_helper = $this->makeClass('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(); $this->Factory->configureAutoloader(); } /** * 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 $language_config = $this->getUnitConfig('lang'); $table = $language_config->getTableName(); $id_field = $language_config->getIDField(); $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; $theme_config = $this->getUnitConfig('theme'); $sql = 'SELECT ' . $theme_config->getIDField() . ' FROM ' . $theme_config->getTableName() . ' 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->getUnitConfig('curr')->getTableName() . ' 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 kDBItem $site_domain */ } if ( $this->siteDomain->isLoaded() ) { return $formatted ? $this->siteDomain->GetField($field, $format) : $this->siteDomain->GetDBField($field); } return false; } /** * Registers classes, that are used before unit configs (where class registration usually is done) are read. * * Called automatically while initializing kApplication. * * @return void * @access public */ public function RegisterDefaultClasses() { // Database. $this->registerClass('IDBConnection', KERNEL_PATH . '/db/i_db_connection.php'); $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'); // Cache. $this->registerClass('kCacheManager', KERNEL_PATH . '/managers/cache_manager.php'); $this->registerClass('kCache', KERNEL_PATH . '/utility/cache.php'); $this->registerClass('kSubscriptionItem', KERNEL_PATH . '/managers/subscription_manager.php'); // Unit configs. $this->registerClass('kUnitConfigReader', KERNEL_PATH . '/utility/unit_config_reader.php'); $this->registerClass('kUnitConfigCloner', KERNEL_PATH . '/utility/unit_config_cloner.php'); // Urls. $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'); // Events. $this->registerClass('kEventManager', KERNEL_PATH . '/event_manager.php'); $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'); // Misc. $this->registerClass('kPhraseCache', KERNEL_PATH . '/languages/phrases_cache.php'); $this->registerClass('kModulesHelper', KERNEL_PATH . self::MODULE_HELPER_PATH); $this->registerClass('CKEditor', FULL_PATH . '/core/ckeditor/ckeditor_php5.php'); // Aliased. $this->registerClass('Params', KERNEL_PATH . '/utility/params.php', 'kActions'); $this->registerClass('kMainTagProcessor', KERNEL_PATH . '/processors/main_processor.php', 'm_TagProcessor'); $this->registerClass('kEmailSendingHelper', KERNEL_PATH . '/utility/email_send.php', 'EmailSender'); + + // security + $this->registerClass('SecurityGenerator', KERNEL_PATH . '/security/SecurityGenerator.php'); + $this->registerClass('SecurityGeneratorPromise', KERNEL_PATH . '/security/SecurityGeneratorPromise.php'); + $this->registerClass('SecurityEncrypter', KERNEL_PATH . '/security/SecurityEncrypter.php'); } /** * 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 } } $this->Phrases->setPhraseEditing(); $this->EventManager->ProcessRequest(); $this->InitParser(); $t = $this->GetVar('render_template', $this->GetVar('t')); if ( !$this->TemplatesCache->TemplateExists($t) && !$this->isAdmin ) { /** @var CategoriesEventHandler $cms_handler */ $cms_handler = $this->recallObject('st_EventHandler'); $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:'); } } /** * Returns console application. * * @return ConsoleApplication */ public function getConsoleApplication() { return $this->makeClass('InPortal\Core\kernel\Console\ConsoleApplication'); } /** * 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'] = time(); $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'] = time(); $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'] = time(); $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'] = time(); $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() { /** @var Session $session */ $session = $this->recallObject('Session'); return $session->GetID(); } /** * Destroys current session * * @return void * @access public * @see UserHelper::logoutUser() */ public function DestroySession() { /** @var Session $session */ $session = $this->recallObject('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) { /** @var Session $session */ $session = $this->recallObject('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) { /** @var Session $session */ $session = $this->recallObject('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) { /** @var kDBTagProcessor $processor */ $processor = $this->Parser->GetProcessor($prefix); 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 seo template by physical template * * @param string $physical_template * @return string * @access public */ public function getSeoTemplate($physical_template) { return $this->UrlManager->getSeoTemplate($physical_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 $domain Domain override. * @param boolean $ssl_redirect Redirect to/from SSL. * * @return string */ public function BaseURL($domain = '', $ssl_redirect = null) { if ( $ssl_redirect === null ) { // stay on same encryption level return PROTOCOL . ($domain ? $domain : SERVER_NAME) . (defined('PORT') ? ':' . PORT : '') . BASE_PATH . '/'; } if ( $ssl_redirect ) { // going from http:// to https:// $protocol = 'https://'; $domain = $this->getSecureDomain(); } else { // going from https:// to http:// $protocol = 'http://'; $domain = $this->siteDomainField('DomainName'); if ( $domain === false ) { $domain = DOMAIN; // not on site domain } } return $protocol . $domain . (defined('PORT') ? ':' . PORT : '') . BASE_PATH . '/'; } /** * Returns secure domain. * * @return string */ public function getSecureDomain() { $ret = $this->isAdmin ? $this->ConfigValue('AdminSSLDomain') : false; if ( !$ret ) { $ssl_domain = $this->siteDomainField('SSLDomainName'); return strlen($ssl_domain) ? $ssl_domain : $this->ConfigValue('SSLDomain'); } return $ret; } /** * 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 /** @var Session $session */ $session = $this->recallObject('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() { /** @var Session $session */ $session = $this->recallObject('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 /** @var UsersItem $user */ $user = $this->recallObject('u.login-admin', null, Array ('form_name' => 'login')); $user->SetError('UserLogin', 'session_expired', 'la_text_sess_expired'); } $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 Event. * * @return void */ public function HandleEvent(kEvent $event) { $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 string $module * @param int $status * @access public */ public function registerScheduledTask($short_name, $event_string, $run_schedule, $module, $status = STATUS_ACTIVE) { $this->EventManager->registerScheduledTask($short_name, $event_string, $run_schedule, $module, $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) { /** @var kArray $aggregator */ $aggregator = $this->recallObject('TagsAggregator', '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); } /** * Returns sub-classes of given ancestor class. * * @param string $ancestor_class Ancestor class. * @param boolean $concrete_only Return only non-abstract classes. * * @return array */ public function getSubClasses($ancestor_class, $concrete_only = true) { return $this->Factory->getSubClasses($ancestor_class, $concrete_only); } /** * 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; } /** * Returns unit config for given prefix * * @param string $prefix * @return kUnitConfig * @access public */ public function getUnitConfig($prefix) { return $this->UnitConfigReader->getUnitConfig($prefix); } /** * Returns true if config exists and is allowed for reading * * @param string $prefix * @return bool */ public function prefixRegistred($prefix) { return $this->UnitConfigReader->prefixRegistered($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->getUnitConfig($current_prefix)->getParentPrefix()) { 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 ()) { /** @var kEmail $email */ $email = $this->makeClass('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(); } /** * Determines if access permissions should not be checked. * * @param integer|null $user_id User ID. * * @return boolean */ public function permissionCheckingDisabled($user_id = null) { if ( !isset($user_id) ) { $user_id = $this->RecallVar('user_id'); } return $user_id == USER_ROOT; } /** * 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) { /** @var kPermissionsHelper $perm_helper */ $perm_helper = $this->recallObject('PermissionsHelper'); 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) { /** @var kPermissionsHelper $perm_helper */ $perm_helper = $this->recallObject('PermissionsHelper'); 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; } /** @var kDBItem $visit */ $visit = $this->recallObject('visits', null, Array ('raise_warnings' => 0)); 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) { /** @var kCountHelper $count_helper */ $count_helper = $this->recallObject('CountHelper'); 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; } /** @var kCountHelper $count_helper */ $count_helper = $this->recallObject('CountHelper'); $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->routers = $data['Application.Routers']; $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.Routers' => $this->routers, '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.3.x/core/kernel/utility/system_config.php =================================================================== --- branches/5.3.x/core/kernel/utility/system_config.php (revision 16722) +++ branches/5.3.x/core/kernel/utility/system_config.php (revision 16723) @@ -1,287 +1,289 @@ parseSections = $parse_section; $this->strictMode = $strict; $this->file = FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'config.php'; } /** * Returns default config values. * * @return array */ protected function getDefaults() { $ret = array( 'AdminDirectory' => '/admin', 'AdminPresetsDirectory' => '/admin', 'ApplicationClass' => 'kApplication', 'ApplicationPath' => '/core/kernel/application.php', 'CacheHandler' => 'Fake', 'CmsMenuRebuildTime' => 10, 'DomainsParsedRebuildTime' => 2, 'EditorPath' => '/core/ckeditor/', 'EnableSystemLog' => '0', 'MemcacheServers' => 'localhost:11211', 'CompressionEngine' => '', 'RestrictedPath' => DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . '.restricted', 'SectionsParsedRebuildTime' => 5, 'StructureTreeRebuildTime' => 10, 'SystemLogMaxLevel' => 5, 'TemplateMappingRebuildTime' => 5, 'TrustProxy' => '0', 'UnitCacheRebuildTime' => 10, 'WebsiteCharset' => 'utf-8', 'WebsitePath' => rtrim(preg_replace('/'.preg_quote(rtrim(defined('REL_PATH') ? REL_PATH : '', '/'), '/').'$/', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))), '/'), 'WriteablePath' => DIRECTORY_SEPARATOR . 'system', + 'SecurityHmacKey' => '', + 'SecurityEncryptionKey' => '', ); return $this->parseSections ? array('Misc' => $ret) : $ret; } /** * Parses "/system/config.php" file and writes the result to the data variable * * @return array * @throws kSystemConfigException When something goes wrong. */ public function parse() { if ( !$this->exists() ) { if ( $this->strictMode ) { throw new kSystemConfigException(sprintf('System config at "%s" not found', $this->file)); } return array(); } elseif ( !is_readable($this->file) ) { throw new kSystemConfigException(sprintf('System config at "%s" could not be opened', $this->file)); } $contents = file($this->file); if ( $contents && $contents[0] == '<' . '?' . 'php die() ?' . ">\n" ) { // format of "config.php" file before 5.1.0 version array_shift($contents); return parse_ini_string(implode('', $contents), $this->parseSections); } $_CONFIG = array(); require($this->file); if ( $this->parseSections ) { if ( isset($_CONFIG['Database']['LoadBalancing']) && $_CONFIG['Database']['LoadBalancing'] ) { require FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'db_servers.php'; } return $_CONFIG; } $ret = array(); foreach ($_CONFIG as $section_variables) { $ret = array_merge($ret, $section_variables); } if ( !count($ret) && $this->strictMode ) { throw new kSystemConfigException(sprintf('System config at "%s" could is empty', $this->file)); } return $ret; } /** * Returns parsed variables from "config.php" file * * @return array */ public function getData() { if ( !$this->data ) { $this->data = array_replace_recursive($this->getDefaults(), $this->parse()); } return $this->data; } /** * Checks if given section is present in config. * * @param string $section * * @return boolean */ function sectionFound($section) { return $this->parseSections ? array_key_exists($section, $this->getData()) : false; } /** * Returns config value * * @param string $key Key name. * @param string $section Section name. * @param mixed $default Default value. * * @return string */ public function get($key, $section = null, $default = false) { $data = $this->getData(); if ( $this->parseSections ) { return isset($data[$section][$key]) ? $data[$section][$key] : $default; } return isset($data[$key]) ? $data[$key] : (isset($section) ? $section : $default); } /** * Checks, if a configuration file exists on disk. * * @return boolean */ public function exists() { return file_exists($this->file); } /** * Returns config status - is changed or not changed * * @return bool */ public function isChanged() { return $this->isChanged; } /** * Sets value to system config (yet saveConfig must be called to write it to file) * * @param string $key Key name. * @param string $section Section name. * @param mixed $value Value. * * @return void */ public function set($key, $section, $value = null) { $this->getData(); $this->isChanged = true; if ( isset($value) ) { // create section, when missing if ( !array_key_exists($section, $this->data) ) { $this->data[$section] = array(); } // create key in section $this->data[$section][$key] = $value; return; } unset($this->data[$section][$key]); } /** * Saves config data to the file * * @param boolean $silent * * @return void * @throws Exception */ public function save($silent = false) { if ( !is_writable($this->file) && !is_writable(dirname($this->file)) ) { $error_msg = 'Cannot write to "' . $this->file . '" file'; if ( $silent ) { trigger_error($error_msg, E_USER_WARNING); return; } throw new Exception($error_msg); } $fp = fopen($this->file, 'w'); fwrite($fp, '<' . '?' . 'php' . "\n\n"); foreach ( $this->getData() as $section_name => $section_data ) { foreach ( $section_data as $key => $value ) { fwrite($fp, '$_CONFIG[\'' . $section_name . '\'][\'' . $key . '\'] = \'' . addslashes($value) . '\';' . "\n"); } fwrite($fp, "\n"); } fclose($fp); if ( function_exists('opcache_invalidate') ) { opcache_invalidate($this->file); } $this->isChanged = false; } } class kSystemConfigException extends Exception { } Index: branches/5.3.x/core/kernel/security/SecurityGeneratorPromise.php =================================================================== --- branches/5.3.x/core/kernel/security/SecurityGeneratorPromise.php (revision 0) +++ branches/5.3.x/core/kernel/security/SecurityGeneratorPromise.php (revision 16723) @@ -0,0 +1,274 @@ + 'generateNumber', + self::TYPE_STRING => 'generateString', + self::TYPE_BYTES => 'generateBytes', + ); + + if ( !isset($mapping[$type]) ) { + throw new InvalidArgumentException('The "' . $type . '" promise type is not supported.'); + } + + $this->method = $mapping[$type]; + $this->arguments = $arguments; + } + + /** + * Makes sure, that resolved value isn't already used in the given database table's column. + * + * @param string $prefix_or_table Unit config prefix or table name. + * @param string $column Column in specified table. + * + * @return mixed + * @throws LogicException When after 10 retries still unable to generate unique value for database. + */ + public function resolveForPersisting($prefix_or_table, $column) + { + $application =& kApplication::Instance(); + + if ( $application->prefixRegistred($prefix_or_table) ) { + $table = $application->getUnitOption($prefix_or_table, 'TableName'); + } + else { + $table = $prefix_or_table; + } + + $retries = 0; + + do { + $resolved_value = $this->resolve(); + + $sql = 'SELECT ' . $column . ' + FROM ' . $table . ' + WHERE ' . $column . ' = ' . $application->Conn->qstr($resolved_value); + $found = $application->Conn->GetOne($sql) !== false; + + if ( $found ) { + $this->resolvedValue = null; + $retries++; + } + } while ( $found && $retries < 10 ); + + if ( $found ) { + throw new LogicException(sprintf( + 'Unable to generate unique value for "%s" column with current generator configuration.', + $table . '.' . $column + )); + } + + return $resolved_value; + } + + /** + * Resolves a promise. + * + * @return mixed + */ + public function resolve() + { + if ( !$this->isResolved() ) { + $this->resolvedValue = call_user_func_array(array($this, $this->method), $this->arguments); + } + + if ( !$this->asSignature ) { + return $this->resolvedValue; + } + + $application =& kApplication::Instance(); + + /** @var SecurityEncrypter $encrypter */ + $encrypter = $application->recallObject('SecurityEncrypter'); + + return $encrypter->createSignature( + $this->resolvedValue, + $this->signatureRawOutput, + $this->signatureKeyOverride + ); + } + + /** + * Configures promise to return signature of a resolved value. + * + * @param boolean $raw_output Return raw signature value during resolving. + * @param string|null $key_override Alternative key used for creating signature of resolved value. + * + * @return self + */ + public function asSignature($raw_output = false, $key_override = null) + { + $this->asSignature = true; + $this->signatureRawOutput = $raw_output; + $this->signatureKeyOverride = $key_override; + + return $this; + } + + /** + * Configures promise to return resolved value as-is. + * + * @return self + */ + public function asValue() + { + $this->asSignature = false; + $this->signatureRawOutput = false; + $this->signatureKeyOverride = null; + + return $this; + } + + /** + * Generate a random string of specified length using supplied character list. + * + * @param integer $length The length of the generated string. + * @param mixed $characters List of characters to use. + * + * @return string + */ + protected function generateString($length, $characters) + { + $ret = ''; + $max_index = mb_strlen($characters) - 1; + + for ( $i = 0; $i < $length; $i++ ) { + $ret .= mb_substr($characters, $this->generateNumber(0, $max_index), 1); + } + + return $ret; + } + + /** + * Generates a random number. + * + * @param integer $min Smallest value. + * @param integer $max Largest value. + * + * @return integer + */ + protected function generateNumber($min, $max) + { + return random_int($min, $max); + } + + /** + * Generates random bytes. + * + * @param integer $length Raw result length. + * @param boolean $raw_output Return raw result. + * + * @return string + */ + protected function generateBytes($length = 16, $raw_output = false) + { + $ret = random_bytes($length); + + return $raw_output ? $ret : bin2hex($ret); + } + + /** + * Determines if promise was already resolved. + * + * @return boolean + */ + protected function isResolved() + { + return $this->resolvedValue !== null; + } + + /** + * Returns promise resolved value casted to string. + * + * @return string + */ + public function __toString() + { + return (string)$this->resolve(); + } + +} Property changes on: branches/5.3.x/core/kernel/security/SecurityGeneratorPromise.php ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + LF Index: branches/5.3.x/core/kernel/security/SecurityGenerator.php =================================================================== --- branches/5.3.x/core/kernel/security/SecurityGenerator.php (revision 0) +++ branches/5.3.x/core/kernel/security/SecurityGenerator.php (revision 16723) @@ -0,0 +1,193 @@ + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + self::CHAR_LOWER => 'abcdefghijklmnopqrstuvwxyz', + self::CHAR_DIGITS => '0123456789', + self::CHAR_UPPER_HEX => 'ABCDEF', + self::CHAR_LOWER_HEX => 'abcdef', + self::CHAR_BASE64 => '+/', + self::CHAR_SYMBOLS => '!"#$%&\'()* +,-./:;<=>?@[\]^_`{|}~', + self::CHAR_BRACKETS => '()[]{}<>', + self::CHAR_PUNCT => ',.;:', + ); + + /** + * Generate a random string of specified length using supplied character list. + * + * @param integer $length The length of the generated string. + * @param mixed $characters List of characters to use or character flags. + * + * @return SecurityGeneratorPromise + */ + public static function generateString($length, $characters) + { + // Combine character sets. + if ( is_int($characters) ) { + $characters = self::expandCharacterSets($characters); + } + + return new SecurityGeneratorPromise( + SecurityGeneratorPromise::TYPE_STRING, + array($length, $characters) + ); + } + + /** + * Expand a character set bitwise spec into a string character set. + * This will also replace EASY_TO_READ characters if the flag is set. + * + * @param integer $spec The spec to expand (bitwise combination of flags). + * + * @return string The expanded string + */ + protected static function expandCharacterSets($spec) + { + $combined = ''; + + if ( $spec == self::EASY_TO_READ ) { + $spec |= self::CHAR_ALNUM; + } + + foreach ( self::$charArrays as $flag => $chars ) { + // Handle this later. + if ( $flag == self::EASY_TO_READ ) { + continue; + } + + if ( ($spec & $flag) === $flag ) { + $combined .= $chars; + } + } + + // Remove ambiguous characters. + if ( $spec & self::EASY_TO_READ ) { + $combined = str_replace(str_split(self::AMBIGUOUS_CHARS), '', $combined); + } + + return count_chars($combined, 3); + } + + /** + * Generates a random number. + * + * @param integer $min Smallest value. + * @param integer $max Largest value. + * + * @return SecurityGeneratorPromise + */ + public static function generateNumber($min, $max) + { + return new SecurityGeneratorPromise( + SecurityGeneratorPromise::TYPE_NUMBER, + array($min, $max) + ); + } + + /** + * Generates random bytes. + * + * @param integer $length Raw result length. + * @param boolean $raw_output Return raw result. + * + * @return SecurityGeneratorPromise + */ + public static function generateBytes($length = 16, $raw_output = false) + { + return new SecurityGeneratorPromise( + SecurityGeneratorPromise::TYPE_BYTES, + array($length, $raw_output) + ); + } + +} Property changes on: branches/5.3.x/core/kernel/security/SecurityGenerator.php ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + LF Index: branches/5.3.x/core/kernel/security/SecurityEncrypter.php =================================================================== --- branches/5.3.x/core/kernel/security/SecurityEncrypter.php (revision 0) +++ branches/5.3.x/core/kernel/security/SecurityEncrypter.php (revision 16723) @@ -0,0 +1,228 @@ +getData(); + + // In the config data is encoded stored to avoid corruption. + $this->hmacKey = base64_decode($vars['SecurityHmacKey']); + + // Equivalent of "hex2bin" for PHP < 5.4. + $this->encryptionKey = pack('H*', $vars['SecurityEncryptionKey']); + } + + /** + * Creates signature. + * + * @param string $string String. + * @param boolean $raw_output Return raw signature version. + * @param string|null $key_override Override key. + * + * @return string + */ + public function createSignature($string, $raw_output = false, $key_override = null) + { + return hash_hmac(self::HASHING_ALGORITHM, $string, $this->_getHmacKey($key_override), $raw_output); + } + + /** + * Returns HMAC key. + * + * @param string|null $key_override Key override. + * + * @return string + * @throws InvalidArgumentException When HMAC key is empty. + */ + private function _getHmacKey($key_override = null) + { + $key = $this->doGetHmacKey($key_override); + + if ( empty($key) ) { + throw new InvalidArgumentException('The HMAC key is empty.'); + } + + if ( mb_strlen($key, '8bit') === self::HASHING_KEY_LENGTH ) { + return $key; + } + + return $this->deriveKey($key, self::HASHING_KEY_LENGTH); + } + + /** + * Returns HMAC key. + * + * @param string|null $key_override Key override. + * + * @return string + */ + protected function doGetHmacKey($key_override = null) + { + return isset($key_override) ? $key_override : $this->hmacKey; + } + + /** + * Returns encryption key. + * + * @param string|null $key_override Key override. + * + * @return string + * @throws InvalidArgumentException When encryption key is empty. + */ + private function _getEncryptionKey($key_override = null) + { + $key = $this->doGetEncryptionKey($key_override); + + if ( empty($key) ) { + throw new InvalidArgumentException('The encryption key is empty.'); + } + + if ( mb_strlen($key, '8bit') === self::ENCRYPTION_KEY_LENGTH ) { + return $key; + } + + return $this->deriveKey($key, self::ENCRYPTION_KEY_LENGTH); + } + + /** + * Returns encryption key. + * + * @param string|null $key_override Key override. + * + * @return string + */ + protected function doGetEncryptionKey($key_override = null) + { + return isset($key_override) ? $key_override : $this->encryptionKey; + } + + /** + * Derives given key. + * + * @param string $key Key. + * @param integer $length Length. + * + * @return string + */ + final public function deriveKey($key, $length) + { + $salt = SecurityGenerator::generateBytes(16, true); + + return hash_pbkdf2(self::HASHING_ALGORITHM, $key, $salt, 80000, $length, true); + } + + /** + * Encrypts a plain text. + * + * @param string $plaintext Plain text. + * @param string|null $key_override Key override. + * + * @return string + */ + final public function encrypt($plaintext, $key_override = null) + { + $iv_size = openssl_cipher_iv_length(self::ENCRYPTION_METHOD); + $iv = openssl_random_pseudo_bytes($iv_size); + + $ciphertext = openssl_encrypt( + $plaintext, + self::ENCRYPTION_METHOD, + $this->_getEncryptionKey($key_override), + OPENSSL_RAW_DATA, + $iv + ); + + // Note: We cover the IV in our HMAC. + $hmac = $this->createSignature($iv . $ciphertext, true); + + return base64_encode($hmac . $iv . $ciphertext); + } + + /** + * Decrypts a cipher text. + * + * @param string $ciphertext Cipher text. + * @param string|null $key_override Key override. + * + * @return string|false + * @throws LogicException When signature verification has failed. + */ + final public function decrypt($ciphertext, $key_override = null) + { + $iv_size = openssl_cipher_iv_length(self::ENCRYPTION_METHOD); + + $decoded = base64_decode($ciphertext); + $hmac = mb_substr($decoded, 0, self::HASHING_KEY_LENGTH, '8bit'); + $iv = mb_substr($decoded, self::HASHING_KEY_LENGTH, $iv_size, '8bit'); + $ciphertext = mb_substr($decoded, self::HASHING_KEY_LENGTH + $iv_size, null, '8bit'); + + $calculated = $this->createSignature($iv . $ciphertext, true); + + if ( !hash_equals($hmac, $calculated) ) { + throw new LogicException('Signature verification of ciphertext failed.'); + } + + return openssl_decrypt( + $ciphertext, + self::ENCRYPTION_METHOD, + $this->_getEncryptionKey($key_override), + OPENSSL_RAW_DATA, + $iv + ); + } + + /** + * Determines if used cipher is available. + * + * @return boolean + */ + final public function cipherAvailable() + { + return in_array(self::ENCRYPTION_METHOD, openssl_get_cipher_methods(), true); + } + +} Property changes on: branches/5.3.x/core/kernel/security/SecurityEncrypter.php ___________________________________________________________________ Added: svn:keywords + Id Added: svn:eol-style + LF Index: branches/5.3.x/core/install/step_templates/sys_requirements.tpl =================================================================== --- branches/5.3.x/core/install/step_templates/sys_requirements.tpl (revision 16722) +++ branches/5.3.x/core/install/step_templates/sys_requirements.tpl (revision 16723) @@ -1,72 +1,73 @@ %s '; $error_tpl = ' %s %s '; $check_titles = Array ( 'php_version' => 'PHP version 5.3.9 or above*', 'url_rewriting' => 'URL rewriting support', 'java' => 'Java template compression', 'composer' => 'Dependencies via Composer*', 'sep1' => 'PHP extensions:', 'memcache' => '- Memory caching support', 'curl' => '- Accessing remote resources (via cURL)*', 'simplexml' => '- XML document processing (via SimpleXML)*', 'spl' => '- Standard PHP Library (SPL)*', 'freetype' => '- TrueType font support (via Freetype)*', 'gd_version' => '- GD Graphics Library 1.8 or above*', 'jpeg' => '- JPEG images support*', 'mysql' => '- Database connectivity (via MySQL)*', 'json' => '- JSON processing support*', + 'openssl' => '- OpenSSL support*', 'sep2' => 'PHP settings:', 'memory_limit' => "- Memory requirements changing on the fly", 'display_errors' => "- Prevent script errors in production environment", 'error_reporting' => "- Change error detalization level", 'date.timezone' => "- Web server timezone is explicitly set*", 'variables_order' => '- Needed super-global arrays registered', 'output_buffering' => "- Script output buffering enabled*", ); $output = sprintf($heading_tpl, 'Server-side requirements'); $check_results = $this->toolkit->CallPrerequisitesMethod('core/', 'CheckSystemRequirements'); foreach ($check_titles AS $key => $title) { if ( substr($key, 0, 3) == 'sep' ) { $check_result = ''; } else { $check_result = $check_results[$key] ? '[PASSED]' : '[FAILED]'; } $output .= sprintf($error_tpl, $title, $check_result); } $output .= sprintf($heading_tpl, 'Client-side requirements', 'text'); $output .= sprintf($error_tpl, 'Cookies enabled', '[FAILED]'); $output .= sprintf($error_tpl, 'JavaScript enabled', '[FAILED]'); $output .= ''; $output .= ''; $output .= ""; echo $output; ?> Index: branches/5.3.x/core/install/prerequisites.php =================================================================== --- branches/5.3.x/core/install/prerequisites.php (revision 16722) +++ branches/5.3.x/core/install/prerequisites.php (revision 16723) @@ -1,243 +1,246 @@ Array ('from' => '5.0.0-B1', 'to' => '5.1.0-B1'), '5.1.0' => Array ('from' => '5.1.0-B1', 'to' => '5.2.0-B1'), '5.2.0' => Array ('from' => '5.2.0-B1', 'to' => '5.3.0-B1'), ); /** * Sets common instance of installator toolkit * * @param kInstallToolkit $instance */ function setToolkit(&$instance) { $this->_toolkit =& $instance; } /** * Checks minimal version, that could be upgradeable * * @return IDBConnection */ function getConnection() { return $this->_toolkit->Conn; } /** * Checks minimal version, that could be upgradeable * * @param Array $versions * @param string $mode when called mode {install, upgrade, standalone) * @return Array */ function CheckPrerequisites($versions, $mode) { $errors = Array (); if ( $mode == 'upgrade' ) { $sql = 'SELECT Version FROM ' . TABLE_PREFIX . 'Modules WHERE Name = "In-Portal"'; $inportal_version = $this->getConnection()->GetOne($sql); if ( $inportal_version === false ) { // only, when In-Portal was installed (below 4.3.x) return $errors; } $min_version = '4.3.1'; // K4-based installator was created, that no longer maintained old upgrade scripts if ( version_compare($inportal_version, $min_version, '<') ) { $errors[] = 'Please upgrade "In-Portal" to version ' . $min_version . ' first'; } // example: to upgrade to 5.1.0-B1 or more you at least need to have 5.0.0 installed foreach ($this->upgradeRules as $min_version => $version_rules) { if ( version_compare($versions[0], $version_rules['from'], '<') && version_compare($versions[1], $version_rules['to'], '>=') ) { $errors[] = 'Please upgrade "In-Portal" to version ' . $min_version . ' first'; break; } } } return $errors; } /** * Returns information about system requirements * * @return array */ function CheckSystemRequirements() { $ret = Array (); $ret['php_version'] = version_compare(PHP_VERSION, '5.3.9', '>='); if ( function_exists('apache_get_modules') ) { $mod_rewrite = in_array('mod_rewrite', apache_get_modules()); } else { $mod_rewrite = getenv('HTTP_MOD_REWRITE') == 'On'; } $ret['url_rewriting'] = $mod_rewrite; $ret['memcache'] = class_exists('Memcache'); $ret['curl'] = function_exists('curl_init'); $ret['simplexml'] = function_exists('simplexml_load_string'); $ret['spl'] = function_exists('spl_autoload_register'); $ret['freetype'] = function_exists('imagettfbbox'); $ret['gd_version'] = false; if ( function_exists('gd_info') ) { $gd_info = gd_info(); $gd_version = preg_replace('/[^\d.]/', '', $gd_info['GD Version']); $ret['gd_version'] = version_compare($gd_version, '1.8', '>='); } $ret['jpeg'] = function_exists('imagecreatefromjpeg'); $ret['mysql'] = function_exists('mysqli_connect'); $ret['json'] = function_exists('json_encode'); + // Unable to properly use "SecurityEncrypter::cipherAvailable" method, because no factory here. + $ret['openssl'] = function_exists('openssl_encrypt') && in_array('aes-128-cbc', openssl_get_cipher_methods(), true); + $output = shell_exec('java -version 2>&1'); $ret['java'] = stripos($output, 'java version') !== false; $ret['composer'] = file_exists(FULL_PATH . '/vendor/autoload.php'); $ret['memory_limit'] = $this->isPhpSettingChangeable('memory_limit', '33M'); $ret['display_errors'] = $this->isPhpSettingChangeable('display_errors', '1'); $ret['error_reporting'] = $this->canChangeErrorReporting(); $ret['date.timezone'] = ini_get('date.timezone') != ''; $ret['variables_order'] = $this->_hasLetters(ini_get('variables_order'), Array ('G', 'P', 'C', 'S')); $output_buffering = strtolower(ini_get('output_buffering')); $ret['output_buffering'] = $output_buffering == 'on' || $output_buffering > 0; return $ret; } /** * Determines of a setting string has all given letters (ignoring order) in it * * @param string $setting * @param Array $search_letters * @return bool * @access protected */ protected function _hasLetters($setting, $search_letters) { $setting = preg_replace('/(' . implode('|', $search_letters) . ')/', '*', $setting); return substr_count($setting, '*') == count($search_letters); } /** * Detects if error reporting can be changed at runtime * * @return bool * @access protected */ protected function canChangeErrorReporting() { $old_value = error_reporting(E_PARSE); $new_value = error_reporting(); if ( $new_value == E_PARSE ) { error_reporting($old_value); return true; } return false; } /** * Detects if setting of php.ini can be changed * * @param string $setting_name * @param string $new_value * @return bool */ protected function isPhpSettingChangeable($setting_name, $new_value) { $old_value = ini_get($setting_name); if ( ini_set($setting_name, $new_value) === false ) { return false; } ini_set($setting_name, $old_value); return true; } /** * Returns information about DB requirements * * @return array */ function CheckDBRequirements() { // check PHP version 5.2+ $ret = Array(); $sql = 'SELECT VERSION()'; $conn = $this->getConnection(); $db_version = preg_replace('/[^\d.]/', '', $conn->GetOne($sql)); $ret['version'] = version_compare($db_version, '5.0', '>='); $sql = 'SHOW VARIABLES LIKE "max_allowed_packet"'; $db_variables = $conn->Query($sql, 'Variable_name'); $ret['packet_size'] = $db_variables['max_allowed_packet']['Value'] >= 1048576; return $ret; } } Index: branches/5.3.x/core/install.php =================================================================== --- branches/5.3.x/core/install.php (revision 16722) +++ branches/5.3.x/core/install.php (revision 16723) @@ -1,1777 +1,1795 @@ Init(); $install_engine->Run(); $install_engine->Done(); class kInstallator { /** * Reference to kApplication class object * * @var kApplication */ var $Application = null; /** * Connection to database * * @var IDBConnection */ var $Conn = null; /** * XML file containing steps information * * @var string */ var $StepDBFile = ''; /** * Step name, that currently being processed * * @var string */ var $currentStep = ''; /** * Steps list (preset) to use for current installation * * @var string */ var $stepsPreset = ''; /** * Installation steps to be done * * @var Array */ var $steps = Array ( 'fresh_install' => Array ('sys_requirements', 'check_paths', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'sys_config', 'select_theme', 'security', 'finish'), 'clean_reinstall' => Array ('install_setup', 'sys_requirements', 'check_paths', 'clean_db', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'sys_config', 'select_theme', 'security', 'finish'), 'already_installed' => Array ('check_paths', 'install_setup'), 'upgrade' => Array ('check_paths', 'install_setup', 'sys_config', 'upgrade_modules', 'skin_upgrade', 'security', 'finish'), 'update_license' => Array ('check_paths', 'install_setup', 'select_license', /*'download_license',*/ 'select_domain', 'security', 'finish'), 'update_config' => Array ('check_paths', 'install_setup', 'sys_config', 'security', 'finish'), 'db_reconfig' => Array ('check_paths', 'install_setup', 'db_reconfig', 'security', 'finish'), 'sys_requirements' => Array ('check_paths', 'install_setup', 'sys_requirements', 'security', 'finish') ); /** * Steps, that doesn't required admin to be logged-in to proceed * * @var Array */ var $skipLoginSteps = Array ('sys_requirements', 'check_paths', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish', -1); /** * Steps, on which kApplication should not be initialized, because of missing correct db table structure * * @var Array */ var $skipApplicationSteps = Array ('sys_requirements', 'check_paths', 'clean_db', 'db_config', 'db_reconfig' /*, 'install_setup'*/); // remove install_setup when application will work separately from install /** * Folders that should be writeable to continue installation. $1 - main writeable folder from config.php ("/system" by default) * * @var Array */ var $writeableFolders = Array ( '$1', '$1/.restricted', '$1/images', '$1/images/pending', '$1/images/emoticons', // for "In-Bulletin" '$1/user_files', '$1/cache', ); /** * Contains last error message text * * @var string */ var $errorMessage = ''; /** * Base path for includes in templates * * @var string */ var $baseURL = ''; /** * Holds number of last executed query in the SQL * * @var int */ var $LastQueryNum = 0; /** * Dependencies, that should be used in upgrade process * * @var Array */ var $upgradeDepencies = Array (); /** * Log of upgrade - list of upgraded modules and their versions * * @var Array */ var $upgradeLog = Array (); /** * Common tools required for installation process * * @var kInstallToolkit */ var $toolkit = null; function Init() { include_once(FULL_PATH . REL_PATH . '/kernel/kbase.php'); // required by kDBConnection class include_once(FULL_PATH . REL_PATH . '/kernel/utility/multibyte.php'); // emulating multi-byte php extension include_once(FULL_PATH . REL_PATH . '/kernel/utility/system_config.php'); require_once(FULL_PATH . REL_PATH . '/install/install_toolkit.php'); // toolkit required for module installations to installator $this->toolkit = new kInstallToolkit(); $this->toolkit->setInstallator($this); $this->StepDBFile = FULL_PATH.'/'.REL_PATH.'/install/steps_db.xml'; $this->baseURL = 'http://' . $_SERVER['HTTP_HOST'] . $this->toolkit->systemConfig->get('WebsitePath', 'Misc') . '/core/install/'; set_error_handler( Array(&$this, 'ErrorHandler') ); if ( $this->toolkit->systemConfigFound() ) { // if config.php found, then check his write permission too $this->writeableFolders[] = $this->toolkit->systemConfig->get('WriteablePath', 'Misc') . '/config.php'; } $this->currentStep = $this->GetVar('step'); // can't check login on steps where no application present anyways :) $this->skipLoginSteps = array_unique(array_merge($this->skipLoginSteps, $this->skipApplicationSteps)); $this->SelectPreset(); if (!$this->currentStep) { $this->SetFirstStep(); // sets first step of current preset } $this->InitStep(); } function SetFirstStep() { reset($this->steps[$this->stepsPreset]); $this->currentStep = current($this->steps[$this->stepsPreset]); } /** * Selects preset to proceed based on various criteria * */ function SelectPreset() { $preset = $this->GetVar('preset'); if ($this->toolkit->systemConfigFound()) { // only at installation first step $status = $this->CheckDatabase(false); if ($status && $this->AlreadyInstalled()) { // if already installed, then all future actions need login to work $this->skipLoginSteps = Array ('check_paths', -1); if (!$preset) { $preset = 'already_installed'; $this->currentStep = ''; } } } if ($preset === false) { $preset = 'fresh_install'; // default preset } $this->stepsPreset = $preset; } /** * Returns variable from request * * @param string $name * @param mixed $default * @return string|bool * @access private */ private function GetVar($name, $default = false) { if ( array_key_exists($name, $_COOKIE) ) { return $_COOKIE[$name]; } if ( array_key_exists($name, $_POST) ) { return $_POST[$name]; } return array_key_exists($name, $_GET) ? $_GET[$name] : $default; } /** * Sets new value for request variable * * @param string $name * @param mixed $value * @return void * @access private */ private function SetVar($name, $value) { $_POST[$name] = $value; } /** * Performs needed intialization of data, that step requires * */ function InitStep() { $require_login = !in_array($this->currentStep, $this->skipLoginSteps); $this->InitApplication($require_login); if ($require_login) { // step require login to proceed if (!$this->Application->LoggedIn()) { $this->stepsPreset = 'already_installed'; $this->currentStep = 'install_setup'; // manually set 2nd step, because 'check_paths' step doesn't contain login form // $this->SetFirstStep(); } } switch ($this->currentStep) { case 'sys_requirements': $required_checks = Array ( 'php_version', 'composer', 'curl', 'simplexml', 'freetype', 'gd_version', - 'jpeg', 'mysql', 'json', 'date.timezone', 'output_buffering', + 'jpeg', 'mysql', 'json', 'openssl', 'date.timezone', 'output_buffering', ); $check_results = $this->toolkit->CallPrerequisitesMethod('core/', 'CheckSystemRequirements'); $required_checks = array_diff($required_checks, array_keys( array_filter($check_results) )); if ( $required_checks ) { // php-based checks failed - show error $this->errorMessage = '
Installation can not continue until all required environment parameters are set correctly'; } elseif ( $this->GetVar('js_enabled') === false ) { // can't check JS without form submit - set some fake error, so user stays on this step $this->errorMessage = ' '; } elseif ( !$this->GetVar('js_enabled') || !$this->GetVar('cookies_enabled') ) { // js/cookies disabled $this->errorMessage = '
Installation can not continue until all required environment parameters are set correctly'; } break; case 'check_paths': $writeable_base = $this->toolkit->systemConfig->get('WriteablePath', 'Misc'); foreach ($this->writeableFolders as $folder_path) { $file_path = FULL_PATH . str_replace('$1', $writeable_base, $folder_path); if (file_exists($file_path) && !is_writable($file_path)) { $this->errorMessage = '
Installation can not continue until all required permissions are set correctly'; break; } } break; case 'clean_db': // don't use Application, because all tables will be erased and it will crash $sql = 'SELECT Path FROM ' . TABLE_PREFIX . 'Modules'; $modules = $this->Conn->GetCol($sql); foreach ($modules as $module_folder) { $remove_file = '/' . $module_folder . 'install/remove_schema.sql'; if (file_exists(FULL_PATH . $remove_file)) { $this->toolkit->RunSQL($remove_file); } } $this->toolkit->deleteEditTables(); $this->currentStep = $this->GetNextStep(); break; case 'db_config': case 'db_reconfig': $fields = Array ( 'DBType', 'DBHost', 'DBName', 'DBUser', 'DBUserPassword', 'DBCollation', 'TablePrefix' ); // set fields foreach ($fields as $field_name) { $submit_value = $this->GetVar($field_name); if ($submit_value !== false) { $this->toolkit->systemConfig->set($field_name, 'Database', $submit_value); } /*else { $this->toolkit->systemConfig->set($field_name, 'Database', ''); }*/ } break; case 'download_license': $license_source = $this->GetVar('license_source'); if ($license_source !== false && $license_source != 1) { // previous step was "Select License" and not "Download from Intechnic" option was selected $this->currentStep = $this->GetNextStep(); } break; case 'choose_modules': // if no modules found, then proceed to next step $modules = $this->ScanModules(); if (!$modules) { $this->currentStep = $this->GetNextStep(); } break; case 'select_theme': // put available theme list in database $this->toolkit->rebuildThemes(); break; case 'upgrade_modules': // get installed modules from db and compare their versions to upgrade script $modules = $this->GetUpgradableModules(); if (!$modules) { $this->currentStep = $this->GetNextStep(); } break; case 'skin_upgrade': if ($this->Application->RecallVar('SkinUpgradeLog') === false) { // no errors during skin upgrade -> skip this step $this->currentStep = $this->GetNextStep(); } break; case 'install_setup': if ( $this->Application->TableFound(TABLE_PREFIX . 'UserSession', true) ) { // update to 5.2.0 -> rename session table before using it // don't rename any other table here, since their names could be used in upgrade script $this->Conn->Query('RENAME TABLE ' . TABLE_PREFIX . 'UserSession TO ' . TABLE_PREFIX . 'UserSessions'); $this->Conn->Query('RENAME TABLE ' . TABLE_PREFIX . 'SessionData TO ' . TABLE_PREFIX . 'UserSessionData'); } $next_preset = $this->Application->GetVar('next_preset'); if ($next_preset !== false) { /** @var UserHelper $user_helper */ $user_helper = $this->Application->recallObject('UserHelper'); $username = $this->Application->GetVar('login'); $password = $this->Application->GetVar('password'); if ($username == 'root') { // verify "root" user using configuration settings $login_result = $user_helper->loginUser($username, $password); if ($login_result != LoginResult::OK) { $error_phrase = $login_result == LoginResult::NO_PERMISSION ? 'la_no_permissions' : 'la_invalid_password'; $this->errorMessage = $this->Application->Phrase($error_phrase) . '. If you don\'t know your username or password, contact Intechnic Support'; } } else { // non "root" user -> verify using licensing server $url_params = Array ( 'login' => md5($username), 'password' => md5($password), 'action' => 'check', 'license_code' => base64_encode( $this->toolkit->systemConfig->get('LicenseCode', 'Intechnic') ), 'version' => '4.3.0',//$this->toolkit->GetMaxModuleVersion('core/'), 'domain' => base64_encode($_SERVER['HTTP_HOST']), ); /** @var kCurlHelper $curl_helper */ $curl_helper = $this->Application->recallObject('CurlHelper'); $curl_helper->SetRequestData($url_params); $file_data = $curl_helper->Send(GET_LICENSE_URL); if ( !$curl_helper->isGoodResponseCode() ) { $this->errorMessage = 'In-Portal servers temporarily unavailable. Please contact In-Portal support personnel directly.'; } elseif (substr($file_data, 0, 5) == 'Error') { $this->errorMessage = substr($file_data, 6) . ' If you don\'t know your username or password, contact Intechnic Support'; } if ($this->errorMessage == '') { $user_helper->loginUserById(USER_ROOT); } } if ($this->errorMessage == '') { // processed with redirect to selected step preset if (!isset($this->steps[$next_preset])) { $this->errorMessage = 'Preset "'.$next_preset.'" not yet implemented'; } else { $this->stepsPreset = $next_preset; } } } else { // if preset was not choosen, then raise error $this->errorMessage = 'Please select action to perform'; } break; case 'security': // perform write check if ($this->Application->GetVar('skip_security_check')) { // administrator intensionally skips security checks break; } $write_check = true; $check_paths = Array ('/', '/index.php', $this->toolkit->systemConfig->get('WriteablePath', 'Misc') . '/config.php', ADMIN_DIRECTORY . '/index.php'); foreach ($check_paths as $check_path) { $path_check_status = $this->toolkit->checkWritePermissions(FULL_PATH . $check_path); if (is_bool($path_check_status) && $path_check_status) { $write_check = false; break; } } // script execute check if (file_exists(WRITEABLE . '/install_check.php')) { unlink(WRITEABLE . '/install_check.php'); } $fp = fopen(WRITEABLE . '/install_check.php', 'w'); fwrite($fp, "Application->recallObject('CurlHelper'); $output = $curl_helper->Send($this->Application->BaseURL() . ltrim(WRITEBALE_BASE, '/') . '/install_check.php'); unlink(WRITEABLE . '/install_check.php'); $execute_check = ($output !== 'OK'); $directive_check = true; $ini_vars = Array ('register_globals' => false, 'open_basedir' => true, 'allow_url_fopen' => false); foreach ($ini_vars as $var_name => $var_value) { $current_value = ini_get($var_name); if (($var_value && !$current_value) || (!$var_value && $current_value)) { $directive_check = false; break; } } if (!$write_check || !$execute_check || !$directive_check) { $this->errorMessage = true; } /*else { $this->currentStep = $this->GetNextStep(); }*/ break; } $this->PerformValidation(); // returns validation status (just in case) } /** * Validates data entered by user * * @return bool */ function PerformValidation() { if ($this->GetVar('step') != $this->currentStep) { // just redirect from previous step, don't validate return true; } $status = true; switch ($this->currentStep) { case 'db_config': case 'db_reconfig': // 1. check if required fields are filled $section_name = 'Database'; $required_fields = Array ('DBType', 'DBHost', 'DBName', 'DBUser', 'DBCollation'); foreach ($required_fields as $required_field) { if (!$this->toolkit->systemConfig->get($required_field, $section_name)) { $status = false; $this->errorMessage = 'Please fill all required fields'; break; } } if ( !$status ) { break; } // 2. check permissions, that use have in this database $status = $this->CheckDatabase(($this->currentStep == 'db_config') && !$this->GetVar('UseExistingSetup')); break; case 'select_license': $license_source = $this->GetVar('license_source'); if ($license_source == 2) { // license from file -> file must be uploaded $upload_error = $_FILES['license_file']['error']; if ($upload_error != UPLOAD_ERR_OK) { $this->errorMessage = 'Missing License File'; } } elseif (!is_numeric($license_source)) { $this->errorMessage = 'Please select license'; } $status = $this->errorMessage == ''; break; case 'root_password': // check, that password & verify password match $password = $this->Application->GetVar('root_password'); $password_verify = $this->Application->GetVar('root_password_verify'); if ($password != $password_verify) { $this->errorMessage = 'Passwords does not match'; } elseif (mb_strlen($password) < 4) { $this->errorMessage = 'Root Password must be at least 4 characters'; } $status = $this->errorMessage == ''; break; case 'choose_modules': break; case 'upgrade_modules': $modules = $this->Application->GetVar('modules'); if (!$modules) { $modules = Array (); $this->errorMessage = 'Please select module(-s) to ' . ($this->currentStep == 'choose_modules' ? 'install' : 'upgrade'); } // check interface module $upgrade_data = $this->GetUpgradableModules(); if (array_key_exists('core', $upgrade_data) && !in_array('core', $modules)) { // core can be upgraded, but isn't selected $this->errorMessage = 'Please select "Core" as interface module'; } $status = $this->errorMessage == ''; break; } return $status; } /** * Perform installation step actions * */ function Run() { if ($this->errorMessage) { // was error during data validation stage return ; } switch ($this->currentStep) { case 'db_config': case 'db_reconfig': // store db configuration $sql = 'SHOW COLLATION LIKE \''.$this->toolkit->systemConfig->get('DBCollation', 'Database').'\''; $collation_info = $this->Conn->Query($sql); if ($collation_info) { $this->toolkit->systemConfig->set('DBCharset', 'Database', $collation_info[0]['Charset']); // database is already connected, that's why set collation on the fly $this->Conn->Query('SET NAMES \''.$this->toolkit->systemConfig->get('DBCharset', 'Database').'\' COLLATE \''.$this->toolkit->systemConfig->get('DBCollation', 'Database').'\''); } $this->toolkit->systemConfig->save(); if ($this->currentStep == 'db_config') { if ($this->GetVar('UseExistingSetup')) { // abort clean install and redirect to already_installed $this->stepsPreset = 'already_installed'; break; } // import base data into new database, not for db_reconfig $this->toolkit->RunSQL('/core/install/install_schema.sql'); $this->toolkit->RunSQL('/core/install/install_data.sql'); // create category using sql, because Application is not available here $table_name = $this->toolkit->systemConfig->get('TablePrefix', 'Database') . 'IdGenerator'; $this->Conn->Query('UPDATE ' . $table_name . ' SET lastid = lastid + 1'); $resource_id = $this->Conn->GetOne('SELECT lastid FROM ' . $table_name); if ($resource_id === false) { $this->Conn->Query('INSERT INTO '.$table_name.' (lastid) VALUES (2)'); $resource_id = 2; } // can't use USER_ROOT constant, since Application isn't available here $fields_hash = Array ( 'l1_Name' => 'Content', 'l1_MenuTitle' => 'Content', 'Filename' => 'Content', 'AutomaticFilename' => 0, 'CreatedById' => -1, 'CreatedOn' => time(), 'ResourceId' => $resource_id - 1, 'l1_Description' => 'Content', 'Status' => 4, ); $this->Conn->doInsert($fields_hash, $this->toolkit->systemConfig->get('TablePrefix', 'Database') . 'Categories'); $this->toolkit->SetModuleRootCategory('Core', $this->Conn->getInsertID()); // set module "Core" version after install (based on upgrade scripts) $this->toolkit->SetModuleVersion('Core', 'core/'); // for now we set "In-Portal" module version to "Core" module version (during clean install) $this->toolkit->SetModuleVersion('In-Portal', 'core/'); } break; case 'select_license': // reset memory cache, when application is first available (on fresh install and clean reinstall steps) $this->Application->HandleEvent(new kEvent('adm:OnResetMemcache')); $license_source = $this->GetVar('license_source'); switch ($license_source) { case 1: // Download from Intechnic break; case 2: // Upload License File $file_data = array_map('trim', file($_FILES['license_file']['tmp_name'])); if ((count($file_data) == 3) && $file_data[1]) { /** @var kModulesHelper $modules_helper */ $modules_helper = $this->Application->recallObject('kModulesHelper'); if ($modules_helper->verifyLicense($file_data[1])) { $this->toolkit->systemConfig->set('License', 'Intechnic', $file_data[1]); $this->toolkit->systemConfig->set('LicenseCode', 'Intechnic', $file_data[2]); $this->toolkit->systemConfig->save(); } else { $this->errorMessage = 'Invalid License File'; } } else { $this->errorMessage = 'Invalid License File'; } break; case 3: // Use Existing License $license_hash = $this->toolkit->systemConfig->get('License', 'Intechnic'); if ($license_hash) { /** @var kModulesHelper $modules_helper */ $modules_helper = $this->Application->recallObject('kModulesHelper'); if (!$modules_helper->verifyLicense($license_hash)) { $this->errorMessage = 'Invalid or corrupt license detected'; } } else { // happens, when browser's "Back" button is used $this->errorMessage = 'Missing License File'; } break; case 4: // Skip License (Local Domain Installation) if ($this->toolkit->sectionFound('Intechnic')) { // remove any previous license information $this->toolkit->systemConfig->set('License', 'Intechnic'); $this->toolkit->systemConfig->set('LicenseCode', 'Intechnic'); $this->toolkit->systemConfig->save(); } break; } break; case 'download_license': $license_login = $this->GetVar('login'); $license_password = $this->GetVar('password'); $license_id = $this->GetVar('licenses'); /** @var kCurlHelper $curl_helper */ $curl_helper = $this->Application->recallObject('CurlHelper'); if (strlen($license_login) && strlen($license_password) && !$license_id) { // Here we determine weather login is ok & check available licenses $url_params = Array ( 'login' => md5($license_login), 'password' => md5($license_password), 'version' => $this->toolkit->GetMaxModuleVersion('core/'), 'domain' => base64_encode($_SERVER['HTTP_HOST']), ); $curl_helper->SetRequestData($url_params); $file_data = $curl_helper->Send(GET_LICENSE_URL); if (!$file_data) { // error connecting to licensing server $this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!'; } else { if (substr($file_data, 0, 5) == 'Error') { // after processing data server returned error $this->errorMessage = substr($file_data, 6); } else { // license received if (substr($file_data, 0, 3) == 'SEL') { // we have more, then one license -> let user choose $this->SetVar('license_selection', base64_encode( substr($file_data, 4) )); // we received html with radio buttons with names "licenses" $this->errorMessage = 'Please select which license to use'; } else { // we have one license $this->toolkit->processLicense($file_data); } } } } else if (!$license_id) { // licenses were not queried AND user/password missing $this->errorMessage = 'Incorrect Username or Password. If you don\'t know your username or password, contact Intechnic Support'; } else { // Here we download license $url_params = Array ( 'license_id' => md5($license_id), 'dlog' => md5($license_login), 'dpass' => md5($license_password), 'version' => $this->toolkit->GetMaxModuleVersion('core/'), 'domain' => base64_encode($_SERVER['HTTP_HOST']), ); $curl_helper->SetRequestData($url_params); $file_data = $curl_helper->Send(GET_LICENSE_URL); if (!$file_data) { // error connecting to licensing server $this->errorMessage = 'Unable to connect to the Intechnic server! Please try again later!'; } else { if (substr($file_data, 0, 5) == 'Error') { // after processing data server returned error $this->errorMessage = substr($file_data, 6); } else { $this->toolkit->processLicense($file_data); } } } break; case 'select_domain': /** @var kModulesHelper $modules_helper */ $modules_helper = $this->Application->recallObject('kModulesHelper'); // get domain name as entered by user on the form $domain = $this->GetVar('domain') == 1 ? $_SERVER['HTTP_HOST'] : str_replace(' ', '', $this->GetVar('other')); $license_hash = $this->toolkit->systemConfig->get('License', 'Intechnic'); if ($license_hash) { // when license present, then extract domain from it $license_hash = base64_decode($license_hash); list ( , , $license_keys) = $modules_helper->_ParseLicense($license_hash); $license_domain = $license_keys[0]['domain']; } else { // when license missing, then use current domain or domain entered by user $license_domain = $domain; } if ($domain != '') { if (strstr($domain, $license_domain) || $modules_helper->_IsLocalSite($domain)) { $this->toolkit->systemConfig->set('Domain', 'Misc', $domain); $this->toolkit->systemConfig->save(); } else { $this->errorMessage = 'Domain name entered does not match domain name in the license!'; } } else { $this->errorMessage = 'Please enter valid domain!'; } break; case 'sys_config': $config_data = $this->GetVar('system_config'); foreach ($config_data as $section => $section_vars) { foreach ($section_vars as $var_name => $var_value) { $this->toolkit->systemConfig->set($var_name, $section, $var_value); } } + if ( !$this->toolkit->systemConfig->get('SecurityHmacKey', 'Misc') + || !$this->toolkit->systemConfig->get('SecurityEncryptionKey', 'Misc') + ) { + $this->toolkit->systemConfig->set( + 'SecurityHmacKey', + 'Misc', + base64_encode(SecurityGenerator::generateString( + SecurityEncrypter::HASHING_KEY_LENGTH, + SecurityGenerator::CHAR_ALNUM | SecurityGenerator::CHAR_SYMBOLS + )) + ); + $this->toolkit->systemConfig->set( + 'SecurityEncryptionKey', + 'Misc', + SecurityGenerator::generateBytes(SecurityEncrypter::ENCRYPTION_KEY_LENGTH) + ); + } + $this->toolkit->systemConfig->save(); break; case 'root_password': // update root password in database /** @var kPasswordFormatter $password_formatter */ $password_formatter = $this->Application->recallObject('kPasswordFormatter'); $config_values = Array ( 'RootPass' => $password_formatter->hashPassword($this->Application->GetVar('root_password')), 'Backup_Path' => FULL_PATH . $this->toolkit->systemConfig->get('WriteablePath', 'Misc') . DIRECTORY_SEPARATOR . 'backupdata', 'DefaultEmailSender' => 'portal@' . $this->toolkit->systemConfig->get('Domain', 'Misc') ); $site_timezone = date_default_timezone_get(); if ($site_timezone) { $config_values['Config_Site_Time'] = $site_timezone; } $this->toolkit->saveConfigValues($config_values); /** @var UserHelper $user_helper */ $user_helper = $this->Application->recallObject('UserHelper'); // login as "root", when no errors on password screen $user_helper->loginUser('root', $this->Application->GetVar('root_password')); // import base language for core (english) $this->toolkit->ImportLanguage('/core/install/english'); // make sure imported language is set as active in session, created during installation $this->Application->Session->SetField('Language', 1); // set imported language as primary /** @var LanguagesItem $lang */ $lang = $this->Application->recallObject('lang.-item', null, Array('skip_autoload' => true)); $lang->Load(1); // fresh install => ID=1 $lang->setPrimary(true); // for Front-End break; case 'choose_modules': // run module install scripts $modules = $this->Application->GetVar('modules'); if ($modules) { foreach ($modules as $module) { $install_file = MODULES_PATH.'/'.$module.'/install.php'; if (file_exists($install_file)) { include_once($install_file); } } } // update category cache /** @var kPermCacheUpdater $updater */ $updater = $this->Application->makeClass('kPermCacheUpdater'); $updater->OneStepRun(); break; case 'post_config': $this->toolkit->saveConfigValues( $this->GetVar('config') ); break; case 'select_theme': // 1. mark theme, that user is selected $theme_id = $this->GetVar('theme'); $theme_config = $this->Application->getUnitConfig('theme'); $theme_table = $theme_config->getTableName(); $theme_id_field = $theme_config->getIDField(); $sql = 'UPDATE ' . $theme_table . ' SET Enabled = 1, PrimaryTheme = 1 WHERE ' . $theme_id_field . ' = ' . $theme_id; $this->Conn->Query($sql); $this->toolkit->rebuildThemes(); // rescan theme to create structure after theme is enabled !!! // install theme dependent demo data if ($this->Application->GetVar('install_demo_data')) { $sql = 'SELECT Name FROM ' . $theme_table . ' WHERE ' . $theme_id_field . ' = ' . $theme_id; $theme_name = $this->Conn->GetOne($sql); $site_path = $this->toolkit->systemConfig->get('WebsitePath','Misc') . '/'; /** @var FileHelper $file_helper */ $file_helper = $this->Application->recallObject('FileHelper'); foreach ($this->Application->ModuleInfo as $module_name => $module_info) { if ($module_name == 'In-Portal') { continue; } $template_path = '/themes' . '/' . $theme_name . '/' . $module_info['TemplatePath']; $this->toolkit->RunSQL( $template_path . '_install/install_data.sql', Array('{ThemeId}', '{SitePath}'), Array($theme_id, $site_path) ); if ( file_exists(FULL_PATH . $template_path . '_install/images') ) { // copy theme demo images into writable path accessible by FCKEditor $file_helper->copyFolderRecursive(FULL_PATH . $template_path . '_install/images' . DIRECTORY_SEPARATOR, WRITEABLE . '/user_files/Images'); } } } break; case 'upgrade_modules': // get installed modules from db and compare their versions to upgrade script $modules = $this->Application->GetVar('modules'); if ($modules) { $upgrade_data = $this->GetUpgradableModules(); $start_from_query = $this->Application->GetVar('start_from_query'); $this->upgradeDepencies = $this->getUpgradeDependencies($modules, $upgrade_data); if ($start_from_query !== false) { $this->upgradeLog = unserialize( $this->Application->RecallVar('UpgradeLog') ); } else { $start_from_query = 0; $this->upgradeLog = Array ('ModuleVersions' => Array ()); // remember each module version, before upgrade scripts are executed foreach ($modules as $module_name) { $module_info = $upgrade_data[$module_name]; $this->upgradeLog['ModuleVersions'][$module_name] = $module_info['FromVersion']; } $this->Application->RemoveVar('UpgradeLog'); } // 1. perform "php before", "sql", "php after" upgrades foreach ($modules as $module_name) { $module_info = $upgrade_data[$module_name]; /*echo '

Upgrading "' . $module_info['Name'] . '" to "' . $module_info['ToVersion'] . '"

' . "\n"; flush();*/ if (!$this->RunUpgrade($module_info['Name'], $module_info['ToVersion'], $upgrade_data, $start_from_query)) { $this->Application->StoreVar('UpgradeLog', serialize($this->upgradeLog)); $this->Done(); } // restore upgradable module version (makes sense after sql error processing) $upgrade_data[$module_name]['FromVersion'] = $this->upgradeLog['ModuleVersions'][$module_name]; } // 2. import language pack, perform "languagepack" upgrade for all upgraded versions foreach ($modules as $module_name) { $module_info = $upgrade_data[$module_name]; $sqls =& $this->getUpgradeQueriesFromVersion($module_info['Path'], $module_info['FromVersion']); preg_match_all('/' . VERSION_MARK . '/s', $sqls, $regs); // import module language pack $this->toolkit->ImportLanguage('/' . $module_info['Path'] . 'install/english', true); // perform advanced language pack upgrade foreach ($regs[1] as $version) { $this->RunUpgradeScript($module_info['Path'], $version, 'languagepack'); } } // 3. update all theme language packs /** @var kThemesHelper $themes_helper */ $themes_helper = $this->Application->recallObject('ThemesHelper'); $themes_helper->synchronizeModule(false); // 4. upgrade admin skin if (in_array('core', $modules)) { $skin_upgrade_log = $this->toolkit->upgradeSkin($upgrade_data['core']); if ($skin_upgrade_log === true) { $this->Application->RemoveVar('SkinUpgradeLog'); } else { $this->Application->StoreVar('SkinUpgradeLog', serialize($skin_upgrade_log)); } // for now we set "In-Portal" module version to "Core" module version (during upgrade) $this->toolkit->SetModuleVersion('In-Portal', false, $upgrade_data['core']['ToVersion']); } } break; case 'finish': // delete cache $this->toolkit->deleteCache(); $this->toolkit->rebuildThemes(); // compile admin skin, so it will be available in 3 frames at once /** @var SkinHelper $skin_helper */ $skin_helper = $this->Application->recallObject('SkinHelper'); /** @var kDBItem $skin */ $skin = $this->Application->recallObject('skin', null, Array ('skip_autoload' => true)); $skin->Load(1, 'IsPrimary'); $skin_helper->compile($skin); // set installation finished mark if ($this->Application->ConfigValue('InstallFinished') === false) { $fields_hash = Array ( 'VariableName' => 'InstallFinished', 'VariableValue' => 1, ); $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'SystemSettings'); } $random_string = $this->Application->ConfigValue('RandomString'); if ( !$random_string ) { $user_helper = $this->Application->recallObject('UserHelper'); /* @var $user_helper UserHelper */ $random_string = $user_helper->generateRandomString(64, true, true); $this->Application->SetConfigValue('RandomString', $random_string); } break; } if ($this->errorMessage) { // was error during run stage return ; } $this->currentStep = $this->GetNextStep(); $this->InitStep(); // init next step (that will be shown now) $this->InitApplication(); if ($this->currentStep == -1) { // step after last step -> redirect to admin /** @var UserHelper $user_helper */ $user_helper = $this->Application->recallObject('UserHelper'); $user_helper->logoutUser(); $this->Application->Redirect($user_helper->event->redirect, $user_helper->event->getRedirectParams(), '', 'index.php'); } } function getUpgradeDependencies($modules, &$upgrade_data) { $dependencies = Array (); foreach ($modules as $module_name) { $module_info = $upgrade_data[$module_name]; $upgrade_object =& $this->getUpgradeObject($module_info['Path']); if (!is_object($upgrade_object)) { continue; } foreach ($upgrade_object->dependencies as $dependent_version => $version_dependencies) { if (!$version_dependencies) { // module is independent -> skip continue; } list ($parent_name, $parent_version) = each($version_dependencies); if (!array_key_exists($parent_name, $dependencies)) { // parent module $dependencies[$parent_name] = Array (); } if (!array_key_exists($parent_version, $dependencies[$parent_name])) { // parent module versions, that are required by other module versions $dependencies[$parent_name][$parent_version] = Array (); } $dependencies[$parent_name][$parent_version][] = Array ($module_info['Name'] => $dependent_version); } } return $dependencies; } /** * Returns database queries, that should be executed to perform upgrade from given to lastest version of given module path * * @param string $module_path * @param string $from_version * @return string */ function &getUpgradeQueriesFromVersion($module_path, $from_version) { $upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'sql'); $sqls = file_get_contents($upgrades_file); $version_mark = preg_replace('/(\(.*?\))/', $from_version, VERSION_MARK); // get only sqls from next (relative to current) version to end of file $start_pos = strpos($sqls, $version_mark); $sqls = substr($sqls, $start_pos); return $sqls; } function RunUpgrade($module_name, $to_version, &$upgrade_data, &$start_from_query) { $module_info = $upgrade_data[ strtolower($module_name) ]; $sqls =& $this->getUpgradeQueriesFromVersion($module_info['Path'], $module_info['FromVersion']); preg_match_all('/(' . VERSION_MARK . ')/s', $sqls, $matches, PREG_SET_ORDER + PREG_OFFSET_CAPTURE); foreach ($matches as $index => $match) { // upgrade version $version = $match[2][0]; if ($this->toolkit->ConvertModuleVersion($version) > $this->toolkit->ConvertModuleVersion($to_version)) { // only upgrade to $to_version, not further break; } if (!in_array($module_name . ':' . $version, $this->upgradeLog)) { if ($this->Application->isDebugMode()) { $this->Application->Debugger->appendHTML('Upgrading "' . $module_name . '" to "' . $version . '" version: BEGIN.'); } /*echo 'Upgrading "' . $module_name . '" to "' . $version . '".
' . "\n"; flush();*/ // don't upgrade same version twice $start_pos = $match[0][1] + strlen($match[0][0]); $end_pos = array_key_exists($index + 1, $matches) ? $matches[$index + 1][0][1] : strlen($sqls); $version_sqls = substr($sqls, $start_pos, $end_pos - $start_pos); if ($start_from_query == 0) { $this->RunUpgradeScript($module_info['Path'], $version, 'before'); } if (!$this->toolkit->RunSQLText($version_sqls, null, null, $start_from_query)) { $this->errorMessage .= ''; $this->errorMessage .= '
Module "' . $module_name . '" upgrade to "' . $version . '" failed.'; $this->errorMessage .= '
Click Continue button below to skip this query and go further
'; return false; } else { // reset query counter, when all queries were processed $start_from_query = 0; } $this->RunUpgradeScript($module_info['Path'], $version, 'after'); if ($this->Application->isDebugMode()) { $this->Application->Debugger->appendHTML('Upgrading "' . $module_name . '" to "' . $version . '" version: END.'); } // remember, that we've already upgraded given version $this->upgradeLog[] = $module_name . ':' . $version; } if (array_key_exists($module_name, $this->upgradeDepencies) && array_key_exists($version, $this->upgradeDepencies[$module_name])) { foreach ($this->upgradeDepencies[$module_name][$version] as $dependency_info) { list ($dependent_module, $dependent_version) = each($dependency_info); if (!$this->RunUpgrade($dependent_module, $dependent_version, $upgrade_data, $start_from_query)) { return false; } } } // only mark module as updated, when all it's dependent modules are upgraded $this->toolkit->SetModuleVersion($module_name, false, $version); } return true; } /** * Run upgrade PHP scripts for module with specified path * * @param string $module_path * @param Array $version * @param string $mode upgrade mode = {before,after,languagepack} */ function RunUpgradeScript($module_path, $version, $mode) { $upgrade_object =& $this->getUpgradeObject($module_path); if (!is_object($upgrade_object)) { return ; } $upgrade_method = 'Upgrade_' . str_replace(Array ('.', '-'), '_', $version); if (method_exists($upgrade_object, $upgrade_method)) { $upgrade_object->$upgrade_method($mode); } } /** * Returns upgrade class for given module path * * @param string $module_path * @return kUpgradeHelper */ function &getUpgradeObject($module_path) { static $upgrade_classes = Array (); $upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'php'); if (!file_exists($upgrades_file)) { $false = false; return $false; } if (!isset($upgrade_classes[$module_path])) { require_once(FULL_PATH . REL_PATH . '/install/upgrade_helper.php'); // save class name, because 2nd time (in after call) // $upgrade_class variable will not be present include_once $upgrades_file; $upgrade_classes[$module_path] = $upgrade_class; } /** @var CoreUpgrades $upgrade_object */ $upgrade_object = new $upgrade_classes[$module_path](); $upgrade_object->setToolkit($this->toolkit); return $upgrade_object; } /** * Initialize kApplication * * @param bool $force initialize in any case */ function InitApplication($force = false) { if (($force || !in_array($this->currentStep, $this->skipApplicationSteps)) && !isset($this->Application)) { // step is allowed for application usage & it was not initialized in previous step global $start, $debugger, $dbg_options; include_once(FULL_PATH.'/core/kernel/startup.php'); $this->Application =& kApplication::Instance(); $this->toolkit->Application =& kApplication::Instance(); $this->includeModuleConstants(); $this->Application->Init(); $this->Conn =& $this->Application->GetADODBConnection(); $this->toolkit->Conn =& $this->Application->GetADODBConnection(); } } /** * When no modules installed, then pre-include all modules contants, since they are used in unit configs * */ function includeModuleConstants() { $modules = $this->ScanModules(); foreach ($modules as $module_path) { $constants_file = MODULES_PATH . '/' . $module_path . '/constants.php'; if ( file_exists($constants_file) ) { kUtil::includeOnce($constants_file); } } } /** * Show next step screen * * @param string $error_message * @return void */ function Done($error_message = null) { if ( isset($error_message) ) { $this->errorMessage = $error_message; } include_once (FULL_PATH . '/' . REL_PATH . '/install/incs/install.tpl'); if ( isset($this->Application) ) { $this->Application->Done(); } exit; } function ConnectToDatabase() { include_once FULL_PATH . '/core/kernel/db/i_db_connection.php'; include_once FULL_PATH . '/core/kernel/db/db_connection.php'; $required_keys = Array ('DBType', 'DBUser', 'DBName'); foreach ($required_keys as $required_key) { if (!$this->toolkit->systemConfig->get($required_key, 'Database')) { // one of required db connection settings missing -> abort connection return false; } } $this->Conn = new kDBConnection($this->toolkit->systemConfig->get('DBType', 'Database'), Array(&$this, 'DBErrorHandler')); $this->Conn->setup($this->toolkit->systemConfig->getData()); // setup toolkit too $this->toolkit->Conn =& $this->Conn; return !$this->Conn->hasError(); } /** * Checks if core is already installed * * @return bool */ function AlreadyInstalled() { $table_prefix = $this->toolkit->systemConfig->get('TablePrefix', 'Database'); $settings_table = $this->TableExists('ConfigurationValues') ? 'ConfigurationValues' : 'SystemSettings'; $sql = 'SELECT VariableValue FROM ' . $table_prefix . $settings_table . ' WHERE VariableName = "InstallFinished"'; return $this->TableExists($settings_table) && $this->Conn->GetOne($sql); } function CheckDatabase($check_installed = true) { // perform various check type to database specified // 1. user is allowed to connect to database // 2. user has all types of permissions in database // 3. database environment settings met minimum requirements if (mb_strlen($this->toolkit->systemConfig->get('TablePrefix', 'Database')) > 7) { $this->errorMessage = 'Table prefix should not be longer than 7 characters'; return false; } // connect to database $status = $this->ConnectToDatabase(); if ($status) { // if connected, then check if all sql statements work $sql_tests[] = 'DROP TABLE IF EXISTS test_table'; $sql_tests[] = 'CREATE TABLE test_table(test_col mediumint(6))'; $sql_tests[] = 'LOCK TABLES test_table WRITE'; $sql_tests[] = 'INSERT INTO test_table(test_col) VALUES (5)'; $sql_tests[] = 'UPDATE test_table SET test_col = 12'; $sql_tests[] = 'UNLOCK TABLES'; $sql_tests[] = 'ALTER TABLE test_table ADD COLUMN new_col varchar(10)'; $sql_tests[] = 'SELECT * FROM test_table'; $sql_tests[] = 'DELETE FROM test_table'; $sql_tests[] = 'DROP TABLE IF EXISTS test_table'; foreach ($sql_tests as $sql_test) { $this->Conn->Query($sql_test); if ($this->Conn->getErrorCode() != 0) { $status = false; break; } } if ($status) { // if statements work & connection made, then check table existance if ($check_installed && $this->AlreadyInstalled()) { $this->errorMessage = 'An In-Portal Database already exists at this location'; return false; } $requirements_error = Array (); $db_check_results = $this->toolkit->CallPrerequisitesMethod('core/', 'CheckDBRequirements'); if ( !$db_check_results['version'] ) { $requirements_error[] = '- MySQL Version is below 5.0'; } if ( !$db_check_results['packet_size'] ) { $requirements_error[] = '- MySQL Packet Size is below 1 MB'; } if ( $requirements_error ) { $this->errorMessage = 'Connection successful, but following system requirements were not met:
' . implode('
', $requirements_error); return false; } } else { // user has insufficient permissions in database specified $this->errorMessage = 'Permission Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg(); return false; } } else { // was error while connecting if (!$this->Conn) return false; $this->errorMessage = 'Connection Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg(); return false; } return true; } /** * Checks if all passed tables exists * * @param string $tables comma separated tables list * @return bool */ function TableExists($tables) { $prefix = $this->toolkit->systemConfig->get('TablePrefix', 'Database'); $all_found = true; $tables = explode(',', $tables); foreach ($tables as $table_name) { $sql = 'SHOW TABLES LIKE "'.$prefix.$table_name.'"'; if (count($this->Conn->Query($sql)) == 0) { $all_found = false; break; } } return $all_found; } /** * Returns modules list found in modules folder * * @return Array */ function ScanModules() { static $modules = null; if ( !isset($modules) ) { // use direct include, because it's called before kApplication::Init, that creates class factory kUtil::includeOnce( KERNEL_PATH . kApplication::MODULE_HELPER_PATH ); $modules_helper = new kModulesHelper(); $modules = $modules_helper->getModules(); } return $modules; } /** * Virtually place module under "modules" folder or it won't be recognized during upgrade to 5.1.0 version * * @param string $name * @param string $path * @param string $version * @return string */ function getModulePath($name, $path, $version) { if ($name == 'Core') { // don't transform path for Core module return $path; } if (!preg_match('/^modules\//', $path)) { // upgrade from 5.0.x/1.0.x to 5.1.x/1.1.x return 'modules/' . $path; } return $path; } /** * Returns list of modules, that can be upgraded * */ function GetUpgradableModules() { $ret = Array (); foreach ($this->Application->ModuleInfo as $module_name => $module_info) { if ($module_name == 'In-Portal') { // don't show In-Portal, because it shares upgrade scripts with Core module continue; } $module_info['Path'] = $this->getModulePath($module_name, $module_info['Path'], $module_info['Version']); $upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql'); if (!file_exists($upgrades_file)) { // no upgrade file continue; } $sqls = file_get_contents($upgrades_file); $versions_found = preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs); if (!$versions_found) { // upgrades file doesn't contain version definitions continue; } $to_version = end($regs[1]); $this_version = $this->toolkit->ConvertModuleVersion($module_info['Version']); if ($this->toolkit->ConvertModuleVersion($to_version) > $this_version) { // destination version is greather then current foreach ($regs[1] as $version) { if ($this->toolkit->ConvertModuleVersion($version) > $this_version) { $from_version = $version; break; } } $version_info = Array ( 'FromVersion' => $from_version, 'ToVersion' => $to_version, ); $ret[ strtolower($module_name) ] = array_merge($module_info, $version_info); } } return $ret; } /** * Returns content to show for current step * * @return string */ function GetStepBody() { $step_template = FULL_PATH.'/core/install/step_templates/'.$this->currentStep.'.tpl'; if (file_exists($step_template)) { ob_start(); include_once ($step_template); return ob_get_clean(); } return '{step template "'.$this->currentStep.'" missing}'; } /** * Parses step information file, cache result for current step ONLY & return it * * @return Array */ function &_getStepInfo() { static $info = Array('help_title' => null, 'step_title' => null, 'help_body' => null, 'queried' => false); if (!$info['queried']) { $fdata = file_get_contents($this->StepDBFile); $parser = xml_parser_create(); xml_parse_into_struct($parser, $fdata, $values, $index); xml_parser_free($parser); foreach ($index['STEP'] as $section_index) { $step_data =& $values[$section_index]; if ($step_data['attributes']['NAME'] == $this->currentStep) { $info['step_title'] = $step_data['attributes']['TITLE']; if (isset($step_data['attributes']['HELP_TITLE'])) { $info['help_title'] = $step_data['attributes']['HELP_TITLE']; } else { // if help title not set, then use step title $info['help_title'] = $step_data['attributes']['TITLE']; } $info['help_body'] = trim($step_data['value']); break; } } $info['queried'] = true; } return $info; } /** * Returns particular information abou current step * * @param string $info_type * @return string */ function GetStepInfo($info_type) { $step_info =& $this->_getStepInfo(); if (isset($step_info[$info_type])) { return $step_info[$info_type]; } return '{step "'.$this->currentStep.'"; param "'.$info_type.'" missing}'; } /** * Returns passed steps titles * * @param Array $steps * @return Array * @see kInstaller:PrintSteps */ function _getStepTitles($steps) { $fdata = file_get_contents($this->StepDBFile); $parser = xml_parser_create(); xml_parse_into_struct($parser, $fdata, $values, $index); xml_parser_free($parser); $ret = Array (); foreach ($index['STEP'] as $section_index) { $step_data =& $values[$section_index]; if (in_array($step_data['attributes']['NAME'], $steps)) { $ret[ $step_data['attributes']['NAME'] ] = $step_data['attributes']['TITLE']; } } return $ret; } /** * Returns current step number in active steps_preset. * Value can't be cached, because same step can have different number in different presets * * @return int */ function GetStepNumber() { return array_search($this->currentStep, $this->steps[$this->stepsPreset]) + 1; } /** * Returns step name to process next * * @return string */ function GetNextStep() { $next_index = $this->GetStepNumber(); if ($next_index > count($this->steps[$this->stepsPreset]) - 1) { return -1; } return $this->steps[$this->stepsPreset][$next_index]; } /** * Returns step name, that was processed before this step * * @return string */ function GetPreviousStep() { $next_index = $this->GetStepNumber() - 1; if ($next_index < 0) { $next_index = 0; } return $this->steps[$this->stepsPreset][$next_index]; } /** * Prints all steps from active steps preset and highlights current step * * @param string $active_tpl * @param string $passive_tpl * @return string */ function PrintSteps($active_tpl, $passive_tpl) { $ret = ''; $step_titles = $this->_getStepTitles($this->steps[$this->stepsPreset]); foreach ($this->steps[$this->stepsPreset] as $step_name) { $template = $step_name == $this->currentStep ? $active_tpl : $passive_tpl; $ret .= sprintf($template, $step_titles[$step_name]); } return $ret; } /** * Installation error handler for sql errors * * @param int $code * @param string $msg * @param string $sql * @return bool * @access private */ function DBErrorHandler($code, $msg, $sql) { $this->errorMessage = 'Query:
'.htmlspecialchars($sql, ENT_QUOTES, 'UTF-8').'
execution result is error:
['.$code.'] '.$msg; return true; } /** * Installation error handler * * @param int $errno * @param string $errstr * @param string $errfile * @param int $errline * @param Array|string $errcontext */ function ErrorHandler($errno, $errstr, $errfile = '', $errline = 0, $errcontext = '') { if ($errno == E_USER_ERROR) { // only react on user fatal errors $this->Done($errstr); } } /** * Checks, that given button should be visible on current installation step * * @param string $name * @return bool */ function buttonVisible($name) { $button_visibility = Array ( 'continue' => $this->GetNextStep() != -1 || ($this->stepsPreset == 'already_installed'), 'refresh' => in_array($this->currentStep, Array ('sys_requirements', 'check_paths', 'security')), 'back' => in_array($this->currentStep, Array (/*'select_license',*/ 'download_license', 'select_domain')), ); if ($name == 'any') { foreach ($button_visibility as $button_name => $button_visible) { if ($button_visible) { return true; } } return false; } return array_key_exists($name, $button_visibility) ? $button_visibility[$name] : true; } } Index: branches/5.3.x/composer.json =================================================================== --- branches/5.3.x/composer.json (revision 16722) +++ branches/5.3.x/composer.json (revision 16723) @@ -1,17 +1,21 @@ { "name": "In-Portal", "require": { + "php": ">=5.3.7", "symfony/console": "~2.6", "stecman/symfony-console-completion": "~0.5", - "symfony/process": "^2.7" + "symfony/process": "^2.7", + "paragonie/random_compat": "^2.0", + "symfony/polyfill-php55": "^1.19", + "symfony/polyfill-php56": "^1.19" }, "require-dev": { "aik099/phpunit-mink": "~2.0", "qa-tools/qa-tools": "~1.0", "aik099/coding-standard": "dev-in-portal", "nikic/php-parser": "~1.2", "mockery/mockery": "~0.9", "behat/mink": "~1.6" } } Index: branches/5.3.x/composer.lock =================================================================== --- branches/5.3.x/composer.lock (revision 16722) +++ branches/5.3.x/composer.lock (revision 16723) @@ -1,1839 +1,2486 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "hash": "d1845e3801289eda5979369163949615", + "content-hash": "f829b982ceec533437242efa2763f61a", "packages": [ { + "name": "ircmaxell/password-compat", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20T16:49:30+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v2.0.21", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/96c132c7f2f7bc3230723b66e89f8f150b29d5ae", + "reference": "96c132c7f2f7bc3230723b66e89f8f150b29d5ae", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "time": "2022-02-16T17:07:03+00:00" + }, + { + "name": "psr/log", + "version": "1.1.4", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", + "reference": "d49695b909c3b7628b6289db5479a1c204601f11", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2021-05-03T11:20:27+00:00" + }, + { "name": "stecman/symfony-console-completion", - "version": "0.5.1", + "version": "0.11.0", + "source": { + "type": "git", + "url": "https://github.com/stecman/symfony-console-completion.git", + "reference": "a9502dab59405e275a9f264536c4e1cb61fc3518" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/stecman/symfony-console-completion/zipball/a9502dab59405e275a9f264536c4e1cb61fc3518", + "reference": "a9502dab59405e275a9f264536c4e1cb61fc3518", + "shasum": "" + }, + "require": { + "php": ">=5.3.2", + "symfony/console": "~2.3 || ~3.0 || ~4.0 || ~5.0" + }, + "require-dev": { + "phpunit/phpunit": "~4.8.36 || ~5.7 || ~6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "0.10.x-dev" + } + }, + "autoload": { + "psr-4": { + "Stecman\\Component\\Symfony\\Console\\BashCompletion\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Stephen Holdaway", + "email": "stephen@stecman.co.nz" + } + ], + "description": "Automatic BASH completion for Symfony Console Component based applications.", + "time": "2019-11-24T17:03:06+00:00" + }, + { + "name": "symfony/console", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "reference": "cbcf4b5e233af15cd2bbd50dee1ccc9b7927dc12", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/debug": "^2.7.2|~3.0.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/event-dispatcher": "~2.1|~3.0.0", + "symfony/process": "~2.1|~3.0.0" + }, + "suggest": { + "psr/log-implementation": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-11-20T15:55:20+00:00" + }, + { + "name": "symfony/debug", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "reference": "74251c8d50dd3be7c4ce0c7b862497cdc641a5d0", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/class-loader": "~2.2|~3.0.0", + "symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony Debug Component", + "homepage": "https://symfony.com", + "abandoned": "symfony/error-handler", + "time": "2018-11-11T11:18:13+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.19.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b5f7b932ee6fa802fc792eabd77c4c88084517ce", + "reference": "b5f7b932ee6fa802fc792eabd77c4c88084517ce", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.19-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T09:01:57+00:00" + }, + { + "name": "symfony/polyfill-php55", + "version": "v1.19.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "248a5c9877b126493abb661e4fb47792e418035b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/248a5c9877b126493abb661e4fb47792e418035b", + "reference": "248a5c9877b126493abb661e4fb47792e418035b", + "shasum": "" + }, + "require": { + "ircmaxell/password-compat": "~1.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.19-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php55\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T09:01:57+00:00" + }, + { + "name": "symfony/polyfill-php56", + "version": "v1.19.0", "source": { "type": "git", - "url": "https://github.com/stecman/symfony-console-completion.git", - "reference": "1a9fc7ab4820cd1aabbdc584c6b25d221e7b6cb5" + "url": "https://github.com/symfony/polyfill-php56.git", + "reference": "ea19621731cbd973a6702cfedef3419768bf3372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/stecman/symfony-console-completion/zipball/1a9fc7ab4820cd1aabbdc584c6b25d221e7b6cb5", - "reference": "1a9fc7ab4820cd1aabbdc584c6b25d221e7b6cb5", + "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/ea19621731cbd973a6702cfedef3419768bf3372", + "reference": "ea19621731cbd973a6702cfedef3419768bf3372", "shasum": "" }, "require": { - "php": ">=5.3.2", - "symfony/console": "~2.2" - }, - "require-dev": { - "phpunit/phpunit": "~4.1" + "php": ">=5.3.3", + "symfony/polyfill-util": "~1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "0.5.x-dev" + "dev-main": "1.19-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { + "files": [ + "bootstrap.php" + ], "psr-4": { - "Stecman\\Component\\Symfony\\Console\\BashCompletion\\": "src/" + "Symfony\\Polyfill\\Php56\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Stephen Holdaway", - "email": "stephen@stecman.co.nz" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Automatic BASH completion for Symfony Console Component based applications.", - "time": "2015-05-07 12:21:50" + "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T09:01:57+00:00" }, { - "name": "symfony/console", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Console", + "name": "symfony/polyfill-util", + "version": "v1.19.0", "source": { "type": "git", - "url": "https://github.com/symfony/Console.git", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272" + "url": "https://github.com/symfony/polyfill-util.git", + "reference": "8df0c3e6a4b85df9a5c6f3f2f46fba5c5c47058a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/ebc5679854aa24ed7d65062e9e3ab0b18a917272", - "reference": "ebc5679854aa24ed7d65062e9e3ab0b18a917272", + "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/8df0c3e6a4b85df9a5c6f3f2f46fba5c5c47058a", + "reference": "8df0c3e6a4b85df9a5c6f3f2f46fba5c5c47058a", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", - "symfony/process": "~2.1" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/process": "" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-main": "1.19-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Console\\": "" + "psr-4": { + "Symfony\\Polyfill\\Util\\": "" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Console Component", + "description": "Symfony utilities for portability of PHP codes", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "keywords": [ + "compat", + "compatibility", + "polyfill", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-21T09:57:48+00:00" }, { "name": "symfony/process", - "version": "v2.7.4", + "version": "v2.8.52", "source": { "type": "git", - "url": "https://github.com/symfony/Process.git", - "reference": "f7b3f73f70a7f8f49a1c838dc3debbf054732d8e" + "url": "https://github.com/symfony/process.git", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Process/zipball/f7b3f73f70a7f8f49a1c838dc3debbf054732d8e", - "reference": "f7b3f73f70a7f8f49a1c838dc3debbf054732d8e", + "url": "https://api.github.com/repos/symfony/process/zipball/c3591a09c78639822b0b290d44edb69bf9f05dc8", + "reference": "c3591a09c78639822b0b290d44edb69bf9f05dc8", "shasum": "" }, "require": { "php": ">=5.3.9" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7-dev" + "dev-master": "2.8-dev" } }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-08-27 06:45:45" + "time": "2018-11-11T11:18:13+00:00" } ], "packages-dev": [ { "name": "aik099/coding-standard", "version": "dev-in-portal", "source": { "type": "git", "url": "https://github.com/aik099/CodingStandard.git", - "reference": "987a6781521c9293b3e36ff3877cdff63010b291" + "reference": "26b67b43b3cb4d57a68a472170bf6fab07334c18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aik099/CodingStandard/zipball/b2d0a7b7e4b69f8a7024c462d511c5a09f46ccb6", - "reference": "987a6781521c9293b3e36ff3877cdff63010b291", + "url": "https://api.github.com/repos/aik099/CodingStandard/zipball/26b67b43b3cb4d57a68a472170bf6fab07334c18", + "reference": "26b67b43b3cb4d57a68a472170bf6fab07334c18", "shasum": "" }, "require-dev": { - "squizlabs/php_codesniffer": "~2.0" + "squizlabs/php_codesniffer": "^3.0", + "yoast/phpunit-polyfills": "^1.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "2.0.x-dev" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Alexander Obuhovich", "email": "aik.bold@gmail.com" } ], "description": "The PHP_CodeSniffer coding standard I'm using on all of my projects.", "keywords": [ "PHP_CodeSniffer", "codesniffer" ], - "time": "2015-05-17 06:49:37" + "time": "2021-11-07T17:05:54+00:00" }, { "name": "aik099/phpunit-mink", - "version": "v2.1.0", + "version": "v2.2.0", "source": { "type": "git", "url": "https://github.com/minkphp/phpunit-mink.git", - "reference": "62889c5b065d69b695c87df6218b22147d78b147" + "reference": "68b94432ac12ad4f714ef540037396aeb369e230" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/phpunit-mink/zipball/62889c5b065d69b695c87df6218b22147d78b147", - "reference": "62889c5b065d69b695c87df6218b22147d78b147", + "url": "https://api.github.com/repos/minkphp/phpunit-mink/zipball/68b94432ac12ad4f714ef540037396aeb369e230", + "reference": "68b94432ac12ad4f714ef540037396aeb369e230", "shasum": "" }, "require": { "behat/mink": "~1.6@dev", "behat/mink-selenium2-driver": "~1.2", "php": ">=5.3.2", - "phpunit/phpunit": ">=3.7.8", - "pimple/pimple": "~2.0|~3.0", - "symfony/event-dispatcher": "~2.4" + "phpunit/phpunit": "~4|~5", + "symfony/event-dispatcher": "~2.4|~3.0" }, "require-dev": { "aik099/coding-standard": "dev-master", "mockery/mockery": "~0.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.1.x-dev" } }, "autoload": { - "psr-0": { - "aik099\\": "./library/" + "psr-4": { + "aik099\\PHPUnit\\": "library/aik099/PHPUnit", + "PimpleCopy\\Pimple\\": "library/PimpleCopy/Pimple" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Alexander Obuhovich", "email": "aik.bold@gmail.com" } ], "description": "Library for using Mink in PHPUnit tests. Supports session sharing between tests in a test case.", "homepage": "http://github.com/minkphp/phpunit-mink", "keywords": [ "BrowserStack", "Mink", "Sauce", "SauceLabs", "phpunit", "selenium", "tests" ], - "time": "2015-05-06 13:33:55" + "time": "2016-06-26T09:07:47+00:00" }, { "name": "behat/mink", - "version": "v1.6.1", + "version": "v1.9.0", "source": { "type": "git", "url": "https://github.com/minkphp/Mink.git", - "reference": "8b68523a339ec991bcd638b39dc8f04f808da88a" + "reference": "e35f4695de8800fc776af34ebf665ad58ebdd996" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/Mink/zipball/8b68523a339ec991bcd638b39dc8f04f808da88a", - "reference": "8b68523a339ec991bcd638b39dc8f04f808da88a", + "url": "https://api.github.com/repos/minkphp/Mink/zipball/e35f4695de8800fc776af34ebf665ad58ebdd996", + "reference": "e35f4695de8800fc776af34ebf665ad58ebdd996", "shasum": "" }, "require": { - "php": ">=5.3.1", - "symfony/css-selector": "~2.0" + "php": ">=5.4", + "symfony/css-selector": "^2.7|^3.0|^4.0|^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5 || ^9.5", + "symfony/debug": "^2.7|^3.0|^4.0|^5.0", + "symfony/phpunit-bridge": "^3.4.38 || ^4.4 || ^5.0.5", + "yoast/phpunit-polyfills": "^1.0" }, "suggest": { "behat/mink-browserkit-driver": "extremely fast headless driver for Symfony\\Kernel-based apps (Sf2, Silex)", "behat/mink-goutte-driver": "fast headless driver for any app without JS emulation", "behat/mink-selenium2-driver": "slow, but JS-enabled driver for any app (requires Selenium2)", - "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)" + "behat/mink-zombie-driver": "fast and JS-enabled headless driver for any app (requires node.js)", + "dmore/chrome-mink-driver": "fast and JS-enabled driver for any app (requires chromium or google chrome)" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.6.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { "psr-4": { "Behat\\Mink\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" } ], "description": "Browser controller/emulator abstraction for PHP", - "homepage": "http://mink.behat.org/", + "homepage": "https://mink.behat.org/", "keywords": [ "browser", "testing", "web" ], - "time": "2015-02-04 17:02:06" + "time": "2021-10-11T11:58:47+00:00" }, { "name": "behat/mink-selenium2-driver", - "version": "v1.2.0", + "version": "v1.5.0", "source": { "type": "git", "url": "https://github.com/minkphp/MinkSelenium2Driver.git", - "reference": "8018fee80bf6573f909ece3e0dfc07d0eb352210" + "reference": "0dee8cceed7e198bf130b4af0fab0ffab6dab47f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/8018fee80bf6573f909ece3e0dfc07d0eb352210", - "reference": "8018fee80bf6573f909ece3e0dfc07d0eb352210", + "url": "https://api.github.com/repos/minkphp/MinkSelenium2Driver/zipball/0dee8cceed7e198bf130b4af0fab0ffab6dab47f", + "reference": "0dee8cceed7e198bf130b4af0fab0ffab6dab47f", "shasum": "" }, "require": { - "behat/mink": "~1.6@dev", + "behat/mink": "~1.7@dev", "instaclick/php-webdriver": "~1.1", - "php": ">=5.3.1" + "php": ">=5.4" + }, + "require-dev": { + "mink/driver-testsuite": "dev-master" }, "type": "mink-driver", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.x-dev" } }, "autoload": { - "psr-0": { - "Behat\\Mink\\Driver": "src/" + "psr-4": { + "Behat\\Mink\\Driver\\": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Konstantin Kudryashov", - "email": "ever.zet@gmail.com", - "homepage": "http://everzet.com" - }, - { "name": "Pete Otaqui", "email": "pete@otaqui.com", "homepage": "https://github.com/pete-otaqui" + }, + { + "name": "Konstantin Kudryashov", + "email": "ever.zet@gmail.com", + "homepage": "http://everzet.com" } ], "description": "Selenium2 (WebDriver) driver for Mink framework", - "homepage": "http://mink.behat.org/", + "homepage": "https://mink.behat.org/", "keywords": [ "ajax", "browser", "javascript", "selenium", "testing", "webdriver" ], - "time": "2014-09-29 13:12:12" + "time": "2021-10-12T16:01:47+00:00" }, { "name": "doctrine/instantiator", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119" + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f976e5de371104877ebc89bd8fecb0019ed9c119", - "reference": "f976e5de371104877ebc89bd8fecb0019ed9c119", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/8e884e78f9f0eb1329e445619e04456e64d8051d", + "reference": "8e884e78f9f0eb1329e445619e04456e64d8051d", "shasum": "" }, "require": { "php": ">=5.3,<8.0-DEV" }, "require-dev": { "athletic/athletic": "~0.1.8", "ext-pdo": "*", "ext-phar": "*", "phpunit/phpunit": "~4.0", - "squizlabs/php_codesniffer": "2.0.*@ALPHA" + "squizlabs/php_codesniffer": "~2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { - "psr-0": { - "Doctrine\\Instantiator\\": "src" + "psr-4": { + "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Marco Pivetta", "email": "ocramius@gmail.com", "homepage": "http://ocramius.github.com/" } ], "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", "homepage": "https://github.com/doctrine/instantiator", "keywords": [ "constructor", "instantiate" ], - "time": "2014-10-13 12:58:55" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "hamcrest/hamcrest-php", "version": "v1.2.2", "source": { "type": "git", "url": "https://github.com/hamcrest/hamcrest-php.git", "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c" }, "dist": { "type": "zip", "url": "https://api.github.com/repos/hamcrest/hamcrest-php/zipball/b37020aa976fa52d3de9aa904aa2522dc518f79c", "reference": "b37020aa976fa52d3de9aa904aa2522dc518f79c", "shasum": "" }, "require": { "php": ">=5.3.2" }, "replace": { "cordoval/hamcrest-php": "*", "davedevelopment/hamcrest-php": "*", "kodova/hamcrest-php": "*" }, "require-dev": { "phpunit/php-file-iterator": "1.3.3", "satooshi/php-coveralls": "dev-master" }, "type": "library", "autoload": { "classmap": [ "hamcrest" ], "files": [ "hamcrest/Hamcrest.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD" ], "description": "This is the PHP port of Hamcrest Matchers", "keywords": [ "test" ], - "time": "2015-05-11 14:41:42" + "time": "2015-05-11T14:41:42+00:00" }, { "name": "instaclick/php-webdriver", - "version": "1.4.2", + "version": "1.4.14", "source": { "type": "git", "url": "https://github.com/instaclick/php-webdriver.git", - "reference": "6aa16bbc02a5897200ab70316e0d2a01664afc51" + "reference": "200b8df772b74d604bebf25ef42ad6f8ee6380a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/6aa16bbc02a5897200ab70316e0d2a01664afc51", - "reference": "6aa16bbc02a5897200ab70316e0d2a01664afc51", + "url": "https://api.github.com/repos/instaclick/php-webdriver/zipball/200b8df772b74d604bebf25ef42ad6f8ee6380a9", + "reference": "200b8df772b74d604bebf25ef42ad6f8ee6380a9", "shasum": "" }, "require": { "ext-curl": "*", "php": ">=5.3.2" }, "require-dev": { - "satooshi/php-coveralls": "dev-master" + "phpunit/phpunit": "^8.5 || ^9.5", + "satooshi/php-coveralls": "^1.0 || ^2.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4.x-dev" } }, "autoload": { "psr-0": { "WebDriver": "lib/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "Apache-2.0" ], "authors": [ { "name": "Justin Bishop", "email": "jubishop@gmail.com", "role": "Developer" }, { "name": "Anthon Pang", "email": "apang@softwaredevelopment.ca", "role": "Fork Maintainer" } ], "description": "PHP WebDriver for Selenium 2", "homepage": "http://instaclick.com/", "keywords": [ "browser", "selenium", "webdriver", "webtest" ], - "time": "2015-04-05 19:52:55" + "time": "2022-04-19T02:06:59+00:00" }, { "name": "mindplay/annotations", - "version": "1.2.0", + "version": "1.3.3", "source": { "type": "git", "url": "https://github.com/php-annotations/php-annotations.git", - "reference": "3e6d5ea14fcc032e18dd0f81b014aa7ca47a1881" + "reference": "d314832b338b88299c4108361c858b0590798d2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-annotations/php-annotations/zipball/3e6d5ea14fcc032e18dd0f81b014aa7ca47a1881", - "reference": "3e6d5ea14fcc032e18dd0f81b014aa7ca47a1881", + "url": "https://api.github.com/repos/php-annotations/php-annotations/zipball/d314832b338b88299c4108361c858b0590798d2c", + "reference": "d314832b338b88299c4108361c858b0590798d2c", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/php-code-coverage": "~1.2.1", - "phpunit/php-file-iterator": ">=1.3.0@stable" + "phpunit/php-file-iterator": ">=1.3.0@stable <2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { "psr-4": { "mindplay\\annotations\\": "src\\annotations" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "LGPL-3.0+" ], "authors": [ { "name": "Rasmus Schultz", "email": "rasmus@mindplay.dk" } ], "description": "Industrial-strength annotations for PHP", "homepage": "http://blog.mindplay.dk/", "keywords": [ "annotations", "framework" ], - "time": "2015-04-15 12:54:35" + "time": "2022-07-16T15:11:03+00:00" }, { "name": "mockery/mockery", - "version": "0.9.4", + "version": "0.9.11", "source": { "type": "git", - "url": "https://github.com/padraic/mockery.git", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b" + "url": "https://github.com/mockery/mockery.git", + "reference": "be9bf28d8e57d67883cba9fcadfcff8caab667f8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/padraic/mockery/zipball/70bba85e4aabc9449626651f48b9018ede04f86b", - "reference": "70bba85e4aabc9449626651f48b9018ede04f86b", + "url": "https://api.github.com/repos/mockery/mockery/zipball/be9bf28d8e57d67883cba9fcadfcff8caab667f8", + "reference": "be9bf28d8e57d67883cba9fcadfcff8caab667f8", "shasum": "" }, "require": { "hamcrest/hamcrest-php": "~1.1", "lib-pcre": ">=7.0", "php": ">=5.3.2" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "0.9.x-dev" } }, "autoload": { "psr-0": { "Mockery": "library/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Pádraic Brady", "email": "padraic.brady@gmail.com", "homepage": "http://blog.astrumfutura.com" }, { "name": "Dave Marshall", "email": "dave.marshall@atstsolutions.co.uk", "homepage": "http://davedevelopment.co.uk" } ], "description": "Mockery is a simple yet flexible PHP mock object framework for use in unit testing with PHPUnit, PHPSpec or any other testing framework. Its core goal is to offer a test double framework with a succinct API capable of clearly defining all possible object operations and interactions using a human readable Domain Specific Language (DSL). Designed as a drop in alternative to PHPUnit's phpunit-mock-objects library, Mockery is easy to integrate with PHPUnit and can operate alongside phpunit-mock-objects without the World ending.", "homepage": "http://github.com/padraic/mockery", "keywords": [ "BDD", "TDD", "library", "mock", "mock objects", "mockery", "stub", "test", "test double", "testing" ], - "time": "2015-04-02 19:54:00" + "time": "2019-02-12T16:07:13+00:00" }, { "name": "nikic/php-parser", - "version": "v1.3.0", + "version": "v1.4.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dff239267fd1befa1cd40430c9ed12591aa720ca" + "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dff239267fd1befa1cd40430c9ed12591aa720ca", - "reference": "dff239267fd1befa1cd40430c9ed12591aa720ca", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", + "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { "files": [ "lib/bootstrap.php" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Nikita Popov" } ], "description": "A PHP parser written in PHP", "keywords": [ "parser", "php" ], - "time": "2015-05-02 15:40:40" + "time": "2015-09-19T14:15:08+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "2.0.4", + "version": "2.0.5", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8" + "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/d68dbdc53dc358a816f00b300704702b2eaff7b8", - "reference": "d68dbdc53dc358a816f00b300704702b2eaff7b8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e6a969a640b00d8daa3c66518b0405fb41ae0c4b", + "reference": "e6a969a640b00d8daa3c66518b0405fb41ae0c4b", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.0" }, "suggest": { "dflydev/markdown": "~1.0", "erusev/parsedown": "~1.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.0.x-dev" } }, "autoload": { "psr-0": { "phpDocumentor": [ "src/" ] } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Mike van Riel", "email": "mike.vanriel@naenius.com" } ], - "time": "2015-02-03 12:10:50" + "time": "2016-01-25T08:17:30+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.4.1", + "version": "v1.10.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373" + "reference": "451c3cd1418cf640de218914901e51b064abb093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", - "reference": "3132b1f44c7bf2ec4c7eb2d3cb78fdeca760d373", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", "shasum": "" }, "require": { "doctrine/instantiator": "^1.0.2", - "phpdocumentor/reflection-docblock": "~2.0", - "sebastian/comparator": "~1.1" + "php": "^5.3|^7.0", + "phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0", + "sebastian/comparator": "^1.2.3|^2.0|^3.0|^4.0", + "sebastian/recursion-context": "^1.0|^2.0|^3.0|^4.0" }, "require-dev": { - "phpspec/phpspec": "~2.0" + "phpspec/phpspec": "^2.5 || ^3.2", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.5 || ^7.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4.x-dev" + "dev-master": "1.10.x-dev" } }, "autoload": { - "psr-0": { - "Prophecy\\": "src/" + "psr-4": { + "Prophecy\\": "src/Prophecy" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Konstantin Kudryashov", "email": "ever.zet@gmail.com", "homepage": "http://everzet.com" }, { "name": "Marcello Duarte", "email": "marcello.duarte@gmail.com" } ], "description": "Highly opinionated mocking framework for PHP 5.3+", "homepage": "https://github.com/phpspec/prophecy", "keywords": [ "Double", "Dummy", "fake", "mock", "spy", "stub" ], - "time": "2015-04-27 22:15:08" + "time": "2020-03-05T15:02:03+00:00" }, { "name": "phpunit/php-code-coverage", - "version": "2.0.16", + "version": "2.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c" + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/934fd03eb6840508231a7f73eb8940cf32c3b66c", - "reference": "934fd03eb6840508231a7f73eb8940cf32c3b66c", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/eabf68b476ac7d0f73793aada060f1c1a9bf8979", + "reference": "eabf68b476ac7d0f73793aada060f1c1a9bf8979", "shasum": "" }, "require": { "php": ">=5.3.3", "phpunit/php-file-iterator": "~1.3", "phpunit/php-text-template": "~1.2", "phpunit/php-token-stream": "~1.3", - "sebastian/environment": "~1.0", + "sebastian/environment": "^1.3.2", "sebastian/version": "~1.0" }, "require-dev": { "ext-xdebug": ">=2.1.4", "phpunit/phpunit": "~4" }, "suggest": { "ext-dom": "*", "ext-xdebug": ">=2.2.1", "ext-xmlwriter": "*" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0.x-dev" + "dev-master": "2.2.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", "homepage": "https://github.com/sebastianbergmann/php-code-coverage", "keywords": [ "coverage", "testing", "xunit" ], - "time": "2015-04-11 04:35:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "1.4.0", + "version": "1.4.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb" + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a923bb15680d0089e2316f7a4af8f437046e96bb", - "reference": "a923bb15680d0089e2316f7a4af8f437046e96bb", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/730b01bc3e867237eaac355e06a36b85dd93a8b4", + "reference": "730b01bc3e867237eaac355e06a36b85dd93a8b4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "FilterIterator implementation that filters files based on a list of suffixes.", "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", "keywords": [ "filesystem", "iterator" ], - "time": "2015-04-02 05:19:05" + "time": "2017-11-27T13:52:08+00:00" }, { "name": "phpunit/php-text-template", - "version": "1.2.0", + "version": "1.2.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a" + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", - "reference": "206dfefc0ffe9cebf65c413e3d0e809c82fbf00a", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/31f8b717e51d9a2afca6c9f046f5d69fc27c8686", + "reference": "31f8b717e51d9a2afca6c9f046f5d69fc27c8686", "shasum": "" }, "require": { "php": ">=5.3.3" }, "type": "library", "autoload": { "classmap": [ - "Text/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", - "email": "sb@sebastian-bergmann.de", + "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Simple template engine.", "homepage": "https://github.com/sebastianbergmann/php-text-template/", "keywords": [ "template" ], - "time": "2014-01-30 17:20:04" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", - "version": "1.0.5", + "version": "1.0.9", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c" + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/19689d4354b295ee3d8c54b4f42c3efb69cbc17c", - "reference": "19689d4354b295ee3d8c54b4f42c3efb69cbc17c", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", + "reference": "3dcf38ca72b158baf0bc245e9184d3fdffa9c46f", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, "autoload": { "classmap": [ - "PHP/" + "src/" ] }, "notification-url": "https://packagist.org/downloads/", - "include-path": [ - "" - ], "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Utility class for timing", "homepage": "https://github.com/sebastianbergmann/php-timer/", "keywords": [ "timer" ], - "time": "2013-08-02 07:42:54" + "time": "2017-02-26T11:10:40+00:00" }, { "name": "phpunit/php-token-stream", - "version": "1.4.1", + "version": "1.4.12", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-token-stream.git", - "reference": "eab81d02569310739373308137284e0158424330" + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/eab81d02569310739373308137284e0158424330", - "reference": "eab81d02569310739373308137284e0158424330", + "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1ce90ba27c42e4e44e6d8458241466380b51fa16", + "reference": "1ce90ba27c42e4e44e6d8458241466380b51fa16", "shasum": "" }, "require": { "ext-tokenizer": "*", "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Wrapper around PHP's tokenizer extension.", "homepage": "https://github.com/sebastianbergmann/php-token-stream/", "keywords": [ "tokenizer" ], - "time": "2015-04-08 04:46:07" + "abandoned": true, + "time": "2017-12-04T08:55:13+00:00" }, { "name": "phpunit/phpunit", - "version": "4.6.6", + "version": "4.8.36", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac" + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3afe303d873a4d64c62ef84de491b97b006fbdac", - "reference": "3afe303d873a4d64c62ef84de491b97b006fbdac", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/46023de9a91eec7dfb06cc56cb4e260017298517", + "reference": "46023de9a91eec7dfb06cc56cb4e260017298517", "shasum": "" }, "require": { "ext-dom": "*", "ext-json": "*", "ext-pcre": "*", "ext-reflection": "*", "ext-spl": "*", "php": ">=5.3.3", - "phpspec/prophecy": "~1.3,>=1.3.1", - "phpunit/php-code-coverage": "~2.0,>=2.0.11", + "phpspec/prophecy": "^1.3.1", + "phpunit/php-code-coverage": "~2.1", "phpunit/php-file-iterator": "~1.4", "phpunit/php-text-template": "~1.2", - "phpunit/php-timer": "~1.0", + "phpunit/php-timer": "^1.0.6", "phpunit/phpunit-mock-objects": "~2.3", - "sebastian/comparator": "~1.1", + "sebastian/comparator": "~1.2.2", "sebastian/diff": "~1.2", - "sebastian/environment": "~1.2", + "sebastian/environment": "~1.3", "sebastian/exporter": "~1.2", "sebastian/global-state": "~1.0", "sebastian/version": "~1.0", "symfony/yaml": "~2.1|~3.0" }, "suggest": { "phpunit/php-invoker": "~1.1" }, "bin": [ "phpunit" ], "type": "library", "extra": { "branch-alias": { - "dev-master": "4.6.x-dev" + "dev-master": "4.8.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "The PHP Unit Testing framework.", "homepage": "https://phpunit.de/", "keywords": [ "phpunit", "testing", "xunit" ], - "time": "2015-04-29 15:18:52" + "time": "2017-06-21T08:07:12+00:00" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.3.1", + "version": "2.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c" + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/74ffb87f527f24616f72460e54b595f508dccb5c", - "reference": "74ffb87f527f24616f72460e54b595f508dccb5c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/ac8e7a3db35738d56ee9a76e78a4e03d97628983", + "reference": "ac8e7a3db35738d56ee9a76e78a4e03d97628983", "shasum": "" }, "require": { - "doctrine/instantiator": "~1.0,>=1.0.2", + "doctrine/instantiator": "^1.0.2", "php": ">=5.3.3", - "phpunit/php-text-template": "~1.2" + "phpunit/php-text-template": "~1.2", + "sebastian/exporter": "~1.2" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "suggest": { "ext-soap": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "2.3.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sb@sebastian-bergmann.de", "role": "lead" } ], "description": "Mock Object library for PHPUnit", "homepage": "https://github.com/sebastianbergmann/phpunit-mock-objects/", "keywords": [ "mock", "xunit" ], - "time": "2015-04-02 05:36:41" + "abandoned": true, + "time": "2015-10-02T06:51:40+00:00" }, { "name": "pimple/pimple", - "version": "v3.0.0", + "version": "v3.2.3", "source": { "type": "git", "url": "https://github.com/silexphp/Pimple.git", - "reference": "876bf0899d01feacd2a2e83f04641e51350099ef" + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/876bf0899d01feacd2a2e83f04641e51350099ef", - "reference": "876bf0899d01feacd2a2e83f04641e51350099ef", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.3.0", + "psr/container": "^1.0" + }, + "require-dev": { + "symfony/phpunit-bridge": "^3.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0.x-dev" + "dev-master": "3.2.x-dev" } }, "autoload": { "psr-0": { "Pimple": "src/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" } ], - "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", + "description": "Pimple, a simple Dependency Injection Container", "homepage": "http://pimple.sensiolabs.org", "keywords": [ "container", "dependency injection" ], - "time": "2014-07-24 09:48:15" + "time": "2018-01-21T07:42:36+00:00" + }, + { + "name": "psr/container", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "reference": "b7ce3b176482dbbc1245ebf52b181af44c2cf55f", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "time": "2017-02-14T16:28:37+00:00" }, { "name": "qa-tools/qa-tools", - "version": "v1.0.1", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/qa-tools/qa-tools.git", - "reference": "5456f64af5b94c5655f21a592b8817690c2096c7" + "reference": "505b14a7766daa718cad21bdb7bcb404cabaa1fc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/qa-tools/qa-tools/zipball/5456f64af5b94c5655f21a592b8817690c2096c7", - "reference": "5456f64af5b94c5655f21a592b8817690c2096c7", + "url": "https://api.github.com/repos/qa-tools/qa-tools/zipball/505b14a7766daa718cad21bdb7bcb404cabaa1fc", + "reference": "505b14a7766daa718cad21bdb7bcb404cabaa1fc", "shasum": "" }, "require": { "behat/mink": "~1.6", - "mindplay/annotations": "~1.2@dev", - "php": ">=5.3.2" + "mindplay/annotations": "~1.2", + "php": ">=5.3.2", + "pimple/pimple": "^2.0|^3.0" }, "replace": { "aik099/qa-tools": "self.version" }, "require-dev": { "aik099/coding-standard": "dev-master", - "behat/mink-selenium2-driver": "~1.2@dev", - "brianium/paratest": "~0.7", - "mockery/mockery": "~0.9" + "behat/mink-selenium2-driver": "~1.2", + "mockery/mockery": "~0.9", + "symfony/phpunit-bridge": "^3.1" }, "suggest": { - "aik099/phpunit-mink": "Allows to use PageObject inside PHPUnit tests and remotely collect code coverage information" + "qa-tools/phpunit-extension": "PHPUnit extension for QA-Tools" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { "psr-0": { "QATools\\QATools\\": "./library/" } }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Alexander Obuhovich", "email": "aik.bold@gmail.com" }, { "name": "Dmitry Kushnikov", "email": "dkushnikov@gmail.com" }, { "name": "Michael Geppert", "email": "evangelion1204@aol.com" } ], "description": "Library that provides easy-to-use way of interaction with web-page elements in functional tests using PageObject pattern.", "keywords": [ "BEM", "HtmlElements", "Mink", "PageObject", "acceptance", "functional", "phpunit", "tests" ], - "time": "2014-09-26 15:15:51" + "time": "2016-07-06T11:31:04+00:00" }, { "name": "sebastian/comparator", - "version": "1.1.1", + "version": "1.2.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e" + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/1dd8869519a225f7f2b9eb663e225298fade819e", - "reference": "1dd8869519a225f7f2b9eb663e225298fade819e", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", + "reference": "2b7424b55f5047b47ac6e5ccb20b2aea4011d9be", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/diff": "~1.2", - "sebastian/exporter": "~1.2" + "sebastian/exporter": "~1.2 || ~2.0" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "1.2.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides the functionality to compare PHP values for equality", "homepage": "http://www.github.com/sebastianbergmann/comparator", "keywords": [ "comparator", "compare", "equality" ], - "time": "2015-01-29 16:28:08" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", - "version": "1.3.0", + "version": "1.4.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3" + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/863df9687835c62aa423a22412d26fa2ebde3fd3", - "reference": "863df9687835c62aa423a22412d26fa2ebde3fd3", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/7f066a26a962dbe58ddea9f72a4e82874a3975a4", + "reference": "7f066a26a962dbe58ddea9f72a4e82874a3975a4", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.2" + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.3-dev" + "dev-master": "1.4-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Kore Nordmann", "email": "mail@kore-nordmann.de" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Diff implementation", - "homepage": "http://www.github.com/sebastianbergmann/diff", + "homepage": "https://github.com/sebastianbergmann/diff", "keywords": [ "diff" ], - "time": "2015-02-22 15:13:53" + "time": "2017-05-22T07:24:03+00:00" }, { "name": "sebastian/environment", - "version": "1.2.2", + "version": "1.3.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e" + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/5a8c7d31914337b69923db26c4221b81ff5a196e", - "reference": "5a8c7d31914337b69923db26c4221b81ff5a196e", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea", + "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": "^5.3.3 || ^7.0" }, "require-dev": { - "phpunit/phpunit": "~4.4" + "phpunit/phpunit": "^4.8 || ^5.0" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.3.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Provides functionality to handle HHVM/PHP environments", "homepage": "http://www.github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", "hhvm" ], - "time": "2015-01-01 10:01:08" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", - "version": "1.2.0", + "version": "1.2.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "84839970d05254c73cde183a721c7af13aede943" + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/84839970d05254c73cde183a721c7af13aede943", - "reference": "84839970d05254c73cde183a721c7af13aede943", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/42c4c2eec485ee3e159ec9884f95b431287edde4", + "reference": "42c4c2eec485ee3e159ec9884f95b431287edde4", "shasum": "" }, "require": { "php": ">=5.3.3", "sebastian/recursion-context": "~1.0" }, "require-dev": { + "ext-mbstring": "*", "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.2.x-dev" + "dev-master": "1.3.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Volker Dusch", "email": "github@wallbash.com" }, { "name": "Bernhard Schussek", "email": "bschussek@2bepublished.at" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides the functionality to export PHP variables for visualization", "homepage": "http://www.github.com/sebastianbergmann/exporter", "keywords": [ "export", "exporter" ], - "time": "2015-01-27 07:23:06" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", - "version": "1.0.0", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01" + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/c7428acdb62ece0a45e6306f1ae85e1c05b09c01", - "reference": "c7428acdb62ece0a45e6306f1ae85e1c05b09c01", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bc37d50fea7d017d3d340f230811c9f1d7280af4", + "reference": "bc37d50fea7d017d3d340f230811c9f1d7280af4", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.2" }, "suggest": { "ext-uopz": "*" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" } ], "description": "Snapshotting of global state", "homepage": "http://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], - "time": "2014-10-06 09:23:50" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/recursion-context", - "version": "1.0.0", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252" + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/3989662bbb30a29d20d9faa04a846af79b276252", - "reference": "3989662bbb30a29d20d9faa04a846af79b276252", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/b19cc3298482a335a95f3016d2f8a6950f0fbcd7", + "reference": "b19cc3298482a335a95f3016d2f8a6950f0fbcd7", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { "phpunit/phpunit": "~4.4" }, "type": "library", "extra": { "branch-alias": { "dev-master": "1.0.x-dev" } }, "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Jeff Welch", "email": "whatthejeff@gmail.com" }, { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de" }, { "name": "Adam Harvey", "email": "aharvey@php.net" } ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-01-24 09:48:32" + "time": "2016-10-03T07:41:43+00:00" }, { "name": "sebastian/version", - "version": "1.0.5", + "version": "1.0.6", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4" + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", - "reference": "ab931d46cd0d3204a91e1b9a40c4bc13032b58e4", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", + "reference": "58b3a85e7999757d6ad81c787a1fbf5ff6c628c6", "shasum": "" }, "type": "library", "autoload": { "classmap": [ "src/" ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "BSD-3-Clause" ], "authors": [ { "name": "Sebastian Bergmann", "email": "sebastian@phpunit.de", "role": "lead" } ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-02-24 06:35:25" + "time": "2015-06-21T13:59:46+00:00" }, { "name": "symfony/css-selector", - "version": "v2.6.7", - "target-dir": "Symfony/Component/CssSelector", + "version": "v2.8.52", "source": { "type": "git", - "url": "https://github.com/symfony/CssSelector.git", - "reference": "189cf0f7f56d7c4be3b778df15a7f16a29f3680d" + "url": "https://github.com/symfony/css-selector.git", + "reference": "7b1692e418d7ccac24c373528453bc90e42797de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/CssSelector/zipball/189cf0f7f56d7c4be3b778df15a7f16a29f3680d", - "reference": "189cf0f7f56d7c4be3b778df15a7f16a29f3680d", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/7b1692e418d7ccac24c373528453bc90e42797de", + "reference": "7b1692e418d7ccac24c373528453bc90e42797de", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "php": ">=5.3.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.8-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\CssSelector\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Jean-François Simon", - "email": "jeanfrancois.simon@sensiolabs.com" - }, - { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { + "name": "Jean-François Simon", + "email": "jeanfrancois.simon@sensiolabs.com" + }, + { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2018-11-11T11:18:13+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v2.6.7", - "target-dir": "Symfony/Component/EventDispatcher", + "version": "v2.8.52", "source": { "type": "git", - "url": "https://github.com/symfony/EventDispatcher.git", - "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02" + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/EventDispatcher/zipball/672593bc4b0043a0acf91903bb75a1c82d8f2e02", - "reference": "672593bc4b0043a0acf91903bb75a1c82d8f2e02", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/a77e974a5fecb4398833b0709210e3d5e334ffb0", + "reference": "a77e974a5fecb4398833b0709210e3d5e334ffb0", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.0,>=2.0.5", - "symfony/dependency-injection": "~2.6", - "symfony/expression-language": "~2.6", - "symfony/phpunit-bridge": "~2.7", - "symfony/stopwatch": "~2.3" + "symfony/config": "^2.0.5|~3.0.0", + "symfony/dependency-injection": "~2.6|~3.0.0", + "symfony/expression-language": "~2.6|~3.0.0", + "symfony/stopwatch": "~2.3|~3.0.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.8-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\EventDispatcher\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2018-11-21T14:20:20+00:00" }, { - "name": "symfony/yaml", - "version": "v2.6.7", - "target-dir": "Symfony/Component/Yaml", + "name": "symfony/polyfill-ctype", + "version": "v1.19.0", "source": { "type": "git", - "url": "https://github.com/symfony/Yaml.git", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/f157ab074e453ecd4c0fa775f721f6e67a99d9e2", - "reference": "f157ab074e453ecd4c0fa775f721f6e67a99d9e2", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/aed596913b70fae57be53d86faa2e9ef85a2297b", + "reference": "aed596913b70fae57be53d86faa2e9ef85a2297b", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "suggest": { + "ext-ctype": "For best performance" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-main": "1.19-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" } }, "autoload": { - "psr-0": { - "Symfony\\Component\\Yaml\\": "" + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-10-23T09:01:57+00:00" + }, + { + "name": "symfony/yaml", + "version": "v2.8.52", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/02c1859112aa779d9ab394ae4f3381911d84052b", + "reference": "02c1859112aa779d9ab394ae4f3381911d84052b", + "shasum": "" + }, + "require": { + "php": ">=5.3.9", + "symfony/polyfill-ctype": "~1.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" } }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { "name": "Fabien Potencier", "email": "fabien@symfony.com" }, { "name": "Symfony Community", "homepage": "https://symfony.com/contributors" } ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2015-05-02 15:18:45" + "time": "2018-11-11T11:18:13+00:00" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": { - "aik099/coding-standard": 20, - "mindplay/annotations": 20 + "aik099/coding-standard": 20 }, "prefer-stable": false, "prefer-lowest": false, - "platform": [], - "platform-dev": [] + "platform": { + "php": ">=5.3.7" + }, + "platform-dev": [], + "plugin-api-version": "1.1.0" } Property changes on: branches/5.3.x ___________________________________________________________________ Modified: svn:mergeinfo Merged /in-portal/branches/5.2.x:r16691