Commit 5e726096 authored by runge's avatar runge

x11vnc: do CLIPBOARD, reverse conn require passwds, -usepw, -debug_sel, -storepasswd homedir.

parent c997e901
2006-03-08 Karl Runge <runge@karlrunge.com>
* x11vnc: manage CLIPBOARD in addition to PRIMARY. -debug_sel
Make reverse connections require passwords. -usepw option.
-storepasswd w/o args prompts and writes ~/.vnc/passwd.
2006-03-06 Karl Runge <runge@karlrunge.com>
* x11vnc: switch remote control to X11VNC_REMOTE property. Put
in -unixpw constraints for reverse connections under -inetd.
......
This diff is collapsed.
......@@ -1491,6 +1491,12 @@ static int do_reverse_connect(char *str) {
return 0;
} else {
rfbLog("reverse_connect: %s/%s OK\n", str, cl->host);
/* let's see if anyone complains: */
if (! getenv("X11VNC_REVERSE_CONNECTION_NO_AUTH")) {
rfbLog("reverse_connect: turning on auth for %s\n",
cl->host);
cl->reverseConnection = FALSE;
}
return 1;
}
}
......
This diff is collapsed.
......@@ -116,6 +116,7 @@ int debug_xdamage = 0; /* -R debug_xdamage:1 or 2 ... */
int debug_wireframe = 0;
int debug_tiles = 0;
int debug_grabs = 0;
int debug_sel = 0;
int xtrap_input = 0; /* -xtrap for user input insertion */
int xinerama = 0; /* -xinerama */
......@@ -274,6 +275,7 @@ int ui_skip = 10; /* see watchloop. negative means ignore input */
int watch_selection = 1; /* normal selection/cutbuffer maintenance */
int watch_primary = 1; /* more dicey, poll for changes in PRIMARY */
int watch_clipboard = 1;
char *sel_direction = NULL; /* "send" or "recv" for one-way */
char *sigpipe = NULL; /* skip, ignore, exit */
......
......@@ -91,6 +91,7 @@ extern int debug_xdamage;
extern int debug_wireframe;
extern int debug_tiles;
extern int debug_grabs;
extern int debug_sel;
extern int xtrap_input;
extern int xinerama;
......@@ -203,6 +204,7 @@ extern int ui_skip;
extern int watch_selection;
extern int watch_primary;
extern int watch_clipboard;
extern char *sel_direction;
extern char *sigpipe;
......
......@@ -22,6 +22,7 @@
#include "cursor.h"
#include "userinput.h"
#include "keyboard.h"
#include "selection.h"
int send_remote_cmd(char *cmd, int query, int wait);
int do_remote_query(char *remote_cmd, char *query_cmd, int remote_sync,
......@@ -2116,6 +2117,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote_cmd: enabling watch selection+primary.\n");
watch_selection = 1;
watch_primary = 1;
watch_clipboard = 1;
} else if (!strcmp(p, "nosel")) {
if (query) {
......@@ -2125,6 +2127,7 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote_cmd: disabling watch selection+primary.\n");
watch_selection = 0;
watch_primary = 0;
watch_clipboard = 0;
} else if (!strcmp(p, "primary")) {
if (query) {
......@@ -2142,6 +2145,54 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("remote_cmd: disabling watch_primary.\n");
watch_primary = 0;
} else if (!strcmp(p, "setprimary")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, set_primary);
goto qry;
}
rfbLog("remote_cmd: enabling set_primary.\n");
set_primary = 1;
} else if (!strcmp(p, "nosetprimary")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !set_primary);
goto qry;
}
rfbLog("remote_cmd: disabling set_primary.\n");
set_primary = 0;
} else if (!strcmp(p, "clipboard")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, watch_clipboard);
goto qry;
}
rfbLog("remote_cmd: enabling watch_clipboard.\n");
watch_clipboard = 1;
} else if (!strcmp(p, "noclipboard")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !watch_clipboard);
goto qry;
}
rfbLog("remote_cmd: disabling watch_clipboard.\n");
watch_clipboard = 0;
} else if (!strcmp(p, "setclipboard")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, set_clipboard);
goto qry;
}
rfbLog("remote_cmd: enabling set_clipboard.\n");
set_clipboard = 1;
} else if (!strcmp(p, "nosetclipboard")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !set_clipboard);
goto qry;
}
rfbLog("remote_cmd: disabling set_clipboard.\n");
set_clipboard = 0;
} else if (strstr(p, "seldir") == p) {
COLON_CHECK("seldir:")
if (query) {
......@@ -3501,6 +3552,21 @@ char *process_remote_cmd(char *cmd, int stringonly) {
debug_grabs = 0;
rfbLog("set debug_grabs to: %d\n", debug_grabs);
} else if (!strcmp(p, "debug_sel")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, debug_sel);
goto qry;
}
debug_sel = 1;
rfbLog("set debug_sel to: %d\n", debug_sel);
} else if (!strcmp(p, "nodebug_sel")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, !debug_sel);
goto qry;
}
debug_sel = 0;
rfbLog("set debug_sel to: %d\n", debug_sel);
} else if (!strcmp(p, "dbg")) {
if (query) {
snprintf(buf, bufn, "ans=%s:%d", p, crash_debug);
......
......@@ -407,7 +407,7 @@ static char *raw_fb_orig_dpy = NULL;
void set_raw_fb_params(int restore) {
static int first = 1;
static int vo0, us0, sm0, ws0, wp0, wb0, na0, tn0;
static int vo0, us0, sm0, ws0, wp0, wc0, wb0, na0, tn0;
static int xr0, sb0;
static char *mc0;
......@@ -421,6 +421,7 @@ void set_raw_fb_params(int restore) {
vo0 = view_only;
ws0 = watch_selection;
wp0 = watch_primary;
wc0 = watch_clipboard;
wb0 = watch_bell;
na0 = no_autorepeat;
sb0 = use_solid_bg;
......@@ -438,6 +439,7 @@ void set_raw_fb_params(int restore) {
view_only = vo0;
watch_selection = ws0;
watch_primary = wp0;
watch_clipboard = wc0;
watch_bell = wb0;
no_autorepeat = na0;
use_solid_bg = sb0;
......@@ -493,6 +495,11 @@ void set_raw_fb_params(int restore) {
"watch_primary\n");
watch_primary = 0;
}
if (watch_clipboard) {
if (! quiet) rfbLog("rawfb: turning off "
"watch_clipboard\n");
watch_clipboard = 0;
}
if (watch_bell) {
if (! quiet) rfbLog("rawfb: turning off watch_bell\n");
watch_bell = 0;
......
......@@ -9,19 +9,24 @@
* Selection/Cutbuffer/Clipboard handlers.
*/
int own_selection = 0; /* whether we currently own PRIMARY or not */
int own_primary = 0; /* whether we currently own PRIMARY or not */
int set_primary = 1;
int own_clipboard = 0; /* whether we currently own CLIPBOARD or not */
int set_clipboard = 1;
int set_cutbuffer = 0; /* to avoid bouncing the CutText right back */
int sel_waittime = 15; /* some seconds to skip before first send */
Window selwin; /* special window for our selection */
Atom clipboard_atom = None;
/*
* This is where we keep our selection: the string sent TO us from VNC
* clients, and the string sent BY us to requesting X11 clients.
*/
char *xcut_str = NULL;
char *xcut_str_primary = NULL;
char *xcut_str_clipboard = NULL;
void selection_request(XEvent *ev);
void selection_request(XEvent *ev, char *type);
int check_sel_direction(char *dir, char *label, char *sel, int len);
void cutbuffer_send(void);
void selection_send(XEvent *ev);
......@@ -29,14 +34,14 @@ void selection_send(XEvent *ev);
/*
* Our callbacks instruct us to check for changes in the cutbuffer
* and PRIMARY selection on the local X11 display.
* and PRIMARY and CLIPBOARD selection on the local X11 display.
*
* We store the new cutbuffer and/or PRIMARY selection data in this
* constant sized array selection_str[].
* TODO: check if malloc does not cause performance issues (esp. WRT
* SelectionNotify handling).
*/
static char selection_str[PROP_MAX+1];
static char cutbuffer_str[PROP_MAX+1];
static char primary_str[PROP_MAX+1];
static char clipboard_str[PROP_MAX+1];
/*
* An X11 (not VNC) client on the local display has requested the selection
......@@ -44,10 +49,11 @@ static char selection_str[PROP_MAX+1];
*
* n.b.: our caller already has the X_LOCK.
*/
void selection_request(XEvent *ev) {
void selection_request(XEvent *ev, char *type) {
XSelectionEvent notify_event;
XSelectionRequestEvent *req_event;
XErrorHandler old_handler;
char *str;
unsigned int length;
unsigned char *data;
#ifndef XA_LENGTH
......@@ -67,11 +73,24 @@ void selection_request(XEvent *ev) {
} else {
notify_event.property = req_event->property;
}
if (xcut_str) {
length = strlen(xcut_str);
if (!strcmp(type, "PRIMARY")) {
str = xcut_str_primary;
} else if (!strcmp(type, "CLIPBOARD")) {
str = xcut_str_clipboard;
} else {
return;
}
if (str) {
length = strlen(str);
} else {
length = 0;
}
if (debug_sel) {
rfbLog("%s\trequest event: owner=0x%x requestor=0x%x sel=%03d targ=%d prop=%d\n",
type, req_event->owner, req_event->requestor, req_event->selection,
req_event->target, req_event->property);
}
/* the window may have gone away, so trap errors */
trapped_xerror = 0;
......@@ -89,7 +108,7 @@ void selection_request(XEvent *ev) {
} else {
/* data request */
data = (unsigned char *)xcut_str;
data = (unsigned char *)str;
XChangeProperty(ev->xselectionrequest.display,
ev->xselectionrequest.requestor,
......@@ -104,7 +123,7 @@ void selection_request(XEvent *ev) {
}
if (trapped_xerror) {
rfbLog("selection_request: ignored XError while sending "
"PRIMARY selection to 0x%x.\n", req_event->requestor);
"%s selection to 0x%x.\n", type, req_event->requestor);
}
XSetErrorHandler(old_handler);
trapped_xerror = 0;
......@@ -114,6 +133,9 @@ void selection_request(XEvent *ev) {
int check_sel_direction(char *dir, char *label, char *sel, int len) {
int db = 0, ok = 1;
if (debug_sel) {
db = 1;
}
if (sel_direction) {
if (strstr(sel_direction, "debug")) {
db = 1;
......@@ -132,7 +154,7 @@ int check_sel_direction(char *dir, char *label, char *sel, int len) {
if (len < n) {
str[len] = '\0';
}
rfbLog("%s: %s...\n", label, str);
rfbLog("%s: '%s'\n", label, str);
if (ok) {
rfbLog("%s: %s-ing it.\n", label, dir);
} else {
......@@ -154,10 +176,11 @@ void cutbuffer_send(void) {
unsigned long nitems = 0, bytes_after = 0;
unsigned char* data = NULL;
selection_str[0] = '\0';
cutbuffer_str[0] = '\0';
slen = 0;
/* read the property value into selection_str: */
/* read the property value into cutbuffer_str: */
do {
if (XGetWindowProperty(dpy, DefaultRootWindow(dpy),
XA_CUT_BUFFER0, nitems/4, PROP_MAX/16, False,
......@@ -172,14 +195,18 @@ void cutbuffer_send(void) {
XFree(data);
break;
}
memcpy(selection_str+slen, data, dlen);
memcpy(cutbuffer_str+slen, data, dlen);
slen += dlen;
selection_str[slen] = '\0';
cutbuffer_str[slen] = '\0';
XFree(data);
}
} while (bytes_after > 0);
selection_str[PROP_MAX] = '\0';
cutbuffer_str[PROP_MAX] = '\0';
if (debug_sel) {
rfbLog("cutbuffer_send: '%s'\n", cutbuffer_str);
}
if (! all_clients_initialized()) {
rfbLog("cutbuffer_send: no send: uninitialized clients\n");
......@@ -193,9 +220,9 @@ void cutbuffer_send(void) {
if (!screen) {
return;
}
len = strlen(selection_str);
if (check_sel_direction("send", "cutbuffer_send", selection_str, len)) {
rfbSendServerCutText(screen, selection_str, len);
len = strlen(cutbuffer_str);
if (check_sel_direction("send", "cutbuffer_send", cutbuffer_str, len)) {
rfbSendServerCutText(screen, cutbuffer_str, len);
}
}
......@@ -219,18 +246,41 @@ void selection_send(XEvent *ev) {
char before[CHKSZ], after[CHKSZ];
unsigned long nitems = 0, bytes_after = 0;
unsigned char* data = NULL;
char *selection_str;
/*
* remember info about our last value of PRIMARY (or CUT_BUFFER0)
* so we can check for any changes below.
*/
if (ev->xselection.selection == XA_PRIMARY) {
if (! watch_primary) {
return;
}
selection_str = primary_str;
if (debug_sel) {
rfbLog("selection_send: event PRIMARY prop: %d requestor: 0x%x atom: %d\n",
ev->xselection.property, ev->xselection.requestor, ev->xselection.selection);
}
} else if (clipboard_atom && ev->xselection.selection == clipboard_atom) {
if (! watch_clipboard) {
return;
}
selection_str = clipboard_str;
if (debug_sel) {
rfbLog("selection_send: event CLIPBOARD prop: %d requestor: 0x%x atom: %d\n",
ev->xselection.property, ev->xselection.requestor, ev->xselection.selection);
}
} else {
return;
}
oldlen = strlen(selection_str);
strncpy(before, selection_str, CHKSZ);
selection_str[0] = '\0';
slen = 0;
/* read in the current value of PRIMARY: */
/* read in the current value of PRIMARY or CLIPBOARD: */
do {
if (XGetWindowProperty(dpy, ev->xselection.requestor,
ev->xselection.property, nitems/4, PROP_MAX/16, True,
......@@ -248,9 +298,11 @@ void selection_send(XEvent *ev) {
err = 5;
}
rfbLog("warning: truncating large PRIMARY"
" selection > %d bytes.\n", PROP_MAX);
"/CLIPBOARD selection > %d bytes.\n",
PROP_MAX);
break;
}
if (debug_sel) fprintf(stderr, "selection_send: data: '%s' dlen: %d nitems: %d ba: %d\n", data, dlen, nitems, bytes_after);
memcpy(selection_str+slen, data, dlen);
slen += dlen;
selection_str[slen] = '\0';
......@@ -269,6 +321,11 @@ void selection_send(XEvent *ev) {
oldlen = -1;
sent_one = 1;
}
if (debug_sel) {
rfbLog("selection_send: %s '%s'\n",
ev->xselection.selection == XA_PRIMARY ? "PRIMARY " : "CLIPBOARD",
selection_str);
}
/* look for changes in the new value */
newlen = strlen(selection_str);
......@@ -276,6 +333,9 @@ void selection_send(XEvent *ev) {
if (oldlen == newlen && strncmp(before, after, CHKSZ) == 0) {
/* evidently no change */
if (debug_sel) {
rfbLog("selection_send: no change.\n");
}
return;
}
if (newlen == 0) {
......
......@@ -3,13 +3,18 @@
/* -- selection.h -- */
extern char *xcut_str;
extern int own_selection;
extern char *xcut_str_primary;
extern char *xcut_str_clipboard;
extern int own_primary;
extern int set_primary;
extern int own_clipboard;
extern int set_clipboard;
extern int set_cutbuffer;
extern int sel_waittime;
extern Window selwin;
extern Atom clipboard_atom;
extern void selection_request(XEvent *ev);
extern void selection_request(XEvent *ev, char *type);
extern int check_sel_direction(char *dir, char *label, char *sel, int len);
extern void cutbuffer_send(void);
extern void selection_send(XEvent *ev);
......
......@@ -96,6 +96,14 @@ int start_stunnel(int stunnel_port, int x11vnc_port) {
return 0;
}
if (no_external_cmds) {
rfbLogEnable(1);
rfbLog("start_stunnel: cannot run external commands in -nocmds mode:\n");
rfbLog(" \"%s\"\n", stunnel_path);
rfbLog(" exiting.\n");
clean_up_exit(1);
}
if (! quiet) {
rfbLog("\n");
rfbLog("starting ssl tunnel: %s %d -> %d\n", stunnel_path,
......
......@@ -95,18 +95,22 @@ Actions
--
=RA ping
=RA update-all
--
=GAL Settings::
=GA save-settings
=SFA load-settings:
=SA defaults-all
=0SA clear-all
--
=F rc:
norc
=GAL LOFF
-- D
=DRA stop+quit
=DGA Quit
Help
=DGA gui
=GA all
=DGA all
Clients
=DRQA current:
......@@ -119,10 +123,12 @@ Clients
vncconnect
-- D
filexfer
=GAL Java-applet::
=D http
httpdir:
httpport:
enablehttpproxy
=GAL LOFF
Displays
=D display:
......@@ -135,7 +141,6 @@ Screen
=DRA refresh
=RA reset
=RA blacken
fixscreen:
-- D
=D scale:
scale_cursor:
......@@ -163,14 +168,17 @@ Screen
=-C:resize,newfbsize,exit xrandr_mode:
padgeom:
=GAL LOFF
--
=GAL Clipping::
=P blackout:
xinerama
clip:
--
=GAL LOFF
=GAL Misc-Screen::
fixscreen:
visual:
rawfb:
pipeinput:
=GAL LOFF
Keyboard
=D norepeat
......@@ -212,28 +220,26 @@ Misc
-- D
=GA all-settings
=RA remote-cmd:
--
=F rc:
norc
filexfer
--
nofb
=D nobell
nolookup
=GAL Selection::
=D nosel
noprimary
nosetprimary
noclipboard
nosetclipboard
seldir:
=GAL LOFF
--
=GAL X-ext::
xtrap
xrecord
=RQA reset_record
=GAL LOFF
--
nofb
=D nobell
nolookup
bg
=-C:ignore,exit sigpipe:
=0 inetd
rfbwait:
Debugging
debug_pointer
......@@ -250,6 +256,7 @@ Debugging
debug_scroll
debug_tiles
debug_grabs
debug_sel
dbg
=GAL LOFF
=GA show-start-cmd
......@@ -258,39 +265,41 @@ Debugging
Permissions
=DRQA lock
=DRQA unlock
=D shared
=D forever
--
=DFP allow:
=D localhost
=RA allowonce:
listen:
-- D
=D shared
=D forever
timeout:
--
=D viewonly
input:
--
safer
unsafe
=RA noremote
--
=GAL Passwords::
passwd:
viewpasswd:
=F passwdfile:
=F rfbauth:
usepw
--
unixpw
unixpw_list:
unixpw_nis
unixpw_nis_list:
=0 storepasswd
=GAL LOFF
=GAL Safe::
safer
unsafe
=RA noremote
=GAL LOFF
=GAL Misc-Perms::
=0S alwaysshared
=0S nevershared
=0S dontdisconnect
=SQA deny_all
timeout:
stunnel
=F stunnel_pem:
=GAL LOFF
......@@ -344,6 +353,7 @@ Tuning
snapfb
threads
wmdt:
rfbwait:
=GAL LOFF
"
}
......@@ -786,6 +796,7 @@ should never use them and just use x11vnc's -shared and -forever options
instead (these give basically the same functionality and if you mixed
them too much unexpected things may happen).
"
#'
set helptext(AlphaBlending:) "
In this sub-menu we provide some tweak parameters for cursors (little
......@@ -808,6 +819,7 @@ The items in this sub-menu let you tweak x11vnc's approximation scheme
for cursors with transparency. Hopefully you won't have to use them.
Certain cursor \"themes\" may require adjustment however.
"
#'
set helptext(OverlayVisuals:) "
In this sub-menu are some options that involve fixing color problems
for \"Overlay\" or \"Multi-Depth\" visuals. This problem is rare
......@@ -924,6 +936,48 @@ video hardware was slow at the time. x11vnc tries to use this same trick
as a speedup for its activities (the network is much slower than video
hardware writes, and the video hardware reads that x11vnc uses to poll
the screen are still slow today).
"
#'"
set helptext(Safe:) "
In this sub-menu are some options for making x11vnc operations
more, or less, safe. E.g. disable the running of external commands, etc.
You can also turn off the Remote control channel (NOTE that doing that
will disable the GUI from being able to communicate with x11vnc).
"
set helptext(X-ext:) "
In this sub-menu are a few rarely used options regarding some X extensions
used by x11vnc.
"
set helptext(Clipping:) "
In this sub-menu are some options regarding clipping or blacking out
portions of the Screen. E.g. under XINERAMA when the multiple monitors
are not the same size.
"
set helptext(Misc-Screen:) "
In this sub-menu are some little used options modifying aspects of
the screen source.
"
set helptext(Settings:) "
In this sub-menu are some options for saving and loading option settings.
The default file to store settings in is ~/.x11vncrc, but you can save
different \"profiles\" in other files for later use.
"
set helptext(Java-applet:) "
In this sub-menu are some options for running the built-in HTTP server
that delivers the TightVNC Java VNC Viewer applet (VncViewer.jar) to
clients. The viewer runs in their Web browser.
The default port listened on is 5800, so the URL is typically:
http://hostname:5800/
but this can be altered by -httpport, etc.
"
set helptext(ScrollCopyRect:) "
......
......@@ -106,18 +106,22 @@ char gui_code[] = "";
" --\n"
" =RA ping\n"
" =RA update-all\n"
" --\n"
" =GAL Settings::\n"
" =GA save-settings\n"
" =SFA load-settings:\n"
" =SA defaults-all\n"
" =0SA clear-all\n"
" --\n"
" =F rc:\n"
" norc\n"
" =GAL LOFF\n"
" -- D\n"
" =DRA stop+quit \n"
" =DGA Quit \n"
"\n"
"Help\n"
" =DGA gui\n"
" =GA all\n"
" =DGA all\n"
"\n"
"Clients\n"
" =DRQA current:\n"
......@@ -130,10 +134,12 @@ char gui_code[] = "";
" vncconnect\n"
" -- D\n"
" filexfer\n"
" =GAL Java-applet::\n"
" =D http\n"
" httpdir:\n"
" httpport:\n"
" enablehttpproxy\n"
" =GAL LOFF\n"
"\n"
"Displays\n"
" =D display:\n"
......@@ -146,7 +152,6 @@ char gui_code[] = "";
" =DRA refresh\n"
" =RA reset\n"
" =RA blacken\n"
" fixscreen:\n"
" -- D\n"
" =D scale:\n"
" scale_cursor:\n"
......@@ -174,14 +179,17 @@ char gui_code[] = "";
" =-C:resize,newfbsize,exit xrandr_mode:\n"
" padgeom:\n"
" =GAL LOFF\n"
" --\n"
" =GAL Clipping::\n"
" =P blackout:\n"
" xinerama\n"
" clip:\n"
" --\n"
" =GAL LOFF\n"
" =GAL Misc-Screen::\n"
" fixscreen:\n"
" visual:\n"
" rawfb:\n"
" pipeinput:\n"
" =GAL LOFF\n"
"\n"
"Keyboard\n"
" =D norepeat\n"
......@@ -223,28 +231,26 @@ char gui_code[] = "";
" -- D\n"
" =GA all-settings\n"
" =RA remote-cmd:\n"
" --\n"
" =F rc:\n"
" norc\n"
" filexfer\n"
" --\n"
" nofb\n"
" =D nobell\n"
" nolookup\n"
" =GAL Selection::\n"
" =D nosel\n"
" noprimary\n"
" nosetprimary\n"
" noclipboard\n"
" nosetclipboard\n"
" seldir:\n"
" =GAL LOFF\n"
" --\n"
" =GAL X-ext::\n"
" xtrap\n"
" xrecord\n"
" =RQA reset_record\n"
" =GAL LOFF\n"
" --\n"
" nofb\n"
" =D nobell\n"
" nolookup\n"
" bg\n"
" =-C:ignore,exit sigpipe:\n"
" =0 inetd\n"
" rfbwait:\n"
"\n"
"Debugging\n"
" debug_pointer\n"
......@@ -261,6 +267,7 @@ char gui_code[] = "";
" debug_scroll\n"
" debug_tiles\n"
" debug_grabs\n"
" debug_sel\n"
" dbg\n"
" =GAL LOFF\n"
" =GA show-start-cmd\n"
......@@ -269,39 +276,41 @@ char gui_code[] = "";
"Permissions\n"
" =DRQA lock\n"
" =DRQA unlock\n"
" =D shared\n"
" =D forever\n"
" --\n"
" =DFP allow:\n"
" =D localhost\n"
" =RA allowonce:\n"
" listen:\n"
" -- D\n"
" =D shared\n"
" =D forever\n"
" timeout:\n"
" --\n"
" =D viewonly\n"
" input:\n"
" --\n"
" safer\n"
" unsafe\n"
" =RA noremote\n"
" --\n"
" =GAL Passwords::\n"
" passwd:\n"
" viewpasswd:\n"
" =F passwdfile:\n"
" =F rfbauth:\n"
" usepw\n"
" --\n"
" unixpw\n"
" unixpw_list:\n"
" unixpw_nis\n"
" unixpw_nis_list:\n"
" =0 storepasswd\n"
" =GAL LOFF\n"
" =GAL Safe::\n"
" safer\n"
" unsafe\n"
" =RA noremote\n"
" =GAL LOFF\n"
" =GAL Misc-Perms::\n"
" =0S alwaysshared\n"
" =0S nevershared\n"
" =0S dontdisconnect\n"
" =SQA deny_all\n"
" timeout:\n"
" stunnel\n"
" =F stunnel_pem:\n"
" =GAL LOFF\n"
......@@ -355,6 +364,7 @@ char gui_code[] = "";
" snapfb\n"
" threads\n"
" wmdt:\n"
" rfbwait:\n"
" =GAL LOFF\n"
"\"\n"
"}\n"
......@@ -797,6 +807,7 @@ char gui_code[] = "";
"instead (these give basically the same functionality and if you mixed\n"
"them too much unexpected things may happen).\n"
"\"\n"
"#'\n"
"\n"
" set helptext(AlphaBlending:) \"\n"
"In this sub-menu we provide some tweak parameters for cursors (little\n"
......@@ -819,6 +830,7 @@ char gui_code[] = "";
"for cursors with transparency. Hopefully you won't have to use them.\n"
"Certain cursor \\\"themes\\\" may require adjustment however.\n"
"\"\n"
"#'\n"
" set helptext(OverlayVisuals:) \"\n"
"In this sub-menu are some options that involve fixing color problems\n"
"for \\\"Overlay\\\" or \\\"Multi-Depth\\\" visuals. This problem is rare\n"
......@@ -936,6 +948,48 @@ char gui_code[] = "";
"hardware writes, and the video hardware reads that x11vnc uses to poll\n"
"the screen are still slow today).\n"
"\"\n"
"#'\"\n"
"\n"
" set helptext(Safe:) \"\n"
"In this sub-menu are some options for making x11vnc operations\n"
"more, or less, safe. E.g. disable the running of external commands, etc.\n"
"\n"
"You can also turn off the Remote control channel (NOTE that doing that\n"
"will disable the GUI from being able to communicate with x11vnc).\n"
"\"\n"
"\n"
" set helptext(X-ext:) \"\n"
"In this sub-menu are a few rarely used options regarding some X extensions\n"
"used by x11vnc.\n"
"\"\n"
" set helptext(Clipping:) \"\n"
"In this sub-menu are some options regarding clipping or blacking out\n"
"portions of the Screen. E.g. under XINERAMA when the multiple monitors\n"
"are not the same size.\n"
"\n"
"\"\n"
" set helptext(Misc-Screen:) \"\n"
"In this sub-menu are some little used options modifying aspects of\n"
"the screen source.\n"
"\"\n"
"\n"
" set helptext(Settings:) \"\n"
"In this sub-menu are some options for saving and loading option settings.\n"
"The default file to store settings in is ~/.x11vncrc, but you can save\n"
"different \\\"profiles\\\" in other files for later use.\n"
"\n"
"\"\n"
" set helptext(Java-applet:) \"\n"
"In this sub-menu are some options for running the built-in HTTP server\n"
"that delivers the TightVNC Java VNC Viewer applet (VncViewer.jar) to\n"
"clients. The viewer runs in their Web browser.\n"
"\n"
"The default port listened on is 5800, so the URL is typically:\n"
"\n"
" http://hostname:5800/\n"
"\n"
"but this can be altered by -httpport, etc.\n"
"\"\n"
"\n"
" set helptext(ScrollCopyRect:) \"\n"
"This sub-menu has some options for the x11vnc Scroll detection and\n"
......
......@@ -371,6 +371,10 @@ int su_verify(char *user, char *pass) {
return 0;
}
}
if (no_external_cmds) {
rfbLog("su_verify: cannot run external commands.\n");
clean_up_exit(1);
}
#define SU_DEBUG 0
#if SU_DEBUG
......@@ -710,6 +714,7 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
unixpw_accept(user);
return;
} else {
rfbLog("unixpw_verify: crypt_verify login for %s failed.\n", user);
usleep(3000*1000);
}
} else {
......@@ -717,6 +722,7 @@ if (db) fprintf(stderr, "unixpw_verify: '%s' '%s'\n", user, db > 1 ? pass : "***
unixpw_accept(user);
return;
}
rfbLog("unixpw_verify: su_verify login for %s failed.\n", user);
}
if (tries < 2) {
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "March 2006" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.8.1, lastmod: 2006-03-06
version: 0.8.1, lastmod: 2006-03-08
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -373,6 +373,13 @@ If \fIstring\fR has the form "host" or "host:port"
the connection is made once at startup. Use commas
for a list of host's and host:port's.
.IP
Note that unlike most vnc servers, x11vnc will require a
password for reverse as well as for forward connections.
(provided password auth has been enabled, \fB-rfbauth,\fR etc)
If you do not want to require a password for reverse
connections set X11VNC_REVERSE_CONNECTION_NO_AUTH=1 in
your environment before starting x11vnc.
.IP
If \fIstring\fR contains "/" it is instead interpreted
as a file to periodically check for new hosts.
The first line is read and then the file is truncated.
......@@ -620,10 +627,13 @@ be readable. Passwords stored in /etc/shadow will
be inaccessible unless run as root. This is called
"NIS" mode simply because in most NIS setups the
user encrypted passwords are accessible (e.g. "ypcat
passwd"). NIS is not required for this mode to
work, but it is unlikely it will work for any other
environment. All of the \fB-unixpw\fR options and contraints
apply.
passwd"). NIS is not required for this mode to work
(only that
.IR getpwnam (3)
return the encrpyted password
is required), but it is unlikely it will work for any
other environment. All of the \fB-unixpw\fR options and
contraints apply.
.PP
\fB-stunnel\fR \fI[pem]\fR
.IP
......@@ -670,16 +680,33 @@ for more examples.
Use version 3.x stunnel command line syntax instead of
version 4.x
.PP
\fB-nopw\fR
\fB-usepw\fR
.IP
Disable the big warning message when you use x11vnc
without some sort of password.
If no other password method was supplied on the command
line, first look for ~/.vnc/passwd and if found use it
with \fB-rfbauth;\fR next, look for ~/.vnc/passwdfile and
use it with \fB-passwdfile;\fR otherwise, prompt the user
for a password to create ~/.vnc/passwd and use it with
the \fB-rfbauth\fR option. If none of these succeed x11vnc
exits immediately.
.IP
Note: \fB-unixpw\fR currently does not count as a password
method by this option.
.PP
\fB-storepasswd\fR \fIpass\fR \fIfile\fR
.IP
Store password \fIpass\fR as the VNC password in the
file \fIfile\fR. Once the password is stored the
program exits. Use the password via "\fB-rfbauth\fR \fIfile\fR"
.IP
If called with no arguments, i.e., "\fB-storepasswd\fR",
the user is prompted for a password and it is stored
in the file ~/.vnc/passwd
.PP
\fB-nopw\fR
.IP
Disable the big warning message when you use x11vnc
without some sort of password.
.PP
\fB-accept\fR \fIstring\fR
.IP
......@@ -1183,7 +1210,7 @@ Note: XBell monitoring requires the XKEYBOARD extension.
\fB-nosel\fR
.IP
Do not manage exchange of X selection/cutbuffer between
VNC viewers and the X server.
VNC viewers and the X server at all.
.PP
\fB-noprimary\fR
.IP
......@@ -1191,6 +1218,22 @@ Do not poll the PRIMARY selection for changes to send
back to clients. (PRIMARY is still set on received
changes, however).
.PP
\fB-nosetprimary\fR
.IP
Do not set the PRIMARY selection for changes received
from VNC clients.
.PP
\fB-noclipboard\fR
.IP
Do not poll the CLIPBOARD selection for changes to send
back to clients. (CLIPBOARD is still set on received
changes, however).
.PP
\fB-nosetclipboard\fR
.IP
Do not set the CLIPBOARD selection for changes
received from VNC clients.
.PP
\fB-seldir\fR \fIstring\fR
.IP
If direction string is "send", only send the selection
......@@ -1740,6 +1783,11 @@ experience a lot of grab deadlock, please report a bug.
Turn on debugging info printout with respect to
XGrabServer() deadlock for \fB-scrollcopyrect__mode_.\fR
.PP
\fB-debug_sel\fR
.IP
Turn on debugging info printout with respect to
PRIMARY, CLIPBOARD, and CUTBUFFER0 selections.
.PP
\fB-pointer_mode\fR \fIn\fR
.IP
Various pointer motion update schemes. "\fB-pm\fR" is
......@@ -2288,7 +2336,9 @@ nodeny allow new connections, same as "unlock"
.IP
connect:host do reverse connection to host, "host"
may be a comma separated list of hosts
or host:ports. See \fB-connect.\fR
or host:ports. See \fB-connect.\fR Passwords
required as with fwd connections.
See X11VNC_REVERSE_CONNECTION_NO_AUTH=1
.IP
disconnect:host disconnect any clients from "host"
same as "close:host". Use host
......@@ -2434,6 +2484,18 @@ noprimary enable \fB-noprimary\fR mode.
.IP
primary disable \fB-noprimary\fR mode.
.IP
nosetprimary enable \fB-nosetprimary\fR mode.
.IP
setprimary disable \fB-nosetprimary\fR mode.
.IP
noclipboard enable \fB-noclipboard\fR mode.
.IP
clipboard disable \fB-noclipboard\fR mode.
.IP
nosetclipboard enable \fB-nosetclipboard\fR mode.
.IP
setclipboard disable \fB-nosetclipboard\fR mode.
.IP
seldir:str set \fB-seldir\fR to "str"
.IP
cursor:mode enable \fB-cursor\fR "mode".
......@@ -2627,6 +2689,10 @@ debug_grabs enable \fB-debug_grabs\fR
.IP
nodebug_grabs disable \fB-debug_grabs\fR
.IP
debug_sel enable \fB-debug_sel\fR
.IP
nodebug_sel disable \fB-debug_sel\fR
.IP
dbg enable \fB-dbg\fR crash shell
.IP
nodbg disable \fB-dbg\fR crash shell
......@@ -2700,17 +2766,19 @@ shared noshared forever noforever once timeout filexfer
nofilexfer deny lock nodeny unlock connect allowonce
allow localhost nolocalhost listen lookup nolookup
accept afteraccept gone shm noshm flipbyteorder
noflipbyteorder onetile noonetile solid_color solid
nosolid blackout xinerama noxinerama xtrap noxtrap
xrandr noxrandr xrandr_mode padgeom quiet q noquiet
modtweak nomodtweak xkb noxkb skip_keycodes sloppy_keys
nosloppy_keys skip_dups noskip_dups add_keysyms
noadd_keysyms clear_mods noclear_mods clear_keys
noclear_keys remap repeat norepeat fb nofb bell
nobell sel nosel primary noprimary seldir cursorshape
nocursorshape cursorpos nocursorpos cursor show_cursor
noshow_cursor nocursor arrow xfixes noxfixes xdamage
noxdamage xd_area xd_mem alphacut alphafrac alpharemove
noflipbyteorder onetile noonetile solid_color
solid nosolid blackout xinerama noxinerama xtrap
noxtrap xrandr noxrandr xrandr_mode padgeom quiet q
noquiet modtweak nomodtweak xkb noxkb skip_keycodes
sloppy_keys nosloppy_keys skip_dups noskip_dups
add_keysyms noadd_keysyms clear_mods noclear_mods
clear_keys noclear_keys remap repeat norepeat fb nofb
bell nobell sel nosel primary noprimary setprimary
nosetprimary clipboard noclipboard setclipboard
nosetclipboard seldir cursorshape nocursorshape
cursorpos nocursorpos cursor show_cursor noshow_cursor
nocursor arrow xfixes noxfixes xdamage noxdamage
xd_area xd_mem alphacut alphafrac alpharemove
noalpharemove alphablend noalphablend xwarppointer
xwarp noxwarppointer noxwarp buttonmap dragging
nodragging wireframe_mode wireframe wf nowireframe
......
......@@ -140,6 +140,7 @@
#include "unixpw.h"
#include "inet.h"
#include "sslcmds.h"
#include "selection.h"
/*
* main routine for the x11vnc program
......@@ -950,6 +951,7 @@ static void quick_pw(char *str) {
}
fprintf(stdout, "password: ");
/* no_external_cmds does not apply */
system("stty -echo");
if(fgets(tmp, 128, stdin) == NULL) {
fprintf(stdout, "\n");
......@@ -1241,6 +1243,7 @@ static void check_loop_mode(int argc, char* argv[]) {
perror("fork");
exit(1);
} else {
/* no_external_cmds does not apply */
execvp(argv[0], argv2);
exit(1);
}
......@@ -1262,6 +1265,91 @@ static void check_loop_mode(int argc, char* argv[]) {
#endif
}
}
static void store_homedir_passwd(void) {
char str1[32], str2[32], *p, *h, *f;
struct stat sbuf;
str1[0] = '\0';
str2[0] = '\0';
if (no_external_cmds) {
fprintf(stderr, "-nocmds cannot be used with -storepasswd\n");
exit(1);
}
fprintf(stderr, "Enter VNC password: ");
system("stty -echo");
if (fgets(str1, 32, stdin) == NULL) {
system("stty echo");
exit(1);
}
fprintf(stderr, "\n");
fprintf(stderr, "Verify password: ");
if (fgets(str2, 32, stdin) == NULL) {
system("stty echo");
exit(1);
}
fprintf(stderr, "\n");
system("stty echo");
if ((p = strchr(str1, '\n')) != NULL) {
*p = '\0';
}
if ((p = strchr(str2, '\n')) != NULL) {
*p = '\0';
}
if (strcmp(str1, str2)) {
fprintf(stderr, "** passwords differ.\n");
exit(1);
}
if (str1[0] == '\0') {
fprintf(stderr, "** no password supplied.\n");
exit(1);
}
h = getenv("HOME");
if (! h) {
fprintf(stderr, "** $HOME not set.\n");
exit(1);
}
f = (char *) malloc(strlen(h) + strlen("/.vnc/passwd") + 1);
sprintf(f, "%s/.vnc", h);
if (stat(f, &sbuf) != 0) {
if (mkdir(f, 0755) != 0) {
fprintf(stderr, "** could not create directory %s\n", f);
perror("mkdir");
exit(1);
}
} else if (! S_ISDIR(sbuf.st_mode)) {
fprintf(stderr, "** not a directory %s\n", f);
exit(1);
}
sprintf(f, "%s/.vnc/passwd", h);
fprintf(stderr, "Write password to %s? [y]/n ", f);
if (fgets(str2, 32, stdin) == NULL) {
exit(1);
}
if (str2[0] == 'n' || str2[0] == 'N') {
fprintf(stderr, "not creating password.\n");
exit(1);
}
if (rfbEncryptAndStorePasswd(str1, f) != 0) {
fprintf(stderr, "** error creating password.\n");
perror("storepasswd");
exit(1);
}
fprintf(stderr, "Password written to: %s\n", f);
if (stat(f, &sbuf) != 0) {
exit(1);
}
exit(0);
}
#define SHOW_NO_PASSWORD_WARNING \
(!got_passwd && !got_rfbauth && (!got_passwdfile || !passwd_list) \
......@@ -1284,6 +1372,7 @@ int main(int argc, char* argv[]) {
int dt = 0, bg = 0;
int got_rfbwait = 0;
int got_httpdir = 0, try_http = 0;
int usepw = 0;
/* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128];
......@@ -1519,7 +1608,13 @@ int main(int argc, char* argv[]) {
}
} else if (!strcmp(arg, "-nopw")) {
nopw = 1;
} else if (!strcmp(arg, "-usepw")) {
usepw = 1;
} else if (!strcmp(arg, "-storepasswd")) {
if (i+1 >= argc) {
store_homedir_passwd();
exit(0);
}
if (i+2 >= argc || rfbEncryptAndStorePasswd(argv[i+1],
argv[i+2]) != 0) {
fprintf(stderr, "-storepasswd failed\n");
......@@ -1667,8 +1762,15 @@ int main(int argc, char* argv[]) {
} else if (!strcmp(arg, "-nosel")) {
watch_selection = 0;
watch_primary = 0;
watch_clipboard = 0;
} else if (!strcmp(arg, "-noprimary")) {
watch_primary = 0;
} else if (!strcmp(arg, "-nosetprimary")) {
set_primary = 0;
} else if (!strcmp(arg, "-noclipboard")) {
watch_clipboard = 0;
} else if (!strcmp(arg, "-nosetclipboard")) {
set_clipboard = 0;
} else if (!strcmp(arg, "-seldir")) {
CHECK_ARGC
sel_direction = strdup(argv[++i]);
......@@ -1890,6 +1992,8 @@ int main(int argc, char* argv[]) {
debug_tiles++;
} else if (!strcmp(arg, "-debug_grabs")) {
debug_grabs++;
} else if (!strcmp(arg, "-debug_sel")) {
debug_sel++;
} else if (!strcmp(arg, "-grab_buster")) {
grab_buster++;
} else if (!strcmp(arg, "-nograb_buster")) {
......@@ -2109,6 +2213,83 @@ int main(int argc, char* argv[]) {
}
}
if (usepw && ! got_rfbauth && ! got_passwd && ! got_passwdfile) {
char *f, *h = getenv("HOME");
struct stat sbuf;
int found = 0, set_rfbauth = 0;
if (!h) {
rfbLog("HOME unset in -usepw mode.\n");
exit(1);
}
f = (char *) malloc(strlen(h)+strlen("/.vnc/passwdfile") + 1);
sprintf(f, "%s/.vnc/passwd", h);
if (stat(f, &sbuf) == 0) {
found = 1;
if (! quiet) {
rfbLog("-usepw: found %s\n", f);
}
got_rfbauth = 1;
set_rfbauth = 1;
}
sprintf(f, "%s/.vnc/passwdfile", h);
if (! found && stat(f, &sbuf) == 0) {
found = 1;
if (! quiet) {
rfbLog("-usepw: found %s\n", f);
}
got_passwdfile = 1;
passwdfile = strdup(f);
}
#if LIBVNCSERVER_HAVE_FORK
#if LIBVNCSERVER_HAVE_SYS_WAIT_H
#if LIBVNCSERVER_HAVE_WAITPID
if (! found) {
pid_t pid = fork();
if (pid < 0) {
;
} else if (pid == 0) {
execlp(argv[0], argv[0], "-storepasswd",
(char *) NULL);
exit(1);
} else {
int s;
waitpid(pid, &s, 0);
if (WIFEXITED(s) && WEXITSTATUS(s) == 0) {
got_rfbauth = 1;
set_rfbauth = 1;
found = 1;
}
}
}
#endif
#endif
#endif
if (set_rfbauth) {
sprintf(f, "%s/.vnc/passwd", h);
if (argc_vnc < 100) {
argv_vnc[argc_vnc++] = strdup("-rfbauth");
} else {
exit(1);
}
if (argc_vnc < 100) {
argv_vnc[argc_vnc++] = strdup(f);
} else {
exit(1);
}
}
if (! found) {
fprintf(stderr, "x11vnc -usepw: could not find"
" a password to use.\n");
exit(1);
}
free(f);
}
if (got_rfbauth && (got_passwd || got_viewpasswd || got_passwdfile)) {
fprintf(stderr, "option -rfbauth is incompatible with:\n");
fprintf(stderr, " -passwd, -viewpasswd, and -passwdfile\n");
......
......@@ -37,9 +37,10 @@
/****************************************************************************/
/* Build-time customization via CPPFLAGS. */
/*
* Build-time customization via CPPFLAGS.
*
* Summary of options to include in CPPFLAGS for custom builds:
*
* -DVNCSHARED to have the vnc display shared by default.
......@@ -63,6 +64,7 @@
* -DWIREFRAME_PARMS=... set default -wirecopyrect parameters.
* -DSCROLL_COPYRECT=0 to have -noscrollcopyrect as the default.
* -DSCROLL_COPYRECT_PARMS=... set default -scrollcopyrect parameters.
* -DSCALING_COPYRECT=0
* -DXDAMAGE=0 to have -noxdamage as the default.
* -DSKIPDUPS=0 to have -noskip_dups as the default or vice versa.
*
......@@ -71,6 +73,8 @@
* -DSMALL_FOOTPRINT=1 for smaller binary size (no help, no gui, etc)
* use 2 or 3 for even smaller footprint.
* -DNOGUI do not include the gui tkx11vnc.
* -DPOLL_8TO24_DELAY=N
* -DDEBUG_XEVENTS=1 enable printout for X events.
*
* Set these in CPPFLAGS before running configure. E.g.:
*
......
......@@ -15,7 +15,7 @@ int xtrap_base_event_type = 0;
int xdamage_base_event_type = 0;
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.8.1 lastmod: 2006-03-06";
char lastmod[] = "0.8.1 lastmod: 2006-03-08";
/* X display info */
......
......@@ -19,6 +19,7 @@ int sync_tod_delay = 3;
void initialize_vnc_connect_prop(void);
void initialize_x11vnc_remote_prop(void);
void initialize_clipboard_atom(void);
void spawn_grab_buster(void);
void sync_tod_with_servertime(void);
void check_keycode_state(void);
......@@ -45,11 +46,25 @@ void initialize_x11vnc_remote_prop(void) {
x11vnc_remote_prop = XInternAtom(dpy, "X11VNC_REMOTE", False);
}
void initialize_clipboard_atom(void) {
clipboard_atom = XInternAtom(dpy, "CLIPBOARD", False);
if (clipboard_atom == None) {
if (! quiet) rfbLog("could not find atom CLIPBOARD\n");
if (watch_clipboard) {
watch_clipboard = 0;
}
if (set_clipboard) {
set_clipboard = 0;
}
}
}
static void initialize_xevents(void) {
static int did_xselect_input = 0;
static int did_xcreate_simple_window = 0;
static int did_vnc_connect_prop = 0;
static int did_x11vnc_remote_prop = 0;
static int did_clipboard_atom = 0;
static int did_xfixes = 0;
static int did_xdamage = 0;
static int did_xrandr = 0;
......@@ -90,6 +105,10 @@ static void initialize_xevents(void) {
kill(run_gui_pid, SIGUSR1);
run_gui_pid = 0;
}
if (!did_clipboard_atom) {
initialize_clipboard_atom();
did_clipboard_atom = 1;
}
if (xfixes_present && use_xfixes && !did_xfixes) {
initialize_xfixes();
did_xfixes = 1;
......@@ -662,13 +681,13 @@ void check_xevents(void) {
XEvent xev;
int tmp, have_clients = 0;
static int sent_some_sel = 0;
static time_t last_request = 0;
static time_t last_call = 0;
static time_t last_bell = 0;
static time_t last_init_check = 0;
static time_t last_sync = 0;
static time_t last_time_sync = 0;
time_t now = time(0);
static double last_request = 0.0;
if (raw_fb && ! dpy) return; /* raw_fb hack */
......@@ -798,56 +817,119 @@ void check_xevents(void) {
#endif
/* check for our PRIMARY request notification: */
if (watch_primary) {
if (watch_primary || watch_clipboard) {
int doprimary = 1, doclipboard = 2, which, own;
double delay = 1.0;
Atom atom;
char *req;
if (XCheckTypedEvent(dpy, SelectionNotify, &xev)) {
if (xev.type == SelectionNotify &&
xev.xselection.requestor == selwin &&
xev.xselection.selection == XA_PRIMARY &&
xev.xselection.property != None &&
xev.xselection.target == XA_STRING) {
/* go retrieve PRIMARY and check it */
Atom s = xev.xselection.selection;
if (s == XA_PRIMARY || s == clipboard_atom) {
/* go retrieve it and check it */
if (now > last_client + sel_waittime
|| sent_some_sel) {
selection_send(&xev);
}
}
}
if (now > last_request) {
}
/*
* Every second or two, request PRIMARY, unless we
* already own it or there is no owner or we have
* no clients.
* Every second or so, request PRIMARY or CLIPBOARD,
* unless we already own it or there is no owner or we
* have no clients.
* TODO: even at this low rate we should look into
* and performance problems in odds cases, etc.
* and performance problems in odds cases (large text,
* modem, etc.)
*/
last_request = now;
if (! own_selection && have_clients &&
XGetSelectionOwner(dpy, XA_PRIMARY) != None) {
XConvertSelection(dpy, XA_PRIMARY, XA_STRING,
XA_STRING, selwin, CurrentTime);
which = 0;
if (watch_primary && watch_clipboard && ! own_clipboard &&
! own_primary) {
delay = 0.6;
}
if (dnow() > last_request + delay) {
/*
* It is not a good idea to do both at the same
* time so we must choose one:
*/
if (watch_primary && watch_clipboard) {
static int count = 0;
if (own_clipboard) {
which = doprimary;
} else if (own_primary) {
which = doclipboard;
} else if (count++ % 3 == 0) {
which = doclipboard;
} else {
which = doprimary;
}
} else if (watch_primary) {
which = doprimary;
} else if (watch_clipboard) {
which = doclipboard;
}
last_request = dnow();
}
atom = None;
req = "none";
if (which == doprimary) {
own = own_primary;
atom = XA_PRIMARY;
req = "PRIMARY";
} else if (which == doclipboard) {
own = own_clipboard;
atom = clipboard_atom;
req = "CLIPBOARD";
}
if (which != 0 && ! own && have_clients &&
XGetSelectionOwner(dpy, atom) != None) {
XConvertSelection(dpy, atom, XA_STRING, XA_STRING,
selwin, CurrentTime);
if (debug_sel) {
rfbLog("request %s\n", req);
}
}
}
if (own_selection) {
/* we own PRIMARY, see if someone requested it: */
if (own_primary || own_clipboard) {
/* we own PRIMARY or CLIPBOARD, see if someone requested it: */
if (XCheckTypedEvent(dpy, SelectionRequest, &xev)) {
if (xev.type == SelectionRequest &&
if (own_primary && xev.type == SelectionRequest &&
xev.xselectionrequest.selection == XA_PRIMARY) {
selection_request(&xev);
selection_request(&xev, "PRIMARY");
}
if (own_clipboard && xev.type == SelectionRequest &&
xev.xselectionrequest.selection == clipboard_atom) {
selection_request(&xev, "CLIPBOARD");
}
}
/* we own PRIMARY, see if we no longer own it: */
/* we own PRIMARY or CLIPBOARD, see if we no longer own it: */
if (XCheckTypedEvent(dpy, SelectionClear, &xev)) {
if (xev.type == SelectionClear &&
if (own_primary && xev.type == SelectionClear &&
xev.xselectionclear.selection == XA_PRIMARY) {
own_selection = 0;
if (xcut_str) {
free(xcut_str);
xcut_str = NULL;
own_primary = 0;
if (xcut_str_primary) {
free(xcut_str_primary);
xcut_str_primary = NULL;
}
if (debug_sel) {
rfbLog("Released PRIMARY.\n");
}
}
if (own_clipboard && xev.type == SelectionClear &&
xev.xselectionclear.selection == clipboard_atom) {
own_clipboard = 0;
if (xcut_str_clipboard) {
free(xcut_str_clipboard);
xcut_str_clipboard = NULL;
}
if (debug_sel) {
rfbLog("Released CLIPBOARD.\n");
}
}
}
......@@ -986,21 +1068,51 @@ void xcut_receive(char *text, int len, rfbClientPtr cl) {
X_LOCK;
/* associate this text with PRIMARY (and SECONDARY...) */
if (! own_selection) {
own_selection = 1;
if (set_primary && ! own_primary) {
own_primary = 1;
/* we need to grab the PRIMARY selection */
XSetSelectionOwner(dpy, XA_PRIMARY, selwin, CurrentTime);
XFlush(dpy);
if (debug_sel) {
rfbLog("Own PRIMARY.\n");
}
}
if (set_clipboard && ! own_clipboard && clipboard_atom != None) {
own_clipboard = 1;
/* we need to grab the CLIPBOARD selection */
XSetSelectionOwner(dpy, clipboard_atom, selwin, CurrentTime);
XFlush(dpy);
if (debug_sel) {
rfbLog("Own CLIPBOARD.\n");
}
}
/* duplicate the text string for our own use. */
if (xcut_str != NULL) {
free(xcut_str);
xcut_str = NULL;
if (set_primary) {
if (xcut_str_primary != NULL) {
free(xcut_str_primary);
xcut_str_primary = NULL;
}
xcut_str_primary = (char *) malloc((size_t) (len+1));
strncpy(xcut_str_primary, text, len);
xcut_str_primary[len] = '\0'; /* make sure null terminated */
if (debug_sel) {
rfbLog("Set PRIMARY '%s'\n", xcut_str_primary);
}
}
if (set_clipboard) {
if (xcut_str_clipboard != NULL) {
free(xcut_str_clipboard);
xcut_str_clipboard = NULL;
}
xcut_str_clipboard = (char *) malloc((size_t) (len+1));
strncpy(xcut_str_clipboard, text, len);
xcut_str_clipboard[len] = '\0'; /* make sure null terminated */
if (debug_sel) {
rfbLog("Set CLIPBOARD '%s'\n", xcut_str_clipboard);
}
}
xcut_str = (char *) malloc((size_t) (len+1));
strncpy(xcut_str, text, len);
xcut_str[len] = '\0'; /* make sure null terminated */
/* copy this text to CUT_BUFFER0 as well: */
XChangeProperty(dpy, rootwin, XA_CUT_BUFFER0, XA_STRING, 8,
......
......@@ -8,6 +8,7 @@ extern int sync_tod_delay;
extern void initialize_vnc_connect_prop(void);
extern void initialize_x11vnc_remote_prop(void);
extern void initialize_clipboard_atom(void);
extern void spawn_grab_buster(void);
extern void sync_tod_with_servertime(void);
extern void check_keycode_state(void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment