PluginProbe
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management / 1.1.0
SureDonation – Donation Forms, Fundraising Campaigns & Donor Management v1.1.0
1.6.0 1.5.1 1.5.0 1.4.0 1.3.0 trunk 0.0.1 1.0.0 1.1.0 1.1.1 1.1.2 1.2.0
← All changes | inc/pdf/pdf-utils.php +2 -88 1.6.0 → 1.1.0 View file →
@@ -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.