Order = $order; if ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') { // when AJAX request is made from jQuery, then create ajax variable, // so any logic based in it (like redirects) will not break down $_GET['ajax'] = 'yes'; } $this->AddAllVars(); $this->specialsToRemove = $this->Get('remove_specials'); if ($this->specialsToRemove) { foreach ($this->specialsToRemove as $prefix_special => $flag) { if ($flag && strpos($prefix_special, '.') === false) { unset($this->specialsToRemove[$prefix_special]); trigger_error('Incorrect usage of "remove_specials['.$prefix_special.']" field (no special found)', E_USER_NOTICE); } } $this->_Params = $this->removeSpecials($this->_Params); } ini_set('magic_quotes_gpc', 0); } /** * Discovers unit form request and returns it's QueryString option on success * * @param string $prefix_special * * @return Array|bool * @access protected */ protected function discoverUnit($prefix_special) { list($prefix) = explode('.', $prefix_special); $query_string = $this->getQueryString($prefix); if ($query_string) { // only units with QueryString option can be discovered $this->discoveredUnits[$prefix_special] = $query_string; return $query_string; } unset( $this->discoveredUnits[$prefix] ); return false; } /** * Returns units, passed in request * * @param bool $prefix_special_only * @return Array * @access protected */ public function getDiscoveredUnits($prefix_special_only = true) { return $prefix_special_only ? array_keys( $this->discoveredUnits ) : $this->discoveredUnits; } /** * Returns QueryMap for requested unit config. * In case if unit config is a clone, then get parent item's (from prefix) config to create clone * * @param string $prefix * @return Array * @access protected */ protected function getQueryString($prefix) { $ret = $this->Application->getUnitOption($prefix, 'QueryString', Array ()); if ( !$ret && preg_match('/(.*?)-(.*)/', $prefix, $regs) ) { // "#prefix" (new format), "prefix" (old format) return $this->_getQueryString('#' . $regs[2]); } return $ret; } /** * Returns query string (with safety check against missing prefixes) * * @param string $prefix * @return Array */ private function _getQueryString($prefix) { if ( $this->Application->prefixRegistred($prefix) ) { return $this->Application->getUnitOption($prefix, 'QueryString'); } return substr($prefix, 0, 1) == '#' ? $this->_getQueryString( substr($prefix, 1) ) : Array (); } function removeSpecials($array) { $ret = Array(); $removed = false; foreach ($this->specialsToRemove as $prefix_special => $flag) { if ($flag) { $removed = true; list ($prefix,$special) = explode('.', $prefix_special, 2); foreach ($array as $key => $val) { $new_key = preg_match("/^".$prefix."[._]{1}".$special."(.*)/", $key, $regs) ? $prefix.$regs[1] : $key; $ret[$new_key] = is_array($val) ? $this->removeSpecials($val) : $val; } } } return $removed ? $ret : $array; } /** * All all requested vars to * common storage place * * @access private */ function AddAllVars() { for ($i=0; $i < strlen($this->Order); $i++) { $current = $this->Order[$i]; switch ($current) { case 'G': $this->Get = $this->AddVars($_GET); if (array_key_exists('sid', $_GET)) { $this->_sidInQueryString = true; } $vars = $this->processQueryString( $this->Get(ENV_VAR_NAME) ); if (array_key_exists('sid', $vars)) { // used by Session::GetPassedSIDValue $this->Get['sid'] = $vars['sid']; } $this->AddParams($vars); break; case 'P': $this->Post = $this->AddVars($_POST); $this->convertPostEvents(); $this->_processPostEnvVariables(); break; case 'C': $this->Cookie = $this->AddVars($_COOKIE); break; case 'E'; $this->Env = $this->AddVars($_ENV); break; case 'S'; $this->Server = $this->AddVars($_SERVER); break; case 'F'; $this->convertFiles(); $this->Files = $this->MergeVars($_FILES, false); //do not strip slashes! break; } } // $this->AfterInit(); } /** * Allow POST variables, that names were transformed by PHP ("." replaced with "_") to * override variables, that were virtually created through enviroment variable parsing * */ function _processPostEnvVariables() { $passed = $this->Get('passed'); if (!$passed) { return ; } $passed = explode(',', $passed); foreach ($passed as $prefix_special) { if (strpos($prefix_special, '.') === false) { continue; } list ($prefix, $special) = explode('.', $prefix_special); $query_map = $this->getQueryString($prefix); $post_prefix_special = $prefix . '_' . $special; foreach ($query_map as $index => $var_name) { if (array_key_exists($post_prefix_special . '_' . $var_name, $this->Post)) { $this->Set($prefix_special . '_' . $var_name, $this->Post[$post_prefix_special . '_' . $var_name]); } } } } function AfterInit() { $rewrite_url = $this->Get('_mod_rw_url_'); if ($this->Application->RewriteURLs() || $rewrite_url) { // maybe call onafterconfigread here if (defined('DEBUG_MODE') && $this->Application->isDebugMode()) { $this->Application->Debugger->profileStart('url_parsing', 'Parsing MOD_REWRITE url'); $this->processRewriteURL(); $description = 'Parsing MOD_REWRITE url (template: ' . $this->Get('t') . ')'; $this->Application->Debugger->profileFinish('url_parsing', $description); } else { $this->processRewriteURL(); } if ( !$rewrite_url && $this->rewriteRedirectRequired() ) { // rewrite url is missing (e.g. not a script from tools folder) $url_params = $this->getRedirectParams(); // no idea about how to check, that given template require category to be passed with it, so pass anyway $url_params['pass_category'] = 1; $url_params['response_code'] = 301; // Moved Permanently $this->Application->Redirect('', $url_params); } } else { $this->Application->VerifyThemeId(); $this->Application->VerifyLanguageId(); } } /** * Checks, that non-rewrite url was visited and it's automatic rewrite is required * * @return bool */ function rewriteRedirectRequired() { $redirect_conditions = Array ( !$this->Application->Session->IsHTTPSRedirect(), // not https <-> http redirect !$this->refererIsOurSite(), // referer doesn't match ssl path or non-ssl domain (same for site domains) !defined('GW_NOTIFY'), // not in payment gateway notification script preg_match('/[\/]{0,1}index.php[\/]{0,1}/', $_SERVER['PHP_SELF']), // "index.php" was visited $this->Get('t') != 'index', // not on index page ); $perform_redirect = true; foreach ($redirect_conditions as $redirect_condition) { $perform_redirect = $perform_redirect && $redirect_condition; if (!$perform_redirect) { return false; } } return true; } /** * Checks, that referer is out site * * @return bool */ function refererIsOurSite() { if ( !array_key_exists('HTTP_REFERER', $_SERVER) ) { // no referer -> don't care what happens return false; } $site_helper =& $this->Application->recallObject('SiteHelper'); /* @var $site_helper SiteHelper */ $found = false; $http_referer = $_SERVER['HTTP_REFERER']; preg_match('/^(.*?):\/\/(.*?)(\/|$)/', $http_referer, $regs); // 1 - protocol, 2 - domain if ($regs[1] == 'https') { $found = $site_helper->getDomainByName('SSLUrl', $http_referer) > 0; if (!$found) { // check if referer starts with our ssl url $ssl_url = $this->Application->ConfigValue('SSL_URL'); $found = $ssl_url && preg_match('/^' . preg_quote($ssl_url, '/') . '/', $http_referer); } } else { $found = $site_helper->getDomainByName('DomainName', $regs[2]) > 0; if (!$found) { $found = $regs[2] == DOMAIN; } } return $found; } function convertFiles() { if ( !$_FILES ) { return ; } $tmp = Array (); $file_keys = Array ('error', 'name', 'size', 'tmp_name', 'type'); foreach ($_FILES as $file_name => $file_info) { if ( is_array($file_info['error']) ) { $tmp[$file_name] = $this->getArrayLevel($file_info['error'], $file_name); } else { $normal_files[$file_name] = $file_info; } } if ( !$tmp ) { return ; } $files = $_FILES; $_FILES = Array (); foreach ($tmp as $prefix => $prefix_files) { $anchor =& $_FILES; foreach ($prefix_files['keys'] as $key) { $anchor =& $anchor[$key]; } foreach ($prefix_files['value'] as $field_name) { unset($inner_anchor, $copy); $work_copy = $prefix_files['keys']; foreach ($file_keys as $file_key) { $inner_anchor =& $files[$prefix][$file_key]; if ( isset($copy) ) { $work_copy = $copy; } else { $copy = $work_copy; } array_shift($work_copy); foreach ($work_copy as $prefix_file_key) { $inner_anchor =& $inner_anchor[$prefix_file_key]; } $anchor[$field_name][$file_key] = $inner_anchor[$field_name]; } } } // keys: img_temp, 0, values: LocalPath, ThumbPath } function getArrayLevel(&$level, $prefix='') { $ret['keys'] = $prefix ? Array($prefix) : Array(); $ret['value'] = Array(); foreach($level as $level_key => $level_value) { if( is_array($level_value) ) { $ret['keys'][] = $level_key; $tmp = $this->getArrayLevel($level_value); $ret['keys'] = array_merge($ret['keys'], $tmp['keys']); $ret['value'] = array_merge($ret['value'], $tmp['value']); } else { $ret['value'][] = $level_key; } } return $ret; } /** * Overwrites GET events with POST events in case if they are set and not empty * * @return void * @access protected */ protected function convertPostEvents() { $events = $this->Get('events', Array ()); /* @var $events Array */ if ( is_array($events) ) { $events = array_filter($events); foreach ($events as $prefix_special => $event_name) { $this->Set($prefix_special . '_event', $event_name); } } } function finalizeParsing($passed = Array(), $module_params = Array() ) { if ($passed) { foreach ($passed as $passed_prefix) { $this->discoverUnit($passed_prefix); // from mod-rewrite url parsing } $this->Set('passed', implode(',', $this->getDiscoveredUnits())); } // get joined version (env var + mod rewrite parsed) $passed = $this->Application->GetVar('passed'); if (!array_key_exists('editing_mode', $module_params)) { $module_params['editing_mode'] = ''; } $module_params['__URLENCODE__'] = 1; $env = $this->Application->BuildEnv( $this->Get('t'), $module_params, $passed, false, false); $this->Set(ENV_VAR_NAME, $env); $_REQUEST['env'] = $_GET['env'] = $env; // for capability with old in-portal code } function processRewriteURL() { $mod_rw_helper =& $this->Application->recallObject('ModRewriteHelper'); /* @var $mod_rw_helper kModRewriteHelper */ $mod_rw_helper->processRewriteURL(); } function getDefaultTemplate($t) { $t = $this->getTemplateName( trim($t, '/') ); if (!$t) $t = 'index'; return trim($t, '/'); } function extractSIDAndTemplate(&$parts) { $vars = Array (); $sub_parts = array_shift($parts); list ($sid, $t) = explode('-', $sub_parts, 2); if ($sid) { // Save Session ID $this->Set('sid', $sid); $vars['sid'] = $sid; } // Save Template Name $vars['t'] = $this->getDefaultTemplate($t); return $vars; } /** * Process QueryString only, create * events, ids, based on config * set template name and sid in * desired application variables. * * @param string $env_var enviroment string value * * @access public */ function processQueryString($env_var, $pass_name = 'passed') { // 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 = array_merge($vars, $this->extractSIDAndTemplate($parts)); } if ($parts) { $passed = Array (); foreach ($parts as $mixed_part) { list ($passed[], $processed_vars) = $this->_parseEnvPart($mixed_part); $vars = array_merge($vars, $processed_vars); } $vars[$pass_name] = implode(',', array_unique($passed)); } } else { $t = $this->getTemplateName('index'); $vars['t'] = $t; } return $vars; } /** * Converts enviroment part into variable array (based on query map for given prefix) * * @param string $mixed_part * @return Array */ function _parseEnvPart($mixed_part) { // In-portal old style env conversion - adds '-' between prefix and first var $mixed_part = str_replace('_&+$$+&_', ':', $mixed_part); $mixed_part = preg_replace("/^([a-zA-Z]+)([0-9]+)-(.*)/", "$1-$2-$3", $mixed_part); // replace escaped "-" symbol not to explode by it $escaped_part = str_replace('\-', '_&+$$+&_', $mixed_part); $escaped_part = explode('-', $escaped_part); $mixed_part = Array(); foreach ($escaped_part as $escaped_val) { $mixed_part[] = str_replace('_&+$$+&_', '-', $escaped_val); } $prefix_special = array_shift($mixed_part); // l.pick, l $query_map = $this->discoverUnit($prefix_special); // from $_GET['env'] $vars = Array (); // if config is not defined for prefix in QueryString, then don't process it if ($query_map) { foreach ($query_map as $index => $var_name) { // l_id, l_page, l_bla-bla-bla $val = $mixed_part[$index - 1]; if ($val == '') $val = false; $vars[$prefix_special.'_'.$var_name] = $val; } } return Array ($prefix_special, $vars); } /** * Removes tpl part from template name + resolved template ID to name * * @param string $t * @return string * @access private */ function getTemplateName($t) { if (array_key_exists('t', $this->Get) && $this->Get['t']) { // template name is passed directly in url (GET method) $t = $this->Get['t']; } // if t was set through env, even in mod_rewrite mode! if ($this->Get('env') && $this->Application->RewriteURLs() && $this->Get('t')) { $t = $this->Get('t'); } return preg_replace('/\.tpl$/', '', $t); } /** * Saves variables from array specified * into common variable storage place * * @param Array $array * @return Array * @access private */ function AddVars($array) { $array = $this->StripSlashes($array); foreach($array as $key => $value) { $this->Set($key,$value); } return $array; } function MergeVars($array, $strip_slashes = true) { if ($strip_slashes) { $array = $this->StripSlashes($array); } foreach($array as $key => $value_array) { // $value_array is an array too $this->_Params = kUtil::array_merge_recursive($this->_Params, Array ($key => $value_array)); } return $array; } function StripSlashes($array) { static $magic_quotes = null; if (!isset($magic_quotes)) { $magic_quotes = get_magic_quotes_gpc(); } foreach ($array as $key => $value) { if (is_array($value)) { $array[$key] = $this->StripSlashes($value); } else { if ($magic_quotes) { $value = stripslashes($value); } if (!$this->Application->isAdmin) { $value = htmlspecialchars($value); } $array[$key] = $value; } } return $array; } /** * Returns all $_GET array excluding system parameters, that are not allowed to be passed through generated urls * * @param bool $access_error Method is called during no_permission, require login, session expiration link preparation * @return Array */ function getRedirectParams($access_error = false) { $vars = $this->Get; $unset_vars = Array (ENV_VAR_NAME, 'rewrite', '_mod_rw_url_', 'Action'); if (!$this->_sidInQueryString) { $unset_vars[] = 'sid'; } // remove system variables foreach ($unset_vars as $var_name) { if (array_key_exists($var_name, $vars)) { unset($vars[$var_name]); } } if ($access_error) { // place 1 of 2 (also in UsersEventHandler::OnSessionExpire) $vars = $this->_removePassThroughVariables($vars); } // transform arrays return $this->_transformArrays($vars); } /** * Removes all pass_though variables from redirect params * * @param Array $url_params * @return Array */ function _removePassThroughVariables($url_params) { $pass_through = array_key_exists('pass_through', $url_params) ? $url_params['pass_through'] : ''; if (!$pass_through) { return $url_params; } $pass_through = explode(',', $pass_through . ',pass_through'); foreach ($pass_through as $pass_through_var) { unset($url_params[$pass_through_var]); } $url_params['no_pass_through'] = 1; // this way kApplication::HREF won't add them again return $url_params; } function _transformArrays($array, $level_prefix = '') { $ret = Array (); foreach ($array as $var_name => $var_value) { $new_var_name = $level_prefix ? $level_prefix . '[' . $var_name . ']' : $var_name; if (is_array($var_value)) { $ret = array_merge($ret, $this->_transformArrays($var_value, $new_var_name)); } else { $ret[$new_var_name] = $var_value; } } return $ret; } function writeRequestLog($filename) { $log_file = (defined('RESTRICTED') ? RESTRICTED : FULL_PATH) . '/' . $filename; if ( is_writable(dirname($log_file)) ) { $fp = fopen($log_file, 'a'); if ( $fp ) { $session =& $this->Application->recallObject('Session'); /* @var $session Session */ $user_id = $session->GetField('PortalUserId'); $admin_mark = $this->Application->isAdmin ? 'ADMIN' : 'FRONT'; $data = '[' . date('D M d H:i:s Y') . '] ' . $admin_mark . '; ip: ' . $_SERVER['REMOTE_ADDR'] . '; user_id: ' . $user_id . '; sid: ' . $this->Application->GetSID() . '; request: ' . "\n"; if ( $this->Get ) { $data .= "_GET:\n" . print_r($this->Get, true); } if ( $this->Post ) { $data .= "_POST:\n" . print_r($this->Post, true); } if ( $this->Cookie ) { $data .= "_COOKIE:\n" . print_r($this->Cookie, true); } $data .= str_repeat('=', 100) . "\n"; fwrite($fp, $data); fclose($fp); } else { trigger_error('Request Log directory not writable', E_USER_WARNING); } } else { trigger_error('Request Log directory not writable', E_USER_WARNING); } } }