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

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

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