PluginProbe
404 Solution / trunk
404 Solution vtrunk
4.3.5 4.3.4 4.3.3 4.3.2 4.3.1 4.3.0 4.2.0 4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.13 4.1.12 4.1.11 4.1.10 4.1.9 4.1.8 4.1.7 4.1.6 4.1.5 4.1.4 4.1.3 trunk 2.30.0 All 109 releases
404-solution / includes / ajax / ResponseCompressionSuppression.php

ResponseCompressionSuppression.php in 404 Solution trunk, at includes/ajax/ResponseCompressionSuppression.php

67 lines 3.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 /**
8 * Ask this response's transport not to compress or transform it, and report
9 * whether each request actually took effect.
10 *
11 * Two mechanisms, because two different parties compress. `Cache-Control:
12 * no-transform` asks an intermediary (LiteSpeed, Cloudflare, a caching reverse
13 * proxy) to leave the bytes alone; `zlib.output_compression` is PHP's own
14 * output handler. Suppressing one and not the other still yields a compressed
15 * response, so the two outcomes are reported separately and `applied` is the
16 * conjunction.
17 *
18 * BOTH are refusable at runtime, and neither refusal raises anything a caller
19 * would notice:
20 *
21 * - Once any byte of output has been emitted, headers_sent() is true, the
22 * header cannot be set, and ini_set() returns false for this directive with
23 * "Cannot change zlib.output_compression - headers already sent".
24 * - A host with ini_set in disable_functions refuses the second half outright
25 * (see ABJ_404_Solution_PhpRuntimeCapabilityAdapter), which is a live user
26 * environment, not a hypothetical one.
27 *
28 * The outcome is returned rather than discarded because the caller is a
29 * diagnostic instrument. A canary rung that suppressed nothing but reports
30 * itself as the suppressed rung does not merely lose a probe: it turns the
31 * ladder's central comparison -- adjacent rungs differing by exactly one
32 * variable -- into a comparison of a step against itself, while every consumer
33 * still reads it as evidence about compression.
34 */
35 final class ABJ_404_Solution_ResponseCompressionSuppression {
36
37 /**
38 * Request suppression from both parties and report what each one did.
39 *
40 * @return array{noTransformHeader: bool, zlibOutputCompression: bool, applied: bool}
41 * `noTransformHeader`: the no-transform header was set on this response.
42 * `zlibOutputCompression`: PHP's output compression is now off (a
43 * directive that was already off still counts -- the state is what the
44 * probe depends on, not whether this call changed it).
45 * `applied`: both, so the response is genuinely unsuppressed-by-nobody.
46 */
47 public static function apply(): array {
48 $noTransformHeader = false;
49 if (!headers_sent()) {
50 header('Cache-Control: no-transform');
51 $noTransformHeader = true;
52 }
53 // setIni() returns the PREVIOUS value on success and false on refusal,
54 // so `!== false` is the test: an empty-string previous value means the
55 // directive was already off, which is success, while a loose truthy
56 // check would read it as failure.
57 $zlibDisabled = ABJ_404_Solution_PhpRuntimeCapabilityAdapter::setIni(
58 array('directive' => 'zlib.output_compression', 'value' => '0')) !== false;
59
60 return array(
61 'noTransformHeader' => $noTransformHeader,
62 'zlibOutputCompression' => $zlibDisabled,
63 'applied' => $noTransformHeader && $zlibDisabled,
64 );
65 }
66 }
67