From 33e80849a817fd12f01681e30c4607346223d8b3 Mon Sep 17 00:00:00 2001 From: ilammy Date: Sun, 9 Apr 2017 02:29:51 +0300 Subject: [PATCH] wClipboard/posix: add local files to file list Finally we can add a file to the file list once we have got its local file name decoded. The interesting part here is what we use for the remote name. Suppose the user has selected two files in different directories. In this case we end up receiving a text/uri-list like this: file:///home/bob/foo/a file:///home/bob/bar/b We'd expect to see "a" and "b" pasted into the remote session, so that's what we should use for the remote names: the base names of the files. These are the parts from the end up to the last directory delimiter. One tricky point here is that Windows expects the file names to be encoded in Unicode, but POSIX does not specify any particular encoding for file names. Operating systems and file systems generally handle the file names as mostly opaque bytes strings and do not really care what encoding is used there. There is no portable API to get the encoding, it's entirely up to the users and the software they use to correctly interpret the file names. But we need to do something here. As of 2017, the most widely used encoding for file names is UTF-8. While there are marginal communities which stick to codepages for legacy reasons, we can safely assume that most of the time the file names will be encoded in UTF-8. In fact, popular desktop environments like GNOME also assume this. So that's what we will do here as well. --- winpr/libwinpr/clipboard/posix.c | 65 +++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/winpr/libwinpr/clipboard/posix.c b/winpr/libwinpr/clipboard/posix.c index 598df584e..4d92317f3 100644 --- a/winpr/libwinpr/clipboard/posix.c +++ b/winpr/libwinpr/clipboard/posix.c @@ -169,10 +169,71 @@ error: return NULL; } +static BOOL add_file_to_list(const char* local_name, const WCHAR* remote_name, wArrayList* files) +{ + struct posix_file* file = NULL; + +#ifdef WITH_DEBUG_WCLIPBOARD + WLog_DBG(TAG, "adding file: %s", local_name); +#endif + + file = make_posix_file(local_name, remote_name); + if (!file) + return FALSE; + + if (ArrayList_Add(files, file) < 0) + { + free_posix_file(file); + + return FALSE; + } + + return TRUE; +} + +static const char* basename(const char* name) +{ + const char* c = name; + const char* last_name = name; + + while (*c++) + { + if (*c == '/') + last_name = c + 1; + } + + return last_name; +} + static BOOL process_file_name(const char* local_name, wArrayList* files) { - /* TBD: add file with `local_name` to `files` */ - return FALSE; + BOOL result = FALSE; + const char* base_name = NULL; + WCHAR* remote_name = NULL; + + /* + * Start with the base name of the file. text/uri-list contains the + * exact files selected by the user, and we want the remote files + * to have names relative to that selection. + * + * Note that local file names are not actually guaranteed to be + * encoded in UTF-8. Filesystems and users can use whatever they + * want. The OS does not care, aside from special treatment of + * '\0' and '/' bytes. But we need to make some decision here. + * Assuming UTF-8 is currently the most sane thing. + */ + base_name = basename(local_name); + if (!ConvertToUnicode(CP_UTF8, 0, base_name, -1, &remote_name, 0)) + { + WLog_ERR(TAG, "Unicode conversion failed for %s", base_name); + goto out; + } + + result = add_file_to_list(local_name, remote_name, files); +out: + free(remote_name); + + return result; } static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files)