725 lines
32 KiB
C#
725 lines
32 KiB
C#
/*
|
|
*
|
|
* (c) Copyright Ascensio System Limited 2010-2018
|
|
*
|
|
* This program is freeware. You can redistribute it and/or modify it under the terms of the GNU
|
|
* General Public License (GPL) version 3 as published by the Free Software Foundation (https://www.gnu.org/copyleft/gpl.html).
|
|
* In accordance with Section 7(a) of the GNU GPL 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 more details, see GNU GPL at https://www.gnu.org/copyleft/gpl.html
|
|
*
|
|
* You can contact Ascensio System SIA by email at sales@onlyoffice.com
|
|
*
|
|
* The interactive user interfaces in modified source and object code versions of ONLYOFFICE must display
|
|
* Appropriate Legal Notices, as required under Section 5 of the GNU GPL version 3.
|
|
*
|
|
* Pursuant to Section 7 § 3(b) of the GNU GPL you must retain the original ONLYOFFICE logo which contains
|
|
* relevant author attributions when distributing the software. If the display of the logo in its graphic
|
|
* form is not reasonably feasible for technical reasons, you must include the words "Powered by ONLYOFFICE"
|
|
* in every copy of the program you distribute.
|
|
* Pursuant to Section 7 § 3(e) we decline to grant you any rights under trademark law for use of our trademarks.
|
|
*
|
|
*/
|
|
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Runtime.Serialization;
|
|
using System.Security;
|
|
using System.Threading;
|
|
using System.Web;
|
|
|
|
using ASC.Common.Caching;
|
|
using ASC.Common.Logging;
|
|
using ASC.Common.Security.Authentication;
|
|
using ASC.Core;
|
|
using ASC.Files.Core;
|
|
using ASC.Files.Core.Security;
|
|
using ASC.MessagingSystem;
|
|
using ASC.Web.Core.Files;
|
|
using ASC.Web.Files.Classes;
|
|
using ASC.Web.Files.Core;
|
|
using ASC.Web.Files.Helpers;
|
|
using ASC.Web.Files.Resources;
|
|
using ASC.Web.Files.Services.DocumentService;
|
|
using ASC.Web.Files.Services.WCFService.FileOperations;
|
|
using ASC.Web.Studio.Core;
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Options;
|
|
|
|
using File = ASC.Files.Core.File;
|
|
using SecurityContext = ASC.Core.SecurityContext;
|
|
|
|
namespace ASC.Web.Files.Utils
|
|
{
|
|
public class FileConverter
|
|
{
|
|
private static readonly object locker = new object();
|
|
private static readonly IDictionary<File, ConvertFileOperationResult> conversionQueue = new Dictionary<File, ConvertFileOperationResult>(new FileComparer());
|
|
private static readonly ICache cache = AscCache.Default;
|
|
|
|
private static Timer timer;
|
|
private static readonly object singleThread = new object();
|
|
private const int TIMER_PERIOD = 500;
|
|
|
|
public FileUtility FileUtility { get; }
|
|
public FilesLinkUtility FilesLinkUtility { get; }
|
|
public IDaoFactory DaoFactory { get; }
|
|
public SetupInfo SetupInfo { get; }
|
|
public PathProvider PathProvider { get; }
|
|
public FileSecurity FileSecurity { get; }
|
|
public FileMarker FileMarker { get; }
|
|
public TenantManager TenantManager { get; }
|
|
public AuthContext AuthContext { get; }
|
|
public EntryManager EntryManager { get; }
|
|
public FilesSettingsHelper FilesSettingsHelper { get; }
|
|
public GlobalFolderHelper GlobalFolderHelper { get; }
|
|
public FilesMessageService FilesMessageService { get; }
|
|
public FileShareLink FileShareLink { get; }
|
|
public DocumentServiceHelper DocumentServiceHelper { get; }
|
|
public DocumentServiceConnector DocumentServiceConnector { get; }
|
|
public IServiceProvider ServiceProvider { get; }
|
|
public IHttpContextAccessor HttpContextAccesor { get; }
|
|
public ILog Logger { get; }
|
|
|
|
public FileConverter(
|
|
FileUtility fileUtility,
|
|
FilesLinkUtility filesLinkUtility,
|
|
IDaoFactory daoFactory,
|
|
SetupInfo setupInfo,
|
|
PathProvider pathProvider,
|
|
FileSecurity fileSecurity,
|
|
FileMarker fileMarker,
|
|
TenantManager tenantManager,
|
|
AuthContext authContext,
|
|
EntryManager entryManager,
|
|
IOptionsMonitor<ILog> options,
|
|
FilesSettingsHelper filesSettingsHelper,
|
|
GlobalFolderHelper globalFolderHelper,
|
|
FilesMessageService filesMessageService,
|
|
FileShareLink fileShareLink,
|
|
DocumentServiceHelper documentServiceHelper,
|
|
DocumentServiceConnector documentServiceConnector,
|
|
IServiceProvider serviceProvider)
|
|
{
|
|
FileUtility = fileUtility;
|
|
FilesLinkUtility = filesLinkUtility;
|
|
DaoFactory = daoFactory;
|
|
SetupInfo = setupInfo;
|
|
PathProvider = pathProvider;
|
|
FileSecurity = fileSecurity;
|
|
FileMarker = fileMarker;
|
|
TenantManager = tenantManager;
|
|
AuthContext = authContext;
|
|
EntryManager = entryManager;
|
|
FilesSettingsHelper = filesSettingsHelper;
|
|
GlobalFolderHelper = globalFolderHelper;
|
|
FilesMessageService = filesMessageService;
|
|
FileShareLink = fileShareLink;
|
|
DocumentServiceHelper = documentServiceHelper;
|
|
DocumentServiceConnector = documentServiceConnector;
|
|
ServiceProvider = serviceProvider;
|
|
Logger = options.CurrentValue;
|
|
}
|
|
public FileConverter(
|
|
FileUtility fileUtility,
|
|
FilesLinkUtility filesLinkUtility,
|
|
IDaoFactory daoFactory,
|
|
SetupInfo setupInfo,
|
|
PathProvider pathProvider,
|
|
FileSecurity fileSecurity,
|
|
FileMarker fileMarker,
|
|
TenantManager tenantManager,
|
|
AuthContext authContext,
|
|
EntryManager entryManager,
|
|
IOptionsMonitor<ILog> options,
|
|
FilesSettingsHelper filesSettingsHelper,
|
|
GlobalFolderHelper globalFolderHelper,
|
|
FilesMessageService filesMessageService,
|
|
FileShareLink fileShareLink,
|
|
DocumentServiceHelper documentServiceHelper,
|
|
DocumentServiceConnector documentServiceConnector,
|
|
IServiceProvider serviceProvider,
|
|
IHttpContextAccessor httpContextAccesor)
|
|
: this(fileUtility, filesLinkUtility, daoFactory, setupInfo, pathProvider, fileSecurity,
|
|
fileMarker, tenantManager, authContext, entryManager, options, filesSettingsHelper,
|
|
globalFolderHelper, filesMessageService, fileShareLink, documentServiceHelper, documentServiceConnector,
|
|
serviceProvider)
|
|
{
|
|
HttpContextAccesor = httpContextAccesor;
|
|
}
|
|
|
|
public bool EnableAsUploaded
|
|
{
|
|
get { return FileUtility.ExtsMustConvert.Any() && !string.IsNullOrEmpty(FilesLinkUtility.DocServiceConverterUrl); }
|
|
}
|
|
|
|
public bool MustConvert(File file)
|
|
{
|
|
if (file == null) return false;
|
|
|
|
var ext = FileUtility.GetFileExtension(file.Title);
|
|
return FileUtility.ExtsMustConvert.Contains(ext);
|
|
}
|
|
|
|
public bool EnableConvert(File file, string toExtension)
|
|
{
|
|
if (file == null || string.IsNullOrEmpty(toExtension))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (file.Encrypted)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var fileExtension = file.ConvertedExtension;
|
|
if (fileExtension.Trim('.').Equals(toExtension.Trim('.'), StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
fileExtension = FileUtility.GetFileExtension(file.Title);
|
|
if (FileUtility.InternalExtension.Values.Contains(toExtension))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return FileUtility.ExtsConvertible.Keys.Contains(fileExtension) && FileUtility.ExtsConvertible[fileExtension].Contains(toExtension);
|
|
}
|
|
|
|
public Stream Exec(File file)
|
|
{
|
|
return Exec(file, FileUtility.GetInternalExtension(file.Title));
|
|
}
|
|
|
|
public Stream Exec(File file, string toExtension)
|
|
{
|
|
if (!EnableConvert(file, toExtension))
|
|
{
|
|
var fileDao = DaoFactory.FileDao;
|
|
return fileDao.GetFileStream(file);
|
|
}
|
|
|
|
if (file.ContentLength > SetupInfo.AvailableFileSize)
|
|
{
|
|
throw new Exception(string.Format(FilesCommonResource.ErrorMassage_FileSizeConvert, FileSizeComment.FilesSizeToString(SetupInfo.AvailableFileSize)));
|
|
}
|
|
|
|
var fileUri = PathProvider.GetFileStreamUrl(file);
|
|
var docKey = DocumentServiceHelper.GetDocKey(file);
|
|
fileUri = DocumentServiceConnector.ReplaceCommunityAdress(fileUri);
|
|
DocumentServiceConnector.GetConvertedUri(fileUri, file.ConvertedExtension, toExtension, docKey, null, false, out var convertUri);
|
|
|
|
if (WorkContext.IsMono && ServicePointManager.ServerCertificateValidationCallback == null)
|
|
{
|
|
ServicePointManager.ServerCertificateValidationCallback += (s, c, n, p) => true; //HACK: http://ubuntuforums.org/showthread.php?t=1841740
|
|
}
|
|
return new ResponseStream(((HttpWebRequest)WebRequest.Create(convertUri)).GetResponse());
|
|
}
|
|
|
|
public File ExecSync(File file, string doc)
|
|
{
|
|
var fileDao = DaoFactory.FileDao;
|
|
var fileSecurity = FileSecurity;
|
|
if (!fileSecurity.CanRead(file))
|
|
{
|
|
var readLink = FileShareLink.Check(doc, true, fileDao, out file);
|
|
if (file == null)
|
|
{
|
|
throw new ArgumentNullException("file", FilesCommonResource.ErrorMassage_FileNotFound);
|
|
}
|
|
if (!readLink)
|
|
{
|
|
throw new SecurityException(FilesCommonResource.ErrorMassage_SecurityException_ReadFile);
|
|
}
|
|
}
|
|
|
|
var fileUri = PathProvider.GetFileStreamUrl(file);
|
|
var fileExtension = file.ConvertedExtension;
|
|
var toExtension = FileUtility.GetInternalExtension(file.Title);
|
|
var docKey = DocumentServiceHelper.GetDocKey(file);
|
|
|
|
fileUri = DocumentServiceConnector.ReplaceCommunityAdress(fileUri);
|
|
DocumentServiceConnector.GetConvertedUri(fileUri, fileExtension, toExtension, docKey, null, false, out var convertUri);
|
|
|
|
return SaveConvertedFile(file, convertUri);
|
|
}
|
|
|
|
public void ExecAsync(File file, bool deleteAfter, string password = null)
|
|
{
|
|
if (!MustConvert(file))
|
|
{
|
|
throw new ArgumentException(FilesCommonResource.ErrorMassage_NotSupportedFormat);
|
|
}
|
|
if (!string.IsNullOrEmpty(file.ConvertedType) || FileUtility.InternalExtension.Values.Contains(FileUtility.GetFileExtension(file.Title)))
|
|
{
|
|
return;
|
|
}
|
|
|
|
FileMarker.RemoveMarkAsNew(file);
|
|
|
|
lock (locker)
|
|
{
|
|
if (conversionQueue.ContainsKey(file))
|
|
{
|
|
return;
|
|
}
|
|
|
|
var queueResult = new ConvertFileOperationResult
|
|
{
|
|
Source = string.Format("{{\"id\":\"{0}\", \"version\":\"{1}\"}}", file.ID, file.Version),
|
|
OperationType = FileOperationType.Convert,
|
|
Error = string.Empty,
|
|
Progress = 0,
|
|
Result = string.Empty,
|
|
Processed = "",
|
|
Id = string.Empty,
|
|
TenantId = TenantManager.GetCurrentTenant().TenantId,
|
|
Account = AuthContext.CurrentAccount,
|
|
Delete = deleteAfter,
|
|
StartDateTime = DateTime.Now,
|
|
Url = HttpContextAccesor?.HttpContext != null ? HttpContextAccesor.HttpContext.Request.GetUrlRewriter().ToString() : null,
|
|
Password = password
|
|
};
|
|
conversionQueue.Add(file, queueResult);
|
|
cache.Insert(GetKey(file), queueResult, TimeSpan.FromMinutes(10));
|
|
|
|
if (timer == null)
|
|
{
|
|
timer = new Timer(CheckConvertFilesStatus, null, 0, Timeout.Infinite);
|
|
}
|
|
else
|
|
{
|
|
timer.Change(0, Timeout.Infinite);
|
|
}
|
|
}
|
|
}
|
|
|
|
public bool IsConverting(File file)
|
|
{
|
|
if (!MustConvert(file) || !string.IsNullOrEmpty(file.ConvertedType))
|
|
{
|
|
return false;
|
|
}
|
|
var result = cache.Get<ConvertFileOperationResult>(GetKey(file));
|
|
return result != null && result.Progress != 100 && string.IsNullOrEmpty(result.Error);
|
|
}
|
|
|
|
public IEnumerable<FileOperationResult> GetStatus(IEnumerable<KeyValuePair<File, bool>> filesPair)
|
|
{
|
|
var fileSecurity = FileSecurity;
|
|
var result = new List<FileOperationResult>();
|
|
foreach (var pair in filesPair)
|
|
{
|
|
var file = pair.Key;
|
|
var key = GetKey(file);
|
|
var operation = cache.Get<ConvertFileOperationResult>(key);
|
|
if (operation != null && (pair.Value || fileSecurity.CanRead(file)))
|
|
{
|
|
result.Add(operation);
|
|
lock (locker)
|
|
{
|
|
if (operation.Progress == 100)
|
|
{
|
|
conversionQueue.Remove(file);
|
|
cache.Remove(key);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private string FileJsonSerializer(File file, string folderTitle)
|
|
{
|
|
if (file == null) return string.Empty;
|
|
|
|
EntryManager.SetFileStatus(file);
|
|
return
|
|
string.Format("{{ \"id\": \"{0}\"," +
|
|
" \"title\": \"{1}\"," +
|
|
" \"version\": \"{2}\"," +
|
|
" \"folderId\": \"{3}\"," +
|
|
" \"folderTitle\": \"{4}\"," +
|
|
" \"fileXml\": \"{5}\" }}",
|
|
file.ID,
|
|
file.Title,
|
|
file.Version,
|
|
file.FolderID,
|
|
folderTitle ?? "",
|
|
File.Serialize(file).Replace('"', '\''));
|
|
}
|
|
|
|
private void CheckConvertFilesStatus(object _)
|
|
{
|
|
if (Monitor.TryEnter(singleThread))
|
|
{
|
|
using var scope = ServiceProvider.CreateScope();
|
|
var logger = scope.ServiceProvider.GetService<IOptionsMonitor<ILog>>().CurrentValue;
|
|
var tenantManager = scope.ServiceProvider.GetService<TenantManager>();
|
|
var userManager = scope.ServiceProvider.GetService<UserManager>();
|
|
var securityContext = scope.ServiceProvider.GetService<SecurityContext>();
|
|
var daoFactory = scope.ServiceProvider.GetService<IDaoFactory>();
|
|
|
|
try
|
|
{
|
|
List<File> filesIsConverting;
|
|
lock (locker)
|
|
{
|
|
timer.Change(Timeout.Infinite, Timeout.Infinite);
|
|
|
|
conversionQueue.Where(x => !string.IsNullOrEmpty(x.Value.Processed)
|
|
&& (x.Value.Progress == 100 && DateTime.UtcNow - x.Value.StopDateTime > TimeSpan.FromMinutes(1) ||
|
|
DateTime.UtcNow - x.Value.StopDateTime > TimeSpan.FromMinutes(10)))
|
|
.ToList()
|
|
.ForEach(x =>
|
|
{
|
|
conversionQueue.Remove(x);
|
|
cache.Remove(GetKey(x.Key));
|
|
});
|
|
|
|
logger.DebugFormat("Run CheckConvertFilesStatus: count {0}", conversionQueue.Count);
|
|
|
|
if (conversionQueue.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
filesIsConverting = conversionQueue
|
|
.Where(x => string.IsNullOrEmpty(x.Value.Processed))
|
|
.Select(x => x.Key)
|
|
.ToList();
|
|
}
|
|
|
|
var fileSecurity = FileSecurity;
|
|
foreach (var file in filesIsConverting)
|
|
{
|
|
var fileUri = file.ID.ToString();
|
|
string convertedFileUrl;
|
|
int operationResultProgress;
|
|
|
|
try
|
|
{
|
|
int tenantId;
|
|
IAccount account;
|
|
string password;
|
|
|
|
lock (locker)
|
|
{
|
|
if (!conversionQueue.Keys.Contains(file)) continue;
|
|
|
|
var operationResult = conversionQueue[file];
|
|
if (!string.IsNullOrEmpty(operationResult.Processed)) continue;
|
|
|
|
operationResult.Processed = "1";
|
|
tenantId = operationResult.TenantId;
|
|
account = operationResult.Account;
|
|
password = operationResult.Password;
|
|
|
|
//if (HttpContext.Current == null && !WorkContext.IsMono)
|
|
//{
|
|
// HttpContext.Current = new HttpContext(
|
|
// new HttpRequest("hack", operationResult.Url, string.Empty),
|
|
// new HttpResponse(new StringWriter()));
|
|
//}
|
|
|
|
cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
|
}
|
|
|
|
tenantManager.SetCurrentTenant(tenantId);
|
|
securityContext.AuthenticateMe(account);
|
|
|
|
var user = userManager.GetUsers(account.ID);
|
|
var culture = string.IsNullOrEmpty(user.CultureName) ? TenantManager.GetCurrentTenant().GetCulture() : CultureInfo.GetCultureInfo(user.CultureName);
|
|
Thread.CurrentThread.CurrentCulture = culture;
|
|
Thread.CurrentThread.CurrentUICulture = culture;
|
|
|
|
if (!fileSecurity.CanRead(file) && file.RootFolderType != FolderType.BUNCH)
|
|
{
|
|
//No rights in CRM after upload before attach
|
|
throw new SecurityException(FilesCommonResource.ErrorMassage_SecurityException_ReadFile);
|
|
}
|
|
if (file.ContentLength > SetupInfo.AvailableFileSize)
|
|
{
|
|
throw new Exception(string.Format(FilesCommonResource.ErrorMassage_FileSizeConvert, FileSizeComment.FilesSizeToString(SetupInfo.AvailableFileSize)));
|
|
}
|
|
|
|
fileUri = PathProvider.GetFileStreamUrl(file);
|
|
|
|
var toExtension = FileUtility.GetInternalExtension(file.Title);
|
|
var fileExtension = file.ConvertedExtension;
|
|
var docKey = DocumentServiceHelper.GetDocKey(file);
|
|
|
|
fileUri = DocumentServiceConnector.ReplaceCommunityAdress(fileUri);
|
|
operationResultProgress = DocumentServiceConnector.GetConvertedUri(fileUri, fileExtension, toExtension, docKey, password, true, out convertedFileUrl);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
var password = exception.InnerException != null
|
|
&& (exception.InnerException is DocumentService.DocumentServiceException documentServiceException)
|
|
&& documentServiceException.Code == DocumentService.DocumentServiceException.ErrorCode.ConvertPassword;
|
|
|
|
logger.Error(string.Format("Error convert {0} with url {1}", file.ID, fileUri), exception);
|
|
lock (locker)
|
|
{
|
|
if (conversionQueue.Keys.Contains(file))
|
|
{
|
|
var operationResult = conversionQueue[file];
|
|
if (operationResult.Delete)
|
|
{
|
|
conversionQueue.Remove(file);
|
|
cache.Remove(GetKey(file));
|
|
}
|
|
else
|
|
{
|
|
operationResult.Progress = 100;
|
|
operationResult.StopDateTime = DateTime.UtcNow;
|
|
operationResult.Error = exception.Message;
|
|
if (password) operationResult.Result = "password";
|
|
cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
|
}
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
|
|
operationResultProgress = Math.Min(operationResultProgress, 100);
|
|
if (operationResultProgress < 100)
|
|
{
|
|
lock (locker)
|
|
{
|
|
if (conversionQueue.Keys.Contains(file))
|
|
{
|
|
var operationResult = conversionQueue[file];
|
|
|
|
if (DateTime.Now - operationResult.StartDateTime > TimeSpan.FromMinutes(10))
|
|
{
|
|
operationResult.StopDateTime = DateTime.UtcNow;
|
|
operationResult.Error = FilesCommonResource.ErrorMassage_ConvertTimeout;
|
|
logger.ErrorFormat("CheckConvertFilesStatus timeout: {0} ({1})", file.ID, file.ContentLengthString);
|
|
}
|
|
else
|
|
{
|
|
operationResult.Processed = "";
|
|
}
|
|
operationResult.Progress = operationResultProgress;
|
|
cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
|
}
|
|
}
|
|
|
|
logger.Debug("CheckConvertFilesStatus iteration continue");
|
|
continue;
|
|
}
|
|
|
|
File newFile = null;
|
|
var operationResultError = string.Empty;
|
|
|
|
try
|
|
{
|
|
newFile = SaveConvertedFile(file, convertedFileUrl);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
operationResultError = e.Message;
|
|
|
|
logger.ErrorFormat("{0} ConvertUrl: {1} fromUrl: {2}: {3}", operationResultError, convertedFileUrl, fileUri, e);
|
|
continue;
|
|
}
|
|
finally
|
|
{
|
|
lock (locker)
|
|
{
|
|
if (conversionQueue.Keys.Contains(file))
|
|
{
|
|
var operationResult = conversionQueue[file];
|
|
if (operationResult.Delete)
|
|
{
|
|
conversionQueue.Remove(file);
|
|
cache.Remove(GetKey(file));
|
|
}
|
|
else
|
|
{
|
|
if (newFile != null)
|
|
{
|
|
var folderDao = daoFactory.FolderDao;
|
|
var folder = folderDao.GetFolder(newFile.FolderID);
|
|
var folderTitle = fileSecurity.CanRead(folder) ? folder.Title : null;
|
|
operationResult.Result = FileJsonSerializer(newFile, folderTitle);
|
|
}
|
|
|
|
operationResult.Progress = 100;
|
|
operationResult.StopDateTime = DateTime.UtcNow;
|
|
operationResult.Processed = "1";
|
|
if (!string.IsNullOrEmpty(operationResultError))
|
|
{
|
|
operationResult.Error = operationResultError;
|
|
}
|
|
cache.Insert(GetKey(file), operationResult, TimeSpan.FromMinutes(10));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
logger.Debug("CheckConvertFilesStatus iteration end");
|
|
}
|
|
|
|
lock (locker)
|
|
{
|
|
timer.Change(TIMER_PERIOD, TIMER_PERIOD);
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
logger.Error(exception.Message, exception);
|
|
lock (locker)
|
|
{
|
|
timer.Change(Timeout.Infinite, Timeout.Infinite);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
Monitor.Exit(singleThread);
|
|
}
|
|
}
|
|
}
|
|
|
|
private File SaveConvertedFile(File file, string convertedFileUrl)
|
|
{
|
|
var fileSecurity = FileSecurity;
|
|
var fileDao = DaoFactory.FileDao;
|
|
var folderDao = DaoFactory.FolderDao;
|
|
File newFile = null;
|
|
var newFileTitle = FileUtility.ReplaceFileExtension(file.Title, FileUtility.GetInternalExtension(file.Title));
|
|
|
|
if (!FilesSettingsHelper.StoreOriginalFiles && fileSecurity.CanEdit(file))
|
|
{
|
|
newFile = (File)file.Clone();
|
|
newFile.Version++;
|
|
}
|
|
else
|
|
{
|
|
var folderId = GlobalFolderHelper.FolderMy;
|
|
|
|
var parent = folderDao.GetFolder(file.FolderID);
|
|
if (parent != null
|
|
&& fileSecurity.CanCreate(parent))
|
|
{
|
|
folderId = parent.ID;
|
|
}
|
|
|
|
if (Equals(folderId, 0)) throw new SecurityException(FilesCommonResource.ErrorMassage_FolderNotFound);
|
|
|
|
if (FilesSettingsHelper.UpdateIfExist && (parent != null && folderId != parent.ID || !file.ProviderEntry))
|
|
{
|
|
newFile = fileDao.GetFile(folderId, newFileTitle);
|
|
if (newFile != null && fileSecurity.CanEdit(newFile) && !EntryManager.FileLockedForMe(newFile.ID) && !FileTracker.IsEditing(newFile.ID))
|
|
{
|
|
newFile.Version++;
|
|
}
|
|
else
|
|
{
|
|
newFile = null;
|
|
}
|
|
}
|
|
|
|
if (newFile == null)
|
|
{
|
|
newFile = new File { FolderID = folderId };
|
|
}
|
|
}
|
|
|
|
newFile.Title = newFileTitle;
|
|
newFile.ConvertedType = null;
|
|
newFile.Comment = string.Format(FilesCommonResource.CommentConvert, file.Title);
|
|
|
|
var req = (HttpWebRequest)WebRequest.Create(convertedFileUrl);
|
|
|
|
if (WorkContext.IsMono && ServicePointManager.ServerCertificateValidationCallback == null)
|
|
{
|
|
ServicePointManager.ServerCertificateValidationCallback += (s, c, n, p) => true; //HACK: http://ubuntuforums.org/showthread.php?t=1841740
|
|
}
|
|
|
|
try
|
|
{
|
|
using (var convertedFileStream = new ResponseStream(req.GetResponse()))
|
|
{
|
|
newFile.ContentLength = convertedFileStream.Length;
|
|
newFile = fileDao.SaveFile(newFile, convertedFileStream);
|
|
}
|
|
}
|
|
catch (WebException e)
|
|
{
|
|
using var response = e.Response;
|
|
var httpResponse = (HttpWebResponse)response;
|
|
var errorString = string.Format("WebException: {0}", httpResponse.StatusCode);
|
|
|
|
if (httpResponse.StatusCode != HttpStatusCode.NotFound)
|
|
{
|
|
using var responseStream = response.GetResponseStream();
|
|
if (responseStream != null)
|
|
{
|
|
using var readStream = new StreamReader(responseStream);
|
|
var text = readStream.ReadToEnd();
|
|
errorString += string.Format(" Error message: {0}", text);
|
|
}
|
|
}
|
|
|
|
throw new Exception(errorString);
|
|
}
|
|
|
|
FilesMessageService.Send(newFile, MessageInitiator.DocsService, MessageAction.FileConverted, newFile.Title);
|
|
FileMarker.MarkAsNew(newFile);
|
|
|
|
var tagDao = DaoFactory.TagDao;
|
|
var tags = tagDao.GetTags(file.ID, FileEntryType.File, TagType.System).ToList();
|
|
if (tags.Any())
|
|
{
|
|
tags.ForEach(r => r.EntryId = newFile.ID);
|
|
tagDao.SaveTags(tags);
|
|
}
|
|
|
|
return newFile;
|
|
}
|
|
|
|
private static string GetKey(File f)
|
|
{
|
|
return string.Format("fileConvertation-{0}", f.ID);
|
|
}
|
|
|
|
|
|
private class FileComparer : IEqualityComparer<File>
|
|
{
|
|
public bool Equals(File x, File y)
|
|
{
|
|
return x != null && y != null && Equals(x.ID, y.ID) && x.Version == y.Version;
|
|
}
|
|
|
|
public int GetHashCode(File obj)
|
|
{
|
|
return obj.ID.GetHashCode() + obj.Version.GetHashCode();
|
|
}
|
|
}
|
|
|
|
[DataContract(Name = "operation_result", Namespace = "")]
|
|
private class ConvertFileOperationResult : FileOperationResult
|
|
{
|
|
public DateTime StartDateTime { get; set; }
|
|
public DateTime StopDateTime { get; set; }
|
|
public int TenantId { get; set; }
|
|
public IAccount Account { get; set; }
|
|
public bool Delete { get; set; }
|
|
public string Url { get; set; }
|
|
public string Password { get; set; }
|
|
}
|
|
}
|
|
} |