PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Shared / File.php

File.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Shared/File.php

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