The purpose of clipboard data locking is to make the other peer
retaining the current file list until a pending paste operation is done,
even though the clipboard selection changed.
As it may be difficult to determine, when a lock is needed, imitate the
same behaviour as mstsc:
When the server side supports clipboard data locking, always attempt to
lock the file list on the server regardless of what is advertised in a
FormatList PDU.
The Lock Clipboard Data PDU can even be already sent, before the
Format List Response PDU is sent.
This is also what mstsc, does: First, lock the new (potential) file
list, then unlock the file list, when the pending paste operation is
done.
So, rework the current clipboard implementation in that direction.
Since the implementation for timeouts for old file lists is a bit hard,
for now always force unlock pending locks, when the selection changes.
However, timeouts for old file lists can still be added in the future.
The reworked clipboard handling is done with the help of three hash
tables:
1. The inode table: This hash table manages all inodes for each file.
The keys in this table are the inodes themselves, while the values
the files and directories and their attributes (file size, last write
time, etc.).
2. The clipdata table: This table manages the locks for each file list.
The keys in this table represent the clip data id and the values the
clip data entries, which have a reference to the clip data dir, a
directory containing the whole selection, and some helper attributes,
like the clip data id itself.
3. The request table: Every file size or file range request is managed
here. When a FileContentsRequest is made, its stream id with the
respective details are added to this table. When a response is
received, these details can then be easily looked up here.
When receiving a file list, xfreerdp3 rebuilds the content of the FUSE
filesystem.
Since fetching uri-lists can happen during a paste action too, xfreerdp3
caches the content of the last fetched mime type.
However, uri-lists exists in different variations, e.g. nautilus uses a
different mime type, than gnome-terminal does.
Furthermore, FormatLists can also contain other formats in addition to
file lists.
Fetching those contents during a paste operation leads to IO errors in
the paste operation.
In order to fix those errors, cache every mimetype in two hash tables:
One for the raw (unconverted) data, and one for the converted data.
When a content request is received, xfreerdp3 can with the already
cached converted data, directly serve the data.
If the content is not available as cached data, but its source data was
already fetched, use that source data to create the converted data.
Then serve the converted data.
Only if no cached converted data or cached raw data is available, issue
a new FormatDataRequest.
Format lists can contain multiple clipboard formats. When the data for
one is requested, xfreerdp caches it.
When the data for a different format in the same format lists is
requested, xfreerdp cannot use the already cached data, since that data
refers to a different format.
As a result, xfreerdp needs to ask for the data of the now requested
format.
However, this is currently not the case. xfreerdp will just provide the
data of the first request after receiving the last format list.
In order to fix this situation, also save the format id of the last
requested format.
If the format id of the cached data matches the one of the current
request, serve the data from the cached data.
Otherwise, issue a new FormatDataRequest.
Commit 6492a00959 introduced a way to
relieve the filename restriction, which ensured that file lists
containing files with names, that have characters, which are not allowed
on MS Windows.
This relief handling kicked in, when xfreerdp did not connect to MS
Windows RDS.
Commit d521c7fa74 got rid of any
wClipboardDelegate occurrence in xf_cliprdr.c, which also got rid of the
filename restriction relieve handling.
However, the relief handling was not added back, so do it now.
to debug bug reports occuring only with certain setups wrap the function
call with a logging edition so we have the arguments available in the
log for debugging.