Index: trunk/core/kernel/startup.php
===================================================================
diff -u -N -r7855 -r8402
--- trunk/core/kernel/startup.php (.../startup.php) (revision 7855)
+++ trunk/core/kernel/startup.php (.../startup.php) (revision 8402)
@@ -36,6 +36,7 @@
if (isset($vars['WriteablePath'])) {
define('WRITEABLE', FULL_PATH.$vars['WriteablePath']);
+ define('WRITEBALE_BASE', $vars['WriteablePath']);
}
if ($vars === false || count($vars) == 0) {
Index: trunk/core/kernel/db/db_tag_processor.php
===================================================================
diff -u -N -r8388 -r8402
--- trunk/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 8388)
+++ trunk/core/kernel/db/db_tag_processor.php (.../db_tag_processor.php) (revision 8402)
@@ -1441,7 +1441,7 @@
case 'multiselect':
case 'radio':
$field_options = $object->GetFieldOptions($field, 'options');
-
+
if ($object->GetDBField('DirectOptions')) {
// used for custom fields
$field_options['options'] = $object->GetDBField('DirectOptions');
@@ -1450,7 +1450,7 @@
// used for configuration
$field_options['options'] = $helper->GetValuesHash( $object->GetDBField($params['value_list_field']) );
}
-
+
$object->SetFieldOptions($field, $field_options);
break;
@@ -1884,6 +1884,34 @@
$this->Application->HandleEvent(new kEvent($prefix.':OnNew'));
}
}
+
+ function PrintSerializedFields($params)
+ {
+ $object =& $this->getObject();
+ $field = $this->SelectParam($params, 'field');
+ $data = unserialize($object->GetDBField($field));
+
+ $o = '';
+ $std_params['name'] = $params['render_as'];
+ $std_params['field'] = $params['field'];
+ $std_params['pass_params'] = true;
+ foreach ($data as $key => $row) {
+ $block_params = array_merge($std_params, $row, array('key'=>$key));
+ $o .= $this->Application->ParseBlock($block_params);
+ }
+ return $o;
+ }
+
+ /**
+ * Checks if current prefix is main item
+ *
+ * @param Array $params
+ * @return bool
+ */
+ function IsTopmostPrefix($params)
+ {
+ return $this->Prefix == $this->Application->GetTopmostPrefix($this->Prefix);
+ }
}
?>
\ No newline at end of file
Index: trunk/core/kernel/session/session.php
===================================================================
diff -u -N -r8104 -r8402
--- trunk/core/kernel/session/session.php (.../session.php) (revision 8104)
+++ trunk/core/kernel/session/session.php (.../session.php) (revision 8402)
@@ -256,7 +256,7 @@
function LoadPersistentVars(&$session)
{
- $user_id = $this->Application->RecallVar('user_id');
+ $user_id = $session->RecallVar('user_id');
if ($user_id != -2) {
// root & normal users
$sql = 'SELECT VariableValue, VariableName
@@ -271,15 +271,33 @@
function StorePersistentVar(&$session, $var_name, $var_value)
{
+ $user_id = $session->RecallVar('user_id');
+ if ($user_id == -2 || $user_id === false) {
+ // -2 (when not logged in), false (when after u:OnLogout event)
+ return ;
+ }
+
$this->PersistentVars[$var_name] = $var_value;
-
- $replace_hash = Array (
- 'PortalUserId' => $this->Application->RecallVar('user_id'),
- 'VariableName' => $var_name,
- 'VariableValue' => $var_value
- );
- $this->Conn->doInsert($replace_hash, TABLE_PREFIX.'PersistantSessionData', 'REPLACE');
-
+
+ $key_clause = 'PortalUserId = '.$user_id.' AND VariableName = '.$this->Conn->qstr($var_name);
+
+ $sql = 'SELECT VariableValue
+ FROM '.TABLE_PREFIX.'PersistantSessionData
+ WHERE '.$key_clause;
+ $record_found = $this->Conn->GetOne($sql);
+
+ $fields_hash = Array (
+ 'PortalUserId' => $user_id,
+ 'VariableName' => $var_name,
+ 'VariableValue' => $var_value,
+ );
+
+ if ($record_found) {
+ $this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'PersistantSessionData', $key_clause);
+ }
+ else {
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'PersistantSessionData');
+ }
}
function RecallPersistentVar(&$session, $var_name, $default = false)
@@ -291,7 +309,7 @@
{
unset($this->PersistentVars[$var_name]);
- $user_id = $this->Application->RecallVar('user_id');
+ $user_id = $session->RecallVar('user_id');
if ($user_id != -2) {
$sql = 'DELETE FROM '.TABLE_PREFIX.'PersistantSessionData
@@ -662,6 +680,8 @@
// front-session called from admin or otherwise, then save it's data
$this->SaveData();
}
+
+ $this->Application->resetCounters('UserSession');
}
/**
@@ -786,6 +806,31 @@
// save other last... variables for mistical purposes (customizations may be)
$this->StoreVar('last_url', $_SERVER['REQUEST_URI']); // needed by ord:StoreContinueShoppingLink
$this->StoreVar('last_env', substr($last_env, strlen(ENV_VAR_NAME)+1));
+
+ // save last_template in persistant session
+ if (!$wid) {
+ if ($this->Application->IsAdmin()) {
+ // only for main window, not popups, not login template, not temp mode (used in adm:MainFrameLink tag)
+ $temp_mode = false;
+ $passed = explode(',', $this->Application->GetVar('passed'));
+ foreach ($passed as $passed_prefix) {
+ if ($this->Application->GetVar($passed_prefix.'_mode')) {
+ $temp_mode = true;
+ break;
+ }
+ }
+
+ if (!$temp_mode) {
+ $this->StorePersistentVar('last_template_popup', $last_template);
+ }
+ }
+ elseif ($this->Application->GetVar('admin') == 1) {
+ $admin_session =& $this->Application->recallObject('Session.admin');
+ /* @var $admin_ses Session */
+
+ $admin_session->StorePersistentVar('last_template_popup', '../'.$last_template);
+ }
+ }
}
function getLastTemplateENV($t, $params)
@@ -871,6 +916,7 @@
{
return $this->Storage->DeleteExpired();
}
+
/**
* Allows to check if user in this session is logged in or not
*
@@ -879,6 +925,7 @@
function LoggedIn()
{
$user_id = $this->RecallVar('user_id');
+
$ret = $user_id > 0;
if ($this->RecallVar('admin') == 1 && ($user_id == -1)) {
$ret = true;
Index: trunk/core/kernel/utility/http_query.php
===================================================================
diff -u -N -r8178 -r8402
--- trunk/core/kernel/utility/http_query.php (.../http_query.php) (revision 8178)
+++ trunk/core/kernel/utility/http_query.php (.../http_query.php) (revision 8402)
@@ -360,12 +360,18 @@
// env=SID:TEMPLATE:m-1-1-1-1:l0-0-0:n-0-0-0:bb-0-0-1-1-1-0
$vars = Array ();
if ($env_var) {
+ $more_vars = strpos($env_var, '&');
+ if ($more_vars !== false) {
+ parse_str(substr($env_var, $more_vars + 1), $vars);
+ $env_var = substr($env_var, 0, $more_vars);
+ }
+
// replace escaped ":" symbol not to explode by it
$env_var = str_replace('\:','_&+$$+&_', $env_var); // replace escaped "=" with spec-chars :)
$parts = explode(':', $env_var);
if (!$this->Application->RewriteURLs() || ($this->Application->RewriteURLs() && $this->Get('rewrite') != 'on')) {
- $vars = $this->extractSIDAndTemplate($parts);
+ $vars = array_merge_recursive2($vars, $this->extractSIDAndTemplate($parts));
}
if ($parts) {
Index: trunk/core/units/users/users_event_handler.php
===================================================================
diff -u -N -r8397 -r8402
--- trunk/core/units/users/users_event_handler.php (.../users_event_handler.php) (revision 8397)
+++ trunk/core/units/users/users_event_handler.php (.../users_event_handler.php) (revision 8402)
@@ -9,23 +9,28 @@
function mapPermissions()
{
parent::mapPermissions();
- $permissions = Array(
- // admin
- 'OnSetPersistantVariable' => Array('self' => 'view'), // because setting to logged in user only
- 'OnUpdateRootPassword' => Array('self' => true), // because setting to logged in user only
+ $permissions = Array (
+ // admin
+ 'OnSetPersistantVariable' => Array('self' => 'view'), // because setting to logged in user only
+ 'OnUpdateRootPassword' => Array('self' => true), // because setting to logged in user only
- // front
- 'OnRefreshForm' => Array('self' => true),
+ // front
+ 'OnRefreshForm' => Array('self' => true),
- 'OnForgotPassword' => Array('self' => true),
- 'OnResetPassword' => Array('self' => true),
- 'OnResetPasswordConfirmed' => Array('self' => true),
+ 'OnForgotPassword' => Array('self' => true),
+ 'OnResetPassword' => Array('self' => true),
+ 'OnResetPasswordConfirmed' => Array('self' => true),
- 'OnSubscribeQuery' => Array('self' => true),
- 'OnSubscribeUser' => Array('self' => true),
+ 'OnSubscribeQuery' => Array('self' => true),
+ 'OnSubscribeUser' => Array('self' => true),
- 'OnRecommend' => Array('self' => true),
- );
+ 'OnRecommend' => Array('self' => true),
+ );
+
+ if (!$this->Application->IsAdmin()) {
+ $permissions['OnItemBuild'] = Array('self' => true);
+ }
+
$this->permMapping = array_merge($this->permMapping, $permissions);
}
Index: trunk/core/units/visits/visits_config.php
===================================================================
diff -u -N -r8015 -r8402
--- trunk/core/units/visits/visits_config.php (.../visits_config.php) (revision 8015)
+++ trunk/core/units/visits/visits_config.php (.../visits_config.php) (revision 8402)
@@ -41,6 +41,9 @@
'IDField' => 'VisitId',
'TableName' => TABLE_PREFIX.'Visits',
+
+ 'PermSection' => Array('main' => 'in-portal:visits'),
+
'TitlePresets' => Array(
'default' => Array(),
'visits_list' => Array('prefixes' => Array('visits_List'), 'format' => "!la_title_Visits! (#visits_recordcount#)"),
Index: trunk/core/units/themes/themes_config.php
===================================================================
diff -u -N -r8099 -r8402
--- trunk/core/units/themes/themes_config.php (.../themes_config.php) (revision 8099)
+++ trunk/core/units/themes/themes_config.php (.../themes_config.php) (revision 8402)
@@ -18,6 +18,8 @@
'IDField' => 'ThemeId',
'StatusField' => Array('Enabled', 'PrimaryTheme'),
+ 'PermSection' => Array('main' => 'in-portal:configure_themes'),
+
'TitleField' => 'Name',
'TitlePresets' => Array (
Index: trunk/core/units/themes/themes_eh.php
===================================================================
diff -u -N -r8075 -r8402
--- trunk/core/units/themes/themes_eh.php (.../themes_eh.php) (revision 8075)
+++ trunk/core/units/themes/themes_eh.php (.../themes_eh.php) (revision 8402)
@@ -3,6 +3,20 @@
class ThemesEventHandler extends kDBEventHandler {
/**
+ * Allows to override standart permission mapping
+ *
+ */
+ function mapPermissions()
+ {
+ parent::mapPermissions();
+ $permissions = Array(
+ 'OnItemBuild' => Array('self' => true),
+ );
+
+ $this->permMapping = array_merge($this->permMapping, $permissions);
+ }
+
+ /**
* Allows to set selected theme as primary
*
* @param kEvent $event
Index: trunk/kernel/units/visits/visits_config.php
===================================================================
diff -u -N -r8015 -r8402
--- trunk/kernel/units/visits/visits_config.php (.../visits_config.php) (revision 8015)
+++ trunk/kernel/units/visits/visits_config.php (.../visits_config.php) (revision 8402)
@@ -41,6 +41,9 @@
'IDField' => 'VisitId',
'TableName' => TABLE_PREFIX.'Visits',
+
+ 'PermSection' => Array('main' => 'in-portal:visits'),
+
'TitlePresets' => Array(
'default' => Array(),
'visits_list' => Array('prefixes' => Array('visits_List'), 'format' => "!la_title_Visits! (#visits_recordcount#)"),
Index: trunk/core/units/languages/languages_event_handler.php
===================================================================
diff -u -N -r8397 -r8402
--- trunk/core/units/languages/languages_event_handler.php (.../languages_event_handler.php) (revision 8397)
+++ trunk/core/units/languages/languages_event_handler.php (.../languages_event_handler.php) (revision 8402)
@@ -10,14 +10,16 @@
{
parent::mapPermissions();
$permissions = Array(
- 'OnChangeLanguage' => Array('self' => true),
- 'OnSetPrimary' => Array('self' => 'advanced:set_primary|add|edit'),
- 'OnImportLanguage' => Array('self' => 'advanced:import'),
- 'OnImportProgress' => Array('self' => 'advanced:import'),
- 'OnExportLanguage' => Array('self' => 'advanced:export'),
- 'OnExportProgress' => Array('self' => 'advanced:export'),
-
- );
+ 'OnChangeLanguage' => Array('self' => true),
+ 'OnSetPrimary' => Array('self' => 'advanced:set_primary|add|edit'),
+ 'OnImportLanguage' => Array('self' => 'advanced:import'),
+ 'OnImportProgress' => Array('self' => 'advanced:import'),
+ 'OnExportLanguage' => Array('self' => 'advanced:export'),
+ 'OnExportProgress' => Array('self' => 'advanced:export'),
+
+ 'OnItemBuild' => Array('self' => true),
+ );
+
$this->permMapping = array_merge($this->permMapping, $permissions);
}
Index: trunk/core/kernel/languages/phrases_cache.php
===================================================================
diff -u -N -r7635 -r8402
--- trunk/core/kernel/languages/phrases_cache.php (.../phrases_cache.php) (revision 7635)
+++ trunk/core/kernel/languages/phrases_cache.php (.../phrases_cache.php) (revision 8402)
@@ -26,7 +26,7 @@
function Init($prefix, $special = '')
{
- $this->LanguageId = $this->Application->GetVar('m_lang');
+ $this->LanguageId = constOn('IS_INSTALL') ? 1 : $this->Application->GetVar('m_lang');
if (isset($this->Application->Caches['PhraseList'])) {
$this->LoadPhrases( $this->Application->Caches['PhraseList'] );
}
Index: trunk/core/units/general/helpers/permissions_helper.php
===================================================================
diff -u -N -r8369 -r8402
--- trunk/core/units/general/helpers/permissions_helper.php (.../permissions_helper.php) (revision 8369)
+++ trunk/core/units/general/helpers/permissions_helper.php (.../permissions_helper.php) (revision 8402)
@@ -121,6 +121,31 @@
}
/**
+ * Returns owner + primary category for each item (used for permission checking)
+ *
+ * @param string $prefix
+ * @param string $ids
+ * @return Array
+ * @author Alex
+ */
+ function GetCategoryItemData($prefix, $ids)
+ {
+ if (is_array($ids)) {
+ $ids = implode(',', $ids);
+ }
+ $id_field = $this->Application->getUnitOption($prefix, 'IDField');
+ $table_name = $this->Application->getUnitOption($prefix, 'TableName');
+ $ci_table = $this->Application->getUnitOption('ci', 'TableName');
+
+ $sql = 'SELECT '.$id_field.', CreatedById, ci.CategoryId
+ FROM '.$table_name.' item_table
+ LEFT JOIN '.$ci_table.' ci ON ci.ItemResourceId = item_table.ResourceId
+ WHERE '.$id_field.' IN ('.$ids.') AND (ci.PrimaryCat = 1)';
+ return $this->Conn->Query($sql, $id_field);
+ }
+
+
+ /**
* Checks non-system permission on event per category basis
*
* @param kEvent $event
@@ -132,6 +157,8 @@
$top_prefix = $event->getEventParam('top_prefix');
$event_handler =& $this->Application->recallObject($event->Prefix.'_EventHandler');
+ /* @var $event_handler kCatDBEventHandler */
+
if ($event->Prefix != $top_prefix) {
$top_event = new kEvent($top_prefix.':'.$event->Name);
$id = $event_handler->getPassedID($top_event);
@@ -140,11 +167,6 @@
$id = $event_handler->getPassedID($event);
}
- // 1. get primary category of category item
- $id_field = $this->Application->getUnitOption($top_prefix, 'IDField');
- $table_name = $this->Application->getUnitOption($top_prefix, 'TableName');
- $ci_table = $this->Application->getUnitOption('ci', 'TableName');
-
if (!$id) {
// item being created -> check by current (before editing started, saved in OnPreCreate event) category permissions
$category_id = $this->Application->IsAdmin() ? $this->Application->RecallVar('m_cat_id') : $this->Application->GetVar('m_cat_id');
@@ -154,41 +176,19 @@
}
else {
// item being edited -> check by it's primary category permissions
- $sql = 'SELECT ci.CategoryId, main_table.CreatedById
- FROM '.$table_name.' main_table
- LEFT JOIN '.$ci_table.' ci ON ci.ItemResourceId = main_table.ResourceId
- WHERE (main_table.'.$id_field.' = '.$id.') AND (ci.PrimaryCat = 1)';
- $item_info = $this->Conn->GetRow($sql);
- $category_id = $item_info['CategoryId'];
- $owner_id = $item_info['CreatedById'];
+ $items_info = $this->GetCategoryItemData($top_prefix, $id);
+ $category_id = $items_info[$id]['CategoryId'];
+ $owner_id = $items_info[$id]['CreatedById'];
}
// specific permission check for pending & owner permissions: begin
- if (substr($event->Name, 0, 9) == 'OnPreSave' || $event->Name == 'OnCreate' || $event->Name == 'OnUpdate') {
- if ($event_handler->isNewItemCreate($event)) {
- $check_status = $this->AddCheckPermission($category_id, $top_prefix);
- }
- else {
- $check_status = $this->AddCheckPermission($category_id, $top_prefix) ||
- $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix);
- }
-
- if (!$check_status) {
- $event->status = erPERM_FAIL;
- }
+ $new_item = $this->Application->IsAdmin() && $event_handler->isNewItemCreate($event) ? true : false;
+ $check_status = $this->checkCombinedPermissions($event, $owner_id, $category_id, $new_item);
+ if (isset($check_status)) {
return $check_status;
}
-
- if ($event->Name == 'OnMassDelete') {
- $check_status = $this->DeleteCheckPermission($owner_id, $category_id, $top_prefix);
- if (!$check_status) {
- $event->status = erPERM_FAIL;
- }
- return $check_status;
- }
// specific permission check for pending & owner permissions: end
-
$perm_status = false;
$check_perms = $this->getPermissionByEvent($event, $event_perm_mapping);
@@ -205,7 +205,6 @@
continue;
}
$perm_name = $item_prefix.'.'.$perm_mapping[$perm_name];
- $this->showDebug('Event '.$event->Name.' permission(-s): '.$perm_name.'', Array());
$perm_status = $this->CheckPermission($perm_name, 0, $category_id);
if ($perm_status) {
@@ -227,12 +226,57 @@
return $perm_status;
}
- function showDebug($text, $params)
+ /**
+ * Allows to check combined permissions (*.owner, *.pending) for add/modify/delete operations from admin & front-end
+ *
+ * @param kEvent $event
+ * @param int $owner_id
+ * @param int $category_id
+ * @param bool $new_item
+ * @return mixed
+ */
+ function checkCombinedPermissions(&$event, $owner_id, $category_id, $new_item = false)
{
- return ;
- $is_ajax = $this->Application->GetVar('ajax') == 'yes' || isset($params['ajax']) || isset($params['tab_init']);
- if (!$this->Application->isDebugMode() || $is_ajax) return true;
- echo $text.'
';
+ $ret = null; // true/false when used, null when not used
+ $top_prefix = $event->getEventParam('top_prefix');
+
+ // check admin permission
+ if (substr($event->Name, 0, 9) == 'OnPreSave') {
+ if ($new_item) {
+ $ret = $this->AddCheckPermission($category_id, $top_prefix);
+ }
+ else {
+ // add & modify because $new_item is false, when item is aready created & then saved in temp table (even with 0 id)
+ $ret = $this->AddCheckPermission($category_id, $top_prefix) ||
+ $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix);
+ }
+ }
+
+ // check front-end permissions
+ switch ($event->Name) {
+ case 'OnItemLoad':
+ break;
+
+ case 'OnCreate':
+ $ret = $this->AddCheckPermission($category_id, $top_prefix);
+ break;
+
+ case 'OnUpdate':
+ $ret = $this->ModifyCheckPermission($owner_id, $category_id, $top_prefix);
+ break;
+
+ case 'OnDelete':
+ case 'OnMassDelete':
+ $ret = $this->DeleteCheckPermission($owner_id, $category_id, $top_prefix);
+ break;
+ }
+
+ if ($ret === 0) {
+ // permission check failed (user has no permission)
+ $event->status = erPERM_FAIL;
+ }
+
+ return $ret;
}
function TagPermissionCheck($params, $tag_name)
@@ -243,7 +287,6 @@
if ($permission_groups) {
// check permissions by permission names in current category
- $this->showDebug('Tag '.$tag_name.' permission(-s): '.$permission_groups.'', $params);
$permission_groups = explode('|', $permission_groups);
$group_has_permission = false;
@@ -270,7 +313,6 @@
}
elseif ($perm_event) {
// check permission by event name
- $this->showDebug('Tag '.$tag_name.' permission_event: '.$perm_event.'', $params);
list($prefix, $event) = explode(':', $perm_event);
$event_handler =& $this->Application->recallObject($prefix.'_EventHandler');
return $event_handler->CheckPermission( new kEvent($perm_event) );
@@ -414,14 +456,20 @@
// cached view permission of category: end
}
- if ($cat_id == 0) {
+ if (is_numeric($cat_id) && $cat_id == 0) {
$cat_hierarchy = Array(0);
}
else {
- $sql = 'SELECT ParentPath
+ if (strpos($cat_id, '|') !== false) {
+ $cat_hierarchy = $cat_id;
+ }
+ else {
+ $sql = 'SELECT ParentPath
FROM '.$this->Application->getUnitOption('c', 'TableName').'
WHERE CategoryId = '.$cat_id;
- $cat_hierarchy = $this->Conn->GetOne($sql);
+ $cat_hierarchy = $this->Conn->GetOne($sql);
+ }
+
$cat_hierarchy = explode('|', substr($cat_hierarchy, 1, -1));
$cat_hierarchy = array_reverse($cat_hierarchy);
array_push($cat_hierarchy, 0);
@@ -479,6 +527,38 @@
}
/**
+ * Allows to check VIEW & "OWNER.VIEW.PENDING" permission combinations on item
+ *
+ * @param int $owner_id user_id, that is owner of the item
+ * @param int $category_id primary category of item
+ * @param string $prefix prefix of item
+ * @return int {0 - no VIEW permission, 1 - has VIEW permission}
+ */
+ function ViewCheckPermission($owner_id, $category_id, $prefix)
+ {
+ $perm_prefix = $this->Application->getUnitOption($prefix, 'PermItemPrefix');
+
+ // in progress
+ $use_pending_editing = $this->Application->getUnitOption($prefix, 'UsePendingEditing');
+
+
+ $live_delete = $this->CheckPermission($perm_prefix.'.VIEW', ptCATEGORY, $category_id);
+ if ($live_delete) {
+ return 1;
+ }
+
+ if ($owner_id == $this->Application->RecallVar('user_id')) {
+ // user is item's OWNER -> check this permissions first
+ $live_delete = $this->CheckPermission($perm_prefix.'.OWNER.DELETE', ptCATEGORY, $category_id);
+ if ($live_delete) {
+ return 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
* Allows to check DELETE & OWNER.DELETE permission combinations on item
*
* @param int $owner_id user_id, that is owner of the item
Index: trunk/core/kernel/db/dblist.php
===================================================================
diff -u -N -r8388 -r8402
--- trunk/core/kernel/db/dblist.php (.../dblist.php) (revision 8388)
+++ trunk/core/kernel/db/dblist.php (.../dblist.php) (revision 8402)
@@ -350,6 +350,14 @@
$sql = $q.' '.$this->Conn->getLimitClause($this->Offset,$limit);
$this->Records = $this->Conn->Query($sql);
+
+ if (!$this->Records && ($this->Page > 1)) {
+ // no records & page > 1, try to reset to 1st page (works only when list in not counted before)
+ $this->Application->StoreVar($this->getPrefixSpecial().'_Page', 1);
+ $this->SetPage(1);
+ $this->Query($force);
+ }
+
$this->SelectedCount = count($this->Records);
if (!$this->Counted) $this->RecordsCount = $this->SelectedCount;
if (!$this->Counted && $this->SelectedCount > $this->PerPage && $this->PerPage != -1) $this->SelectedCount--;
Index: trunk/core/kernel/processors/tag_processor.php
===================================================================
diff -u -N -r8358 -r8402
--- trunk/core/kernel/processors/tag_processor.php (.../tag_processor.php) (revision 8358)
+++ trunk/core/kernel/processors/tag_processor.php (.../tag_processor.php) (revision 8402)
@@ -76,7 +76,6 @@
$this->Special = $backup_special;
if ($flag_values['js_escape']) {
- $ret = str_replace('\'', ''', $ret);
$ret = addslashes($ret);
$ret = str_replace(Array("\r", "\n"), Array('\r', '\n'), $ret);
$ret = str_replace('', "'+'script>", $ret);
Index: trunk/core/admin_templates/tools/system_tools.tpl
===================================================================
diff -u -N -r8397 -r8402
--- trunk/core/admin_templates/tools/system_tools.tpl (.../system_tools.tpl) (revision 8397)
+++ trunk/core/admin_templates/tools/system_tools.tpl (.../system_tools.tpl) (revision 8402)
@@ -23,7 +23,6 @@
', '');" value="Go">
|
- |
@@ -41,7 +40,7 @@
Table Structure:
|
-
+ |
table name (prefix optional) OR unit config prefix
Index: trunk/kernel/units/visits/visits_event_handler.php
===================================================================
diff -u -N -r7391 -r8402
--- trunk/kernel/units/visits/visits_event_handler.php (.../visits_event_handler.php) (revision 7391)
+++ trunk/kernel/units/visits/visits_event_handler.php (.../visits_event_handler.php) (revision 8402)
@@ -3,6 +3,20 @@
class VisitsEventHandler extends kDBEventHandler {
/**
+ * Allows to override standart permission mapping
+ *
+ */
+ function mapPermissions()
+ {
+ parent::mapPermissions();
+ $permissions = Array(
+ 'OnItemBuild' => Array('self' => true),
+ );
+
+ $this->permMapping = array_merge($this->permMapping, $permissions);
+ }
+
+ /**
* Registers user visit to site
*
* @param kEvent $event
Index: trunk/core/kernel/application.php
===================================================================
diff -u -N -r8178 -r8402
--- trunk/core/kernel/application.php (.../application.php) (revision 8178)
+++ trunk/core/kernel/application.php (.../application.php) (revision 8402)
@@ -325,6 +325,7 @@
return false;
}
$modules_helper =& $this->recallObject('ModulesHelper');
+ $this->ModuleInfo = $this->Conn->Query('SELECT * FROM '.TABLE_PREFIX.'Modules WHERE Loaded = 1 ORDER BY LoadOrder', 'Name');
$sql = 'SELECT *
FROM '.TABLE_PREFIX.'Modules
WHERE '.$modules_helper->getWhereClause().'
@@ -1867,6 +1868,7 @@
*/
function &recallTagProcessor($prefix)
{
+ $this->InitParser(); // because kDBTagProcesor is in TemplateParser dependencies
$result =& $this->recallObject($prefix.'_TagProcessor');
return $result;
}
@@ -2245,8 +2247,8 @@
*/
function LoggedIn()
{
- return $this->Session->LoggedIn();
-
+ // no session during expiration process
+ return is_null($this->Session) ? false : $this->Session->LoggedIn();
}
/**
@@ -2484,6 +2486,10 @@
*/
function resetCounters($tables)
{
+ if (constOn('IS_INSTALL')) {
+ return ;
+ }
+
$count_helper =& $this->Application->recallObject('CountHelper');
/* @var $count_helper kCountHelper */
Index: trunk/core/kernel/globals.php
===================================================================
diff -u -N -r7887 -r8402
--- trunk/core/kernel/globals.php (.../globals.php) (revision 7887)
+++ trunk/core/kernel/globals.php (.../globals.php) (revision 8402)
@@ -113,7 +113,7 @@
{
if(!defined($const_name)) define($const_name,$const_value);
}
-
+
if( !function_exists('parse_portal_ini') )
{
function parse_portal_ini($file, $parse_section = false)
@@ -335,6 +335,9 @@
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
}
+ elseif ($request_type == 'GET' && isset($post) && strlen($post) > 0) {
+ curl_setopt($ch, CURLOPT_URL, preg_match('/\?/', $url) ? $url.'&'.$post : $url.'?'.$post);
+ }
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@@ -488,4 +491,62 @@
}
return $string;
}
+
+ /**
+ * Checks, that user IP address is within allowed range
+ *
+ * @param string $ip_list semi-column (by default) separated ip address list
+ * @param string $separator ip address separator (default ";")
+ *
+ * @return bool
+ */
+ function ipMatch($ip_list, $separator = ';')
+ {
+ $ip_match = false;
+ $ip_addresses = $ip_list ? explode($separator, $ip_list) : Array ();
+ foreach ($ip_addresses as $ip_address) {
+ if (netMatch($ip_address, $_SERVER['REMOTE_ADDR'])) {
+ $ip_match = true;
+ break;
+ }
+ }
+
+ return $ip_match;
+ }
+
+ function netMatch($network, $ip) {
+ $network = trim($network);
+ $ip = trim($ip);
+
+ if ($network == $ip) {
+ // comparing 2 ip addresses directly
+ return true;
+ }
+
+ $d = strpos($network, '-');
+ if ($d === false) {
+ // sigle subnet specified
+ $ip_arr = explode('/', $network);
+
+ if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) {
+ $ip_arr[0] .= '.0'; // Alternate form 194.1.4/24
+ }
+
+ $network_long = ip2long($ip_arr[0]);
+ $x = ip2long($ip_arr[1]);
+
+ $mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1]));
+ $ip_long = ip2long($ip);
+
+ return ($ip_long & $mask) == ($network_long & $mask);
+ }
+ else {
+ // ip address range specified
+ $from = ip2long(trim(substr($network, 0, $d)));
+ $to = ip2long(trim(substr($network, $d + 1)));
+
+ $ip = ip2long($ip);
+ return ($ip >= $from && $ip <= $to);
+ }
+ }
?>
\ No newline at end of file
Index: trunk/core/admin_templates/js/uploader.js
===================================================================
diff -u -N -r8178 -r8402
--- trunk/core/admin_templates/js/uploader.js (.../uploader.js) (revision 8178)
+++ trunk/core/admin_templates/js/uploader.js (.../uploader.js) (revision 8402)
@@ -33,7 +33,7 @@
this.uploaded = 0;
this.flash_id = UploadsManager.NextFlashId();
- this.swf = new SWFObject('SWFUpload.swf', this.flash_id, "0", "0", "8", "#000000");
+ this.swf = new SWFObject('swfupload.swf', this.flash_id, "0", "0", "8", "#000000");
this.swf.setAttribute('style', '');
this.swf.addVariable("uploadScript", '');
this.swf.addVariable("maxFiles", escape(this.params.multiple));
@@ -48,7 +48,6 @@
this.swf.addVariable("uploadFileCancelCallback", escape('UploadsManager.FileCancelled'));
this.swf.addVariable("uploadQueueCompleteCallback", escape('UploadsManager.UploadQueueComplete'));
this.swf.addVariable("uploadFileErrorCallback", escape('UploadsManager.UploadError'));
- this.swf.addVariable("uploadCancelCallback", escape('uploadCancel'));
this.swf.addVariable("autoUpload", escape('false'));
// this.swf.addVariable("flashLoadedCallback", 'flashLoadedCallback');
@@ -310,7 +309,7 @@
upl.files.push(file);
upl.total += file.size;
if (upl.files[0].uploaded) {
- UploadsManager.DeleteFile(file.uploader_id, upl.files[0].name);
+ UploadsManager.DeleteFile(file.uploader_id, upl.files[0].name, true);
}
else {
upl.flash.cancelFile(upl.files[0].id);
@@ -337,15 +336,25 @@
UploadsManager.UploadError = function(errno, file, msg)
{
- alert('error '+errno)
- alert('Error: '+msg+' on file '+file.name);
+ this.Uploaders[file.uploader_id].RemoveFile(file);
+ if (errno == -10) {
+ switch (msg.toString()) {
+ case '403':
+ msg = 'You don\'t have permission to upload';
+ break;
+ case '500':
+ msg = 'Write permissions not set on the server, please contact server administrator';
+ break;
+ }
+ }
+ alert('Error: '+msg+'\nOccured on file '+file.name);
}
-UploadsManager.DeleteFile = function(mov, fname)
+UploadsManager.DeleteFile = function(mov, fname, confirmed)
{
- if (!confirm('Are you sure you want to delete this file?')) return;
+ if (!confirmed && !confirm('Are you sure you want to delete this file?')) return;
Request.makeRequest(
- this.Uploaders[mov].deleteURL.replace('#FILE#', fname),
+ this.Uploaders[mov].deleteURL.replace('#FILE#', fname).replace('#FIELD#', this.Uploaders[mov].params.field),
false, '',
function(req, fname, upl) {
upl.RemoveFile({id:fname})
Index: trunk/core/units/general/cat_event_handler.php
===================================================================
diff -u -N -r8369 -r8402
--- trunk/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 8369)
+++ trunk/core/units/general/cat_event_handler.php (.../cat_event_handler.php) (revision 8402)
@@ -49,31 +49,28 @@
$this->Application->StoreVar('m_cat_id', $root_category);
}
- if ($event->Name == 'OnEdit' || $event->Name == 'OnSave') {
+ $check_events = Array ('OnEdit', 'OnSave', 'OnMassDelete');
+ if (in_array($event->Name, $check_events)) {
// check each id from selected individually and only if all are allowed proceed next
- if ($event->Name == 'OnEdit') {
- $selected_ids = implode(',', $this->StoreSelectedIDs($event));
- }
- else {
+ if ($event->Name == 'OnSave') {
$selected_ids = implode(',', $this->getSelectedIDs($event, true));
if (!$selected_ids) {
$selected_ids = 0; // when saving newly created item (OnPreCreate -> OnPreSave -> OnSave)
}
}
+ else {
+ $selected_ids = implode(',', $this->StoreSelectedIDs($event));
+ }
$perm_value = true;
if (strlen($selected_ids)) {
- $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField');
- $table_name = $this->Application->getUnitOption($event->Prefix, 'TableName');
- $sql = 'SELECT '.$id_field.', CreatedById, ci.CategoryId
- FROM '.$table_name.' item_table
- LEFT JOIN '.$this->Application->getUnitOption('ci', 'TableName').' ci ON ci.ItemResourceId = item_table.ResourceId
- WHERE '.$id_field.' IN ('.$selected_ids.') AND (ci.PrimaryCat = 1)';
- $items = $this->Conn->Query($sql, $id_field);
-
$perm_helper =& $this->Application->recallObject('PermissionsHelper');
+ /* @var $perm_helper kPermissionsHelper */
+
+ $items = $perm_helper->GetCategoryItemData($event->Prefix, $selected_ids);
+ $check_method = ($event->Name == 'OnMassDelete') ? 'DeleteCheckPermission' : 'ModifyCheckPermission';
foreach ($items as $item_id => $item_data) {
- if ($perm_helper->ModifyCheckPermission($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) == 0) {
+ if ($perm_helper->$check_method($item_data['CreatedById'], $item_data['CategoryId'], $event->Prefix) == 0) {
// one of items selected has no permission
$perm_value = false;
break;
@@ -357,7 +354,7 @@
if ( !$this->Application->IsAdmin() )
{
- $object->addFilter('status_filter', $object->TableName.'.Status = 1');
+ $object->addFilter('status_filter', '%1$s.Status = 1');
if ($this->Application->getUnitOption($event->Prefix, 'UsePendingEditing')) {
// if category item uses pending editing abilities, then in no cases show pending copies on front
$object->addFilter('original_filter', '%1$s.OrgId = 0 OR %1$s.OrgId IS NULL');
@@ -1749,14 +1746,37 @@
function OnCreate(&$event)
{
parent::OnCreate($event);
+ $this->SetFrontRedirectTemplate($event, 'suggest');
+ }
+
+ /**
+ * Creates category item & redirects to confirmation template (front-end only)
+ *
+ * @param kEvent $event
+ */
+ function OnUpdate(&$event)
+ {
+ parent::OnUpdate($event);
+ $this->SetFrontRedirectTemplate($event, 'modify');
+ }
+
+ /**
+ * Sets next template to one required for front-end after adding/modifying item
+ *
+ * @param kEvent $event
+ * @param string $template_key - {suggest,modify}
+ */
+ function SetFrontRedirectTemplate(&$event, $template_key)
+ {
+ if ($this->Application->IsAdmin() || $event->status != erSUCCESS) {
+ return ;
+ }
- if (!$this->Application->IsAdmin()) {
- $event->SetRedirectParam('opener', 's');
+ $event->SetRedirectParam('opener', 's');
- $object =& $event->getObject();
- $next_template = $object->GetDBField('Status') == STATUS_ACTIVE ? 'suggest_confirm_template' : 'suggest_pending_confirm_template';
- $event->redirect = $this->Application->GetVar($next_template);
- }
+ $object =& $event->getObject();
+ $next_template = $object->GetDBField('Status') == STATUS_ACTIVE ? 'confirm_template' : 'pending_confirm_template';
+ $event->redirect = $this->Application->GetVar($template_key.'_'.$next_template);
}
/**
Index: trunk/core/units/visits/visits_event_handler.php
===================================================================
diff -u -N -r7391 -r8402
--- trunk/core/units/visits/visits_event_handler.php (.../visits_event_handler.php) (revision 7391)
+++ trunk/core/units/visits/visits_event_handler.php (.../visits_event_handler.php) (revision 8402)
@@ -3,6 +3,20 @@
class VisitsEventHandler extends kDBEventHandler {
/**
+ * Allows to override standart permission mapping
+ *
+ */
+ function mapPermissions()
+ {
+ parent::mapPermissions();
+ $permissions = Array(
+ 'OnItemBuild' => Array('self' => true),
+ );
+
+ $this->permMapping = array_merge($this->permMapping, $permissions);
+ }
+
+ /**
* Registers user visit to site
*
* @param kEvent $event
Index: trunk/core/kernel/utility/formatters/unit_formatter.php
===================================================================
diff -u -N -r7635 -r8402
--- trunk/core/kernel/utility/formatters/unit_formatter.php (.../unit_formatter.php) (revision 7635)
+++ trunk/core/kernel/utility/formatters/unit_formatter.php (.../unit_formatter.php) (revision 8402)
@@ -29,6 +29,7 @@
{
if( !isset($options['master_field']) )
{
+ if ($value == -1) return; // for infinity setting, otherwise infinity is incorrectly converted back to Kg
$regional =& $this->Application->recallObject('lang.current');
switch( $regional->GetDBField('UnitSystem') )
{
Index: trunk/core/kernel/utility/formatters/serialized_formatter.php
===================================================================
diff -u -N -r4758 -r8402
--- trunk/core/kernel/utility/formatters/serialized_formatter.php (.../serialized_formatter.php) (revision 4758)
+++ trunk/core/kernel/utility/formatters/serialized_formatter.php (.../serialized_formatter.php) (revision 8402)
@@ -2,10 +2,19 @@
class kSerializedFormatter extends kFormatter {
+ function Parse($value, $field_name, &$object)
+ {
+ $options = $object->GetFieldOptions($field_name);
+ $value = array_merge_recursive2(unserialize($options['default']), $value);
+ return serialize($value);
+ }
+
function Format($value, $field_name, $object, $format=null)
{
$data = unserialize($value);
- return $data[$format];
+ $format = explode('.', $format);
+ $format = '\''.implode('\', \'', $format).'\'';
+ return eval('return getArrayValue($data, '.$format.');');
}
}
Index: trunk/core/kernel/utility/debugger.php
===================================================================
diff -u -N -r8078 -r8402
--- trunk/core/kernel/utility/debugger.php (.../debugger.php) (revision 8078)
+++ trunk/core/kernel/utility/debugger.php (.../debugger.php) (revision 8402)
@@ -840,6 +840,10 @@
$error_map['PHP5 Strict'] = Array(E_STRICT);
}
+ if (defined('E_RECOVERABLE_ERROR')) {
+ $error_map['Fatal Error (recoverable)'] = Array(E_RECOVERABLE_ERROR);
+ }
+
foreach ($error_map as $error_name => $error_codes) {
if (in_array($error_code, $error_codes)) {
return $error_name;
Index: trunk/core/kernel/db/db_event_handler.php
===================================================================
diff -u -N -r8360 -r8402
--- trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 8360)
+++ trunk/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 8402)
@@ -95,7 +95,10 @@
parent::mapPermissions();
$permissions = Array(
'OnLoad' => Array('self' => 'view', 'subitem' => 'view'),
-
+ 'OnItemBuild' => Array('self' => 'view', 'subitem' => 'view'),
+
+ 'OnBuild' => Array('self' => true),
+
'OnNew' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnCreate' => Array('self' => 'add', 'subitem' => 'add|edit'),
'OnUpdate' => Array('self' => 'edit', 'subitem' => 'add|edit'),
@@ -379,7 +382,19 @@
$auto_load = $this->Application->getUnitOption($event->Prefix,'AutoLoad');
$skip_autload = $event->getEventParam('skip_autoload');
- if($auto_load && !$skip_autload) $this->LoadItem($event);
+ if ($auto_load && !$skip_autload) {
+ $event->setEventParam('top_prefix', $this->Application->GetTopmostPrefix($event->Prefix, true));
+ if (($this->Application->RecallVar('user_id') == -1) || $this->CheckPermission($event)) {
+ // don't autoload item, when user doesn't have view permission
+ $this->LoadItem($event);
+ }
+ else {
+ // when no permission to view item -> redirect to no pemrission template
+ trigger_error('ItemLoad Permission Failed for prefix ['.$event->getPrefixSpecial().']', E_USER_WARNING);
+ $next_template = $this->Application->IsAdmin() ? 'no_permission' : $this->Application->ConfigValue('NoPermissionTemplate');
+ $this->Application->Redirect($next_template, Array('pass' => 'm'));
+ }
+ }
$actions =& $this->Application->recallObject('kActions');
$actions->Set($event->Prefix_Special.'_GoTab', '');
@@ -483,7 +498,8 @@
$sql = $this->ListPrepareQuery($event);
$sql = $this->Application->ReplaceLanguageTags($sql);
$object->setSelectSQL($sql);
-
+ $object->Counted = false; // when requery="1" should re-count records too!
+
$object->linkToParent( $this->getMainSpecial($event) );
$this->AddFilters($event);
@@ -986,12 +1002,10 @@
{
$object =& $event->getObject( Array('skip_autoload' => true) );
$object->ID = $this->getPassedID($event);
- if( $object->Delete() )
- {
+ if ($object->Delete()) {
$event->status = erSUCCESS;
}
- else
- {
+ else {
$event->status = erFAIL;
$event->redirect = false;
}
@@ -1102,6 +1116,8 @@
{
$this->setTempWindowID($event);
$this->StoreSelectedIDs($event);
+ $var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid');
+ $this->Application->RemoveVar($var_name);
$temp =& $this->Application->recallObject($event->getPrefixSpecial().'_TempHandler', 'kTempTablesHandler');
/* @var $temp kTempTablesHandler */
@@ -1126,6 +1142,17 @@
if (!$this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
$live_ids = $temp->SaveEdit($event->getEventParam('master_ids') ? $event->getEventParam('master_ids') : Array());
+
+ // Deleteing files scheduled for delete
+ $var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid');
+ $schedule = $this->Application->RecallVar($var_name);
+ $schedule = $schedule ? unserialize($schedule) : array();
+ foreach ($schedule as $data) {
+ if ($data['action'] == 'delete') {
+ unlink($data['file']);
+ }
+ }
+
if ($live_ids) {
// ensure, that newly created item ids are avalable as if they were selected from grid
// NOTE: only works if main item has subitems !!!
@@ -1783,93 +1810,6 @@
}
/**
- * Dynamically fills customdata config
- *
- * @param kEvent $event
- */
- function OnCreateCustomFields(&$event)
- {
- if (defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound('CustomField')) {
- return false;
- }
- $main_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
- if (!$main_prefix) return false;
- $item_type = $this->Application->getUnitOption($main_prefix, 'ItemType');
- if (!$item_type) {
- // no main config of such type
- return false;
- }
-
- // 1. get custom field information
- $sql = 'SELECT *
- FROM '.TABLE_PREFIX.'CustomField
- WHERE Type = '.$item_type.'
- ORDER BY CustomFieldId';
- $custom_fields = $this->Conn->Query($sql, 'CustomFieldId');
- if (!$custom_fields) {
- // config doesn't have custom fields
- return false;
- }
-
- // 2. create fields (for customdata item)
- $fields = $this->Application->getUnitOption($event->Prefix, 'Fields', Array());
- $field_options = Array('type' => 'string', 'formatter' => 'kMultiLanguage', 'db_type' => 'text', 'default' => '');
- foreach ($custom_fields as $custom_id => $custom_params) {
- if (isset($fields['cust_'.$custom_id])) continue;
- $fields['cust_'.$custom_id] = $field_options;
- }
- $this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
-
- // 3. create virtual & calculated fields (for main item)
- $calculated_fields = Array();
- $virtual_fields = $this->Application->getUnitOption($main_prefix, 'VirtualFields', Array());
-
- $cf_helper =& $this->Application->recallObject('InpCustomFieldsHelper');
- $field_options = Array('type' => 'string', 'not_null' => 1, 'default' => '');
- $ml_formatter =& $this->Application->recallObject('kMultiLanguage');
-
- foreach ($custom_fields as $custom_id => $custom_params) {
- switch ($custom_params['ElementType']) {
- case 'date':
- case 'datetime':
- unset($field_options['options']);
- $field_options['formatter'] = 'kDateFormatter';
- break;
-
- case 'select':
- case 'multiselect':
- case 'radio':
- if ($custom_params['ValueList']) {
- $field_options['options'] = $cf_helper->GetValuesHash($custom_params['ValueList']);
- $field_options['formatter'] = 'kOptionsFormatter';
- }
- break;
-
- default:
- unset($field_options['options'], $field_options['formatter']);
- break;
- }
-
- $custom_name = $custom_params['FieldName'];
- $calculated_fields['cust_'.$custom_name] = 'cust.'.$ml_formatter->LangFieldName('cust_'.$custom_id);
- if (!isset($virtual_fields['cust_'.$custom_name])) {
- $virtual_fields['cust_'.$custom_name] = Array();
- }
- $virtual_fields['cust_'.$custom_name] = array_merge_recursive2($field_options, $virtual_fields['cust_'.$custom_name]);
- $custom_fields[$custom_id] = $custom_name;
- }
-
- $config_calculated_fields = $this->Application->getUnitOption($main_prefix, 'CalculatedFields', Array());
- foreach ($config_calculated_fields as $special => $special_fields) {
- $config_calculated_fields[$special] = array_merge_recursive2($config_calculated_fields[$special], $calculated_fields);
- }
- $this->Application->setUnitOption($main_prefix, 'CalculatedFields', $config_calculated_fields);
-
- $this->Application->setUnitOption($main_prefix, 'CustomFields', $custom_fields);
- $this->Application->setUnitOption($main_prefix, 'VirtualFields', $virtual_fields);
- }
-
- /**
* Saves selected user in needed field
*
* @param kEvent $event
@@ -2067,6 +2007,8 @@
$section = $event->getSection();
if (!$perm_helper->CheckUserPermission($user, $section.'.add') && !$perm_helper->CheckUserPermission($user, $section.'.edit')) {
$event->status = erPERM_FAIL;
+ header('HTTP/1.0 403 You don\'t have permissions to upload');
+ exit;
return;
}
@@ -2079,6 +2021,11 @@
$id = $this->Application->GetVar('id');
if ($id) $fname = $id.'_'.$fname;
+ if (!is_writable($tmp_path)) {
+ header('HTTP/1.0 500 Write permissions not set on the server');
+ exit;
+ }
+
move_uploaded_file($value['tmp_name'], $tmp_path.$fname);
exit;
}
@@ -2090,12 +2037,16 @@
*/
function OnDeleteFile(&$event)
{
- $var_name = $event->getPrefixSpecial().'_file_pending_actions';
+ if (strpos($this->Application->GetVar('file'), '../') !== false) return ;
+ $object =& $event->getObject(array('skip_autoload'=>true));
+ $options = $object->GetFieldOptions($this->Application->GetVar('field'));
+
+ $var_name = $event->getPrefixSpecial().'_file_pending_actions'.$this->Application->GetVar('m_wid');
$schedule = $this->Application->RecallVar($var_name);
$schedule = $schedule ? unserialize($schedule) : array();
- $schedule[] = array('action'=>'delete', 'file'=>$this->Application->GetVar('file'));
+ $schedule[] = array('action'=>'delete', 'file'=>$path = FULL_PATH.$options['upload_dir'].$this->Application->GetVar('file'));
$this->Application->StoreVar($var_name, serialize($schedule));
- exit;
+ $this->Application->Session->SaveData();
}
/**
@@ -2105,6 +2056,7 @@
*/
function OnViewFile(&$event)
{
+ if (strpos($this->Application->GetVar('file'), '../') !== false) return ;
if ($this->Application->GetVar('tmp')) {
$path = WRITEABLE.'/tmp/'.$this->Application->GetVar('id').'_'.$this->Application->GetVar('file');
}
@@ -2120,6 +2072,8 @@
header('Content-Length: '.filesize($path));
header('Content-Type: '.$type);
+ safeDefine('DBG_SKIP_REPORTING',1);
+
readfile($path);
exit();
}
Index: trunk/core/kernel/utility/unit_config_reader.php
===================================================================
diff -u -N -r8104 -r8402
--- trunk/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 8104)
+++ trunk/core/kernel/utility/unit_config_reader.php (.../unit_config_reader.php) (revision 8402)
@@ -203,6 +203,7 @@
*/
function ParseConfigs()
{
+ // 1. process normal configs and their dependencies
$prioritized_configs = array();
foreach ($this->configData as $prefix => $config) {
if (isset($config['ConfigPriority'])) {
@@ -218,10 +219,15 @@
$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()
@@ -233,10 +239,57 @@
$this->Application->HandleEvent( new kEvent($prefix.':OnAfterConfigRead') );
$this->AfterConfigProcessed[] = $prefix;
}
- if ($this->StoreCache) $this->CacheParsedData();
+
+ if ($this->StoreCache) {
+ $this->processDynamicClones();
+ $this->CacheParsedData();
+
+ if ($this->Application->isDebugMode(false) && constOn('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);
+ }
+ }
+ }
}
/**
+ * Re-reads all configs
+ *
+ */
+ function ReReadConfigs()
+ {
+ $this->includeConfigFiles(MODULES_PATH);
+ $this->ParseConfigs();
+ $this->AfterConfigRead();
+ $this->processDynamicClones();
+ }
+
+ /**
+ * 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;
+ }
+ }
+
+ /**
* Register nessasary classes
* This method should only process the data which is cached!
*
@@ -349,15 +402,14 @@
// replacement templates defined in this config
$this->Application->ReplacementTemplates = array_merge_recursive2($this->Application->ReplacementTemplates, $config['ReplacementTemplates']);
}
-
- if ( $this->Application->isDebugMode(false) && constOn('DBG_VALIDATE_CONFIGS') && isset($config['TableName']) ) {
- $this->ValidateConfig($prefix);
- }
}
+
function ValidateConfig($prefix)
{
global $debugger;
+
$config =& $this->configData[$prefix];
+
$tablename = $config['TableName'];
$float_types = Array ('float', 'double', 'numeric');
$conn =& $this->Application->GetADODBConnection();
@@ -369,8 +421,10 @@
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 %s exists in the database, but is not defined in config',
'default_missing' => 'Default value for field %s not set in config',
@@ -380,6 +434,7 @@
'invalid_default' => 'Default value for field %s%s not sync. to db (in config = %s, in db = %s)',
'type_missing' => 'Type definition for field %s missing in config',
);
+
$config_errors = Array ();
$tablename = preg_replace('/^'.preg_quote(TABLE_PREFIX, '/').'(.*)/', '\\1', $tablename); // remove table prefix
@@ -391,6 +446,7 @@
// skip multilingual fields
continue;
}
+
if (!array_key_exists ($f_name, $config['Fields'])) {
$config_errors[] = sprintf($error_messages['field_not_found'], $f_name);
}
@@ -405,6 +461,7 @@
$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']) ) {
@@ -419,9 +476,11 @@
$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'], 'IDField ', $f_name, $this->varDump($options['default']), $this->varDump($field['Default']));
@@ -433,18 +492,19 @@
}
}
}
+
if ($config_errors) {
$error_prefix = 'Config Error'.(count($config_errors) > 1 ? 's' : '').': for prefix '.$config_link.' ('.$tablename.') in unit config: ';
$config_errors = $error_prefix.' '.implode(' ', $config_errors);
+
$debugger->appendHTML($config_errors);
- safeDefine('DBG_RAISE_ON_WARNINGS', 1);
- }
+ safeDefine('DBG_RAISE_ON_WARNINGS', 1);
+ }
}
function varDump($value)
{
return ''.var_export($value, true).' of '.gettype($value);
-
}
function ProcessDependencies($prefix)
@@ -464,7 +524,7 @@
function postProcessConfig($prefix, $config_key, $dst_prefix_var)
{
$main_config =& $this->configData[$prefix];
- $sub_configs = getArrayValue($main_config, $config_key);
+ $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();
}
Index: trunk/core/units/general/cat_tag_processor.php
===================================================================
diff -u -N -r8391 -r8402
--- trunk/core/units/general/cat_tag_processor.php (.../cat_tag_processor.php) (revision 8391)
+++ trunk/core/units/general/cat_tag_processor.php (.../cat_tag_processor.php) (revision 8402)
@@ -209,7 +209,7 @@
$object =& $this->getObject($params);
/* @var $object kDBItem */
- $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('CategoryId') : $this->Application->GetVar('m_cat_id');
+ $params['cat_id'] = $object->isLoaded() ? $object->GetDBField('ParentPath') : $this->Application->GetVar('m_cat_id');
return $perm_helper->TagPermissionCheck($params, $this->getPrefixSpecial().'_HasPermission');
}
Index: trunk/core/units/categories/categories_tag_processor.php
===================================================================
diff -u -N -r8385 -r8402
--- trunk/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 8385)
+++ trunk/core/units/categories/categories_tag_processor.php (.../categories_tag_processor.php) (revision 8402)
@@ -6,18 +6,15 @@
{
$object =& $this->getObject($params);
- $sql = 'SELECT COUNT(*)
- FROM '.$object->TableName.'
- WHERE ParentPath LIKE "'.$object->GetDBField('ParentPath').'%"';
-
if (isset($params['today']) && $params['today']) {
- $sql .= ' AND CreatedOn > '.(adodb_mktime() - 86400);
+ $sql = 'SELECT COUNT(*)
+ FROM '.$object->TableName.'
+ WHERE (ParentPath LIKE "'.$object->GetDBField('ParentPath').'%") AND (CreatedOn > '.(adodb_mktime() - 86400).')';
+ return $this->Conn->GetOne($sql) - 1;
}
- if (!$this->Application->IsAdmin()) {
- $sql .= ' AND Status = '.STATUS_ACTIVE;
- }
- return $this->Conn->GetOne($sql) - 1;
+ return $object->GetDBField('CachedDescendantCatsQty');
+
}
function IsNew($params)
Index: trunk/core/kernel/utility/email_send.php
===================================================================
diff -u -N -r7855 -r8402
--- trunk/core/kernel/utility/email_send.php (.../email_send.php) (revision 7855)
+++ trunk/core/kernel/utility/email_send.php (.../email_send.php) (revision 8402)
@@ -1913,27 +1913,51 @@
{
if (isset($message)) {
// if message is given directly, then use it
- $message_headers = Array ();
- list ($headers, $message_body) = explode("\n\n", $message, 2);
- $headers = explode("\n", $headers);
- foreach ($headers as $header) {
- $header = explode(':', $header, 2);
- $message_headers[ trim($header[0]) ] = trim($header[1]);
+ if (is_array($message)) {
+ $message_headers =& $message[0];
+ $message_body =& $message[1];
}
+ else {
+ $message_headers = Array ();
+ list ($headers, $message_body) = explode("\n\n", $message, 2);
+ $headers = explode("\n", $headers);
+ foreach ($headers as $header) {
+ $header = explode(':', $header, 2);
+ $message_headers[ trim($header[0]) ] = trim($header[1]);
+ }
+ }
$composed = true;
} else {
// direct message not given, then assemble message from available parts
$composed = $this->GetHeadersAndBody($message_headers, $message_body);
}
- if ($composed && $immediate_send) {
- $send_method = 'Send'.$this->sendMethod;
- $result = $this->$send_method($message_headers, $message_body);
-
- if ($immediate_clear) {
- $this->Clear();
+ if ($composed) {
+ if ($immediate_send) {
+ $send_method = 'Send'.$this->sendMethod;
+ $result = $this->$send_method($message_headers, $message_body);
+
+ if ($immediate_clear) {
+ $this->Clear();
+ }
+ return $result;
}
- return $result;
+ else {
+ $fields_hash = Array (
+ 'ToEmail' => $message_headers['To'],
+ 'Subject' => $message_headers['Subject'],
+ 'Queued' => adodb_mktime(),
+ 'SendRetries' => 0,
+ 'LastSendRetry' => 0,
+ );
+ $fields_hash['MessageHeaders'] = serialize($message_headers);
+ $fields_hash['MessageBody'] =& $message_body;
+ $this->Conn->doInsert($fields_hash, TABLE_PREFIX.'EmailQueue');
+
+ if ($immediate_clear) {
+ $this->Clear();
+ }
+ }
}
// if not immediate send, then send result is positive :)
|