1<?php
2/**
3 * DokuWiki Plugin PreserveFilenames / common.php
4 *
5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
6 * @author  Kazutaka Miyasaka <kazmiya@gmail.com>
7 */
8
9// must be run within DokuWiki
10if (!defined('DOKU_INC')) {
11    die();
12}
13
14class PreserveFilenames_Common
15{
16    /**
17     * Returns a correct basename
18     * (fixes PHP Bug #37738: basename() bug in handling multibyte filenames)
19     *
20     * @see http://bugs.php.net/37738
21     */
22    function _correctBasename($path)
23    {
24        return rawurldecode(basename(preg_replace_callback(
25            '/%(?:[013-7][0-9a-fA-F]|2[0-46-9a-fA-F])/', // ASCII except for '%'
26            array(self, '_correctBasename_callback'),
27            rawurlencode($path)
28        )));
29    }
30
31    /**
32     * Callback function for _correctBasename() (only does rawurldecode)
33     */
34    static function _correctBasename_callback($matches)
35    {
36        return rawurldecode($matches[0]);
37    }
38
39    /**
40     * Returns a sanitized safe filename
41     *
42     * @see http://en.wikipedia.org/wiki/Filename
43     */
44    function _sanitizeFileName($filename)
45    {
46        $filename = preg_replace('/[\x00-\x1F\x7F]/', '',  $filename); // control
47        $filename = preg_replace('/["*:<>?|\/\\\\]/', '_', $filename); // graphic
48        $filename = preg_replace('/[#&]/', '_', $filename); // dw technical issues
49
50        return $filename;
51    }
52
53    /**
54     * Builds appropriate "Content-Disposition" header strings
55     *
56     * @see http://greenbytes.de/tech/tc2231/
57     */
58    function _buildContentDispositionHeader($download, $filename, $no_pathinfo = false)
59    {
60        global $conf;
61
62        $ua   = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
63        $type = $download ? 'attachment' : 'inline';
64        $ret  = "Content-Disposition: $type;";
65
66        if (!preg_match('/[\x00-\x1F\x7F-\xFF"*:<>?|\/\\\\]/', $filename)) {
67            // no problem with filename-safe ascii characters
68            $ret .= ' filename="' . $filename . '";';
69        } elseif (preg_match('/(?:Gecko\/|Opera\/| Opera )/', $ua)) {
70            // use RFC2231 if accessed via RFC2231-compliant browser
71            $ret .= " filename*=UTF-8''" . rawurlencode($filename) . ';';
72        } elseif (
73            strpos($filename, '"') === false
74            && strpos($ua, 'Safari/') !== false
75            && strpos($ua, 'Chrome/') === false
76            && preg_match('/Version\/[4-9]/', $ua)
77            && !preg_match('/Mac OS X 10_[1-4]_/', $ua)
78        ) {
79            // raw UTF-8 quoted-string
80            $ret .= ' filename="' . $filename . '"';
81        } elseif (
82            !$no_pathinfo
83            && $conf['useslash']
84            && $conf['userewrite']
85            && strpos($ua, 'Safari/') !== false
86            && strpos($ua, 'Chrome/') === false
87        ) {
88            // leave filename-parm field empty
89            // (browsers can retrieve a filename from pathinfo of its url)
90        } else {
91            // fallback to the DokuWiki default
92            $ret .= ' filename="' . rawurlencode($filename) . '";';
93        }
94
95        return $ret;
96    }
97}
98