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

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

1,365 lines 48.9 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.11.0
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-2018 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 update_headers_directives();
681 update_auth_credentials();
682 update_auth_directives();
683 update_content_encoding_directives();
684 update_expires_directives();
685 update_cookie_security_directives();
686 update_timing_directives();
687
688 } elseif (get_option('hh_method') == 'htaccess') {
689 # When particular header is changed
690 switch (true) {
691 case array_key_exists('hh_www_authenticate', $_POST):
692 check_admin_referer('http-headers-wwa-options');
693 update_auth_credentials();
694 update_auth_directives();
695 break;
696 case array_key_exists('hh_content_encoding', $_POST):
697 check_admin_referer('http-headers-ce-options');
698 update_content_encoding_directives();
699 break;
700 case array_key_exists('hh_vary', $_POST):
701 check_admin_referer('http-headers-vary-options');
702 update_content_encoding_directives();
703 break;
704 case array_key_exists('hh_expires', $_POST):
705 check_admin_referer('http-headers-exp-options');
706 update_expires_directives();
707 break;
708 case array_key_exists('hh_cookie_security', $_POST):
709 check_admin_referer('http-headers-cose-options');
710 update_cookie_security_directives();
711 break;
712 case array_key_exists('hh_timing_allow_origin', $_POST):
713 check_admin_referer('http-headers-tao-options');
714 update_timing_directives();
715 break;
716 case array_key_exists('option_page', $_POST) && strpos($_POST['option_page'], 'http-headers-') === 0:
717 check_admin_referer($_POST['option_page'].'-options');
718 update_headers_directives();
719 break;
720 }
721 }
722 }
723
724 function nginx_headers_directives() {
725 $lines = array();
726 list($headers, $statuses, $unset, $append) = get_http_headers();
727
728 foreach ($unset as $header) {
729 $lines[] = sprintf(' more_clear_headers "%s";', $header);
730 }
731 $cors = $cors_header = $cors_inner = $cors_footer = array();
732 $all = array();
733 foreach ($headers as $key => $value) {
734 if (in_array($key, array('WWW-Authenticate'))) {
735 continue;
736 }
737 if (in_array($key, array('X-Content-Type-Options'))) {
738 $all[] = sprintf('add_header %s %s always;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
739 continue;
740 }
741 if ($key == 'Access-Control-Allow-Origin' && is_array($value)) {
742 $cors_header[] = sprintf('if ($http_origin ~* ^(%s)$) {', str_replace('.', '\.', join('|', $value)));
743 $cors_footer[] = '}';
744 $cors_inner[] = ' add_header Access-Control-Allow-Origin "$http_origin";';
745 continue;
746 }
747 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'))) {
748 $cors_inner[] = sprintf(' add_header %s %s;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
749 continue;
750 }
751 $lines[] = sprintf(' add_header %s %s;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
752 }
753 foreach ($append as $key => $value) {
754 $lines[] = sprintf(' add_header %s %s;', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
755 }
756 if (!empty($cors_inner))
757 {
758 $cors = array_merge(
759 $cors_header,
760 $cors_inner,
761 $cors_footer
762 );
763 }
764 if (!empty($lines)) {
765 $lines = array_merge(
766 $all,
767 $cors,
768 array('location ~* \.(php|html)$ {'),
769 $lines,
770 array('}')
771 );
772 }
773 return $lines;
774 }
775
776 function nginx_content_encoding_directives() {
777 $lines = array();
778 if (get_option('hh_content_encoding') == 1) {
779
780 $lines[] = 'gzip on;';
781
782 $content_encoding_value = get_option('hh_content_encoding_value');
783 if (!$content_encoding_value) {
784 $content_encoding_value = array();
785 }
786
787 $content_encoding_ext = get_option('hh_content_encoding_ext');
788 if (!$content_encoding_ext) {
789 $content_encoding_ext = array();
790 }
791 if (!empty($content_encoding_ext)) {
792 //$lines[] = sprintf('<FilesMatch "\.(%s)$">', join('|', array_keys($content_encoding_ext)));
793 }
794 if (!empty($content_encoding_value)) {
795 $lines[] = sprintf('gzip_types %s;', join(' ', array_keys($content_encoding_value)));
796 }
797 }
798 return $lines;
799 }
800
801 function nginx_expires_directives() {
802 $lines = array();
803 if (get_option('hh_expires') == 1) {
804
805 $types = get_option('hh_expires_type', array());
806 $values = get_option('hh_expires_value', array());
807
808 $lines[] = 'map $sent_http_content_type $expires {';
809 foreach ($types as $type => $whatever) {
810 list($base, $period, $suffix) = explode('_', $values[$type]);
811 if (in_array($base, array('access', 'modification'))) {
812 $lines[] = $type != 'default'
813 ? sprintf(' %s %u%s;', $type, $period, $suffix[0])
814 : sprintf(' default %u%s;', $period, $suffix[0]);
815 } elseif ($base == 'invalid') {
816 $lines[] = $type != 'default'
817 ? sprintf(' %s 0;', $type)
818 : sprintf(' default 0;');
819 }
820 }
821 $lines[] = '}';
822
823 $lines[] = 'expires $expires;';
824 }
825 return $lines;
826 }
827
828 function nginx_timing_directives() {
829 $lines = array();
830 if (get_option('hh_timing_allow_origin') == 1) {
831 $value = get_option('hh_timing_allow_origin_value');
832 switch ($value)
833 {
834 case 'origin':
835 $value = get_option('hh_timing_allow_origin_url');
836 break;
837 }
838 if (!empty($value))
839 {
840 $lines[] = 'location ~* \.(js|css|jpe?g|png|gif|eot|otf|svg|ttf|woff2?)$ {';
841 $lines[] = sprintf(' add_header Timing-Allow-Origin "%s";', $value);
842 $lines[] = '}';
843 }
844 }
845 return $lines;
846 }
847
848 function nginx_auth_directives() {
849 $lines = array();
850 if (get_option('hh_www_authenticate') == 1) {
851
852 $type = get_option('hh_www_authenticate_type');
853
854 $file = $type == 'Basic' ? '.hh-htpasswd' : '.hh-htdigest';
855
856 $lines[] = 'location ~ ^\.hh-ht(digest|passwd)$ {';
857 $lines[] = ' deny all;';
858 $lines[] = '}';
859
860 $lines[] = sprintf('location %s {', get_home_path());
861 if ($type == 'Basic') {
862 $lines[] = sprintf(' auth_basic "%s";', get_option('hh_www_authenticate_realm'));
863 $lines[] = sprintf(' auth_basic_user_file %s%s;', get_home_path(), $file);
864 } else {
865 $lines[] = sprintf(' auth_digest "%s";', get_option('hh_www_authenticate_realm'));
866 $lines[] = sprintf(' auth_digest_user_file %s%s;', get_home_path(), $file);
867 }
868 $lines[] = '}';
869 }
870 return $lines;
871 }
872
873 function nginx_auth_credentials() {
874 return apache_auth_credentials();
875 }
876
877 function nginx_cookie_security_directives() {
878 $lines = array();
879
880 //TODO
881
882 return $lines;
883 }
884
885 function nginx_check_requirements() {
886 //TODO scheduled for v2.0.0
887 return true;
888 }
889
890 function iis_headers_directives() {
891 //TODO scheduled for v2.0.0
892 }
893
894 function iis_content_encoding_directives() {
895 //TODO scheduled for v2.0.0
896 }
897
898 function iis_expires_directives() {
899 //TODO scheduled for v2.0.0
900 }
901
902 function iis_timing_directives() {
903 //TODO scheduled for v2.0.0
904 }
905
906 function iis_auth_directives() {
907 //TODO scheduled for v2.0.0
908 }
909
910 function iis_auth_credentials() {
911 //TODO scheduled for v2.0.0
912 }
913
914 function iis_cookie_security_directives() {
915 //TODO scheduled for v2.0.0
916 }
917
918 function iis_check_requirements() {
919 //TODO scheduled for v2.0.0
920 return true;
921 }
922
923 function apache_headers_directives() {
924 $lines = array();
925 list($headers, $statuses, $unset, $append) = get_http_headers();
926
927 foreach ($unset as $header) {
928 $lines[] = sprintf(' Header unset %s', $header);
929 }
930 $all = array();
931 foreach ($headers as $key => $value) {
932 if (in_array($key, array('WWW-Authenticate'))) {
933 continue;
934 }
935 if (in_array($key, array('X-Content-Type-Options'))) {
936 $all[] = sprintf(' Header always set %s %s', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
937 continue;
938 }
939 if ($key == 'Strict-Transport-Security') {
940 $lines[] = sprintf(' Header set %s %s env=HTTPS', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
941 continue;
942 }
943 if ($key == 'Access-Control-Allow-Origin') {
944 $all[] = ' <IfModule mod_setenvif.c>';
945 if (is_array($value))
946 {
947 $all[] = sprintf(' SetEnvIf Origin "^(%s)$" CORS=$0', str_replace('.', '\.', join('|', $value)));
948 } else {
949 $all[] = ' SetEnvIf Origin "^(.+)$" CORS=$0';
950 }
951 $all[] = ' </IfModule>';
952 $all[] = ' Header set Access-Control-Allow-Origin %{CORS}e env=CORS';
953 continue;
954 }
955 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'))) {
956 $all[] = sprintf(' Header set %s %s env=CORS', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
957 continue;
958 }
959 $lines[] = sprintf(' Header set %s %s', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
960 }
961 foreach ($append as $key => $value) {
962 $lines[] = sprintf(' Header append %s %s', $key, sprintf('%1$s%2$s%1$s', strpos($value, '"') === false ? '"' : "'", $value));
963 }
964 if (!empty($lines)) {
965 $lines = array_merge(
966 array('<IfModule mod_headers.c>'),
967 $all,
968 array(' <FilesMatch "\.(php|html)$">'),
969 $lines,
970 array(' </FilesMatch>', '</IfModule>')
971 );
972 }
973 return $lines;
974 }
975
976 function apache_content_encoding_directives() {
977 $lines = array();
978 if (get_option('hh_content_encoding') == 1) {
979
980 $content_encoding_value = get_option('hh_content_encoding_value');
981 if (!$content_encoding_value) {
982 $content_encoding_value = array();
983 }
984
985 $content_encoding_ext = get_option('hh_content_encoding_ext');
986 if (!$content_encoding_ext) {
987 $content_encoding_ext = array();
988 }
989 if (!empty($content_encoding_ext)) {
990 $lines[] = sprintf('<FilesMatch "\.(%s)$">', join('|', array_keys($content_encoding_ext)));
991 $lines[] = ' <IfModule mod_deflate.c>';
992 $lines[] = ' SetOutputFilter DEFLATE';
993 $lines[] = ' </IfModule>';
994 $lines[] = '</FilesMatch>';
995 }
996 if (!empty($content_encoding_value)) {
997 if (!empty($lines)) {
998 $lines[] = '';
999 }
1000 $lines[] = '<IfModule mod_deflate.c>';
1001 foreach ($content_encoding_value as $item => $whatever) {
1002 $lines[] = sprintf(' AddOutputFilterByType DEFLATE %s', $item);
1003 }
1004 $lines[] = '</IfModule>';
1005 }
1006 }
1007
1008 return $lines;
1009 }
1010
1011 function apache_expires_directives() {
1012 $lines = array();
1013 if (get_option('hh_expires') == 1) {
1014
1015 $types = get_option('hh_expires_type', array());
1016 $values = get_option('hh_expires_value', array());
1017
1018 $lines[] = '<IfModule mod_expires.c>';
1019 $lines[] = ' ExpiresActive On';
1020 foreach ($types as $type => $whatever) {
1021 list($base, $period, $suffix) = explode('_', $values[$type]);
1022 if (in_array($base, array('access', 'modification'))) {
1023 $lines[] = $type != 'default'
1024 ? sprintf(' ExpiresByType %s "%s plus %u %s"', $type, $base, $period, $suffix)
1025 : sprintf(' ExpiresDefault "%s plus %u %s"', $base, $period, $suffix);
1026 } elseif ($base == 'invalid') {
1027 $lines[] = $type != 'default'
1028 ? sprintf(' ExpiresByType %s A0', $type)
1029 : sprintf(' ExpiresDefault A0');
1030 }
1031 }
1032 $lines[] = '</IfModule>';
1033 }
1034
1035 return $lines;
1036 }
1037
1038 function apache_timing_directives() {
1039 $lines = array();
1040 if (get_option('hh_timing_allow_origin') == 1) {
1041 $value = get_option('hh_timing_allow_origin_value');
1042 switch ($value)
1043 {
1044 case 'origin':
1045 $value = get_option('hh_timing_allow_origin_url');
1046 break;
1047 }
1048 if (!empty($value))
1049 {
1050 $lines[] = '<IfModule mod_headers.c>';
1051 $lines[] = ' <FilesMatch "\\.(js|css|jpe?g|png|gif|eot|otf|svg|ttf|woff2?)$">';
1052 $lines[] = sprintf(' Header set Timing-Allow-Origin "%s"', $value);
1053 $lines[] = ' </FilesMatch>';
1054 $lines[] = '</IfModule>';
1055 }
1056 }
1057
1058 return $lines;
1059 }
1060
1061 function apache_auth_directives() {
1062 $lines = array();
1063 if (get_option('hh_www_authenticate') == 1) {
1064
1065 $type = get_option('hh_www_authenticate_type');
1066
1067 $file = $type == 'Basic' ? '.hh-htpasswd' : '.hh-htdigest';
1068
1069 $lines[] = '<FilesMatch "^\.hh-ht(digest|passwd)$">';
1070 $lines[] = ' Order deny,allow';
1071 $lines[] = ' Deny from all';
1072 $lines[] = '</FilesMatch>';
1073
1074 $lines[] = sprintf('<IfModule mod_auth_%s.c>', strtolower($type));
1075 $lines[] = sprintf(' AuthType %s', get_option('hh_www_authenticate_type'));
1076 $lines[] = sprintf(' AuthName "%s"', get_option('hh_www_authenticate_realm'));
1077 $lines[] = sprintf(' AuthUserFile "%s%s"', get_home_path(), $file);
1078 $lines[] = ' Require valid-user';
1079 $lines[] = '</IfModule>';
1080 }
1081
1082 return $lines;
1083 }
1084
1085 function apache_auth_credentials() {
1086 if (get_option('hh_www_authenticate') == 1) {
1087 $type = get_option('hh_www_authenticate_type');
1088 $usernames = get_option('hh_www_authenticate_user', array());
1089 $passwords = get_option('hh_www_authenticate_pswd', array());
1090 if (!is_array($usernames)) {
1091 $usernames = array($usernames);
1092 }
1093 if (!is_array($passwords)) {
1094 $passwords = array($passwords);
1095 }
1096 $realm = get_option('hh_www_authenticate_realm');
1097 $auth = array();
1098 switch ($type) {
1099 case 'Basic':
1100 $ht_file = get_home_path().'.hh-htpasswd';
1101 foreach ($usernames as $k => $user) {
1102 $auth[] = sprintf('%s:{SHA}%s', $user, base64_encode(sha1($passwords[$k], true)));
1103 }
1104 break;
1105 case 'Digest':
1106 $ht_file = get_home_path().'.hh-htdigest';
1107 foreach ($usernames as $k => $user) {
1108 $auth[] = sprintf('%s:%s:%s', $user, $realm, md5($user.':'.$realm.':'.$passwords[$k]));
1109 }
1110 break;
1111 }
1112 $auth = join("\n", $auth);
1113
1114 return compact('ht_file', 'auth');
1115 }
1116 return false;
1117 }
1118
1119 function apache_cookie_security_directives() {
1120 $lines = array();
1121 if (get_option('hh_cookie_security') == 1) {
1122 $value = get_option('hh_cookie_security_value', array());
1123 if (isset($value['HttpOnly'])) {
1124 $lines[] = 'php_flag session.cookie_httponly on';
1125 }
1126 if (isset($value['Secure'])) {
1127 $lines[] = 'php_flag session.cookie_secure on';
1128 }
1129 }
1130
1131 return $lines;
1132 }
1133
1134 function apache_check_requirements() {
1135 return check_filename(get_home_path().'.htaccess');
1136 }
1137
1138 function update_headers_directives() {
1139 $lines = array();
1140 if (get_option('hh_method') == 'htaccess') {
1141 $lines = apache_headers_directives();
1142 }
1143
1144 return insert_with_markers(get_home_path().'.htaccess', "HttpHeaders", $lines);
1145 }
1146
1147 function update_content_encoding_directives() {
1148 $lines = array();
1149 if (get_option('hh_method') == 'htaccess') {
1150 $lines = apache_content_encoding_directives();
1151 }
1152
1153 return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersCompression", $lines);
1154 }
1155
1156 function update_expires_directives() {
1157 $lines = array();
1158 if (get_option('hh_method') == 'htaccess') {
1159 $lines = apache_expires_directives();
1160 }
1161
1162 return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersExpires", $lines);
1163 }
1164
1165 function update_timing_directives() {
1166 $lines = array();
1167 if (get_option('hh_method') == 'htaccess') {
1168 $lines = apache_timing_directives();
1169 }
1170
1171 return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersTiming", $lines);
1172 }
1173
1174 function update_auth_directives() {
1175 $lines = array();
1176 if (get_option('hh_method') == 'htaccess') {
1177 $lines = apache_auth_directives();
1178 }
1179
1180 return insert_with_markers(get_home_path().'.htaccess', "HttpHeadersAuth", $lines);
1181 }
1182
1183 function update_auth_credentials() {
1184 if (get_option('hh_method') == 'htaccess') {
1185 $credentials = apache_auth_credentials();
1186
1187 return @file_put_contents($credentials['ht_file'], $credentials['auth']);
1188 }
1189
1190 return false;
1191 }
1192
1193 function update_cookie_security_directives() {
1194 $lines = array();
1195 if (strpos(PHP_SAPI, 'cgi') !== false) {
1196 $filename = get_home_path().ini_get('user_ini.filename');
1197 $lines = php_cookie_security_directives();
1198 } elseif (get_option('hh_method') == 'htaccess') {
1199 $filename = get_home_path().'.htaccess';
1200 $lines = apache_cookie_security_directives();
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 add_action('wp_logout', 'http_headers_logout');
1346
1347 if ( is_admin() ){ // admin actions
1348 add_action('admin_menu', 'http_headers_admin_add_page');
1349 add_action('admin_init', 'http_headers_admin');
1350 add_action("added_option", 'http_headers_option');
1351 add_action("updated_option", 'http_headers_option');
1352 add_action('admin_enqueue_scripts', 'http_headers_enqueue');
1353 add_action('after_setup_theme', 'http_headers_after_setup_theme');
1354 add_action('plugins_loaded', 'http_headers_text_domain');
1355 add_action('wp_ajax_inspect', 'http_headers_ajax_inspect');
1356 add_action('admin_post_import', 'http_headers_post_import');
1357 add_action('admin_post_export', 'http_headers_post_export');
1358 } else {
1359 // non-admin enqueues, actions, and filters
1360 add_action('send_headers', 'http_headers');
1361 }
1362
1363 function http_headers_admin_page() {
1364 include 'views/index.php';
1365 }