ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilFileXMLParser.php
Go to the documentation of this file.
1<?php
2
3/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4
17
18include_once './Services/Xml/classes/class.ilSaxParser.php';
19include_once 'Modules/File/classes/class.ilFileException.php';
20include_once 'Services/Utilities/classes/class.ilFileUtils.php';
21
23{
24 public static $CONTENT_NOT_COMPRESSED = 0;
25 public static $CONTENT_GZ_COMPRESSED = 1;
26 public static $CONTENT_ZLIB_COMPRESSED = 2;
27 public static $CONTENT_COPY = 4;
28 // begin-patch fm
29 public static $CONTENT_REST = 5;
30 // end-patch fm
36 public $file;
43 public $obj_id;
49 public $result;
55 public $mode;
61 //var $content;
62
74 //var $content;
75
79 protected $version = null;
83 protected $action = null;
87 protected $max_version = null;
91 protected $date = null;
95 protected $usr_id = null;
99 protected $versions = [];
100
101
111 public function __construct($file, $a_xml_data, $obj_id = -1, $mode = 0)
112 {
114 $this->file = $file;
115 $this->setXMLContent($a_xml_data);
116 $this->obj_id = $obj_id;
117 $this->result = false;
118 $this->mode = $mode;
119 }
120
121
127 public function setImportDirectory($a_val)
128 {
129 $this->importDirectory = $a_val;
130 }
131
132
138 public function getImportDirectory()
139 {
140 return $this->importDirectory;
141 }
142
143
151 public function setHandlers($a_xml_parser)
152 {
153 xml_set_object($a_xml_parser, $this);
154 xml_set_element_handler($a_xml_parser, 'handlerBeginTag', 'handlerEndTag');
155 xml_set_character_data_handler($a_xml_parser, 'handlerCharacterData');
156 }
157
158
169 public function handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
170 {
171 global $DIC;
172 $ilErr = $DIC['ilErr'];
173
174 global $DIC;
175 $ilLog = $DIC['ilLog'];
176
177 switch ($a_name) {
178 case 'File':
179 if (isset($a_attribs["obj_id"])) {
180 $read_obj_id = ilUtil::__extractId($a_attribs["obj_id"], IL_INST_ID);
181 if ($this->obj_id != -1 && (int) $read_obj_id != -1 && (int) $this->obj_id != (int) $read_obj_id) {
182 throw new ilFileException(
183 "Object IDs (xml $read_obj_id and argument " . $this->obj_id . ") do not match!",
185 );
186 }
187 }
188 if (isset($a_attribs["type"])) {
189 $this->file->setFileType($a_attribs["type"]);
190 }
191 $this->file->setVersion($a_attribs["version"]); // Selected version
192 $this->file->setMaxVersion($a_attribs["max_version"]);
193 break;
194 case 'Content': // Old import files
195 case 'Version':
196 if ($a_name === "Version" && !isset($a_attribs["mode"])) {
197 // Old import files
198 $this->version = null;
199 if ($this->date === null) {
200 // Version tag comes after Content tag. Take only first (= Should be latest)
201 $this->date = $a_attribs["date"];
202 $this->usr_id = $a_attribs["usr_id"];
203 $this->versions[0]["date"] = $this->date;
204 $this->versions[0]["usr_id"] = $this->usr_id;
205 }
206 break;
207 }
208
210 $this->isReadingFile = true;
211 $this->tmpFilename = ilUtil::ilTempnam();
212 #echo $a_attribs["mode"];
213 if (isset($a_attribs["mode"])) {
214 if ($a_attribs["mode"] == "GZIP") {
215 if (!function_exists("gzread")) {
216 throw new ilFileException("Deflating with gzip is not supported", ilFileException::$ID_DEFLATE_METHOD_MISMATCH);
217 }
218
220 } elseif ($a_attribs["mode"] == "ZLIB") {
221 if (!function_exists("gzuncompress")) {
222 throw new ilFileException("Deflating with zlib (compress/uncompress) is not supported", ilFileException::$ID_DEFLATE_METHOD_MISMATCH);
223 }
224
226 } elseif ($a_attribs["mode"] == "COPY") {
227 $this->mode = ilFileXMLParser::$CONTENT_COPY;
228 } // begin-patch fm
229 elseif ($a_attribs['mode'] == 'REST') {
230 $this->mode = ilFileXMLParser::$CONTENT_REST;
231 }
232 // end-patch fm
233 }
234
235 if ($a_name === "Version") {
236 $this->version = $a_attribs["version"];
237 $this->max_version = $a_attribs["max_version"];
238 $this->date = $a_attribs["date"];
239 $this->usr_id = $a_attribs["usr_id"];
240 $this->action = $a_attribs["action"];
241 } else {
242 // Old import files
243 //$this->version = $this->file->getVersion();
244 $this->version = 1;
245 $this->file->setVersion($this->version);
246 }
247 }
248 }
249
250
257 public function handlerEndTag($a_xml_parser, $a_name)
258 {
259 $this->cdata = trim($this->cdata);
260
261 $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': ' . $this->cdata);
262
263 switch ($a_name) {
264 case 'File':
265 $this->result = true;
266 break;
267 case 'Filename':
268 if (strlen($this->cdata) == 0) {
269 throw new ilFileException("Filename ist missing!");
270 }
271
272 $this->file->setFilename($this->cdata);
273 $this->file->setTitle($this->cdata);
274
275 break;
276 case 'Title':
277 $this->file->setTitle(trim($this->cdata));
278 break;
279 case 'Description':
280 $this->file->setDescription(trim($this->cdata));
281 break;
282 case 'Rating':
283 $this->file->setRating((bool) $this->cdata);
284 break;
285 case 'Content': // Old import files
286 case 'Version':
287 if ($a_name === "Version" && $this->version === null) {
288 // Old import files
289 break;
290 }
291
292 $GLOBALS['DIC']['ilLog']->write($this->mode);
293 $this->isReadingFile = false;
294 $baseDecodedFilename = ilUtil::ilTempnam();
295 if ($this->mode == ilFileXMLParser::$CONTENT_COPY) {
296 $this->tmpFilename = $this->getImportDirectory() . "/" . self::normalizeRelativePath($this->cdata);
297 } // begin-patch fm
298 elseif ($this->mode == ilFileXMLParser::$CONTENT_REST) {
299 include_once './Services/WebServices/Rest/classes/class.ilRestFileStorage.php';
300 $storage = new ilRestFileStorage();
301 $this->tmpFilename = $storage->getStoredFilePath(self::normalizeRelativePath($this->cdata));
302 if (!ilFileUtils::fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
303 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
304 }
305 $this->tmpFilename = $baseDecodedFilename;
306 } // end-patch fm
307 else {
308 if (!ilFileUtils::fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
309 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
310 }
311 if ($this->mode == ilFileXMLParser::$CONTENT_GZ_COMPRESSED) {
312 if (!ilFileUtils::fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
313 throw new ilFileException("Deflating with fastzunzip failed", ilFileException::$DECOMPRESSION_FAILED);
314 }
315 unlink($baseDecodedFilename);
316 } elseif ($this->mode == ilFileXMLParser::$CONTENT_ZLIB_COMPRESSED) {
317 if (!ilFileUtils::fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
318 throw new ilFileException("Deflating with fastDecompress failed", ilFileException::$DECOMPRESSION_FAILED);
319 }
320 unlink($baseDecodedFilename);
321 } else {
322 $this->tmpFilename = $baseDecodedFilename;
323 }
324 }
325
326 //$this->content = $content;
327 // see #17211
328
329 if ($this->version == $this->file->getVersion()) {
330 if (is_file($this->tmpFilename)) {
331 $this->file->setFileSize(filesize($this->tmpFilename)); // strlen($this->content));
332 }
333
334 // if no file type is given => lookup mime type
335 if (!$this->file->getFileType()) {
336 global $DIC;
337 $ilLog = $DIC['ilLog'];
338
339 #$ilLog->write(__METHOD__.': Trying to detect mime type...');
340 include_once('./Services/Utilities/classes/class.ilFileUtils.php');
341 $this->file->setFileType(ilFileUtils::_lookupMimeType($this->tmpFilename));
342 }
343 }
344
345 $this->versions[] = [
346 "version" => $this->version,
347 "max_version" => $this->max_version,
348 "tmpFilename" => $this->tmpFilename,
349 "date" => $this->date,
350 "usr_id" => $this->usr_id,
351 "action" => $this->action,
352 ];
353 $this->version = null;
354 $this->date = null;
355 $this->usr_id = null;
356 break;
357 }
358
359 $this->cdata = '';
360
361 return;
362 }
363
364
371 public function handlerCharacterData($a_xml_parser, $a_data)
372 {
373 if ($a_data != "\n") {
374 // begin-patch fm
375 if ($this->isReadingFile && $this->mode != ilFileXMLParser::$CONTENT_COPY
376 && $this->mode != ilFileXMLParser::$CONTENT_REST
377 ) { // begin-patch fm
378 $handle = fopen($this->tmpFilename, "a");
379 fwrite($handle, $a_data);
380 fclose($handle);
381 } else {
382 $this->cdata .= $a_data;
383 }
384 }
385 }
386
387
393 public function setFileContents()
394 {
395 // Delete exists version 1 history
396 ilHistory::_removeEntriesForObject($this->file->getId());
397
398 foreach ($this->versions as $version) {
399 if (!file_exists($version["tmpFilename"])) {
400 if (!isset($version["tmpFilename"])) {
401 continue;
402 }
403 // try to get first file of directory
404 $files = scandir(dirname($version["tmpFilename"]));
405 $version["tmpFilename"] = rtrim(dirname($version["tmpFilename"]),
406 "/") . "/" . $files[2];// because [0] = "." [1] = ".."
407 if (!file_exists($version["tmpFilename"])) {
408 ilLoggerFactory::getLogger('file')->error(__METHOD__ . ' "' . ($version["tmpFilename"]) . '" file not found.');
409
410 continue;
411 }
412 }
413
414 if (filesize($version["tmpFilename"]) == 0) {
415 continue;
416 }
417
418 // imported file version
419 $import_file_version_path = $version["tmpFilename"];
420
421 $stream = Streams::ofResource(fopen($import_file_version_path, 'rb'));
422 $this->file->appendStream($stream, $this->file->getTitle());
423 }
424 }
425
426
432 public function updateFileContents()
433 {
434 if ($this->setFileContents()) {
435
436 if ($this->file->getAction() != "" and $this->file->getAction() != null) {
437 ilHistory::_createEntry($this->file->getId(), $this->file->getAction(), $this->file->getFilename() . "," . $this->file->getVersion() . "," . $this->file->getMaxVersion());
438 } else {
439 ilHistory::_createEntry($this->file->getId(), "replace", $this->file->getFilename() . "," . $this->file->getVersion() . "," . $this->file->getMaxVersion());
440 }
441
442 $this->file->notifyUpdate($this->file->getId(), $this->file->getDescription());
443 }
444 }
445
446
454 public function start()
455 {
456 $this->startParsing();
457
458 return $this->result > 0;
459 }
460
461
474 public static function normalizeRelativePath($path)
475 {
476 $path = str_replace('\\', '/', $path);
477
478 while (preg_match('#\p{C}+|^\./#u', $path)) {
479 $path = preg_replace('#\p{C}+|^\./#u', '', $path);
480 }
481
482 $parts = [];
483 foreach (explode('/', $path) as $part) {
484 switch ($part) {
485 case '':
486 case '.':
487 break;
488 case '..':
489 array_pop($parts);
490 break;
491 default:
492 $parts[] = $part;
493 break;
494 }
495 }
496
497 return implode('/', $parts);
498 }
499}
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
An exception for terminatinating execution or to throw for unit testing.
Class Streams Stream factory which enables the user to create streams without the knowledge of the co...
Definition: Streams.php:17
Class to report exception.
fastGunzip($in, $out)
fast uncompressing the file with the zlib-extension without memory consumption
static _lookupMimeType($a_file)
static fastBase64Decode($filein, $fileout)
decodes base encoded file row by row to prevent memory exhaust
getImportDirectory()
Get import directory.
setHandlers($a_xml_parser)
set event handlers
setFileContents()
update file according to filename and version, does not update history has to be called after (!...
updateFileContents()
update file according to filename and version and create history entry has to be called after (!...
handlerEndTag($a_xml_parser, $a_name)
handler for end of element
handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
handler for begin of element
setImportDirectory($a_val)
Set import directory.
start()
starts parsing an changes object by side effect.
__construct($file, $a_xml_data, $obj_id=-1, $mode=0)
Constructor.
handlerCharacterData($a_xml_parser, $a_data)
handler for character data
static normalizeRelativePath($path)
Normalize relative directories in a path.
static _removeEntriesForObject($a_obj_id)
remove all history entries for an object
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.
File storage handling.
Base class for sax-based expat parsing extended classes need to overwrite the method setHandlers and ...
setXMLContent($a_xml_content)
startParsing()
stores xml data in array
static ilTempnam($a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
static __extractId($ilias_id, $inst_id)
extract ref id from role title, e.g.
const IL_INST_ID
Definition: constants.php:38
global $DIC
Definition: goto.php:24
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$ilErr
Definition: raiseError.php:18