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