Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorCampbell Barton <campbell@blender.org>2022-08-04 15:33:23 +0300
committerCampbell Barton <campbell@blender.org>2022-08-04 15:33:23 +0300
commita95103f6f4abda2be9020f13df1256bf0f62c255 (patch)
tree56239f477fd583771e1bb339b48f43eb67868775 /intern
parent727cc426bc723c8757941ce9bf23745ee5f6ab9d (diff)
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.
Diffstat (limited to 'intern')
-rw-r--r--intern/ghost/CMakeLists.txt2
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.cpp81
-rw-r--r--intern/ghost/intern/GHOST_DropTargetX11.h8
-rw-r--r--intern/ghost/intern/GHOST_PathUtils.cpp101
-rw-r--r--intern/ghost/intern/GHOST_PathUtils.h24
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp4
6 files changed, 130 insertions, 90 deletions
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
@@ -65,14 +65,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.
* \return decoded file path (result should be free-d).
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);