DocSpace-buildtools/common/ASC.Data.Storage/DiscStorage/DiscDataStore.cs

757 lines
25 KiB
C#
Raw Normal View History

2022-03-15 18:00:53 +00:00
// (c) Copyright Ascensio System SIA 2010-2022
//
// This program is a free software product.
// You can redistribute it and/or modify it under the terms
// of the GNU Affero General Public License (AGPL) version 3 as published by the Free Software
// Foundation. In accordance with Section 7(a) of the GNU AGPL its Section 15 shall be amended
// to the effect that Ascensio System SIA expressly excludes the warranty of non-infringement of
// any third-party rights.
//
// This program is distributed WITHOUT ANY WARRANTY, without even the implied warranty
// of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For details, see
// the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
//
// You can contact Ascensio System SIA at Lubanas st. 125a-25, Riga, Latvia, EU, LV-1021.
//
// The interactive user interfaces in modified source and object code versions of the Program must
// display Appropriate Legal Notices, as required under Section 5 of the GNU AGPL version 3.
//
// Pursuant to Section 7(b) of the License you must retain the original Product logo when
// distributing the program. Pursuant to Section 7(e) we decline to grant you any rights under
// trademark law for use of our trademarks.
//
// All the Product's GUI elements, including illustrations and icon sets, as well as technical writing
// content are licensed under the terms of the Creative Commons Attribution-ShareAlike 4.0
// International. See the License terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
namespace ASC.Data.Storage.DiscStorage;
[Scope]
public class DiscDataStore : BaseStorage
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
public override bool IsSupportInternalUri => false;
public override bool IsSupportedPreSignedUri => false;
public override bool IsSupportChunking => true;
private readonly Dictionary<string, MappedPath> _mappedPaths = new Dictionary<string, MappedPath>();
private ICrypt _crypt;
2022-03-17 15:07:17 +00:00
private readonly EncryptionSettingsHelper _encryptionSettingsHelper;
private readonly EncryptionFactory _encryptionFactory;
2022-02-10 11:24:16 +00:00
public override IDataStore Configure(string tenant, Handler handlerConfig, Module moduleConfig, IDictionary<string, string> props)
{
2022-02-11 10:04:06 +00:00
Tenant = tenant;
2022-02-10 11:24:16 +00:00
//Fill map path
2022-02-11 10:04:06 +00:00
Modulename = moduleConfig.Name;
DataList = new DataList(moduleConfig);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
foreach (var domain in moduleConfig.Domain)
2019-06-04 14:43:20 +00:00
{
2022-02-11 10:04:06 +00:00
_mappedPaths.Add(domain.Name, new MappedPath(TpathUtils, tenant, moduleConfig.AppendTenantId, domain.Path, handlerConfig.GetProperties()));
2022-02-10 11:24:16 +00:00
}
2022-02-10 11:24:16 +00:00
//Add default
2022-02-11 10:04:06 +00:00
_mappedPaths.Add(string.Empty, new MappedPath(TpathUtils, tenant, moduleConfig.AppendTenantId, PathUtils.Normalize(moduleConfig.Path), handlerConfig.GetProperties()));
2022-02-10 11:24:16 +00:00
//Make expires
2022-02-11 10:04:06 +00:00
DomainsExpires =
2022-02-10 11:24:16 +00:00
moduleConfig.Domain.Where(x => x.Expires != TimeSpan.Zero).
ToDictionary(x => x.Name,
y => y.Expires);
2022-02-11 10:04:06 +00:00
DomainsExpires.Add(string.Empty, moduleConfig.Expires);
2022-02-10 11:24:16 +00:00
var settings = moduleConfig.DisabledEncryption ? new EncryptionSettings() : _encryptionSettingsHelper.Load();
_crypt = _encryptionFactory.GetCrypt(moduleConfig.Name, settings);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
return this;
}
2022-02-10 11:24:16 +00:00
public DiscDataStore(
TempStream tempStream,
TenantManager tenantManager,
PathUtils pathUtils,
EmailValidationKeyProvider emailValidationKeyProvider,
IHttpContextAccessor httpContextAccessor,
IOptionsMonitor<ILog> options,
EncryptionSettingsHelper encryptionSettingsHelper,
2022-01-13 11:19:39 +00:00
EncryptionFactory encryptionFactory,
IHttpClientFactory clientFactory)
: base(tempStream, tenantManager, pathUtils, emailValidationKeyProvider, httpContextAccessor, options, clientFactory)
2022-02-10 11:24:16 +00:00
{
_encryptionSettingsHelper = encryptionSettingsHelper;
_encryptionFactory = encryptionFactory;
}
public string GetPhysicalPath(string domain, string path)
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var pathMap = GetPath(domain);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
return (pathMap.PhysicalPath + EnsureLeadingSlash(path)).Replace('\\', '/');
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<Stream> GetReadStreamAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
return Task.FromResult(GetReadStream(domain, path, true));
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
public Stream GetReadStream(string domain, string path, bool withDecription)
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
2022-02-10 11:24:16 +00:00
if (File.Exists(target))
{
return withDecription ? _crypt.GetReadStream(target) : File.OpenRead(target);
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("File not found", Path.GetFullPath(target));
}
2022-02-10 11:24:16 +00:00
public override Task<Stream> GetReadStreamAsync(string domain, string path, int offset)
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
if (File.Exists(target))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
var stream = _crypt.GetReadStream(target);
if (0 < offset && stream.CanSeek)
2022-02-10 11:06:37 +00:00
{
2022-02-10 11:24:16 +00:00
stream.Seek(offset, SeekOrigin.Begin);
2022-02-10 11:06:37 +00:00
}
2022-03-09 17:15:51 +00:00
return Task.FromResult(stream);
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("File not found", Path.GetFullPath(target));
}
2022-03-09 17:15:51 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentType, string contentDisposition)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
return SaveAsync(domain, path, stream);
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream, string contentEncoding, int cacheDays)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
return SaveAsync(domain, path, stream);
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream)
2022-02-10 11:24:16 +00:00
{
Logger.Debug("Save " + path);
2019-06-04 14:43:20 +00:00
2022-02-11 10:04:06 +00:00
var buffered = TempStream.GetBuffered(stream);
2022-02-10 11:24:16 +00:00
if (QuotaController != null)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
QuotaController.QuotaUsedCheck(buffered.Length);
2019-06-04 14:43:20 +00:00
}
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
ArgumentNullException.ThrowIfNull(stream);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Try seek to start
2022-03-09 17:15:51 +00:00
return InternalSaveAsync(domain, path, buffered);
}
2022-02-16 12:57:37 +00:00
2022-03-09 17:15:51 +00:00
private async Task<Uri> InternalSaveAsync(string domain, string path, Stream buffered)
{
//Try seek to start
2022-02-10 11:24:16 +00:00
if (buffered.CanSeek)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
buffered.Seek(0, SeekOrigin.Begin);
}
2022-02-10 11:24:16 +00:00
//Lookup domain
var target = GetTarget(domain, path);
CreateDirectory(target);
//Copy stream
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//optimaze disk file copy
long fslen;
if (buffered is FileStream fileStream)
{
File.Copy(fileStream.Name, target, true);
fslen = fileStream.Length;
}
else
{
using var fs = File.Open(target, FileMode.Create);
2022-03-09 17:15:51 +00:00
await buffered.CopyToAsync(fs);
2022-02-10 11:24:16 +00:00
fslen = fs.Length;
}
2022-02-10 11:06:37 +00:00
2022-02-10 11:24:16 +00:00
QuotaUsedAdd(domain, fslen);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
_crypt.EncryptFile(target);
2022-03-09 17:15:51 +00:00
return await GetUriAsync(domain, path);
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<Uri> SaveAsync(string domain, string path, Stream stream, ACL acl)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
return SaveAsync(domain, path, stream);
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
#region chunking
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override async Task<string> UploadChunkAsync(string domain, string path, string uploadId, Stream stream, long defaultChunkSize, int chunkNumber, long chunkLength)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(domain, path);
var mode = chunkNumber == 0 ? FileMode.Create : FileMode.Append;
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
using (var fs = new FileStream(target, mode))
2019-06-04 14:43:20 +00:00
{
2022-03-09 17:15:51 +00:00
await stream.CopyToAsync(fs);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
return string.Format("{0}_{1}", chunkNumber, uploadId);
}
2022-03-09 17:15:51 +00:00
public override Task<Uri> FinalizeChunkedUploadAsync(string domain, string path, string uploadId, Dictionary<int, string> eTags)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(domain, path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
if (QuotaController != null)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
if (!File.Exists(target))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("file not found " + target);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
var size = _crypt.GetFileSize(target);
QuotaUsedAdd(domain, size);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
_crypt.EncryptFile(target);
2022-03-09 17:15:51 +00:00
return GetUriAsync(domain, path);
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task AbortChunkedUploadAsync(string domain, string path, string uploadId)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(domain, path);
if (File.Exists(target))
{
File.Delete(target);
2019-06-04 14:43:20 +00:00
}
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
#endregion
2022-03-09 17:15:51 +00:00
public override Task DeleteAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
if (File.Exists(target))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
var size = _crypt.GetFileSize(target);
File.Delete(target);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
QuotaUsedDelete(domain, size);
2022-03-09 17:15:51 +00:00
return Task.CompletedTask; ;
2022-02-10 11:24:16 +00:00
}
else
{
throw new FileNotFoundException("file not found", target);
}
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task DeleteFilesAsync(string domain, List<string> paths)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(paths);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
foreach (var path in paths)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
if (!File.Exists(target))
2022-02-10 11:06:37 +00:00
{
2022-02-10 11:24:16 +00:00
continue;
2022-02-10 11:06:37 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var size = _crypt.GetFileSize(target);
File.Delete(target);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
QuotaUsedDelete(domain, size);
}
2022-01-25 09:29:11 +00:00
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task DeleteFilesAsync(string domain, string folderPath, string pattern, bool recursive)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(folderPath);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, folderPath);
if (Directory.Exists(targetDir))
{
var entries = Directory.GetFiles(targetDir, pattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
foreach (var entry in entries)
{
var size = _crypt.GetFileSize(entry);
File.Delete(entry);
2019-06-04 14:43:20 +00:00
QuotaUsedDelete(domain, size);
}
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
else
{
2022-03-09 17:15:51 +00:00
throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
2022-02-10 11:24:16 +00:00
}
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task DeleteFilesAsync(string domain, string folderPath, DateTime fromDate, DateTime toDate)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(folderPath);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, folderPath);
if (Directory.Exists(targetDir))
{
var entries = Directory.GetFiles(targetDir, "*", SearchOption.AllDirectories);
foreach (var entry in entries)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
var fileInfo = new FileInfo(entry);
if (fileInfo.LastWriteTime >= fromDate && fileInfo.LastWriteTime <= toDate)
2019-06-04 14:43:20 +00:00
{
var size = _crypt.GetFileSize(entry);
2019-06-04 14:43:20 +00:00
File.Delete(entry);
QuotaUsedDelete(domain, size);
}
}
}
2022-02-10 11:24:16 +00:00
else
2019-06-04 14:43:20 +00:00
{
2022-03-09 17:15:51 +00:00
throw new DirectoryNotFoundException($"Directory '{targetDir}' not found");
2019-06-04 14:43:20 +00:00
}
2022-01-25 09:29:11 +00:00
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task MoveDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(srcdomain, srcdir);
var newtarget = GetTarget(newdomain, newdir);
var newtargetSub = newtarget.Remove(newtarget.LastIndexOf(Path.DirectorySeparatorChar));
if (!Directory.Exists(newtargetSub))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
Directory.CreateDirectory(newtargetSub);
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
Directory.Move(target, newtarget);
2022-01-25 09:29:11 +00:00
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task<Uri> MoveAsync(string srcdomain, string srcpath, string newdomain, string newpath, bool quotaCheckFileSize = true)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(srcpath);
ArgumentNullException.ThrowIfNull(newpath);
2022-02-10 11:24:16 +00:00
var target = GetTarget(srcdomain, srcpath);
var newtarget = GetTarget(newdomain, newpath);
2022-02-10 11:06:37 +00:00
2022-02-10 11:24:16 +00:00
if (File.Exists(target))
{
if (!Directory.Exists(Path.GetDirectoryName(newtarget)))
2022-02-10 11:06:37 +00:00
{
2022-02-10 11:24:16 +00:00
Directory.CreateDirectory(Path.GetDirectoryName(newtarget));
2022-02-10 11:06:37 +00:00
}
2022-02-10 11:24:16 +00:00
var flength = _crypt.GetFileSize(target);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Delete file if exists
if (File.Exists(newtarget))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
File.Delete(newtarget);
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
File.Move(target, newtarget);
2022-02-10 11:24:16 +00:00
QuotaUsedDelete(srcdomain, flength);
QuotaUsedAdd(newdomain, flength, quotaCheckFileSize);
}
else
{
throw new FileNotFoundException("File not found", Path.GetFullPath(target));
}
2022-03-09 17:15:51 +00:00
return GetUriAsync(newdomain, newpath);
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task<bool> IsDirectoryAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, path);
if (!string.IsNullOrEmpty(targetDir) && !targetDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
targetDir += Path.DirectorySeparatorChar;
}
2022-03-09 17:15:51 +00:00
return Task.FromResult(!string.IsNullOrEmpty(targetDir) && Directory.Exists(targetDir));
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task DeleteDirectoryAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, path);
if (string.IsNullOrEmpty(targetDir))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
throw new Exception("targetDir is null");
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
if (!targetDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
2022-02-10 11:24:16 +00:00
{
targetDir += Path.DirectorySeparatorChar;
}
2019-06-04 14:43:20 +00:00
2022-03-17 15:01:39 +00:00
if (!Directory.Exists(targetDir))
{
return Task.CompletedTask;
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var entries = Directory.GetFiles(targetDir, "*.*", SearchOption.AllDirectories);
var size = entries.Select(entry => _crypt.GetFileSize(entry)).Sum();
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var subDirs = Directory.GetDirectories(targetDir, "*", SearchOption.AllDirectories).ToList();
subDirs.Reverse();
subDirs.ForEach(subdir => Directory.Delete(subdir, true));
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
Directory.Delete(targetDir, true);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
QuotaUsedDelete(domain, size);
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<long> GetFileSizeAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(domain, path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
if (File.Exists(target))
{
2022-03-09 17:15:51 +00:00
return Task.FromResult(_crypt.GetFileSize(target));
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("file not found " + target);
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<long> GetDirectorySizeAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(domain, path);
2022-02-10 11:24:16 +00:00
if (Directory.Exists(target))
{
2022-03-09 17:15:51 +00:00
return Task.FromResult(Directory.GetFiles(target, "*.*", SearchOption.AllDirectories)
.Select(entry => _crypt.GetFileSize(entry))
.Sum());
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("directory not found " + target);
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<Uri> SaveTempAsync(string domain, out string assignedPath, Stream stream)
2022-02-10 11:24:16 +00:00
{
assignedPath = Guid.NewGuid().ToString();
2022-03-09 17:15:51 +00:00
return SaveAsync(domain, assignedPath, stream);
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override async Task<string> SavePrivateAsync(string domain, string path, Stream stream, DateTime expires)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
var result = await SaveAsync(domain, path, stream);
return result.ToString();
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task DeleteExpiredAsync(string domain, string folderPath, TimeSpan oldThreshold)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(folderPath);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, folderPath);
if (!Directory.Exists(targetDir))
2019-06-04 14:43:20 +00:00
{
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
var entries = Directory.GetFiles(targetDir, "*.*", SearchOption.TopDirectoryOnly);
foreach (var entry in entries)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
var finfo = new FileInfo(entry);
if ((DateTime.UtcNow - finfo.CreationTimeUtc) > oldThreshold)
2022-02-10 11:06:37 +00:00
{
2022-02-10 11:24:16 +00:00
var size = _crypt.GetFileSize(entry);
File.Delete(entry);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
QuotaUsedDelete(domain, size);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
}
2022-01-25 09:29:11 +00:00
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
public override string GetUploadForm(string domain, string directoryPath, string redirectTo, long maxUploadSize, string contentType, string contentDisposition, string submitLabel)
{
throw new NotSupportedException("This operation supported only on s3 storage");
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<string> GetUploadedUrlAsync(string domain, string directoryPath)
2022-02-10 11:24:16 +00:00
{
throw new NotSupportedException("This operation supported only on s3 storage");
}
public override string GetUploadUrl()
{
throw new NotSupportedException("This operation supported only on s3 storage");
}
public override string GetPostParams(string domain, string directoryPath, long maxUploadSize, string contentType, string contentDisposition)
{
throw new NotSupportedException("This operation supported only on s3 storage");
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override IAsyncEnumerable<string> ListDirectoriesRelativeAsync(string domain, string path, bool recursive)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, path);
if (!string.IsNullOrEmpty(targetDir) && !targetDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
targetDir += Path.DirectorySeparatorChar;
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
if (Directory.Exists(targetDir))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
var entries = Directory.GetDirectories(targetDir, "*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
2022-03-09 17:15:51 +00:00
var tmp = Array.ConvertAll(
entries,
x => x.Substring(targetDir.Length));
return tmp.ToAsyncEnumerable();
2019-06-04 14:43:20 +00:00
}
2022-03-09 17:15:51 +00:00
return AsyncEnumerable.Empty<string>();
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override IAsyncEnumerable<string> ListFilesRelativeAsync(string domain, string path, string pattern, bool recursive)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var targetDir = GetTarget(domain, path);
if (!string.IsNullOrEmpty(targetDir) && !targetDir.EndsWith(Path.DirectorySeparatorChar.ToString()))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
targetDir += Path.DirectorySeparatorChar;
}
2022-02-10 11:24:16 +00:00
if (Directory.Exists(targetDir))
{
var entries = Directory.GetFiles(targetDir, pattern, recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
2022-03-09 17:15:51 +00:00
var tmp = Array.ConvertAll(
entries,
x => x.Substring(targetDir.Length));
return tmp.ToAsyncEnumerable();
2019-06-04 14:43:20 +00:00
}
2022-03-09 17:15:51 +00:00
return AsyncEnumerable.Empty<string>();
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task<bool> IsFileAsync(string domain, string path)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
//Return dirs
var target = GetTarget(domain, path);
var result = File.Exists(target);
2022-03-09 17:15:51 +00:00
return Task.FromResult(result);
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override async Task<long> ResetQuotaAsync(string domain)
2022-02-10 11:24:16 +00:00
{
if (QuotaController != null)
{
2022-03-09 17:15:51 +00:00
var size = await GetUsedQuotaAsync(domain);
2022-02-11 10:04:06 +00:00
QuotaController.QuotaUsedSet(Modulename, domain, DataList.GetData(domain), size);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
return 0;
}
2019-06-04 14:43:20 +00:00
2022-03-09 17:15:51 +00:00
public override Task<long> GetUsedQuotaAsync(string domain)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(domain, string.Empty);
long size = 0;
2022-02-10 11:24:16 +00:00
if (Directory.Exists(target))
{
var entries = Directory.GetFiles(target, "*.*", SearchOption.AllDirectories);
size = entries.Select(entry => _crypt.GetFileSize(entry)).Sum();
2019-06-04 14:43:20 +00:00
}
2022-03-09 17:15:51 +00:00
return Task.FromResult(size);
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task<Uri> CopyAsync(string srcdomain, string srcpath, string newdomain, string newpath)
2022-02-10 11:24:16 +00:00
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(srcpath);
ArgumentNullException.ThrowIfNull(newpath);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var target = GetTarget(srcdomain, srcpath);
var newtarget = GetTarget(newdomain, newpath);
2022-02-10 11:24:16 +00:00
if (File.Exists(target))
{
if (!Directory.Exists(Path.GetDirectoryName(newtarget)))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
Directory.CreateDirectory(Path.GetDirectoryName(newtarget));
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
File.Copy(target, newtarget, true);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var flength = _crypt.GetFileSize(target);
QuotaUsedAdd(newdomain, flength);
}
else
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("File not found", Path.GetFullPath(target));
}
2022-03-09 17:15:51 +00:00
return GetUriAsync(newdomain, newpath);
2022-02-10 11:24:16 +00:00
}
2022-03-09 17:15:51 +00:00
public override Task CopyDirectoryAsync(string srcdomain, string srcdir, string newdomain, string newdir)
2022-02-10 11:24:16 +00:00
{
var target = GetTarget(srcdomain, srcdir);
var newtarget = GetTarget(newdomain, newdir);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var diSource = new DirectoryInfo(target);
var diTarget = new DirectoryInfo(newtarget);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
CopyAll(diSource, diTarget, newdomain);
2022-03-09 17:15:51 +00:00
return Task.CompletedTask;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
public Stream GetWriteStream(string domain, string path)
{
return GetWriteStream(domain, path, FileMode.Create);
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
public Stream GetWriteStream(string domain, string path, FileMode fileMode)
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
CreateDirectory(target);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
return File.Open(target, fileMode);
}
public void Decrypt(string domain, string path)
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
2022-02-10 11:24:16 +00:00
if (File.Exists(target))
{
2022-02-10 11:24:16 +00:00
_crypt.DecryptFile(target);
}
2022-02-10 11:24:16 +00:00
else
{
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("file not found", target);
}
}
2022-03-09 17:15:51 +00:00
protected override Task<Uri> SaveWithAutoAttachmentAsync(string domain, string path, Stream stream, string attachmentFileName)
{
return SaveAsync(domain, path, stream);
}
2022-02-10 11:24:16 +00:00
private void CopyAll(DirectoryInfo source, DirectoryInfo target, string newdomain)
{
// Check if the target directory exists, if not, create it.
if (!Directory.Exists(target.FullName))
{
Directory.CreateDirectory(target.FullName);
}
2022-02-10 11:24:16 +00:00
// Copy each file into it's new directory.
foreach (var fi in source.GetFiles())
{
2022-02-10 11:24:16 +00:00
var fp = CrossPlatform.PathCombine(target.ToString(), fi.Name);
fi.CopyTo(fp, true);
var size = _crypt.GetFileSize(fp);
QuotaUsedAdd(newdomain, size);
}
2022-02-10 11:24:16 +00:00
// Copy each subdirectory using recursion.
foreach (var diSourceSubDir in source.GetDirectories())
{
2022-02-10 11:24:16 +00:00
var nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir, newdomain);
}
2022-02-10 11:24:16 +00:00
}
2022-02-10 11:24:16 +00:00
private MappedPath GetPath(string domain)
{
if (domain != null && _mappedPaths.TryGetValue(domain, out var value))
2019-06-04 14:43:20 +00:00
{
2022-03-09 17:15:51 +00:00
return value;
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
return _mappedPaths[string.Empty].AppendDomain(domain);
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
private static void CreateDirectory(string target)
{
var targetDirectory = Path.GetDirectoryName(target);
if (!Directory.Exists(targetDirectory))
{
Directory.CreateDirectory(targetDirectory);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
private string GetTarget(string domain, string path)
{
var pathMap = GetPath(domain);
//Build Dir
var target = CrossPlatform.PathCombine(pathMap.PhysicalPath, PathUtils.Normalize(path));
ValidatePath(target);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
return target;
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
private static void ValidatePath(string target)
{
if (Path.GetDirectoryName(target).IndexOfAny(Path.GetInvalidPathChars()) != -1 ||
Path.GetFileName(target).IndexOfAny(Path.GetInvalidFileNameChars()) != -1)
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
//Throw
throw new ArgumentException("bad path");
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
}
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
public void Encrypt(string domain, string path)
{
2022-03-09 17:15:51 +00:00
ArgumentNullException.ThrowIfNull(path);
2019-06-04 14:43:20 +00:00
2022-02-10 11:24:16 +00:00
var target = GetTarget(domain, path);
if (File.Exists(target))
2019-06-04 14:43:20 +00:00
{
2022-02-10 11:24:16 +00:00
_crypt.EncryptFile(target);
2019-06-04 14:43:20 +00:00
}
2022-02-10 11:24:16 +00:00
else
{
2022-02-10 11:24:16 +00:00
throw new FileNotFoundException("file not found", target);
}
2019-08-15 12:04:42 +00:00
}
2022-02-10 11:24:16 +00:00
}