Syncovery의 PascalScript
Syncovery에는 PascalScript 엔진이 포함되어 있어, 프로필의 동작을 여러 방식으로 사용자 지정할 수 있습니다. PascalScript는 Syncovery 8에 추가되었으며, 첫 출시 이후 많은 새로운 훅과 함수가 추가되었습니다.
특정 동작을 변경하려면 훅 함수를 작성하고 몇 가지 코드를 작성해야 합니다. 대부분의 경우 기술 지원팀이 코드를 작성해 드립니다. 더 크거나 복잡한 스크립트의 경우, 맞춤 스크립트 개발이 포함된 프리미엄 지원 구독을 고려해 보십시오.
스크립트는 작업 설정 카테고리 탭 시트의 “Pascal Script…” 체크 항목을 통해 프로필에 지정합니다.
PascalScript는 모든 프로필 설정에 접근할 수 있으며, GetProfileProperty 및 SetProfileProperty 유틸리티 함수를 사용하여 이를 읽고 수정할 수 있습니다.
유용한 바로 사용 가능한 스크립트
다음 스크립트는 그대로 사용할 수 있으며, PascalScript 대화상자에 스크립트를 붙여넣기만 하면 됩니다.
- 긴 경로 줄이기
이 스크립트는 전체 경로 길이가 250자를 초과하면 파일 이름을 줄입니다. 축약된 이름이 고유하도록 원래 파일 이름을 기반으로 CRC32 해시를 추가합니다. 폴더 이름은 수정되지 않습니다. 축약된 이름은 왼쪽에서 오른쪽으로 복사할 때만 사용됩니다. 왼쪽은 그대로 유지됩니다. - 긴 파일 이름 줄이기
이 스크립트는 114자를 초과하는 파일 이름을 줄이고, 축약된 이름이 고유하도록 원래 파일 이름을 기반으로 CRC32 해시를 추가합니다. 이전 스크립트와 마찬가지로 폴더 이름은 수정되지 않으며, 축약된 이름은 오른쪽에만 영향을 줍니다. - Windows에서 허용되지 않는 문자 변환
이 스크립트를 사용하면 허용되지 않는 문자 /:\?|<>왼쪽의 파일 이름에 “*를 사용합니다. 오른쪽은 로컬 NTFS 드라이브와 같은 Windows 호환 스토리지여야 합니다. - 간단한 이메일 알림
이 스크립트는 이메일 알림을 단순화하며, 쉽게 편집하여 이메일을 사용자 지정할 수 있습니다. - 프로필 결과에 따라 이메일 알림 보내기
이 스크립트는 왼쪽에서 오른쪽으로 복사된 파일 수가 10개 미만이거나 100개를 초과하는 경우에만 이메일 알림을 보내도록 합니다. - FTP 연결을 특정 LAN 포트에 바인딩
이 스크립트를 사용하면 FTP 연결에 사용할 LAN 포트를 지정할 수 있습니다. 이 기능은 FTP 라이브러리 3에서만(Windows에서) 또는 다른 플랫폼에서는 2에서만 작동합니다. - 원본(왼쪽)에서 30일이 지난 파일 삭제
이 스크립트는 단방향 동기화의 원본 쪽에서 오래된 파일을 Syncovery가 삭제하도록 합니다. 원본 쪽은 왼쪽이어야 합니다. 오른쪽은 모든 과거 파일이 보관되는 아카이브 역할을 하며, 왼쪽에는 최근 30일 동안의 파일만 남습니다. 새 파일은 왼쪽에만 나타나는 것으로 가정합니다. 이 프로필은 “Standard Copying” 작업 모드에서만 사용해야 합니다. 일수는 스크립트에서 조정할 수 있습니다. 또한 새로 복사된 파일(30일보다 오래되었을 가능성은 낮음) 및/또는 작업 실행 시 양쪽에 이미 존재하는 파일(더 가능성이 높은 경우)을 삭제할지 선택할 수 있습니다.
사용 가능한 PascalScript 훅
현재 다음 훅을 사용할 수 있습니다. 고객 요청을 충족하기 위해 필요에 따라 추가 훅이 제공될 예정입니다.
- OnActionComplete
- OnAfterFileCopy
- OnBeforeFileCopy
- OnBeforeFileUpload
- OnBeforeFolderCreate
- OnBeforeMainActionPhase
- OnCanRunProfile
- OnCloudConnect
- OnCloudDisconnect
- OnDownloadComplete
- OnFileCopy
- OnGetCustomHeaders
- OnGetNextRunTime
- OnGetProfilePathBeforeListing
- OnGetProfilePathBeforeCopying
- OnHttpPost
- OnIncludeItem
- OnLogFileClosed
- OnMoveFileToDeletedFolder
- OnNeedToReRun
- OnNoActionItem
- OnNormalizeFilename
- OnProfileStart
- OnProfileResults
- OnProgress
- OnReplaceFilenameLeftToRight
- OnReplaceFilenameRightToLeft
- OnScanFolder
- OnSendEmail
- OnSkipOrIgnoreItem
- OnUploadComplete
- OnVerifySSHServerFingerprint
- OnVerifyTLSCertificate
- OnVolumeShadowComplete
사용 가능한 PascalScript 함수
다음 함수를 호출할 수 있습니다.
- Pos, Copy, Length, Ord와 같은 표준 함수
- function GetProfileProperty(const fieldname:UnicodeString):UnicodeString;
- function SetProfileProperty(const fieldname:UnicodeString;const val:UnicodeString):Boolean;(이 함수들은 XML 형식 및 명령줄과 동일한 필드 이름을 사용합니다. Syncovery 명령줄 페이지 하단의 설정 사전을 참조하십시오)
- function SaveProfileSettings:Boolean;
- procedure LoadFolderPriorityTextFile(const s:UnicodeString);
- function ConcatPath(const a,b:UnicodeString; const t: Int64):UnicodeString;
- function ConcatPathWithDelim(const a,b,delim:UnicodeString):UnicodeString;
- function ExtractFileName(const s: UnicodeString):UnicodeString;
- function ExtractFileNameFTP(const s: UnicodeString):UnicodeString;
- function ExtractFilePath(const s: UnicodeString):UnicodeString;
- function ExtractFilePathFTP(const s: UnicodeString):UnicodeString;
- function ExtractURLPartAfterServer(const s: UnicodeString):UnicodeString;
- function ExtractFileExt(const s: UnicodeString):UnicodeString;
- function ChangeFileExt(const s,t: UnicodeString):UnicodeString;
- function FileExists(const FileName: UnicodeString):Boolean;
- function FileExistsMatching(const FileName: UnicodeString):Boolean;
- function EntryExists(const FileName: UnicodeString):Boolean;
- function FileAge(const FileName: UnicodeString):Double;
- function FileCopy(const ASource,ADest:UnicodeString):Int64;
- function FileDelete(const AFile:UnicodeString):Int64;
- function FileRename(const ASource,ADest:UnicodeString):Int64;
- function ProfileRunning(const s: UnicodeString):Boolean;
- procedure Log(const s:UnicodeString);
- procedure MessageBox(const s:UnicodeString);
- function Execute(const s:UnicodeString; const TimeOutSeconds: Int64):Int64;
- function GetProfileName:UnicodeString;
- procedure SetProfileResult(const AResultText:UnicodeString);
- function CreateS3Connector(const BucketName,AccessID,SecretKey:UnicodeString;const Options:Integer):Opaque;
- function UploadFile(const LocalPath,DestinationPath:UnicodeString;const Connector:Opaque):Int64;
- function CloseConnector(const Connector:Opaque):Int64;
- function ConnFileExists(const Connector:Opaque; const FileName: UnicodeString):Boolean;
- function ConnDirectoryExists(const Connector:Opaque; const Name: UnicodeString):Boolean;
- function ConnCustomFTPCommand(const Connector:Opaque; const ACommand: UnicodeString;
const AOkResponse1,AOkResponse2,AOkResponse3:Integer;
var ResponseText: UnicodeString):Integer; - function ConnProcessWebForm(const Connector:Opaque;
const URL, AFormName, AField1, AValue1, AField2, AValue2: AnsiString;
const SaveResultPage: Boolean;
const SavePageFileName: UnicodeString): Boolean; - function ConnRenameFile(const Connector:Opaque; const AFromFileName,AToFileName: UnicodeString):Boolean;
- function ConnDeleteFile(const Connector:Opaque; const AFileName: UnicodeString):Boolean;
- function ConnDeleteFiles(const Connector:Opaque; const APath,AMask: UnicodeString):Integer;
- function ConnDeleteFilesOlderThan(const Connector:Opaque; const APath,AMask: UnicodeString;const AWhen:Double):Integer;
- function SendHTTPRequest(const requestype,mimetype,additionalheaders,URL,PostData:AnsiString;var ResultCode:Int64;var Response,ErrorResponse:AnsiString):Boolean;
- function StringReplace(const Source, OldPattern, NewPattern: UnicodeString;const CaseSensitive:Boolean): UnicodeString;
- function EncodeBase64(const s: UnicodeString):UnicodeString;
- function DecodeBase64(const s: UnicodeString):UnicodeString;
- function Utf8Encode(const s: UnicodeString):AnsiString;
- function Utf8Decode(const s: AnsiString):UnicodeString;
- function DecodeAnsiURL(const anurl:AnsiString):AnsiString;
- function DecodeUnicodeURL(const anurl:UnicodeString):UnicodeString;
- function UnicodeStringMD5Hex(const s: UnicodeString):UnicodeString;
- function EightBitStringMD5Hex(const s: AnsiString):AnsiString;
- function UnicodeStringMD5Base64(const s: UnicodeString):UnicodeString;
- function EightBitStringMD5Base64(const s: AnsiString):AnsiString;
- function UnicodeStringCRC32Hex(const s: UnicodeString):UnicodeString;
- function EightBitStringCRC32Hex(const s: AnsiString):AnsiString;
- function UnicodeStringCRC32Base64(const s: UnicodeString):UnicodeString;
- function EightBitStringCRC32Base64(const s: AnsiString):AnsiString;
- function SimpleEncrypt(const s: UnicodeString):UnicodeString;
- function SimpleDecrypt(const s: UnicodeString):UnicodeString;
- function AESEncrypt(const s,passphrase: UnicodeString):UnicodeString;
- function AESDecrypt(const s,passphrase: UnicodeString):UnicodeString;
- function ChooseFile(const Prompt,Extension:UnicodeString):UnicodeString;
- function OpenIniFile(const AFileName:UnicodeString):Int64;
- procedure CloseIniFile(const AnIni:Int64);
- function ReadIniString(const AnIni:Int64;const Section,Ident,Default:UnicodeString):UnicodeString;
- function GetInput(const s: UnicodeString):UnicodeString;
- function GetPassword(const s: UnicodeString):UnicodeString;
- function ReadRegistryString(const Key,OptName:UnicodeString):UnicodeString;
- procedure WriteRegistryString(const Key,OptName,Value:UnicodeString);
- function GetProfileRunID:UnicodeString;
- procedure ClearBody;
- function GetBodyLine(const i:Integer):UnicodeString;
- procedure SetBodyLine(const i:Integer;const s:UnicodeString);
- procedure DeleteBodyLine(const i:Integer);
- procedure AddBodyText(const s:UnicodeString);
- function GetActionList:UnicodeString;
- function GetProfileSettings:UnicodeString;
- function Now:Double;
- function NowUTC:Double;
- function OffsetFromUTC:Double;
- function TimeToStr(const DateTime: Double):UnicodeString;
- function DateTimeToStr(const DateTime: Double):UnicodeString;
- function DateToStr(const DateTime: Double):UnicodeString’;
- function DateTimeToStrWithFormat(const DateTime: Double;const FormatString:UnicodeString):UnicodeString;
- function MakeSurePathExists(const s:UnicodeString;const isRightSide:Boolean):Boolean;
- function GetTempDir:UnicodeString;
- function GetTempFilename(const TryCreateIt:Boolean;const Extension:UnicodeString):UnicodeString;
- function PathDelim:UnicodeString;
- function LeftDelim:UnicodeString;
- function RightDelim:UnicodeString;
- function GetDelim(const Connector: Opaque):UnicodeString;
- function IncludeLeadingPathDelim(const s: UnicodeString):UnicodeString;
- function OpenTextFile(const s:UnicodeString):Opaque;
- function AppendTextFile(const s:UnicodeString):Opaque;
- function CreateTextFile(const s:UnicodeString):Opaque;
- procedure WriteLine(const F:Opaque;const ALine:UnicodeString);
- function ReadLine(const F:Opaque):UnicodeString;
- function EOF(const F:Opaque):Boolean;
- procedure CloseFile(const F:Opaque);
- function AtomicAppendTextFileLine(const APath,ALine:UnicodeString):Boolean;(멀티 스레드 및 멀티 프로세스 환경에서 안전하게 한 줄을 추가합니다)
- function YearOf(const dt:Double):Integer;
- function MonthOf(const dt:Double):Integer;
- function WeekOf(const dt:Double):Integer;
- function DayOf(const dt:Double):Integer;
- function DayOfTheWeek(const dt:Double):Integer;
- function SecondOf(const dt:Double):Integer;
- function HourOf(const dt:Double):Integer;
- function MinuteOf(const dt:Double):Integer;
- function EncodeDateTime(const AYear, AMonth, ADay, AHour, AMinute, ASecond, AMilliSecond: Integer): Double;
- function FileToCopyExistsLeft:Boolean;
- function FileToCopyExistsRight:Boolean;
- function FileToCopyLeftSize:Int64;
- function FileToCopyRightSize:Int64;
- function FileToCopyLeftModified:Double;
- function FileToCopyRightModified:Double;
- function CurrentFileModified:Double;
- function CurrentFileCreated:Double;
- function CurrentFileLastAccessed:Double;
- procedure CountDeletedFiles(const Left,Right:Integer);
(파일 이름의 와일드카드와 함께 사용할 수 있지만, 상위 폴더에서는 사용할 수 없습니다)
사용 가능한 전역 변수
이 전역 변수들을 사용하면 Syncovery의 내부 필드에 직접 접근할 수 있습니다. 일부는 읽기 전용으로 간주해야 하며, 다른 일부는 필요에 따라 변경하도록 되어 있습니다.
- ProfileTempDir: UnicodeString;
- LeftBasePath: UnicodeString;
- RightBasePath: UnicodeString;
- ProfileName: UnicodeString;
- ResultSummary: UnicodeString;
- LeftBindIP: UnicodeString;
- RightBindIP: UnicodeString;
- MinimumFreeSpaceLeft: Int64;
- MinimumFreeSpaceRight: Int64;
- MaxWaitWhenFreeSpaceLowSeconds: Integer;
- MinDate: Double;
- MaxDate: Double;
- FilterTimestamps: Boolean;
- FilterOnSourceSideOnly: Boolean;
- FiltersMustMatchOnBothSides:Boolean;
- NeedActionsLog: Boolean;
- UseBinaryCompToAvoidCopying: Boolean;
- RemoveEmptyFoldersOnlyOneLevelWhereAFileHasBeenRemoved: Boolean;
- IgnoreFileSizes: Boolean;
- SkipIfFileSizeChanging: Boolean;
- ActionsLogging: Boolean;
- FreeSpaceLogging: Boolean;
- CopyingStatisticsLogging: Boolean;
- FileCopyNoStatNeeded: Boolean;
- DoSmartTrackingDeletionsEvenIfOtherSideModified: Boolean;
OnActionComplete 샘플 스크립트
이 훅은 파일 또는 폴더와 관련된 모든 작업이 수행된 후 호출됩니다. 예를 들어 파일 복사, 이동, 삭제 등이 해당됩니다. 예제는 작업을 로그에 기록하기만 합니다. 함수 결과는 Syncovery에서 무시됩니다.
function OnActionComplete(const StartTimeUTC, CompletionTimeUTC: Double;
const Success: Boolean;
const ActionStr, DirectionStr, Filename,
LeftFile, RightFile, Subfolder, MovedTo,
ErrorMsg: UnicodeString;
const ResultCode: Int64;
const ErrorSide: UnicodeString;
const ASize,ACompressedSize:Int64):Boolean;
begin
Log('Action Complete: '+ActionStr+' '+DirectionStr+' '+Filename);
Result:=true;
end;
OnAfterFileCopy 샘플 스크립트
이 훅은 파일이 복사된 후 호출됩니다. 함수의 결과값은 Syncovery에서 무시됩니다. 이 훅은 샘플 스크립트 “30일보다 오래된 파일을 원본(왼쪽) 쪽에서 삭제”에서 사용됩니다.
function OnAfterFileCopy(const DirectionIsL2R:Boolean;
const Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString;
const ResultCode:Int64):Boolean;
begin
Log('File Copy Complete: '+Source+' to '+Dest);
Result:=true;
end;
OnCanRunProfile 샘플 스크립트
이 훅은 스케줄러가 프로필을 실행하려고 할 때 호출됩니다. 실제로 지금 실행할지, 아니면 나중으로 연기할지 결정할 수 있습니다. 이 예제에서는 두 개의 특정 프로필이 동시에 실행되거나 서로 겹치지 않도록 방지하는 데 이 훅을 사용합니다. 이 스크립트는 프로그램 설정 대화상자의 고급 탭에서 전역 PascalScript로 입력해야 합니다.
const p1='Profile Name 1';
p2='Profile Name 2';
function OnCanRunProfile(const ProfileName:UnicodeString; var PostponeBySeconds:Integer):Boolean;
begin
if ProfileName=p1 then
Result:=not ProfileRunning(p2)
else
if ProfileName=p2 then
Result:=not ProfileRunning(p1)
else
Result:=true;
if not Result then
PostponeBySeconds:=60;
end;
OnFileCopy 샘플 스크립트
이 훅을 사용하면 파일 복사 로직을 대체할 수 있습니다. 성공 시 0을 반환하고, Syncovery가 일반적인 방식으로 복사하도록 하려면 -1을 반환하고, 그 외의 값은 오류 코드로 간주됩니다.
function OnFileCopy(const DirectionIsL2R:Boolean;
const Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString;
const SourceConnector,DestConnector: Opaque):Int64;
begin
Result:=Execute('XCOPY.EXE "'+Source+'" "'+DestPath+'"',60);
end;
OnGetCustomHeaders 샘플 스크립트
이 훅을 사용하면 Amazon S3 요청에 사용자 지정 HTTP 헤더를 추가할 수 있습니다. 향후 Syncovery 버전에서는 고객 요청에 따라 이 기능을 다른 클라우드 저장소 및 프로토콜에도 추가할 수 있습니다(원하시면 요청해 주세요).
function OnGetCustomHeaders(const RelativePath: UnicodeString;
const URL:AnsiString;var MIMEType, Headers: AnsiString;
const Connector:Opaque):Boolean;
var strDate:string;
begin
Result:=true;
Headers:='Cache-Control: 10';
Log('');
Log('Headers Added to '+RelativePath);
Log(Headers);
Log('');
end;
OnGetNextRunTime 샘플 스크립트
이 훅을 사용하면 스케줄을 수정할 수 있습니다. 가장 좋은 사용 방법은 프로필에 규칙적이고 단순한 스케줄을 지정한 다음, 훅을 사용해 원하지 않는 실행 시간을 건너뛰도록 하는 것입니다. 이 예제는 “매일 XX:YY에 실행”으로 예약된 프로필을 위한 것입니다. 이 훅은 실제로는 한 달의 첫 번째 평일에만 실행되도록 보장합니다.
function OnGetNextRunTime(const LastRun, ProposedNextRun: Double):Double;
var DidItRunThisMonth:Boolean;
begin
Result:=ProposedNextRun;
DidItRunThisMonth:=(MonthOf(LastRun)=MonthOf(Now)) and
(MonthOf(LastRun)=MonthOf(ProposedNextRun)) and
(DayOf(LastRun)<DayOf(ProposedNextRun));
if DidItRunThisMonth then begin
// go to the next month
while DayOf(Result)>1 do
Result:=Result+1;
end
else begin
// go to the next month if we are beyond week #1
while DayOf(Result)>7 do
Result:=Result+1;
end;
// second, advance further until it's not a weekend
while DayOfTheWeek(Result)>=6 do
Result:=Result+1;
end;
OnIncludeItem 샘플 스크립트들
OnIncludeItem 훅은 동기화의 각 쪽에 대해 개별적으로 호출됩니다. isRightSide 매개변수는 현재 어느 쪽을 보고 있는지를 나타냅니다.
다음 스크립트는 파일 확장자가 없는 파일을 제외하는 데 사용됩니다. 이러한 제외는 Exclusion Masks로는 불가능합니다.
function OnIncludeItem(const FileName, RelativePath: UnicodeString;
const isRightSide, isFolder:Boolean;
const FileSize:Int64; const FileAttr:LongWord;
const Connector: Opaque):Boolean;
begin
Result:=isFolder or (Pos('.',FileName)>0);
end;
OnIncludeItem의 두 번째 예제는 READY.toprocess 파일이 포함된 하위 폴더와 오른쪽에 존재하는 모든 하위 폴더만 처리합니다.
function OnIncludeItem(const FileName, RelativePath: UnicodeString;
const isRightSide, isFolder:Boolean;
const FileSize:Int64; const FileAttr:LongWord;
const Connector: Opaque):Boolean;
begin
Result:=isRightSide or not isFolder or
ConnFileExists(Connector,ConcatPath(ConcatPath(LeftBasePath,RelativePath,Connector),FileName,Connector)+
'\READY.toprocess');
end;
OnScanFolder 샘플 스크립트
‘READY.toprocess’를 찾는 더 좋은 방법일 것입니다. OnScanFolder 훅은 폴더를 스캔하기 직전에 호출되며, 이 훅에서는 양쪽의 정보를 모두 사용할 수 있습니다.
function OnScanFolder(const FolderLevel: Integer;
const RelativePath, LeftCompletePath, RightCompletePath: UnicodeString;
const LeftExists,RightExists:Boolean;
const LeftConnector, RightConnector: Opaque):Boolean;
begin
Result:=RightExists or ConnFileExists(LeftConnector,LeftCompletePath+'\READY.toprocess');
end;
OnProfileStart 샘플 스크립트
이 함수는 시작 시 프로필 설정을 확인하거나 수정하는 데 사용할 수 있으며, PascalScript를 통해서만 해제할 수 있는 일부 기능도 포함됩니다. 이 예제는 “파일 버퍼링 우회” 체크박스가 선택되어 있는지 확인하고 이를 제거합니다.
var Checked:Boolean;
function OnProfileStart:Boolean;
begin
Result:=true;
if Checked then
Exit;
Checked:=true;
if (GetProfileProperty('BypassOSFileBufferingLeft')='Yes') or
(GetProfileProperty('BypassOSFileBufferingRight')='Yes') then begin
SetProfileProperty('BypassOSFileBufferingLeft','No');
SetProfileProperty('BypassOSFileBufferingRight','No');
SaveProfileSettings;
Log('');
Log('Bypass File Buffering has been removed via PascalScript.');
end
else begin
Log('');
Log('File buffering settings have been verified via PascalScript.');
end;
end;
OnProfileResults 샘플 스크립트
이 스크립트는 아무 작업도 하지 않지만, 프로필이 완료되면 함수가 일부 통계와 함께 호출됩니다. 실제로 유용하게 사용할 수 있는 예제는 이 페이지 상단 근처에서 다운로드할 수 있습니다(“프로필 결과에 따라 이메일 알림 보내기”). 이 함수의 반환값(“Result”)은 무시됩니다.
function OnProfileResults(const FilesCopiedL2R,FilesCopiedR2L:Integer;
const FilesToCopyL2R,FilesToCopyR2L:Integer;
const BytesCopiedL2R,BytesCopiedR2L:Int64;
const ResultString:UnicodeString;
const Error:Boolean):Boolean;
begin
Result:=true;
end;
OnNormalizeFilename 샘플 스크립트
이 훅을 사용하면 Syncovery가 작은 차이에도 파일 이름을 동일한 것으로 인식할 수 있도록 파일 이름을 “정규화”할 수 있습니다. 샘플 스크립트는 공백 문자를 정규화하여 다른 문자들 사이에는 항상 공백이 하나만 있도록 합니다. 연속된 두 개 이상의 공백은 하나의 공백으로 정규화됩니다. 그 결과 프로필 양쪽에서 연속 공백의 개수가 다른 파일도 Syncovery가 동일한 것으로 인식합니다. 이러한 파일 이름은 디스크에서 수정되지 않습니다. 수정은 비교를 위해 메모리에서만 이루어집니다. 동기화 미리보기에는 정규화된 파일 이름이 표시됩니다.
function OnNormalizeFilename(const FileName: UnicodeString;
const isFolder, isRightSide: Boolean):UnicodeString;
var Changed:UnicodeString;
begin
Result:=FileName;
repeat
Changed:=StringReplace(Result,' ',' ',true);
if Changed=Result then
break;
Result:=Changed;
until false;
end;
OnReplaceFilenameLeftToRight 샘플 스크립트
이 스크립트는 파일이 왼쪽에서 오른쪽으로 복사될 때 파일 이름을 변경합니다. 이 예제에서는 파일 이름 확장자 앞에 ‘-draft’가 추가됩니다.
function OnReplaceFilenameLeftToRight(const FileName: UnicodeString;
const isFolder: Boolean):UnicodeString;
begin
if isFolder then
Result:=FileName
else
Result:=ChangeFileExt(FileName,'-draft')+ExtractFileExt(FileName);
end;
OnReplaceFilenameRightToLeft 샘플 스크립트
양방향 동기화를 수행하고 오른쪽에 새 파일이 나타날 수 있다면, 반대 방향으로 이름을 변경하는 방법도 필요합니다. 이 샘플 스크립트는 이름에서 ‘-draft’ 삽입 부분을 제거합니다.
function OnReplaceFilenameRightToLeft(const FileName: UnicodeString;
const isFolder: Boolean):UnicodeString;
var ToFind:UnicodeString;
P:Integer;
begin
if isFolder then
Result:=FileName
else begin
ToFind:=''-draft''+ExtractFileExt(FileName);
p:=Pos(ToFind,FileName);
if p>0 then
Result:=Copy(FileName,1,p-1)+ExtractFileExt(FileName)
else
Result:=FileName
end;
end;
OnUploadComplete 샘플 스크립트
이 스크립트는 FTP를 통해 업로드된 파일의 권한을 777로 설정합니다.
function OnUploadComplete(const FileName, LocalFilePath, CompleteURL: UnicodeString;
const isRightSide:Boolean;
const FileSize:Int64;
const Connector: Opaque):Boolean;
var CmdRes:Int64;
ResponseText:UnicodeString;
begin
CmdRes:=ConnCustomFTPCommand(Connector,'SITE CHMOD 777 '+FileName,200,200,200,ResponseText);
Log('Set Permissions for '+FileName+': '+ResponseText);
Result:=true;
end;
OnDownloadComplete 샘플 스크립트
이 스크립트는 다운로드한 파일 이름 끝에 추가 “.downloaded” 확장자를 붙여 이름을 변경합니다.
function OnDownloadComplete(const FileName, CompleteURL, LocalFilePath: UnicodeString;
const isRightSide:Boolean;
const FileSize:Int64;
const Connector: Opaque):Boolean;
begin
if ConnRenameFile(Connector,CompleteURL,FileName+'.downloaded') then
Log('Renamed '+FileName+' to '+FileName+'.downloaded')
else
Log('Rename failed: '+FileName+' to '+FileName+'.downloaded');
Result:=true;
end;
OnVolumeShadowComplete 샘플 스크립트
이 스크립트는 볼륨 섀도우가 생성된 직후 외부 명령(배치 또는 CMD 파일)을 실행합니다.
function OnVolumeShadowComplete(const Volume,ShadowPath:UnicodeString):Boolean;
begin
Result:=Execute('C:\Tests\test.bat',120)=0;
end;
OnBeforeFolderCreate 샘플 스크립트
이 스크립트는 대상에 파일을 복사하기 위해 필요한 경우를 제외하고는 어떤 폴더 생성도 방지합니다. 또한 이 훅을 사용하여 대상의 폴더 경로를 조작할 수도 있습니다.
function OnBeforeFolderCreate(const DirectionIsL2R:Boolean;
var Source,Dest,Reason:UnicodeString):Boolean;
begin
Result:=false;
end;
OnBeforeFileCopy 샘플 스크립트
이 스크립트는 복사 대상 경로를 조작합니다(왼쪽에서 오른쪽으로). 소스 쪽에는 없는 추가 하위 폴더 ‘archive’를 추가합니다.
function OnBeforeFileCopy(const DirectionIsL2R:Boolean;
var Source,Dest,DestPath,LeftSubPath,RightSubPath:UnicodeString):Boolean;
var AddFolderName,NewDestPath,NewDest,NewRightSubPath:UnicodeString;
begin
Result:=true;
if not DirectionIsL2R then
Exit;
AddFolderName:='archive';
NewDestPath:=ConcatPathWithDelim(DestPath,AddFolderName,PathDelim);
NewDest:=ConcatPathWithDelim(NewDestPath,ExtractFileName(Dest),PathDelim);
NewRightSubPath:=IncludeLeadingPathDelim(ConcatPathWithDelim(RightSubPath,AddFolderName,PathDelim));
if not MakeSurePathExists(NewDestPath,true) then begin
Log('Could not create '+NewDestPath);
Exit;
end;
Log('OnBeforeFileCopy');
Log('Source:'+Source);
Log('DestPath:'+DestPath+' changed to '+NewDestPath);
Log('Dest:'+Dest+' changed to '+NewDest);
Log('LeftSubPath:'+LeftSubPath);
Log('RightSubPath:'+RightSubPath+' changed to '+NewRightSubPath);
Log('');
Dest:=NewDest;
DestPath:=NewDestPath;
RightSubPath:=NewRightSubPath;
end;
OnBeforeFileUpload 샘플 스크립트
이 스크립트는 인터넷 프로토콜을 통해 파일을 업로드하기 전에 호출되며, 업로드 동작을 수정하는 데 사용할 수 있습니다. 아래 예제 함수는 업로드 전에 바이러스 백신 스캐너를 실행합니다.
function OnBeforeFileUpload(const DirectionIsL2R:Boolean;
var Source,Dest,DestPath,LeftSubPath,RightSubPath,ErrorMsg:UnicodeString;
var ErrorCode:Int64):Boolean;
begin
if not DirectionisL2R then begin
Result:=true;
Exit;
end;
Result:=Execute('"C:\Program Files\ClamAV\clamscan.exe" '+Source,60)=0;
if Result then
Log('Virus scan OK: '+Source)
else begin
Log('Virus scan failed, not uploading: '+Source);
ErrorMsg:='Virus detected';
ErrorCode:=$E1;
end;
end;
OnHttpPost 샘플 스크립트
이 훅은 HTTP 프로토콜을 통한 파일 업로드를 활성화하는 데 사용할 수 있습니다. 스크립트는 관련 헤더와 폼 속성을 설정해야 합니다.
function OnHttpPost(const RelativePath : UnicodeString;
var URL, MIMEType, Header : AnsiString; var LAsForm : Boolean;
var LFormData : AnsiString;
const Connector : Opaque) : Boolean;
begin
URL := 'https://ko.syncovery.com';
Header := 'Authorization: Bearer abcdefghijklmnopqrstuvwxyz';
LAsForm := true;
Result := true;
LFormData := 'orderstates';
Log('');
Log('Header Added to '+RelativePath);
Log(Header);
Log('');
end;
OnGetProfilePathBeforeListing 샘플 스크립트
이 스크립트는 이 훅을 사용하여 프로필에 대한 개별 TEMP 폴더를 지정합니다. 함수의 원래 목적은 왼쪽 또는 오른쪽 경로 및/또는 자격 증명을 수정하는 것입니다.
function OnGetProfilePathBeforeListing(const isRightSide:Boolean;
var Path,UserName,Password:UnicodeString;
var AuthKey,AuthKeyPassword:AnsiString;
var Port:Integer):Boolean;
begin
ProfileTempDir:='H:\TEMP';
Result:=true;
end;
OnGetProfilePathBeforeCopying 샘플 스크립트
이 훅은 경로 및/또는 자격 증명을 수정하는 데 사용할 수 있습니다. 샘플 스크립트는 아무 작업도 하지 않습니다.
function OnGetProfilePathBeforeCopying(const isRightSide:Boolean;
var Path,UserName,Password:UnicodeString;
var AuthKey,AuthKeyPassword:AnsiString;
var Port:Integer):Boolean;
begin
Result:=true;
end;
OnBeforeMainActionPhase 샘플 스크립트
이 스크립트는 왼쪽에서 오른쪽으로 복사할 파일이 정해진 개수일 때만 작업이 실행되도록 합니다.
function OnBeforeMainActionPhase(const CopyL2RCount,CopyR2LCount,DeleteLCount,DeleteRCount,MoveLCount,MoveRCount:Int64;
const CopyL2RBytes,CopyR2LBytes,DeleteLBytes,DeleteRBytes,MoveLBytes,MoveRBytes:Int64):Boolean;
begin
if CopyL2RCount=14 then
Result:=true
else begin
Result:=false;
Log('Not continuing because CopyL2RCount is '+IntToStr(CopyL2RCount));
end;
end;
OnCloudConnect 샘플 스크립트
이 스크립트는 URL에서 파일을 다운로드할 때 HTTP 프로토콜을 사용하여 웹 사이트에 로그인하는 데 사용할 수 있습니다.
function OnCloudConnect(const URL:AnsiString;
const isRightSide,isFirstConnectionInJob:Boolean;
const Connector: Opaque):Boolean;
begin
if isFirstConnectionInJob and not isRightSide then
Result:=ConnProcessWebForm(Connector,
'https://www.superflexible.com/usrlogin.php?',
'login',
'username','tobias',
'password','abcdefghijklmn',
false,'')
else
Result:=true;
end;
OnCloudDisconnect 샘플 스크립트
이 훅은 프로필 실행이 끝날 때 클라우드 또는 FTP 서버와의 최종 연결 해제 전에 호출됩니다.
마지막 정리 작업을 수행하는 데 사용할 수 있습니다.
예제 스크립트는 아무 작업도 하지 않습니다.
function OnCloudDisconnect(const URL:AnsiString;
const isRightSide,isMainConnectionInJob,isFinalDisconnection:Boolean;
const Connector: Opaque):Boolean;
begin
Log('Before final disconnection');
Result:=true;
end;
OnLogFileClosed 샘플 스크립트
이 스크립트는 로그 파일이 닫힌 후 로그 파일을 다른 폴더로 복사합니다.
function OnLogFileClosed(const FileName:UnicodeString):Boolean;
begin
FileCopy(FileName,'E:\LogCopies\'+ExtractFileName(FileName));
Result:=true;
end;
OnMoveFileToDeletedFolder 샘플 스크립트
이 스크립트는 삭제된 파일 폴더에서 잠재적으로 이미 존재하는 파일을 먼저 삭제하여 삭제된 파일의 여러 버전을 보관하지 않도록 합니다.
function OnMoveFileToDeletedFolder(const Path:UnicodeString;
var MoveToPath:UnicodeString;
var proceedToDeleteInsteadOfMoving:Boolean;
const Connector:Opaque):Boolean;
begin
if FileExists(MoveToPath) then FileDelete(MoveToPath);
Result:=true;
end;
OnNeedToRerun 샘플 스크립트
이 스크립트는 예상 조건이 충족될 때까지(최소한 하나의 파일이 복사될 때까지) 작업을 다시 실행하게 합니다.
function OnNeedToReRun(const FilesCopiedL2R,FilesCopiedR2L:Integer;
const FilesToCopyL2R,FilesToCopyR2L:Integer;
const BytesCopiedL2R,BytesCopiedR2L:Int64;
const ResultString:UnicodeString;
const Error:Boolean):Boolean;
begin
if FilesCopiedL2R+FilesCopiedR2L>0 then
Result:=false
else
Result:=true;
end;
