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://.
This commit is contained in:
ilammy 2017-04-09 02:29:51 +03:00
parent 09e73a00cb
commit 64e1073044

View File

@ -98,10 +98,98 @@ static void free_posix_file(void* the_file)
free(file);
}
static char* decode_percent_encoded_string(const char* str, size_t len)
{
/* TBD: decode percent-encoded URI into a fresh null-terminated string */
return NULL;
}
static BOOL process_file_name(const char* local_name, wArrayList* files)
{
/* TBD: add file with `local_name` to `files` */
return FALSE;
}
static BOOL process_uri(const char* uri, size_t uri_len, wArrayList* files)
{
BOOL result = FALSE;
char* name = NULL;
#ifdef WITH_DEBUG_WCLIPBOARD
WLog_DBG(TAG, "processing URI: %.*s", uri_len, uri);
#endif
if ((uri_len < strlen("file://")) || strncmp(uri, "file://", strlen("file://")))
{
WLog_ERR(TAG, "non-'file://' URI schemes are not supported");
goto out;
}
name = decode_percent_encoded_string(uri + strlen("file://"), uri_len - strlen("file://"));
if (!name)
goto out;
result = process_file_name(name, files);
out:
free(name);
return result;
}
static BOOL process_uri_list(const char* data, size_t length, wArrayList* files)
{
const char* cur = data;
const char* lim = data + length;
const char* start = NULL;
const char* stop = NULL;
#ifdef WITH_DEBUG_WCLIPBOARD
WLog_DBG(TAG, "processing URI list:\n%.*s", length, data);
#endif
ArrayList_Clear(files);
/* TBD: parse text/uri-list `data` and store it into `files` */
/*
* The "text/uri-list" Internet Media Type is specified by RFC 2483.
*
* While the RFCs 2046 and 2483 require the lines of text/... formats
* to be terminated by CRLF sequence, be prepared for those who don't
* read the spec, use plain LFs, and don't leave the trailing CRLF.
*/
while (cur < lim)
{
BOOL comment = (*cur == '#');
start = cur;
stop = cur;
for (stop = cur; stop < lim; stop++)
{
if (*stop == '\r')
{
if ((stop + 1 < lim) && (*(stop + 1) == '\n'))
cur = stop + 2;
else
cur = stop + 1;
break;
}
if (*stop == '\n')
{
cur = stop + 1;
break;
}
}
if (stop == lim)
cur = lim;
if (comment)
continue;
if (!process_uri(start, stop - start, files))
return FALSE;
}
return TRUE;
}