Skip to content

Instantly share code, notes, and snippets.

@helhum
Created November 17, 2014 20:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save helhum/87ef0a64c662647a30b2 to your computer and use it in GitHub Desktop.
Save helhum/87ef0a64c662647a30b2 to your computer and use it in GitHub Desktop.
Secure TYPO3 CMS frontent delivery
<?php
$boot = function($extensionKey) {
/** @var \TYPO3\CMS\Extbase\SignalSlot\Dispatcher $signalSlotDispatcher */
$signalSlotDispatcher = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\SignalSlot\\Dispatcher');
if (TYPO3_MODE === 'FE' && defined('TYPO3_PATH_WEB')) {
// Required for secure Web Directory
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_pagerenderer.php']['render-preProcess'][] = 'Helhum\OstkreuzSite\Hooks\ResourcePublisher->publishPageRendererResources';
$signalSlotDispatcher->connect('TYPO3\\CMS\\Core\\Resource\\ResourceStorage', \TYPO3\CMS\Core\Resource\ResourceStorageInterface::SIGNAL_PreGeneratePublicUrl, 'Helhum\OstkreuzSite\Hooks\ResourcePublisher', 'publishFalResource');
}
}
$boot($_EXTKEY);
unset($boot);
<?php
namespace Helhum\YourSitePackage\Hooks;
/***************************************************************
* Copyright notice
*
* (c) 2014 Helmut Hummel <helmut.hummel@typo3.org>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the text file GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use TYPO3\CMS\Core\Resource\Driver\DriverInterface;
use TYPO3\CMS\Core\Resource\Driver\LocalDriver;
use TYPO3\CMS\Core\Resource\ResourceInterface;
use TYPO3\CMS\Core\Resource\ResourceStorage;
use TYPO3\CMS\Core\SingletonInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\PathUtility;
/**
* Class ResourcePublisher
*/
class ResourcePublisher implements SingletonInterface {
protected $publishedStatic = FALSE;
/**
* Called by ResourceStorage::getPublicUrl
*
* @param ResourceStorage $storage
* @param $driver
* @param ResourceInterface $resource
*/
public function publishFalResource(ResourceStorage $storage, DriverInterface $driver, ResourceInterface $resource) {
if (!$driver instanceof LocalDriver || !$storage->isPublic()) {
return;
}
$resourceBasePath = $this->getResourcesSourcePathByResourceStorage($storage);
$pathAndFilename = PathUtility::getCanonicalPath($resourceBasePath . $resource->getIdentifier());
$relativeResourceFileName = PathUtility::stripPathSitePrefix($pathAndFilename);
$this->publishResource($relativeResourceFileName);
}
/**
* Page renderer post processing
*
* @param array $pageRendererResources
*/
public function publishPageRendererResources(array $pageRendererResources) {
foreach ($pageRendererResources as $resourceName => $resourceCollection) {
if (is_array($resourceCollection)) {
foreach ($resourceCollection as $resource) {
if (!in_array($resourceName, array('headerData', 'footerData'), TRUE)) {
$this->publishResource($resource['file']);
// } else {
// // TODO: Compatibility layer really needed?
// $this->findResources($resource);
}
}
}
}
// TODO: better place to ensure resource publishing for uncached pages?
$this->publishStaticResources();
}
/**
* Iterates over all loaded packages and publishes all files in Resources/Public
*/
public function publishStaticResources() {
if ($this->publishedStatic === TRUE) {
return;
}
foreach ($GLOBALS['TYPO3_LOADED_EXT'] as $_EXTKEY => $extensionInformation) {
if ((is_array($extensionInformation) || $extensionInformation instanceof \ArrayAccess)) {
$publicResourcesPath = PATH_site . $extensionInformation['siteRelPath'] . 'Resources/Public/';
if (is_dir($publicResourcesPath)) {
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($publicResourcesPath, \RecursiveDirectoryIterator::SKIP_DOTS | \RecursiveDirectoryIterator::FOLLOW_SYMLINKS),
\RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $item) {
if ($item->isFile()) {
$relativeResourcePath = PathUtility::stripPathSitePrefix($item->getPathname());
$this->publishResource($relativeResourcePath);
}
}
}
}
}
$this->publishedStatic = TRUE;
}
/**
* @param $resourceContent
*/
protected function findResources($resourceContent) {
$matches = array();
$matchCount = preg_match_all('#"([/]?)(typo3temp|typo3conf|fileadmin)(/[^"]*)"#', $resourceContent, $matches);
if ($matchCount > 0) {
foreach ($matches[3] as $index => $potentialResource) {
$parsedResource = parse_url($potentialResource);
$this->publishResource($matches[1][$index] . $matches[2][$index] . $parsedResource['path']);
}
unset($matches, $potentialResource, $parsedResource);
}
}
/**
* @param string $relativeResourceFileName
*/
protected function publishResource($relativeResourceFileName) {
$relativeResourceFileName = ltrim($relativeResourceFileName, '/');
$targetDirectory = dirname(TYPO3_PATH_WEB . $relativeResourceFileName);
$this->ensureDirectoryExists($targetDirectory);
if (!is_link(TYPO3_PATH_WEB . $relativeResourceFileName)) {
symlink(PATH_site . $relativeResourceFileName, TYPO3_PATH_WEB . $relativeResourceFileName);
}
}
/**
* @param string $dirName
*/
protected function ensureDirectoryExists($dirName) {
if (!is_dir($dirName)) {
GeneralUtility::mkdir_deep($dirName);
}
}
/**
* @param ResourceStorage $storage
* @return string
*/
protected function getResourcesSourcePathByResourceStorage(ResourceStorage $storage) {
$storageConfiguration = $storage->getConfiguration();
if ($storageConfiguration['pathType'] === 'absolute') {
$sourcePath = PathUtility::getCanonicalPath($storageConfiguration['basePath']) . '/';
} else {
$sourcePath = PathUtility::getCanonicalPath(PATH_site . $storageConfiguration['basePath']) . '/';
}
return $sourcePath;
}
}
<?php
// This is the index.php file to be placed in the document root directory named "Web"
// "Web" must be on the same level "fileadmin" or "typo3temp"
// This file only works with TYPO3 6.2
require __DIR__ . '/../typo3/sysext/core/Classes/Core/Bootstrap.php';
\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
->baseSetup('Web/')
->redirectToInstallerIfEssentialConfigurationDoesNotExist();
define('TYPO3_PATH_WEB', __DIR__ . '/');
require(PATH_tslib . 'index_ts.php');
<?php
// This is the index.php file to be placed in the document root directory named "Web"
// "Web" must be on the same level "fileadmin" or "typo3temp"
// This file only works with TYPO3 7.0-dev
define('TYPO3_MODE', 'FE');
define('TYPO3_PATH_WEB', __DIR__ . '/');
require __DIR__ . '/typo3/sysext/core/Classes/Core/Bootstrap.php';
\TYPO3\CMS\Core\Core\Bootstrap::getInstance()
->baseSetup('Web/')
->redirectToInstallerIfEssentialConfigurationDoesNotExist()
->startOutputBuffering()
->loadConfigurationAndInitialize();
$frontendRequestHandler = new \TYPO3\CMS\Frontend\FrontendRequestHandler();
$frontendRequestHandler->handleRequest();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment