ILIAS  release_5-0 Revision 5.0.0-1144-gc4397b1f87
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 
5 
17 include_once './Services/Xml/classes/class.ilSaxParser.php';
18 include_once 'Modules/File/classes/class.ilFileException.php';
19 include_once 'Services/Utilities/classes/class.ilFileUtils.php';
20 
21 
23 {
27  static $CONTENT_COPY = 4;
28  // begin-patch fm
29  static $CONTENT_REST = 5;
30  // end-patch fm
31 
37  var $file;
38 
45  var $obj_id;
46 
47 
53  var $result;
54 
60  var $mode;
61 
62 
68  //var $content;
69 
76 
77 
86  function ilFileXMLParser(& $file, $a_xml_data, $obj_id = -1, $mode = 0)
87  {
88  parent::ilSaxParser();
89  $this->file = $file;
90  $this->setXMLContent($a_xml_data);
91  $this->obj_id = $obj_id;
92  $this->result = false;
93  $this->mode = $mode;
94  }
95 
101  function setImportDirectory($a_val)
102  {
103  $this->importDirectory = $a_val;
104  }
105 
112  {
113  return $this->importDirectory;
114  }
121  function setHandlers($a_xml_parser)
122  {
123  xml_set_object($a_xml_parser,$this);
124  xml_set_element_handler($a_xml_parser,'handlerBeginTag','handlerEndTag');
125  xml_set_character_data_handler($a_xml_parser,'handlerCharacterData');
126  }
127 
137  function handlerBeginTag($a_xml_parser,$a_name,$a_attribs)
138  {
139  global $ilErr;
140 
141  global $ilLog;
142 
143  switch($a_name)
144  {
145  case 'File':
146  if (isset($a_attribs["obj_id"]))
147  {
148  $read_obj_id = ilUtil::__extractId($a_attribs["obj_id"], IL_INST_ID);
149  if ($this->obj_id != -1 && (int) $read_obj_id != -1 && (int) $this->obj_id != (int) $read_obj_id)
150  {
151  throw new ilFileException ("Object IDs (xml $read_obj_id and argument ".$this->obj_id.") do not match!", ilFileException::$ID_MISMATCH);
152  }
153  }
154  if (isset($a_attribs["type"]))
155  {
156  $this->file->setFileType($a_attribs["type"]);
157  }
158  $this->file->setVersion($this->file->getVersion() + 1);
159  break;
160  case 'Content':
161  $this->tmpFilename = ilUtil::ilTempnam();
163  $this->isReadingFile = true;
164 #echo $a_attribs["mode"];
165  if (isset($a_attribs["mode"]))
166  {
167  if($a_attribs["mode"] == "GZIP")
168  {
169  if (!function_exists("gzread"))
170  throw new ilFileException ("Deflating with gzip is not supported", ilFileException::$ID_DEFLATE_METHOD_MISMATCH);
171 
173  }
174  elseif ($a_attribs["mode"] == "ZLIB")
175  {
176  if (!function_exists("gzuncompress"))
177  throw new ilFileException ("Deflating with zlib (compress/uncompress) is not supported", ilFileException::$ID_DEFLATE_METHOD_MISMATCH);
178 
180  }
181  elseif ($a_attribs["mode"] == "COPY")
182  {
183  $this->mode = ilFileXMLParser::$CONTENT_COPY;
184  }
185  // begin-patch fm
186  elseif($a_attribs['mode'] == 'REST')
187  {
188  $this->mode = ilFileXMLParser::$CONTENT_REST;
189  }
190  // end-patch fm
191  }
192  }
193  }
194 
195 
196 
203  function handlerEndTag($a_xml_parser,$a_name)
204  {
205  $this->cdata = trim($this->cdata);
206 
207  $GLOBALS['ilLog']->write(__METHOD__.': '.$this->cdata);
208 
209  switch($a_name)
210  {
211  case 'File':
212  $this->result = true;
213  break;
214  case 'Filename':
215  if (strlen($this->cdata) == 0)
216  throw new ilFileException("Filename ist missing!");
217 
218  $this->file->setFilename(basename(self::normalizeRelativePath($this->cdata)));
219  $this->file->setTitle($this->cdata);
220 
221  break;
222  case 'Title':
223  $this->file->setTitle(trim($this->cdata));
224  break;
225  case 'Description':
226  $this->file->setDescription(trim($this->cdata));
227  break;
228  case 'Rating':
229  $this->file->setRating((bool)$this->cdata);
230  break;
231  case 'Content':
232  $GLOBALS['ilLog']->write($this->mode);
233  $this->isReadingFile = false;
234  $baseDecodedFilename = ilUtil::ilTempnam();
235  if ($this->mode == ilFileXMLParser::$CONTENT_COPY)
236  {
237  $this->tmpFilename = $this->getImportDirectory()."/".self::normalizeRelativePath($this->cdata);
238  }
239  // begin-patch fm
240  elseif($this->mode == ilFileXMLParser::$CONTENT_REST)
241  {
242  include_once './Services/WebServices/Rest/classes/class.ilRestFileStorage.php';
243  $storage = new ilRestFileStorage();
244  $this->tmpFilename = $storage->getStoredFilePath(self::normalizeRelativePath($this->cdata));
245  if(!ilFileUtils::fastBase64Decode($this->tmpFilename, $baseDecodedFilename))
246  {
247  throw new ilFileException("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
248  }
249  $this->tmpFilename = $baseDecodedFilename;
250  }
251  // end-patch fm
252  else
253  {
254  if (!ilFileUtils::fastBase64Decode($this->tmpFilename, $baseDecodedFilename))
255  {
256  throw new ilFileException ("Base64-Decoding failed", ilFileException::$DECOMPRESSION_FAILED);
257  }
258  if ($this->mode == ilFileXMLParser::$CONTENT_GZ_COMPRESSED)
259  {
260  if (!ilFileUtils::fastGunzip ($baseDecodedFilename, $this->tmpFilename))
261  {
262  throw new ilFileException ("Deflating with fastzunzip failed", ilFileException::$DECOMPRESSION_FAILED);
263  }
264  unlink ($baseDecodedFilename);
265  }
266  elseif ($this->mode == ilFileXMLParser::$CONTENT_ZLIB_COMPRESSED)
267  {
268  if (!ilFileUtils::fastGunzip ($baseDecodedFilename, $this->tmpFilename))
269  {
270  throw new ilFileException ("Deflating with fastDecompress failed", ilFileException::$DECOMPRESSION_FAILED);
271  }
272  unlink ($baseDecodedFilename);
273  }
274  else
275  {
276  $this->tmpFilename = $baseDecodedFilename;
277  }
278  }
279  //$this->content = $content;
280  $this->file->setFileSize(filesize($this->tmpFilename)); // strlen($this->content));
281 
282  // if no file type is given => lookup mime type
283  if(!$this->file->getFileType())
284  {
285  global $ilLog;
286 
287  #$ilLog->write(__METHOD__.': Trying to detect mime type...');
288  include_once('./Services/Utilities/classes/class.ilFileUtils.php');
289  $this->file->setFileType(ilFileUtils::_lookupMimeType($this->tmpFilename));
290  }
291 
292  break;
293  }
294 
295  $this->cdata = '';
296 
297  return;
298  }
299 
306  function handlerCharacterData($a_xml_parser,$a_data)
307  {
308  if($a_data != "\n")
309  {
310  // begin-patch fm
311  if ($this->isReadingFile && $this->mode != ilFileXMLParser::$CONTENT_COPY && $this->mode != ilFileXMLParser::$CONTENT_REST)
312  // begin-patch fm
313  {
314  $handle = fopen($this->tmpFilename, "a");
315  fwrite ($handle, $a_data);
316  fclose ($handle);
317  } else
318  $this->cdata .= $a_data;
319  }
320  }
321 
327  public function setFileContents ()
328  {
329  if (filesize ($this->tmpFilename) == 0) {
330  return;
331  }
332 
333  $filedir = $this->file->getDirectory($this->file->getVersion());
334 
335  if (!is_dir($filedir))
336  {
337  $this->file->createDirectory();
338  ilUtil::makeDir($filedir);
339  }
340 
341  $filename = $filedir."/".$this->file->getFileName();
342 
343  if (file_exists($filename))
344  unlink($filename);
345 
346  return rename($this->tmpFilename, $filename);
347  }
348 
349 
355  public function updateFileContents ()
356  {
357  if ($this->setFileContents())
358  {
359  require_once("./Services/History/classes/class.ilHistory.php");
360  ilHistory::_createEntry($this->file->getId(), "replace", $this->file->getFilename().",".$this->file->getVersion());
361  $this->file->addNewsNotification("file_updated");
362  }
363  }
364 
372  public function start () {
373  $this->startParsing();
374  return $this->result > 0;
375  }
376 
377 
390  public static function normalizeRelativePath($path) {
391  $path = str_replace('\\', '/', $path);
392 
393  while (preg_match('#\p{C}+|^\./#u', $path)) {
394  $path = preg_replace('#\p{C}+|^\./#u', '', $path);
395  }
396 
397  $parts = [];
398  foreach (explode('/', $path) as $part) {
399  switch ($part) {
400  case '':
401  case '.':
402  break;
403  case '..':
404  array_pop($parts);
405  break;
406  default:
407  $parts[] = $part;
408  break;
409  }
410  }
411 
412  return implode('/', $parts);
413  }
414 }
setImportDirectory($a_val)
Set import directory.
static normalizeRelativePath($path)
Normalize relative directories in a path.
startParsing()
stores xml data in array
Exercise XML Parser which completes/updates a given file by an xml string.
handlerEndTag($a_xml_parser, $a_name)
handler for end of element
Base class for sax-based expat parsing extended classes need to overwrite the method setHandlers and ...
start()
starts parsing an changes object by side effect.
static _lookupMimeType($a_file)
handlerCharacterData($a_xml_parser, $a_data)
handler for character data
_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.
$GLOBALS['ct_recipient']
Class to report exception.
ilFileXMLParser(& $file, $a_xml_data, $obj_id=-1, $mode=0)
Constructor.
$filename
Definition: buildRTE.php:89
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
setHandlers($a_xml_parser)
set event handlers
File storage handling.
fastBase64Decode($filein, $fileout)
decodes base encoded file row by row to prevent memory exhaust
updateFileContents()
update file according to filename and version and create history entry has to be called after (!) fil...
static ilTempnam()
Create a temporary file in an ILIAS writable directory.
$path
Definition: index.php:22
fastGunzip($in, $out)
fast uncompressing the file with the zlib-extension without memory consumption
getImportDirectory()
Get import directory.
setXMLContent($a_xml_content)
static __extractId($ilias_id, $inst_id)
extract ref id from role title, e.g.
handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
handler for begin of element
setFileContents()
update file according to filename and version, does not update history has to be called after (!) fil...