/src/FreeRDP/channels/cliprdr/client/cliprdr_format.c
Line | Count | Source (jump to first uncovered line) |
1 | | /** |
2 | | * FreeRDP: A Remote Desktop Protocol Implementation |
3 | | * Clipboard Virtual Channel |
4 | | * |
5 | | * Copyright 2009-2011 Jay Sorg |
6 | | * Copyright 2010-2011 Vic Lee |
7 | | * Copyright 2015 Thincast Technologies GmbH |
8 | | * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com> |
9 | | * |
10 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
11 | | * you may not use this file except in compliance with the License. |
12 | | * You may obtain a copy of the License at |
13 | | * |
14 | | * http://www.apache.org/licenses/LICENSE-2.0 |
15 | | * |
16 | | * Unless required by applicable law or agreed to in writing, software |
17 | | * distributed under the License is distributed on an "AS IS" BASIS, |
18 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
19 | | * See the License for the specific language governing permissions and |
20 | | * limitations under the License. |
21 | | */ |
22 | | |
23 | | #include <freerdp/config.h> |
24 | | |
25 | | #include <winpr/crt.h> |
26 | | #include <winpr/print.h> |
27 | | |
28 | | #include <freerdp/types.h> |
29 | | #include <freerdp/freerdp.h> |
30 | | #include <freerdp/settings.h> |
31 | | #include <freerdp/constants.h> |
32 | | #include <freerdp/client/cliprdr.h> |
33 | | |
34 | | #include "cliprdr_main.h" |
35 | | #include "cliprdr_format.h" |
36 | | #include "../cliprdr_common.h" |
37 | | |
38 | | CLIPRDR_FORMAT_LIST cliprdr_filter_format_list(const CLIPRDR_FORMAT_LIST* list, const UINT32 mask, |
39 | | const UINT32 checkMask) |
40 | 0 | { |
41 | 0 | const UINT32 maskData = |
42 | 0 | checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_REMOTE_TO_LOCAL); |
43 | 0 | const UINT32 maskFiles = |
44 | 0 | checkMask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES); |
45 | 0 | WINPR_ASSERT(list); |
46 | | |
47 | 0 | CLIPRDR_FORMAT_LIST filtered = { 0 }; |
48 | 0 | filtered.common.msgType = CB_FORMAT_LIST; |
49 | 0 | filtered.numFormats = list->numFormats; |
50 | 0 | filtered.formats = calloc(filtered.numFormats, sizeof(CLIPRDR_FORMAT)); |
51 | |
|
52 | 0 | size_t wpos = 0; |
53 | 0 | if ((mask & checkMask) == checkMask) |
54 | 0 | { |
55 | 0 | for (size_t x = 0; x < list->numFormats; x++) |
56 | 0 | { |
57 | 0 | const CLIPRDR_FORMAT* format = &list->formats[x]; |
58 | 0 | CLIPRDR_FORMAT* cur = &filtered.formats[x]; |
59 | 0 | cur->formatId = format->formatId; |
60 | 0 | if (format->formatName) |
61 | 0 | cur->formatName = _strdup(format->formatName); |
62 | 0 | wpos++; |
63 | 0 | } |
64 | 0 | } |
65 | 0 | else if ((mask & maskFiles) != 0) |
66 | 0 | { |
67 | 0 | for (size_t x = 0; x < list->numFormats; x++) |
68 | 0 | { |
69 | 0 | const CLIPRDR_FORMAT* format = &list->formats[x]; |
70 | 0 | CLIPRDR_FORMAT* cur = &filtered.formats[wpos]; |
71 | |
|
72 | 0 | if (!format->formatName) |
73 | 0 | continue; |
74 | 0 | if (strcmp(format->formatName, type_FileGroupDescriptorW) == 0 || |
75 | 0 | strcmp(format->formatName, type_FileContents) == 0) |
76 | 0 | { |
77 | 0 | cur->formatId = format->formatId; |
78 | 0 | cur->formatName = _strdup(format->formatName); |
79 | 0 | wpos++; |
80 | 0 | } |
81 | 0 | } |
82 | 0 | } |
83 | 0 | else if ((mask & maskData) != 0) |
84 | 0 | { |
85 | 0 | for (size_t x = 0; x < list->numFormats; x++) |
86 | 0 | { |
87 | 0 | const CLIPRDR_FORMAT* format = &list->formats[x]; |
88 | 0 | CLIPRDR_FORMAT* cur = &filtered.formats[wpos]; |
89 | |
|
90 | 0 | if (!format->formatName || |
91 | 0 | (strcmp(format->formatName, type_FileGroupDescriptorW) != 0 && |
92 | 0 | strcmp(format->formatName, type_FileContents) != 0)) |
93 | 0 | { |
94 | 0 | cur->formatId = format->formatId; |
95 | 0 | if (format->formatName) |
96 | 0 | cur->formatName = _strdup(format->formatName); |
97 | 0 | wpos++; |
98 | 0 | } |
99 | 0 | } |
100 | 0 | } |
101 | 0 | filtered.numFormats = wpos; |
102 | 0 | return filtered; |
103 | 0 | } |
104 | | |
105 | | /** |
106 | | * Function description |
107 | | * |
108 | | * @return 0 on success, otherwise a Win32 error code |
109 | | */ |
110 | | UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, |
111 | | UINT16 msgFlags) |
112 | 0 | { |
113 | 0 | CLIPRDR_FORMAT_LIST formatList = { 0 }; |
114 | 0 | CLIPRDR_FORMAT_LIST filteredFormatList = { 0 }; |
115 | 0 | CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); |
116 | 0 | UINT error = CHANNEL_RC_OK; |
117 | |
|
118 | 0 | formatList.common.msgType = CB_FORMAT_LIST; |
119 | 0 | formatList.common.msgFlags = msgFlags; |
120 | 0 | formatList.common.dataLen = dataLen; |
121 | |
|
122 | 0 | if ((error = cliprdr_read_format_list(s, &formatList, cliprdr->useLongFormatNames))) |
123 | 0 | goto error_out; |
124 | | |
125 | 0 | const UINT32 mask = |
126 | 0 | freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask); |
127 | 0 | filteredFormatList = cliprdr_filter_format_list( |
128 | 0 | &formatList, mask, CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES); |
129 | 0 | if (filteredFormatList.numFormats == 0) |
130 | 0 | goto error_out; |
131 | | |
132 | 0 | WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %" PRIu32 "", |
133 | 0 | filteredFormatList.numFormats); |
134 | |
|
135 | 0 | if (context->ServerFormatList) |
136 | 0 | { |
137 | 0 | if ((error = context->ServerFormatList(context, &filteredFormatList))) |
138 | 0 | WLog_ERR(TAG, "ServerFormatList failed with error %" PRIu32 "", error); |
139 | 0 | } |
140 | |
|
141 | 0 | error_out: |
142 | 0 | cliprdr_free_format_list(&filteredFormatList); |
143 | 0 | cliprdr_free_format_list(&formatList); |
144 | 0 | return error; |
145 | 0 | } |
146 | | |
147 | | /** |
148 | | * Function description |
149 | | * |
150 | | * @return 0 on success, otherwise a Win32 error code |
151 | | */ |
152 | | UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, |
153 | | UINT16 msgFlags) |
154 | 0 | { |
155 | 0 | CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse = { 0 }; |
156 | 0 | CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); |
157 | 0 | UINT error = CHANNEL_RC_OK; |
158 | |
|
159 | 0 | WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatListResponse"); |
160 | |
|
161 | 0 | formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE; |
162 | 0 | formatListResponse.common.msgFlags = msgFlags; |
163 | 0 | formatListResponse.common.dataLen = dataLen; |
164 | |
|
165 | 0 | IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse); |
166 | 0 | if (error) |
167 | 0 | WLog_ERR(TAG, "ServerFormatListResponse failed with error %" PRIu32 "!", error); |
168 | |
|
169 | 0 | return error; |
170 | 0 | } |
171 | | |
172 | | /** |
173 | | * Function description |
174 | | * |
175 | | * @return 0 on success, otherwise a Win32 error code |
176 | | */ |
177 | | UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, |
178 | | UINT16 msgFlags) |
179 | 0 | { |
180 | 0 | CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = { 0 }; |
181 | 0 | CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); |
182 | 0 | UINT error = CHANNEL_RC_OK; |
183 | |
|
184 | 0 | WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataRequest"); |
185 | |
|
186 | 0 | formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST; |
187 | 0 | formatDataRequest.common.msgFlags = msgFlags; |
188 | 0 | formatDataRequest.common.dataLen = dataLen; |
189 | |
|
190 | 0 | if ((error = cliprdr_read_format_data_request(s, &formatDataRequest))) |
191 | 0 | return error; |
192 | | |
193 | 0 | const UINT32 mask = |
194 | 0 | freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask); |
195 | 0 | if ((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) == 0) |
196 | 0 | { |
197 | 0 | return cliprdr_send_error_response(cliprdr, CB_FORMAT_DATA_RESPONSE); |
198 | 0 | } |
199 | | |
200 | 0 | context->lastRequestedFormatId = formatDataRequest.requestedFormatId; |
201 | 0 | IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest); |
202 | 0 | if (error) |
203 | 0 | WLog_ERR(TAG, "ServerFormatDataRequest failed with error %" PRIu32 "!", error); |
204 | |
|
205 | 0 | return error; |
206 | 0 | } |
207 | | |
208 | | /** |
209 | | * Function description |
210 | | * |
211 | | * @return 0 on success, otherwise a Win32 error code |
212 | | */ |
213 | | UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, |
214 | | UINT16 msgFlags) |
215 | 0 | { |
216 | 0 | CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse = { 0 }; |
217 | 0 | CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); |
218 | 0 | UINT error = CHANNEL_RC_OK; |
219 | |
|
220 | 0 | WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatDataResponse"); |
221 | |
|
222 | 0 | formatDataResponse.common.msgType = CB_FORMAT_DATA_RESPONSE; |
223 | 0 | formatDataResponse.common.msgFlags = msgFlags; |
224 | 0 | formatDataResponse.common.dataLen = dataLen; |
225 | |
|
226 | 0 | if ((error = cliprdr_read_format_data_response(s, &formatDataResponse))) |
227 | 0 | return error; |
228 | | |
229 | 0 | const UINT32 mask = |
230 | 0 | freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask); |
231 | 0 | if ((mask & (CLIPRDR_FLAG_REMOTE_TO_LOCAL | CLIPRDR_FLAG_REMOTE_TO_LOCAL_FILES)) == 0) |
232 | 0 | { |
233 | 0 | WLog_WARN(TAG, |
234 | 0 | "Received ServerFormatDataResponse but remote -> local clipboard is disabled"); |
235 | 0 | return CHANNEL_RC_OK; |
236 | 0 | } |
237 | | |
238 | 0 | IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse); |
239 | 0 | if (error) |
240 | 0 | WLog_ERR(TAG, "ServerFormatDataResponse failed with error %" PRIu32 "!", error); |
241 | |
|
242 | 0 | return error; |
243 | 0 | } |