From e7d2f62ce60537fc71680a7075d39703dc882737 Mon Sep 17 00:00:00 2001 From: jackyzy823 Date: Fri, 8 Jan 2021 21:53:28 +0800 Subject: [PATCH] x11: handle special chars in generating file uri --- winpr/libwinpr/clipboard/posix.c | 78 ++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/winpr/libwinpr/clipboard/posix.c b/winpr/libwinpr/clipboard/posix.c index 08560e820..1b69c9a0c 100644 --- a/winpr/libwinpr/clipboard/posix.c +++ b/winpr/libwinpr/clipboard/posix.c @@ -41,6 +41,7 @@ #include #include #include +#include #include "clipboard.h" #include "posix.h" @@ -581,6 +582,35 @@ static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 f return descriptors; } +static size_t count_special_chars(const WCHAR* str) +{ + size_t count = 0; + WCHAR* start = (WCHAR*)str; + while (*start) + { + if (*start == L'#' || *start == L'?' || *start == L'*' || *start == L'!' || *start == L'%') + { + count++; + } + start++; + } + return count; +} + +static char* stop_at_special_chars(const char* str) +{ + char* start = (char*)str; + while (*start) + { + if (*start == '#' || *start == '?' || *start == '*' || *start == '!' || *start == '%') + { + return start; + } + start++; + } + return NULL; +} + /* The universal converter from filedescriptors to different file lists */ static void* convert_filedescriptors_to_file_list(wClipboard* clipboard, UINT32 formatId, const void* data, UINT32* pSize, @@ -635,6 +665,7 @@ static void* convert_filedescriptors_to_file_list(wClipboard* clipboard, UINT32 size_t curLen = _wcsnlen(descriptors[x].cFileName, ARRAYSIZE(descriptors[x].cFileName)); alloc += WideCharToMultiByte(CP_UTF8, 0, descriptors[x].cFileName, (int)curLen, NULL, 0, NULL, NULL); + alloc += count_special_chars(descriptors[x].cFileName) * 2; alloc += decoration_len; } } @@ -661,21 +692,62 @@ static void* convert_filedescriptors_to_file_list(wClipboard* clipboard, UINT32 const FILEDESCRIPTORW* cur = &descriptors[x]; size_t curLen = _wcsnlen(cur->cFileName, ARRAYSIZE(cur->cFileName)); char* curName = NULL; + char* stop_at = NULL; + char* previous_at = NULL; rc = ConvertFromUnicode(CP_UTF8, 0, cur->cFileName, (int)curLen, &curName, 0, NULL, NULL); - rc = _snprintf(&dst[pos], alloc - pos, "%s%s/%s%s", lineprefix, - clipboard->delegate.basePath, curName, lineending); - free(curName); + rc = _snprintf(&dst[pos], alloc - pos, "%s%s/", lineprefix, clipboard->delegate.basePath); if (rc < 0) { free(dst); return NULL; } + pos += (size_t)rc; + + previous_at = curName; + while ((stop_at = stop_at_special_chars(previous_at)) != NULL) + { + char* tmp = strndup(previous_at, stop_at - previous_at); + if (!tmp) + { + free(dst); + free(curName); + return NULL; + } + rc = _snprintf(&dst[pos], stop_at - previous_at + 1, "%s", tmp); + free(tmp); + if (rc < 0) + { + free(dst); + free(curName); + return NULL; + } + pos += (size_t)rc; + rc = _snprintf(&dst[pos], 4, "%%%x", *stop_at); + if (rc < 0) + { + free(dst); + free(curName); + return NULL; + } + pos += (size_t)rc; + previous_at = stop_at + 1; + } + + rc = _snprintf(&dst[pos], alloc - pos, "%s%s", previous_at, lineending); + if (rc < 0) + { + free(dst); + free(curName); + return NULL; + } + free(curName); pos += (size_t)rc; } + winpr_HexDump(TAG, WLOG_DEBUG, (const BYTE*)dst, alloc); *pSize = (UINT32)alloc; clipboard->fileListSequenceNumber = clipboard->sequenceNumber; return dst;