| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118 | //---------------------------------------------------------------------------#include <vcl.h>#pragma hdrstop#include "Common.h"#include "Exceptions.h"#include "CopyParam.h"#include "HierarchicalStorage.h"#include "TextsCore.h"#include "Interface.h"//---------------------------------------------------------------------------const wchar_t * TransferModeNames[] = { L"binary", L"ascii", L"automatic" };const int TransferModeNamesCount = LENOF(TransferModeNames);//---------------------------------------------------------------------------__fastcall TCopyParamType::TCopyParamType(){  Default();}//---------------------------------------------------------------------------__fastcall TCopyParamType::TCopyParamType(const TCopyParamType & Source){  Assign(&Source);}//---------------------------------------------------------------------------__fastcall TCopyParamType::~TCopyParamType(){}//---------------------------------------------------------------------------void __fastcall TCopyParamType::Default(){  // when changing defaults, make sure GetInfoStr() can handle it  FileNameCase = ncNoChange;  PreserveReadOnly = false;  PreserveTime = true;  PreserveTimeDirs = false;  Rights.Number = TRights::rfDefault;  PreserveRights = false; // Was True until #106  IgnorePermErrors = false;  AsciiFileMask.Masks = L"*.*html; *.htm; *.txt; *.php; *.php3; *.cgi; *.c; *.cpp; *.h; *.pas; "    "*.bas; *.tex; *.pl; *.js; .htaccess; *.xtml; *.css; *.cfg; *.ini; *.sh; *.xml";  TransferMode = tmBinary;  AddXToDirectories = true;  ResumeSupport = rsSmart;  ResumeThreshold = 100 * 1024; // (100 KB)  InvalidCharsReplacement = TokenReplacement;  LocalInvalidChars = ::LocalInvalidChars;  CalculateSize = true;  FileMask = AnyMask;  IncludeFileMask.Masks = L"";  TransferSkipList = NULL;  TransferResumeFile = L"";  ClearArchive = false;  RemoveCtrlZ = false;  RemoveBOM = false;  CPSLimit = 0;  NewerOnly = false;  EncryptNewFiles = true;  ExcludeHiddenFiles = false;  ExcludeEmptyDirectories = false;  Size = -1;  PartOffset = -1;  PartSize = -1;  OnceDoneOperation = odoIdle;  OnTransferOut = NULL;  OnTransferIn = NULL;}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::GetInfoStr(  UnicodeString Separator, int Attrs) const{  UnicodeString Result;  bool SomeAttrIncluded;  UnicodeString ScriptArgs;  UnicodeString AssemblyCode;  DoGetInfoStr(    Separator, Attrs, Result, SomeAttrIncluded,    UnicodeString(), ScriptArgs, TAssemblyLanguage(0), AssemblyCode);  return Result;}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::AnyUsableCopyParam(int Attrs) const{  UnicodeString Result;  bool SomeAttrIncluded;  UnicodeString ScriptArgs;  UnicodeString AssemblyCode;  DoGetInfoStr(    L";", Attrs, Result, SomeAttrIncluded,    UnicodeString(), ScriptArgs, TAssemblyLanguage(0), AssemblyCode);  return SomeAttrIncluded;}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::GenerateTransferCommandArgs(int Attrs, const UnicodeString & Link) const{  UnicodeString Result;  bool SomeAttrIncluded;  UnicodeString ScriptArgs;  UnicodeString AssemblyCode;  DoGetInfoStr(    L";", Attrs, Result, SomeAttrIncluded,    Link, ScriptArgs, TAssemblyLanguage(0), AssemblyCode);  return ScriptArgs;}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::GenerateAssemblyCode(TAssemblyLanguage Language, int Attrs) const{  UnicodeString Result;  bool SomeAttrIncluded;  UnicodeString ScriptArgs;  UnicodeString AssemblyCode;  DoGetInfoStr(L";", Attrs, Result, SomeAttrIncluded, UnicodeString(), ScriptArgs, Language, AssemblyCode);  return AssemblyCode;}//---------------------------------------------------------------------------void __fastcall TCopyParamType::DoGetInfoStr(  UnicodeString Separator, int Options,  UnicodeString & Result, bool & SomeAttrIncluded,  const UnicodeString & Link, UnicodeString & ScriptArgs, TAssemblyLanguage Language, UnicodeString & AssemblyCode) const{  TCopyParamType Defaults;  TCopyParamType ScriptNonDefaults;  TCopyParamType CodeNonDefaults;  bool SomeAttrExcluded = false;  SomeAttrIncluded = false;  #define ADD(STR, EXCEPT) \    FLAGCLEAR(Options, EXCEPT) ? (AddToList(Result, (STR), Separator), SomeAttrIncluded = true, true) : (SomeAttrExcluded = true, false)  bool AsciiFileMaskDiffers = (TransferMode == tmAutomatic) && !(AsciiFileMask == Defaults.AsciiFileMask);  bool TransferModeDiffers = ((TransferMode != Defaults.TransferMode) || AsciiFileMaskDiffers);  if (FLAGCLEAR(Options, cpaIncludeMaskOnly | cpaNoTransferMode))  {    // Adding Transfer type unconditionally    bool FormatMask;    int Ident;    switch (TransferMode)    {      case tmBinary:        FormatMask = false;        Ident = 2;        break;      case tmAscii:        FormatMask = false;        Ident = 3;        break;      case tmAutomatic:      default:        FormatMask = !(AsciiFileMask == Defaults.AsciiFileMask);        Ident = FormatMask ? 4 : 5;        break;    }    UnicodeString S = FORMAT(LoadStrPart(COPY_INFO_TRANSFER_TYPE2, 1),      (LoadStrPart(COPY_INFO_TRANSFER_TYPE2, Ident)));    if (FormatMask)    {      S = FORMAT(S, (AsciiFileMask.Masks));    }    AddToList(Result, S, Separator);    if (TransferModeDiffers)    {      ADD("", cpaIncludeMaskOnly | cpaNoTransferMode);      ScriptArgs += RtfSwitchValue(TRANSFER_SWITCH, Link, TransferModeNames[TransferMode]);      const wchar_t * TransferModeMembers[] = { L"Binary", L"Ascii", L"Automatic" };      AssemblyCode += AssemblyProperty(        Language, TransferOptionsClassName, L"TransferMode", L"TransferMode", TransferModeMembers[TransferMode], false);      if (AsciiFileMaskDiffers)      {        ScriptNonDefaults.AsciiFileMask = AsciiFileMask;        CodeNonDefaults.AsciiFileMask = AsciiFileMask;      }    }  }  else  {    if (TransferModeDiffers)    {      SomeAttrExcluded = true;    }  }  if (FileNameCase != Defaults.FileNameCase)  {    if (ADD(FORMAT(LoadStrPart(COPY_INFO_FILENAME, 1),         (LoadStrPart(COPY_INFO_FILENAME, FileNameCase + 2))),         cpaIncludeMaskOnly))    {      ScriptNonDefaults.FileNameCase = FileNameCase;      CodeNonDefaults.FileNameCase = FileNameCase;    }  }  if (InvalidCharsReplacement != Defaults.InvalidCharsReplacement)  {    int Except = cpaIncludeMaskOnly;    if (InvalidCharsReplacement == NoReplacement)    {      ADD(LoadStr(COPY_INFO_DONT_REPLACE_INV_CHARS), Except);    }    if (FLAGCLEAR(Options, Except))    {      ScriptNonDefaults.InvalidCharsReplacement = InvalidCharsReplacement;      CodeNonDefaults.InvalidCharsReplacement = InvalidCharsReplacement;    }  }  if ((PreserveRights != Defaults.PreserveRights) ||      (PreserveRights &&       ((Rights != Defaults.Rights) || (AddXToDirectories != Defaults.AddXToDirectories))))  {    const int Except = cpaIncludeMaskOnly | cpaNoRights;    if (DebugAlwaysTrue(PreserveRights))    {      UnicodeString RightsStr = Rights.Text;      if (AddXToDirectories)      {        RightsStr += L", " + LoadStr(COPY_INFO_ADD_X_TO_DIRS);      }      ADD(FORMAT(LoadStr(COPY_INFO_PERMISSIONS), (RightsStr)),        Except);      if (FLAGCLEAR(Options, Except))      {        ScriptArgs += RtfSwitchValue(PERMISSIONS_SWITCH, Link, Rights.Octal);        const UnicodeString FilePermissionsClassName = L"FilePermissions";        const bool Inline = true;        UnicodeString FilePermissions =          AssemblyNewClassInstanceStart(Language, FilePermissionsClassName, Inline) +          AssemblyProperty(Language, FilePermissionsClassName, L"Octal", Rights.Octal, Inline) +          AssemblyNewClassInstanceEnd(Language, Inline);        AssemblyCode += AssemblyPropertyRaw(Language, TransferOptionsClassName, L"FilePermissions", FilePermissions, false);      }    }    if ((AddXToDirectories != Defaults.AddXToDirectories) && FLAGCLEAR(Options, Except))    {      ScriptNonDefaults.AddXToDirectories = AddXToDirectories;      CodeNonDefaults.AddXToDirectories = AddXToDirectories;    }  }  bool APreserveTimeDirs = PreserveTime && PreserveTimeDirs;  if ((PreserveTime != Defaults.PreserveTime) || (APreserveTimeDirs != Defaults.PreserveTimeDirs))  {    bool AddPreserveTime = false;    UnicodeString Str = LoadStr(PreserveTime ? COPY_INFO_TIMESTAMP : COPY_INFO_DONT_PRESERVE_TIME);    const int ExceptDirs = cpaNoPreserveTimeDirs;    if (APreserveTimeDirs != Defaults.PreserveTimeDirs)    {      if (DebugAlwaysTrue(PreserveTimeDirs))      {        if (FLAGCLEAR(Options, ExceptDirs))        {          Str = FMTLOAD(COPY_INFO_PRESERVE_TIME_DIRS, (Str));          AddPreserveTime = true;        }      }      ADD("", ExceptDirs);    }    const int Except = cpaIncludeMaskOnly | cpaNoPreserveTime;    if (PreserveTime != Defaults.PreserveTime)    {      if (FLAGCLEAR(Options, Except))      {        AddPreserveTime = true;      }      ADD(L"", Except);    }    if (AddPreserveTime)    {      AddToList(Result, Str, Separator);    }    if (FLAGCLEAR(Options, Except))    {      if (PreserveTime)      {        if (PreserveTimeDirs && FLAGCLEAR(Options, ExceptDirs))        {          ScriptArgs += RtfSwitchValue(PRESERVETIME_SWITCH, Link, PRESERVETIMEDIRS_SWITCH_VALUE);          CodeNonDefaults.PreserveTimeDirs = PreserveTimeDirs;        }        else        {          ScriptArgs += RtfSwitch(PRESERVETIME_SWITCH, Link);        }      }      else      {        ScriptArgs += RtfSwitch(NOPRESERVETIME_SWITCH, Link);        AssemblyCode += AssemblyProperty(Language, TransferOptionsClassName, L"PreserveTimestamp", false, false);      }    }  }  if ((PreserveRights || PreserveTime) &&      (IgnorePermErrors != Defaults.IgnorePermErrors))  {    if (DebugAlwaysTrue(IgnorePermErrors))    {      if (ADD(LoadStr(COPY_INFO_IGNORE_PERM_ERRORS), cpaIncludeMaskOnly | cpaNoIgnorePermErrors))      {        ScriptNonDefaults.IgnorePermErrors = IgnorePermErrors;        CodeNonDefaults.IgnorePermErrors = IgnorePermErrors;      }    }  }  if (PreserveReadOnly != Defaults.PreserveReadOnly)  {    if (DebugAlwaysTrue(PreserveReadOnly))    {      if (ADD(LoadStr(COPY_INFO_PRESERVE_READONLY), cpaIncludeMaskOnly | cpaNoPreserveReadOnly))      {        ScriptNonDefaults.PreserveReadOnly = PreserveReadOnly;        CodeNonDefaults.PreserveReadOnly = PreserveReadOnly;      }    }  }  if (CalculateSize != Defaults.CalculateSize)  {    if (DebugAlwaysTrue(!CalculateSize))    {      ADD(LoadStr(COPY_INFO_DONT_CALCULATE_SIZE), cpaIncludeMaskOnly | cpaNoCalculateSize);      // Always false in scripting, in assembly controlled by use of FileTransferProgress    }  }  if (ClearArchive != Defaults.ClearArchive)  {    if (DebugAlwaysTrue(ClearArchive))    {      if (ADD(LoadStr(COPY_INFO_CLEAR_ARCHIVE), cpaIncludeMaskOnly | cpaNoClearArchive))      {        ScriptNonDefaults.ClearArchive = ClearArchive;        CodeNonDefaults.ClearArchive = ClearArchive;      }    }  }  if ((TransferMode == tmAscii) || (TransferMode == tmAutomatic))  {    if (RemoveBOM != Defaults.RemoveBOM)    {      if (DebugAlwaysTrue(RemoveBOM))      {        if (ADD(LoadStr(COPY_INFO_REMOVE_BOM), cpaIncludeMaskOnly | cpaNoRemoveBOM | cpaNoTransferMode))        {          ScriptNonDefaults.RemoveBOM = RemoveBOM;          CodeNonDefaults.RemoveBOM = RemoveBOM;        }      }    }    if (RemoveCtrlZ != Defaults.RemoveCtrlZ)    {      if (DebugAlwaysTrue(RemoveCtrlZ))      {        if (ADD(LoadStr(COPY_INFO_REMOVE_CTRLZ), cpaIncludeMaskOnly | cpaNoRemoveCtrlZ | cpaNoTransferMode))        {          ScriptNonDefaults.RemoveCtrlZ = RemoveCtrlZ;          CodeNonDefaults.RemoveCtrlZ = RemoveCtrlZ;        }      }    }  }  if (!(IncludeFileMask == Defaults.IncludeFileMask))  {    if (ADD(FORMAT(LoadStr(COPY_INFO_FILE_MASK), (IncludeFileMask.Masks)), cpaNoIncludeMask))    {      ScriptArgs += RtfSwitch(FILEMASK_SWITCH, Link, IncludeFileMask.Masks);      AssemblyCode += AssemblyProperty(Language, TransferOptionsClassName, L"FileMask", IncludeFileMask.Masks, false);    }  }  DebugAssert(FTransferSkipList.get() == NULL);  DebugAssert(FTransferResumeFile.IsEmpty());  if (CPSLimit > 0)  {    int LimitKB = int(CPSLimit / 1024);    if (ADD(FMTLOAD(COPY_INFO_CPS_LIMIT2, (LimitKB)), cpaIncludeMaskOnly))    {      ScriptArgs += RtfSwitch(SPEED_SWITCH, Link, LimitKB);      AssemblyCode += AssemblyProperty(Language, TransferOptionsClassName, L"SpeedLimit", LimitKB, false);    }  }  if (NewerOnly != Defaults.NewerOnly)  {    if (DebugAlwaysTrue(NewerOnly))    {      if (ADD(StripHotkey(LoadStr(COPY_PARAM_NEWER_ONLY)), cpaIncludeMaskOnly | cpaNoNewerOnly))      {        ScriptArgs += RtfSwitch(NEWERONLY_SWICH, Link);        CodeNonDefaults.NewerOnly = NewerOnly;      }    }  }  if (EncryptNewFiles != Defaults.EncryptNewFiles)  {    if (!DebugAlwaysFalse(EncryptNewFiles))    {      if (ADD(StripHotkey(LoadStr(COPY_INFO_DONT_ENCRYPT_NEW_FILES)), cpaIncludeMaskOnly | cpaNoEncryptNewFiles))      {        ScriptNonDefaults.EncryptNewFiles = EncryptNewFiles;        CodeNonDefaults.EncryptNewFiles = EncryptNewFiles;      }    }  }  if (ExcludeHiddenFiles != Defaults.ExcludeHiddenFiles)  {    if (DebugAlwaysTrue(ExcludeHiddenFiles))    {      if (ADD(StripHotkey(LoadStr(COPY_INFO_EXCLUDE_HIDDEN_FILES)), cpaNoIncludeMask))      {        ScriptNonDefaults.ExcludeHiddenFiles = ExcludeHiddenFiles;        CodeNonDefaults.ExcludeHiddenFiles = ExcludeHiddenFiles;      }    }  }  if (ExcludeEmptyDirectories != Defaults.ExcludeEmptyDirectories)  {    if (DebugAlwaysTrue(ExcludeEmptyDirectories))    {      if (ADD(StripHotkey(LoadStr(COPY_INFO_EXCLUDE_EMPTY_DIRS)), 0))      {        ScriptNonDefaults.ExcludeEmptyDirectories = ExcludeEmptyDirectories;        CodeNonDefaults.ExcludeEmptyDirectories = ExcludeEmptyDirectories;      }    }  }  bool ResumeThresholdDiffers = ((ResumeSupport == rsSmart) && (ResumeThreshold != Defaults.ResumeThreshold));  if (((ResumeSupport != Defaults.ResumeSupport) || ResumeThresholdDiffers) &&      (TransferMode != tmAscii) && FLAGCLEAR(Options, cpaNoResumeSupport))  {    UnicodeString Value;    UnicodeString CodeState;    int ResumeThresholdKB = static_cast<int>(ResumeThreshold / 1024);    switch (ResumeSupport)    {      case rsOff:        Value = ToggleNames[ToggleOff];        CodeState = L"Off";        break;      case rsOn:        Value = ToggleNames[ToggleOn];        CodeState = L"On";        break;      case rsSmart:        Value = IntToStr(ResumeThresholdKB);        break;    }    ScriptArgs += RtfSwitchValue(RESUMESUPPORT_SWITCH, Link, Value);    const UnicodeString ResumeSupportClassName = L"TransferResumeSupport";    const bool Inline = true;    UnicodeString ResumeSupportCode =      AssemblyNewClassInstanceStart(Language, ResumeSupportClassName, Inline);    if (ResumeSupport == rsSmart)    {      ResumeSupportCode += AssemblyProperty(Language, ResumeSupportClassName, L"Threshold", ResumeThresholdKB, Inline);    }    else    {      ResumeSupportCode += AssemblyProperty(Language, ResumeSupportClassName, L"State", L"TransferResumeSupportState", CodeState, Inline);    }    ResumeSupportCode += AssemblyNewClassInstanceEnd(Language, Inline);    AssemblyCode += AssemblyPropertyRaw(Language, TransferOptionsClassName, L"ResumeSupport", ResumeSupportCode, false);  }  std::unique_ptr<TStringList> RawOptions;  std::unique_ptr<TOptionsStorage> OptionsStorage;  RawOptions.reset(new TStringList());  OptionsStorage.reset(new TOptionsStorage(RawOptions.get(), true));  ScriptNonDefaults.Save(OptionsStorage.get(), &Defaults);  if (RawOptions->Count > 0)  {    ScriptArgs +=      RtfSwitch(RAWTRANSFERSETTINGS_SWITCH, Link) +      FORMAT(L"[%d]", (RawOptions->Count)) +      StringsToParams(RawOptions.get());  }  RawOptions.reset(new TStringList());  OptionsStorage.reset(new TOptionsStorage(RawOptions.get(), true));  CodeNonDefaults.Save(OptionsStorage.get(), &Defaults);  if (!AssemblyCode.IsEmpty())  {    AssemblyCode =      AssemblyNewClassInstanceStart(Language, TransferOptionsClassName, false) +      AssemblyCode +      AssemblyNewClassInstanceEnd(Language, false);  }  if (RawOptions->Count > 0)  {    if (AssemblyCode.IsEmpty())    {      AssemblyCode = AssemblyVariableDeclaration(Language) + AssemblyNewClassInstance(Language, TransferOptionsClassName, false);      if (Language == alCSharp)      {        AssemblyCode += RtfText(L"()");      }      AssemblyCode += AssemblyStatementSeparator(Language) + RtfPara;    }    else    {      AssemblyCode += RtfPara;    }    AssemblyCode +=      AssemblyAddRawSettings(Language, RawOptions.get(), TransferOptionsClassName, L"AddRawSettings");  }  if (SomeAttrExcluded)  {    Result += (Result.IsEmpty() ? UnicodeString() : Separator) +      FORMAT(LoadStrPart(COPY_INFO_NOT_USABLE, 1),        (LoadStrPart(COPY_INFO_NOT_USABLE, (SomeAttrIncluded ? 2 : 3))));  }  else if (Result.IsEmpty())  {    Result = LoadStr(COPY_INFO_DEFAULT);  }  #undef ADD}//---------------------------------------------------------------------------void __fastcall TCopyParamType::Assign(const TCopyParamType * Source){  DebugAssert(Source != NULL);  #define COPY(Prop) Prop = Source->Prop  COPY(FileNameCase);  COPY(PreserveReadOnly);  COPY(PreserveTime);  COPY(PreserveTimeDirs);  COPY(Rights);  COPY(AsciiFileMask);  COPY(TransferMode);  COPY(AddXToDirectories);  COPY(PreserveRights);  COPY(IgnorePermErrors);  COPY(ResumeSupport);  COPY(ResumeThreshold);  COPY(InvalidCharsReplacement);  COPY(LocalInvalidChars);  COPY(CalculateSize);  COPY(FileMask);  COPY(IncludeFileMask);  COPY(TransferSkipList);  COPY(TransferResumeFile);  COPY(ClearArchive);  COPY(RemoveCtrlZ);  COPY(RemoveBOM);  COPY(CPSLimit);  COPY(NewerOnly);  COPY(EncryptNewFiles);  COPY(ExcludeHiddenFiles);  COPY(ExcludeEmptyDirectories);  COPY(Size);  COPY(PartOffset);  COPY(PartSize);  COPY(OnceDoneOperation);  COPY(OnTransferOut);  COPY(OnTransferIn);  #undef COPY}//---------------------------------------------------------------------------TCopyParamType & __fastcall TCopyParamType::operator =(const TCopyParamType & rhp){  Assign(&rhp);  return *this;}//---------------------------------------------------------------------------void __fastcall TCopyParamType::SetLocalInvalidChars(UnicodeString value){  if (value != LocalInvalidChars)  {    FLocalInvalidChars = value;    FTokenizibleChars = FLocalInvalidChars + TokenPrefix;  }}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::GetReplaceInvalidChars() const{  return (InvalidCharsReplacement != NoReplacement);}//---------------------------------------------------------------------------void __fastcall TCopyParamType::SetReplaceInvalidChars(bool value){  if (ReplaceInvalidChars != value)  {    InvalidCharsReplacement = (value ? TokenReplacement : NoReplacement);  }}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::ValidLocalFileName(UnicodeString FileName) const{  return ::ValidLocalFileName(FileName, InvalidCharsReplacement, FTokenizibleChars, LocalInvalidChars);}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::RestoreChars(UnicodeString FileName) const{  if (InvalidCharsReplacement == TokenReplacement)  {    wchar_t * InvalidChar = FileName.c_str();    while ((InvalidChar = wcschr(InvalidChar, TokenPrefix)) != NULL)    {      int Index = InvalidChar - FileName.c_str() + 1;      if (FileName.Length() >= Index + 2)      {        UnicodeString Hex = FileName.SubString(Index + 1, 2);        wchar_t Char = static_cast<wchar_t>(HexToByte(Hex));        if ((Char != L'\0') &&            ((FTokenizibleChars.Pos(Char) > 0) ||             (((Char == L' ') || (Char == L'.')) && (Index == FileName.Length() - 2))))        {          FileName[Index] = Char;          FileName.Delete(Index + 1, 2);          InvalidChar = FileName.c_str() + Index;        }        else if ((Hex == L"00") &&                 ((Index == FileName.Length() - 2) || (FileName[Index + 3] == L'.')) &&                 IsReservedName(FileName.SubString(1, Index - 1) + FileName.SubString(Index + 3, FileName.Length() - Index - 3 + 1)))        {          FileName.Delete(Index, 3);          InvalidChar = FileName.c_str() + Index - 1;        }        else        {          InvalidChar++;        }      }      else      {        InvalidChar++;      }    }  }  return FileName;}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::ValidLocalPath(UnicodeString Path) const{  UnicodeString Result;  while (!Path.IsEmpty())  {    if (!Result.IsEmpty())    {      Result += L"\\";    }    Result += ValidLocalFileName(CutToChar(Path, L'\\', false));  }  return Result;}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::ChangeFileName(UnicodeString FileName,  TOperationSide Side, bool FirstLevel) const{  if (FirstLevel)  {    FileName = MaskFileName(FileName, FileMask);  }  switch (FileNameCase) {    case ncUpperCase: FileName = FileName.UpperCase(); break;    case ncLowerCase: FileName = FileName.LowerCase(); break;    case ncFirstUpperCase: FileName = FileName.SubString(1, 1).UpperCase() +      FileName.SubString(2, FileName.Length()-1).LowerCase(); break;    case ncLowerCaseShort:      if ((FileName.Length() <= 12) && (FileName.Pos(L".") <= 9) &&          (FileName == FileName.UpperCase()))      {        FileName = FileName.LowerCase();      }      break;    case ncNoChange:    default:      /*nothing*/      break;  }  if (Side == osRemote)  {    FileName = ValidLocalFileName(FileName);  }  else  {    FileName = RestoreChars(FileName);  }  return FileName;}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::UseAsciiTransfer(UnicodeString FileName,  TOperationSide Side, const TFileMasks::TParams & Params) const{  switch (TransferMode)  {    case tmBinary: return false;    case tmAscii: return true;    case tmAutomatic: return AsciiFileMask.Matches(FileName, (Side == osLocal),      false, &Params);    default: DebugFail(); return false;  }}//---------------------------------------------------------------------------TRights __fastcall TCopyParamType::RemoteFileRights(Integer Attrs) const{  TRights R = Rights;  if ((Attrs & faDirectory) && AddXToDirectories)    R.AddExecute();  return R;}//---------------------------------------------------------------------------UnicodeString __fastcall TCopyParamType::GetLogStr() const{  wchar_t CaseC[] = L"NULFS";  wchar_t ModeC[] = L"BAM";  wchar_t ResumeC[] = L"YSN";  // OpenArray (ARRAYOFCONST) supports only up to 19 arguments, so we had to split it  return    FORMAT(      L"  PrTime: %s%s; PrRO: %s; Rght: %s; PrR: %s (%s); FnCs: %s; RIC: %s; "         "Resume: %s (%d); CalcS: %s; Mask: %s\n",      (BooleanToEngStr(PreserveTime),       UnicodeString(PreserveTime && PreserveTimeDirs ? L"+Dirs" : L""),       BooleanToEngStr(PreserveReadOnly),       Rights.Text,       BooleanToEngStr(PreserveRights),       BooleanToEngStr(IgnorePermErrors),       CaseC[FileNameCase],       CharToHex(InvalidCharsReplacement),       ResumeC[ResumeSupport],       (int)ResumeThreshold,       BooleanToEngStr(CalculateSize),       FileMask)) +    FORMAT(      L"  TM: %s; ClAr: %s; RemEOF: %s; RemBOM: %s; CPS: %u; NewerOnly: %s; EncryptNewFiles: %s; ExcludeHiddenFiles: %s; ExcludeEmptyDirectories: %s; InclM: %s; ResumeL: %d\n"       "  AscM: %s\n",      (ModeC[TransferMode],       BooleanToEngStr(ClearArchive),       BooleanToEngStr(RemoveCtrlZ),       BooleanToEngStr(RemoveBOM),       int(CPSLimit),       BooleanToEngStr(NewerOnly),       BooleanToEngStr(EncryptNewFiles),       BooleanToEngStr(ExcludeHiddenFiles),       BooleanToEngStr(ExcludeEmptyDirectories),       IncludeFileMask.Masks,       ((FTransferSkipList.get() != NULL) ? FTransferSkipList->Count : 0) + (!FTransferResumeFile.IsEmpty() ? 1 : 0),       AsciiFileMask.Masks));}//---------------------------------------------------------------------------int __fastcall TCopyParamType::LocalFileAttrs(const TRights & Rights) const{  int Result = 0;  if (PreserveReadOnly && !Rights.Right[TRights::rrUserWrite])  {    Result |= faReadOnly;  }  return Result;}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::AllowResume(__int64 Size, const UnicodeString & FileName) const{  bool Result;  if (FileName.Length() + PartialExt.Length() > 255) // it's a different limit than MAX_PATH  {    Result = false;  }  else  {    switch (ResumeSupport)    {      case rsOn: Result = true; break;      case rsOff: Result = false; break;      case rsSmart: Result = (Size >= ResumeThreshold); break;      default: DebugFail(); Result = false; break;    }  }  return Result;}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::AllowAnyTransfer() const{  return    IncludeFileMask.Masks.IsEmpty() &&    !ExcludeHiddenFiles &&    !ExcludeEmptyDirectories &&    ((FTransferSkipList.get() == NULL) || (FTransferSkipList->Count == 0)) &&    FTransferResumeFile.IsEmpty();}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::AllowTransfer(UnicodeString FileName,  TOperationSide Side, bool Directory, const TFileMasks::TParams & Params, bool Hidden) const{  bool Result = true;  if (Hidden && ExcludeHiddenFiles)  {    Result = false;  }  else if (!IncludeFileMask.Masks.IsEmpty())  {    Result = IncludeFileMask.Matches(FileName, (Side == osLocal),      Directory, &Params);  }  return Result;}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::SkipTransfer(  UnicodeString FileName, bool Directory) const{  bool Result = false;  // we deliberately do not filter directories, as path is added to resume list  // when a transfer of file or directory is started,  // so for directories we need to recurse and check every single file  if (!Directory && (FTransferSkipList.get() != NULL))  {    Result = (FTransferSkipList->IndexOf(FileName) >= 0);  }  return Result;}//---------------------------------------------------------------------------bool __fastcall TCopyParamType::ResumeTransfer(UnicodeString FileName) const{  // Returning true has the same effect as cpResume  return    (FileName == FTransferResumeFile) &&    DebugAlwaysTrue(!FTransferResumeFile.IsEmpty());}//---------------------------------------------------------------------------TStrings * __fastcall TCopyParamType::GetTransferSkipList() const{  return FTransferSkipList.get();}//---------------------------------------------------------------------------void __fastcall TCopyParamType::SetTransferSkipList(TStrings * value){  if ((value == NULL) || (value->Count == 0))  {    FTransferSkipList.reset(NULL);  }  else  {    FTransferSkipList.reset(new TStringList());    FTransferSkipList->AddStrings(value);    FTransferSkipList->Sorted = true;  }}//---------------------------------------------------------------------------void __fastcall TCopyParamType::Load(THierarchicalStorage * Storage){  AddXToDirectories = Storage->ReadBool(L"AddXToDirectories", AddXToDirectories);  AsciiFileMask.Masks = Storage->ReadString(L"Masks", AsciiFileMask.Masks);  FileNameCase = (TFileNameCase)Storage->ReadInteger(L"FileNameCase", FileNameCase);  PreserveReadOnly = Storage->ReadBool(L"PreserveReadOnly", PreserveReadOnly);  PreserveTime = Storage->ReadBool(L"PreserveTime", PreserveTime);  PreserveTimeDirs = Storage->ReadBool(L"PreserveTimeDirs", PreserveTimeDirs);  PreserveRights = Storage->ReadBool(L"PreserveRights", PreserveRights);  IgnorePermErrors = Storage->ReadBool(L"IgnorePermErrors", IgnorePermErrors);  Rights.Text = Storage->ReadString(L"Text", Rights.Text);  TransferMode = (TTransferMode)Storage->ReadInteger(L"TransferMode", TransferMode);  ResumeSupport = (TResumeSupport)Storage->ReadInteger(L"ResumeSupport", ResumeSupport);  ResumeThreshold = Storage->ReadInt64(L"ResumeThreshold", ResumeThreshold);  InvalidCharsReplacement = (wchar_t)Storage->ReadInteger(L"ReplaceInvalidChars",    (unsigned int)InvalidCharsReplacement);  LocalInvalidChars = Storage->ReadString(L"LocalInvalidChars", LocalInvalidChars);  CalculateSize = Storage->ReadBool(L"CalculateSize", CalculateSize);  if (Storage->ValueExists(L"IncludeFileMask"))  {    IncludeFileMask.Masks = Storage->ReadString(L"IncludeFileMask", IncludeFileMask.Masks);  }  else if (Storage->ValueExists(L"ExcludeFileMask"))  {    UnicodeString ExcludeFileMask = Storage->ReadString(L"ExcludeFileMask", L"");    if (!ExcludeFileMask.IsEmpty())    {      bool NegativeExclude = Storage->ReadBool(L"NegativeExclude", false);      if (NegativeExclude)      {        IncludeFileMask.Masks = ExcludeFileMask;      }      // convert at least simple cases to new format      else if (ExcludeFileMask.Pos(IncludeExcludeFileMasksDelimiter) == 0)      {        IncludeFileMask.Masks = UnicodeString(IncludeExcludeFileMasksDelimiter) + ExcludeFileMask;      }    }  }  TransferSkipList = NULL;  TransferResumeFile = L"";  ClearArchive = Storage->ReadBool(L"ClearArchive", ClearArchive);  RemoveCtrlZ = Storage->ReadBool(L"RemoveCtrlZ", RemoveCtrlZ);  RemoveBOM = Storage->ReadBool(L"RemoveBOM", RemoveBOM);  CPSLimit = Storage->ReadInteger(L"CPSLimit", CPSLimit);  NewerOnly = Storage->ReadBool(L"NewerOnly", NewerOnly);  EncryptNewFiles = Storage->ReadBool(L"EncryptNewFiles", EncryptNewFiles);  ExcludeHiddenFiles = Storage->ReadBool(L"ExcludeHiddenFiles", ExcludeHiddenFiles);  ExcludeEmptyDirectories = Storage->ReadBool(L"ExcludeEmptyDirectories", ExcludeEmptyDirectories);  Size = -1;  PartOffset = -1;  PartSize = -1;  OnceDoneOperation = odoIdle;  OnTransferOut = NULL;  OnTransferIn = NULL;}//---------------------------------------------------------------------------void __fastcall TCopyParamType::Save(THierarchicalStorage * Storage, const TCopyParamType * Defaults) const{  // Same as in TSessionData::DoSave  #define WRITE_DATA_EX(TYPE, NAME, PROPERTY, CONV) \    if ((Defaults != NULL) && (CONV(Defaults->PROPERTY) == CONV(PROPERTY))) \    { \      Storage->DeleteValue(NAME); \    } \    else \    { \      Storage->Write ## TYPE(NAME, CONV(PROPERTY)); \    }  #define WRITE_DATA_CONV(TYPE, NAME, PROPERTY) WRITE_DATA_EX(TYPE, NAME, PROPERTY, WRITE_DATA_CONV_FUNC)  #define WRITE_DATA(TYPE, PROPERTY) WRITE_DATA_EX(TYPE, TEXT(#PROPERTY), PROPERTY, )  WRITE_DATA(Bool, AddXToDirectories);  WRITE_DATA_EX(String, L"Masks", AsciiFileMask.Masks, );  WRITE_DATA(Integer, FileNameCase);  WRITE_DATA(Bool, PreserveReadOnly);  WRITE_DATA(Bool, PreserveTime);  WRITE_DATA(Bool, PreserveTimeDirs);  WRITE_DATA(Bool, PreserveRights);  WRITE_DATA(Bool, IgnorePermErrors);  WRITE_DATA_EX(String, L"Text", Rights.Text, );  WRITE_DATA(Integer, TransferMode);  WRITE_DATA(Integer, ResumeSupport);  WRITE_DATA(Int64, ResumeThreshold);  #define WRITE_DATA_CONV_FUNC(X) (unsigned int)(X)  WRITE_DATA_CONV(Integer, L"ReplaceInvalidChars", InvalidCharsReplacement);  WRITE_DATA(String, LocalInvalidChars);  WRITE_DATA(Bool, CalculateSize);  WRITE_DATA_EX(String, L"IncludeFileMask", IncludeFileMask.Masks, );  Storage->DeleteValue(L"ExcludeFileMask"); // obsolete  Storage->DeleteValue(L"NegativeExclude"); // obsolete  DebugAssert(FTransferSkipList.get() == NULL);  DebugAssert(FTransferResumeFile.IsEmpty());  WRITE_DATA(Bool, ClearArchive);  WRITE_DATA(Bool, RemoveCtrlZ);  WRITE_DATA(Bool, RemoveBOM);  WRITE_DATA(Integer, CPSLimit);  WRITE_DATA(Bool, NewerOnly);  WRITE_DATA(Bool, EncryptNewFiles);  WRITE_DATA(Bool, ExcludeHiddenFiles);  WRITE_DATA(Bool, ExcludeEmptyDirectories);  DebugAssert(Size < 0);  DebugAssert(PartOffset < 0);  DebugAssert(PartSize < 0);  DebugAssert(OnceDoneOperation == odoIdle);  DebugAssert(OnTransferOut == NULL);  DebugAssert(OnTransferIn == NULL);}//---------------------------------------------------------------------------#define C(Property) (Property == rhp.Property)bool __fastcall TCopyParamType::operator==(const TCopyParamType & rhp) const{  DebugAssert(FTransferSkipList.get() == NULL);  DebugAssert(FTransferResumeFile.IsEmpty());  DebugAssert(OnTransferOut == NULL);  DebugAssert(OnTransferIn == NULL);  DebugAssert(rhp.FTransferSkipList.get() == NULL);  DebugAssert(rhp.FTransferResumeFile.IsEmpty());  DebugAssert(rhp.OnTransferOut == NULL);  DebugAssert(rhp.OnTransferIn == NULL);  return    C(AddXToDirectories) &&    C(AsciiFileMask) &&    C(FileNameCase) &&    C(PreserveReadOnly) &&    C(PreserveTime) &&    C(PreserveTimeDirs) &&    C(PreserveRights) &&    C(IgnorePermErrors) &&    C(Rights) &&    C(TransferMode) &&    C(ResumeSupport) &&    C(ResumeThreshold) &&    C(InvalidCharsReplacement) &&    C(LocalInvalidChars) &&    C(CalculateSize) &&    C(IncludeFileMask) &&    C(ClearArchive) &&    C(RemoveCtrlZ) &&    C(RemoveBOM) &&    C(CPSLimit) &&    C(NewerOnly) &&    C(EncryptNewFiles) &&    C(ExcludeHiddenFiles) &&    C(ExcludeEmptyDirectories) &&    C(Size) &&    C(PartOffset) &&    C(PartSize) &&    C(OnceDoneOperation) &&    true;}#undef C//---------------------------------------------------------------------------const unsigned long MinSpeed = 8 * 1024;const unsigned long MaxSpeed = 8 * 1024 * 1024;//---------------------------------------------------------------------------static bool __fastcall TryGetSpeedLimit(const UnicodeString & Text, unsigned long & Speed){  bool Result;  if (AnsiSameText(Text, LoadStr(SPEED_UNLIMITED)))  {    Speed = 0;    Result = true;  }  else  {    int SSpeed;    Result = TryStrToInt(Text, SSpeed) && (SSpeed >= 0);    if (Result)    {      Speed = SSpeed * 1024;    }  }  return Result;}//---------------------------------------------------------------------------unsigned long __fastcall GetSpeedLimit(const UnicodeString & Text){  unsigned long Speed;  if (!TryGetSpeedLimit(Text, Speed))  {    throw Exception(FMTLOAD(SPEED_INVALID, (Text)));  }  return Speed;}//---------------------------------------------------------------------------UnicodeString __fastcall SetSpeedLimit(unsigned long Limit){  UnicodeString Text;  if (Limit == 0)  {    Text = LoadStr(SPEED_UNLIMITED);  }  else  {    Text = IntToStr(int(Limit / 1024));  }  return Text;}//---------------------------------------------------------------------------void __fastcall CopySpeedLimits(TStrings * Source, TStrings * Dest){  std::unique_ptr<TStringList> Temp(new TStringList());  bool Unlimited = false;  for (int Index = 0; Index < Source->Count; Index++)  {    UnicodeString Text = Source->Strings[Index];    unsigned long Speed;    bool Valid = TryGetSpeedLimit(Text, Speed);    if ((!Valid || (Speed == 0)) && !Unlimited)    {      Temp->Add(LoadStr(SPEED_UNLIMITED));      Unlimited = true;    }    else if (Valid && (Speed > 0))    {      Temp->Add(Text);    }  }  if (!Unlimited)  {    Temp->Insert(0, LoadStr(SPEED_UNLIMITED));  }  Dest->Assign(Temp.get());}//---------------------------------------------------------------------------TOperationSide ReverseOperationSide(TOperationSide Side){  TOperationSide Result;  switch (Side)  {    case osLocal:      Result = osRemote;      break;    case osRemote:      Result = osLocal;      break;    default:    case osCurrent:      DebugFail();      Result = Side;      break;  }  return Result;}
 |