ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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
16include_once './Services/Xml/classes/class.ilSaxParser.php';
17include_once 'Modules/File/classes/class.ilFileException.php';
18include_once 'Services/Utilities/classes/class.ilFileUtils.php';
19
21{
22 public static $CONTENT_NOT_COMPRESSED = 0;
23 public static $CONTENT_GZ_COMPRESSED = 1;
24 public static $CONTENT_ZLIB_COMPRESSED = 2;
25 public static $CONTENT_COPY = 4;
26 // begin-patch fm
27 public static $CONTENT_REST = 5;
28 // end-patch fm
34 public $file;
41 public $obj_id;
47 public $result;
53 public $mode;
59 //var $content;
60
67
68
78 public function __construct(&$file, $a_xml_data, $obj_id = -1, $mode = 0)
79 {
80 parent::__construct();
81 $this->file = $file;
82 $this->setXMLContent($a_xml_data);
83 $this->obj_id = $obj_id;
84 $this->result = false;
85 $this->mode = $mode;
86 }
87
88
94 public function setImportDirectory($a_val)
95 {
96 $this->importDirectory = $a_val;
97 }
98
99
105 public function getImportDirectory()
106 {
107 return $this->importDirectory;
108 }
109
110
118 public function setHandlers($a_xml_parser)
119 {
120 xml_set_object($a_xml_parser, $this);
121 xml_set_element_handler($a_xml_parser, 'handlerBeginTag', 'handlerEndTag');
122 xml_set_character_data_handler($a_xml_parser, 'handlerCharacterData');
123 }
124
125
136 public function handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
137 {
138 global $DIC;
139 $ilErr = $DIC['ilErr'];
140
141 global $DIC;
142 $ilLog = $DIC['ilLog'];
143
144 switch ($a_name) {
145 case 'File':
146 if (isset($a_attribs["obj_id"])) {
147 $read_obj_id = ilUtil::__extractId($a_attribs["obj_id"], IL_INST_ID);
148 if ($this->obj_id != -1 && (int) $read_obj_id != -1 && (int) $this->obj_id != (int) $read_obj_id) {
149 throw new ilFileException("Object IDs (xml $read_obj_id and argument " . $this->obj_id . ") do not match!", ilFileException::$ID_MISMATCH);
150 }
151 }
152 if (isset($a_attribs["type"])) {
153 $this->file->setFileType($a_attribs["type"]);
154 }
155 $this->file->setVersion($this->file->getVersion() + 1);
156 break;
157 case 'Content':
158 $this->tmpFilename = ilUtil::ilTempnam();
160 $this->isReadingFile = true;
161 #echo $a_attribs["mode"];
162 if (isset($a_attribs["mode"])) {
163 if ($a_attribs["mode"] == "GZIP") {
164 if (!function_exists("gzread")) {
165 throw new ilFileException("Deflating with gzip is not supported", ilFileException::$ID_DEFLATE_METHOD_MISMATCH);
166 }
167
169 } elseif ($a_attribs["mode"] == "ZLIB") {
170 if (!function_exists("gzuncompress")) {
171 throw new ilFileException("Deflating with zlib (compress/uncompress) is not supported", ilFileException::$ID_DEFLATE_METHOD_MISMATCH);
172 }
173
175 } elseif ($a_attribs["mode"] == "COPY") {
176 $this->mode = ilFileXMLParser::$CONTENT_COPY;
177 } // begin-patch fm
178 elseif ($a_attribs['mode'] == 'REST') {
179 $this->mode = ilFileXMLParser::$CONTENT_REST;
180 }
181 // end-patch fm
182 }
183 }
184 }
185
186
193 public function handlerEndTag($a_xml_parser, $a_name)
194 {
195 $this->cdata = trim($this->cdata);
196
197 $GLOBALS['DIC']['ilLog']->write(__METHOD__ . ': ' . $this->cdata);
198
199 switch ($a_name) {
200 case 'File':
201 $this->result = true;
202 break;
203 case 'Filename':
204 if (strlen($this->cdata) == 0) {
205 throw new ilFileException("Filename ist missing!");
206 }
207
208 $this->file->setFilename(basename(self::normalizeRelativePath($this->cdata)));
209 $this->file->setTitle($this->cdata);
210
211 break;
212 case 'Title':
213 $this->file->setTitle(trim($this->cdata));
214 break;
215 case 'Description':
216 $this->file->setDescription(trim($this->cdata));
217 break;
218 case 'Rating':
219 $this->file->setRating((bool) $this->cdata);
220 break;
221 case 'Content':
222 $GLOBALS['DIC']['ilLog']->write($this->mode);
223 $this->isReadingFile = false;
224 $baseDecodedFilename = ilUtil::ilTempnam();
225 if ($this->mode == ilFileXMLParser::$CONTENT_COPY) {
226 $this->tmpFilename = $this->getImportDirectory() . "/" . self::normalizeRelativePath($this->cdata);
227 } // begin-patch fm
228 elseif ($this->mode == ilFileXMLParser::$CONTENT_REST) {
229 include_once './Services/WebServices/Rest/classes/class.ilRestFileStorage.php';
230 $storage = new ilRestFileStorage();
231 $this->tmpFilename = $storage->getStoredFilePath(self::normalizeRelativePath($this->cdata));
232 if (!ilFileUtils::fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
233 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
234 }
235 $this->tmpFilename = $baseDecodedFilename;
236 } // end-patch fm
237 else {
238 if (!ilFileUtils::fastBase64Decode($this->tmpFilename, $baseDecodedFilename)) {
239 throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
240 }
241 if ($this->mode == ilFileXMLParser::$CONTENT_GZ_COMPRESSED) {
242 if (!ilFileUtils::fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
243 throw new ilFileException("Deflating with fastzunzip failed", ilFileException::$DECOMPRESSION_FAILED);
244 }
245 unlink($baseDecodedFilename);
246 } elseif ($this->mode == ilFileXMLParser::$CONTENT_ZLIB_COMPRESSED) {
247 if (!ilFileUtils::fastGunzip($baseDecodedFilename, $this->tmpFilename)) {
248 throw new ilFileException("Deflating with fastDecompress failed", ilFileException::$DECOMPRESSION_FAILED);
249 }
250 unlink($baseDecodedFilename);
251 } else {
252 $this->tmpFilename = $baseDecodedFilename;
253 }
254 }
255 //$this->content = $content;
256 // see #17211
257 if (is_file($this->tmpFilename)) {
258 $this->file->setFileSize(filesize($this->tmpFilename)); // strlen($this->content));
259 }
260
261 // if no file type is given => lookup mime type
262 if (!$this->file->getFileType()) {
263 global $DIC;
264 $ilLog = $DIC['ilLog'];
265
266 #$ilLog->write(__METHOD__.': Trying to detect mime type...');
267 include_once('./Services/Utilities/classes/class.ilFileUtils.php');
268 $this->file->setFileType(ilFileUtils::_lookupMimeType($this->tmpFilename));
269 }
270
271 break;
272 }
273
274 $this->cdata = '';
275
276 return;
277 }
278
279
286 public function handlerCharacterData($a_xml_parser, $a_data)
287 {
288 if ($a_data != "\n") {
289 // begin-patch fm
290 if ($this->isReadingFile && $this->mode != ilFileXMLParser::$CONTENT_COPY && $this->mode != ilFileXMLParser::$CONTENT_REST) { // begin-patch fm
291 $handle = fopen($this->tmpFilename, "a");
292 fwrite($handle, $a_data);
293 fclose($handle);
294 } else {
295 $this->cdata .= $a_data;
296 }
297 }
298 }
299
300
306 public function setFileContents()
307 {
308 if (!file_exists($this->tmpFilename)) {
309 ilLoggerFactory::getLogger('file')->error(__METHOD__ . ' "' . $this->tmpFilename . '" file not found.');
310
311 return;
312 }
313
314 if (filesize($this->tmpFilename) == 0) {
315 return;
316 }
317
318 $filedir = $this->file->getDirectory($this->file->getVersion());
319
320 if (!is_dir($filedir)) {
321 $this->file->createDirectory();
322 ilUtil::makeDir($filedir);
323 }
324
325 $filename = $filedir . "/" . $this->file->getFileName();
326
327 if (file_exists($filename)) {
328 unlink($filename);
329 }
330
331 return ilFileUtils::rename($this->tmpFilename, $filename);
332 }
333
334
340 public function updateFileContents()
341 {
342 if ($this->setFileContents()) {
343 require_once("./Services/History/classes/class.ilHistory.php");
344 ilHistory::_createEntry($this->file->getId(), "replace", $this->file->getFilename() . "," . $this->file->getVersion());
345 $this->file->addNewsNotification("file_updated");
346 }
347 }
348
349
357 public function start()
358 {
359 $this->startParsing();
360
361 return $this->result > 0;
362 }
363
364
377 public static function normalizeRelativePath($path)
378 {
379 $path = str_replace('\\', '/', $path);
380
381 while (preg_match('#\p{C}+|^\./#u', $path)) {
382 $path = preg_replace('#\p{C}+|^\./#u', '', $path);
383 }
384
385 $parts = [];
386 foreach (explode('/', $path) as $part) {
387 switch ($part) {
388 case '':
389 case '.':
390 break;
391 case '..':
392 array_pop($parts);
393 break;
394 default:
395 $parts[] = $part;
396 break;
397 }
398 }
399
400 return implode('/', $parts);
401 }
402}
An exception for terminatinating execution or to throw for unit testing.
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
static rename($a_source, $a_target)
Rename a file.
Exercise XML Parser which completes/updates a given file by an xml string.
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
__construct(&$file, $a_xml_data, $obj_id=-1, $mode=0)
Constructor.
setImportDirectory($a_val)
Set import directory.
start()
starts parsing an changes object by side effect.
handlerCharacterData($a_xml_parser, $a_data)
handler for character data
static normalizeRelativePath($path)
Normalize relative directories in a path.
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)
Create a temporary file in an ILIAS writable directory.
static __extractId($ilias_id, $inst_id)
extract ref id from role title, e.g.
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
$GLOBALS['loaded']
Global hash that tracks already loaded includes.
global $ilErr
Definition: raiseError.php:16
global $DIC
Definition: saml.php:7