PluginProbe ʕ •ᴥ•ʔ
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF / trunk
Robin Image Optimizer – Unlimited Image Optimization, WebP & AVIF vtrunk
2.0.5 trunk 1.3.7 1.4.0 1.4.1 1.4.2 1.4.6 1.5.0 1.5.3 1.5.6 1.5.8 1.6.5 1.6.6 1.6.9 1.7.0 1.7.4 1.8.1 1.8.2 1.9.0 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4
robin-image-optimizer / libs / addons / includes / classes / webp / class-webp-server.php
robin-image-optimizer / libs / addons / includes / classes / webp Last commit date
vendor 5 months ago class-webp-api.php 5 months ago class-webp-delivery.php 3 months ago class-webp-html-image-urls-replacer.php 5 months ago class-webp-html-picture-tags.php 5 months ago class-webp-listener.php 3 months ago class-webp-server.php 5 months ago composer.json 3 years ago composer.lock 3 years ago
class-webp-server.php
324 lines
1 <?php
2
3 namespace WRIO\WEBP;
4
5 /**
6 * @version 1.0
7 */
8 class Server {
9
10 /**
11 * return the server home path
12 *
13 * @since 1.0.4
14 */
15 public static function get_home_path() {
16 $home = set_url_scheme( get_option( 'home' ), 'http' );
17 $siteurl = set_url_scheme( get_option( 'siteurl' ), 'http' );
18
19 if ( ! empty( $home ) && 0 !== strcasecmp( $home, $siteurl ) ) {
20 $wp_path_rel_to_home = str_ireplace( $home, '', $siteurl ); /* $siteurl - $home */
21 $pos = strripos( str_replace( '\\', '/', $_SERVER['SCRIPT_FILENAME'] ), trailingslashit( $wp_path_rel_to_home ) );
22
23 if ( $pos !== false ) {
24 $home_path = substr( $_SERVER['SCRIPT_FILENAME'], 0, $pos );
25 $home_path = trim( $home_path, '/\\' ) . DIRECTORY_SEPARATOR;
26
27 } else {
28 $wp_path_rel_to_home = DIRECTORY_SEPARATOR . trim( $wp_path_rel_to_home, '/\\' ) . DIRECTORY_SEPARATOR;
29
30 $real_apth = realpath( ABSPATH ) . DIRECTORY_SEPARATOR;
31
32 $pos = strpos( $real_apth, $wp_path_rel_to_home );
33 $home_path = substr( $real_apth, 0, $pos );
34 $home_path = trim( $home_path, '/\\' ) . DIRECTORY_SEPARATOR;
35 }
36 } else {
37 $home_path = ABSPATH;
38 }
39
40 $home_path = trim( $home_path, '\\/ ' );
41
42 // not for windows
43 if ( DIRECTORY_SEPARATOR != '\\' ) {
44 $home_path = DIRECTORY_SEPARATOR . $home_path;
45 }
46
47 return $home_path;
48 }
49
50 /**
51 * Return if the server run Apache
52 *
53 * @since 1.0.4
54 * @return bool
55 */
56 public static function is_apache() {
57 $is_apache = ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Apache' ) !== false || strpos( $_SERVER['SERVER_SOFTWARE'], 'LiteSpeed' ) !== false );
58
59 return $is_apache;
60 }
61
62 /**
63 * Return if the server run on nginx
64 *
65 * @since 1.0.4
66 * @return bool
67 */
68 public static function is_nginx() {
69 $is_nginx = ( strpos( $_SERVER['SERVER_SOFTWARE'], 'nginx' ) !== false );
70
71 return $is_nginx;
72 }
73
74 /**
75 * Return if the server run on IIS
76 *
77 * @since 1.0.4
78 * @return bool
79 */
80 public static function is_iss() {
81 $is_IIS = ! static::is_apache() && ( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS' ) !== false || strpos( $_SERVER['SERVER_SOFTWARE'], 'ExpressionDevServer' ) !== false );
82
83 return $is_IIS;
84 }
85
86 /**
87 * Return if the server run on IIS version 7 and up
88 *
89 * @since 1.0.4
90 * @return bool
91 */
92 public static function is_iis7() {
93 $is_iis7 = static::is_iss() && intval( substr( $_SERVER['SERVER_SOFTWARE'], strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/' ) + 14 ) ) >= 7;
94
95 return $is_iis7;
96 }
97
98 /**
99 * Is permalink enabled?
100 *
101 * @since 1.0.4
102 * @return bool
103 * @global \WP_Rewrite $wp_rewrite
104 */
105 public static function is_permalink() {
106 global $wp_rewrite;
107
108 if ( ! isset( $wp_rewrite ) || ! is_object( $wp_rewrite ) || ! $wp_rewrite->using_permalinks() ) {
109 return false;
110 }
111
112 return true;
113 }
114
115 /**
116 * Return whatever the htaccess config file is writable
117 *
118 * @since 1.0.4
119 * @return bool
120 */
121 public static function is_writable_htaccess( $htaccess_file ) {
122 if ( ( ! file_exists( $htaccess_file ) && static::is_permalink() ) || is_writable( $htaccess_file ) ) {
123 return true;
124 }
125
126 return false;
127 }
128
129 /**
130 * Return whatever the web.config config file is writable
131 *
132 * @since 1.0.4
133 */
134 public static function is_writable_webconfig_file() {
135 $home_path = static::get_home_path();
136 $web_config_file = $home_path . 'web.config';
137
138 if ( ( ! file_exists( $web_config_file ) && self::is_permalink() ) || win_is_writable( $web_config_file ) ) {
139 return true;
140 }
141
142 return false;
143 }
144
145 /**
146 * @since 1.0.4
147 * @return bool
148 */
149 public static function got_mod_rewrite() {
150 if ( self::apache_mod_loaded( 'mod_rewrite', true ) ) {
151 return true;
152 }
153
154 return false;
155 }
156
157 /**
158 * Does the specified module exist in the Apache config?
159 *
160 * @since 1.0.4
161 *
162 * @param string $mod The module, e.g. mod_rewrite.
163 * @param bool $default Optional. The default return value if the module is not found. Default false.
164 *
165 * @return bool Whether the specified module is loaded.
166 * @global bool $is_apache
167 */
168 public static function apache_mod_loaded( $mod, $default = false ) {
169 if ( ! static::is_apache() ) {
170 return false;
171 }
172
173 if ( function_exists( 'apache_get_modules' ) ) {
174 $mods = apache_get_modules();
175 if ( in_array( $mod, $mods ) ) {
176 return true;
177 }
178 } elseif ( getenv( 'HTTP_MOD_REWRITE' ) !== false ) {
179 $mod_found = getenv( 'HTTP_MOD_REWRITE' ) == 'On' ? true : false;
180
181 return $mod_found;
182 } elseif ( function_exists( 'phpinfo' ) && false === strpos( ini_get( 'disable_functions' ), 'phpinfo' ) ) {
183 ob_start();
184 phpinfo( 8 );
185 $phpinfo = ob_get_clean();
186 if ( false !== strpos( $phpinfo, $mod ) ) {
187 return true;
188 }
189 }
190
191 return $default;
192 }
193
194 /**
195 * Return whatever server using the .htaccess config file
196 *
197 * @since 1.0.4
198 * @return bool
199 */
200 public static function server_use_htaccess() {
201 $home_path = static::get_home_path();
202 $htaccess_file = $home_path . DIRECTORY_SEPARATOR . '.htaccess';
203
204 if ( ( ! file_exists( $htaccess_file ) && is_writable( $home_path ) && static::is_permalink() ) || is_writable( $htaccess_file ) ) {
205 if ( static::got_mod_rewrite() ) {
206 return true;
207 }
208 }
209
210 return false;
211 }
212
213 /**
214 * Cleans webp rules from htaccess file. Use when deactivating a plugin
215 * or turn off webp support option.
216 *
217 * @since 1.0.4
218 */
219 public static function htaccess_clear_webp_rules() {
220 $wp_upload_dir = wp_upload_dir();
221 $root_htaccess_file_path = static::get_home_path() . DIRECTORY_SEPARATOR . '.htaccess';
222 $wp_content_htaccess_file_path = trailingslashit( WP_CONTENT_DIR ) . '.htaccess';
223
224 static::insert_with_markers( $root_htaccess_file_path, '' );
225
226 if ( isset( $wp_upload_dir['error'] ) && $wp_upload_dir['error'] !== false ) {
227 \WRIO_Plugin::app()->logger->error( 'It is not possible to update webp rules for htaccess, because upload dir is not writable.' );
228 } else {
229
230 $upload_base = $wp_upload_dir['basedir'];
231 $uploads_htaccess_file_path = trailingslashit( $upload_base ) . '.htaccess';
232
233 static::insert_with_markers( $uploads_htaccess_file_path, '' );
234 }
235
236 static::insert_with_markers( $wp_content_htaccess_file_path, '' );
237 }
238
239 /**
240 * Add webp rules in htaccess file. Use when activating a plugin
241 * or turn on webp support option.
242 *
243 * @since @since 1.0.4
244 *
245 * @param bool $clear
246 */
247 public static function htaccess_update_webp_rules() {
248 // [BS] Backward compat. 11/03/2019 - remove possible settings from root .htaccess
249 $wp_upload_dir = wp_upload_dir();
250 $root_htaccess_file_path = static::get_home_path() . DIRECTORY_SEPARATOR . '.htaccess';
251 $wp_content_htaccess_file_path = trailingslashit( WP_CONTENT_DIR ) . '.htaccess';
252
253 $rules = '
254 <IfModule mod_rewrite.c>
255 RewriteEngine On
256
257 ##### TRY FIRST the file appended with .webp (ex. test.jpg.webp) #####
258 # Does browser explicitly support webp?
259 RewriteCond %{HTTP_USER_AGENT} Chrome [OR]
260 # OR Is request from Page Speed
261 RewriteCond %{HTTP_USER_AGENT} "Google Page Speed Insights" [OR]
262 # OR does this browser explicitly support webp
263 RewriteCond %{HTTP_ACCEPT} image/webp
264 # AND is the request a jpg or png?
265 RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png)$
266 # AND does a .ext.webp image exist?
267 RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI}.webp -f
268 # THEN send the webp image and set the env var webp
269 RewriteRule ^(.+)$ $1.webp [NC,T=image/webp,E=webp,L]
270
271 ##### IF NOT, try the file with replaced extension (test.webp) #####
272 RewriteCond %{HTTP_USER_AGENT} Chrome [OR]
273 RewriteCond %{HTTP_USER_AGENT} "Google Page Speed Insights" [OR]
274 RewriteCond %{HTTP_ACCEPT} image/webp
275 # AND is the request a jpg or png? (also grab the basepath %1 to match in the next rule)
276 RewriteCond %{REQUEST_URI} ^(.+)\.(?:jpe?g|png)$
277 # AND does a .ext.webp image exist?
278 RewriteCond %{DOCUMENT_ROOT}/%1.webp -f
279 # THEN send the webp image and set the env var webp
280 RewriteRule (.+)\.(?:jpe?g|png)$ $1.webp [NC,T=image/webp,E=webp,L]
281
282 </IfModule>
283 <IfModule mod_headers.c>
284 # If REDIRECT_webp env var exists, append Accept to the Vary header
285 Header append Vary Accept env=REDIRECT_webp
286 </IfModule>
287
288 <IfModule mod_mime.c>
289 AddType image/webp .webp
290 </IfModule>
291 ';
292
293 static::insert_with_markers( $root_htaccess_file_path, $rules );
294
295 if ( isset( $wp_upload_dir['error'] ) && $wp_upload_dir['error'] !== false ) {
296 \WRIO_Plugin::app()->logger->error( 'It is not possible to update webp rules for htaccess, because upload dir is not writable.' );
297 } else {
298
299 $upload_base = $wp_upload_dir['basedir'];
300 $uploads_htaccess_file_path = trailingslashit( $upload_base ) . '.htaccess';
301
302 static::insert_with_markers( $uploads_htaccess_file_path, $rules );
303 }
304
305 static::insert_with_markers( $wp_content_htaccess_file_path, $rules );
306 }
307
308 public static function insert_with_markers( $file_path, $content ) {
309 if ( ! static::is_writable_htaccess( $file_path ) ) {
310 \WRIO_Plugin::app()->logger->error( sprintf( 'It is not possible to update webp rules for htaccess, because file (%s) is not writable.', $file_path ) );
311 } else {
312 if ( ! static::got_mod_rewrite() ) {
313 \WRIO_Plugin::app()->logger->error( "It isn't possible to update webp rules for htaccess, because mode rewrite is unsupported." );
314
315 return;
316 }
317
318 if ( ! insert_with_markers( $file_path, 'Robin Image Optimizer Webp', $content ) ) {
319 \WRIO_Plugin::app()->logger->error( 'Failed write webp rules to htaccess file (%s)' );
320 }
321 }
322 }
323 }
324