PluginProbe
HTTP Headers / 1.12.1
HTTP Headers v1.12.1
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
http-headers / http-headers.php

http-headers.php in HTTP Headers 1.12.1, at http-headers.php

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