summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sesman/chansrv/Makefile.am1
-rw-r--r--sesman/chansrv/clipboard.c294
-rw-r--r--sesman/chansrv/clipboard.h2
-rw-r--r--sesman/chansrv/clipboard_file.c327
-rw-r--r--sesman/chansrv/clipboard_file.h31
5 files changed, 368 insertions, 287 deletions
diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am
index a1b5bed9..252ef72e 100644
--- a/sesman/chansrv/Makefile.am
+++ b/sesman/chansrv/Makefile.am
@@ -28,6 +28,7 @@ xrdp_chansrv_SOURCES = \
chansrv.c \
sound.c \
clipboard.c \
+ clipboard_file.c \
devredir.c \
rail.c \
xcommon.c \
diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c
index 18712dc8..af07b00b 100644
--- a/sesman/chansrv/clipboard.c
+++ b/sesman/chansrv/clipboard.c
@@ -52,6 +52,7 @@ xlsatoms - dump atoms
#include "os_calls.h"
#include "chansrv.h"
#include "clipboard.h"
+#include "clipboard_file.h"
#include "xcommon.h"
#define LLOG_LEVEL 11
@@ -103,7 +104,8 @@ static Atom g_file_atom2 = 0; /* x-special/gnome-copied-files */
static Window g_wnd = 0;
static int g_xfixes_event_base = 0;
-static int g_last_clip_size = 0;
+int g_last_clip_size = 0;
+
static char *g_last_clip_data = 0;
static Atom g_last_clip_type = 0;
static int g_last_xrdp_clip_type = 0;
@@ -145,17 +147,6 @@ static int g_cliprdr_flags = CB_USE_LONG_FORMAT_NAMES |
static int g_formatIds[16];
static int g_num_formatIds = 0;
-struct cb_file_info
-{
- char pathname[256];
- char filename[256];
- int flags;
- int size;
-};
-
-static struct cb_file_info g_files[64];
-static int g_num_files = 0;
-
/*****************************************************************************/
/* this is one way to get the current time from the x server */
static Time APP_CC
@@ -405,10 +396,10 @@ clipboard_send_format_ack(void)
make_stream(s);
init_stream(s, 8192);
- out_uint16_le(s, 3); /* CLIPRDR_FORMAT_ACK */
- out_uint16_le(s, 1); /* status */
+ out_uint16_le(s, CB_FORMAT_LIST_RESPONSE); /* 3 CLIPRDR_FORMAT_ACK */
+ out_uint16_le(s, CB_RESPONSE_OK); /* 1 status */
out_uint32_le(s, 0); /* length */
- out_uint32_le(s, 0); /* extra 4 bytes ? */
+ out_uint32_le(s, 0); /* extra 4 bytes */
s_mark_end(s);
size = (int)(s->end - s->data);
LOGM((LOG_LEVEL_DEBUG, "clipboard_send_format_ack: data out, sending "
@@ -420,7 +411,7 @@ clipboard_send_format_ack(void)
/*****************************************************************************/
/* returns number of bytes written */
-static int APP_CC
+int APP_CC
clipboard_out_unicode(struct stream *s, char *text, int num_chars)
{
int index;
@@ -645,164 +636,6 @@ clipboard_send_data_response_for_text(char* data, int data_size)
/*****************************************************************************/
static int APP_CC
-clipboard_get_file(char* file, int bytes)
-{
- int sindex;
- int pindex;
- char full_fn[256];
- char filename[256];
- char pathname[256];
-
- sindex = 0;
- if (g_strncmp(file, "file:///", 8) == 0)
- {
- sindex = 7;
- }
- pindex = bytes;
- while (pindex > sindex)
- {
- if (file[pindex] == '/')
- {
- break;
- }
- pindex--;
- }
- g_memset(pathname, 0, 256);
- g_memset(filename, 0, 256);
- g_memcpy(pathname, file + sindex, pindex - sindex);
- if (pathname[0] == 0)
- {
- pathname[0] = '/';
- }
- g_memcpy(filename, file + pindex + 1, (bytes - 1) - pindex);
- g_snprintf(full_fn, 255, "%s/%s", pathname, filename);
- if (g_directory_exist(full_fn))
- {
- LLOGLN(0, ("clipboard_get_file: file [%s] is a directory, "
- "not supported", full_fn));
- return 1;
- }
- if (!g_file_exist(full_fn))
- {
- LLOGLN(0, ("clipboard_get_file: file [%s] does not exist",
- full_fn));
- return 1;
- }
- else
- {
- g_strcpy(g_files[g_num_files].filename, filename);
- g_strcpy(g_files[g_num_files].pathname, pathname);
- g_files[g_num_files].size = g_file_get_size(full_fn);
- g_writeln("ok filename [%s] pathname [%s] size [%d]",
- g_files[g_num_files].filename,
- g_files[g_num_files].pathname,
- g_files[g_num_files].size);
- g_num_files++;
- }
- return 0;
-}
-
-/*****************************************************************************/
-static int APP_CC
-clipboard_get_files(char* files, int bytes)
-{
- int index;
- int file_index;
- char file[512];
-
- g_num_files = 0;
- file_index = 0;
- for (index = 0; index < bytes; index++)
- {
- if (files[index] == '\n' || files[index] == '\r')
- {
- if (file_index > 0)
- {
- if (clipboard_get_file(file, file_index) == 0)
- {
- }
- file_index = 0;
- }
- }
- else
- {
- file[file_index] = files[index];
- file_index++;
- }
- if (g_num_files > 60)
- {
- break;
- }
- }
- if (file_index > 0)
- {
- if (clipboard_get_file(file, file_index) == 0)
- {
- }
- }
- if (g_num_files < 1)
- {
- return 1;
- }
- return 0;
-}
-
-/*****************************************************************************/
-static int APP_CC
-clipboard_send_data_response_for_file(char *data, int data_size)
-{
- struct stream *s;
- int size;
- int rv;
- int bytes_after_header;
- int cItems;
- int flags;
- int index;
- char fn[256];
-
- LLOGLN(10, ("clipboard_send_data_response_for_file: g_last_clip_size %d",
- g_last_clip_size));
- g_hexdump(data, data_size);
- clipboard_get_files(data, data_size);
- cItems = g_num_files;
- bytes_after_header = cItems * 592 + 4;
- make_stream(s);
- init_stream(s, 64 + bytes_after_header);
- out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
- out_uint16_le(s, 1); // CB_RESPONSE_OK); /* 1 status */
- out_uint32_le(s, bytes_after_header);
- out_uint32_le(s, cItems);
- for (index = 0; index < cItems; index++)
- {
- flags = CB_FD_ATTRIBUTES | CB_FD_FILESIZE | CB_FD_WRITESTIME | CB_FD_PROGRESSUI;
- out_uint32_le(s, flags);
- out_uint8s(s, 32); /* reserved1 */
- flags = CB_FILE_ATTRIBUTE_ARCHIVE;
- //flags = CB_FILE_ATTRIBUTE_NORMAL;
- out_uint32_le(s, flags);
- out_uint8s(s, 16); /* reserved2 */
- /* file time */
- out_uint32_le(s, 0x2c305d08);
- out_uint32_le(s, 0x01ca55f3);
- /* file size */
- out_uint32_le(s, 0);
- out_uint32_le(s, g_files[index].size);
- g_writeln("jay size %d", g_files[index].size);
- g_snprintf(fn, 255, "%s", g_files[index].filename);
- clipboard_out_unicode(s, fn, 256);
- out_uint8s(s, 8); /* pad */
- }
- out_uint32_le(s, 0);
- s_mark_end(s);
- size = (int)(s->end - s->data);
- g_hexdump(s->data, size);
- rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
- free_stream(s);
- return rv;
-}
-
-/*****************************************************************************/
-static int APP_CC
clipboard_send_data_response(int xrdp_clip_type, char *data, int data_size)
{
LLOGLN(10, ("clipboard_send_data_response:"));
@@ -1253,119 +1086,6 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status,
}
/*****************************************************************************/
-static int APP_CC
-clipboard_send_file_size(int streamId, int lindex)
-{
- struct stream *s;
- int size;
- int rv;
- int file_size;
-
- file_size = g_files[lindex].size;
- LLOGLN(10, ("clipboard_send_file_size: streamId %d file_size %d",
- streamId, file_size));
- make_stream(s);
- init_stream(s, 8192);
- out_uint16_le(s, CB_FILECONTENTS_RESPONSE); /* 9 */
- out_uint16_le(s, CB_RESPONSE_OK); /* 1 status */
- out_uint32_le(s, 12);
- out_uint32_le(s, streamId);
- out_uint32_le(s, file_size);
- g_writeln("file_size %d", file_size);
- out_uint32_le(s, 0);
- out_uint32_le(s, 0);
- s_mark_end(s);
- size = (int)(s->end - s->data);
- rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
- free_stream(s);
- return rv;
-}
-
-/*****************************************************************************/
-static int APP_CC
-clipboard_send_file_data(int streamId, int lindex,
- int nPositionLow, int cbRequested)
-{
- struct stream *s;
- int size;
- int rv;
- int fd;
- char full_fn[256];
-
- LLOGLN(10, ("clipboard_send_file_data: streamId %d lindex %d "
- "nPositionLow %d cbRequested %d", streamId, lindex,
- nPositionLow, cbRequested));
- g_snprintf(full_fn, 255, "%s/%s", g_files[lindex].pathname,
- g_files[lindex].filename);
- fd = g_file_open_ex(full_fn, 1, 0, 0, 0);
- if (fd == -1)
- {
- LLOGLN(0, ("clipboard_send_file_data: file open [%s] failed",
- full_fn));
- return 1;
- }
- g_file_seek(fd, nPositionLow);
- make_stream(s);
- init_stream(s, cbRequested + 64);
- //g_memset(s->data + 12, 26, cbRequested);
- size = g_file_read(fd, s->data + 12, cbRequested);
- g_writeln("size %d", size);
- if (size < 1)
- {
- LLOGLN(10, ("clipboard_send_file_data: read error, want %d got %d",
- cbRequested, size));
- free_stream(s);
- g_file_close(fd);
- return 1;
- }
- out_uint16_le(s, CB_FILECONTENTS_RESPONSE); /* 9 */
- out_uint16_le(s, CB_RESPONSE_OK); /* 1 status */
- out_uint32_le(s, size + 4);
- out_uint32_le(s, streamId);
- s->p += size;
- out_uint32_le(s, 0);
- s_mark_end(s);
- size = (int)(s->end - s->data);
- rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
- free_stream(s);
- g_file_close(fd);
- return rv;
-}
-
-/*****************************************************************************/
-static int APP_CC
-clipboard_process_file_request(struct stream *s, int clip_msg_status,
- int clip_msg_len)
-{
- int streamId;
- int lindex;
- int dwFlags;
- int nPositionLow;
- int nPositionHigh;
- int cbRequested;
- //int clipDataId;
-
- LLOGLN(10, ("clipboard_process_file_request:"));
- g_hexdump(s->p, clip_msg_len);
- in_uint32_le(s, streamId);
- in_uint32_le(s, lindex);
- in_uint32_le(s, dwFlags);
- in_uint32_le(s, nPositionLow);
- in_uint32_le(s, nPositionHigh);
- in_uint32_le(s, cbRequested);
- //in_uint32_le(s, clipDataId); /* options, used when locking */
- if (dwFlags & CB_FILECONTENTS_SIZE)
- {
- clipboard_send_file_size(streamId, lindex);
- }
- if (dwFlags & CB_FILECONTENTS_RANGE)
- {
- clipboard_send_file_data(streamId, lindex, nPositionLow, cbRequested);
- }
- return 0;
-}
-
-/*****************************************************************************/
int APP_CC
clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length,
int total_length)
diff --git a/sesman/chansrv/clipboard.h b/sesman/chansrv/clipboard.h
index 80d8da3e..965ccdc5 100644
--- a/sesman/chansrv/clipboard.h
+++ b/sesman/chansrv/clipboard.h
@@ -89,6 +89,8 @@ clipboard_init(void);
int APP_CC
clipboard_deinit(void);
int APP_CC
+clipboard_out_unicode(struct stream *s, char *text, int num_chars);
+int APP_CC
clipboard_data_in(struct stream* s, int chan_id, int chan_flags, int length,
int total_length);
int APP_CC
diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c
new file mode 100644
index 00000000..0d6ebf5c
--- /dev/null
+++ b/sesman/chansrv/clipboard_file.c
@@ -0,0 +1,327 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xfixes.h>
+#include "arch.h"
+#include "parse.h"
+#include "os_calls.h"
+#include "chansrv.h"
+#include "clipboard.h"
+#include "clipboard_file.h"
+#include "xcommon.h"
+
+#define LLOG_LEVEL 11
+#define LLOGLN(_level, _args) \
+ do \
+ { \
+ if (_level < LLOG_LEVEL) \
+ { \
+ g_write("chansrv:clip [%10.10u]: ", g_time3()); \
+ g_writeln _args ; \
+ } \
+ } \
+ while (0)
+
+extern int g_cliprdr_chan_id; /* in chansrv.c */
+
+extern int g_last_clip_size; /* in clipboard.c */
+
+struct cb_file_info
+{
+ char pathname[256];
+ char filename[256];
+ int flags;
+ int size;
+};
+
+static struct cb_file_info g_files[64];
+static int g_num_files = 0;
+
+/*****************************************************************************/
+static int APP_CC
+clipboard_get_file(char* file, int bytes)
+{
+ int sindex;
+ int pindex;
+ char full_fn[256];
+ char filename[256];
+ char pathname[256];
+
+ sindex = 0;
+ if (g_strncmp(file, "file:///", 8) == 0)
+ {
+ sindex = 7;
+ }
+ pindex = bytes;
+ while (pindex > sindex)
+ {
+ if (file[pindex] == '/')
+ {
+ break;
+ }
+ pindex--;
+ }
+ g_memset(pathname, 0, 256);
+ g_memset(filename, 0, 256);
+ g_memcpy(pathname, file + sindex, pindex - sindex);
+ if (pathname[0] == 0)
+ {
+ pathname[0] = '/';
+ }
+ g_memcpy(filename, file + pindex + 1, (bytes - 1) - pindex);
+ g_snprintf(full_fn, 255, "%s/%s", pathname, filename);
+ if (g_directory_exist(full_fn))
+ {
+ LLOGLN(0, ("clipboard_get_file: file [%s] is a directory, "
+ "not supported", full_fn));
+ return 1;
+ }
+ if (!g_file_exist(full_fn))
+ {
+ LLOGLN(0, ("clipboard_get_file: file [%s] does not exist",
+ full_fn));
+ return 1;
+ }
+ else
+ {
+ g_strcpy(g_files[g_num_files].filename, filename);
+ g_strcpy(g_files[g_num_files].pathname, pathname);
+ g_files[g_num_files].size = g_file_get_size(full_fn);
+ g_writeln("ok filename [%s] pathname [%s] size [%d]",
+ g_files[g_num_files].filename,
+ g_files[g_num_files].pathname,
+ g_files[g_num_files].size);
+ g_num_files++;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+static int APP_CC
+clipboard_get_files(char *files, int bytes)
+{
+ int index;
+ int file_index;
+ char file[512];
+
+ g_num_files = 0;
+ file_index = 0;
+ for (index = 0; index < bytes; index++)
+ {
+ if (files[index] == '\n' || files[index] == '\r')
+ {
+ if (file_index > 0)
+ {
+ if (clipboard_get_file(file, file_index) == 0)
+ {
+ }
+ file_index = 0;
+ }
+ }
+ else
+ {
+ file[file_index] = files[index];
+ file_index++;
+ }
+ if (g_num_files > 60)
+ {
+ break;
+ }
+ }
+ if (file_index > 0)
+ {
+ if (clipboard_get_file(file, file_index) == 0)
+ {
+ }
+ }
+ if (g_num_files < 1)
+ {
+ return 1;
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+int APP_CC
+clipboard_send_data_response_for_file(char *data, int data_size)
+{
+ struct stream *s;
+ int size;
+ int rv;
+ int bytes_after_header;
+ int cItems;
+ int flags;
+ int index;
+ char fn[256];
+
+ LLOGLN(10, ("clipboard_send_data_response_for_file: g_last_clip_size %d",
+ g_last_clip_size));
+ g_hexdump(data, data_size);
+ clipboard_get_files(data, data_size);
+ cItems = g_num_files;
+ bytes_after_header = cItems * 592 + 4;
+ make_stream(s);
+ init_stream(s, 64 + bytes_after_header);
+ out_uint16_le(s, CB_FORMAT_DATA_RESPONSE); /* 5 CLIPRDR_DATA_RESPONSE */
+ out_uint16_le(s, 1); // CB_RESPONSE_OK); /* 1 status */
+ out_uint32_le(s, bytes_after_header);
+ out_uint32_le(s, cItems);
+ for (index = 0; index < cItems; index++)
+ {
+ flags = CB_FD_ATTRIBUTES | CB_FD_FILESIZE | CB_FD_WRITESTIME | CB_FD_PROGRESSUI;
+ out_uint32_le(s, flags);
+ out_uint8s(s, 32); /* reserved1 */
+ flags = CB_FILE_ATTRIBUTE_ARCHIVE;
+ //flags = CB_FILE_ATTRIBUTE_NORMAL;
+ out_uint32_le(s, flags);
+ out_uint8s(s, 16); /* reserved2 */
+ /* file time */
+ /* 100-nanoseconds intervals since 1 January 1601 */
+ out_uint32_le(s, 0x2c305d08); /* 25 October 2009, 21:17 */
+ out_uint32_le(s, 0x01ca55f3);
+ /* file size */
+ out_uint32_le(s, 0);
+ out_uint32_le(s, g_files[index].size);
+ g_writeln("jay size %d", g_files[index].size);
+ g_snprintf(fn, 255, "%s", g_files[index].filename);
+ clipboard_out_unicode(s, fn, 256);
+ out_uint8s(s, 8); /* pad */
+ }
+ out_uint32_le(s, 0);
+ s_mark_end(s);
+ size = (int)(s->end - s->data);
+ g_hexdump(s->data, size);
+ rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
+ free_stream(s);
+ return rv;
+}
+
+/*****************************************************************************/
+static int APP_CC
+clipboard_send_file_size(int streamId, int lindex)
+{
+ struct stream *s;
+ int size;
+ int rv;
+ int file_size;
+
+ file_size = g_files[lindex].size;
+ LLOGLN(10, ("clipboard_send_file_size: streamId %d file_size %d",
+ streamId, file_size));
+ make_stream(s);
+ init_stream(s, 8192);
+ out_uint16_le(s, CB_FILECONTENTS_RESPONSE); /* 9 */
+ out_uint16_le(s, CB_RESPONSE_OK); /* 1 status */
+ out_uint32_le(s, 12);
+ out_uint32_le(s, streamId);
+ out_uint32_le(s, file_size);
+ g_writeln("file_size %d", file_size);
+ out_uint32_le(s, 0);
+ out_uint32_le(s, 0);
+ s_mark_end(s);
+ size = (int)(s->end - s->data);
+ rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
+ free_stream(s);
+ return rv;
+}
+
+/*****************************************************************************/
+static int APP_CC
+clipboard_send_file_data(int streamId, int lindex,
+ int nPositionLow, int cbRequested)
+{
+ struct stream *s;
+ int size;
+ int rv;
+ int fd;
+ char full_fn[256];
+
+ LLOGLN(10, ("clipboard_send_file_data: streamId %d lindex %d "
+ "nPositionLow %d cbRequested %d", streamId, lindex,
+ nPositionLow, cbRequested));
+ g_snprintf(full_fn, 255, "%s/%s", g_files[lindex].pathname,
+ g_files[lindex].filename);
+ fd = g_file_open_ex(full_fn, 1, 0, 0, 0);
+ if (fd == -1)
+ {
+ LLOGLN(0, ("clipboard_send_file_data: file open [%s] failed",
+ full_fn));
+ return 1;
+ }
+ g_file_seek(fd, nPositionLow);
+ make_stream(s);
+ init_stream(s, cbRequested + 64);
+ //g_memset(s->data + 12, 26, cbRequested);
+ size = g_file_read(fd, s->data + 12, cbRequested);
+ g_writeln("size %d", size);
+ if (size < 1)
+ {
+ LLOGLN(10, ("clipboard_send_file_data: read error, want %d got %d",
+ cbRequested, size));
+ free_stream(s);
+ g_file_close(fd);
+ return 1;
+ }
+ out_uint16_le(s, CB_FILECONTENTS_RESPONSE); /* 9 */
+ out_uint16_le(s, CB_RESPONSE_OK); /* 1 status */
+ out_uint32_le(s, size + 4);
+ out_uint32_le(s, streamId);
+ s->p += size;
+ out_uint32_le(s, 0);
+ s_mark_end(s);
+ size = (int)(s->end - s->data);
+ rv = send_channel_data(g_cliprdr_chan_id, s->data, size);
+ free_stream(s);
+ g_file_close(fd);
+ return rv;
+}
+
+/*****************************************************************************/
+int APP_CC
+clipboard_process_file_request(struct stream *s, int clip_msg_status,
+ int clip_msg_len)
+{
+ int streamId;
+ int lindex;
+ int dwFlags;
+ int nPositionLow;
+ int nPositionHigh;
+ int cbRequested;
+ //int clipDataId;
+
+ LLOGLN(10, ("clipboard_process_file_request:"));
+ g_hexdump(s->p, clip_msg_len);
+ in_uint32_le(s, streamId);
+ in_uint32_le(s, lindex);
+ in_uint32_le(s, dwFlags);
+ in_uint32_le(s, nPositionLow);
+ in_uint32_le(s, nPositionHigh);
+ in_uint32_le(s, cbRequested);
+ //in_uint32_le(s, clipDataId); /* options, used when locking */
+ if (dwFlags & CB_FILECONTENTS_SIZE)
+ {
+ clipboard_send_file_size(streamId, lindex);
+ }
+ if (dwFlags & CB_FILECONTENTS_RANGE)
+ {
+ clipboard_send_file_data(streamId, lindex, nPositionLow, cbRequested);
+ }
+ return 0;
+}
diff --git a/sesman/chansrv/clipboard_file.h b/sesman/chansrv/clipboard_file.h
new file mode 100644
index 00000000..5bddeb99
--- /dev/null
+++ b/sesman/chansrv/clipboard_file.h
@@ -0,0 +1,31 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#if !defined(CLIPBOARD_FILE_H)
+#define CLIPBOARD_FILE_H
+
+#include "arch.h"
+#include "parse.h"
+
+int APP_CC
+clipboard_send_data_response_for_file(char *data, int data_size);
+int APP_CC
+clipboard_process_file_request(struct stream *s, int clip_msg_status,
+ int clip_msg_len);
+
+#endif