Skip to content

Commit

Permalink
cloneHash/addByHash/addFileToCloud functions refactored: addFileByIde…
Browse files Browse the repository at this point in the history
…ntity function implemented instead
  • Loading branch information
Pozitronik authored and Pozitronik committed May 16, 2019
1 parent 4237590 commit 7482b7c
Showing 1 changed file with 52 additions and 61 deletions.
113 changes: 52 additions & 61 deletions CloudMailRu.pas
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ TCloudMailRu = class
function getShard(var Shard: WideString): Boolean;
function getUserSpace(var SpaceInfo: TCloudMailRuSpaceInfo): Boolean;
function putFileToCloud(FileName: WideString; FileStream: TStream; var FileIdentity: TCloudMailRuFileIdentity): integer; overload; //отправка на сервер данных из потока
function addFileToCloud(Hash: WideString; size: int64; remotePath: WideString; var JSONAnswer: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT; LogErrors: Boolean = true): Boolean; //LogErrors=false => не логируем результат операции, нужно для поиска данных в облаке по хешу

{PRIVATE UPLOAD METHODS CHAIN (CALLED FROM putFile())}
function putFileWhole(localPath, remotePath: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT): integer; //Загрузка файла целиком
function putFileSplit(localPath, remotePath: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT; ChunkOverwriteMode: integer = 0): integer; //Загрузка файла по частям
Expand All @@ -61,8 +59,6 @@ TCloudMailRu = class
function CloudResultToFsResult(CloudResult: integer; OperationStatus: integer; ErrorPrefix: WideString = ''): integer;
function cloudHash(Path: WideString): WideString; overload; //get cloud hash for specified file
function cloudHash(Stream: TStream; SourceName: WideString = ''): WideString; overload; //get cloud hash for data in stream

function addByHash(Hash: WideString; size: int64; remotePath: WideString): Boolean; //addFileToCloud function wrapper with result parsing
protected
{REGULAR CLOUD}
function loginRegular(method: integer = CLOUD_AUTH_METHOD_WEB): Boolean;
Expand Down Expand Up @@ -102,7 +98,10 @@ TCloudMailRu = class
function deleteFile(Path: WideString): Boolean;
function publishFile(Path: WideString; var PublicLink: WideString; publish: Boolean = CLOUD_PUBLISH): Boolean;
function cloneWeblink(Path, link: WideString; ConflictMode: WideString = CLOUD_CONFLICT_RENAME): integer; //клонировать публичную ссылку в текущий каталог
function cloneHash(Path, Hash: WideString; size: int64; FileName: WideString; ConflictMode: WideString = CLOUD_CONFLICT_RENAME): integer; //создать клон файла по известному хешу и размеру

function addFileByIdentity(FileIdentity: TCloudMailRuFileIdentity; remotePath: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT; LogErrors: Boolean = true; LogSuccess: Boolean = false): integer; overload;
function addFileByIdentity(FileIdentity: TCloudMailRuDirListingItem; remotePath: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT; LogErrors: Boolean = true; LogSuccess: Boolean = false): integer; overload;

function getShareInfo(Path: WideString; var InviteListing: TCloudMailRuInviteInfoListing): Boolean;
function shareFolder(Path, email: WideString; access: integer): Boolean;
function trashbinRestore(Path: WideString; RestoreRevision: integer; ConflictMode: WideString = CLOUD_CONFLICT_RENAME): Boolean;
Expand All @@ -118,62 +117,53 @@ TCloudMailRu = class
class function CloudAccessToString(access: WideString; Invert: Boolean = false): WideString; static;
class function StringToCloudAccess(accessString: WideString; Invert: Boolean = false): integer; static;
class function ErrorCodeText(ErrorCode: integer): WideString; static;
class function IsSameIdentity(IdentityOne, IdentityTwo: TCloudMailRuFileIdentity): Boolean;
end;

implementation

{TCloudMailRu}
{TODO: принимать TCloudMailRuFileIdentity}
function TCloudMailRu.addByHash(Hash: WideString; size: int64; remotePath: WideString): Boolean;
var
JSONAnswer: WideString;
OperationStatus: integer;
begin
OperationStatus := 0;
if self.addFileToCloud(Hash, size, remotePath, JSONAnswer, CLOUD_CONFLICT_STRICT, false) then
begin
if fromJSON_OperationResult(JSONAnswer, OperationStatus) = CLOUD_OPERATION_OK then
begin
Log(LogLevelDetail, MSGTYPE_DETAILS, 'File ' + remotePath + ' found by hash.');
exit(true);
end;
end;
exit(false);
end;

{TODO: принимать TCloudMailRuFileIdentity}
function TCloudMailRu.addFileToCloud(Hash: WideString; size: int64; remotePath: WideString; var JSONAnswer: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT; LogErrors: Boolean = true): Boolean;
function TCloudMailRu.addFileByIdentity(FileIdentity: TCloudMailRuFileIdentity; remotePath: WideString; ConflictMode: WideString = CLOUD_CONFLICT_STRICT; LogErrors: Boolean = true; LogSuccess: Boolean = false): integer;
var
FileName: WideString;
JSON, FileName: WideString;
OperationStatus, OperationResult: integer;
begin
{Экспериментально выяснено, что параметры api, build, email, x-email, x-page-id в запросе не обязательны}
result := FS_FILE_WRITEERROR;
if not(Assigned(self)) then
exit; //Проверка на вызов без инициализации
if self.public_account then
exit(FS_FILE_NOTSUPPORTED);

if self.crypt_filenames then
begin
FileName := ExtractUniversalFileName(remotePath);
FileName := FileCipher.CryptFileName(FileName);
remotePath := ChangePathFileName(remotePath, FileName);
end;
result := self.HTTP.PostForm(API_FILE_ADD, 'conflict=' + ConflictMode + '&home=/' + PathToUrl(remotePath) + '&hash=' + Hash + '&size=' + size.ToString + self.united_params, JSONAnswer, 'application/x-www-form-urlencoded', LogErrors);
{Экспериментально выяснено, что параметры api, build, email, x-email, x-page-id в запросе не обязательны}
if self.HTTP.PostForm(API_FILE_ADD, 'conflict=' + ConflictMode + '&home=/' + PathToUrl(remotePath) + '&hash=' + FileIdentity.Hash + '&size=' + FileIdentity.size.ToString + self.united_params, JSON, 'application/x-www-form-urlencoded', LogErrors) then
begin
OperationResult := fromJSON_OperationResult(JSON, OperationStatus);
if CLOUD_OPERATION_OK = OperationResult then
begin
if LogSuccess then
Log(LogLevelDetail, MSGTYPE_DETAILS, 'File ' + remotePath + ' found by hash.');

exit(FS_FILE_OK);
end else begin
result := CloudResultToFsResult(OperationResult, OperationStatus, 'File uploading error: ');
end;
end;
end;

{TODO: принимать TCloudMailRuFileIdentity}
{TODO: Объединить код addByHash}
function TCloudMailRu.cloneHash(Path, Hash: WideString; size: int64; FileName: WideString; ConflictMode: WideString = CLOUD_CONFLICT_RENAME): integer; //создать клон файла по известному хешу и размеру
function TCloudMailRu.addFileByIdentity(FileIdentity: TCloudMailRuDirListingItem; remotePath, ConflictMode: WideString; LogErrors, LogSuccess: Boolean): integer;
var
JSON: WideString;
OperationStatus, OperationResult: integer;
CloudFileIdentity: TCloudMailRuFileIdentity;
begin
result := FS_FILE_WRITEERROR;
if not(Assigned(self)) then
exit; //Проверка на вызов без инициализации
if self.public_account then
exit(FS_FILE_NOTSUPPORTED);
if self.addFileToCloud(Hash, size, IncludeTrailingBackslash(Path) + FileName, JSON, ConflictMode, true) then
begin
OperationResult := fromJSON_OperationResult(JSON, OperationStatus);
result := CloudResultToFsResult(OperationResult, OperationStatus, 'File uploading error: ');
end;
CloudFileIdentity.Hash := FileIdentity.Hash;
CloudFileIdentity.size := FileIdentity.size;
result := self.addFileByIdentity(CloudFileIdentity, remotePath, ConflictMode, LogErrors, LogSuccess)
end;

function TCloudMailRu.cloneWeblink(Path, link, ConflictMode: WideString): integer;
Expand Down Expand Up @@ -235,6 +225,11 @@ function TCloudMailRu.CloudResultToFsResult(CloudResult: integer; OperationStatu
end;
end;

class function TCloudMailRu.IsSameIdentity(IdentityOne, IdentityTwo: TCloudMailRuFileIdentity): Boolean;
begin
result := (IdentityOne.size = IdentityTwo.size) and (IdentityOne.Hash = IdentityTwo.Hash);
end;

function TCloudMailRu.copyFile(OldName, ToPath: WideString): integer;
var
JSON: WideString;
Expand Down Expand Up @@ -1252,10 +1247,7 @@ function TCloudMailRu.rejectInvite(invite_token: WideString): Boolean;

function TCloudMailRu.putFileStream(FileName, remotePath: WideString; FileStream: TStream; ConflictMode: WideString): integer;
var
FileIdentity: TCloudMailRuFileIdentity;
JSONAnswer: WideString;
LocalFileHash: WideString;
OperationStatus: integer;
LocalFileIdentity, RemoteFileIdentity: TCloudMailRuFileIdentity;
OperationResult: integer;
MemoryStream: TMemoryStream;
begin
Expand All @@ -1265,20 +1257,22 @@ function TCloudMailRu.putFileStream(FileName, remotePath: WideString; FileStream

if self.PrecalculateHash or self.CheckCRC then
begin
LocalFileHash := cloudHash(FileStream);
LocalFileIdentity.Hash := cloudHash(FileStream);
LocalFileIdentity.size := FileStream.size;
end;
if self.PrecalculateHash and (LocalFileHash <> EmptyWideStr) and (not self.crypt_files) and (self.addByHash(LocalFileHash, FileStream.size, remotePath)) then {issue #135}
if self.PrecalculateHash and (LocalFileIdentity.Hash <> EmptyWideStr) and (not self.crypt_files) and (FS_FILE_OK = self.addFileByIdentity(LocalFileIdentity, remotePath, CLOUD_CONFLICT_STRICT, false, true)) then {issue #135}
exit(CLOUD_OPERATION_OK);

MemoryStream := TMemoryStream.Create;

try
if self.crypt_files then {Will encrypt any type of data passed here}
begin
self.FileCipher.CryptStream(FileStream, MemoryStream);
MemoryStream.Position := 0;
OperationResult := self.putFileToCloud(FileName, MemoryStream, FileIdentity)
OperationResult := self.putFileToCloud(FileName, MemoryStream, RemoteFileIdentity)
end else begin
OperationResult := self.putFileToCloud(FileName, FileStream, FileIdentity)
OperationResult := self.putFileToCloud(FileName, FileStream, RemoteFileIdentity)
end;
Except
on E: Exception do
Expand All @@ -1296,7 +1290,7 @@ function TCloudMailRu.putFileStream(FileName, remotePath: WideString; FileStream
begin
if self.CheckCRC then
begin
if (FileStream.size <> FileIdentity.size) or (LocalFileHash <> FileIdentity.Hash) then {При включённой проверке CRC сравниваем хеши и размеры}
if not IsSameIdentity(LocalFileIdentity, RemoteFileIdentity) then {При включённой проверке CRC сравниваем хеши и размеры}
result := CLOUD_OPERATION_FAILED;

end;
Expand All @@ -1306,13 +1300,8 @@ function TCloudMailRu.putFileStream(FileName, remotePath: WideString; FileStream
end;

if OperationResult = CLOUD_OPERATION_OK then
begin
if self.addFileToCloud(FileIdentity.Hash, FileIdentity.size, remotePath, JSONAnswer, ConflictMode) then
begin
OperationResult := fromJSON_OperationResult(JSONAnswer, OperationStatus);
result := CloudResultToFsResult(OperationResult, OperationStatus, 'File uploading error: ');
end;
end;
result := self.addFileByIdentity(RemoteFileIdentity, remotePath, ConflictMode);

MemoryStream.Destroy;
end;

Expand All @@ -1331,18 +1320,20 @@ function TCloudMailRu.putFileWhole(localPath, remotePath, ConflictMode: WideStri

function TCloudMailRu.putFileSplit(localPath, remotePath, ConflictMode: WideString; ChunkOverwriteMode: integer): integer;
var
LocalFileIdentity: TCloudMailRuFileIdentity;
SplitFileInfo: TFileSplitInfo;
SplittedPartIndex: integer;
ChunkRemotePath, LocalFileHash, CRCRemotePath: WideString;
ChunkRemotePath, CRCRemotePath: WideString;
ChunkStream: TChunkedFileStream;
CRCStream: TMemoryStream;
begin

if self.PrecalculateHash then //try to add whole file by hash at first.
begin
LocalFileHash := cloudHash(localPath);
LocalFileIdentity.Hash := cloudHash(localPath);
LocalFileIdentity.size := SizeOfFile(localPath);
end;
if self.PrecalculateHash and (LocalFileHash <> EmptyWideStr) and (not self.crypt_files) and (self.addByHash(LocalFileHash, SizeOfFile(localPath), remotePath)) then {issue #135}
if self.PrecalculateHash and (LocalFileIdentity.Hash <> EmptyWideStr) and (not self.crypt_files) and (FS_FILE_OK = self.addFileByIdentity(LocalFileIdentity, remotePath, CLOUD_CONFLICT_STRICT, false, true)) then {issue #135}
exit(CLOUD_OPERATION_OK);

SplitFileInfo := TFileSplitInfo.Create(localPath, self.split_file_size); //quickly get information about file parts
Expand Down

0 comments on commit 7482b7c

Please sign in to comment.