ILIAS  release_8 Revision v8.24
class.ilFileXMLParser.php
Go to the documentation of this file.
1<?php
2
31
33{
34 public static int $CONTENT_NOT_COMPRESSED = 0;
35 public static int $CONTENT_GZ_COMPRESSED = 1;
36 public static int $CONTENT_ZLIB_COMPRESSED = 2;
37 public static int $CONTENT_COPY = 4;
38 // begin-patch fm
39 public static int $CONTENT_REST = 5;
40 // end-patch fm
44 public \ilObjFile $file;
49 public int $obj_id;
53 public bool $result;
57 public int $mode;
61 public ?string $tmpFilename = null;
62
63 protected ?int $version = null;
64 protected ?string $action = null;
65 protected ?int $max_version = null;
66 protected ?int $date = null;
67 protected ?int $usr_id = null;
68 protected array $versions = [];
69 protected ?string $import_directory = null;
70 protected ?string $cdata = null;
71
75 public function __construct(ilObjFile $file, string $a_xml_data, int $obj_id = -1, int $mode = 0)
76 {
78 $this->file = $file;
79 $this->setXMLContent($a_xml_data);
80 $this->obj_id = $obj_id;
81 $this->result = false;
82 $this->mode = $mode;
83 }
84
90 public function setImportDirectory(?string $a_val): void
91 {
92 $this->import_directory = $a_val;
93 }
94
100 public function getImportDirectory(): ?string
101 {
103 }
104
112 public function setHandlers($a_xml_parser): void
113 {
114 xml_set_object($a_xml_parser, $this);
115 xml_set_element_handler($a_xml_parser, 'handlerBeginTag', 'handlerEndTag');
116 xml_set_character_data_handler($a_xml_parser, 'handlerCharacterData');
117 }
118
129 public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
130 {
131 global $DIC;
132
133 global $DIC;
134
135 switch ($a_name) {
136 case 'File':
137 if (isset($a_attribs["obj_id"])) {
138 $read_obj_id = ilUtil::__extractId($a_attribs["obj_id"], IL_INST_ID);
139 if ($this->obj_id != -1 && (int) $read_obj_id != -1 && $this->obj_id != (int) $read_obj_id) {
140 throw new ilFileException(
141 "Object IDs (xml $read_obj_id and argument " . $this->obj_id . ") do not match!",
143 );
144 }
145 }
146
147 break;
148 case 'Content': // Old import files
149 case 'Version':
150 if ($a_name === "Version" && !isset($a_attribs["mode"])) {
151 // Old import files
152 $this->version = null;
153 if ($this->date === null) {
154 // Version tag comes after Content tag. Take only first (= Should be latest)
155 $this->date = $a_attribs["date"];
156 $this->usr_id = (int) $a_attribs["usr_id"];
157 $this->versions[0]["date"] = $this->date;
158 $this->versions[0]["usr_id"] = $this->usr_id;
159 }
160 break;
161 }
162
164 #echo $a_attribs["mode"];
165 if (isset($a_attribs["mode"])) {
166 if ($a_attribs["mode"] == "GZIP") {
167 if (!function_exists("gzread")) {
168 throw new ilFileException(
169 "Deflating with gzip is not supported",
171 );
172 }
173
175 } elseif ($a_attribs["mode"] == "ZLIB") {
176 if (!function_exists("gzuncompress")) {
177 throw new ilFileException(
178 "Deflating with zlib (compress/uncompress) is not supported",
180 );
181 }
182
184 } elseif ($a_attribs["mode"] == "COPY") {
185 $this->mode = ilFileXMLParser::$CONTENT_COPY;
186 } // begin-patch fm
187 elseif ($a_attribs['mode'] == 'REST') {
188 $this->mode = ilFileXMLParser::$CONTENT_REST;
189 }
190 // end-patch fm
191 }
192
193 if ($a_name === "Version") {
194 $this->version = (int) $a_attribs["version"];
195 $this->max_version = (int) $a_attribs["max_version"];
196 $this->date = (int) $a_attribs["date"];
197 $this->usr_id = (int) $a_attribs["usr_id"];
198 $this->action = (string) $a_attribs["action"];
199 }
200 }
201 }
202
209 public function handlerEndTag($a_xml_parser, string $a_name): void
210 {
211 $this->cdata = trim($this->cdata);
212
213 $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': ' . $this->cdata);
214
215 switch ($a_name) {
216 case 'File':
217 $this->result = true;
218 break;
219 case 'Filename':
220 if ($this->cdata === '') {
221 throw new ilFileException("Filename ist missing!");
222 }
223
224 $this->file->setFilename($this->cdata);
225 $this->file->setTitle($this->cdata);
226
227 break;
228 case 'Title':
229 $this->file->setTitle(trim($this->cdata));
230 break;
231 case 'Description':
232 $this->file->setDescription(trim($this->cdata));
233 break;
234 case 'Rating':
235 $this->file->setRating((bool) $this->cdata);
236 break;
237 case 'Content': // Old import files
238 case 'Version':
239 if ($a_name === "Version" && $this->version === null) {
240 // Old import files
241 break;
242 }
243
244 $baseDecodedFilename = ilFileUtils::ilTempnam();
245 if ($this->mode == ilFileXMLParser::$CONTENT_COPY) {
246 $this->tmpFilename = $this->getImportDirectory() . "/" . self::normalizeRelativePath($this->cdata);
247 } // begin-patch fm
248 elseif ($this->mode == ilFileXMLParser::$CONTENT_REST) {
249 $storage = new ilRestFileStorage();
250 $this->tmpFilename = $storage->getStoredFilePath(self::normalizeRelativePath($this->cdata));
251 if (!$this->fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
252 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
253 }
254 $this->tmpFilename = $baseDecodedFilename;
255 } // end-patch fm
256 else {
257 if (!$this->fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
258 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
259 }
260 if ($this->mode == ilFileXMLParser::$CONTENT_GZ_COMPRESSED) {
261 if (!$this->fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
262 throw new ilFileException(
263 "Deflating with fastzunzip failed",
265 );
266 }
267 unlink($baseDecodedFilename);
268 } elseif ($this->mode == ilFileXMLParser::$CONTENT_ZLIB_COMPRESSED) {
269 if (!$this->fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
270 throw new ilFileException(
271 "Deflating with fastDecompress failed",
273 );
274 }
275 unlink($baseDecodedFilename);
276 } else {
277 $this->tmpFilename = $baseDecodedFilename;
278 }
279 }
280
281 //$this->content = $content;
282 // see #17211
283
284 if ($this->version == $this->file->getVersion()) {
285 if (is_file($this->tmpFilename)) {
286 $this->file->setFileSize(filesize($this->tmpFilename)); // strlen($this->content));
287 }
288
289 // if no file type is given => lookup mime type
290 if (!$this->file->getFileType()) {
291 global $DIC;
292 $this->file->setFileType(MimeType::getMimeType($this->tmpFilename));
293 }
294 }
295
296 $this->versions[] = [
297 "version" => $this->version,
298 "max_version" => $this->max_version,
299 "tmpFilename" => $this->tmpFilename,
300 "date" => $this->date,
301 "usr_id" => $this->usr_id,
302 "action" => $this->action,
303 ];
304 $this->version = null;
305 $this->date = null;
306 $this->usr_id = null;
307 break;
308 }
309
310 $this->cdata = '';
311 }
312
319 public function handlerCharacterData($a_xml_parser, string $a_data): void
320 {
321 if ($a_data != "\n") {
322 // begin-patch fm
323 if ($this->mode != ilFileXMLParser::$CONTENT_COPY
324 && $this->mode != ilFileXMLParser::$CONTENT_REST
325 ) { // begin-patch fm
326 $this->cdata .= $a_data;
327 } else {
328 $this->cdata .= $a_data;
329 }
330 }
331 }
332
338 public function setFileContents(): void
339 {
340 // Delete exists version 1 history
341 ilHistory::_removeEntriesForObject($this->file->getId());
342
343 foreach ($this->versions as $version) {
344 if (!file_exists($version["tmpFilename"])) {
345 if (!isset($version["tmpFilename"])) {
346 continue;
347 }
348 // try to get first file of directory
349 $files = scandir(dirname($version["tmpFilename"]));
350 $version["tmpFilename"] = rtrim(
351 dirname($version["tmpFilename"]),
352 "/"
353 ) . "/" . $files[2];// because [0] = "." [1] = ".."
354 if (!file_exists($version["tmpFilename"])) {
355 ilLoggerFactory::getLogger('file')->error(__METHOD__ . ' "' . ($version["tmpFilename"]) . '" file not found.');
356
357 continue;
358 }
359 }
360
361 if (filesize($version["tmpFilename"]) == 0) {
362 continue;
363 }
364
365 // imported file version
366 $import_file_version_path = $version["tmpFilename"];
367
368 $stream = Streams::ofResource(fopen($import_file_version_path, 'rb'));
369 $this->file->appendStream($stream, $this->file->getTitle());
370 }
371 }
372
378 public function updateFileContents(): void
379 {
380 // removed
381 }
382
390 public function start(): bool
391 {
392 $this->startParsing();
393
394 return $this->result > 0;
395 }
396
407 public static function normalizeRelativePath(string $path): string
408 {
409 $path = str_replace('\\', '/', $path);
410
411 while (preg_match('#\p{C}+|^\./#u', $path)) {
412 $path = preg_replace('#\p{C}+|^\./#u', '', $path);
413 }
414
415 $parts = [];
416 foreach (explode('/', $path) as $part) {
417 switch ($part) {
418 case '':
419 case '.':
420 break;
421 case '..':
422 array_pop($parts);
423 break;
424 default:
425 $parts[] = $part;
426 break;
427 }
428 }
429
430 return implode('/', $parts);
431 }
432
433 private function fastBase64Decode(string $filein, string $fileout): bool
434 {
435 $fh = fopen($filein, 'rb');
436 $fh2 = fopen($fileout, 'wb');
437 stream_filter_append($fh2, 'convert.base64-decode');
438
439 while (!feof($fh)) {
440 $chunk = fgets($fh);
441 if ($chunk === false) {
442 break;
443 }
444 fwrite($fh2, $chunk);
445 }
446 fclose($fh);
447 fclose($fh2);
448
449 return true;
450 }
451
452 private function fastGunzip(string $in, string $out): bool
453 {
454 if (!file_exists($in) || !is_readable($in)) {
455 return false;
456 }
457 if ((!file_exists($out) && !is_writable(dirname($out)) || (file_exists($out) && !is_writable($out)))) {
458 return false;
459 }
460
461 $in_file = gzopen($in, "rb");
462 $out_file = fopen($out, "wb");
463
464 while (!gzeof($in_file)) {
465 $buffer = gzread($in_file, 4096);
466 fwrite($out_file, $buffer, 4096);
467 }
468
469 gzclose($in_file);
470 fclose($out_file);
471
472 return true;
473 }
474}
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
$out
Definition: buildRTE.php:24
Mime type determination.
Definition: MimeType.php:28
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static int $DECOMPRESSION_FAILED
static int $ID_DEFLATE_METHOD_MISMATCH
static ilTempnam(?string $a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
static int $CONTENT_GZ_COMPRESSED
fastGunzip(string $in, string $out)
getImportDirectory()
Get import directory.
static int $CONTENT_ZLIB_COMPRESSED
string $tmpFilename
file of temporary file where we store the file content instead of in memory
setHandlers($a_xml_parser)
set event handlers
setFileContents()
update file according to filename and version, does not update history has to be called after (!...
handlerCharacterData($a_xml_parser, string $a_data)
handler for character data
updateFileContents()
update file according to filename and version and create history entry has to be called after (!...
setImportDirectory(?string $a_val)
Set import directory.
handlerEndTag($a_xml_parser, string $a_name)
handler for end of element
int $obj_id
this will be matched against the id in the xml in case we want to update an exercise
start()
starts parsing an changes object by side effect.
bool $result
result of parsing and updating
static normalizeRelativePath(string $path)
Normalize relative directories in a path.
int $mode
Content compression mode, defaults to no compression.
__construct(ilObjFile $file, string $a_xml_data, int $obj_id=-1, int $mode=0)
Constructor.
static int $CONTENT_NOT_COMPRESSED
fastBase64Decode(string $filein, string $fileout)
ilObjFile $file
Exercise object which has been parsed.
handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs)
handler for begin of element
static _removeEntriesForObject(int $a_obj_id)
remove all history entries for an object
static getLogger(string $a_component_id)
Get component logger.
Class ilObjFile.
File storage handling.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setXMLContent(string $a_xml_content)
startParsing()
stores xml data in array
static __extractId(string $ilias_id, int $inst_id)
extract ref id from role title, e.g.
const IL_INST_ID
Definition: constants.php:40
global $DIC
Definition: feed.php:28
$path
Definition: ltiservices.php:32
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc