ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
class.ilObjFileDAV.php
Go to the documentation of this file.
1<?php
2
5
6require_once 'Modules/File/classes/class.ilObjFile.php';
7
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}
$path
Definition: aliased.php:25
An exception for terminatinating execution or to throw for unit testing.
This exception indicates that an UI component was accepted by the JF but is not backed by a real impl...
Main Exception class.
Definition: Exception.php:18
static getValidFilename($a_filename)
Get valid filename.
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.
static getLogger($a_component_id)
Get component logger.
static lookupMimeType($path_to_file, $fallback=self::APPLICATION__OCTET_STREAM, $a_external=null)
Class ilObjFileDAV.
getSize()
Returns the size of the node, in bytes.
fileUploadWithString(string $a_data, string $file_dest_path)
Write given data (as string) to the given file.
getName()
Returns title of file object.
handleFileUpload($a_data)
Handle uploaded file.
put($data)
Replaces the contents of the file.
setObjValuesForNewFileVersion()
Set object values for a new file version.
__construct(ilObjFile $a_obj, ilWebDAVRepositoryHelper $repo_helper, ilWebDAVObjDAVHelper $dav_helper)
ilObjFileDAV represents the WebDAV-Interface to an ILIAS-Object
getContentType()
Returns the mime-type for a file.
createHistoryAndNotificationForObjUpdate()
Create history entry and a news notification for file object update.
checkForVirus(string $file_dest_path)
getETag()
Returns the ETag for a file.
getPathToFile()
This method is called in 2 use cases:
fileUploadWithStream($a_data, string $file_dest_path)
Write given data (as Resource) to the given file.
Class ilObjFile.
Class ilObjectDAV.
static virusHandling($a_file, $a_orig_name="", $a_clean=true)
scan file for viruses and clean files if possible
static makeDirParents($a_dir)
Create a new directory and all parent directories.
Class ilWebDAVObjDAVHelper.
Class ilWebDAVRepositoryHelper.
This interface represents a file in the directory tree.
Definition: IFile.php:16
$data
Definition: bench.php:6