PluginProbe
HTTP Headers / 1.12.2
HTTP Headers v1.12.2
1.19.5 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.12.0 1.12.1 1.12.2 1.13.0 1.13.1 1.13.2 1.13.3 1.13.4 1.14.0 1.14.1 1.14.2 1.15.0 All 60 releases
http-headers / http-headers.php

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

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