See Release Notes
Long Term Support Release
Differences Between: [Versions 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 401 and 403]
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 throw new ReaderException("Could not find zip member $zipfile"); 166 } 167 } 168 } 169 170 /** 171 * Same as assertFile, except return true/false and don't throw Exception. 172 */ 173 public static function testFileNoThrow(string $filename, ?string $zipMember = null): bool 174 { 175 if (!is_file($filename)) { 176 return false; 177 } 178 if (!is_readable($filename)) { 179 return false; 180 } 181 if ($zipMember === null) { 182 return true; 183 } 184 // validate zip, but don't check specific member 185 if ($zipMember === '') { 186 return self::validateZipFirst4($filename); 187 } 188 189 return self::fileExists("zip://$filename#$zipMember"); 190 } 191 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body