/**
  * Retrieves field list to check for modification
  *
  * @param string $tableName
  * @return	array
  */
 protected function getFieldList($tableName)
 {
     if ($tableName == 'pages_language_overlay') {
         $fieldList = TX_REALURL_SEGTITLEFIELDLIST_PLO;
     } else {
         if (isset($this->config['pagePath']['segTitleFieldList'])) {
             $fieldList = $this->config['pagePath']['segTitleFieldList'];
         } else {
             $fieldList = TX_REALURL_SEGTITLEFIELDLIST_DEFAULT;
         }
     }
     $fieldList .= ',hidden';
     return array_unique($this->apiWrapper->trimExplode(',', $fieldList, true));
 }
Esempio n. 2
0
 /**
  * Parse speaking URL and translate it to parameters understood by TYPO3
  * Function is called from tslib_fe
  * The overall format of a speaking URL is these five parts [TYPO3_SITE_URL] / [pre-var] / [page-identification] / [post-vars] / [file.ext]
  * - "TYPO3_SITE_URL" is fixed value from the environment,
  * - "pre-var" is any number of segments separated by "/" mapping to GETvars AND with a known lenght,
  * - "page-identification" identifies the page id in TYPO3 possibly with multiple segments separated by "/" BUT with an UNKNOWN length,
  * - "post-vars" is sets of segments offering the same features as "pre-var"
  * - "file.ext" is any filename that might apply
  *
  * @param array $params Params for hook
  * @return void Setting internal variables.
  */
 public function decodeSpURL($params)
 {
     $this->devLog('Entering decodeSpURL');
     // Setting parent object reference (which is $GLOBALS['TSFE'])
     $this->pObj =& $params['pObj'];
     // Initializing config / request URL
     $this->setConfig();
     $this->adjustConfigurationByHost('decode');
     $this->adjustRootPageId();
     // If there has been a redirect (basically; we arrived here otherwise than via "index.php" in the URL) this can happend either due to a CGI-script or because of reWrite rule. Earlier we used $GLOBALS['HTTP_SERVER_VARS']['REDIRECT_URL'] to check but...
     if ($this->pObj->siteScript && substr($this->pObj->siteScript, 0, 9) != 'index.php' && substr($this->pObj->siteScript, 0, 1) != '?') {
         // Getting the path which is above the current site url
         // For instance "first/second/third/index.html?&param1=value1&param2=value2"
         // should be the result of the URL
         // "http://localhost/typo3/dev/dummy_1/first/second/third/index.html?&param1=value1&param2=value2"
         // Note: sometimes in fcgi installations it is absolute, so we have to make it
         // relative to work properly.
         $speakingURIpath = $this->pObj->siteScript[0] == '/' ? substr($this->pObj->siteScript, 1) : $this->pObj->siteScript;
         // Call hooks
         if (is_array($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['decodeSpURL_preProc'])) {
             foreach ($GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['realurl']['decodeSpURL_preProc'] as $userFunc) {
                 $hookParams = array('pObj' => &$this, 'params' => $params, 'URL' => &$speakingURIpath);
                 $this->apiWrapper->callUserFunction($userFunc, $hookParams, $this);
             }
         }
         // Append missing slash if configured for
         if ($this->extConf['init']['appendMissingSlash']) {
             $regexp = '~^([^\\?]*[^/])(\\?.*)?$~';
             if (substr($speakingURIpath, -1, 1) == '?') {
                 $speakingURIpath = substr($speakingURIpath, 0, -1);
             }
             if (preg_match($regexp, $speakingURIpath)) {
                 // Only process if a slash is missing:
                 $options = $this->apiWrapper->trimExplode(',', $this->extConf['init']['appendMissingSlash'], true);
                 if (in_array('ifNotFile', $options)) {
                     if (!preg_match('/\\/[^\\/\\?]+\\.[^\\/]+(\\?.*)?$/', '/' . $speakingURIpath)) {
                         $speakingURIpath = preg_replace($regexp, '\\1/\\2', $speakingURIpath);
                         $this->appendedSlash = true;
                     }
                 } else {
                     $speakingURIpath = preg_replace($regexp, '\\1/\\2', $speakingURIpath);
                     $this->appendedSlash = true;
                 }
                 if ($this->appendedSlash && count($options) > 0) {
                     foreach ($options as $option) {
                         $matches = array();
                         if (preg_match('/^redirect(\\[(30[1237])\\])?$/', $option, $matches)) {
                             $code = count($matches) > 1 ? $matches[2] : 301;
                             $status = 'HTTP/1.1 ' . $code . ' TYPO3 RealURL redirect M' . __LINE__;
                             // Check path segment to be relative for the current site.
                             // parse_url() does not work with relative URLs, so we use it to test
                             if (!@parse_url($speakingURIpath, PHP_URL_HOST)) {
                                 @ob_end_clean();
                                 header($status);
                                 header('Location: ' . $this->apiWrapper->locationHeaderUrl($speakingURIpath));
                                 exit;
                             }
                         }
                     }
                 }
             }
         }
         // If the URL is a single script like "123.1.html" it might be an "old" simulateStaticDocument request. If this is the case and support for this is configured, do NOT try and resolve it as a Speaking URL
         $fI = $this->apiWrapper->split_fileref($speakingURIpath);
         if (!$this->apiWrapper->testInt($this->pObj->id) && $fI['path'] == '' && $this->extConf['fileName']['defaultToHTMLsuffixOnPrev'] && $this->extConf['init']['respectSimulateStaticURLs']) {
             // If page ID does not exist yet and page is on the root level and both
             // respectSimulateStaticURLs and defaultToHTMLsuffixOnPrev are set, than
             // ignore respectSimulateStaticURLs and attempt to resolve page id.
             // See http://bugs.typo3.org/view.php?id=1530
             /** @noinspection PhpUndefinedMethodInspection */
             $GLOBALS['TT']->setTSlogMessage('decodeSpURL: ignoring respectSimulateStaticURLs due defaultToHTMLsuffixOnPrev for the root level page!)', 2);
             $this->extConf['init']['respectSimulateStaticURLs'] = false;
         }
         if (!$this->extConf['init']['respectSimulateStaticURLs'] || $fI['path']) {
             $this->devLog('RealURL powered decoding (TM) starting!');
             // Parse path
             $uParts = @parse_url($speakingURIpath);
             if (!is_array($uParts)) {
                 $this->decodeSpURL_throw404('Current URL is invalid');
             }
             $speakingURIpath = $this->speakingURIpath_procValue = $uParts['path'];
             // Redirecting if needed (exits if so).
             $this->decodeSpURL_checkRedirects($speakingURIpath);
             // Looking for cached information
             $cachedInfo = $this->decodeSpURL_decodeCache($speakingURIpath);
             // If no cached info was found, create it
             if (!is_array($cachedInfo)) {
                 // Decode URL
                 $cachedInfo = $this->decodeSpURL_doDecode($speakingURIpath, $this->extConf['init']['enableCHashCache']);
                 // Storing cached information
                 $this->decodeSpURL_decodeCache($speakingURIpath, $cachedInfo);
             }
             // Re-create QUERY_STRING from Get vars for use with typoLink()
             $_SERVER['QUERY_STRING'] = $this->decodeSpURL_createQueryString($cachedInfo['GET_VARS']);
             // Jump-admin if configured
             $this->decodeSpURL_jumpAdmin_goBackend($cachedInfo['id']);
             // Setting info in TSFE
             $this->pObj->mergingWithGetVars($cachedInfo['GET_VARS']);
             $this->pObj->id = $cachedInfo['id'];
             if ($this->mimeType) {
                 header('Content-type: ' . $this->mimeType);
                 $this->mimeType = null;
             }
         }
     }
 }
 /**
  * Search for a title in a certain PID
  *
  * @param int $searchPid Page id in which to search subpages matching title
  * @param string $title Title to search for
  * @return array First entry is uid, second entry is the row selected, including information about the page as a mount point.
  * @see findPageBySegment()
  */
 protected function findPageBySegmentAndPid($searchPid, $title)
 {
     // List of "pages" fields to traverse for a "directory title" in the speaking URL (only from RootLine!!)
     $segTitleFieldList = $this->conf['segTitleFieldList'] ? $this->conf['segTitleFieldList'] : TX_REALURL_SEGTITLEFIELDLIST_DEFAULT;
     $selList = $this->apiWrapper->uniqueList('uid,pid,doktype,mount_pid,mount_pid_ol,tx_realurl_exclude,' . $segTitleFieldList);
     $segTitleFieldArray = $this->apiWrapper->trimExplode(',', $segTitleFieldList, 1);
     // page select object - used to analyse mount points.
     $pageRepository = $this->apiWrapper->getPageRepository();
     // Build an array with encoded values from the segTitleFieldArray of the subpages
     // First we find field values from the default language
     // Pages are selected in menu order and if duplicate titles are found the first takes precedence!
     $titles = array();
     // array(title => uid);
     $exclude = array();
     $uidTrack = array();
     /** @noinspection PhpUndefinedMethodInspection */
     $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery($selList, 'pages', 'pid=' . intval($searchPid) . ' AND deleted=0 AND doktype<>255', '', 'sorting');
     /** @noinspection PhpUndefinedMethodInspection */
     while (false != ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))) {
         // Mount points
         $mount_info = $pageRepository->getMountPointInfo($row['uid'], $row);
         if (is_array($mount_info)) {
             // There is a valid mount point.
             if ($mount_info['overlay']) {
                 // Overlay mode: Substitute WHOLE record
                 /** @noinspection PhpUndefinedMethodInspection */
                 $result2 = $GLOBALS['TYPO3_DB']->exec_SELECTquery($selList, 'pages', 'uid=' . intval($mount_info['mount_pid']) . ' AND deleted=0 AND doktype<>255');
                 /** @noinspection PhpUndefinedMethodInspection */
                 $mp_row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result2);
                 if (is_array($mp_row)) {
                     $row = $mp_row;
                 } else {
                     unset($row);
                     // If the mount point could not be fetched, unset the row
                 }
             }
             $row['_IS_MOUNTPOINT'] = $mount_info;
         }
         // Collect titles from selected row
         if (is_array($row)) {
             if ($row['tx_realurl_exclude']) {
                 // segment is excluded
                 $exclude[] = $row;
             }
             // Process titles. Note that excluded segments are also searched
             // otherwise they will never be found
             $uidTrack[$row['uid']] = $row;
             foreach ($segTitleFieldArray as $fieldName) {
                 if ($row[$fieldName]) {
                     $encodedTitle = $this->encodeTitle($row[$fieldName]);
                     if (!isset($titles[$fieldName][$encodedTitle])) {
                         $titles[$fieldName][$encodedTitle] = $row['uid'];
                     }
                 }
             }
         }
     }
     /** @noinspection PhpUndefinedMethodInspection */
     $GLOBALS['TYPO3_DB']->sql_free_result($result);
     // We have to search the language overlay too, if: a) the language isn't the default (0), b) if it's not set (-1)
     $uidTrackKeys = array_keys($uidTrack);
     $language = $this->pObj->getDetectedLanguage();
     if ($language != 0) {
         foreach ($uidTrackKeys as $l_id) {
             /** @noinspection PhpUndefinedMethodInspection */
             $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(TX_REALURL_SEGTITLEFIELDLIST_PLO, 'pages_language_overlay', 'pid=' . intval($l_id) . ' AND deleted=0' . ($language > 0 ? ' AND sys_language_uid=' . $language : ''));
             /** @noinspection PhpUndefinedMethodInspection */
             while (false != ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result))) {
                 foreach ($segTitleFieldArray as $fieldName) {
                     if ($row[$fieldName]) {
                         $encodedTitle = $this->encodeTitle($row[$fieldName]);
                         if (!isset($titles[$fieldName][$encodedTitle])) {
                             $titles[$fieldName][$encodedTitle] = $l_id;
                         }
                     }
                 }
             }
             /** @noinspection PhpUndefinedMethodInspection */
             $GLOBALS['TYPO3_DB']->sql_free_result($result);
         }
     }
     // Merge titles
     $segTitleFieldArray = array_reverse($segTitleFieldArray);
     // To observe the priority order...
     $allTitles = array();
     foreach ($segTitleFieldArray as $fieldName) {
         if (is_array($titles[$fieldName])) {
             $allTitles = $this->apiWrapper->array_merge($allTitles, $titles[$fieldName]);
         }
     }
     // Return
     $encodedTitle = $this->encodeTitle($title);
     $possibleMatch = array();
     if (isset($allTitles[$encodedTitle])) {
         if (!$uidTrack[$allTitles[$encodedTitle]]['tx_realurl_exclude']) {
             return array($allTitles[$encodedTitle], $uidTrack[$allTitles[$encodedTitle]], false, array());
         }
         $possibleMatch = $uidTrack[$allTitles[$encodedTitle]];
     }
     return array(false, false, $exclude, $possibleMatch);
 }