PascalScript no Syncovery

O Syncovery inclui um motor PascalScript, permitindo-lhe personalizar o comportamento do seu perfil de muitas formas. O PascalScript foi adicionado no Syncovery 8, e desde a primeira versão foram adicionados muitos novos hooks e funções.

Para alterar um comportamento específico, tem de escrever uma função hook e algum código. Na maioria dos casos, o nosso suporte técnico escreverá o código por si. Para scripts maiores ou mais complexos, considere uma Assinatura de Suporte Premium que inclui desenvolvimento de scripts personalizados.

O script é especificado no perfil através da opção “Pascal Script…” no separador da categoria Definições da Tarefa.

Os PascalScripts têm acesso a todas as definições do perfil e podem lê-las e alterá-las utilizando as funções utilitárias GetProfileProperty e SetProfileProperty.

Scripts úteis prontos a utilizar

Os scripts seguintes podem ser utilizados tal como estão; basta colá-los na janela de diálogo do PascalScript.

  • Reduzir caminhos longos
    Este script reduz os nomes dos ficheiros se o caminho total ultrapassar 250 caracteres. Adiciona um hash CRC32 com base no nome original do ficheiro para garantir que os nomes reduzidos são únicos. Os nomes das pastas não são modificados. Os nomes reduzidos são utilizados apenas ao copiar do lado esquerdo para o lado direito. O lado esquerdo permanece inalterado.
  • Reduzir nomes de ficheiros longos
    Este script reduz nomes de ficheiros com mais de 114 caracteres, adicionando um hash CRC32 com base no nome original do ficheiro para garantir que os nomes reduzidos são únicos. Tal como no script anterior, os nomes das pastas não são modificados, e os nomes reduzidos afetam apenas o lado direito.
  • Converter caracteres não permitidos no Windows
    Este script permite-lhe ter os caracteres não permitidos /:\?|<>“* nos nomes de ficheiros do lado esquerdo. O lado direito pode ser armazenamento compatível com Windows, como uma unidade NTFS local.
  • Notificações simples por e-mail
    Este script simplifica as notificações por e-mail e pode ser facilmente editado para personalizar os seus e-mails.
  • Enviar notificações por e-mail consoante os resultados do perfil
    Este script faz com que as notificações por e-mail sejam enviadas apenas se tiverem sido copiados menos de 10 ou mais de 100 ficheiros do lado esquerdo para o lado direito.
  • Associar uma ligação FTP a uma porta LAN específica
    Este script permite-lhe especificar que porta LAN deve ser usada para uma ligação FTP. Note que isto funciona apenas com a biblioteca FTP 3 (no Windows) ou 2 (noutras plataformas).
  • Eliminar ficheiros com mais de 30 dias do lado de origem (esquerdo)
    Este script fará com que o Syncovery elimine ficheiros mais antigos do lado de origem de uma sincronização unidirecional. O lado de origem tem de ser o lado esquerdo. O lado direito servirá como arquivo, onde todos os ficheiros históricos são mantidos, enquanto o lado esquerdo contém apenas os ficheiros dos últimos 30 dias. Assume-se que os novos ficheiros aparecem apenas no lado esquerdo. O perfil deve ser utilizado apenas com o modo de operação “Standard Copying”. O número de dias pode ser ajustado no script. Também pode escolher se pretende eliminar ficheiros copiados recentemente (pouco provável, porque provavelmente não têm mais de 30 dias) e/ou ficheiros que já existam em ambos os lados quando a tarefa é executada (o caso mais provável).

Gatilhos PascalScript disponíveis

Os seguintes gatilhos estão atualmente disponíveis. Serão adicionados gatilhos adicionais conforme necessário para satisfazer os pedidos dos clientes.

  • 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

Funções PascalScript disponíveis

As seguintes funções estão disponíveis para chamada.

  • funções padrão como Pos, Copy, Length, Ord
     
  • function GetProfileProperty(const fieldname:UnicodeString):UnicodeString;
  • function SetProfileProperty(const fieldname:UnicodeString;const val:UnicodeString):Boolean;(estas funções usam os mesmos nomes de campos que o formato XML e a linha de comandos. Consulte o dicionário de definições no fim da página da Linha de Comandos do 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;
  • (pode ser utilizado com caracteres universais no nome do ficheiro, mas não nas pastas principais)

  • 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;(acrescenta uma linha de forma segura para múltiplas threads e múltiplos processos)
     
  • 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);

Variáveis globais disponíveis

Estas variáveis globais permitem acesso direto aos campos internos do Syncovery. Algumas devem ser consideradas só de leitura, enquanto outras destinam-se a ser alteradas conforme necessário.

  • 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;

Script de exemplo OnActionComplete

Este gatilho é chamado após qualquer ação relacionada com ficheiros ou pastas, como copiar, mover ou eliminar um ficheiro, entre outras. O exemplo apenas regista a ação. O resultado da função é ignorado pelo 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;

Script de exemplo OnAfterFileCopy

Este gancho é chamado depois de um ficheiro ter sido copiado. O resultado da função é ignorado pelo Syncovery. É usado pelo script de exemplo “Delete files older than 30 days from the source (left) side”.

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;

Script de Exemplo OnCanRunProfile

Este gancho é chamado quando o agendador está prestes a executar um perfil. Pode decidir se deve realmente ser executado agora ou se deve ser adiado. O exemplo usa o gancho para impedir que dois perfis específicos sejam executados ao mesmo tempo, ou se sobreponham. Este script deve ser introduzido como um PascalScript global através da janela de diálogo Definições do Programa, no separador Avançadas.

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;

Script de Exemplo OnFileCopy

Este gancho permite-lhe substituir a lógica de cópia de ficheiros. Devolva 0 em caso de sucesso, -1 se o Syncovery deve efetuar a cópia normalmente, ou qualquer outro valor como código de erro.

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;

Script de Exemplo OnGetCustomHeaders

Este gancho permite-lhe adicionar cabeçalhos HTTP personalizados a pedidos do Amazon S3. Em versões futuras do Syncovery, esta funcionalidade poderá ser adicionada a outros armazenamentos na nuvem e protocolos (a pedido do cliente – basta solicitar).

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;

Script de Exemplo OnGetNextRunTime

Este gancho permite-lhe modificar o agendamento. A melhor forma de o utilizar é atribuir ao perfil um agendamento simples e regular, e usar o gancho para saltar horários de execução indesejados. Este exemplo destina-se a um perfil agendado para ser executado “todos os dias às XX:YY”. O gancho garante que, na prática, só é executado no primeiro dia útil de um mês.

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;

Scripts de Exemplo OnIncludeItem

O hook OnIncludeItem é chamado individualmente para cada lado da sincronização. O parâmetro isRightSide indica que lado estamos a ver neste momento.

O script seguinte serve para excluir ficheiros sem extensão de nome de ficheiro. Tal exclusão não é possível através das Máscaras de Exclusão.

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;

O segundo exemplo de OnIncludeItem só processará as subpastas que contenham o ficheiro READY.toprocess, bem como quaisquer subpastas que existam do lado direito.

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;

Script de Exemplo OnScanFolder

Esta é provavelmente uma melhor forma de procurar por ‘READY.toprocess’. O gancho OnScanFolder é chamado imediatamente antes de a pasta ser analisada, e o conhecimento de ambos os lados pode ser usado no gancho.

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;

Script de Exemplo OnProfileStart

Esta função pode ser usada para verificar ou modificar as definições do perfil ao iniciar, incluindo algumas funcionalidades que só podem ser desbloqueadas via PascalScript. O exemplo verifica se alguma das opções “Bypass File Buffering” está selecionada e remove-as.

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;

Script de Exemplo OnProfileResults

Este script não faz nada, mas a função é chamada com algumas estatísticas quando um perfil termina. Um exemplo com utilidade real pode ser descarregado perto do topo desta página (“Send E-Mail Notifications Depending on Profile Results”). O valor de retorno desta função (“Result”) é ignorado.

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;

Script de Exemplo OnNormalizeFilename

Este gancho permite-lhe “normalizar” nomes de ficheiros para que o Syncovery possa considerar nomes de ficheiros como idênticos apesar de pequenas diferenças. O script de exemplo normaliza caracteres de espaço, de modo a que exista sempre apenas um carácter de espaço entre outros caracteres. Dois ou mais espaços consecutivos são normalizados para apenas um. O resultado é que o Syncovery considera ficheiros idênticos aqueles que têm números diferentes de espaços consecutivos em cada lado do perfil. Estes nomes de ficheiro não são modificados no disco. A modificação é apenas em memória, para fins de comparação. A Pré-visualização da Sincronização mostrará os nomes de ficheiro normalizados.

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;

Script de Exemplo OnReplaceFilenameLeftToRight

Este script irá mudar o nome dos ficheiros quando o ficheiro é copiado da esquerda para a direita. No nosso exemplo, “-draft” é adicionado antes da extensão do ficheiro.

function OnReplaceFilenameLeftToRight(const FileName: UnicodeString;
        const isFolder: Boolean):UnicodeString;
begin
  if isFolder then
    Result:=FileName
  else
    Result:=ChangeFileExt(FileName,'-draft')+ExtractFileExt(FileName);
  end;

Script de Exemplo OnReplaceFilenameRightToLeft

Se fizer uma sincronização bidirecional, e novos ficheiros puderem aparecer do lado direito, também precisamos de uma forma de mudar o nome no outro sentido. Este script de exemplo remove o acréscimo “-draft” dos nomes.

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;

Script de Exemplo OnUploadComplete

Este script irá definir permissões 777 para os ficheiros carregados via FTP.

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;

Script de Exemplo OnDownloadComplete

Este script irá mudar o nome dos ficheiros descarregados, adicionando uma extensão adicional “.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;

Script de Exemplo OnVolumeShadowComplete

Este script irá executar um comando externo (ficheiro batch ou CMD) logo após ter sido criada uma shadow copy de volume.

function OnVolumeShadowComplete(const Volume,ShadowPath:UnicodeString):Boolean;
begin
  Result:=Execute('C:\Tests\test.bat',120)=0;
  end;

Script de Exemplo OnBeforeFolderCreate

Este script impedirá a criação de quaisquer pastas, exceto quando tal for necessário para copiar ficheiros para o destino. Também pode usar este gancho para manipular caminhos de pastas no destino.

function OnBeforeFolderCreate(const DirectionIsL2R:Boolean;
        var Source,Dest,Reason:UnicodeString):Boolean;
begin
  Result:=false;
  end;

Script de Exemplo OnBeforeFileCopy

Este script irá manipular os caminhos de destino para a cópia (da esquerda para a direita), adicionando uma subpasta adicional ‘archive’ que não existe no lado de origem.

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;

Script de exemplo OnBeforeFileUpload

Este script é chamado antes de um envio de ficheiro através do protocolo Internet e pode ser usado para modificar o comportamento do envio. A função de exemplo abaixo irá invocar um verificador antivírus antes do envio.

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;

Script de exemplo OnHttpPost

Este hook pode ser usado para ativar o envio de ficheiros via protocolo HTTP. O script precisa de definir os cabeçalhos relevantes e as propriedades do formulário.

function OnHttpPost(const RelativePath : UnicodeString;
        var URL, MIMEType, Header : AnsiString; var LAsForm : Boolean;
        var LFormData : AnsiString;
        const Connector : Opaque) : Boolean;
begin
  URL := 'https://pt.syncovery.com';
  Header := 'Authorization: Bearer abcdefghijklmnopqrstuvwxyz';
  LAsForm := true;
  Result := true;
  LFormData := 'orderstates';
  Log('');
  Log('Header Added to '+RelativePath);
  Log(Header);
  Log('');
  end;

Script de exemplo OnGetProfilePathBeforeListing

Este script usa este hook para especificar uma pasta TEMP individual para o perfil. O objetivo original da função é modificar o caminho esquerdo ou direito e/ou as credenciais.

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;

Script de exemplo OnGetProfilePathBeforeCopying

Este hook pode ser usado para modificar o caminho e/ou as credenciais. O script de exemplo não faz nada.

function OnGetProfilePathBeforeCopying(const isRightSide:Boolean;
        var Path,UserName,Password:UnicodeString;
        var AuthKey,AuthKeyPassword:AnsiString;
        var Port:Integer):Boolean;
begin
  Result:=true;
  end;

Script de exemplo OnBeforeMainActionPhase

Este script só permite que o trabalho seja executado se tiver de ser copiado um número fixo de ficheiros da esquerda para a direita.

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;

Script de exemplo OnCloudConnect

Este script pode ser usado para iniciar sessão num site ao utilizar o protocolo HTTP para descarregar ficheiros a partir de um URL.

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;

Script de exemplo OnCloudDisconnect

Este hook é chamado antes da desconexão final de um servidor na cloud ou FTP no final de uma execução do perfil.
Pode ser utilizado para realizar algumas tarefas finais.
O script de exemplo não faz nada.

function OnCloudDisconnect(const URL:AnsiString;
                const isRightSide,isMainConnectionInJob,isFinalDisconnection:Boolean;
                const Connector: Opaque):Boolean;
begin
  Log('Before final disconnection');
  Result:=true;
  end;

Script de exemplo OnLogFileClosed

Este script copia o ficheiro de registo para outra pasta depois de o ficheiro de registo ter sido fechado.

function OnLogFileClosed(const FileName:UnicodeString):Boolean;
begin
  FileCopy(FileName,'E:\LogCopies\'+ExtractFileName(FileName));
  Result:=true;
  end;

Script de exemplo OnMoveFileToDeletedFolder

Este script impede a manutenção de várias versões de ficheiros eliminados, eliminando primeiro o ficheiro potencialmente existente da pasta de ficheiros eliminados.

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;

Script de exemplo OnNeedToRerun

Este script faz com que o trabalho seja executado novamente até que a condição esperada tenha sido cumprida (pelo menos um ficheiro foi copiado).

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;