Page MenuHomeIn-Portal Phabricator

in-portal
No OneTemporary

File Metadata

Created
Thu, Feb 6, 4:15 AM

in-portal

Index: branches/5.1.x/core/kernel/processors/main_processor.php
===================================================================
--- branches/5.1.x/core/kernel/processors/main_processor.php (revision 13112)
+++ branches/5.1.x/core/kernel/processors/main_processor.php (revision 13113)
@@ -1,1031 +1,1037 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kMainTagProcessor extends kTagProcessor {
function Init($prefix, $special, $event_params = null)
{
parent::Init($prefix, $special, $event_params);
$actions =& $this->Application->recallObject('kActions');
$actions->Set('t', $this->Application->GetVar('t'));
$actions->Set('sid', $this->Application->GetSID());
$actions->Set('m_opener', $this->Application->GetVar('m_opener') );
}
/**
* Base folder for all template includes
*
* @param Array $params
* @return string
*/
function TemplatesBase($params)
{
static $cached = Array ();
$cache_key = crc32( serialize($params) );
if (!array_key_exists($cache_key, $cached)) {
- $force_admin = array_key_exists('force_admin', $params) && $params['force_admin'];
$module = array_key_exists('module', $params) ? $params['module'] : 'core';
- if ($this->Application->isAdmin || $force_admin) {
+ if ($this->Application->isAdmin) {
if ($module == 'in-portal') {
$module = 'kernel';
}
- $path = $force_admin ? '/core/admin_templates' : THEMES_PATH;
- $path = preg_replace('/\/(.*?)\/(.*)/', $module.'/\\2', $path); // remove leading slash + substitute module
+ // remove leading slash + substitute module
+ $module_path = $this->Application->findModule('Name', $module, 'Path');
+
+ if ($module_path !== false) {
+ $path = $module_path . 'admin_templates';
+ }
+ else {
+ // remove leading slash + substitute module
+ $path = preg_replace('/\/(.*?)\/(.*)/', $module . '/\\2', THEMES_PATH);
+ }
}
else {
$path = mb_substr(THEMES_PATH, 1);
if (mb_strtolower($module) == 'in-portal') {
$module_folder = 'platform';
}
else {
$module_folder = $this->Application->findModule('Name', $module, 'TemplatePath');
}
$path .= rtrim('/' . trim($module_folder, '/'), '/') . '/';
}
$cached[$cache_key] = $this->Application->BaseURL() . $path;
}
return $cached[$cache_key];
}
/**
* Creates <base href ..> HTML tag for all templates
* affects future css, js files and href params of links
*
* @return string
* @access public
*/
function Base_Ref($params)
{
return '<base href="'.$this->TemplatesBase($params).'/" />';
}
/**
* Returns base url for web-site
*
* @return string
* @access public
*/
function BaseURL()
{
return $this->Application->BaseURL();
}
//for compatability with K3 tags
function Base($params)
{
return $this->TemplatesBase($params).'/';
}
function ProjectBase($params)
{
return $this->Application->BaseURL();
}
/*function Base($params)
{
return $this->Application->BaseURL().$params['add'];
}*/
/**
* Used to create link to any template.
* use "pass" paramter if "t" tag to specify
* prefix & special of object to be represented
* in resulting url
*
* @param Array $params
* @return string
* @access public
*/
function T($params)
{
//by default link to current template
$t = $this->SelectParam($params, 't,template');
unset($params['t']);
unset($params['template']);
$prefix=isset($params['prefix']) ? $params['prefix'] : ''; unset($params['prefix']);
$index_file = isset($params['index_file']) ? $params['index_file'] : null; unset($params['index_file']);
return $this->Application->HREF($t, $prefix, $params, $index_file);
}
function Link($params)
{
if (isset($params['template'])) {
$params['t'] = $params['template'];
unset($params['template']);
}
if (!isset($params['pass']) && !isset($params['no_pass'])) $params['pass'] = 'm';
if (isset($params['no_pass'])) unset($params['no_pass']);
if ( $this->Application->GetVar('admin') ) {
$params['admin'] = 1;
if (!array_key_exists('editing_mode', $params)) {
$params['editing_mode'] = EDITING_MODE;
}
}
return $this->T($params);
}
function Env($params)
{
$t = $params['template'];
unset($params['template']);
return $this->Application->BuildEnv($t, $params, 'm', null, false);
}
function FormAction($params)
{
$params['pass'] = 'all,m';
$params['pass_category'] = 1;
return $this->Application->HREF('', '', $params);
}
/*// NEEDS TEST
function Config($params)
{
return $this->Application->ConfigOption($params['var']);
}
function Object($params)
{
$name = $params['name'];
$method = $params['method'];
$tmp =& $this->Application->recallObject($name);
if ($tmp != null) {
if (method_exists($tmp, $method))
return $tmp->$method($params);
else
echo "Method $method does not exist in object ".get_class($tmp)." named $name<br>";
}
else
echo "Object $name does not exist in the appliaction<br>";
}*/
/**
* Tag, that always returns true.
* For parser testing purposes
*
* @param Array $params
* @return bool
* @access public
*/
function True($params)
{
return true;
}
/**
* Tag, that always returns false.
* For parser testing purposes
*
* @param Array $params
* @return bool
* @access public
*/
function False($params)
{
return false;
}
/**
* Returns block parameter by name (used only as "check" parameter value for "m_if" tag!)
*
* @param Array $params
* @return stirng
* @access public
*/
function Param($params)
{
$name = $params['name'];
if (array_key_exists($name, $this->Application->Parser->Captures)) {
$capture_params = $params;
$capture_params['name'] = '__capture_' . $name;
$this->Application->Parser->SetParam($name, $this->Application->ParseBlock($capture_params));
}
$res = $this->Application->Parser->GetParam($name);
if ($res === false) {
$res = '';
}
if (array_key_exists('plus', $params)) {
$res += $params['plus'];
}
return $res;
}
/**
* Compares block parameter with value specified
*
* @param Array $params
* @return bool
* @access public
*/
function ParamEquals($params)
{
$name = $this->SelectParam($params, 'name,var,param');
$value = $params['value'];
return ($this->Application->Parser->GetParam($name) == $value);
}
/*function PHP_Self($params)
{
return $HTTP_SERVER_VARS['PHP_SELF'];
}
*/
/**
* Returns session variable value by name
*
* @param Array $params
* @return string
* @access public
*/
function Recall($params)
{
$var_name = $this->SelectParam($params,'name,var,param');
if (isset($params['persistent']) && $params['persistent']) {
$ret = $this->Application->RecallPersistentVar($var_name);
}
else {
$ret = $this->Application->RecallVar($var_name);
}
$ret = ($ret === false && isset($params['no_null'])) ? '' : $ret;
if (getArrayValue($params, 'special') || getArrayValue($params, 'htmlchars')) {
$ret = htmlspecialchars($ret);
}
if (getArrayValue($params, 'urlencode')) {
$ret = urlencode($ret);
}
return $ret;
}
function RemoveVar($params)
{
$this->Application->RemoveVar( $this->SelectParam($params,'name,var,param') );
}
// bad style to store something from template to session !!! (by Alex)
// Used here only to test how session works, nothing more
function Store($params)
{
//echo"Store $params[name]<br>";
$name = $params['name'];
$value = $params['value'];
$this->Application->StoreVar($name,$value);
}
/**
* Sets application variable value(-s)
*
* @param Array $params
* @access public
*/
function Set($params)
{
foreach ($params as $param => $value) {
$this->Application->SetVar($param, $value);
}
}
/**
* Increment application variable
* specified by number specified
*
* @param Array $params
* @access public
*/
function Inc($params)
{
$this->Application->SetVar($params['param'], $this->Application->GetVar($params['param']) + $params['by']);
}
/**
* Retrieves application variable
* value by name
*
* @param Array $params
* @return string
* @access public
*/
function Get($params)
{
$ret = $this->Application->GetVar($this->SelectParam($params, 'name,var,param'), '');
return getArrayValue($params, 'htmlchars') ? htmlspecialchars($ret) : $ret;
}
/**
* Retrieves application constant
* value by name
*
* @param Array $params
* @return string
* @access public
*/
function GetConst($params)
{
$constant_name = $this->SelectParam($params, 'name,const');
return defined($constant_name) ? constant($constant_name) : '';
}
/**
* Retrieves configuration variable value by name
*
* @param Array $params
* @return string
* @access public
*/
function GetConfig($params)
{
$config_name = $this->SelectParam($params, 'name,var');
$ret = $this->Application->ConfigValue($config_name);
if( getArrayValue($params, 'escape') ) $ret = addslashes($ret);
return $ret;
}
function ConfigEquals($params)
{
$option = $this->SelectParam($params, 'name,option,var');
return $this->Application->ConfigValue($option) == getArrayValue($params, 'value');
}
/**
* Creates all hidden fields
* needed for kernel_form
*
* @param Array $params
* @return string
* @access public
*/
function DumpSystemInfo($params)
{
$actions =& $this->Application->recallObject('kActions');
$actions->Set('t', $this->Application->GetVar('t') );
$params = $actions->GetParams();
$o='';
foreach ($params AS $name => $val)
{
$o .= "<input type='hidden' name='$name' id='$name' value='$val'>\n";
}
return $o;
}
/**
* Used for search sidebox on front-end only
*
* @param Array $params
* @return string
* @author Alex
*/
function GetFormHiddens($params)
{
$t = $this->SelectParam($params, 'template,t');
unset($params['template']);
$form_fields = Array ();
if ($this->Application->RewriteURLs()) {
$session =& $this->Application->recallObject('Session');
if ($session->NeedQueryString()) {
$form_fields['sid'] = $this->Application->GetSID();
}
}
else {
$form_fields['env'] = $this->Application->BuildEnv($t, $params, 'm', null, false);
}
if ($this->Application->GetVar('admin') == 1) {
$form_fields['admin'] = 1;
}
$ret = '';
$field_tpl = '<input type="hidden" name="%1$s" id="%1$s" value="%2$s"/>'."\n";
foreach ($form_fields as $form_field => $field_value) {
$ret .= sprintf($field_tpl, $form_field, $field_value);
}
return $ret;
}
function Odd_Even($params)
{
$odd = $params['odd'];
$even = $params['even'];
if (!isset($params['var'])) {
$var = 'odd_even';
}
else {
$var = $params['var'];
}
if ($this->Application->GetVar($var) == 'even') {
if (!isset($params['readonly']) || !$params['readonly']) {
$this->Application->SetVar($var, 'odd');
}
return $even;
}
else {
if (!isset($params['readonly']) || !$params['readonly']) {
$this->Application->SetVar($var, 'even');
}
return $odd;
}
}
/**
* Returns phrase translation by name
*
* @param Array $params
* @return string
* @access public
*/
function Phrase($params)
{
$phrase_name = $this->SelectParam($params, 'label,name,title');
$no_editing = array_key_exists('no_editing', $params) && $params['no_editing'];
$translation = $this->Application->Phrase($phrase_name, !$no_editing);
if (isset($params['escape']) && $params['escape']) {
$translation = htmlspecialchars($translation, ENT_QUOTES);
$translation = addslashes($translation);
}
return $translation;
}
// for tabs
function is_active($params)
{
$test_templ = $this->SelectParam($params, 'templ,template,t');
if ( !getArrayValue($params,'allow_empty') )
{
$if_true=getArrayValue($params,'true') ? $params['true'] : 1;
$if_false=getArrayValue($params,'false') ? $params['false'] : 0;
}
else
{
$if_true=$params['true'];
$if_false=$params['false'];
}
if ( preg_match("/^".str_replace('/', '\/', $test_templ)."/i", $this->Application->GetVar('t'))) {
return $if_true;
}
else {
return $if_false;
}
}
function IsNotActive($params)
{
return !$this->is_active($params);
}
function IsActive($params)
{
return $this->is_active($params);
}
function is_t_active($params)
{
return $this->is_active($params);
}
function CurrentTemplate($params)
{
return $this->is_active($params);
}
/**
* Checks if session variable
* specified by name value match
* value passed as parameter
*
* @param Array $params
* @return string
* @access public
*/
function RecallEquals($params)
{
$name = $this->SelectParam($params, 'name,var');
$value = $params['value'];
if (isset($params['persistent']) && $params['persistent']) {
return $this->Application->RecallPersistentVar($name) == $value;
}
return ($this->Application->RecallVar($name) == $value);
}
/**
* Checks if application variable
* specified by name value match
* value passed as parameter
*
* @param Array $params
* @return bool
* @access public
*/
function GetEquals($params)
{
$name = $this->SelectParam($params, 'var,name,param');
$value = $params['value'];
if ($this->Application->GetVar($name) == $value) {
return 1;
}
}
function ModuleInclude($params)
{
$ret = '';
+ $included = Array ();
$block_params = array_merge($params, Array('is_silent' => 2)); // don't make fatal errors in case if template is missing
$current_template = $this->Application->GetVar('t');
$replace_main = isset($params['replace_m']) && $params['replace_m'];
$skip_prefixes = isset($params['skip_prefixes']) ? explode(',', $params['skip_prefixes']) : Array();
$cms_mode = $this->Application->GetVar('admin');
- $included = Array ();
-
foreach ($this->Application->ModuleInfo as $module_name => $module_data) {
$module_key = mb_strtolower($module_name);
if ($module_name == 'In-Portal') {
if (!$cms_mode && $this->Application->isAdmin) {
// don't process In-Portal templates in admin
continue;
}
// Front-End still relies on In-Portal module
$module_prefix = $module_data['TemplatePath'];
}
elseif ($this->Application->isAdmin) {
- $module_prefix = $module_data['Path']; // was $module_key . '/';
+ $module_prefix = $module_key . '/'; // was $module_data['Path'];
}
else {
$module_prefix = $module_data['TemplatePath']; // always have trailing "/"
}
if (in_array($module_prefix, $included)) {
// template by this path was already included by other module (e.g. in-portal used core's template)
continue;
}
$block_params['t'] = $module_prefix.$this->SelectParam($params, $module_key.'_template,'.$module_key.'_t,template,t');
$check_prefix = $module_data['Var'];
if ($check_prefix == 'adm' && $replace_main) {
$check_prefix = 'c';
}
if ($block_params['t'] == $current_template || in_array($check_prefix, $skip_prefixes)) {
continue;
}
$no_data = $this->SelectParam($params, $module_key.'_block_no_data,block_no_data');
if ($no_data) {
$block_params['block_no_data'] = $module_prefix.'/'.$no_data;
}
$ret .= $this->Application->IncludeTemplate($block_params);
$included[] = $module_prefix;
}
return $ret;
}
function ModuleEnabled($params)
{
return $this->Application->isModuleEnabled( $params['module'] );
}
/**
* Checks if debug mode is on
*
* @param Array $params
* @return bool
* @access public
*/
function IsDebugMode($params)
{
return defined('DEBUG_MODE') && $this->Application->isDebugMode();
}
/*function MassParse($params)
{
$qty = $params['qty'];
$block = $params['block'];
$mode = $params['mode'];
$o = '';
if ($mode == 'func') {
$func = create_function('$params', '
$o = \'<tr>\';
$o.= \'<td>a\'.$params[\'param1\'].\'</td>\';
$o.= \'<td>a\'.$params[\'param2\'].\'</td>\';
$o.= \'<td>a\'.$params[\'param3\'].\'</td>\';
$o.= \'<td>a\'.$params[\'param4\'].\'</td>\';
$o.= \'</tr>\';
return $o;
');
for ($i=1; $i<$qty; $i++) {
$block_params['param1'] = rand(1, 10000);
$block_params['param2'] = rand(1, 10000);
$block_params['param3'] = rand(1, 10000);
$block_params['param4'] = rand(1, 10000);
$o .= $func($block_params);
}
return $o;
}
$block_params['name'] = $block;
for ($i=0; $i<$qty; $i++) {
$block_params['param1'] = rand(1, 10000);
$block_params['param2'] = rand(1, 10000);
$block_params['param3'] = rand(1, 10000);
$block_params['param4'] = rand(1, 10000);
$block_params['passed'] = $params['passed'];
$block_params['prefix'] = 'm';
$o.= $this->Application->ParseBlock($block_params, 1);
}
return $o;
}*/
function LoggedIn($params)
{
return $this->Application->LoggedIn();
}
/**
* Allows to check if permission exists directly in template and perform additional actions if required
*
* @param Array $params
* @return bool
*/
function CheckPermission($params)
{
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
return $perm_helper->TagPermissionCheck($params);
}
/**
* Checks if user is logged in and if not redirects it to template passed
*
* @param Array $params
*/
function RequireLogin($params)
{
$t = $this->Application->GetVar('t');
if ($next_t = getArrayValue($params, 'next_template')) {
$t = $next_t;
}
// check by permissions: begin
if ((isset($params['perm_event']) && $params['perm_event']) ||
(isset($params['perm_prefix']) && $params['perm_prefix']) ||
(isset($params['permissions']) && $params['permissions'])) {
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
/* @var $perm_helper kPermissionsHelper */
$perm_status = $perm_helper->TagPermissionCheck($params);
if (!$perm_status) {
list($redirect_template, $redirect_params) = $perm_helper->getPermissionTemplate($params);
$this->Application->Redirect($redirect_template, $redirect_params);
}
else {
return ;
}
}
// check by permissions: end
// check by configuration value: begin
$condition = getArrayValue($params, 'condition');
if (!$condition) {
$condition = true;
}
else {
if (substr($condition, 0, 1) == '!') {
$condition = !$this->Application->ConfigValue(substr($condition, 1));
}
else {
$condition = $this->Application->ConfigValue($condition);
}
}
// check by configuration value: end
// check by belonging to group: begin
$group = $this->SelectParam($params, 'group');
$group_access = true;
if ($group) {
$conn =& $this->Application->GetADODBConnection();
$group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group));
if ($group_id) {
$groups = explode(',', $this->Application->RecallVar('UserGroups'));
$group_access = in_array($group_id, $groups);
}
}
// check by belonging to group: end
if ((!$this->Application->LoggedIn() || !$group_access) && $condition) {
$redirect_params = $this->Application->HttpQuery->getRedirectParams(true);
if (array_key_exists('pass_category', $params)) {
$redirect_params['pass_category'] = $params['pass_category'];
}
if (MOD_REWRITE) {
// TODO: $next_t variable is ignored !!! (is anyone using m_RequireLogin tag with "next_template" parameter?)
$redirect_params = Array (
'm_cat_id' => 0,
'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']),
);
}
else {
$redirect_params['next_template'] = $t;
}
if ( $this->Application->LoggedIn() && !$group_access) {
$this->Application->Redirect($params['no_group_perm_template'], $redirect_params);
}
$this->Application->Redirect($params['login_template'], $redirect_params);
}
}
function IsMember($params)
{
$group = getArrayValue($params, 'group');
$conn =& $this->Application->DB;
$group_id = $conn->GetOne('SELECT GroupId FROM '.TABLE_PREFIX.'PortalGroup WHERE Name = '.$conn->qstr($group));
if ($group_id) {
$groups = explode(',', $this->Application->RecallVar('UserGroups'));
$group_access = in_array($group_id, $groups);
}
return $group_access;
}
/**
* Checks if SSL is on and redirects to SSL URL if needed
* If SSL_URL is not defined in config - the tag does not do anything
* If for_logged_in_only="1" exits if user is not logged in.
* If called without params forces https right away. If called with by_config="1" checks the
* Require SSL setting from General Config and if it is ON forces https
*
* @param unknown_type $params
*/
function CheckSSL($params)
{
$ssl = $this->Application->isAdmin ? $this->Application->ConfigValue('AdminSSL_URL') : false;
if (!$ssl) {
// not in admin or admin ssl url is empty
$ssl = $this->Application->ConfigValue('SSL_URL');
}
if (!$ssl) return; //SSL URL is not set - no way to require SSL
$require = false;
if (isset($params['mode']) && $params['mode'] == 'required') {
$require = true;
if (isset($params['for_logged_in_only']) && $params['for_logged_in_only'] && !$this->Application->LoggedIn()) {
$require = false;
}
if (isset($params['condition'])) {
if (!$this->Application->ConfigValue($params['condition'])) {
$require = false;
}
}
}
$http_query =& $this->Application->recallObject('HTTPQuery');
$pass = $http_query->getRedirectParams();
if ($require) {
if (PROTOCOL == 'https://') {
$this->Application->SetVar('__KEEP_SSL__', 1);
return;
}
$this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 1)));
}
else {
if (PROTOCOL == 'https://' && $this->Application->ConfigValue('Force_HTTP_When_SSL_Not_Required')) {
if ($this->Application->GetVar('__KEEP_SSL__')) return;
// $pass_more = Array ('pass' => 'm', 'm_cat_id' => 0, '__SSL__' => 0);
$this->Application->Redirect('', array_merge_recursive2($pass, Array('__SSL__' => 0))); // $pass_more
}
}
}
function ConstOn($params)
{
$name = $this->SelectParam($params,'name,const');
return constOn($name);
}
function SetDefaultCategory($params)
{
$category_id = $this->Application->findModule('Name', $params['module'], 'RootCat');
$this->Application->SetVar('m_cat_id', $category_id);
}
function XMLTemplate($params)
{
safeDefine('DBG_SKIP_REPORTING', 1);
if (isset($params['cache']) && $params['cache']) {
$nextyear = intval(date('Y') + 1);
$format = "D, d M Y H:i:s";
$expiration = gmdate($format, mktime() + $params['cache']).' GMT';
$last_modified = mktime();
header ('Cache-Control: public, cache, max-age='.$params['cache']);
header ("Expires: $expiration");
header ('Pragma: public');
// Getting headers sent by the client.
$headers = request_headers();
// Checking if the client is validating his cache and if it is current.
if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) > $last_modified-$params['cache'])) {
// Client's cache IS current, so we just respond '304 Not Modified'.
header('Last-Modified: '.date($format, strtotime($headers['If-Modified-Since'])).' GMT', true, 304);
exit();
} else {
// Image not cached or cache outdated, we respond '200 OK' and output the image.
header('Last-Modified: '.gmdate($format, $last_modified).' GMT', true, 200);
}
}
// xml documents are usually long
set_time_limit(0);
ini_set('memory_limit', -1);
return $this->Application->XMLHeader(getArrayValue($params, 'xml_version'));
}
function Header($params)
{
header($params['data']);
}
function NoDebug($params)
{
if (!$this->Application->GetVar('debug')) {
define('DBG_SKIP_REPORTING', 1);
}
}
function RootCategoryName($params)
{
$phrase_name = $this->Application->ConfigValue('Root_Name');
$no_editing = array_key_exists('no_editing', $params) && $params['no_editing'];
return $this->Application->Phrase($phrase_name, !$no_editing);
}
/**
* Allows to attach file directly from email event template
*
* @param Array $params
*/
function AttachFile($params)
{
$esender =& $application->recallObject('EmailSender'.(isset($params['special']) ? '.'.$params['special'] : ''));
/* @var $esender kEmailSendingHelper */
$path = FULL_PATH.'/'.$params['path'];
if (file_exists($path)) {
$esender->AddAttachment($path);
}
}
function CaptchaImage($params)
{
$this->NoDebug($params);
$this->Application->SetVar('skip_last_template', 1);
$captcha_helper =& $this->Application->recallObject('CaptchaHelper');
/* @var $captcha_helper kCaptchaHelper */
// generate captcha code
$code = $captcha_helper->prepareCode( $this->Application->GetVar('var') );
$captcha_helper->GenerateCaptchaImage($code, $this->Application->GetVar('w'), $this->Application->GetVar('h'), true);
}
function SID($params)
{
return $this->Application->GetSID();
}
function ModuleInfo($params)
{
return $this->Application->findModule($params['key'], $params['value'], $params['return']);
}
function Random($params)
{
return rand(1, 100000000);
}
/**
* Prints parser params, available at current deep level
*
* @param Array $params
* @return string
*/
function PrintCurrentParams($params)
{
$current_params = $this->Application->Parser->Params;
foreach ($current_params as $param_name => $param_value) {
$current_params[$param_name] = $param_name . ' = "' . $param_value . '"';
}
return '<pre>' . implode("\n", $current_params) . '</pre>';
}
/**
* Gets previously defined counter result
*
* @param Array $params
* @return int
*/
function GetCounter($params)
{
return $this->Application->getCounter($params['name'], $params);
}
/**
* Increments PageHit counter
*
* @param Array $params
* @return int
*/
function RegisterPageHit($params)
{
if ($this->Application->ConfigValue('UsePageHitCounter')) {
$db =& $this->Application->GetADODBConnection();
// get current counte
$sql = 'SELECT VariableValue
FROM '.TABLE_PREFIX.'ConfigurationValues
WHERE VariableName = "PageHitCounter"';
$page_counter = (int)$db->GetOne($sql);
$sql = 'UPDATE LOW_PRIORITY '.TABLE_PREFIX.'ConfigurationValues
SET VariableValue = '.($page_counter + 1).'
WHERE VariableName = "PageHitCounter"';
$db->Query($sql);
}
}
function Timestamp($params)
{
$format = isset($params['format']) ? $params['format'] : 'd.m.Y H:i:s';
return adodb_date($format);
}
}
Index: branches/5.1.x/core/kernel/utility/unit_config_reader.php
===================================================================
--- branches/5.1.x/core/kernel/utility/unit_config_reader.php (revision 13112)
+++ branches/5.1.x/core/kernel/utility/unit_config_reader.php (revision 13113)
@@ -1,992 +1,1004 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kUnitConfigReader extends kBase {
/**
* Configs readed
*
* @var Array
* @access private
*/
var $configData = Array();
var $configFiles = Array();
var $CacheExpired = false;
var $prefixFiles = array();
var $ProcessAllConfigs = false;
var $FinalStage = false;
var $StoreCache = false;
var $AfterConfigProcessed = array();
/**
* Escaped directory separator for using in regular expressions
*
* @var string
*/
var $_directorySeparator = '';
/**
+ * Regular expression for detecting module folder
+ *
+ * @var string
+ */
+ var $_moduleFolderRegExp = '';
+
+ /**
* Folders to skip during unit config search
*
* @var Array
*/
var $_skipFolders = Array ('CVS', '.svn', 'admin_templates', 'libchart');
/**
* Scan kernel and user classes
* for available configs
*
* @access protected
*/
function Init($prefix,$special)
{
parent::Init($prefix,$special);
- $this->_directorySeparator = preg_quote( DIRECTORY_SEPARATOR );
- $this->_skipFolders[] = trim(WRITEBALE_BASE, '/'); // system folder (where web server can write)
+ $this->_directorySeparator = preg_quote(DIRECTORY_SEPARATOR);
$editor_path = explode('/', trim(EDITOR_PATH, '/'));
$this->_skipFolders[] = array_pop($editor_path); // last of cmseditor folders
+
+ $this->_moduleFolderRegExp = '#' . $this->_directorySeparator . '(core|modules' . $this->_directorySeparator . '.*?)' . $this->_directorySeparator . '#';
}
function CacheParsedData()
{
$event_manager =& $this->Application->recallObject('EventManager');
$aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray');
$config_vars = Array (
'SessionTimeout',
'SessionCookieName',
'SessionBrowserSignatureCheck',
'SessionIPAddressCheck',
'CookieSessions',
'UseCronForRegularEvent',
'User_GuestGroup',
'User_LoggedInGroup',
'SessionTimeout',
'UseModRewrite',
'UseOutputCompression',
'OutputCompressionLevel',
'KeepSessionOnBrowserClose',
'Config_Server_Time',
'Config_Site_Time',
'UseChangeLog',
'UseVisitorTracking',
);
foreach ($config_vars as $var) {
$this->Application->ConfigValue($var);
}
$cache = Array(
- 'Factory.Files' => $this->Application->Factory->Files,
- 'Factory.realClasses' => $this->Application->Factory->realClasses,
- 'Factory.Dependencies' => $this->Application->Factory->Dependencies,
- 'ConfigReader.prefixFiles' => $this->prefixFiles,
- 'EventManager.buildEvents' => $event_manager->buildEvents,
- 'EventManager.beforeRegularEvents' => $event_manager->beforeRegularEvents,
- 'EventManager.afterRegularEvents' => $event_manager->afterRegularEvents,
- 'EventManager.beforeHooks' => $event_manager->beforeHooks,
- 'EventManager.afterHooks' => $event_manager->afterHooks,
- 'TagsAggregator.data' => $aggregator->_Array,
-
- // the following caches should be reset based on admin interaction (adjusting config, enabling modules etc)
- 'Application.Caches.ConfigVariables' => $this->Application->Caches['ConfigVariables'],
- 'Application.ConfigCacheIds' => $this->Application->ConfigCacheIds,
- 'Application.ConfigHash' => $this->Application->ConfigHash,
- 'Application.ReplacementTemplates' => $this->Application->ReplacementTemplates,
- 'Application.RewriteListeners' => $this->Application->RewriteListeners,
- 'Application.ModuleInfo' => $this->Application->ModuleInfo,
+ 'Factory.Files' => $this->Application->Factory->Files,
+ 'Factory.realClasses' => $this->Application->Factory->realClasses,
+ 'Factory.Dependencies' => $this->Application->Factory->Dependencies,
+ 'ConfigReader.prefixFiles' => $this->prefixFiles,
+ 'EventManager.buildEvents' => $event_manager->buildEvents,
+ 'EventManager.beforeRegularEvents' => $event_manager->beforeRegularEvents,
+ 'EventManager.afterRegularEvents' => $event_manager->afterRegularEvents,
+ 'EventManager.beforeHooks' => $event_manager->beforeHooks,
+ 'EventManager.afterHooks' => $event_manager->afterHooks,
+ 'TagsAggregator.data' => $aggregator->_Array,
+
+ // the following caches should be reset based on admin interaction (adjusting config, enabling modules etc)
+ 'Application.Caches.ConfigVariables' => $this->Application->Caches['ConfigVariables'],
+ 'Application.ConfigCacheIds' => $this->Application->ConfigCacheIds,
+ 'Application.ConfigHash' => $this->Application->ConfigHash,
+ 'Application.ReplacementTemplates' => $this->Application->ReplacementTemplates,
+ 'Application.RewriteListeners' => $this->Application->RewriteListeners,
+ 'Application.ModuleInfo' => $this->Application->ModuleInfo,
);
$conn =& $this->Application->GetADODBConnection();
if (isset($this->Application->Memcached)) {
$this->Application->Memcached->set('master:configs_parsed', serialize($cache));
$this->Application->Memcached->set('master:config_files', serialize($this->configFiles));
}
else {
$conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("configs_parsed", '.$conn->qstr(serialize($cache)).', '.adodb_mktime().')');
$conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("config_files", '.$conn->qstr(serialize($this->configFiles)).', '.adodb_mktime().')');
}
$cache_rebuild_by = SERVER_NAME . ' (' . getenv('REMOTE_ADDR') . ') - ' . adodb_date('d/m/Y H:i:s');
$conn->Query('REPLACE ' . TABLE_PREFIX . 'Cache (VarName, Data, Cached) VALUES ("last_cache_rebuild", ' . $conn->qstr($cache_rebuild_by) . ', ' . adodb_mktime() . ')');
unset($this->configFiles);
}
function RestoreParsedData()
{
$conn =& $this->Application->GetADODBConnection();
if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:configs_parsed'))) {
$data = $conn->GetOne('SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName = "configs_parsed"');
}
if ($data) {
$cache = unserialize($data);
$this->Application->Factory->Files = $cache['Factory.Files'];
$this->Application->Factory->realClasses = $cache['Factory.realClasses'];
$this->Application->Factory->Dependencies = $cache['Factory.Dependencies'];
$this->prefixFiles = $cache['ConfigReader.prefixFiles'];
$event_manager =& $this->Application->recallObject('EventManager');
$event_manager->buildEvents = $cache['EventManager.buildEvents'];
$event_manager->beforeRegularEvents = $cache['EventManager.beforeRegularEvents'];
$event_manager->afterRegularEvents = $cache['EventManager.afterRegularEvents'];
$event_manager->beforeHooks = $cache['EventManager.beforeHooks'];
$event_manager->afterHooks = $cache['EventManager.afterHooks'];
$aggregator =& $this->Application->recallObject('TagsAggregator', 'kArray');
$aggregator->_Array = $cache['TagsAggregator.data'];
$this->Application->ConfigHash = $cache['Application.ConfigHash'];
$this->Application->Caches['ConfigVariables'] = $cache['Application.ConfigCacheIds'];
$this->Application->ConfigCacheIds = $cache['Application.ConfigCacheIds'];
$this->Application->ReplacementTemplates = $cache['Application.ReplacementTemplates'];
$this->Application->RewriteListeners = $cache['Application.RewriteListeners'];
$this->Application->ModuleInfo = $cache['Application.ModuleInfo'];
return true;
}
else return false;
}
function ResetParsedData($include_sections = false)
{
$conn =& $this->Application->GetADODBConnection();
$conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "configs_parsed"');
if (isset($this->Application->Memcached)) {
$this->Application->Memcached->delete('master:configs_parsed');
}
if ($include_sections) {
$conn->Query('DELETE FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
if (isset($this->Application->Memcached)) {
$this->Application->Memcached->delete('master:sections_parsed');
}
}
}
function scanModules($folderPath, $cache = true)
{
if (defined('IS_INSTALL') && IS_INSTALL && !defined('FORCE_CONFIG_CACHE')) {
// disable config caching during installation
$cache = false;
}
if ($cache) {
$restored = $this->RestoreParsedData();
if ($restored) return;
}
$this->ProcessAllConfigs = true;
$this->includeConfigFiles($folderPath, $cache);
$this->ParseConfigs();
// tell AfterConfigRead to store cache if neede
// can't store it here beacuse AfterConfigRead needs ability to change config data
$this->StoreCache = $cache;
}
function findConfigFiles($folderPath, $level = 0)
{
/*if ($level == 0) {
if ($this->Application->isDebugMode()) {
$start_time = getmicrotime();
$this->Application->Debugger->appendHTML('kUnitConfigReader::findConfigFiles("' . $folderPath . '")');
$this->Application->Debugger->appendTrace();
}
}*/
// if FULL_PATH = "/" ensure, that all "/" in $folderPath are not deleted
$reg_exp = '/^' . preg_quote(FULL_PATH, '/') . '/';
$folderPath = preg_replace($reg_exp, '', $folderPath, 1); // this make sense, since $folderPath may NOT contain FULL_PATH
$base_folder = FULL_PATH . $folderPath . DIRECTORY_SEPARATOR;
$sub_folders = glob($base_folder . '*', GLOB_ONLYDIR);
if (!$sub_folders) {
return ;
}
if ($level == 0) {
// don't scan Front-End themes because of extensive directory structure
$sub_folders = array_diff($sub_folders, Array ($base_folder . 'themes', $base_folder . 'tools'));
}
foreach ($sub_folders as $full_path) {
$sub_folder = substr($full_path, strlen($base_folder));
if (in_array($sub_folder, $this->_skipFolders)) {
continue;
}
if (preg_match('/^\./', $sub_folder)) {
// don't scan ".folders"
continue;
}
$config_name = $this->getConfigName($folderPath . DIRECTORY_SEPARATOR . $sub_folder);
if (file_exists(FULL_PATH . $config_name)) {
$this->configFiles[] = $config_name;
}
$this->findConfigFiles($full_path, $level + 1);
}
/*if ($level == 0) {
if ($this->Application->isDebugMode()) {
$this->Application->Debugger->appendHTML('kUnitConfigReader::findConfigFiles("' . FULL_PATH . $folderPath . '"): ' . (getmicrotime() - $start_time));
}
}*/
}
function includeConfigFiles($folderPath, $cache = true)
{
$this->Application->refreshModuleInfo();
$conn =& $this->Application->GetADODBConnection();
if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:config_files'))) {
$data = $conn->GetOne('SELECT Data FROM ' . TABLE_PREFIX . 'Cache WHERE VarName = "config_files"');
}
if ($cache && $data) {
$this->configFiles = unserialize($data);
shuffle($this->configFiles);
}
else {
- $this->findConfigFiles($folderPath); // search from base directory
+ $this->findConfigFiles(FULL_PATH . '/core'); // search from core directory
+ $this->findConfigFiles($folderPath); // search from modules directory
}
foreach ($this->configFiles as $filename)
{
$prefix = $this->PreloadConfigFile($filename);
if (!$prefix) {
trigger_error('Prefix not defined in config file ' . $filename, E_USER_ERROR);
}
}
}
/**
* Process all read config files - called ONLY when there is no cache!
*
*/
function ParseConfigs()
{
// 1. process normal configs and their dependencies
$prioritized_configs = array();
foreach ($this->configData as $prefix => $config) {
if (isset($config['ConfigPriority'])) {
$prioritized_configs[$prefix] = $config['ConfigPriority'];
continue;
}
$this->parseConfig($prefix);
}
foreach ($this->configData as $prefix => $config) {
$this->ProcessDependencies($prefix);
$this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix');
$clones = $this->postProcessConfig($prefix, 'Clones', 'prefix');
}
// 2. process prioritized configs and their dependencies
asort($prioritized_configs);
foreach ($prioritized_configs as $prefix => $priority) {
$this->parseConfig($prefix);
}
foreach ($prioritized_configs as $prefix => $priority) {
$this->ProcessDependencies($prefix);
}
}
function AfterConfigRead($store_cache = null)
{
// if (!$this->ProcessAllConfigs) return ;
$this->FinalStage = true;
foreach ($this->configData as $prefix => $config) {
if (in_array($prefix, $this->AfterConfigProcessed)) {
continue;
}
$this->Application->HandleEvent( new kEvent($prefix.':OnAfterConfigRead') );
$this->AfterConfigProcessed[] = $prefix;
}
if (!isset($store_cache)) {
// store cache not overrided -> use global setting
$store_cache = $this->StoreCache;
}
if ($store_cache || (defined('IS_INSTALL') && IS_INSTALL)) {
// cache is not stored during install, but dynamic clones should be processed in any case
$this->processDynamicClones();
$this->retrieveCollections();
}
if ($store_cache) {
$this->_sortRewriteListeners();
$this->CacheParsedData();
if (defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_VALIDATE_CONFIGS') && DBG_VALIDATE_CONFIGS) {
// validate configs here to have changes from OnAfterConfigRead hooks to prefixes
foreach ($this->configData as $prefix => $config) {
if (!isset($config['TableName'])) continue;
$this->ValidateConfig($prefix);
}
}
$after_event = new kEvent('adm:OnAfterCacheRebuild');
$this->Application->HandleEvent($after_event);
}
}
/**
* Sort rewrite listeners according to RewritePriority (non-prioritized listeners goes first)
*
*/
function _sortRewriteListeners()
{
$listeners = Array ();
$prioritized_listeners = Array ();
// process non-prioritized listeners
foreach ($this->Application->RewriteListeners as $prefix => $listener_data) {
if ($listener_data['priority'] === false) {
$listeners[$prefix] = $listener_data;
}
else {
$prioritized_listeners[$prefix] = $listener_data['priority'];
}
}
// process prioritized listeners
asort($prioritized_listeners);
foreach ($prioritized_listeners as $prefix => $priority) {
$listeners[$prefix] = $this->Application->RewriteListeners[$prefix];
}
$this->Application->RewriteListeners = $listeners;
}
/**
* Re-reads all configs
*
*/
function ReReadConfigs()
{
// clear restored cache (not in db)
$this->Application->Factory->Files = Array ();
$this->Application->Factory->realClasses = Array ();
$this->Application->Factory->Dependencies = Array ();
$this->Application->EventManager->beforeRegularEvents = Array ();
$this->Application->EventManager->afterRegularEvents = Array ();
$this->Application->EventManager->beforeHooks = Array ();
$this->Application->EventManager->afterHooks = Array ();
// otherwise ModulesHelper indirectly used from includeConfigFiles won't work
$this->Application->RegisterDefaultClasses();
// parse all configs
$this->ProcessAllConfigs = true;
$this->includeConfigFiles(MODULES_PATH, false);
$this->ParseConfigs();
$this->AfterConfigRead(false);
$this->processDynamicClones();
$this->retrieveCollections();
}
/**
* Process clones, that were defined via OnAfterConfigRead event
*
*/
function processDynamicClones()
{
$new_clones = Array();
foreach ($this->configData as $prefix => $config) {
$clones = $this->postProcessConfig($prefix, 'Clones', 'prefix');
if ($clones) {
$new_clones = array_merge($new_clones, $clones);
}
}
// call OnAfterConfigRead for cloned configs
$new_clones = array_unique($new_clones);
foreach ($new_clones as $prefix) {
if (in_array($prefix, $this->AfterConfigProcessed)) {
continue;
}
$this->Application->HandleEvent( new kEvent($prefix.':OnAfterConfigRead') );
$this->AfterConfigProcessed[] = $prefix;
}
}
/**
* Process all collectable unit config options here to also catch ones, defined from OnAfterConfigRead events
*
*/
function retrieveCollections()
{
foreach ($this->configData as $prefix => $config) {
// collect replacement templates
if (array_key_exists('ReplacementTemplates', $config) && $config['ReplacementTemplates']) {
$this->Application->ReplacementTemplates = array_merge($this->Application->ReplacementTemplates, $config['ReplacementTemplates']);
}
// collect rewrite listeners
if (array_key_exists('RewriteListener', $config) && $config['RewriteListener']) {
$rewrite_listener = $config['RewriteListener'];
if (strpos($rewrite_listener, ':') === false) {
$rewrite_listener = $prefix . '_EventHandler:' . $rewrite_listener;
}
$rewrite_priority = array_key_exists('RewritePriority', $config) ? $config['RewritePriority'] : false;
$this->Application->RewriteListeners[$prefix] = Array ('listener' => $rewrite_listener, 'priority' => $rewrite_priority);
}
}
}
/**
* Register nessasary classes
* This method should only process the data which is cached!
*
* @param string $prefix
* @access private
*/
function parseConfig($prefix)
{
$config =& $this->configData[$prefix];
$event_manager =& $this->Application->recallObject('EventManager');
/* @var $event_manager kEventManager */
$register_classes = getArrayValue($config,'RegisterClasses');
if (!$register_classes) $register_classes = Array();
$class_params=Array('ItemClass','ListClass','EventHandlerClass','TagProcessorClass');
foreach($class_params as $param_name)
{
if ( !(isset($config[$param_name]) ) ) continue;
$config[$param_name]['pseudo'] = $this->getPrefixByParamName($param_name,$prefix);
$register_classes[] = $config[$param_name];
}
foreach($register_classes as $class_info)
{
$require_classes = getArrayValue($class_info, 'require_classes');
if ($require_classes) {
if (!is_array($require_classes)) {
$require_classes = array($require_classes);
}
if (!isset($config['_Dependencies'][$class_info['class']])) {
$config['_Dependencies'][$class_info['class']] = array();
}
$config['_Dependencies'][$class_info['class']] = array_merge($config['_Dependencies'][$class_info['class']], $require_classes);
}
$this->Application->registerClass(
$class_info['class'],
$config['BasePath'] . DIRECTORY_SEPARATOR . $class_info['file'],
$class_info['pseudo']/*,
getArrayValue($class_info, 'require_classes')*/
);
if (getArrayValue($class_info, 'build_event')) {
$event_manager->registerBuildEvent($class_info['pseudo'],$class_info['build_event']);
}
}
$regular_events = getArrayValue($config, 'RegularEvents');
if ($regular_events) {
foreach ($regular_events as $short_name => $regular_event_info) {
$event_status = array_key_exists('Status', $regular_event_info) ? $regular_event_info['Status'] : STATUS_ACTIVE;
$event_manager->registerRegularEvent( $short_name, $config['Prefix'].':'.$regular_event_info['EventName'], $regular_event_info['RunInterval'], $regular_event_info['Type'], $event_status);
}
}
$hooks = getArrayValue($config, 'Hooks');
if (is_array($hooks) && count($hooks) > 0) {
foreach ($hooks as $hook) {
if (isset($config['ParentPrefix']) && $hook['HookToPrefix'] == $config['ParentPrefix']) {
trigger_error('Depricated Hook Usage [prefix: <b>'.$config['Prefix'].'</b>; do_prefix: <b>'.$hook['DoPrefix'].'</b>] use <b>#PARENT#</b> as <b>HookToPrefix</b> value, where HookToPrefix is same as ParentPrefix', E_USER_NOTICE);
}
if ($hook['HookToPrefix'] == '') {
$hook['HookToPrefix'] = $config['Prefix']; // new: set hooktoprefix to current prefix if not set
}
if (isset($config['ParentPrefix'])) {
// new: allow to set hook to parent prefix what ever it is
if ($hook['HookToPrefix'] == '#PARENT#') {
$hook['HookToPrefix'] = $config['ParentPrefix'];
}
if ($hook['DoPrefix'] == '#PARENT#') {
$hook['DoPrefix'] = $config['ParentPrefix'];
}
}
elseif ($hook['HookToPrefix'] == '#PARENT#' || $hook['DoPrefix'] == '#PARENT#') {
continue; // we need parent prefix but it's not set !
}
$do_prefix = $hook['DoPrefix'] == '' ? $config['Prefix'] : $hook['DoPrefix'];
if ( !is_array($hook['HookToEvent']) ) {
$hook_events = Array( $hook['HookToEvent'] );
}
else {
$hook_events = $hook['HookToEvent'];
}
foreach ($hook_events as $hook_event) {
$this->Application->registerHook($hook['HookToPrefix'], $hook['HookToSpecial'], $hook_event, $hook['Mode'], $do_prefix, $hook['DoSpecial'], $hook['DoEvent'], $hook['Conditional']);
}
}
}
if ( is_array(getArrayValue($config, 'AggregateTags')) ) {
foreach ($config['AggregateTags'] as $aggregate_tag) {
if (isset($config['ParentPrefix'])) {
if ($aggregate_tag['AggregateTo'] == $config['ParentPrefix']) {
trigger_error('Depricated Aggregate Tag Usage [prefix: <b>'.$config['Prefix'].'</b>; AggregateTo: <b>'.$aggregate_tag['AggregateTo'].'</b>] use <b>#PARENT#</b> as <b>AggregateTo</b> value, where AggregateTo is same as ParentPrefix', E_USER_NOTICE);
}
if ($aggregate_tag['AggregateTo'] == '#PARENT#') {
$aggregate_tag['AggregateTo'] = $config['ParentPrefix'];
}
}
$aggregate_tag['LocalPrefix'] = $config['Prefix'];
$this->Application->registerAggregateTag($aggregate_tag);
}
}
}
function ValidateConfig($prefix)
{
global $debugger;
$config =& $this->configData[$prefix];
$tablename = $config['TableName'];
$float_types = Array ('float', 'double', 'numeric');
$conn =& $this->Application->GetADODBConnection();
$table_found = $conn->Query('SHOW TABLES LIKE "'.$tablename.'"');
if (!$table_found) {
// config present, but table missing, strange
$debugger->appendHTML("<b class='debug_error'>Config Warning: </b>Table <strong>$tablename</strong> missing, but prefix <b>".$config['Prefix']."</b> requires it!");
safeDefine('DBG_RAISE_ON_WARNINGS', 1);
return ;
}
$res = $conn->Query('DESCRIBE '.$tablename);
$config_link = $debugger->getFileLink(FULL_PATH.$this->prefixFiles[$config['Prefix']], 1, $config['Prefix']);
$error_messages = Array (
'field_not_found' => 'Field <strong>%s</strong> exists in the database, but <strong>is not defined</strong> in config',
'default_missing' => 'Default value for field <strong>%s</strong> not set in config',
'not_null_error1' => 'Field <strong>%s</strong> is NOT NULL in the database, but is not configured as not_null', // or required',
'not_null_error2' => 'Field <strong>%s</strong> is described as NOT NULL in config, but <strong>does not have DEFAULT value</strong>',
'not_null_error3' => 'Field <strong>%s</strong> is described as <strong>NOT NULL in config</strong>, but is <strong>NULL in db</strong>',
'invalid_default' => '<strong>Default value</strong> for field %s<strong>%s</strong> not sync. to db (in config = %s, in db = %s)',
'type_missing' => '<strong>Type definition</strong> for field <strong>%s</strong> missing in config',
);
$config_errors = Array ();
$tablename = preg_replace('/^'.preg_quote(TABLE_PREFIX, '/').'(.*)/', '\\1', $tablename); // remove table prefix
foreach ($res as $field) {
$f_name = $field['Field'];
if (getArrayValue($config, 'Fields')) {
if (preg_match('/l[\d]+_[\w]/', $f_name)) {
// skip multilingual fields
continue;
}
if (!array_key_exists ($f_name, $config['Fields'])) {
$config_errors[] = sprintf($error_messages['field_not_found'], $f_name);
}
else {
if (is_numeric($field['Default'])) {
$field['Default'] = preg_match('/[\.,]/', $field['Default']) ? (float)$field['Default'] : (int)$field['Default'];
}
$options = $config['Fields'][$f_name];
$default_missing = false;
if (!array_key_exists('default', $options)) {
$config_errors[] = sprintf($error_messages['default_missing'], $f_name);
$default_missing = true;
}
if ($field['Null'] != 'YES') {
// field is NOT NULL in database (MySQL5 for null returns "NO", but MySQL4 returns "")
if ( $f_name != $config['IDField'] && !isset($options['not_null']) /*&& !isset($options['required'])*/ ) {
$config_errors[] = sprintf($error_messages['not_null_error1'], $f_name);
}
if (isset($options['not_null']) && $options['not_null'] && !isset($options['default']) ) {
$config_errors[] = sprintf($error_messages['not_null_error2'], $f_name);
}
}
else {
if (isset($options['not_null']) && $options['not_null']) {
$config_errors[] = sprintf($error_messages['not_null_error3'], $f_name);
}
}
if (!array_key_exists('type', $options)) {
$config_errors[] = sprintf($error_messages['type_missing'], $f_name);
}
if (!$default_missing) {
if ($f_name == $config['IDField'] && $options['type'] != 'string' && $options['default'] !== 0) {
$config_errors[] = sprintf($error_messages['invalid_default'], '<span class="debug_error">IDField</span> ', $f_name, $this->varDump($options['default']), $this->varDump($field['Default']));
}
else if ($options['default'] != '#NOW#' && $field['Default'] !== $options['default'] && !in_array($options['type'], $float_types)) {
$config_errors[] = sprintf($error_messages['invalid_default'], '', $f_name, $this->varDump($options['default']), $this->varDump($field['Default']));
}
}
}
}
}
if ($config_errors) {
$error_prefix = '<strong class="debug_error">Config Error'.(count($config_errors) > 1 ? 's' : '').': </strong> for prefix <strong>'.$config_link.'</strong> ('.$tablename.') in unit config:<br />';
$config_errors = $error_prefix.'&nbsp;&nbsp;&nbsp;'.implode('<br />&nbsp;&nbsp;&nbsp;', $config_errors);
$debugger->appendHTML($config_errors);
safeDefine('DBG_RAISE_ON_WARNINGS', 1);
}
}
function varDump($value)
{
return '<strong>'.var_export($value, true).'</strong> of '.gettype($value);
}
function ProcessDependencies($prefix)
{
$config =& $this->configData[$prefix];
$deps = getArrayValue($config, '_Dependencies');
if (!$deps) return ;
foreach ($deps as $real_class => $requires) {
foreach ($requires as $class) {
$this->Application->registerDependency($real_class, $class);
}
}
unset($config['_Dependencies']);
}
function postProcessConfig($prefix, $config_key, $dst_prefix_var)
{
$main_config =& $this->configData[$prefix];
$sub_configs = isset($main_config[$config_key]) && $main_config[$config_key] ? $main_config[$config_key] : false; // getArrayValue($main_config, $config_key);
if (!$sub_configs) {
return array();
}
unset($main_config[$config_key]);
$processed = array();
foreach ($sub_configs as $sub_prefix => $sub_config) {
if ($config_key == 'AggregateConfigs' && !isset($this->configData[$sub_prefix])) {
$this->loadConfig($sub_prefix);
}
$sub_config['Prefix'] = $sub_prefix;
$this->configData[$sub_prefix] = array_merge_recursive2($this->configData[$$dst_prefix_var], $sub_config);
// when merging empty array to non-empty results non-empty array, but empty is required
foreach ($sub_config as $sub_key => $sub_value) {
if (!$sub_value) {
unset($this->configData[$sub_prefix][$sub_key]);
}
}
if ($config_key == 'Clones') {
$this->prefixFiles[$sub_prefix] = $this->prefixFiles[$prefix];
}
$this->postProcessConfig($sub_prefix, $config_key, $dst_prefix_var);
if ($config_key == 'AggregateConfigs') {
$processed = array_merge($this->postProcessConfig($sub_prefix, 'Clones', 'prefix'), $processed);
}
elseif ($this->ProcessAllConfigs) {
$this->parseConfig($sub_prefix);
}
array_push($processed, $sub_prefix);
}
if (!$prefix) {
// configs, that used only for cloning & not used ifself
unset($this->configData[$prefix]);
}
return array_unique($processed);
}
function PreloadConfigFile($filename)
{
- $config_found = file_exists(FULL_PATH.$filename) && $this->configAllowed($filename);
+ $config_found = file_exists(FULL_PATH . $filename) && $this->configAllowed($filename);
if (defined('DEBUG_MODE') && DEBUG_MODE && defined('DBG_PROFILE_INCLUDES') && DBG_PROFILE_INCLUDES) {
if ( in_array($filename, get_required_files()) ) {
return;
}
global $debugger;
if ($config_found) {
$file = FULL_PATH . $filename;
$file_crc = crc32($file);
$debugger->ProfileStart('inc_' . $file_crc, $file);
include_once($file);
$debugger->ProfileFinish('inc_' . $file_crc);
$debugger->profilerAddTotal('includes', 'inc_' . $file_crc);
}
}
elseif ($config_found) {
include_once(FULL_PATH . $filename);
}
if ($config_found) {
if (isset($config) && $config) {
// config file is included for 1st time -> save it's content for future processing
$prefix = array_key_exists('Prefix', $config) ? $config['Prefix'] : '';
- preg_match('#' . $this->_directorySeparator . '(.*)' . $this->_directorySeparator . '#U', $filename, $rets);
+ preg_match($this->_moduleFolderRegExp, $filename, $rets);
$config['ModuleFolder'] = $rets[1];
$config['BasePath'] = dirname(FULL_PATH . $filename);
if (array_key_exists('AdminTemplatePath', $config)) {
// append template base folder for admin templates path of this prefix
$module_templates = $rets[1] == 'core' ? '' : $rets[1] . '/';
$config['AdminTemplatePath'] = $module_templates . $config['AdminTemplatePath'];
}
if (array_key_exists($prefix, $this->prefixFiles) && ($this->prefixFiles[$prefix] != $filename)) {
trigger_error(
'Single unit config prefix "<strong>' . $prefix . '</strong>" ' .
'is used in multiple unit config files: ' .
'"<strong>' . $this->prefixFiles[$prefix] . '</strong>", "<strong>' . $filename . '</strong>"',
E_USER_WARNING
);
}
$this->configData[$prefix] = $config;
$this->prefixFiles[$prefix] = $filename;
return $prefix;
}
elseif ($prefix = array_search($filename, $this->prefixFiles)) {
// attempt is made to include config file twice or more, but include_once prevents that,
// but file exists on hdd, then it is already saved to all required arrays, just return it's prefix
return $prefix;
}
}
return 'dummy';
}
function loadConfig($prefix)
{
if (!isset($this->prefixFiles[$prefix])) {
if ($this->Application->isDebugMode()) $this->Application->Debugger->appendTrace();
trigger_error('Configuration file for prefix <b>'.$prefix.'</b> is unknown', E_USER_ERROR);
return ;
}
$file = $this->prefixFiles[$prefix];
$prefix = $this->PreloadConfigFile($file);
$clones = $this->postProcessConfig($prefix, 'AggregateConfigs', 'sub_prefix');
$clones = array_merge($this->postProcessConfig($prefix, 'Clones', 'prefix'), $clones);
if ($this->FinalStage) {
array_unshift($clones, $prefix);
$clones = array_unique($clones);
foreach ($clones as $a_prefix) {
$this->Application->HandleEvent( new kEvent($a_prefix.':OnAfterConfigRead') );
}
}
}
/**
* Reads unit (specified by $prefix)
* option specified by $option
*
* @param string $prefix
* @param string $name
* @param mixed $default
* @return string
* @access public
*/
function getUnitOption($prefix, $name, $default = false)
{
if (preg_match('/(.*)\.(.*)/', $prefix, $rets)) {
if (!isset($this->configData[$rets[1]])) {
$this->loadConfig($rets[1]);
}
$ret = isset($this->configData[$rets[1]][$name][$rets[2]]) ? $this->configData[$rets[1]][$name][$rets[2]] : false;
// $ret = getArrayValue($this->configData, $rets[1], $name, $rets[2]);
}
else {
if (!isset($this->configData[$prefix])) {
$this->loadConfig($prefix);
}
$ret = isset($this->configData[$prefix][$name]) ? $this->configData[$prefix][$name] : false;
// $ret = getArrayValue($this->configData, $prefix, $name);
}
return $ret === false ? $default : $ret;
}
/**
* Read all unit with $prefix options
*
* @param string $prefix
* @return Array
* @access public
*/
function getUnitOptions($prefix)
{
if (!isset($this->configData[$prefix])) {
$this->loadConfig($prefix);
}
return $this->configData[$prefix];
}
/**
* Set's new unit option value
*
* @param string $prefix
* @param string $name
* @param string $value
* @access public
*/
function setUnitOption($prefix, $name, $value)
{
if (preg_match('/(.*)\.(.*)/', $prefix, $rets)) {
if (!isset($this->configData[$rets[1]])) {
$this->loadConfig($rets[1]);
}
$this->configData[$rets[1]][$name][$rets[2]] = $value;
}
else {
if (!isset($this->configData[$prefix])) {
$this->loadConfig($prefix);
}
$this->configData[$prefix][$name] = $value;
}
}
function getPrefixByParamName($paramName,$prefix)
{
$pseudo_class_map=Array(
'ItemClass'=>'%s',
'ListClass'=>'%s_List',
'EventHandlerClass'=>'%s_EventHandler',
'TagProcessorClass'=>'%s_TagProcessor'
);
return sprintf($pseudo_class_map[$paramName],$prefix);
}
/**
* Get's config file name based
* on folder name supplied
*
* @param string $folderPath
* @return string
* @access private
*/
function getConfigName($folderPath)
{
return $folderPath . DIRECTORY_SEPARATOR . basename($folderPath) . '_config.php';
}
/**
* Checks if config file is allowed for includion (if module of config is installed)
*
* @param string $config_path relative path from in-portal directory
*/
function configAllowed($config_path)
{
+ static $module_paths = null;
+
if (defined('IS_INSTALL') && IS_INSTALL) {
// at installation start no modules in db and kernel configs could not be read
return true;
}
- if (preg_match('#' . $this->_directorySeparator . 'plugins' . $this->_directorySeparator . '|' . $this->_directorySeparator . 'core#', $config_path)) {
- // always allow to include configs from core and plugins folder
+ if (preg_match('#^' . $this->_directorySeparator . 'core#', $config_path)) {
+ // always allow to include configs from "core" module's folder
return true;
}
- $module_found = false;
if (!$this->Application->ModuleInfo) {
return false;
}
- foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
- $module_path = DIRECTORY_SEPARATOR . trim($module_info['Path'], '/') . DIRECTORY_SEPARATOR;
+ if (!isset($module_paths)) {
+ $module_paths = Array ();
- // config file path starts with module folder path
- if (substr($config_path, 0, strlen($module_path)) == $module_path) {
-// if (preg_match('#^' . preg_quote($module_path, '/') . '#', $config_path)) {
- $module_found = true;
- break;
+ foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
+ $module_paths[] = rtrim($module_info['Path'], '/');
}
+
+ $module_paths = array_unique($module_paths);
}
- return $module_found;
+ preg_match($this->_moduleFolderRegExp, $config_path, $rets);
+
+ // config file path starts with module folder path
+ return in_array($rets[1], $module_paths);
}
/**
* Returns true if config exists and is allowed for reading
*
* @param string $prefix
* @return bool
*/
function prefixRegistred($prefix)
{
return isset($this->prefixFiles[$prefix]) ? true : false;
}
/**
* Returns config file for given prefix
*
* @param string $prefix
* @return string
*/
function getPrefixFile($prefix)
{
return array_key_exists($prefix, $this->prefixFiles) ? $this->prefixFiles[$prefix] : false;
}
function iterateConfigs($callback_function, $params)
{
$this->includeConfigFiles(MODULES_PATH); //make sure to re-read all configs
$this->AfterConfigRead();
foreach ($this->configData as $prefix => $config_data) {
$callback_function[0]->$callback_function[1]($prefix, $config_data, $params);
}
}
}
\ No newline at end of file
Index: branches/5.1.x/core/kernel/startup.php
===================================================================
--- branches/5.1.x/core/kernel/startup.php (revision 13112)
+++ branches/5.1.x/core/kernel/startup.php (revision 13113)
@@ -1,160 +1,160 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
define('KERNEL_PATH', FULL_PATH . '/core/kernel');
if (!function_exists('getmicrotime')) {
function getmicrotime()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
}
$globals_start = getmicrotime();
include_once(KERNEL_PATH . '/globals.php'); // non OOP functions used through kernel, e.g. print_pre
include_once(KERNEL_PATH . '/utility/multibyte.php'); // emulating multi-byte php extension
$globals_end = getmicrotime();
$vars = parse_portal_ini(FULL_PATH . '/config.php');
$admin_directory = isset($vars['AdminDirectory']) ? $vars['AdminDirectory'] : '/admin';
define('ADMIN_DIRECTORY', $admin_directory);
# New path detection method: begin
if (defined('REL_PATH')) {
// location of index.php relatively to site base folder
$relative_path = preg_replace('/^[\/]{0,1}admin(.*)/', $admin_directory . '\\1', REL_PATH);
}
else {
// default index.php relative location is administrative console folder
define('REL_PATH', $admin_directory);
$relative_path = REL_PATH;
}
$ps = rtrim(preg_replace('/' . preg_quote(rtrim($relative_path, '/'), '/') . '$/', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))), '/');
safeDefine('BASE_PATH', $ps); // in case in-portal has defined it before
# New path detection method: end
safeDefine('SERVER_NAME', $_SERVER['HTTP_HOST'] ? $_SERVER['HTTP_HOST'] : $vars['Domain']);
$https_mark = getArrayValue($_SERVER, 'HTTPS');
safeDefine('PROTOCOL', ($https_mark == 'on') || ($https_mark == '1') ? 'https://' : 'http://');
safeDefine('APPLICATION_CLASS', isset($vars['ApplicationClass']) ? $vars['ApplicationClass'] : 'kApplication');
safeDefine('APPLICATION_PATH', isset($vars['ApplicationPath']) ? $vars['ApplicationPath'] : '/core/kernel/application.php');
if (isset($vars['WriteablePath'])) {
define('WRITEABLE', FULL_PATH . $vars['WriteablePath']);
define('WRITEBALE_BASE', $vars['WriteablePath']);
}
if ($vars === false || count($vars) == 0) {
global $rootURL;
echo 'In-Portal is probably not installed, or configuration file is missing.<br>';
echo 'Please use the installation script to fix the problem.<br><br>';
echo '<a href="' . PROTOCOL . SERVER_NAME . rtrim(BASE_PATH, '/') . '/core/install.php">Go to installation script</a><br><br>';
flush();
exit;
}
define('SQL_TYPE', $vars['DBType']);
define('SQL_SERVER', $vars['DBHost']);
define('SQL_USER', $vars['DBUser']);
define('SQL_PASS', $vars['DBUserPassword']);
define('SQL_DB', $vars['DBName']);
if (isset($vars['DBCollation']) && isset($vars['DBCharset'])) {
define('SQL_COLLATION', $vars['DBCollation']);
define('SQL_CHARSET', $vars['DBCharset']);
}
define('TABLE_PREFIX', $vars['TablePrefix']);
define('DOMAIN', getArrayValue($vars, 'Domain'));
ini_set('memory_limit', '50M');
- define('MODULES_PATH', FULL_PATH);
+ define('MODULES_PATH', FULL_PATH . '/modules');
define('EXPORT_BASE_PATH', WRITEBALE_BASE . '/export');
define('EXPORT_PATH', FULL_PATH . EXPORT_BASE_PATH);
define('GW_CLASS_PATH', MODULES_PATH . '/in-commerce/units/gateways/gw_classes'); // Payment Gateway Classes Path
define('SYNC_CLASS_PATH', FULL_PATH . '/sync'); // path for 3rd party user syncronization scripts
safeDefine('ENV_VAR_NAME','env');
define('IMAGES_PATH', WRITEBALE_BASE . '/images/');
define('IMAGES_PENDING_PATH', IMAGES_PATH . 'pending/');
safeDefine('MAX_UPLOAD_SIZE', min(ini_get('upload_max_filesize'), ini_get('post_max_size'))*1024*1024);
safeDefine('EDITOR_PATH', isset($vars['EditorPath']) ? $vars['EditorPath'] : '/core/editor/');
if (ini_get('safe_mode')) {
// safe mode will be removed at all in PHP6
define('SAFE_MODE', 1);
}
if (file_exists(FULL_PATH . '/debug.php')) {
include_once(FULL_PATH . '/debug.php');
if (array_key_exists('DEBUG_MODE', $dbg_options) && $dbg_options['DEBUG_MODE']) {
$debugger_start = getmicrotime();
include_once(KERNEL_PATH . '/utility/debugger.php');
$debugger_end = getmicrotime();
if (isset($debugger) && constOn('DBG_PROFILE_INCLUDES')) {
$debugger->profileStart('inc_globals', KERNEL_PATH . '/globals.php', $globals_start);
$debugger->profileFinish('inc_globals', KERNEL_PATH . '/globals.php', $globals_end);
$debugger->profilerAddTotal('includes', 'inc_globals');
$debugger->profileStart('inc_debugger', KERNEL_PATH . '/utility/debugger.php', $debugger_start);
$debugger->profileFinish('inc_debugger', KERNEL_PATH . '/utility/debugger.php', $debugger_end);
$debugger->profilerAddTotal('includes', 'inc_debugger');
}
}
}
safeDefine('SILENT_LOG', 0);
$includes = Array(
KERNEL_PATH . '/application.php',
FULL_PATH . APPLICATION_PATH,
KERNEL_PATH . '/db/db_connection.php',
KERNEL_PATH . "/kbase.php",
KERNEL_PATH . '/utility/event.php',
KERNEL_PATH . "/utility/factory.php",
KERNEL_PATH . "/languages/phrases_cache.php",
KERNEL_PATH . "/db/dblist.php",
KERNEL_PATH . "/db/dbitem.php",
KERNEL_PATH . "/event_handler.php",
KERNEL_PATH . '/db/db_event_handler.php',
);
foreach ($includes as $a_file) {
k4_include_once($a_file);
}
if (defined('DEBUG_MODE') && DEBUG_MODE && isset($debugger)) {
$debugger->AttachToApplication();
}
if( !function_exists('adodb_mktime') ) {
include_once(KERNEL_PATH . '/utility/adodb-time.inc.php');
}
// global constants
define ('KG_TO_POUND', 2.20462262);
define ('POUND_TO_KG', 0.45359237);
\ No newline at end of file
Index: branches/5.1.x/core/kernel/nparser/template_cache.php
===================================================================
--- branches/5.1.x/core/kernel/nparser/template_cache.php (revision 13112)
+++ branches/5.1.x/core/kernel/nparser/template_cache.php (revision 13113)
@@ -1,451 +1,439 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class TemplatesCache extends kHelper {
/**
* Base path for searching templates
*
* @var string
*/
var $BasePath;
/**
* Force templates cache to search templates on front-end:
* true - search for theme name in template name
* false - don't search anywhere
* name - theme name to prepend for each template name
*
* @var mixed
*/
var $forceThemeName = false;
/**
* Compile templates to database
*
* @var bool
*/
var $_compileToDatabase = false;
/**
* Compress compiled templates
*
* @var bool
*/
var $_compressOutput = false;
/**
* Template locations of each module
*
* @var Array
*/
var $_modulePaths = Array ();
function TemplatesCache()
{
parent::kBase();
$this->BasePath = FULL_PATH . THEMES_PATH;
$this->_compileToDatabase = defined('SAFE_MODE') && SAFE_MODE;
$this->_compressOutput = $this->Application->ConfigValue('UseTemplateCompression');
if ($this->Application->isAdmin) {
// prepare module template paths for quick access
$module_paths = Array ();
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
- $module_paths[$module_name] = rtrim($module_info['Path'], '/');
+ $module_paths[ mb_strtolower($module_name) ] = rtrim($module_info['Path'], '/');
}
$this->_modulePaths = $module_paths;
}
}
/**
* Based on template name gets it's location on disk and owner module
*
* @param string $filename
* @return Array 0 - path on disk, 1 - template name
*/
function GetTemplatePaths($filename)
{
if ($this->Application->isAdmin && array_key_exists($filename, $this->Application->ReplacementTemplates)) {
+ // process admin template replacement
$filename = $this->Application->ReplacementTemplates[$filename];
}
// allows to use non-replaced version of replaced template
$filename = preg_replace('/^original:(.*)/', '\\1', $filename);
if (preg_match('#^[\/]{0,1}([^\/]*)\/(.*)#', $filename, $regs)) {
- $module_filename = $regs[2];
$first_dir = $regs[1];
+ $module_filename = $regs[2];
}
else {
$first_dir = '';
$module_filename = $filename;
}
if (is_string($this->forceThemeName)) {
// when defined, then all templates are read from given theme name
$first_dir = 'theme:' . $this->forceThemeName . ($first_dir ? '/' . $first_dir : '');
}
- // !preg_match for backward compatability with full-path plugins
- if ($this->Application->isAdmin && ($first_dir == 'plugins') && !preg_match('/admin_templates/', $module_filename)) {
- if (preg_match('#^[\/]{0,1}([^\/]*)\/(.*)#', $module_filename, $regs)) {;
- $path = MODULES_PATH.'/'.mb_strtolower($first_dir).'/'.$regs[1].'/admin_templates';
- $module_filename = $regs[2];
- }
- else {
- $first_dir = '';
- $module_filename = $filename;
- }
- }
- elseif ($this->Application->isAdmin && in_array($first_dir, $this->_modulePaths)) {
- // $this->Application->findModule('Name', $first_dir)
- /*if ($first_dir == 'in-portal') {
- $first_dir = 'kernel';
- }*/
- $path = MODULES_PATH.'/'.mb_strtolower($first_dir).'/admin_templates';
+ if ($this->Application->isAdmin && array_key_exists($first_dir, $this->_modulePaths)) {
+ // template belongs to one of the modules
+ $path = FULL_PATH . '/' . $this->_modulePaths[$first_dir] . '/admin_templates';
}
elseif ($this->forceThemeName && preg_match('/^theme:(.*)/', $first_dir, $regs)) {
// ability to use Front-End templates in admin (only during mass compilation)
$path = FULL_PATH . '/themes/' . $regs[1];
}
else {
+ // template from "core" module
$path = $this->BasePath;
- $module_filename = $first_dir.'/'.$module_filename;
+ $module_filename = $first_dir . '/' . $module_filename;
}
return Array ($path, $module_filename);
}
/**
* Returns template filename by given template name
*
* @param string $filename
* @return string
*/
function GetRealFilename($filename)
{
list ($path, $module_filename) = $this->GetTemplatePaths($filename);
return $path.'/'.trim($module_filename, '/');
}
/**
* Checks, that given template exists on disk
*
* @param string $filename
* @return bool
*/
function TemplateExists($filename)
{
if ((strpos($filename, '../') !== false) || (trim($filename) !== $filename)) {
// when relative paths or special chars are found template names from url, then it's hacking attempt
return false;
}
$real_file = $this->GetRealFilename( strtolower($filename) );
if (substr($real_file, -4) != '.tpl') {
// add ".tpl" file extension, when not specified in template name
$real_file .= '.tpl';
}
return file_exists($real_file);
}
/**
* Returns information about template compilation status
*
* @param string $template
* @return Array
*/
function GetPreParsed($template)
{
$real_name = $this->GetRealFilename($template);
$fname = str_replace(FULL_PATH, WRITEABLE . '/cache', $real_name . '.php');
$tname = $real_name . '.tpl';
if (!file_exists($tname)) {
// given template doesn't exist
return false;
}
if ($this->_compileToDatabase) {
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "' . $fname . '"';
$cached = $this->Conn->GetRow($sql);
if ($cached !== false && $cached['Cached'] > filemtime($tname)) {
return Array ('active' => 1, 'fname' => $fname, 'tname' => $tname, 'mode' => 'db', 'content' => $cached['Data']);
}
}
else {
if (file_exists($fname) && file_exists($tname) && filemtime($fname) > filemtime($tname)) {
return Array ('active' => 1, 'fname' => $fname, 'tname' => $tname, 'mode' => 'file');
}
if (!file_exists($fname)) {
// make sure to create directory if pre-parsed file does not exist
$this->CheckDir(dirname($fname), WRITEABLE . '/cache');
}
}
// when compiled template is expired or doesn't exist
return Array ('active' => 0, 'fname' => $fname, 'tname' => $tname, 'mode' => 'file');
}
/**
* Saves compiled template version to database or disk
*
* @param string $filename
* @param string $compiled_template
*/
function saveTemplate($filename, &$compiled_template)
{
if ($this->_compileToDatabase) {
$fields_hash = Array (
'VarName' => $filename,
'Data' => &$compiled_template,
'Cached' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache', 'REPLACE');
}
else {
$fp = fopen($filename, 'w');
if ($this->_compressOutput) {
$compiled_template = $this->_compress($compiled_template);
}
if (!fwrite($fp, $compiled_template)) {
trigger_error('Saving compiled template failed', E_USER_ERROR);
}
fclose($fp);
}
}
/**
* Runs template and returns result (template already should be compiled by now)
*
* @param NParser $_parser
* @param Array $pre_parsed
* @return string
*/
function &runTemplate(&$_parser, &$pre_parsed)
{
ob_start();
if ($this->_compileToDatabase) {
$sql = 'SELECT *
FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName = "' . $pre_parsed['fname'] . '"';
$cached = $this->Conn->GetRow($sql);
if (($cached !== false) && ($cached['Cached'] > filemtime($pre_parsed['tname']))) {
eval('?' . '>' . $cached['Data']);
}
}
else {
if ($pre_parsed['mode'] == 'file') {
include($pre_parsed['fname']);
}
else {
eval('?' . '>' . $pre_parsed['content']);
}
}
$output = ob_get_clean();
return $output;
}
/**
* Compress given php code
*
* @param string $src
* @return string
*/
function _compress($src) {
// Whitespaces left and right from this signs can be ignored
static $IW = array(
T_CONCAT_EQUAL, // .=
T_DOUBLE_ARROW, // =>
T_BOOLEAN_AND, // &&
T_BOOLEAN_OR, // ||
T_IS_EQUAL, // ==
T_IS_NOT_EQUAL, // != or <>
T_IS_SMALLER_OR_EQUAL, // <=
T_IS_GREATER_OR_EQUAL, // >=
T_INC, // ++
T_DEC, // --
T_PLUS_EQUAL, // +=
T_MINUS_EQUAL, // -=
T_MUL_EQUAL, // *=
T_DIV_EQUAL, // /=
T_IS_IDENTICAL, // ===
T_IS_NOT_IDENTICAL, // !==
T_DOUBLE_COLON, // ::
T_PAAMAYIM_NEKUDOTAYIM, // ::
T_OBJECT_OPERATOR, // ->
T_DOLLAR_OPEN_CURLY_BRACES, // ${
T_AND_EQUAL, // &=
T_MOD_EQUAL, // %=
T_XOR_EQUAL, // ^=
T_OR_EQUAL, // |=
T_SL, // <<
T_SR, // >>
T_SL_EQUAL, // <<=
T_SR_EQUAL, // >>=
);
$tokens = token_get_all($src);
$new = "";
$c = sizeof($tokens);
$iw = false; // ignore whitespace
$ih = false; // in HEREDOC
$ls = ""; // last sign
$ot = null; // open tag
for ($i = 0; $i < $c; $i++) {
$token = $tokens[$i];
if (is_array($token)) {
list ($tn, $ts) = $token; // tokens: number, string, line
$tname = token_name($tn);
if ($tn == T_INLINE_HTML) {
$new .= $ts;
$iw = false;
} else {
if ($tn == T_OPEN_TAG) {
if (strpos($ts, " ") || strpos($ts, "\n") || strpos($ts, "\t") || strpos($ts, "\r")) {
$ts = rtrim($ts);
}
$ts .= " ";
$new .= $ts;
$ot = T_OPEN_TAG;
$iw = true;
} elseif ($tn == T_OPEN_TAG_WITH_ECHO) {
$new .= $ts;
$ot = T_OPEN_TAG_WITH_ECHO;
$iw = true;
} elseif ($tn == T_CLOSE_TAG) {
if ($ot == T_OPEN_TAG_WITH_ECHO) {
$new = rtrim($new, "; ");
} else {
$ts = " ".$ts;
}
$new .= $ts;
$ot = null;
$iw = false;
} elseif (in_array($tn, $IW)) {
$new .= $ts;
$iw = true;
} elseif ($tn == T_CONSTANT_ENCAPSED_STRING || $tn == T_ENCAPSED_AND_WHITESPACE) {
if ($ts[0] == '"') {
$ts = addcslashes($ts, "\n\t\r");
}
$new .= $ts;
$iw = true;
} elseif ($tn == T_WHITESPACE) {
$nt = @$tokens[$i+1];
if (!$iw && (!is_string($nt) || $nt == '$') && !in_array($nt[0], $IW)) {
$new .= " ";
}
$iw = false;
} elseif ($tn == T_START_HEREDOC) {
$new .= "<<<S\n";
$iw = false;
$ih = true; // in HEREDOC
} elseif ($tn == T_END_HEREDOC) {
$new .= "S;";
$iw = true;
$ih = false; // in HEREDOC
for ($j = $i + 1; $j < $c; $j++) {
if (is_string($tokens[$j]) && $tokens[$j] == ";") {
$i = $j;
break;
} else if ($tokens[$j][0] == T_CLOSE_TAG) {
break;
}
}
} elseif ($tn == T_COMMENT || $tn == T_DOC_COMMENT) {
$iw = true;
} else {
/*if (!$ih) {
// this also lowecases attribute names :(
$ts = strtolower($ts);
}*/
$new .= $ts;
$iw = false;
}
}
$ls = "";
} else {
if (($token != ";" && $token != ":") || $ls != $token) {
$new .= $token;
$ls = $token;
}
$iw = true;
}
}
return $new;
}
/**
* Recursive mkdir
*
* @param string $dir
* @param string $base_path base path to directory where folders should be created in
*/
function CheckDir($dir, $base_path = '')
{
if (file_exists($dir)) {
return;
}
else {
// remove $base_path from beggining because it is already created during install
$dir = preg_replace('/^'.preg_quote($base_path.'/', '/').'/', '', $dir, 1);
$segments = explode('/', $dir);
$cur_path = $base_path;
foreach ($segments as $segment) {
// do not add leading / for windows paths (c:\...)
$cur_path .= preg_match('/^[a-zA-Z]{1}:/', $segment) ? $segment : '/'.$segment;
if (!file_exists($cur_path)) {
mkdir($cur_path);
}
}
}
}
}
\ No newline at end of file
Index: branches/5.1.x/core/units/helpers/modules_helper.php
===================================================================
--- branches/5.1.x/core/units/helpers/modules_helper.php (revision 13112)
+++ branches/5.1.x/core/units/helpers/modules_helper.php (revision 13113)
@@ -1,438 +1,438 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kModulesHelper extends kHelper {
function getWhereClause()
{
$where_clause = Array('Loaded = 1');
if (!$this->Application->isAdmin) {
// no license checks on front-end
return implode(' AND ', $where_clause);
}
$modules = $this->_GetModules();
if ($modules) {
foreach ($modules as $module_index => $module) {
$modules[$module_index] = $this->Conn->qstr($module);
}
$where_clause[] = 'Name IN ('.implode(',', $modules).')';
}
return implode(' AND ', $where_clause);
}
function _EnableCookieSID()
{
$session =& $this->Application->recallObject('Session');
return $session->CookiesEnabled;
}
function _IsSpider($UserAgent)
{
global $robots;
$lines = file(FULL_PATH.'/robots_list.txt');
if (!is_array($robots)) {
$robots = Array();
for($i = 0; $i < count($lines); $i++) {
$l = $lines[$i];
$p = explode("\t", $l, 3);
$robots[] = $p[2];
}
}
return in_array($UserAgent, $robots);
}
function _MatchIp($ip1, $ip2)
{
$matched = TRUE;
$ip = explode('.', $ip1);
$MatchIp = explode('.', $ip2);
for ($i = 0; $i < count($ip); $i++) {
if($i == count($MatchIp)) break;
if (trim($ip[$i]) != trim($MatchIp[$i]) || trim($ip[$i]) == '*') {
$matched = FALSE;
break;
}
}
return $matched;
}
function _IpAccess($IpAddress, $AllowList, $DenyList)
{
$allowed = explode(',', $AllowList);
$denied = explode(',', $DenyList);
$MatchAllowed = FALSE;
for ($x = 0; $x < count($allowed); $x++) {
$ip = explode('.', $allowed[$x]);
$MatchAllowed = $this->_MatchIp($IpAddress, $allowed[$x]);
if ($MatchAllowed)
break;
}
$MatchDenied = FALSE;
for ($x = 0; $x < count($denied); $x++) {
$ip = explode('.', $denied[$x]);
$MatchDenied = $this->_MatchIp($IpAddress, $denied[$x]);
if ($MatchDenied)
break;
}
$Result = (($MatchAllowed && !$MatchDenied) || (!$MatchAllowed && !$MatchDenied) ||
($MatchAllowed && $MatchDenied));
return $Result;
}
/**
* Leaves only domain part from hostname (e.g. extract "intechnic.lv" from "test.intechnic.lv")
* Used for admin login license check
*
* @param string $d
* @return string
*/
function _StripDomainHost($d)
{
$IsIp = false;
$dotcount = substr_count($d, '.');
if ($dotcount == 3) {
$IsIp = true;
for ($x = 0; $x < strlen($d); $x++) {
if (!is_numeric(substr($d, $x, 1)) && substr($d, $x, 1) != '.')
{
$IsIp = false;
break;
}
}
}
if ($dotcount > 1 && !$IsIp) {
$p = explode('.', $d);
$ret = $p[count($p) - 2].'.'.$p[count($p) - 1];
}
else {
$ret = $d;
}
return $ret;
}
/**
* When logging into admin then check only last 2 parts of host name VS domain in license
*
* @param string $user_domain
* @param string $license_domain
* @return int
*/
function _CheckDomain($user_domain, $license_domain)
{
if ($this->Application->isAdmin) {
$user_domain = $this->_StripDomainHost($user_domain);
return preg_match('/(.*)'.preg_quote($user_domain, '/').'$/', $license_domain);
}
else {
return preg_match('/(.*)'.preg_quote($license_domain, '/').'$/', $user_domain);
}
}
/**
* Returns modules list, that are in license
*
* @return Array
*/
function _GetModules()
{
static $modules = null;
if (isset($modules)) {
return $modules;
}
$modules = Array();
$vars = parse_portal_ini(FULL_PATH . DIRECTORY_SEPARATOR . 'config.php');
$license = array_key_exists('License', $vars) ? base64_decode($vars['License']) : false;
if ($license) {
list ( , , $i_Keys) = $this->_ParseLicense($license);
$domain = $this->_GetDomain($vars);
if (!$this->_IsLocalSite($domain)) {
for ($x = 0; $x < count($i_Keys); $x++) {
$key = $i_Keys[$x];
if ($this->_CheckDomain($domain, $key['domain'])) {
// used hostname is subdomain or matches domain from license
$modules = explode(',', $key['mod']);
}
}
}
else {
// all already installed modules are licensed for localhost
$modules = array_keys($this->Application->ModuleInfo);
}
}
// all modules starting from "in-" doesn't require license
$base_modules = Array ('Core', 'In-Portal', 'Custom');
$modules = array_merge($modules, $base_modules, $this->_getFreeModules($vars));
$modules = array_unique( array_map('strtolower', $modules) );
return $modules;
}
/**
* Get all modules, that don't require licensing
*
* @return Array
*/
function _getFreeModules($vars)
{
$skip_modules = Array ('.', '..');
$domain = $this->_GetDomain($vars);
if (!$this->_IsLocalSite($domain)) {
array_push($skip_modules, 'in-commerce', 'in-auction');
}
$folder = dir(MODULES_PATH);
$ret = Array ();
while (($entry = $folder->read()) !== false) {
$entry_lowercased = strtolower($entry);
- if (!is_dir($folder->path . '/' . $entry) || in_array($entry_lowercased, $skip_modules) || (substr($entry_lowercased, 0, 3) != 'in-')) {
+ if (!is_dir($folder->path . '/' . $entry) || in_array($entry_lowercased, $skip_modules)) {
continue;
}
$ret[] = $entry_lowercased;
}
$folder->close();
return $ret;
}
/**
* Allows to determine if module is licensed
*
* @param string $name
* @return bool
*/
function _ModuleLicensed($name)
{
$modules = $this->_GetModules();
return in_array($name, $modules);
}
/**
* Returns domain from licences (and direct in case of install script)
*
* @return string
*/
function _GetDomain($vars)
{
$config_domain = array_key_exists('Domain', $vars) ? $vars['Domain'] : false;
return $this->Application->ConfigValue('DomainDetect') ? $_SERVER['HTTP_HOST'] : $config_domain;
}
function _keyED($txt, $encrypt_key)
{
$encrypt_key = md5($encrypt_key);
$ctr = 0;
$tmp = '';
for ($i = 0; $i < strlen($txt); $i++) {
if ($ctr == strlen($encrypt_key)) $ctr = 0;
$tmp .= substr($txt, $i, 1) ^ substr($encrypt_key, $ctr, 1);
$ctr++;
}
return $tmp;
}
function _decrypt($txt, $key)
{
$txt = $this->_keyED($txt,$key);
$tmp = '';
for ($i = 0; $i < strlen($txt); $i++) {
$md5 = substr($txt, $i, 1);
$i++;
$tmp .= (substr($txt, $i, 1) ^ $md5);
}
return $tmp;
}
function LoadFromRemote()
{
return '';
}
function DLid()
{
die($GLOBALS['lid']."\n");
}
function _LoadLicense($LoadRemote = false)
{
$f = FULL_PATH.'/intechnic.php';
if ($this->_falseIsLocalSite($f)) $ret = true;
if (file_exists($f)) {
$contents = file($f);
$data = base64_decode($contents[1]);
}
else {
if ($LoadRemote) return $LoadFromRemote;
}
return $data;
}
function _VerifyKey($domain, $k)
{
$key = md5($domain);
$lkey = substr($key, 0, strlen($key) / 2);
$rkey = substr($key, strlen($key) / 2);
$r = $rkey.$lkey;
if ($k == $r) return true;
return false;
}
function _ParseLicense($txt)
{
// global $i_User, $i_Pswd, $i_Keys;
if (!$this->_falseIsLocalSite($txt)) {
$nah = false;
}
$data = $this->_decrypt($txt, 'beagle');
$i_User = $i_Pswd = '';
$i_Keys = Array();
$lines = explode("\n", $data);
for ($x = 0; $x < count($lines); $x++) {
$l = $lines[$x];
$p = explode('=', $l, 2);
switch($p[0]) {
case 'Username':
$i_User = $p[1];
break;
case 'UserPass':
$i_Pswd = $p[1];
break;
default:
if (substr($p[0], 0, 3) == 'key') {
$parts = explode('|', $p[1]);
if ($this->_VerifyKey($parts[0], $parts[1])) {
unset($K);
$k['domain'] = $parts[0];
$k['key'] = $parts[1];
$k['desc'] = $parts[2];
$k['mod'] = $parts[3];
$i_Keys[] = $k;
}
}
break;
}
}
return Array ($i_User, $i_Pswd, $i_Keys);
}
function _GetObscureValue($i)
{
if ($i == 'x') return 0254; $z = '';
if ($i == 'z') return 0x7F.'.';
if ($i == 'c') return '--code--';
if ($i >= 5 && $i < 7) return $this->_GetObscureValue($z)*$this->_GetObscureValue('e');
if ($i > 30) return Array(0x6c,0x6f,0x63,0x61,0x6c,0x68,0x6f,0x73,0x74);
if ($i > 20) return 99;
if ($i > 10) return '.'.($this->_GetObscureValue(6.5)+1);
if ($i == 'a') return 0xa;
}
function _Chr($val)
{
$x = $this->_GetObscureValue(25);
$f = chr($x).chr($x+5).chr($x+15);
return $f($val);
}
function _IsLocalSite($domain)
{
$ee = $this->_GetObscureValue(35); $yy = '';
foreach ($ee as $e) $yy .= $this->_Chr($e);
$localb = FALSE;
if(substr($domain,0,3)==$this->_GetObscureValue('x'))
{
$b = substr($domain,0,6);
$p = explode(".",$domain);
$subnet = $p[1];
if($p[1]>15 && $p[1]<32)
$localb=TRUE;
}
$zz = $this->_GetObscureValue('z').$this->_GetObscureValue(5).'.'.(int)$this->_GetObscureValue(7).$this->_GetObscureValue(12);
$ff = $this->_GetObscureValue('z')+65;
$hh = $ff-0x18;
if($domain==$yy || $domain==$zz || substr($domain,0,7)==$ff.$this->_Chr(46).$hh ||
substr($domain,0,3)==$this->_GetObscureValue('a').$this->_Chr(46) || $localb || strpos($domain,".")==0)
{
return TRUE;
}
return FALSE;
}
function _falseIsLocalSite($domain)
{
$localb = FALSE;
if(substr($domain,0,3)=="172")
{
$b = substr($domain,0,6);
$p = explode(".",$domain);
$subnet = $p[1];
if($p[1]>15 && $p[1]<32)
$localb=TRUE;
}
if($domain=="localhost" || $domain=="127.0.0.1" || substr($domain,0,7)=="192.168" ||
substr($domain,0,3)=="10." || $localb || strpos($domain,".")==0)
{
return TRUE;
}
return FALSE;
}
function verifyLicense($license_hash)
{
$license_hash = base64_decode($license_hash);
list ($license_user, $license_password, ) = $this->_ParseLicense($license_hash);
return strlen($license_user) && strlen($license_password);
}
function moduleInstalled($module_name)
{
static $modules = null;
if (is_null($modules)) {
$sql = 'SELECT LOWER(Name)
FROM ' . $this->Application->getUnitOption('mod', 'TableName');
$modules = $this->Conn->GetCol($sql);
}
if ($module_name == 'kernel') {
$module_name = 'in-portal';
}
return in_array(strtolower($module_name), $modules);
}
}
\ No newline at end of file
Index: branches/5.1.x/core/units/helpers/sections_helper.php
===================================================================
--- branches/5.1.x/core/units/helpers/sections_helper.php (revision 13112)
+++ branches/5.1.x/core/units/helpers/sections_helper.php (revision 13113)
@@ -1,306 +1,309 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/**
* Processes sections info from the configs
*
*/
class kSectionsHelper extends kHelper {
/**
* Holds information about all sections
*
* @var Array
*/
var $Tree = Array();
/**
* Set's prefix and special
*
* @param string $prefix
* @param string $special
* @access public
*/
function Init($prefix, $special, $event_params = null)
{
parent::Init($prefix, $special, $event_params);
$this->BuildTree();
}
/**
* Builds xml for tree in left frame in admin
*
* @param Array $params
*/
function BuildTree()
{
if (!isset($this->Application->Memcached) || !($data = $this->Application->Memcached->get('master:sections_parsed'))) {
$data = $this->Conn->GetOne('SELECT Data FROM '.TABLE_PREFIX.'Cache WHERE VarName = "sections_parsed"');
}
if ($data) {
$this->Tree = unserialize($data);
return ;
}
if (!(defined('IS_INSTALL') && IS_INSTALL)) {
// don't reread all configs during install, because they are reread on every install step
$this->Application->UnitConfigReader->ReReadConfigs();
}
$this->Tree = Array ();
// 1. build base tree (don't update parent with children list yet)
// 1.1. process prefixes without priority
$prioritized_prefixes = Array ();
$prefixes = array_keys($this->Application->UnitConfigReader->configData);
foreach ($prefixes as $prefix) {
$config =& $this->Application->UnitConfigReader->configData[$prefix];
if (array_key_exists('ConfigPriority', $config)) {
$prioritized_prefixes[$prefix] = $config['ConfigPriority'];
continue;
}
$this->_processPrefixSections($prefix);
}
// 2. process prefixes with priority
asort($prioritized_prefixes);
foreach ($prioritized_prefixes as $prefix => $priority) {
$this->_processPrefixSections($prefix);
}
// 2. apply section ajustments
foreach ($prefixes as $prefix) {
$config =& $this->Application->UnitConfigReader->configData[$prefix];
$section_ajustments = getArrayValue($config, 'SectionAdjustments');
if (!$section_ajustments) continue;
foreach ($section_ajustments as $section_name => $ajustment_params) {
if (is_array($ajustment_params)) {
if (!array_key_exists($section_name, $this->Tree)) {
// don't process ajustments for non-existing sections
continue;
}
$this->Tree[$section_name] = array_merge_recursive2($this->Tree[$section_name], $ajustment_params);
}
else {
// then remove section
unset($this->Tree[$section_name]);
}
}
}
// 3.
foreach ($this->Tree as $section_name => $section_params) {
// 3.1. update parent -> children references
$parent_section = $section_params['parent'];
$section_order = "{$section_params['priority']}";
if (!isset($parent_section)) {
// don't process parent section of "in-portal:root" section
continue;
}
if (!array_key_exists('children', $this->Tree[$parent_section])) {
$this->Tree[$parent_section]['children'] = Array ();
}
if (array_key_exists($section_order, $this->Tree[$parent_section]['children'])) {
trigger_error(
'Section "<strong>' . $section_name . '</strong>" has replaced section "<strong>' .
$this->Tree[$parent_section]['children'][$section_order] .
'</strong>" (parent section: "<strong>' . $parent_section .
'</strong>"; duplicate priority: <strong>' . $section_order . '</strong>)',
E_USER_WARNING
);
}
$this->Tree[$parent_section]['children'][$section_order] = $section_name;
if ($section_params['type'] == stTAB) {
// if this is tab, then mark parent section as TabOnly
$this->Tree[$parent_section]['tabs_only'] = true;
}
// 3.2. process icons here, because they also can be ajusted
if (isset($section_params['icon']) && preg_match('/([^:]+):(.*)/', $section_params['icon'], $regs)) {
$this->Tree[$section_name]['icon'] = $regs[2];
$this->Tree[$section_name]['icon_module'] = $regs[1]; // set "icon_module" used in "combined_header" block
$module_folder = trim( $this->Application->findModule('Name', $regs[1], 'Path'), '/');
+
if ($module_folder == '') {
$module_folder = 'core';
}
}
else {
$module_folder = $this->Application->getUnitOption($section_params['SectionPrefix'], 'ModuleFolder');
if (!array_key_exists('icon_module', $section_params)) {
- $this->Tree[$section_name]['icon_module'] = $module_folder; // set "icon_module" used in "combined_header" block
+ // set "icon_module" used in "combined_header" block
+ $this->Tree[$section_name]['icon_module'] = $this->Application->findModule('Path', $module_folder . '/', 'Name');
}
}
// this is to display HELP icon instead of missing one.. can be replaced with some other icon to draw attention
$icon_file = $module_folder.'/admin_templates/img/icons/icon24_'.$this->Tree[$section_name]['icon'];
- /*$core_file = FULL_PATH.'/core/admin_templates/img/icons/icon24_' . $this->Tree[$section_name]['icon'].'.gif';
- if ($module_folder != 'core' && file_exists($core_file) && file_exists(FULL_PATH.'/'.$icon_file.'.gif')) {
- if (crc32(file_get_contents($core_file)) == crc32(file_get_contents(FULL_PATH.'/'.$icon_file.'.gif'))) {
+ /*$core_file = FULL_PATH.'/core/admin_templates/img/icons/icon24_' . $this->Tree[$section_name]['icon'].'.png';
+ if ($module_folder != 'core' && file_exists($core_file) && file_exists(FULL_PATH.'/'.$icon_file.'.png')) {
+ if (crc32(file_get_contents($core_file)) == crc32(file_get_contents(FULL_PATH.'/'.$icon_file.'.png'))) {
trigger_error('Section "<strong>' . $section_name . '</strong>" uses icon copy from "Core" module', E_USER_NOTICE);
}
}*/
-// if (!file_exists(FULL_PATH.'/'.$icon_file.'.png')) {
-// $this->Tree[$section_name]['icon'] = 'help';
-// $this->Tree[$section_name]['icon_module'] = 'core';
-// }
+ if (!file_exists(FULL_PATH . '/' . $icon_file . '.png')) {
+ $this->Tree[$section_name]['icon'] = 'help';
+ $this->Tree[$section_name]['icon_module'] = 'core';
+ }
}
+
$this->Application->HandleEvent( new kEvent('adm:OnAfterBuildTree') );
if (isset($this->Application->Memcached)) {
$this->Application->Memcached->set('master:sections_parsed',serialize($this->Tree), 0, 0);
return;
}
$this->Conn->Query('REPLACE '.TABLE_PREFIX.'Cache (VarName, Data, Cached) VALUES ("sections_parsed", '.$this->Conn->qstr(serialize($this->Tree)).', '.adodb_mktime().')');
}
function _processPrefixSections($prefix)
{
$config =& $this->Application->UnitConfigReader->configData[$prefix];
$sections = getArrayValue($config, 'Sections');
if (!$sections) {
return ;
}
// echo 'Prefix: ['.$prefix.'] has ['.count($sections).'] sections<br />';
foreach ($sections as $section_name => $section_params) {
// we could also skip not allowed sections here in future
if ( isset($section_params['SectionPrefix']) ) {
$section_prefix = $section_params['SectionPrefix'];
}
elseif ( $this->Application->getUnitOption($prefix, 'SectionPrefix') ) {
$section_prefix = $this->Application->getUnitOption($prefix, 'SectionPrefix');
}
else {
$section_prefix = $prefix;
}
$section_params['SectionPrefix'] = $section_prefix;
$section_params['url']['m_opener'] = 'r';
$section_params['url']['no_pass_through'] = 1;
$pass_section = getArrayValue($section_params, 'url', 'pass_section');
if ($pass_section) {
unset($section_params['url']['pass_section']);
$section_params['url']['section'] = $section_name;
if (!isset($section_params['url']['module'])) {
$module_name = $this->Application->findModule('Path', $config['ModuleFolder'].'/', 'Name');
$section_params['url']['module'] = $module_name;
}
}
if (!isset($section_params['url']['t'])) {
$section_params['url']['t'] = 'index';
}
if (!isset($section_params['onclick'])) {
$section_params['onclick'] = 'checkEditMode()';
}
if (!isset($section_params['container'])) {
$section_params['container'] = 0; // for js tree printing to xml
}
$current_data = isset($this->Tree[$section_name]) ? $this->Tree[$section_name] : Array();
if ($current_data) {
trigger_error('Section "<strong>' . $section_name . '</strong>" declaration (originally defined in "<strong>' . $current_data['SectionPrefix'] . '</strong>") was overwriten from "<strong>' . $prefix . '</strong>"', E_USER_NOTICE);
}
$this->Tree[$section_name] = array_merge_recursive2($current_data, $section_params);
}
}
/**
* Returns details information about section
*
* @param string $section_name
* @return Array
*/
function &getSectionData($section_name)
{
if (isset($this->Tree[$section_name])) {
$ret =& $this->Tree[$section_name];
}
else {
$ret = Array();
}
return $ret;
}
/**
* Returns first child, that is not a folder
*
* @param string $section_name
* @param Array $tree
* @return stirng
*/
function getFirstChild($section_name, $check_permission = false)
{
$section_data =& $this->getSectionData($section_name);
$children = isset($section_data['children']) && $section_data['children'] ? $section_data['children'] : false;
if ($children) {
// get 1st child
ksort($children, SORT_NUMERIC);
foreach ($children as $child_priority => $child_section) {
$section_data =& $this->getSectionData($child_section);
$perm_section = $this->getPermSection($child_section);
$perm_status = $check_permission ? $this->Application->CheckPermission($perm_section.'.view') : true;
if ((isset($section_data['show_mode']) && $section_data['show_mode']) || !$perm_status) {
continue;
}
break;
}
return $this->getFirstChild($child_section, $check_permission);
}
return $section_name;
}
/**
* Returns section for permission checking based on given section
*
* @param string $section_name
* @return string
*/
function getPermSection($section_name)
{
$ret = $section_name;
$section_data =& $this->getSectionData($section_name);
if ($section_data && isset($section_data['perm_prefix'])) {
// this section uses other section permissions
$ret = $this->Application->getUnitOption($section_data['perm_prefix'].'.main', 'PermSection');
}
return $ret;
}
}
\ No newline at end of file
Index: branches/5.1.x/core/units/modules/modules_event_handler.php
===================================================================
--- branches/5.1.x/core/units/modules/modules_event_handler.php (revision 13112)
+++ branches/5.1.x/core/units/modules/modules_event_handler.php (revision 13113)
@@ -1,187 +1,187 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class ModulesEventHandler extends kDBEventHandler {
/**
* Builds item
*
* @param kEvent $event
* @access protected
*/
function OnItemBuild(&$event)
{
$this->Application->SetVar($event->getPrefixSpecial(true).'_id', $event->Special);
parent::OnItemBuild($event);
}
/**
* List with one record if special passed
*
* @param kEvent $event
*/
function SetCustomQuery(&$event)
{
$object =& $event->getObject();
if ($event->Special) {
$object->addFilter('current_module', 'Name = '.$event->Special);
}
$object->addFilter('not_core', '%1$s.Name <> "Core"');
}
function mapEvents()
{
parent::mapEvents();
$this->eventMethods['OnMassApprove'] = 'moduleAction';
$this->eventMethods['OnMassDecline'] = 'moduleAction';
}
/**
* Disabled modules, but not In-Portal
*
* @param kEvent $event
*/
function moduleAction(&$event)
{
if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$event->status = erFAIL;
return ;
}
$object =& $event->getObject( Array('skip_autoload' => true) );
$ids = $this->StoreSelectedIDs($event);
if (!$ids) {
return true;
}
$status_field = array_shift( $this->Application->getUnitOption($event->Prefix, 'StatusField') );
foreach ($ids as $id) {
if (($event->Name == 'OnMassDecline') && ($id == 'In-Portal')) {
// don't allow to disable in-portal
continue;
}
if ($id == 'Core') {
// don't allow any kind of manupulations with kernel
continue;
}
$object->Load($id);
$object->SetDBField($status_field, $event->Name == 'OnMassApprove' ? 1 : 0);
if ($object->Update()) {
$sql = 'UPDATE ' . TABLE_PREFIX . 'ImportScripts
SET Status = ' . ($event->Name == 'OnMassApprove' ? STATUS_ACTIVE : STATUS_DISABLED) . '
WHERE Module = "' . $object->GetDBField('Name') . '"';
$this->Conn->Query($sql);
$event->status = erSUCCESS;
$event->redirect_params = Array('opener' => 's'); //stay!
}
else {
$event->status = erFAIL;
$event->redirect = false;
break;
}
}
$this->Application->UnitConfigReader->ResetParsedData(true); //true to reset sections cache also
$event->SetRedirectParam('RefreshTree', 1);
}
/**
* Occures after list is queried
*
* @param kEvent $event
*/
function OnAfterListQuery(&$event)
{
parent::OnAfterListQuery($event);
$new_modules = $this->_getNewModules();
if (!$new_modules || $this->Application->RecallVar('user_id') != -1) {
return ;
}
require_once FULL_PATH . '/core/install/install_toolkit.php';
$toolkit = new kInstallToolkit();
$object =& $event->getObject();
/* @var $object kDBList */
foreach ($new_modules as $module) {
$module_record = Array (
'Name' => $toolkit->getModuleName($module),
- 'Path' => $module . '/',
+ 'Path' => 'modules/' . $module . '/',
'Version' => $toolkit->GetMaxModuleVersion($module),
'Loaded' => 0,
'BuildDate' => null,
);
$object->addRecord($module_record);
}
}
/**
* Returns list of modules, that are not installed, but available in file system
*
* @return Array
*/
function _getNewModules()
{
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$modules = Array ();
if ($dir = @opendir(MODULES_PATH)) {
while (($file = readdir($dir)) !== false) {
if ($file != '.' && $file != '..') {
$module_folder = MODULES_PATH . '/' . $file;
if (is_dir($module_folder) && $this->_isModule($module_folder)) {
// this is module -> check if it's installed already
if (!$modules_helper->moduleInstalled($file)) {
$install_order = trim( file_get_contents($module_folder . '/install/install_order.txt') );
$modules[$install_order] = $file;
}
}
}
}
closedir($dir);
}
// allows to control module install order
ksort($modules, SORT_NUMERIC);
return $modules;
}
/**
* Checks, that given folder is module root folder
*
* @param string $folder
* @return bool
*/
function _isModule($folder)
{
return file_exists($folder . '/install.php') && file_exists($folder . '/install/install_schema.sql');
}
}
\ No newline at end of file
Index: branches/5.1.x/core/units/admin/admin_config.php
===================================================================
--- branches/5.1.x/core/units/admin/admin_config.php (revision 13112)
+++ branches/5.1.x/core/units/admin/admin_config.php (revision 13113)
@@ -1,99 +1,99 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
$config = Array (
'Prefix' => 'adm',
'ItemClass' => Array ('class' => 'kDBItem','file'=>'','build_event'=>'OnItemBuild'),
'EventHandlerClass' => Array ('class' => 'AdminEventsHandler', 'file' => 'admin_events_handler.php', 'build_event' => 'OnBuild'),
'TagProcessorClass' => Array ('class' => 'AdminTagProcessor', 'file' => 'admin_tag_processor.php', 'build_event' => 'OnBuild'),
'QueryString' => Array (
1 => 'event',
),
'TitlePresets' => Array (
'tree_root' => Array ('format' => '!la_section_overview!'),
'tree_reports' => Array ('format' => '!la_section_overview!'),
'tree_system' => Array ('format' => '!la_section_overview!'),
'tree_tools' => Array ('format' => '!la_section_overview!'),
'system_tools' => Array ('format' => '!la_title_SystemTools!'),
'backup' => Array ('format' => '!la_performing_backup! - !la_Step! <span id="step_number"></span>'),
'import' => Array ('format' => '!la_performing_import! - !la_Step! <span id="step_number"></span>'),
'restore' => Array ('format' => '!la_performing_restore! - !la_Step! <span id="step_number"></span>'),
'server_info' => Array ('format' => '!la_tab_ServerInfo!'),
'sql_query' => Array ('format' => '!la_tab_QueryDB!'),
'no_permissions' => Array ('format' => '!la_title_NoPermissions!'),
'column_picker' => Array ('format' => '!la_title_ColumnPicker!'),
'csv_export' => Array ('format' => '!la_title_CSVExport!'),
'csv_import' => Array ('format' => '!la_title_CSVImport!'),
),
'PermSection' => Array ('main' => 'in-portal:service'),
'Sections' => Array (
'in-portal:root' => Array (
'parent' => null,
'icon' => 'site',
'label' => $this->Application->ConfigValue('Site_Name'),
'url' => Array ('t' => 'index', 'pass' => 'm', 'pass_section' => true, 'no_amp' => 1),
'permissions' => Array ('advanced:admin_login', 'advanced:front_login'),
'priority' => 0,
'container' => true,
'type' => stTREE,
- 'icon_module' => 'in-portal',
+ 'icon_module' => 'core',
),
'in-portal:service' => Array (
'parent' => 'in-portal:tools',
'icon' => 'service',
'label' => 'la_tab_Service',
'url' => Array ('t' => 'tools/system_tools', 'pass' => 'm'),
'permissions' => Array ('view', 'edit'),
'priority' => 6,
'type' => stTREE,
),
),
'ListSQLs' => Array (
'' => '', // to prevent warning
),
'Fields' => Array (), // we need empty array because kernel doesn't use virtual fields else
'VirtualFields' => Array (
'ImportFile' => Array (
'type' => 'string',
'formatter' => 'kUploadFormatter', 'max_size' => MAX_UPLOAD_SIZE, // in Bytes !
'error_msgs' => Array (
'cant_open_file' => '!la_error_CantOpenFile!',
'no_matching_columns' => '!la_error_NoMatchingColumns!',
),
'file_types' => '*.csv', 'files_description' => '!la_hint_CSVFiles!',
'upload_dir' => '/system/import/', // relative to project's home
'multiple' => false, 'direct_links' => false,
'default' => null,
),
'Content' => Array ('type' => 'string', 'default' => ''),
),
);
Index: branches/5.1.x/core/admin_templates/js/catalog.js
===================================================================
--- branches/5.1.x/core/admin_templates/js/catalog.js (revision 13112)
+++ branches/5.1.x/core/admin_templates/js/catalog.js (revision 13113)
@@ -1,450 +1,450 @@
function Catalog($url_mask, $cookie_prefix, $type) {
this.type = $type;
this.CookiePrefix = $cookie_prefix ? $cookie_prefix : '';
this.BusyRequest = new Array();
this.URLMask = $url_mask;
this.Separator = '#separator#';
this.ParentCategoryID = 0;
this.OnResponceMethod = null;
this.TabRegistry = new Array();
if (window.location.hash && window.location.hash.match(/^#tab-(.*)/)) {
// get active tab from anchor
this.ActivePrefix = RegExp.$1;
}
else {
// get active tab from cookie
this.ActivePrefix = getCookie(this.CookiePrefix + 'active_prefix');
}
this.PreviousPrefix = this.ActivePrefix;
this.TabByCategory = false; // preselect tab by category (used in catalog only)
$ViewMenus = new Array('c');
this.searchInfo = {}; // information about search (for each tab)
}
Catalog.prototype.Init = function ($auto_hide_tabs) {
var $prefix = this.queryTabRegistry('prefix', this.ActivePrefix, 'prefix');
if ($prefix !== this.ActivePrefix && this.TabRegistry.length > 0) {
// ActivePrefix not set or has non-existing prefix value
this.ActivePrefix = this.TabRegistry[0]['prefix'];
}
if ($auto_hide_tabs === undefined) {
$auto_hide_tabs = true;
}
if ((this.TabRegistry.length == 1) && $auto_hide_tabs) {
// only one tab -> hide all tab bar
$('div.tab-viewport').parents('table:first').hide();
}
this.SetAlternativeTabs();
this.AfterInit();
}
Catalog.prototype.AfterInit = function () {
this.go_to_cat();
}
Catalog.prototype.SetAlternativeTabs = function () {
// set alternative grids between all items (catalog is set when tab is loaded via AJAX first time)
var $i = 0;
while ($i < this.TabRegistry.length) {
// run through all prefixes
var $j = 0;
while ($j < this.TabRegistry.length) {
if (this.TabRegistry[$i]['prefix'] == this.TabRegistry[$j]['prefix']) {
$j++;
continue;
}
// and set alternative to all other prefixes
$GridManager.AddAlternativeGrid(this.TabRegistry[$i]['prefix'], this.TabRegistry[$j]['prefix']);
$j++;
}
$i++;
}
}
Catalog.prototype.submit_kernel_form = function($tab_id) {
var $prefix = 'dummy';
var $result_div = '';
if (isset($tab_id)) {
// responce result + progress are required
$prefix = this.queryTabRegistry('tab_id', $tab_id, 'prefix');
$result_div = $tab_id + '_div';
}
var $kf = document.getElementById($form_name);
Request.params = Request.serializeForm($kf);
Request.method = $kf.method.toUpperCase();
this.BusyRequest[$prefix] = false;
Request.makeRequest($kf.action, this.BusyRequest[$prefix], $result_div, this.successCallback, this.errorCallback, $result_div, this);
$form_name = 'kernel_form'; // restore back to main form with current category id of catalog
}
Catalog.prototype.successCallback = function($request, $params, $object) {
if (Request.processRedirect($request)) {
return ;
}
var $text = $request.responseText;
$params = $params.split(',');
var $js_end = $text.indexOf($object.Separator);
if ($js_end != -1) {
// allow to detect if output is permitted by ajax request parameters
var $request_visible = '$request_visible = ' + ($params[0].length ? 'true' : 'false') + "\n";
if ($params[0].length) {
// document.getElementById($params[0]).innerHTML = $text.substring($js_end + $object.Separator.length);
$( document.getElementById($params[0]) ).html( $text.substring($js_end + $object.Separator.length) );
eval($request_visible + $text.substring(0, $js_end));
}
else {
// eval JS only & set mark that js should not use HTML as usual in grids
eval($request_visible + $text.substring(0, $js_end));
}
}
else if ($params[0].length) {
document.getElementById($params[0]).innerHTML = $text;
}
-
+
// pass catalog object and loaded tab name to event handler
$('body').trigger('CatalogTabLoad', [$object, $params[0].replace(/_div$/, '')]);
-
+
if (typeof($object.OnResponceMethod) == 'function') {
$object.OnResponceMethod($object);
$object.OnResponceMethod = null;
}
if (typeof($Debugger) != 'undefined') {
$Debugger.Clear();
}
// var $tab_id = $params[0].replace(/_div$/, '');
// var $prefix = $object.queryTabRegistry('tab_id', $tab_id, 'prefix');
}
Catalog.prototype.resizeGrid = function ($prefix) {
if ($prefix != this.ActivePrefix) {
// no need to resize, because grid is already visible
return true;
}
var $grid = GridScrollers[$prefix];
if ($grid) {
$grid.RefreshPos();
$grid.Resize( $grid.GetAutoSize('auto') );
return true;
}
return false;
}
Catalog.prototype.trim = function ($string) {
return $string.replace(/\s*((\S+\s*)*)/, "$1").replace(/((\s*\S+)*)\s*/, "$1");
}
Catalog.prototype.errorCallback = function($request, $params, $object) {
// $Debugger.ShowProps($request, 'req');
alert('AJAX Error; class: Catalog; ' + Request.getErrorHtml($request));
}
Catalog.prototype.submit_event = function($prefix_special, $event, $t, $OnResponceMethod) {
if (typeof($OnResponceMethod) == 'function') {
this.OnResponceMethod = $OnResponceMethod;
}
var $prev_template = get_hidden_field('t');
if (!isset($prefix_special)) $prefix_special = this.getCurrentPrefix();
var $tab_id = this.queryTabRegistry('prefix', $prefix_special, 'tab_id');
$form_name = $tab_id + '_form'; // set firstly, because set_hidden_field uses it
if (isset($event)) set_hidden_field('events[' + $prefix_special + ']', $event);
if (isset($t)) set_hidden_field('t', $t);
this.submit_kernel_form($tab_id);
set_hidden_field('t', $prev_template);
}
Catalog.prototype.go_to_cat = function($cat_id, $module_prefix) {
if (!isset($cat_id)) {
// gets current category
$cat_id = get_hidden_field('m_cat_id');
}
else {
// sets new category to kernel_form in case if item tab
// loads faster and will check if it's category is same
// as parent category of categories list
if (get_hidden_field('m_cat_id') == $cat_id) {
// it's the same category, then don't reload category list
return ;
}
set_hidden_field('m_cat_id', $cat_id);
}
// 1. make all tabs unselected
this.resetTabs(false);
// 2. update grid for current tab
this.switchTab(this.TabByCategory ? $module_prefix : null); // refresh current item tab
// 3. update counters for all tabs
var $prefix = this.TabRegistry[0]['prefix'];
var $url = this.URLMask.replace('#TEMPLATE_NAME#', 'catalog/catalog_counters').replace('#CATEGORY_ID#', $cat_id);
this.BusyRequest[$prefix] = false;
Request.makeRequest($url, this.BusyRequest[$prefix], '', this.updateCounters, this.errorCallback, '', this);
}
Catalog.prototype.updateCounters = function($request, $params, $object) {
if (Request.processRedirect($request)) {
return ;
}
eval($request.responseText);
}
// set all item tabs counters to "?" before quering catagories
Catalog.prototype.resetTabs = function($reset_content) {
var $i = 0;
while ($i < this.TabRegistry.length) {
this.setItemCount(this.TabRegistry[$i]['prefix'], '?');
$i++;
}
if ($reset_content) {
// set category for all tabs to -1 (forces reload next time)
$i = 0;
while ($i < this.TabRegistry.length) {
document.getElementById(this.TabRegistry[$i]['tab_id'] + '_div').setAttribute('category_id', -1);
$i++;
}
}
}
Catalog.prototype.switchTab = function($prefix, $force) {
if (this.queryTabRegistry('prefix', this.ActivePrefix, 'prefix') != this.ActivePrefix) {
// active prefix is not registred -> cookie left, but not modules installed/enabled at the moment
return false;
}
if (!isset($prefix) || $prefix == '' || this.queryTabRegistry('prefix', $prefix, 'prefix') === false) {
// prefix not given OR empty prefix OR non-existing tab
$prefix = this.ActivePrefix;
}
if (this.BusyRequest[$prefix]) {
alert('prefix: ['+$prefix+']; request busy: ['+this.BusyRequest[$prefix]+']');
}
if (this.ActivePrefix != $prefix) {
// hide source tab
this.PreviousPrefix = this.ActivePrefix;
$( jq('#' + this.PreviousPrefix + '_tab') ).removeClass('tab-active');
var $prev_div_id = this.queryTabRegistry('prefix', this.PreviousPrefix, 'tab_id') + '_div';
document.getElementById($prev_div_id).style.display = 'none';
var $prev_div_container = $( jq('#' + $prev_div_id + '_container') );
if ($prev_div_container.length) {
$prev_div_container.hide();
}
this.HideDependentButtons(this.PreviousPrefix);
}
// show destination tab
this.ActivePrefix = $prefix;
$( jq('#' + this.ActivePrefix + '_tab') ).addClass('tab-active');
var $div_id = this.queryTabRegistry('prefix', this.ActivePrefix, 'tab_id') + '_div'; // destination tab
document.getElementById($div_id).style.display = 'block';
var $div_container = $( jq('#' + $div_id + '_container') );
if ($div_container.length) {
$div_container.show();
}
this.ShowDependentButtons(this.ActivePrefix);
this.displaySearch($prefix);
this.setViewMenu(this.ActivePrefix);
setCookie(this.CookiePrefix + 'active_prefix', this.ActivePrefix);
window.location.hash = '#tab-' + this.ActivePrefix;
this.refreshTab($prefix, $div_id, $force);
}
Catalog.prototype.refreshTab = function($prefix, $div_id, $force) {
var $cat_id = get_hidden_field('m_cat_id');
var $tab_cat_id = document.getElementById($div_id).getAttribute('category_id');
if ($cat_id != $tab_cat_id || $force) {
// query tab content only in case if not queried or category don't match
var $url = this.URLMask.replace('#TEMPLATE_NAME#', this.queryTabRegistry('prefix', $prefix, 'view_template'));
$url = $url.replace('#CATEGORY_ID#', $cat_id);
$url = $url.replace('#PREFIX#', $prefix);
this.BusyRequest[$prefix] = false;
Request.makeRequest($url, this.BusyRequest[$prefix], $div_id, this.successCallback, this.errorCallback, $div_id, this);
}
else {
// alert('refresh disabled = {tab: '+this.ActivePrefix+'; cat_id: '+$cat_id+'; form_name: '+$form_name+'}');
this.resizeGrid($prefix);
}
}
// adds information about tab to tab_registry
Catalog.prototype.registerTab = function($tab_id) {
var $tab = document.getElementById($tab_id + '_div');
var $index = this.TabRegistry.length;
this.TabRegistry[$index] = new Array();
this.TabRegistry[$index]['tab_id'] = $tab_id;
this.TabRegistry[$index]['prefix'] = $tab.getAttribute('prefix');
if ($tab_id == 'categories') {
this.TabRegistry[$index]['module_path'] = 'in-portal/';
}
else {
this.TabRegistry[$index]['module_path'] = $tab.getAttribute('edit_template').substring(0, $tab.getAttribute('edit_template').indexOf('/'));
}
this.TabRegistry[$index]['view_template'] = $tab.getAttribute('view_template');
this.TabRegistry[$index]['edit_template'] = $tab.getAttribute('edit_template');
this.TabRegistry[$index]['dep_buttons'] = $tab.getAttribute('dep_buttons').length > 0 ? $tab.getAttribute('dep_buttons').split(',') : new Array();
this.TabRegistry[$index]['index'] = $index;
}
// allows to get any information about tab
Catalog.prototype.queryTabRegistry = function($search_key, $search_value, $return_key) {
var $i = 0;
// alert('looking in '+$search_key+' for '+$search_value+' will return '+$return_key)
while ($i < this.TabRegistry.length) {
if (this.TabRegistry[$i][$search_key] == $search_value) {
// alert('got '+this.TabRegistry[$i][$return_key])
return this.TabRegistry[$i][$return_key];
break;
}
$i++;
}
return false;
}
Catalog.prototype.ShowDependentButtons = function($prefix) {
/*var $tab_id = this.queryTabRegistry('prefix', $prefix, 'tab_id')
if (!document.getElementById($tab_id + '_form')) {
// tab form not found => no permission to view -> no permission to do any actions
alert('no form: ['+$tab_id + '_form'+']');
return ;
}
else {
alert('has form: ['+$tab_id + '_form'+']');
}*/
var $dep_buttons = this.queryTabRegistry('prefix', $prefix, 'dep_buttons');
var $i = 0;
while ($i < $dep_buttons.length) {
a_toolbar.ShowButton($dep_buttons[$i]);
$i++;
}
}
Catalog.prototype.HideDependentButtons = function($prefix) {
var $dep_buttons = this.queryTabRegistry('prefix', $prefix, 'dep_buttons');
var $i = 0;
while ($i < $dep_buttons.length) {
a_toolbar.HideButton($dep_buttons[$i]);
$i++;
}
}
Catalog.prototype.setItemCount = function($prefix, $count) {
setInnerHTML($prefix + '_item_count', $count);
}
Catalog.prototype.saveSearch = function ($prefix, $keyword, $grid_name) {
this.searchInfo[$prefix] = {
'keyword': $keyword,
'grid': $grid_name
}
this.displaySearch($prefix);
}
Catalog.prototype.displaySearch = function ($prefix) {
var $search_input = $('#search_keyword');
$search_input.attr('PrefixSpecial', $prefix);
if (this.searchInfo[$prefix]) {
$search_input
.val(this.searchInfo[$prefix].keyword)
.attr('Grid', this.searchInfo[$prefix].grid);
if (this.searchInfo[$prefix].keyword) {
// catalog tab found and keyword present
$search_input.addClass('filter-active');
}
else {
// catalog tab found and keyword missing
$search_input.removeClass('filter-active');
}
}
else {
// catalog tab not found
$search_input.removeClass('filter-active');
}
}
Catalog.prototype.setCurrentCategory = function($prefix, $category_id) {
var $tab_id = this.queryTabRegistry('prefix', $prefix, 'tab_id');
// alert('setting current category for prefix: ['+$prefix+']; tab_id ['+$tab_id+'] = ['+$category_id+']');
document.getElementById($tab_id + '_div').setAttribute('category_id', $category_id);
}
Catalog.prototype.getCurrentPrefix = function() {
return this.ActivePrefix;
}
Catalog.prototype.setViewMenu = function($item_prefix) {
$ViewMenus = isset($item_prefix) ? new Array($item_prefix) : new Array();
}
Catalog.prototype.reflectPasteButton = function($status) {
a_toolbar.SetEnabled('paste', $status);
a_toolbar.SetEnabled('clear_clipboard', $status);
}
Catalog.prototype.storeIDs = function ($category_variable) {
if ($category_variable) {
var $category_ids = '';
if (Grids['c'] != undefined) {
$category_ids = Grids['c'].GetSelected().join(',');
}
if (!$category_ids) {
$category_ids = get_hidden_field('m_cat_id'); // current category
}
set_hidden_field($category_variable, $category_ids);
}
// get selectes category items
for (var $i in Grids[this.ActivePrefix].Items) {
if (Grids[this.ActivePrefix].Items[$i].selected) {
set_hidden_field(Grids[this.ActivePrefix].Items[$i].CheckBox.id, 'on', false);
}
}
}
\ No newline at end of file
Index: branches/5.1.x/core/admin_templates/js/toolbar.js
===================================================================
--- branches/5.1.x/core/admin_templates/js/toolbar.js (revision 13112)
+++ branches/5.1.x/core/admin_templates/js/toolbar.js (revision 13113)
@@ -1,378 +1,374 @@
function ToolBarButton(title, alt, onclick, $hidden, prefix)
{
this.Title = title || '';
this.TranslateLink = false;
this.CheckTitleModule();
this.Alt = RemoveTranslationLink(alt || '');
if (this.Alt != alt) {
this.TranslateLink = alt || '';
this.TranslateLink = this.TranslateLink.replace(/&lt;a href=&quot;(.*?)&quot;&gt;(.*?)&lt;\/a&gt;/g, '$1');
}
if (this.Alt.match(/(.*)::(.*)/)) {
this.Alt = RegExp.$1;
this.Label = RegExp.$2
}
else {
this.Label = this.Alt;
}
if (typeof(onclick) == 'function') {
this.onClick = onclick;
}
else {
this.onClick = function() {
if (eval('typeof('+this.Title+')') == 'function')
eval(this.Title + '()');
}
}
this.imgObject = null;
this.Enabled = true;
this.Hidden = $hidden ? true : false;
this.ToolBar = null;
this.Prefix = prefix ? prefix : '';
this.Separator = false;
}
ToolBarButton.prototype.CheckTitleModule = function()
{
if (this.Title.match(/([^:]+):(.*)$/)) {
// has module set directly
this.Title = RegExp.$2;
- this.Module = RegExp.$1;
+ this.Module = RegExp.$1.toLowerCase();
+
if (this.Module == 'in-portal') {
- this.Module = 'kernel';
+ this.Module = 'core';
}
}
else {
// use default module
this.Module = 'core';
}
}
ToolBarButton.prototype.IconsPath = function()
{
if (typeof(img_path) == 'undefined') {
//alert('error: toolbar image path not set');
}
- return img_path.replace('#MODULE#', this.Module) + 'toolbar/';
+
+ var $module_path = this.Module;
+
+ if (this.Module != 'core') {
+ $module_path = 'modules/' + $module_path;
+ }
+
+ return img_path.replace('#MODULE#', $module_path) + 'toolbar/';
}
ToolBarButton.prototype.GetHTML = function() {
var add_style = this.ToolBar.ButtonStyle ? 'style="'+this.ToolBar.ButtonStyle+'"' : '';
var o = '<div class="toolbar-button" id="'+this.GetToolID('div')+'" '+add_style+'>'
o += '<img id="' + this.GetToolID() + '" width="'+this.ToolBar.IconSize.w+'" height="'+this.ToolBar.IconSize.h+'" src="' + this.IconsPath() + this.ToolBar.IconPrefix + this.Title + '.gif" title="' + this.Alt + '&nbsp;">';
if (this.ToolBar.UseLabels) o += '<br/>'+this.Label;
o += '</div>'
return o;
}
ToolBarButton.prototype.GetToolID = function(item) {
if (!item) item = 'tool'
return this.Prefix == '' ? item+'_' + this.Title : item+'_['+this.Prefix+'][' + this.Title+']'
}
ToolBarButton.prototype.Init = function() {
img = document.getElementById(this.GetToolID());
this.imgObject = img;
this.Container = document.getElementById(this.GetToolID('div')) ? document.getElementById(this.GetToolID('div')) : false;
this.Container.btn = this;
img.btn = this;
this.MouseOverImg = new Image();
this.MouseOverImg.src = this.IconsPath() + this.ToolBar.IconPrefix + this.Title + '_f2.gif';
this.MouseOutImg = new Image();
this.MouseOutImg.src = this.IconsPath() + this.ToolBar.IconPrefix + this.Title + '.gif';
this.SetOnMouseOver();
this.SetOnMouseOut();
this.SetOnClick();
this.SetOnRightClick()
if (this.Hidden) this.Hide();
-
- if (!img.complete) {
- var real_path = img_path.replace('#MODULE#', this.Module) + 'toolbar/';
- var old_path = img_path.replace('#MODULE#', 'kernel') + 'toolbar/'+this.ToolBar.IconPrefix + this.Title+'.gif';
- real_path = real_path.replace('http://kostja.prod.intechnic.lv/in-portal.RC', '.');
- old_path = old_path.replace('http://kostja.prod.intechnic.lv/in-portal.RC', '.');
- var source = old_path.replace('/core/', '/kernel/').replace('.gif', '*.gif');
- var path = 'cp '+source+' '+real_path;
-// prompt('exec: ', path)
-// img.src = 'img/bad_button.GIF';
- }
-// preg_print_pre(img, /natural|compl/i)
}
ToolBarButton.prototype.EditTitle = function() {
if (this.TranslateLink !== false) {
var $links = this.TranslateLink;
$links = $links.split('::');
var $i = 0;
while ($i < $links.length) {
var $link = $links[$i];
if ($link.match(/(javascript:|http:\/\/)(.*)/)) {
var $link_type = RegExp.$1;
$link = RegExp.$2.replace(/&#[0]{0,1}39;/g, '"');
if ($link_type == 'javascript:') {
eval($link);
}
else {
window.location.href = 'http://' + $link;
}
// edit one phrase at a time
break;
}
$i++;
}
return false;
}
return true;
}
ToolBarButton.prototype.SetOnMouseOver = function() {
this.Container.onmouseover = function() {
this.btn.imgObject.src = this.btn.MouseOverImg.src;
this.className = 'toolbar-button-over';
};
}
ToolBarButton.prototype.SetOnMouseOut = function() {
this.Container.onmouseout = function() {
this.btn.imgObject.src = this.btn.MouseOutImg.src;
this.className = 'toolbar-button';
};
}
ToolBarButton.prototype.SetOnClick = function() {
// we have SetOnMouseOut for this ???
/*this.Container.onmouseout = function() {
this.btn.imgObject.src = this.btn.IconsPath() + this.btn.ToolBar.IconPrefix + this.btn.Title + '.gif';
};*/
this.Container.inClick = false;
if (typeof(this.onClick) != 'function') {
this.Container.onclick = function() {
if (this.inClick) return;
this.inClick = true;
if (eval('typeof('+this.btn.Title+')') == 'function')
eval(this.btn.Title + '()');
this.inClick = false;
}
}
else {
this.Container.onclick = function() {
if (this.inClick) return;
this.inClick = true;
this.btn.onClick();
this.inClick = false;
}
}
// the following lines are correct, as long as mozilla understands 'pointer', but IE 'hand',
// do not change the order of these lines!
if (is.ie6up || is.gecko) {
this.Container.style.cursor = 'pointer';
}
else {
// somehow set cursor hand for IE 5/ 5.5
// this.imgObject.style = 'cursor: hand';
}
}
ToolBarButton.prototype.SetOnRightClick = function() {
this.Container.oncontextmenu = function() {
return this.btn.EditTitle();
}
}
ToolBarButton.prototype.Disable = function() {
if ( !this.Enabled ) return;
if (typeof(this.DisabledImg) == 'undefined') {
this.DisabledImg = new Image();
this.DisabledImg.src = this.IconsPath() + this.ToolBar.IconPrefix + this.Title + '_f3.gif';
}
this.imgObject.src = this.DisabledImg.src;
this.Container.onmouseover = null;
this.Container.onmouseout = null;
this.Container.onclick = null;
this.Container.style.cursor = 'default';
this.Enabled = false;
this.Container.className = 'toolbar-button-disabled'
}
ToolBarButton.prototype.Enable = function() {
if (this.Enabled) return;
this.imgObject.src = this.MouseOutImg.src;
this.SetOnMouseOver();
this.SetOnMouseOut();
this.SetOnClick();
this.Enabled = true;
this.Container.className = 'toolbar-button'
}
ToolBarButton.prototype.Hide = function() {
this.Container.style.display = 'none';
this.Hidden = true;
}
ToolBarButton.prototype.Show = function() {
this.Container.style.display = '';
this.Hidden = false;
}
/* ----------- */
function ToolBarSeparator(title, $hidden) //extends ToolBarButton
{
this.Title = title;
this.Hidden = $hidden ? true : false;
this.Separator = true;
}
ToolBarSeparator.prototype = new ToolBarButton;
ToolBarSeparator.prototype.GetHTML = function() {
var add_style = this.ToolBar.ButtonStyle ? 'style="'+this.ToolBar.ButtonStyle+'"' : '';
var padding = this.ToolBar.UseLabels ? '12px' : '2px'
return '<div id="'+this.GetToolID('div')+'" class="toolbar-button" style="padding-top: '+padding+'; height: 32px;" '+add_style+'><img id="' + this.GetToolID() + '" src="' + this.IconsPath() + 'tool_divider.gif"></div>';
var add_style = this.ToolBar.ButtonStyle ? 'style="'+this.ToolBar.ButtonStyle+'"' : '';
return '<div id="'+this.GetToolID('div')+'" class="toolbar-button" style="border: 1px solid black; height: 100%;" '+add_style+'><img id="' + this.GetToolID() + '" src="' + this.IconsPath() + 'tool_divider.gif"></div>';
}
ToolBarSeparator.prototype.Init = function() {
img = document.getElementById(this.ToolBar.IconPrefix + this.Title);
this.Container = document.getElementById(this.GetToolID('div')) ? document.getElementById(this.GetToolID('div')) : false;
this.imgObject = img;
img.btn = this;
if (this.Hidden) {
this.Hide();
}
}
ToolBarSeparator.prototype.Enable = function() { }
ToolBarSeparator.prototype.Disable = function() { }
/* ----------- */
function ToolBarMarkup(title, html) //extends ToolBarButton
{
this.Title = title;
this.HTML = html;
}
ToolBarMarkup.prototype = new ToolBarButton;
ToolBarMarkup.prototype.GetHTML = function() {
return this.HTML;
}
ToolBarMarkup.prototype.Init = function() { }
ToolBarMarkup.prototype.Enable = function() { }
ToolBarMarkup.prototype.Disable = function() { }
/* ----------- */
function ToolBar(icon_prefix, $module)
{
this.Module = $module ? $module : 'core';
this.IconPrefix = icon_prefix ? icon_prefix : 'tool_';
this.IconSize = {w:32,h:32};
this.Buttons = {};
this.UseLabels = typeof($use_toolbarlabels) != 'undefined' ? $use_toolbarlabels : false;
}
ToolBar.prototype.AddButton = function(a_button)
{
if ($visible_toolbar_buttons === true || in_array(a_button.Title, $visible_toolbar_buttons) || a_button.Separator) {
a_button.ToolBar = this;
this.Buttons[a_button.Title] = a_button;
}
}
ToolBar.prototype._removeSeparators = function()
{
// TODO: find a way to cut first and last separators from non-indexed array, like $new_buttons.
var $separator = false;
var $new_buttons = {};
for (var $button_title in this.Buttons) {
if ($separator && this.Buttons[$button_title].Separator) {
continue;
}
$separator = this.Buttons[$button_title].Separator;
$new_buttons[$button_title] = this.Buttons[$button_title];
}
this.Buttons = $new_buttons;
}
ToolBar.prototype.Render = function($container)
{
// remove duplicate separators or separators at the end of button list
this._removeSeparators();
if ($container) {
var tmp = '';
for (var i in this.Buttons) {
btn = this.Buttons[i];
tmp += btn.GetHTML();
}
$container.innerHTML = tmp; // container will contain only buttons
// init all buttons after because objects are not yet created directly after assigning to innerHTML
for (var i in this.Buttons) {
btn = this.Buttons[i];
btn.Init();
}
}
else {
for (var i in this.Buttons) {
btn = this.Buttons[i];
document.write( btn.GetHTML() );
btn.Init();
}
}
}
ToolBar.prototype.EnableButton = function(button_id) {
if(this.ButtonExists(button_id)) this.Buttons[button_id].Enable();
}
ToolBar.prototype.DisableButton = function(button_id) {
if(this.ButtonExists(button_id)) this.Buttons[button_id].Disable();
}
ToolBar.prototype.HideButton = function(button_id) {
if(this.ButtonExists(button_id)) this.Buttons[button_id].Hide();
}
ToolBar.prototype.ShowButton = function(button_id) {
if(this.ButtonExists(button_id)) this.Buttons[button_id].Show();
}
ToolBar.prototype.SetEnabled = function(button_id, $enabled) {
var $ret = $enabled ? this.EnableButton(button_id) : this.DisableButton(button_id);
}
ToolBar.prototype.SetVisible = function(button_id, $visible) {
var $ret = $visible ? this.ShowButton(button_id) : this.HideButton(button_id);
}
ToolBar.prototype.GetButtonImage = function(button_id) {
if( this.ButtonExists(button_id) ) return this.Buttons[button_id].imgObject;
}
ToolBar.prototype.ButtonExists = function(button_id) {
return typeof(this.Buttons[button_id]) == 'object';
}
Index: branches/5.1.x/core/install/install_toolkit.php
===================================================================
--- branches/5.1.x/core/install/install_toolkit.php (revision 13112)
+++ branches/5.1.x/core/install/install_toolkit.php (revision 13113)
@@ -1,866 +1,866 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
/**
* Upgrade sqls are located using this mask
*
*/
define('UPGRADES_FILE', FULL_PATH.'/%sinstall/upgrades.%s');
/**
* Prerequisit check classes are located using this mask
*
*/
define('PREREQUISITE_FILE', FULL_PATH.'/%sinstall/prerequisites.php');
/**
* Format of version identificator in upgrade files (normal, beta, release candidate)
*
*/
define('VERSION_MARK', '# ===== v ([\d]+\.[\d]+\.[\d]+|[\d]+\.[\d]+\.[\d]+-B[\d]+|[\d]+\.[\d]+\.[\d]+-RC[\d]+) =====');
if (!defined('GET_LICENSE_URL')) {
/**
* Url used for retrieving user licenses from Intechnic licensing server
*
*/
define('GET_LICENSE_URL', 'http://www.intechnic.com/myaccount/license.php');
}
/**
* Misc functions, that are required during installation, when
*
*/
class kInstallToolkit {
/**
* Reference to kApplication class object
*
* @var kApplication
*/
var $Application = null;
/**
* Connection to database
*
* @var kDBConnection
*/
var $Conn = null;
/**
* Path to config.php
*
* @var string
*/
var $INIFile = '';
/**
* Parsed data from config.php
*
* @var Array
*/
var $systemConfig = Array ();
/**
* Installator instance
*
* @var kInstallator
*/
var $_installator = null;
function kInstallToolkit()
{
if (class_exists('kApplication')) {
// auto-setup in case of separate module install
$this->Application =& kApplication::Instance();
$this->Conn =& $this->Application->GetADODBConnection();
}
$this->INIFile = FULL_PATH . DIRECTORY_SEPARATOR . 'config.php';
$this->systemConfig = $this->ParseConfig(true);
}
/**
* Sets installator
*
* @param kInstallator $instance
*/
function setInstallator(&$instance)
{
$this->_installator =& $instance;
}
/**
* Checks prerequisities before module install or upgrade
*
* @param string $module_path
* @param string $versions
* @param string $mode upgrade mode = {install, standalone, upgrade}
*/
function CheckPrerequisites($module_path, $versions, $mode)
{
static $prerequisit_classes = Array ();
$prerequisites_file = sprintf(PREREQUISITE_FILE, $module_path);
if (!file_exists($prerequisites_file) || !$versions) {
return Array ();
}
if (!isset($prerequisit_classes[$module_path])) {
// save class name, because 2nd time
// (in after call $prerequisite_class variable will not be present)
include_once $prerequisites_file;
$prerequisit_classes[$module_path] = $prerequisite_class;
}
$prerequisite_object = new $prerequisit_classes[$module_path]();
if (method_exists($prerequisite_object, 'setToolkit')) {
$prerequisite_object->setToolkit($this);
}
// some errors possible
return $prerequisite_object->CheckPrerequisites($versions, $mode);
}
/**
* Processes one license, received from server
*
* @param string $file_data
*/
function processLicense($file_data)
{
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$file_data = explode('Code==:', $file_data);
$file_data[0] = str_replace('In-Portal License File - do not edit!' . "\n", '', $file_data[0]);
$file_data = array_map('trim', $file_data);
if ($modules_helper->verifyLicense($file_data[0])) {
$this->setSystemConfig('Intechnic', 'License', $file_data[0]);
if (array_key_exists(1, $file_data)) {
$this->setSystemConfig('Intechnic', 'LicenseCode', $file_data[1]);
}
else {
$this->setSystemConfig('Intechnic', 'LicenseCode');
}
$this->SaveConfig();
}
else {
// invalid license received from licensing server
$this->_installator->errorMessage = 'Invalid License File';
}
}
/**
* Saves given configuration values to database
*
* @param Array $config
*/
function saveConfigValues($config)
{
foreach ($config as $config_var => $value) {
$sql = 'UPDATE ' . TABLE_PREFIX . 'ConfigurationValues
SET VariableValue = ' . $this->Conn->qstr($value) . '
WHERE VariableName = ' . $this->Conn->qstr($config_var);
$this->Conn->Query($sql);
}
}
/**
* Sets module version to passed
*
* @param string $module_name
* @param string $version
*/
function SetModuleVersion($module_name, $version = false)
{
if ($version === false) {
$version = $this->GetMaxModuleVersion($module_name);
}
// get table prefix from config, because application may not be available here
$table_prefix = $this->getSystemConfig('Database', 'TablePrefix');
if ($module_name == 'kernel') {
$module_name = 'in-portal';
}
// don't use "adodb_mktime" here, because it's not yet included
$sql = 'UPDATE ' . $table_prefix . 'Modules
SET Version = "' . $version . '", BuildDate = ' . time() . '
WHERE LOWER(Name) = "' . strtolower($module_name) . '"';
$this->Conn->Query($sql);
}
/**
* Sets module root category to passed
*
* @param string $module_name
* @param string $category_id
*/
function SetModuleRootCategory($module_name, $category_id = 0)
{
// get table prefix from config, because application may not be available here
$table_prefix = $this->getSystemConfig('Database', 'TablePrefix');
if ($module_name == 'kernel') {
$module_name = 'in-portal';
}
$sql = 'UPDATE ' . $table_prefix . 'Modules
SET RootCat = ' . $category_id . '
WHERE LOWER(Name) = "' . strtolower($module_name) . '"';
$this->Conn->Query($sql);
}
/**
* Returns maximal version of given module by scanning it's upgrade scripts
*
* @param string $module_name
* @return string
*/
function GetMaxModuleVersion($module_name)
{
$upgrades_file = sprintf(UPGRADES_FILE, mb_strtolower($module_name).'/', 'sql');
if (!file_exists($upgrades_file)) {
// no upgrade file
- return '4.0.1';
+ return '5.0.0';
}
$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
- return '4.0.1';
+ return '5.0.0';
}
return end($regs[1]);
}
/**
* Runs SQLs from file
*
* @param string $filename
* @param mixed $replace_from
* @param mixed $replace_to
*/
function RunSQL($filename, $replace_from = null, $replace_to = null)
{
if (!file_exists(FULL_PATH.$filename)) {
return ;
}
$sqls = file_get_contents(FULL_PATH.$filename);
if (!$this->RunSQLText($sqls, $replace_from, $replace_to)) {
if (is_object($this->_installator)) {
$this->_installator->Done();
}
else {
if (isset($this->Application)) {
$this->Application->Done();
}
exit;
}
}
}
/**
* Runs SQLs from string
*
* @param string $sqls
* @param mixed $replace_from
* @param mixed $replace_to
*/
function RunSQLText(&$sqls, $replace_from = null, $replace_to = null, $start_from=0)
{
$table_prefix = $this->getSystemConfig('Database', 'TablePrefix');
// add prefix to all tables
if (strlen($table_prefix) > 0) {
$replacements = Array ('INSERT INTO ', 'UPDATE ', 'ALTER TABLE ', 'DELETE FROM ', 'REPLACE INTO ');
foreach ($replacements as $replacement) {
$sqls = str_replace($replacement, $replacement . $table_prefix, $sqls);
}
}
$sqls = str_replace('CREATE TABLE ', 'CREATE TABLE IF NOT EXISTS ' . $table_prefix, $sqls);
$sqls = str_replace('DROP TABLE ', 'DROP TABLE IF EXISTS ' . $table_prefix, $sqls);
$sqls = str_replace('<%TABLE_PREFIX%>', $table_prefix, $sqls);
if (isset($replace_from) && isset($replace_to)) {
// replace something additionally, e.g. module root category
$sqls = str_replace($replace_from, $replace_to, $sqls);
}
$sqls = str_replace("\r\n", "\n", $sqls); // convert to linux line endings
$no_comment_sqls = preg_replace("/#\s([^;]*?)\n/is", '', $sqls); // remove all comments "#" on new lines
if ($no_comment_sqls === null) {
// "ini.pcre.backtrack-limit" reached and error happened
$sqls = explode(";\n", $sqls . "\n"); // ensures that last sql won't have ";" in it
$sqls = array_map('trim', $sqls);
// remove all comments "#" on new lines (takes about 2 seconds for 53000 sqls)
$sqls = preg_replace("/#\s([^;]*?)/", '', $sqls);
}
else {
$sqls = explode(";\n", $no_comment_sqls . "\n"); // ensures that last sql won't have ";" in it
$sqls = array_map('trim', $sqls);
}
$sql_count = count($sqls);
$db_collation = $this->getSystemConfig('Database', 'DBCollation');
for ($i = $start_from; $i < $sql_count; $i++) {
$sql = $sqls[$i];
if (!$sql || (substr($sql, 0, 1) == '#')) {
continue; // usually last line
}
if (substr($sql, 0, 13) == 'CREATE TABLE ' && $db_collation) {
// it is CREATE TABLE statement -> add collation
$sql .= ' COLLATE \'' . $db_collation . '\'';
}
$this->Conn->Query($sql);
if ($this->Conn->getErrorCode() != 0) {
if (is_object($this->_installator)) {
$this->_installator->errorMessage = 'Error: ('.$this->Conn->getErrorCode().') '.$this->Conn->getErrorMsg().'<br /><br />Last Database Query:<br /><textarea cols="70" rows="10" readonly>'.htmlspecialchars($sql).'</textarea>';
$this->_installator->LastQueryNum = $i + 1;
}
return false;
}
}
return true;
}
/**
* Performs clean language import from given xml file
*
* @param string $lang_file
* @param bool $upgrade
* @todo Import for "core/install/english.lang" (322KB) takes 18 seconds to work on Windows
*/
function ImportLanguage($lang_file, $upgrade = false)
{
$lang_file = FULL_PATH.$lang_file.'.lang';
if (!file_exists($lang_file)) {
return ;
}
$language_import_helper =& $this->Application->recallObject('LanguageImportHelper');
/* @var $language_import_helper LanguageImportHelper */
$language_import_helper->performImport($lang_file, '|0|1|2|', '', $upgrade ? LANG_SKIP_EXISTING : LANG_OVERWRITE_EXISTING);
}
/**
* Converts module version in format X.Y.Z[-BN/-RCM] to signle integer
*
* @param string $version
* @return int
*/
function ConvertModuleVersion($version)
{
if (preg_match('/(.*)-(B|RC)([\d]+)/', $version, $regs)) {
// -B<M> or RC-<N>
$parts = explode('.', $regs[1]);
$parts[] = $regs[2] == 'B' ? 1 : 2; // B reliases goes before RC releases
$parts[] = $regs[3];
}
else {
// releases without B/RC marks go after any B/RC releases
$parts = explode('.', $version . '.3.100');
}
$bin = '';
foreach ($parts as $part_index => $part) {
if ($part_index == 3) {
// version type only can be 1/2/3 (11 in binary form), so don't use padding at all
$pad_count = 2;
}
else {
$pad_count = 8;
}
$bin .= str_pad(decbin($part), $pad_count, '0', STR_PAD_LEFT);
}
return bindec($bin);
}
/**
* Returns themes, found in system
*
* @param bool $rebuild
* @return int
*/
function getThemes($rebuild = false)
{
if ($rebuild) {
$this->rebuildThemes();
}
$id_field = $this->Application->getUnitOption('theme', 'IDField');
$table_name = $this->Application->getUnitOption('theme', 'TableName');
$sql = 'SELECT Name, ' . $id_field . '
FROM ' . $table_name . '
ORDER BY Name ASC';
return $this->Conn->GetCol($sql, $id_field);
}
function ParseConfig($parse_section = false)
{
if (!file_exists($this->INIFile)) {
return Array();
}
if( file_exists($this->INIFile) && !is_readable($this->INIFile) ) {
die('Could Not Open Ini File');
}
$contents = file($this->INIFile);
$retval = Array();
$section = '';
$ln = 1;
$resave = false;
foreach ($contents as $line) {
if ($ln == 1 && $line != '<'.'?'.'php die() ?'.">\n") {
$resave = true;
}
$ln++;
$line = trim($line);
$line = preg_replace('/;[.]*/', '', $line);
if (strlen($line) > 0) {
//echo $line . " - ";
if (preg_match('/^\[[a-z]+\]$/i', str_replace(' ', '', $line))) {
//echo 'section';
$section = mb_substr($line, 1, (mb_strlen($line) - 2));
if ($parse_section) {
$retval[$section] = array();
}
continue;
} elseif (strpos($line, '=') !== false) {
//echo 'main element';
list ($key, $val) = explode(' = ', $line);
if (!$parse_section) {
$retval[trim($key)] = str_replace('"', '', $val);
}
else {
$retval[$section][trim($key)] = str_replace('"', '', $val);
}
}
}
}
if ($resave) {
$fp = fopen($this->INIFile, 'w');
reset($contents);
fwrite($fp,'<'.'?'.'php die() ?'.">\n\n");
foreach ($contents as $line) {
fwrite($fp,"$line");
}
fclose($fp);
}
return $retval;
}
function SaveConfig($silent = false)
{
if (!is_writable($this->INIFile) && !is_writable(dirname($this->INIFile))) {
trigger_error('Cannot write to "' . $this->INIFile . '" file.', $silent ? E_USER_NOTICE : E_USER_ERROR);
return ;
}
$fp = fopen($this->INIFile, 'w');
fwrite($fp,'<'.'?'.'php die() ?'.">\n\n");
foreach ($this->systemConfig as $section_name => $section_data) {
fwrite($fp, '['.$section_name."]\n");
foreach ($section_data as $key => $value) {
fwrite($fp, $key.' = "'.$value.'"'."\n");
}
fwrite($fp, "\n");
}
fclose($fp);
}
/**
* Sets value to system config (yet SaveConfig must be called to write it to file)
*
* @param string $section
* @param string $key
* @param string $value
*/
function setSystemConfig($section, $key, $value = null)
{
if (isset($value)) {
if (!array_key_exists($section, $this->systemConfig)) {
// create section, when missing
$this->systemConfig[$section] = Array ();
}
// create key in section
$this->systemConfig[$section][$key] = $value;
return ;
}
unset($this->systemConfig[$section][$key]);
}
/**
* Returns information from system config
*
* @return string
*/
function getSystemConfig($section, $key)
{
if (!array_key_exists($section, $this->systemConfig)) {
return false;
}
if (!array_key_exists($key, $this->systemConfig[$section])) {
return false;
}
return $this->systemConfig[$section][$key] ? $this->systemConfig[$section][$key] : false;
}
/**
* Checks if system config is present and is not empty
*
* @return bool
*/
function systemConfigFound()
{
return file_exists($this->INIFile) && $this->systemConfig;
}
/**
* Checks if given section is present in config
*
* @param string $section
* @return bool
*/
function sectionFound($section)
{
return array_key_exists($section, $this->systemConfig);
}
/**
* Returns formatted module name based on it's root folder
*
* @param string $module_folder
* @return string
*/
function getModuleName($module_folder)
{
return implode('-', array_map('ucfirst', explode('-', $module_folder)));
}
/**
* Returns information about module (based on "install/module_info.xml" file)
*
* @param string $module_folder
* @return Array
*/
function getModuleInfo($module_folder)
{
$info_file = MODULES_PATH . '/' . $module_folder . '/install/module_info.xml';
if (!file_exists($info_file)) {
return Array ();
}
$xml_helper =& $this->Application->recallObject('kXMLHelper');
/* @var $xml_helper kXMLHelper */
$root_node =& $xml_helper->Parse( file_get_contents($info_file) );
if (!is_object($root_node) || !preg_match('/^kxmlnode/i', get_class($root_node)) || ($root_node->Name == 'ERROR')) {
// non-valid xml file
return Array ();
}
$ret = Array ();
$current_node =& $root_node->firstChild;
do {
$ret[ strtolower($current_node->Name) ] = trim($current_node->Data);
} while (($current_node =& $current_node->NextSibling()));
return $ret;
}
/**
* Returns nice module string to be used on install/upgrade screens
*
* @param string $module_folder
* @param string $version_string
* @return string
*/
function getModuleString($module_folder, $version_string)
{
// image (if exists) <description> (<name> <version>)
$ret = Array ();
$module_info = $this->getModuleInfo($module_folder);
if (array_key_exists('name', $module_info) && $module_info['name']) {
$module_name = $module_info['name'];
}
else {
$module_name = $this->getModuleName($module_folder);
}
if (array_key_exists('image', $module_info) && $module_info['image']) {
$image_src = $module_info['image'];
if (!preg_match('/^(http|https):\/\//', $image_src)) {
// local image -> make absolute url
$image_src = $this->Application->BaseURL() . $image_src;
}
$ret[] = '<img src="' . $image_src . '" alt="' . htmlspecialchars($module_name) . '" title="' . htmlspecialchars($module_name) . '" style="vertical-align:middle; margin: 3px 0 3px 5px"/>';
}
if (array_key_exists('description', $module_info) && $module_info['description']) {
$ret[] = $module_info['description'];
}
else {
$ret[] = $module_name;
}
$ret[] = '(' . $module_name . ' ' . $version_string . ')';
return implode(' ', $ret);
}
/**
* Creates module root category in "Home" category using given data and returns it
*
* @param string $name
* @param string $description
* @param string $category_template
* @param string $category_icon
* @return kDBItem
*/
function &createModuleCategory($name, $description, $category_template = null, $category_icon = null)
{
static $fields = null;
if (!isset($fields)) {
$ml_formatter =& $this->Application->recallObject('kMultiLanguage');
$fields['name'] = $ml_formatter->LangFieldName('Name');
$fields['description'] = $ml_formatter->LangFieldName('Description');
}
$category =& $this->Application->recallObject('c', null, Array ('skip_autoload' => true));
/* @var $category kDBItem */
$category_fields = Array (
$fields['name'] => $name, 'Filename' => $name, 'AutomaticFilename' => 1,
$fields['description'] => $description, 'Status' => STATUS_ACTIVE, 'Priority' => -9999,
);
$category_fields['ParentId'] = $this->Application->findModule('Name', 'Core', 'RootCat');
if (isset($category_template)) {
$category_fields['Template'] = $category_template;
$category_fields['CachedTemplate'] = $category_template;
}
if (isset($category_icon)) {
$category_fields['UseMenuIconUrl'] = 1;
$category_fields['MenuIconUrl'] = $category_icon;
}
$category->Clear();
$category->SetDBFieldsFromHash($category_fields);
$category->Create();
$priority_helper =& $this->Application->recallObject('PriorityHelper');
/* @var $priority_helper kPriorityHelper */
$event = new kEvent('c:OnListBuild');
// ensure, that newly created category has proper value in Priority field
$priority_helper->recalculatePriorities($event, 'ParentId = ' . $category_fields['ParentId']);
// update Priority field in object, becase "CategoriesItem::Update" method will be called
// from "kInstallToolkit::setModuleItemTemplate" and otherwise will set 0 to Priority field
$sql = 'SELECT Priority
FROM ' . $category->TableName . '
WHERE ' . $category->IDField . ' = ' . $category->GetID();
$category->SetDBField('Priority', $this->Conn->GetOne($sql));
return $category;
}
/**
* Sets category item template into custom field for given prefix
*
* @param kDBItem $category
* @param string $prefix
* @param string $item_template
*/
function setModuleItemTemplate(&$category, $prefix, $item_template)
{
$this->Application->removeObject('c-cdata');
// recreate all fields, because custom fields are added during install script
$category->defineFields();
$category->prepareConfigOptions(); // creates ml fields
$category->SetDBField('cust_' . $prefix .'_ItemTemplate', $item_template);
$category->Update();
}
/**
* Link custom field records with search config records + create custom field columns
*
* @param string $module_folder
* @param int $item_type
*/
function linkCustomFields($module_folder, $prefix, $item_type)
{
$module_folder = strtolower($module_folder);
$module_name = $module_folder;
if ($module_folder == 'kernel') {
$module_name = 'in-portal';
$module_folder = 'core';
}
$db =& $this->Application->GetADODBConnection();
$sql = 'SELECT FieldName, CustomFieldId
FROM ' . TABLE_PREFIX . 'CustomField
WHERE Type = ' . $item_type . ' AND IsSystem = 0'; // config is not read here yet :( $this->Application->getUnitOption('p', 'ItemType');
$custom_fields = $db->GetCol($sql, 'CustomFieldId');
foreach ($custom_fields as $cf_id => $cf_name) {
$sql = 'UPDATE ' . TABLE_PREFIX . 'SearchConfig
SET CustomFieldId = ' . $cf_id . '
WHERE (TableName = "CustomField") AND (LOWER(ModuleName) = "' . $module_name . '") AND (FieldName = ' . $db->qstr($cf_name) . ')';
$db->Query($sql);
}
$this->Application->refreshModuleInfo(); // this module configs are now processed
// because of configs was read only from installed before modules (in-portal), then reread configs
$unit_config_reader =& $this->Application->recallObject('kUnitConfigReader');
/* @var $unit_config_reader kUnitConfigReader */
$unit_config_reader->scanModules(MODULES_PATH . DIRECTORY_SEPARATOR . $module_folder);
// create correct columns in CustomData table
$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
$ml_helper->createFields($prefix . '-cdata', true);
}
/**
* Deletes cache, useful after separate module install and installator last step
*
*/
function deleteCache($refresh_permissions = false)
{
$sql = 'DELETE FROM ' . TABLE_PREFIX . 'Cache
WHERE VarName IN ("config_files", "configs_parsed", "sections_parsed")';
$this->Conn->Query($sql);
$this->Application->HandleEvent($event, 'c:OnResetCMSMenuCache');
if ($refresh_permissions) {
if ($this->Application->ConfigValue('QuickCategoryPermissionRebuild')) {
// refresh permission without progress bar
$updater =& $this->Application->recallObject('kPermCacheUpdater');
/* @var $updater kPermCacheUpdater */
$updater->OneStepRun();
}
else {
// refresh permissions with ajax progress bar (when available)
$fields_hash = Array (
'VarName' => 'ForcePermCacheUpdate',
'Data' => 1,
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Cache');
}
}
}
/**
* Perform redirect after separate module install
*
* @param string $module_folder
* @param bool $refresh_permissions
*/
function finalizeModuleInstall($module_folder, $refresh_permissions = false)
{
if (!$this->Application->GetVar('redirect')) {
return ;
}
$this->SetModuleVersion($module_folder);
$this->deleteCache($refresh_permissions);
$url_params = Array (
'pass' => 'm', 'admin' => 1,
'RefreshTree' => 1, 'index_file' => 'index.php',
);
$this->Application->Redirect('modules/modules_list', $url_params);
}
/**
* Performs rebuild of themes
*
*/
function rebuildThemes()
{
$this->Application->HandleEvent($themes_event, 'adm:OnRebuildThemes');
}
/**
* Checks that file is writable by group or others
*
* @param string $file
* @return boolean
*/
function checkWritePermissions($file)
{
if (DIRECTORY_SEPARATOR == '\\') {
// windows doen't allow to check permissions (always returns null)
return null;
}
$permissions = fileperms($file);
return $permissions & 0x0010 || $permissions & 0x0002;
}
}
\ No newline at end of file
Index: branches/5.1.x/core/install.php
===================================================================
--- branches/5.1.x/core/install.php (revision 13112)
+++ branches/5.1.x/core/install.php (revision 13113)
@@ -1,1455 +1,1451 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
ini_set('display_errors', 1);
error_reporting(E_ALL);
define('IS_INSTALL', 1);
define('ADMIN', 1);
define('FULL_PATH', realpath(dirname(__FILE__).'/..') );
define('REL_PATH', '/core');
// run installator
$install_engine = new kInstallator();
$install_engine->Init();
$install_engine->Run();
$install_engine->Done();
class kInstallator {
/**
* Reference to kApplication class object
*
* @var kApplication
*/
var $Application = null;
/**
* Connection to database
*
* @var kDBConnection
*/
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 = '';
/**
* Installtion steps to be done
*
* @var Array
*/
var $steps = Array (
'fresh_install' => Array ('check_paths', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish'),
'clean_reinstall' => Array ('check_paths', 'clean_db', 'db_config', 'select_license', /*'download_license',*/ 'select_domain', 'root_password', 'choose_modules', 'post_config', 'select_theme', 'security', 'finish'),
'already_installed' => Array ('check_paths', 'install_setup'),
'upgrade' => Array ('check_paths', 'install_setup', 'upgrade_modules', 'security', 'finish'),
'update_license' => Array ('check_paths', 'install_setup', 'select_license', /*'download_license',*/ 'select_domain', 'security', 'finish'),
'db_reconfig' => Array ('check_paths', 'install_setup', 'db_reconfig', 'security', 'finish'),
'fix_paths' => Array ('check_paths', 'install_setup', 'fix_paths', 'security', 'finish'),
);
/**
* Steps, that doesn't required admin to be logged-in to proceed
*
* @var Array
*/
var $skipLoginSteps = Array ('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 ('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/images',
'$1/images/resized',
'$1/images/pending',
'$1/images/pending/resized',
'$1/images/emoticons', // for "In-Bulletin"
'$1/images/manufacturers', // for "In-Commerce"
'$1/images/manufacturers/resized', // for "In-Commerce"
'$1/images/polls', // for "In-Bulletin"
'$1/images/polls/resized', // for "In-Bulletin"
'$1/backupdata',
'$1/export',
'$1/stylesheets',
'$1/user_files',
'$1/cache',
'/themes',
);
/**
* 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;
/**
* Common tools required for installation process
*
* @var kInstallToolkit
*/
var $toolkit = null;
function Init()
{
include_once(FULL_PATH . REL_PATH . '/kernel/utility/multibyte.php'); // emulating multi-byte php extension
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';
$base_path = rtrim(preg_replace('/'.preg_quote(rtrim(REL_PATH, '/'), '/').'$/', '', str_replace('\\', '/', dirname($_SERVER['PHP_SELF']))), '/');
$this->baseURL = 'http://'.$_SERVER['HTTP_HOST'].$base_path.'/core/install/';
set_error_handler( Array(&$this, 'ErrorHandler') );
if (file_exists($this->toolkit->INIFile)) {
// if config.php found, then check his write permission too
$this->writeableFolders[] = '/config.php';
}
else {
$this->writeableFolders[] = '/';
}
if (!$this->toolkit->getSystemConfig('Misc', 'WriteablePath')) {
// set global writable folder when such setting is missing
$this->toolkit->setSystemConfig('Misc', 'WriteablePath', DIRECTORY_SEPARATOR . 'system');
$this->toolkit->SaveConfig(true); // immediately save, because this path will be used in Application later
}
$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;
}
function GetVar($name)
{
return array_key_exists($name, $_REQUEST) ? $_REQUEST[$name] : false;
}
function SetVar($name, $value)
{
$_REQUEST[$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 'check_paths':
$writeable_base = $this->toolkit->getSystemConfig('Misc', 'WriteablePath');
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 = '<br/>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->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->setSystemConfig('Database', $field_name, $submit_value);
}
/*else {
$this->toolkit->setSystemConfig('Database', $field_name, '');
}*/
}
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 'install_setup':
$next_preset = $this->Application->GetVar('next_preset');
if ($next_preset !== false) {
if ($this->Application->GetVar('login') == 'root') {
// verify "root" user using configuration settings
$login_event = new kEvent('u.current:OnLogin');
$this->Application->HandleEvent($login_event);
if ($login_event->status != erSUCCESS) {
$user =& $this->Application->recallObject('u.current');
/* @var $user UsersItem */
$this->errorMessage = $user->GetErrorMsg('ValidateLogin') . '. 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( $this->GetVar('login') ),
'password=' . md5( $this->GetVar('password') ),
'action=check',
'license_code=' . base64_encode( $this->toolkit->getSystemConfig('Intechnic', 'LicenseCode') ),
'version=' . '4.3.0',//$this->toolkit->GetMaxModuleVersion('In-Portal'),
'domain=' . base64_encode($_SERVER['HTTP_HOST']),
);
$license_url = GET_LICENSE_URL . '?' . implode('&', $url_params);
$file_data = curl_post($license_url, '', null, 'GET');
if (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_id = -1;
$session =& $this->Application->recallObject('Session');
$session->SetField('PortalUserId', $user_id);
$this->Application->SetVar('u.current_id', $user_id);
$this->Application->StoreVar('user_id', $user_id);
}
}
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', '/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, "<?php\n\techo 'OK';\n");
fclose($fp);
$curl_helper =& $this->Application->recallObject('CurlHelper');
/* @var $curl_helper kCurlHelper */
$output = $curl_helper->Send($this->Application->BaseURL(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->getSystemConfig($section_name, $required_field)) {
$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->getSystemConfig('Database', 'DBCollation').'\'';
$collation_info = $this->Conn->Query($sql);
if ($collation_info) {
$this->toolkit->setSystemConfig('Database', 'DBCharset', $collation_info[0]['Charset']);
// database is already connected, that's why set collation on the fly
$this->Conn->Query('SET NAMES \''.$this->toolkit->getSystemConfig('Database', 'DBCharset').'\' COLLATE \''.$this->toolkit->getSystemConfig('Database', 'DBCollation').'\'');
}
$this->toolkit->SaveConfig();
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->getSystemConfig('Database', 'TablePrefix') . '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;
}
$fields_hash = Array (
'l1_Name' => '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->getSystemConfig('Database', 'TablePrefix') . 'Category');
$this->toolkit->SetModuleRootCategory('Core', $this->Conn->getInsertID());
// set module "Core" version after install (based on upgrade scripts)
$this->toolkit->SetModuleVersion('Core');
// for now we set "In-Portal" module version to "Core" module version (during clean install)
$this->toolkit->SetModuleVersion('In-Portal', $this->toolkit->GetMaxModuleVersion('Core'));
}
break;
case 'select_license':
$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]) {
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
if ($modules_helper->verifyLicense($file_data[1])) {
$this->toolkit->setSystemConfig('Intechnic', 'License', $file_data[1]);
$this->toolkit->setSystemConfig('Intechnic', 'LicenseCode', $file_data[2]);
$this->toolkit->SaveConfig();
}
else {
$this->errorMessage = 'Invalid License File';
}
}
else {
$this->errorMessage = 'Invalid License File';
}
break;
case 3: // Use Existing License
$license_hash = $this->toolkit->getSystemConfig('Intechnic', 'License');
if ($license_hash) {
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper 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->setSystemConfig('Intechnic', 'License');
$this->toolkit->setSystemConfig('Intechnic', 'LicenseCode');
$this->toolkit->SaveConfig();
}
break;
}
break;
case 'download_license':
$license_login = $this->GetVar('login');
$license_password = $this->GetVar('password');
$license_id = $this->GetVar('licenses');
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('In-Portal'),
'domain=' . base64_encode($_SERVER['HTTP_HOST']),
);
$license_url = GET_LICENSE_URL . '?' . implode('&', $url_params);
$file_data = curl_post($license_url, '', null, 'GET');
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('In-Portal'),
'domain=' . base64_encode($_SERVER['HTTP_HOST']),
);
$license_url = GET_LICENSE_URL . '?' . implode('&', $url_params);
$file_data = curl_post($license_url, '', null, 'GET');
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':
$modules_helper =& $this->Application->recallObject('ModulesHelper');
/* @var $modules_helper kModulesHelper */
$license_hash = $this->toolkit->getSystemConfig('Intechnic', 'License');
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
$license_domain = $_SERVER['HTTP_HOST'];
}
$domain = $this->GetVar('domain') == 1 ? $_SERVER['HTTP_HOST'] : str_replace(' ', '', $this->GetVar('other'));
if ($domain != '') {
if (strstr($domain, $license_domain) || $modules_helper->_IsLocalSite($domain)) {
$this->toolkit->setSystemConfig('Misc', 'Domain', $domain);
$this->toolkit->SaveConfig();
}
else {
$this->errorMessage = 'Domain name entered does not match domain name in the license!';
}
}
else {
$this->errorMessage = 'Please enter valid domain!';
}
break;
case 'root_password':
// update root password in database
$password = md5( md5($this->Application->GetVar('root_password')) . 'b38');
$config_values = Array (
'RootPass' => $password,
'Site_Path' => BASE_PATH.'/', // set Site_Path (for SSL & old in-portal code)
'Backup_Path' => FULL_PATH . $this->toolkit->getSystemConfig('Misc', 'WriteablePath') . DIRECTORY_SEPARATOR . 'backupdata',
'Smtp_AdminMailFrom' => 'portal@' . $this->toolkit->getSystemConfig('Misc', 'Domain')
);
$this->toolkit->saveConfigValues($config_values);
// login as "root", when no errors on password screen
$this->Application->SetVar('login', 'root');
$this->Application->SetVar('password', $this->Application->GetVar('root_password'));
$login_event = new kEvent('u.current:OnLogin');
$this->Application->HandleEvent($login_event);
// 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
$lang =& $this->Application->recallObject('lang.-item', null, Array('skip_autoload' => true));
/* @var $lang LanguagesItem */
$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);
// set module version after install (based on upgrade scripts)
$this->toolkit->SetModuleVersion($module);
}
}
}
// update category cache
$updater =& $this->Application->recallObject('kPermCacheUpdater');
/* @var $updater 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_table = $this->Application->getUnitOption('theme', 'TableName');
$theme_idfield = $this->Application->getUnitOption('theme', 'IDField');
$sql = 'UPDATE ' . $theme_table . '
SET Enabled = 1, PrimaryTheme = 1
WHERE ' . $theme_idfield . ' = ' . $theme_id;
$this->Conn->Query($sql);
$this->toolkit->rebuildThemes(); // rescan theme to create structure after theme is enabled !!!
if ($this->Application->isModuleEnabled('In-Portal')) {
// 2. compile theme stylesheets (only In-Portal uses them)
$css_table = $this->Application->getUnitOption('css', 'TableName');
$css_idfield = $this->Application->getUnitOption('css', 'IDField');
$sql = 'SELECT LOWER(Name) AS Name, ' . $css_idfield . '
FROM ' . $css_table;
$css_hash = $this->Conn->GetCol($sql, $css_idfield);
$css_item =& $this->Application->recallObject('css', null, Array('skip_autoload' => true));
/* @var $css_item StyleshetsItem */
foreach ($css_hash as $stylesheet_id => $theme_name) {
$css_item->Load($stylesheet_id);
$css_item->Compile();
$sql = 'UPDATE ' . $theme_table . '
SET StylesheetId = ' . $stylesheet_id . '
WHERE LOWER(Name) = ' . $this->Conn->qstr($theme_name);
$this->Conn->Query($sql);
}
}
// install theme dependent demo data
if ($this->Application->GetVar('install_demo_data')) {
$sql = 'SELECT Name
FROM ' . $theme_table . '
WHERE ' . $theme_idfield . ' = ' . $theme_id;
$theme_name = $this->Conn->GetOne($sql);
foreach ($this->Application->ModuleInfo as $module_name => $module_info) {
if ($module_name == 'In-Portal') {
continue;
}
$this->toolkit->RunSQL('/themes' . '/' . $theme_name . '/' . $module_info['TemplatePath'] . '_install/install_data.sql', '{ThemeId}', $theme_id);
}
}
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_module = $this->GetVar('continue_from_module');
$start_from_query = $this->GetVar('continue_from_query');
if (!$start_from_query) $start_from_query = 0;
foreach ($modules as $module_name) {
if ($start_from_module && $module_name != $start_from_module) {
continue;
}
else {
$start_from_module = false; //otherwise it will skip all modules after the one we start with!
}
$module_info = $upgrade_data[$module_name];
$upgrades_file = sprintf(UPGRADES_FILE, $module_info['Path'], 'sql');
$sqls = file_get_contents($upgrades_file);
$version_mark = preg_replace('/(\(.*?\))/', $module_info['FromVersion'], 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);
preg_match_all('/'.VERSION_MARK.'/s', $sqls, $regs);
if (!$start_from_module) {
$this->RunUpgrades($module_info['Path'], $regs[1], 'before');
}
if (!$this->toolkit->RunSQLText($sqls, null, null, $start_from_query)) {
$this->errorMessage .= '<input type="hidden" name="continue_from_module" value="'.$module_name.'">';
$this->errorMessage .= '<input type="hidden" name="continue_from_query" value="'.$this->LastQueryNum.'">';
$this->errorMessage .= '<br/>Click Continue button below to skip this query and go further<br/>';
$this->Done();
}
$start_from_query = 0; // so that next module start from the beggining
$this->toolkit->ImportLanguage('/' . $module_info['Path'] . 'install/english', true);
$this->RunUpgrades($module_info['Path'], $regs[1], 'after'); // upgrade script could operate resulting language pack
// after upgrade sqls are executed update version and upgrade language pack
$this->toolkit->SetModuleVersion($module_name, $module_info['ToVersion']);
}
// for now we set "In-Portal" module version to "Core" module version (during upgrade)
if (in_array('core', $modules)) {
$this->toolkit->SetModuleVersion('In-Portal', $upgrade_data['core']['ToVersion']);
}
}
break;
case 'fix_paths':
$this->toolkit->saveConfigValues( $this->Application->GetVar('config') );
break;
case 'finish':
// delete cache
$this->toolkit->deleteCache();
// set installation finished mark
if ($this->Application->ConfigValue('InstallFinished') === false) {
$fields_hash = Array (
'VariableName' => 'InstallFinished',
'VariableValue' => 1,
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX.'ConfigurationValues');
}
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
$this->Application->Redirect('index', null, '', 'index.php');
}
}
/**
* Run upgrade PHP scripts for module with specified path
*
* @param string $module_path
* @param Array $versions
* @param string $mode upgrade mode = {before,after}
*/
function RunUpgrades($module_path, $versions, $mode)
{
static $upgrade_classes = Array ();
$upgrades_file = sprintf(UPGRADES_FILE, $module_path, 'php');
if (!file_exists($upgrades_file) || !$versions) {
return ;
}
if (!isset($upgrade_classes[$module_path])) {
// 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;
}
$upgrade_object = new $upgrade_classes[$module_path]();
if (method_exists($upgrade_object, 'setToolkit')) {
$upgrade_object->setToolkit($this->toolkit);
}
foreach ($versions as $version) {
$upgrade_method = 'Upgrade_'.str_replace(Array ('.', '-'), '_', $version);
if (method_exists($upgrade_object, $upgrade_method)) {
$upgrade_object->$upgrade_method($mode);
}
}
}
/**
* 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->Application->Init();
$this->Conn =& $this->Application->GetADODBConnection();
$this->toolkit->Conn =& $this->Application->GetADODBConnection();
}
}
/**
* Show next step screen
*
*/
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/db_connection.php';
$required_keys = Array ('DBType', 'DBUser', 'DBName');
foreach ($required_keys as $required_key) {
if (!$this->toolkit->getSystemConfig('Database', $required_key)) {
// one of required db connection settings missing -> abort connection
return false;
}
}
$this->Conn = new kDBConnection($this->toolkit->getSystemConfig('Database', 'DBType'), Array(&$this, 'DBErrorHandler'));
$this->Conn->Connect(
$this->toolkit->getSystemConfig('Database', 'DBHost'),
$this->toolkit->getSystemConfig('Database', 'DBUser'),
$this->toolkit->getSystemConfig('Database', 'DBUserPassword'),
$this->toolkit->getSystemConfig('Database', 'DBName')
);
// setup toolkit too
$this->toolkit->Conn =& $this->Conn;
return $this->Conn->errorCode == 0;
}
/**
* Checks if core is already installed
*
* @return bool
*/
function AlreadyInstalled()
{
$table_prefix = $this->toolkit->getSystemConfig('Database', 'TablePrefix');
$sql = 'SELECT VariableValue
FROM ' . $table_prefix . 'ConfigurationValues
WHERE VariableName = "InstallFinished"';
return $this->TableExists('ConfigurationValues') && $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
if (mb_strlen($this->toolkit->getSystemConfig('Database', 'TablePrefix')) > 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;
}
}
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->getSystemConfig('Database', 'TablePrefix');
$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)) {
$modules = Array();
$fh = opendir(MODULES_PATH);
while ( ($sub_folder = readdir($fh)) ) {
$folder_path = MODULES_PATH . '/'.$sub_folder;
if ($sub_folder != '.' && $sub_folder != '..' && is_dir($folder_path)) {
- if ($sub_folder == 'core') {
- // skip modules here
- continue;
- }
// this is folder in MODULES_PATH directory
if (file_exists($folder_path.'/install.php') && file_exists($folder_path.'/install/install_schema.sql')) {
$install_order = trim( file_get_contents($folder_path . '/install/install_order.txt') );
$modules[$install_order] = $sub_folder;
}
}
}
}
// allows to control module install order
ksort($modules, SORT_NUMERIC);
return $modules;
}
/**
* 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;
}
$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_recursive2($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: <br />'.htmlspecialchars($sql).'<br />execution result is error:<br />['.$code.'] '.$msg;
return true;
}
/**
* Installation error handler
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
* @param Array $errcontext
*/
function ErrorHandler($errno, $errstr, $errfile = '', $errline = '', $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 ('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;
}
}

Event Timeline