| @@ -71,25 +71,9 @@ | ||
| 71 | 71 | |
| 72 | 72 | /** |
| 73 | 73 | * Ensure the receipts directory exists with security files. |
| 74 | 74 | * |
| 75 | - * The denial files only bind where the server reads them: .htaccess on | |
| 76 | - * Apache and LiteSpeed, web.config on IIS. nginx and Caddy read neither, so | |
| 77 | - * there the unguessable 128-bit filename is the only control — which is why | |
| 78 | - * the generator proceeds regardless of what this returns. A host that | |
| 79 | - * cannot write a denial file should not lose the ability to issue receipts; | |
| 80 | - * refusing would trade a real feature for a control those servers were | |
| 81 | - * never going to enforce anyway. | |
| 82 | - * | |
| 83 | - * There is no receipt download route in this plugin. Delivery — email | |
| 84 | - * attachment and authenticated streaming download alike — lives entirely | |
| 85 | - * in Pro; an earlier version of this note claimed a REST streaming | |
| 86 | - * endpoint here, and none exists. | |
| 87 | - * | |
| 88 | - * @return bool True when the directory exists *and* every denial file this | |
| 89 | - * method writes is present. Callers that need to know whether | |
| 90 | - * the directory is actually hardened can act on it; the | |
| 91 | - * generator deliberately does not, for the reason above. | |
| 75 | + * @return bool True if directory exists or was created. | |
| 92 | 76 | * @since 1.0.0 |
| 93 | 77 | */ |
| 94 | 78 | public static function ensure_receipts_dir() { |
| 95 | 79 | $dir = self::get_receipts_dir(); |
| @@ -97,18 +81,8 @@ | ||
| 97 | 81 | if ( ! file_exists( $dir ) ) { |
| 98 | 82 | wp_mkdir_p( $dir ); |
| 99 | 83 | } |
| 100 | 84 | |
| 101 | - // Bail before writing if the directory is not there. Every write below | |
| 102 | - // is unconditional on the directory existing, so on a host where | |
| 103 | - // wp_mkdir_p() fails — an unwritable uploads path, an open_basedir | |
| 104 | - // restriction — each one emitted a PHP warning into the log before | |
| 105 | - // failing anyway. Nothing downstream is worse off: the caller already | |
| 106 | - // treats a false return as "not hardened". | |
| 107 | - if ( ! is_dir( $dir ) ) { | |
| 108 | - return false; | |
| 109 | - } | |
| 110 | - | |
| 111 | 85 | // Add .htaccess to prevent direct access. |
| 112 | 86 | $htaccess = $dir . '/.htaccess'; |
| 113 | 87 | if ( ! file_exists( $htaccess ) ) { |
| 114 | 88 | file_put_contents( $htaccess, "deny from all\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents |
| @@ -119,69 +93,9 @@ | ||
| 119 | 93 | if ( ! file_exists( $index ) ) { |
| 120 | 94 | file_put_contents( $index, "<?php\n// Silence is golden.\n" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents |
| 121 | 95 | } |
| 122 | 96 | |
| 123 | - // IIS reads neither .htaccess nor index.php as an access rule, so it | |
| 124 | - // needs its own denial. Written unconditionally rather than detected: | |
| 125 | - // the file is inert on Apache/nginx/LiteSpeed, and detecting the server | |
| 126 | - // from $_SERVER['SERVER_SOFTWARE'] is unreliable behind a proxy. | |
| 127 | - // | |
| 128 | - // requestFiltering under system.webServer/security, matching SureMail's | |
| 129 | - // attachments directory — minus its <handlers><remove> block. That block | |
| 130 | - // is belt-and-braces on top of two controls already here, and IIS raises | |
| 131 | - // a configuration error when <remove> names a handler the site does not | |
| 132 | - // have (the names are host-specific — SureMail hardcodes | |
| 133 | - // 'php-7.4.33'). Shipping something that can itself 500 the directory | |
| 134 | - // is the exact failure this rewrite exists to remove, and it cannot be | |
| 135 | - // tested from here, so it is left out: hiddenSegments already refuses | |
| 136 | - // every request to the path, and fileExtensions already refuses | |
| 137 | - // executables. | |
| 138 | - // | |
| 139 | - // The first attempt used | |
| 140 | - // system.webServer/authorization, which is not a real section — the | |
| 141 | - // ASP.NET element misplaced. IIS answers 500.19 on an unrecognised | |
| 142 | - // section, so the directory ended up "protected" by a configuration | |
| 143 | - // error rather than by the control this claims, and would have opened | |
| 144 | - // the moment somebody fixed the 500. requestFiltering also needs no | |
| 145 | - // extra role service, where URL Authorization 500s unless it is | |
| 146 | - // installed. | |
| 147 | - $web_config = $dir . '/web.config'; | |
| 148 | - if ( ! file_exists( $web_config ) ) { | |
| 149 | - $config = '<?xml version="1.0" encoding="UTF-8"?>' . "\n" | |
| 150 | - . '<configuration>' . "\n" | |
| 151 | - . ' <system.webServer>' . "\n" | |
| 152 | - . ' <security>' . "\n" | |
| 153 | - . ' <requestFiltering>' . "\n" | |
| 154 | - . ' <hiddenSegments>' . "\n" | |
| 155 | - . ' <add segment="receipts" />' . "\n" | |
| 156 | - . ' </hiddenSegments>' . "\n" | |
| 157 | - . ' <fileExtensions allowUnlisted="true">' . "\n" | |
| 158 | - . ' <add fileExtension=".php" allowed="false" />' . "\n" | |
| 159 | - . ' <add fileExtension=".phtml" allowed="false" />' . "\n" | |
| 160 | - . ' <add fileExtension=".php3" allowed="false" />' . "\n" | |
| 161 | - . ' <add fileExtension=".php4" allowed="false" />' . "\n" | |
| 162 | - . ' <add fileExtension=".php5" allowed="false" />' . "\n" | |
| 163 | - . ' <add fileExtension=".php7" allowed="false" />' . "\n" | |
| 164 | - . ' <add fileExtension=".phar" allowed="false" />' . "\n" | |
| 165 | - . ' <add fileExtension=".phps" allowed="false" />' . "\n" | |
| 166 | - . ' <add fileExtension=".pht" allowed="false" />' . "\n" | |
| 167 | - . ' <add fileExtension=".phpt" allowed="false" />' . "\n" | |
| 168 | - . ' <add fileExtension=".inc" allowed="false" />' . "\n" | |
| 169 | - . ' </fileExtensions>' . "\n" | |
| 170 | - . ' </requestFiltering>' . "\n" | |
| 171 | - . ' </security>' . "\n" | |
| 172 | - . ' </system.webServer>' . "\n" | |
| 173 | - . '</configuration>' . "\n"; | |
| 174 | - file_put_contents( $web_config, $config ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents | |
| 175 | - } | |
| 176 | - | |
| 177 | - // The directory has to exist *and* be protected. Returning only | |
| 178 | - // is_dir() reported success on a directory whose hardening writes had | |
| 179 | - // silently failed — an open receipts directory holding donor names, | |
| 180 | - // addresses and amounts, with the caller told everything was fine. | |
| 181 | - // web.config included: it was left out, so on IIS — the one platform it | |
| 182 | - // exists for — a failed write still reported success. | |
| 183 | - return is_dir( $dir ) && file_exists( $htaccess ) && file_exists( $index ) && file_exists( $web_config ); | |
| 97 | + return is_dir( $dir ); | |
| 184 | 98 | } |
| 185 | 99 | |
| 186 | 100 | /** |
| 187 | 101 | * Get the temp directory for mPDF. |