PluginProbe
HTTP Headers / 1.2.0
HTTP Headers v1.2.0
1.19.5 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.12.0 1.12.1 1.12.2 1.13.0 1.13.1 1.13.2 1.13.3 1.13.4 1.14.0 1.14.1 1.14.2 1.15.0 All 60 releases
← All changes | http-headers.php +93 -1286 1.15.01.2.0 View file →
@@ -1,10 +1,10 @@
1 1 <?php
2 2 /*
3 3 Plugin Name: HTTP Headers
4 4 Plugin URI: https://zinoui.com/blog/http-headers-for-wordpress
5 -Description: A plugin for HTTP headers management including security, access-control (CORS), caching, compression, and authentication.
6 -Version: 1.15.0
5 +Description: This plugin adds CORS & security HTTP headers to your website. Improves your website overall security.
6 +Version: 1.2.0
7 7 Author: Dimitar Ivanov
8 8 Author URI: https://zinoui.com
9 9 License: GPLv2 or later
10 10 Text Domain: http-headers
@@ -23,126 +23,40 @@
23 23
24 24 You should have received a copy of the GNU General Public License
25 25 along with this program. If not, see <http://www.gnu.org/copyleft/gpl.html>.
26 26
27 -Copyright (c) 2017-2020 Zino UI
27 +Copyright (c) 2017 Zino UI
28 28 */
29 29
30 -if (!defined('ABSPATH')) {
31 - exit;
30 +if (get_option('hh_strict_transport_security_max_age') === false) {
31 + $value = get_option('hh_strict_transport_security_value');
32 + $max_age = preg_match('/max-age=(\d+)/', $value, $match) ? $match[1] : 0;
33 + $sub_domains = strpos($value, 'includeSubDomains') !== false ? 1 : 0;
34 + add_option('hh_strict_transport_security_max_age', $max_age, null, 'yes');
35 + add_option('hh_strict_transport_security_sub_domains', $sub_domains, null, 'yes');
36 + add_option('hh_strict_transport_security_preload', 0, null, 'yes');
32 37 }
33 38
34 -$options = include dirname(__FILE__) . '/views/includes/options.inc.php';
35 -foreach ($options as $option) {
36 - if (get_option($option[0]) === false) {
37 - add_option($option[0], $option[1], null, 'yes');
38 - }
39 +if (get_option('hh_referrer_policy') === false) {
40 + add_option('hh_referrer_policy', 0, null, 'yes');
41 + add_option('hh_referrer_policy_value', null, null, 'yes');
39 42 }
40 43
41 -function build_csp_value($value) {
42 - $csp = array();
43 - foreach ($value as $key => $val)
44 - {
45 - if (is_array($val))
46 - {
47 - $source = NULL;
48 - if (isset($val['source']))
49 - {
50 - $source = $val['source'];
51 - unset($val['source']);
52 - }
53 - if (!empty($val))
54 - {
55 - $val = join(" ", array_keys($val));
56 - if ($source)
57 - {
58 - $val .= " " . $source;
59 - }
60 - $csp[] = sprintf("%s %s", $key, $val);
61 - } elseif ($source) {
62 - $csp[] = sprintf("%s %s", $key, $source);
63 - }
64 - } else {
65 - if (in_array($key, array('block-all-mixed-content', 'upgrade-insecure-requests')))
66 - {
67 - $csp[] = $key;
68 - }
69 - if (in_array($key, array('plugin-types', 'report-to')) && !empty($val))
70 - {
71 - $csp[] = sprintf("%s %s", $key, $val);
72 - }
73 - }
74 - }
75 -
76 - if (!$csp)
77 - {
78 - return NULL;
79 - }
80 -
81 - return join('; ', $csp);
82 -}
83 -
84 -function get_http_headers() {
85 - $statuses = array();
86 - $unset = array();
87 - $headers = array();
88 - $append = array();
44 +function http_headers() {
45 +
89 46 if (get_option('hh_x_frame_options') == 1) {
90 47 $x_frame_options_value = strtoupper(get_option('hh_x_frame_options_value'));
91 48 if ($x_frame_options_value == 'ALLOW-FROM') {
92 49 $x_frame_options_value .= ' ' . get_option('hh_x_frame_options_domain');
93 50 }
94 - $headers['X-Frame-Options'] = $x_frame_options_value;
51 + header("X-Frame-Options: " . $x_frame_options_value);
95 52 }
96 - if (get_option('hh_x_powered_by') == 1) {
97 - if (get_option('hh_x_powered_by_option') == 'set') {
98 - $headers['X-Powered-By'] = get_option('hh_x_powered_by_value');
99 - } else {
100 - $unset[] = 'X-Powered-By';
101 - }
102 - }
103 53 if (get_option('hh_x_xxs_protection') == 1) {
104 - $headers['X-XSS-Protection'] = get_option('hh_x_xxs_protection_value');
105 - if ($headers['X-XSS-Protection'] == '1; report=') {
106 - $headers['X-XSS-Protection'] .= get_option('hh_x_xxs_protection_uri');
107 - }
54 + header("X-XSS-Protection: " . get_option('hh_x_xxs_protection_value'));
108 55 }
109 56 if (get_option('hh_x_content_type_options') == 1) {
110 - $headers['X-Content-Type-Options'] = get_option('hh_x_content_type_options_value');
57 + header("X-Content-Type-Options: " . get_option('hh_x_content_type_options_value'));
111 58 }
112 - if (get_option('hh_x_download_options') == 1) {
113 - $headers['X-Download-Options'] = get_option('hh_x_download_options_value');
114 - }
115 - if (get_option('hh_x_permitted_cross_domain_policies') == 1) {
116 - $headers['X-Permitted-Cross-Domain-Policies'] = get_option('hh_x_permitted_cross_domain_policies_value');
117 - }
118 - if (get_option('hh_x_dns_prefetch_control') == 1) {
119 - $headers['X-DNS-Prefetch-Control'] = get_option('hh_x_dns_prefetch_control_value');
120 - }
121 - if (get_option('hh_connection') == 1) {
122 - $headers['Connection'] = get_option('hh_connection_value');
123 - }
124 - if (get_option('hh_pragma') == 1) {
125 - $headers['Pragma'] = get_option('hh_pragma_value');
126 - }
127 - if (get_option('hh_age') == 1) {
128 - $headers['Age'] = sprintf("%u", get_option('hh_age_value'));
129 - }
130 - if (get_option('hh_cache_control') == 1) {
131 - $hh_cache_control_value = get_option('hh_cache_control_value', array());
132 - $tmp = array();
133 - foreach ($hh_cache_control_value as $k => $v) {
134 - if (in_array($k, array('max-age', 's-maxage', 'stale-while-revalidate', 'stale-if-error'))) {
135 - if (strlen($v) > 0) {
136 - $tmp[] = sprintf("%s=%u", $k, $v);
137 - }
138 - } else {
139 - $tmp[] = $k;
140 - }
141 - }
142 - $hh_cache_control_value = join(', ', $tmp);
143 - $headers['Cache-Control'] = $hh_cache_control_value;
144 - }
145 59 if (get_option('hh_strict_transport_security') == 1) {
146 60 $hh_strict_transport_security = array();
147 61
148 62 $hh_strict_transport_security_max_age = get_option('hh_strict_transport_security_max_age');
@@ -159,24 +73,37 @@
159 73 }
160 74 } else {
161 75 $hh_strict_transport_security = array(get_option('hh_strict_transport_security_value'));
162 76 }
163 - $headers['Strict-Transport-Security'] = join('; ', $hh_strict_transport_security);
77 + header("Strict-Transport-Security: " . join('; ', $hh_strict_transport_security));
164 78 }
165 79 if (get_option('hh_x_ua_compatible') == 1) {
166 - $headers['X-UA-Compatible'] = get_option('hh_x_ua_compatible_value');
80 + header("X-UA-Compatible: " . get_option('hh_x_ua_compatible_value'));
167 81 }
168 -
169 - if (get_option('hh_content_security_policy') == 1)
170 - {
171 - $value = get_option('hh_content_security_policy_value');
172 - $csp = build_csp_value($value);
173 - if ($csp)
174 - {
175 - $csp_report_only = get_option('hh_content_security_policy_report_only');
176 - $headers['Content-Security-Policy'.($csp_report_only ? '-Report-Only' : NULL)] = $csp;
82 + if (get_option('hh_public_key_pins') == 1) {
83 + $public_key_pins_sha256_1 = get_option('hh_public_key_pins_sha256_1');
84 + $public_key_pins_sha256_2 = get_option('hh_public_key_pins_sha256_2');
85 + $public_key_pins_max_age = get_option('hh_public_key_pins_max_age');
86 + $public_key_pins_sub_domains = get_option('hh_public_key_pins_sub_domains');
87 + $public_key_pins_report_uri = get_option('hh_public_key_pins_report_uri');
88 + if (!empty($public_key_pins_sha256_1) && !empty($public_key_pins_sha256_2) && !empty($public_key_pins_max_age)) {
89 +
90 + $public_key_pins = array();
91 + $public_key_pins[] = sprintf('pin-sha256="%s"', $public_key_pins_sha256_1);
92 + $public_key_pins[] = sprintf('pin-sha256="%s"', $public_key_pins_sha256_2);
93 + $public_key_pins[] = sprintf("max-age=%u", $public_key_pins_max_age);
94 + if ($public_key_pins_sub_domains) {
95 + $public_key_pins[] = "includeSubDomains";
96 + }
97 + if (!empty($public_key_pins_report_uri)) {
98 + $public_key_pins[] = sprintf('report-uri="%s"', $public_key_pins_report_uri);
99 + }
100 + header(sprintf("Public-Key-Pins: %s", join('; ', $public_key_pins)));
177 101 }
178 102 }
103 +
104 + # TODO
105 + //header("Content-Security-Policy: default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self';");
179 106
180 107 if (get_option('hh_access_control_allow_origin') == 1)
181 108 {
182 109 $value = get_option('hh_access_control_allow_origin_value');
@@ -181,24 +108,23 @@
181 108 {
182 109 $value = get_option('hh_access_control_allow_origin_value');
183 110 switch ($value)
184 111 {
112 + case 'HTTP_ORIGIN':
113 + $value = @$_SERVER['HTTP_ORIGIN'];
114 + break;
185 115 case 'origin':
186 - $value = get_option('hh_access_control_allow_origin_url', array());
187 - if (is_scalar($value))
188 - {
189 - $value = array($value);
190 - }
116 + $value = get_option('hh_access_control_allow_origin_url');
191 117 break;
192 118 }
193 119 if (!empty($value))
194 120 {
195 - $headers['Access-Control-Allow-Origin'] = $value;
121 + header("Access-Control-Allow-Origin: " . $value);
196 122 }
197 123 }
198 124 if (get_option('hh_access_control_allow_credentials') == 1)
199 125 {
200 - $headers['Access-Control-Allow-Credentials'] = get_option('hh_access_control_allow_credentials_value');
126 + header("Access-Control-Allow-Credentials: " . get_option('hh_access_control_allow_credentials_value'));
201 127 }
202 128 if (get_option('hh_access_control_max_age') == 1)
203 129 {
204 130 $value = get_option('hh_access_control_max_age_value');
@@ -203,9 +129,9 @@
203 129 {
204 130 $value = get_option('hh_access_control_max_age_value');
205 131 if (!empty($value))
206 132 {
207 - $headers['Access-Control-Max-Age'] = intval($value);
133 + header("Access-Control-Max-Age: " . intval($value));
208 134 }
209 135 }
210 136 if (get_option('hh_access_control_allow_methods') == 1)
211 137 {
@@ -211,50 +137,26 @@
211 137 {
212 138 $value = get_option('hh_access_control_allow_methods_value');
213 139 if (!empty($value))
214 140 {
215 - $headers['Access-Control-Allow-Methods'] = join(', ', array_keys($value));
141 + header("Access-Control-Allow-Methods: " . join(', ', array_keys($value)));
216 142 }
217 143 }
218 144 if (get_option('hh_access_control_allow_headers') == 1)
219 145 {
220 - $tmp = array();
221 146 $value = get_option('hh_access_control_allow_headers_value');
222 147 if (!empty($value))
223 148 {
224 - $tmp = array_merge($tmp, array_keys($value));
149 + header("Access-Control-Allow-Headers: " . join(', ', array_keys($value)));
225 150 }
226 - $custom = get_option('hh_access_control_allow_headers_custom');
227 - if (!empty($custom))
228 - {
229 - $tmp = array_merge($tmp, $custom);
230 - }
231 - if ($tmp)
232 - {
233 - $tmp = array_filter($tmp, 'trim');
234 - $tmp = array_unique($tmp);
235 - $headers['Access-Control-Allow-Headers'] = join(', ', $tmp);
236 - }
237 151 }
238 152 if (get_option('hh_access_control_expose_headers') == 1)
239 153 {
240 - $tmp = array();
241 154 $value = get_option('hh_access_control_expose_headers_value');
242 155 if (!empty($value))
243 156 {
244 - $tmp = array_merge($tmp, array_keys($value));
157 + header("Access-Control-Expose-Headers: " . join(', ', array_keys($value)));
245 158 }
246 - $custom = get_option('hh_access_control_expose_headers_custom');
247 - if (!empty($custom))
248 - {
249 - $tmp = array_merge($tmp, $custom);
250 - }
251 - if ($tmp)
252 - {
253 - $tmp = array_filter($tmp, 'trim');
254 - $tmp = array_unique($tmp);
255 - $headers['Access-Control-Expose-Headers'] = join(', ', $tmp);
256 - }
257 159 }
258 160 if (get_option('hh_p3p') == 1)
259 161 {
260 162 $value = get_option('hh_p3p_value');
@@ -259,982 +161,60 @@
259 161 {
260 162 $value = get_option('hh_p3p_value');
261 163 if (!empty($value))
262 164 {
263 - $headers['P3P'] = 'CP="' . join(' ', array_keys($value)) . '"';
165 + header('P3P: CP="' . join(' ', array_keys($value)) . '"');
264 166 }
265 167 }
266 168 if (get_option('hh_referrer_policy') == 1) {
267 - $headers['Referrer-Policy'] = get_option('hh_referrer_policy_value');
169 + header("Referrer-Policy: " . get_option('hh_referrer_policy_value'));
268 170 }
269 - if (get_option('hh_cross_origin_resource_policy') == 1) {
270 - $headers['Cross-Origin-Resource-Policy'] = get_option('hh_cross_origin_resource_policy_value');
271 - }
272 - if (get_option('hh_www_authenticate') == 1) {
273 -
274 - switch (get_option('hh_www_authenticate_type')) {
275 - case 'Basic':
276 - if (!(isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])
277 - && $_SERVER['PHP_AUTH_USER'] == get_option('hh_www_authenticate_user')
278 - && $_SERVER['PHP_AUTH_PW'] == get_option('hh_www_authenticate_pswd'))) {
279 - $headers['WWW-Authenticate'] = sprintf("Basic realm='%s'", get_option('hh_www_authenticate_realm'));
280 - $statuses['HTTP/1.1'] = '401 Unauthorized';
281 - }
282 - break;
283 - case 'Digest':
284 - if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
285 - $realm = get_option('hh_www_authenticate_realm');
286 - $headers['WWW-Authenticate'] = sprintf("Digest realm='%s',qop='auth',nonce='%s',opaque='%s'",
287 - $realm, uniqid(), md5($realm));
288 - $statuses['HTTP/1.1'] = '401 Unauthorized';
289 - }
290 - break;
291 - }
292 - }
293 - if (get_option('hh_vary') == 1)
294 - {
295 - $value = get_option('hh_vary_value');
296 - if (!empty($value))
297 - {
298 - $append['Vary'] = join(', ', array_keys($value));
299 - }
300 - }
301 -
302 - if (get_option('hh_expect_ct') == 1) {
303 - $expect_ct_max_age = get_option('hh_expect_ct_max_age');
304 - $expect_ct_report_uri = get_option('hh_expect_ct_report_uri');
305 - if (!empty($expect_ct_report_uri) && !empty($expect_ct_max_age)) {
306 -
307 - $expect_ct = array();
308 - $expect_ct[] = sprintf("max-age=%u", $expect_ct_max_age);
309 - if (get_option('hh_expect_ct_enforce') == 1) {
310 - $expect_ct[] = "enforce";
311 - }
312 - $expect_ct[] = sprintf('report-uri="%s"', $expect_ct_report_uri);
313 - $headers['Expect-CT'] = join(', ', $expect_ct);
314 - }
315 - }
316 - if (get_option('hh_custom_headers') == 1) {
317 - $custom_headers = get_option('hh_custom_headers_value');
318 - if (isset($custom_headers['name'], $custom_headers['value']) && !empty($custom_headers['name'])) {
319 - foreach ($custom_headers['name'] as $key => $name) {
320 - $name = trim($name);
321 - $value = trim($custom_headers['value'][$key]);
322 - if (empty($name) || empty($value)) {
323 - continue;
324 - }
325 - $headers[$name] = $value;
326 - }
327 - }
328 - }
329 - if (get_option('hh_report_to') == 1) {
330 - $report_to = get_option('hh_report_to_value');
331 - $tmp = array();
332 - foreach ($report_to as $item)
333 - {
334 - $tmp[] = sprintf('{"url": "%s", "group": "%s", "max-age": %u%s}',
335 - $item['url'], $item['group'], $item['max-age'], isset($item['includeSubDomains']) ? ', includeSubDomains' : NULL);
336 - }
337 - if ($tmp)
338 - {
339 - $headers['Report-To'] = join(', ', $tmp);
340 - }
341 - }
342 - if (get_option('hh_feature_policy') == 1) {
343 - $feature_policy_feature = get_option('hh_feature_policy_feature');
344 - $feature_policy_value = get_option('hh_feature_policy_value');
345 - $feature_policy_origin = get_option('hh_feature_policy_origin');
346 - $tmp = array();
347 - $feature_policy_feature = is_array($feature_policy_feature) ? $feature_policy_feature : array();
348 - foreach (array_keys($feature_policy_feature) as $feature)
349 - {
350 - $value = NULL;
351 - switch ($feature_policy_value[$feature])
352 - {
353 - case '*':
354 - case "'none'":
355 - $value = $feature_policy_value[$feature];
356 - break;
357 - case "'self'":
358 - $value = $feature_policy_value[$feature];
359 - if (!empty($feature_policy_origin[$feature]))
360 - {
361 - $value .= " " . $feature_policy_origin[$feature];
362 - }
363 - break;
364 - case 'origin(s)':
365 - $value = $feature_policy_origin[$feature];
366 - break;
367 - }
368 -
369 - $tmp[] = sprintf("%s %s", $feature, $value);
370 - }
371 - if ($tmp)
372 - {
373 - $headers['Feature-Policy'] = join('; ', $tmp);
374 - }
375 - }
376 -
377 - return array($headers, $statuses, $unset, $append);
378 171 }
379 172
380 -function http_digest_parse($txt) {
381 - $txt = stripslashes($txt);
382 -
383 - $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
384 - $data = array();
385 - $keys = implode('|', array_keys($needed_parts));
386 -
387 - preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
388 -
389 - foreach ($matches as $m) {
390 - $data[$m[1]] = $m[3] ? $m[3] : $m[4];
391 - unset($needed_parts[$m[1]]);
392 - }
393 -
394 - return $needed_parts ? false : $data;
395 -}
396 -
397 -function php_auth_digest() {
398 - if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) || get_option('hh_www_authenticate_user') != $data['username']) {
399 - die('Wrong Credentials!');
400 - }
401 -
402 - $A1 = md5($data['username'] . ':' . get_option('hh_www_authenticate_realm') . ':' . get_option('hh_www_authenticate_pswd'));
403 - $A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
404 - $valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);
405 - if ($data['response'] != $valid_response) {
406 - die('Wrong Credentials!');
407 - }
408 -}
409 -
410 -function php_content_encoding() {
411 - if (substr_count($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip')) {
412 - ob_start('ob_gzhandler');
413 - } else {
414 - ob_start();
415 - }
416 -}
417 -
418 -function php_cookie_security_directives() {
419 - $lines = array();
420 - if (get_option('hh_cookie_security') == 1) {
421 - $value = get_option('hh_cookie_security_value', array());
422 - if (isset($value['HttpOnly'])) {
423 - $lines[] = 'session.cookie_httponly = on';
424 - }
425 - if (isset($value['Secure'])) {
426 - $lines[] = 'session.cookie_secure = on';
427 - }
428 - if (isset($value['SameSite']) && in_array($value['SameSite'], array('None', 'Lax', 'Strict'))) {
429 - $lines[] = sprintf('session.cookie_samesite = "%s"', $value['SameSite']);
430 - }
431 - }
432 -
433 - return $lines;
434 -}
435 -
436 -function http_headers() {
437 - if (get_option('hh_method') !== 'php') {
438 - return;
439 - }
440 - // PHP method below
441 - list($headers, $statuses, $unset, $append) = get_http_headers();
442 - $isCors = false;
443 - foreach ($headers as $key => $value) {
444 - if ($key == 'Access-Control-Allow-Origin') {
445 - if (isset($_SERVER['HTTP_ORIGIN'])) {
446 - if (in_array($value, array('*', 'null'))) {
447 - $isCors = true;
448 - header(sprintf("%s: *", $key));
449 - }
450 -
451 - if (is_array($value) && in_array($_SERVER['HTTP_ORIGIN'], $value)) {
452 - $isCors = true;
453 - header(sprintf("%s: %s", $key, $_SERVER['HTTP_ORIGIN']));
454 - header("Vary: Origin", false);
455 - }
456 - }
457 - continue;
458 - }
459 - if (in_array($key, array('Access-Control-Allow-Headers', 'Access-Control-Allow-Methods', 'Access-Control-Allow-Credentials', 'Access-Control-Max-Age', 'Access-Control-Expose-Headers'))) {
460 - if ($isCors) {
461 - header(sprintf("%s: %s", $key, $value));
462 - }
463 - continue;
464 - }
465 - header(sprintf("%s: %s", $key, $value));
466 - }
467 - foreach ($append as $key => $value) {
468 - header(sprintf("%s: %s", $key, $value), false);
469 - }
470 - foreach ($unset as $header) {
471 - if (function_exists('header_remove')) {
472 - header_remove($header);
473 - } else {
474 - header("$header:");
475 - }
476 - }
477 - foreach ($statuses as $key => $value) {
478 - header(sprintf("%s %s", $key, $value));
479 - exit;
480 - }
481 -
482 - if (get_option('hh_www_authenticate') == 1) {
483 - php_auth_digest();
484 - }
485 -
486 - if (get_option('hh_content_encoding') == 1) {
487 - php_content_encoding();
488 - }
489 -}
490 -
491 173 function http_headers_admin_add_page() {
492 174 add_options_page('HTTP Headers', 'HTTP Headers', 'manage_options', 'http-headers', 'http_headers_admin_page');
493 175 }
494 176
495 177 function http_headers_admin() {
496 - register_setting('http-headers-mtd', 'hh_method');
497 - register_setting('http-headers-xfo', 'hh_x_frame_options');
498 - register_setting('http-headers-xfo', 'hh_x_frame_options_value');
499 - register_setting('http-headers-xfo', 'hh_x_frame_options_domain');
500 - register_setting('http-headers-xss', 'hh_x_xxs_protection');
501 - register_setting('http-headers-xss', 'hh_x_xxs_protection_value');
502 - register_setting('http-headers-xss', 'hh_x_xxs_protection_uri');
503 - register_setting('http-headers-cto', 'hh_x_content_type_options');
504 - register_setting('http-headers-cto', 'hh_x_content_type_options_value');
505 - register_setting('http-headers-sts', 'hh_strict_transport_security');
506 - register_setting('http-headers-sts', 'hh_strict_transport_security_value'); //obsolete
507 - register_setting('http-headers-sts', 'hh_strict_transport_security_max_age');
508 - register_setting('http-headers-sts', 'hh_strict_transport_security_sub_domains');
509 - register_setting('http-headers-sts', 'hh_strict_transport_security_preload');
510 - register_setting('http-headers-uac', 'hh_x_ua_compatible');
511 - register_setting('http-headers-uac', 'hh_x_ua_compatible_value');
512 - register_setting('http-headers-p3p', 'hh_p3p');
513 - register_setting('http-headers-p3p', 'hh_p3p_value');
514 - register_setting('http-headers-rp', 'hh_referrer_policy');
515 - register_setting('http-headers-rp', 'hh_referrer_policy_value');
516 - register_setting('http-headers-csp', 'hh_content_security_policy');
517 - register_setting('http-headers-csp', 'hh_content_security_policy_value');
518 - register_setting('http-headers-csp', 'hh_content_security_policy_report_only');
519 - register_setting('http-headers-acao', 'hh_access_control_allow_origin');
520 - register_setting('http-headers-acao', 'hh_access_control_allow_origin_value');
521 - register_setting('http-headers-acao', 'hh_access_control_allow_origin_url');
522 - register_setting('http-headers-acac', 'hh_access_control_allow_credentials');
523 - register_setting('http-headers-acac', 'hh_access_control_allow_credentials_value');
524 - register_setting('http-headers-acam', 'hh_access_control_allow_methods');
525 - register_setting('http-headers-acam', 'hh_access_control_allow_methods_value');
526 - register_setting('http-headers-acah', 'hh_access_control_allow_headers');
527 - register_setting('http-headers-acah', 'hh_access_control_allow_headers_value');
528 - register_setting('http-headers-acah', 'hh_access_control_allow_headers_custom');
529 - register_setting('http-headers-aceh', 'hh_access_control_expose_headers');
530 - register_setting('http-headers-aceh', 'hh_access_control_expose_headers_value');
531 - register_setting('http-headers-aceh', 'hh_access_control_expose_headers_custom');
532 - register_setting('http-headers-acma', 'hh_access_control_max_age');
533 - register_setting('http-headers-acma', 'hh_access_control_max_age_value');
534 - register_setting('http-headers-ce', 'hh_content_encoding');
535 - register_setting('http-headers-ce', 'hh_content_encoding_module');
536 - register_setting('http-headers-ce', 'hh_content_encoding_value');
537 - register_setting('http-headers-ce', 'hh_content_encoding_ext');
538 - register_setting('http-headers-vary', 'hh_vary');
539 - register_setting('http-headers-vary', 'hh_vary_value');
540 - register_setting('http-headers-xpb', 'hh_x_powered_by');
541 - register_setting('http-headers-xpb', 'hh_x_powered_by_option');
542 - register_setting('http-headers-xpb', 'hh_x_powered_by_value');
543 - register_setting('http-headers-wwa', 'hh_www_authenticate');
544 - register_setting('http-headers-wwa', 'hh_www_authenticate_type');
545 - register_setting('http-headers-wwa', 'hh_www_authenticate_realm');
546 - register_setting('http-headers-wwa', 'hh_www_authenticate_user');
547 - register_setting('http-headers-wwa', 'hh_www_authenticate_pswd');
548 - register_setting('http-headers-cc', 'hh_cache_control');
549 - register_setting('http-headers-cc', 'hh_cache_control_value');
550 - register_setting('http-headers-age', 'hh_age');
551 - register_setting('http-headers-age', 'hh_age_value');
552 - register_setting('http-headers-pra', 'hh_pragma');
553 - register_setting('http-headers-pra', 'hh_pragma_value');
554 - register_setting('http-headers-exp', 'hh_expires');
555 - register_setting('http-headers-exp', 'hh_expires_value');
556 - register_setting('http-headers-exp', 'hh_expires_type');
557 - register_setting('http-headers-con', 'hh_connection');
558 - register_setting('http-headers-con', 'hh_connection_value');
559 - register_setting('http-headers-cose', 'hh_cookie_security');
560 - register_setting('http-headers-cose', 'hh_cookie_security_value');
561 - register_setting('http-headers-ect', 'hh_expect_ct');
562 - register_setting('http-headers-ect', 'hh_expect_ct_max_age');
563 - register_setting('http-headers-ect', 'hh_expect_ct_report_uri');
564 - register_setting('http-headers-ect', 'hh_expect_ct_enforce');
565 - register_setting('http-headers-tao', 'hh_timing_allow_origin');
566 - register_setting('http-headers-tao', 'hh_timing_allow_origin_value');
567 - register_setting('http-headers-tao', 'hh_timing_allow_origin_url');
568 - register_setting('http-headers-che', 'hh_custom_headers');
569 - register_setting('http-headers-che', 'hh_custom_headers_value');
570 - register_setting('http-headers-xdo', 'hh_x_download_options');
571 - register_setting('http-headers-xdo', 'hh_x_download_options_value');
572 - register_setting('http-headers-xpcd', 'hh_x_permitted_cross_domain_policies');
573 - register_setting('http-headers-xpcd', 'hh_x_permitted_cross_domain_policies_value');
574 - register_setting('http-headers-xdpc', 'hh_x_dns_prefetch_control');
575 - register_setting('http-headers-xdpc', 'hh_x_dns_prefetch_control_value');
576 - register_setting('http-headers-rt', 'hh_report_to');
577 - register_setting('http-headers-rt', 'hh_report_to_value');
578 - register_setting('http-headers-fp', 'hh_feature_policy');
579 - register_setting('http-headers-fp', 'hh_feature_policy_value');
580 - register_setting('http-headers-fp', 'hh_feature_policy_feature');
581 - register_setting('http-headers-fp', 'hh_feature_policy_origin');
582 - register_setting('http-headers-csd', 'hh_clear_site_data');
583 - register_setting('http-headers-csd', 'hh_clear_site_data_value');
584 - register_setting('http-headers-cty', 'hh_content_type');
585 - register_setting('http-headers-cty', 'hh_content_type_value');
586 - register_setting('http-headers-corp', 'hh_cross_origin_resource_policy');
587 - register_setting('http-headers-corp', 'hh_cross_origin_resource_policy_value');
178 + register_setting('http-headers-group', 'hh_x_frame_options');
179 + register_setting('http-headers-group', 'hh_x_frame_options_value');
180 + register_setting('http-headers-group', 'hh_x_frame_options_domain');
181 + register_setting('http-headers-group', 'hh_x_xxs_protection');
182 + register_setting('http-headers-group', 'hh_x_xxs_protection_value');
183 + register_setting('http-headers-group', 'hh_x_content_type_options');
184 + register_setting('http-headers-group', 'hh_x_content_type_options_value');
185 + register_setting('http-headers-group', 'hh_strict_transport_security');
186 + register_setting('http-headers-group', 'hh_strict_transport_security_value'); //obsolete
187 + register_setting('http-headers-group', 'hh_strict_transport_security_max_age');
188 + register_setting('http-headers-group', 'hh_strict_transport_security_sub_domains');
189 + register_setting('http-headers-group', 'hh_strict_transport_security_preload');
190 + register_setting('http-headers-group', 'hh_public_key_pins');
191 + register_setting('http-headers-group', 'hh_public_key_pins_sha256_1');
192 + register_setting('http-headers-group', 'hh_public_key_pins_sha256_2');
193 + register_setting('http-headers-group', 'hh_public_key_pins_max_age');
194 + register_setting('http-headers-group', 'hh_public_key_pins_sub_domains');
195 + register_setting('http-headers-group', 'hh_public_key_pins_report_uri');
196 + register_setting('http-headers-group', 'hh_x_ua_compatible');
197 + register_setting('http-headers-group', 'hh_x_ua_compatible_value');
198 + register_setting('http-headers-group', 'hh_p3p');
199 + register_setting('http-headers-group', 'hh_p3p_value');
200 + register_setting('http-headers-group', 'hh_referrer_policy');
201 + register_setting('http-headers-group', 'hh_referrer_policy_value');
202 + register_setting('http-headers-cors', 'hh_access_control_allow_origin');
203 + register_setting('http-headers-cors', 'hh_access_control_allow_origin_value');
204 + register_setting('http-headers-cors', 'hh_access_control_allow_origin_url');
205 + register_setting('http-headers-cors', 'hh_access_control_allow_credentials');
206 + register_setting('http-headers-cors', 'hh_access_control_allow_credentials_value');
207 + register_setting('http-headers-cors', 'hh_access_control_allow_methods');
208 + register_setting('http-headers-cors', 'hh_access_control_allow_methods_value');
209 + register_setting('http-headers-cors', 'hh_access_control_allow_headers');
210 + register_setting('http-headers-cors', 'hh_access_control_allow_headers_value');
211 + register_setting('http-headers-cors', 'hh_access_control_expose_headers');
212 + register_setting('http-headers-cors', 'hh_access_control_expose_headers_value');
213 + register_setting('http-headers-cors', 'hh_access_control_max_age');
214 + register_setting('http-headers-cors', 'hh_access_control_max_age_value');
588 215 }
589 -
590 -function http_headers_option($option) {
591 -
592 - include_once ABSPATH . 'wp-admin/includes/admin.php';
593 -
594 - if (isset($_POST['hh_method']))
595 - {
596 - check_admin_referer('http-headers-mtd-options');
597 - # When method is changed
598 - http_headers_activate();
599 -
600 - } elseif (get_option('hh_method') == 'htaccess') {
601 - # When particular header is changed
602 - switch (true) {
603 - case array_key_exists('hh_www_authenticate', $_POST):
604 - check_admin_referer('http-headers-wwa-options');
605 - update_auth_credentials();
606 - update_auth_directives();
607 - break;
608 - case array_key_exists('hh_content_encoding', $_POST):
609 - check_admin_referer('http-headers-ce-options');
610 - update_content_encoding_directives();
611 - break;
612 - case array_key_exists('hh_content_type', $_POST):
613 - check_admin_referer('http-headers-cty-options');
614 - update_content_type_directives();
615 - break;
616 - case array_key_exists('hh_expires', $_POST):
617 - check_admin_referer('http-headers-exp-options');
618 - update_expires_directives();
619 - break;
620 - case array_key_exists('hh_cookie_security', $_POST):
621 - check_admin_referer('http-headers-cose-options');
622 - update_cookie_security_directives();
623 - break;
624 - case array_key_exists('hh_timing_allow_origin', $_POST):
625 - check_admin_referer('http-headers-tao-options');
626 - update_timing_directives();
627 - break;
628 - case array_key_exists('option_page', $_POST) && strpos($_POST['option_page'], 'http-headers-') === 0:
629 - check_admin_referer($_POST['option_page'].'-options');
630 - update_headers_directives();
631 - break;
632 - }
633 - }
634 -}
635 -
636 -function nginx_headers_directives() {
637 - $lines = array();
638 - list($headers, $statuses, $unset, $append) = get_http_headers();
639 -
640 - foreach ($unset as $header) {
641 - $lines[] = sprintf(' more_clear_headers "%s";', $header);
642 - }
643 - $cors = $cors_header = $cors_inner = $cors_footer = array();
644 - $all = array();
645 - foreach ($headers as $key => $value) {
646 - if (in_array($key, array('WWW-Authenticate'))) {
647 - continue;
648 - }
649 - if (in_array($key, array('X-Content-Type-Options'))) {
650 - $all[] = sprintf('add_header %s %s always;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
651 - continue;
652 - }
653 - if ($key == 'Access-Control-Allow-Origin' && is_array($value)) {
654 - $cors_header[] = sprintf('if ($http_origin ~* ^(%s)$) {', str_replace('.', '\.', join('|', $value)));
655 - $cors_footer[] = '}';
656 - $cors_inner[] = ' add_header Access-Control-Allow-Origin "$http_origin";';
657 - if (!in_array('*', $value))
658 - {
659 - $cors_inner[] = ' add_header Vary "Origin";';
660 - }
661 - continue;
662 - }
663 - if (in_array($key, array('Access-Control-Allow-Headers', 'Access-Control-Allow-Methods', 'Access-Control-Allow-Credentials', 'Access-Control-Max-Age', 'Access-Control-Expose-Headers'))) {
664 - $cors_inner[] = sprintf(' add_header %s %s;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
665 - continue;
666 - }
667 - $lines[] = sprintf(' add_header %s %s;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
668 - }
669 - foreach ($append as $key => $value) {
670 - $lines[] = sprintf(' add_header %s %s;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
671 - }
672 - if (!empty($cors_inner))
673 - {
674 - $cors = array_merge(
675 - $cors_header,
676 - $cors_inner,
677 - $cors_footer
678 - );
679 - }
680 - if (!empty($lines)) {
681 - $lines = array_merge(
682 - $all,
683 - $cors,
684 - array('location ~* \.(php|html)$ {'),
685 - $lines,
686 - array('}')
687 - );
688 - }
689 - return $lines;
690 -}
691 216
692 -function nginx_content_encoding_directives() {
693 - $lines = array();
694 - if (get_option('hh_content_encoding') == 1) {
695 -
696 - $lines[] = 'gzip on;';
697 -
698 - $content_encoding_value = get_option('hh_content_encoding_value');
699 - if (!$content_encoding_value) {
700 - $content_encoding_value = array();
701 - }
702 -
703 - $content_encoding_ext = get_option('hh_content_encoding_ext');
704 - if (!$content_encoding_ext) {
705 - $content_encoding_ext = array();
706 - }
707 - if (!empty($content_encoding_ext)) {
708 - //$lines[] = sprintf('<FilesMatch "\.(%s)$">', join('|', array_keys($content_encoding_ext)));
709 - }
710 - if (!empty($content_encoding_value)) {
711 - $lines[] = sprintf('gzip_types %s;', join(' ', array_keys($content_encoding_value)));
712 - }
713 - }
714 - return $lines;
715 -}
716 -
717 -function nginx_content_type_directives() {
718 - $lines = array();
719 - if (get_option('hh_content_type') == 1) {
720 - $values = get_option('hh_content_type_value', array());
721 - foreach ($values as $ext => $media_type) {
722 - $lines[] = sprintf("%s %s;", $media_type, $ext);
723 - }
724 - }
725 -
726 - return $lines;
727 -}
728 -
729 -function nginx_expires_directives() {
730 - $lines = array();
731 - if (get_option('hh_expires') == 1) {
732 -
733 - $types = get_option('hh_expires_type', array());
734 - $values = get_option('hh_expires_value', array());
735 -
736 - $lines[] = 'map $sent_http_content_type $expires {';
737 - foreach ($types as $type => $whatever) {
738 - list($base, $period, $suffix) = explode('_', $values[$type]);
739 - if (in_array($base, array('access', 'modification'))) {
740 - $lines[] = $type != 'default'
741 - ? sprintf(' %s %u%s;', $type, $period, $suffix[0])
742 - : sprintf(' default %u%s;', $period, $suffix[0]);
743 - } elseif ($base == 'invalid') {
744 - $lines[] = $type != 'default'
745 - ? sprintf(' %s 0;', $type)
746 - : sprintf(' default 0;');
747 - }
748 - }
749 - $lines[] = '}';
750 -
751 - $lines[] = 'expires $expires;';
752 - }
753 - return $lines;
754 -}
755 -
756 -function nginx_timing_directives() {
757 - $lines = array();
758 - if (get_option('hh_timing_allow_origin') == 1) {
759 - $value = get_option('hh_timing_allow_origin_value');
760 - switch ($value)
761 - {
762 - case 'origin':
763 - $value = get_option('hh_timing_allow_origin_url');
764 - break;
765 - }
766 - if (!empty($value))
767 - {
768 - $lines[] = 'location ~* \.(js|css|jpe?g|png|gif|eot|otf|svg|ttf|woff2?)$ {';
769 - $lines[] = sprintf(' add_header Timing-Allow-Origin "%s";', $value);
770 - $lines[] = '}';
771 - }
772 - }
773 - return $lines;
774 -}
775 -
776 -function nginx_auth_directives() {
777 - $lines = array();
778 - if (get_option('hh_www_authenticate') == 1) {
779 -
780 - $type = get_option('hh_www_authenticate_type');
781 -
782 - $file = $type == 'Basic' ? '.hh-htpasswd' : '.hh-htdigest';
783 -
784 - $lines[] = 'location ~ ^\.hh-ht(digest|passwd)$ {';
785 - $lines[] = ' deny all;';
786 - $lines[] = '}';
787 -
788 - $lines[] = sprintf('location %s {', get_home_path());
789 - if ($type == 'Basic') {
790 - $lines[] = sprintf(' auth_basic "%s";', get_option('hh_www_authenticate_realm'));
791 - $lines[] = sprintf(' auth_basic_user_file %s%s;', get_home_path(), $file);
792 - } else {
793 - $lines[] = sprintf(' auth_digest "%s";', get_option('hh_www_authenticate_realm'));
794 - $lines[] = sprintf(' auth_digest_user_file %s%s;', get_home_path(), $file);
795 - }
796 - $lines[] = '}';
797 - }
798 - return $lines;
799 -}
800 -
801 -function nginx_auth_credentials() {
802 - return apache_auth_credentials();
803 -}
804 -
805 -function nginx_cookie_security_directives() {
806 - $lines = array();
807 -
808 - //TODO
809 -
810 - return $lines;
811 -}
812 -
813 -function nginx_check_requirements() {
814 - //TODO scheduled for v2.0.0
815 - return true;
816 -}
817 -
818 -function iis_headers_directives() {
819 - //TODO scheduled for v2.0.0
820 -}
821 -
822 -function iis_content_encoding_directives() {
823 - //TODO scheduled for v2.0.0
824 -}
825 -
826 -function iis_content_type_directives() {
827 - //TODO scheduled for v2.0.0
828 -}
829 -
830 -function iis_expires_directives() {
831 - //TODO scheduled for v2.0.0
832 -}
833 -
834 -function iis_timing_directives() {
835 - //TODO scheduled for v2.0.0
836 -}
837 -
838 -function iis_auth_directives() {
839 - //TODO scheduled for v2.0.0
840 -}
841 -
842 -function iis_auth_credentials() {
843 - //TODO scheduled for v2.0.0
844 -}
845 -
846 -function iis_cookie_security_directives() {
847 - //TODO scheduled for v2.0.0
848 -}
849 -
850 -function iis_check_requirements() {
851 - //TODO scheduled for v2.0.0
852 - return true;
853 -}
854 -
855 -function apache_headers_directives() {
856 - $lines = array();
857 - list($headers, $statuses, $unset, $append) = get_http_headers();
858 -
859 - foreach ($unset as $header) {
860 - $lines[] = sprintf(' Header always unset %s', $header);
861 - $lines[] = sprintf(' Header unset %s', $header);
862 - }
863 - $all = array();
864 - foreach ($headers as $key => $value) {
865 - if (in_array($key, array('WWW-Authenticate'))) {
866 - continue;
867 - }
868 - if (in_array($key, array('X-Content-Type-Options'))) {
869 - $all[] = sprintf(' Header always set %s %s', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
870 - continue;
871 - }
872 - if ($key == 'Strict-Transport-Security') {
873 - $lines[] = sprintf(' Header set %s %s env=HTTPS', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
874 - continue;
875 - }
876 - if ($key == 'Access-Control-Allow-Origin') {
877 - $all[] = ' <IfModule mod_setenvif.c>';
878 - if (!is_array($value)) {
879 - if ($value) {
880 - $value = array($value);
881 - } else {
882 - $value = array();
883 - }
884 - }
885 - //$value[] = 'null';
886 - if (is_array($value))
887 - {
888 - $all[] = sprintf(' SetEnvIf Origin "^(%s)$" CORS=$0', str_replace(array('.', '*'), array('\.', '\*'), join('|', $value)));
889 - } else {
890 - $all[] = ' SetEnvIf Origin "^(.+)$" CORS=$0';
891 - }
892 - $all[] = ' </IfModule>';
893 - $all[] = ' Header set Access-Control-Allow-Origin %{CORS}e env=CORS';
894 - if (!in_array('*', $value))
895 - {
896 - $all[] = ' Header append Vary "Origin" env=CORS';
897 - }
898 - continue;
899 - }
900 - if (in_array($key, array('Access-Control-Allow-Headers', 'Access-Control-Allow-Methods', 'Access-Control-Allow-Credentials', 'Access-Control-Max-Age', 'Access-Control-Expose-Headers'))) {
901 - $all[] = sprintf(' Header set %s %s env=CORS', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
902 - continue;
903 - }
904 - $lines[] = sprintf(' Header set %s %s', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
905 - }
906 - foreach ($append as $key => $value) {
907 - $lines[] = sprintf(' Header append %s %s', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
908 - }
909 - if (!empty($lines) || !empty($all)) {
910 - $lines = array_merge(
911 - array('<IfModule mod_headers.c>'),
912 - $all,
913 - array(' <FilesMatch "\.(php|html)$">'),
914 - $lines,
915 - array(' </FilesMatch>', '</IfModule>')
916 - );
917 - }
918 - return $lines;
919 -}
920 -
921 -function apache_content_encoding_directives() {
922 - $lines = array();
923 - if (get_option('hh_content_encoding') == 1) {
924 -
925 - $content_encoding_module = get_option('hh_content_encoding_module');
926 -
927 - $module = 'mod_deflate.c';
928 - $filter = 'DEFLATE';
929 - $accept_encoding = 'gzip';
930 -
931 - if ($content_encoding_module == 'brotli') {
932 - $module = 'mod_brotli.c';
933 - $filter = 'BROTLI_COMPRESS';
934 - $accept_encoding = 'br';
935 - }
936 -
937 - $content_encoding_value = get_option('hh_content_encoding_value');
938 - if (!$content_encoding_value) {
939 - $content_encoding_value = array();
940 - }
941 -
942 - $content_encoding_ext = get_option('hh_content_encoding_ext');
943 - if (!$content_encoding_ext) {
944 - $content_encoding_ext = array();
945 - }
946 -
947 - $type = join('|', array_keys($content_encoding_value));
948 - $ext = join('|', array_keys($content_encoding_ext));
949 -
950 - if (!empty($type) && !empty($ext)) {
951 - $expression = sprintf('(%%{CONTENT_TYPE} =~ m#^(%1$s)# || %%{REQUEST_FILENAME} =~ /.(%2$s)$/)', $type, $ext);
952 - } elseif (!empty($type)) {
953 - $expression = sprintf('%%{CONTENT_TYPE} =~ m#^(%1$s)#', $type);
954 - } elseif (!empty($ext)) {
955 - $expression = sprintf('%%{REQUEST_FILENAME} =~ /.(%1$s)$/', $ext);
956 - }
957 -
958 - if (isset($expression)) {
959 - $lines[] = '<IfModule mod_filter.c>';
960 - $lines[] = ' FilterDeclare HttpHeaders';
961 - if (in_array($content_encoding_module, array('brotli', 'deflate'))) {
962 - $lines[] = sprintf('<IfModule %s>', $module);
963 - $lines[] = sprintf(' FilterProvider HttpHeaders %1$s "%%{HTTP:Accept-Encoding} =~ /%2$s/ && %3$s"', $filter, $accept_encoding, $expression);
964 - $lines[] = ' </IfModule>';
965 - } else {
966 - $lines[] = ' <IfModule mod_deflate.c>';
967 - $lines[] = ' <IfModule !mod_brotli.c>';
968 - $lines[] = sprintf(' FilterProvider HttpHeaders DEFLATE "%%{HTTP:Accept-Encoding} =~ /gzip/ && %1$s"', $expression);
969 - $lines[] = ' </IfModule>';
970 - $lines[] = ' </IfModule>';
971 - $lines[] = ' <IfModule mod_brotli.c>';
972 - $lines[] = sprintf(' FilterProvider HttpHeaders BROTLI_COMPRESS "%%{HTTP:Accept-Encoding} =~ /br/ && %1$s"', $expression);
973 - $lines[] = ' </IfModule>';
974 - }
975 - $lines[] = ' FilterChain HttpHeaders';
976 - $lines[] = '</IfModule>';
977 - }
978 - }
979 -
980 - return $lines;
981 -}
982 -
983 -function apache_expires_directives() {
984 - $lines = array();
985 - if (get_option('hh_expires') == 1) {
986 -
987 - $types = get_option('hh_expires_type', array());
988 - $values = get_option('hh_expires_value', array());
989 -
990 - $lines[] = '<IfModule mod_expires.c>';
991 - $lines[] = ' ExpiresActive On';
992 - foreach ($types as $type => $whatever) {
993 - list($base, $period, $suffix) = explode('_', $values[$type]);
994 - if (in_array($base, array('access', 'modification'))) {
995 - $lines[] = $type != 'default'
996 - ? sprintf(' ExpiresByType %s "%s plus %u %s"', $type, $base, $period, $suffix)
997 - : sprintf(' ExpiresDefault "%s plus %u %s"', $base, $period, $suffix);
998 - } elseif ($base == 'invalid') {
999 - $lines[] = $type != 'default'
1000 - ? sprintf(' ExpiresByType %s A0', $type)
1001 - : sprintf(' ExpiresDefault A0');
1002 - }
1003 - }
1004 - $lines[] = '</IfModule>';
1005 - }
1006 -
1007 - return $lines;
1008 -}
1009 -
1010 -function apache_content_type_directives() {
1011 - $lines = array();
1012 - if (get_option('hh_content_type') == 1) {
1013 - $values = get_option('hh_content_type_value', array());
1014 - $lines[] = '<IfModule mod_mime.c>';
1015 - foreach ($values as $ext => $media_type) {
1016 - $lines[] = sprintf(" AddType %s .%s", $media_type, $ext);
1017 - }
1018 - $lines[] = '</IfModule>';
1019 - }
1020 -
1021 - return $lines;
1022 -}
1023 -
1024 -function apache_timing_directives() {
1025 - $lines = array();
1026 - if (get_option('hh_timing_allow_origin') == 1) {
1027 - $value = get_option('hh_timing_allow_origin_value');
1028 - switch ($value)
1029 - {
1030 - case 'origin':
1031 - $value = get_option('hh_timing_allow_origin_url');
1032 - break;
1033 - }
1034 - if (!empty($value))
1035 - {
1036 - $lines[] = '<IfModule mod_headers.c>';
1037 - $lines[] = ' <FilesMatch "\\.(js|css|jpe?g|png|gif|eot|otf|svg|ttf|woff2?)$">';
1038 - $lines[] = sprintf(' Header set Timing-Allow-Origin "%s"', $value);
1039 - $lines[] = ' </FilesMatch>';
1040 - $lines[] = '</IfModule>';
1041 - }
1042 - }
1043 -
1044 - return $lines;
1045 -}
1046 -
1047 -function apache_auth_directives() {
1048 - $lines = array();
1049 - if (get_option('hh_www_authenticate') == 1) {
1050 -
1051 - $type = get_option('hh_www_authenticate_type');
1052 -
1053 - $file = $type == 'Basic' ? '.hh-htpasswd' : '.hh-htdigest';
1054 -
1055 - $lines[] = '<FilesMatch "^\.hh-ht(digest|passwd)$">';
1056 - $lines[] = ' <IfModule mod_authz_core.c>';
1057 - $lines[] = ' Require all denied';
1058 - $lines[] = ' </IfModule>';
1059 - $lines[] = ' <IfModule !mod_authz_core.c>';
1060 - $lines[] = ' Order deny,allow';
1061 - $lines[] = ' Deny from all';
1062 - $lines[] = ' </IfModule>';
1063 - $lines[] = '</FilesMatch>';
1064 - // no empty AuthName
1065 - $realm = get_option('hh_www_authenticate_realm'); // AuthName
1066 - $realm = ($realm == '') ? 'restricted area':$realm; // Empty => give fixed value
1067 -
1068 - $lines[] = sprintf('<IfModule mod_auth_%s.c>', strtolower($type));
1069 - $lines[] = sprintf(' AuthType %s', get_option('hh_www_authenticate_type'));
1070 - $lines[] = sprintf(' AuthName "%s"', $realm);
1071 - $lines[] = sprintf(' AuthUserFile "%s%s"', get_home_path(), $file);
1072 - $lines[] = ' Require valid-user';
1073 - $lines[] = '</IfModule>';
1074 - }
1075 -
1076 - return $lines;
1077 -}
1078 -
1079 -function apache_auth_credentials() {
1080 - if (get_option('hh_www_authenticate') == 1) {
1081 - $type = get_option('hh_www_authenticate_type');
1082 - $usernames = get_option('hh_www_authenticate_user', array());
1083 - $passwords = get_option('hh_www_authenticate_pswd', array());
1084 - if (!is_array($usernames)) {
1085 - $usernames = array($usernames);
1086 - }
1087 - if (!is_array($passwords)) {
1088 - $passwords = array($passwords);
1089 - }
1090 - $realm = get_option('hh_www_authenticate_realm');
1091 - $auth = array();
1092 - switch ($type) {
1093 - case 'Basic':
1094 - $ht_file = get_home_path().'.hh-htpasswd';
1095 - foreach ($usernames as $k => $user) {
1096 - $auth[] = sprintf('%s:{SHA}%s', $user, base64_encode(sha1($passwords[$k], true)));
1097 - }
1098 - break;
1099 - case 'Digest':
1100 - $ht_file = get_home_path().'.hh-htdigest';
1101 - foreach ($usernames as $k => $user) {
1102 - $auth[] = sprintf('%s:%s:%s', $user, $realm, md5($user.':'.$realm.':'.$passwords[$k]));
1103 - }
1104 - break;
1105 - }
1106 - $auth = join("\n", $auth);
1107 -
1108 - return compact('ht_file', 'auth');
1109 - }
1110 - return false;
1111 -}
1112 -
1113 -function apache_cookie_security_directives() {
1114 - $lines = array();
1115 - if (get_option('hh_cookie_security') == 1) {
1116 - $value = get_option('hh_cookie_security_value', array());
1117 - if (isset($value['HttpOnly'])) {
1118 - $lines[] = 'php_flag session.cookie_httponly on';
1119 - }
1120 - if (isset($value['Secure'])) {
1121 - $lines[] = 'php_flag session.cookie_secure on';
1122 - }
1123 - if (isset($value['SameSite']) && in_array($value['SameSite'], array('None', 'Lax', 'Strict'))) {
1124 - $lines[] = sprintf('php_value session.cookie_samesite "%s"', $value['SameSite']);
1125 - }
1126 - }
1127 -
1128 - return $lines;
1129 -}
1130 -
1131 -function apache_check_requirements() {
1132 - return check_filename(get_home_path().'.htaccess');
1133 -}
1134 -
1135 -function update_headers_directives() {
1136 - $lines = array();
1137 - if (get_option('hh_method') == 'htaccess') {
1138 - $lines = apache_headers_directives();
1139 - }
1140 -
1141 - return insert_with_markers(get_home_path().'.htaccess', "HttpHeaders", $lines);
1142 -}
1143 -
1144 -function update_content_encoding_directives() {
1145 - $lines = array();
1146 - if (get_option('hh_method') == 'htaccess') {
1147 - $lines = apache_content_encoding_directives();
1148 - }
1149 -
1150 - return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersCompression", $lines);
1151 -}
1152 -
1153 -function update_expires_directives() {
1154 - $lines = array();
1155 - if (get_option('hh_method') == 'htaccess') {
1156 - $lines = apache_expires_directives();
1157 - }
1158 -
1159 - return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersExpires", $lines);
1160 -}
1161 -
1162 -function update_content_type_directives() {
1163 - $lines = array();
1164 - if (get_option('hh_method') == 'htaccess') {
1165 - $lines = apache_content_type_directives();
1166 - }
1167 -
1168 - return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersContentType", $lines);
1169 -}
1170 -
1171 -function update_timing_directives() {
1172 - $lines = array();
1173 - if (get_option('hh_method') == 'htaccess') {
1174 - $lines = apache_timing_directives();
1175 - }
1176 -
1177 - return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersTiming", $lines);
1178 -}
1179 -
1180 -function update_auth_directives() {
1181 - $lines = array();
1182 - if (get_option('hh_method') == 'htaccess') {
1183 - $lines = apache_auth_directives();
1184 - }
1185 -
1186 - return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersAuth", $lines);
1187 - }
1188 -
1189 -function update_auth_credentials() {
1190 - if (get_option('hh_method') == 'htaccess') {
1191 - $credentials = apache_auth_credentials();
1192 -
1193 - return @file_put_contents($credentials['ht_file'], $credentials['auth']);
1194 - }
1195 -
1196 - return false;
1197 -}
1198 -
1199 -function update_cookie_security_directives() {
1200 - $lines = array();
1201 - $is_apache = get_option('hh_method') == 'htaccess';
1202 - $htaccess = get_home_path().'.htaccess';
1203 - if (strpos(PHP_SAPI, 'cgi') !== false) {
1204 - $filename = get_home_path().ini_get('user_ini.filename');
1205 - $lines = php_cookie_security_directives();
1206 - } elseif ($is_apache) {
1207 - $filename = $htaccess;
1208 - $lines = apache_cookie_security_directives();
1209 - }
1210 -
1211 - if (!$is_apache) {
1212 - insert_with_markers($htaccess, "HttpHeadersCookieSecurity", array());
1213 - }
1214 -
1215 - return insert_with_markers($filename, "HttpHeadersCookieSecurity", $lines);
1216 -}
1217 -
1218 -function is_samesite_supported() {
1219 - return version_compare(PHP_VERSION, '7.3.0', '>=');
1220 -}
1221 -
1222 -function http_headers_text_domain() {
1223 - load_plugin_textdomain('http-headers', false, basename( dirname( __FILE__ ) ) . '/languages/');
1224 -}
1225 -
1226 -function http_headers_settings_link( $links ) {
1227 - $url = get_admin_url() . 'options-general.php?page=http-headers';
1228 - $settings_link = '<a href="' . $url . '">' . __('Settings', 'http-headers') . '</a>';
1229 - array_unshift( $links, $settings_link );
1230 - return $links;
1231 -}
1232 -
1233 -function http_headers_after_setup_theme() {
1234 - add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'http_headers_settings_link');
1235 -}
1236 -
1237 217 function http_headers_enqueue($hook) {
1238 218 if ( 'http-headers.php' != $hook ) {
1239 219 # FIXME
1240 220 //return;
@@ -1239,190 +219,17 @@
1239 219 # FIXME
1240 220 //return;
1241 221 }
1242 222
1243 - wp_enqueue_script('http_headers_admin_scripts', plugin_dir_url( __FILE__ ) . 'assets/scripts.js', array(), '1.14.0', true);
1244 - wp_localize_script('http_headers_admin_scripts', 'hh', array(
1245 - 'lbl_delete' => __('Delete', 'http-headers'),
1246 - 'lbl_value' => __('Value', 'http-headers'),
1247 - ));
223 + wp_enqueue_script('http_headers_admin_scripts', plugin_dir_url( __FILE__ ) . 'assets/scripts.js');
1248 224 wp_enqueue_style('http_headers_admin_styles', plugin_dir_url( __FILE__ ) . 'assets/styles.css');
1249 225 }
1250 226
1251 -function http_headers_ajax_inspect() {
1252 - check_ajax_referer('inspect');
1253 - if (current_user_can('manage_options')) {
1254 - include 'views/ajax-inspect.php';
1255 - }
1256 - wp_die();
1257 -}
1258 227
1259 -function http_headers_post_import() {
1260 - check_admin_referer('import');
1261 - global $wpdb;
1262 - if (!(isset($_FILES['file']['tmp_name'])
1263 - && is_uploaded_file($_FILES['file']['tmp_name'])
1264 - && $_FILES['file']['error'] == UPLOAD_ERR_OK
1265 - )) {
1266 - wp_redirect(sprintf("%soptions-general.php?page=http-headers&tab=advanced&status=ERR&code=100", get_admin_url()));
1267 - exit;
1268 - }
1269 -
1270 - $string = @file_get_contents($_FILES['file']['tmp_name']);
1271 - if ($string === false) {
1272 - wp_redirect(sprintf("%soptions-general.php?page=http-headers&tab=advanced&status=ERR&code=101", get_admin_url()));
1273 - exit;
1274 - }
1275 -
1276 - $arr = preg_split('/;(\s+)?\n/', $string);
1277 - foreach ($arr as $statement) {
1278 - $statement = preg_replace("/(INSERT\s*INTO\s*)[\w\_]+options/", '${1}'.$wpdb->options, $statement);
1279 - $wpdb->query($statement);
1280 - }
1281 -
1282 - wp_redirect(sprintf("%soptions-general.php?page=http-headers&tab=advanced&status=OK", get_admin_url()));
1283 - exit;
1284 -}
1285 -
1286 -function http_headers_post_export() {
1287 - check_admin_referer('export');
1288 - global $wpdb;
1289 - $options = include dirname(__FILE__) . '/views/includes/options.inc.php';
1290 - $opts = array();
1291 - foreach ($options as $option)
1292 - {
1293 - $opts[] = $option[0];
1294 - }
1295 - $statement = sprintf("SELECT * FROM %s WHERE option_name IN ('%s');", $wpdb->options, join("','", $opts));
1296 - $results = $wpdb->get_results($statement, ARRAY_A);
1297 - $sql = array();
1298 -
1299 - $indexes = array();
1300 - foreach ($options as $option)
1301 - {
1302 - foreach ($results as $item)
1303 - {
1304 - if ($item['option_name'] == $option[0])
1305 - {
1306 - $indexes[$option[0]] = 1;
1307 -
1308 - $value = str_replace("'", "''", $item['option_value']);
1309 - $query = array();
1310 - $query[] = sprintf("INSERT INTO %s (option_id, option_name, option_value, autoload)", $wpdb->options);
1311 - $query[] = sprintf("VALUES (NULL, '%s', '%s', '%s')", $item['option_name'], $value, $item['autoload']);
1312 - $query[] = sprintf("ON DUPLICATE KEY UPDATE option_value = '%s', autoload = '%s';", $value, $item['autoload']);
1313 - $sql[] = join("\n", $query);
1314 - break;
1315 - }
1316 - }
1317 -
1318 - if (!isset($indexes[$option[0]]))
1319 - {
1320 - $query = array();
1321 - $query[] = sprintf("INSERT INTO %s (option_id, option_name, option_value, autoload)", $wpdb->options);
1322 - $query[] = sprintf("VALUES (NULL, '%s', '%s', 'yes')", $option[0], $option[1]);
1323 - $query[] = sprintf("ON DUPLICATE KEY UPDATE option_value = '%s', autoload = 'yes';", $option[1]);
1324 - $sql[] = join("\n", $query);
1325 - }
1326 - }
1327 -
1328 - $sql = join("\n\n", $sql);
1329 - $length = function_exists('mb_strlen') ? mb_strlen($sql) : strlen($sql);
1330 - $name = sprintf('WP-HTTP-Headers-%u.sql', time());
1331 -
1332 - # Send headers
1333 - header('Pragma: public');
1334 - header('Expires: 0');
1335 - header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
1336 - header('Cache-Control: private', false);
1337 - header('Content-Transfer-Encoding: binary');
1338 - header('Content-Disposition: attachment; filename="'.$name.'";');
1339 - header('Content-Type: application/sql');
1340 - header('Content-Length: ' . $length);
1341 -
1342 - echo $sql;
1343 - exit;
1344 -}
1345 -
1346 -function check_filename($filename) {
1347 - if (!is_file($filename)) {
1348 - return -1;
1349 - }
1350 -
1351 - clearstatcache();
1352 - if (!is_writable($filename)) {
1353 - return -2;
1354 - }
1355 -
1356 - return true;
1357 -}
1358 -
1359 -function check_webserver_requirements() {
1360 - $method = get_option('hh_method');
1361 - if ($method == 'htaccess') {
1362 - return apache_check_requirements();
1363 - }
1364 -
1365 - return true;
1366 -}
1367 -
1368 -function check_php_requirements() {
1369 - if (strpos(PHP_SAPI, 'cgi') !== false) {
1370 - // cgi, cgi-fcgi, fpm-fcgi
1371 - return check_filename(get_home_path().ini_get('user_ini.filename'));
1372 - }
1373 -
1374 - return true;
1375 -}
1376 -
1377 -function http_headers_logout() {
1378 - if (get_option('hh_clear_site_data') == 1) {
1379 - $values = get_option('hh_clear_site_data_value', array());
1380 - $tmp = array_keys($values);
1381 - if ($tmp) {
1382 - header(sprintf('Clear-Site-Data: "%s"', join('", "', $tmp)));
1383 - }
1384 - }
1385 -}
1386 -
1387 -function http_headers_activate() {
1388 - update_headers_directives();
1389 - update_auth_credentials();
1390 - update_auth_directives();
1391 - update_content_encoding_directives();
1392 - update_content_type_directives();
1393 - update_expires_directives();
1394 - update_cookie_security_directives();
1395 - update_timing_directives();
1396 -}
1397 -
1398 -function http_headers_deactivate() {
1399 - $filename = get_home_path().'.htaccess';
1400 -
1401 - insert_with_markers($filename, "HttpHeaders", array());
1402 - insert_with_markers($filename, "HttpHeadersCompression", array());
1403 - insert_with_markers($filename, "HttpHeadersContentType", array());
1404 - insert_with_markers($filename, "HttpHeadersExpires", array());
1405 - insert_with_markers($filename, "HttpHeadersTiming", array());
1406 - insert_with_markers($filename, "HttpHeadersAuth", array());
1407 - insert_with_markers($filename, "HttpHeadersCookieSecurity", array());
1408 -}
1409 -
1410 -register_activation_hook(__FILE__, 'http_headers_activate');
1411 -register_deactivation_hook(__FILE__, 'http_headers_deactivate');
1412 -add_action('wp_logout', 'http_headers_logout');
1413 -
1414 228 if ( is_admin() ){ // admin actions
1415 229 add_action('admin_menu', 'http_headers_admin_add_page');
1416 230 add_action('admin_init', 'http_headers_admin');
1417 - add_action("added_option", 'http_headers_option');
1418 - add_action("updated_option", 'http_headers_option');
1419 231 add_action('admin_enqueue_scripts', 'http_headers_enqueue');
1420 - add_action('after_setup_theme', 'http_headers_after_setup_theme');
1421 - add_action('plugins_loaded', 'http_headers_text_domain');
1422 - add_action('wp_ajax_inspect', 'http_headers_ajax_inspect');
1423 - add_action('admin_post_import', 'http_headers_post_import');
1424 - add_action('admin_post_export', 'http_headers_post_export');
1425 232 } else {
1426 233 // non-admin enqueues, actions, and filters
1427 234 add_action('send_headers', 'http_headers');
1428 235 }
@@ -1427,6 +234,6 @@
1427 234 add_action('send_headers', 'http_headers');
1428 235 }
1429 236
1430 237 function http_headers_admin_page() {
1431 - include 'views/index.php';
238 + include 'views/admin.php';
1432 239 }