winpr/clipboard: Allow overriding ValidFileNameComponent call

When using the wClipboard API, the connected peer might not be on the
Windows platform, where further filename restriction exists.
As a result, it is currently not possible to use the wClipboard API,
when intending to allow filenames, containing characters like ':'.

So, add a callback to the wClipboardDelegate, which is set to the
ValidFileNameComponent call by default.
This callback can be overridden by the API user, when it is known, that
there is no need to impose very strict filename restrictions.
This commit is contained in:
Pascal Nowack 2022-07-06 12:00:16 +02:00 committed by akallabeth
parent 9a21f79ae1
commit 5f9c519f03
2 changed files with 38 additions and 23 deletions

View File

@ -64,6 +64,8 @@ struct _wClipboardDelegate
(wClipboardDelegate*, const wClipboardFileRangeRequest*, const BYTE* data, UINT32 size);
UINT(*ClipboardFileRangeFailure)
(wClipboardDelegate*, const wClipboardFileRangeRequest*, UINT errorCode);
BOOL (*IsFileNameComponentValid)(LPCWSTR lpFileName);
};
#ifdef __cplusplus

View File

@ -182,10 +182,13 @@ error:
* Note that the function converts a single file name component,
* it does not take care of component separators.
*/
static WCHAR* convert_local_name_component_to_remote(const char* local_name)
static WCHAR* convert_local_name_component_to_remote(wClipboard* clipboard, const char* local_name)
{
wClipboardDelegate* delegate = ClipboardGetDelegate(clipboard);
WCHAR* remote_name = NULL;
WINPR_ASSERT(delegate);
/*
* Note that local file names are not actually guaranteed to be
* encoded in UTF-8. Filesystems and users can use whatever they
@ -203,8 +206,12 @@ static WCHAR* convert_local_name_component_to_remote(const char* local_name)
* Some file names are not valid on Windows. Check for these now
* so that we won't get ourselves into a trouble later as such names
* are known to crash some Windows shells when pasted via clipboard.
*
* The IsFileNameComponentValid callback can be overridden by the API
* user, if it is known, that the connected peer is not on the
* Windows platform.
*/
if (!ValidFileNameComponent(remote_name))
if (!delegate->IsFileNameComponentValid(remote_name))
{
WLog_ERR(TAG, "invalid file name component: %s", local_name);
goto error;
@ -252,10 +259,12 @@ static WCHAR* concat_remote_name(const WCHAR* dir, const WCHAR* file)
return buffer;
}
static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files);
static BOOL add_file_to_list(wClipboard* clipboard, const char* local_name,
const WCHAR* remote_name, wArrayList* files);
static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR* remote_dir_name,
const struct dirent* entry, wArrayList* files)
static BOOL add_directory_entry_to_list(wClipboard* clipboard, const char* local_dir_name,
const WCHAR* remote_dir_name, const struct dirent* entry,
wArrayList* files)
{
BOOL result = FALSE;
char* local_name = NULL;
@ -266,7 +275,7 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR*
if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0))
return TRUE;
remote_base_name = convert_local_name_component_to_remote(entry->d_name);
remote_base_name = convert_local_name_component_to_remote(clipboard, entry->d_name);
if (!remote_base_name)
return FALSE;
@ -275,7 +284,7 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR*
remote_name = concat_remote_name(remote_dir_name, remote_base_name);
if (local_name && remote_name)
result = add_file_to_list(local_name, remote_name, files);
result = add_file_to_list(clipboard, local_name, remote_name, files);
free(remote_base_name);
free(remote_name);
@ -283,8 +292,9 @@ static BOOL add_directory_entry_to_list(const char* local_dir_name, const WCHAR*
return result;
}
static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name,
DIR* dirp, wArrayList* files)
static BOOL do_add_directory_contents_to_list(wClipboard* clipboard, const char* local_name,
const WCHAR* remote_name, DIR* dirp,
wArrayList* files)
{
/*
* For some reason POSIX does not require readdir() to be thread-safe.
@ -316,15 +326,15 @@ static BOOL do_add_directory_contents_to_list(const char* local_name, const WCHA
return FALSE;
}
if (!add_directory_entry_to_list(local_name, remote_name, entry, files))
if (!add_directory_entry_to_list(clipboard, local_name, remote_name, entry, files))
return FALSE;
}
return TRUE;
}
static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR* remote_name,
wArrayList* files)
static BOOL add_directory_contents_to_list(wClipboard* clipboard, const char* local_name,
const WCHAR* remote_name, wArrayList* files)
{
BOOL result = FALSE;
DIR* dirp = NULL;
@ -338,7 +348,7 @@ static BOOL add_directory_contents_to_list(const char* local_name, const WCHAR*
goto out;
}
result = do_add_directory_contents_to_list(local_name, remote_name, dirp, files);
result = do_add_directory_contents_to_list(clipboard, local_name, remote_name, dirp, files);
if (closedir(dirp))
{
@ -350,7 +360,8 @@ out:
return result;
}
static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files)
static BOOL add_file_to_list(wClipboard* clipboard, const char* local_name,
const WCHAR* remote_name, wArrayList* files)
{
struct posix_file* file = NULL;
WLog_VRB(TAG, "adding file: %s", local_name);
@ -371,7 +382,7 @@ static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, w
* This is effectively a recursive call, but we do not track
* recursion depth, thus filesystem loops can cause a crash.
*/
if (!add_directory_contents_to_list(local_name, remote_name, files))
if (!add_directory_contents_to_list(clipboard, local_name, remote_name, files))
return FALSE;
}
@ -392,7 +403,7 @@ static const char* get_basename(const char* name)
return last_name;
}
static BOOL process_file_name(const char* local_name, wArrayList* files)
static BOOL process_file_name(wClipboard* clipboard, const char* local_name, wArrayList* files)
{
BOOL result = FALSE;
const char* base_name = NULL;
@ -403,17 +414,17 @@ static BOOL process_file_name(const char* local_name, wArrayList* files)
* to have names relative to that selection.
*/
base_name = get_basename(local_name);
remote_name = convert_local_name_component_to_remote(base_name);
remote_name = convert_local_name_component_to_remote(clipboard, base_name);
if (!remote_name)
return FALSE;
result = add_file_to_list(local_name, remote_name, files);
result = add_file_to_list(clipboard, local_name, remote_name, files);
free(remote_name);
return result;
}
static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files)
static BOOL process_uri(wClipboard* clipboard, const char* uri, size_t uri_len, wArrayList* files)
{
const char prefix[] = "file://";
BOOL result = FALSE;
@ -432,13 +443,14 @@ static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files)
if (!name)
goto out;
result = process_file_name(name, files);
result = process_file_name(clipboard, name, files);
out:
free(name);
return result;
}
static BOOL process_uri_list(const char* data, size_t length, wArrayList* files)
static BOOL process_uri_list(wClipboard* clipboard, const char* data, size_t length,
wArrayList* files)
{
const char* cur = data;
const char* lim = data + length;
@ -485,7 +497,7 @@ static BOOL process_uri_list(const char* data, size_t length, wArrayList* files)
if (comment)
continue;
if (!process_uri(start, stop - start, files))
if (!process_uri(clipboard, start, stop - start, files))
return FALSE;
}
@ -561,7 +573,7 @@ static void* convert_uri_list_to_filedescriptors(wClipboard* clipboard, UINT32 f
if (formatId != ClipboardGetFormatId(clipboard, "text/uri-list"))
return NULL;
if (!process_uri_list((const char*)data, *pSize, clipboard->localFiles))
if (!process_uri_list(clipboard, (const char*)data, *pSize, clipboard->localFiles))
return NULL;
descriptors = convert_local_file_list_to_filedescriptors(clipboard->localFiles);
@ -946,6 +958,7 @@ static void setup_delegate(wClipboardDelegate* delegate)
delegate->ClientRequestFileRange = posix_file_request_range;
delegate->ClipboardFileRangeSuccess = dummy_file_range_success;
delegate->ClipboardFileRangeFailure = dummy_file_range_failure;
delegate->IsFileNameComponentValid = ValidFileNameComponent;
}
BOOL ClipboardInitPosixFileSubsystem(wClipboard* clipboard)