ソースを参照

Bug 572: Amazon S3 protocol (duplicating)

https://winscp.net/tracker/572

- cp script command now queries the server for source file/dir, as we need the information for S3_deinitialize
- DUPLICATE_FOLDER_NOT_SUPPORTED was by mistake already committed in 32d26ba76eaa (Remote file duplication in scripting, .NET assembly and XML log)

Source commit: b0e54d4ef136c6d798ef8010648ba759d02229e4
Martin Prikryl 8 年 前
コミット
60aa9c8da5

+ 1 - 1
source/core/FileSystems.h

@@ -76,7 +76,7 @@ public:
     TRemoteFile *& File) = 0;
   virtual void __fastcall RenameFile(const UnicodeString FileName,
     const UnicodeString NewName) = 0;
-  virtual void __fastcall CopyFile(const UnicodeString FileName,
+  virtual void __fastcall CopyFile(const UnicodeString FileName, const TRemoteFile * File,
     const UnicodeString NewName) = 0;
   virtual TStrings * __fastcall GetFixedPaths() = 0;
   virtual void __fastcall SpaceAvailable(const UnicodeString Path,

+ 1 - 1
source/core/FtpFileSystem.cpp

@@ -2918,7 +2918,7 @@ void __fastcall TFTPFileSystem::RenameFile(const UnicodeString AFileName,
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TFTPFileSystem::CopyFile(const UnicodeString FileName,
+void __fastcall TFTPFileSystem::CopyFile(const UnicodeString FileName, const TRemoteFile * /*File*/,
   const UnicodeString NewName)
 {
   DebugAssert(SupportsSiteCommand(CopySiteCommand));

+ 1 - 1
source/core/FtpFileSystem.h

@@ -69,7 +69,7 @@ public:
     TRemoteFile *& File);
   virtual void __fastcall RenameFile(const UnicodeString FileName,
     const UnicodeString NewName);
-  virtual void __fastcall CopyFile(const UnicodeString FileName,
+  virtual void __fastcall CopyFile(const UnicodeString FileName, const TRemoteFile * File,
     const UnicodeString NewName);
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const UnicodeString Path,

+ 37 - 4
source/core/S3FileSystem.cpp

@@ -564,6 +564,7 @@ bool __fastcall TS3FileSystem::IsCapable(int Capability) const
     // Only to make double-click on file edit/open the file,
     // instead of trying to open it as directory
     case fcResolveSymlink:
+    case fcRemoteCopy:
       return true;
 
     case fcRename:
@@ -573,7 +574,6 @@ bool __fastcall TS3FileSystem::IsCapable(int Capability) const
     case fcCheckingSpaceAvailable:
     case fsSkipTransfer:
     case fsParallelTransfers:
-    case fcRemoteCopy:
     case fcUserGroupListing:
     case fcModeChanging:
     case fcModeChangingUpload:
@@ -912,10 +912,43 @@ void __fastcall TS3FileSystem::RenameFile(const UnicodeString FileName,
   throw Exception(L"Not implemented");
 }
 //---------------------------------------------------------------------------
-void __fastcall TS3FileSystem::CopyFile(const UnicodeString FileName,
-    const UnicodeString NewName)
+void __fastcall TS3FileSystem::CopyFile(const UnicodeString AFileName, const TRemoteFile * File,
+  const UnicodeString ANewName)
 {
-  throw Exception(L"Not implemented");
+  if (DebugAlwaysTrue(File != NULL) && File->IsDirectory)
+  {
+    throw Exception(LoadStr(DUPLICATE_FOLDER_NOT_SUPPORTED));
+  }
+
+  UnicodeString FileName = AbsolutePath(AFileName, false);
+  UnicodeString NewName = AbsolutePath(ANewName, false);
+
+  UnicodeString SourceBucketName, SourceKey;
+  ParsePath(FileName, SourceBucketName, SourceKey);
+  DebugAssert(!SourceKey.IsEmpty()); // it's not a folder, so it cannot be a bucket or root
+
+  UnicodeString DestBucketName, DestKey;
+  ParsePath(NewName, DestBucketName, DestKey);
+
+  if (DestKey.IsEmpty())
+  {
+    throw Exception(LoadStr(MISSING_TARGET_BUCKET));
+  }
+
+  TLibS3BucketContext BucketContext = GetBucketContext(DestBucketName);
+  BucketContext.BucketNameBuf = SourceBucketName;
+  BucketContext.bucketName = BucketContext.BucketNameBuf.c_str();
+
+  S3ResponseHandler ResponseHandler = CreateResponseHandler();
+
+  TLibS3CallbackData Data;
+  RequestInit(Data);
+
+  S3_copy_object(
+    &BucketContext, StrToS3(SourceKey), StrToS3(DestBucketName), StrToS3(DestKey),
+    NULL, NULL, 0, NULL, FRequestContext, FTimeout, &ResponseHandler, &Data);
+
+  CheckLibS3Error(Data);
 }
 //---------------------------------------------------------------------------
 void __fastcall TS3FileSystem::CreateDirectory(const UnicodeString ADirName)

+ 1 - 1
source/core/S3FileSystem.h

@@ -77,7 +77,7 @@ public:
     TRemoteFile *& File);
   virtual void __fastcall RenameFile(const UnicodeString FileName,
     const UnicodeString NewName);
-  virtual void __fastcall CopyFile(const UnicodeString FileName,
+  virtual void __fastcall CopyFile(const UnicodeString FileName, const TRemoteFile * File,
     const UnicodeString NewName);
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const UnicodeString Path,

+ 1 - 1
source/core/ScpFileSystem.cpp

@@ -1166,7 +1166,7 @@ void __fastcall TSCPFileSystem::RenameFile(const UnicodeString FileName,
   ExecCommand(fsRenameFile, ARRAYOFCONST((DelimitStr(FileName), DelimitStr(NewName))));
 }
 //---------------------------------------------------------------------------
-void __fastcall TSCPFileSystem::CopyFile(const UnicodeString FileName,
+void __fastcall TSCPFileSystem::CopyFile(const UnicodeString FileName, const TRemoteFile * /*File*/,
   const UnicodeString NewName)
 {
   UnicodeString DelimitedFileName = DelimitStr(FileName);

+ 1 - 1
source/core/ScpFileSystem.h

@@ -59,7 +59,7 @@ public:
     TRemoteFile *& File);
   virtual void __fastcall RenameFile(const UnicodeString FileName,
     const UnicodeString NewName);
-  virtual void __fastcall CopyFile(const UnicodeString FileName,
+  virtual void __fastcall CopyFile(const UnicodeString FileName, const TRemoteFile * File,
     const UnicodeString NewName);
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const UnicodeString Path,

+ 5 - 5
source/core/Script.cpp

@@ -1332,7 +1332,7 @@ void __fastcall TScript::RmDirProc(TScriptProcParams * Parameters)
   }
 }
 //---------------------------------------------------------------------------
-void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp)
+void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp, TFileListType FileListMask)
 {
   CheckSession();
 
@@ -1341,8 +1341,8 @@ void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability
     NotSupported();
   }
 
-  TStrings * FileList = CreateFileList(Parameters, 1, Parameters->ParamCount - 1,
-    fltMask);
+  TStrings * FileList =
+    CreateFileList(Parameters, 1, Parameters->ParamCount - 1, TFileListType(fltMask | FileListMask));
   try
   {
     DebugAssert(Parameters->ParamCount >= 1);
@@ -1369,12 +1369,12 @@ void __fastcall TScript::DoMvOrCp(TScriptProcParams * Parameters, TFSCapability
 //---------------------------------------------------------------------------
 void __fastcall TScript::MvProc(TScriptProcParams * Parameters)
 {
-  DoMvOrCp(Parameters, fcRemoteMove, false);
+  DoMvOrCp(Parameters, fcRemoteMove, false, fltDefault);
 }
 //---------------------------------------------------------------------------
 void __fastcall TScript::CpProc(TScriptProcParams * Parameters)
 {
-  DoMvOrCp(Parameters, fcRemoteCopy, true);
+  DoMvOrCp(Parameters, fcRemoteCopy, true, fltQueryServer);
 }
 //---------------------------------------------------------------------------
 void __fastcall TScript::ChModProc(TScriptProcParams * Parameters)

+ 1 - 1
source/core/Script.h

@@ -180,7 +180,7 @@ private:
   void __fastcall NotSupported();
   void __fastcall CheckMultiFilesToOne(TStrings * FileList, const UnicodeString & Target, bool Unix);
   void __fastcall LogOption(const UnicodeString & LogStr);
-  void __fastcall DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp);
+  void __fastcall DoMvOrCp(TScriptProcParams * Parameters, TFSCapability Capability, bool Cp, TFileListType FileListMask);
 };
 //---------------------------------------------------------------------------
 typedef void __fastcall (__closure *TScriptInputEvent)(TScript * Script, const UnicodeString Prompt, UnicodeString & Str);

+ 1 - 1
source/core/SftpFileSystem.cpp

@@ -3720,7 +3720,7 @@ void __fastcall TSFTPFileSystem::RenameFile(const UnicodeString FileName,
   SendPacketAndReceiveResponse(&Packet, &Packet, SSH_FXP_STATUS);
 }
 //---------------------------------------------------------------------------
-void __fastcall TSFTPFileSystem::CopyFile(const UnicodeString FileName,
+void __fastcall TSFTPFileSystem::CopyFile(const UnicodeString FileName, const TRemoteFile * /*File*/,
   const UnicodeString NewName)
 {
   // Implemented by ProFTPD/mod_sftp and Bitvise WinSSHD (without announcing it)

+ 1 - 1
source/core/SftpFileSystem.h

@@ -70,7 +70,7 @@ public:
     TRemoteFile *& File);
   virtual void __fastcall RenameFile(const UnicodeString FileName,
     const UnicodeString NewName);
-  virtual void __fastcall CopyFile(const UnicodeString FileName,
+  virtual void __fastcall CopyFile(const UnicodeString FileName, const TRemoteFile * File,
     const UnicodeString NewName);
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const UnicodeString Path,

+ 5 - 5
source/core/Terminal.cpp

@@ -4479,7 +4479,7 @@ bool __fastcall TTerminal::MoveFiles(TStrings * FileList, const UnicodeString Ta
   return Result;
 }
 //---------------------------------------------------------------------------
-void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
+void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName, const TRemoteFile * File,
   const UnicodeString NewName)
 {
   TRetryOperationLoop RetryLoop(this);
@@ -4491,7 +4491,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
       DebugAssert(FFileSystem);
       if (IsCapable[fcRemoteCopy])
       {
-        FFileSystem->CopyFile(FileName, NewName);
+        FFileSystem->CopyFile(FileName, File, NewName);
       }
       else
       {
@@ -4499,7 +4499,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
         DebugAssert(FCommandSession->FSProtocol == cfsSCP);
         LogEvent(L"Copying file on command session.");
         FCommandSession->CurrentDirectory = CurrentDirectory;
-        FCommandSession->FFileSystem->CopyFile(FileName, NewName);
+        FCommandSession->FFileSystem->CopyFile(FileName, File, NewName);
       }
     }
     catch(Exception & E)
@@ -4511,7 +4511,7 @@ void __fastcall TTerminal::DoCopyFile(const UnicodeString FileName,
 }
 //---------------------------------------------------------------------------
 void __fastcall TTerminal::CopyFile(const UnicodeString FileName,
-  const TRemoteFile * /*File*/, /*const TMoveFileParams*/ void * Param)
+  const TRemoteFile * File, /*const TMoveFileParams*/ void * Param)
 {
   StartOperationWithFile(FileName, foRemoteCopy);
   DebugAssert(Param != NULL);
@@ -4519,7 +4519,7 @@ void __fastcall TTerminal::CopyFile(const UnicodeString FileName,
   UnicodeString NewName = UnixIncludeTrailingBackslash(Params.Target) +
     MaskFileName(UnixExtractFileName(FileName), Params.FileMask);
   LogEvent(FORMAT(L"Copying file \"%s\" to \"%s\".", (FileName, NewName)));
-  DoCopyFile(FileName, NewName);
+  DoCopyFile(FileName, File, NewName);
   ReactOnCommand(fsCopyFile);
 }
 //---------------------------------------------------------------------------

+ 1 - 1
source/core/Terminal.h

@@ -262,7 +262,7 @@ protected:
     const TRemoteFile * File, UnicodeString Command, int Params, TCaptureOutputEvent OutputEvent);
   void __fastcall DoRenameFile(const UnicodeString FileName,
     const UnicodeString NewName, bool Move);
-  void __fastcall DoCopyFile(const UnicodeString FileName, const UnicodeString NewName);
+  void __fastcall DoCopyFile(const UnicodeString FileName, const TRemoteFile * File, const UnicodeString NewName);
   void __fastcall DoChangeFileProperties(const UnicodeString FileName,
     const TRemoteFile * File, const TRemoteProperties * Properties);
   void __fastcall DoChangeDirectory();

+ 2 - 2
source/core/WebDAVFileSystem.cpp

@@ -1055,8 +1055,8 @@ int __fastcall TWebDAVFileSystem::CopyFileInternal(const UnicodeString & FileNam
   return ne_copy(FNeonSession, 0, NE_DEPTH_INFINITE, PathToNeon(FileName), PathToNeon(NewName));
 }
 //---------------------------------------------------------------------------
-void __fastcall TWebDAVFileSystem::CopyFile(const UnicodeString FileName,
-    const UnicodeString NewName)
+void __fastcall TWebDAVFileSystem::CopyFile(const UnicodeString FileName, const TRemoteFile * /*File*/,
+  const UnicodeString NewName)
 {
   ClearNeonError();
   TOperationVisualizer Visualizer(FTerminal->UseBusyCursor);

+ 1 - 1
source/core/WebDAVFileSystem.h

@@ -68,7 +68,7 @@ public:
     TRemoteFile *& File);
   virtual void __fastcall RenameFile(const UnicodeString FileName,
     const UnicodeString NewName);
-  virtual void __fastcall CopyFile(const UnicodeString FileName,
+  virtual void __fastcall CopyFile(const UnicodeString FileName, const TRemoteFile * File,
     const UnicodeString NewName);
   virtual TStrings * __fastcall GetFixedPaths();
   virtual void __fastcall SpaceAvailable(const UnicodeString Path,

+ 1 - 0
source/resource/TextsCore.h

@@ -322,6 +322,7 @@
 #define S3_SECRET_ACCESS_KEY_TITLE 358
 #define S3_SECRET_ACCESS_KEY_PROMPT 359
 #define DUPLICATE_FOLDER_NOT_SUPPORTED 360
+#define MISSING_TARGET_BUCKET   361
 
 #define CORE_INFORMATION_STRINGS 400
 #define YES_STR                 401

+ 1 - 0
source/resource/TextsCore1.rc

@@ -238,6 +238,7 @@ BEGIN
   S3_ERROR_EXTRA_DETAILS, "Extra Details: "
   S3_STATUS_ACCESS_DENIED, "Access denied."
   DUPLICATE_FOLDER_NOT_SUPPORTED, "Direct duplication of folders is not supported. Use a duplication via a local temporary copy."
+  MISSING_TARGET_BUCKET, "Specify target bucket."
 
   CORE_CONFIRMATION_STRINGS, "CORE_CONFIRMATION"
   CONFIRM_PROLONG_TIMEOUT3, "Host is not communicating for %d seconds.\n\nWait for another %0:d seconds?"