blob: f4ade8c1e54adbcdcb8c37bef2ac471f0063330e [file] [log] [blame]
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18#include <stdio.h>
19
20#define NEED_REPLIES
21#include <X11/Xlib.h>
22#include <X11/Xlibint.h>
23#define _VNCEXT_PROTO_
24#include "vncExt.h"
25
26static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
27 xEvent* w);
28static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
29 xEvent* w);
30static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
31 xEvent* w);
32
33static Bool extensionInited = False;
34static XExtCodes* codes = 0;
35
36static Bool checkExtension(Display* dpy)
37{
38 if (!extensionInited) {
39 extensionInited = True;
40 codes = XInitExtension(dpy, VNCEXTNAME);
41 if (!codes) return False;
42 XESetWireToEvent(dpy, codes->first_event + VncExtClientCutTextNotify,
43 XVncExtClientCutTextNotifyWireToEvent);
44 XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify,
45 XVncExtSelectionChangeNotifyWireToEvent);
46 XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify,
47 XVncExtQueryConnectNotifyWireToEvent);
48 }
49 return codes != 0;
50}
51
52Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep)
53{
54 if (!checkExtension(dpy)) return False;
55 *event_basep = codes->first_event;
56 *error_basep = codes->first_error;
57 return True;
58}
59
60Bool XVncExtSetParam(Display* dpy, const char* param)
61{
62 xVncExtSetParamReq* req;
63 xVncExtSetParamReply rep;
64
65 int paramLen = strlen(param);
66 if (paramLen > 255) return False;
67 if (!checkExtension(dpy)) return False;
68
69 LockDisplay(dpy);
70 GetReq(VncExtSetParam, req);
71 req->reqType = codes->major_opcode;
72 req->vncExtReqType = X_VncExtSetParam;
73 req->length += (paramLen + 3) >> 2;
74 req->paramLen = paramLen;
75 Data(dpy, param, paramLen);
76 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
77 UnlockDisplay(dpy);
78 SyncHandle();
79 return False;
80 }
81 UnlockDisplay(dpy);
82 SyncHandle();
83 return rep.success;
84}
85
86Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len)
87{
88 xVncExtGetParamReq* req;
89 xVncExtGetParamReply rep;
90
91 int paramLen = strlen(param);
92 *value = 0;
93 *len = 0;
94 if (paramLen > 255) return False;
95 if (!checkExtension(dpy)) return False;
96
97 LockDisplay(dpy);
98 GetReq(VncExtGetParam, req);
99 req->reqType = codes->major_opcode;
100 req->vncExtReqType = X_VncExtGetParam;
101 req->length += (paramLen + 3) >> 2;
102 req->paramLen = paramLen;
103 Data(dpy, param, paramLen);
104 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
105 UnlockDisplay(dpy);
106 SyncHandle();
107 return False;
108 }
109 if (rep.success) {
110 *len = rep.valueLen;
111 *value = (char*) Xmalloc (*len+1);
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200112 if (!*value) {
113 _XEatData(dpy, (*len+1)&~1);
114 return False;
115 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000116 _XReadPad(dpy, *value, *len);
117 (*value)[*len] = 0;
118 }
119 UnlockDisplay(dpy);
120 SyncHandle();
121 return rep.success;
122}
123
124char* XVncExtGetParamDesc(Display* dpy, const char* param)
125{
126 xVncExtGetParamDescReq* req;
127 xVncExtGetParamDescReply rep;
128 char* desc = 0;
129
130 int paramLen = strlen(param);
131 if (paramLen > 255) return False;
132 if (!checkExtension(dpy)) return False;
133
134 LockDisplay(dpy);
135 GetReq(VncExtGetParamDesc, req);
136 req->reqType = codes->major_opcode;
137 req->vncExtReqType = X_VncExtGetParamDesc;
138 req->length += (paramLen + 3) >> 2;
139 req->paramLen = paramLen;
140 Data(dpy, param, paramLen);
141 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
142 UnlockDisplay(dpy);
143 SyncHandle();
144 return False;
145 }
146 if (rep.success) {
147 desc = (char*)Xmalloc(rep.descLen+1);
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200148 if (!*desc) {
149 _XEatData(dpy, (rep.descLen+1)&~1);
150 return False;
151 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000152 _XReadPad(dpy, desc, rep.descLen);
153 desc[rep.descLen] = 0;
154 }
155 UnlockDisplay(dpy);
156 SyncHandle();
157 return desc;
158}
159
160char** XVncExtListParams(Display* dpy, int* nParams)
161{
162 xVncExtListParamsReq* req;
163 xVncExtListParamsReply rep;
164 char** list = 0;
165 char* ch;
166 int rlen, paramLen, i;
167
168 if (!checkExtension(dpy)) return False;
169
170 LockDisplay(dpy);
171 GetReq(VncExtListParams, req);
172 req->reqType = codes->major_opcode;
173 req->vncExtReqType = X_VncExtListParams;
174 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
175 UnlockDisplay(dpy);
176 SyncHandle();
177 return False;
178 }
179 UnlockDisplay(dpy);
180 SyncHandle();
181 if (rep.nParams) {
182 list = (char**)Xmalloc(rep.nParams * sizeof(char*));
183 rlen = rep.length << 2;
184 ch = (char*)Xmalloc(rlen + 1);
185 if (!list || !ch) {
186 if (list) Xfree((char*)list);
187 if (ch) Xfree(ch);
188 _XEatData(dpy, rlen);
189 UnlockDisplay(dpy);
190 SyncHandle();
191 return 0;
192 }
193 _XReadPad(dpy, ch, rlen);
194 paramLen = *ch++;
195 for (i = 0; i < rep.nParams; i++) {
196 list[i] = ch;
197 ch += paramLen;
198 paramLen = *ch;
199 *ch++ = 0;
200 }
201 }
202 *nParams = rep.nParams;
203 UnlockDisplay(dpy);
204 SyncHandle();
205 return list;
206}
207
208void XVncExtFreeParamList(char** list)
209{
210 if (list) {
211 Xfree(list[0]-1);
212 Xfree((char*)list);
213 }
214}
215
216Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len)
217{
218 xVncExtSetServerCutTextReq* req;
219
220 if (!checkExtension(dpy)) return False;
221
222 LockDisplay(dpy);
223 GetReq(VncExtSetServerCutText, req);
224 req->reqType = codes->major_opcode;
225 req->vncExtReqType = X_VncExtSetServerCutText;
226 req->length += (len + 3) >> 2;
227 req->textLen = len;
228 Data(dpy, str, len);
229 UnlockDisplay(dpy);
230 SyncHandle();
231 return True;
232}
233
234Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len)
235{
236 xVncExtGetClientCutTextReq* req;
237 xVncExtGetClientCutTextReply rep;
238
239 if (!checkExtension(dpy)) return False;
240
241 LockDisplay(dpy);
242 GetReq(VncExtGetClientCutText, req);
243 req->reqType = codes->major_opcode;
244 req->vncExtReqType = X_VncExtGetClientCutText;
245 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
246 UnlockDisplay(dpy);
247 SyncHandle();
248 return False;
249 }
250 UnlockDisplay(dpy);
251 SyncHandle();
252 *len = rep.textLen;
253 *str = (char*) Xmalloc (*len+1);
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200254 if (!*str) {
255 _XEatData(dpy, (*len+1)&~1);
256 return False;
257 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000258 _XReadPad(dpy, *str, *len);
259 (*str)[*len] = 0;
260 return True;
261}
262
263Bool XVncExtSelectInput(Display* dpy, Window w, int mask)
264{
265 xVncExtSelectInputReq* req;
266
267 if (!checkExtension(dpy)) return False;
268
269 LockDisplay(dpy);
270 GetReq(VncExtSelectInput, req);
271 req->reqType = codes->major_opcode;
272 req->vncExtReqType = X_VncExtSelectInput;
273 req->window = w;
274 req->mask = mask;
275 UnlockDisplay(dpy);
276 SyncHandle();
277 return True;
278}
279
280Bool XVncExtConnect(Display* dpy, char* hostAndPort)
281{
282 xVncExtConnectReq* req;
283 xVncExtConnectReply rep;
284
285 int strLen = strlen(hostAndPort);
286 if (strLen > 255) return False;
287 if (!checkExtension(dpy)) return False;
288
289 LockDisplay(dpy);
290 GetReq(VncExtConnect, req);
291 req->reqType = codes->major_opcode;
292 req->vncExtReqType = X_VncExtConnect;
293 req->length += (strLen + 3) >> 2;
294 req->strLen = strLen;
295 Data(dpy, hostAndPort, strLen);
296 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
297 UnlockDisplay(dpy);
298 SyncHandle();
299 return False;
300 }
301 UnlockDisplay(dpy);
302 SyncHandle();
303 return rep.success;
304}
305
306Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user,
307 int* timeout, void** opaqueId)
308{
309 xVncExtGetQueryConnectReq* req;
310 xVncExtGetQueryConnectReply rep;
311
312 if (!checkExtension(dpy)) return False;
313
314 LockDisplay(dpy);
315 GetReq(VncExtGetQueryConnect, req);
316 req->reqType = codes->major_opcode;
317 req->vncExtReqType = X_VncExtGetQueryConnect;
318 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
319 UnlockDisplay(dpy);
320 SyncHandle();
321 return False;
322 }
323 UnlockDisplay(dpy);
324 SyncHandle();
325
326 *addr = Xmalloc(rep.addrLen+1);
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200327 *user = Xmalloc(rep.userLen+1);
328 if (!*addr || !*user) {
329 Xfree(*addr);
330 Xfree(*user);
Pierre Ossman7728be22015-03-03 16:39:37 +0100331 _XEatData(dpy, ((rep.addrLen+1)&~1) + ((rep.userLen+1)&~1));
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200332 return False;
333 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000334 _XReadPad(dpy, *addr, rep.addrLen);
335 (*addr)[rep.addrLen] = 0;
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000336 _XReadPad(dpy, *user, rep.userLen);
337 (*user)[rep.userLen] = 0;
338 *timeout = rep.timeout;
339 *opaqueId = (void*)rep.opaqueId;
340 return True;
341}
342
343Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve)
344{
345 xVncExtApproveConnectReq* req;
346
347 if (!checkExtension(dpy)) return False;
348
349 LockDisplay(dpy);
350 GetReq(VncExtApproveConnect, req);
351 req->reqType = codes->major_opcode;
352 req->vncExtReqType = X_VncExtApproveConnect;
353 req->approve = approve;
354 req->opaqueId = (CARD32)opaqueId;
355 UnlockDisplay(dpy);
356 SyncHandle();
357 return True;
358}
359
360
361static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
362 xEvent* w)
363{
364 XVncExtClientCutTextEvent* ev = (XVncExtClientCutTextEvent*)e;
365 xVncExtClientCutTextNotifyEvent* wire = (xVncExtClientCutTextNotifyEvent*)w;
366 ev->type = wire->type & 0x7f;
367 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
368 ev->send_event = (wire->type & 0x80) != 0;
369 ev->display = dpy;
370 ev->window = wire->window;
371 ev->time = wire->time;
372 return True;
373}
374
375static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
376 xEvent* w)
377{
378 XVncExtSelectionChangeEvent* ev = (XVncExtSelectionChangeEvent*)e;
379 xVncExtSelectionChangeNotifyEvent* wire
380 = (xVncExtSelectionChangeNotifyEvent*)w;
381 ev->type = wire->type & 0x7f;
382 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
383 ev->send_event = (wire->type & 0x80) != 0;
384 ev->display = dpy;
385 ev->window = wire->window;
386 ev->selection = wire->selection;
387 return True;
388}
389
390static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
391 xEvent* w)
392{
393 XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e;
394 xVncExtQueryConnectNotifyEvent* wire
395 = (xVncExtQueryConnectNotifyEvent*)w;
396 ev->type = wire->type & 0x7f;
397 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
398 ev->send_event = (wire->type & 0x80) != 0;
399 ev->display = dpy;
400 ev->window = wire->window;
401 return True;
402}