/[rdesktop]/sourceforge.net/tags/RDESKTOP-1-3-1/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/tags/RDESKTOP-1-3-1/rdesktop/cliprdr.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 384 - (hide annotations)
Fri Jun 6 09:22:25 2003 UTC (21 years ago) by forsberg
Original Path: sourceforge.net/trunk/rdesktop/cliprdr.c
File MIME type: text/plain
File size: 10095 byte(s)
Proof-of-concept, clipboard transfer server->client works!
A lot of stuff remains for a full implementation.

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     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     out_uint32_le(s, 0);
302    
303     s_mark_end(s);
304     sec_send_to_channel(s, encryption ? SEC_ENCRYPT : 0, 1005); // FIXME: Don't hardcode channel!
305     }
306    
307 forsberg 384
308 forsberg 383 static void
309     cliprdr_handle_first_handshake(STREAM s)
310     {
311     uint32 remaining_length, pad;
312     in_uint32_le(s, remaining_length);
313     in_uint32_le(s, pad);
314     DEBUG_CLIPBOARD(("Remaining length in first handshake frm server is %d, pad is %d\n",
315     remaining_length, pad));
316     cliprdr_send_format_announce();
317     }
318    
319 forsberg 384 void cliprdr_handle_server_data(uint32 length, STREAM s)
320     {
321     uint32 remaining_length;
322     char *data;
323     int res;
324     in_uint32_le(s, remaining_length);
325     data = s->p;
326     res = XChangeProperty(display,
327     selection_event.requestor,
328     selection_event.property,
329     XInternAtom(display, "STRING", False),
330     8,
331     PropModeAppend,
332     data,
333     remaining_length);
334    
335     DEBUG_CLIPBOARD(("res after XChangeProperty is "));
336     print_X_error(res);
337    
338     res = XSendEvent(display,
339     selection_event.requestor,
340     False,
341     NoEventMask,
342     (XEvent *)&selection_event);
343    
344     DEBUG_CLIPBOARD(("res after XSendEvent is "));
345     print_X_error(res);
346    
347     }
348    
349 forsberg 383 void cliprdr_callback(STREAM s)
350     {
351     uint32 length, flags;
352     uint16 ptype0, ptype1;
353     DEBUG_CLIPBOARD(("cliprdr_callback called, clipboard data:\n"));
354     #ifdef WITH_DEBUG_CLIPBOARD
355     hexdump(s->p, s->end - s->p);
356     #endif
357     in_uint32_le(s, length);
358     in_uint32_le(s, flags);
359    
360     DEBUG_CLIPBOARD(("length is %d, flags are %d\n", length, flags));
361    
362     if (flags & 0x03 || flags & 0x01) /* Single-write op or first-packet-of-several op */
363     {
364     in_uint16_le(s, ptype0);
365     in_uint16_le(s, ptype1);
366     DEBUG_CLIPBOARD(("ptype0 is %d, ptype1 is %d\n", ptype0, ptype1));
367     if (1 == ptype0 && 0 == ptype1) {
368     cliprdr_handle_first_handshake(s);
369     return;
370     } else if (3 == ptype0 && 1 == ptype1)
371     {
372     // Acknowledgment on our format announce. Do we care? Not right now.
373     // There is a strange pad in this packet that we might need some time,
374     // but probably not.
375     DEBUG_CLIPBOARD(("Received format announce ACK\n"));
376     return;
377 forsberg 384
378 forsberg 383 } else if (2 == ptype0 && 0 == ptype1)
379     {
380     cliprdr_register_server_formats(s);
381     cliprdr_select_X_clipboards();
382 forsberg 384 cliprdr_ack_format_list();
383 forsberg 383 return;
384 forsberg 384 } else if (5 == ptype0 && 1 == ptype1)
385     {
386     cliprdr_handle_server_data(length, s);
387 forsberg 383 }
388    
389     }
390     }
391    
392 forsberg 384
393 forsberg 383 void cliprdr_init(void)
394     {
395     primary_atom = XInternAtom(display, "PRIMARY", False);
396     clipboard_atom = XInternAtom(display, "CLIPBOARD", False);
397     targets_atom = XInternAtom(display, "TARGETS", True);
398     timestamp_atom = XInternAtom(display, "TIMESTAMP", True);
399     }

  ViewVC Help
Powered by ViewVC 1.1.26