diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index b63a4ed0..036ae6f8 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -33,6 +33,7 @@ #include "os_calls.h" #include "chansrv.h" #include "chansrv_fuse.h" +#include "clipboard_file.h" #define LLOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -56,6 +57,9 @@ static time_t g_time = 0; static int g_uid = 0; static int g_gid = 0; +/* used for file data request sent to client */ +static fuse_req_t g_req = 0; + struct dirbuf { char *p; @@ -66,6 +70,7 @@ struct dirbuf struct xfuse_file_info { int ino; + int lindex; char pathname[256]; char filename[256]; int flags; @@ -252,8 +257,8 @@ dirbuf_add(fuse_req_t req, struct dirbuf *b, const char *name, fuse_ino_t ino) } g_memset(&stbuf, 0, sizeof(stbuf)); stbuf.st_ino = ino; - fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, &stbuf, - b->size); + fuse_add_direntry(req, b->p + oldsize, b->size - oldsize, name, + &stbuf, b->size); } #define lmin(x, y) ((x) < (y) ? (x) : (y)) @@ -331,11 +336,26 @@ xrdp_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi) { char *data; + int stream_id; + struct xfuse_file_info *ffi; LLOGLN(0, ("xrdp_ll_read: %d %d %d", (int)ino, (int)off, (int)size)); + + ffi = fuse_find_file_info_by_ino(g_fuse_files, ino); + if (ffi != 0) + { + stream_id = 0; + clipboard_request_file_data(stream_id, ffi->lindex, off, size); + g_req = req; + /* reply later */ + return; + } + + LLOGLN(0, ("xrdp_ll_read: fuse_find_file_info_by_ino failed")); data = (char *)g_malloc(size, 1); - reply_buf_limited(req, data, size, off, size); + fuse_reply_buf(req, data, size); g_free(data); + } /*****************************************************************************/ @@ -409,7 +429,7 @@ fuse_clear_clip_dir(void) /*****************************************************************************/ /* returns error */ int APP_CC -fuse_add_clip_dir_item(char *filename, int flags, int size) +fuse_add_clip_dir_item(char *filename, int flags, int size, int lindex) { struct xfuse_file_info *ffi; struct xfuse_file_info *ffi1; @@ -422,6 +442,7 @@ fuse_add_clip_dir_item(char *filename, int flags, int size) g_malloc(sizeof(struct xfuse_file_info), 1); ffi1->flags = flags; ffi1->ino = g_ino++; + ffi1->lindex = lindex; ffi1->size = size; g_strncpy(ffi1->filename, filename, 255); g_fuse_files = ffi1; @@ -435,6 +456,7 @@ fuse_add_clip_dir_item(char *filename, int flags, int size) g_malloc(sizeof(struct xfuse_file_info), 1); ffi1->flags = flags; ffi1->ino = g_ino++; + ffi1->lindex = lindex; ffi1->size = size; g_strncpy(ffi1->filename, filename, 255); ffi->next = ffi1; @@ -549,6 +571,23 @@ fuse_deinit(void) return 0; } +/*****************************************************************************/ +int APP_CC +fuse_file_contents_size(int stream_id, int file_size) +{ + LLOGLN(0, ("fuse_file_contents_size: file_size %d", file_size)); + return 0; +} + +/*****************************************************************************/ +int APP_CC +fuse_file_contents_range(int stream_id, char *data, int data_bytes) +{ + LLOGLN(0, ("fuse_file_contents_range: data_bytes %d", data_bytes)); + fuse_reply_buf(g_req, data, data_bytes); + return 0; +} + #else #include "arch.h" @@ -590,7 +629,21 @@ fuse_clear_clip_dir(void) /*****************************************************************************/ int APP_CC -fuse_add_clip_dir_item(char *filename, int flags, int size) +fuse_add_clip_dir_item(char *filename, int flags, int size, int lindex) +{ + return 0; +} + +/*****************************************************************************/ +int APP_CC +fuse_file_contents_size(int stream_id, int file_size) +{ + return 0; +} + +/*****************************************************************************/ +int APP_CC +fuse_file_contents_range(int stream_id, char *data, int data_bytes) { return 0; } diff --git a/sesman/chansrv/chansrv_fuse.h b/sesman/chansrv/chansrv_fuse.h index 80427699..0ccde368 100644 --- a/sesman/chansrv/chansrv_fuse.h +++ b/sesman/chansrv/chansrv_fuse.h @@ -5,7 +5,7 @@ int APP_CC fuse_clear_clip_dir(void); int APP_CC -fuse_add_clip_dir_item(char *filename, int flags, int size); +fuse_add_clip_dir_item(char *filename, int flags, int size, int lindex); int APP_CC fuse_get_wait_objs(tbus *objs, int *count, int *timeout); int APP_CC @@ -15,4 +15,9 @@ fuse_init(void); int APP_CC fuse_deinit(void); +int APP_CC +fuse_file_contents_size(int stream_id, int file_size); +int APP_CC +fuse_file_contents_range(int stream_id, char *data, int data_bytes); + #endif diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index 9a2ab708..e3018179 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -42,6 +42,76 @@ TIMESTAMP wininfo - show window info xlsatoms - dump atoms +dolphin 1.4 KDE 4.4.5 copy one file +text/uri-list +text/x-moz-url +text/plain +UTF8_STRING +STRING +TEXT +COMPOUND_TEXT +application/x-qiconlist +TARGETS +MULTIPLE +TIMESTAMP +SAVE_TARGETS + +kolourpaint 4.4.5 KDE 4.4.5 copy image area +application/x-kolourpaint-selection-400 +application/x-qt-image +image/png +image/bw +image/eps +image/epsf +image/epsi +image/pcx +image/rgb +image/rgba +image/sgi +image/tga +image/bmp +image/ico +image/jp2 +image/jpeg +image/jpg +image/ppm +PIXMAP +image/tif +image/tiff +image/xbm +image/xpm +image/xv +TARGETS +MULTIPLE +TIMESTAMP +SAVE_TARGETS + +kate 3.4.5 KDE 4.4.5 copy text +text/plain +UTF8_STRING +STRING +TEXT +COMPOUND_TEXT +TARGETS +MULTIPLE +TIMESTAMP +SAVE_TARGETS + +gimp 2.6.10 copy image area +TIMESTAMP +TARGETS +MULTIPLE +SAVE_TARGETS +image/png +image/bmp +image/x-bmp +image/x-MS-bmp +image/tiff +image/x-icon +image/x-ico +image/x-win-bitmap +image/jpeg + */ #include @@ -1280,6 +1350,10 @@ clipboard_data_in(struct stream *s, int chan_id, int chan_flags, int length, rv = clipboard_process_file_request(ls, clip_msg_status, clip_msg_len); break; + case CB_FILECONTENTS_RESPONSE: /* 9 */ + rv = clipboard_process_file_response(ls, clip_msg_status, + clip_msg_len); + break; default: LLOGLN(0, ("clipboard_data_in: unknown clip_msg_id %d", clip_msg_id)); LOGM((LOG_LEVEL_ERROR, "clipboard_data_in: unknown clip_msg_id %d", diff --git a/sesman/chansrv/clipboard_file.c b/sesman/chansrv/clipboard_file.c index e169d89f..b60a1bad 100644 --- a/sesman/chansrv/clipboard_file.c +++ b/sesman/chansrv/clipboard_file.c @@ -77,6 +77,7 @@ struct clip_file_desc /* CLIPRDR_FILEDESCRIPTOR */ static struct cb_file_info g_files[64]; static int g_num_files = 0; +static int g_file_request_sent_type = 0; /* number of seconds from 1 Jan. 1601 00:00 to 1 Jan 1970 00:00 UTC */ #define CB_EPOCH_DIFF 11644473600LL @@ -336,7 +337,7 @@ clipboard_send_file_size(int streamId, int lindex) /*****************************************************************************/ /* ask the client to send the file size */ int APP_CC -clipboard_request_file_size(int streamId, int lindex) +clipboard_request_file_size(int stream_id, int lindex) { struct stream *s; int size; @@ -345,12 +346,17 @@ clipboard_request_file_size(int streamId, int lindex) file_size = g_files[lindex].size; LLOGLN(10, ("clipboard_request_file_size:")); + if (g_file_request_sent_type != 0) + { + LLOGLN(0, ("clipboard_request_file_size: warning, still waiting " + "for CB_FILECONTENTS_RESPONSE")); + } make_stream(s); init_stream(s, 8192); out_uint16_le(s, CB_FILECONTENTS_REQUEST); /* 8 */ out_uint16_le(s, 0); out_uint32_le(s, 28); - out_uint32_le(s, streamId); + out_uint32_le(s, stream_id); out_uint32_le(s, lindex); out_uint32_le(s, CB_FILECONTENTS_SIZE); out_uint32_le(s, 0); /* nPositionLow */ @@ -362,6 +368,7 @@ clipboard_request_file_size(int streamId, int lindex) size = (int)(s->end - s->data); rv = send_channel_data(g_cliprdr_chan_id, s->data, size); free_stream(s); + g_file_request_sent_type = CB_FILECONTENTS_SIZE; return rv; } @@ -417,6 +424,46 @@ clipboard_send_file_data(int streamId, int lindex, return rv; } +/*****************************************************************************/ +/* ask the client to send the file size */ +int APP_CC +clipboard_request_file_data(int stream_id, int lindex, int offset, + int request_bytes) +{ + struct stream *s; + int size; + int rv; + int file_size; + + file_size = g_files[lindex].size; + LLOGLN(10, ("clipboard_request_file_data:")); + if (g_file_request_sent_type != 0) + { + LLOGLN(0, ("clipboard_request_file_data: warning, still waiting " + "for CB_FILECONTENTS_RESPONSE")); + } + make_stream(s); + init_stream(s, 8192); + out_uint16_le(s, CB_FILECONTENTS_REQUEST); /* 8 */ + out_uint16_le(s, 0); + out_uint32_le(s, 28); + out_uint32_le(s, stream_id); + out_uint32_le(s, lindex); + out_uint32_le(s, CB_FILECONTENTS_RANGE); + out_uint32_le(s, offset); /* nPositionLow */ + out_uint32_le(s, 0); /* nPositionHigh */ + out_uint32_le(s, request_bytes); /* cbRequested */ + out_uint32_le(s, 0); /* clipDataId */ + 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_request_sent_type = CB_FILECONTENTS_RANGE; + return rv; +} + + /*****************************************************************************/ int APP_CC clipboard_process_file_request(struct stream *s, int clip_msg_status, @@ -450,6 +497,35 @@ clipboard_process_file_request(struct stream *s, int clip_msg_status, return 0; } +/*****************************************************************************/ +/* server requested info about the file and this is the responce + it's either the file size or file data */ +int APP_CC +clipboard_process_file_response(struct stream *s, int clip_msg_status, + int clip_msg_len) +{ + int streamId; + int file_size; + char *data; + + LLOGLN(0, ("clipboard_process_file_response:")); + if (g_file_request_sent_type == CB_FILECONTENTS_SIZE) + { + in_uint32_le(s, streamId); + in_uint32_le(s, file_size); + LLOGLN(0, ("clipboard_process_file_response: streamId %d " + "file_size %d", streamId, file_size)); + fuse_file_contents_size(streamId, file_size); + } + else if (g_file_request_sent_type == CB_FILECONTENTS_RANGE) + { + in_uint32_le(s, streamId); + fuse_file_contents_range(streamId, s->p, clip_msg_len - 4); + } + g_file_request_sent_type = 0; + return 0; +} + /*****************************************************************************/ /* read in CLIPRDR_FILEDESCRIPTOR */ static int APP_CC @@ -487,17 +563,17 @@ clipboard_c2s_in_file_info(struct stream *s, struct clip_file_desc *cfd) int APP_CC clipboard_c2s_in_files(struct stream *s) { - tui32 cItems; + int cItems; + int lindex; struct clip_file_desc cfd; in_uint32_le(s, cItems); fuse_clear_clip_dir(); LLOGLN(0, ("clipboard_c2s_in_files: cItems %d", cItems)); - while (cItems > 0) + for (lindex = 0; lindex < cItems; lindex++) { clipboard_c2s_in_file_info(s, &cfd); - fuse_add_clip_dir_item(cfd.cFileName, 0, cfd.fileSizeLow); - cItems--; + fuse_add_clip_dir_item(cfd.cFileName, 0, cfd.fileSizeLow, lindex); } return 0; } diff --git a/sesman/chansrv/clipboard_file.h b/sesman/chansrv/clipboard_file.h index 37391c4c..46c41d51 100644 --- a/sesman/chansrv/clipboard_file.h +++ b/sesman/chansrv/clipboard_file.h @@ -31,6 +31,9 @@ int APP_CC clipboard_c2s_in_files(struct stream *s); int APP_CC -clipboard_request_file_size(int streamId, int lindex); +clipboard_request_file_size(int stream_id, int lindex); +int APP_CC +clipboard_request_file_data(int stream_id, int lindex, int offset, + int request_bytes); #endif