SyncoveryのPascalScript

Syncovery には PascalScript エンジンが組み込まれており、プロファイルの動作をさまざまな方法でカスタマイズできます。PascalScript は Syncovery 8 で追加され、それ以来、数多くの新しいフックと関数が追加されました。

特定の動作を変更するには、フック関数を記述してコードを追加する必要があります。ほとんどの場合、弊社の技術サポートがコードを作成します。より大規模または複雑なスクリプトについては、カスタムスクリプト開発を含む プレミアムサポートサブスクリプション をご検討ください。

スクリプトは、[ジョブ設定]カテゴリのタブシートにある「Pascal Script…」チェックボックスを通じてプロファイル内で指定します。

PascalScript からはすべてのプロファイル設定にアクセスでき、GetProfileProperty および SetProfileProperty ユーティリティ関数を使って読み取りや変更ができます。

すぐに使える便利なスクリプト

以下のスクリプトはそのまま使用できます。PascalScriptダイアログにスクリプトを貼り付けてください。

  • 長いパス名を短縮
    このスクリプトは、合計パス長が 250 文字を超える場合にファイル名を短縮します。短縮後の名前が一意になるように、元のファイル名に基づく CRC32 ハッシュを追加します。フォルダー名は変更されません。短縮後の名前は、左側から右側へコピーする場合にのみ使用されます。左側は変更されません。
  • 長いファイル名を短縮
    このスクリプトは、114 文字を超えるファイル名を短縮し、短縮後の名前が一意になるように、元のファイル名に基づく CRC32 ハッシュを追加します。前のスクリプトと同様に、フォルダー名は変更されず、短縮後の名前は右側にのみ影響します。
  • Windows で使用できない文字を変換
    このスクリプトを使うと、使用できない文字 /:\?|<>左側のファイル名にある”*。右側には、ローカルNTFSドライブなどのWindows互換ストレージを指定できます。
  • 簡単なメール通知
    このスクリプトはメール通知を簡略化し、メールを簡単に編集してカスタマイズできるようにします。
  • プロファイル結果に応じて E-Mail 通知を送信
    このスクリプトでは、左から右へコピーされたファイル数が10未満または100を超える場合にのみ、E-Mail 通知が送信されます。
  • FTP 接続を特定の LAN ポートにバインド
    このスクリプトを使用すると、FTP 接続で使用する LAN ポートを指定できます。なお、これは FTP ライブラリ 3 のみで有効です(Windows では)または 2(その他のプラットフォーム)です。
  • ソース(左側)から 30 日より古いファイルを削除
    このスクリプトにより、Syncovery は一方向同期のソース側から古いファイルを削除します。ソース側は左側である必要があります。右側はアーカイブとして機能し、すべての履歴ファイルが保持されます。一方、左側には直近 30 日分のファイルのみが残ります。新しいファイルは左側にのみ現れるものと想定されます。このプロファイルは「標準コピー」操作モードでのみ使用してください。日数はスクリプト内で調整できます。また、新しくコピーされたファイル(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 サンプル スクリプト

このフックは、スケジューラがプロファイルを実行しようとするときに呼び出されます。実際に今すぐ実行するか、延期するかを判断できます。この例では、2 つの特定のプロファイルが同時に実行されたり、重なって実行されたりしないように、このフックを使用しています。このスクリプトは、[プログラム設定]ダイアログの[詳細設定]タブで、グローバル 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 パラメータは、現在どちら側を見ているかを示します。

次のスクリプトは、拡張子のないファイルを除外するためのものです。このような除外は除外マスクではできません。

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 の 2 つ目の例では、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 が同一のファイル名として認識できるようにできます。サンプル スクリプトではスペース文字を正規化し、他の文字の間には常に 1 つのスペース文字だけが入るようにします。連続する 2 つ以上のスペースは、1 つのスペースに正規化されます。その結果、プロファイルの左右で連続スペースの数が異なるファイルでも、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://ja.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 プロトコルを使用して Web サイトにログインするために使用できます。

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 サンプルスクリプト

このスクリプトは、期待される条件が満たされるまで(少なくとも 1 つのファイルがコピーされるまで)、ジョブを再実行させます。

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;