/[rdesktop]/sourceforge.net/trunk/rdesktop/cliprdr.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/cliprdr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 385 - (show annotations)
Fri Jun 6 09:23:28 2003 UTC (20 years, 11 months ago) by forsberg
File MIME type: text/plain
File size: 11376 byte(s)
More proof-of-concept:

* Send a hardcoded string to the server when it wants our clipboard data.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Protocol services - Clipboard functions
4 Copyright (C) Erik Forsberg <forsberg@cendio.se> 2003
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <X11/Xlib.h>
22 #include <X11/Xatom.h>
23 #include "rdesktop.h"
24
25 extern BOOL encryption;
26 extern Display *display;
27 extern Window wnd;
28 extern Time last_keyrelease;
29
30 static Atom clipboard_atom, primary_atom, targets_atom, timestamp_atom;
31 static cliprdr_dataformat *server_formats = NULL;
32 static uint16 num_server_formats = 0;
33 static XSelectionEvent selection_event;
34
35 static void
36 cliprdr_print_server_formats(void)
37 {
38 #ifdef WITH_DEBUG_CLIPBOARD
39 cliprdr_dataformat *this;
40 uint16 i = 0;
41 this = server_formats;
42 DEBUG_CLIPBOARD(("There should be %d server formats.\n", num_server_formats));
43 while (NULL != this)
44 {
45 DEBUG_CLIPBOARD(("Format code %d\n", this->identifier));
46 i++;
47 this = this->next;
48 }
49 DEBUG_CLIPBOARD(("There were %d server formats.\n", i));
50 #endif
51 }
52
53 void
54 cliprdr_handle_SelectionNotify(void)
55 {
56 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionNotify\n"));
57 }
58
59 void
60 cliprdr_handle_SelectionClear(void)
61 {
62 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionClear\n"));
63 }
64
65 void print_X_error(int res)
66 {
67 switch(res) {
68 case Success:
69 DEBUG_CLIPBOARD(("Success\n"));
70 break;
71
72 case BadAtom:
73 DEBUG_CLIPBOARD(("BadAtom\n"));
74 break;
75
76 case BadRequest:
77 DEBUG_CLIPBOARD(("BadRequest\n"));
78 break;
79
80 case BadAlloc:
81 DEBUG_CLIPBOARD(("BadAlloc\n"));
82 break;
83
84 case BadMatch:
85 DEBUG_CLIPBOARD(("BadMatch\n"));
86 break;
87
88 case BadValue:
89 DEBUG_CLIPBOARD(("BadValue\n"));
90 break;
91
92 case BadWindow:
93 DEBUG_CLIPBOARD(("BadWindow\n"));
94 break;
95
96 default:
97 DEBUG_CLIPBOARD(("Unknown X error code %d\n", res));
98 }
99 }
100
101 static void
102 cliprdr_request_clipboard_data(uint32 formatcode)
103 {
104 STREAM s;
105 s = sec_init(encryption ? SEC_ENCRYPT : 0, 24);
106 out_uint32_le(s, 16);
107 out_uint32_le(s, 0x13);
108 out_uint16_le(s, 4);
109 out_uint16_le(s, 0);
110 out_uint32_le(s, 4); // Remaining length
111 out_uint32_le(s, formatcode);
112 out_uint32_le(s, 0); // Unknown. Garbage pad?
113
114 s_mark_end(s);
115
116 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
117 }
118
119
120 void
121 cliprdr_handle_SelectionRequest(XSelectionRequestEvent *xevent)
122 {
123
124 Atom *targets;
125 int res;
126
127 XSelectionEvent xev;
128 DEBUG_CLIPBOARD(("cliprdr_handle_SelectionRequest\n"));
129 DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
130 (unsigned)xevent->requestor));
131 if (clipboard_atom == xevent->selection) {
132 DEBUG_CLIPBOARD(("wants CLIPBOARD\n"));
133 }
134 if (primary_atom == xevent->selection) {
135 DEBUG_CLIPBOARD(("wants PRIMARY\n"));
136 }
137 DEBUG_CLIPBOARD(("Target is %s (0x%x), property is %s (0x%x)\n",
138 XGetAtomName(display, xevent->target),
139 (unsigned)xevent->target,
140 XGetAtomName(display, xevent->property),
141 (unsigned)xevent->property));
142
143 xev.type = SelectionNotify;
144 xev.serial = 0;
145 xev.send_event = True;
146 xev.requestor = xevent->requestor;
147 xev.selection = xevent->selection;
148 xev.target = xevent->target;
149 xev.property = xevent->property;
150 xev.time = xevent->time;
151
152 if (targets_atom == xevent->target)
153 {
154 DEBUG_CLIPBOARD(("TARGETS requested, sending list..\n"));
155 targets = xmalloc(4*sizeof(Atom));
156 targets[0] = xevent->target;
157 targets[1] = XInternAtom(display, "TEXT", True);
158 targets[2] = XInternAtom(display, "UTF8_STRING", True);
159 targets[3] = XInternAtom(display, "TIMESTAMP", True);
160 res = XChangeProperty(display,
161 xevent->requestor,
162 xevent->property,
163 XA_ATOM,
164 32,
165 PropModeAppend,
166 (unsigned char *)targets,
167 3);
168 DEBUG_CLIPBOARD(("res after XChangeProperty is "));
169 print_X_error(res);
170
171 res = XSendEvent(display,
172 xevent->requestor,
173 False,
174 NoEventMask,
175 (XEvent *)&xev);
176 return;
177 } else if (timestamp_atom == xevent->target)
178 {
179 DEBUG_CLIPBOARD(("TIMESTAMP requested... sending 0x%x\n",
180 (unsigned)last_keyrelease));
181 res = XChangeProperty(display,
182 xevent->requestor,
183 xevent->property,
184 XA_INTEGER,
185 32,
186 PropModeAppend,
187 (unsigned char *)&last_keyrelease,
188 1);
189 res = XSendEvent(display,
190 xevent->requestor,
191 False,
192 NoEventMask,
193 (XEvent *)&xev);
194 } else /* Some other target */
195 {
196 cliprdr_request_clipboard_data(CF_TEXT);
197 memcpy(&selection_event, &xev, sizeof(xev));
198 /* Return and wait for data, handled by
199 cliprdr_handle_server_data */
200 }
201 }
202
203
204 static void
205 cliprdr_ack_format_list(void)
206 {
207 STREAM s;
208 s = sec_init(encryption ? SEC_ENCRYPT : 0, 20);
209 out_uint32_le(s, 12);
210 out_uint32_le(s, 0x13);
211 out_uint16_le(s, 3);
212 out_uint16_le(s, 1);
213 out_uint32_le(s, 0);
214 out_uint32_le(s, 0x0000c0da);
215
216 s_mark_end(s);
217
218 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
219 }
220
221
222
223
224
225 static void
226 cliprdr_register_server_formats(STREAM s)
227 {
228 uint32 remaining_length, pad;
229 uint16 num_formats;
230 cliprdr_dataformat *this, *next;
231
232 DEBUG_CLIPBOARD(("cliprdr_register_server_formats\n"));
233 in_uint32_le(s, remaining_length);
234
235 num_formats = remaining_length / 36;
236 if (NULL != server_formats) {
237 this = server_formats;
238 next = this->next;
239 while (NULL != next) {
240 xfree(this);
241 this = NULL;
242 this = next;
243 next = this->next;
244 }
245 }
246 this = xmalloc(sizeof(cliprdr_dataformat));
247 this->next = NULL;
248 server_formats = this;
249 num_server_formats = num_formats;
250 while (1 < num_formats) {
251 in_uint32_le(s, this->identifier);
252 in_uint8a(s, this->textual_description, 32);
253 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
254 this->identifier));
255 this-> next = xmalloc(sizeof(cliprdr_dataformat));
256 this = this->next;
257 num_formats--;
258 }
259 in_uint32_le(s, this->identifier);
260 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n", this->identifier));
261 in_uint8a(s, this->textual_description, 32);
262 this -> next = NULL;
263 in_uint32_le(s, pad);
264 cliprdr_print_server_formats();
265 }
266
267 static void
268 cliprdr_select_X_clipboards(void)
269 {
270 XSetSelectionOwner(display, primary_atom, wnd, last_keyrelease);
271 if (wnd != XGetSelectionOwner(display, primary_atom))
272 {
273 warning("Failed to aquire ownership of PRIMARY clipboard\n");
274 }
275 XSetSelectionOwner(display, clipboard_atom, wnd, CurrentTime);
276 if (wnd != XGetSelectionOwner(display, clipboard_atom))
277 {
278 warning("Failed to aquire ownership of CLIPBOARD clipboard\n");
279 }
280
281 }
282
283
284
285 static void
286 cliprdr_send_format_announce(void)
287 {
288 STREAM s;
289 int number_of_formats = 1;
290 s = sec_init(encryption ? SEC_ENCRYPT : 0, number_of_formats*36+12+4+4);
291 out_uint32_le(s, number_of_formats*36+12);
292 out_uint32_le(s, 0x13);
293 out_uint16_le(s, 2);
294 out_uint16_le(s, 0);
295 out_uint32_le(s, number_of_formats*36);
296
297 // out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..
298 // rdp_out_unistr(s, "", 16);
299 // out_uint8s(s, 32);
300
301
302 out_uint32_le(s, 1); // FIXME: This is a rather bogus text description..
303 out_uint8s(s, 32);
304
305 out_uint32_le(s, 0);
306
307 s_mark_end(s);
308 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
309 }
310
311
312 static void
313 cliprdr_handle_first_handshake(STREAM s)
314 {
315 uint32 remaining_length, pad;
316 in_uint32_le(s, remaining_length);
317 in_uint32_le(s, pad);
318 DEBUG_CLIPBOARD(("Remaining length in first handshake frm server is %d, pad is %d\n",
319 remaining_length, pad));
320 cliprdr_send_format_announce();
321 }
322
323 void cliprdr_handle_server_data(uint32 length, STREAM s)
324 {
325 uint32 remaining_length;
326 char *data;
327 int res;
328 in_uint32_le(s, remaining_length);
329 data = s->p;
330 res = XChangeProperty(display,
331 selection_event.requestor,
332 selection_event.property,
333 XInternAtom(display, "STRING", False),
334 8,
335 PropModeAppend,
336 data,
337 remaining_length);
338
339 DEBUG_CLIPBOARD(("res after XChangeProperty is "));
340 print_X_error(res);
341
342 res = XSendEvent(display,
343 selection_event.requestor,
344 False,
345 NoEventMask,
346 (XEvent *)&selection_event);
347
348 DEBUG_CLIPBOARD(("res after XSendEvent is "));
349 print_X_error(res);
350
351 }
352
353 void cliprdr_handle_server_data_request(STREAM s)
354 {
355 uint32 remaining_length;
356 uint32 wanted_formatcode, pad;
357 int ret;
358 STREAM out;
359
360 in_uint32_le(s, remaining_length);
361 in_uint32_le(s, wanted_formatcode);
362 in_uint32_le(s, pad);
363
364 /* FIXME: Check that we support this formatcode */
365
366 DEBUG_CLIPBOARD(("Request from server for format %d\n",
367 wanted_formatcode));
368
369 out = sec_init(encryption ? SEC_ENCRYPT : 0,
370 26);
371 out_uint32_le(out, 18);
372 out_uint32_le(out, 0x13);
373 out_uint16_le(out, 5);
374 out_uint16_le(out, 1);
375 out_uint32_le(out, 6);
376 out_uint8p(out, "fnorp", 6);
377 out_uint32_le(out, 0);
378
379 s_mark_end(out);
380
381 sec_send_to_channel(out, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
382
383 /*
384 if (1 != wanted_formatcode)
385 {
386 out = sec_init(encryption ? SEC_ENCRYPT : 0,
387 20);
388 out_uint32_le(s, 12);
389 out_uint32_le(s, 0x13);
390 out_uint16_le(s, 5);
391 out_uint16_le(s, 2);
392 out_uint32_le(s, 0);
393 out_uint32_le(s, 0);
394 s_mark_end(s);
395 sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
396 }
397 */
398 }
399
400
401 void cliprdr_callback(STREAM s)
402 {
403 uint32 length, flags;
404 uint16 ptype0, ptype1;
405 DEBUG_CLIPBOARD(("cliprdr_callback called, clipboard data:\n"));
406 #ifdef WITH_DEBUG_CLIPBOARD
407 hexdump(s->p, s->end - s->p);
408 #endif
409 in_uint32_le(s, length);
410 in_uint32_le(s, flags);
411
412 DEBUG_CLIPBOARD(("length is %d, flags are %d\n", length, flags));
413
414 if (flags & 0x03 || flags & 0x01) /* Single-write op or first-packet-of-several op */
415 {
416 in_uint16_le(s, ptype0);
417 in_uint16_le(s, ptype1);
418 DEBUG_CLIPBOARD(("ptype0 is %d, ptype1 is %d\n", ptype0, ptype1));
419 if (1 == ptype0 && 0 == ptype1) {
420 cliprdr_handle_first_handshake(s);
421 return;
422 } else if (3 == ptype0 && 1 == ptype1)
423 {
424 // Acknowledgment on our format announce. Do we care? Not right now.
425 // There is a strange pad in this packet that we might need some time,
426 // but probably not.
427 DEBUG_CLIPBOARD(("Received format announce ACK\n"));
428 return;
429
430 } else if (2 == ptype0 && 0 == ptype1)
431 {
432 cliprdr_register_server_formats(s);
433 cliprdr_select_X_clipboards();
434 cliprdr_ack_format_list();
435 return;
436 } else if (5 == ptype0 && 1 == ptype1)
437 {
438 cliprdr_handle_server_data(length, s);
439 } else if (4 == ptype0 && 0 == ptype1)
440 {
441 cliprdr_handle_server_data_request(s);
442 }
443
444
445 }
446 }
447
448
449 void cliprdr_init(void)
450 {
451 primary_atom = XInternAtom(display, "PRIMARY", False);
452 clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
453 targets_atom = XInternAtom(display, "TARGETS", True);
454 timestamp_atom = XInternAtom(display, "TIMESTAMP", True);
455 }

  ViewVC Help
Powered by ViewVC 1.1.26