Commit Graph

130 Commits

Author SHA1 Message Date
ilammy
6c6b122a37 wClipboard/posix: add directories to file list
text/uri-list contains only the files which were immediately selected by
the user. However, we need to enumerate *all* files and directories to
be pasted in CLIPRDR_FILELIST. Thus we need to walk through the
directories and add their content to the file list as well.

We use readdir() function to traverse the directory entries. It has more
sane interface than readdir_r(), but lacks (standardized) thread-safety
guarantees.  However, most C liraries guarantee that so we can use it.
There is no compile-time check because it cannot be made robust. You
deserve a crash here if you are using a C library developed by people
who cannot keep their unhealthy addiction to global state under control.

Note that recursive traversal is also a good opportunity to maintain
good remote names. We just need to concatenate the directory paths and
file names correctly.

However, this recursion has one caveat: it is not bounded, so if the
file system contains a loop then we will crash due to a stack overflow.
We could track symlink loops (and hardlinks too if we try hard) to avoid
the crash, but I think it's not a common thing to do so we can ignore
this possibility.
2017-04-09 03:15:49 +03:00
ilammy
33e80849a8 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.
2017-04-09 03:15:49 +03:00
ilammy
50038bb725 wClipboard/posix: decode percent-encoding
Nothing really interesting here, it's exactly what it says on the tin.
The percent-encoding is specified by RFC 3986. And we take care to
detect invalid encodings.
2017-04-09 03:15:49 +03:00
ilammy
64e1073044 wClipboard/posix: parse text/uri-list format
Now we start handling the actual format data. As the first step we need
to convert the text/uri-list data into the list of file names. Each file
or directory the user selects to copy is represented with a URI, and the
whole list looks like this:

  file:///home/bob/text-file
  file:///home/bob/a-directory
  file:///home/bob/white%20space

The MIME format is actually specified by RFC 2483. As said in the
comments, we allow some slack for other applications: they can use
singular LF and CR as line terminators, and we also will handle missing
terminator for the last line (some applications actually do this, but I
can't recall which ones at the moment).

We will handle only the file:// URI scheme because these refer to local
filesystem paths. It is possible for text/uri-list to contain URIs with
other schemes when the user selects files from remote filesystems (like
an FTP server or an SMB share connect to from a file manager). We cannot
pass such paths to open() and for some reason the file managers use the
remote URIs even when the remote filesystems are actually mapped to the
local filesystem via FUSE. Therefore we restrict ourselves to handling
only file://.
2017-04-09 03:15:48 +03:00
ilammy
09e73a00cb wClipboard/posix: conversion to FILEDESCRIPTORs
Now we do the actual conversion of a list of struct posix_files into an
array of FILEDESCRIPTORs. In order to correctly fill in the fields we
need to know the size of the file and whether it is a directory. This
can be looked up by stat() call. Do this during struct posix_file
construction and cache the values for later use (we will need them).

Define _FILE_OFFSET_BITS to make off_t a 64-bit value and to call
appropriate functions when we write stat() in the code. FILEDESCRIPTOR
and cliprdr protocol expect the file sizes to be 64-bit so we can
provide accurate information with that. Take care to define it before
including any system headers ("config.h" contains only defines).

Also take care to not overrun the file name buffer. Windows has a hard
cap of 260 Unicode characters for the full file name, including the
terminating null character.
2017-04-09 03:15:48 +03:00
ilammy
907f21e720 wClipboard/posix: basic file list handling
Here you can see an outline of our approach to handling file lists put
on the clipboard. Typical usage of wClipboard by the clients sums up to
doing a ClipboardSetData() call followed by a ClipboardGetData() call
with appropriate format ID passed to them. Thus for files we would
expect the clients to first set the local format (like "text/uri-list")
and then to get the remote format (the "FileGroupDescriptorW").

MS-RDPECLIP has a concept of locally-stored list of files on the
clipboard. This is modeled by clipboard->localFiles ArrayList.  We need
to populate this list before we serialize it into CLIPRDR_FILELIST and
send it to the server. The easiest way to achieve this is a bit hacky,
but it works: we populate the file list from inside the synthesizer
callback registered for text/uri-list -> FileGroupDescriptorW
conversion.

So the client would first set the data it received from local clipboard
as "text/uri-list" format, then it gets a "FileGroupDescriptorW" format,
during that conversion we will prepare to serve file content requests,
and in the end we provide a FILEDESCRIPTOR array to the client as the
conversion result. The client will then serialize the array into
CLIPRDR_FILELIST and sent it to the server. (We cannot do serialization
in WinPR as WinPR should not know about cliprdr and its data formats.)

The subsystems are expected to store their private structures in the
clipboard->localFiles array. POSIX subsystem uses struct posix_file
which currently has bare minimum of fields: the local file name (for
open() and the like) and the remote file name (the one to put into
FILEDESCRIPTOR).
2017-04-09 03:15:48 +03:00
ilammy
b0bc59595d wClipboard: local file subsystem boilerplate
This adds some initial skeleton for local file subsystems of wClipboard.

The idea is to delegate handling of local file formats to dedicated
subsystems selected at runtime based on the compiled-in support code.
This is somewhat similar to the approach used by audin, rdpsnd, rdpgfx
channels in FreeRDP.

Only one subsystem is actually used by wClipboard during runtime. It is
selected by the ClipboardInitLocalFileSubsystem() function which will
try initializing the compiled-in subsystems in the preferred order. Thus
when adding new subsystems one must make sure to 1) return as soon as
any initialization succeeds, 2) leave wClipboard in usable state if the
initialization fails.

A POSIX file subsystem is added as a pioneer. It will handle local file
format "text/uri-list" and will use POSIX API to access the files. This
is the combination one would expect to be supported by Linux systems
which can run the XFreeRDP client.

The POSIX subsystem is enabled only when CMake detects <unistd.h> as
available. This is the core POSIX include file so we can reasonably
expect the rest of the POSIX API to be available along with that file.

We also define a new configuration option WITH_DEBUG_WCLIPBOARD which
will be used to guard some debug-only verbose logging in wClipboad.
2017-04-09 03:15:48 +03:00
ilammy
228916bcec wClipboard: improve error handling
Unify error handling in ClipboardInitFormats() and actually handle the
return value of ClipboardInitSynthesizers(). Currently it always returns
TRUE, but this may change, so we'd better be clean.

Declare 'formatName' in wClipboardFormat as non-const. It is customary
in C to declare owned pointers as non-const because various deallocation
functions like free() take non-const pointers as arguments. Furthermore,
const char* is tightly associated with "string literals" which must not
be freed. Thus declaring this field as non-const is more accurate, and
removes that ugly void* cast from ClipboardInitFormats().

Unify error handling in ClipboardCreate(). The cleanup snippet should
not be repeated as it's prone to errors, like leaking the allocation of
clipboard->formats when ClipboardInitFormats() fails. Unified error
handling makes it much harder to forget resource cleanup on errors.
2017-04-09 03:15:48 +03:00
Armin Novak
09d43a66f4 Fixed tests and dead store warnings. 2017-03-28 16:49:56 +02:00
Norbert Federa
ab0408ae5e ctest for int format specifiers and usage doc 2016-12-16 14:20:30 +01:00
Norbert Federa
f71b6b46e8 fix string format specifiers
- fixed invalid, missing or additional arguments
- removed all type casts from arguments
- added missing (void*) typecasts for %p arguments
- use inttypes defines where appropriate
2016-12-16 13:48:43 +01:00
Armin Novak
fb1dcf2689 Fixed invalid const type. 2016-10-07 14:08:33 +02:00
Armin Novak
8f1adf64ee Refactored ClipboardSetData. 2016-10-06 13:43:15 +02:00
Armin Novak
64c5d78b3f Fixed clang warnings. 2016-10-06 13:43:09 +02:00
Marc-André Moreau
d0f413db12 winpr: initial port to Universal Windows Platform (UWP) 2016-02-05 16:28:45 -05:00
Bernhard Miklautz
cbbc680131 clipboard: fix of by one error on cleanup 2015-06-25 11:53:03 +02:00
Bernhard Miklautz
9f6fa7ef4c Fix possible endless loops on cleanup.
Some cleanup code possibly create endless loops because an unsigned
type was used as run variable but the check was >= 0 in the for loop.
2015-06-24 12:26:13 +02:00
Bernhard Miklautz
77927c213e android: fix misc compiler warnings
with gcc version arm-linux-androideabi-gcc (GCC) 4.8
2015-06-22 19:09:59 +02:00
Bernhard Miklautz
bf73f4e4f1 Fix unchecked strdups
* add missing checks
* adapt function return values where necessary
* add initial test for settings
2015-06-22 19:09:59 +02:00
Bernhard Miklautz
850de59b55 winpr: add checks for *alloc
Add missing checks if memory allocation was successful. Also adapt
caller(s) when possible.
2015-04-08 11:34:37 +02:00
Marc-André Moreau
08c8c6f285 channels/cliprdr: fix empty clipboard format lists, server-side locking 2014-12-20 13:07:30 -05:00
Marc-André Moreau
f2267a2277 libwinpr-clipboard: fix memory corruption and leaks 2014-12-04 13:19:10 -05:00
Marc-André Moreau
0818846d7c winpr: fix build warnings 2014-11-21 15:12:49 -05:00
Marc-André Moreau
9258ecca37 libwinpr-clipboard: improve robustness 2014-11-20 12:08:01 -05:00
Marc-André Moreau
ce7302a999 wfreerdp: cleanup clipboard 2014-10-22 22:32:55 -04:00
Marc-André Moreau
83ecddd6c1 xfreerdp: replace cliprdr to wire format conversion 2014-10-17 20:40:11 -04:00
Marc-André Moreau
e8312e2dac libwinpr-clipboard: add more synthetic clipboard formats 2014-10-17 19:14:54 -04:00
Marc-André Moreau
0e4659403f libwinpr-clipboard: add basic clipboard synthesizers 2014-10-17 18:23:07 -04:00
Marc-André Moreau
c27888ed72 libwinpr-clipboard: initial clipboard synthetic format support 2014-10-17 16:45:36 -04:00
Marc-André Moreau
d98ce1a819 libwinpr-clipboard: initial commit 2014-10-17 15:19:05 -04:00