1: <?php
2: /**
3: * This code is licensed under AGPLv3 license or Afterlogic Software License
4: * if commercial version of the product was purchased.
5: * For full statements of the licenses see LICENSE-AFTERLOGIC and LICENSE-AGPL3 files.
6: */
7:
8: namespace Aurora\Modules\PersonalFiles;
9:
10: use Afterlogic\DAV\Constants;
11: use Afterlogic\DAV\FS\Directory;
12: use Afterlogic\DAV\FS\File;
13: use Afterlogic\DAV\Server;
14: use Aurora\Api;
15: use Aurora\Modules\Core\Module as CoreModule;
16: use Aurora\Modules\Files\Classes\FileItem;
17: use Aurora\Modules\Files\Enums\ErrorCodes;
18: use Aurora\Modules\Files\Module as FilesModule;
19: use Aurora\System\Exceptions\ApiException;
20:
21: /**
22: * @license https://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
23: * @license https://afterlogic.com/products/common-licensing Afterlogic Software License
24: * @copyright Copyright (c) 2023, Afterlogic Corp.
25:
26: * @package Modules
27: */
28: class Module extends \Aurora\System\Module\AbstractModule
29: {
30: protected static $sStorageType = 'personal';
31: protected static $iStorageOrder = 0;
32:
33: /**
34: * Indicates if it's allowed to move files/folders to this storage.
35: * @var type bool
36: */
37: protected static $bIsDroppable = true;
38:
39: protected $oBeforeDeleteUserRootPath = '';
40: protected $oBeforeDeleteUser = null;
41: /**
42: *
43: * @var \CApiFilesManager
44: */
45: public $oManager = null;
46:
47: /**
48: *
49: * @var \CApiModuleDecorator
50: */
51: protected $oMinModuleDecorator = null;
52:
53: public function getManager()
54: {
55: if ($this->oManager === null) {
56: $this->oManager = new Manager($this);
57: }
58:
59: return $this->oManager;
60: }
61:
62: /**
63: * Initializes Files Module.
64: *
65: * @ignore
66: */
67: public function init()
68: {
69: ini_set('default_charset', 'UTF-8'); //support for cyrillic characters in file names
70:
71: $this->subscribeEvent('Files::GetFile', array($this, 'onGetFile'));
72: $this->subscribeEvent('Files::CreateFile', array($this, 'onCreateFile'));
73: $this->subscribeEvent('Files::GetLinkType', array($this, 'onGetLinkType'));
74: $this->subscribeEvent('Files::CheckUrl', array($this, 'onCheckUrl'));
75:
76: $this->subscribeEvent('Files::GetStorages::after', array($this, 'onAfterGetStorages'));
77: $this->subscribeEvent('Files::GetFileInfo::after', array($this, 'onAfterGetFileInfo'), 10);
78: $this->subscribeEvent('Files::GetItems', array($this, 'onGetItems'));
79: $this->subscribeEvent('Files::CreateFolder::after', array($this, 'onAfterCreateFolder'));
80: $this->subscribeEvent('Files::Copy::after', array($this, 'onAfterCopy'));
81: $this->subscribeEvent('Files::Move::after', array($this, 'onAfterMove'));
82: $this->subscribeEvent('Files::Rename::after', array($this, 'onAfterRename'));
83: $this->subscribeEvent('Files::Delete::after', array($this, 'onAfterDelete'));
84: $this->subscribeEvent('Files::GetQuota::after', array($this, 'onAfterGetQuota'));
85: $this->subscribeEvent('Files::CreateLink::after', array($this, 'onAfterCreateLink'));
86: $this->subscribeEvent('Files::CreatePublicLink::after', array($this, 'onAfterCreatePublicLink'));
87: $this->subscribeEvent('Files::GetFileContent::after', array($this, 'onAfterGetFileContent'));
88: $this->subscribeEvent('Files::IsFileExists::after', array($this, 'onAfterIsFileExists'));
89: $this->subscribeEvent('Files::PopulateFileItem::after', array($this, 'onAfterPopulateFileItem'));
90: $this->subscribeEvent('Files::CheckQuota::after', array($this, 'onAfterCheckQuota'));
91: $this->subscribeEvent('Files::DeletePublicLink::after', array($this, 'onAfterDeletePublicLink'));
92: $this->subscribeEvent('Files::GetSubModules::after', array($this, 'onAfterGetSubModules'));
93: $this->subscribeEvent('Files::UpdateExtendedProps::after', array($this, 'onAfterUpdateExtendedProps'));
94: $this->subscribeEvent('Files::GetExtendedProps::after', array($this, 'onAfterGetExtendedProps'));
95:
96: $this->subscribeEvent('Core::DeleteUser::before', array($this, 'onBeforeDeleteUser'));
97: $this->subscribeEvent('Core::DeleteUser::after', array($this, 'onAfterDeleteUser'));
98:
99: $this->subscribeEvent('Files::GetNonExistentFileName::after', array($this, 'onAfterGetNonExistentFileName'));
100:
101: $this->subscribeEvent('Files::GetAccessInfoForPath::after', array($this, 'onAfterGetAccessInfoForPath'));
102: }
103:
104: /**
105: * Obtains list of module settings.
106: *
107: * @return array
108: */
109: public function GetSettings()
110: {
111: Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::Anonymous);
112:
113: return array(
114: 'UserSpaceLimitMb' => $this->getUserSpaceLimitMb(),
115: );
116: }
117:
118: /**
119: * Updates module's settings - saves them to config.json file.
120: *
121: * @param int $UserSpaceLimitMb User space limit setting in Mb.
122: * @return bool
123: */
124: public function UpdateSettings($UserSpaceLimitMb)
125: {
126: Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::TenantAdmin);
127:
128: FilesModule::getInstance()->setConfig('UserSpaceLimitMb', $UserSpaceLimitMb);
129: return (bool) FilesModule::getInstance()->saveModuleConfig();
130: }
131:
132: public function UpdateUsedSpace()
133: {
134: $iResult = 0;
135: Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
136: $oUser = Api::getAuthenticatedUser();
137:
138: if ($oUser) {
139: $iResult = $this->getManager()->getUserSpaceUsed($oUser->PublicId, [\Aurora\System\Enums\FileStorageType::Personal]);
140: $oUser->setExtendedProp(self::GetName() . '::UsedSpace', $iResult);
141: $oUser->save();
142: }
143:
144: return $iResult;
145: }
146:
147: /**
148: * Returns Min module decorator.
149: *
150: * @return \Aurora\System\Module\Decorator
151: */
152: private function getMinModuleDecorator()
153: {
154: return Api::GetModuleDecorator('Min');
155: }
156:
157: /**
158: * Checks if storage type is personal.
159: *
160: * @param string $Type Storage type.
161: * @return bool
162: */
163: protected function checkStorageType($Type)
164: {
165: return $Type === static::$sStorageType;
166: }
167:
168: /**
169: * Returns HTML title for specified URL.
170: * @param string $sUrl
171: * @return string
172: */
173: protected function getHtmlTitle($sUrl)
174: {
175: $oCurl = curl_init();
176: \curl_setopt_array($oCurl, array(
177: CURLOPT_URL => $sUrl,
178: CURLOPT_FOLLOWLOCATION => true,
179: CURLOPT_ENCODING => '',
180: CURLOPT_RETURNTRANSFER => true,
181: CURLOPT_AUTOREFERER => true,
182: CURLOPT_SSL_VERIFYPEER => false, //required for https urls
183: CURLOPT_CONNECTTIMEOUT => 5,
184: CURLOPT_TIMEOUT => 5,
185: CURLOPT_MAXREDIRS => 5
186: ));
187: $sContent = curl_exec($oCurl);
188: //$aInfo = curl_getinfo($oCurl);
189: curl_close($oCurl);
190:
191: preg_match('/<title>(.*?)<\/title>/s', $sContent, $aTitle);
192: return isset($aTitle['1']) ? trim($aTitle['1']) : '';
193: }
194:
195: /**
196: * Puts file content to $mResult.
197: * @ignore
198: * @param array $aArgs Arguments of event.
199: * @param mixed $mResult Is passed by reference.
200: */
201: public function onGetFile($aArgs, &$mResult)
202: {
203: if ($this->checkStorageType($aArgs['Type'])) {
204: $UserId = $aArgs['UserId'];
205:
206: $sUserPiblicId = Api::getUserPublicIdById($UserId);
207: $iOffset = isset($aArgs['Offset']) ? $aArgs['Offset'] : 0;
208: $iChunkSizet = isset($aArgs['ChunkSize']) ? $aArgs['ChunkSize'] : 0;
209:
210: try {
211: $mResult = $this->getManager()->getFile($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['Id'], $iOffset, $iChunkSizet);
212: } catch (\Sabre\DAV\Exception\NotFound $oEx) {
213: $mResult = false;
214: // echo(\Aurora\System\Managers\Response::GetJsonFromObject('Json', \Aurora\System\Managers\Response::FalseResponse(__METHOD__, 404, 'Not Found')));
215: $this->oHttp->StatusHeader(404);
216: exit;
217: }
218:
219: return true;
220: }
221: }
222:
223: /**
224: * Creates file.
225: * @ignore
226: * @param array $aArgs Arguments of event.
227: * @param mixed $mResult Is passed by reference.
228: */
229: public function onCreateFile($aArgs, &$Result)
230: {
231: if ($this->checkStorageType($aArgs['Type'])) {
232: $UserId = $aArgs['UserId'];
233: Api::CheckAccess($UserId);
234:
235: $currentUser = Server::getUser();
236: Server::setUser(Api::getUserPublicIdById($UserId));
237: $Result = $this->getManager()->createFile(
238: Api::getUserPublicIdById($UserId),
239: isset($aArgs['Type']) ? $aArgs['Type'] : null,
240: isset($aArgs['Path']) ? $aArgs['Path'] : null,
241: isset($aArgs['Name']) ? $aArgs['Name'] : null,
242: isset($aArgs['Data']) ? $aArgs['Data'] : null,
243: isset($aArgs['Overwrite']) ? $aArgs['Overwrite'] : null,
244: isset($aArgs['RangeType']) ? $aArgs['RangeType'] : null,
245: isset($aArgs['Offset']) ? $aArgs['Offset'] : null,
246: isset($aArgs['ExtendedProps']) ? $aArgs['ExtendedProps'] : null
247: );
248: Server::setUser($currentUser);
249:
250: self::Decorator()->UpdateUsedSpace();
251: return true;
252: }
253: }
254:
255: /**
256: * @ignore
257: * @param array $aArgs Arguments of event.
258: * @param mixed $mResult Is passed by reference.
259: */
260: public function onGetLinkType($aArgs, &$mResult)
261: {
262: $mResult = '';
263: }
264:
265: /**
266: * @ignore
267: * @param array $aArgs Arguments of event.
268: * @param mixed $mResult Is passed by reference.
269: */
270: public function onCheckUrl($aArgs, &$mResult)
271: {
272: $iUserId = Api::getAuthenticatedUserId();
273:
274: if ($iUserId) {
275: if (!empty($aArgs['Url'])) {
276: $sUrl = $aArgs['Url'];
277: if ($sUrl) {
278: $aRemoteFileInfo = \Aurora\System\Utils::GetRemoteFileInfo($sUrl);
279: if ((int)$aRemoteFileInfo['code'] > 0) {
280: $sFileName = basename($sUrl);
281: $sFileExtension = \Aurora\System\Utils::GetFileExtension($sFileName);
282:
283: if (empty($sFileExtension)) {
284: $sFileExtension = \Aurora\System\Utils::GetFileExtensionFromMimeContentType($aRemoteFileInfo['content-type']);
285: $sFileName .= '.'.$sFileExtension;
286: }
287:
288: if ($sFileExtension === 'htm' || $sFileExtension === 'html') {
289: $sTitle = $this->getHtmlTitle($sUrl);
290: }
291:
292: $mResult['Name'] = isset($sTitle) && strlen($sTitle)> 0 ? $sTitle : urldecode($sFileName);
293: $mResult['Size'] = $aRemoteFileInfo['size'];
294: }
295: }
296: }
297: }
298: }
299:
300: /**
301: * @ignore
302: * @param array $aArgs Arguments of event.
303: * @param \Aurora\Modules\Files\Classes\FileItem $oItem
304: * @return bool
305: */
306: public function onAfterPopulateFileItem($aArgs, &$oItem)
307: {
308: if ($oItem->IsLink) {
309: $sFileName = basename($oItem->LinkUrl);
310: $sFileExtension = \Aurora\System\Utils::GetFileExtension($sFileName);
311: if ($sFileExtension === 'htm' || $sFileExtension === 'html') {
312: // $oItem->Name = $this->getHtmlTitle($oItem->LinkUrl);
313: return true;
314: }
315: }
316:
317: return false;
318: }
319:
320: /**
321: * @ignore
322: * @param array $aArgs Arguments of event.
323: * @param mixed $mResult Is passed by reference.
324: */
325: public function onBeforeDeleteUser($aArgs, &$mResult)
326: {
327: if (isset($aArgs['UserId'])) {
328: $this->oBeforeDeleteUser = Api::getUserById($aArgs['UserId']);
329: if ($this->oBeforeDeleteUser) {
330: $this->oBeforeDeleteUserRootPath = $this->getManager()->oStorage->getRootPath($this->oBeforeDeleteUser->PublicId, \Aurora\System\Enums\FileStorageType::Personal, true);
331: }
332: }
333: }
334:
335: /**
336: * @ignore
337: * @param array $aArgs Arguments of event.
338: * @param mixed $mResult Is passed by reference.
339: */
340: public function onAfterDeleteUser($aArgs, $mResult)
341: {
342: if ($mResult && !empty($this->oBeforeDeleteUserRootPath)) {
343: \Aurora\System\Utils::RecRmdir($this->oBeforeDeleteUserRootPath);
344: $this->oBeforeDeleteUserRootPath = '';
345: }
346: }
347:
348: /**
349: * @ignore
350: * @param array $aArgs Arguments of event.
351: * @param mixed $mResult Is passed by reference.
352: */
353: public function onAfterGetStorages($aArgs, &$mResult)
354: {
355: array_unshift($mResult, [
356: 'Type' => static::$sStorageType,
357: 'DisplayName' => $this->i18N('LABEL_STORAGE'),
358: 'IsExternal' => false,
359: 'Order' => static::$iStorageOrder,
360: 'IsDroppable' => static::$bIsDroppable
361: ]);
362: }
363:
364: /**
365: * @ignore
366: * @param array $aArgs Arguments of event.
367: * @param mixed $mResult Is passed by reference.
368: */
369: public function onAfterGetSubModules($aArgs, &$mResult)
370: {
371: array_unshift($mResult, 'local.' . static::$sStorageType);
372: }
373:
374: /**
375: * @ignore
376: * @param array $aArgs Arguments of event.
377: * @param mixed $mResult Is passed by reference.
378: */
379: public function onGetItems($aArgs, &$mResult)
380: {
381: if ($this->checkStorageType($aArgs['Type'])) {
382: $UserId = $aArgs['UserId'];
383: Api::CheckAccess($UserId);
384:
385: $sUserPiblicId = Api::getUserPublicIdById($UserId);
386: $sHash = isset($aArgs['PublicHash']) ? $aArgs['PublicHash'] : null;
387: $bIsShared = isset($aArgs['Shared']) ? !!$aArgs['Shared'] : false;
388: $mResult = array_merge(
389: $mResult,
390: $this->getManager()->getFiles(
391: $sUserPiblicId,
392: $aArgs['Type'],
393: $aArgs['Path'],
394: $aArgs['Pattern'],
395: $sHash,
396: $bIsShared
397: )
398: );
399: }
400: }
401:
402: /**
403: * @ignore
404: * @param array $aArgs Arguments of event.
405: * @param mixed $mResult Is passed by reference.
406: */
407: public function onAfterGetFileContent($aArgs, &$mResult)
408: {
409: $UserId = $aArgs['UserId'];
410: Api::CheckAccess($UserId);
411:
412: $sUUID = Api::getUserPublicIdById($UserId);
413: $Type = $aArgs['Type'];
414: $Path = $aArgs['Path'];
415: $Name = $aArgs['Name'];
416:
417: $mFile = $this->getManager()->getFile($sUUID, $Type, $Path, $Name);
418: if (is_resource($mFile)) {
419: $mResult = stream_get_contents($mFile);
420: }
421: }
422:
423: /**
424: * @ignore
425: * @param array $aArgs Arguments of event.
426: * @param mixed $mResult Is passed by reference.
427: */
428: public function onAfterGetFileInfo($aArgs, &$mResult)
429: {
430: if ($this->checkStorageType($aArgs['Type'])) {
431: $UserId = $aArgs['UserId'];
432: Api::CheckAccess($UserId);
433:
434: $sUserPiblicId = Api::getUserPublicIdById($UserId);
435: $mResult = $this->getManager()->getFileInfo($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['Id']);
436:
437: // return true;
438: }
439: }
440:
441: /**
442: * @ignore
443: * @param array $aArgs Arguments of event.
444: * @param mixed $mResult Is passed by reference.
445: */
446: public function onAfterCreateFolder(&$aArgs, &$mResult)
447: {
448: $UserId = $aArgs['UserId'];
449: Api::CheckAccess($UserId);
450: $sUserPiblicId = Api::getUserPublicIdById($UserId);
451: if ($this->checkStorageType($aArgs['Type'])) {
452: $mResult = $this->getManager()->createFolder($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['FolderName']);
453: return true;
454: }
455: }
456:
457: /**
458: * @ignore
459: * @param array $aArgs Arguments of event.
460: * @param mixed $mResult Is passed by reference.
461: */
462: public function onAfterCreateLink($aArgs, &$mResult)
463: {
464: Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
465:
466: if ($this->checkStorageType($aArgs['Type'])) {
467: $Type = $aArgs['Type'];
468: $UserId = $aArgs['UserId'];
469: $Path = $aArgs['Path'];
470: $Name = $aArgs['Name'];
471: $Link = $aArgs['Link'];
472:
473: Api::CheckAccess($UserId);
474:
475: if (substr($Link, 0, 11) === 'javascript:') {
476: $Link = substr($Link, 11);
477: }
478:
479: $sUserPiblicId = Api::getUserPublicIdById($UserId);
480: if ($this->checkStorageType($Type)) {
481: $Name = \trim(\MailSo\Base\Utils::ClearFileName($Name));
482: $mResult = $this->getManager()->createLink($sUserPiblicId, $Type, $Path, $Link, $Name);
483: self::Decorator()->UpdateUsedSpace();
484: }
485: }
486: }
487:
488: /**
489: * @ignore
490: * @param array $aArgs Arguments of event.
491: * @param mixed $mResult Is passed by reference.
492: */
493: public function onAfterDelete(&$aArgs, &$mResult)
494: {
495: $UserId = $aArgs['UserId'];
496: Api::CheckAccess($UserId);
497: if ($this->checkStorageType($aArgs['Type'])) {
498: $mResult = false;
499:
500: foreach ($aArgs['Items'] as $aItem) {
501: try {
502: $oNode = Server::getNodeForPath(Constants::FILESTORAGE_PATH_ROOT . '/' . $aArgs['Type'] . '/' . $aItem['Path'] . '/' . $aItem['Name']);
503: } catch (\Exception $oEx) {
504: Api::LogException($oEx);
505: throw new ApiException(ErrorCodes::NotFound, $oEx, "Node not found");
506: }
507:
508: if (!$oNode) {
509: throw new ApiException(ErrorCodes::NotFound, null, "Node not found");
510: }
511:
512: if ($oNode instanceof \Afterlogic\DAV\FS\Shared\File || $oNode instanceof \Afterlogic\DAV\FS\Shared\Directory) {
513: if (!$oNode->isInherited()) {
514: throw new ApiException(ErrorCodes::CantDeleteSharedItem);
515: }
516: }
517:
518: $oNode->delete();
519:
520: $oItem = new FileItem();
521: $oItem->Id = $aItem['Name'];
522: $oItem->Name = $aItem['Name'];
523: $oItem->TypeStr = $aArgs['Type'];
524: $oItem->Path = $aItem['Path'];
525:
526: FilesModule::Decorator()->DeletePublicLink($UserId, $aArgs['Type'], $aItem['Path'], $aItem['Name']);
527: \Aurora\System\Managers\Thumb::RemoveFromCache($UserId, $oItem->getHash(), $aItem['Name']);
528:
529: $mResult = true;
530: }
531:
532: self::Decorator()->UpdateUsedSpace();
533: }
534: }
535:
536: /**
537: * @ignore
538: * @param array $aArgs Arguments of event.
539: * @param mixed $mResult Is passed by reference.
540: */
541: public function onAfterRename(&$aArgs, &$mResult)
542: {
543: if ($this->checkStorageType($aArgs['Type'])) {
544: $UserId = $aArgs['UserId'];
545: Api::CheckAccess($UserId);
546:
547: $sUserPiblicId = Api::getUserPublicIdById($UserId);
548: $sNewName = \trim(\MailSo\Base\Utils::ClearFileName($aArgs['NewName']));
549:
550: // $sNewName = $this->getManager()->getNonExistentFileName($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $sNewName);
551: $bIsLink = isset($aArgs['IsLink']) ? $aArgs['IsLink'] : false;
552: $mResult = $this->getManager()->rename($sUserPiblicId, $aArgs['Type'], $aArgs['Path'], $aArgs['Name'], $sNewName, $bIsLink);
553: }
554: }
555:
556: /**
557: * @ignore
558: * @param array $aArgs Arguments of event.
559: * @param mixed $mResult Is passed by reference.
560: */
561: public function onAfterCopy(&$aArgs, &$mResult)
562: {
563: $UserId = $aArgs['UserId'];
564: Api::CheckAccess($UserId);
565:
566: $sUserPiblicId = Api::getUserPublicIdById($UserId);
567:
568: if ($this->checkStorageType($aArgs['FromType'])) {
569: foreach ($aArgs['Files'] as $aItem) {
570: $bFolderIntoItself = isset($aItem['IsFolder']) && $aItem['IsFolder'] && $aArgs['ToPath'] === $aItem['FromPath'].'/'.$aItem['Name'];
571: if (!$bFolderIntoItself) {
572: $sNewName = isset($aItem['NewName']) ? $aItem['NewName'] : $aItem['Name'];
573: $mResult = $this->getManager()->copy(
574: $sUserPiblicId,
575: $aItem['FromType'],
576: $aArgs['ToType'],
577: $aItem['FromPath'],
578: $aArgs['ToPath'],
579: $aItem['Name'],
580: $this->getManager()->getNonExistentFileName(
581: $sUserPiblicId,
582: $aArgs['ToType'],
583: $aArgs['ToPath'],
584: $sNewName
585: )
586: );
587: }
588: }
589: self::Decorator()->UpdateUsedSpace();
590: }
591: }
592:
593: /**
594: * @ignore
595: * @param array $aArgs Arguments of event.
596: * @param mixed $mResult Is passed by reference.
597: */
598: public function onAfterMove(&$aArgs, &$mResult)
599: {
600: if ($this->checkStorageType($aArgs['FromType'])) {
601: $UserId = $aArgs['UserId'];
602: Api::CheckAccess($UserId);
603:
604: $sUserPiblicId = Api::getUserPublicIdById($UserId);
605: foreach ($aArgs['Files'] as $aItem) {
606: $bIntoItself = $aArgs['ToType'].'/'.$aArgs['ToPath'] === $aItem['FromType'].'/'.$aItem['FromPath'];
607:
608: if (!$bIntoItself) {
609: $sNewName = isset($aItem['NewName']) ? $aItem['NewName'] : $aItem['Name'];
610: $mResult = $this->getManager()->copy(
611: $sUserPiblicId,
612: $aItem['FromType'],
613: $aArgs['ToType'],
614: $aItem['FromPath'],
615: $aArgs['ToPath'],
616: $aItem['Name'],
617: $this->getManager()->getNonExistentFileName(
618: $sUserPiblicId,
619: $aArgs['ToType'],
620: $aArgs['ToPath'],
621: $sNewName
622: ),
623: true
624: );
625: } else {
626: throw new ApiException(ErrorCodes::CannotCopyOrMoveItemToItself);
627: }
628: }
629:
630: self::Decorator()->UpdateUsedSpace();
631: }
632: }
633:
634: protected function getUserSpaceLimitMb()
635: {
636: $iSpaceLimitMb = FilesModule::getInstance()->getConfig('UserSpaceLimitMb', 0);
637:
638: $iUserId = Api::getAuthenticatedUserId();
639: $oUser = CoreModule::Decorator()->GetUserUnchecked($iUserId);
640:
641: if ($oUser) {
642: $iSpaceLimitMb = $oUser->{'Files::UserSpaceLimitMb'};
643: }
644:
645: $aArgs = [
646: 'UserId' => $iUserId
647: ];
648: $this->broadcastEvent(
649: 'GetUserSpaceLimitMb',
650: $aArgs,
651: $iSpaceLimitMb
652: );
653: return $iSpaceLimitMb;
654: }
655:
656: /**
657: * @ignore
658: * @param array $aArgs Arguments of event.
659: * @param mixed $mResult Is passed by reference.
660: */
661: public function onAfterGetQuota($aArgs, &$mResult)
662: {
663: if ($this->checkStorageType($aArgs['Type'])) {
664: $iSize = 0;
665:
666: $oUser = CoreModule::Decorator()->GetUserUnchecked($aArgs['UserId']);
667:
668: if ($oUser) {
669: $iSize = isset($oUser->{self::GetName() . '::UsedSpace'}) ? $oUser->{self::GetName() . '::UsedSpace'} : 0;
670: }
671:
672: $mResult = array(
673: 'Used' => (int) $iSize,
674: 'Limit' => $this->getUserSpaceLimitMb() * 1024 * 1024
675: );
676: }
677: }
678:
679: /**
680: * Creates public link for file or folder.
681: * @ignore
682: * @param array $aArgs Arguments of event.
683: * @param mixed $mResult Is passed by reference.
684: */
685: public function onAfterCreatePublicLink($aArgs, &$mResult)
686: {
687: if ($this->checkStorageType($aArgs['Type'])) {
688: $UserId = (int) $aArgs['UserId'];
689: $Type = $aArgs['Type'];
690: $Path = $aArgs['Path'];
691: $Name = $aArgs['Name'];
692: $Size = $aArgs['Size'];
693: $IsFolder = $aArgs['IsFolder'];
694:
695: Api::CheckAccess($UserId);
696:
697: Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
698: $sUserPiblicId = Api::getUserPublicIdById($UserId);
699: $bFolder = (bool) $IsFolder;
700: $mResult = $this->getManager()->createPublicLink($sUserPiblicId, $Type, $Path, $Name, $Size, $bFolder);
701: self::Decorator()->UpdateUsedSpace();
702: }
703: }
704:
705: /**
706: * Deletes public link from file or folder.
707: * @ignore
708: * @param array $aArgs Arguments of event.
709: * @param mixed $mResult Is passed by reference.
710: */
711: public function onAfterDeletePublicLink($aArgs, &$mResult)
712: {
713: if ($this->checkStorageType($aArgs['Type'])) {
714: $UserId = $aArgs['UserId'];
715: $Type = $aArgs['Type'];
716: $Path = $aArgs['Path'];
717: $Name = $aArgs['Name'];
718:
719: Api::CheckAccess($UserId);
720:
721: Api::checkUserRoleIsAtLeast(\Aurora\System\Enums\UserRole::NormalUser);
722:
723: $sUserPiblicId = Api::getUserPublicIdById($UserId);
724:
725: $mResult = $this->getManager()->deletePublicLink($sUserPiblicId, $Type, $Path, $Name);
726: self::Decorator()->UpdateUsedSpace();
727: }
728: }
729:
730: /**
731: * @ignore
732: * @param array $aArgs Arguments of event.
733: * @param mixed $mResult Is passed by reference.
734: */
735: public function onAfterIsFileExists($aArgs, &$mResult)
736: {
737: if (isset($aArgs['Type']) && $this->checkStorageType($aArgs['Type'])) {
738: $UserId = $aArgs['UserId'];
739: Api::CheckAccess($UserId);
740:
741: $mResult = $this->getManager()->isFileExists(
742: Api::getUserPublicIdById($UserId),
743: $aArgs['Type'],
744: $aArgs['Path'],
745: $aArgs['Name']
746: );
747: }
748: }
749:
750: /**
751: * @ignore
752: * @param array $aArgs Arguments of event.
753: * @param mixed $mResult Is passed by reference.
754: */
755: public function onAfterCheckQuota($aArgs, &$mResult)
756: {
757: $Type = $aArgs['Type'];
758: if ($this->checkStorageType($Type)) {
759: $sUserId = $aArgs['UserId'];
760: $iSize = (int) $aArgs['Size'];
761: $aQuota = FilesModule::Decorator()->GetQuota($sUserId, $Type);
762: $Limit = (int) $aQuota['Limit'];
763: $Used = (int) $aQuota['Used'];
764: $mResult = !($Limit > 0 && $Used + $iSize > $Limit);
765: return true;
766: }
767: }
768:
769: /**
770: * @ignore
771: * @param array $aArgs Arguments of event.
772: * @param mixed $mResult Is passed by reference.
773: */
774: public function onAfterUpdateExtendedProps(&$aArgs, &$mResult)
775: {
776: if ($this->checkStorageType($aArgs['Type'])) {
777: $UserId = $aArgs['UserId'];
778: Api::CheckAccess($UserId);
779: $sUserPiblicId = Api::getUserPublicIdById($UserId);
780: $mResult = $this->getManager()->updateExtendedProps(
781: $sUserPiblicId,
782: $aArgs['Type'],
783: $aArgs['Path'],
784: $aArgs['Name'],
785: $aArgs['ExtendedProps']
786: );
787: }
788: }
789:
790: /**
791: * @ignore
792: * @param array $aArgs Arguments of event.
793: * @param mixed $mResult Is passed by reference.
794: */
795: public function onAfterGetExtendedProps(&$aArgs, &$mResult)
796: {
797: $bCorrectArgs = isset($aArgs['Type']) && isset($aArgs['Path']) && isset($aArgs['Name']);
798: if ($bCorrectArgs && $this->checkStorageType($aArgs['Type'])) {
799: $UserId = $aArgs['UserId'];
800: Api::CheckAccess($UserId);
801: $sUserPiblicId = Api::getUserPublicIdById($UserId);
802: $mResult = $this->getManager()->getExtendedProps(
803: $sUserPiblicId,
804: $aArgs['Type'],
805: $aArgs['Path'],
806: $aArgs['Name']
807: );
808: }
809: }
810:
811: public function onAfterGetNonExistentFileName(&$aArgs, &$mResult)
812: {
813: if ($this->checkStorageType($aArgs['Type'])) {
814: $UserId = $aArgs['UserId'];
815: Api::CheckAccess($UserId);
816: $sUserPiblicId = Api::getUserPublicIdById($UserId);
817: $mResult = $this->getManager()->getNonExistentFileName(
818: $sUserPiblicId,
819: $aArgs['Type'],
820: $aArgs['Path'],
821: $aArgs['Name'],
822: $aArgs['WithoutGroup']
823: );
824: }
825: }
826:
827: public function onAfterGetAccessInfoForPath(&$aArgs, &$mResult)
828: {
829: if ($this->checkStorageType($aArgs['Type'])) {
830: $UserId = $aArgs['UserId'];
831: Api::CheckAccess($UserId);
832: $sUserPiblicId = Api::getUserPublicIdById($UserId);
833:
834: $aItems = [];
835: $sPath = $aArgs['Path'];
836: $aPaths = explode('/', $sPath);
837: do {
838: $oNode = Server::getNodeForPath('files/' . $aArgs['Type'] . '/' . $sPath, $sUserPiblicId);
839: if ($oNode instanceof File || $oNode instanceof Directory) {
840: $aItems[$sPath] = $oNode->getAccess();
841: }
842: array_pop($aPaths);
843: $sPath = implode('/', $aPaths);
844: } while (count($aPaths) > 0);
845: $mResult = $aItems;
846: }
847: }
848: }
849: