HEX
Server: Apache/2.4.65 (Debian)
System: Linux 88f31f35b0b8 6.1.0-38-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.147-1 (2025-08-02) x86_64
User: www-data (33)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/html/wp-content/plugins/tiny-compress-images/src/class-tiny-apache-rewrite.php
<?php
/*
* Tiny Compress Images - WordPress plugin.
* Copyright (C) 2015-2018 Tinify B.V.
*
* This program 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.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\n*/

/**
 * Tiny_Apache_Rewrite
 * class responsible for the apache rules for image delivery.
 * - toggling the rules when saving settings
 * - inserting/removing rules from htaccess
 *
 * We are only updating rules when:
 * - updating the option convert_format
 * - uninstalling the plug-in
 */
class Tiny_Apache_Rewrite extends Tiny_WP_Base {

	/**
	 * seperator when rules are inserted
	 * @var string
	 */
	const MARKER = 'tiny-compress-images';

	/**
	 * Installs or uninstalls the htaccess rules
	 * hooked into `update_option_tinypng_convert_format`
	 * https://developer.wordpress.org/reference/hooks/update_option_option/
	 *
	 *
	 * @param mixed $old_value
	 * @param mixed $value
	 * @param string $option
	 * @return void
	 */
	public static function toggle_rules( $old_value, $value, $option ) {
		$old_delivery = isset( $old_value['delivery_method'] ) ?
			$old_value['delivery_method'] : null;
		$new_delivery = isset( $value['delivery_method'] ) ?
			$value['delivery_method'] : null;

		if ( $old_delivery === $new_delivery ) {
			return;
		}

		if ( 'htaccess' === $new_delivery ) {
			$installed = self::install_rules();
			Tiny_Logger::debug( 'htaccess rules installed: ' . $installed );
			return;
		}

		// We only uninstall if we were previously using htaccess
		if ( 'htaccess' === $old_delivery ) {
			$uninstalled = self::uninstall_rules();
			Tiny_Logger::debug( 'htaccess rules uninstaled: ' . $uninstalled );
		}
	}

	/**
	 * Generate .htaccess rewrite rules for serving WebP and AVIF images.
	 *
	 * @return string The .htaccess rules
	 */
	private static function get_rewrite_rules() {
		$rules   = array();
		$rules[] = '<IfModule mod_rewrite.c>';
		$rules[] = 'RewriteEngine On';
		$rules[] = 'RewriteOptions Inherit';

		$rules = array_merge( $rules, self::get_avif_rules() );
		$rules = array_merge( $rules, self::get_webp_rules() );

		$rules[] = '</IfModule>';

		$rules[] = '<IfModule mod_headers.c>';
		$rules[] = '<FilesMatch "\.(jpe?g|png)$">';
		$rules[] = 'Header append Vary Accept';
		$rules[] = '</FilesMatch>';
		$rules[] = '</IfModule>';

		$rules[] = '<IfModule mod_mime.c>';
		$rules[] = 'AddType image/webp .webp';
		$rules[] = 'AddType image/avif .avif';
		$rules[] = '</IfModule>';

		return implode( "\n", $rules );
	}

	/**
	 * Generate AVIF rewrite rules.
	 *
	 * @return array[] AVIF rewrite rules
	 */
	private static function get_avif_rules() {
		$rules   = array();
		$rules[] = 'RewriteCond %{HTTP_ACCEPT} image/avif';
		$rules[] = 'RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png)$';
		$rules[] = 'RewriteCond %{DOCUMENT_ROOT}/%1.avif -f';
		$rules[] = 'RewriteCond %{QUERY_STRING} !type=original';
		$rules[] = 'RewriteRule (.+)\.(?:jpe?g|png)$ $1.avif [T=image/avif,L]';
		return $rules;
	}

	/**
	 * Generate WebP rewrite rules.
	 *
	 * @return array[] WebP rewrite rules
	 */
	private static function get_webp_rules() {
		$rules   = array();
		$rules[] = 'RewriteCond %{HTTP_ACCEPT} image/webp';
		$rules[] = 'RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png)$';
		$rules[] = 'RewriteCond %{DOCUMENT_ROOT}/%1.webp -f';
		$rules[] = 'RewriteCond %{QUERY_STRING} !type=original';
		$rules[] = 'RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [T=image/webp,L]';

		return $rules;
	}

	/**
	 * Install rewrite rules to .htaccess files.
	 *
	 * @return bool True on success, false otherwise
	 */
	private static function install_rules() {
		$rules      = self::get_rewrite_rules();
		$upload_dir = wp_upload_dir();
		if ( isset( $upload_dir['basedir'] ) && is_writable( $upload_dir['basedir'] ) ) {
			$htaccess_file = $upload_dir['basedir'] . '/.htaccess';
			return insert_with_markers( $htaccess_file, self::MARKER, $rules );
		}

		return false;
	}

	/**
	 * Remove rewrite rules from .htaccess files.
	 *
	 * @return bool True on success, false otherwise
	 */
	public static function uninstall_rules() {
		$upload_dir = wp_upload_dir();
		if (
			file_exists( $upload_dir['basedir'] . '/.htaccess' )
		) {
			$htaccess_file = $upload_dir['basedir'] . '/.htaccess';
			return insert_with_markers( $htaccess_file, self::MARKER, '' );
		}

		return false;
	}
}