Forráskód Böngészése

Bug 1876: Compatibility with WebDAV servers that incorrectly encode file URL

https://winscp.net/tracker/1876
(cherry picked from commit 218f33154a299e3f6517681dab4c8fe584669d63)

Source commit: c58ece07f059e30d9aba96730227d2bbd03201cd
Martin Prikryl 5 éve
szülő
commit
719396f835

+ 9 - 0
libs/neon/src/ne_207.c

@@ -188,6 +188,15 @@ end_element(void *userdata, int state, const char *nspace, const char *name)
                 cdata = hh;
             }
 
+            #ifdef WINSCP
+            if (p->flags & NE_207_LIBERAL_ESCAPING) {
+                hh = ne_path_escapef(cdata, NE_PATH_NONPC);
+                NE_DEBUG(NE_DBG_XML, "207: Enabled liberal href escaping [%s]->[%s]\n",
+                         cdata, hh);
+                cdata = hh;
+            }
+            #endif
+
             ret = ne_uri_parse(cdata, &ref);
             if (!ret) {
                 ne_uri_resolve(&p->base, &ref, &resolved);

+ 4 - 0
libs/neon/src/ne_207.h

@@ -73,6 +73,10 @@ ne_207_parser *ne_207_create(ne_xml_parser *parser, const ne_uri *base,
 
 /* Enable special href escaping hacks for Microsoft SharePoint. */
 #define NE_207_MSSP_ESCAPING (0x0001)
+#ifdef WINSCP
+/* Enable any character in file name in URL */
+#define NE_207_LIBERAL_ESCAPING (0x0002)
+#endif
 
 /* Set given flags for the parser. */
 void ne_207_set_flags(ne_207_parser *p, unsigned int flags);

+ 4 - 0
libs/neon/src/ne_props.c

@@ -608,6 +608,10 @@ ne_propfind_create(ne_session *sess, const char *uri, int depth)
 
     if (ne_get_session_flag(sess, NE_SESSFLAG_SHAREPOINT))
         ne_207_set_flags(ret->parser207, NE_207_MSSP_ESCAPING);
+    #ifdef WINSCP
+    if (ne_get_session_flag(sess, NE_SESSFLAG_LIBERAL_ESCAPING))
+        ne_207_set_flags(ret->parser207, NE_207_LIBERAL_ESCAPING);
+    #endif
 
     /* The start of the request body is fixed: */
     ne_buffer_czappend(ret->body, 

+ 4 - 0
libs/neon/src/ne_session.h

@@ -104,6 +104,10 @@ typedef enum ne_session_flag_e {
                              * to improve interoperability with
                              * SharePoint */
 
+    #ifdef WINSCP
+    NE_SESSFLAG_LIBERAL_ESCAPING,
+    #endif
+
     NE_SESSFLAG_LAST /* enum sentinel value */
 } ne_session_flag;
 

+ 6 - 0
libs/neon/src/ne_uri.c

@@ -93,6 +93,9 @@
 
 /* any characters which should be path-escaped: */
 #define URI_ESCAPE ((URI_GENDELIM & ~(FS)) | URI_SUBDELIM | OT | PC)
+#ifdef WINSCP
+#define URI_NONPC (URI_ESCAPE & (~PC))
+#endif
 
 static const unsigned short uri_chars[256] = {
 /* 0xXX    x0      x2      x4      x6      x8      xA      xC      xE     */
@@ -493,6 +496,9 @@ char *ne_path_escapef(const char *path, unsigned int flags)
 
     if (flags & NE_PATH_NONRES) mask |= URI_ESCAPE;
     if (flags & NE_PATH_NONURI) mask |= URI_NONURI;
+    #ifdef WINSCP
+    if (flags & NE_PATH_NONPC) mask |= URI_NONPC;
+    #endif
 
     for (pnt = (const unsigned char *)path; *pnt != '\0'; pnt++) {
         count += path_escape_ch(*pnt, mask);

+ 4 - 0
libs/neon/src/ne_uri.h

@@ -38,6 +38,10 @@ char *ne_path_escape(const char *path);
 #define NE_PATH_NONRES (0x0001)
 /* Escape any characters outside of those allowed in URIs. */
 #define NE_PATH_NONURI (0x0002)
+#ifdef WINSCP
+/* As NE_PATH_NONRES, but excluding %, so it can be used on already encoded URI */
+#define NE_PATH_NONPC (0x0004)
+#endif
 
 /* Return a copy of a path string with escaping applied per rules
  * determined by any combination of NE_PATH_* flags given.  Returns a

+ 13 - 0
source/core/SessionData.cpp

@@ -174,6 +174,8 @@ void __fastcall TSessionData::DefaultSettings()
 
   EncryptKey = UnicodeString();
 
+  WebDavLiberalEscaping = false;
+
   ProxyMethod = ::pmNone;
   ProxyHost = L"proxy";
   ProxyPort = ProxyPortNumber;
@@ -449,6 +451,8 @@ void __fastcall TSessionData::NonPersistant()
   \
   PROPERTY_HANDLER(EncryptKey, F); \
   \
+  PROPERTY(WebDavLiberalEscaping); \
+  \
   PROPERTY(PuttySettings); \
   \
   PROPERTY(CustomParam1); \
@@ -849,6 +853,8 @@ void __fastcall TSessionData::DoLoad(THierarchicalStorage * Storage, bool PuttyI
     SET_SESSION_PROPERTY_FROM(EncryptKey, AEncryptKey);
   }
 
+  WebDavLiberalEscaping = Storage->ReadBool(L"WebDavLiberalEscaping", WebDavLiberalEscaping);
+
   IsWorkspace = Storage->ReadBool(L"IsWorkspace", IsWorkspace);
   Link = Storage->ReadString(L"Link", Link);
   NameOverride = Storage->ReadString(L"NameOverride", NameOverride);
@@ -1187,6 +1193,8 @@ void __fastcall TSessionData::DoSave(THierarchicalStorage * Storage,
     WRITE_DATA(Integer, MinTlsVersion);
     WRITE_DATA(Integer, MaxTlsVersion);
 
+    WRITE_DATA(Bool, WebDavLiberalEscaping);
+
     WRITE_DATA(Bool, IsWorkspace);
     WRITE_DATA(String, Link);
     WRITE_DATA(String, NameOverride);
@@ -4107,6 +4115,11 @@ void __fastcall TSessionData::SetEncryptKey(UnicodeString avalue)
   SET_SESSION_PROPERTY(EncryptKey);
 }
 //---------------------------------------------------------------------
+void __fastcall TSessionData::SetWebDavLiberalEscaping(bool value)
+{
+  SET_SESSION_PROPERTY(WebDavLiberalEscaping);
+}
+//---------------------------------------------------------------------
 UnicodeString __fastcall TSessionData::GetInfoTip()
 {
   if (UsesSsh)

+ 3 - 0
source/core/SessionData.h

@@ -231,6 +231,7 @@ private:
   UnicodeString FNote;
   UnicodeString FWinTitle;
   RawByteString FEncryptKey;
+  bool FWebDavLiberalEscaping;
 
   UnicodeString FOrigHostName;
   int FOrigPortNumber;
@@ -409,6 +410,7 @@ private:
   void __fastcall SetWinTitle(UnicodeString value);
   UnicodeString __fastcall GetEncryptKey() const;
   void __fastcall SetEncryptKey(UnicodeString value);
+  void __fastcall SetWebDavLiberalEscaping(bool value);
 
   TDateTime __fastcall GetTimeoutDT();
   void __fastcall SavePasswords(THierarchicalStorage * Storage, bool PuttyExport, bool DoNotEncryptPasswords, bool SaveAll);
@@ -671,6 +673,7 @@ public:
   __property UnicodeString Note = { read = FNote, write = SetNote };
   __property UnicodeString WinTitle = { read = FWinTitle, write = SetWinTitle };
   __property UnicodeString EncryptKey = { read = GetEncryptKey, write = SetEncryptKey };
+  __property bool WebDavLiberalEscaping = { read = FWebDavLiberalEscaping, write = SetWebDavLiberalEscaping };
 
   __property UnicodeString StorageKey = { read = GetStorageKey };
   __property UnicodeString SiteKey = { read = GetSiteKey };

+ 1 - 0
source/core/SessionInfo.cpp

@@ -1353,6 +1353,7 @@ void __fastcall TSessionLog::DoAddStartupInfo(TSessionData * Data)
       FtpsOn = (Data->Ftps != ftpsNone);
       ADF(L"HTTPS: %s [Client certificate: %s]",
         (BooleanToEngStr(FtpsOn), LogSensitive(Data->TlsCertificateFile)));
+      ADF(L"WebDAV: Tolerate non-encoded: %s", (BooleanToEngStr(Data->WebDavLiberalEscaping)));
     }
     if (Data->FSProtocol == fsS3)
     {

+ 2 - 0
source/core/WebDAVFileSystem.cpp

@@ -293,6 +293,8 @@ void __fastcall TWebDAVFileSystem::InitSession(ne_session_s * Session)
   ne_set_connect_timeout(Session, Data->Timeout);
 
   ne_set_session_private(Session, SESSION_FS_KEY, this);
+
+  ne_set_session_flag(Session, NE_SESSFLAG_LIBERAL_ESCAPING, Data->WebDavLiberalEscaping);
 }
 //---------------------------------------------------------------------------
 void TWebDAVFileSystem::NeonOpen(UnicodeString & CorrectedUrl, const UnicodeString & Url)

+ 9 - 0
source/forms/SiteAdvanced.cpp

@@ -416,6 +416,9 @@ void __fastcall TSiteAdvancedDialog::LoadSession()
     EncryptFilesCheck->Checked = !FSessionData->EncryptKey.IsEmpty();
     GetEncryptKeyEdit()->Text = FSessionData->EncryptKey;
 
+    // webdav page
+    WebDavLiberalEscapingCheck->Checked = FSessionData->WebDavLiberalEscaping;
+
     // color
     FColor = (TColor)FSessionData->Color;
   }
@@ -686,6 +689,9 @@ void __fastcall TSiteAdvancedDialog::SaveSession(TSessionData * SessionData)
   // Encryption page
   SessionData->EncryptKey = EncryptFilesCheck->Checked ? GetEncryptKeyEdit()->Text : UnicodeString();
 
+  // webdav page
+  SessionData->WebDavLiberalEscaping = WebDavLiberalEscapingCheck->Checked;
+
   // color
   SessionData->Color = FColor;
 }
@@ -1059,6 +1065,9 @@ void __fastcall TSiteAdvancedDialog::UpdateControls()
     EncryptionSheet->Enabled = SftpProtocol;
     EnableControl(EncryptFilesGroup, EncryptFilesCheck->Checked);
 
+    // environment/webdav
+    WebDavSheet->Enabled = WebDavProtocol;
+
     UpdateNavigationTree();
 
     // color

+ 47 - 15
source/forms/SiteAdvanced.dfm

@@ -1068,6 +1068,37 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
           end
         end
       end
+      object WebDavSheet: TTabSheet
+        Tag = 2
+        Caption = 'WebDAV'
+        ImageIndex = 17
+        TabVisible = False
+        DesignSize = (
+          401
+          382)
+        object WebdavGroup: TGroupBox
+          Left = 0
+          Top = 6
+          Width = 393
+          Height = 46
+          Anchors = [akLeft, akTop, akRight]
+          Caption = 'Protocol options'
+          TabOrder = 0
+          DesignSize = (
+            393
+            46)
+          object WebDavLiberalEscapingCheck: TCheckBox
+            Left = 12
+            Top = 19
+            Width = 369
+            Height = 17
+            Anchors = [akLeft, akTop, akRight]
+            Caption = '&Tolerate non-encoded special characters in filenames'
+            TabOrder = 0
+            OnClick = DataChange
+          end
+        end
+      end
       object ConnSheet: TTabSheet
         Tag = 1
         HelpType = htKeyword
@@ -2605,7 +2636,7 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
         OnCollapsing = NavigationTreeCollapsing
         Items.NodeData = {
           030400000036000000000000000000000000000000FFFFFFFF00000000000000
-          0007000000010C45006E007600690072006F006E006D0065006E007400580036
+          0008000000010C45006E007600690072006F006E006D0065006E007400580036
           000000000000000000000000000000FFFFFFFF00000000000000000000000001
           0C4400690072006500630074006F007200690065007300580036000000000000
           000000000000000000FFFFFFFF000000000000000000000000010C5200650063
@@ -2616,20 +2647,21 @@ object SiteAdvancedDialog: TSiteAdvancedDialog
           00000000000000FFFFFFFF000000000000000000000000010453004300500058
           00260000000000000000000000FFFFFFFFFFFFFFFF0000000000000000000000
           000104460054005000580024000000000000000000000000000000FFFFFFFF00
-          0000000000000000000000010353003300580034000000000000000000000000
-          000000FFFFFFFF000000000000000002000000010B43006F006E006E00650063
-          00740069006F006E0058002A000000000000000000000000000000FFFFFFFF00
-          00000000000000000000000106500072006F007800790058002C000000000000
-          000000000000000000FFFFFFFF0000000000000000000000000107540075006E
-          006E0065006C00580026000000000000000000000000000000FFFFFFFF000000
-          0000000000030000000104530053004800580038000000000000000000000000
-          000000FFFFFFFF000000000000000000000000010D4B00650078002000650078
-          006300680061006E006700650058003C000000000000000000000000000000FF
-          FFFFFF000000000000000000000000010F410075007400680065006E00740069
-          0063006100740069006F006E00580028000000000000000000000000000000FF
-          FFFFFF0000000000000000000000000105420075006700730058002800000000
-          0000000000000000000000FFFFFFFF00000000000000000000000001054E006F
-          00740065005800}
+          000000000000000000000001035300330058002C0000000000000000000000FF
+          FFFFFFFFFFFFFF00000000000000000000000001075700650062004400410056
+          00580034000000000000000000000000000000FFFFFFFF000000000000000002
+          000000010B43006F006E006E0065006300740069006F006E0058002A00000000
+          0000000000000000000000FFFFFFFF0000000000000000000000000106500072
+          006F007800790058002C000000000000000000000000000000FFFFFFFF000000
+          0000000000000000000107540075006E006E0065006C00580026000000000000
+          000000000000000000FFFFFFFF00000000000000000300000001045300530048
+          00580038000000000000000000000000000000FFFFFFFF000000000000000000
+          000000010D4B00650078002000650078006300680061006E006700650058003C
+          000000000000000000000000000000FFFFFFFF00000000000000000000000001
+          0F410075007400680065006E007400690063006100740069006F006E00580028
+          000000000000000000000000000000FFFFFFFF00000000000000000000000001
+          054200750067007300580028000000000000000000000000000000FFFFFFFF00
+          000000000000000000000001054E006F00740065005800}
       end
     end
   end

+ 3 - 0
source/forms/SiteAdvanced.h

@@ -281,6 +281,9 @@ __published:
   TLabel *PuttySettingsLabel;
   TEdit *PuttySettingsEdit;
   TCheckBox *AuthGSSAPIKEXCheck;
+  TTabSheet *WebDavSheet;
+  TGroupBox *WebdavGroup;
+  TCheckBox *WebDavLiberalEscapingCheck;
   void __fastcall DataChange(TObject *Sender);
   void __fastcall FormShow(TObject *Sender);
   void __fastcall PageControlChange(TObject *Sender);