Exemplo n.º 1
0
 /**
  * Add the template output to the cache and add the cache headers
  */
 protected function addToCache()
 {
     /** @var PageModel $objPage */
     global $objPage;
     $intCache = 0;
     // Decide whether the page shall be cached
     if (!isset($_GET['file']) && !isset($_GET['token']) && empty($_POST) && !BE_USER_LOGGED_IN && !FE_USER_LOGGED_IN && !$_SESSION['DISABLE_CACHE'] && !isset($_SESSION['LOGIN_ERROR']) && !\Message::hasMessages() && intval($objPage->cache) > 0 && !$objPage->protected) {
         $intCache = time() + intval($objPage->cache);
     }
     // Server-side cache
     if ($intCache > 0 && (\Config::get('cacheMode') == 'both' || \Config::get('cacheMode') == 'server')) {
         // If the request string is empty, use a special cache tag which considers the page language
         if (\Environment::get('relativeRequest') == '') {
             $strCacheKey = \Environment::get('host') . '/empty.' . $objPage->language;
         } else {
             $strCacheKey = \Environment::get('host') . '/' . \Environment::get('relativeRequest');
         }
         // HOOK: add custom logic
         if (isset($GLOBALS['TL_HOOKS']['getCacheKey']) && is_array($GLOBALS['TL_HOOKS']['getCacheKey'])) {
             foreach ($GLOBALS['TL_HOOKS']['getCacheKey'] as $callback) {
                 $this->import($callback[0]);
                 $strCacheKey = $this->{$callback[0]}->{$callback[1]}($strCacheKey);
             }
         }
         // Add a suffix if there is a mobile layout (see #7826)
         if ($objPage->mobileLayout > 0) {
             if (\Input::cookie('TL_VIEW') == 'mobile' || \Environment::get('agent')->mobile && \Input::cookie('TL_VIEW') != 'desktop') {
                 $strCacheKey .= '.mobile';
             } else {
                 $strCacheKey .= '.desktop';
             }
         }
         // Replace insert tags for caching
         $strBuffer = $this->replaceInsertTags($this->strBuffer);
         $strBuffer = $this->replaceDynamicScriptTags($strBuffer);
         // see #4203
         // Add the cache file header
         $strHeader = sprintf("<?php /* %s */ \$expire = %d; \$content = %s; \$type = %s; \$files = %s; \$assets = %s; ?>\n", $strCacheKey, (int) $intCache, var_export($this->strContentType, true), var_export($objPage->type, true), var_export(TL_FILES_URL, true), var_export(TL_ASSETS_URL, true));
         $strCachePath = str_replace(TL_ROOT . '/', '', \System::getContainer()->getParameter('kernel.cache_dir'));
         // Create the cache file
         $strMd5CacheKey = md5($strCacheKey);
         $objFile = new \File($strCachePath . '/contao/html/' . substr($strMd5CacheKey, 0, 1) . '/' . $strMd5CacheKey . '.html');
         $objFile->write($strHeader);
         $objFile->append($this->minifyHtml($strBuffer), '');
         $objFile->close();
     }
     // Client-side cache
     if (!headers_sent()) {
         if ($intCache > 0 && (\Config::get('cacheMode') == 'both' || \Config::get('cacheMode') == 'browser')) {
             header('Cache-Control: private, max-age=' . ($intCache - time()));
             header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
             header('Expires: ' . gmdate('D, d M Y H:i:s', $intCache) . ' GMT');
         } else {
             header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
             header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
             header('Expires: Fri, 06 Jun 1975 15:10:00 GMT');
         }
     }
 }
Exemplo n.º 2
0
 /**
  * Restore a version
  *
  * @param integer $intVersion
  */
 public function restore($intVersion)
 {
     if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning']) {
         return;
     }
     $objData = $this->Database->prepare("SELECT * FROM tl_version WHERE fromTable=? AND pid=? AND version=?")->limit(1)->execute($this->strTable, $this->intPid, $intVersion);
     if ($objData->numRows < 1) {
         return;
     }
     $data = \StringUtil::deserialize($objData->data);
     if (!is_array($data)) {
         return;
     }
     // Restore the content
     if ($this->strPath !== null) {
         $objFile = new \File($this->strPath);
         $objFile->write($data['content']);
         $objFile->close();
     }
     // Get the currently available fields
     $arrFields = array_flip($this->Database->getFieldNames($this->strTable));
     // Unset fields that do not exist (see #5219)
     $data = array_intersect_key($data, $arrFields);
     $this->loadDataContainer($this->strTable);
     // Reset fields added after storing the version to their default value (see #7755)
     foreach (array_diff_key($arrFields, $data) as $k => $v) {
         $data[$k] = \Widget::getEmptyValueByFieldType($GLOBALS['TL_DCA'][$this->strTable]['fields'][$k]['sql']);
     }
     $this->Database->prepare("UPDATE " . $this->strTable . " %s WHERE id=?")->set($data)->execute($this->intPid);
     $this->Database->prepare("UPDATE tl_version SET active='' WHERE fromTable=? AND pid=?")->execute($this->strTable, $this->intPid);
     $this->Database->prepare("UPDATE tl_version SET active=1 WHERE fromTable=? AND pid=? AND version=?")->execute($this->strTable, $this->intPid, $intVersion);
     // Trigger the onrestore_version_callback
     if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onrestore_version_callback'])) {
         foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onrestore_version_callback'] as $callback) {
             if (is_array($callback)) {
                 $this->import($callback[0]);
                 $this->{$callback[0]}->{$callback[1]}($this->strTable, $this->intPid, $intVersion, $data);
             } elseif (is_callable($callback)) {
                 $callback($this->strTable, $this->intPid, $intVersion, $data);
             }
         }
     }
     // Trigger the deprecated onrestore_callback
     if (is_array($GLOBALS['TL_DCA'][$this->strTable]['config']['onrestore_callback'])) {
         @trigger_error('Using the onrestore_callback has been deprecated and will no longer work in Contao 5.0. Use the onrestore_version_callback instead.', E_USER_DEPRECATED);
         foreach ($GLOBALS['TL_DCA'][$this->strTable]['config']['onrestore_callback'] as $callback) {
             if (is_array($callback)) {
                 $this->import($callback[0]);
                 $this->{$callback[0]}->{$callback[1]}($this->intPid, $this->strTable, $data, $intVersion);
             } elseif (is_callable($callback)) {
                 $callback($this->intPid, $this->strTable, $data, $intVersion);
             }
         }
     }
     $this->log('Version ' . $intVersion . ' of record "' . $this->strTable . '.id=' . $this->intPid . '" has been restored' . $this->getParentEntries($this->strTable, $this->intPid), __METHOD__, TL_GENERAL);
 }
Exemplo n.º 3
0
 /**
  * Generate the combined file and return its path
  *
  * @param string $strUrl An optional URL to prepend
  *
  * @return string The path to the combined file
  */
 public function getCombinedFile($strUrl = null)
 {
     if ($strUrl === null) {
         $strUrl = TL_ASSETS_URL;
     }
     $strTarget = substr($this->strMode, 1);
     $strKey = substr(md5($this->strKey), 0, 12);
     // Do not combine the files in debug mode (see #6450)
     if (\Config::get('debugMode')) {
         $return = array();
         foreach ($this->arrFiles as $arrFile) {
             $content = file_get_contents(TL_ROOT . '/' . $arrFile['name']);
             // Compile SCSS/LESS files into temporary files
             if ($arrFile['extension'] == self::SCSS || $arrFile['extension'] == self::LESS) {
                 $strPath = 'assets/' . $strTarget . '/' . str_replace('/', '_', $arrFile['name']) . $this->strMode;
                 $objFile = new \File($strPath, true);
                 $objFile->write($this->handleScssLess($content, $arrFile));
                 $objFile->close();
                 $return[] = $strPath;
             } else {
                 $name = $arrFile['name'];
                 // Add the media query (see #7070)
                 if ($arrFile['media'] != '' && $arrFile['media'] != 'all' && strpos($content, '@media') === false) {
                     $name .= '" media="' . $arrFile['media'];
                 }
                 $return[] = $name;
             }
         }
         if ($this->strMode == self::JS) {
             return implode('"></script><script src="', $return);
         } else {
             return implode('"><link rel="stylesheet" href="', $return);
         }
     }
     // Load the existing file
     if (file_exists(TL_ROOT . '/assets/' . $strTarget . '/' . $strKey . $this->strMode)) {
         return $strUrl . 'assets/' . $strTarget . '/' . $strKey . $this->strMode;
     }
     // Create the file
     $objFile = new \File('assets/' . $strTarget . '/' . $strKey . $this->strMode, true);
     $objFile->truncate();
     foreach ($this->arrFiles as $arrFile) {
         $content = file_get_contents(TL_ROOT . '/' . $arrFile['name']);
         // HOOK: modify the file content
         if (isset($GLOBALS['TL_HOOKS']['getCombinedFile']) && is_array($GLOBALS['TL_HOOKS']['getCombinedFile'])) {
             foreach ($GLOBALS['TL_HOOKS']['getCombinedFile'] as $callback) {
                 $this->import($callback[0]);
                 $content = $this->{$callback}[0]->{$callback}[1]($content, $strKey, $this->strMode, $arrFile);
             }
         }
         if ($arrFile['extension'] == self::CSS) {
             $content = $this->handleCss($content, $arrFile);
         } elseif ($arrFile['extension'] == self::SCSS || $arrFile['extension'] == self::LESS) {
             $content = $this->handleScssLess($content, $arrFile);
         }
         $objFile->append($content);
     }
     unset($content);
     $objFile->close();
     // Create a gzipped version
     if (\Config::get('gzipScripts') && function_exists('gzencode')) {
         \File::putContent('assets/' . $strTarget . '/' . $strKey . $this->strMode . '.gz', gzencode(file_get_contents(TL_ROOT . '/assets/' . $strTarget . '/' . $strKey . $this->strMode), 9));
     }
     return $strUrl . 'assets/' . $strTarget . '/' . $strKey . $this->strMode;
 }
Exemplo n.º 4
0
 /**
  * Set the video image
  *
  * @param string $key
  * @param string $content
  */
 public function setImage($key, $content)
 {
     $folder = new Folder(static::$imagesFolder);
     // Create the .htaccess file so images are accessible
     if (!is_file(TL_ROOT . '/' . $folder->path . '/.htaccess')) {
         $htaccessFile = new File($folder->path . '/.htaccess');
         $htaccessFile->write("<IfModule !mod_authz_core.c>\r\nOrder allow,deny\r\nAllow from all\r\n</IfModule>\r\n<IfModule mod_authz_core.c>\r\n  Require all granted\r\n</IfModule>");
         $htaccessFile->close();
     }
     $file = new \File($this->getImageFilePath($key));
     $file->truncate();
     $file->write($content);
     $file->close();
 }
Exemplo n.º 5
0
    /**
     * Load the source editor
     *
     * @return string
     *
     * @throws InternalServerErrorException
     */
    public function source()
    {
        $this->isValid($this->intId);
        if (is_dir(TL_ROOT . '/' . $this->intId)) {
            throw new InternalServerErrorException('Folder "' . $this->intId . '" cannot be edited.');
        } elseif (!file_exists(TL_ROOT . '/' . $this->intId)) {
            throw new InternalServerErrorException('File "' . $this->intId . '" does not exist.');
        }
        $this->import('BackendUser', 'User');
        // Check user permission
        if (!$this->User->hasAccess('f5', 'fop')) {
            throw new AccessDeniedException('Not enough permissions to edit the file source of file "' . $this->intId . '".');
        }
        $objFile = new \File($this->intId);
        // Check whether file type is editable
        if (!in_array($objFile->extension, trimsplit(',', \Config::get('editableFiles')))) {
            throw new AccessDeniedException('File type "' . $objFile->extension . '" (' . $this->intId . ') is not allowed to be edited.');
        }
        $objMeta = null;
        $objVersions = null;
        // Add the versioning routines
        if ($this->blnIsDbAssisted && \Dbafs::shouldBeSynchronized($this->intId)) {
            $objMeta = \FilesModel::findByPath($objFile->value);
            if ($objMeta === null) {
                $objMeta = \Dbafs::addResource($objFile->value);
            }
            $objVersions = new \Versions($this->strTable, $objMeta->id);
            if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu']) {
                // Compare versions
                if (\Input::get('versions')) {
                    $objVersions->compare();
                }
                // Restore a version
                if (\Input::post('FORM_SUBMIT') == 'tl_version' && \Input::post('version') != '') {
                    $objVersions->restore(\Input::post('version'));
                    // Purge the script cache (see #7005)
                    if ($objFile->extension == 'css' || $objFile->extension == 'scss' || $objFile->extension == 'less') {
                        $this->import('Automator');
                        $this->Automator->purgeScriptCache();
                    }
                    $this->reload();
                }
            }
            $objVersions->initialize();
        }
        $strContent = $objFile->getContent();
        if ($objFile->extension == 'svgz') {
            $strContent = gzdecode($strContent);
        }
        // Process the request
        if (\Input::post('FORM_SUBMIT') == 'tl_files') {
            // Restore the basic entities (see #7170)
            $strSource = \StringUtil::restoreBasicEntities(\Input::postRaw('source'));
            // Save the file
            if (md5($strContent) != md5($strSource)) {
                if ($objFile->extension == 'svgz') {
                    $strSource = gzencode($strSource);
                }
                // Write the file
                $objFile->write($strSource);
                $objFile->close();
                // Update the database
                if ($this->blnIsDbAssisted && $objMeta !== null) {
                    /** @var FilesModel $objMeta */
                    $objMeta->hash = $objFile->hash;
                    $objMeta->save();
                    $objVersions->create();
                }
                // Purge the script cache (see #7005)
                if ($objFile->extension == 'css' || $objFile->extension == 'scss' || $objFile->extension == 'less') {
                    $this->import('Automator');
                    $this->Automator->purgeScriptCache();
                }
            }
            if (isset($_POST['saveNclose'])) {
                \System::setCookie('BE_PAGE_OFFSET', 0, 0);
                $this->redirect($this->getReferer());
            }
            $this->reload();
        }
        $codeEditor = '';
        // Prepare the code editor
        if (\Config::get('useCE')) {
            /** @var BackendTemplate|object $objTemplate */
            $objTemplate = new \BackendTemplate('be_ace');
            $objTemplate->selector = 'ctrl_source';
            $objTemplate->type = $objFile->extension;
            $codeEditor = $objTemplate->parse();
        }
        // Versions overview
        if ($GLOBALS['TL_DCA'][$this->strTable]['config']['enableVersioning'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['hideVersionMenu'] && $this->blnIsDbAssisted && $objVersions !== null) {
            $version = $objVersions->renderDropdown();
        } else {
            $version = '';
        }
        // Submit buttons
        $arrButtons = array();
        $arrButtons['save'] = '<button type="submit" name="save" id="save" class="tl_submit" accesskey="s">' . $GLOBALS['TL_LANG']['MSC']['save'] . '</button>';
        $arrButtons['saveNclose'] = '<button type="submit" name="saveNclose" id="saveNclose" class="tl_submit" accesskey="c">' . $GLOBALS['TL_LANG']['MSC']['saveNclose'] . '</button>';
        // Call the buttons_callback (see #4691)
        if (is_array($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'])) {
            foreach ($GLOBALS['TL_DCA'][$this->strTable]['edit']['buttons_callback'] as $callback) {
                if (is_array($callback)) {
                    $this->import($callback[0]);
                    $arrButtons = $this->{$callback[0]}->{$callback[1]}($arrButtons, $this);
                } elseif (is_callable($callback)) {
                    $arrButtons = $callback($arrButtons, $this);
                }
            }
        }
        // Add the form
        return $version . '
<div id="tl_buttons">
<a href="' . $this->getReferer(true) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>
</div>
' . \Message::generate() . '
<form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_files" class="tl_form" method="post">
<div class="tl_formbody_edit">
<input type="hidden" name="FORM_SUBMIT" value="tl_files">
<input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">
<div class="tl_tbox">
  <h3><label for="ctrl_source">' . $GLOBALS['TL_LANG']['tl_files']['editor'][0] . '</label></h3>
  <textarea name="source" id="ctrl_source" class="tl_textarea monospace" rows="12" cols="80" style="height:400px" onfocus="Backend.getScrollOffset()">' . "\n" . htmlspecialchars($strContent) . '</textarea>' . (\Config::get('showHelp') && strlen($GLOBALS['TL_LANG']['tl_files']['editor'][1]) ? '
  <p class="tl_help tl_tip">' . $GLOBALS['TL_LANG']['tl_files']['editor'][1] . '</p>' : '') . '
</div>
</div>

<div class="tl_formbody_submit">

<div class="tl_submit_container">
  ' . implode(' ', $arrButtons) . '
</div>

</div>
</form>' . "\n\n" . $codeEditor;
    }
Exemplo n.º 6
0
 /**
  * Generates the files and returns the URLs.
  *
  * @return array The file URLs
  */
 public function getFileUrls()
 {
     $return = array();
     $strTarget = substr($this->strMode, 1);
     foreach ($this->arrFiles as $arrFile) {
         $content = file_get_contents(TL_ROOT . '/' . $arrFile['name']);
         // Compile SCSS/LESS files into temporary files
         if ($arrFile['extension'] == self::SCSS || $arrFile['extension'] == self::LESS) {
             $strPath = 'assets/' . $strTarget . '/' . str_replace('/', '_', $arrFile['name']) . $this->strMode;
             $objFile = new \File($strPath);
             $objFile->write($this->handleScssLess($content, $arrFile));
             $objFile->close();
             $return[] = $strPath;
         } else {
             $name = $arrFile['name'];
             // Strip the web/ prefix (see #328)
             if (strncmp($name, 'web/', 4) === 0) {
                 $name = substr($name, 4);
             }
             // Add the media query (see #7070)
             if ($arrFile['media'] != '' && $arrFile['media'] != 'all' && strpos($content, '@media') === false) {
                 $name .= '" media="' . $arrFile['media'];
             }
             $return[] = $name;
         }
     }
     return $return;
 }