diff --git a/sesman/chansrv/clipboard.c b/sesman/chansrv/clipboard.c index 9ba41b2e4..101f2d3b3 100644 --- a/sesman/chansrv/clipboard.c +++ b/sesman/chansrv/clipboard.c @@ -183,13 +183,21 @@ x-special/gnome-copied-files static char g_bmp_image_header[] = { - /* this is known to work */ - //0x42, 0x4d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - - /* THIS IS BEING SENT BY WIN2008 */ - 0x42, 0x4d, 0x16, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00 + /* + * Bitmap file header + * https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header + * + * NOTE: All of the integer values are stored in little-endian format + */ + 0x42, 0x4d, /* signature */ + 0x00, 0x00, 0x00, 0x00, /* file size, to be filled later */ + 0x00, 0x00, /* reserved 1 */ + 0x00, 0x00, /* reserved 2 */ + 0x36, 0x00, 0x00, 0x00 /* offset to pixel array (14 + 40 bytes) */ }; +#define BMPFILEHEADER_LEN sizeof(g_bmp_image_header) + extern int g_cliprdr_chan_id; /* in chansrv.c */ extern Display *g_display; /* in xcommon.c */ @@ -1135,6 +1143,8 @@ clipboard_process_data_response_for_image(struct stream *s, { XSelectionRequestEvent *lxev; int len; + char bmp_file_header[BMPFILEHEADER_LEN] = { 0 }; + uint32_t bmp_size; /* file size stored in bmp file header */ LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: " "CLIPRDR_DATA_RESPONSE_FOR_IMAGE"); @@ -1148,20 +1158,35 @@ clipboard_process_data_response_for_image(struct stream *s, { return 0; } + g_free(g_clip_c2s.data); - g_clip_c2s.data = (char *) g_malloc(len + 14, 0); + g_clip_c2s.data = (char *) g_malloc(len + BMPFILEHEADER_LEN, 0); if (g_clip_c2s.data == 0) { g_clip_c2s.total_bytes = 0; return 0; } - g_clip_c2s.total_bytes = len; + g_clip_c2s.total_bytes = len + BMPFILEHEADER_LEN; g_clip_c2s.read_bytes_done = g_clip_c2s.total_bytes; - g_memcpy(g_clip_c2s.data, g_bmp_image_header, 14); - in_uint8a(s, g_clip_c2s.data + 14, len); + + /* assemble bmp header */ + g_memcpy(bmp_file_header, g_bmp_image_header, BMPFILEHEADER_LEN); + bmp_size = (uint32_t) g_clip_c2s.total_bytes; +#if defined(L_ENDIAN) + for (int i = 2, j = 0; i < 6; i++, j += 8) +#else + for (int i = 5, j = 0; i >= 2; i--, j += 8) +#endif + { + bmp_file_header[i] = ((bmp_size >> j) & 0xff); + } + + g_memcpy(g_clip_c2s.data, bmp_file_header, BMPFILEHEADER_LEN); + in_uint8a(s, g_clip_c2s.data + BMPFILEHEADER_LEN, len); LOG_DEVEL(LOG_LEVEL_DEBUG, "clipboard_process_data_response_for_image: calling " "clipboard_provide_selection_c2s"); clipboard_provide_selection_c2s(lxev, lxev->target); + return 0; }