ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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;
43 public bool $result = false;
47 public ?string $tmpFilename = null;
48
49 protected ?int $version = null;
50 protected ?string $action = null;
51 protected ?int $max_version = null;
52 protected ?int $date = null;
53 protected ?int $usr_id = null;
54 protected array $versions = [];
55 protected ?string $import_directory = null;
56 protected ?string $cdata = null;
57
61 public function __construct(// end-patch fm
65 public ilObjFile $file,
66 string $a_xml_data,
71 public int $obj_id = -1,
75 public int $mode = 0
76 ) {
78 $this->setXMLContent($a_xml_data);
79 }
80
86 public function setImportDirectory(?string $a_val): void
87 {
88 $this->import_directory = $a_val;
89 }
90
96 public function getImportDirectory(): ?string
97 {
99 }
100
108 public function setHandlers($a_xml_parser): void
109 {
110 xml_set_element_handler($a_xml_parser, $this->handlerBeginTag(...), $this->handlerEndTag(...));
111 xml_set_character_data_handler($a_xml_parser, $this->handlerCharacterData(...));
112 }
113
124 public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs): void
125 {
126 global $DIC;
127
128 global $DIC;
129
130 switch ($a_name) {
131 case 'File':
132 if (isset($a_attribs["obj_id"])) {
133 $read_obj_id = ilUtil::__extractId($a_attribs["obj_id"], IL_INST_ID);
134 if ($this->obj_id != -1 && (int) $read_obj_id != -1 && $this->obj_id !== (int) $read_obj_id) {
135 throw new ilFileException(
136 "Object IDs (xml $read_obj_id and argument " . $this->obj_id . ") do not match!",
138 );
139 }
140 }
141
142 break;
143 case 'Content': // Old import files
144 case 'Version':
145 if ($a_name === "Version" && !isset($a_attribs["mode"])) {
146 // Old import files
147 $this->version = null;
148 if ($this->date === null) {
149 // Version tag comes after Content tag. Take only first (= Should be latest)
150 $this->date = $a_attribs["date"];
151 $this->usr_id = (int) $a_attribs["usr_id"];
152 $this->versions[0]["date"] = $this->date;
153 $this->versions[0]["usr_id"] = $this->usr_id;
154 }
155 break;
156 }
157
159 #echo $a_attribs["mode"];
160 if (isset($a_attribs["mode"])) {
161 if ($a_attribs["mode"] == "GZIP") {
162 if (!function_exists("gzread")) {
163 throw new ilFileException(
164 "Deflating with gzip is not supported",
166 );
167 }
168
170 } elseif ($a_attribs["mode"] == "ZLIB") {
171 if (!function_exists("gzuncompress")) {
172 throw new ilFileException(
173 "Deflating with zlib (compress/uncompress) is not supported",
175 );
176 }
177
179 } elseif ($a_attribs["mode"] == "COPY") {
180 $this->mode = ilFileXMLParser::$CONTENT_COPY;
181 } // begin-patch fm
182 elseif ($a_attribs['mode'] == 'REST') {
183 $this->mode = ilFileXMLParser::$CONTENT_REST;
184 }
185 // end-patch fm
186 }
187
188 if ($a_name === "Version") {
189 $this->version = (int) $a_attribs["version"];
190 $this->max_version = (int) $a_attribs["max_version"];
191 $this->date = (int) $a_attribs["date"];
192 $this->usr_id = (int) $a_attribs["usr_id"];
193 $this->action = (string) $a_attribs["action"];
194 }
195 }
196 }
197
204 public function handlerEndTag($a_xml_parser, string $a_name): void
205 {
206 $this->cdata = trim($this->cdata ?? '');
207
208 $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': ' . $this->cdata);
209
210 switch ($a_name) {
211 case 'File':
212 $this->result = true;
213 break;
214 case 'Filename':
215 $this->file->setFilename($this->cdata ?? 'unkown');
216 $this->file->setTitle($this->cdata ?? 'unkown');
217
218 break;
219 case 'Title':
220 $this->file->setTitle(trim($this->cdata));
221 break;
222 case 'Description':
223 $this->file->setDescription(trim($this->cdata));
224 break;
225 case 'Rating':
226 $this->file->setRating((bool) $this->cdata);
227 break;
228 case 'Content': // Old import files
229 case 'Version':
230 if ($a_name === "Version" && $this->version === null) {
231 // Old import files
232 break;
233 }
234
235 $baseDecodedFilename = ilFileUtils::ilTempnam();
236 if ($this->mode === ilFileXMLParser::$CONTENT_COPY) {
237 $this->tmpFilename = $this->getImportDirectory() . "/" . self::normalizeRelativePath($this->cdata);
238 } // begin-patch fm
239 elseif ($this->mode === ilFileXMLParser::$CONTENT_REST) {
240 $storage = new ilRestFileStorage();
241 $this->tmpFilename = $storage->getStoredFilePath(self::normalizeRelativePath($this->cdata));
242 if (!$this->fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
243 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
244 }
245 $this->tmpFilename = $baseDecodedFilename;
246 } // end-patch fm
247 else {
248 if (!$this->fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
249 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
250 }
251 if ($this->mode === ilFileXMLParser::$CONTENT_GZ_COMPRESSED) {
252 if (!$this->fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
253 throw new ilFileException(
254 "Deflating with fastzunzip failed",
256 );
257 }
258 unlink($baseDecodedFilename);
259 } elseif ($this->mode === ilFileXMLParser::$CONTENT_ZLIB_COMPRESSED) {
260 if (!$this->fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
261 throw new ilFileException(
262 "Deflating with fastDecompress failed",
264 );
265 }
266 unlink($baseDecodedFilename);
267 } else {
268 $this->tmpFilename = $baseDecodedFilename;
269 }
270 }
271
272 //$this->content = $content;
273 // see #17211
274
275 if ($this->version == $this->file->getVersion()) {
276 if (is_file($this->tmpFilename)) {
277 $this->file->setFileSize(filesize($this->tmpFilename)); // strlen($this->content));
278 }
279
280 // if no file type is given => lookup mime type
281 if ($this->file->getFileType() === '' || $this->file->getFileType() === '0') {
282 global $DIC;
283 $this->file->setFileType(MimeType::getMimeType($this->tmpFilename));
284 }
285 }
286
287 $this->versions[] = [
288 "version" => $this->version,
289 "max_version" => $this->max_version,
290 "tmpFilename" => $this->tmpFilename,
291 "date" => $this->date,
292 "usr_id" => $this->usr_id,
293 "action" => $this->action,
294 ];
295 $this->version = null;
296 $this->date = null;
297 $this->usr_id = null;
298 break;
299 }
300
301 $this->cdata = '';
302 }
303
310 public function handlerCharacterData($a_xml_parser, string $a_data): void
311 {
312 if ($a_data !== "\n") {
313 // begin-patch fm
314 if ($this->mode !== ilFileXMLParser::$CONTENT_COPY
315 && $this->mode !== ilFileXMLParser::$CONTENT_REST
316 ) { // begin-patch fm
317 $this->cdata .= $a_data;
318 } else {
319 $this->cdata .= $a_data;
320 }
321 }
322 }
323
329 public function setFileContents(): void
330 {
331 // Delete exists version 1 history
332 ilHistory::_removeEntriesForObject($this->file->getId());
333
334 foreach ($this->versions as $version) {
335 if (!file_exists($version["tmpFilename"])) {
336 if (!isset($version["tmpFilename"])) {
337 continue;
338 }
339 // try to get first file of directory
340 $files = scandir(dirname((string) $version["tmpFilename"]));
341 $version["tmpFilename"] = rtrim(
342 dirname((string) $version["tmpFilename"]),
343 "/"
344 ) . "/" . $files[2];// because [0] = "." [1] = ".."
345 if (!file_exists($version["tmpFilename"])) {
346 ilLoggerFactory::getLogger('file')->error(
347 __METHOD__ . ' "' . ($version["tmpFilename"]) . '" file not found.'
348 );
349
350 continue;
351 }
352 }
353
354 if (filesize($version["tmpFilename"]) == 0) {
355 continue;
356 }
357
358 // imported file version
359 $import_file_version_path = $version["tmpFilename"];
360
361 $stream = Streams::ofResource(fopen($import_file_version_path, 'rb'));
362 $this->file->appendStream($stream, $this->file->getTitle());
363 }
364 }
365
371 public function updateFileContents(): void
372 {
373 // removed
374 }
375
383 public function start(): bool
384 {
385 $this->startParsing();
386
387 return $this->result > 0;
388 }
389
400 public static function normalizeRelativePath(string $path): string
401 {
402 $path = str_replace('\\', '/', $path);
403
404 while (preg_match('#\p{C}+|^\./#u', (string) $path)) {
405 $path = preg_replace('#\p{C}+|^\./#u', '', (string) $path);
406 }
407
408 $parts = [];
409 foreach (explode('/', (string) $path) as $part) {
410 switch ($part) {
411 case '':
412 case '.':
413 break;
414 case '..':
415 array_pop($parts);
416 break;
417 default:
418 $parts[] = $part;
419 break;
420 }
421 }
422
423 return implode('/', $parts);
424 }
425
426 private function fastBase64Decode(string $filein, string $fileout): bool
427 {
428 $fh = fopen($filein, 'rb');
429 $fh2 = fopen($fileout, 'wb');
430 stream_filter_append($fh2, 'convert.base64-decode');
431
432 while (!feof($fh)) {
433 $chunk = fgets($fh);
434 if ($chunk === false) {
435 break;
436 }
437 fwrite($fh2, $chunk);
438 }
439 fclose($fh);
440 fclose($fh2);
441
442 return true;
443 }
444
445 private function fastGunzip(string $in, string $out): bool
446 {
447 if (!file_exists($in)) {
448 return false;
449 }
450 if (!is_readable($in)) {
451 return false;
452 }
453 if (!file_exists($out) && !is_writable(dirname($out))) {
454 return false;
455 }
456 if (file_exists($out) && !is_writable($out)) {
457 return false;
458 }
459 $in_file = gzopen($in, "rb");
460 $out_file = fopen($out, "wb");
461
462 while (!gzeof($in_file)) {
463 $buffer = gzread($in_file, 4096);
464 fwrite($out_file, $buffer, 4096);
465 }
466
467 gzclose($in_file);
468 fclose($out_file);
469
470 return true;
471 }
472}
$out
Definition: buildRTE.php:24
Mime type determination.
Definition: MimeType.php:30
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
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 (!...
__construct(public ilObjFile $file, string $a_xml_data, public int $obj_id=-1, public int $mode=0)
Constructor.
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
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.
static int $CONTENT_NOT_COMPRESSED
fastBase64Decode(string $filein, string $fileout)
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
$path
Definition: ltiservices.php:30
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
global $DIC
Definition: shib_login.php:26
$GLOBALS["DIC"]
Definition: wac.php:54