[winpr,clipboard] fix url unescape for file uri

This commit is contained in:
akallabeth
2023-05-11 13:03:39 +02:00
committed by akallabeth
parent 7073aef79f
commit 4a006322af
5 changed files with 144 additions and 3 deletions

View File

@@ -1955,7 +1955,7 @@ static BOOL cliprdr_local_file_new(CliprdrFileContext* context, CliprdrLocalFile
*f = empty;
f->context = context;
f->name = _strdup(path);
f->name = winpr_str_url_decode(path, strlen(path));
if (!f->name)
goto fail;

View File

@@ -33,6 +33,9 @@ extern "C"
{
#endif
WINPR_API char* winpr_str_url_encode(const char* str, size_t len);
WINPR_API char* winpr_str_url_decode(const char* str, size_t len);
WINPR_API BOOL winpr_str_append(const char* what, char* buffer, size_t size,
const char* separator);

View File

@@ -726,10 +726,9 @@ char* parse_uri_to_local_file(const char* uri, size_t uri_len)
} while (0);
buffer = calloc(localLen + 1, sizeof(char));
buffer = winpr_str_url_decode(localName, localLen);
if (buffer)
{
memcpy(buffer, localName, localLen);
if (buffer[1] == '|' &&
((buffer[0] >= 'A' && buffer[0] <= 'Z') || (buffer[0] >= 'a' && buffer[0] <= 'z')))
buffer[1] = ':';

View File

@@ -39,6 +39,92 @@
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#endif
static const char rfc3986[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x2e, 0x00,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f,
0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static char hex2bin(char what)
{
if (what >= 'a')
what -= 'a' - 'A';
if (what >= 'A')
what -= ('A' - 10);
else
what -= '0';
return what;
}
static char unescape(const char* what, size_t* px)
{
if ((*what == '%') && (isxdigit(what[1]) && isxdigit(what[2])))
{
*px += 2;
return 16 * hex2bin(what[1]) + hex2bin(what[2]);
}
if (*what == '+')
return ' ';
return *what;
}
char* winpr_str_url_decode(const char* str, size_t len)
{
char* dst = calloc(len + 1, sizeof(char));
if (!dst)
return NULL;
size_t pos = 0;
for (size_t x = 0; x < strnlen(str, len); x++)
{
const char* cur = &str[x];
dst[pos++] = unescape(cur, &x);
}
return dst;
}
static char* escape(char* dst, char what)
{
if (rfc3986[what & 0xff])
{
*dst = what;
return dst + 1;
}
sprintf(dst, "%%%02" PRIX8, what & 0xff);
return dst + 3;
}
char* winpr_str_url_encode(const char* str, size_t len)
{
char* dst = calloc(len + 1, sizeof(char) * 3);
if (!dst)
return NULL;
char* ptr = dst;
for (size_t x = 0; x < strnlen(str, len); x++)
{
const char cur = str[x];
ptr = escape(ptr, cur);
}
return dst;
}
BOOL winpr_str_append(const char* what, char* buffer, size_t size, const char* separator)
{
const size_t used = strnlen(buffer, size);

View File

@@ -27,6 +27,56 @@ static WCHAR testDelimiter[] = { '\r', '\n', '\0' };
#define testDelimiter_Length ((sizeof(testDelimiter) / sizeof(WCHAR)) - 1)
struct url_test_pair
{
const char* what;
const char* escaped;
};
static const struct url_test_pair url_tests[] = {
{ "xxx%bar ga<ka>ee#%%#%{h}g{f{e%d|c\\b^a~p[q]r`s;t/u?v:w@x=y&z$xxx",
"xxx%25bar%20ga%3Cka%3Eee%23%25%25%23%25%7Bh%7Dg%7Bf%7Be%25d%7Cc%5Cb%5Ea~p%5Bq%5Dr%60s%3Bt%"
"2Fu%3Fv%3Aw%40x%3Dy%26z%24xxx" },
{ "äöúëü", "%C3%A4%C3%B6%C3%BA%C3%AB%C3%BC" },
{ "🎅🏄🤘😈", "%F0%9F%8E%85%F0%9F%8F%84%F0%9F%A4%98%F0%9F%98%88" }
};
static BOOL test_url_escape(void)
{
for (size_t x = 0; x < ARRAYSIZE(url_tests); x++)
{
const struct url_test_pair* cur = &url_tests[x];
char* escaped = winpr_str_url_encode(cur->what, strlen(cur->what) + 1);
char* what = winpr_str_url_decode(cur->escaped, strlen(cur->escaped) + 1);
const size_t elen = strlen(escaped);
const size_t wlen = strlen(what);
const size_t pelen = strlen(cur->escaped);
const size_t pwlen = strlen(cur->what);
BOOL rc = TRUE;
if (!escaped || (elen != pelen) || (strcmp(escaped, cur->escaped) != 0))
{
printf("expected: [%" PRIuz "] %s\n", pelen, cur->escaped);
printf("got : [%" PRIuz "] %s\n", elen, escaped);
rc = FALSE;
}
else if (!what || (wlen != pwlen) || (strcmp(what, cur->what) != 0))
{
printf("expected: [%" PRIuz "] %s\n", pwlen, cur->what);
printf("got : [%" PRIuz "] %s\n", wlen, what);
rc = FALSE;
}
free(escaped);
free(what);
if (!rc)
return FALSE;
}
return TRUE;
}
int TestString(int argc, char* argv[])
{
const WCHAR* p;
@@ -37,6 +87,9 @@ int TestString(int argc, char* argv[])
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
if (!test_url_escape())
return -1;
#ifdef __BIG_ENDIAN__
/* Be sure that we always use LE encoded string */
ByteSwapUnicode(testStringW, testStringW_Length);