PluginProbe
HTTP Headers / 1.10.4
HTTP Headers v1.10.4
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.10.4, at http-headers.php

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