302 lines
8.4 KiB
PHP
302 lines
8.4 KiB
PHP
<?php
|
|
/**
|
|
* @package JEM
|
|
* @copyright (C) 2013-2024 joomlaeventmanager.net
|
|
* @copyright (C) 2005-2009 Christoph Lukes
|
|
* @license https://www.gnu.org/licenses/gpl-3.0 GNU/GPL
|
|
*/
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\CMS\Filesystem\File;
|
|
use Joomla\CMS\Filesystem\Folder;
|
|
use Joomla\CMS\Table\Table;
|
|
use Joomla\CMS\Language\Text;
|
|
use Joomla\CMS\Object\CMSObject;
|
|
use Joomla\CMS\Filesystem\Path;
|
|
|
|
// ensure JemFactory is loaded (because this class is used by modules or plugins too)
|
|
require_once(JPATH_SITE.'/components/com_jem/factory.php');
|
|
|
|
/**
|
|
* Holds the logic for attachments manipulation
|
|
*
|
|
* @package JEM
|
|
*/
|
|
class JemAttachment extends CMSObject
|
|
{
|
|
/**
|
|
* upload files for the specified object
|
|
*
|
|
* @param array data from JInputFiles (as array of n arrays of params, [n][params])
|
|
* @param string object identification (should be event<eventid>, category<categoryid>, etc...)
|
|
*/
|
|
static public function postUpload($post_files, $object)
|
|
{
|
|
require_once JPATH_SITE.'/components/com_jem/classes/image.class.php';
|
|
|
|
$user = JemFactory::getUser();
|
|
$jemsettings = JemHelper::config();
|
|
|
|
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$object;
|
|
|
|
if (!(is_array($post_files) && count($post_files))) {
|
|
return false;
|
|
}
|
|
|
|
$allowed = explode(",", $jemsettings->attachments_types);
|
|
foreach ($allowed as $k => $v) {
|
|
$allowed[$k] = ($v ? trim($v) : $v);
|
|
}
|
|
|
|
$maxsizeinput = $jemsettings->attachments_maxsize*1024; //size in kb
|
|
|
|
foreach ($post_files as $k => $rec)
|
|
{
|
|
$file = array_key_exists('name', $rec) ? $rec['name'] : '';
|
|
if (empty($file)) {
|
|
continue;
|
|
}
|
|
|
|
// check if the filetype is valid
|
|
$fileext = strtolower(File::getExt($file));
|
|
if (!in_array($fileext, $allowed)) {
|
|
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_ATTACHEMENT_EXTENSION_NOT_ALLOWED').': '.$file, 'warning');
|
|
continue;
|
|
}
|
|
// check size
|
|
if ($rec['size'] > $maxsizeinput) {
|
|
Factory::getApplication()->enqueueMessage(Text::sprintf('COM_JEM_ERROR_ATTACHEMENT_FILE_TOO_BIG', $file, $rec['size'], $maxsizeinput), 'warning');
|
|
continue;
|
|
}
|
|
|
|
if (!Folder::exists($path)) {
|
|
// try to create it
|
|
$res = Folder::create($path);
|
|
if (!$res) {
|
|
Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_COULD_NOT_CREATE_FOLDER').': '.$path, 'warning');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// TODO: Probably move this to a helper class
|
|
|
|
$sanitizedFilename = JemImage::sanitize($path, $file);
|
|
|
|
// Make sure that the full file path is safe.
|
|
$filepath = Path::clean( $path.'/'.$sanitizedFilename);
|
|
// Since Joomla! 3.4.0 File::upload has some more params to control new security parsing
|
|
// switch off parsing archives for byte sequences looking like a script file extension
|
|
// but keep all other checks running
|
|
File::upload($rec['tmp_name'], $filepath, false, false, array('fobidden_ext_in_content' => false));
|
|
|
|
$table = Table::getInstance('jem_attachments', '');
|
|
$table->file = $sanitizedFilename;
|
|
$table->object = $object;
|
|
if (isset($rec['customname']) && !empty($rec['customname'])) {
|
|
$table->name = $rec['customname'];
|
|
}
|
|
if (isset($rec['description']) && !empty($rec['description'])) {
|
|
$table->description = $rec['description'];
|
|
}
|
|
if (isset($rec['access'])) {
|
|
$table->access = intval($rec['access']);
|
|
}
|
|
|
|
$table->added = date('Y-m-d H:i:s');
|
|
$table->added_by = $user->get('id');
|
|
|
|
if (!($table->check() && $table->store())) {
|
|
\Joomla\CMS\Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_ATTACHMENT_SAVING_TO_DB').': '.$table->getError(), 'warning');
|
|
}
|
|
} // foreach
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* update attachment record in db
|
|
* @param array (id, name, description, access)
|
|
*/
|
|
static public function update($attach)
|
|
{
|
|
if (!is_array($attach) || !isset($attach['id']) || !(intval($attach['id']))) {
|
|
return false;
|
|
}
|
|
|
|
$table = Table::getInstance('jem_attachments', '');
|
|
$table->load($attach['id']);
|
|
$table->bind($attach);
|
|
|
|
if (!($table->check() && $table->store())) {
|
|
\Joomla\CMS\Factory::getApplication()->enqueueMessage(Text::_('COM_JEM_ERROR_ATTACHMENT_UPDATING_RECORD').': '.$table->getError(), 'warning');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* return attachments for objects
|
|
* @param string object identification (should be event<eventid>, category<categoryid>, etc...)
|
|
* @return array
|
|
*/
|
|
static public function getAttachments($object)
|
|
{
|
|
$jemsettings = JemHelper::config();
|
|
|
|
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$object;
|
|
|
|
if (!file_exists($path)) {
|
|
return array();
|
|
}
|
|
|
|
// first list files in the folder
|
|
$files = Folder::files($path, null, false, false);
|
|
|
|
// then get info for files from db
|
|
$db = Factory::getContainer()->get('DatabaseDriver');
|
|
$fnames = array();
|
|
foreach ($files as $f) {
|
|
$fnames[] = $db->Quote($f);
|
|
}
|
|
|
|
if (!count($fnames)) {
|
|
return array();
|
|
}
|
|
|
|
// Check access level if not a Super User on Backend.
|
|
$user = JemFactory::getUser();
|
|
if (Factory::getApplication()->isClient('administrator') && $user->authorise('core.manage')) {
|
|
$qAccess = '';
|
|
} else {
|
|
$levels = $user->getAuthorisedViewLevels();
|
|
$qAccess = ' AND access IN (' . implode(',', $levels) . ')';
|
|
}
|
|
|
|
$query = 'SELECT * '
|
|
. ' FROM #__jem_attachments '
|
|
. ' WHERE file IN ('. implode(',', $fnames) .')'
|
|
. ' AND object = '. $db->Quote($object)
|
|
. $qAccess
|
|
. ' ORDER BY ordering ASC ';
|
|
|
|
$db->setQuery($query);
|
|
$res = $db->loadObjectList();
|
|
|
|
return $res;
|
|
}
|
|
|
|
/**
|
|
* get the file
|
|
*
|
|
* @param int $id
|
|
*/
|
|
static public function getAttachmentPath($id)
|
|
{
|
|
$jemsettings = JemHelper::config();
|
|
|
|
$user = JemFactory::getUser();
|
|
// Support Joomla access levels instead of single group id
|
|
$levels = $user->getAuthorisedViewLevels();
|
|
|
|
$db = Factory::getContainer()->get('DatabaseDriver');
|
|
$query = 'SELECT * '
|
|
. ' FROM #__jem_attachments '
|
|
. ' WHERE id = '. $db->Quote(intval($id));
|
|
|
|
$db->setQuery($query);
|
|
$res = $db->loadObject();
|
|
|
|
if (!$res) {
|
|
throw new Exception(Text::_('COM_JEM_FILE_NOT_FOUND'), 404);
|
|
}
|
|
|
|
if (!in_array($res->access, $levels)) {
|
|
throw new Exception(Text::_('COM_JEM_NO_ACCESS'), 403);
|
|
}
|
|
|
|
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$res->object.'/'.$res->file;
|
|
if (!file_exists($path)) {
|
|
throw new Exception(Text::_('COM_JEM_FILE_NOT_FOUND'), 404);
|
|
}
|
|
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* remove attachment for objects
|
|
*
|
|
* @param id from db
|
|
* @param string object identification (should be event<eventid>, category<categoryid>, etc...)
|
|
* @return boolean
|
|
*/
|
|
static public function remove($id)
|
|
{
|
|
$jemsettings = JemHelper::config();
|
|
|
|
$user = JemFactory::getUser();
|
|
// Support Joomla access levels instead of single group id
|
|
$levels = $user->getAuthorisedViewLevels();
|
|
$userid = $user->get('id');
|
|
|
|
// then get info for files from db
|
|
$db = Factory::getContainer()->get('DatabaseDriver');
|
|
|
|
$query = 'SELECT file, object, added_by '
|
|
. ' FROM #__jem_attachments '
|
|
. ' WHERE id = ' . $db->Quote($id) . ' AND access IN (0,' . implode(',', $levels) . ')';
|
|
|
|
$db->setQuery($query);
|
|
$res = $db->loadObject();
|
|
|
|
if (!$res) {
|
|
return false;
|
|
}
|
|
|
|
// check permission
|
|
if (empty($userid) || ($userid != $res->added_by)) {
|
|
if (strncasecmp($res->object, 'event', 5) == 0) {
|
|
$type = 'event';
|
|
$itemid = (int)substr($res->object, 5);
|
|
$table = '#__jem_events';
|
|
} elseif (strncasecmp($res->object, 'venue', 5) == 0) {
|
|
$type = 'venue';
|
|
$itemid = (int)substr($res->object, 5);
|
|
$table = '#__jem_venues';
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
// get item owner
|
|
$query = 'SELECT created_by FROM ' . $table . ' WHERE id = ' . $db->Quote($itemid);
|
|
$db->setQuery($query);
|
|
$created_by = $db->loadResult();
|
|
|
|
if (!$user->can('edit', $type, $itemid, $created_by)) {
|
|
JemHelper::addLogEntry("User {$userid} is not permritted to remove attachment " . $res->object, __METHOD__);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
JemHelper::addLogEntry("User {$userid} removes attachment " . $res->object.'/'.$res->file, __METHOD__);
|
|
$path = JPATH_SITE.'/'.$jemsettings->attachments_path.'/'.$res->object.'/'.$res->file;
|
|
if (file_exists($path)) {
|
|
File::delete($path);
|
|
}
|
|
|
|
$query = 'DELETE FROM #__jem_attachments '
|
|
. ' WHERE id = '. $db->Quote($id);
|
|
|
|
$db->setQuery($query);
|
|
$res = $db->execute();
|
|
|
|
if (!$res) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|