/home/ivoiecob/email.hirewise-va.com/modules/PersonalFiles/Module.php
<?php
/**
* This code is licensed under AGPLv3 license or Afterlogic Software License
* if commercial version of the product was purchased.
* For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
*/
namespace Aurora\Modules\PersonalFiles;
use Afterlogic\DAV\Constants;
use Afterlogic\DAV\FS\Directory;
use Afterlogic\DAV\FS\File;
use Afterlogic\DAV\FS\Shared\File as SharedFile;
use Afterlogic\DAV\FS\Shared\Directory as SharedDirectory;
use Afterlogic\DAV\Server;
use Aurora\Api;
use Aurora\Modules\Core\Module as CoreModule;
use Aurora\Modules\Files\Classes\FileItem;
use Aurora\Modules\Files\Enums\ErrorCodes;
use Aurora\Modules\Files\Module as FilesModule;
use Aurora\System\Exceptions\ApiException;
/**
* @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
* @license https://afterlogic.com/products/common-licensing Afterlogic Software License
* @copyright Copyright (c) 2023, Afterlogic Corp.
* @property Settings $oModuleSettings
*
* @package Modules
*/
class Module extends \Aurora\System\Module\AbstractModule
{
protected static $sStorageType = 'personal';
protected static $iStorageOrder = 0;
/**
* Indicates if it's allowed to move files/folders to this storage.
* @var boolean
*/
protected static $bIsDroppable = true;
protected $oBeforeDeleteUserRootPath = '';
protected $oBeforeDeleteUser = null;
public static $sTrashFolder = '.trash';
/**
*
* @var \Aurora\Modules\PersonalFiles\Manager
*/
public $oManager = null;
/**
*
* @var \Aurora\Modules\Min\Module
*/
protected $oMinModuleDecorator = null;
public function getManager()
{
if ($this->oManager === null) {
$this->oManager = new Manager($this);
}
return $this->oManager;
}
/**
* @return Module
*/
public static function getInstance()
{
return parent::getInstance();
}
/**
* @return Module
*/
public static function Decorator()
{
return parent::Decorator();
}
/**
* @return Settings
*/
public function getModuleSettings()
{
return $this->oModuleSettings;
}
/**
* Initializes Files Module.
*
* @ignore
*/
public function init()
{
ini_set('default_charset', 'UTF-8'); //support for cyrillic characters in file names
$this->subscribeEvent('Files::GetFile', array($this, 'onGetFile'));
$this->subscribeEvent('Files::CreateFile', array($this, 'onCreateFile'));
$this->subscribeEvent('Files::GetLinkType', array($this, 'onGetLinkType'));
$this->subscribeEvent('Files::CheckUrl', array($this, 'onCheckUrl'));
$this->subscribeEvent('Files::GetStorages::after', array($this, 'onAfterGetStorages'));
$this->subscribeEvent('Files::GetFileInfo::after', array($this, 'onAfterGetFileInfo'), 10);
$this->subscribeEvent('Files::GetItems::before', [$this, 'onBeforeGetItems']);
$this->subscribeEvent('Files::GetItems', array($this, 'onGetItems'));
$this->subscribeEvent('Files::CreateFolder::after', array($this, 'onAfterCreateFolder'));
$this->subscribeEvent('Files::Copy::after', array($this, 'onAfterCopy'));
$this->subscribeEvent('Files::Move::after', array($this, 'onAfterMove'));
$this->subscribeEvent('Files::Rename::after', array($this, 'onAfterRename'));
$this->subscribeEvent('Files::Delete::after', array($this, 'onAfterDelete'));
$this->subscribeEvent('Files::Restore::after', array($this, 'onAfterRestore'));
$this->subscribeEvent('Files::GetQuota::after', array($this, 'onAfterGetQuota'));
$this->subscribeEvent('Files::CreateLink::after', array($this, 'onAfterCreateLink'));
$this->subscribeEvent('Files::CreatePublicLink::after', array($this, 'onAfterCreatePublicLink'));
$this->subscribeEvent('Files::GetFileContent::after', array($this, 'onAfterGetFileContent'));
$this->subscribeEvent('Files::IsFileExists::after', array($this, 'onAfterIsFileExists'));
$this->subscribeEvent('Files::PopulateFileItem::after', array($this, 'onAfterPopulateFileItem'));
$this->subscribeEvent('Files::CheckQuota::after', array($this, 'onAfterCheckQuota'));
$this->subscribeEvent('Files::DeletePublicLink::after', array($this, 'onAfterDeletePublicLink'));
$this->subscribeEvent('Files::GetSubModules::after', array($this, 'onAfterGetSubModules'));
$this->subscribeEvent('Files::UpdateExtendedProps::after', array($this, 'onAfterUpdateExtendedProps'));
$this->subscribeEvent('Files::GetExtendedProps::after', array($this, 'onAfterGetExtendedProps'));
$this->subscribeEvent('Core::DeleteUser::before', array($this, 'onBeforeDeleteUser'));
$this->subscribeEvent('Core::DeleteUser::after', array($this, 'onAfterDeleteUser'));
$this->subscribeEvent('Files::GetNonExistentFileName::after', array($this, 'onAfterGetNonExistentFileName'));
$this->subscribeEvent('Files::GetAccessInfoForPath::after', array($this, 'onAfterGetAccessInfoForPath'));
}
/**
* Obtains list of module settings.
*
* @return array
*/
public function GetSettings()
{
Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
return array(
'UserSpaceLimitMb' => $this->getUserSpaceLimitMb(),
);
}
/**
* Updates module's settings - saves them to config.json file.
*
* @param int $UserSpaceLimitMb User space limit setting in Mb.
* @return bool
*/
public function UpdateSettings($UserSpaceLimitMb)
{
Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::TenantAdmin);
FilesModule::getInstance()->setConfig('UserSpaceLimitMb', $UserSpaceLimitMb);
return (bool) FilesModule::getInstance()->saveModuleConfig();
}
public function UpdateUsedSpace()
{
$iResult = 0;
Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
$oUser = Api::getAuthenticatedUser();
if ($oUser) {
$iResult = $this->getManager()->getUserSpaceUsed($oUser->PublicId, [\Aurora\System\Enums\FileStorageType::Personal]);
$oUser->setExtendedProp('PersonalFiles::UsedSpace', $iResult);
$oUser->save();
}
return $iResult;
}
/**
* Returns Min module decorator.
*
* @return \Aurora\System\Module\Decorator
*/
private function getMinModuleDecorator()
{
return Api::GetModuleDecorator('Min');
}
/**
* Checks if storage type is personal.
*
* @param string $Type Storage type.
* @return bool
*/
protected function checkStorageType($Type)
{
return $Type === static::$sStorageType;
}
/**
* Returns HTML title for specified URL.
* @param string $sUrl
* @return string
*/
protected function getHtmlTitle($sUrl)
{
$oCurl = curl_init();
\curl_setopt_array($oCurl, array(
CURLOPT_URL => $sUrl,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => '',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_AUTOREFERER => true,
CURLOPT_SSL_VERIFYPEER => false, //required for https urls
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 5,
CURLOPT_MAXREDIRS => 5
));
$sContent = curl_exec($oCurl);
//$aInfo = curl_getinfo($oCurl);
curl_close($oCurl);
preg_match('/<title>(.*?)<\/title>/s', $sContent, $aTitle);
return isset($aTitle['1']) ? trim($aTitle['1']) : '';
}
/**
* Checks if file name is allowed.
*
* @param string $FileName
*
* @return bool
*/
protected function isFileAllowed($FileName)
{
$forbiddenFileList = [
'.sabredav'
];
$FileName = \trim(\MailSo\Base\Utils::ClearFileName($FileName));
$result = !in_array($FileName, $forbiddenFileList);
return $result;
}
protected function getTrashPath($sPath)
{
return '/' . self::$sTrashFolder . \ltrim($sPath);
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onBeforeGetItems(&$aArgs, &$mResult)
{
if ($this->getConfig('AllowTrash', true) && $aArgs['Type'] === 'trash') {
$aArgs['Type'] = \Aurora\System\Enums\FileStorageType::Personal;
$aArgs['Path'] = $this->getTrashPath($aArgs['Path']);
if (!FilesModule::Decorator()->IsFileExists($aArgs['UserId'], \Aurora\System\Enums\FileStorageType::Personal, '', self::$sTrashFolder)) {
FilesModule::Decorator()->CreateFolder($aArgs['UserId'], \Aurora\System\Enums\FileStorageType::Personal, '', self::$sTrashFolder);
}
}
}
/**
* Puts file content to $mResult.
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onGetFile($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$iOffset = isset($aArgs['Offset']) ? $aArgs['Offset'] : 0;
$iChunkSizet = isset($aArgs['ChunkSize']) ? $aArgs['ChunkSize'] : 0;
try {
$mResult = $this->getManager()->getFile($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['Id'], $iOffset, $iChunkSizet);
} catch (\Sabre\DAV\Exception\NotFound $oEx) {
$mResult = false;
// echo(\Aurora\System\Managers\Response::GetJsonFromObject('Json', \Aurora\System\Managers\Response::FalseResponse(__METHOD__, 404, 'Not Found')));
$this->oHttp->StatusHeader(404);
exit;
}
return true;
}
}
/**
* Creates file.
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onCreateFile($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
if (!self::isFileAllowed($aArgs['Name'])) {
throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::CanNotUploadFileErrorData);
}
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$currentUser = Server::getUser();
Server::setUser(Api::getUserPublicIdById($UserId));
$mResult = $this->getManager()->createFile(
Api::getUserPublicIdById($UserId),
isset($aArgs['Type']) ? $aArgs['Type'] : null,
isset($aArgs['Path']) ? $aArgs['Path'] : null,
isset($aArgs['Name']) ? $aArgs['Name'] : null,
isset($aArgs['Data']) ? $aArgs['Data'] : null,
isset($aArgs['Overwrite']) ? $aArgs['Overwrite'] : null,
isset($aArgs['RangeType']) ? $aArgs['RangeType'] : null,
isset($aArgs['Offset']) ? $aArgs['Offset'] : null,
isset($aArgs['ExtendedProps']) ? $aArgs['ExtendedProps'] : null
);
Server::setUser($currentUser);
self::Decorator()->UpdateUsedSpace();
return $mResult;
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onGetLinkType($aArgs, &$mResult)
{
$mResult = '';
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onCheckUrl($aArgs, &$mResult)
{
$iUserId = Api::getAuthenticatedUserId();
if ($iUserId) {
if (!empty($aArgs['Url'])) {
$sUrl = $aArgs['Url'];
if ($sUrl) {
$aRemoteFileInfo = \Aurora\System\Utils::GetRemoteFileInfo($sUrl);
if ((int)$aRemoteFileInfo['code'] > 0) {
$sFileName = basename($sUrl);
$sFileExtension = \Aurora\System\Utils::GetFileExtension($sFileName);
if (empty($sFileExtension)) {
$sFileExtension = \Aurora\System\Utils::GetFileExtensionFromMimeContentType($aRemoteFileInfo['content-type']);
$sFileName .= '.' . $sFileExtension;
}
if ($sFileExtension === 'htm' || $sFileExtension === 'html') {
$sTitle = $this->getHtmlTitle($sUrl);
}
$mResult['Name'] = isset($sTitle) && strlen($sTitle) > 0 ? $sTitle : urldecode($sFileName);
$mResult['Size'] = $aRemoteFileInfo['size'];
}
}
}
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param \Aurora\Modules\Files\Classes\FileItem $oItem
* @return bool
*/
public function onAfterPopulateFileItem($aArgs, &$oItem)
{
if ($oItem->IsLink) {
$sFileName = basename($oItem->LinkUrl);
$sFileExtension = \Aurora\System\Utils::GetFileExtension($sFileName);
if ($sFileExtension === 'htm' || $sFileExtension === 'html') {
// $oItem->Name = $this->getHtmlTitle($oItem->LinkUrl);
return true;
}
}
return false;
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onBeforeDeleteUser($aArgs, &$mResult)
{
if (isset($aArgs['UserId'])) {
$this->oBeforeDeleteUser = Api::getUserById($aArgs['UserId']);
if ($this->oBeforeDeleteUser) {
$this->oBeforeDeleteUserRootPath = $this->getManager()->oStorage->getRootPath($this->oBeforeDeleteUser->PublicId, \Aurora\System\Enums\FileStorageType::Personal, true);
}
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterDeleteUser($aArgs, $mResult)
{
if ($mResult && !empty($this->oBeforeDeleteUserRootPath)) {
\Aurora\System\Utils::RecRmdir($this->oBeforeDeleteUserRootPath);
$this->oBeforeDeleteUserRootPath = '';
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterGetStorages($aArgs, &$mResult)
{
array_unshift($mResult, [
'Type' => static::$sStorageType,
'DisplayName' => $this->i18N('LABEL_STORAGE'),
'IsExternal' => false,
'Order' => static::$iStorageOrder,
'IsDroppable' => static::$bIsDroppable
]);
if (FilesModule::getInstance()->getConfig('AllowTrash', true) && $this->checkStorageType(\Aurora\System\Enums\FileStorageType::Personal)) {
array_unshift($mResult, [
'Type' => 'trash',
'DisplayName' => $this->i18N('LABEL_TRASH_STORAGE'),
'IsExternal' => false,
'Order' => 999,
'IsDroppable' => false
]);
}
if (FilesModule::getInstance()->getConfig('AllowFavorites', true) && $this->checkStorageType(\Aurora\System\Enums\FileStorageType::Personal)) {
array_unshift($mResult, [
'Type' => 'favorites',
'DisplayName' => $this->i18N('LABEL_FAVORITES_STORAGE'),
'IsExternal' => false,
'Order' => 998,
'IsDroppable' => false
]);
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterGetSubModules($aArgs, &$mResult)
{
array_unshift($mResult, 'local.' . static::$sStorageType);
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onGetItems($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$sHash = isset($aArgs['PublicHash']) ? $aArgs['PublicHash'] : null;
$bIsShared = isset($aArgs['Shared']) ? !!$aArgs['Shared'] : false;
$files = $this->getManager()->getFiles(
$sUserPiblicId,
$aArgs['Type'],
$aArgs['Path'],
$aArgs['Pattern'],
$sHash,
$bIsShared
);
if ($aArgs['Path'] === '' && is_array($files)) {
foreach ($files as $iKey => $oFileItem) {
if ($oFileItem instanceof FileItem && $oFileItem->IsFolder && $oFileItem->Name === self::$sTrashFolder) {
unset($files[$iKey]);
}
}
}
$mResult = array_merge(
$mResult,
$files
);
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterGetFileContent($aArgs, &$mResult)
{
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUUID = Api::getUserPublicIdById($UserId);
$Type = $aArgs['Type'];
$Path = $aArgs['Path'];
$Name = $aArgs['Name'];
$mFile = $this->getManager()->getFile($sUUID, $Type, $Path, $Name);
if (is_resource($mFile)) {
$mResult = stream_get_contents($mFile);
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterGetFileInfo($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$mResult = $this->getManager()->getFileInfo($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['Id']);
// return true;
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterCreateFolder(&$aArgs, &$mResult)
{
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
if ($this->checkStorageType($aArgs['Type'])) {
$mResult = $this->getManager()->createFolder($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['FolderName']);
return true;
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterCreateLink($aArgs, &$mResult)
{
Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
if ($this->checkStorageType($aArgs['Type'])) {
$Type = $aArgs['Type'];
$UserId = $aArgs['UserId'];
$Path = $aArgs['Path'];
$Name = $aArgs['Name'];
$Link = $aArgs['Link'];
Api::CheckAccess($UserId);
if (substr($Link, 0, 11) === 'javascript:') {
$Link = substr($Link, 11);
}
$sUserPiblicId = Api::getUserPublicIdById($UserId);
if ($this->checkStorageType($Type)) {
$Name = \trim(\MailSo\Base\Utils::ClearFileName($Name));
$mResult = $this->getManager()->createLink($sUserPiblicId, $Type, $Path, $Link, $Name);
self::Decorator()->UpdateUsedSpace();
}
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterDelete(&$aArgs, &$mResult)
{
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
if ($this->checkStorageType($aArgs['Type'])) {
$mResult = false;
$sUserPiblicId = Api::getUserPublicIdById($UserId);
foreach ($aArgs['Items'] as $key => $aItem) {
try {
$oNode = Server::getNodeForPath(Constants::FILESTORAGE_PATH_ROOT . '/' . $aArgs['Type'] . '/' . $aItem['Path'] . '/' . $aItem['Name']);
} catch (\Exception $oEx) {
Api::LogException($oEx);
throw new ApiException(ErrorCodes::NotFound, $oEx, "Node not found");
}
if (!$oNode) {
throw new ApiException(ErrorCodes::NotFound, null, "Node not found");
}
if ($oNode instanceof SharedFile || $oNode instanceof SharedDirectory) {
if (!$oNode->isInherited()) {
throw new ApiException(ErrorCodes::CantDeleteSharedItem);
}
}
$aPathItems = preg_split('/' . preg_quote('/', '/') . '/', \trim($aItem['Path'], '/'));
$sFirstPath = isset($aPathItems[0]) ? $aPathItems[0] : '';
if ($this->getConfig('AllowTrash', true) && $sFirstPath !== self::$sTrashFolder) {
$oNode->deleteShares();
if (!FilesModule::Decorator()->IsFileExists($aArgs['UserId'], \Aurora\System\Enums\FileStorageType::Personal, '', self::$sTrashFolder)) {
FilesModule::Decorator()->CreateFolder($aArgs['UserId'], \Aurora\System\Enums\FileStorageType::Personal, '', self::$sTrashFolder);
}
$sNewName = $this->getManager()->getNonExistentFileName(
$sUserPiblicId,
\Aurora\System\Enums\FileStorageType::Personal,
'/' . self::$sTrashFolder,
$aItem['Name']
);
$aArgs['Files'][$key]['NewName'] = $sNewName;
$mResult = $this->getManager()->copy(
$sUserPiblicId,
$aArgs['Type'],
\Aurora\System\Enums\FileStorageType::Personal,
$aItem['Path'],
'/' . self::$sTrashFolder,
$aItem['Name'],
$sNewName,
true
);
if ($mResult) {
$oNode = Server::getNodeForPath(Constants::FILESTORAGE_PATH_ROOT . '/' . \Aurora\System\Enums\FileStorageType::Personal . '/' . self::$sTrashFolder . '/' . $sNewName);
if ($oNode) {
$mExtendedProps = $oNode->getProperty('ExtendedProps');
$aExtendedProps = is_array($mExtendedProps) ? $mExtendedProps : [];
$aExtendedProps['TrashOriginalPath'] = $aItem['Path'] . '/' . $aItem['Name'];
$oNode->setProperty('ExtendedProps', $aExtendedProps);
}
}
} else {
Server::deleteNode('files/' . $aArgs['Type'] . '/' . $aItem['Path'] . '/' . $aItem['Name']);
}
$oItem = new FileItem();
$oItem->Id = $aItem['Name'];
$oItem->Name = $aItem['Name'];
$oItem->TypeStr = $aArgs['Type'];
$oItem->Path = $aItem['Path'];
FilesModule::Decorator()->DeletePublicLink($UserId, $aArgs['Type'], $aItem['Path'], $aItem['Name']);
\Aurora\System\Managers\Thumb::RemoveFromCache($UserId, $oItem->getHash(), $aItem['Name']);
$mResult = true;
}
self::Decorator()->UpdateUsedSpace();
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterRestore(&$aArgs, &$mResult)
{
if (static::$sStorageType === \Aurora\System\Enums\FileStorageType::Personal) {
$UserId = $aArgs['UserId'];
$Items = $aArgs['Items'];
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$Files = [];
foreach ($Items as $item) {
$oNode = Server::getNodeForPath(Constants::FILESTORAGE_PATH_ROOT . '/personal/' . self::$sTrashFolder . '/' . $item);
if ($oNode) {
$mExtendedProps = $oNode->getProperty('ExtendedProps');
$aExtendedProps = is_array($mExtendedProps) ? $mExtendedProps : [];
$originalPath = isset($aExtendedProps['TrashOriginalPath']) ? $aExtendedProps['TrashOriginalPath'] : false;
if ($originalPath === false) {
Api::Log('ERROR: The node \'' . $item . '\' has no original path');
} else {
list($toPath, $toOriginalName) = \Sabre\Uri\split($originalPath);
$toName = $this->getManager()->getNonExistentFileName(
$sUserPiblicId,
'personal',
$toPath,
$toOriginalName
);
$fileItem = [
'FromPath' => '/' . self::$sTrashFolder,
'FromName' => $item,
'ToPath' => $toPath,
'ToName' => $toName,
'ToOriginalName' => $toOriginalName
];
$Files[] = $fileItem;
}
}
}
if (is_array($Files)) {
$mResult = [];
}
foreach ($Files as $aFileItem) {
if ($this->getManager()->copy(
$sUserPiblicId,
'personal',
'personal',
$aFileItem['FromPath'],
$aFileItem['ToPath'],
$aFileItem['FromName'],
$aFileItem['ToName'],
true
)) {
$mResult[$aFileItem['ToOriginalName']] = $aFileItem['ToName'];
}
}
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterRename(&$aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
if (!self::isFileAllowed($aArgs['Name'])) {
throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::CanNotUploadFileErrorData);
}
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$sNewName = \trim(\MailSo\Base\Utils::ClearFileName($aArgs['NewName']));
// $sNewName = $this->getManager()->getNonExistentFileName($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $sNewName);
$bIsLink = isset($aArgs['IsLink']) ? $aArgs['IsLink'] : false;
$mResult = $this->getManager()->rename($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['Name'], $sNewName, $bIsLink);
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterCopy(&$aArgs, &$mResult)
{
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
if ($this->checkStorageType($aArgs['FromType'])) {
foreach ($aArgs['Files'] as $aItem) {
$bFolderIntoItself = isset($aItem['IsFolder']) && $aItem['IsFolder'] && $aArgs['ToPath'] === $aItem['FromPath'] . '/' . $aItem['Name'];
if (!$bFolderIntoItself) {
$sNewName = isset($aItem['NewName']) ? $aItem['NewName'] : $aItem['Name'];
$mResult = $this->getManager()->copy(
$sUserPiblicId,
$aItem['FromType'],
$aArgs['ToType'],
$aItem['FromPath'],
$aArgs['ToPath'],
$aItem['Name'],
$this->getManager()->getNonExistentFileName(
$sUserPiblicId,
$aArgs['ToType'],
$aArgs['ToPath'],
$sNewName
)
);
}
}
self::Decorator()->UpdateUsedSpace();
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterMove(&$aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['FromType'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
foreach ($aArgs['Files'] as $key => $aItem) {
$bIntoItself = $aArgs['ToType'] . '/' . $aArgs['ToPath'] === $aItem['FromType'] . '/' . $aItem['FromPath'];
if (!$bIntoItself) {
$sNewName = isset($aItem['NewName']) ? $aItem['NewName'] : $aItem['Name'];
if (!self::IsFileAllowed(basename($sNewName))) {
throw new \Aurora\System\Exceptions\ApiException(\Aurora\System\Notifications::CanNotUploadFileErrorData);
}
$sNewName = $this->getManager()->getNonExistentFileName(
$sUserPiblicId,
$aArgs['ToType'],
$aArgs['ToPath'],
$sNewName
);
$aArgs['Files'][$key]['NewName'] = $sNewName;
$mResult = $this->getManager()->copy(
$sUserPiblicId,
$aItem['FromType'],
$aArgs['ToType'],
$aItem['FromPath'],
$aArgs['ToPath'],
$aItem['Name'],
$sNewName,
true
);
} else {
throw new ApiException(ErrorCodes::CannotCopyOrMoveItemToItself);
}
}
self::Decorator()->UpdateUsedSpace();
}
}
protected function getUserSpaceLimitMb()
{
$iSpaceLimitMb = FilesModule::getInstance()->oModuleSettings->UserSpaceLimitMb;
$iUserId = Api::getAuthenticatedUserId();
$oUser = \Aurora\Api::getUserById($iUserId);
if ($oUser) {
$iSpaceLimitMb = $oUser->getExtendedProp('Files::UserSpaceLimitMb');
}
$aArgs = [
'UserId' => $iUserId
];
$this->broadcastEvent(
'GetUserSpaceLimitMb',
$aArgs,
$iSpaceLimitMb
);
return $iSpaceLimitMb;
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterGetQuota($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$iSize = 0;
$oUser = \Aurora\Api::getUserById($aArgs['UserId']);
if ($oUser) {
$iSize = null !== $oUser->getExtendedProp('PersonalFiles::UsedSpace') ? $oUser->getExtendedProp('PersonalFiles::UsedSpace') : 0;
}
$mResult = array(
'Used' => (int) $iSize,
'Limit' => $this->getUserSpaceLimitMb() * 1024 * 1024
);
}
}
/**
* Creates public link for file or folder.
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterCreatePublicLink($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = (int) $aArgs['UserId'];
$Type = $aArgs['Type'];
$Path = $aArgs['Path'];
$Name = $aArgs['Name'];
$Size = $aArgs['Size'];
$IsFolder = $aArgs['IsFolder'];
Api::CheckAccess($UserId);
Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$bFolder = (bool) $IsFolder;
$mResult = $this->getManager()->createPublicLink($sUserPiblicId, $Type, $Path, $Name, $Size, $bFolder);
self::Decorator()->UpdateUsedSpace();
}
}
/**
* Deletes public link from file or folder.
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterDeletePublicLink($aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
$Type = $aArgs['Type'];
$Path = $aArgs['Path'];
$Name = $aArgs['Name'];
Api::CheckAccess($UserId);
Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$mResult = $this->getManager()->deletePublicLink($sUserPiblicId, $Type, $Path, $Name);
self::Decorator()->UpdateUsedSpace();
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterIsFileExists($aArgs, &$mResult)
{
if (isset($aArgs['Type']) && $this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$mResult = $this->getManager()->isFileExists(
Api::getUserPublicIdById($UserId),
$aArgs['Type'],
$aArgs['Path'],
$aArgs['Name']
);
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterCheckQuota($aArgs, &$mResult)
{
$Type = $aArgs['Type'];
if ($this->checkStorageType($Type)) {
$sUserId = $aArgs['UserId'];
$iSize = (int) $aArgs['Size'];
$aQuota = FilesModule::Decorator()->GetQuota($sUserId, $Type);
$Limit = (int) $aQuota['Limit'];
$Used = (int) $aQuota['Used'];
$mResult = !($Limit > 0 && $Used + $iSize > $Limit);
return true;
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterUpdateExtendedProps(&$aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$mResult = $this->getManager()->updateExtendedProps(
$sUserPiblicId,
$aArgs['Type'],
$aArgs['Path'],
$aArgs['Name'],
$aArgs['ExtendedProps']
);
}
}
/**
* @ignore
* @param array $aArgs Arguments of event.
* @param mixed $mResult Is passed by reference.
*/
public function onAfterGetExtendedProps(&$aArgs, &$mResult)
{
$bCorrectArgs = isset($aArgs['Type']) && isset($aArgs['Path']) && isset($aArgs['Name']);
if ($bCorrectArgs && $this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$mResult = $this->getManager()->getExtendedProps(
$sUserPiblicId,
$aArgs['Type'],
$aArgs['Path'],
$aArgs['Name']
);
}
}
public function onAfterGetNonExistentFileName(&$aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$mResult = $this->getManager()->getNonExistentFileName(
$sUserPiblicId,
$aArgs['Type'],
$aArgs['Path'],
$aArgs['Name'],
$aArgs['WithoutGroup']
);
}
}
public function onAfterGetAccessInfoForPath(&$aArgs, &$mResult)
{
if ($this->checkStorageType($aArgs['Type'])) {
$UserId = $aArgs['UserId'];
Api::CheckAccess($UserId);
$sUserPiblicId = Api::getUserPublicIdById($UserId);
$aItems = [];
$sPath = $aArgs['Path'];
$aPaths = explode('/', $sPath);
do {
$oNode = Server::getNodeForPath('files/' . $aArgs['Type'] . '/' . $sPath, $sUserPiblicId);
if (!empty($sPath) && ($oNode instanceof SharedFile || $oNode instanceof SharedDirectory)) {
$aItems[$sPath] = $oNode->getAccess();
}
array_pop($aPaths);
$sPath = implode('/', $aPaths);
} while (count($aPaths) > 0);
$mResult = $aItems;
}
}
}