Issues (1)

src/Testers/ModuleLoadedTester.php (1 issue)

Severity
1
<?php
2
3
namespace HtaccessCapabilityTester\Testers;
4
5
use \HtaccessCapabilityTester\TestResult;
6
7
/**
8
 * Class for testing if a module is loaded.
9
 *
10
 * @package    HtaccessCapabilityTester
11
 * @author     Bjørn Rosell <[email protected]>
12
 * @since      Class available since 0.7
13
 */
14
class ModuleLoadedTester extends AbstractTester
15
{
16
17
    /* @var string A valid Apache module name (ie "rewrite") */
18
    protected $moduleName;
19
20
    /**
21
     * Constructor.
22
     *
23
     * @return void
24
     */
25 16
    public function __construct($moduleName)
26
    {
27 16
        $this->moduleName = $moduleName;
28 16
    }
29
30
    /**
31
     * Child classes must implement this method, which tells which subdir the
32
     * test files are to be put.
33
     *
34
     * @return  string  A subdir for the test files
35
     */
36 14
    public function getSubDir()
37
    {
38 14
        return 'module-loaded/' . $this->moduleName;
39
    }
40
41
    /**
42
     * Register the test files using the "registerTestFile" method
43
     *
44
     * @return  void
45
     */
46 16
    public function registerTestFiles()
47
    {
48
        // No test files for this test
49 16
    }
50
51 14
    private function getServerSignatureBasedTest()
52
    {
53
        // Test files, method : Using ServerSignature
54
        // --------------------------------------------------
55
        // Requires (in order not to be inconclusive):
56
        // - Override: All
57
        // - Status: Core
58
        // - Directives: ServerSignature, IfModule
59
        // - PHP?: Yes
60
61
        $php = <<<'EOD'
62 14
<?php
63
if (isset($_SERVER['SERVER_SIGNATURE']) && ($_SERVER['SERVER_SIGNATURE'] != '')) {
64
    echo 1;
65
} else {
66
    echo 0;
67
}
68
EOD;
69
70
        $htaccess = <<<'EOD'
71 14
# The beauty of this trick is that ServerSignature is available in core.
72
# (it requires no modules and cannot easily be made forbidden)
73
# However, it requires PHP to check for the effect
74
75
ServerSignature Off
76
<IfModule mod_xxx.c>
77
ServerSignature On
78
</IfModule>
79
EOD;
80
81 14
        $htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
82
83
        return [
84 14
            'subdir' => $this->getSubDir() . '/server-signature',
85
            'files' => [
86 14
                ['.htaccess', $htaccess],
87 14
                ['test.php', $php],
88
            ],
89 14
            'request' => 'test.php',
90
            'interpretation' => [
91
                ['success', 'body', 'equals', '1'],
92
                ['failure', 'body', 'equals', '0'],
93
                // This time we do not fail for 500 because it is very unlikely that any of the
94
                // directives used are forbidden
95
            ]
96
        ];
97
    }
98
99
    /**
100
     *  @return  array
101
     */
102 4
    private function getRewriteBasedTest()
103
    {
104
        // Test files, method: Using Rewrite
105
        // --------------------------------------------------
106
        // Requires (in order not to be inconclusive)
107
        // - Module: mod_rewrite
108
        // - Override: FileInfo
109
        // - Directives: RewriteEngine, RewriteRule and IfModule
110
        // - PHP?: No
111
112
        $htaccess = <<<'EOD'
113 4
RewriteEngine On
114
<IfModule mod_xxx.c>
115
    RewriteRule ^request-me\.txt$ 1.txt [L]
116
</IfModule>
117
<IfModule !mod_xxx.c>
118
    RewriteRule ^request-me\.txt$ 0.txt [L]
119
</IfModule>
120
EOD;
121
122 4
        $htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
123
124
        return [
125 4
            'subdir' => $this->getSubDir() . '/rewrite',
126
            'files' => [
127 4
                ['.htaccess', $htaccess],
128
                ['0.txt', '0'],
129
                ['1.txt', '1'],
130
                ['request-me.txt', 'Redirect failed even though rewriting has been proven to work. Strange!'],
131
            ],
132 4
            'request' => 'request-me.txt',
133
            'interpretation' => [
134
                ['success', 'body', 'equals', '1'],
135
                ['failure', 'body', 'equals', '0'],
136
                //['inconclusive', 'status-code', 'not-equals', '200'],
137
            ]
138
        ];
139
    }
140
141
    /**
142
     *  @return  array
143
     */
144 2
    private function getHeaderSetBasedTest()
145
    {
146
147
        // Test files, method: Using Response Header
148
        // --------------------------------------------------
149
        // Requires (in order not to be inconclusive)
150
        // - Module: mod_headers
151
        // - Override: FileInfo
152
        // - Directives: Header and IfModule
153
        // - PHP?: No
154
155
        $htaccess = <<<'EOD'
156 2
<IfModule mod_xxx.c>
157
    Header set X-Response-Header-Test: 1
158
</IfModule>
159
<IfModule !mod_xxx.c>
160
    Header set X-Response-Header-Test: 0
161
</IfModule>
162
EOD;
163
164 2
        $htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
165
166
        return [
167 2
            'subdir' => $this->getSubDir() . '/header-set',
168
            'files' => [
169 2
                ['.htaccess', $htaccess],
170
                ['request-me.txt', 'thanks'],
171
            ],
172 2
            'request' => 'request-me.txt',
173
            'interpretation' => [
174
                ['success', 'headers', 'contains-key-value', 'X-Response-Header-Test', '1'],
175
                ['failure', 'headers', 'contains-key-value', 'X-Response-Header-Test', '0'],
176
            ]
177
        ];
178
    }
179
180
    /**
181
     *  @return  array
182
     */
183 2
    private function getContentDigestBasedTest()
184
    {
185
        // Test files, method: Using ContentDigest
186
        // --------------------------------------------------
187
        //
188
        // Requires (in order not to be inconclusive)
189
        // - Module: None - its in core
190
        // - Override: Options
191
        // - Directives: ContentDigest
192
        // - PHP?: No
193
194
        $htaccess = <<<'EOD'
195 2
<IfModule mod_xxx.c>
196
    ContentDigest On
197
</IfModule>
198
<IfModule !mod_xxx.c>
199
    ContentDigest Off
200
</IfModule>
201
EOD;
202
203 2
        $htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
204
205
        return [
206 2
            'subdir' => $this->getSubDir() . '/content-digest',
207
            'files' => [
208 2
                ['.htaccess', $htaccess],
209
                ['request-me.txt', 'thanks'],
210
            ],
211 2
            'request' => 'request-me.txt',
212
            'interpretation' => [
213
                ['success', 'headers', 'contains-key', 'Content-MD5'],
214
                ['failure', 'headers', 'not-contains-key', 'Content-MD5'],
215
            ]
216
        ];
217
    }
218
219
    /**
220
     *  @return  array
221
     */
222 2
    private function getDirectoryIndexBasedTest()
223
    {
224
        // Test files, method: Using DirectoryIndex
225
        // --------------------------------------------------
226
        //
227
        // Requires (in order not to be inconclusive)
228
        // - Module: mod_dir (Status: Base)
229
        // - Override: Indexes
230
        // - Directives: DirectoryIndex
231
        // - PHP?: No
232
233
        $htaccess = <<<'EOD'
234 2
<IfModule mod_xxx.c>
235
    DirectoryIndex 1.html
236
</IfModule>
237
<IfModule !mod_xxx.c>
238
    DirectoryIndex 0.html
239
</IfModule>
240
EOD;
241
242 2
        $htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
243
244
        return [
245 2
            'subdir' => $this->getSubDir() . '/directory-index',
246
            'files' => [
247 2
                ['.htaccess', $htaccess],
248
                ['0.html', '0'],
249
                ['1.html', '1'],
250
            ],
251 2
            'request' => '',        // empty - in order to request the index
252
            'interpretation' => [
253
                ['success', 'body', 'equals', '1'],
254
                ['failure', 'body', 'equals', '0'],
255
            ]
256
        ];
257
    }
258
259
260
    /**
261
     *  @return  array
262
     */
263 2
    private function getAddTypeBasedTest()
264
    {
265
        // Test files, method: Using AddType
266
        // --------------------------------------------------
267
        //
268
        // Requires (in order not to be inconclusive)
269
        // - Module: mod_mime
270
        // - Override: FileInfo
271
        // - Directives: AddType and IfModule
272
        // - PHP?: No
273
274
        $htaccess = <<<'EOD'
275 2
<IfModule mod_xxx.c>
276
    AddType image/gif .test
277
</IfModule>
278
<IfModule !mod_xxx.c>
279
    AddType image/jpeg .test
280
</IfModule>
281
EOD;
282
283 2
        $htaccess = str_replace('mod_xxx', 'mod_' . $this->moduleName, $htaccess);
284
285
        return [
286 2
            'subdir' => $this->getSubDir() . '/add-type',
287
            'files' => [
288 2
                ['.htaccess', $htaccess],
289
                ['request-me.test', 'hi'],
290
            ],
291 2
            'request' => 'request-me.test',
292
            'interpretation' => [
293
                ['success', 'headers', 'contains-key-value', 'Content-Type', 'image/gif'],
294
                ['failure', 'headers', 'contains-key-value', 'Content-Type', 'image/jpeg'],
295
            ]
296
        ];
297
    }
298
299
    /**
300
     * @return  bool|null
301
     */
302 14
    private function run2()
303
    {
304 14
        $hct = $this->getHtaccessCapabilityTester();
305
306 14
        $testResult = $hct->customTest($this->getServerSignatureBasedTest());
307 14
        if (!is_null($testResult)) {
308
            // PHP
309 2
            return $testResult;
310
        }
311
312 12
        if ($hct->contentDigestWorks()) {
313
            // Override: Options
314 2
            return $hct->customTest($this->getContentDigestBasedTest());
315
        }
316
317 10
        if ($hct->addTypeWorks()) {
318
            // Override: FileInfo, Status: Base (mod_mime)
319 2
            return $hct->customTest($this->getAddTypeBasedTest());
320
        }
321
322 8
        if ($hct->directoryIndexWorks()) {
323
            // Override: Indexes, Status: Base (mod_dir)
324 2
            return $hct->customTest($this->getDirectoryIndexBasedTest());
325
        }
326
327 6
        if ($hct->rewriteWorks()) {
328
            // Override: FileInfo, Module: mod_rewrite
329 4
            return $hct->customTest($this->getRewriteBasedTest());
330
        }
331
332 2
        if ($hct->headerSetWorks()) {
333
            //Override: FileInfo, Module: mod_headers
334 2
            return $hct->customTest($this->getHeaderSetBasedTest());
335
        }
336
        return null;
337
    }
338
339
    /**
340
     *  Run the test.
341
     *
342
     * @param  string  $baseDir  Directory on the server where the test files can be put
343
     * @param  string  $baseUrl  The base URL of the test files
344
     *
345
     * @return TestResult   Returns a test result
346
     */
347 16
    public function run($baseDir, $baseUrl)
348
    {
349 16
        $this->prepareForRun($baseDir, $baseUrl);
350
351 16
        $hct = $this->getHtaccessCapabilityTester();
352
353 16
        $htaccessEnabledTest = $hct->htaccessEnabled();
354 16
        if ($htaccessEnabledTest === false) {
355 1
            return new TestResult(false, '.htaccess files are ignored');
356 15
        } elseif (is_null($htaccessEnabledTest)) {
0 ignored issues
show
The condition is_null($htaccessEnabledTest) is always false.
Loading history...
357
            // We happen to know that if that test cannot establish anything,
358
            // then none of the usual weapons works - we can surrender right away
359 1
            return new TestResult(null, 'no methods available - we surrender early');
360
        }
361
362 14
        $status = $this->run2();
363 14
        if (is_null($status)) {
364
            return new TestResult(null, 'no methods worked');
365
        } else {
366 14
            return new TestResult($status, '');
367
        }
368
    }
369
}
370