Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
 
3
namespace PhpOffice\PhpSpreadsheet\Shared;
4
 
5
use PhpOffice\PhpSpreadsheet\Exception;
6
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
7
use ZipArchive;
8
 
9
class File
10
{
11
    /**
12
     * Use Temp or File Upload Temp for temporary files.
13
     *
14
     * @var bool
15
     */
16
    protected static $useUploadTempDirectory = false;
17
 
18
    /**
19
     * Set the flag indicating whether the File Upload Temp directory should be used for temporary files.
20
     */
21
    public static function setUseUploadTempDirectory(bool $useUploadTempDir): void
22
    {
23
        self::$useUploadTempDirectory = (bool) $useUploadTempDir;
24
    }
25
 
26
    /**
27
     * Get the flag indicating whether the File Upload Temp directory should be used for temporary files.
28
     */
29
    public static function getUseUploadTempDirectory(): bool
30
    {
31
        return self::$useUploadTempDirectory;
32
    }
33
 
34
    // https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT
35
    // Section 4.3.7
36
    // Looks like there might be endian-ness considerations
37
    private const ZIP_FIRST_4 = [
38
        "\x50\x4b\x03\x04", // what it looks like on my system
39
        "\x04\x03\x4b\x50", // what it says in documentation
40
    ];
41
 
42
    private static function validateZipFirst4(string $zipFile): bool
43
    {
44
        $contents = @file_get_contents($zipFile, false, null, 0, 4);
45
 
46
        return in_array($contents, self::ZIP_FIRST_4, true);
47
    }
48
 
49
    /**
50
     * Verify if a file exists.
51
     */
52
    public static function fileExists(string $filename): bool
53
    {
54
        // Sick construction, but it seems that
55
        // file_exists returns strange values when
56
        // doing the original file_exists on ZIP archives...
57
        if (strtolower(substr($filename, 0, 6)) == 'zip://') {
58
            // Open ZIP file and verify if the file exists
59
            $zipFile = substr($filename, 6, strrpos($filename, '#') - 6);
60
            $archiveFile = substr($filename, strrpos($filename, '#') + 1);
61
 
62
            if (self::validateZipFirst4($zipFile)) {
63
                $zip = new ZipArchive();
64
                $res = $zip->open($zipFile);
65
                if ($res === true) {
66
                    $returnValue = ($zip->getFromName($archiveFile) !== false);
67
                    $zip->close();
68
 
69
                    return $returnValue;
70
                }
71
            }
72
 
73
            return false;
74
        }
75
 
76
        return file_exists($filename);
77
    }
78
 
79
    /**
80
     * Returns canonicalized absolute pathname, also for ZIP archives.
81
     */
82
    public static function realpath(string $filename): string
83
    {
84
        // Returnvalue
85
        $returnValue = '';
86
 
87
        // Try using realpath()
88
        if (file_exists($filename)) {
89
            $returnValue = realpath($filename) ?: '';
90
        }
91
 
92
        // Found something?
93
        if ($returnValue === '') {
94
            $pathArray = explode('/', $filename);
95
            while (in_array('..', $pathArray) && $pathArray[0] != '..') {
96
                $iMax = count($pathArray);
97
                for ($i = 0; $i < $iMax; ++$i) {
98
                    if ($pathArray[$i] == '..' && $i > 0) {
99
                        unset($pathArray[$i], $pathArray[$i - 1]);
100
 
101
                        break;
102
                    }
103
                }
104
            }
105
            $returnValue = implode('/', $pathArray);
106
        }
107
 
108
        // Return
109
        return $returnValue;
110
    }
111
 
112
    /**
113
     * Get the systems temporary directory.
114
     */
115
    public static function sysGetTempDir(): string
116
    {
117
        // Moodle hack!
118
        if (function_exists('make_temp_directory')) {
119
            $temp = make_temp_directory('phpspreadsheet');
120
            return realpath(dirname($temp));
121
        }
122
 
123
        $path = sys_get_temp_dir();
124
        if (self::$useUploadTempDirectory) {
125
            //  use upload-directory when defined to allow running on environments having very restricted
126
            //      open_basedir configs
127
            if (ini_get('upload_tmp_dir') !== false) {
128
                if ($temp = ini_get('upload_tmp_dir')) {
129
                    if (file_exists($temp)) {
130
                        $path = $temp;
131
                    }
132
                }
133
            }
134
        }
135
 
136
        return realpath($path) ?: '';
137
    }
138
 
139
    public static function temporaryFilename(): string
140
    {
141
        $filename = tempnam(self::sysGetTempDir(), 'phpspreadsheet');
142
        if ($filename === false) {
143
            throw new Exception('Could not create temporary file');
144
        }
145
 
146
        return $filename;
147
    }
148
 
149
    /**
150
     * Assert that given path is an existing file and is readable, otherwise throw exception.
151
     */
152
    public static function assertFile(string $filename, string $zipMember = ''): void
153
    {
154
        if (!is_file($filename)) {
155
            throw new ReaderException('File "' . $filename . '" does not exist.');
156
        }
157
 
158
        if (!is_readable($filename)) {
159
            throw new ReaderException('Could not open "' . $filename . '" for reading.');
160
        }
161
 
162
        if ($zipMember !== '') {
163
            $zipfile = "zip://$filename#$zipMember";
164
            if (!self::fileExists($zipfile)) {
165
                // Has the file been saved with Windoze directory separators rather than unix?
166
                $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember);
167
                if (!self::fileExists($zipfile)) {
168
                    throw new ReaderException("Could not find zip member $zipfile");
169
                }
170
            }
171
        }
172
    }
173
 
174
    /**
175
     * Same as assertFile, except return true/false and don't throw Exception.
176
     */
177
    public static function testFileNoThrow(string $filename, ?string $zipMember = null): bool
178
    {
179
        if (!is_file($filename)) {
180
            return false;
181
        }
182
        if (!is_readable($filename)) {
183
            return false;
184
        }
185
        if ($zipMember === null) {
186
            return true;
187
        }
188
        // validate zip, but don't check specific member
189
        if ($zipMember === '') {
190
            return self::validateZipFirst4($filename);
191
        }
192
 
193
        $zipfile = "zip://$filename#$zipMember";
194
        if (self::fileExists($zipfile)) {
195
            return true;
196
        }
197
 
198
        // Has the file been saved with Windoze directory separators rather than unix?
199
        $zipfile = "zip://$filename#" . str_replace('/', '\\', $zipMember);
200
 
201
        return self::fileExists($zipfile);
202
    }
203
}