static void xf_cliprdr_process_html(clipboardContext* cb, BYTE* data, int size) { char* start_str; char* end_str; int start; int end; start_str = strstr((char*) data, "StartHTML:"); end_str = strstr((char*) data, "EndHTML:"); if (start_str == NULL || end_str == NULL) { DEBUG_X11_CLIPRDR("invalid HTML clipboard format"); return; } start = atoi(start_str + 10); end = atoi(end_str + 8); if (start > size || end > size || start >= end) { DEBUG_X11_CLIPRDR("invalid HTML offset"); return; } cb->data = (BYTE*) malloc(size - start + 1); CopyMemory(cb->data, data + start, end - start); cb->data_length = end - start; crlf2lf(cb->data, &cb->data_length); }
static void xf_cliprdr_process_text(clipboardContext* cb, BYTE* data, int size) { cb->data = (BYTE*) malloc(size); CopyMemory(cb->data, data, size); cb->data_length = size; crlf2lf(cb->data, &cb->data_length); }
static void xf_cliprdr_process_text(clipboardContext* cb, uint8* data, int size) { cb->data = (uint8*) xmalloc(size); memcpy(cb->data, data, size); cb->data_length = size; crlf2lf(cb->data, &cb->data_length); }
static void xf_cliprdr_process_unicodetext(clipboardContext* cb, uint8* data, int size) { UNICONV* uniconv; uniconv = freerdp_uniconv_new(); cb->data = (uint8*) freerdp_uniconv_in(uniconv, data, size); freerdp_uniconv_free(uniconv); cb->data_length = strlen((char*) cb->data); crlf2lf(cb->data, &cb->data_length); }
static void xf_cliprdr_process_unicodetext(clipboardContext* cb, BYTE* data, int size) { cb->data_length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) data, size / 2, (CHAR**) &(cb->data), 0, NULL, NULL); crlf2lf(cb->data, &cb->data_length); }
void remmina_rdp_cliprdr_process_data_response(RemminaProtocolWidget* gp, RDP_CB_DATA_RESPONSE_EVENT* event) { UINT8* data; size_t size; rfContext* rfi = GET_DATA(gp); GdkPixbufLoader *pixbuf; gpointer output = NULL; data = event->data; size = event->size; if (size > 0) { switch (rfi->format) { case CB_FORMAT_UNICODETEXT: { size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)data, size / 2, (CHAR**)&data, 0, NULL, NULL); crlf2lf(data, &size); output = data; break; } case CB_FORMAT_TEXT: case CB_FORMAT_HTML: { crlf2lf(data, &size); output = data; break; } case CB_FORMAT_DIB: { wStream* s; UINT16 bpp; UINT32 offset; UINT32 ncolors; s = Stream_New(data, size); Stream_Seek(s, 14); Stream_Read_UINT16(s, bpp); Stream_Read_UINT32(s, ncolors); offset = 14 + 40 + (bpp <= 8 ? (ncolors == 0 ? (1 << bpp) : ncolors) * 4 : 0); Stream_Free(s, TRUE); s = Stream_New(NULL, 14 + size); Stream_Write_UINT8(s, 'B'); Stream_Write_UINT8(s, 'M'); Stream_Write_UINT32(s, 14 + size); Stream_Write_UINT32(s, 0); Stream_Write_UINT32(s, offset); Stream_Write(s, data, size); data = Stream_Buffer(s); size = Stream_Length(s); pixbuf = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(pixbuf, data, size, NULL); gdk_pixbuf_loader_close(pixbuf, NULL); Stream_Free(s, TRUE); output = g_object_ref(gdk_pixbuf_loader_get_pixbuf(pixbuf)); g_object_unref(pixbuf); break; } case CB_FORMAT_PNG: case CB_FORMAT_JPEG: { pixbuf = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(pixbuf, data, size, NULL); output = g_object_ref(gdk_pixbuf_loader_get_pixbuf(pixbuf)); gdk_pixbuf_loader_close(pixbuf, NULL); g_object_unref(pixbuf); break; } } } g_async_queue_push(rfi->clipboard_queue, output); }
static void xf_cliprdr_process_unicodetext(clipboardContext* cb, BYTE* data, int size) { cb->data_length = freerdp_UnicodeToAsciiAlloc((WCHAR*) data, (CHAR**) &(cb->data), size / 2); crlf2lf(cb->data, &cb->data_length); }
static UINT remmina_rdp_cliprdr_server_format_data_response(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) { TRACE_CALL(__func__); UINT8* data; size_t size; rfContext* rfi; RemminaProtocolWidget* gp; rfClipboard* clipboard; GdkPixbufLoader *pixbuf; gpointer output = NULL; RemminaPluginRdpUiObject *ui; clipboard = (rfClipboard*)context->custom; gp = clipboard->rfi->protocol_widget; rfi = GET_PLUGIN_DATA(gp); data = formatDataResponse->requestedFormatData; size = formatDataResponse->dataLen; // formatDataResponse->requestedFormatData is allocated // by freerdp and freed after returning from this callback function. // So we must make a copy if we need to preserve it if (size > 0) { switch (rfi->clipboard.format) { case CF_UNICODETEXT: { size = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)data, size / 2, (CHAR**)&output, 0, NULL, NULL); crlf2lf(output, &size); break; } case CF_TEXT: case CB_FORMAT_HTML: { output = (gpointer)calloc(1, size + 1); if (output) { memcpy(output, data, size); crlf2lf(output, &size); } break; } case CF_DIBV5: case CF_DIB: { wStream* s; UINT32 offset; GError *perr; BITMAPINFOHEADER* pbi; BITMAPV5HEADER* pbi5; pbi = (BITMAPINFOHEADER*)data; // offset calculation inspired by http://downloads.poolelan.com/MSDN/MSDNLibrary6/Disk1/Samples/VC/OS/WindowsXP/GetImage/BitmapUtil.cpp offset = 14 + pbi->biSize; if (pbi->biClrUsed != 0) offset += sizeof(RGBQUAD) * pbi->biClrUsed; else if (pbi->biBitCount <= 8) offset += sizeof(RGBQUAD) * (1 << pbi->biBitCount); if (pbi->biSize == sizeof(BITMAPINFOHEADER)) { if (pbi->biCompression == 3) // BI_BITFIELDS is 3 offset += 12; } else if (pbi->biSize >= sizeof(BITMAPV5HEADER)) { pbi5 = (BITMAPV5HEADER*)pbi; if (pbi5->bV5ProfileData <= offset) offset += pbi5->bV5ProfileSize; } s = Stream_New(NULL, 14 + size); Stream_Write_UINT8(s, 'B'); Stream_Write_UINT8(s, 'M'); Stream_Write_UINT32(s, 14 + size); Stream_Write_UINT32(s, 0); Stream_Write_UINT32(s, offset); Stream_Write(s, data, size); data = Stream_Buffer(s); size = Stream_Length(s); pixbuf = gdk_pixbuf_loader_new(); perr = NULL; if ( !gdk_pixbuf_loader_write(pixbuf, data, size, &perr) ) { remmina_plugin_service->log_printf("[RDP] rdp_cliprdr: gdk_pixbuf_loader_write() returned error %s\n", perr->message); }else { if ( !gdk_pixbuf_loader_close(pixbuf, &perr) ) { remmina_plugin_service->log_printf("[RDP] rdp_cliprdr: gdk_pixbuf_loader_close() returned error %s\n", perr->message); perr = NULL; } Stream_Free(s, TRUE); output = g_object_ref(gdk_pixbuf_loader_get_pixbuf(pixbuf)); } g_object_unref(pixbuf); break; } case CB_FORMAT_PNG: case CB_FORMAT_JPEG: { pixbuf = gdk_pixbuf_loader_new(); gdk_pixbuf_loader_write(pixbuf, data, size, NULL); output = g_object_ref(gdk_pixbuf_loader_get_pixbuf(pixbuf)); gdk_pixbuf_loader_close(pixbuf, NULL); g_object_unref(pixbuf); break; } } } pthread_mutex_lock(&clipboard->transfer_clip_mutex); pthread_cond_signal(&clipboard->transfer_clip_cond); if ( clipboard->srv_clip_data_wait == SCDW_BUSY_WAIT ) { clipboard->srv_data = output; }else { // Clipboard data arrived from server when we are not busywaiting. // Just put it on the local clipboard ui = g_new0(RemminaPluginRdpUiObject, 1); ui->type = REMMINA_RDP_UI_CLIPBOARD; ui->clipboard.clipboard = clipboard; ui->clipboard.type = REMMINA_RDP_UI_CLIPBOARD_SET_CONTENT; ui->clipboard.data = output; ui->clipboard.format = clipboard->format; remmina_rdp_event_queue_ui_sync_retint(gp, ui); clipboard->srv_clip_data_wait = SCDW_NONE; } pthread_mutex_unlock(&clipboard->transfer_clip_mutex); return CHANNEL_RC_OK; }