Browse Source

Finishing code generation for file transfers + Limiting generated code to 3 files + Not escaping local paths in generated script + Correcting all-files transfer script

Source commit: 786b4d04f633b16a544ebc9da06a89d4e24b1b47
Martin Prikryl 9 years ago
parent
commit
2830b1e889

+ 46 - 11
source/core/Common.cpp

@@ -2930,6 +2930,7 @@ bool __fastcall IsHttpUrl(const UnicodeString & S)
 const UnicodeString RtfPara = L"\\par\n";
 const UnicodeString AssemblyNamespace = L"WinSCP";
 const UnicodeString TransferOptionsClassName(L"TransferOptions");
+const UnicodeString SessionClassName(L"Session");
 const UnicodeString RtfHyperlinkField = L"HYPERLINK";
 const UnicodeString RtfHyperlinkFieldPrefix = RtfHyperlinkField + L" \"";
 const UnicodeString RtfHyperlinkFieldSuffix = L"\" ";
@@ -3155,14 +3156,41 @@ UnicodeString __fastcall RtfLibraryClass(const UnicodeString & ClassName)
   return RtfLink(L"library_" + ClassName.LowerCase(), RtfClass(ClassName));
 }
 //---------------------------------------------------------------------
+UnicodeString __fastcall RtfLibraryMethod(const UnicodeString & ClassName, const UnicodeString & MethodName, bool InPage)
+{
+  return RtfLink(L"library_" + ClassName.LowerCase() + (InPage ? L"#" : L"_") + MethodName.LowerCase(), RtfOverrideColorText(MethodName));
+}
+//---------------------------------------------------------------------
 static UnicodeString __fastcall RtfLibraryProperty(const UnicodeString & ClassName, const UnicodeString & PropertyName)
 {
   return RtfLink(L"library_" + ClassName.LowerCase() + L"#" + PropertyName.LowerCase(), RtfOverrideColorText(PropertyName));
 }
 //---------------------------------------------------------------------
-UnicodeString AssemblyVariableName(const UnicodeString & ClassName)
+UnicodeString __fastcall AssemblyVariableName(TAssemblyLanguage Language, const UnicodeString & ClassName)
 {
-  return ClassName.SubString(1, 1).LowerCase() + ClassName.SubString(2, ClassName.Length() - 1);
+  UnicodeString Result = ClassName.SubString(1, 1).LowerCase() + ClassName.SubString(2, ClassName.Length() - 1);
+  if (Language == alPowerShell)
+  {
+    Result = L"$" + Result;
+  }
+  return Result;
+}
+//---------------------------------------------------------------------
+UnicodeString __fastcall AssemblyStatementSeparator(TAssemblyLanguage Language)
+{
+  UnicodeString Result;
+  switch (Language)
+  {
+    case alCSharp:
+      Result = L";";
+      break;
+
+    case alVBNET:
+    case alPowerShell:
+      // noop
+      break;
+  }
+  return Result;
 }
 //---------------------------------------------------------------------
 UnicodeString __fastcall AssemblyPropertyRaw(
@@ -3225,32 +3253,39 @@ UnicodeString __fastcall AssemblyProperty(
   return AssemblyPropertyRaw(Language, ClassName, Name, IntToStr(Value), Inline);
 }
 //---------------------------------------------------------------------
-UnicodeString __fastcall AssemblyProperty(
-  TAssemblyLanguage Language, const UnicodeString & ClassName, const UnicodeString & Name, bool Value, bool Inline)
+UnicodeString __fastcall AssemblyBoolean(TAssemblyLanguage Language, bool Value)
 {
-  UnicodeString PropertyValue;
+  UnicodeString Result;
 
   switch (Language)
   {
     case alCSharp:
-      PropertyValue = (Value ? L"true" : L"false");
+      Result = (Value ? L"true" : L"false");
       break;
 
     case alVBNET:
-      PropertyValue = (Value ? L"True" : L"False");
+      Result = (Value ? L"True" : L"False");
       break;
 
     case alPowerShell:
-      PropertyValue = (Value ? L"$True" : L"$False");
+      Result = (Value ? L"$True" : L"$False");
       break;
   }
 
+  return Result;
+}
+//---------------------------------------------------------------------
+UnicodeString __fastcall AssemblyProperty(
+  TAssemblyLanguage Language, const UnicodeString & ClassName, const UnicodeString & Name, bool Value, bool Inline)
+{
+  UnicodeString PropertyValue = AssemblyBoolean(Language, Value);
+
   return AssemblyPropertyRaw(Language, ClassName, Name, PropertyValue, Inline);
 }
 //---------------------------------------------------------------------
 UnicodeString __fastcall AssemblyNewClassInstance(TAssemblyLanguage Language, const UnicodeString & ClassName, bool Inline)
 {
-  UnicodeString VariableName = AssemblyVariableName(ClassName);
+  UnicodeString VariableName = AssemblyVariableName(Language, ClassName);
   UnicodeString RtfClass = RtfLibraryClass(ClassName);
 
   UnicodeString Result;
@@ -3275,7 +3310,7 @@ UnicodeString __fastcall AssemblyNewClassInstance(TAssemblyLanguage Language, co
     case alPowerShell:
       if (!Inline)
       {
-        Result += RtfText(L"$" + VariableName + L" = ");
+        Result += RtfText(VariableName + L" = ");
       }
       Result += RtfKeyword(L"New-Object") + RtfText(L" " + AssemblyNamespace + L".") + RtfClass;
       break;
@@ -3313,7 +3348,7 @@ UnicodeString __fastcall AssemblyNewClassInstanceStart(
       }
       else
       {
-        Result += RtfText(L" " + AssemblyVariableName(ClassName)) + RtfPara;
+        Result += RtfText(L" " + AssemblyVariableName(Language, ClassName)) + RtfPara;
       }
       break;
 

+ 5 - 1
source/core/Common.h

@@ -205,6 +205,7 @@ MethodT __fastcall MakeMethod(void * Data, void * Code)
 enum TAssemblyLanguage { alCSharp, alVBNET, alPowerShell };
 extern const UnicodeString RtfPara;
 extern const UnicodeString AssemblyNamespace;
+extern const UnicodeString SessionClassName;
 extern const UnicodeString TransferOptionsClassName;
 //---------------------------------------------------------------------
 UnicodeString __fastcall RtfText(const UnicodeString & Text);
@@ -223,6 +224,7 @@ UnicodeString __fastcall RtfSwitch(const UnicodeString & Name, const UnicodeStri
 UnicodeString __fastcall RtfEscapeParam(UnicodeString Param);
 UnicodeString __fastcall RtfRemoveHyperlinks(UnicodeString Text);
 UnicodeString __fastcall ScriptCommandLink(const UnicodeString & Command);
+UnicodeString __fastcall AssemblyBoolean(TAssemblyLanguage Language, bool Value);
 UnicodeString __fastcall AssemblyString(TAssemblyLanguage Language, UnicodeString S);
 UnicodeString __fastcall AssemblyCommentLine(TAssemblyLanguage Language, const UnicodeString & Text);
 UnicodeString __fastcall AssemblyPropertyRaw(
@@ -238,8 +240,10 @@ UnicodeString __fastcall AssemblyProperty(
   TAssemblyLanguage Language, const UnicodeString & ClassName, const UnicodeString & Name, int Value, bool Inline);
 UnicodeString __fastcall AssemblyProperty(
   TAssemblyLanguage Language, const UnicodeString & ClassName, const UnicodeString & Name, bool Value, bool Inline);
+UnicodeString __fastcall RtfLibraryMethod(const UnicodeString & ClassName, const UnicodeString & MethodName, bool Inpage);
 UnicodeString __fastcall RtfLibraryClass(const UnicodeString & ClassName);
-UnicodeString AssemblyVariableName(const UnicodeString & ClassName);
+UnicodeString __fastcall AssemblyVariableName(TAssemblyLanguage Language, const UnicodeString & ClassName);
+UnicodeString __fastcall AssemblyStatementSeparator(TAssemblyLanguage Language);
 UnicodeString __fastcall AssemblyNewClassInstance(
   TAssemblyLanguage Language, const UnicodeString & ClassName, bool Inline);
 UnicodeString __fastcall AssemblyNewClassInstanceStart(

+ 15 - 19
source/core/SessionData.cpp

@@ -2559,11 +2559,6 @@ void __fastcall TSessionData::LookupLastFingerprint()
   }
 }
 //---------------------------------------------------------------------
-static UnicodeString __fastcall RtfLibraryMethod(const UnicodeString & ClassName, const UnicodeString & MethodName)
-{
-  return RtfLink(L"library_" + ClassName.LowerCase() + L"_" + MethodName.LowerCase(), RtfOverrideColorText(MethodName));
-}
-//---------------------------------------------------------------------
 UnicodeString __fastcall TSessionData::GenerateOpenCommandArgs()
 {
   std::unique_ptr<TSessionData> FactoryDefaults(new TSessionData(L""));
@@ -2642,7 +2637,6 @@ UnicodeString __fastcall TSessionData::GenerateOpenCommandArgs()
 }
 //---------------------------------------------------------------------
 UnicodeString SessionOptionsClassName(L"SessionOptions");
-UnicodeString SessionClassName(L"Session");
 //---------------------------------------------------------------------
 void __fastcall TSessionData::AddAssemblyProperty(
   UnicodeString & Result, TAssemblyLanguage Language,
@@ -2848,7 +2842,7 @@ void __fastcall TSessionData::GenerateAssemblyCode(
 
   std::unique_ptr<TStrings> RawSettings(SessionData->SaveToOptions(FactoryDefaults.get()));
 
-  UnicodeString SessionOptionsVariableName = AssemblyVariableName(SessionOptionsClassName);
+  UnicodeString SessionOptionsVariableName = AssemblyVariableName(Language, SessionOptionsClassName);
 
   if (RawSettings->Count > 0)
   {
@@ -2859,7 +2853,7 @@ void __fastcall TSessionData::GenerateAssemblyCode(
       UnicodeString Name = RawSettings->Names[Index];
       UnicodeString Value = RawSettings->ValueFromIndex[Index];
       UnicodeString AddRawSettingsMethod =
-        RtfLibraryMethod(SessionOptionsClassName, L"AddRawSettings") +
+        RtfLibraryMethod(SessionOptionsClassName, L"AddRawSettings", false) +
         FORMAT(L"(%s, %s)", (AssemblyString(Language, Name), AssemblyString(Language, Value)));
       switch (Language)
       {
@@ -2872,18 +2866,22 @@ void __fastcall TSessionData::GenerateAssemblyCode(
           break;
 
         case alPowerShell:
-          Head += RtfText(L"$" + SessionOptionsVariableName + L".") + AddRawSettingsMethod + RtfPara;
+          Head += RtfText(SessionOptionsVariableName + L".") + AddRawSettingsMethod + RtfPara;
           break;
       }
     }
   }
 
-  UnicodeString CodeCommentLine = L"    " + AssemblyCommentLine(Language, LoadStr(CODE_CONNECT));
-  UnicodeString SessionVariableName = AssemblyVariableName(SessionClassName);
+  UnicodeString Indentation = L"    ";
+  UnicodeString SessionVariableName = AssemblyVariableName(Language, SessionClassName);
   UnicodeString RtfSessionClass = RtfLibraryClass(SessionClassName);
-  UnicodeString RtfSessionOpenMethod = RtfLibraryMethod(SessionClassName, L"Open");
+  UnicodeString RtfSessionOpenMethod = RtfLibraryMethod(SessionClassName, L"Open", false);
 
   UnicodeString NewSessionInstance = AssemblyNewClassInstance(Language, SessionClassName, false);
+  UnicodeString OpenCall =
+    Indentation + AssemblyCommentLine(Language, LoadStr(CODE_CONNECT)) +
+    Indentation + RtfText(SessionVariableName + L".") + RtfSessionOpenMethod + RtfText(L"(" + SessionOptionsVariableName + L")") +
+      AssemblyStatementSeparator(Language) + RtfPara;
 
   switch (Language)
   {
@@ -2892,8 +2890,7 @@ void __fastcall TSessionData::GenerateAssemblyCode(
         RtfPara +
         RtfKeyword(L"using") + RtfText(" (") + NewSessionInstance + RtfText(L"())") + RtfPara +
         RtfText(L"{") + RtfPara +
-        CodeCommentLine +
-        RtfText(L"    " + SessionVariableName + L".") + RtfSessionOpenMethod + RtfText(L"(" + SessionOptionsVariableName + L");") + RtfPara;
+        OpenCall;
 
       Tail =
         RtfText(L"}") + RtfPara;
@@ -2904,8 +2901,7 @@ void __fastcall TSessionData::GenerateAssemblyCode(
         AssemblyNewClassInstanceEnd(Language, false) +
         RtfPara +
         RtfKeyword(L"Using") + RtfText(L" ") + NewSessionInstance + RtfPara +
-        CodeCommentLine +
-        RtfText(L"    " + SessionVariableName + L".") + RtfSessionOpenMethod + RtfText(L"(" + SessionOptionsVariableName + L")") + RtfPara;
+        OpenCall;
 
       Tail =
         RtfKeyword(L"End Using");
@@ -2918,14 +2914,14 @@ void __fastcall TSessionData::GenerateAssemblyCode(
         RtfPara +
         RtfKeyword(L"try") + RtfPara +
         RtfText(L"{") + RtfPara +
-        CodeCommentLine +
-        RtfText(L"    $" + SessionVariableName + L".") + RtfSessionOpenMethod + RtfText(L"($" + SessionOptionsVariableName + L")") + RtfPara;
+        OpenCall;
 
       Tail =
         RtfText(L"}") + RtfPara +
         RtfKeyword(L"finally") + RtfPara +
         RtfText(L"{") + RtfPara +
-        RtfText(L"    $" + SessionVariableName + L".") + RtfLibraryMethod(SessionClassName, L"Dispose") + RtfText(L"()") + RtfPara +
+        RtfText(Indentation + SessionVariableName + L".") +
+          RtfLibraryMethod(SessionClassName, L"Dispose", false) + RtfText(L"()") + RtfPara +
         RtfText(L"}") + RtfPara;
       break;
   }

+ 132 - 5
source/forms/GenerateUrl.cpp

@@ -17,6 +17,9 @@
 #pragma resource "*.dfm"
 #endif
 //---------------------------------------------------------------------------
+const UnicodeString AllFilesMask(L"*");
+const UnicodeString NoOpOperationMask(L"*");
+//---------------------------------------------------------------------------
 void __fastcall DoGenerateUrlDialog(TSessionData * Data, TStrings * Paths)
 {
   std::unique_ptr<TGenerateUrlDialog> Dialog(
@@ -145,11 +148,23 @@ __fastcall TGenerateUrlDialog::TGenerateUrlDialog(
   FMove = Move;
   FCopyParamAttrs = CopyParamAttrs;
   FCopyParam = CopyParam;
+  FFilesSelected = FilesSelected;
+  FPathsSample = false;
 
   if (FTransfer)
   {
     DebugAssert(FPaths.get() != NULL);
 
+    const int MaxSample = 3;
+    if ((FFilesSelected == fsList) && (FPaths->Count > MaxSample))
+    {
+      FPathsSample = true;
+      while (FPaths->Count > MaxSample)
+      {
+        FPaths->Delete(FPaths->Count - 1);
+      }
+    }
+
     if (FToRemote)
     {
       UnicodeString FirstPath = Paths->Strings[0];
@@ -171,7 +186,6 @@ __fastcall TGenerateUrlDialog::TGenerateUrlDialog(
   }
 
   FPath = Path;
-  FFilesSelected = FilesSelected;
   FChanging = false;
 
   FResultMemo41 = new TRichEdit41(this);
@@ -337,18 +351,25 @@ UnicodeString __fastcall TGenerateUrlDialog::GenerateScript(UnicodeString & Scri
       ScriptDescription += LoadStr(GENERATE_URL_COPY_PARAM_SCRIPT_REMAINING) + L"\n";
     }
 
+    AddSampleDescription(ScriptDescription);
+
     TransferCommand = RtfScriptCommand(TransferCommand) + TransferCommandArgs;
 
     if (FFilesSelected == fsList)
     {
       for (int Index = 0; Index < FPaths->Count; Index++)
       {
-        Commands.push_back(TransferCommand + L" " + RtfText(QuoteStringParam(EscapeFileMask(FPaths->Strings[Index]))));
+        UnicodeString Path = ExtractFileName(FPaths->Strings[Index], !FToRemote);
+        if (!FToRemote)
+        {
+          Path = EscapeFileMask(Path);
+        }
+        Commands.push_back(TransferCommand + L" " + RtfText(QuoteStringParam(Path)));
       }
     }
     else
     {
-      Commands.push_back(TransferCommand + L" " + RtfText(QuoteStringParam(FSourcePath + L"*")));
+      Commands.push_back(TransferCommand + L" " + RtfText(AllFilesMask));
     }
   }
   else
@@ -486,12 +507,118 @@ UnicodeString __fastcall TGenerateUrlDialog::GenerateAssemblyCode(UnicodeString
       AssemblyDescription += LoadStr(GENERATE_URL_COPY_PARAM_CODE_REMAINING) + L"\n";
     }
 
-    if (!CopyParamProperties.IsEmpty())
+    bool HasTransferOptions = !CopyParamProperties.IsEmpty();
+    if (HasTransferOptions)
     {
       Code +=
+        AssemblyCommentLine(Language, LoadStr(GENERATE_URL_COPY_PARAM)) +
         AssemblyNewClassInstanceStart(Language, TransferOptionsClassName, false) +
         CopyParamProperties +
-        AssemblyNewClassInstanceEnd(Language, false);
+        AssemblyNewClassInstanceEnd(Language, false) +
+        RtfPara;
+    }
+
+    Code += AssemblyCommentLine(Language, LoadStr(GENERATE_URL_TRANSFER_FILES));
+
+    AddSampleDescription(AssemblyDescription);
+
+    UnicodeString DestPath = FPath;
+    UnicodeString TransferMethodName;
+    if (FToRemote)
+    {
+      TransferMethodName = L"PutFiles";
+      DestPath = UnixIncludeTrailingBackslash(DestPath);
+    }
+    else
+    {
+      TransferMethodName = L"GetFiles";
+      DestPath = IncludeTrailingBackslash(DestPath);
+    }
+    DestPath += NoOpOperationMask;
+
+    UnicodeString DestPathVariableName = AssemblyVariableName(Language, L"remotePath");
+    UnicodeString StatementSeparator = AssemblyStatementSeparator(Language);
+    UnicodeString DestPathString = AssemblyString(Language, DestPath);
+    UnicodeString DestPathCode;
+    if ((FFilesSelected != fsList) || (FPaths->Count == 1))
+    {
+      DestPathCode = DestPathString;
+    }
+    else
+    {
+      switch (Language)
+      {
+        case alCSharp:
+          Code += RtfKeyword(L"const") + L" " + RtfKeyword(L"string") + L" " + DestPathVariableName;
+          break;
+
+        case alVBNET:
+          Code += RtfKeyword(L"Const") + L" " + DestPathVariableName;
+          break;
+
+        case alPowerShell:
+          Code += DestPathVariableName;
+          break;
+      }
+      Code += L" = " + DestPathString + StatementSeparator + RtfPara;
+      DestPathCode = DestPathVariableName;
+    }
+
+    UnicodeString TransferMethodCallStart =
+      AssemblyVariableName(Language, SessionClassName) + L"." +
+      RtfLibraryMethod(SessionClassName, TransferMethodName, false) + L"(";
+    const UnicodeString ParameterSeparator = L", ";
+    UnicodeString TransferMethodCallEnd = ParameterSeparator + DestPathCode;
+    if (FMove || HasTransferOptions)
+    {
+      TransferMethodCallEnd += ParameterSeparator + AssemblyBoolean(Language, FMove);
+    }
+    if (HasTransferOptions)
+    {
+      TransferMethodCallEnd += ParameterSeparator + AssemblyVariableName(Language, TransferOptionsClassName);
+    }
+
+    TransferMethodCallEnd +=
+      L")." + RtfLibraryMethod(L"OperationResultBase", L"Check", true) + L"()" +
+      StatementSeparator + RtfPara;
+
+    if (FFilesSelected == fsList)
+    {
+      for (int Index = 0; Index < FPaths->Count; Index++)
+      {
+        UnicodeString FileName = FPaths->Strings[Index];
+        UnicodeString Path;
+        if (!FToRemote)
+        {
+          Path = UnixIncludeTrailingBackslash(FSourcePath) + FileName;
+        }
+        else
+        {
+          Path = IncludeTrailingBackslash(FSourcePath) + FileName;
+        }
+        UnicodeString PathCode = AssemblyString(Language, Path);
+        if (!FToRemote && (FileName != EscapeFileMask(FileName)))
+        {
+          PathCode =
+            AssemblyVariableName(Language, SessionClassName) + L"." +
+            RtfLibraryMethod(SessionClassName, L"EscapeFileMask", false) + L"(" + PathCode + L")";
+        }
+        Code += TransferMethodCallStart + PathCode + TransferMethodCallEnd;
+      }
+    }
+    else
+    {
+      UnicodeString SourcePath = FSourcePath;
+      if (FToRemote)
+      {
+        SourcePath = IncludeTrailingBackslash(SourcePath);
+      }
+      else
+      {
+        SourcePath = UnixIncludeTrailingBackslash(SourcePath);
+      }
+      SourcePath += AllFilesMask;
+      Code += TransferMethodCallStart + AssemblyString(Language, SourcePath) + TransferMethodCallEnd;
     }
   }
   else

+ 2 - 0
source/forms/GenerateUrl.h

@@ -55,6 +55,7 @@ __published:
 private:
   TSessionData * FData;
   std::unique_ptr<TStrings> FPaths;
+  bool FPathsSample;
   bool FChanging;
   TRichEdit41 * FResultMemo41;
   bool FTransfer;
@@ -75,6 +76,7 @@ protected:
   UnicodeString __fastcall GenerateUrl();
   UnicodeString __fastcall GenerateScript(UnicodeString & ScriptDescription);
   UnicodeString __fastcall GenerateAssemblyCode(UnicodeString & AssemblyDescription);
+ void __fastcall AddSampleDescription(UnicodeString & Description);
 
 public:
   __fastcall TGenerateUrlDialog(

+ 3 - 0
source/resource/TextsWin.h

@@ -568,6 +568,9 @@
 #define GENERATE_URL_PATH_TO_SCRIPT 1966
 #define GENERATE_URL_YOUR_CODE  1967
 #define GENERATE_URL_COPY_PARAM_CODE_REMAINING 1968
+#define GENERATE_URL_COPY_PARAM 1969
+#define GENERATE_URL_TRANSFER_FILES 1970
+#define GENERATE_URL_FILE_SAMPLE 1971
 
 // 2xxx is reserved for TextsFileZilla.h
 

+ 3 - 0
source/resource/TextsWin1.rc

@@ -571,6 +571,9 @@ BEGIN
         GENERATE_URL_PATH_TO_SCRIPT, "C:\\path\\to\\script\\script.txt"
         GENERATE_URL_YOUR_CODE, "Your code"
         GENERATE_URL_COPY_PARAM_CODE_REMAINING, "Some configured transfer settings do not have an equivalent in .NET assembly API. Use the Session.AddRawConfiguration instead."
+        GENERATE_URL_COPY_PARAM, "Set up transfer options"
+        GENERATE_URL_TRANSFER_FILES, "Transfer files"
+        GENERATE_URL_FILE_SAMPLE, "A sample file list is used only, consider using a file mask to select files for the transfer."
 
         WIN_VARIABLE_STRINGS, "WIN_VARIABLE"
         WINSCP_COPYRIGHT, "Copyright © 2000-2016 Martin Prikryl"