/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 385 - (hide annotations)
Fri Jun 6 09:23:28 2003 UTC (21 years 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 forsberg 383 /* -*- 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 forsberg 384 static XSelectionEvent selection_event;
34 forsberg 383
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 forsberg 384 DEBUG_CLIPBOARD(("There were %d server formats.\n", i));
50 forsberg 383 #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 forsberg 384 DEBUG_CLIPBOARD(("BadWindow\n"));
94 forsberg 383 break;
95    
96     default:
97     DEBUG_CLIPBOARD(("Unknown X error code %d\n", res));
98     }
99     }
100    
101 forsberg 384 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 forsberg 383 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 forsberg 384 DEBUG_CLIPBOARD(("Requestor window id 0x%x ",
130     (unsigned)xevent->requestor));
131 forsberg 383 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 forsberg 384 (unsigned)xevent->target,
140 forsberg 383 XGetAtomName(display, xevent->property),
141 forsberg 384 (unsigned)xevent->property));
142 forsberg 383
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 forsberg 384 (unsigned)last_keyrelease));
181 forsberg 383 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 forsberg 384 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 forsberg 383
203    
204 forsberg 384 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 forsberg 383 }
220    
221 forsberg 384
222 forsberg 383
223 forsberg 384
224    
225 forsberg 383 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 forsberg 384 DEBUG_CLIPBOARD(("Stored format description with numeric id %d\n",
254     this->identifier));
255 forsberg 383 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 forsberg 384
284    
285 forsberg 383 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 forsberg 385 // out_uint32_le(s, 0xd); // FIXME: This is a rather bogus unicode text description..
298 forsberg 383 // rdp_out_unistr(s, "", 16);
299 forsberg 385 // out_uint8s(s, 32);
300    
301    
302     out_uint32_le(s, 1); // FIXME: This is a rather bogus text description..
303 forsberg 383 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 forsberg 384
312 forsberg 383 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 forsberg 384 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 forsberg 385 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 forsberg 383 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 forsberg 384
430 forsberg 383 } else if (2 == ptype0 && 0 == ptype1)
431     {
432     cliprdr_register_server_formats(s);
433     cliprdr_select_X_clipboards();
434 forsberg 384 cliprdr_ack_format_list();
435 forsberg 383 return;
436 forsberg 384 } else if (5 == ptype0 && 1 == ptype1)
437     {
438     cliprdr_handle_server_data(length, s);
439 forsberg 385 } else if (4 == ptype0 && 0 == ptype1)
440     {
441     cliprdr_handle_server_data_request(s);
442 forsberg 383 }
443 forsberg 385
444 forsberg 383
445     }
446     }
447    
448 forsberg 384
449 forsberg 383 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