/wp-content/plugins/zencache/src/includes/closures/Plugin/HtaccessUtils.php
PHP | 273 lines | 151 code | 29 blank | 93 comment | 45 complexity | c7ebf73a9e88322f0c79a0299780b16e MD5 | raw file
- <?php
- namespace WebSharks\ZenCache;
- /*
- * Unique comment marker.
- *
- * @since 151220 Enhancing `.htaccess` tweaks.
- *
- * @return string Used in `.htaccess` parsing.
- */
- $self->htaccess_marker = 'WmVuQ2FjaGU';
- /*
- * Plugin options that have associated htaccess rules.
- *
- * @since 15xxxx Improving `.htaccess` tweaks.
- *
- * @return array Plugin options that have associated htaccess rules
- *
- * @note We keep track of this to avoid the issue described here: http://git.io/vEFIH
- */
- $self->options_with_htaccess_rules = array('cdn_enable');
- /*
- * Add template blocks to `/.htaccess` file.
- *
- * @since 151114 Adding `.htaccess` tweaks.
- *
- * @return boolean True if added successfully.
- *
- * @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
- */
- $self->addWpHtaccess = function () use ($self) {
- global $is_apache;
- if (!$is_apache) {
- return false; // Not running the Apache web server.
- }
- if (!$self->options['enable']) {
- return true; // Nothing to do.
- }
- if (!$self->needHtaccessRules()) {
- if($self->findHtaccessMarker()) { // Do we need to clean up previously added rules?
- $self->removeWpHtaccess(); // Fail silently since we don't need rules in place.
- }
- return true; // Nothing to do; no options enabled that require htaccess rules.
- }
- if (!$self->removeWpHtaccess()) {
- return false; // Unable to remove.
- }
- if (!($htaccess = $self->readHtaccessFile())) {
- return false; // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
- }
- $template_blocks = ''; // Initialize.
- if (is_dir($templates_dir = dirname(dirname(dirname(__FILE__))).'/templates/htaccess')) {
- foreach (scandir($templates_dir) as $_template_file) {
- switch ($_template_file) {
-
- }
- }
- unset($_template_file); // Housekeeping.
- }
- if(empty($template_blocks)) { // Do we need to add anything to htaccess?
- $self->closeHtaccessFile($htaccess); // No need to write to htaccess file in this case.
- return true; // Nothing to do, but no failures either.
- }
- $template_header = '# BEGIN '.NAME.' '.$self->htaccess_marker.' (the '.$self->htaccess_marker.' marker is required for '.NAME.'; do not remove)'."\n";
- $template_footer = '# END '.NAME.' '.$self->htaccess_marker;
- $htaccess['file_contents'] = $template_header.trim($template_blocks)."\n".$template_footer."\n\n".$htaccess['file_contents'];
- if (!$self->writeHtaccessFile($htaccess, true)) {
- return false; // Failure; could not write changes.
- }
- return true; // Added successfully.
- };
- /*
- * Remove template blocks from `/.htaccess` file.
- *
- * @since 151114 Adding `.htaccess` tweaks.
- *
- * @return boolean True if removed successfully.
- *
- * @TODO Improve error reporting detail to better catch unexpected failures; see http://git.io/vEFLT
- */
- $self->removeWpHtaccess = function () use ($self) {
- global $is_apache;
- if (!$is_apache) {
- return false; // Not running the Apache web server.
- }
- if (!($htaccess_file = $self->findHtaccessFile())) {
- return true; // File does not exist.
- }
- if (!$self->findHtaccessMarker()) {
- return true; // Template blocks are already gone.
- }
- if (!($htaccess = $self->readHtaccessFile())) {
- return false; // Failure; could not read file, create file, or invalid UTF8 encountered, file may be corrupt.
- }
- $regex = '/#\s*BEGIN\s+'.preg_quote(NAME, '/').'\s+'.$self->htaccess_marker.'.*?#\s*END\s+'.preg_quote(NAME, '/').'\s+'.$self->htaccess_marker.'\s*/is';
- $htaccess['file_contents'] = preg_replace($regex, '', $htaccess['file_contents']);
- if (!$self->writeHtaccessFile($htaccess, false)) {
- return false; // Failure; could not write changes.
- }
- return true; // Removed successfully.
- };
- /*
- * Finds absolute server path to `/.htaccess` file.
- *
- * @since 151114 Adding `.htaccess` tweaks.
- *
- * @return string Absolute server path to `/.htaccess` file;
- * else an empty string if unable to locate the file.
- */
- $self->findHtaccessFile = function () use ($self) {
- $file = ''; // Initialize.
- $home_path = $self->wpHomePath();
- if (is_file($htaccess_file = $home_path.'.htaccess')) {
- $file = $htaccess_file;
- }
- return $file;
- };
- /*
- * Determines if there are any plugin options enabled that require htaccess rules to be added.
- *
- * @since 15xxxx Improving `.htaccess` tweaks.
- *
- * @return bool True when an option is enabled that requires htaccess rules, false otherwise.
- */
- $self->needHtaccessRules = function () use ($self) {
- if(!is_array($self->options_with_htaccess_rules)) {
- return false; // Nothing to do.
- }
- foreach ($self->options_with_htaccess_rules as $option) {
- if ($self->options[$option]) {
- return true; // Yes, there are options enabled that require htaccess rules.
- }
- }
- return false; // No, there are no options enabled that require htaccess rules.
- };
- /*
- * Utility method used to check if htaccess file contains $htaccess_marker
- *
- * @since 151114 Adding `.htaccess` tweaks.
- *
- * @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
- *
- * @return bool False on failure or when marker does not exist in htaccess, true otherwise.
- */
- $self->findHtaccessMarker = function ($htaccess_marker = '') use ($self) {
- if (!($htaccess_file = $self->findHtaccessFile())) {
- return false; // File does not exist.
- }
- if (!is_readable($htaccess_file)) {
- return false; // Not possible.
- }
- if (($htaccess_file_contents = file_get_contents($htaccess_file)) === false) {
- return false; // Failure; could not read file.
- }
- if (empty($htaccess_marker)) {
- $htaccess_marker = $self->htaccess_marker;
- }
- if (stripos($htaccess_file_contents, $htaccess_marker) === false) {
- return false; // Htaccess marker is missing
- }
- return true; // Htaccess has the marker
- };
- /*
- * Gets contents of `/.htaccess` file with exclusive lock to read+write. If file doesn't exist, we attempt to create it.
- *
- * @since 151220 Improving `.htaccess` utils.
- *
- * @param string $htaccess_file Absolute path to the htaccess file. Optional.
- * If not provided, we attempt to find it or create it if it doesn't exist.
- *
- * @return array|bool Returns an array with data necessary to call $self->writeHtaccessFile():
- * `fp` a file pointer resource, `file_contents` a string. Returns `false` on failure.
- *
- * @note If a call to this method is not followed by a call to $self->writeHtaccessFile(),
- * you must make sure that you unlock and close the `fp` resource yourself.
- */
- $self->readHtaccessFile = function ($htaccess_file = '') use ($self) {
- if (empty($htaccess_file) && !($htaccess_file = $self->findHtaccessFile())) {
- if (!is_writable($self->wpHomePath()) || file_put_contents($htaccess_file = $self->wpHomePath().'.htaccess', '') === false) {
- return false; // Unable to find and/or create `.htaccess`.
- } // If it doesn't exist, we create the `.htaccess` file here.
- }
- if (!is_readable($htaccess_file) || !is_writable($htaccess_file) || (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS)) {
- return false; // Not possible.
- }
- if (!($fp = fopen($htaccess_file, 'rb+')) || !flock($fp, LOCK_EX)) {
- fclose($fp); // Just in case we opened it before failing to obtain a lock.
- return false; // Failure; could not open file and obtain an exclusive lock.
- }
- if (($file_contents = fread($fp, filesize($htaccess_file))) && ($file_contents === wp_check_invalid_utf8($file_contents))) {
- rewind($fp); // Rewind pointer to beginning of file.
- return compact('fp', 'file_contents');
- } else { // Failure; could not read file or invalid UTF8 encountered, file may be corrupt.
- flock($fp, LOCK_UN);
- fclose($fp);
- return false;
- }
- };
- /*
- * Writes to `/.htaccess` file using provided file pointer.
- *
- * @since 151220 Improving `.htaccess` utils.
- *
- * @param array $htaccess Array containing `fp` file resource pointing to htaccess file and `file_contents` to write to file.
- * @param bool $require_marker Whether or not to require the marker be present in contents before writing.
- * @param string $htaccess_marker Unique comment marker used to identify rules added by this plugin.
- *
- * @return bool True on success, false on failure.
- */
- $self->writeHtaccessFile = function (array $htaccess, $require_marker = true, $htaccess_marker = '') use ($self) {
- if (defined('DISALLOW_FILE_MODS') && DISALLOW_FILE_MODS) {
- return false; // Not possible.
- }
- if (!is_resource($htaccess['fp'])) {
- return false;
- }
- $htaccess_marker = $htaccess_marker ?: $self->htaccess_marker;
- $_have_marker = stripos($htaccess['file_contents'], $htaccess_marker);
- // Note: rewind() necessary here because we fread() above.
- if (($require_marker && $_have_marker === false) || !rewind($htaccess['fp']) || !ftruncate($htaccess['fp'], 0) || !fwrite($htaccess['fp'], $htaccess['file_contents'])) {
- flock($htaccess['fp'], LOCK_UN);
- fclose($htaccess['fp']);
- return false; // Failure; could not write changes.
- }
- fflush($htaccess['fp']);
- flock($htaccess['fp'], LOCK_UN);
- fclose($htaccess['fp']);
- return true;
- };
- /*
- * Utility method used to unlock and close htaccess file resource.
- *
- * @since 151114 Adding `.htaccess` tweaks.
- *
- * @param array $htaccess Array containing at least an `fp` file resource pointing to htaccess file.
- *
- * @return bool False on failure, true otherwise.
- */
- $self->closeHtaccessFile = function (array $htaccess) use ($self) {
- if (!is_resource($htaccess['fp'])) {
- return false; // Failure; requires a valid file resource.
- }
- flock($htaccess['fp'], LOCK_UN);
- fclose($htaccess['fp']);
- return true;
- };