xref: /dokuwiki/lib/exe/fetch.php (revision 90fb952c4c30c09c8446076ba05991c89a3f0b01)
1<?php
2/**
3 * DokuWiki media passthrough file
4 *
5 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author     Andreas Gohr <andi@splitbrain.org>
7 */
8
9use dokuwiki\Input\Input;
10use dokuwiki\Extension\Event;
11
12if (!defined('DOKU_INC')) define('DOKU_INC', __DIR__ . '/../../');
13if (!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT', 1);
14require_once(DOKU_INC . 'inc/init.php');
15session_write_close(); //close session
16
17require_once(DOKU_INC . 'inc/fetch.functions.php');
18
19if (defined('SIMPLE_TEST')) {
20    $INPUT = new Input();
21}
22
23// BEGIN main
24$mimetypes = getMimeTypes();
25
26//get input
27$MEDIA = stripctl(getID('media', false)); // no cleaning except control chars - maybe external
28$CACHE = calc_cache($INPUT->str('cache'));
29$WIDTH = $INPUT->int('w');
30$HEIGHT = $INPUT->int('h');
31$REV = &$INPUT->ref('rev');
32//sanitize revision
33$REV = preg_replace('/[^0-9]/', '', $REV);
34
35[$EXT, $MIME, $DL] = mimetype($MEDIA, false);
36if ($EXT === false) {
37    $EXT = 'unknown';
38    $MIME = 'application/octet-stream';
39    $DL = true;
40}
41
42// check for permissions, preconditions and cache external files
43[$STATUS, $STATUSMESSAGE] = checkFileStatus($MEDIA, $FILE, $REV, $WIDTH, $HEIGHT);
44
45// prepare data for plugin events
46$data = [
47    'media' => $MEDIA,
48    'file' => $FILE,
49    'orig' => $FILE,
50    'mime' => $MIME,
51    'download' => $DL,
52    'cache' => $CACHE,
53    'ext' => $EXT,
54    'width' => $WIDTH,
55    'height' => $HEIGHT,
56    'status' => $STATUS,
57    'statusmessage' => $STATUSMESSAGE,
58    'ispublic' => media_ispublic($MEDIA),
59    'csp' => [
60        'default-src' => "'none'",
61        'style-src' => "'unsafe-inline'",
62        'media-src' => "'self'",
63        'object-src' => "'self'",
64        'font-src' => "'self' data:",
65        'form-action' => "'none'",
66        'frame-ancestors' => "'self'",
67    ]
68];
69
70// handle the file status
71$evt = new Event('FETCH_MEDIA_STATUS', $data);
72if ($evt->advise_before()) {
73    // redirects
74    if ($data['status'] > 300 && $data['status'] <= 304) {
75        if (defined('SIMPLE_TEST')) return; //TestResponse doesn't recognize redirects
76        send_redirect($data['statusmessage']);
77    }
78    // send any non 200 status
79    if ($data['status'] != 200) {
80        http_status($data['status'], $data['statusmessage']);
81    }
82    // die on errors
83    if ($data['status'] > 203) {
84        echo $data['statusmessage'];
85        if (defined('SIMPLE_TEST')) return;
86        exit;
87    }
88}
89$evt->advise_after();
90unset($evt);
91
92//handle image resizing/cropping
93$evt = new Event('MEDIA_RESIZE', $data);
94if ($evt->advise_before()) {
95    if (
96        $MIME != 'image/svg+xml' &&
97        (substr($MIME, 0, 5) == 'image') &&
98        ($WIDTH || $HEIGHT)
99    ) {
100        if ($HEIGHT && $WIDTH) {
101            $data['file'] = $FILE = media_crop_image($data['file'], $EXT, $WIDTH, $HEIGHT);
102        } else {
103            $data['file'] = $FILE = media_resize_image($data['file'], $EXT, $WIDTH, $HEIGHT);
104        }
105    }
106}
107$evt->advise_after();
108unset($evt);
109
110// finally send the file to the client
111$evt = new Event('MEDIA_SENDFILE', $data);
112if ($evt->advise_before()) {
113    sendFile(
114        $data['file'],
115        $data['mime'],
116        $data['download'],
117        $data['cache'],
118        $data['ispublic'],
119        $data['orig'],
120        $data['csp']
121    );
122}
123// Do something after the download finished.
124$evt->advise_after();  // will not be emitted on 304 or x-sendfile
125
126// END DO main
127