ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilFileSystemGUI.php
Go to the documentation of this file.
1 <?php
23 
26 
33 {
34  use SecureString; // This is just for those legacy classes which will be removed soon anyway.
35  public const PARAMETER_CDIR = "cdir";
36  public const SESSION_LAST_COMMAND = "fsys_lastcomm";
37  public const PARAMETER_NEWDIR = "newdir";
38  public const PARAMETER_FHSH = "fhsh";
39  public const POST_PARAM_FILE = "file";
40  public const PARAM_RESETOFFSET = "resetoffset";
41  public const PARAM_OLD_NAME = "old_name";
42  public const PARAM_UPFILE = "upfile";
43  public const POST_PARAM_NEW_NAME = "new_name";
44  public const POST_PARAM_NEW_DIR = "new_dir";
45  public const POST_PARAM_UPLOADED_FILE = "uploaded_file";
46  public const CMD_UNZIP_FILE = "unzipFile";
47  private \ILIAS\UI\Factory $ui_factory;
48  private \ILIAS\UI\Renderer $ui_renderer;
49  protected \ILIAS\Filesystem\Util\Archive\LegacyArchives $unzip;
51  protected bool $use_upload_directory = false;
52  protected array $allowed_suffixes = [];
53  protected array $forbidden_suffixes = [];
54  protected ilLanguage $lng;
55  protected string $main_absolute_dir;
56  protected bool $post_dir_path = false;
58  protected array $file_labels = [];
59  protected bool $label_enable = false;
60  protected bool $allow_directories = true;
61  protected string $table_id = '';
62  protected string $title = '';
63  protected array $commands = [];
64  protected string $label_header = '';
65  protected bool $directory_creation = false;
66  protected bool $file_creation = false;
67  protected \ILIAS\HTTP\Wrapper\WrapperFactory $wrapper;
68  protected \ILIAS\Refinery\Factory $refinery;
69 
73  public function __construct(string $main_absolute_directory)
74  {
75  global $DIC;
76 
77  $this->ctrl = $DIC->ctrl();
78  $this->lng = $DIC->language();
79  $this->tpl = $DIC->ui()->mainTemplate();
80  $this->wrapper = $DIC->http()->wrapper();
81  $this->refinery = $DIC->refinery();
82  $this->main_absolute_dir = realpath($main_absolute_directory);
83  $this->ui_factory = $DIC->ui()->factory();
84  $this->ui_renderer = $DIC->ui()->renderer();
85  $this->unzip = $DIC->legacyArchives();
86 
87  $this->defineCommands();
88 
89  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
90  $this->lng->loadLanguageModule("content");
91  $this->setAllowDirectories(true);
92  $this->setAllowDirectoryCreation(true);
93  $this->setAllowFileCreation(true);
94  }
95 
99  public function setAllowedSuffixes(array $a_suffixes): void
100  {
101  $this->allowed_suffixes = $a_suffixes;
102  }
103 
107  public function getAllowedSuffixes(): array
108  {
110  }
111 
115  public function setForbiddenSuffixes(array $a_suffixes): void
116  {
117  $this->forbidden_suffixes = $a_suffixes;
118  }
119 
123  public function getForbiddenSuffixes(): array
124  {
126  }
127 
128  public function isValidSuffix(string $a_suffix): bool
129  {
130  if (empty($a_suffix)) {
131  return true;
132  }
133 
134  if (is_array($this->getForbiddenSuffixes()) && in_array($a_suffix, $this->getForbiddenSuffixes())) {
135  return false;
136  }
137  if (is_array($this->getAllowedSuffixes()) && in_array($a_suffix, $this->getAllowedSuffixes())) {
138  return true;
139  }
140  if (!is_array($this->getAllowedSuffixes()) || count($this->getAllowedSuffixes()) == 0) {
141  return true;
142  }
143  return false;
144  }
145 
146  public function setAllowDirectories(bool $a_val): void
147  {
148  $this->allow_directories = $a_val;
149  }
150 
151  public function getAllowDirectories(): bool
152  {
154  }
155 
156  public function setPostDirPath(bool $a_val): void
157  {
158  $this->post_dir_path = $a_val;
159  }
160 
161  public function getPostDirPath(): bool
162  {
163  return $this->post_dir_path;
164  }
165 
166  public function setTableId(string $a_val): void
167  {
168  $this->table_id = $a_val;
169  }
170 
171  public function getTableId(): string
172  {
173  return $this->table_id;
174  }
175 
176  public function setTitle(string $a_val): void
177  {
178  $this->title = $a_val;
179  }
180 
181  public function getTitle(): string
182  {
183  return $this->title;
184  }
185 
186  public function setUseUploadDirectory(bool $a_val): void
187  {
188  $this->use_upload_directory = $a_val;
189  }
190 
191  public function getUseUploadDirectory(): bool
192  {
194  }
195 
201  protected function setPerformedCommand($command, array $pars = []): void
202  {
203  if (!is_array($pars)) {
204  $pars = [];
205  }
206  ilSession::set(self::SESSION_LAST_COMMAND, array_merge(
207  ["cmd" => $command],
208  $pars
209  ));
210  }
211 
215  public function getLastPerformedCommand(): array
216  {
217  if (!ilSession::has(self::SESSION_LAST_COMMAND)) {
218  return [];
219  }
220  $ret = ilSession::get(self::SESSION_LAST_COMMAND);
221  ilSession::set(self::SESSION_LAST_COMMAND, null);
222  return (array) $ret;
223  }
224 
225  public function executeCommand(): string
226  {
227  $next_class = $this->ctrl->getNextClass($this);
228  $cmd = $this->ctrl->getCmd("listFiles");
229  if (substr($cmd, 0, 11) == "extCommand_") {
230  $ret = $this->extCommand(substr($cmd, 11, strlen($cmd) - 11));
231  } else {
232  $ret = $this->$cmd();
233  }
234 
235  return $ret ?? '';
236  }
237 
238  public function addCommand(
239  object $a_obj,
240  string $a_func,
241  string $a_name,
242  bool $a_single = true,
243  bool $a_allow_dir = false
244  ): void {
245  $i = count($this->commands);
246 
247  $this->commands[$i]["object"] = $a_obj;
248  $this->commands[$i]["method"] = $a_func;
249  $this->commands[$i]["name"] = $a_name;
250  $this->commands[$i]["single"] = $a_single;
251  $this->commands[$i]["allow_dir"] = $a_allow_dir;
252  }
253 
254  public function clearCommands(): void
255  {
256  $this->commands = [];
257  }
258 
259  public function labelFile(string $a_file, string $a_label): void
260  {
261  $this->file_labels[$a_file][] = $a_label;
262  }
263 
264  public function activateLabels(bool $a_act, string $a_label_header): void
265  {
266  $this->label_enable = $a_act;
267  $this->label_header = $a_label_header;
268  }
269 
273  protected function parseCurrentDirectory(): array
274  {
275  // determine directory
276  // FIXME: I have to call stripSlashes here twice, because I could not
277  // determine where the second layer of slashes is added to the
278  // URL Parameter
279 
280  $cur_subdir = $this->wrapper->query()->has(self::PARAMETER_CDIR)
281  ? $this->wrapper->query()->retrieve(self::PARAMETER_CDIR, $this->refinery->to()->string())
282  : '';
283 
284  $new_subdir = $this->wrapper->query()->has(self::PARAMETER_NEWDIR)
285  ? $this->wrapper->query()->retrieve(self::PARAMETER_NEWDIR, $this->refinery->to()->string())
286  : '';
287 
288  $cur_subdir = ilUtil::stripSlashes(ilUtil::stripSlashes($cur_subdir));
289  $new_subdir = ilUtil::stripSlashes(ilUtil::stripSlashes($new_subdir));
290 
291  if ($new_subdir === "..") {
292  $cur_subdir = substr($cur_subdir, 0, strrpos($cur_subdir, "/"));
293  } else {
294  if (!empty($new_subdir)) {
295  if (!empty($cur_subdir)) {
296  $cur_subdir = $cur_subdir . "/" . $new_subdir;
297  } else {
298  $cur_subdir = $new_subdir;
299  }
300  }
301  }
302 
303  $cur_subdir = str_replace("..", "", $cur_subdir);
304  $cur_dir = (!empty($cur_subdir))
305  ? $this->main_absolute_dir . "/" . $cur_subdir
306  : $this->main_absolute_dir;
307 
308  return [
309  "dir" => realpath($cur_dir),
310  "subdir" => $cur_subdir
311  ];
312  }
313 
317  protected function getFileList(string $a_dir, ?string $a_subdir = null): array
318  {
319  $items = [];
320 
321  $entries = (is_dir($a_dir))
322  ? ilFileUtils::getDir($a_dir)
323  : array(array("type" => "dir", "entry" => ".."));
324 
325  $items = array();
326  foreach ($entries as $e) {
327  if (($e["entry"] == ".") ||
328  ($e["entry"] == ".." && empty($a_subdir))) {
329  continue;
330  }
331 
332  $cfile = (!empty($a_subdir))
333  ? $a_subdir . "/" . $e["entry"]
334  : $e["entry"];
335 
336  $items[] = array(
337  self::POST_PARAM_FILE => $cfile,
338  "entry" => $e["entry"],
339  "type" => $e["type"],
340  "size" => $e["size"] ?? 0,
341  "hash" => md5($e["entry"])
342  );
343  }
344 
345  return $items;
346  }
347 
351  protected function getIncomingFiles(): array
352  {
353  $sel_files = $hashes = [];
354  if ($this->wrapper->post()->has(self::POST_PARAM_FILE)) {
355  $hashes = $this->wrapper->post()->retrieve(
356  self::POST_PARAM_FILE,
357  $this->refinery->to()->listOf(
358  $this->refinery->to()->string()
359  )
360  );
361  } elseif ($this->wrapper->query()->has(self::PARAMETER_FHSH)) {
362  $hashes = [$this->wrapper->query()->retrieve(
363  self::PARAMETER_FHSH,
364  $this->refinery->to()->string()
365  )
366  ];
367  }
368 
369  if (count($hashes) > 0) {
370  $dir = $this->parseCurrentDirectory();
371  $all_files = $this->getFileList($dir["dir"], $dir["subdir"]);
372  foreach ($hashes as $hash) {
373  foreach ($all_files as $file) {
374  if ($file["hash"] == $hash) {
375  $sel_files[] = $this->getPostDirPath()
376  ? $file[self::POST_PARAM_FILE]
377  : $file["entry"];
378  break;
379  }
380  }
381  }
382  }
383 
384  return $sel_files;
385  }
386 
387  private function extCommand(int $a_nr): string
388  {
389  $selected = $this->getIncomingFiles();
390 
391  if (!count($selected)) {
392  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("no_checkbox"), true);
393  $this->ctrl->redirect($this, "listFiles");
394  }
395 
396  // check if only one item is select, if command does not allow multiple selection
397  if (count($selected) > 1 && ($this->commands[$a_nr]["single"] ?? false)) {
398  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("cont_select_max_one_item"), true);
399  $this->ctrl->redirect($this, "listFiles");
400  }
401 
402  $cur_subdir = $this->sanitizeCurrentDirectory();
403 
404  // collect files and
405  $files = array();
406  foreach ($selected as $file) {
407  $file = ilUtil::stripSlashes($file);
408  $file = (!empty($cur_subdir))
409  ? $cur_subdir . "/" . $file
410  : $file;
411 
412  // check wether selected item is a directory
413  if (is_dir($this->main_absolute_dir . "/" . $file) &&
414  !$this->commands[$a_nr]["allow_dir"]) {
415  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("select_a_file"), true);
416  $this->ctrl->redirect($this, "listFiles");
417  }
418 
419  $files[] = $file;
420  }
421 
422  if ($this->commands[$a_nr]["single"] ?? false) {
423  $files = array_shift($files);
424  }
425 
426  $obj = $this->commands[$a_nr]["object"];
427  $method = $this->commands[$a_nr]["method"];
428 
429  return (string) $obj->$method($files);
430  }
431 
432  public function setAllowDirectoryCreation(bool $a_val): void
433  {
434  $this->directory_creation = $a_val;
435  }
436 
437  public function getAllowDirectoryCreation(): bool
438  {
440  }
441 
445  public function setAllowFileCreation(bool $a_val): void
446  {
447  $this->file_creation = $a_val;
448  }
449 
450  public function getAllowFileCreation(): bool
451  {
452  return $this->file_creation;
453  }
454 
455  public function listFiles(?ilTable2GUI $a_table_gui = null): void
456  {
457  global $DIC;
458  $ilToolbar = $DIC['ilToolbar'];
459  $lng = $DIC['lng'];
460  $ilCtrl = $DIC['ilCtrl'];
461 
462  $dir = $this->parseCurrentDirectory();
463 
464  $this->ctrl->setParameter($this, self::PARAMETER_CDIR, $dir["subdir"]);
465 
466  // toolbar for adding files/directories
467  $ilToolbar->setFormAction($ilCtrl->getFormAction($this), true);
468 
469  if ($this->getAllowDirectories() && $this->getAllowDirectoryCreation()) {
470  $ti = new ilTextInputGUI($this->lng->txt("cont_new_dir"), self::POST_PARAM_NEW_DIR);
471  $ti->setMaxLength(80);
472  $ti->setSize(10);
473  $ilToolbar->addInputItem($ti, true);
474  $ilToolbar->addFormButton($lng->txt("create"), "createDirectory");
475 
476  $ilToolbar->addSeparator();
477  }
478  if ($this->getAllowFileCreation()) {
479  $fi = new ilFileInputGUI($this->lng->txt("cont_new_file"), "new_file");
480  $fi->setSize(10);
481  $ilToolbar->addInputItem($fi, true);
482  $ilToolbar->addFormButton($lng->txt("upload"), "uploadFile");
483  }
485  $ilToolbar->addSeparator();
487  $options[""] = $lng->txt("cont_select_from_upload_dir");
488  foreach ($files as $file) {
489  $file = htmlspecialchars($file, ENT_QUOTES, "utf-8");
490  $options[$file] = $file;
491  }
492  $si = new ilSelectInputGUI($this->lng->txt("cont_uploaded_file"), self::POST_PARAM_UPLOADED_FILE);
493  $si->setOptions($options);
494  $ilToolbar->addInputItem($si, true);
495  $ilToolbar->addFormButton($lng->txt("copy"), "uploadFile");
496  }
497 
498  $fs_table = $this->getTable($dir["dir"], $dir["subdir"]);
499 
500  if ($this->getTitle() != "") {
501  $fs_table->setTitle($this->getTitle());
502  }
503  if (
504  $this->wrapper->query()->has(self::PARAM_RESETOFFSET)
505  && $this->wrapper->query()->retrieve(
506  self::PARAM_RESETOFFSET,
507  $this->refinery->kindlyTo()->int()
508  ) == 1) {
509  $fs_table->resetOffset();
510  }
511  $this->tpl->setContent($fs_table->getHTML());
512  }
513 
514  public function getTable(string $a_dir, string $a_subdir): \ilFileSystemTableGUI
515  {
516  return new ilFileSystemTableGUI(
517  $this,
518  "listFiles",
519  $a_dir,
520  $a_subdir,
521  $this->label_enable,
522  $this->file_labels,
523  $this->label_header,
524  $this->commands,
525  $this->getPostDirPath(),
526  $this->getTableId()
527  );
528  }
529 
530  public function renameFileForm(string $a_file): void
531  {
532  $cur_subdir = $this->sanitizeCurrentDirectory();
533  $file = $this->main_absolute_dir . "/" . $a_file;
534 
535  $this->ctrl->setParameter($this, self::PARAM_OLD_NAME, basename($a_file));
536  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
537  $form = new ilPropertyFormGUI();
538 
539  // file/dir name
540  $ti = new ilTextInputGUI($this->lng->txt("name"), self::POST_PARAM_NEW_NAME);
541  $ti->setMaxLength(200);
542  $ti->setSize(40);
543  $ti->setValue(basename($a_file));
544  $form->addItem($ti);
545 
546  // save and cancel commands
547  $form->addCommandButton("renameFile", $this->lng->txt("rename"));
548  $form->addCommandButton("cancelRename", $this->lng->txt("cancel"));
549  $form->setFormAction($this->ctrl->getFormAction($this, "renameFile"));
550 
551  if (is_dir($file)) {
552  $form->setTitle($this->lng->txt("cont_rename_dir"));
553  } else {
554  $form->setTitle($this->lng->txt("rename_file"));
555  }
556 
557  $this->tpl->setContent($form->getHTML());
558  }
559 
560  public function renameFile(): void
561  {
562  $new_name = $this->wrapper->post()->has(self::POST_PARAM_NEW_NAME)
563  ? $this->wrapper->post()->retrieve(self::POST_PARAM_NEW_NAME, $this->refinery->to()->string())
564  : '';
565 
566  $new_name = str_replace("..", "", ilUtil::stripSlashes($new_name));
567  $new_name = str_replace("/", "", $new_name);
568  if ($new_name === "") {
569  throw new LogicException($this->lng->txt("enter_new_name"));
570  }
571 
572  $pi = pathinfo($new_name);
573  $suffix = $pi["extension"] ?? "";
574  if ($suffix != "" && !$this->isValidSuffix($suffix)) {
575  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("file_no_valid_file_type") . " ($suffix)", true);
576  $this->ctrl->redirect($this, "listFiles");
577  }
578 
579  $cur_subdir = $this->sanitizeCurrentDirectory();
580  $dir = (!empty($cur_subdir))
581  ? $this->main_absolute_dir . "/" . $cur_subdir . "/"
582  : $this->main_absolute_dir . "/";
583 
584  $old_name = $this->wrapper->query()->has(self::PARAM_OLD_NAME)
585  ? $this->wrapper->query()->retrieve(self::PARAM_OLD_NAME, $this->refinery->to()->string())
586  : null;
587 
588  // check if this path is inside $dir
589  $old_name = ilUtil::stripSlashes($old_name);
590  $realpath = realpath($dir . $old_name);
591  if (strpos($realpath, realpath($dir)) !== 0) {
592  throw new ilException($this->lng->txt("no_permission"));
593  }
594 
595  if (is_dir($dir . $old_name)) {
596  rename($dir . $old_name, $dir . $new_name);
597  } else {
598  try {
599  ilFileUtils::rename($dir . $old_name, $dir . $new_name);
600  } catch (ilException $e) {
601  $this->tpl->setOnScreenMessage('failure', $e->getMessage(), true);
602  $this->ctrl->redirect($this, "listFiles");
603  }
604  }
605 
606  ilFileUtils::renameExecutables($this->main_absolute_dir);
607  if (is_dir($dir . $new_name)) {
608  $this->tpl->setOnScreenMessage(
609  'success',
610  $this->lng->txt("cont_dir_renamed"),
611  true
612  );
613  $this->setPerformedCommand("rename_dir", [self::PARAM_OLD_NAME => $old_name,
614  self::POST_PARAM_NEW_NAME => $new_name
615  ]);
616  } else {
617  $this->tpl->setOnScreenMessage(
618  'success',
619  $this->lng->txt("cont_file_renamed"),
620  true
621  );
622  $this->setPerformedCommand("rename_file", array(self::PARAM_OLD_NAME => $old_name,
623  self::POST_PARAM_NEW_NAME => $new_name
624  ));
625  }
626  $this->ctrl->redirect($this, "listFiles");
627  }
628 
629  public function cancelRename(): void
630  {
631  $this->ctrl->redirect($this, "listFiles");
632  }
633 
634  public function createDirectory(): void
635  {
636  global $DIC;
637  $lng = $DIC['lng'];
638 
639  // determine directory
640  $cur_subdir = $this->sanitizeCurrentDirectory();
641  $cur_dir = (!empty($cur_subdir))
642  ? $this->main_absolute_dir . "/" . $cur_subdir
643  : $this->main_absolute_dir;
644 
645  $new_dir = $this->wrapper->post()->has(self::POST_PARAM_NEW_DIR)
646  ? $this->wrapper->post()->retrieve(self::POST_PARAM_NEW_DIR, $this->refinery->to()->string())
647  : '';
648 
649  $new_dir = str_replace(".", "", ilUtil::stripSlashes($new_dir));
650  $new_dir = str_replace("/", "", $new_dir);
651 
652  if (!empty($new_dir)) {
653  ilFileUtils::makeDir($cur_dir . "/" . $new_dir);
654  if (is_dir($cur_dir . "/" . $new_dir)) {
655  $this->tpl->setOnScreenMessage('success', $lng->txt("cont_dir_created"), true);
656  $this->setPerformedCommand("create_dir", array("name" => $new_dir));
657  }
658  } else {
659  $this->tpl->setOnScreenMessage('failure', $lng->txt("cont_enter_a_dir_name"), true);
660  }
661  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
662  $this->ctrl->redirect($this, 'listFiles');
663  }
664 
665  public function uploadFile(): void
666  {
667  global $DIC;
668  $lng = $DIC['lng'];
669 
670  // determine directory
671  $cur_subdir = $this->sanitizeCurrentDirectory();
672  $cur_dir = (!empty($cur_subdir))
673  ? $this->main_absolute_dir . "/" . $cur_subdir
674  : $this->main_absolute_dir;
675 
676  $tgt_file = null;
677 
678  $pi = pathinfo($_FILES["new_file"]["name"]);
679  $suffix = $pi["extension"] ?? "";
680  if (!$this->isValidSuffix($suffix)) {
681  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("file_no_valid_file_type") . " ($suffix)", true);
682  $this->ctrl->redirect($this, "listFiles");
683  }
684 
685  $uploaded_file = $this->wrapper->post()->has(self::POST_PARAM_UPLOADED_FILE)
686  ? $this->wrapper->post()->retrieve(self::POST_PARAM_UPLOADED_FILE, $this->refinery->to()->string())
687  : '';
688  if (is_file($_FILES["new_file"]["tmp_name"])) {
689  $name = $this->secure(ilUtil::stripSlashes($_FILES["new_file"]["name"]));
690  $tgt_file = $cur_dir . "/" . $name;
691 
692  // use filesystem directly
693  //ilFileUtils::moveUploadedFile(, $name, $tgt_file);
694  $upload = $DIC->upload();
695 
696  // If the upload has not yet been processed make sure he gets processed now.
697  if (!$upload->hasBeenProcessed()) {
698  $upload->process();
699  }
700 
701 
702  if (!$upload->hasUploads()) {
703  throw new ilException(
704  $DIC->language()->txt("upload_error_file_not_found")
705  );
706  }
707  $upload_result = $upload->getResults()[$_FILES["new_file"]["tmp_name"]];
708  if ($upload_result instanceof UploadResult) {
709  $processing_status = $upload_result->getStatus();
710  if ($processing_status->getCode() === ProcessingStatus::REJECTED) {
711  $this->tpl->setOnScreenMessage(
712  'failure',
713  $processing_status->getMessage(),
714  true
715  );
716  $this->ctrl->redirect($this, "listFiles");
717  }
718  }
719 
720  $upload->moveOneFileTo(
721  $upload_result,
722  LegacyPathHelper::createRelativePath($cur_dir . "/"),
723  LegacyPathHelper::deriveLocationFrom($cur_dir),
724  $name,
725  true
726  );
727  // end upload
728  } elseif ($uploaded_file) {
729  // check if the file is in the ftp directory and readable
730  if (ilUploadFiles::_checkUploadFile($uploaded_file)) {
731  $tgt_file = $cur_dir . "/" . ilUtil::stripSlashes($uploaded_file);
732 
733  // copy uploaded file to data directory
734  ilUploadFiles::_copyUploadFile($uploaded_file, $tgt_file);
735  }
736  } elseif (trim($_FILES["new_file"]["name"]) == "") {
737  $this->tpl->setOnScreenMessage('failure', $lng->txt("cont_enter_a_file"), true);
738  }
739 
740  if ($tgt_file && is_file($tgt_file)) {
741  $unzip = null;
742  if (MimeType::getMimeType($tgt_file) == "application/zip") {
743  $this->ctrl->setParameter($this, self::PARAM_UPFILE, basename($tgt_file));
744  $url = $this->ctrl->getLinkTarget($this, self::CMD_UNZIP_FILE);
745  $this->ctrl->setParameter($this, self::PARAM_UPFILE, "");
746 
747  $unzip_link = $this->ui_factory->link()->standard(
748  $this->lng->txt("unzip"),
749  $url
750  );
751 
752  $unzip = " " . $this->ui_renderer->render($unzip_link);
753  }
754 
755  $this->tpl->setOnScreenMessage('success', $lng->txt("cont_file_created") . $unzip, true);
756 
757  $this->setPerformedCommand(
758  "create_file",
759  array("name" => substr($tgt_file, strlen($this->main_absolute_dir) + 1))
760  );
761  }
762 
763  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
764 
765  ilFileUtils::renameExecutables($this->main_absolute_dir);
766 
767  $this->ctrl->redirect($this, 'listFiles');
768  }
769 
770  public function confirmDeleteFile(array $a_files): void
771  {
772  global $DIC;
773  $ilCtrl = $DIC['ilCtrl'];
774  $tpl = $DIC['tpl'];
775  $lng = $DIC['lng'];
776 
777  $cgui = new ilConfirmationGUI();
778  $cgui->setFormAction($ilCtrl->getFormAction($this));
779  $cgui->setHeaderText($lng->txt("info_delete_sure"));
780  $cgui->setCancel($lng->txt("cancel"), "listFiles");
781  $cgui->setConfirm($lng->txt("delete"), "deleteFile");
782 
783  foreach ($a_files as $i) {
784  $cgui->addItem("file[]", $i, $i);
785  }
786 
787  $tpl->setContent($cgui->getHTML());
788  }
789 
790  public function deleteFile(): void
791  {
792  if (!$this->wrapper->post()->has(self::POST_PARAM_FILE)) {
793  throw new LogicException($this->lng->txt("no_checkbox"));
794  }
795  $is_dir = false;
796  $post_file = null;
797 
798  $postfiles = $this->wrapper->post()->retrieve(
799  self::POST_PARAM_FILE,
800  $this->refinery->to()->listOf(
801  $this->refinery->to()->string()
802  )
803  );
804  foreach ($postfiles as $post_file) {
805  if (ilUtil::stripSlashes($post_file) == "..") {
806  throw new LogicException($this->lng->txt("no_checkbox"));
807  break;
808  }
809 
810  $cur_subdir = $this->sanitizeCurrentDirectory();
811  $cur_dir = (!empty($cur_subdir))
812  ? $this->main_absolute_dir . "/" . $cur_subdir
813  : $this->main_absolute_dir;
814  $pi = pathinfo($post_file);
815  $file = $cur_dir . "/" . ilUtil::stripSlashes($pi["basename"]);
816 
817  if (is_file($file)) {
818  unlink($file);
819  }
820 
821  if (is_dir($file)) {
822  $is_dir = true;
823  ilFileUtils::delDir($file);
824  }
825  }
826 
827  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
828  if ($is_dir) {
829  $this->tpl->setOnScreenMessage('success', $this->lng->txt("cont_dir_deleted"), true);
830  $this->setPerformedCommand(
831  "delete_dir",
832  array("name" => ilUtil::stripSlashes($post_file))
833  );
834  } else {
835  $this->tpl->setOnScreenMessage('success', $this->lng->txt("cont_file_deleted"), true);
836  $this->setPerformedCommand(
837  "delete_file",
838  array("name" => ilUtil::stripSlashes($post_file))
839  );
840  }
841  $this->ctrl->redirect($this, 'listFiles');
842  }
843 
844  public function unzipFile(?string $a_file = null): void
845  {
846  // #17470 - direct unzip call (after upload)
847  $upname = $this->wrapper->query()->has(self::PARAM_UPFILE)
848  ? $this->wrapper->query()->retrieve(self::PARAM_UPFILE, $this->refinery->to()->string())
849  : null;
850  if (is_null($a_file) && $upname !== null) {
851  $a_file = basename($upname);
852  }
853 
854  $cur_subdir = $this->sanitizeCurrentDirectory();
855  $cur_dir = (!empty($cur_subdir))
856  ? $this->main_absolute_dir . "/" . $cur_subdir
857  : $this->main_absolute_dir;
858  $a_file = $this->main_absolute_dir . "/" . $a_file;
859 
860  if (is_file($a_file)) {
861  $cur_files = array_keys(ilFileUtils::getDir($cur_dir));
862  $cur_files_r = iterator_to_array(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cur_dir)));
863 
864  $this->unzip->unzip(
865  $a_file,
866  null,
867  true,
868  !$this->getAllowDirectories(),
869  false
870  );
871 
872  $new_files = array_keys(ilFileUtils::getDir($cur_dir));
873  $new_files_r = iterator_to_array(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cur_dir)));
874 
875  $diff = array_diff($new_files, $cur_files);
876  $diff_r = array_diff($new_files_r, $cur_files_r);
877 
878  // unlink forbidden file types
879  foreach ($diff_r as $f => $d) {
880  $pi = pathinfo($f);
881  if (!is_dir($f) && !$this->isValidSuffix(strtolower($pi["extension"] ?? ''))) {
882  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("file_some_invalid_file_types_removed") . " (" . $pi["extension"] . ")", true);
883  unlink($f);
884  }
885  }
886 
887  if (sizeof($diff)) {
888  if ($this->getAllowDirectories()) {
889  $new_files = array();
890 
891  foreach ($diff as $new_item) {
892  if (is_dir($cur_dir . "/" . $new_item)) {
893  ilFileUtils::recursive_dirscan($cur_dir . "/" . $new_item, $new_files);
894  }
895  }
896 
897  if (isset($new_files["path"])) {
898  foreach ($new_files["path"] as $idx => $path) {
899  $path = substr($path, strlen($this->main_absolute_dir) + 1);
900  $diff[] = $path . $new_files[self::POST_PARAM_FILE][$idx];
901  }
902  }
903  }
904 
905  $this->setPerformedCommand(
906  "unzip_file",
907  array("added" => $diff
908  )
909  );
910  }
911  }
912 
913  ilFileUtils::renameExecutables($this->main_absolute_dir);
914 
915  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
916  $this->tpl->setOnScreenMessage('success', $this->lng->txt("cont_file_unzipped"), true);
917  $this->ctrl->redirect($this, "listFiles");
918  }
919 
920  public function downloadFile(string $a_file): void
921  {
922  $file = $this->main_absolute_dir . "/" . $a_file;
923 
924  if (is_file($file) && !(is_dir($file))) {
925  ilFileDelivery::deliverFileLegacy($file, basename($a_file));
926  exit;
927  } else {
928  $this->ctrl->saveParameter($this, self::PARAMETER_CDIR);
929  $this->ctrl->redirect($this, "listFiles");
930  }
931  }
932 
936  public function getActionCommands(): array
937  {
938  return $this->commands;
939  }
940 
941  public function defineCommands(): void
942  {
943  $this->commands = array(
944  0 => array(
945  "object" => $this,
946  "method" => "downloadFile",
947  "name" => $this->lng->txt("download"),
948  "int" => true,
949  "single" => true
950  ),
951  1 => array(
952  "object" => $this,
953  "method" => "confirmDeleteFile",
954  "name" => $this->lng->txt("delete"),
955  "allow_dir" => true,
956  "int" => true
957  ),
958  2 => array(
959  "object" => $this,
960  "method" => self::CMD_UNZIP_FILE,
961  "name" => $this->lng->txt("unzip"),
962  "allow_dir" => true,
963  "int" => true,
964  "single" => true
965  ),
966  3 => array(
967  "object" => $this,
968  "method" => "renameFileForm",
969  "name" => $this->lng->txt("rename"),
970  "allow_dir" => true,
971  "int" => true,
972  "single" => true
973  ),
974  );
975  }
976 
977  private function sanitizeCurrentDirectory(): string
978  {
979  $cur_subdir = $this->wrapper->query()->has(self::PARAMETER_CDIR)
980  ? $this->wrapper->query()->retrieve(self::PARAMETER_CDIR, $this->refinery->to()->string())
981  : '';
982 
983  return str_replace(
984  "..",
985  "",
986  ilUtil::stripSlashes($cur_subdir)
987  );
988  }
989 }
static get(string $a_var)
activateLabels(bool $a_act, string $a_label_header)
ILIAS HTTP Wrapper WrapperFactory $wrapper
exit
Definition: login.php:29
static _copyUploadFile(string $a_file, string $a_target, bool $a_raise_errors=true)
downloadFile(string $a_file)
This class represents a selection list property in a property form.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
renameFileForm(string $a_file)
This class represents a file property in a property form.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
ilGlobalTemplateInterface $tpl
static _getUploadDirectory()
setOptions(array $a_options)
addCommand(object $a_obj, string $a_func, string $a_name, bool $a_single=true, bool $a_allow_dir=false)
setAllowDirectoryCreation(bool $a_val)
listFiles(?ilTable2GUI $a_table_gui=null)
$path
Definition: ltiservices.php:32
getTable(string $a_dir, string $a_subdir)
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
global $DIC
Definition: feed.php:28
static renameExecutables(string $a_dir)
isValidSuffix(string $a_suffix)
ILIAS Filesystem Util Archive LegacyArchives $unzip
__construct(string $main_absolute_directory)
setContent(string $a_html)
Sets content for standard template.
setAllowedSuffixes(array $a_suffixes)
static recursive_dirscan(string $dir, array &$arr)
Recursively scans a given directory and writes path and filename into referenced array.
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
setUseUploadDirectory(bool $a_val)
setAllowDirectories(bool $a_val)
$url
Definition: ltiregstart.php:35
static has($a_var)
ILIAS UI Factory $ui_factory
static getDir(string $a_dir, bool $a_rec=false, ?string $a_sub_dir="")
get directory
ilCtrlInterface $ctrl
labelFile(string $a_file, string $a_label)
getFileList(string $a_dir, ?string $a_subdir=null)
ILIAS UI Renderer $ui_renderer
static _checkUploadFile(string $a_file)
setPerformedCommand($command, array $pars=[])
setForbiddenSuffixes(array $a_suffixes)
ILIAS Refinery Factory $refinery
confirmDeleteFile(array $a_files)
static rename(string $a_source, string $a_target)
File System Explorer GUI class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static set(string $a_var, $a_val)
Set a value.
setAllowFileCreation(bool $a_val)
Set allowed file creation.
unzipFile(?string $a_file=null)
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
setTableId(string $a_val)