1<?php 2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4include_once 'Services/UIComponent/Toolbar/interfaces/interface.ilToolbarItem.php'; 5include_once("./Services/Form/classes/class.ilSubEnabledFormPropertyGUI.php"); 6 7/** 8* This class represents a file property in a property form. 9* 10* @author Alex Killing <alex.killing@gmx.de> 11* @version $Id$ 12* @ingroup ServicesForm 13*/ 14class ilFileInputGUI extends ilSubEnabledFormPropertyGUI implements ilToolbarItem 15{ 16 /** 17 * @var ilLanguage 18 */ 19 protected $lng; 20 21 private $filename; 22 private $filename_post; 23 protected $size = 40; 24 protected $pending; 25 protected $allow_deletion; 26 27 protected static $check_wsp_quota; 28 29 /** 30 * @var array 31 */ 32 protected $forbidden_suffixes = array(); 33 34 /** 35 * Constructor 36 * 37 * @param string $a_title Title 38 * @param string $a_postvar Post Variable 39 */ 40 public function __construct($a_title = "", $a_postvar = "") 41 { 42 global $DIC; 43 44 $this->lng = $DIC->language(); 45 $lng = $DIC->language(); 46 47 parent::__construct($a_title, $a_postvar); 48 $this->setType("file"); 49 $this->setHiddenTitle("(" . $lng->txt("form_file_input") . ")"); 50 } 51 52 /** 53 * Set value by array 54 * 55 * @param array $a_values value array 56 */ 57 public function setValueByArray($a_values) 58 { 59 if (!is_array($a_values[$this->getPostVar()])) { 60 $this->setValue($a_values[$this->getPostVar()]); 61 } 62 $this->setFilename($a_values[$this->getFileNamePostVar()]); 63 } 64 65 /** 66 * Set Value. (used for displaying file title of existing file below input field) 67 * 68 * @param string $a_value Value 69 */ 70 public function setValue($a_value) 71 { 72 $this->value = $a_value; 73 } 74 75 /** 76 * Get Value. 77 * 78 * @return string Value 79 */ 80 public function getValue() 81 { 82 return $this->value; 83 } 84 85 /** 86 * Set Size. 87 * 88 * @param int $a_size Size 89 */ 90 public function setSize($a_size) 91 { 92 $this->size = $a_size; 93 } 94 95 /** 96 * Get Size. 97 * 98 * @return int Size 99 */ 100 public function getSize() 101 { 102 return $this->size; 103 } 104 105 /** 106 * Set filename value (if filename selection is enabled) 107 * 108 * @param string $a_val 109 */ 110 public function setFilename($a_val) 111 { 112 $this->filename = $a_val; 113 } 114 115 /** 116 * Get Value. 117 * 118 * @return string Value 119 */ 120 public function getFilename() 121 { 122 return $this->filename; 123 } 124 125 126 127 /** 128 * Set Accepted Suffixes. 129 * 130 * @param array $a_suffixes Accepted Suffixes 131 */ 132 public function setSuffixes($a_suffixes) 133 { 134 $this->suffixes = $a_suffixes; 135 } 136 137 /** 138 * Get Accepted Suffixes. 139 * 140 * @return array Accepted Suffixes 141 */ 142 public function getSuffixes() 143 { 144 return $this->suffixes; 145 } 146 147 /** 148 * Set forbidden Suffixes. 149 * 150 * @param array $a_suffixes forbidden Suffixes 151 */ 152 public function setForbiddenSuffixes($a_suffixes) 153 { 154 $this->forbidden_suffixes = $a_suffixes; 155 } 156 157 /** 158 * Get Accepted Suffixes. 159 * 160 * @return array forbidden Suffixes 161 */ 162 public function getForbiddenSuffixes() 163 { 164 return $this->forbidden_suffixes; 165 } 166 167 /** 168 * Set pending filename value 169 * 170 * @param string $a_val 171 */ 172 public function setPending($a_val) 173 { 174 $this->pending = $a_val; 175 } 176 177 /** 178 * Get pending filename 179 * 180 * @return string Value 181 */ 182 public function getPending() 183 { 184 return $this->pending; 185 } 186 187 /** 188 * If enabled, users get the possibility to enter a filename for the uploaded file 189 * 190 * @access public 191 * @param string post variable 192 * 193 */ 194 public function enableFileNameSelection($a_post_var) 195 { 196 $this->filename_selection = true; 197 $this->filename_post = $a_post_var; 198 } 199 200 /** 201 * Check if filename selection is enabled 202 * 203 * @access public 204 * @return bool enabled/disabled 205 */ 206 public function isFileNameSelectionEnabled() 207 { 208 return $this->filename_selection ? true : false; 209 } 210 211 /** 212 * Get file name post var 213 * 214 * @access public 215 * @param string file name post var 216 * 217 */ 218 public function getFileNamePostVar() 219 { 220 return $this->filename_post; 221 } 222 223 /** 224 * Set allow deletion 225 * 226 * @param boolean $a_val allow deletion 227 */ 228 public function setALlowDeletion($a_val) 229 { 230 $this->allow_deletion = $a_val; 231 } 232 233 /** 234 * Get allow deletion 235 * 236 * @return boolean allow deletion 237 */ 238 public function getALlowDeletion() 239 { 240 return $this->allow_deletion; 241 } 242 243 /** 244 * Check input, strip slashes etc. set alert, if input is not ok. 245 * 246 * @return boolean Input ok, true/false 247 */ 248 public function checkInput() 249 { 250 $lng = $this->lng; 251 252 // #18756 253 if ($this->getDisabled()) { 254 return true; 255 } 256 257 // if no information is received, something went wrong 258 // this is e.g. the case, if the post_max_size has been exceeded 259 if (!is_array($_FILES[$this->getPostVar()])) { 260 $this->setAlert($lng->txt("form_msg_file_size_exceeds")); 261 return false; 262 } 263 264 $_FILES[$this->getPostVar()]["name"] = ilUtil::stripSlashes($_FILES[$this->getPostVar()]["name"]); 265 266 include_once("./Services/Utilities/classes/class.ilStr.php"); 267 $_FILES[$this->getPostVar()]["name"] = ilStr::normalizeUtf8String($_FILES[$this->getPostVar()]["name"]); 268 269 // remove trailing '/' 270 $_FILES[$this->getPostVar()]["name"] = rtrim($_FILES[$this->getPostVar()]["name"], '/'); 271 272 $filename = $_FILES[$this->getPostVar()]["name"]; 273 $filename_arr = pathinfo($_FILES[$this->getPostVar()]["name"]); 274 $suffix = $filename_arr["extension"]; 275 $mimetype = $_FILES[$this->getPostVar()]["type"]; 276 $size_bytes = $_FILES[$this->getPostVar()]["size"]; 277 $temp_name = $_FILES[$this->getPostVar()]["tmp_name"]; 278 $error = $_FILES[$this->getPostVar()]["error"]; 279 $_POST[$this->getPostVar()] = $_FILES[$this->getPostVar()]; 280 281 // error handling 282 if ($error > 0) { 283 switch ($error) { 284 case UPLOAD_ERR_INI_SIZE: 285 $this->setAlert($lng->txt("form_msg_file_size_exceeds")); 286 return false; 287 break; 288 289 case UPLOAD_ERR_FORM_SIZE: 290 $this->setAlert($lng->txt("form_msg_file_size_exceeds")); 291 return false; 292 break; 293 294 case UPLOAD_ERR_PARTIAL: 295 $this->setAlert($lng->txt("form_msg_file_partially_uploaded")); 296 return false; 297 break; 298 299 case UPLOAD_ERR_NO_FILE: 300 if ($this->getRequired()) { 301 if (!strlen($this->getValue())) { 302 $this->setAlert($lng->txt("form_msg_file_no_upload")); 303 return false; 304 } 305 } 306 break; 307 308 case UPLOAD_ERR_NO_TMP_DIR: 309 $this->setAlert($lng->txt("form_msg_file_missing_tmp_dir")); 310 return false; 311 break; 312 313 case UPLOAD_ERR_CANT_WRITE: 314 $this->setAlert($lng->txt("form_msg_file_cannot_write_to_disk")); 315 return false; 316 break; 317 318 case UPLOAD_ERR_EXTENSION: 319 $this->setAlert($lng->txt("form_msg_file_upload_stopped_ext")); 320 return false; 321 break; 322 } 323 } 324 325 // check suffixes 326 if ($_FILES[$this->getPostVar()]["tmp_name"] != "") { 327 if (is_array($this->forbidden_suffixes) && in_array(strtolower($suffix), $this->forbidden_suffixes)) { 328 $this->setAlert($lng->txt("form_msg_file_type_is_not_allowed") . " (" . $suffix . ")"); 329 return false; 330 } 331 if (is_array($this->getSuffixes()) && count($this->getSuffixes()) > 0) { 332 if (!in_array(strtolower($suffix), $this->getSuffixes())) { 333 $this->setAlert($lng->txt("form_msg_file_wrong_file_type")); 334 return false; 335 } 336 } 337 } 338 339 // virus handling 340 if ($_FILES[$this->getPostVar()]["tmp_name"] != "") { 341 $vir = ilUtil::virusHandling($temp_name, $filename); 342 if ($vir[0] == false) { 343 $this->setAlert($lng->txt("form_msg_file_virus_found") . "<br />" . $vir[1]); 344 return false; 345 } 346 } 347 348 return true; 349 } 350 351 /** 352 * Render html 353 */ 354 public function render($a_mode = "") 355 { 356 $lng = $this->lng; 357 358 $quota_exceeded = $quota_legend = false; 359 if (self::$check_wsp_quota) { 360 include_once "Services/DiskQuota/classes/class.ilDiskQuotaHandler.php"; 361 if (!ilDiskQuotaHandler::isUploadPossible()) { 362 $lng->loadLanguageModule("file"); 363 $quota_exceeded = $lng->txt("personal_resources_quota_exceeded_warning"); 364 } else { 365 $quota_legend = ilDiskQuotaHandler::getStatusLegend(); 366 } 367 } 368 369 $f_tpl = new ilTemplate("tpl.prop_file.html", true, true, "Services/Form"); 370 371 372 // show filename selection if enabled 373 if ($this->isFileNameSelectionEnabled()) { 374 $f_tpl->setCurrentBlock('filename'); 375 $f_tpl->setVariable('POST_FILENAME', $this->getFileNamePostVar()); 376 $f_tpl->setVariable('VAL_FILENAME', $this->getFilename()); 377 $f_tpl->setVariable('FILENAME_ID', $this->getFieldId()); 378 $f_tpl->setVAriable('TXT_FILENAME_HINT', $lng->txt('if_no_title_then_filename')); 379 $f_tpl->parseCurrentBlock(); 380 } else { 381 if (trim($this->getValue() != "")) { 382 if (!$this->getDisabled() && $this->getALlowDeletion()) { 383 $f_tpl->setCurrentBlock("delete_bl"); 384 $f_tpl->setVariable("POST_VAR_D", $this->getPostVar()); 385 $f_tpl->setVariable( 386 "TXT_DELETE_EXISTING", 387 $lng->txt("delete_existing_file") 388 ); 389 $f_tpl->parseCurrentBlock(); 390 } 391 392 $f_tpl->setCurrentBlock('prop_file_propval'); 393 $f_tpl->setVariable('FILE_VAL', $this->getValue()); 394 $f_tpl->parseCurrentBlock(); 395 } 396 } 397 398 if ($a_mode != "toolbar") { 399 if (!$quota_exceeded) { 400 $this->outputSuffixes($f_tpl); 401 402 $f_tpl->setCurrentBlock("max_size"); 403 $f_tpl->setVariable("TXT_MAX_SIZE", $lng->txt("file_notice") . " " . 404 $this->getMaxFileSizeString()); 405 $f_tpl->parseCurrentBlock(); 406 407 if ($quota_legend) { 408 $f_tpl->setVariable("TXT_MAX_SIZE", $quota_legend); 409 $f_tpl->parseCurrentBlock(); 410 } 411 } else { 412 $f_tpl->setCurrentBlock("max_size"); 413 $f_tpl->setVariable("TXT_MAX_SIZE", $quota_exceeded); 414 $f_tpl->parseCurrentBlock(); 415 } 416 } elseif ($quota_exceeded) { 417 return $quota_exceeded; 418 } 419 420 $pending = $this->getPending(); 421 if ($pending) { 422 $f_tpl->setCurrentBlock("pending"); 423 $f_tpl->setVariable("TXT_PENDING", $lng->txt("file_upload_pending") . 424 ": " . $pending); 425 $f_tpl->parseCurrentBlock(); 426 } 427 428 if ($this->getDisabled() || $quota_exceeded) { 429 $f_tpl->setVariable( 430 "DISABLED", 431 " disabled=\"disabled\"" 432 ); 433 } 434 435 $f_tpl->setVariable("POST_VAR", $this->getPostVar()); 436 $f_tpl->setVariable("ID", $this->getFieldId()); 437 $f_tpl->setVariable("SIZE", $this->getSize()); 438 439 440 /* experimental: bootstrap'ed file upload */ 441 $f_tpl->setVariable("TXT_BROWSE", $lng->txt("select_file")); 442 443 444 return $f_tpl->get(); 445 } 446 447 /** 448 * Insert property html 449 * 450 * @return int Size 451 */ 452 public function insert($a_tpl) 453 { 454 $html = $this->render(); 455 456 $a_tpl->setCurrentBlock("prop_generic"); 457 $a_tpl->setVariable("PROP_GENERIC", $html); 458 $a_tpl->parseCurrentBlock(); 459 } 460 461 462 protected function outputSuffixes($a_tpl, $a_block = "allowed_suffixes") 463 { 464 $lng = $this->lng; 465 466 if (is_array($this->getSuffixes()) && count($this->getSuffixes()) > 0) { 467 $suff_str = $delim = ""; 468 foreach ($this->getSuffixes() as $suffix) { 469 $suff_str .= $delim . "." . $suffix; 470 $delim = ", "; 471 } 472 $a_tpl->setCurrentBlock($a_block); 473 $a_tpl->setVariable( 474 "TXT_ALLOWED_SUFFIXES", 475 $lng->txt("file_allowed_suffixes") . " " . $suff_str 476 ); 477 $a_tpl->parseCurrentBlock(); 478 } 479 } 480 481 protected function getMaxFileSizeString() 482 { 483 // get the value for the maximal uploadable filesize from the php.ini (if available) 484 $umf = ini_get("upload_max_filesize"); 485 // get the value for the maximal post data from the php.ini (if available) 486 $pms = ini_get("post_max_size"); 487 488 //convert from short-string representation to "real" bytes 489 $multiplier_a = array("K" => 1024, "M" => 1024 * 1024, "G" => 1024 * 1024 * 1024); 490 491 $umf_parts = preg_split("/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); 492 $pms_parts = preg_split("/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); 493 494 if (count($umf_parts) == 2) { 495 $umf = $umf_parts[0] * $multiplier_a[$umf_parts[1]]; 496 } 497 if (count($pms_parts) == 2) { 498 $pms = $pms_parts[0] * $multiplier_a[$pms_parts[1]]; 499 } 500 501 // use the smaller one as limit 502 $max_filesize = min($umf, $pms); 503 504 if (!$max_filesize) { 505 $max_filesize = max($umf, $pms); 506 } 507 508 //format for display in mega-bytes 509 $max_filesize = sprintf("%.1f MB", $max_filesize / 1024 / 1024); 510 511 return $max_filesize; 512 } 513 514 /** 515 * Get number of maximum file uploads as declared in php.ini 516 * 517 * @return int 518 */ 519 protected function getMaxFileUploads() 520 { 521 return (int) ini_get("max_file_uploads"); 522 } 523 524 /** 525 * Get deletion flag 526 */ 527 public function getDeletionFlag() 528 { 529 if ($_POST[$this->getPostVar() . "_delete"]) { 530 return true; 531 } 532 return false; 533 } 534 535 /** 536 * Get HTML for toolbar 537 */ 538 public function getToolbarHTML() 539 { 540 $html = $this->render("toolbar"); 541 return $html; 542 } 543 544 public static function setPersonalWorkspaceQuotaCheck($a_value) 545 { 546 if ((bool) $a_value) { 547 if (ilDiskQuotaActivationChecker::_isPersonalWorkspaceActive()) { 548 self::$check_wsp_quota = true; 549 return; 550 } 551 } 552 self::$check_wsp_quota = false; 553 } 554} 555