ILIAS  release_8 Revision v8.19
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilFileUtils.php
Go to the documentation of this file.
1 <?php
2 
24 
33 {
37  public static function processZipFile(
38  string $a_directory,
39  string $a_file,
40  bool $structure
41  ): void {
42  global $DIC;
43 
44  $lng = $DIC->language();
45 
46  $pathinfo = pathinfo($a_file);
47  $file = $pathinfo["basename"];
48 
49  // see 22727
50  if ($pathinfo["extension"] ?? '' === '') {
51  $file .= ".zip";
52  }
53 
54  // Copy zip-file to new directory, unzip and remove it
55  // TODO: check archive for broken file
56  //copy ($a_file, $a_directory . "/" . $file);
57  self::moveUploadedFile($a_file, $file, $a_directory . "/" . $file);
58  self::unzip($a_directory . "/" . $file);
59  unlink($a_directory . "/" . $file);
60  //echo "-".$a_directory . "/" . $file."-";
61  // Stores filename and paths into $filearray to check for viruses
62  // Checks if filenames can be read, else -> throw exception and leave
63  $filearray = [];
64  ilFileUtils::recursive_dirscan($a_directory, $filearray);
65 
66  // if there are no files unziped (->broken file!)
67  if (empty($filearray)) {
68  throw new ilFileUtilsException(
69  $lng->txt("archive_broken"),
71  );
72  }
73 
74  // virus handling
75  foreach ($filearray["file"] as $key => $value) {
76  // remove "invisible" files
77  if (substr($value, 0, 1) == "." || stristr(
78  $filearray["path"][$key],
79  "/__MACOSX/"
80  )) {
81  unlink($filearray["path"][$key] . $value);
82  unset($filearray["path"][$key]);
83  unset($filearray["file"][$key]);
84  continue;
85  }
86 
87  $vir = ilVirusScanner::virusHandling($filearray["path"][$key], $value);
88  if (!$vir[0]) {
89  // Unlink file and throw exception
90  unlink($filearray['path'][$key]);
91  throw new ilFileUtilsException(
92  $lng->txt("file_is_infected") . "<br />" . $vir[1],
94  );
95  } elseif ($vir[1] != "") {
96  throw new ilFileUtilsException(
97  $vir[1],
99  );
100  }
101  }
102 
103  // If archive is to be used "flat"
104  $doublettes = '';
105  if (!$structure) {
106  foreach (array_count_values($filearray["file"]) as $key => $value) {
107  // Archive contains same filenames in different directories
108  if ($value != "1") {
109  $doublettes .= " '" . ilFileUtils::utf8_encode($key) . "'";
110  }
111  }
112  if (strlen($doublettes) > 0) {
113  throw new ilFileUtilsException(
114  $lng->txt("exc_upload_error") . "<br />" . $lng->txt(
115  "zip_structure_error"
116  ) . $doublettes,
118  );
119  }
120  } else {
121  $mac_dir = $a_directory . "/__MACOSX";
122  if (file_exists($mac_dir)) {
123  self::delDir($mac_dir);
124  }
125  }
126  }
127 
137  public static function recursive_dirscan(string $dir, array &$arr): void
138  {
139  global $DIC;
140 
141  $lng = $DIC->language();
142 
143  $dirlist = opendir($dir);
144  while (false !== ($file = readdir($dirlist))) {
145  if (!is_file($dir . "/" . $file) && !is_dir($dir . "/" . $file)) {
146  throw new ilFileUtilsException(
147  $lng->txt("filenames_not_supported"),
149  );
150  }
151 
152  if ($file != '.' && $file != '..') {
153  $newpath = $dir . '/' . $file;
154  $level = explode('/', $newpath);
155  if (is_dir($newpath)) {
156  ilFileUtils::recursive_dirscan($newpath, $arr);
157  } else {
158  $arr["path"][] = $dir . "/";
159  $arr["file"][] = end($level);
160  }
161  }
162  }
163  closedir($dirlist);
164  }
165 
175  public static function utf8_encode(string $string): string
176  {
177 
178  // From http://w3.org/International/questions/qa-forms-utf-8.html
179  return (preg_match(
180  '%^(?:
181  [\x09\x0A\x0D\x20-\x7E] # ASCII
182  | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
183  | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
184  | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
185  | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
186  | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
187  | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
188  | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
189  )*$%xs',
190  $string
191  )) ? $string : utf8_encode($string);
192  }
193 
197  public static function getValidFilename(string $a_filename): string
198  {
199  global $DIC;
200  $sanitizer = new ilFileServicesFilenameSanitizer(
201  $DIC->fileServiceSettings()
202  );
203 
204  return $sanitizer->sanitize($a_filename);
205  }
206 
210  public static function rename(string $a_source, string $a_target): bool
211  {
212  $pi = pathinfo($a_target);
213  global $DIC;
214  $sanitizer = new ilFileServicesFilenameSanitizer(
215  $DIC->fileServiceSettings()
216  );
217 
218  if (!$sanitizer->isClean($a_target)) {
219  throw new ilFileUtilsException("Invalid target file");
220  }
221 
222  return rename($a_source, $a_target);
223  }
224 
242  public static function rCopy(
243  string $a_sdir,
244  string $a_tdir,
245  bool $preserveTimeAttributes = false
246  ): bool {
247  $sourceFS = LegacyPathHelper::deriveFilesystemFrom($a_sdir);
248  $targetFS = LegacyPathHelper::deriveFilesystemFrom($a_tdir);
249 
250  $sourceDir = LegacyPathHelper::createRelativePath($a_sdir);
251  $targetDir = LegacyPathHelper::createRelativePath($a_tdir);
252 
253  // check if arguments are directories
254  if (!$sourceFS->hasDir($sourceDir)) {
255  return false;
256  }
257 
258  $sourceList = $sourceFS->listContents($sourceDir, true);
259 
260  foreach ($sourceList as $item) {
261  if ($item->isDir()) {
262  continue;
263  }
264  try {
265  $itemPath = $targetDir . '/' . substr(
266  $item->getPath(),
267  strlen($sourceDir)
268  );
269  $stream = $sourceFS->readStream($item->getPath());
270  $targetFS->writeStream($itemPath, $stream);
271  } catch (\ILIAS\Filesystem\Exception\FileAlreadyExistsException $e) {
272  // Do nothing with that type of exception
273  }
274  }
275 
276  return true;
277  }
278 
298  public static function makeDirParents(string $a_dir): bool
299  {
300  $dirs = [$a_dir];
301  $a_dir = dirname($a_dir);
302  $last_dirname = '';
303  while ($last_dirname != $a_dir) {
304  array_unshift($dirs, $a_dir);
305  $last_dirname = $a_dir;
306  $a_dir = dirname($a_dir);
307  }
308 
309  // find the first existing dir
310  $reverse_paths = array_reverse($dirs, true);
311  $found_index = -1;
312  foreach ($reverse_paths as $key => $value) {
313  if ($found_index == -1) {
314  if (is_dir($value)) {
315  $found_index = $key;
316  }
317  }
318  }
319 
320  $old_mask = umask(0000);
321  foreach ($dirs as $dirindex => $dir) {
322  // starting with the longest existing path
323  if ($dirindex >= $found_index) {
324  if (!file_exists($dir)) {
325  if (strcmp(substr($dir, strlen($dir) - 1, 1), "/") == 0) {
326  // on some systems there is an error when there is a slash
327  // at the end of a directory in mkdir, see Mantis #2554
328  $dir = substr($dir, 0, strlen($dir) - 1);
329  }
330  if (!mkdir($dir)) {
331  error_log("Can't make directory: $dir");
332  return false;
333  }
334  } elseif (!is_dir($dir)) {
335  error_log("$dir is not a directory");
336  return false;
337  } else {
338  // get umask of the last existing parent directory
339  $umask = fileperms($dir);
340  }
341  }
342  }
343  umask($old_mask);
344 
345  return true;
346  }
347 
358  public static function getDataDir(): string
359  {
360  return CLIENT_DATA_DIR;
361  }
362 
371  public static function dirsize(string $directory): int
372  {
373  $size = 0;
374  if (!is_dir($directory)) {
375  // dirsize of non-existing directory
376  $size = @filesize($directory);
377  return ($size === false) ? -1 : $size;
378  }
379  if ($DIR = opendir($directory)) {
380  while (($dirfile = readdir($DIR)) !== false) {
381  if (is_link(
382  $directory . DIRECTORY_SEPARATOR . $dirfile
383  ) || $dirfile == '.' || $dirfile == '..') {
384  continue;
385  }
386  if (is_file($directory . DIRECTORY_SEPARATOR . $dirfile)) {
387  $size += filesize(
388  $directory . DIRECTORY_SEPARATOR . $dirfile
389  );
390  } elseif (is_dir($directory . DIRECTORY_SEPARATOR . $dirfile)) {
391  $dirSize = ilFileUtils::dirsize(
392  $directory . DIRECTORY_SEPARATOR . $dirfile
393  );
394  if ($dirSize >= 0) {
395  $size += $dirSize;
396  } else {
397  return -1;
398  }
399  }
400  }
401  closedir($DIR);
402  }
403  return $size;
404  }
405 
424  public static function makeDir(string $a_dir): bool
425  {
426  $a_dir = trim($a_dir);
427 
428  // remove trailing slash (bugfix for php 4.2.x)
429  if (substr($a_dir, -1) == "/") {
430  $a_dir = substr($a_dir, 0, -1);
431  }
432 
433  // check if a_dir comes with a path
434  if (!($path = substr(
435  $a_dir,
436  0,
437  strrpos($a_dir, "/") - strlen($a_dir)
438  ))) {
439  $path = ".";
440  }
441 
442  // create directory with file permissions of parent directory
443  if (is_dir($a_dir)) {
444  return true;
445  }
446  $old_mask = umask(0000);
447  $result = @mkdir($a_dir, fileperms($path));
448  umask($old_mask);
449 
450  return $result;
451  }
452 
453  protected static function sanitateTargetPath(string $a_target): array
454  {
455  switch (true) {
456  case strpos($a_target, ILIAS_WEB_DIR . '/' . CLIENT_ID) === 0:
457  case strpos(
458  $a_target,
459  './' . ILIAS_WEB_DIR . '/' . CLIENT_ID
460  ) === 0:
461  case strpos($a_target, CLIENT_WEB_DIR) === 0:
462  $targetFilesystem = \ILIAS\FileUpload\Location::WEB;
463  break;
464  case strpos($a_target, CLIENT_DATA_DIR . "/temp") === 0:
465  $targetFilesystem = \ILIAS\FileUpload\Location::TEMPORARY;
466  break;
467  case strpos($a_target, CLIENT_DATA_DIR) === 0:
468  $targetFilesystem = \ILIAS\FileUpload\Location::STORAGE;
469  break;
470  case strpos($a_target, ILIAS_ABSOLUTE_PATH . '/Customizing') === 0:
471  $targetFilesystem = \ILIAS\FileUpload\Location::CUSTOMIZING;
472  break;
473  default:
474  throw new InvalidArgumentException(
475  "Can not move files to \"$a_target\" because path can not be mapped to web, storage or customizing location."
476  );
477  }
478 
479  $absTargetDir = dirname($a_target);
480  $targetDir = LegacyPathHelper::createRelativePath($absTargetDir);
481 
482  return [$targetFilesystem, $targetDir];
483  }
484 
504  public static function moveUploadedFile(
505  string $a_file,
506  string $a_name,
507  string $a_target,
508  bool $a_raise_errors = true,
509  string $a_mode = "move_uploaded"
510  ): bool {
511  global $DIC;
512  $main_tpl = $DIC->ui()->mainTemplate();
513  $target_filename = basename($a_target);
514 
515  $target_filename = ilFileUtils::getValidFilename($target_filename);
516 
517  // Make sure the target is in a valid subfolder. (e.g. no uploads to ilias/setup/....)
518  [$target_filesystem, $target_dir] = self::sanitateTargetPath($a_target);
519 
520  $upload = $DIC->upload();
521 
522  // If the upload has not yet been processed make sure he gets processed now.
523  if (!$upload->hasBeenProcessed()) {
524  $upload->process();
525  }
526 
527  try {
528  if (!$upload->hasUploads()) {
529  throw new ilException(
530  $DIC->language()->txt("upload_error_file_not_found")
531  );
532  }
533  $upload_result = $upload->getResults()[$a_file] ?? null;
534  if ($upload_result instanceof UploadResult) {
535  if (!$upload_result->isOK()) {
536  throw new ilException($upload_result->getStatus()->getMessage());
537  }
538  } else {
539  return false;
540  }
541  } catch (ilException $e) {
542  if (!$a_raise_errors) {
543  $main_tpl->setOnScreenMessage('failure', $e->getMessage(), true);
544  } else {
545  throw $e;
546  }
547 
548  return false;
549  }
550 
551  $upload->moveOneFileTo(
552  $upload_result,
553  $target_dir,
554  $target_filesystem,
555  $target_filename,
556  true
557  );
558 
559  return true;
560  }
561 
568  public static function zip(
569  string $a_dir,
570  string $a_file,
571  bool $compress_content = false
572  ): bool {
573  $cdir = getcwd();
574 
575  if ($compress_content) {
576  $a_dir .= "/*";
577  $pathinfo = pathinfo($a_dir);
578  chdir($pathinfo["dirname"]);
579  }
580 
581  $pathinfo = pathinfo($a_file);
582  $dir = $pathinfo["dirname"];
583  $file = $pathinfo["basename"];
584 
585  if (!$compress_content) {
586  chdir($dir);
587  }
588 
589  $zip = PATH_TO_ZIP;
590 
591  if (!$zip) {
592  chdir($cdir);
593  return false;
594  }
595 
596  if (is_array($a_dir)) {
597  $source = "";
598  foreach ($a_dir as $dir) {
599  $name = basename($dir);
601  }
602  } else {
603  $name = basename($a_dir);
604  if (trim($name) != "*") {
606  } else {
607  $source = $name;
608  }
609  }
610 
611  $zipcmd = "-r " . ilShellUtil::escapeShellArg($a_file) . " " . $source;
612  ilShellUtil::execQuoted($zip, $zipcmd);
613  chdir($cdir);
614  return true;
615  }
616 
632  public static function delDir(string $a_dir, bool $a_clean_only = false): void
633  {
634  if (!is_dir($a_dir) || is_int(strpos($a_dir, ".."))) {
635  return;
636  }
637 
638  $current_dir = opendir($a_dir);
639 
640  $files = [];
641 
642  // this extra loop has been necessary because of a strange bug
643  // at least on MacOS X. A looped readdir() didn't work
644  // correctly with larger directories
645  // when an unlink happened inside the loop. Getting all files
646  // into the memory first solved the problem.
647  while ($entryname = readdir($current_dir)) {
648  $files[] = $entryname;
649  }
650 
651  foreach ($files as $file) {
652  if (is_dir(
653  $a_dir . "/" . $file
654  ) and ($file != "." and $file != "..")) {
655  ilFileUtils::delDir($a_dir . "/" . $file);
656  } elseif ($file != "." and $file != "..") {
657  unlink($a_dir . "/" . $file);
658  }
659  }
660 
661  closedir($current_dir);
662  if (!$a_clean_only) {
663  @rmdir($a_dir);
664  }
665  }
666 
667  public static function getSafeFilename(string $a_initial_filename): string
668  {
669  $file_peaces = explode('.', $a_initial_filename);
670 
671  $file_extension = array_pop($file_peaces);
672 
673  if (SUFFIX_REPL_ADDITIONAL) {
674  $string_extensions = SUFFIX_REPL_DEFAULT . "," . SUFFIX_REPL_ADDITIONAL;
675  } else {
676  $string_extensions = SUFFIX_REPL_DEFAULT;
677  }
678 
679  $sufixes = explode(",", $string_extensions);
680 
681  if (in_array($file_extension, $sufixes)) {
682  $file_extension = "sec";
683  }
684 
685  $file_peaces[] = $file_extension;
686 
687  $safe_filename = "";
688  foreach ($file_peaces as $piece) {
689  $safe_filename .= "$piece";
690  if ($piece != end($file_peaces)) {
691  $safe_filename .= ".";
692  }
693  }
694 
695  return $safe_filename;
696  }
697 
713  public static function getDir(
714  string $a_dir,
715  bool $a_rec = false,
716  ?string $a_sub_dir = ""
717  ): array {
718  $current_dir = opendir($a_dir . $a_sub_dir);
719 
720  $dirs = [];
721  $files = [];
722  $subitems = [];
723  while ($entry = readdir($current_dir)) {
724  if (is_dir($a_dir . "/" . $entry)) {
725  $dirs[$entry] = ["type" => "dir",
726  "entry" => $entry,
727  "subdir" => $a_sub_dir
728  ];
729  if ($a_rec && $entry != "." && $entry != "..") {
730  $si = ilFileUtils::getDir(
731  $a_dir,
732  true,
733  $a_sub_dir . "/" . $entry
734  );
735  $subitems = array_merge($subitems, $si);
736  }
737  } else {
738  if ($entry != "." && $entry != "..") {
739  $size = filesize($a_dir . $a_sub_dir . "/" . $entry);
740  $files[$entry] = ["type" => "file",
741  "entry" => $entry,
742  "size" => $size,
743  "subdir" => $a_sub_dir
744  ];
745  }
746  }
747  }
748  ksort($dirs);
749  ksort($files);
750 
751  return array_merge($dirs, $files, $subitems);
752  }
753 
769  public static function getWebspaceDir(string $mode = "filesystem"): string
770  {
771  if ($mode === "filesystem") {
772  return "./" . ILIAS_WEB_DIR . "/" . CLIENT_ID;
773  } else {
774  if (defined("ILIAS_MODULE")) {
775  return "../" . ILIAS_WEB_DIR . "/" . CLIENT_ID;
776  } else {
777  return "./" . ILIAS_WEB_DIR . "/" . CLIENT_ID;
778  }
779  }
780  }
781 
794  public static function createDirectory(string $a_dir, int $a_mod = 0755): void
795  {
796  ilFileUtils::makeDir($a_dir);
797  }
798 
799  public static function getFileSizeInfo(): string
800  {
801  global $DIC;
802  $size = new DataSize(self::getUploadSizeLimitBytes(), DataSize::MB);
803  $max_filesize = $size->__toString();
804  $lng = $DIC->language();
805 
806  return $lng->txt("file_notice") . " $max_filesize.";
807  }
808 
812  public static function getASCIIFilename(string $a_filename): string
813  {
814  global $DIC;
815  $policy = new ilFileServicesPolicy($DIC->fileServiceSettings());
816  return $policy->ascii($a_filename);
817  }
818 
826  public static function ilTempnam(?string $a_temp_path = null): string
827  {
828  if ($a_temp_path === null) {
829  $temp_path = ilFileUtils::getDataDir() . "/temp";
830  } else {
831  $temp_path = $a_temp_path;
832  }
833 
834  if (!is_dir($temp_path)) {
835  ilFileUtils::createDirectory($temp_path);
836  }
837  $temp_name = $temp_path . "/" . uniqid("tmp");
838 
839  return $temp_name;
840  }
841 
842  public static function unzip(
843  string $path_to_zip_file,
844  bool $overwrite_existing = false,
845  bool $unpack_flat = false
846  ): void {
847  global $DIC;
848 
849  $sanitizer = new ilFileServicesFilenameSanitizer(
850  $DIC->fileServiceSettings()
851  );
852 
853  $log = $DIC->logger()->root();
854 
855  if (!is_file($path_to_zip_file)) {
856  return;
857  }
858 
859  // we unpack the zip always in a temp directory
860  $temporary_unzip_directory = self::ilTempnam();
861  self::makeDir($temporary_unzip_directory);
862  copy($path_to_zip_file, $temporary_unzip_directory . DIRECTORY_SEPARATOR . basename($path_to_zip_file));
863  $original_path_to_zip_file = $path_to_zip_file;
864  $path_to_zip_file = $temporary_unzip_directory . DIRECTORY_SEPARATOR . basename($path_to_zip_file);
865  $original_zip_path_info = pathinfo($original_path_to_zip_file);
866  $unzippable_zip_path_info = pathinfo($path_to_zip_file);
867 
868  $unzippable_zip_directory = $unzippable_zip_path_info["dirname"];
869  $unzippable_zip_filename = $unzippable_zip_path_info["basename"];
870 
871  // unzip
872  $current_directory = getcwd();
873  chdir($unzippable_zip_directory);
874  $unzip_command = PATH_TO_UNZIP;
875 
876  // real unzip
877  if (!$overwrite_existing) {
878  $unzip_parameters = ilShellUtil::escapeShellArg($unzippable_zip_filename);
879  } else {
880  $unzip_parameters = "-o " . ilShellUtil::escapeShellArg($unzippable_zip_filename);
881  }
882  ilShellUtil::execQuoted($unzip_command, $unzip_parameters);
883  // move back
884  chdir($current_directory);
885 
886  // remove all sym links
887  clearstatcache(); // prevent is_link from using cache
888  $dir_realpath = realpath($unzippable_zip_directory);
889  foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($unzippable_zip_directory)) as $name => $f) {
890  if (is_link($name)) {
891  $target = readlink($name);
892  if (substr($target, 0, strlen($dir_realpath)) != $dir_realpath) {
893  unlink($name);
894  $log->info("Removed symlink " . $name);
895  }
896  }
897  if (is_file($name) && $name !== $sanitizer->sanitize($name)) {
898  // rename file if it contains invalid suffix
900  rename($name, $new_name);
901  }
902  }
903 
904  // rename executables
905  self::renameExecutables($unzippable_zip_directory);
906 
907  // now we have to move the files to the original directory.
908  // if $a_flat is true, we move the files only without directories, otherwise we move the whole directory.
909  // since some provide a realtive path here, we have to get the absolute path first
910  $target_dir_name = $original_zip_path_info["dirname"];
911  $target_dir_name = realpath($target_dir_name);
912 
913  if ($unpack_flat) {
914  $file_array = [];
915  self::recursive_dirscan($temporary_unzip_directory, $file_array);
916  if (is_array($file_array["file"])) {
917  foreach ($file_array["file"] as $k => $f) {
918  if (
919  substr($f, 0, 1) !== "."
920  && $f !== basename($original_path_to_zip_file)
921  ) {
922  copy(
923  $file_array["path"][$k] . $f,
924  $target_dir_name . DIRECTORY_SEPARATOR . $f
925  );
926  }
927  }
928  }
929  } else {
930  $target_directory = $target_dir_name;
931  self::rCopy(
932  $temporary_unzip_directory,
933  $target_directory
934  );
935  }
936 
937  self::delDir($temporary_unzip_directory);
938  }
939 
943  public static function renameExecutables(string $a_dir): void
944  {
945  $def_arr = explode(",", SUFFIX_REPL_DEFAULT);
946  foreach ($def_arr as $def) {
947  self::rRenameSuffix($a_dir, trim($def), "sec");
948  }
949 
950  $def_arr = explode(",", SUFFIX_REPL_ADDITIONAL);
951  foreach ($def_arr as $def) {
952  self::rRenameSuffix($a_dir, trim($def), "sec");
953  }
954  }
955 
962  public static function rRenameSuffix(string $a_dir, string $a_old_suffix, string $a_new_suffix): bool
963  {
964  if ($a_dir === "/"
965  || $a_dir === ""
966  || strpos($a_dir, "..") !== false
967  || trim($a_old_suffix) === "") {
968  return false;
969  }
970 
971  // check if argument is directory
972  if (!@is_dir($a_dir)) {
973  return false;
974  }
975 
976  // read a_dir
977  $dir = opendir($a_dir);
978  if ($dir === false) {
979  return false;
980  }
981 
982  $prohibited = [
983  '...'
984  ];
985 
986  while ($file = readdir($dir)) {
987  if (
988  $file !== "."
989  && $file !== ".."
990  ) {
991  // triple dot is not allowed in filenames
992  if (in_array($file, $prohibited)) {
993  unlink($a_dir . "/" . $file);
994  continue;
995  }
996 
997  // directories
998  if (@is_dir($a_dir . "/" . $file)) {
999  self::rRenameSuffix($a_dir . "/" . $file, $a_old_suffix, $a_new_suffix);
1000  }
1001 
1002  // files
1003  if (@is_file($a_dir . "/" . $file)) {
1004  // first check for files with trailing dot
1005  if (strrpos($file, '.') == (strlen($file) - 1)) {
1006  try {
1007  rename($a_dir . '/' . $file, substr($a_dir . '/' . $file, 0, -1));
1008  } catch (Throwable $t) {
1009  // to avoid exploits we do delete this file and continue renaming
1010  unlink($a_dir . '/' . $file);
1011  continue;
1012  }
1013 
1014  $file = substr($file, 0, -1);
1015  }
1016 
1017  $path_info = pathinfo($a_dir . "/" . $file);
1018 
1019  if (strtolower($path_info["extension"] ?? '') === strtolower($a_old_suffix)) {
1020  $pos = strrpos($a_dir . "/" . $file, ".");
1021  $new_name = substr($a_dir . "/" . $file, 0, $pos) . "." . $a_new_suffix;
1022  // check if file exists
1023  if (file_exists($new_name)) {
1024  if (is_dir($new_name)) {
1025  self::delDir($new_name);
1026  } else {
1027  unlink($new_name);
1028  }
1029  }
1030  rename($a_dir . "/" . $file, $new_name);
1031  }
1032  }
1033  }
1034  }
1035  return true;
1036  }
1037 
1038  public static function removeTrailingPathSeparators(string $path): string
1039  {
1040  $path = preg_replace("/[\/\\\]+$/", "", $path);
1041  return (string) $path;
1042  }
1043 
1047  public static function getUploadSizeLimitBytes(): string
1048  {
1049  $convertPhpIniSizeValueToBytes = function ($phpIniSizeValue) {
1050  if (is_numeric($phpIniSizeValue)) {
1051  return $phpIniSizeValue;
1052  }
1053 
1054  $suffix = substr($phpIniSizeValue, -1);
1055  $value = substr($phpIniSizeValue, 0, -1);
1056 
1057  switch (strtoupper($suffix)) {
1058  case 'P':
1059  $value *= 1024;
1060  // no break
1061  case 'T':
1062  $value *= 1024;
1063  // no break
1064  case 'G':
1065  $value *= 1024;
1066  // no break
1067  case 'M':
1068  $value *= 1024;
1069  // no break
1070  case 'K':
1071  $value *= 1024;
1072  break;
1073  }
1074 
1075  return $value;
1076  };
1077 
1078 
1079  $uploadSizeLimitBytes = min(
1080  $convertPhpIniSizeValueToBytes(ini_get('post_max_size')),
1081  $convertPhpIniSizeValueToBytes(ini_get('upload_max_filesize'))
1082  );
1083 
1084  return $uploadSizeLimitBytes;
1085  }
1086 
1087  public static function _sanitizeFilemame(string $a_filename): string
1088  {
1089  return strip_tags(ilUtil::stripSlashes($a_filename));
1090  }
1091 }
static getWebspaceDir(string $mode="filesystem")
get webspace directory
Class ilFileServicesPolicy.
const STORAGE
The filesystem outside of the ilias web root.
Definition: Location.php:40
$lng
static utf8_encode(string $string)
utf8-encodes string if it is not a valid utf8-string.
Class ChatMainBarProvider .
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static processZipFile(string $a_directory, string $a_file, bool $structure)
static virusHandling(string $a_file, string $a_orig_name='', bool $a_clean=true)
This class provides the data size with additional information to remove the work to calculate the siz...
Definition: DataSize.php:30
static rCopy(string $a_sdir, string $a_tdir, bool $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
static getValidFilename(string $a_filename)
static rRenameSuffix(string $a_dir, string $a_old_suffix, string $a_new_suffix)
Renames all files with certain suffix and gives them a new suffix.
static escapeShellArg(string $a_arg)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static getUploadSizeLimitBytes()
$path
Definition: ltiservices.php:32
static removeTrailingPathSeparators(string $path)
static unzip(string $path_to_zip_file, bool $overwrite_existing=false, bool $unpack_flat=false)
static getSafeFilename(string $a_initial_filename)
static getASCIIFilename(string $a_filename)
global $DIC
Definition: feed.php:28
static renameExecutables(string $a_dir)
if($format !==null) $name
Definition: metadata.php:247
const CLIENT_DATA_DIR
Definition: constants.php:46
static recursive_dirscan(string $dir, array &$arr)
Recursively scans a given directory and writes path and filename into referenced array.
static dirsize(string $directory)
get size of a directory or a file.
$log
Definition: result.php:33
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
const CLIENT_ID
Definition: constants.php:41
static createDirectory(string $a_dir, int $a_mod=0755)
create directory
string $key
Consumer key/client ID value.
Definition: System.php:193
const CUSTOMIZING
The filesystem within the web root where all the skins and plugins are saved.
Definition: Location.php:45
static getDir(string $a_dir, bool $a_rec=false, ?string $a_sub_dir="")
get directory
const CLIENT_WEB_DIR
Definition: constants.php:47
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
static getDataDir()
get data directory (outside webspace)
static getFileSizeInfo()
static sanitateTargetPath(string $a_target)
static execQuoted(string $cmd, ?string $args=null)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _sanitizeFilemame(string $a_filename)
Class ilFileServicesFilenameSanitizer.
static ilTempnam(?string $a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
static zip(string $a_dir, string $a_file, bool $compress_content=false)
zips given directory/file into given zip.file
const TEMPORARY
The ILIAS temporary directory.
Definition: Location.php:50
static rename(string $a_source, string $a_target)
$source
Definition: metadata.php:93
Class FlySystemFileAccessTest disabled disabled disabled.
const WEB
The filesystem within the ilias web root.
Definition: Location.php:35
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
const ILIAS_WEB_DIR
Definition: constants.php:45