Index: branches/5.1.x/core/kernel/db/db_event_handler.php =================================================================== diff -u -r12127 -r12657 --- branches/5.1.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 12127) +++ branches/5.1.x/core/kernel/db/db_event_handler.php (.../db_event_handler.php) (revision 12657) @@ -1,6 +1,6 @@ Array('self' => 'view', 'subitem' => 'view'), 'OnItemBuild' => Array('self' => 'view', 'subitem' => 'view'), + 'OnSuggestValues' => Array('self' => 'view', 'subitem' => 'view'), 'OnBuild' => Array('self' => true), @@ -267,9 +270,17 @@ $ids = $event->getEventParam('ids'); if (isset($direct_ids) || ($ids !== false)) { - // save ids directly if they given - $this->Application->StoreVar($session_name, implode(',', $direct_ids ? $direct_ids : $ids)); - return $direct_ids ? $direct_ids : $ids; + // save ids directly if they given + reset array indexes + $resulting_ids = $direct_ids ? array_values($direct_ids) : ($ids ? array_values($ids) : false); + if ($resulting_ids) { + $this->Application->SetVar($event->getPrefixSpecial() . '_selected_ids', implode(',', $resulting_ids)); + $this->Application->LinkVar($event->getPrefixSpecial() . '_selected_ids', $session_name); + $this->Application->SetVar($event->getPrefixSpecial() . '_id', $resulting_ids[0]); + + return $resulting_ids; + } + + return Array (); } $ret = Array(); @@ -298,7 +309,7 @@ $ret = array_unique(array_merge($ret, $ids)); $this->Application->SetVar($event->getPrefixSpecial().'_selected_ids', implode(',',$ret)); - $this->Application->LinkVar($event->getPrefixSpecial().'_selected_ids', $session_name); + $this->Application->LinkVar($event->getPrefixSpecial().'_selected_ids', $session_name, '', !$ret); // optional when IDs are missing // This is critical - otherwise getPassedID will return last ID stored in session! (not exactly true) // this smells... needs to be refactored @@ -465,6 +476,8 @@ $this->Application->SetVar('t', $error_template); $this->Application->SetVar('m_cat_id', $themes_helper->getPageByTemplate($error_template)); + // in case if missing item is recalled first from event (not from template) + $this->Application->InitParser(); $this->Application->HTML = $this->Application->ParseBlock( Array ('name' => $error_template) ); $this->Application->Done(); exit; @@ -499,7 +512,10 @@ $this->LoadItem($event); $status_checked = true; - if ($user_id != -1 && !$this->Application->IsAdmin() && !$this->checkItemStatus($event)) { + $editing_mode = defined('EDITING_MODE') ? EDITING_MODE : false; + + if ($user_id != -1 && !$this->Application->IsAdmin() && !($editing_mode || $this->checkItemStatus($event))) { + // non-root user AND on front-end AND (not editing mode || incorrect status) $perm_status = false; } } @@ -699,7 +715,7 @@ $object =& $event->getObject(); $object->SetPerPage($per_page); - $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1); + $this->Application->StoreVarDefault($event->getPrefixSpecial().'_Page', 1, true); // true for optional $page = $this->Application->GetVar($event->getPrefixSpecial().'_Page'); if (!$page) { @@ -1144,27 +1160,25 @@ $object =& $event->getObject( Array('skip_autoload' => true) ); $items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) ); - if($items_info) - { - foreach($items_info as $id => $field_values) - { + if ($items_info) { + foreach ($items_info as $id => $field_values) { $object->Load($id); $object->SetFieldsFromHash($field_values); $this->customProcessing($event, 'before'); - if( $object->Update($id) ) - { + + if ( $object->Update($id) ) { $this->customProcessing($event, 'after'); - $event->status=erSUCCESS; + $event->status = erSUCCESS; } - else - { - $event->status=erFAIL; - $event->redirect=false; + else { + $event->status = erFAIL; + $event->redirect = false; break; } } } - $event->redirect_params = Array('opener'=>'u'); + + $event->SetRedirectParam('opener', 'u'); } /** @@ -2304,7 +2318,7 @@ return ; } - $tmp_path = defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/'; + $tmp_path = WRITEABLE . '/tmp/'; $fname = $value['name']; $id = $this->Application->GetVar('id'); if ($id) { @@ -2385,18 +2399,28 @@ */ function OnViewFile(&$event) { - if (strpos($this->Application->GetVar('file'), '../') !== false) return ; + $file = $this->Application->GetVar('file'); + if ((strpos($file, '../') !== false) || (trim($file) !== $file)) { + // when relative paths or special chars are found template names from url, then it's hacking attempt + return ; + } + if ($this->Application->GetVar('tmp')) { - $path = (defined('WRITEABLE') ? WRITEABLE.'/tmp/' : FULL_PATH.'/kernel/cache/').$this->Application->GetVar('id').'_'.$this->Application->GetVar('file'); + $path = WRITEABLE . '/tmp/' . $this->Application->GetVar('id') . '_' . $this->Application->GetVar('file'); } else { $object =& $event->getObject(array('skip_autoload'=>true)); $options = $object->GetFieldOptions($this->Application->GetVar('field')); - $path = FULL_PATH.$options['upload_dir'].$this->Application->GetVar('file'); + $path = FULL_PATH.$options['upload_dir'].$file; } $path = str_replace('/', DIRECTORY_SEPARATOR, $path); + + if (!file_exists($path)) { + exit; + } + $type = mime_content_type($path); header('Content-Length: '.filesize($path)); @@ -2428,35 +2452,44 @@ */ function OnSuggestValues(&$event) { - $this->Application->XMLHeader(); + if (!$this->Application->IsAdmin() || !$this->Application->LoggedIn()) { + // very careful here, because this event allows to + // view every object field -> limit only to logged-in admins + return ; + } + $event->status = erSTOP; + $field = $this->Application->GetVar('field'); $cur_value = $this->Application->GetVar('cur_value'); - if (!$field || !$cur_value) { - exit; + + $object =& $event->getObject(); + + if (!$field || !$cur_value || !array_key_exists($field, $object->Fields)) { + return ; } $limit = $this->Application->GetVar('limit'); if (!$limit) { $limit = 20; } - $object =& $event->getObject(); $sql = 'SELECT DISTINCT '.$field.' FROM '.$object->TableName.' WHERE '.$field.' LIKE '.$this->Conn->qstr($cur_value.'%').' ORDER BY '.$field.' LIMIT 0,' . $limit; - $data = $this->Conn->GetCol($sql); + $this->Application->XMLHeader(); + echo ''; + foreach ($data as $item) { echo '' . htmlspecialchars($item) . ''; } - echo ''; - $event->status = erSTOP; + echo ''; } /** @@ -2495,7 +2528,4 @@ // abstract, for hooking } - } - - -?> \ No newline at end of file + } \ No newline at end of file