ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assFileUpload.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
24 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
25 
34 {
35  protected $maxsize;
36  protected $allowedextensions;
37 
50  function __construct(
51  $title = "",
52  $comment = "",
53  $author = "",
54  $owner = -1,
55  $question = ""
56  )
57  {
59  }
60 
66  public function isComplete()
67  {
68  if (($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() > 0))
69  {
70  return true;
71  }
72  else
73  {
74  return false;
75  }
76  }
77 
82  public function saveToDb($original_id = "")
83  {
84  global $ilDB;
85 
87 
88  // save additional data
89 
90  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
91  array("integer"),
92  array($this->getId())
93  );
94  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, maxsize, allowedextensions) VALUES (%s, %s, %s)",
95  array("integer", "float", "text"),
96  array(
97  $this->getId(),
98  (strlen($this->getMaxSize())) ? $this->getMaxSize() : NULL,
99  (strlen($this->getAllowedExtensions())) ? $this->getAllowedExtensions() : NULL
100  )
101  );
103  }
104 
111  public function loadFromDb($question_id)
112  {
113  global $ilDB;
114  $result = $ilDB->queryF("SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
115  array("integer"),
116  array($question_id)
117  );
118  if ($result->numRows() == 1)
119  {
120  $data = $ilDB->fetchAssoc($result);
121  $this->setId($question_id);
122  $this->setTitle($data["title"]);
123  $this->setComment($data["description"]);
124  $this->setNrOfTries($data['nr_of_tries']);
125  $this->setSuggestedSolution($data["solution_hint"]);
126  $this->setOriginalId($data["original_id"]);
127  $this->setObjId($data["obj_fi"]);
128  $this->setAuthor($data["author"]);
129  $this->setOwner($data["owner"]);
130  $this->setPoints($data["points"]);
131 
132  include_once("./Services/RTE/classes/class.ilRTE.php");
133  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
134  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
135  $this->setMaxSize($data["maxsize"]);
136  $this->setAllowedExtensions($data["allowedextensions"]);
137  }
138  parent::loadFromDb($question_id);
139  }
140 
144  public function duplicate($for_test = true, $title = "", $author = "", $owner = "")
145  {
146  if ($this->id <= 0)
147  {
148  // The question has not been saved. It cannot be duplicated
149  return;
150  }
151  // duplicate the question in database
152  $this_id = $this->getId();
153  $clone = $this;
154  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
156  $clone->id = -1;
157  if ($title)
158  {
159  $clone->setTitle($title);
160  }
161 
162  if ($author)
163  {
164  $clone->setAuthor($author);
165  }
166  if ($owner)
167  {
168  $clone->setOwner($owner);
169  }
170 
171  if ($for_test)
172  {
173  $clone->saveToDb($original_id);
174  }
175  else
176  {
177  $clone->saveToDb();
178  }
179 
180  // copy question page content
181  $clone->copyPageOfQuestion($this_id);
182  // copy XHTML media objects
183  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
184  // duplicate the generic feedback
185  $clone->duplicateFeedbackGeneric($this_id);
186 
187  $clone->onDuplicate($this_id);
188  return $clone->id;
189  }
190 
194  public function copyObject($target_questionpool, $title = "")
195  {
196  if ($this->id <= 0)
197  {
198  // The question has not been saved. It cannot be duplicated
199  return;
200  }
201  // duplicate the question in database
202  $clone = $this;
203  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
205  $clone->id = -1;
206  $source_questionpool = $this->getObjId();
207  $clone->setObjId($target_questionpool);
208  if ($title)
209  {
210  $clone->setTitle($title);
211  }
212  $clone->saveToDb();
213 
214  // copy question page content
215  $clone->copyPageOfQuestion($original_id);
216  // copy XHTML media objects
217  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
218  // duplicate the generic feedback
219  $clone->duplicateFeedbackGeneric($original_id);
220 
221  $clone->onCopy($this->getObjId(), $this->getId());
222 
223  return $clone->id;
224  }
225 
231  public function getMaximumPoints()
232  {
233  return $this->getPoints();
234  }
235 
244  public function calculateReachedPoints($active_id, $pass = NULL)
245  {
246  global $ilDB;
247 
248  if (is_null($pass))
249  {
250  $pass = $this->getSolutionMaxPass($active_id);
251  }
252  $points = 0;
253  $points = parent::calculateReachedPoints($active_id, $pass = NULL, $points);
254  return $points;
255  }
256 
262  function checkUpload()
263  {
264  $this->lng->loadLanguageModule("form");
265  // remove trailing '/'
266  while (substr($_FILES["upload"]["name"],-1) == '/')
267  {
268  $_FILES["upload"]["name"] = substr($_FILES["upload"]["name"],0,-1);
269  }
270 
271  $filename = $_FILES["upload"]["name"];
272  $filename_arr = pathinfo($_FILES["upload"]["name"]);
273  $suffix = $filename_arr["extension"];
274  $mimetype = $_FILES["upload"]["type"];
275  $size_bytes = $_FILES["upload"]["size"];
276  $temp_name = $_FILES["upload"]["tmp_name"];
277  $error = $_FILES["upload"]["error"];
278 
279  if ($size_bytes > $this->getMaxFilesizeInBytes())
280  {
281  ilUtil::sendInfo($this->lng->txt("form_msg_file_size_exceeds"), true);
282  return false;
283  }
284 
285  // error handling
286  if ($error > 0)
287  {
288  switch ($error)
289  {
290  case UPLOAD_ERR_INI_SIZE:
291  ilUtil::sendInfo($this->lng->txt("form_msg_file_size_exceeds"), true);
292  return false;
293  break;
294 
295  case UPLOAD_ERR_FORM_SIZE:
296  ilUtil::sendInfo($this->lng->txt("form_msg_file_size_exceeds"), true);
297  return false;
298  break;
299 
300  case UPLOAD_ERR_PARTIAL:
301  ilUtil::sendInfo($this->lng->txt("form_msg_file_partially_uploaded"), true);
302  return false;
303  break;
304 
305  case UPLOAD_ERR_NO_FILE:
306  ilUtil::sendInfo($this->lng->txt("form_msg_file_no_upload"), true);
307  return false;
308  break;
309 
310  case UPLOAD_ERR_NO_TMP_DIR:
311  ilUtil::sendInfo($this->lng->txt("form_msg_file_missing_tmp_dir"), true);
312  return false;
313  break;
314 
315  case UPLOAD_ERR_CANT_WRITE:
316  ilUtil::sendInfo($this->lng->txt("form_msg_file_cannot_write_to_disk"), true);
317  return false;
318  break;
319 
320  case UPLOAD_ERR_EXTENSION:
321  ilUtil::sendInfo($this->lng->txt("form_msg_file_upload_stopped_ext"), true);
322  return false;
323  break;
324  }
325  }
326 
327  // check suffixes
328  if (strlen($suffix) && count($this->getAllowedExtensionsArray()))
329  {
330  if (!in_array(strtolower($suffix), $this->getAllowedExtensionsArray()))
331  {
332  ilUtil::sendInfo($this->lng->txt("form_msg_file_wrong_file_type"), true);
333  return false;
334  }
335  }
336 
337  // virus handling
338  if (strlen($temp_name))
339  {
340  $vir = ilUtil::virusHandling($temp_name, $filename);
341  if ($vir[0] == false)
342  {
343  ilUtil::sendInfo($this->lng->txt("form_msg_file_virus_found")."<br />".$vir[1], true);
344  return false;
345  }
346  }
347  return true;
348  }
349 
353  protected function getFileUploadPath($test_id, $active_id, $question_id = null)
354  {
355  if (is_null($question_id)) $question_id = $this->getId();
356  return CLIENT_WEB_DIR . "/assessment/tst_$test_id/$active_id/$question_id/files/";
357  }
358 
364  function getFileUploadPathWeb($test_id, $active_id, $question_id = null)
365  {
366  if (is_null($question_id)) $question_id = $this->getId();
367  include_once "./Services/Utilities/classes/class.ilUtil.php";
368  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/tst_$test_id/$active_id/$question_id/files/";
370  }
371 
377  public function getUploadedFiles($active_id, $pass = null)
378  {
379  global $ilDB;
380  if (is_null($pass))
381  {
382  $pass = $this->getSolutionMaxPass($active_id);
383  }
384  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s ORDER BY tstamp",
385  array("integer", "integer", "integer"),
386  array($active_id, $this->getId(), $pass)
387  );
388  $found = array();
389  while ($data = $ilDB->fetchAssoc($result))
390  {
391  array_push($found, $data);
392  }
393  return $found;
394  }
395 
401  public function getUploadedFilesForWeb($active_id, $pass)
402  {
403  global $ilDB;
404 
405  $found = $this->getUploadedFiles($active_id, $pass);
406  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
407  array('integer'),
408  array($active_id)
409  );
410  if ($result->numRows() == 1)
411  {
412  $row = $ilDB->fetchAssoc($result);
413  $test_id = $row["test_fi"];
414  $path = $this->getFileUploadPathWeb($test_id, $active_id);
415  foreach ($found as $idx => $data)
416  {
417  $found[$idx]['webpath'] = $path;
418  }
419  }
420  return $found;
421  }
422 
428  protected function deleteUploadedFiles($files, $test_id, $active_id)
429  {
430  global $ilDB;
431 
432  $pass = null;
433  $active_id = null;
434  foreach ($files as $solution_id)
435  {
436  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE solution_id = %s",
437  array("integer"),
438  array($solution_id)
439  );
440  if ($result->numRows() == 1)
441  {
442  $data = $ilDB->fetchAssoc($result);
443  $pass = $data['pass'];
444  $active_id = $data['active_fi'];
445  @unlink($this->getFileUploadPath($test_id, $active_id) . $data['value1']);
446  }
447  }
448  foreach ($files as $solution_id)
449  {
450  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE solution_id = %s",
451  array("integer"),
452  array($solution_id)
453  );
454  }
455  }
456 
462  public function getMaxFilesizeAsString()
463  {
464  $size = $this->getMaxFilesizeInBytes();
465  if ($size < 1024)
466  {
467  $max_filesize = sprintf("%.1f Bytes",$size);
468  }
469  else if ($size < 1024*1024)
470  {
471  $max_filesize = sprintf("%.1f KB",$size/1024);
472  }
473  else
474  {
475  $max_filesize = sprintf("%.1f MB",$size/1024/1024);
476  }
477 
478  return $max_filesize;
479  }
480 
486  public function getMaxFilesizeInBytes()
487  {
488  if (strlen($this->getMaxSize()))
489  {
490  return $this->getMaxSize();
491  }
492  else
493  {
494  // get the value for the maximal uploadable filesize from the php.ini (if available)
495  $umf = get_cfg_var("upload_max_filesize");
496  // get the value for the maximal post data from the php.ini (if available)
497  $pms = get_cfg_var("post_max_size");
498 
499  //convert from short-string representation to "real" bytes
500  $multiplier_a=array("K"=>1024, "M"=>1024*1024, "G"=>1024*1024*1024);
501 
502  $umf_parts=preg_split("/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
503  $pms_parts=preg_split("/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
504 
505  if (count($umf_parts) == 2) { $umf = $umf_parts[0]*$multiplier_a[$umf_parts[1]]; }
506  if (count($pms_parts) == 2) { $pms = $pms_parts[0]*$multiplier_a[$pms_parts[1]]; }
507 
508  // use the smaller one as limit
509  $max_filesize = min($umf, $pms);
510 
511  if (!$max_filesize) $max_filesize=max($umf, $pms);
512  return $max_filesize;
513  }
514  }
515 
523  public function saveWorkingData($active_id, $pass = NULL)
524  {
525  global $ilDB;
526  global $ilUser;
527 
528  if (is_null($pass))
529  {
530  include_once "./Modules/Test/classes/class.ilObjTest.php";
531  $pass = ilObjTest::_getPass($active_id);
532  }
533 
534  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
535  array('integer'),
536  array($active_id)
537  );
538  $test_id = 0;
539  if ($result->numRows() == 1)
540  {
541  $row = $ilDB->fetchAssoc($result);
542  $test_id = $row["test_fi"];
543  }
544 
545  $entered_values = false;
546  if (strcmp($_POST['cmd']['gotoquestion'], $this->lng->txt('delete')) == 0)
547  {
548  $deletefiles = $_POST['file'];
549  if (is_array($deletefiles) && count($deletefiles) > 0)
550  {
551  $this->deleteUploadedFiles($deletefiles, $test_id, $active_id);
552  }
553  else
554  {
555  ilUtil::sendInfo($this->lng->txt('no_checkbox'), true);
556  }
557  }
558  else
559  {
560  if (strlen($_FILES["upload"]["tmp_name"]))
561  {
562  if ($this->checkUpload())
563  {
564  if (!@file_exists($this->getFileUploadPath($test_id, $active_id))) ilUtil::makeDirParents($this->getFileUploadPath($test_id, $active_id));
565  $version = time();
566  $filename_arr = pathinfo($_FILES["upload"]["name"]);
567  $extension = $filename_arr["extension"];
568  $newfile = "file_" . $active_id . "_" . $pass . "_" . $version . "." . $extension;
569  ilUtil::moveUploadedFile($_FILES["upload"]["tmp_name"], $_FILES["upload"]["name"], $this->getFileUploadPath($test_id, $active_id) . $newfile);
570  $next_id = $ilDB->nextId('tst_solutions');
571  $affectedRows = $ilDB->insert("tst_solutions", array(
572  "solution_id" => array("integer", $next_id),
573  "active_fi" => array("integer", $active_id),
574  "question_fi" => array("integer", $this->getId()),
575  "value1" => array("clob", $newfile),
576  "value2" => array("clob", $_FILES['upload']['name']),
577  "pass" => array("integer", $pass),
578  "tstamp" => array("integer", time())
579  ));
580  $entered_values = true;
581  }
582  }
583  }
584  if ($entered_values)
585  {
586  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
588  {
589  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
590  }
591  }
592  else
593  {
594  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
596  {
597  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
598  }
599  }
600  parent::saveWorkingData($active_id, $pass);
601  return true;
602  }
603 
609  public function getQuestionType()
610  {
611  return "assFileUpload";
612  }
613 
619  public function getAdditionalTableName()
620  {
621  return "qpl_qst_fileupload";
622  }
623 
629  public function getAnswerTableName()
630  {
631  return "";
632  }
633 
639  public function deleteAnswers($question_id)
640  {
641  }
642 
647  public function getRTETextWithMediaObjects()
648  {
650  return $text;
651  }
652 
661  public function setExportDetailsXLS(&$adapter, $startrow, $active_id, $pass)
662  {
663  $adapter->setCellValue($startrow, 0, $this->lng->txt($this->getQuestionType()), CELL_FORMAT_TITLE);
664  $adapter->setCellValue($startrow, 1, $this->getTitle(), CELL_FORMAT_TITLE);
665 // $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
666 // $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
667  $i = 1;
668  $solutions = $this->getSolutionValues($active_id, $pass);
669  foreach ($solutions as $solution)
670  {
671  $adapter->setCellValue($startrow + $i, 0, $this->lng->txt("result"), CELL_FORMAT_BOLD);
672 // $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($this->lng->txt("result")), $format_bold);
673  if (strlen($solution["value1"]))
674  {
675  $adapter->setCellValue($startrow + $i, 1, $solution["value1"]);
676  $adapter->setCellValue($startrow + $i, 2, $solution["value2"]);
677 // $worksheet->write($startrow + $i, 1, ilExcelUtils::_convert_text($solution["value1"]));
678 // $worksheet->write($startrow + $i, 2, ilExcelUtils::_convert_text($solution["value2"]));
679  }
680  $i++;
681  }
682  return $startrow + $i + 1;
683  }
684 
697  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
698  {
699  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assFileUploadImport.php";
700  $import = new assFileUploadImport($this);
701  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
702  }
703 
710  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
711  {
712  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assFileUploadExport.php";
713  $export = new assFileUploadExport($this);
714  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
715  }
716 
722  public function getBestSolution($active_id, $pass)
723  {
724  $user_solution = array();
725  return $user_solution;
726  }
727 
733  public function getMaxSize()
734  {
735  return $this->maxsize;
736  }
737 
743  public function setMaxSize($a_value)
744  {
745  $this->maxsize = $a_value;
746  }
747 
753  public function getAllowedExtensionsArray()
754  {
755  if (strlen($this->allowedextensions))
756  {
757  return split(",", $this->allowedextensions);
758  }
759  return array();
760  }
761 
767  public function getAllowedExtensions()
768  {
770  }
771 
777  public function setAllowedExtensions($a_value)
778  {
779  $this->allowedextensions = strtolower(trim($a_value));
780  }
781 
785  public function __get($value)
786  {
787  switch ($value)
788  {
789  case "maxsize":
790  return $this->getMaxSize();
791  break;
792  case "allowedextensions":
793  return $this->getAllowedExtensions();
794  break;
795  default:
796  return parent::__get($value);
797  break;
798  }
799  }
800 
804  public function __set($key, $value)
805  {
806  switch ($key)
807  {
808  case "maxsize":
809  $this->setMaxSize($value);
810  break;
811  case "allowedextensions":
812  $this->setAllowedExtensions($value);
813  break;
814  default:
815  parent::__set($key, $value);
816  break;
817  }
818  }
819 
825  public function hasFileUploads($test_id)
826  {
827  global $ilDB;
828  $result = $ilDB->queryF("SELECT tst_solutions.solution_id FROM tst_solutions, tst_active, qpl_questions WHERE tst_solutions.active_fi = tst_active.active_id AND tst_solutions.question_fi = qpl_questions.question_id AND qpl_questions.question_id = %s AND tst_active.test_fi = %s",
829  array("integer", "integer"),
830  array($this->getId(), $test_id)
831  );
832  if ($result->numRows() > 0)
833  {
834  return true;
835  }
836  else
837  {
838  return false;
839  }
840  }
841 
846  {
847  global $ilDB, $ilLog;
848  $result = $ilDB->queryF("SELECT tst_solutions.solution_id, tst_solutions.pass, tst_solutions.active_fi, tst_solutions.question_fi, tst_solutions.value1, tst_solutions.value2, tst_solutions.tstamp FROM tst_solutions, tst_active, qpl_questions WHERE tst_solutions.active_fi = tst_active.active_id AND tst_solutions.question_fi = qpl_questions.question_id AND qpl_questions.question_id = %s AND tst_active.test_fi = %s ORDER BY tst_solutions.active_fi, tst_solutions.tstamp",
849  array("integer", "integer"),
850  array($this->getId(), $test_id)
851  );
852  $zipfile = ilUtil::ilTempnam() . ".zip";
853  $tempdir = ilUtil::ilTempnam();
854  if ($result->numRows())
855  {
856  $userdata = array();
857  $data .= "<html><head>";
858  $data .= '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />';
859  $data .= '<style>
860  table { border: 1px #333 solid; border-collapse:collapse;}
861  td, th { border: 1px #333 solid; padding: 0.25em;}
862  th { color: #fff; background-color: #666;}
863  </style>
864  ';
865  $data .= "<title>" . $this->getTitle() . "</title></head><body>\n";
866  $data .= "<h1>" . $this->getTitle() . "</h1>\n";
867  $data .= "<table><thead>\n";
868  $data .= "<tr><th>" . $this->lng->txt("name") . "</th><th>" . $this->lng->txt("filename") . "</th><th>" . $this->lng->txt("pass") . "</th><th>" . $this->lng->txt("location") . "</th><th>" . $this->lng->txt("date") . "</th></tr></thead><tbody>\n";
869  while ($row = $ilDB->fetchAssoc($result))
870  {
871  ilUtil::makeDirParents($tempdir . "/" . $row["active_fi"]."/".$row["question_fi"]);
872  @copy($this->getFileUploadPath($test_id, $row["active_fi"], $row["question_fi"]) . $row["value1"], $tempdir . "/" . $row["active_fi"]."/".$row["question_fi"] . "/" . $row["value1"]);
873  if (!array_key_exists($row["active_fi"], $userdata))
874  {
875  include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
876  $userdata[$row["active_fi"]] = ilObjTestAccess::_getParticipantData($row["active_fi"]);
877  }
878  $data .= "<tr><td>".$userdata[$row["active_fi"]]."</td><td><a href=\"".$row["active_fi"]."/".$row["question_fi"]."/".$row["value1"]."\" target=\"_blank\">".$row["value2"]."</a></td><td>".$row["pass"]."</td><td>".$row["active_fi"]."/".$row["question_fi"]."/".$row["value1"]."</td>";
879  $data .= "<td>" . ilFormat::fmtDateTime(ilFormat::unixtimestamp2datetime($row["tstamp"]), $this->lng->txt("lang_dateformat"), $this->lng->txt("lang_timeformat"), "datetime", FALSE) . "</td>";
880  $data .= "</tr>\n";
881  }
882  $data .= "</tbody></table>\n";
883  $data .= "</body></html>\n";
884 
885  $indexfile = $tempdir . "/index.html";
886  $fh = fopen($indexfile, 'w');
887  fwrite($fh, $data);
888  fclose($fh);
889  }
890  ilUtil::zip($tempdir, $zipfile);
891  ilUtil::delDir($tempdir);
892  ilUtil::deliverFile($zipfile, ilUtil::getASCIIFilename($this->getTitle().".zip"), "application/zip", false, true);
893  }
894 }
895 
896 ?>