public function HandleUpload($uploadDirectory) { // Security issue: when upload is disabled, stop here if (!(bool) $this->Params->get("uploaddisplay", 0)) { return array('error' => " [upload disabled]"); } if (!is_writable($uploadDirectory)) { return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_DIR_NOT_WRITABLE')); } // Check file size $size = $this->get_file_size(); if ($size == 0) { return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_FILE_EMPTY')); } // uploadmax_file_size defaults to 0 to prevent hack attempts $max = $this->Params->get("uploadmax_file_size", 0) * KB; // and < max limit if ($size > $max) { return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_FILE_TOO_LARGE')); } $realname = $this->get_file_name(); // Keep the client name untouched, and start working on a server side name $filename = JFilterInput::getInstance()->clean($realname, "cmd"); // Forbid Directory Traversal by removing residual directory $filename = basename($filename); // Forbid initial and final dots $realname = trim($this->get_file_name(), '.'); // Block scripts based on their extension $forbidden_extensions = '/ph(p[345st]?|t|tml|ar)/i'; // php|php3|php4|php5|phps|phpt|pht|phtml|phar if (preg_match($forbidden_extensions, $filename)) { $this->Log->Write("Blocked a file upload attempt [forbidden extension]: " . $filename); // dangerous file extension return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_MIME') . " [forbidden extension]"); } // Assign a random unique id to the file name $filename = uniqid() . "-" . $filename; $full_filename = $uploadDirectory . $filename; if (!$this->save_file($full_filename)) { return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_SAVE_FILE')); } $mimetype = new FMimeType(); if (!$mimetype->Check($full_filename, $this->Params)) { // Delete the file uploaded unlink($full_filename); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_MIME') . " [" . $mimetype->Mimetype . "]"); } // Read the current file list from the session $filelist = $this->session->get("filelist", array(), $this->namespace); // Block further uploads once exceeded the max limit if (count($filelist) >= $this->Params->get("upload_max_files", 10)) { return array("error" => JText::_("COM_FOXCONTACT_ERR_MAX_UPLOAD_FILES_EXCEEDED")); } // Block scripts based on their content. To avoid memory limitations which may vary based on the server configuration, analyzes the file in chunks of a reasonable length. $chunk_size = 1048576; // 1Mb $back_step = -6; // Given by strlen('<script') - 1 // Open the file $handle = fopen($full_filename, "rb"); do { // Read a chunk $content = fread($handle, $chunk_size); // Take back the file pointer in case we are ended just in the middle of the string we have to find fseek($handle, $back_step, SEEK_CUR); // search for the string if (strpos($content, '<?php') !== false || strpos($content, '<script') !== false) { // contains php directive fclose($handle); unlink($full_filename); $this->Log->Write("Blocked a file upload attempt [forbidden content]: " . $filename); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_MIME') . " [forbidden content]"); } // If we have read exactly it's highly probable that we have not reached the end of file } while (strlen($content) == $chunk_size); // Close the file fclose($handle); // Append this file to the file list $filelist[] = array("filename" => $filename, "realname" => $realname, "size" => $size); // Save the new list to the session $this->session->set("filelist", $filelist, $this->namespace); // move the internal pointer to the end of the array end($filelist); // fetches the key of the last element $last = key($filelist); $this->Log->Write("File " . $filename . " uploaded succesful."); return array("success" => true, "index" => $last); }
protected function DoUpload() { //Retrieve file details from uploaded file, sent from upload form $file = JRequest::getVar('foxstdupload', NULL, 'files', 'array'); // $file is null when a browser with javascipt didn't send $_FILES at all // $file['error'] is UPLOAD_ERR_NO_FILE when a browser without javascipt sent $_FILES empty if (!$this->Submitted || !$file || $file['error'] == UPLOAD_ERR_NO_FILE) { return true; } $upload_directory = JPATH_SITE . "/components/" . $GLOBALS["com_name"] . "/uploads/"; if (!is_writable($upload_directory)) { $this->MessageBoard->Add(JText::_($GLOBALS["COM_NAME"] . '_ERR_DIR_NOT_WRITABLE'), FoxMessageBoard::error); return false; } // Check for http $_FILES upload errors if ($file['error']) { // case 1 UPLOAD_ERR_INI_SIZE: 'The uploaded file exceeds the upload_max_filesize directive in php.ini'; // case 2 UPLOAD_ERR_FORM_SIZE: 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form'; // case 3 UPLOAD_ERR_PARTIAL: 'The uploaded file was only partially uploaded'; // case 4 UPLOAD_ERR_NO_FILE: 'No file was uploaded'; // case 6 UPLOAD_ERR_NO_TMP_DIR: 'Missing a temporary folder'; // case 7 UPLOAD_ERR_CANT_WRITE: 'Failed to write file to disk'; // case 8 UPLOAD_ERR_EXTENSION: 'File upload stopped by extension'; $this->MessageBoard->Add(JText::sprintf($GLOBALS["COM_NAME"] . '_ERR_UPLOAD', $file['error']), FoxMessageBoard::error); return false; } // Check file size $size = $file['size']; if ($size == 0) { $this->MessageBoard->Add(JText::_($GLOBALS["COM_NAME"] . '_ERR_FILE_EMPTY'), FoxMessageBoard::error); return false; } $max_filesize = intval($this->Params->get("uploadmax_file_size", "0")) * KB; if ($size > $max_filesize) { $this->MessageBoard->Add(JText::_($GLOBALS["COM_NAME"] . '_ERR_FILE_TOO_LARGE'), FoxMessageBoard::error); return false; } $mimetype = new FMimeType(); if (!$mimetype->Check($file['tmp_name'], $this->Params)) { // Noo need to delete the file uploaded //unlink($file['tmp_name']); $this->MessageBoard->Add(JText::_($GLOBALS["COM_NAME"] . '_ERR_MIME') . " [" . $mimetype->Mimetype . "]", FoxMessageBoard::error); return false; } //Import filesystem libraries. Perhaps not necessary, but does not hurt jimport('joomla.filesystem.file'); //Clean up filename to get rid of strange characters like spaces and others $filename = JFile::makeSafe($file['name']); // Assign a random unique id to the file name, to avoid that lamers can force the server to execute their uploaded shit $filename = uniqid() . "-" . $filename; $dest = $upload_directory . $filename; // Todo: This attempt doesn't intercept the exception /* try { JFile::upload($file['tmp_name'], $dest); } catch (Exception $e) { //$e->getMessage() return false; } */ if (!JFile::upload($file['tmp_name'], $dest)) { return false; } // Upload successful. Add an element to the uploads list $jsession =& JFactory::getSession(); $fsession = new FSession($jsession->getId(), $this->Application->cid, $this->Application->mid); // session_id, cid, mid // Store the answer in the session $data = $fsession->Load('filelist'); // Read the list from the session if ($data) { $filelist = explode("|", $data); } else { $filelist = array(); } $filelist[] = $filename; // Append this file to the list $data = implode("|", $filelist); $fsession->Save($data, "filelist"); return true; }
public function HandleUpload($uploadDirectory) { $this->DebugLog->Write("HandleUpload() started"); if (!is_writable($uploadDirectory)) { $this->DebugLog->Write("Directory " . $uploadDirectory . " is not writable"); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_DIR_NOT_WRITABLE')); } $this->DebugLog->Write("Directory " . $uploadDirectory . " is ok"); // Check file size $size = $this->get_file_size(); if ($size == 0) { $this->DebugLog->Write("File size is 0"); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_FILE_EMPTY')); } $this->DebugLog->Write("File size is > 0"); // uploadmax_file_size defaults to 0 to prevent hack attempts $max = $this->Params->get("uploadmax_file_size", 0) * KB; // and < max limit if ($size > $max) { $this->DebugLog->Write("File size too large ({$size} > {$max})"); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_FILE_TOO_LARGE')); } $this->DebugLog->Write("File size ({$size} / {$max}) is ok"); // Clean file name $filename = preg_replace("/[^\\w\\.-_]/", "_", $this->get_file_name()); // Assign a random unique id to the file name, to avoid that lamers can force the server to execute their uploaded shit $filename = uniqid() . "-" . $filename; $full_filename = $uploadDirectory . $filename; if (!$this->save_file($full_filename)) { $this->DebugLog->Write("Error saving file"); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_SAVE_FILE')); } $this->DebugLog->Write("File saved"); $mimetype = new FMimeType(); if (!$mimetype->Check($full_filename, $this->Params)) { // Delete the file uploaded unlink($full_filename); $this->DebugLog->Write("File type [" . $mimetype->Mimetype . "] is not allowed. Allowed types are:" . PHP_EOL . print_r($mimetype->Allowed, true)); return array('error' => JFactory::getLanguage()->_($GLOBALS["COM_NAME"] . '_ERR_MIME') . " [" . $mimetype->Mimetype . "]"); } $this->DebugLog->Write("File type [" . $mimetype->Mimetype . "] is allowed"); $cid = JFactory::getApplication()->input->get("cid", NULL); $mid = JFactory::getApplication()->input->get("mid", NULL); $owner = JFactory::getApplication()->input->get("owner", NULL); $id = JFactory::getApplication()->input->get("id", NULL); $jsession = JFactory::getSession(); $fsession = new FSession($jsession->getId(), $cid, $mid); // Store the answer in the session $data = $fsession->Load('filelist'); // Read the list from the session if ($data) { $filelist = explode("|", $data); } else { $filelist = array(); } $filelist[] = $filename; // Append this file to the list $data = implode("|", $filelist); $fsession->Save($data, "filelist"); $this->Log->Write("File " . $filename . " uploaded succesful."); $this->DebugLog->Write("File uploaded succesful."); return array("success" => true); }