[Bf-blender-cvs] [a95103f6f4a] master: GHOST/Wayland: support URL decoding for file drag & drop

Campbell Barton noreply at git.blender.org
Thu Aug 4 14:34:20 CEST 2022


Commit: a95103f6f4abda2be9020f13df1256bf0f62c255
Author: Campbell Barton
Date:   Thu Aug 4 22:33:23 2022 +1000
Branches: master
https://developer.blender.org/rBa95103f6f4abda2be9020f13df1256bf0f62c255

GHOST/Wayland: support URL decoding for file drag & drop

Paths that contained characters that needed escaping as URL's failed
to import.

Move URL decoding to a new file (GHOST_PathUtils), shared with X11 but
maybe be useful for other platforms too.

===================================================================

M	intern/ghost/CMakeLists.txt
M	intern/ghost/intern/GHOST_DropTargetX11.cpp
M	intern/ghost/intern/GHOST_DropTargetX11.h
A	intern/ghost/intern/GHOST_PathUtils.cpp
A	intern/ghost/intern/GHOST_PathUtils.h
M	intern/ghost/intern/GHOST_SystemWayland.cpp

===================================================================

diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index cf0d4b1e35d..0ac3a234946 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -26,6 +26,7 @@ set(SRC
   intern/GHOST_ISystemPaths.cpp
   intern/GHOST_ModifierKeys.cpp
   intern/GHOST_Path-api.cpp
+  intern/GHOST_PathUtils.cpp
   intern/GHOST_Rect.cpp
   intern/GHOST_System.cpp
   intern/GHOST_TimerManager.cpp
@@ -60,6 +61,7 @@ set(SRC
   intern/GHOST_EventTrackpad.h
   intern/GHOST_EventWheel.h
   intern/GHOST_ModifierKeys.h
+  intern/GHOST_PathUtils.h
   intern/GHOST_System.h
   intern/GHOST_SystemPaths.h
   intern/GHOST_TimerManager.h
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.cpp b/intern/ghost/intern/GHOST_DropTargetX11.cpp
index 252a8bfd095..b4cb088cbeb 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.cpp
+++ b/intern/ghost/intern/GHOST_DropTargetX11.cpp
@@ -97,89 +97,10 @@ GHOST_DropTargetX11::~GHOST_DropTargetX11()
   }
 }
 
-/* Based on: https://stackoverflow.com/a/2766963/432509 */
-
-using DecodeState_e = enum DecodeState_e {
-  /** Searching for an ampersand to convert. */
-  STATE_SEARCH = 0,
-  /** Convert the two proceeding characters from hex. */
-  STATE_CONVERTING
-};
-
-void GHOST_DropTargetX11::UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn)
-{
-  unsigned int i;
-  unsigned int len = strlen(encodedIn);
-  DecodeState_e state = STATE_SEARCH;
-  int j;
-  unsigned int asciiCharacter;
-  char tempNumBuf[3] = {0};
-  bool bothDigits = true;
-
-  memset(decodedOut, 0, bufferSize);
-
-  for (i = 0; i < len; ++i) {
-    switch (state) {
-      case STATE_SEARCH:
-        if (encodedIn[i] != '%') {
-          strncat(decodedOut, &encodedIn[i], 1);
-          assert((int)strlen(decodedOut) < bufferSize);
-          break;
-        }
-
-        /* We are now converting */
-        state = STATE_CONVERTING;
-        break;
-
-      case STATE_CONVERTING:
-        bothDigits = true;
-
-        /* Create a buffer to hold the hex. For example, if %20, this
-         * buffer would hold 20 (in ASCII) */
-        memset(tempNumBuf, 0, sizeof(tempNumBuf));
-
-        /* Conversion complete (i.e. don't convert again next iter) */
-        state = STATE_SEARCH;
-
-        strncpy(tempNumBuf, &encodedIn[i], 2);
-
-        /* Ensure both characters are hexadecimal */
-
-        for (j = 0; j < 2; ++j) {
-          if (!isxdigit(tempNumBuf[j])) {
-            bothDigits = false;
-          }
-        }
-
-        if (!bothDigits) {
-          break;
-        }
-        /* Convert two hexadecimal characters into one character */
-        sscanf(tempNumBuf, "%x", &asciiCharacter);
-
-        /* Ensure we aren't going to overflow */
-        assert((int)strlen(decodedOut) < bufferSize);
-
-        /* Concatenate this character onto the output */
-        strncat(decodedOut, (char *)&asciiCharacter, 1);
-
-        /* Skip the next character */
-        i++;
-        break;
-    }
-  }
-}
-
 char *GHOST_DropTargetX11::FileUrlDecode(char *fileUrl)
 {
   if (strncmp(fileUrl, "file://", 7) == 0) {
-    /* assume one character of encoded URL can be expanded to 4 chars max */
-    int decodedSize = 4 * strlen(fileUrl) + 1;
-    char *decodedPath = (char *)malloc(decodedSize);
-
-    UrlDecode(decodedPath, decodedSize, fileUrl + 7);
-
-    return decodedPath;
+    return GHOST_URL_decode_alloc(fileUrl + 7);
   }
 
   return nullptr;
diff --git a/intern/ghost/intern/GHOST_DropTargetX11.h b/intern/ghost/intern/GHOST_DropTargetX11.h
index f0ef27697e1..db73ddff70f 100644
--- a/intern/ghost/intern/GHOST_DropTargetX11.h
+++ b/intern/ghost/intern/GHOST_DropTargetX11.h
@@ -64,14 +64,6 @@ class GHOST_DropTargetX11 {
    */
   void *getURIListGhostData(unsigned char *dropBuffer, int dropBufferSize);
 
-  /**
-   * Decode URL (i.e. converts `file:///a%20b/test` to `file:///a b/test`)
-   * \param decodedOut: - buffer for decoded URL.
-   * \param bufferSize: - size of output buffer.
-   * \param encodedIn: - input encoded buffer to be decoded.
-   */
-  void UrlDecode(char *decodedOut, int bufferSize, const char *encodedIn);
-
   /**
    * Fully decode file URL (i.e. converts `file:///a%20b/test` to `/a b/test`)
    * \param fileUrl: - file path URL to be fully decoded.
diff --git a/intern/ghost/intern/GHOST_PathUtils.cpp b/intern/ghost/intern/GHOST_PathUtils.cpp
new file mode 100644
index 00000000000..3b57480039a
--- /dev/null
+++ b/intern/ghost/intern/GHOST_PathUtils.cpp
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2010 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+
+#include "GHOST_PathUtils.h"
+#include "GHOST_Types.h"
+
+/* Based on: https://stackoverflow.com/a/2766963/432509 */
+
+using DecodeState_e = enum DecodeState_e {
+  /** Searching for an ampersand to convert. */
+  STATE_SEARCH = 0,
+  /** Convert the two proceeding characters from hex. */
+  STATE_CONVERTING
+};
+
+void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src)
+{
+  const unsigned int buf_src_len = strlen(buf_src);
+  DecodeState_e state = STATE_SEARCH;
+  unsigned int ascii_character;
+  char temp_num_buf[3] = {0};
+
+  memset(buf_dst, 0, buf_dst_size);
+
+  for (unsigned int i = 0; i < buf_src_len; i++) {
+    switch (state) {
+      case STATE_SEARCH: {
+        if (buf_src[i] != '%') {
+          strncat(buf_dst, &buf_src[i], 1);
+          assert((int)strlen(buf_dst) < buf_dst_size);
+          break;
+        }
+
+        /* We are now converting. */
+        state = STATE_CONVERTING;
+        break;
+      }
+      case STATE_CONVERTING: {
+        bool both_digits = true;
+
+        /* Create a buffer to hold the hex. For example, if `%20`,
+         * this buffer would hold 20 (in ASCII). */
+        memset(temp_num_buf, 0, sizeof(temp_num_buf));
+
+        /* Conversion complete (i.e. don't convert again next iteration). */
+        state = STATE_SEARCH;
+
+        strncpy(temp_num_buf, &buf_src[i], 2);
+
+        /* Ensure both characters are hexadecimal. */
+        for (int j = 0; j < 2; j++) {
+          if (!isxdigit(temp_num_buf[j])) {
+            both_digits = false;
+          }
+        }
+
+        if (!both_digits) {
+          break;
+        }
+        /* Convert two hexadecimal characters into one character. */
+        sscanf(temp_num_buf, "%x", &ascii_character);
+
+        /* Ensure we aren't going to overflow. */
+        assert((int)strlen(buf_dst) < buf_dst_size);
+
+        /* Concatenate this character onto the output. */
+        strncat(buf_dst, (char *)&ascii_character, 1);
+
+        /* Skip the next character. */
+        i++;
+        break;
+      }
+    }
+  }
+}
+
+char *GHOST_URL_decode_alloc(const char *buf_src)
+{
+  /* Assume one character of encoded URL can be expanded to 4 chars max. */
+  const size_t decoded_size_max = 4 * strlen(buf_src) + 1;
+  char *buf_dst = (char *)malloc(decoded_size_max);
+  GHOST_URL_decode(buf_dst, decoded_size_max, buf_src);
+  const size_t decoded_size = strlen(buf_dst) + 1;
+  if (decoded_size != decoded_size_max) {
+    char *buf_dst_trim = (char *)malloc(decoded_size);
+    memcpy(buf_dst_trim, buf_dst, decoded_size);
+    free(buf_dst);
+    buf_dst = buf_dst_trim;
+  }
+  return buf_dst;
+}
diff --git a/intern/ghost/intern/GHOST_PathUtils.h b/intern/ghost/intern/GHOST_PathUtils.h
new file mode 100644
index 00000000000..26a31d1f5c6
--- /dev/null
+++ b/intern/ghost/intern/GHOST_PathUtils.h
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ * Copyright 2010 Blender Foundation. All rights reserved. */
+
+/** \file
+ * \ingroup GHOST
+ */
+
+#pragma once
+
+/**
+ * Decode URL (i.e. converts `file:///a%20b/test` to `file:///a b/test`)
+ *
+ * \param buf_dst: Buffer for decoded URL.
+ * \param buf_dst_maxlen: Size of output buffer.
+ * \param buf_src: Input encoded buffer to be decoded.
+ */
+void GHOST_URL_decode(char *buf_dst, int buf_dst_size, const char *buf_src);
+/**
+ * A version of #GHOST_URL_decode that allocates the string & returns it.
+ *
+ * \param buf_src: Input encoded buffer to be decoded.
+ * \return The decoded output buffer.
+ */
+char *GHOST_URL_decode_alloc(const char *buf_src);
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 7da8d56ed0d..e6366d25788 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -11,6 +11,7 @@
 #include "GHOST_EventDragnDrop.h"
 #include "GHOST_EventKey.h"
 #include "GHOST_EventWheel.h"
+#include "GHOST_PathUtils.h"
 #include "GHOST_TimerManager.h"
 #include "GHOST_WindowManager.h"
 #include "GHOST_utildefines.h"
@@ -1257,8 +1258,7 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
       flist->count = int(uris.size());
       flist->strings = static_cast<uint8_t **>(malloc(uris.size() * sizeof(uint8_t *)));
       for (size_t i = 0; i < uris.size(); i++) {
-        flist->strings[i] = static_cast<uint8_t *>(malloc((uris[i].size() + 1) * sizeof(uint8_t)));
-        memcpy(flist->strings[i], uris[i].data(), uris[i].size() + 1);
+        flist->strings[i] = (uint8_t *)GHOST_URL_decode_alloc(uris[i].c_str());
       }
 
       CLOG_INFO(LOG, 2, "drop_read_uris_fn file_count=%d", flist->count);



More information about the Bf-blender-cvs mailing list