Script.cpp 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078
  1. //---------------------------------------------------------------------------
  2. #include <CorePCH.h>
  3. #pragma hdrstop
  4. #include "Script.h"
  5. #include "Terminal.h"
  6. #include "SessionData.h"
  7. //---------------------------------------------------------------------------
  8. #pragma package(smart_init)
  9. //---------------------------------------------------------------------------
  10. const wchar_t * ToggleNames[] = { L"off", L"on" };
  11. const UnicodeString InOutParam(TraceInitStr(L"-"));
  12. //---------------------------------------------------------------------------
  13. __fastcall TScriptProcParams::TScriptProcParams(const UnicodeString & FullCommand, const UnicodeString & ParamsStr)
  14. {
  15. int P = FSwitchMarks.Pos(L"/");
  16. DebugAssert(P > 0);
  17. if (P > 0)
  18. {
  19. FSwitchMarks.Delete(P, 1);
  20. }
  21. FFullCommand = FullCommand;
  22. FParamsStr = ParamsStr;
  23. Parse(ParamsStr);
  24. }
  25. //---------------------------------------------------------------------------
  26. //---------------------------------------------------------------------------
  27. class TScriptCommands : TStringList
  28. {
  29. public:
  30. typedef void __fastcall (__closure *TCommandProc)(TScriptProcParams * Parameters);
  31. __fastcall TScriptCommands(TScript * Script);
  32. virtual __fastcall ~TScriptCommands();
  33. void __fastcall Execute(const UnicodeString & Command, const UnicodeString & Params);
  34. UnicodeString __fastcall ResolveCommand(const UnicodeString & Command);
  35. void __fastcall Register(const wchar_t * Command,
  36. const UnicodeString Description, const UnicodeString Help, TCommandProc Proc,
  37. int MinParams, int MaxParams, bool Switches);
  38. void __fastcall Register(const wchar_t * Command,
  39. int Description, int Help, TCommandProc Proc,
  40. int MinParams, int MaxParams, bool Switches);
  41. bool __fastcall Info(const UnicodeString Command,
  42. UnicodeString * Description, UnicodeString * Help);
  43. bool __fastcall Enumerate(int Index,
  44. UnicodeString * Command, UnicodeString * Description, UnicodeString * Help);
  45. static int __fastcall FindCommand(TStrings * Commands, const UnicodeString Command,
  46. UnicodeString * Matches = NULL);
  47. static int __fastcall FindCommand(const wchar_t ** Commands, size_t Count,
  48. const UnicodeString Command, UnicodeString * Matches = NULL);
  49. static void __fastcall CheckParams(TOptions * Parameters, bool Switches);
  50. protected:
  51. struct TScriptCommand
  52. {
  53. UnicodeString Description;
  54. UnicodeString Help;
  55. TCommandProc Proc;
  56. int MinParams;
  57. int MaxParams;
  58. bool Switches;
  59. };
  60. TScript * FScript;
  61. };
  62. //---------------------------------------------------------------------------
  63. __fastcall TScriptCommands::TScriptCommands(TScript * Script)
  64. {
  65. FScript = Script;
  66. Sorted = true;
  67. CaseSensitive = false;
  68. }
  69. //---------------------------------------------------------------------------
  70. __fastcall TScriptCommands::~TScriptCommands()
  71. {
  72. for (int Index = 0; Index < Count; Index++)
  73. {
  74. delete reinterpret_cast<TScriptCommand *>(Objects[Index]);
  75. }
  76. }
  77. //---------------------------------------------------------------------------
  78. void __fastcall TScriptCommands::Register(const wchar_t * Command,
  79. const UnicodeString Description, const UnicodeString Help, TCommandProc Proc,
  80. int MinParams, int MaxParams, bool Switches)
  81. {
  82. TScriptCommand * ScriptCommand = new TScriptCommand;
  83. ScriptCommand->Description = Description;
  84. ScriptCommand->Help = Help;
  85. ScriptCommand->Proc = Proc;
  86. ScriptCommand->MinParams = MinParams;
  87. ScriptCommand->MaxParams = MaxParams;
  88. ScriptCommand->Switches = Switches;
  89. AddObject(Command, reinterpret_cast<TObject *>(ScriptCommand));
  90. }
  91. //---------------------------------------------------------------------------
  92. void __fastcall TScriptCommands::Register(const wchar_t * Command,
  93. int Description, int Help, TCommandProc Proc,
  94. int MinParams, int MaxParams, bool Switches)
  95. {
  96. UnicodeString ADescription;
  97. if (Description > 0)
  98. {
  99. ADescription = LoadStr(Description);
  100. }
  101. UnicodeString AHelp;
  102. if (Help > 0)
  103. {
  104. AHelp = LoadStr(Help, 10240);
  105. }
  106. Register(Command, ADescription, AHelp, Proc, MinParams, MaxParams, Switches);
  107. }
  108. //---------------------------------------------------------------------------
  109. bool __fastcall TScriptCommands::Info(const UnicodeString Command,
  110. UnicodeString * Description, UnicodeString * Help)
  111. {
  112. int Index = FindCommand(this, Command);
  113. bool Result = (Index >= 0);
  114. if (Result)
  115. {
  116. TScriptCommand * ScriptCommand = reinterpret_cast<TScriptCommand *>(Objects[Index]);
  117. if (Description != NULL)
  118. {
  119. *Description = ScriptCommand->Description;
  120. }
  121. if (Help != NULL)
  122. {
  123. *Help = ScriptCommand->Help;
  124. }
  125. }
  126. return Result;
  127. }
  128. //---------------------------------------------------------------------------
  129. bool __fastcall TScriptCommands::Enumerate(int Index,
  130. UnicodeString * Command, UnicodeString * Description, UnicodeString * Help)
  131. {
  132. bool Result = (Index < Count);
  133. if (Result)
  134. {
  135. TScriptCommand * ScriptCommand = reinterpret_cast<TScriptCommand *>(Objects[Index]);
  136. if (Command != NULL)
  137. {
  138. *Command = Strings[Index];
  139. }
  140. if (Description != NULL)
  141. {
  142. *Description = ScriptCommand->Description;
  143. }
  144. if (Help != NULL)
  145. {
  146. *Help = ScriptCommand->Help;
  147. }
  148. }
  149. return Result;
  150. }
  151. //---------------------------------------------------------------------------
  152. int __fastcall TScriptCommands::FindCommand(TStrings * Commands,
  153. const UnicodeString Command, UnicodeString * Matches)
  154. {
  155. int Result = Commands->IndexOf(Command);
  156. if (Result < 0)
  157. {
  158. int MatchesCount = 0;
  159. for (int i = 0; i < Commands->Count; i++)
  160. {
  161. if ((Command.Length() <= Commands->Strings[i].Length()) &&
  162. SameText(Command, Commands->Strings[i].SubString(1, Command.Length())))
  163. {
  164. if (Matches != NULL)
  165. {
  166. if (!Matches->IsEmpty())
  167. {
  168. *Matches += L", ";
  169. }
  170. *Matches += Commands->Strings[i];
  171. }
  172. MatchesCount++;
  173. Result = i;
  174. }
  175. }
  176. if (MatchesCount == 0)
  177. {
  178. Result = -1;
  179. }
  180. else if (MatchesCount > 1)
  181. {
  182. Result = -2;
  183. }
  184. }
  185. return Result;
  186. }
  187. //---------------------------------------------------------------------------
  188. int __fastcall TScriptCommands::FindCommand(const wchar_t ** Commands, size_t Count,
  189. const UnicodeString Command, UnicodeString * Matches)
  190. {
  191. int Result;
  192. TStringList * Strings = new TStringList;
  193. try
  194. {
  195. Strings->CaseSensitive = false;
  196. for (unsigned int i = 0; i < Count; i++)
  197. {
  198. Strings->Add(Commands[i]);
  199. }
  200. Result = FindCommand(Strings, Command, Matches);
  201. }
  202. __finally
  203. {
  204. delete Strings;
  205. }
  206. return Result;
  207. }
  208. //---------------------------------------------------------------------------
  209. void __fastcall TScriptCommands::CheckParams(TOptions * Parameters,
  210. bool Switches)
  211. {
  212. UnicodeString Switch;
  213. if (!Switches && Parameters->UnusedSwitch(Switch))
  214. {
  215. throw Exception(FMTLOAD(SCRIPT_UNKNOWN_SWITCH, (Switch)));
  216. }
  217. }
  218. //---------------------------------------------------------------------------
  219. UnicodeString __fastcall TScriptCommands::ResolveCommand(const UnicodeString & Command)
  220. {
  221. UnicodeString Matches;
  222. int Index = FindCommand(this, Command, &Matches);
  223. if (Index >= 0)
  224. {
  225. return Strings[Index];
  226. }
  227. else
  228. {
  229. return UnicodeString();
  230. }
  231. }
  232. //---------------------------------------------------------------------------
  233. // parameters are by purpose passed by (constant) reference.
  234. // because if passed by value (copy), UnicodeString reference is not for some reason
  235. // decreased on exit by exception, leading to memory leak
  236. void __fastcall TScriptCommands::Execute(const UnicodeString & Command, const UnicodeString & Params)
  237. {
  238. UnicodeString Matches;
  239. int Index = FindCommand(this, Command, &Matches);
  240. if (Index == -2)
  241. {
  242. throw Exception(FMTLOAD(SCRIPT_COMMAND_AMBIGUOUS, (Command, Matches)));
  243. }
  244. else if (Index < 0)
  245. {
  246. throw Exception(FMTLOAD(SCRIPT_COMMAND_UNKNOWN, (Command)));
  247. }
  248. TScriptCommand * ScriptCommand = reinterpret_cast<TScriptCommand *>(Objects[Index]);
  249. UnicodeString FullCommand = Strings[Index];
  250. std::unique_ptr<TScriptProcParams> Parameters(new TScriptProcParams(FullCommand, Params));
  251. if (Parameters->ParamCount < ScriptCommand->MinParams)
  252. {
  253. throw Exception(FMTLOAD(SCRIPT_MISSING_PARAMS, (FullCommand)));
  254. }
  255. else if ((ScriptCommand->MaxParams >= 0) && (Parameters->ParamCount > ScriptCommand->MaxParams))
  256. {
  257. throw Exception(FMTLOAD(SCRIPT_TOO_MANY_PARAMS, (FullCommand)));
  258. }
  259. else
  260. {
  261. CheckParams(Parameters.get(), ScriptCommand->Switches);
  262. ScriptCommand->Proc(Parameters.get());
  263. }
  264. }
  265. //---------------------------------------------------------------------------
  266. //---------------------------------------------------------------------------
  267. // keep in sync with Session constructor in .NET
  268. const int BatchSessionReopenTimeout = 2 * MSecsPerSec * SecsPerMin; // 2 mins
  269. //---------------------------------------------------------------------------
  270. __fastcall TScript::TScript(bool LimitedOutput)
  271. {
  272. FLimitedOutput = LimitedOutput;
  273. FTerminal = NULL;
  274. FLoggingTerminal = NULL;
  275. FGroups = false;
  276. FWantsProgress = false;
  277. FUsageWarnings = true;
  278. FOnTransferOut = NULL;
  279. FOnTransferIn = NULL;
  280. FIncludeFileMaskOptionUsed = false;
  281. FPendingLogLines = new TStringList();
  282. FPrintInformation = false;
  283. Init();
  284. }
  285. //---------------------------------------------------------------------------
  286. __fastcall TScript::~TScript()
  287. {
  288. delete FCommands;
  289. delete FPendingLogLines;
  290. }
  291. //---------------------------------------------------------------------------
  292. void __fastcall TScript::Init()
  293. {
  294. FBatch = BatchAbort;
  295. FInteractiveBatch = BatchOff;
  296. FConfirm = false;
  297. FInteractiveConfirm = true;
  298. FSessionReopenTimeout = Configuration->SessionReopenTimeout;
  299. FInteractiveSessionReopenTimeout = FSessionReopenTimeout;
  300. if (FSessionReopenTimeout == 0)
  301. {
  302. FSessionReopenTimeout = BatchSessionReopenTimeout;
  303. }
  304. FEcho = false;
  305. FFailOnNoMatch = false;
  306. FSynchronizeParams = 0;
  307. FOnPrint = NULL;
  308. FOnTerminalSynchronizeDirectory = NULL;
  309. FOnSynchronizeStartStop = NULL;
  310. FSynchronizeMode = -1;
  311. FKeepingUpToDate = false;
  312. FWarnNonDefaultCopyParam = false;
  313. FWarnNonDefaultSynchronizeParams = false;
  314. FCommands = new TScriptCommands(this);
  315. FCommands->Register(L"help", SCRIPT_HELP_DESC, SCRIPT_HELP_HELP, &HelpProc, 0, -1, false);
  316. FCommands->Register(L"man", 0, SCRIPT_HELP_HELP, &HelpProc, 0, -1, false);
  317. // the call command does not have switches itself, but the commands may have
  318. FCommands->Register(L"call", SCRIPT_CALL_DESC2, SCRIPT_CALL_HELP2, &CallProc, 1, -1, true);
  319. FCommands->Register(L"!", 0, SCRIPT_CALL_HELP2, &CallProc, 1, -1, true);
  320. FCommands->Register(L"pwd", SCRIPT_PWD_DESC, SCRIPT_PWD_HELP, &PwdProc, 0, 0, false);
  321. FCommands->Register(L"cd", SCRIPT_CD_DESC, SCRIPT_CD_HELP, &CdProc, 0, 1, false);
  322. FCommands->Register(L"ls", SCRIPT_LS_DESC, SCRIPT_LS_HELP2, &LsProc, 0, 1, false);
  323. FCommands->Register(L"dir", 0, SCRIPT_LS_HELP2, &LsProc, 0, 1, false);
  324. FCommands->Register(L"rm", SCRIPT_RM_DESC, SCRIPT_RM_HELP2, &RmProc, 1, -1, true);
  325. FCommands->Register(L"rmdir", SCRIPT_RMDIR_DESC, SCRIPT_RMDIR_HELP, &RmDirProc, 1, -1, false);
  326. FCommands->Register(L"mv", SCRIPT_MV_DESC, SCRIPT_MV_HELP2, &MvProc, 2, -1, false);
  327. FCommands->Register(L"rename", 0, SCRIPT_MV_HELP2, &MvProc, 2, -1, false);
  328. FCommands->Register(L"cp", SCRIPT_CP_DESC, SCRIPT_CP_HELP, &CpProc, 2, -1, false);
  329. FCommands->Register(L"chmod", SCRIPT_CHMOD_DESC, SCRIPT_CHMOD_HELP2, &ChModProc, 2, -1, false);
  330. FCommands->Register(L"ln", SCRIPT_LN_DESC, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
  331. FCommands->Register(L"symlink", 0, SCRIPT_LN_HELP, &LnProc, 2, 2, false);
  332. FCommands->Register(L"mkdir", SCRIPT_MKDIR_DESC, SCRIPT_MKDIR_HELP, &MkDirProc, 1, 1, false);
  333. FCommands->Register(L"get", SCRIPT_GET_DESC, SCRIPT_GET_HELP8, &GetProc, 0, -1, true);
  334. FCommands->Register(L"recv", 0, SCRIPT_GET_HELP8, &GetProc, 0, -1, true);
  335. FCommands->Register(L"mget", 0, SCRIPT_GET_HELP8, &GetProc, 0, -1, true);
  336. FCommands->Register(L"put", SCRIPT_PUT_DESC, SCRIPT_PUT_HELP8, &PutProc, 0, -1, true);
  337. FCommands->Register(L"send", 0, SCRIPT_PUT_HELP8, &PutProc, 0, -1, true);
  338. FCommands->Register(L"mput", 0, SCRIPT_PUT_HELP8, &PutProc, 0, -1, true);
  339. FCommands->Register(L"option", SCRIPT_OPTION_DESC, SCRIPT_OPTION_HELP7, &OptionProc, -1, 2, false);
  340. FCommands->Register(L"ascii", 0, SCRIPT_OPTION_HELP7, &AsciiProc, 0, 0, false);
  341. FCommands->Register(L"binary", 0, SCRIPT_OPTION_HELP7, &BinaryProc, 0, 0, false);
  342. FCommands->Register(L"synchronize", SCRIPT_SYNCHRONIZE_DESC, SCRIPT_SYNCHRONIZE_HELP7, &SynchronizeProc, 0, -1, true);
  343. FCommands->Register(L"keepuptodate", SCRIPT_KEEPUPTODATE_DESC, SCRIPT_KEEPUPTODATE_HELP5, &KeepUpToDateProc, 0, 2, true);
  344. // the echo command does not have switches actually, but it must handle dashes in its arguments
  345. FCommands->Register(L"echo", SCRIPT_ECHO_DESC, SCRIPT_ECHO_HELP, &EchoProc, -1, -1, true);
  346. FCommands->Register(L"stat", SCRIPT_STAT_DESC, SCRIPT_STAT_HELP, &StatProc, 1, 1, false);
  347. FCommands->Register(L"checksum", SCRIPT_CHECKSUM_DESC, SCRIPT_CHECKSUM_HELP, &ChecksumProc, 2, 2, false);
  348. FCommands->Register(COPYID_COMMAND, 0, 0, &CopyIdProc, 1, 1, false);
  349. }
  350. //---------------------------------------------------------------------------
  351. void __fastcall TScript::RequireParams(TScriptProcParams * Parameters, int MinParams)
  352. {
  353. if (Parameters->ParamCount < MinParams)
  354. {
  355. throw Exception(FMTLOAD(SCRIPT_MISSING_PARAMS, (Parameters->FullCommand)));
  356. }
  357. }
  358. //---------------------------------------------------------------------------
  359. void __fastcall TScript::CheckDefaultCopyParam()
  360. {
  361. if (FWarnNonDefaultCopyParam)
  362. {
  363. // started with non-factory settings and still have them, warn
  364. if (HasNonDefaultCopyParams())
  365. {
  366. PrintLine(LoadStr(SCRIPT_NON_DEFAULT_COPY_PARAM));
  367. }
  368. FWarnNonDefaultCopyParam = false;
  369. }
  370. }
  371. //---------------------------------------------------------------------------
  372. bool __fastcall TScript::HasNonDefaultCopyParams()
  373. {
  374. return !(FCopyParam == TCopyParamType());
  375. }
  376. //---------------------------------------------------------------------------
  377. void __fastcall TScript::SetCopyParam(const TCopyParamType & value)
  378. {
  379. FCopyParam.Assign(&value);
  380. FWarnNonDefaultCopyParam = HasNonDefaultCopyParams();
  381. }
  382. //---------------------------------------------------------------------------
  383. void __fastcall TScript::CheckDefaultSynchronizeParams()
  384. {
  385. if (FWarnNonDefaultSynchronizeParams)
  386. {
  387. // as opposite to CheckDefaultCopyParam(), not checking
  388. // current params as we cannot override any of those we accept anyway
  389. PrintLine(LoadStr(SCRIPT_NON_DEFAULT_SYNC_PARAM));
  390. FWarnNonDefaultSynchronizeParams = false;
  391. }
  392. }
  393. //---------------------------------------------------------------------------
  394. void __fastcall TScript::SetSynchronizeParams(int value)
  395. {
  396. const int AcceptedParams =
  397. TTerminal::spExistingOnly | TTerminal::spTimestamp |
  398. TTerminal::spNotByTime | TTerminal::spBySize | TTerminal::spByChecksum | TTerminal::spCaseSensitive;
  399. FSynchronizeParams = (value & AcceptedParams);
  400. FWarnNonDefaultSynchronizeParams =
  401. (FSynchronizeParams != (TTerminal::spDefault & AcceptedParams));
  402. }
  403. //---------------------------------------------------------------------------
  404. bool __fastcall TScript::IsTerminalLogging(TTerminal * ATerminal)
  405. {
  406. return (ATerminal != NULL) && ATerminal->Log->Logging;
  407. }
  408. //---------------------------------------------------------------------------
  409. const static UnicodeString ScriptLogFormat(L"Script: %s");
  410. void __fastcall TScript::Log(TLogLineType Type, const UnicodeString & AStr, TTerminal * ATerminal)
  411. {
  412. UnicodeString Str = FORMAT(ScriptLogFormat, (AStr));
  413. TTerminal * LoggingTerminal = (ATerminal != NULL ? ATerminal : (FLoggingTerminal != NULL ? FLoggingTerminal : Terminal));
  414. if (IsTerminalLogging(LoggingTerminal))
  415. {
  416. LoggingTerminal->Log->Add(Type, Str);
  417. }
  418. else if (Configuration->Logging)
  419. {
  420. FPendingLogLines->AddObject(Str, reinterpret_cast<TObject *>(Type));
  421. }
  422. }
  423. //---------------------------------------------------------------------------
  424. void __fastcall TScript::LogOption(const UnicodeString & LogStr)
  425. {
  426. Log(llInput, LogStr);
  427. }
  428. //---------------------------------------------------------------------------
  429. void __fastcall TScript::LogPendingLines(TTerminal * ATerminal)
  430. {
  431. if (IsTerminalLogging(ATerminal) && (FPendingLogLines->Count > 0))
  432. {
  433. // not using Log(), as we want to log to ATerminal, not Terminal,
  434. // what is different here, as we are called from TManagementScript::Connect()
  435. ATerminal->Log->Add(llMessage, FORMAT(ScriptLogFormat, (L"Retrospectively logging previous script records:")));
  436. for (int Index = 0; Index < FPendingLogLines->Count; Index++)
  437. {
  438. ATerminal->Log->Add(
  439. static_cast<TLogLineType>(reinterpret_cast<uintptr_t>(FPendingLogLines->Objects[Index])),
  440. FPendingLogLines->Strings[Index]);
  441. }
  442. FPendingLogLines->Clear();
  443. ATerminal->Log->AddSeparator();
  444. }
  445. }
  446. //---------------------------------------------------------------------------
  447. UnicodeString __fastcall TScript::GetLogCmd(const UnicodeString & FullCommand,
  448. const UnicodeString & /*Command*/, const UnicodeString & /*Params*/)
  449. {
  450. return FullCommand;
  451. }
  452. //---------------------------------------------------------------------------
  453. void __fastcall TScript::StartInteractive()
  454. {
  455. FBatch = FInteractiveBatch;
  456. FConfirm = FInteractiveConfirm;
  457. FSessionReopenTimeout = FInteractiveSessionReopenTimeout;
  458. }
  459. //---------------------------------------------------------------------------
  460. void __fastcall TScript::Command(UnicodeString Cmd)
  461. {
  462. try
  463. {
  464. if (!Cmd.Trim().IsEmpty() && (Cmd[1] != L';') && (Cmd[1] != L'#'))
  465. {
  466. UnicodeString FullCmd = Cmd;
  467. UnicodeString Command;
  468. if (CutToken(Cmd, Command))
  469. {
  470. UnicodeString LogCmd = GetLogCmd(FullCmd, Command, Cmd);
  471. Log(llInput, LogCmd);
  472. if (Configuration->ActualLogProtocol >= 1)
  473. {
  474. UnicodeString LogCmdParams = LogCmd;
  475. UnicodeString DummyLogCmd;
  476. if (DebugAlwaysTrue(CutToken(LogCmdParams, DummyLogCmd)))
  477. {
  478. std::unique_ptr<TScriptProcParams> Parameters(new TScriptProcParams(FCommands->ResolveCommand(Cmd), LogCmdParams));
  479. Parameters->LogOptions(LogOption);
  480. }
  481. }
  482. if (FEcho)
  483. {
  484. PrintLine(LogCmd);
  485. }
  486. TTerminal * BeforeGroupTerminal = FGroups ? Terminal : NULL;
  487. if (BeforeGroupTerminal != NULL)
  488. {
  489. BeforeGroupTerminal->ActionLog->BeginGroup(LogCmd);
  490. }
  491. int ASessionReopenTimeout = Configuration->SessionReopenTimeout;
  492. try
  493. {
  494. Configuration->SessionReopenTimeout = FSessionReopenTimeout;
  495. try
  496. {
  497. FCommands->Execute(Command, Cmd);
  498. }
  499. catch(Exception & E)
  500. {
  501. // seemingly duplicate (to the method-level one) catch clause,
  502. // ensures the <failure/> tag is enclosed in <group/> tag
  503. if (!HandleExtendedException(&E))
  504. {
  505. throw;
  506. }
  507. }
  508. }
  509. __finally
  510. {
  511. Configuration->SessionReopenTimeout = ASessionReopenTimeout;
  512. TTerminal * AfterGroupTerminal = FGroups ? Terminal : NULL;
  513. if (AfterGroupTerminal != NULL)
  514. {
  515. // this happens for "open" command
  516. if (AfterGroupTerminal != BeforeGroupTerminal)
  517. {
  518. AfterGroupTerminal->ActionLog->BeginGroup(LogCmd);
  519. }
  520. AfterGroupTerminal->ActionLog->EndGroup();
  521. }
  522. }
  523. }
  524. }
  525. }
  526. catch(Exception & E)
  527. {
  528. if (!HandleExtendedException(&E))
  529. {
  530. throw;
  531. }
  532. }
  533. }
  534. //---------------------------------------------------------------------------
  535. TStrings * __fastcall TScript::CreateFileList(TScriptProcParams * Parameters, int Start,
  536. int End, TFileListType ListType)
  537. {
  538. TStrings * Result = new TStringList();
  539. try
  540. {
  541. TStringList * FileLists = NULL;
  542. try
  543. {
  544. for (int i = Start; i <= End; i++)
  545. {
  546. UnicodeString FileName = Parameters->Param[i];
  547. if (SimpleUnixExcludeTrailingBackslash(FileName) != FileName)
  548. {
  549. PrintLine(LoadStr(SCRIPT_AMBIGUOUS_SLASH_IN_PATH));
  550. }
  551. if (FLAGSET(ListType, fltDirectories))
  552. {
  553. TRemoteFile * File = new TRemoteFile();
  554. File->FileName = FileName;
  555. File->Type = FILETYPE_DIRECTORY;
  556. Result->AddObject(FileName, File);
  557. }
  558. else if (FLAGSET(ListType, fltMask) && TFileMasks::IsMask(FileName))
  559. {
  560. UnicodeString FileDirectory = UnixExtractFilePath(FileName);
  561. UnicodeString Directory = FileDirectory;
  562. if (Directory.IsEmpty())
  563. {
  564. Directory = UnixIncludeTrailingBackslash(FTerminal->CurrentDirectory);
  565. }
  566. TRemoteFileList * FileList = NULL;
  567. if (FileLists != NULL)
  568. {
  569. int Index = FileLists->IndexOf(Directory);
  570. if (Index > 0)
  571. {
  572. FileList = dynamic_cast<TRemoteFileList *>(FileLists->Objects[Index]);
  573. }
  574. }
  575. if (FileList == NULL)
  576. {
  577. FileList = FTerminal->CustomReadDirectoryListing(Directory, false);
  578. if (FileLists == NULL)
  579. {
  580. FileLists = new TStringList();
  581. FileLists->OwnsObjects = true;
  582. }
  583. FileLists->AddObject(Directory, FileList);
  584. }
  585. TFileMasks Mask;
  586. Mask.SetMask(UnixExtractFileName(FileName));
  587. bool AnyFound = false;
  588. // Can happen in "batch continue" mode
  589. if (FileList != NULL)
  590. {
  591. for (int i = 0; i < FileList->Count; i++)
  592. {
  593. TRemoteFile * File = FileList->Files[i];
  594. TFileMasks::TParams Params;
  595. Params.Size = File->Size;
  596. Params.Modification = File->Modification;
  597. if (IsRealFile(File->FileName) &&
  598. Mask.MatchesFileName(File->FileName, false, &Params))
  599. {
  600. Result->AddObject(FileDirectory + File->FileName,
  601. FLAGSET(ListType, fltQueryServer) ? File->Duplicate() : NULL);
  602. AnyFound = true;
  603. }
  604. }
  605. }
  606. if (!AnyFound)
  607. {
  608. NoMatch(Mask.Masks, UnicodeString());
  609. }
  610. }
  611. else
  612. {
  613. TRemoteFile * File = NULL;
  614. if (FLAGSET(ListType, fltQueryServer))
  615. {
  616. FTerminal->ExceptionOnFail = true;
  617. try
  618. {
  619. File = FTerminal->ReadFile(UnixExcludeTrailingBackslash(FileName));
  620. if (!File->HaveFullFileName)
  621. {
  622. File->FullFileName = FileName;
  623. }
  624. }
  625. __finally
  626. {
  627. FTerminal->ExceptionOnFail = false;
  628. }
  629. }
  630. Result->AddObject(FileName, File);
  631. }
  632. }
  633. }
  634. __finally
  635. {
  636. delete FileLists;
  637. }
  638. if (FLAGSET(ListType, fltLatest) && (Result->Count > 1))
  639. {
  640. // otherwise we do not have TRemoteFile's
  641. DebugAssert(FLAGSET(ListType, fltQueryServer));
  642. int LatestIndex = 0;
  643. for (int Index = 1; Index < Result->Count; Index++)
  644. {
  645. TRemoteFile * File = dynamic_cast<TRemoteFile *>(Result->Objects[Index]);
  646. if (dynamic_cast<TRemoteFile *>(Result->Objects[LatestIndex])->Modification < File->Modification)
  647. {
  648. LatestIndex = Index;
  649. }
  650. }
  651. TRemoteFile * File = dynamic_cast<TRemoteFile *>(Result->Objects[LatestIndex]);
  652. UnicodeString Path = Result->Strings[LatestIndex];
  653. Result->Delete(LatestIndex);
  654. FreeFiles(Result);
  655. Result->Clear();
  656. Result->AddObject(Path, File);
  657. }
  658. if (FLAGSET(ListType, fltOnlyFile))
  659. {
  660. for (int Index = 0; Index < Result->Count; Index++)
  661. {
  662. TRemoteFile * File = dynamic_cast<TRemoteFile *>(Result->Objects[Index]);
  663. if (File->IsDirectory)
  664. {
  665. throw Exception(FMTLOAD(NOT_FILE_ERROR, (File->FileName)));
  666. }
  667. }
  668. }
  669. }
  670. catch (...)
  671. {
  672. FreeFileList(Result);
  673. throw;
  674. }
  675. return Result;
  676. }
  677. //---------------------------------------------------------------------------
  678. TStrings * __fastcall TScript::CreateLocalFileList(TScriptProcParams * Parameters,
  679. int Start, int End, TFileListType ListType)
  680. {
  681. TStringList * Result = new TStringList();
  682. try
  683. {
  684. Result->OwnsObjects = true;
  685. UnicodeString LatestFileName;
  686. TDateTime LatestModification; // initialized to 0
  687. for (int i = Start; i <= End; i++)
  688. {
  689. // FindFirstFile called (indirectly) below fails if path ends with slash.
  690. // (it actually won't make a difference functionally as we fall back to adding
  691. // the path as is in "else" branch, but the comment "let it fail later" won't stand)
  692. UnicodeString FileName = ExcludeTrailingBackslash(Parameters->Param[i]);
  693. if (FileName != Parameters->Param[i])
  694. {
  695. PrintLine(LoadStr(SCRIPT_AMBIGUOUS_SLASH_IN_PATH));
  696. }
  697. if (FLAGSET(ListType, fltMask))
  698. {
  699. TSearchRecOwned SearchRec;
  700. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  701. UnicodeString Error;
  702. bool AnyFound = false;
  703. if (FindFirstUnchecked(FileName, FindAttrs, SearchRec) == 0)
  704. {
  705. do
  706. {
  707. if (SearchRec.IsRealFile())
  708. {
  709. UnicodeString FileName = SearchRec.GetFilePath();
  710. TLocalFile * LocalFile = new TLocalFile;
  711. CopySearchRec(SearchRec, LocalFile->SearchRec);
  712. Result->AddObject(FileName, LocalFile);
  713. if (SearchRec.TimeStamp > LatestModification)
  714. {
  715. LatestFileName = FileName;
  716. LatestModification = SearchRec.TimeStamp;
  717. }
  718. AnyFound = true;
  719. }
  720. }
  721. while (FindNextChecked(SearchRec) == 0);
  722. }
  723. else
  724. {
  725. if (FileName.LastDelimiter(L"?*") == 0)
  726. {
  727. // No match, and it is not a mask, let it fail latter.
  728. // But with -latest, we have to fail straight away
  729. // (so maybe we should fail unconditionally now,
  730. // once we need to have the code in place anyway)
  731. if (FLAGSET(ListType, fltLatest))
  732. {
  733. throw Exception(FMTLOAD(FILE_NOT_EXISTS, (FileName)));
  734. }
  735. Result->Add(FileName);
  736. AnyFound = true;
  737. }
  738. else
  739. {
  740. Error = ListingSysErrorMessage();
  741. }
  742. }
  743. if (!AnyFound)
  744. {
  745. NoMatch(ExtractFileName(FileName), Error);
  746. }
  747. }
  748. else
  749. {
  750. DebugAssert(FLAGCLEAR(ListType, fltLatest));
  751. // this branch is currently never used
  752. Result->Add(FileName);
  753. }
  754. }
  755. if (FLAGSET(ListType, fltLatest))
  756. {
  757. Result->Clear();
  758. if (!LatestFileName.IsEmpty())
  759. {
  760. Result->Add(LatestFileName);
  761. }
  762. }
  763. }
  764. catch(...)
  765. {
  766. delete Result;
  767. throw;
  768. }
  769. return Result;
  770. }
  771. //---------------------------------------------------------------------------
  772. UnicodeString __fastcall TScript::ListingSysErrorMessage()
  773. {
  774. UnicodeString Result;
  775. int LastError = GetLastError();
  776. // System error text for ERROR_FILE_NOT_FOUND is more or less redundant to ours
  777. // SCRIPT_MATCH_NO_MATCH. Also the system error does not look nice/user friendly
  778. // so avoid using it for this frequent case.
  779. if (LastError != ERROR_FILE_NOT_FOUND)
  780. {
  781. Result = SysErrorMessageForError(LastError);
  782. }
  783. return Result;
  784. }
  785. //---------------------------------------------------------------------------
  786. void __fastcall TScript::NoMatch(const UnicodeString & Message)
  787. {
  788. if (FFailOnNoMatch)
  789. {
  790. throw Exception(Message);
  791. }
  792. else
  793. {
  794. PrintLine(Message);
  795. }
  796. }
  797. //---------------------------------------------------------------------------
  798. void __fastcall TScript::NoMatch(const UnicodeString & Mask, const UnicodeString & Error)
  799. {
  800. UnicodeString Message = FMTLOAD(SCRIPT_MATCH_NO_MATCH, (Mask));
  801. if (!Error.IsEmpty())
  802. {
  803. Message += FORMAT(L" (%s)", (Error));
  804. }
  805. NoMatch(Message);
  806. }
  807. //---------------------------------------------------------------------------
  808. void __fastcall TScript::FreeFiles(TStrings * FileList)
  809. {
  810. for (int i = 0; i < FileList->Count; i++)
  811. {
  812. if (FileList->Objects[i] != NULL)
  813. {
  814. TRemoteFile * File = dynamic_cast<TRemoteFile *>(FileList->Objects[i]);
  815. delete File;
  816. }
  817. }
  818. }
  819. //---------------------------------------------------------------------------
  820. void __fastcall TScript::FreeFileList(TStrings * FileList)
  821. {
  822. FreeFiles(FileList);
  823. delete FileList;
  824. }
  825. //---------------------------------------------------------------------------
  826. void __fastcall TScript::ConnectTerminal(TTerminal * ATerminal)
  827. {
  828. ATerminal->Open();
  829. }
  830. //---------------------------------------------------------------------------
  831. void __fastcall TScript::Print(const UnicodeString Str, bool Error)
  832. {
  833. if (FOnPrint != NULL)
  834. {
  835. FOnPrint(this, Str, Error);
  836. }
  837. }
  838. //---------------------------------------------------------------------------
  839. void __fastcall TScript::PrintLine(const UnicodeString Str, bool Error, TTerminal * ATerminal)
  840. {
  841. Log(llOutput, Str, ATerminal);
  842. Print(Str + L"\n", Error);
  843. }
  844. //---------------------------------------------------------------------------
  845. bool __fastcall TScript::HandleExtendedException(Exception * E, TTerminal * ATerminal)
  846. {
  847. bool Result = (OnShowExtendedException != NULL);
  848. if (Result)
  849. {
  850. if (ATerminal == NULL)
  851. {
  852. ATerminal = FTerminal;
  853. }
  854. OnShowExtendedException(ATerminal, E, NULL);
  855. }
  856. return Result;
  857. }
  858. //---------------------------------------------------------------------------
  859. void __fastcall TScript::CheckSession()
  860. {
  861. if (FTerminal == NULL)
  862. {
  863. throw Exception(LoadStr(SCRIPT_NO_SESSION));
  864. }
  865. }
  866. //---------------------------------------------------------------------------
  867. void __fastcall TScript::CheckMultiFilesToOne(TStrings * FileList, const UnicodeString & Target, bool Unix)
  868. {
  869. UnicodeString Name;
  870. if (Unix)
  871. {
  872. Name = UnixExtractFileName(Target);
  873. }
  874. else
  875. {
  876. Name = ExtractFileName(Target);
  877. }
  878. if (!IsFileNameMask(Name) && (FileList->Count > 1))
  879. {
  880. UnicodeString Message =
  881. RemoveEmptyLines(UnformatMessage(FormatMultiFilesToOneConfirmation(Target, Unix)));
  882. PrintLine(Message);
  883. }
  884. }
  885. //---------------------------------------------------------------------------
  886. void __fastcall TScript::CheckParams(TScriptProcParams * Parameters)
  887. {
  888. TScriptCommands::CheckParams(Parameters, false);
  889. }
  890. //---------------------------------------------------------------------------
  891. void __fastcall TScript::TransferParamParams(int & Params, TScriptProcParams * Parameters)
  892. {
  893. Params |= FLAGMASK(!FConfirm, cpNoConfirmation);
  894. if (Parameters->FindSwitch(DELETE_SWITCH))
  895. {
  896. Params |= cpDelete;
  897. }
  898. if (Parameters->FindSwitch(L"resume"))
  899. {
  900. Params |= cpResume;
  901. }
  902. else if (Parameters->FindSwitch(L"append"))
  903. {
  904. Params |= cpAppend;
  905. }
  906. }
  907. //---------------------------------------------------------------------------
  908. void __fastcall TScript::CopyParamParams(TCopyParamType & CopyParam, TScriptProcParams * Parameters)
  909. {
  910. UnicodeString Value;
  911. if (!FWantsProgress)
  912. {
  913. // total size is not visualized, hence it makes no sense to calculate it
  914. CopyParam.CalculateSize = false;
  915. }
  916. if (Parameters->FindSwitch(NOPRESERVETIME_SWITCH))
  917. {
  918. CopyParam.PreserveTime = false;
  919. CopyParam.PreserveTimeDirs = false;
  920. }
  921. if (Parameters->FindSwitch(PRESERVETIME_SWITCH, Value))
  922. {
  923. CopyParam.PreserveTime = true;
  924. if (SameText(Value, PRESERVETIMEDIRS_SWITCH_VALUE))
  925. {
  926. CopyParam.PreserveTimeDirs = true;
  927. }
  928. }
  929. if (Parameters->FindSwitch(NOPERMISSIONS_SWITCH))
  930. {
  931. CopyParam.PreserveRights = false;
  932. }
  933. if (Parameters->FindSwitch(PERMISSIONS_SWITCH, Value))
  934. {
  935. CopyParam.PreserveRights = true;
  936. CopyParam.Rights.Octal = Value;
  937. }
  938. if (Parameters->FindSwitch(SPEED_SWITCH, Value))
  939. {
  940. int CPSLimit;
  941. if (Value.IsEmpty())
  942. {
  943. CPSLimit = 0;
  944. }
  945. else
  946. {
  947. CPSLimit = StrToInt(Value) * 1024;
  948. if (CPSLimit < 0)
  949. {
  950. CPSLimit = 0;
  951. }
  952. }
  953. CopyParam.CPSLimit = CPSLimit;
  954. }
  955. if (Parameters->FindSwitch(TRANSFER_SWITCH, Value))
  956. {
  957. CopyParam.TransferMode = ParseTransferModeName(Value);
  958. }
  959. if (Parameters->FindSwitch(FILEMASK_SWITCH, Value))
  960. {
  961. CopyParam.IncludeFileMask = Value;
  962. if (FIncludeFileMaskOptionUsed)
  963. {
  964. PrintLine(LoadStr(SCRIPT_FILEMASK_INCLUDE_EXCLUDE));
  965. }
  966. }
  967. if (Parameters->FindSwitch(RESUMESUPPORT_SWITCH, Value))
  968. {
  969. int ToggleValue = TScriptCommands::FindCommand(ToggleNames,
  970. LENOF(ToggleNames), Value);
  971. if (ToggleValue >= 0)
  972. {
  973. switch (ToggleValue)
  974. {
  975. case ToggleOff:
  976. CopyParam.ResumeSupport = rsOff;
  977. break;
  978. case ToggleOn:
  979. CopyParam.ResumeSupport = rsOn;
  980. break;
  981. default:
  982. DebugFail();
  983. break;
  984. }
  985. }
  986. else
  987. {
  988. int ThresholdValue;
  989. if (!TryStrToInt(Value, ThresholdValue))
  990. {
  991. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (RESUMESUPPORT_SWITCH, Value)));
  992. }
  993. CopyParam.ResumeSupport = rsSmart;
  994. CopyParam.ResumeThreshold = ThresholdValue * 1024;
  995. }
  996. }
  997. if (Parameters->FindSwitch(NONEWERONLY_SWICH))
  998. {
  999. CopyParam.NewerOnly = false;
  1000. }
  1001. if (Parameters->FindSwitch(NEWERONLY_SWICH))
  1002. {
  1003. CopyParam.NewerOnly = true;
  1004. }
  1005. std::unique_ptr<TStrings> RawSettings(new TStringList());
  1006. if (Parameters->FindSwitch(RAWTRANSFERSETTINGS_SWITCH, RawSettings.get()))
  1007. {
  1008. std::unique_ptr<TOptionsStorage> OptionsStorage(new TOptionsStorage(RawSettings.get(), false));
  1009. CopyParam.Load(OptionsStorage.get());
  1010. }
  1011. }
  1012. //---------------------------------------------------------------------------
  1013. void __fastcall TScript::ResetTransfer()
  1014. {
  1015. }
  1016. //---------------------------------------------------------------------------
  1017. bool __fastcall TScript::EnsureCommandSessionFallback(
  1018. TFSCapability Capability, TSessionAction * Action)
  1019. {
  1020. bool Result = FTerminal->IsCapable[Capability] ||
  1021. FTerminal->CommandSessionOpened;
  1022. if (!Result)
  1023. {
  1024. try
  1025. {
  1026. ConnectTerminal(FTerminal->CommandSession);
  1027. Result = true;
  1028. }
  1029. catch(Exception & E)
  1030. {
  1031. if (Action != NULL)
  1032. {
  1033. Action->Rollback(&E);
  1034. }
  1035. HandleExtendedException(&E, FTerminal->CommandSession);
  1036. Result = false;
  1037. }
  1038. }
  1039. return Result;
  1040. }
  1041. //---------------------------------------------------------------------------
  1042. void __fastcall TScript::HelpProc(TScriptProcParams * Parameters)
  1043. {
  1044. UnicodeString Output;
  1045. if (Parameters->ParamCount == 0)
  1046. {
  1047. UnicodeString Command;
  1048. UnicodeString Description;
  1049. int Index = 0;
  1050. while (FCommands->Enumerate(Index, &Command, &Description, NULL))
  1051. {
  1052. if (!Description.IsEmpty())
  1053. {
  1054. Output += FORMAT(L"%-8s %s\n", (Command, Description));
  1055. }
  1056. Index++;
  1057. }
  1058. }
  1059. else
  1060. {
  1061. for (int i = 1; i <= Parameters->ParamCount; i++)
  1062. {
  1063. UnicodeString Help;
  1064. if (FCommands->Info(Parameters->Param[i], NULL, &Help))
  1065. {
  1066. Output += Help;
  1067. }
  1068. else
  1069. {
  1070. throw Exception(FMTLOAD(SCRIPT_COMMAND_UNKNOWN, (Parameters->Param[i])));
  1071. }
  1072. }
  1073. }
  1074. Print(Output);
  1075. }
  1076. //---------------------------------------------------------------------------
  1077. void __fastcall TScript::CallProc(TScriptProcParams * Parameters)
  1078. {
  1079. CheckSession();
  1080. if (!FTerminal->IsCapable[fcAnyCommand] &&
  1081. !FTerminal->IsCapable[fcSecondaryShell])
  1082. {
  1083. NotSupported();
  1084. }
  1085. // this is used only to log failures to open separate shell session,
  1086. // the actual call logging is done in TTerminal::AnyCommand
  1087. TCallSessionAction Action(
  1088. FTerminal->ActionLog, Parameters->ParamsStr, FTerminal->CurrentDirectory);
  1089. if (EnsureCommandSessionFallback(fcAnyCommand, &Action))
  1090. {
  1091. Action.Cancel();
  1092. FTerminal->AnyCommand(Parameters->ParamsStr, TerminalCaptureLog);
  1093. }
  1094. }
  1095. //---------------------------------------------------------------------------
  1096. void __fastcall TScript::EchoProc(TScriptProcParams * Parameters)
  1097. {
  1098. PrintLine(Parameters->ParamsStr);
  1099. }
  1100. //---------------------------------------------------------------------------
  1101. void __fastcall TScript::StatProc(TScriptProcParams * Parameters)
  1102. {
  1103. CheckSession();
  1104. UnicodeString Path = UnixExcludeTrailingBackslash(Parameters->Param[1]);
  1105. FTerminal->ExceptionOnFail = true;
  1106. TRemoteFile * File = NULL;
  1107. try
  1108. {
  1109. File = FTerminal->ReadFileListing(Path);
  1110. PrintLine(File->ListingStr);
  1111. }
  1112. __finally
  1113. {
  1114. FTerminal->ExceptionOnFail = false;
  1115. delete File;
  1116. }
  1117. }
  1118. //---------------------------------------------------------------------------
  1119. void __fastcall TScript::DoCalculatedChecksum(
  1120. const UnicodeString & FileName, const UnicodeString & DebugUsedArg(Alg), const UnicodeString & Hash)
  1121. {
  1122. PrintLine(FORMAT(L"%s %s", (Hash, FileName)));
  1123. }
  1124. //---------------------------------------------------------------------------
  1125. void __fastcall TScript::ChecksumProc(TScriptProcParams * Parameters)
  1126. {
  1127. CheckSession();
  1128. if (!FTerminal->IsCapable[fcCalculatingChecksum] &&
  1129. (!FTerminal->IsCapable[fcSecondaryShell] || FTerminal->IsEncryptingFiles()))
  1130. {
  1131. NotSupported();
  1132. }
  1133. // this is used only to log failures to open separate shell session,
  1134. // the actual call logging is done in TTerminal::CalculateFilesChecksum
  1135. TChecksumSessionAction Action(FTerminal->ActionLog);
  1136. if (EnsureCommandSessionFallback(fcCalculatingChecksum, &Action))
  1137. {
  1138. Action.Cancel();
  1139. UnicodeString Alg = Parameters->Param[1];
  1140. TStrings * FileList = CreateFileList(Parameters, 2, 2, fltQueryServer);
  1141. FTerminal->ExceptionOnFail = true;
  1142. try
  1143. {
  1144. if ((FileList->Count != 1) ||
  1145. DebugNotNull(dynamic_cast<TRemoteFile *>(FileList->Objects[0]))->IsDirectory)
  1146. {
  1147. throw Exception(FMTLOAD(NOT_FILE_ERROR, (FileList->Strings[0])));
  1148. }
  1149. FTerminal->CalculateFilesChecksum(Alg, FileList, DoCalculatedChecksum);
  1150. }
  1151. __finally
  1152. {
  1153. FTerminal->ExceptionOnFail = false;
  1154. FreeFileList(FileList);
  1155. }
  1156. }
  1157. }
  1158. //---------------------------------------------------------------------------
  1159. void __fastcall TScript::CopyIdProc(TScriptProcParams * Parameters)
  1160. {
  1161. CheckSession();
  1162. UnicodeString FileName = Parameters->Param[1];
  1163. TAutoFlag AutoFlag(FPrintInformation);
  1164. FTerminal->UploadPublicKey(FileName);
  1165. }
  1166. //---------------------------------------------------------------------------
  1167. void __fastcall TScript::TerminalCaptureLog(const UnicodeString & AddedLine,
  1168. TCaptureOutputType OutputType)
  1169. {
  1170. if ((OutputType == cotOutput) || (OutputType == cotError))
  1171. {
  1172. PrintLine(AddedLine);
  1173. }
  1174. }
  1175. //---------------------------------------------------------------------------
  1176. void __fastcall TScript::PwdProc(TScriptProcParams * /*Parameters*/)
  1177. {
  1178. CheckSession();
  1179. PrintLine(FTerminal->CurrentDirectory);
  1180. TCwdSessionAction Action(FTerminal->ActionLog, FTerminal->CurrentDirectory);
  1181. }
  1182. //---------------------------------------------------------------------------
  1183. void __fastcall TScript::CdProc(TScriptProcParams * Parameters)
  1184. {
  1185. CheckSession();
  1186. if (Parameters->ParamCount == 0)
  1187. {
  1188. FTerminal->HomeDirectory();
  1189. }
  1190. else
  1191. {
  1192. FTerminal->ChangeDirectory(Parameters->Param[1]);
  1193. }
  1194. PrintLine(FTerminal->CurrentDirectory);
  1195. }
  1196. //---------------------------------------------------------------------------
  1197. void __fastcall TScript::LsProc(TScriptProcParams * Parameters)
  1198. {
  1199. CheckSession();
  1200. UnicodeString Directory;
  1201. TFileMasks Mask;
  1202. bool HaveMask = false;
  1203. if (Parameters->ParamCount > 0)
  1204. {
  1205. Directory = Parameters->Param[1];
  1206. UnicodeString MaskStr = UnixExtractFileName(Directory);
  1207. HaveMask = TFileMasks::IsMask(MaskStr);
  1208. if (HaveMask)
  1209. {
  1210. Mask.SetMask(MaskStr);
  1211. Directory = UnixExtractFilePath(Directory);
  1212. }
  1213. }
  1214. if (Directory.IsEmpty())
  1215. {
  1216. Directory = FTerminal->CurrentDirectory;
  1217. }
  1218. TRemoteFileList * FileList = FTerminal->ReadDirectoryListing(Directory, Mask);
  1219. // on error user may select "skip", then we get NULL
  1220. if (FileList != NULL)
  1221. {
  1222. try
  1223. {
  1224. if (FileList->Count > 0)
  1225. {
  1226. for (int i = 0; i < FileList->Count; i++)
  1227. {
  1228. PrintLine(FileList->Files[i]->ListingStr);
  1229. }
  1230. }
  1231. else
  1232. {
  1233. if (HaveMask)
  1234. {
  1235. NoMatch(Mask.Masks, UnicodeString());
  1236. }
  1237. }
  1238. }
  1239. __finally
  1240. {
  1241. delete FileList;
  1242. }
  1243. }
  1244. }
  1245. //---------------------------------------------------------------------------
  1246. void __fastcall TScript::RmProc(TScriptProcParams * Parameters)
  1247. {
  1248. CheckSession();
  1249. bool OnlyFile = Parameters->FindSwitch(L"onlyfile");
  1250. TStrings * FileList = CreateFileList(
  1251. Parameters, 1, Parameters->ParamCount,
  1252. (TFileListType)(fltQueryServer | fltMask| FLAGMASK(OnlyFile, fltOnlyFile)));
  1253. try
  1254. {
  1255. CheckParams(Parameters);
  1256. FTerminal->DeleteFiles(FileList);
  1257. }
  1258. __finally
  1259. {
  1260. FreeFileList(FileList);
  1261. }
  1262. }
  1263. //---------------------------------------------------------------------------
  1264. void __fastcall TScript::RmDirProc(TScriptProcParams * Parameters)
  1265. {
  1266. CheckSession();
  1267. TStrings * FileList = CreateFileList(Parameters, 1, Parameters->ParamCount, fltDirectories);
  1268. try
  1269. {
  1270. FTerminal->DeleteFiles(FileList);
  1271. }
  1272. __finally
  1273. {
  1274. FreeFileList(FileList);
  1275. }
  1276. }
  1277. //---------------------------------------------------------------------------
  1278. void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp)
  1279. {
  1280. CheckSession();
  1281. if (!FTerminal->IsCapable[Capability])
  1282. {
  1283. NotSupported();
  1284. }
  1285. TStrings * FileList =
  1286. CreateFileList(Parameters, 1, Parameters->ParamCount - 1, TFileListType(fltMask | fltQueryServer));
  1287. try
  1288. {
  1289. DebugAssert(Parameters->ParamCount >= 1);
  1290. UnicodeString Target = Parameters->Param[Parameters->ParamCount];
  1291. UnicodeString TargetDirectory = UnixExtractFilePath(Target);
  1292. UnicodeString FileMask = UnixExtractFileName(Target);
  1293. Target = UnixIncludeTrailingBackslash(TargetDirectory) + FileMask;
  1294. CheckMultiFilesToOne(FileList, Target, true);
  1295. bool DontOverwrite = true; // might use FConfirm eventually, but that would be breaking change
  1296. if (Cp)
  1297. {
  1298. FTerminal->CopyFiles(FileList, TargetDirectory, FileMask, DontOverwrite);
  1299. }
  1300. else
  1301. {
  1302. FTerminal->MoveFiles(FileList, TargetDirectory, FileMask, DontOverwrite);
  1303. }
  1304. }
  1305. __finally
  1306. {
  1307. FreeFileList(FileList);
  1308. }
  1309. }
  1310. //---------------------------------------------------------------------------
  1311. void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
  1312. {
  1313. DoMvOrCp(Parameters, fcRemoteMove, false);
  1314. }
  1315. //---------------------------------------------------------------------------
  1316. void __fastcall TScript::CpProc(TScriptProcParams * Parameters)
  1317. {
  1318. DoMvOrCp(Parameters, fcRemoteCopy, true);
  1319. }
  1320. //---------------------------------------------------------------------------
  1321. void __fastcall TScript::ChModProc(TScriptProcParams * Parameters)
  1322. {
  1323. CheckSession();
  1324. if (!FTerminal->IsCapable[fcModeChanging])
  1325. {
  1326. NotSupported();
  1327. }
  1328. TStrings * FileList = CreateFileList(Parameters, 2, Parameters->ParamCount,
  1329. fltMask);
  1330. try
  1331. {
  1332. TRemoteProperties Properties;
  1333. Properties.Valid = TValidProperties() << vpRights;
  1334. Properties.Rights.Octal = Parameters->Param[1];
  1335. FTerminal->ChangeFilesProperties(FileList, &Properties);
  1336. }
  1337. __finally
  1338. {
  1339. FreeFileList(FileList);
  1340. }
  1341. }
  1342. //---------------------------------------------------------------------------
  1343. void __fastcall TScript::LnProc(TScriptProcParams * Parameters)
  1344. {
  1345. CheckSession();
  1346. if (!FTerminal->IsCapable[fcSymbolicLink])
  1347. {
  1348. NotSupported();
  1349. }
  1350. DebugAssert(Parameters->ParamCount == 2);
  1351. FTerminal->CreateLink(Parameters->Param[2], Parameters->Param[1], true);
  1352. }
  1353. //---------------------------------------------------------------------------
  1354. void __fastcall TScript::MkDirProc(TScriptProcParams * Parameters)
  1355. {
  1356. CheckSession();
  1357. TRemoteProperties Properties;
  1358. Properties.Valid = TValidProperties() << vpEncrypt;
  1359. Properties.Encrypt = FCopyParam.EncryptNewFiles;
  1360. FTerminal->CreateDirectory(Parameters->Param[1], &Properties);
  1361. }
  1362. //---------------------------------------------------------------------------
  1363. void __fastcall TScript::GetProc(TScriptProcParams * Parameters)
  1364. {
  1365. CheckSession();
  1366. ResetTransfer();
  1367. bool Latest = Parameters->FindSwitch(L"latest");
  1368. bool OnlyFile = Parameters->FindSwitch(L"onlyfile");
  1369. CheckDefaultCopyParam();
  1370. TCopyParamType CopyParam = FCopyParam;
  1371. CopyParamParams(CopyParam, Parameters);
  1372. int Params = 0;
  1373. TransferParamParams(Params, Parameters);
  1374. RequireParams(Parameters, 1);
  1375. int LastFileParam = (Parameters->ParamCount == 1 ? 1 : Parameters->ParamCount - 1);
  1376. DebugAssert(CopyParam.OnTransferOut == NULL);
  1377. if ((OnTransferOut != NULL) && (Parameters->ParamCount > 1) && SameText(Parameters->Param[Parameters->ParamCount], InOutParam))
  1378. {
  1379. CopyParam.OnTransferOut = OnTransferOut;
  1380. OnlyFile = true;
  1381. }
  1382. TStrings * FileList = CreateFileList(Parameters, 1, LastFileParam,
  1383. (TFileListType)(fltQueryServer | fltMask | FLAGMASK(Latest, fltLatest) | FLAGMASK(OnlyFile, fltOnlyFile)));
  1384. try
  1385. {
  1386. UnicodeString TargetDirectory;
  1387. if (CopyParam.OnTransferOut == NULL)
  1388. {
  1389. if (Parameters->ParamCount == 1)
  1390. {
  1391. TargetDirectory = GetCurrentDir();
  1392. CopyParam.FileMask = L"";
  1393. }
  1394. else
  1395. {
  1396. UnicodeString Target = Parameters->Param[Parameters->ParamCount];
  1397. TargetDirectory = ExtractFilePath(Target);
  1398. if (TargetDirectory.IsEmpty())
  1399. {
  1400. TargetDirectory = GetCurrentDir();
  1401. }
  1402. CopyParam.FileMask = ExtractFileName(Target);
  1403. Target = IncludeTrailingBackslash(TargetDirectory) + CopyParam.FileMask;
  1404. CheckMultiFilesToOne(FileList, Target, false);
  1405. }
  1406. }
  1407. CheckParams(Parameters);
  1408. CopyParam.IncludeFileMask.SetRoots(TargetDirectory, FileList);
  1409. FTerminal->CopyToLocal(FileList, TargetDirectory, &CopyParam, Params, NULL);
  1410. }
  1411. __finally
  1412. {
  1413. FreeFileList(FileList);
  1414. }
  1415. }
  1416. //---------------------------------------------------------------------------
  1417. void __fastcall TScript::PutProc(TScriptProcParams * Parameters)
  1418. {
  1419. CheckSession();
  1420. ResetTransfer();
  1421. bool Latest = Parameters->FindSwitch(L"latest");
  1422. CheckDefaultCopyParam();
  1423. TCopyParamType CopyParam = FCopyParam;
  1424. CopyParamParams(CopyParam, Parameters);
  1425. int Params = 0;
  1426. TransferParamParams(Params, Parameters);
  1427. RequireParams(Parameters, 1);
  1428. int LastFileParam = (Parameters->ParamCount == 1 ? 1 : Parameters->ParamCount - 1);
  1429. DebugAssert(CopyParam.OnTransferIn == NULL);
  1430. TStrings * FileList;
  1431. // We use stdin only if - is the very first parameter
  1432. if ((OnTransferIn != NULL) && SameText(Parameters->Param[1], InOutParam))
  1433. {
  1434. if (Parameters->ParamCount > 2)
  1435. {
  1436. throw Exception(LoadStr(STREAM_IN_SCRIPT_ERROR));
  1437. }
  1438. CopyParam.OnTransferIn = OnTransferIn;
  1439. FileList = new TStringList();
  1440. }
  1441. else
  1442. {
  1443. FileList = CreateLocalFileList(Parameters, 1, LastFileParam, (TFileListType)(fltMask | FLAGMASK(Latest, fltLatest)));
  1444. }
  1445. try
  1446. {
  1447. UnicodeString TargetDirectory;
  1448. if (Parameters->ParamCount == 1)
  1449. {
  1450. TargetDirectory = FTerminal->CurrentDirectory;
  1451. CopyParam.FileMask = L"";
  1452. }
  1453. else
  1454. {
  1455. UnicodeString Target = Parameters->Param[Parameters->ParamCount];
  1456. TargetDirectory = UnixExtractFilePath(Target);
  1457. if (TargetDirectory.IsEmpty())
  1458. {
  1459. TargetDirectory = FTerminal->CurrentDirectory;
  1460. }
  1461. CopyParam.FileMask = UnixExtractFileName(Target);
  1462. Target = UnixIncludeTrailingBackslash(TargetDirectory) + CopyParam.FileMask;
  1463. CheckMultiFilesToOne(FileList, Target, true);
  1464. }
  1465. if (CopyParam.OnTransferIn != NULL)
  1466. {
  1467. if (IsFileNameMask(CopyParam.FileMask))
  1468. {
  1469. throw Exception(LoadStr(STREAM_IN_SCRIPT_ERROR));
  1470. }
  1471. FileList->Add(CopyParam.FileMask);
  1472. }
  1473. CheckParams(Parameters);
  1474. CopyParam.IncludeFileMask.SetRoots(FileList, TargetDirectory);
  1475. FTerminal->CopyToRemote(FileList, TargetDirectory, &CopyParam, Params, NULL);
  1476. }
  1477. __finally
  1478. {
  1479. delete FileList;
  1480. }
  1481. }
  1482. //---------------------------------------------------------------------------
  1483. TTransferMode __fastcall TScript::ParseTransferModeName(UnicodeString Name)
  1484. {
  1485. DebugAssert((tmBinary == 0) && (tmAscii == 1) && (tmAutomatic == 2));
  1486. int Value = TScriptCommands::FindCommand(TransferModeNames,
  1487. TransferModeNamesCount, Name);
  1488. if (Value < 0)
  1489. {
  1490. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (L"transfer", Name)));
  1491. }
  1492. return (TTransferMode)Value;
  1493. }
  1494. //---------------------------------------------------------------------------
  1495. void __fastcall TScript::OptionImpl(UnicodeString OptionName, UnicodeString ValueName)
  1496. {
  1497. enum { Echo, Batch, Confirm, Transfer, SynchDelete, Exclude, Include, ReconnectTime, FailOnNoMatch };
  1498. static const wchar_t * Names[] = { L"echo", L"batch", L"confirm", L"transfer",
  1499. L"synchdelete", L"exclude", L"include", L"reconnecttime", L"failonnomatch" };
  1500. DebugAssert((BatchOff == 0) && (BatchOn == 1) && (BatchAbort == 2) && (BatchContinue == 3));
  1501. static const wchar_t * BatchModeNames[] = { L"off", L"on", L"abort", L"continue" };
  1502. int Option = -1;
  1503. if (!OptionName.IsEmpty())
  1504. {
  1505. Option = TScriptCommands::FindCommand(Names, LENOF(Names), OptionName);
  1506. if (Option < 0)
  1507. {
  1508. throw Exception(FMTLOAD(SCRIPT_OPTION_UNKNOWN, (OptionName)));
  1509. }
  1510. else
  1511. {
  1512. OptionName = Names[Option];
  1513. }
  1514. }
  1515. #define OPT(OPT) ((Option < 0) || (Option == OPT))
  1516. const wchar_t * ListFormat = L"%-15s %-10s";
  1517. bool SetValue = !ValueName.IsEmpty();
  1518. bool PrintReconnectTime = false;
  1519. if (OPT(Echo))
  1520. {
  1521. if (SetValue)
  1522. {
  1523. int Value = TScriptCommands::FindCommand(ToggleNames, LENOF(ToggleNames), ValueName);
  1524. if (Value < 0)
  1525. {
  1526. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (ValueName, OptionName)));
  1527. }
  1528. FEcho = (Value == ToggleOn);
  1529. }
  1530. PrintLine(FORMAT(ListFormat, (Names[Echo], ToggleNames[FEcho ? ToggleOn : ToggleOff])));
  1531. }
  1532. if (OPT(Batch))
  1533. {
  1534. if (SetValue)
  1535. {
  1536. int Value = TScriptCommands::FindCommand(BatchModeNames, LENOF(BatchModeNames), ValueName);
  1537. if (Value < 0)
  1538. {
  1539. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (ValueName, OptionName)));
  1540. }
  1541. FBatch = (TBatchMode)Value;
  1542. FInteractiveBatch = FBatch;
  1543. if (SetValue && (FBatch != BatchOff) && (FSessionReopenTimeout == 0))
  1544. {
  1545. FSessionReopenTimeout = BatchSessionReopenTimeout;
  1546. FInteractiveSessionReopenTimeout = FSessionReopenTimeout;
  1547. PrintReconnectTime = true;
  1548. }
  1549. }
  1550. PrintLine(FORMAT(ListFormat, (Names[Batch], BatchModeNames[FBatch])));
  1551. }
  1552. if (OPT(Confirm))
  1553. {
  1554. if (SetValue)
  1555. {
  1556. int Value = TScriptCommands::FindCommand(ToggleNames, LENOF(ToggleNames), ValueName);
  1557. if (Value < 0)
  1558. {
  1559. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (ValueName, OptionName)));
  1560. }
  1561. FConfirm = (Value == ToggleOn);
  1562. FInteractiveConfirm = FConfirm;
  1563. }
  1564. PrintLine(FORMAT(ListFormat, (Names[Confirm], ToggleNames[FConfirm ? ToggleOn : ToggleOff])));
  1565. }
  1566. // omit the option in listing
  1567. if (Option == Transfer)
  1568. {
  1569. if (SetValue)
  1570. {
  1571. FCopyParam.TransferMode = ParseTransferModeName(ValueName);
  1572. }
  1573. DebugAssert(FCopyParam.TransferMode < (TTransferMode)TransferModeNamesCount);
  1574. const wchar_t * Value = TransferModeNames[FCopyParam.TransferMode];
  1575. PrintLine(FORMAT(ListFormat, (Names[Transfer], Value)));
  1576. }
  1577. // omit the option in listing
  1578. if (Option == SynchDelete)
  1579. {
  1580. if (SetValue)
  1581. {
  1582. int Value = TScriptCommands::FindCommand(ToggleNames, LENOF(ToggleNames), ValueName);
  1583. if (Value < 0)
  1584. {
  1585. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (ValueName, OptionName)));
  1586. }
  1587. FSynchronizeParams =
  1588. (FSynchronizeParams & ~TTerminal::spDelete) |
  1589. FLAGMASK(Value == ToggleOn, TTerminal::spDelete);
  1590. }
  1591. PrintLine(FORMAT(ListFormat, (Names[SynchDelete],
  1592. ToggleNames[FLAGSET(FSynchronizeParams, TTerminal::spDelete) ? ToggleOn : ToggleOff])));
  1593. }
  1594. static const wchar_t * Clear = L"clear";
  1595. // omit the option in listing
  1596. if (Option == Include)
  1597. {
  1598. if (SetValue)
  1599. {
  1600. FCopyParam.IncludeFileMask =
  1601. (ValueName == Clear ? UnicodeString() : ValueName);
  1602. FIncludeFileMaskOptionUsed = (ValueName != Clear);
  1603. }
  1604. PrintLine(FORMAT(ListFormat, (Names[Include], FCopyParam.IncludeFileMask.Masks)));
  1605. }
  1606. // omit the option in listing
  1607. if (Option == Exclude)
  1608. {
  1609. if (SetValue)
  1610. {
  1611. // will throw if ValueName already includes IncludeExcludeFileMasksDelimiter
  1612. FCopyParam.IncludeFileMask =
  1613. (ValueName == Clear ? UnicodeString() : UnicodeString(IncludeExcludeFileMasksDelimiter) + ValueName);
  1614. FIncludeFileMaskOptionUsed = (ValueName != Clear);
  1615. }
  1616. PrintLine(FORMAT(ListFormat, (Names[Include], FCopyParam.IncludeFileMask.Masks)));
  1617. }
  1618. if (OPT(ReconnectTime) || PrintReconnectTime)
  1619. {
  1620. if (SetValue && !PrintReconnectTime)
  1621. {
  1622. int Value;
  1623. if (SameText(ValueName, ToggleNames[ToggleOff]))
  1624. {
  1625. Value = 0;
  1626. }
  1627. else
  1628. {
  1629. if (!TryStrToInt(ValueName, Value))
  1630. {
  1631. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (ValueName, OptionName)));
  1632. }
  1633. else
  1634. {
  1635. Value *= MSecsPerSec;
  1636. }
  1637. }
  1638. FSessionReopenTimeout = Value;
  1639. FInteractiveSessionReopenTimeout = FSessionReopenTimeout;
  1640. }
  1641. if (FSessionReopenTimeout == 0)
  1642. {
  1643. ValueName = ToggleNames[ToggleOff];
  1644. }
  1645. else
  1646. {
  1647. ValueName = IntToStr(FSessionReopenTimeout / MSecsPerSec);
  1648. }
  1649. PrintLine(FORMAT(ListFormat, (Names[ReconnectTime], ValueName)));
  1650. }
  1651. if (OPT(FailOnNoMatch))
  1652. {
  1653. if (SetValue)
  1654. {
  1655. int Value = TScriptCommands::FindCommand(ToggleNames, LENOF(ToggleNames), ValueName);
  1656. if (Value < 0)
  1657. {
  1658. throw Exception(FMTLOAD(SCRIPT_VALUE_UNKNOWN, (ValueName, OptionName)));
  1659. }
  1660. FFailOnNoMatch = (Value == ToggleOn);
  1661. }
  1662. PrintLine(FORMAT(ListFormat, (Names[FailOnNoMatch], ToggleNames[FFailOnNoMatch ? ToggleOn : ToggleOff])));
  1663. }
  1664. #undef OPT
  1665. }
  1666. //---------------------------------------------------------------------------
  1667. void __fastcall TScript::OptionProc(TScriptProcParams * Parameters)
  1668. {
  1669. UnicodeString OptionName;
  1670. UnicodeString ValueName;
  1671. if (Parameters->ParamCount >= 1)
  1672. {
  1673. OptionName = Parameters->Param[1];
  1674. }
  1675. if (Parameters->ParamCount >= 2)
  1676. {
  1677. ValueName = Parameters->Param[2];
  1678. }
  1679. OptionImpl(OptionName, ValueName);
  1680. }
  1681. //---------------------------------------------------------------------------
  1682. void __fastcall TScript::AsciiProc(TScriptProcParams * /*Parameters*/)
  1683. {
  1684. OptionImpl(L"transfer", L"ascii");
  1685. }
  1686. //---------------------------------------------------------------------------
  1687. void __fastcall TScript::BinaryProc(TScriptProcParams * /*Parameters*/)
  1688. {
  1689. OptionImpl(L"transfer", L"binary");
  1690. }
  1691. //---------------------------------------------------------------------------
  1692. void __fastcall TScript::SynchronizeDirectories(TScriptProcParams * Parameters,
  1693. UnicodeString & LocalDirectory, UnicodeString & RemoteDirectory, int FirstParam)
  1694. {
  1695. if (Parameters->ParamCount >= FirstParam)
  1696. {
  1697. LocalDirectory = Parameters->Param[FirstParam];
  1698. }
  1699. else
  1700. {
  1701. LocalDirectory = GetCurrentDir();
  1702. }
  1703. if (Parameters->ParamCount >= FirstParam + 1)
  1704. {
  1705. RemoteDirectory = Parameters->Param[FirstParam + 1];
  1706. }
  1707. else
  1708. {
  1709. RemoteDirectory = FTerminal->CurrentDirectory;
  1710. }
  1711. }
  1712. //---------------------------------------------------------------------------
  1713. UnicodeString __fastcall TScript::SynchronizeFileRecord(
  1714. const UnicodeString & RootDirectory, const TSynchronizeChecklist::TItem * Item, bool Local)
  1715. {
  1716. const TSynchronizeChecklist::TItem::TFileInfo & FileInfo =
  1717. Local ? Item->Local : Item->Remote;
  1718. UnicodeString Path;
  1719. if (Local)
  1720. {
  1721. Path = IncludeTrailingBackslash(FileInfo.Directory) + FileInfo.FileName;
  1722. }
  1723. else
  1724. {
  1725. Path = UnixIncludeTrailingBackslash(FileInfo.Directory) + FileInfo.FileName;
  1726. }
  1727. if (SameText(RootDirectory, Path.SubString(1, RootDirectory.Length())))
  1728. {
  1729. Path[1] = L'.';
  1730. Path.Delete(2, RootDirectory.Length() - 2);
  1731. }
  1732. UnicodeString Result;
  1733. if (Item->IsDirectory)
  1734. {
  1735. if (Local)
  1736. {
  1737. Result = IncludeTrailingBackslash(Path);
  1738. }
  1739. else
  1740. {
  1741. Result = UnixIncludeTrailingBackslash(Path);
  1742. }
  1743. }
  1744. else
  1745. {
  1746. UnicodeString SizeStr = IntToStr(FileInfo.Size);
  1747. UnicodeString ModificationStr =
  1748. ::ModificationStr(FileInfo.Modification, FileInfo.ModificationFmt);
  1749. Result = FORMAT("%s [%s, %s]", (Path, SizeStr, ModificationStr));
  1750. }
  1751. return Result;
  1752. }
  1753. //---------------------------------------------------------------------------
  1754. void __fastcall TScript::SynchronizePreview(
  1755. UnicodeString LocalDirectory, UnicodeString RemoteDirectory,
  1756. TSynchronizeChecklist * Checklist)
  1757. {
  1758. LocalDirectory = IncludeTrailingBackslash(LocalDirectory);
  1759. RemoteDirectory = UnixIncludeTrailingBackslash(RemoteDirectory);
  1760. int Index = 0;
  1761. const TSynchronizeChecklist::TItem * Item;
  1762. while (Checklist->GetNextChecked(Index, Item))
  1763. {
  1764. TDifferenceSessionAction Action(FTerminal->ActionLog, Item);
  1765. UnicodeString Message;
  1766. UnicodeString LocalRecord = SynchronizeFileRecord(LocalDirectory, Item, true);
  1767. UnicodeString RemoteRecord = SynchronizeFileRecord(RemoteDirectory, Item, false);
  1768. switch (Item->Action)
  1769. {
  1770. case TSynchronizeChecklist::saUploadNew:
  1771. Message =
  1772. FMTLOAD(SCRIPT_SYNC_UPLOAD_NEW, (LocalRecord));
  1773. break;
  1774. case TSynchronizeChecklist::saDownloadNew:
  1775. Message =
  1776. FMTLOAD(SCRIPT_SYNC_DOWNLOAD_NEW, (RemoteRecord));
  1777. break;
  1778. case TSynchronizeChecklist::saUploadUpdate:
  1779. Message =
  1780. FMTLOAD(SCRIPT_SYNC_UPLOAD_UPDATE,
  1781. (LocalRecord, RemoteRecord));
  1782. break;
  1783. case TSynchronizeChecklist::saDownloadUpdate:
  1784. Message =
  1785. FMTLOAD(SCRIPT_SYNC_DOWNLOAD_UPDATE,
  1786. (RemoteRecord, LocalRecord));
  1787. break;
  1788. case TSynchronizeChecklist::saDeleteRemote:
  1789. Message =
  1790. FMTLOAD(SCRIPT_SYNC_DELETE_REMOTE, (RemoteRecord));
  1791. break;
  1792. case TSynchronizeChecklist::saDeleteLocal:
  1793. Message =
  1794. FMTLOAD(SCRIPT_SYNC_DELETE_LOCAL, (LocalRecord));
  1795. break;
  1796. default:
  1797. DebugFail();
  1798. }
  1799. PrintLine(Message);
  1800. }
  1801. }
  1802. //---------------------------------------------------------------------------
  1803. void __fastcall TScript::SynchronizeProc(TScriptProcParams * Parameters)
  1804. {
  1805. CheckSession();
  1806. ResetTransfer();
  1807. static const wchar_t * ModeNames[] = { L"remote", L"local", L"both" };
  1808. CheckDefaultCopyParam();
  1809. TCopyParamType CopyParam = FCopyParam;
  1810. CopyParamParams(CopyParam, Parameters);
  1811. RequireParams(Parameters, 1);
  1812. if (Parameters->ParamCount > 3)
  1813. {
  1814. throw Exception(FMTLOAD(SCRIPT_TOO_MANY_PARAMS, (L"synchronize")));
  1815. }
  1816. UnicodeString ModeName = Parameters->Param[1];
  1817. DebugAssert(FSynchronizeMode < 0);
  1818. FSynchronizeMode = TScriptCommands::FindCommand(ModeNames, LENOF(ModeNames), ModeName);
  1819. try
  1820. {
  1821. if (FSynchronizeMode < 0)
  1822. {
  1823. throw Exception(FMTLOAD(SCRIPT_OPTION_UNKNOWN, (ModeName)));
  1824. }
  1825. UnicodeString LocalDirectory;
  1826. UnicodeString RemoteDirectory;
  1827. SynchronizeDirectories(Parameters, LocalDirectory, RemoteDirectory, 2);
  1828. CopyParam.IncludeFileMask.SetRoots(LocalDirectory, RemoteDirectory);
  1829. CheckDefaultSynchronizeParams();
  1830. int SynchronizeParams = FSynchronizeParams | TTerminal::spNoConfirmation;
  1831. UnicodeString Value;
  1832. if (Parameters->FindSwitch(L"delete"))
  1833. {
  1834. SynchronizeParams |= TTerminal::spDelete;
  1835. }
  1836. if (Parameters->FindSwitch(L"mirror") &&
  1837. (FSynchronizeMode != TTerminal::smBoth))
  1838. {
  1839. SynchronizeParams |= TTerminal::spMirror;
  1840. }
  1841. if (Parameters->FindSwitch(L"criteria", Value))
  1842. {
  1843. enum { None, Either, EitherBoth };
  1844. static const wchar_t * CriteriaNames[] = { L"none", L"either", L"both" };
  1845. int Criteria = TScriptCommands::FindCommand(CriteriaNames, LENOF(CriteriaNames), Value);
  1846. if (Criteria >= 0)
  1847. {
  1848. switch (Criteria)
  1849. {
  1850. case None:
  1851. SynchronizeParams |= TTerminal::spNotByTime;
  1852. SynchronizeParams &= ~TTerminal::spBySize;
  1853. break;
  1854. case Either:
  1855. case EitherBoth:
  1856. SynchronizeParams &= ~TTerminal::spNotByTime;
  1857. SynchronizeParams |= TTerminal::spBySize;
  1858. break;
  1859. }
  1860. }
  1861. else
  1862. {
  1863. int Params = TTerminal::spNotByTime;
  1864. while ((Params >= 0) && !Value.IsEmpty())
  1865. {
  1866. UnicodeString Token = CutToChar(Value, L',', true);
  1867. enum { Time, Size, Checksum };
  1868. static const wchar_t * CriteriaNames[] = { L"time", L"size", L"checksum" };
  1869. int Criteria = TScriptCommands::FindCommand(CriteriaNames, LENOF(CriteriaNames), Token);
  1870. switch (Criteria)
  1871. {
  1872. case Time:
  1873. Params &= ~TTerminal::spNotByTime;
  1874. break;
  1875. case Size:
  1876. Params |= TTerminal::spBySize;
  1877. break;
  1878. case Checksum:
  1879. Params |= TTerminal::spByChecksum;
  1880. break;
  1881. default:
  1882. Params = -1;
  1883. break;
  1884. }
  1885. }
  1886. if (Params >= 0)
  1887. {
  1888. SynchronizeParams &= ~(TTerminal::spNotByTime | TTerminal::spBySize | TTerminal::spByChecksum);
  1889. SynchronizeParams |= Params;
  1890. }
  1891. }
  1892. }
  1893. bool Preview = Parameters->FindSwitch(L"preview");
  1894. // enforce rules
  1895. if (FSynchronizeMode == TTerminal::smBoth)
  1896. {
  1897. SynchronizeParams &= ~(TTerminal::spNotByTime | TTerminal::spBySize | TTerminal::spByChecksum);
  1898. }
  1899. CheckParams(Parameters);
  1900. bool Continue = true;
  1901. if (FLAGSET(SynchronizeParams, TTerminal::spByChecksum) &&
  1902. !FTerminal->IsCapable[fcCalculatingChecksum])
  1903. {
  1904. if (!FTerminal->IsCapable[fcSecondaryShell])
  1905. {
  1906. NotSupported();
  1907. }
  1908. else
  1909. {
  1910. Continue = EnsureCommandSessionFallback(fcCalculatingChecksum, NULL);
  1911. }
  1912. }
  1913. if (Continue)
  1914. {
  1915. PrintLine(LoadStr(SCRIPT_SYNCHRONIZE_COLLECTING));
  1916. TSynchronizeChecklist * Checklist =
  1917. FTerminal->SynchronizeCollect(LocalDirectory, RemoteDirectory,
  1918. static_cast<TTerminal::TSynchronizeMode>(FSynchronizeMode),
  1919. &CopyParam, SynchronizeParams, OnTerminalSynchronizeDirectory, NULL);
  1920. try
  1921. {
  1922. int Index = 0;
  1923. const TSynchronizeChecklist::TItem * DummyItem;
  1924. if (Checklist->GetNextChecked(Index, DummyItem))
  1925. {
  1926. if (Preview)
  1927. {
  1928. PrintLine(LoadStr(SCRIPT_SYNCHRONIZE_CHECKLIST));
  1929. SynchronizePreview(LocalDirectory, RemoteDirectory, Checklist);
  1930. }
  1931. else
  1932. {
  1933. PrintLine(LoadStr(SCRIPT_SYNCHRONIZE_SYNCHRONIZING));
  1934. FTerminal->SynchronizeApply(
  1935. Checklist, &CopyParam, SynchronizeParams, OnTerminalSynchronizeDirectory, NULL, NULL, NULL, NULL);
  1936. }
  1937. }
  1938. else
  1939. {
  1940. NoMatch(LoadStr(SCRIPT_SYNCHRONIZE_NODIFFERENCE));
  1941. }
  1942. }
  1943. __finally
  1944. {
  1945. delete Checklist;
  1946. }
  1947. }
  1948. }
  1949. __finally
  1950. {
  1951. FSynchronizeMode = -1;
  1952. }
  1953. }
  1954. //---------------------------------------------------------------------------
  1955. void __fastcall TScript::Synchronize(const UnicodeString LocalDirectory,
  1956. const UnicodeString RemoteDirectory, const TCopyParamType & CopyParam,
  1957. int SynchronizeParams, TSynchronizeChecklist ** Checklist)
  1958. {
  1959. try
  1960. {
  1961. FKeepingUpToDate = true;
  1962. TSynchronizeChecklist * AChecklist =
  1963. FTerminal->SynchronizeCollect(LocalDirectory, RemoteDirectory, TTerminal::smRemote,
  1964. &CopyParam, SynchronizeParams, NULL, NULL);
  1965. try
  1966. {
  1967. if (AChecklist->Count > 0)
  1968. {
  1969. FTerminal->SynchronizeApply(
  1970. AChecklist, &CopyParam, SynchronizeParams, OnTerminalSynchronizeDirectory, NULL, NULL, NULL, NULL);
  1971. }
  1972. }
  1973. __finally
  1974. {
  1975. if (Checklist == NULL)
  1976. {
  1977. delete AChecklist;
  1978. }
  1979. else
  1980. {
  1981. *Checklist = AChecklist;
  1982. }
  1983. }
  1984. // to break line after the last transfer (if any);
  1985. Print(L"");
  1986. FKeepingUpToDate = false;
  1987. }
  1988. catch(Exception & E)
  1989. {
  1990. FKeepingUpToDate = false;
  1991. HandleExtendedException(&E);
  1992. throw;
  1993. }
  1994. }
  1995. //---------------------------------------------------------------------------
  1996. void __fastcall TScript::KeepUpToDateProc(TScriptProcParams * Parameters)
  1997. {
  1998. if (OnSynchronizeStartStop == NULL)
  1999. {
  2000. Abort();
  2001. }
  2002. CheckSession();
  2003. ResetTransfer();
  2004. CheckDefaultCopyParam();
  2005. TCopyParamType CopyParam = FCopyParam;
  2006. CopyParamParams(CopyParam, Parameters);
  2007. UnicodeString LocalDirectory;
  2008. UnicodeString RemoteDirectory;
  2009. SynchronizeDirectories(Parameters, LocalDirectory, RemoteDirectory, 1);
  2010. CheckDefaultSynchronizeParams();
  2011. int SynchronizeParams = FSynchronizeParams | TTerminal::spNoConfirmation |
  2012. TTerminal::spNoRecurse | TTerminal::spUseCache | TTerminal::spDelayProgress |
  2013. TTerminal::spSubDirs;
  2014. if (Parameters->FindSwitch(L"delete"))
  2015. {
  2016. SynchronizeParams |= TTerminal::spDelete;
  2017. }
  2018. CheckParams(Parameters);
  2019. PrintLine(LoadStr(SCRIPT_KEEPING_UP_TO_DATE));
  2020. OnSynchronizeStartStop(this, LocalDirectory, RemoteDirectory, CopyParam, SynchronizeParams);
  2021. }
  2022. //---------------------------------------------------------------------------
  2023. //---------------------------------------------------------------------------
  2024. __fastcall TManagementScript::TManagementScript(TStoredSessionList * StoredSessions,
  2025. bool LimitedOutput) :
  2026. TScript(LimitedOutput)
  2027. {
  2028. DebugAssert(StoredSessions != NULL);
  2029. FOnInput = NULL;
  2030. FOnTerminalPromptUser = NULL;
  2031. FOnShowExtendedException = NULL;
  2032. FOnTerminalQueryUser = NULL;
  2033. FStoredSessions = StoredSessions;
  2034. FTerminalList = new TTerminalList(Configuration);
  2035. FOnQueryCancel = NULL;
  2036. FContinue = true;
  2037. OnTerminalSynchronizeDirectory = TerminalSynchronizeDirectory;
  2038. FCommands->Register(EXIT_COMMAND, SCRIPT_EXIT_DESC, SCRIPT_EXIT_HELP, &ExitProc, 0, 0, false);
  2039. FCommands->Register(L"bye", 0, SCRIPT_EXIT_HELP, &ExitProc, 0, 0, false);
  2040. FCommands->Register(L"open", SCRIPT_OPEN_DESC, SCRIPT_OPEN_HELP11, &OpenProc, 0, -1, true);
  2041. FCommands->Register(L"close", SCRIPT_CLOSE_DESC, SCRIPT_CLOSE_HELP, &CloseProc, 0, 1, false);
  2042. FCommands->Register(L"session", SCRIPT_SESSION_DESC, SCRIPT_SESSION_HELP, &SessionProc, 0, 1, false);
  2043. FCommands->Register(L"lpwd", SCRIPT_LPWD_DESC, SCRIPT_LPWD_HELP, &LPwdProc, 0, 0, false);
  2044. FCommands->Register(L"lcd", SCRIPT_LCD_DESC, SCRIPT_LCD_HELP, &LCdProc, 1, 1, false);
  2045. FCommands->Register(L"lls", SCRIPT_LLS_DESC, SCRIPT_LLS_HELP2, &LLsProc, 0, 1, false);
  2046. }
  2047. //---------------------------------------------------------------------------
  2048. __fastcall TManagementScript::~TManagementScript()
  2049. {
  2050. while (FTerminalList->Count > 0)
  2051. {
  2052. FreeTerminal(FTerminalList->Terminals[0]);
  2053. }
  2054. delete FTerminalList;
  2055. }
  2056. //---------------------------------------------------------------------------
  2057. void __fastcall TManagementScript::FreeTerminal(TTerminal * ATerminal)
  2058. {
  2059. TSessionData * Data = StoredSessions->FindSame(ATerminal->SessionData);
  2060. if (Data != NULL)
  2061. {
  2062. ATerminal->SessionData->RemoteDirectory = ATerminal->CurrentDirectory;
  2063. bool Changed = false;
  2064. if (ATerminal->SessionData->UpdateDirectories)
  2065. {
  2066. Data->RemoteDirectory = ATerminal->SessionData->RemoteDirectory;
  2067. Changed = true;
  2068. }
  2069. if (Changed)
  2070. {
  2071. // only modified, implicit
  2072. StoredSessions->Save(false, false);
  2073. }
  2074. }
  2075. FTerminalList->FreeTerminal(ATerminal);
  2076. }
  2077. //---------------------------------------------------------------------------
  2078. void __fastcall TManagementScript::Input(const UnicodeString Prompt,
  2079. UnicodeString & Str, bool AllowEmpty)
  2080. {
  2081. do
  2082. {
  2083. Str = L"";
  2084. if (FOnInput != NULL)
  2085. {
  2086. FOnInput(this, Prompt, Str);
  2087. }
  2088. else
  2089. {
  2090. Abort();
  2091. }
  2092. }
  2093. while (Str.Trim().IsEmpty() && !AllowEmpty);
  2094. }
  2095. //---------------------------------------------------------------------------
  2096. void __fastcall TManagementScript::PrintProgress(bool First, const UnicodeString Str)
  2097. {
  2098. if (FOnPrintProgress != NULL)
  2099. {
  2100. FOnPrintProgress(this, First, Str);
  2101. }
  2102. }
  2103. //---------------------------------------------------------------------------
  2104. void __fastcall TManagementScript::ResetTransfer()
  2105. {
  2106. TScript::ResetTransfer();
  2107. FLastProgressFile = EmptyStr;
  2108. FLastProgressTime = 0;
  2109. FLastProgressEventTime = 0;
  2110. FLastProgressEventDoneFileName = EmptyStr;
  2111. FLastProgressOverallDone = false;
  2112. FLastProgressMessage = EmptyStr;
  2113. }
  2114. //---------------------------------------------------------------------------
  2115. bool __fastcall TManagementScript::QueryCancel()
  2116. {
  2117. bool Result = false;
  2118. if (OnQueryCancel != NULL)
  2119. {
  2120. OnQueryCancel(this, Result);
  2121. }
  2122. return Result;
  2123. }
  2124. //---------------------------------------------------------------------------
  2125. void __fastcall TManagementScript::TerminalInformation(
  2126. TTerminal * ATerminal, const UnicodeString & Str, int Phase, const UnicodeString & DebugUsedArg(Additional))
  2127. {
  2128. DebugAssert(ATerminal != NULL);
  2129. if ((Phase < 0) && ((ATerminal->Status == ssOpening) || FPrintInformation))
  2130. {
  2131. PrintLine(Str, false, ATerminal);
  2132. }
  2133. }
  2134. //---------------------------------------------------------------------------
  2135. void __fastcall TManagementScript::TerminalPromptUser(TTerminal * ATerminal,
  2136. TPromptKind Kind, UnicodeString Name, UnicodeString Instructions, TStrings * Prompts,
  2137. TStrings * Results, bool & Result, void * Arg)
  2138. {
  2139. // When authentication using stored password fails,
  2140. // do not ask user for another password.
  2141. if ((!ATerminal->StoredCredentialsTried ||
  2142. !IsAuthenticationPrompt(Kind) ||
  2143. (Prompts->Count == 0)) && // allow instructions-only prompts
  2144. (OnTerminalPromptUser != NULL))
  2145. {
  2146. OnTerminalPromptUser(ATerminal, Kind, Name, Instructions, Prompts, Results, Result, Arg);
  2147. }
  2148. }
  2149. //---------------------------------------------------------------------------
  2150. bool __fastcall TManagementScript::Synchronizing()
  2151. {
  2152. return (FKeepingUpToDate || (FSynchronizeMode >= 0));
  2153. }
  2154. //---------------------------------------------------------------------------
  2155. void __fastcall TManagementScript::ShowPendingProgress()
  2156. {
  2157. if (!FSynchronizeIntro.IsEmpty())
  2158. {
  2159. if (Synchronizing())
  2160. {
  2161. PrintLine(FSynchronizeIntro);
  2162. }
  2163. FSynchronizeIntro = L"";
  2164. }
  2165. }
  2166. //---------------------------------------------------------------------------
  2167. void __fastcall TManagementScript::TerminalOperationProgress(
  2168. TFileOperationProgressType & ProgressData)
  2169. {
  2170. if (ProgressData.IsTransfer())
  2171. {
  2172. if (ProgressData.InProgress && ProgressData.FileInProgress &&
  2173. !ProgressData.FileName.IsEmpty())
  2174. {
  2175. bool DoPrint = false;
  2176. bool First = false;
  2177. UnicodeString ProgressFileName = ProgressData.FileName;
  2178. if (ProgressData.Side == osLocal)
  2179. {
  2180. ProgressFileName = ExcludeTrailingBackslash(ProgressFileName);
  2181. }
  2182. else
  2183. {
  2184. ProgressFileName = UnixExcludeTrailingBackslash(ProgressFileName);
  2185. }
  2186. if (ProgressFileName != FLastProgressFile)
  2187. {
  2188. First = true;
  2189. DoPrint = true;
  2190. ShowPendingProgress();
  2191. }
  2192. time_t Time = time(NULL);
  2193. if ((OnProgress != NULL) && WantsProgress)
  2194. {
  2195. int OverallProgress = ProgressData.OverallProgress();
  2196. bool OverallDone = (OverallProgress == 100);
  2197. if (DoPrint ||
  2198. (FLastProgressEventTime != Time) ||
  2199. (ProgressData.IsTransferDone() && (FLastProgressEventDoneFileName != ProgressData.FullFileName)) ||
  2200. (OverallDone && !FLastProgressOverallDone))
  2201. {
  2202. FLastProgressEventTime = Time;
  2203. // When transferring a growing file, we would report the progress constantly
  2204. FLastProgressEventDoneFileName = ProgressData.IsTransferDone() ? ProgressData.FullFileName : EmptyStr;
  2205. FLastProgressOverallDone = OverallDone;
  2206. TScriptProgress Progress;
  2207. Progress.Operation = ProgressData.Operation;
  2208. Progress.Side = ProgressData.Side;
  2209. Progress.FileName = ProgressData.FullFileName;
  2210. Progress.Directory = ProgressData.Directory;
  2211. Progress.OverallProgress = OverallProgress;
  2212. Progress.FileProgress = ProgressData.TransferProgress();
  2213. Progress.CPS = ProgressData.CPS();
  2214. Progress.Cancel = false;
  2215. OnProgress(this, Progress);
  2216. if (Progress.Cancel)
  2217. {
  2218. ProgressData.SetCancel(csCancel);
  2219. }
  2220. }
  2221. }
  2222. if (!DoPrint && ((FLastProgressTime != Time) || ProgressData.IsTransferDone()))
  2223. {
  2224. DoPrint = true;
  2225. }
  2226. if (DoPrint)
  2227. {
  2228. UnicodeString FileName;
  2229. if (FLimitedOutput)
  2230. {
  2231. bool Unix = (ProgressData.Side == osRemote);
  2232. FileName = MinimizeName(ProgressFileName, Configuration->ScriptProgressFileNameLimit, Unix);
  2233. }
  2234. else
  2235. {
  2236. FileName = ProgressFileName;
  2237. }
  2238. UnicodeString TransferredSizeStr;
  2239. if (ProgressData.TransferredSize < 1024)
  2240. {
  2241. TransferredSizeStr = FORMAT("%d B", (static_cast<int>(ProgressData.TransferredSize)));
  2242. }
  2243. else
  2244. {
  2245. TransferredSizeStr = FORMAT("%d KB", (static_cast<int>(ProgressData.TransferredSize / 1024)));
  2246. }
  2247. UnicodeString ProgressMessage = FORMAT(L"%-*s | %14s | %6.1f KB/s | %-6.6s | %3d%%",
  2248. (Configuration->ScriptProgressFileNameLimit, FileName,
  2249. TransferredSizeStr,
  2250. static_cast<long double>(ProgressData.CPS()) / 1024,
  2251. ProgressData.AsciiTransfer ? L"ascii" : L"binary",
  2252. ProgressData.TransferProgress()));
  2253. if (FLastProgressMessage != ProgressMessage)
  2254. {
  2255. FLastProgressTime = Time;
  2256. PrintProgress(First, ProgressMessage);
  2257. FLastProgressMessage = ProgressMessage;
  2258. FLastProgressFile = ProgressFileName;
  2259. }
  2260. }
  2261. }
  2262. else
  2263. {
  2264. FLastProgressFile = L"";
  2265. }
  2266. }
  2267. if (QueryCancel())
  2268. {
  2269. ProgressData.SetCancel(csCancel);
  2270. }
  2271. }
  2272. //---------------------------------------------------------------------------
  2273. void __fastcall TManagementScript::TerminalOperationFinished(
  2274. TFileOperation Operation, TOperationSide /*Side*/,
  2275. bool /*Temp*/, const UnicodeString & FileName, bool Success, bool NotCancelled,
  2276. TOnceDoneOperation & /*OnceDoneOperation*/)
  2277. {
  2278. if (Success && NotCancelled &&
  2279. (Operation != foCalculateSize) && (Operation != foCalculateChecksum) &&
  2280. !TFileOperationProgressType::IsTransferOperation(Operation))
  2281. {
  2282. ShowPendingProgress();
  2283. // For FKeepingUpToDate we should send events to synchronize controller eventually.
  2284. if (Synchronizing() && (Operation == foDelete))
  2285. {
  2286. // Note that this is duplicated with "keep up to date" log.
  2287. PrintLine(FMTLOAD(SCRIPT_SYNCHRONIZE_DELETED, (FileName)));
  2288. }
  2289. else
  2290. {
  2291. PrintLine(FileName);
  2292. }
  2293. }
  2294. }
  2295. //---------------------------------------------------------------------------
  2296. void __fastcall TManagementScript::TerminalSynchronizeDirectory(
  2297. const UnicodeString & LocalDirectory, const UnicodeString & RemoteDirectory,
  2298. bool & Continue, bool Collect, const TSynchronizeOptions *)
  2299. {
  2300. int SynchronizeMode = FSynchronizeMode;
  2301. if (FKeepingUpToDate)
  2302. {
  2303. SynchronizeMode = TTerminal::smRemote;
  2304. }
  2305. UnicodeString Arrow;
  2306. switch (SynchronizeMode)
  2307. {
  2308. case TTerminal::smRemote:
  2309. Arrow = L"=>";
  2310. break;
  2311. case TTerminal::smLocal:
  2312. Arrow = L"<=";
  2313. break;
  2314. case TTerminal::smBoth:
  2315. Arrow = L"<=>";
  2316. break;
  2317. }
  2318. UnicodeString Progress = FMTLOAD(SCRIPT_SYNCHRONIZE, (ExcludeTrailingBackslash(LocalDirectory),
  2319. Arrow, UnixExcludeTrailingBackslash(RemoteDirectory)));
  2320. if (Collect)
  2321. {
  2322. PrintProgress(false, Progress);
  2323. }
  2324. else
  2325. {
  2326. FSynchronizeIntro = Progress;
  2327. }
  2328. if (QueryCancel())
  2329. {
  2330. Continue = false;
  2331. }
  2332. }
  2333. //---------------------------------------------------------------------------
  2334. void __fastcall TManagementScript::TerminalInitializeLog(TObject * Sender)
  2335. {
  2336. TTerminal * ATerminal = dynamic_cast<TTerminal *>(Sender);
  2337. if (DebugAlwaysTrue(ATerminal != NULL))
  2338. {
  2339. LogPendingLines(ATerminal);
  2340. }
  2341. }
  2342. //---------------------------------------------------------------------------
  2343. TTerminal * __fastcall TManagementScript::FindSession(const UnicodeString Index)
  2344. {
  2345. int i = StrToIntDef(Index, -1);
  2346. if ((i <= 0) || (i > FTerminalList->Count))
  2347. {
  2348. throw Exception(FMTLOAD(SCRIPT_SESSION_INDEX_INVALID, (Index)));
  2349. }
  2350. else
  2351. {
  2352. return FTerminalList->Terminals[i - 1];
  2353. }
  2354. }
  2355. //---------------------------------------------------------------------------
  2356. void __fastcall TManagementScript::PrintActiveSession()
  2357. {
  2358. DebugAssert(FTerminal != NULL);
  2359. PrintLine(FMTLOAD(SCRIPT_ACTIVE_SESSION,
  2360. (FTerminalList->IndexOf(FTerminal) + 1, FTerminal->SessionData->SessionName)));
  2361. }
  2362. //---------------------------------------------------------------------------
  2363. bool __fastcall TManagementScript::HandleExtendedException(Exception * E,
  2364. TTerminal * ATerminal)
  2365. {
  2366. bool Result = TScript::HandleExtendedException(E, ATerminal);
  2367. if (ATerminal == NULL)
  2368. {
  2369. ATerminal = FTerminal;
  2370. }
  2371. if ((ATerminal != NULL) && (ATerminal == FTerminal) && (dynamic_cast<EFatal*>(E) != NULL))
  2372. {
  2373. try
  2374. {
  2375. DoClose(ATerminal);
  2376. }
  2377. catch(...)
  2378. {
  2379. // ignore disconnect errors
  2380. }
  2381. }
  2382. return Result;
  2383. }
  2384. //---------------------------------------------------------------------------
  2385. void __fastcall TManagementScript::MaskPasswordInCommandLine(UnicodeString & Command, bool Recurse)
  2386. {
  2387. UnicodeString Url;
  2388. UnicodeString MaskedParamsPre;
  2389. UnicodeString MaskedParamsPost;
  2390. UnicodeString Param;
  2391. UnicodeString RawParam;
  2392. UnicodeString Separator;
  2393. UnicodeString Separator2;
  2394. UnicodeString OptionWithParameters;
  2395. bool AnyMaskedParam = false;
  2396. TOptions Options;
  2397. UnicodeString ACommand = Command;
  2398. bool SubCommands = false;
  2399. while (CutToken(ACommand, Param, &RawParam, &Separator2))
  2400. {
  2401. Options.Add(Param);
  2402. // "Param 1" is the "winscp.exe" or "open"
  2403. if ((Options.ParamCount == 2) && Url.IsEmpty() && !SubCommands)
  2404. {
  2405. Url = Param;
  2406. }
  2407. else
  2408. {
  2409. UnicodeString & MaskedParams = Url.IsEmpty() ? MaskedParamsPre : MaskedParamsPost;
  2410. UnicodeString Switch, Value;
  2411. wchar_t SwitchMark;
  2412. if (Options.WasSwitchAdded(Switch, Value, SwitchMark))
  2413. {
  2414. OptionWithParameters = L"";
  2415. if (TSessionData::IsSensitiveOption(Switch, Value))
  2416. {
  2417. // We should use something like TProgramParams::FormatSwitch here
  2418. RawParam = FORMAT(L"%s%s=%s", (SwitchMark, Switch, PasswordMask));
  2419. AnyMaskedParam = true;
  2420. }
  2421. else if (TSessionData::IsOptionWithParameters(Switch))
  2422. {
  2423. OptionWithParameters = Switch;
  2424. }
  2425. SubCommands = SameText(Switch, COMMAND_SWITCH);
  2426. }
  2427. else
  2428. {
  2429. if (!OptionWithParameters.IsEmpty())
  2430. {
  2431. if (TSessionData::MaskPasswordInOptionParameter(OptionWithParameters, Param))
  2432. {
  2433. RawParam = Param;
  2434. AnyMaskedParam = true;
  2435. }
  2436. }
  2437. if (Recurse && SubCommands)
  2438. {
  2439. UnicodeString Cmd2 = Param;
  2440. UnicodeString Command2;
  2441. if (CutToken(Cmd2, Command2))
  2442. {
  2443. UnicodeString MaskedParam = MaskPasswordInCommand(Param, Command2);
  2444. if (MaskedParam != Param)
  2445. {
  2446. RawParam = AddQuotes(EscapeParam(MaskedParam));
  2447. AnyMaskedParam = true;
  2448. }
  2449. }
  2450. }
  2451. }
  2452. // Separator is empty on the first loop, but so is the MaskedParams
  2453. AddToList(MaskedParams, RawParam, Separator);
  2454. }
  2455. Separator = Separator2;
  2456. }
  2457. if (!Url.IsEmpty() || AnyMaskedParam)
  2458. {
  2459. UnicodeString MaskedUrl;
  2460. if (!Url.IsEmpty())
  2461. {
  2462. bool DefaultsOnly;
  2463. std::unique_ptr<TSessionData> Data(
  2464. StoredSessions->ParseUrl(Url, &Options, DefaultsOnly, NULL, NULL, &MaskedUrl));
  2465. }
  2466. if ((Url != MaskedUrl) || AnyMaskedParam)
  2467. {
  2468. Command = MaskedParamsPre;
  2469. // AddToList is noop, when respective component is empty
  2470. AddToList(Command, AddQuotes(MaskedUrl), L" ");
  2471. AddToList(Command, MaskedParamsPost, L" ");
  2472. }
  2473. }
  2474. }
  2475. //---------------------------------------------------------------------------
  2476. UnicodeString __fastcall TManagementScript::MaskPasswordInCommand(const UnicodeString & FullCommand,
  2477. const UnicodeString & Command)
  2478. {
  2479. UnicodeString Result = FullCommand;
  2480. if (SameText(FCommands->ResolveCommand(Command), L"open") &&
  2481. !Configuration->LogSensitive)
  2482. {
  2483. MaskPasswordInCommandLine(Result, false);
  2484. }
  2485. return Result;
  2486. }
  2487. //---------------------------------------------------------------------------
  2488. UnicodeString __fastcall TManagementScript::GetLogCmd(const UnicodeString & FullCommand,
  2489. const UnicodeString & Command, const UnicodeString & Params)
  2490. {
  2491. UnicodeString Result = MaskPasswordInCommand(FullCommand, Command);
  2492. return TScript::GetLogCmd(Result, Command, Params);
  2493. }
  2494. //---------------------------------------------------------------------------
  2495. void __fastcall TManagementScript::Connect(const UnicodeString Session,
  2496. TOptions * Options, bool CheckParams)
  2497. {
  2498. try
  2499. {
  2500. bool DefaultsOnly;
  2501. TSessionData * Data;
  2502. if (Options->FindSwitch(L"filezilla"))
  2503. {
  2504. UnicodeString Error;
  2505. std::unique_ptr<TStoredSessionList> FilezillaSessionList(
  2506. Configuration->SelectFilezillaSessionsForImport(StoredSessions, Error));
  2507. if (!Error.IsEmpty())
  2508. {
  2509. throw Exception(Error);
  2510. }
  2511. Data = dynamic_cast<TSessionData *>(FilezillaSessionList->FindByName(Session));
  2512. if (Data == NULL)
  2513. {
  2514. throw Exception(FMTLOAD(FILEZILLA_SITE_NOT_EXIST, (Session)));
  2515. }
  2516. else
  2517. {
  2518. Data = Data->Clone();
  2519. }
  2520. DefaultsOnly = false;
  2521. }
  2522. else
  2523. {
  2524. if (FStoredSessions->IsFolder(Session) ||
  2525. FStoredSessions->IsWorkspace(Session))
  2526. {
  2527. throw Exception(LoadStr(CANNOT_OPEN_SESSION_FOLDER));
  2528. }
  2529. Data = FStoredSessions->ParseUrl(Session, Options, DefaultsOnly);
  2530. }
  2531. try
  2532. {
  2533. if (CheckParams)
  2534. {
  2535. if (Options->ParamCount > 1)
  2536. {
  2537. throw Exception(FMTLOAD(SCRIPT_TOO_MANY_PARAMS, (L"open")));
  2538. }
  2539. TScriptCommands::CheckParams(Options, false);
  2540. }
  2541. if (!Session.IsEmpty() && (Data->Source != ::ssNone) && (Batch != TScript::BatchOff) && UsageWarnings)
  2542. {
  2543. std::unique_ptr<TSessionData> DataWithFingerprint(Data->Clone());
  2544. DataWithFingerprint->LookupLastFingerprint();
  2545. DataWithFingerprint->MaskPasswords();
  2546. PrintLine(LoadStr(SCRIPT_SITE_WARNING));
  2547. PrintLine(L"open " + DataWithFingerprint->GenerateOpenCommandArgs(false));
  2548. }
  2549. DebugAssert(Data != NULL);
  2550. if (!Data->CanLogin || DefaultsOnly)
  2551. {
  2552. if (Data->HostName.IsEmpty())
  2553. {
  2554. UnicodeString Value;
  2555. Input(LoadStr(SCRIPT_HOST_PROMPT), Value, false);
  2556. Data->HostName = Value;
  2557. }
  2558. DebugAssert(Data->CanLogin);
  2559. }
  2560. bool WasLogActions = Configuration->LogActions;
  2561. TTerminal * ATerminal = FTerminalList->NewTerminal(Data);
  2562. DebugAssert(FLoggingTerminal == NULL);
  2563. FLoggingTerminal = ATerminal;
  2564. try
  2565. {
  2566. try
  2567. {
  2568. ATerminal->AutoReadDirectory = false;
  2569. ATerminal->OnInformation = TerminalInformation;
  2570. ATerminal->OnPromptUser = TerminalPromptUser;
  2571. ATerminal->OnShowExtendedException = OnShowExtendedException;
  2572. ATerminal->OnQueryUser = OnTerminalQueryUser;
  2573. ATerminal->OnProgress = TerminalOperationProgress;
  2574. ATerminal->OnFinished = TerminalOperationFinished;
  2575. ATerminal->OnInitializeLog = TerminalInitializeLog;
  2576. ConnectTerminal(ATerminal);
  2577. }
  2578. catch(Exception & E)
  2579. {
  2580. // fatal error, most probably caused by XML logging failure (as it has been turned off),
  2581. // and XML log is required => abort
  2582. if ((dynamic_cast<EFatal *>(&E) != NULL) &&
  2583. WasLogActions && !Configuration->LogActions &&
  2584. Configuration->LogActionsRequired)
  2585. {
  2586. FContinue = false;
  2587. }
  2588. // make sure errors (mainly fatal ones) are associated
  2589. // with this terminal, not the last active one
  2590. bool Handled = HandleExtendedException(&E, ATerminal);
  2591. FTerminalList->FreeTerminal(ATerminal);
  2592. ATerminal = NULL;
  2593. if (!Handled)
  2594. {
  2595. throw;
  2596. }
  2597. }
  2598. }
  2599. __finally
  2600. {
  2601. FLoggingTerminal = NULL;
  2602. }
  2603. if (ATerminal != NULL)
  2604. {
  2605. FTerminal = ATerminal;
  2606. if (!Data->LocalDirectory.IsEmpty())
  2607. {
  2608. try
  2609. {
  2610. DoChangeLocalDirectory(Data->LocalDirectoryExpanded);
  2611. }
  2612. catch(Exception & E)
  2613. {
  2614. if (!HandleExtendedException(&E))
  2615. {
  2616. throw;
  2617. }
  2618. }
  2619. }
  2620. PrintActiveSession();
  2621. }
  2622. }
  2623. __finally
  2624. {
  2625. delete Data;
  2626. }
  2627. }
  2628. catch(Exception & E)
  2629. {
  2630. if (!HandleExtendedException(&E))
  2631. {
  2632. throw;
  2633. }
  2634. }
  2635. }
  2636. //---------------------------------------------------------------------------
  2637. void __fastcall TManagementScript::DoClose(TTerminal * ATerminal)
  2638. {
  2639. int Index = FTerminalList->IndexOf(ATerminal);
  2640. DebugAssert(Index >= 0);
  2641. bool WasActiveTerminal = (FTerminal == ATerminal);
  2642. try
  2643. {
  2644. if (ATerminal->Active)
  2645. {
  2646. ATerminal->Close();
  2647. }
  2648. UnicodeString SessionName = ATerminal->SessionData->SessionName;
  2649. FreeTerminal(ATerminal);
  2650. if (WasActiveTerminal)
  2651. {
  2652. FTerminal = NULL;
  2653. }
  2654. PrintLine(FMTLOAD(SCRIPT_SESSION_CLOSED, (SessionName)));
  2655. }
  2656. __finally
  2657. {
  2658. if (WasActiveTerminal)
  2659. {
  2660. if (FTerminalList->Count > 0)
  2661. {
  2662. if (Index < FTerminalList->Count)
  2663. {
  2664. FTerminal = FTerminalList->Terminals[Index];
  2665. }
  2666. else
  2667. {
  2668. FTerminal = FTerminalList->Terminals[0];
  2669. }
  2670. PrintActiveSession();
  2671. }
  2672. else
  2673. {
  2674. PrintLine(LoadStr(SCRIPT_NO_SESSION));
  2675. }
  2676. }
  2677. }
  2678. }
  2679. //---------------------------------------------------------------------------
  2680. void __fastcall TManagementScript::DoChangeLocalDirectory(UnicodeString Directory)
  2681. {
  2682. if (!SetCurrentDir(ApiPath(Directory)))
  2683. {
  2684. throw EOSExtException(FMTLOAD(CHANGE_DIR_ERROR, (Directory)));
  2685. }
  2686. }
  2687. //---------------------------------------------------------------------------
  2688. void __fastcall TManagementScript::ExitProc(TScriptProcParams * /*Parameters*/)
  2689. {
  2690. FContinue = false;
  2691. }
  2692. //---------------------------------------------------------------------------
  2693. void __fastcall TManagementScript::OpenProc(TScriptProcParams * Parameters)
  2694. {
  2695. Connect(Parameters->ParamCount > 0 ? Parameters->Param[1] : UnicodeString(),
  2696. Parameters, true);
  2697. }
  2698. //---------------------------------------------------------------------------
  2699. void __fastcall TManagementScript::CloseProc(TScriptProcParams * Parameters)
  2700. {
  2701. CheckSession();
  2702. TTerminal * ATerminal;
  2703. if (Parameters->ParamCount == 0)
  2704. {
  2705. ATerminal = FTerminal;
  2706. }
  2707. else
  2708. {
  2709. ATerminal = FindSession(Parameters->Param[1]);
  2710. }
  2711. DoClose(ATerminal);
  2712. }
  2713. //---------------------------------------------------------------------------
  2714. void __fastcall TManagementScript::SessionProc(TScriptProcParams * Parameters)
  2715. {
  2716. CheckSession();
  2717. if (Parameters->ParamCount == 0)
  2718. {
  2719. for (int i = 0; i < FTerminalList->Count; i++)
  2720. {
  2721. PrintLine(FORMAT(L"%3d %s",
  2722. (i + 1, FTerminalList->Terminals[i]->SessionData->SessionName)));
  2723. }
  2724. PrintActiveSession();
  2725. }
  2726. else
  2727. {
  2728. FTerminal = FindSession(Parameters->Param[1]);
  2729. PrintActiveSession();
  2730. }
  2731. }
  2732. //---------------------------------------------------------------------------
  2733. void __fastcall TManagementScript::LPwdProc(TScriptProcParams * /*Parameters*/)
  2734. {
  2735. PrintLine(GetCurrentDir());
  2736. }
  2737. //---------------------------------------------------------------------------
  2738. void __fastcall TManagementScript::LCdProc(TScriptProcParams * Parameters)
  2739. {
  2740. DebugAssert(Parameters->ParamCount == 1);
  2741. DoChangeLocalDirectory(Parameters->Param[1]);
  2742. PrintLine(GetCurrentDir());
  2743. }
  2744. //---------------------------------------------------------------------------
  2745. void __fastcall TManagementScript::LLsProc(TScriptProcParams * Parameters)
  2746. {
  2747. UnicodeString Directory;
  2748. UnicodeString Mask;
  2749. if (Parameters->ParamCount > 0)
  2750. {
  2751. Directory = Parameters->Param[1];
  2752. Mask = ExtractFileName(Directory);
  2753. if (TFileMasks::IsMask(Mask))
  2754. {
  2755. Directory = ExtractFilePath(Directory);
  2756. }
  2757. else
  2758. {
  2759. Mask = L"";
  2760. }
  2761. }
  2762. if (Directory.IsEmpty())
  2763. {
  2764. Directory = GetCurrentDir();
  2765. }
  2766. if (Mask.IsEmpty())
  2767. {
  2768. Mask = L"*.*";
  2769. }
  2770. TSearchRecOwned SearchRec;
  2771. int FindAttrs = faReadOnly | faHidden | faSysFile | faDirectory | faArchive;
  2772. if (FindFirstUnchecked(IncludeTrailingBackslash(Directory) + Mask, FindAttrs, SearchRec) != 0)
  2773. {
  2774. NoMatch(Mask, ListingSysErrorMessage());
  2775. }
  2776. else
  2777. {
  2778. UnicodeString TimeFormat = FixedLenDateTimeFormat(FormatSettings.ShortTimeFormat);
  2779. UnicodeString DateFormat = FixedLenDateTimeFormat(FormatSettings.ShortDateFormat);
  2780. int DateLen = 0;
  2781. int TimeLen = 0;
  2782. bool First = true;
  2783. do
  2784. {
  2785. if (SearchRec.Name != L".")
  2786. {
  2787. TDateTime DateTime = SearchRec.GetLastWriteTime();
  2788. UnicodeString TimeStr = FormatDateTime(TimeFormat, DateTime);
  2789. UnicodeString DateStr = FormatDateTime(DateFormat, DateTime);
  2790. if (First)
  2791. {
  2792. if (TimeLen < TimeStr.Length())
  2793. {
  2794. TimeLen = TimeStr.Length();
  2795. }
  2796. if (DateLen < DateStr.Length())
  2797. {
  2798. DateLen = DateStr.Length();
  2799. }
  2800. First = false;
  2801. }
  2802. UnicodeString SizeStr;
  2803. if (SearchRec.IsDirectory())
  2804. {
  2805. SizeStr = L"<DIR>";
  2806. }
  2807. else
  2808. {
  2809. SizeStr = FORMAT(L"%14.0n", (static_cast<long double>(SearchRec.Size)));
  2810. }
  2811. PrintLine(FORMAT(L"%-*s %-*s %-14s %s", (
  2812. DateLen, DateStr, TimeLen, TimeStr, SizeStr, SearchRec.Name)));
  2813. }
  2814. }
  2815. while (FindNextChecked(SearchRec) == 0);
  2816. }
  2817. }
  2818. //---------------------------------------------------------------------------
  2819. void __fastcall TManagementScript::ReflectSettings()
  2820. {
  2821. for (int i = 0; i < FTerminalList->Count; i++)
  2822. {
  2823. FTerminalList->Terminals[i]->ReflectSettings();
  2824. }
  2825. }
  2826. //---------------------------------------------------------------------------