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; @@ -643,164 +634,6 @@ clipboard_send_data_response_for_text(char* data, int data_size) return rv; } -/*****************************************************************************/ -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) @@ -1252,119 +1085,6 @@ clipboard_process_clip_caps(struct stream *s, int clip_msg_status, return 0; } -/*****************************************************************************/ -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, 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 +#include +#include +#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