summaryrefslogtreecommitdiffstats
path: root/x11vnc/x11vnc.c
diff options
context:
space:
mode:
authorrunge <runge>2005-02-11 04:14:20 +0000
committerrunge <runge>2005-02-11 04:14:20 +0000
commit86ccf267b18b30a3c0d4f5b96b6738f3c2b17e2b (patch)
tree519106dc628376f40e8cf065742cda1396fe8084 /x11vnc/x11vnc.c
parent5b18d40136b20695b4048a69fcfbd0631ad7bb81 (diff)
downloadlibtdevnc-86ccf267b18b30a3c0d4f5b96b6738f3c2b17e2b.tar.gz
libtdevnc-86ccf267b18b30a3c0d4f5b96b6738f3c2b17e2b.zip
x11vnc -input to fine tune allow user input. per-client settings -R
Diffstat (limited to 'x11vnc/x11vnc.c')
-rw-r--r--x11vnc/x11vnc.c614
1 files changed, 501 insertions, 113 deletions
diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c
index af15260..89bef9d 100644
--- a/x11vnc/x11vnc.c
+++ b/x11vnc/x11vnc.c
@@ -290,7 +290,7 @@ static int xdamage_base_event_type;
#endif
/* date +'lastmod: %Y-%m-%d' */
-char lastmod[] = "0.7.1pre lastmod: 2005-02-08";
+char lastmod[] = "0.7.1pre lastmod: 2005-02-10";
/* X display info */
@@ -346,13 +346,19 @@ unsigned short main_red_shift, main_green_shift, main_blue_shift;
/* we now have a struct with client specific data: */
#define RATE_SAMPLES 5
+#define CILEN 10
typedef struct _ClientData {
- int had_cursor_shape_updates;
- int had_cursor_pos_updates;
int uid;
+ char *hostname;
int client_port;
int server_port;
char *server_ip;
+ char input[CILEN];
+ int login_viewonly;
+
+ int had_cursor_shape_updates;
+ int had_cursor_pos_updates;
+
double timer;
double send_cmp_rate;
double send_raw_rate;
@@ -445,6 +451,7 @@ double dtime(double *);
void initialize_blackouts(char *);
void initialize_blackouts_and_xinerama(void);
void initialize_keyboard_and_pointer(void);
+void initialize_allowed_input(void);
void initialize_modtweak(void);
void initialize_pointer_map(char *);
void initialize_cursors_mode(void);
@@ -519,6 +526,8 @@ void check_xevents(void);
char *this_host(void);
void set_vnc_desktop_name(void);
+char *short_kmb(char *);
+
int get_cmp_rate(void);
int get_raw_rate(void);
int get_read_rate(void);
@@ -574,6 +583,9 @@ char *allow_once = NULL; /* one time -allow */
char *accept_cmd = NULL; /* for -accept */
char *gone_cmd = NULL; /* for -gone */
int view_only = 0; /* clients can only watch. */
+char *allowed_input_view_only = NULL;
+char *allowed_input_normal = NULL;
+char *allowed_input_str = NULL;
char *viewonly_passwd = NULL; /* view only passwd. */
int inetd = 0; /* spawned from inetd(1) */
int connect_once = 1; /* disconnect after first connection session. */
@@ -776,6 +788,18 @@ void lowercase(char *str) {
}
}
+void uppercase(char *str) {
+ char *p;
+ if (str == NULL) {
+ return;
+ }
+ p = str;
+ while (*p != '\0') {
+ *p = toupper(*p);
+ p++;
+ }
+}
+
char *lblanks(char *str) {
char *p = str;
while (*p) {
@@ -1325,6 +1349,31 @@ char *host2ip(char *host) {
return str;
}
+char *ip2host(char *ip) {
+ char *str;
+#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
+ struct hostent *hp;
+#ifndef in_addr_t
+typedef unsigned int in_addr_t;
+#endif
+ in_addr_t iaddr;
+
+ iaddr = inet_addr(ip);
+ if (iaddr == INADDR_NONE) {
+ return strdup("unknown");
+ }
+
+ hp = gethostbyaddr((char *)&iaddr, sizeof(in_addr_t), AF_INET);
+ if (!hp) {
+ return strdup("unknown");
+ }
+ str = strdup(hp->h_name);
+#else
+ str = strdup("unknown");
+#endif
+ return str;
+}
+
int dotted_ip(char *host) {
char *p = host;
while (*p != '\0') {
@@ -1337,20 +1386,34 @@ int dotted_ip(char *host) {
return 1;
}
-int get_remote_port(int sock) {
+int get_port(int sock, int remote) {
struct sockaddr_in saddr;
int saddr_len, saddr_port;
saddr_len = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
saddr_port = -1;
- if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
- saddr_port = ntohs(saddr.sin_port);
+ if (remote) {
+ if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
+ saddr_port = ntohs(saddr.sin_port);
+ }
+ } else {
+ if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
+ saddr_port = ntohs(saddr.sin_port);
+ }
}
return saddr_port;
}
-char *get_remote_host(int sock) {
+int get_remote_port(int sock) {
+ return get_port(sock, 1);
+}
+
+int get_local_port(int sock) {
+ return get_port(sock, 0);
+}
+
+char *get_host(int sock, int remote) {
struct sockaddr_in saddr;
int saddr_len, saddr_port;
char *saddr_ip_str = NULL;
@@ -1358,47 +1421,29 @@ char *get_remote_host(int sock) {
saddr_len = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
saddr_port = -1;
- if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
#if LIBVNCSERVER_HAVE_NETINET_IN_H
- saddr_ip_str = inet_ntoa(saddr.sin_addr);
-#endif
+ if (remote) {
+ if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
+ saddr_ip_str = inet_ntoa(saddr.sin_addr);
+ }
+ } else {
+ if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
+ saddr_ip_str = inet_ntoa(saddr.sin_addr);
+ }
}
+#endif
if (! saddr_ip_str) {
- saddr_ip_str = strdup("unknown");
+ saddr_ip_str = "unknown";
}
- return saddr_ip_str;
+ return strdup(saddr_ip_str);
}
-int get_local_port(int sock) {
- struct sockaddr_in saddr;
- int saddr_len, saddr_port;
-
- saddr_len = sizeof(saddr);
- memset(&saddr, 0, sizeof(saddr));
- saddr_port = -1;
- if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
- saddr_port = ntohs(saddr.sin_port);
- }
- return saddr_port;
+char *get_remote_host(int sock) {
+ return get_host(sock, 1);
}
char *get_local_host(int sock) {
- struct sockaddr_in saddr;
- int saddr_len, saddr_port;
- char *saddr_ip_str = NULL;
-
- saddr_len = sizeof(saddr);
- memset(&saddr, 0, sizeof(saddr));
- saddr_port = -1;
- if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
-#if LIBVNCSERVER_HAVE_NETINET_IN_H
- saddr_ip_str = inet_ntoa(saddr.sin_addr);
-#endif
- }
- if (! saddr_ip_str) {
- saddr_ip_str = strdup("unknown");
- }
- return saddr_ip_str;
+ return get_host(sock, 0);
}
/*
@@ -2072,10 +2117,13 @@ char *list_clients(void) {
rfbReleaseClientIterator(iter);
/*
- * each client: 123.123.123.123:60000/0x11111111-rw, = 36 bytes
- * so count+1 * 100 must cover it.
+ * each client:
+ * <id>:<ip>:<port>:<hostname>:<input>:<loginview>,
+ * 8+1+16+1+5+1+256+1+5+1+1+1
+ * 123.123.123.123:60000/0x11111111-rw, = 297 bytes
+ * so count+1 * 400 must cover it.
*/
- list = (char *) malloc((count+1)*100);
+ list = (char *) malloc((count+1)*400);
list[0] = '\0';
@@ -2085,14 +2133,18 @@ char *list_clients(void) {
if (*list != '\0') {
strcat(list, ",");
}
+ sprintf(tmp, "0x%x:", cd->uid);
+ strcat(list, tmp);
strcat(list, cl->host);
- sprintf(tmp, ":%d/0x%x", get_remote_port(cl->sock), cd->uid);
+ strcat(list, ":");
+ sprintf(tmp, "%d:", cd->client_port);
+ strcat(list, tmp);
+ strcat(list, cd->hostname);
+ strcat(list, ":");
+ strcat(list, cd->input);
+ strcat(list, ":");
+ sprintf(tmp, "%d", cd->login_viewonly);
strcat(list, tmp);
- if (cl->viewOnly) {
- strcat(list, "-ro");
- } else {
- strcat(list, "-rw");
- }
}
rfbReleaseClientIterator(iter);
return list;
@@ -2114,23 +2166,18 @@ void close_all_clients(void) {
rfbReleaseClientIterator(iter);
}
-void close_clients(char *str) {
+rfbClientPtr *client_match(char *str) {
rfbClientIteratorPtr iter;
- rfbClientPtr cl;
- int host_warn = 0, hex_warn = 0;
-
- if (!strcmp(str, "all") || !strcmp(str, "*")) {
- close_all_clients();
- return;
- }
-
- if (! screen) {
- return;
- }
+ rfbClientPtr cl, *cl_list;
+ int i, n, host_warn = 0, hex_warn = 0;
+ n = client_count + 10;
+ cl_list = (rfbClientPtr *) malloc(n * sizeof(rfbClientPtr));
+
+ i = 0;
iter = rfbGetClientIterator(screen);
while( (cl = rfbClientIteratorNext(iter)) ) {
- if (strstr(str, "0x")) {
+ if (strstr(str, "0x") == str) {
int id;
ClientData *cd = (ClientData *) cl->clientData;
if (sscanf(str, "0x%x", &id) != 1) {
@@ -2141,8 +2188,7 @@ void close_clients(char *str) {
continue;
}
if ( cd->uid == id) {
- rfbCloseClient(cl);
- rfbClientConnectionGone(cl);
+ cl_list[i++] = cl;
}
} else {
char *rstr = str;
@@ -2159,15 +2205,77 @@ void close_clients(char *str) {
rfbLog("lookup: %s -> %s\n", str, rstr);
}
if (!strcmp(rstr, cl->host)) {
- rfbCloseClient(cl);
- rfbClientConnectionGone(cl);
+ cl_list[i++] = cl;
}
if (rstr != str) {
free(rstr);
}
}
+ if (i >= n - 1) {
+ break;
+ }
}
rfbReleaseClientIterator(iter);
+
+ cl_list[i] = NULL;
+
+ return cl_list;
+}
+
+void close_clients(char *str) {
+ rfbClientPtr *cl_list, *cp;
+
+ if (!strcmp(str, "all") || !strcmp(str, "*")) {
+ close_all_clients();
+ return;
+ }
+
+ if (! screen) {
+ return;
+ }
+
+ cl_list = client_match(str);
+
+ cp = cl_list;
+ while (*cp) {
+ rfbCloseClient(*cp);
+ rfbClientConnectionGone(*cp);
+ cp++;
+ }
+ free(cl_list);
+}
+
+void set_client_input(char *str) {
+ rfbClientPtr *cl_list, *cp;
+ char *p, *val;
+
+ /* str is "match:value" */
+
+ if (! screen) {
+ return;
+ }
+
+ p = strchr(str, ':');
+ if (! p) {
+ return;
+ }
+ *p = '\0';
+ p++;
+ val = short_kmb(p);
+
+ cl_list = client_match(str);
+
+ cp = cl_list;
+ while (*cp) {
+ ClientData *cd = (ClientData *) (*cp)->clientData;
+ cd->input[0] = '\0';
+ strcat(cd->input, "_");
+ strcat(cd->input, val);
+ cp++;
+ }
+
+ free(val);
+ free(cl_list);
}
/*
@@ -2221,7 +2329,9 @@ static int run_user_command(char *cmd, rfbClientPtr client, char *mode) {
if (cd && cd->server_ip) {
set_env("RFB_SERVER_IP", cd->server_ip);
} else {
- set_env("RFB_SERVER_IP", get_local_host(client->sock));
+ char *sip = get_local_host(client->sock);
+ set_env("RFB_SERVER_IP", sip);
+ free(sip);
}
if (cd && cd->server_port > 0) {
@@ -2287,8 +2397,13 @@ static void client_gone(rfbClientPtr client) {
if (client->clientData) {
ClientData *cd = (ClientData *) client->clientData;
- if (cd && cd->server_ip) {
- free(cd->server_ip);
+ if (cd) {
+ if (cd->server_ip) {
+ free(cd->server_ip);
+ }
+ if (cd->hostname) {
+ free(cd->hostname);
+ }
}
free(client->clientData);
}
@@ -3288,9 +3403,6 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
return(RFB_CLIENT_REFUSE);
}
- if (view_only) {
- client->viewOnly = TRUE;
- }
client->clientData = (void *) calloc(sizeof(ClientData), 1);
cd = (ClientData *) client->clientData;
@@ -3298,7 +3410,11 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
cd->client_port = get_remote_port(client->sock);
cd->server_port = get_local_port(client->sock);
- cd->server_ip = strdup(get_remote_host(client->sock));
+ cd->server_ip = get_local_host(client->sock);
+ cd->hostname = ip2host(client->host);
+
+ cd->input[0] = '-';
+ cd->login_viewonly = -1;
client->clientGoneHook = client_gone;
client_count++;
@@ -3327,6 +3443,54 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
return(RFB_CLIENT_ACCEPT);
}
+void check_new_clients(void) {
+ static int last_count = 0;
+ rfbClientIteratorPtr iter;
+ rfbClientPtr cl;
+
+ if (client_count == last_count) {
+ return;
+ }
+
+ if (! all_clients_initialized()) {
+ return;
+ }
+
+ last_count = client_count;
+ if (! client_count) {
+ return;
+ }
+ if (! screen) {
+ return;
+ }
+
+ iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) ) {
+ ClientData *cd = (ClientData *) cl->clientData;
+
+ if (cd->login_viewonly < 0) {
+ /* this is a general trigger to initialize things */
+ if (cl->viewOnly) {
+ cd->login_viewonly = 1;
+ if (allowed_input_view_only) {
+ cl->viewOnly = FALSE;
+ cd->input[0] = '\0';
+ strncpy(cd->input,
+ allowed_input_view_only, CILEN);
+ }
+ } else {
+ cd->login_viewonly = 0;
+ if (allowed_input_normal) {
+ cd->input[0] = '\0';
+ strncpy(cd->input,
+ allowed_input_normal, CILEN);
+ }
+ }
+ }
+ }
+ rfbReleaseClientIterator(iter);
+}
+
/* -- keyboard.c -- */
/*
* Routine to retreive current state keyboard. 1 means down, 0 up.
@@ -4494,6 +4658,99 @@ if (sym >> 8 == 0) { \
}
#endif
+char *short_kmb(char *str) {
+ int i, saw_k = 0, saw_m = 0, saw_b = 0, n = 10;
+ char *p, tmp[10];
+
+ for (i=0; i<n; i++) {
+ tmp[i] = '\0';
+ }
+
+ p = str;
+ i = 0;
+ while (*p) {
+ if ((*p == 'K' || *p == 'k') && !saw_k) {
+ tmp[i++] = 'K';
+ saw_k = 1;
+ } else if ((*p == 'M' || *p == 'm') && !saw_m) {
+ tmp[i++] = 'M';
+ saw_m = 1;
+ } else if ((*p == 'B' || *p == 'b') && !saw_b) {
+ tmp[i++] = 'B';
+ saw_b = 1;
+ }
+ p++;
+ }
+ return(strdup(tmp));
+}
+
+void initialize_allowed_input(void) {
+ char *str;
+
+ if (allowed_input_normal) {
+ free(allowed_input_normal);
+ }
+ if (allowed_input_view_only) {
+ free(allowed_input_view_only);
+ }
+
+ if (! allowed_input_str) {
+ allowed_input_normal = strdup("KMB");
+ allowed_input_view_only = strdup("");
+ } else {
+ char *p, *str = strdup(allowed_input_str);
+ p = strchr(str, ',');
+ if (p) {
+ allowed_input_view_only = strdup(p+1);
+ *p = '\0';
+ allowed_input_normal = strdup(str);
+ } else {
+ allowed_input_normal = strdup(str);
+ allowed_input_view_only = strdup("");
+ }
+ free(str);
+ }
+
+ /* shorten them */
+ str = short_kmb(allowed_input_normal);
+ free(allowed_input_normal);
+ allowed_input_normal = str;
+
+ str = short_kmb(allowed_input_view_only);
+ free(allowed_input_view_only);
+ allowed_input_view_only = str;
+
+ if (screen) {
+ rfbClientIteratorPtr iter;
+ rfbClientPtr cl;
+
+ iter = rfbGetClientIterator(screen);
+ while( (cl = rfbClientIteratorNext(iter)) ) {
+ ClientData *cd = (ClientData *) cl->clientData;
+
+ if (cd->input[0] == '=') {
+ ; /* custom setting */
+ } else if (cd->login_viewonly) {
+ if (*allowed_input_view_only != '\0') {
+ cl->viewOnly = FALSE;
+ cd->input[0] = '\0';
+ strncpy(cd->input,
+ allowed_input_view_only, CILEN);
+ } else {
+ cl->viewOnly = TRUE;
+ }
+ } else {
+ if (allowed_input_normal) {
+ cd->input[0] = '\0';
+ strncpy(cd->input,
+ allowed_input_normal, CILEN);
+ }
+ }
+ }
+ rfbReleaseClientIterator(iter);
+ }
+}
+
void initialize_keyboard_and_pointer(void) {
if (use_modifier_tweak) {
initialize_modtweak();
@@ -4664,13 +4921,6 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
down ? "down" : "up", (int) keysym);
}
- if (view_only) {
- return;
- }
- if (client && client->viewOnly) {
- return;
- }
-
#define ADJUSTMOD(sym, state) \
if (keysym == sym) { \
if (down) { \
@@ -4715,6 +4965,54 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
}
}
+typedef struct allowed_input {
+ int keystroke;
+ int motion;
+ int button;
+} allowed_input_t;
+
+void get_allowed_input(rfbClientPtr client, allowed_input_t *input) {
+ ClientData *cd;
+ char *str;
+
+ input->keystroke = 0;
+ input->motion = 0;
+ input->button = 0;
+
+ if (! client) {
+ return;
+ }
+
+ cd = (ClientData *) client->clientData;
+
+ if (cd->input[0] != '-') {
+ str = cd->input;
+ } else if (client->viewOnly) {
+ if (allowed_input_view_only) {
+ str = allowed_input_view_only;
+ } else {
+ str = "";
+ }
+ } else {
+ if (allowed_input_normal) {
+ str = allowed_input_normal;
+ } else {
+ str = "KMB";
+ }
+ }
+
+ while (*str) {
+ if (*str == 'K') {
+ input->keystroke = 1;
+ } else if (*str == 'M') {
+ input->motion = 1;
+ } else if (*str == 'B') {
+ input->button = 1;
+ }
+ str++;
+ }
+}
+
/*
* key event handler. See the above functions for contortions for
* running under -modtweak.
@@ -4724,6 +5022,7 @@ static rfbClientPtr last_keyboard_client = NULL;
void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
KeyCode k;
int isbutton = 0;
+ allowed_input_t input;
if (debug_keyboard) {
char *str;
@@ -4737,7 +5036,8 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
if (view_only) {
return;
}
- if (client && client->viewOnly) {
+ get_allowed_input(client, &input);
+ if (! input.keystroke) {
return;
}
@@ -5074,10 +5374,9 @@ void initialize_pointer_map(char *pointer_remap) {
}
/*
- * Send a pointer event to the X server.
+ * Send a pointer position event to the X server.
*/
-static void update_x11_pointer(int mask, int x, int y) {
- int i, mb;
+static void update_x11_pointer_position(int x, int y) {
X_LOCK;
if (use_xwarppointer) {
@@ -5100,6 +5399,25 @@ static void update_x11_pointer(int mask, int x, int y) {
last_event = last_input = time(0);
+ if (nofb) {
+ /*
+ * nofb is for, e.g. Win2VNC, where fastest pointer
+ * updates are desired.
+ */
+ X_LOCK;
+ XFlush(dpy);
+ X_UNLOCK;
+ }
+}
+
+/*
+ * Send a pointer position event to the X server.
+ */
+static void update_x11_pointer_mask(int mask) {
+ int i, mb;
+
+ last_event = last_input = time(0);
+
X_LOCK;
/* look for buttons that have be clicked or released: */
for (i=0; i < MAX_BUTTONS; i++) {
@@ -5165,14 +5483,6 @@ static void update_x11_pointer(int mask, int x, int y) {
}
}
- if (nofb) {
- /*
- * nofb is for, e.g. Win2VNC, where fastest pointer
- * updates are desired.
- */
- XFlush(dpy);
- }
-
X_UNLOCK;
/*
@@ -5185,9 +5495,10 @@ static void update_x11_pointer(int mask, int x, int y) {
/*
* Actual callback from libvncserver when it gets a pointer event.
* This may queue pointer events rather than sending them immediately
- * to the X server. (see update_x11_pointer())
+ * to the X server. (see update_x11_pointer*())
*/
void pointer(int mask, int x, int y, rfbClientPtr client) {
+ allowed_input_t input;
if (debug_pointer && mask >= 0) {
static int show_motion = -1;
@@ -5207,7 +5518,8 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
if (view_only) {
return;
}
- if (client && client->viewOnly) {
+ get_allowed_input(client, &input);
+ if (! input.motion && ! input.button) {
return;
}
if (scaling) {
@@ -5277,6 +5589,13 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
ev[i][0] = mask;
ev[i][1] = x;
ev[i][2] = y;
+ if (! input.button) {
+ ev[i][0] = -1;
+ }
+ if (! input.motion) {
+ ev[i][1] = -1;
+ ev[i][2] = -1;
+ }
UNLOCK(pointerMutex);
if (debug_pointer) {
rfbLog("pointer(): deferring event "
@@ -5291,7 +5610,12 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
if (debug_pointer) {
rfbLog("pointer(): sending event %d\n", i+1);
}
- update_x11_pointer(ev[i][0], ev[i][1], ev[i][2]);
+ if (ev[i][1] >= 0) {
+ update_x11_pointer_position(ev[i][1], ev[i][2]);
+ }
+ if (ev[i][0] >= 0) {
+ update_x11_pointer_mask(ev[i][0]);
+ }
}
if (nevents && dt > maxwait) {
X_LOCK;
@@ -5313,7 +5637,12 @@ void pointer(int mask, int x, int y, rfbClientPtr client) {
}
/* update the X display with the event: */
- update_x11_pointer(mask, x, y);
+ if (input.motion) {
+ update_x11_pointer_position(x, y);
+ }
+ if (input.button) {
+ update_x11_pointer_mask(mask);
+ }
}
/* -- xkb_bell.c -- */
@@ -6098,16 +6427,22 @@ void check_xevents(void) {
* hook called when a VNC client sends us some "XCut" text (rfbClientCutText).
*/
void xcut_receive(char *text, int len, rfbClientPtr cl) {
+ allowed_input_t input;
if (!watch_selection) {
return;
}
- if (cl && cl->viewOnly) {
+ if (view_only) {
return;
}
if (text == NULL || len == 0) {
return;
}
+ get_allowed_input(cl, &input);
+ if (!input.keystroke && !input.motion && !input.button) {
+ /* maybe someday KMBC for cut text... */
+ return;
+ }
X_LOCK;
@@ -8013,6 +8348,34 @@ char *process_remote_cmd(char *cmd, int stringonly) {
rfbLog("process_remote_cmd: setting input_skip %d\n", is);
ui_skip = is;
+ } else if (strstr(p, "input") == p) {
+ int doit = 1;
+ COLON_CHECK("input:")
+ if (query) {
+ snprintf(buf, bufn, "ans=%s%s%s", p, co,
+ NONUL(allowed_input_str));
+ goto qry;
+ }
+ p += strlen("input:");
+ if (allowed_input_str && !strcmp(p, allowed_input_str)) {
+ doit = 0;
+ }
+ rfbLog("process_remote_cmd: setting input %s\n", p);
+ if (allowed_input_str) free(allowed_input_str);
+ if (*p == '\0') {
+ allowed_input_str = NULL;
+ } else {
+ allowed_input_str = strdup(p);
+ }
+ if (doit) {
+ initialize_allowed_input();
+ }
+ } else if (strstr(p, "client_input") == p) {
+ NOTAPP
+ COLON_CHECK("client_input:")
+ p += strlen("client_input:");
+ set_client_input(p);
+
} else if (strstr(p, "speeds") == p) {
COLON_CHECK("speeds:")
if (query) {
@@ -15328,6 +15691,7 @@ static void watch_loop(void) {
copy_screen();
}
+ check_new_clients();
check_xevents();
check_connect_inputs();
check_padded_fb();
@@ -15366,10 +15730,7 @@ static void watch_loop(void) {
}
if (watch_bell) {
- /*
- * check for any bell events.
- * n.b. assumes -nofb folks do not want bell...
- */
+ /* n.b. assumes -nofb folks do not want bell... */
check_bell_event();
}
@@ -15579,6 +15940,19 @@ static void print_help(int mode) {
" each time a new client connects. Lines can be commented\n"
" out with the \"#\" character in the usual way.\n"
"-localhost Same as -allow 127.0.0.1\n"
+"\n"
+"-input string Fine tuning of allowed user input. If \"string\" does\n"
+" not contain a comma \",\" the tuning applies only to\n"
+" normal clients. Otherwise the part before \",\" is\n"
+" for normal clients and the part after for view-only\n"
+" clients. \"K\" is for Keystroke input, \"M\" for\n"
+" Mouse-motion input, and \"B\" for Button-click input.\n"
+" Their presence in the string enables that type of input.\n"
+" E.g. \"-input M\" means normal users can only move\n"
+" the mouse and \"-input KMB,M\" lets normal users do\n"
+" anything and enables view-only users to move the mouse.\n"
+" This option is ignored when a global -viewonly is in\n"
+" effect (all input is discarded).\n"
"-viewpasswd string Supply a 2nd password for view-only logins. The -passwd\n"
" (full-access) password must also be supplied.\n"
"-passwdfile filename Specify libvncserver -passwd via the first line of\n"
@@ -15692,7 +16066,8 @@ static void print_help(int mode) {
" it switch immediately regardless if the display can\n"
" be reopened or not prefix the username with the +\n"
" character. E.g. \"-users +bob\" or \"-users +nobody\".\n"
-" The latter is probably the only use of this option\n"
+" The latter (i.e. switching immediately to user\n"
+" \"nobody\") is probably the only use of this option\n"
" that increases security. To switch to a user *before*\n"
" connections to the display are made or any files opened\n"
" use the \"=\" character: \"-users =username\".\n"
@@ -15700,7 +16075,7 @@ static void print_help(int mode) {
" The special user \"guess\" means to examine the utmpx\n"
" database looking for a user attached to the display\n"
" number and try him/her. To limit the list of guesses,\n"
-" use: \"-users guess=bob,fred\". Be especially careful\n"
+" use: \"-users guess=bob,betty\". Be especially careful\n"
" using this mode.\n"
" \n"
"-noshm Do not use the MIT-SHM extension for the polling.\n"
@@ -16258,6 +16633,11 @@ static void print_help(int mode) {
" use \"-host\" to delete a single host\n"
" localhost enable -localhost mode\n"
" nolocalhost disable -localhost mode\n"
+" input:str set -input to \"str\", empty to disable.\n"
+" client_input:str set the K, M, B -input on a per-client\n"
+" basis. select which client as for\n"
+" disconnect, e.g. client_input:host:MB\n"
+" or client_input:0x2:K\n"
/* ext. cmd. */
" accept:cmd set -accept \"cmd\" (empty to disable).\n"
" gone:cmd set -gone \"cmd\" (empty to disable).\n"
@@ -16429,13 +16809,13 @@ static void print_help(int mode) {
" xrandr_mode padgeom quiet q noquiet modtweak nomodtweak\n"
" xkb noxkb skip_keycodes add_keysyms noadd_keysyms\n"
" clear_mods noclear_mods clear_keys noclear_keys\n"
-" remap repeat norepeat fb nofb bell nobell sel nosel\n"
-" primary noprimary cursorshape nocursorshape cursorpos\n"
-" nocursorpos cursor show_cursor noshow_cursor\n"
-" nocursor xfixes noxfixes alphacut alphafrac\n"
-" alpharemove noalpharemove alphablend noalphablend\n"
-" xwarp xwarppointer noxwarp noxwarppointer buttonmap\n"
-" dragging nodragging pointer_mode pm input_skip speeds\n"
+" remap repeat norepeat fb nofb bell nobell sel\n"
+" nosel primary noprimary cursorshape nocursorshape\n"
+" cursorpos nocursorpos cursor show_cursor noshow_cursor\n"
+" nocursor xfixes noxfixes alphacut alphafrac alpharemove\n"
+" noalpharemove alphablend noalphablend xwarp xwarppointer\n"
+" noxwarp noxwarppointer buttonmap dragging nodragging\n"
+" pointer_mode pm input_skip input client_input speeds\n"
" debug_pointer dp nodebug_pointer nodp debug_keyboard dk\n"
" nodebug_keyboard nodk deferupdate defer wait rfbwait\n"
" nap nonap sb screen_blank fs gaps grow fuzz snapfb\n"
@@ -16483,10 +16863,13 @@ static void print_help(int mode) {
" Note that if they can modify VNC_CONNECT, they could\n"
" also run their own x11vnc and have complete control\n"
" of the desktop. If the \"-connect /path/to/file\"\n"
-" channel is being used, obviously anyone who can write\n"
-" to /path/to/file can remotely control x11vnc. So be\n"
-" sure to protect the X display and that file's write\n"
-" permissions.\n"
+" channel is being used, obviously anyone who can\n"
+" write to /path/to/file can remotely control x11vnc.\n"
+" So be sure to protect the X display and that file's\n"
+" write permissions.\n"
+"\n"
+" To disable the VNC_CONNECT property channel completely\n"
+" use -novncconnect.\n"
"\n"
"-unsafe If x11vnc is running as root (e.g. inetd or Xsetup for\n"
" a display manager) a few remote commands are disabled\n"
@@ -17044,6 +17427,9 @@ int main(int argc, char* argv[]) {
allow_list = strdup(argv[++i]);
} else if (!strcmp(arg, "-localhost")) {
allow_list = strdup("127.0.0.1");
+ } else if (!strcmp(arg, "-input")) {
+ CHECK_ARGC
+ allowed_input_str = strdup(argv[++i]);
} else if (!strcmp(arg, "-viewpasswd")) {
vpw_loc = i;
CHECK_ARGC
@@ -17987,6 +18373,8 @@ int main(int argc, char* argv[]) {
initialize_keyboard_and_pointer();
+ initialize_allowed_input();
+
if (! inetd) {
if (! screen->port || screen->listenSock < 0) {
rfbLog("Error: could not obtain listening port.\n");