ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilObjFileDAV.php
Go to the documentation of this file.
1 <?php
2 
5 
6 require_once 'Modules/File/classes/class.ilObjFile.php';
7 
19 class ilObjFileDAV extends ilObjectDAV implements Sabre\DAV\IFile
20 {
26  protected $obj;
27 
39  {
40  parent::__construct($a_obj, $repo_helper, $dav_helper);
41  }
42 
65  public function put($data)
66  {
67  if ($this->repo_helper->checkAccess('write', $this->getRefId())) {
69  $this->handleFileUpload($data);
70  return $this->getETag();
71  }
72  throw new Exception\Forbidden("Permission denied. No write access for this file");
73  }
74 
83  public function get()
84  {
85  if ($this->repo_helper->checkAccess("read", $this->obj->getRefId())) {
86  $file = $this->getPathToFile();
87  if (file_exists($file)) {
88  return fopen($file, 'r');
89  } else {
90  throw new Exception\NotFound("File not found");
91  }
92  }
93 
94  throw new Exception\Forbidden("Permission denied. No read access for this file");
95  }
96 
102  public function getName()
103  {
104  return ilFileUtils::getValidFilename($this->obj->getTitle());
105  }
106 
114  public function getContentType()
115  {
116  return $this->obj->guessFileType();
117  }
118 
133  public function getETag()
134  {
135  if (file_exists($path = $this->getPathToFile())) {
136  return '"' . sha1(
137  fileinode($path) .
138  filesize($path) .
139  filemtime($path)
140  ) . '"';
141  }
142 
143  return null;
144  }
145 
151  public function getSize()
152  {
153  if (file_exists($this->getPathToFile())) {
154  return $this->obj->getFileSize();
155  }
156  return 0;
157  }
158 
163  public function setName($a_name)
164  {
165  if ($this->dav_helper->isValidFileNameWithValidFileExtension($a_name)) {
166  parent::setName($a_name);
167  } else {
168  throw new Exception\Forbidden("Invalid file extension");
169  }
170  }
171 
182  public function handleFileUpload($a_data)
183  {
184  // Set name for uploaded file because due to the versioning, the title can change for different versions. This setter-call here
185  // ensures that the uploaded file is saved with the title of the object. This obj->setFileName() has to be called
186  // before $this->getPathToFile(). Otherwise, the file could be saved under the wrong filename.
187  $this->obj->setFileName($this->getName());
188  $file_dest_path = $this->getPathToFile();
189 
190  // If dir does not exist yet -> create it
191  if (!file_exists($file_dest_path)) {
193  }
194 
195  // File upload
196  if (is_resource($a_data)) {
197  $written_length = $this->fileUploadWithStream($a_data, $file_dest_path);
198  } elseif (is_string($a_data)) {
199  $written_length = $this->fileUploadWithString($a_data, $file_dest_path);
200  } else {
201  ilLoggerFactory::getLogger('WebDAV')->warning(get_class($this) . ' ' . $this->obj->getTitle() . " -> invalid upload data sent");
202  throw new Exception\BadRequest('Invalid put data sent');
203  }
204 
205  // Security checks
206  $this->checkForVirus($file_dest_path);
207 
208  // Set last meta data
209  include_once("./Services/Utilities/classes/class.ilMimeTypeUtil.php");
210  $this->obj->setFileType(ilMimeTypeUtil::lookupMimeType($file_dest_path));
211  $this->obj->setFileSize($written_length);
212  if ($this->obj->update() && $this->obj->getMaxVersion() > 1) {
214  }
215  }
216 
225  protected function fileUploadWithStream($a_data, string $file_dest_path)
226  {
227  try {
228  $written_length = 0;
229  $write_stream = fopen($file_dest_path, 'w');
230  while (!feof($a_data)) {
231  if (false === ($written = fwrite($write_stream, fread($a_data, 4096)))) {
232  fclose($write_stream);
233  throw new Exception\Forbidden('Forbidden to write file');
234  }
235  $written_length += $written;
236  }
237  } catch (Exception $e) {
238  ilLoggerFactory::getLogger('WebDAV')->error("Error on uploading {$this->obj->getTitle()} to path $file_dest_path with message: " . $e->getMessage());
239  throw new Exception();
240  } finally {
241  fclose($write_stream);
242  }
243 
244  return $written_length;
245  }
246 
255  protected function fileUploadWithString(string $a_data, string $file_dest_path)
256  {
257  $write_stream = fopen($file_dest_path, 'w');
258  $written_length = fwrite($write_stream, $a_data);
259  fclose($write_stream);
260  if ($written_length === false && strlen($a_data) > 0) {
261  throw new Exception\Forbidden('Forbidden to write file');
262  }
263  return $written_length;
264  }
265 
266  protected function getPathToDirectory()
267  {
268  return $this->obj->getDirectory($this->obj->getVersion());
269  }
270 
280  protected function getPathToFile()
281  {
282  // ilObjFile delivers the filename like it was on the upload. But if the file-extension is forbidden, the file
283  // will be safed as .sec-file. In this case ->getFileName returns the wrong file name
284  $path = $this->getPathToDirectory() . "/" . $this->obj->getFileName();
285 
286  // For the case of forbidden file-extensions, ::getValidFilename($path) returns the path with the .sec extension
288  }
289 
290  protected function checkForVirus(string $file_dest_path)
291  {
292  $vrs = ilUtil::virusHandling($file_dest_path, '', true);
293  // If vrs[0] == false -> virus found
294  if ($vrs[0] == false) {
295  ilLoggerFactory::getLogger('WebDAV')->error(get_class($this) . ' ' . $this->obj->getTitle() . " -> virus found on '$file_dest_path'!");
296  unlink($file_dest_path);
297  $this->obj->delete();
298  throw new Exception\Forbidden('Virus found!');
299  }
300  }
301 
305  protected function setObjValuesForNewFileVersion()
306  {
307  // This is necessary for windows explorer. Because windows explorer makes always 2 PUT requests. One with a 0 Byte
308  // file to test, if the user has write permissions and the second one to upload the original file.
309  if ($this->obj->getFileSize() > 0) {
310  // Stolen from ilObjFile->addFileVersion
311  $this->obj->setVersion($this->obj->getMaxVersion() + 1);
312  $this->obj->setMaxVersion($this->obj->getMaxVersion() + 1);
313  }
314  }
315 
320  {
321  // Add history entry and notification for new file version (stolen from ilObjFile->addFileVersion)
322  ilHistory::_createEntry($this->obj->getId(), "new_version", $this->obj->getTitle() . "," . $this->obj->getVersion() . "," . $this->obj->getMaxVersion());
323  $this->obj->addNewsNotification("file_updated");
324  }
325 }
static makeDirParents($a_dir)
Create a new directory and all parent directories.
getSize()
Returns the size of the node, in bytes.
$path
Definition: aliased.php:25
Class ilObjFileDAV.
static virusHandling($a_file, $a_orig_name="", $a_clean=true)
scan file for viruses and clean files if possible
getPathToFile()
This method is called in 2 use cases:
put($data)
Replaces the contents of the file.
Class ilWebDAVRepositoryHelper.
static lookupMimeType($path_to_file, $fallback=self::APPLICATION__OCTET_STREAM, $a_external=null)
static _createEntry( $a_obj_id, $a_action, $a_info_params="", $a_obj_type="", $a_user_comment="", $a_update_last=false)
Creates a new history entry for an object.
fileUploadWithStream($a_data, string $file_dest_path)
Write given data (as Resource) to the given file.
Class ilWebDAVObjDAVHelper.
setObjValuesForNewFileVersion()
Set object values for a new file version.
createHistoryAndNotificationForObjUpdate()
Create history entry and a news notification for file object update.
handleFileUpload($a_data)
Handle uploaded file.
This interface represents a file in the directory tree.
Definition: IFile.php:16
Class ilObjectDAV.
fileUploadWithString(string $a_data, string $file_dest_path)
Write given data (as string) to the given file.
static getLogger($a_component_id)
Get component logger.
getName()
Returns title of file object.
__construct(ilObjFile $a_obj, ilWebDAVRepositoryHelper $repo_helper, ilWebDAVObjDAVHelper $dav_helper)
ilObjFileDAV represents the WebDAV-Interface to an ILIAS-Object
checkForVirus(string $file_dest_path)
getETag()
Returns the ETag for a file.
static getValidFilename($a_filename)
Get valid filename.
getContentType()
Returns the mime-type for a file.
$data
Definition: bench.php:6