xref: /dokuwiki/_test/tests/inc/httputils_xaccel.test.php (revision a7e1021671c06230d0a9890646b3531d28d5d29a)
1<?php
2
3/**
4 * Tests for the nginx X-Accel-Redirect URL construction
5 *
6 * @see http_xaccel_url()
7 * @see https://github.com/dokuwiki/dokuwiki/issues/2895
8 */
9class httputils_xaccel_test extends DokuWikiTest
10{
11    /**
12     * Files inside the DokuWiki directory keep their path relative to the root.
13     * This is the default layout and must match the historic behaviour.
14     */
15    public function test_file_inside_dokuwiki()
16    {
17        $file = DOKU_INC . 'data/media/wiki/dokuwiki.png';
18        $this->assertEquals(
19            DOKU_REL . 'data/media/wiki/dokuwiki.png',
20            http_xaccel_url($file)
21        );
22    }
23
24    /**
25     * lib/ files (also inside the DokuWiki directory) work too.
26     */
27    public function test_libfile_inside_dokuwiki()
28    {
29        $file = DOKU_INC . 'lib/images/fileicons/png.png';
30        $this->assertEquals(
31            DOKU_REL . 'lib/images/fileicons/png.png',
32            http_xaccel_url($file)
33        );
34    }
35
36    /**
37     * A media directory moved out of the DokuWiki root is mapped to the URL it
38     * would have by default (below data/media/). This is the regression in
39     * issue #2895, where the previous blind substr() produced a broken path.
40     */
41    public function test_relocated_mediadir()
42    {
43        global $conf;
44        $conf['mediadir'] = '/srv/dokuwiki-media';
45        $file = '/srv/dokuwiki-media/wiki/dokuwiki.png';
46        $this->assertEquals(
47            DOKU_REL . 'data/media/wiki/dokuwiki.png',
48            http_xaccel_url($file)
49        );
50    }
51
52    /**
53     * The cache directory (used for resized media, compiled CSS/JS and the
54     * sitemap) is mapped as well when relocated.
55     */
56    public function test_relocated_cachedir()
57    {
58        global $conf;
59        $conf['cachedir'] = '/var/cache/dokuwiki';
60        $file = '/var/cache/dokuwiki/a/abcdef0123.css';
61        $this->assertEquals(
62            DOKU_REL . 'data/cache/a/abcdef0123.css',
63            http_xaccel_url($file)
64        );
65    }
66
67    /**
68     * The most specific (longest) configured directory must win, so a file
69     * below a relocated mediadir is not swallowed by a relocated savedir.
70     */
71    public function test_most_specific_dir_wins()
72    {
73        global $conf;
74        $conf['savedir'] = '/srv/dwdata';
75        $conf['mediadir'] = '/srv/dwdata/media';
76        $file = '/srv/dwdata/media/wiki/dokuwiki.png';
77        $this->assertEquals(
78            DOKU_REL . 'data/media/wiki/dokuwiki.png',
79            http_xaccel_url($file)
80        );
81    }
82
83    /**
84     * A file outside DokuWiki and all data directories (e.g. served by a
85     * plugin from an arbitrary location) is emitted as its absolute path
86     * behind the dedicated opt-in prefix.
87     */
88    public function test_arbitrary_file_uses_escape_hatch()
89    {
90        $file = '/opt/secret-downloads/report.pdf';
91        $this->assertEquals(
92            DOKU_REL . '_x_accel_redirect/opt/secret-downloads/report.pdf',
93            http_xaccel_url($file)
94        );
95    }
96
97    /**
98     * File names with spaces or other special characters must be URL-encoded,
99     * because nginx URL-decodes the X-Accel-Redirect target.
100     */
101    public function test_special_characters_are_encoded()
102    {
103        $file = DOKU_INC . 'data/media/wiki/some file & more.png';
104        $this->assertEquals(
105            DOKU_REL . 'data/media/wiki/some%20file%20%26%20more.png',
106            http_xaccel_url($file)
107        );
108    }
109}
110