| Current Path : /proc/self/root/home/antonen/poznajlitwe.lt/components/com_foxcontact/controller/ |
| Current File : //proc/self/root/home/antonen/poznajlitwe.lt/components/com_foxcontact/controller/uploader.php |
<?php defined('_JEXEC') or die(file_get_contents('index.html'));
/**
* @package Fox Contact for Joomla
* @copyright Copyright (c) 2010 - 2015 Demis Palma. All rights reserved.
* @license Distributed under the terms of the GNU General Public License GNU/GPL v3 http://www.gnu.org/licenses/gpl-3.0.html
* @see Documentation: http://www.fox.ra.it/forum/2-documentation.html
*/
jimport('foxcontact.constants');
jimport('foxcontact.form.model');
jimport('foxcontact.html.mimetype');
jimport('foxcontact.system.log');
use FoxContact\Log;
class FoxContactControllerUploader extends JControllerLegacy
{
public function receive()
{
$input = JFactory::getApplication()->input;
$form = FoxFormModel::getFormByUid($input->get('uid'));
$item = $form->getDesign()->getFoxDesignItemByType('attachments');
if (is_null($item))
{
$result = array('error' => 'Upload is disabled');
}
else
{
$manager = $this->getUploaderRequestManager();
$result = !is_null($manager) ? $manager->exec(JPATH_COMPONENT . '/uploads/', $item) : array('error' => JText::_('COM_FOXCONTACT_ERR_NO_FILE'));
$form->save();
}
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
JFactory::getApplication()->close();
}
private function getUploaderRequestManager()
{
$input = JFactory::getApplication()->input;
if ($input->get('qqfile'))
{
return new XhrUploadRequestManager();
}
if (count($input->files->get('qqfile', array(), 'array')))
{
return new FormUploadRequestManager();
}
if (JFactory::getApplication()->input->get('action', 0) == 'deletefile')
{
return new XhrDeleteRequestManager();
}
return null;
}
}
abstract class RequestManager
{
public abstract function exec($upload_directory, $item);
}
abstract class UploadRequestManager extends RequestManager
{
public function exec($upload_directory, $item)
{
if (!is_writable($upload_directory))
{
return array('error' => JText::_('COM_FOXCONTACT_ERR_DIR_NOT_WRITABLE'));
}
$size = $this->getFileSize();
if ($size == 0)
{
return array('error' => JText::_('COM_FOXCONTACT_ERR_FILE_EMPTY'));
}
if ($size > constant($item->get('file.size', 'MB100')))
{
return array('error' => JText::_('COM_FOXCONTACT_ERR_FILE_TOO_LARGE'));
}
$realname = $this->getFileName();
$filename = str_replace(array('\\', '/', '&', '"', '\'', '<', '>', ':', '|', '?', '*'), '', $realname);
$filename = preg_replace('/\\.{2,}/', '.', $filename);
setlocale(LC_ALL, 'C.UTF-8');
$filename = basename($filename);
$filename = trim($filename, '.');
$forbidden_extensions = '/ph(p[345st]?|t|tml|ar)/i';
if (preg_match($forbidden_extensions, $filename))
{
Log::GetInstance()->Add("Blocked a file upload attempt [forbidden extension]: {$filename}", 'info', 'upload');
return array('error' => JText::_('COM_FOXCONTACT_ERR_MIME') . ' [forbidden extension]');
}
$content_type = JFactory::getApplication()->input->server->get('CONTENT_TYPE', '', 'string');
if (!$this->checkMimeType($content_type, $item))
{
$type = preg_replace('/;.*/', '', $content_type);
return array('error' => JText::_('COM_FOXCONTACT_ERR_MIME') . " [{$type}]");
}
$filename = uniqid() . '-' . $filename;
$full_filename = $upload_directory . $filename;
$item_data = $item->getValue();
if (count($item_data) >= $item->get('file.max', 10))
{
return array('error' => JText::_('COM_FOXCONTACT_ERR_MAX_UPLOAD_FILES_EXCEEDED'));
}
if (!$this->saveFile($full_filename))
{
return array('error' => JText::_('COM_FOXCONTACT_ERR_SAVE_FILE'));
}
if (!$this->checkFileContent($full_filename))
{
Log::GetInstance()->Add("Blocked a file upload attempt [forbidden content]: {$filename}", 'info', 'upload');
unlink($full_filename);
return array('error' => JText::_('COM_FOXCONTACT_ERR_MIME') . ' [forbidden content]');
}
$item_data[] = array('filename' => $filename, 'realname' => $realname, 'size' => $size);
$item->setValue($item_data);
end($item_data);
$last = key($item_data);
Log::GetInstance()->Add("File {$filename} uploaded succesful.", 'info', 'upload');
return array('success' => true, 'index' => $last);
}
private function checkMimeType($mime_type, $item)
{
if (!(bool) $item->get('filter.enable', 1))
{
return true;
}
$allowed = array('/^application\\/octet-stream$/');
if ((bool) $item->get('filter.audio', 0))
{
$allowed[] = '/^audio\\//';
}
if ((bool) $item->get('filter.video', 0))
{
$allowed[] = '/^video\\//';
}
if ((bool) $item->get('filter.image', 0))
{
$allowed[] = '/^image\\//';
}
if ((bool) $item->get('filter.zip', 0))
{
$allowed[] = '/^application\\/.*zip/';
$allowed[] = '/^application\\/x-compress/';
$allowed[] = '/^application\\/x-compressed/';
$allowed[] = '/^application\\/x-gzip/';
$allowed[] = '/^application\\/x-rar/';
}
if ((bool) $item->get('filter.document', 0))
{
$allowed[] = '/^(application|text)\\/rtf/';
$allowed[] = '/^application\\/pdf/';
$allowed[] = '/^application\\/msword/';
$allowed[] = '/^application\\/vnd.ms-/';
$allowed[] = '/^application\\/vnd\\.openxmlformats-officedocument\\./';
$allowed[] = '/^application\\/x-mspublisher/';
$allowed[] = '/^application\\/x-mswrite/';
$allowed[] = '/^application\\/vnd\\.oasis\\.opendocument\\.text/';
}
foreach ($allowed as $allowed_type)
{
if ((bool) preg_match($allowed_type, $mime_type))
{
return true;
}
}
return false;
}
public static function checkFileContent($full_filename)
{
$chunk_size = MB1;
$back_step = -6;
$handle = fopen($full_filename, 'rb');
do
{
$content = fread($handle, $chunk_size);
fseek($handle, $back_step, SEEK_CUR);
if (strpos($content, '<?php') !== false || strpos($content, '<script') !== false)
{
fclose($handle);
return false;
}
} while (strlen($content) == $chunk_size);
fclose($handle);
return true;
}
protected abstract function saveFile($path);
protected abstract function getFileName();
protected abstract function getFileSize();
}
class XhrUploadRequestManager extends UploadRequestManager
{
protected function saveFile($path)
{
$input = fopen('php://input', 'r');
$target = fopen($path, 'w');
$real_size = $input !== false && $target !== false ? stream_copy_to_stream($input, $target) : false;
if ($input !== false)
{
fclose($input);
}
if ($target !== false)
{
fclose($target);
}
return $real_size !== false && $real_size === $this->getFileSize();
}
protected function getFileName()
{
return JFactory::getApplication()->input->get->get('qqfile', '', 'string');
}
protected function getFileSize()
{
return JFactory::getApplication()->input->server->get('CONTENT_LENGTH', 0, 'int');
}
}
class FormUploadRequestManager extends UploadRequestManager
{
private $files;
public function __construct()
{
$this->files = JFactory::getApplication()->input->files->get('qqfile', array('size' => 0), 'array');
}
protected function saveFile($path)
{
return move_uploaded_file($this->files['tmp_name'], $path);
}
protected function getFileName()
{
return $this->files['name'];
}
protected function getFileSize()
{
return $this->files['size'];
}
}
class XhrDeleteRequestManager extends RequestManager
{
public function exec($upload_directory, $item)
{
$file_index = JFactory::getApplication()->input->get('fileindex', 0);
$item_data = $item->getValue();
if (!isset($item_data[$file_index]))
{
return array('error' => 'Index not found');
}
$deleted = @unlink("{$upload_directory}{$item_data[$file_index]['filename']}");
if (!$deleted)
{
}
unset($item_data[$file_index]);
$item->setValue($item_data);
return array('success' => true);
}
}