%PDF- %PDF-
Direktori : /var/www/projetos/stb.ind.br/wp-content/plugins/webp-express/lib/classes/ |
Current File : /var/www/projetos/stb.ind.br/wp-content/plugins/webp-express/lib/classes/HTAccess.php |
<?php namespace WebPExpress; use \WebPExpress\Config; use \WebPExpress\FileHelper; use \WebPExpress\HTAccessRules; use \WebPExpress\Paths; use \WebPExpress\State; class HTAccess { public static function inlineInstructions($instructions, $marker) { if ($marker == 'WebP Express') { return []; } else { return $instructions; } } /** * Must be parsed ie "wp-content", "index", etc. Not real dirs */ public static function addToActiveHTAccessDirsArray($dirId) { $activeHtaccessDirs = State::getState('active-htaccess-dirs', []); if (!in_array($dirId, $activeHtaccessDirs)) { $activeHtaccessDirs[] = $dirId; State::setState('active-htaccess-dirs', array_values($activeHtaccessDirs)); } } public static function removeFromActiveHTAccessDirsArray($dirId) { $activeHtaccessDirs = State::getState('active-htaccess-dirs', []); if (in_array($dirId, $activeHtaccessDirs)) { $activeHtaccessDirs = array_diff($activeHtaccessDirs, [$dirId]); State::setState('active-htaccess-dirs', array_values($activeHtaccessDirs)); } } public static function isInActiveHTAccessDirsArray($dirId) { $activeHtaccessDirs = State::getState('active-htaccess-dirs', []); return (in_array($dirId, $activeHtaccessDirs)); } public static function hasRecordOfSavingHTAccessToDir($dir) { $dirId = Paths::getAbsDirId($dir); if ($dirId !== false) { return self::isInActiveHTAccessDirsArray($dirId); } return false; } /** * @return string|false Rules, or false if no rules found or file does not exist. */ public static function extractWebPExpressRulesFromHTAccess($filename) { if (FileHelper::fileExists($filename)) { $content = FileHelper::loadFile($filename); if ($content === false) { return false; } $pos1 = strpos($content, '# BEGIN WebP Express'); if ($pos1 === false) { return false; } $pos2 = strrpos($content, '# END WebP Express'); if ($pos2 === false) { return false; } return substr($content, $pos1, $pos2 - $pos1); } else { // the .htaccess isn't even there. So there are no rules. return false; } } /** * Sneak peak into .htaccess to see if we have rules in it * This may not be possible (it requires read permission) * Return true, false, or null if we just can't tell */ public static function haveWeRulesInThisHTAccess($filename) { if (FileHelper::fileExists($filename)) { $content = FileHelper::loadFile($filename); if ($content === false) { return null; } $weRules = (self::extractWebPExpressRulesFromHTAccess($filename)); if ($weRules === false) { return false; } return (strpos($weRules, '<IfModule ') !== false); } else { // the .htaccess isn't even there. So there are no rules. return false; } } public static function haveWeRulesInThisHTAccessBestGuess($filename) { // First try to sneak peak. May return null if it cannot be determined. $result = self::haveWeRulesInThisHTAccess($filename); if ($result === true) { return true; } if ($result === null) { // We were not allowed to sneak-peak. // Well, good thing that we stored successful .htaccess write locations ;) // If we recorded a successful write, then we assume there are still rules there // If we did not, we assume there are no rules there $dir = FileHelper::dirName($filename); return self::hasRecordOfSavingHTAccessToDir($dir); } } public static function getRootsWithWebPExpressRulesIn() { $allIds = Paths::getImageRootIds(); $allIds[] = 'cache'; $result = []; foreach ($allIds as $imageRootId) { $filename = Paths::getAbsDirById($imageRootId) . '/.htaccess'; if (self::haveWeRulesInThisHTAccessBestGuess($filename)) { $result[] = $imageRootId; } } return $result; } public static function saveHTAccessRulesToFile($filename, $rules, $createIfMissing = false) { if (!@file_exists($filename)) { if (!$createIfMissing) { return false; } // insert_with_markers will create file if it doesn't exist, so we can continue... } $existingFilePermission = null; $existingDirPermission = null; // Try to make .htaccess writable if its not if (@file_exists($filename)) { if (!@is_writable($filename)) { $existingFilePermission = FileHelper::filePerm($filename); @chmod($filename, 0664); // chmod may fail, we know... } } else { $dir = FileHelper::dirName($filename); if (!@is_writable($dir)) { $existingDirPermission = FileHelper::filePerm($dir); @chmod($dir, 0775); } } /* Add rules to .htaccess */ if (!function_exists('insert_with_markers')) { require_once ABSPATH . 'wp-admin/includes/misc.php'; } // Convert to array, because string version has bugs in Wordpress 4.3 $rules = explode("\n", $rules); add_filter('insert_with_markers_inline_instructions', array('\WebPExpress\HTAccess', 'inlineInstructions'), 10, 2); $success = insert_with_markers($filename, 'WebP Express', $rules); // Revert file or dir permissions if (!is_null($existingFilePermission)) { @chmod($filename, $existingFilePermission); } if (!is_null($existingDirPermission)) { @chmod($dir, $existingDirPermission); } if ($success) { State::setState('htaccess-rules-saved-at-some-point', true); //$containsRules = (strpos(implode('',$rules), '# Redirect images to webp-on-demand.php') != false); $containsRules = (strpos(implode('',$rules), '<IfModule mod_rewrite.c>') !== false); $dir = FileHelper::dirName($filename); $dirId = Paths::getAbsDirId($dir); if ($dirId !== false) { if ($containsRules) { self::addToActiveHTAccessDirsArray($dirId); } else { self::removeFromActiveHTAccessDirsArray($dirId); } } } return $success; } public static function saveHTAccessRules($rootId, $rules, $createIfMissing = true) { $filename = Paths::getAbsDirById($rootId) . '/.htaccess'; return self::saveHTAccessRulesToFile($filename, $rules, $createIfMissing); } /* only called in this file */ public static function saveHTAccessRulesToFirstWritableHTAccessDir($dirs, $rules) { foreach ($dirs as $dir) { if (self::saveHTAccessRulesToFile($dir . '/.htaccess', $rules, true)) { return $dir; } } return false; } /** * Try to deactivate all .htaccess rules. * If success, we return true. * If we fail, we return an array of filenames that have problems * @return true|array */ public static function deactivateHTAccessRules($comment = '# Plugin is deactivated') { $rootsToClean = Paths::getImageRootIds(); $rootsToClean[] = 'home'; $rootsToClean[] = 'cache'; $failures = []; $successes = []; foreach ($rootsToClean as $imageRootId) { $dir = Paths::getAbsDirById($imageRootId); $filename = $dir . '/.htaccess'; if (!FileHelper::fileExists($filename)) { //error_log('exists not:' . $filename); continue; } else { if (self::haveWeRulesInThisHTAccessBestGuess($filename)) { if (self::saveHTAccessRulesToFile($filename, $comment, false)) { $successes[] = $imageRootId; } else { $failures[] = $imageRootId; } } else { //error_log('no rules:' . $filename); } } } $success = (count($failures) == 0); return [$success, $failures, $successes]; } public static function testLinks($config) { /* if (isset($_SERVER['HTTP_ACCEPT']) && (strpos($_SERVER['HTTP_ACCEPT'], 'image/webp') !== false )) { if ($config['operation-mode'] != 'no-conversion') { if ($config['image-types'] != 0) { $webpExpressRoot = Paths::getWebPExpressPluginUrlPath(); $links = ''; if ($config['enable-redirection-to-converter']) { $links = '<br>'; $links .= '<a href="/' . $webpExpressRoot . '/test/test.jpg?debug&time=' . time() . '" target="_blank">Convert test image (show debug)</a><br>'; $links .= '<a href="/' . $webpExpressRoot . '/test/test.jpg?' . time() . '" target="_blank">Convert test image</a><br>'; } // TODO: webp-realizer test links (to missing webp) if ($config['enable-redirection-to-webp-realizer']) { } // TODO: test link for testing redirection to existing if ($config['redirect-to-existing-in-htaccess']) { } return $links; } } }*/ return ''; } public static function getHTAccessDirRequirements() { $minRequired = 'index'; if (Paths::isWPContentDirMovedOutOfAbsPath()) { $minRequired = 'wp-content'; $pluginToo = Paths::isPluginDirMovedOutOfWpContent() ? 'yes' : 'no'; $uploadToo = Paths::isUploadDirMovedOutOfWPContentDir() ? 'yes' : 'no'; } else { // plugin requirement depends... // - if user grants access to 'index', the requirement is Paths::isPluginDirMovedOutOfAbsPath() // - if user grants access to 'wp-content', the requirement is Paths::isPluginDirMovedOutOfWpContent() $pluginToo = 'depends'; // plugin requirement depends... // - if user grants access to 'index', we should be fine, as UPLOADS is always in ABSPATH. // - if user grants access to 'wp-content', the requirement is Paths::isUploadDirMovedOutOfWPContentDir() $uploadToo = 'depends'; } // We need upload too for rewrite rules when destination structure is image-roots. // but it is also good otherwise. So lets always do it. $uploadToo = 'yes'; return [ $minRequired, $pluginToo, // 'yes', 'no' or 'depends' $uploadToo ]; } public static function saveRules($config, $showMessage = true) { list($success, $failedDeactivations, $successfulDeactivations) = self::deactivateHTAccessRules('# The rules have left the building'); $rootsToPutRewritesIn = $config['scope']; if ($config['destination-structure'] == 'doc-root') { // Commented out to quickfix #338 // $rootsToPutRewritesIn = Paths::filterOutSubRoots($rootsToPutRewritesIn); } $dirsContainingWebps = []; $mingled = ($config['destination-folder'] == 'mingled'); if ($mingled) { $dirsContainingWebps[] = 'uploads'; } $scopeOtherThanUpload = (str_replace('uploads', '', implode(',', $config['scope'])) != ''); if ($scopeOtherThanUpload || (!$mingled)) { $dirsContainingWebps[] = 'cache'; } $dirsToPutRewritesIn = array_unique(array_merge($rootsToPutRewritesIn, $dirsContainingWebps)); $failedWrites = []; $successfullWrites = []; foreach ($dirsToPutRewritesIn as $rootId) { $dirContainsSourceImages = in_array($rootId, $rootsToPutRewritesIn); $dirContainsWebPImages = in_array($rootId, $dirsContainingWebps); $rules = HTAccessRules::generateHTAccessRulesFromConfigObj( $config, $rootId, $dirContainsSourceImages, $dirContainsWebPImages ); $success = self::saveHTAccessRules( $rootId, $rules, true ); if ($success) { $successfullWrites[] = $rootId; // Remove it from $successfulDeactivations (if it is there) if (($key = array_search($rootId, $successfulDeactivations)) !== false) { unset($successfulDeactivations[$key]); } } else { $failedWrites[] = $rootId; // Remove it from $failedDeactivations (if it is there) if (($key = array_search($rootId, $failedDeactivations)) !== false) { unset($failedDeactivations[$key]); } } } $success = ((count($failedDeactivations) == 0) && (count($failedWrites) == 0)); $return = [$success, $successfullWrites, $successfulDeactivations, $failedWrites, $failedDeactivations]; if ($showMessage) { self::showSaveRulesMessages($return); } return $return; } public static function showSaveRulesMessages($saveRulesResult) { list($success, $successfullWrites, $successfulDeactivations, $failedWrites, $failedDeactivations) = $saveRulesResult; $msg = ''; if (count($successfullWrites) > 0) { $msg .= '<p>Rewrite rules were saved to the following files:</p>'; foreach ($successfullWrites as $rootId) { $msg .= '<i>' . Paths::getAbsDirById($rootId) . '/.htaccess</i> (' . $rootId . ')<br>'; } } if (count($successfulDeactivations) > 0) { $msg .= '<p>Rewrite rules were removed from the following files:</p>'; foreach ($successfulDeactivations as $rootId) { $msg .= '<i>' . Paths::getAbsDirById($rootId) . '/.htaccess</i> (' . $rootId . ')<br>'; } } if ($msg != '') { Messenger::addMessage( ($success ? 'success' : 'info'), $msg ); } if (count($failedWrites) > 0) { $msg = '<p>Failed writing rewrite rules to the following files:</p>'; foreach ($failedWrites as $rootId) { $msg .= '<i>' . Paths::getAbsDirById($rootId) . '/.htaccess</i> (' . $rootId . ')<br>'; } $msg .= 'You need to change the file permissions to allow WebP Express to save the rules.'; Messenger::addMessage('error', $msg); } else { if (count($failedDeactivations) > 0) { $msg = '<p>Failed deleting unused rewrite rules in the following files:</p>'; foreach ($failedDeactivations as $rootId) { $msg .= '<i>' . Paths::getAbsDirById($rootId) . '/.htaccess</i> (' . $rootId . ')<br>'; } $msg .= 'You need to change the file permissions to allow WebP Express to remove the rules or ' . 'remove them manually'; Messenger::addMessage('error', $msg); } } } }