/**
  * @param array $params
  * @param \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController $pObj
  * @param string $hookType
  */
 protected function contentPostProc($params, $pObj, $hookType)
 {
     if ($this->extensionConfiguration->shouldIncludeEofe() && !$this->extensionConfiguration->hasIncludedEofe()) {
         $this->extensionConfiguration->setIncludedEofe(true);
         $eofe = $pObj->cObj->cObjGetSingle($pObj->tmpl->setup['config.']['extbase_hijax.']['eofe'], $pObj->tmpl->setup['config.']['extbase_hijax.']['eofe.']);
         $pObj->content = str_ireplace('</body>', $eofe . '</body>', $pObj->content);
     }
     if ($this->extensionConfiguration->shouldIncludeSofe() && !$this->extensionConfiguration->hasIncludedSofe()) {
         $this->extensionConfiguration->setIncludedSofe(true);
         $sofe = $pObj->cObj->cObjGetSingle($pObj->tmpl->setup['config.']['extbase_hijax.']['sofe'], $pObj->tmpl->setup['config.']['extbase_hijax.']['sofe.']);
         $pObj->content = preg_replace('/<body([^>]*)>/msU', '<body$1>' . $sofe, $pObj->content);
     }
     $bodyClass = $pObj->tmpl->setup['config.']['extbase_hijax.']['bodyClass'];
     if ($bodyClass && !$this->extensionConfiguration->hasAddedBodyClass()) {
         $matches = array();
         preg_match('/<body([^>]*)class="([^>]*)">/msU', $pObj->content, $matches);
         $count = 0;
         if (count($matches)) {
             $classes = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(" ", $matches[2], true);
             if (!in_array($bodyClass, $classes)) {
                 $pObj->content = preg_replace('/<body([^>]*)class="([^>]*)">/msU', '<body$1class="$2 ' . $bodyClass . '">', $pObj->content, -1, $count);
             }
         } else {
             $pObj->content = preg_replace('/<body([^>]*)>/msU', '<body$1 class="' . $bodyClass . '">', $pObj->content, -1, $count);
         }
         if ($count) {
             $this->extensionConfiguration->setAddedBodyClass(true);
         }
     }
     if ($hookType == 'output') {
         while ($this->hijaxEventDispatcher->hasPendingNextPhaseEvents()) {
             // trick to force double rendering of some content elements
             $GLOBALS['TSFE']->recordRegister = array();
             // trick to force loading of full TS template
             if (!$pObj->tmpl->loaded) {
                 $pObj->forceTemplateParsing = TRUE;
                 $pObj->getConfigArray();
             }
             $this->hijaxEventDispatcher->promoteNextPhaseEvents();
             $this->hijaxEventDispatcher->parseAndRunEventListeners($pObj->content);
             if (!$pObj->config['INTincScript']) {
                 $pObj->config['INTincScript'] = array();
             }
             $pObj->INTincScript();
             if (self::$loopCount++ > 99) {
                 // preventing dead loops
                 break;
             }
         }
     }
     if ($hookType == 'output' || $pObj->isStaticCacheble()) {
         $this->hijaxEventDispatcher->replaceXMLCommentsWithDivs($pObj->content);
     }
     if ($hookType == 'output') {
         if (count($this->nonCacheableFooterCode)) {
             ksort($this->nonCacheableFooterCode);
             $pObj->content = $this->str_lreplace('</body>', '<!-- x123456 -->' . implode('', $this->nonCacheableFooterCode) . '</body>', $pObj->content);
         }
         if (count($this->nonCacheableHeaderCode)) {
             ksort($this->nonCacheableHeaderCode);
             $pObj->content = $this->str_lreplace('</head>', '<!-- x123456 -->' . implode('', $this->nonCacheableHeaderCode) . '</head>', $pObj->content);
         }
     }
 }
 /**
  * Called by ajax.php / eID.php
  * Builds an extbase context and returns the response.
  * 
  * @return void
  */
 public function dispatch()
 {
     $this->setIsActive(true);
     $callback = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('callback');
     $requests = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('r');
     $eventsToListen = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('evts') ? \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('evts') : \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('e');
     $preventDirectOutput = false;
     try {
         $this->initializeDatabase();
         $this->hijaxEventDispatcher->promoteNextPhaseEvents();
         $responses = array('original' => array(), 'affected' => array());
         foreach ($requests as $r) {
             if ($r['secureLocalStorage']) {
                 echo file_get_contents(\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath('extbase_hijax', 'Resources/Private/Templates/SecureLocalStorage/IFrame.html'));
                 exit;
             }
             $skipProcessing = FALSE;
             $configuration = array();
             $allowCaching = FALSE;
             if ($r['chash']) {
                 /* @var $cacheHash \TYPO3\CMS\Frontend\Page\CacheHashCalculator */
                 $cacheHash = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\CacheHashCalculator');
                 $allowCaching = $r['chash'] == $cacheHash->calculateCacheHash(array('encryptionKey' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], 'action' => $r['action'], 'controller' => $r['controller'], 'extension' => $r['extension'], 'plugin' => $r['plugin'], 'arguments' => $r['arguments'], 'settingsHash' => $r['settingsHash']));
             }
             if ($r['tsSource']) {
                 $this->initialize();
                 if ($this->serviceContent->isAllowedTypoScriptPath($r['tsSource'])) {
                     /* @var $listener \EssentialDots\ExtbaseHijax\Event\Listener */
                     $encodedSettings = str_replace('.', '---', $r['tsSource']);
                     $settingsHash = \TYPO3\CMS\Core\Utility\GeneralUtility::hmac($encodedSettings);
                     $listener = $this->listenerFactory->findById('h-' . $settingsHash . '-' . $encodedSettings);
                     $configuration = $listener->getConfiguration();
                     $r['extension'] = $configuration['extensionName'];
                     $r['plugin'] = $configuration['pluginName'];
                     $r['controller'] = $configuration['controller'];
                     $r['action'] = $configuration['action'];
                 } else {
                     throw new \Exception('Path not allowed.', 503);
                 }
             } elseif ($r['settingsHash']) {
                 /* @var $listener \EssentialDots\ExtbaseHijax\Event\Listener */
                 $listener = $this->listenerFactory->findById($r['settingsHash']);
             }
             $bootstrap = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Core\\Bootstrap');
             // load settings saved under settingsHash
             if ($listener) {
                 $configuration = $listener->getConfiguration();
                 $request = $listener->getRequest();
                 $bootstrap->cObj = $listener->getCObj();
                 $this->checkAllowedControllerActions($configuration, $r);
             } elseif (\EssentialDots\ExtbaseHijax\Utility\Extension::isAllowedHijaxAction($r['extension'], $r['controller'], $r['action'], $r['vendor'])) {
                 $allowCaching = FALSE;
                 // we do not want to cache this request
                 $configuration['extensionName'] = $r['extension'];
                 $configuration['vendorName'] = $r['vendor'];
                 $configuration['pluginName'] = $r['plugin'];
                 $configuration['controller'] = $r['controller'];
                 $configuration['action'] = $r['action'];
             } else {
                 $skipProcessing = TRUE;
             }
             if (!$skipProcessing) {
                 if ($allowCaching && $this->cacheRepository) {
                     $cacheConf = array('contentFunc' => array($this, 'handleFrontendRequest'), 'contentFuncParams' => array($bootstrap, $configuration, $r, $request, $listener, TRUE));
                     if ($configuration['settings']['extbaseHijaxDefaultCacheExpiryPeriod']) {
                         $cacheConf['expire_on_datetime'] = $GLOBALS['EXEC_TIME'] + $configuration['settings']['extbaseHijaxDefaultCacheExpiryPeriod'];
                     }
                     $cachedResponse = $this->cacheRepository->getByKey('hijax_' . $r['chash'], $cacheConf, $bootstrap->cObj);
                     $cachedResponse['id'] = $r['id'];
                     $responses['original'][] = $cachedResponse;
                 } else {
                     $responses['original'][] = $this->handleFrontendRequest($bootstrap, $configuration, $r, $request, $listener, FALSE);
                 }
             }
         }
         // see if there are affected elements on the page as well
         // and run their code generation again
         $this->parseAndRunEventListeners($responses, $eventsToListen, FALSE);
         while ($this->hijaxEventDispatcher->hasPendingNextPhaseEvents()) {
             $this->hijaxEventDispatcher->promoteNextPhaseEvents();
             $this->parseAndRunEventListeners($responses, $eventsToListen);
             if (self::$loopCount++ > 99) {
                 // preventing dead loops
                 break;
             }
         }
         foreach ($responses['original'] as $i => $response) {
             $this->hijaxEventDispatcher->replaceXMLCommentsWithDivs($responses['original'][$i]['response'], $responses['original'][$i]['format']);
             if ($responses['original'][$i]['format'] == 'json') {
                 // yes, non-optimal, but no time for now to change the extbase core...
                 $responses['original'][$i]['response'] = json_decode($responses['original'][$i]['response']);
             }
         }
         foreach ($responses['affected'] as $i => $response) {
             $this->hijaxEventDispatcher->replaceXMLCommentsWithDivs($responses['affected'][$i]['response'], $responses['affected'][$i]['format']);
             if ($responses['affected'][$i]['format'] == 'json') {
                 // yes, non-optimal, but no time for now to change the extbase core...
                 $responses['affected'][$i]['response'] = json_decode($responses['affected'][$i]['response']);
             }
         }
         $this->cleanShutDown();
     } catch (\EssentialDots\ExtbaseHijax\MVC\Exception\RedirectAction $redirectException) {
         $responses = array('redirect' => array('url' => $redirectException->getUrl(), 'code' => $redirectException->getHttpStatus()));
         $preventDirectOutput = true;
     } catch (\Exception $e) {
         header('HTTP/1.1 503 Service Unavailable');
         header('Status: 503 Service Unavailable');
         error_log($e->getMessage());
         $responses = array('success' => false, 'code' => $e->getCode());
     }
     if (!$preventDirectOutput && $responses['original'][0]['format'] != 'html' && is_string($responses['original'][0]['response'])) {
         foreach ($responses['original'][0]['headers'] as $header) {
             header(trim($header));
         }
         header('Cache-control: private');
         header('Connection: Keep-Alive');
         header('Content-Length: ' . strlen($responses['original'][0]['response']));
         echo $responses['original'][0]['response'];
     } elseif ($callback) {
         header('Content-type: text/javascript');
         echo $callback . '(' . json_encode($responses) . ')';
     } else {
         header('Content-type: application/x-json');
         echo json_encode($responses);
     }
     $this->setIsActive(false);
 }