x11vnc -input to fine tune allow user input. per-client settings -R

pull/1/head
runge 19 years ago
parent 5b18d40136
commit 86ccf267b1

@ -1,3 +1,7 @@
2005-02-10 Karl Runge <runge@karlrunge.com>
* x11vnc: -input option to fine tune allowed client input,
additions to remote control and gui for this.
2005-02-09 Karl Runge <runge@karlrunge.com>
* x11vnc: -users, fix -solid on gnome and kde.
* configure.ac: add pwd.h, wait.h, and utmpx.h checks.

@ -1,3 +1,8 @@
2005-02-10 Karl Runge <runge@karlrunge.com>
* Add -input to fine tune client input (keystroke, mouse motion,
and button presses). Allow per-client setting via remote cntl.
* fix bug in get_remote_port, add ip2host for client info.
2005-02-09 Karl Runge <runge@karlrunge.com>
* Add -users switch user mechanism and related utilities.
* fix -solid for gnome and kde.

@ -1,5 +1,5 @@
x11vnc README file Date: Wed Feb 9 00:21:28 EST 2005
x11vnc README file Date: Thu Feb 10 23:33:03 EST 2005
The following information is taken from these URLs:
@ -594,6 +594,8 @@ ls -l ./x11vnc/x11vnc
Please feel free to [45]contact me if you have any questions,
problems, or comments about x11vnc, etc.
[PayPal]
_________________________________________________________________
x11vnc FAQ:

@ -196,6 +196,8 @@ Permissions
forever
timeout:
--
input:
--
=SA alwaysshared
=SA nevershared
=SA dontdisconnect
@ -279,6 +281,11 @@ Check if x11vnc still responds to \"ping\" remote command.
set helptext(update-all) "
Query the x11vnc server for the current values of all variables.
Populate the values into the gui's database.
Normally the gui will refresh this info every time it interacts
with the x11vnc server, so one doesn't need to use this action
very often (unless something else is changing the state of the
x11vnc server, or new clients have connected, etc).
"
set helptext(clear-all) "
@ -321,8 +328,27 @@ Terminate the tkx11vnc gui. Any x11vnc servers will be left running.
set helptext(current) "
Shows a menu of currently connected VNC clients on the x11vnc server.
Allows you to find more information about them or disconnect them.
Allows you to find more information about them, change their input
permissions, or disconnect them.
You will be prompted to confirm any disconnections.
"
set helptext(client) "
After selecting a VNC client from the \"Clients -> current\" menu,
you will be presented with a dialog that shows the information
about the VNC client.
You can chose to disconnect the client by clicking on the
\"Disconnect\" checkbox and pressing \"OK\". There will be a
confirmation dialog to doublecheck.
Alternatively, you can fine tune the VNC client's input permissions
by selecting any of the Keystrokes, Mouse Motion, or Button Clicks
checkboxes and pressing \"OK\". This is like the \"-input\" option
but on a per-client basis.
To not change any aspects of the VNC client press \"Skip\".
"
set helptext(solid_color) "
@ -470,12 +496,18 @@ proc textheight {text} {
return $count
}
proc set_name {name} {
wm title . "$name"
wm iconname . "$name"
}
proc make_toplevel {w {title ""}} {
catch {destroy $w}
toplevel $w;
bind $w <Escape> "destroy $w"
if {$title != ""} {
wm title $w $title
wm title $w $title
wm iconname $w $title
}
}
@ -1054,6 +1086,195 @@ proc push_new_value {item name new {query 1}} {
}
}
proc set_kmb_str {} {
global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb
set str ""
if {$vl_bk} {
append str "K"
}
if {$vl_bm} {
append str "M"
}
if {$vl_bb} {
append str "B"
}
if {$vr_bk || $vr_bm || $vr_bb} {
append str ","
}
if {$vr_bk} {
append str "K"
}
if {$vr_bm} {
append str "M"
}
if {$vr_bb} {
append str "B"
}
entry_insert $str
}
proc insert_input_window {} {
global text_area cleanup_window
global ffont menu_var
global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb
append_text "\nUse these checkboxes to set the input permissions, "
append_text "or type in the \"KMB...\"\n-input string manually. "
append_text "Then press \"OK\" or \"Skip\".\n\n"
set w "$text_area.wk_f"
catch {destroy $w}
frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
set fl $w.fl
frame $fl
set fr $w.fr
frame $fr
label $fl.l -font $ffont -text "Normal clients: "
checkbutton $fl.bk -pady 1 -font $ffont -anchor w -variable vl_bk \
-pady 1 -command set_kmb_str -text "Keystrokes"
checkbutton $fl.bm -font $ffont -anchor w -variable vl_bm \
-pady 1 -command set_kmb_str -text "Mouse Motion"
checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \
-pady 1 -command set_kmb_str -text "Button Clicks"
label $fr.l -pady 1 -font $ffont -text "View-only clients:"
checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \
-pady 1 -command set_kmb_str -text "Keystrokes"
checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \
-pady 1 -command set_kmb_str -text "Mouse Motion"
checkbutton $fr.bb -font $ffont -anchor w -variable vr_bb \
-pady 1 -command set_kmb_str -text "Button Clicks"
if {[info exists menu_var(input)]} {
set input_str $menu_var(input)
} else {
set input_str ""
}
if {[regexp {(.*),(.*)} $input_str match normal viewonly]} {
;
} else {
set normal $input_str
set viewonly ""
}
set vl_bk 0
set vl_bm 0
set vl_bb 0
set vr_bk 0
set vr_bm 0
set vr_bb 0
if {[regexp -nocase {K} $normal]} {
set vl_bk 1
}
if {[regexp -nocase {M} $normal]} {
set vl_bm 1
}
if {[regexp -nocase {B} $normal]} {
set vl_bb 1
}
if {[regexp -nocase {K} $viewonly]} {
set vr_bk 1
}
if {[regexp -nocase {M} $viewonly]} {
set vr_bm 1
}
if {[regexp -nocase {B} $viewonly]} {
set vr_bb 1
}
pack $fl.l $fl.bk $fl.bm $fl.bb -side top -fill x
pack $fr.l $fr.bk $fr.bm $fr.bb -side top -fill x
pack $fl $fr -side left
update
update idletasks
$text_area window create end -window $w
$text_area see end
$text_area insert end "\n"
# $text_area insert end "\n\n\n\n\n\n\n\n\n"
set cleanup_window $w
}
proc set_ca_str {w} {
global ca_bk ca_bm ca_bb ca_bk ca_di
if {$ca_di} {
entry_insert "disconnect"
$w.bk configure -state disabled
$w.bm configure -state disabled
$w.bb configure -state disabled
return
}
$w.bk configure -state normal
$w.bm configure -state normal
$w.bb configure -state normal
set str ""
if {$ca_bk} {
append str "K"
}
if {$ca_bm} {
append str "M"
}
if {$ca_bb} {
append str "B"
}
entry_insert $str
}
proc insert_client_action_window {input} {
global text_area cleanup_window
global ffont menu_var
global ca_bk ca_bm ca_bb ca_bk ca_di
append_text "\nUse these checkboxes to set the input permissions "
append_text "for this client\n-or- whether to disconnect it instead. "
append_text "Then press \"OK\" or \"Skip\".\n\n"
set w "$text_area.ca_f"
catch {destroy $w}
frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
checkbutton $w.di -pady 1 -font $ffont -anchor w -variable ca_di \
-pady 1 -command "set_ca_str $w" -text "Disconnect "
checkbutton $w.bk -font $ffont -anchor w -variable ca_bk \
-pady 1 -command "set_ca_str $w" -text "Keystrokes"
checkbutton $w.bm -font $ffont -anchor w -variable ca_bm \
-pady 1 -command "set_ca_str $w" -text "Mouse Motion"
checkbutton $w.bb -font $ffont -anchor w -variable ca_bb \
-pady 1 -command "set_ca_str $w" -text "Button Clicks"
set ca_di 0
set ca_bk 0
set ca_bm 0
set ca_bb 0
if {[regexp -nocase {K} $input]} {
set ca_bk 1
}
if {[regexp -nocase {M} $input]} {
set ca_bm 1
}
if {[regexp -nocase {B} $input]} {
set ca_bb 1
}
pack $w.di $w.bk $w.bm $w.bb -side left
update
update idletasks
$text_area window create end -window $w
$text_area see end
$text_area insert end "\n"
set cleanup_window $w
}
proc cleanup_text_window {} {
global cleanup_window
if {[info exists cleanup_window]} {
catch {destroy $cleanup_window}
}
}
# For updating a string variable. Also used for simple OK/Skip dialogs
# with entry = 0.
proc entry_dialog {item {entry 1}} {
@ -1084,6 +1305,13 @@ proc entry_dialog {item {entry 1}} {
entry_disable box
}
set clean_text_window 0;
if {$item == "input"} {
insert_input_window
set clean_text_window 1
}
update
# wait for user reply:
@ -1101,6 +1329,11 @@ proc entry_dialog {item {entry 1}} {
entry_delete
entry_disable
menus_enable
if {$clean_text_window} {
cleanup_text_window;
}
update
if {! $entry} {
@ -1205,7 +1438,8 @@ proc see_if_ok {query item expected} {
} elseif {[regexp {:[0-9]\.[0-9]} $expected]} {
append_text "\t($msg)\n"
return 1
} elseif {$item == "connect" || $item == "disconnect"} {
} elseif {$item == "connect" || $item == "disconnect"
|| $item == "client" || $item == "client_input"} {
append_text "\t($msg)\n"
return 1
} else {
@ -1259,7 +1493,7 @@ proc clear_all {} {
continue
}
if {[info exists menu_var($item)]} {
if [is_action $item] {
if {[is_action $item]} {
set menu_var($item) ""
} elseif {[value_is_bool $item]} {
set menu_var($item) 0
@ -1494,7 +1728,7 @@ proc do_action {item} {
push_new_value $item $name $new 0
set_connected no
} elseif [opt_match Q $item] {
} elseif {[opt_match Q $item]} {
push_new_value $item $name $new 1
} else {
push_new_value $item $name $new 0
@ -1660,7 +1894,7 @@ proc split_query {query} {
proc set_x11_display {name} {
global x11_display
set x11_display "x11vnc X display: $name"
wm title . "tkx11vnc - $name"
set_name "tkx11vnc - $name"
}
proc set_vnc_display {name} {
global vnc_display
@ -1672,7 +1906,7 @@ proc set_vnc_url {name} {
}
proc no_x11_display {} {
set_x11_display "(*none*)"
wm title . "tkx11vnc"
set_name "tkx11vnc"
}
proc no_vnc_display {} {
set_vnc_display "(*none*)"
@ -1713,20 +1947,99 @@ proc fetch_displays {} {
}
}
proc client_dialog {client} {
set cid ""
set host ""
set ip ""
global menu_var text_area cleanup_window item_bool
append_text "\nClient info string: $client\n\n"
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6]} {
# id:ip:port:hostname:input:loginvo
set cid $m1
set ip $m2
set port $m3
set host $m4
regsub {\..*$} $host "" host
set input $m5
set logvo $m6
append_text "Host: $host, Port: $port, IP: $ip, Id: $cid\n"
append_text " - originally logged in as: "
if {$logvo == "1" } {
append_text "View-Only Client\n"
} else {
append_text "Normal Client\n"
}
append_text " - currently allowed input: "
set sk 0
set sm 0
set sb 0
if {[regexp -nocase {K} $input]} {
append_text "Keystroke"
set sk 1
}
if {[regexp -nocase {M} $input]} {
if {$sk} {
append_text ", "
}
append_text "Mouse-Motion"
set sm 1
}
if {[regexp -nocase {B} $input]} {
if {$sk || $sm} {
append_text ", "
}
append_text "Button-Click"
set sb 1
}
if {! $sk && ! $sm && ! $sb} {
append_text "None"
}
append_text "\n"
}
if {$cid == ""} {
append_text "Invalid client info string: $client\n"
return
}
regsub -all {_} $input "" input
set menu_var(client) "$input"
set item_bool(client) 0
insert_client_action_window $input
set rc [entry_dialog client 1]
cleanup_text_window
set val $menu_var(client)
#puts "rc: $rc val: $val"
if {! $rc} {
return;
} elseif {[regexp -nocase {(disconnect|close)} $val]} {
disconnect_dialog $client
} else {
regsub -all -nocase {[^KMB]} $val ""
set item_bool(client_input) 0
push_new_value "client_input" "client_input" "$cid:$val" 0
}
}
proc disconnect_dialog {client} {
set cid ""
set host ""
set msg "\n"
append msg "*** Client info string: $client\n"
if {[regexp {^(.*):(.*)/(.*)-(.*)$} $client m0 m1 m2 m3 m4]} {
if {$m4 == "ro"} {
set view "(viewonly)"
} else {
set view "(interactive)"
}
set host $m1
set cid $m3
append msg "*** Host: $m1, Port: $m2 Id: $m3 $view\n"
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} $client m0 m1 m2 m3 m4 m5 m6]} {
set cid $m1
set ip $m2
set port $m3
set host $m4
regsub {\..*$} $host "" host
set input $m5
set logvo $m6
append_text "Host: $host, Port: $port, IP: $ip, Id: $cid\n"
}
if {$cid == ""} {
append_text "Invalid client info string: $client\n"
@ -1734,7 +2047,7 @@ proc disconnect_dialog {client} {
}
append msg "*** To *DISCONNECT* this client press \"OK\", otherwise press \"Skip\"\n"
bell
if [warning_dialog $msg "current"] {
if {[warning_dialog $msg "current"]} {
push_new_value "disconnect" "disconnect" $cid 1
} else {
append_text "disconnect cancelled.\n"
@ -1756,7 +2069,7 @@ proc update_clients_and_repost {} {
continue
}
set name [$casc entrycget $i -label]
if {[regexp {^#} $name]} {
if {[regexp {^num-clients} $name]} {
continue
}
if {[regexp {^refresh-list} $name]} {
@ -1783,12 +2096,20 @@ proc update_clients_menu {list} {
$subm add separator
set count 0
foreach client [split $list ","] {
regsub {:[0-9][0-9]*/} $client {/} lab
$subm add command -label "$client" \
-command "disconnect_dialog $client"
if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \
$client m0 m1 m2 m3 m4 m5 m6]} {
# id:ip:port:hostname:input:loginvo
set host $m4
regsub {\..*$} $host "" host
set clabel "$host $m1"
} else {
regsub {:.*$} $client "" clabel
}
$subm add command -label "$clabel" \
-command "client_dialog $client"
incr count
}
$subm entryconfigure 0 -label "#clients: $count"
$subm entryconfigure 0 -label "num-clients: $count"
}
proc set_widgets {} {
@ -2076,7 +2397,7 @@ proc make_widgets {} {
pack $df -side top -fill x
# text area
text .text -height 11 -relief ridge -font $ffont
text .text -height 12 -relief ridge -font $ffont
set text_area .text
pack .text -side top -fill both -expand 1
@ -2622,7 +2943,7 @@ tweak_both screen_blank sb
set_template
wm title . "tkx11vnc"
set_name "tkx11vnc"
make_widgets;
menu_bindings;

@ -202,6 +202,8 @@
" forever\n"
" timeout:\n"
" --\n"
" input:\n"
" --\n"
" =SA alwaysshared\n"
" =SA nevershared\n"
" =SA dontdisconnect\n"
@ -285,6 +287,11 @@
" set helptext(update-all) \"\n"
"Query the x11vnc server for the current values of all variables.\n"
"Populate the values into the gui's database.\n"
"\n"
"Normally the gui will refresh this info every time it interacts\n"
"with the x11vnc server, so one doesn't need to use this action\n"
"very often (unless something else is changing the state of the\n"
"x11vnc server, or new clients have connected, etc).\n"
"\"\n"
"\n"
" set helptext(clear-all) \"\n"
@ -327,10 +334,29 @@
" set helptext(current) \"\n"
"Shows a menu of currently connected VNC clients on the x11vnc server.\n"
"\n"
"Allows you to find more information about them or disconnect them.\n"
"Allows you to find more information about them, change their input\n"
"permissions, or disconnect them.\n"
"\n"
"You will be prompted to confirm any disconnections.\n"
"\"\n"
"\n"
" set helptext(client) \"\n"
"After selecting a VNC client from the \\\"Clients -> current\\\" menu,\n"
"you will be presented with a dialog that shows the information\n"
"about the VNC client.\n"
"\n"
"You can chose to disconnect the client by clicking on the \n"
"\\\"Disconnect\\\" checkbox and pressing \\\"OK\\\". There will be a\n"
"confirmation dialog to doublecheck.\n"
"\n"
"Alternatively, you can fine tune the VNC client's input permissions\n"
"by selecting any of the Keystrokes, Mouse Motion, or Button Clicks\n"
"checkboxes and pressing \\\"OK\\\". This is like the \\\"-input\\\" option\n"
"but on a per-client basis.\n"
"\n"
"To not change any aspects of the VNC client press \\\"Skip\\\".\n"
"\"\n"
"\n"
" set helptext(solid_color) \"\n"
"Set the -solid color value.\n"
"\"\n"
@ -476,12 +502,18 @@
" return $count\n"
"}\n"
"\n"
"proc set_name {name} {\n"
" wm title . \"$name\"\n"
" wm iconname . \"$name\"\n"
"}\n"
"\n"
"proc make_toplevel {w {title \"\"}} {\n"
" catch {destroy $w}\n"
" toplevel $w;\n"
" bind $w <Escape> \"destroy $w\"\n"
" if {$title != \"\"} {\n"
" wm title $w $title\n"
" wm title $w $title\n"
" wm iconname $w $title\n"
" }\n"
"}\n"
"\n"
@ -1060,6 +1092,195 @@
" }\n"
"}\n"
"\n"
"proc set_kmb_str {} {\n"
" global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb \n"
"\n"
" set str \"\"\n"
" if {$vl_bk} {\n"
" append str \"K\"\n"
" }\n"
" if {$vl_bm} {\n"
" append str \"M\"\n"
" }\n"
" if {$vl_bb} {\n"
" append str \"B\"\n"
" }\n"
" if {$vr_bk || $vr_bm || $vr_bb} {\n"
" append str \",\"\n"
" }\n"
" if {$vr_bk} {\n"
" append str \"K\"\n"
" }\n"
" if {$vr_bm} {\n"
" append str \"M\"\n"
" }\n"
" if {$vr_bb} {\n"
" append str \"B\"\n"
" }\n"
" entry_insert $str\n"
"}\n"
"\n"
"proc insert_input_window {} {\n"
" global text_area cleanup_window\n"
" global ffont menu_var\n"
" global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb \n"
"\n"
" append_text \"\\nUse these checkboxes to set the input permissions, \"\n"
" append_text \"or type in the \\\"KMB...\\\"\\n-input string manually. \"\n"
" append_text \"Then press \\\"OK\\\" or \\\"Skip\\\".\\n\\n\"\n"
" set w \"$text_area.wk_f\"\n"
" catch {destroy $w}\n"
" frame $w -bd 1 -relief ridge -cursor {top_left_arrow}\n"
" set fl $w.fl\n"
" frame $fl\n"
" set fr $w.fr\n"
" frame $fr\n"
" label $fl.l -font $ffont -text \"Normal clients: \"\n"
" checkbutton $fl.bk -pady 1 -font $ffont -anchor w -variable vl_bk \\\n"
" -pady 1 -command set_kmb_str -text \"Keystrokes\" \n"
" checkbutton $fl.bm -font $ffont -anchor w -variable vl_bm \\\n"
" -pady 1 -command set_kmb_str -text \"Mouse Motion\" \n"
" checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \\\n"
" -pady 1 -command set_kmb_str -text \"Button Clicks\"\n"
" label $fr.l -pady 1 -font $ffont -text \"View-only clients:\"\n"
" checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \\\n"
" -pady 1 -command set_kmb_str -text \"Keystrokes\" \n"
" checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \\\n"
" -pady 1 -command set_kmb_str -text \"Mouse Motion\" \n"
" checkbutton $fr.bb -font $ffont -anchor w -variable vr_bb \\\n"
" -pady 1 -command set_kmb_str -text \"Button Clicks\"\n"
"\n"
" if {[info exists menu_var(input)]} {\n"
" set input_str $menu_var(input)\n"
" } else {\n"
" set input_str \"\"\n"
" }\n"
"\n"
" if {[regexp {(.*),(.*)} $input_str match normal viewonly]} {\n"
" ;\n"
" } else {\n"
" set normal $input_str\n"
" set viewonly \"\"\n"
" }\n"
" set vl_bk 0\n"
" set vl_bm 0\n"
" set vl_bb 0\n"
" set vr_bk 0\n"
" set vr_bm 0\n"
" set vr_bb 0\n"
"\n"
" if {[regexp -nocase {K} $normal]} {\n"
" set vl_bk 1\n"
" }\n"
" if {[regexp -nocase {M} $normal]} {\n"
" set vl_bm 1\n"
" }\n"
" if {[regexp -nocase {B} $normal]} {\n"
" set vl_bb 1\n"
" }\n"
" if {[regexp -nocase {K} $viewonly]} {\n"
" set vr_bk 1\n"
" }\n"
" if {[regexp -nocase {M} $viewonly]} {\n"
" set vr_bm 1\n"
" }\n"
" if {[regexp -nocase {B} $viewonly]} {\n"
" set vr_bb 1\n"
" }\n"
"\n"
" pack $fl.l $fl.bk $fl.bm $fl.bb -side top -fill x\n"
" pack $fr.l $fr.bk $fr.bm $fr.bb -side top -fill x\n"
" pack $fl $fr -side left\n"
" update\n"
" update idletasks\n"
" $text_area window create end -window $w\n"
" $text_area see end\n"
" $text_area insert end \"\\n\"\n"
"# $text_area insert end \"\\n\\n\\n\\n\\n\\n\\n\\n\\n\"\n"
"\n"
" set cleanup_window $w\n"
"}\n"
"\n"
"proc set_ca_str {w} {\n"
" global ca_bk ca_bm ca_bb ca_bk ca_di\n"
"\n"
" if {$ca_di} {\n"
" entry_insert \"disconnect\"\n"
" $w.bk configure -state disabled\n"
" $w.bm configure -state disabled\n"
" $w.bb configure -state disabled\n"
" return\n"
" }\n"
"\n"
" $w.bk configure -state normal\n"
" $w.bm configure -state normal\n"
" $w.bb configure -state normal\n"
"\n"
" set str \"\"\n"
" if {$ca_bk} {\n"
" append str \"K\"\n"
" }\n"
" if {$ca_bm} {\n"
" append str \"M\"\n"
" }\n"
" if {$ca_bb} {\n"
" append str \"B\"\n"
" }\n"
" entry_insert $str\n"
"}\n"
"\n"
"proc insert_client_action_window {input} {\n"
" global text_area cleanup_window\n"
" global ffont menu_var\n"
" global ca_bk ca_bm ca_bb ca_bk ca_di\n"
"\n"
" append_text \"\\nUse these checkboxes to set the input permissions \"\n"
" append_text \"for this client\\n-or- whether to disconnect it instead. \"\n"
" append_text \"Then press \\\"OK\\\" or \\\"Skip\\\".\\n\\n\"\n"
" set w \"$text_area.ca_f\"\n"
" catch {destroy $w}\n"
" frame $w -bd 1 -relief ridge -cursor {top_left_arrow}\n"
" checkbutton $w.di -pady 1 -font $ffont -anchor w -variable ca_di \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Disconnect \" \n"
" checkbutton $w.bk -font $ffont -anchor w -variable ca_bk \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Keystrokes\" \n"
" checkbutton $w.bm -font $ffont -anchor w -variable ca_bm \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Mouse Motion\" \n"
" checkbutton $w.bb -font $ffont -anchor w -variable ca_bb \\\n"
" -pady 1 -command \"set_ca_str $w\" -text \"Button Clicks\"\n"
"\n"
" set ca_di 0\n"
" set ca_bk 0\n"
" set ca_bm 0\n"
" set ca_bb 0\n"
"\n"
" if {[regexp -nocase {K} $input]} {\n"
" set ca_bk 1\n"
" }\n"
" if {[regexp -nocase {M} $input]} {\n"
" set ca_bm 1\n"
" }\n"
" if {[regexp -nocase {B} $input]} {\n"
" set ca_bb 1\n"
" }\n"
"\n"
" pack $w.di $w.bk $w.bm $w.bb -side left\n"
" update\n"
" update idletasks\n"
" $text_area window create end -window $w\n"
" $text_area see end\n"
" $text_area insert end \"\\n\"\n"
"\n"
" set cleanup_window $w\n"
"}\n"
"\n"
"proc cleanup_text_window {} {\n"
" global cleanup_window\n"
" if {[info exists cleanup_window]} {\n"
" catch {destroy $cleanup_window}\n"
" }\n"
"}\n"
"\n"
"# For updating a string variable. Also used for simple OK/Skip dialogs\n"
"# with entry = 0.\n"
"proc entry_dialog {item {entry 1}} {\n"
@ -1090,6 +1311,13 @@
" entry_disable box\n"
" }\n"
"\n"
" set clean_text_window 0;\n"
"\n"
" if {$item == \"input\"} {\n"
" insert_input_window\n"
" set clean_text_window 1\n"
" }\n"
"\n"
" update\n"
"\n"
" # wait for user reply:\n"
@ -1107,6 +1335,11 @@
" entry_delete\n"
" entry_disable\n"
" menus_enable\n"
"\n"
" if {$clean_text_window} {\n"
" cleanup_text_window;\n"
" }\n"
"\n"
" update\n"
"\n"
" if {! $entry} {\n"
@ -1211,7 +1444,8 @@
" } elseif {[regexp {:[0-9]\\.[0-9]} $expected]} {\n"
" append_text \"\\t($msg)\\n\"\n"
" return 1\n"
" } elseif {$item == \"connect\" || $item == \"disconnect\"} {\n"
" } elseif {$item == \"connect\" || $item == \"disconnect\"\n"
" || $item == \"client\" || $item == \"client_input\"} {\n"
" append_text \"\\t($msg)\\n\"\n"
" return 1\n"
" } else {\n"
@ -1265,7 +1499,7 @@
" continue\n"
" }\n"
" if {[info exists menu_var($item)]} {\n"
" if [is_action $item] {\n"
" if {[is_action $item]} {\n"
" set menu_var($item) \"\"\n"
" } elseif {[value_is_bool $item]} {\n"
" set menu_var($item) 0\n"
@ -1500,7 +1734,7 @@
" push_new_value $item $name $new 0\n"
" set_connected no\n"
" \n"
" } elseif [opt_match Q $item] {\n"
" } elseif {[opt_match Q $item]} {\n"
" push_new_value $item $name $new 1\n"
" } else {\n"
" push_new_value $item $name $new 0\n"
@ -1666,7 +1900,7 @@
"proc set_x11_display {name} {\n"
" global x11_display\n"
" set x11_display \"x11vnc X display: $name\"\n"
" wm title . \"tkx11vnc - $name\"\n"
" set_name \"tkx11vnc - $name\"\n"
"}\n"
"proc set_vnc_display {name} {\n"
" global vnc_display\n"
@ -1678,7 +1912,7 @@
"}\n"
"proc no_x11_display {} {\n"
" set_x11_display \"(*none*)\"\n"
" wm title . \"tkx11vnc\"\n"
" set_name \"tkx11vnc\"\n"
"}\n"
"proc no_vnc_display {} {\n"
" set_vnc_display \"(*none*)\"\n"
@ -1719,20 +1953,99 @@
" }\n"
"}\n"
"\n"
"proc client_dialog {client} {\n"
" set cid \"\"\n"
" set host \"\"\n"
" set ip \"\"\n"
" global menu_var text_area cleanup_window item_bool\n"
"\n"
" append_text \"\\nClient info string: $client\\n\\n\"\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6]} {\n"
" # id:ip:port:hostname:input:loginvo\n"
" set cid $m1\n"
" set ip $m2\n"
" set port $m3\n"
" set host $m4\n"
" regsub {\\..*$} $host \"\" host\n"
" set input $m5\n"
" set logvo $m6\n"
" append_text \"Host: $host, Port: $port, IP: $ip, Id: $cid\\n\"\n"
" append_text \" - originally logged in as: \"\n"
" if {$logvo == \"1\" } {\n"
" append_text \"View-Only Client\\n\"\n"
" } else {\n"
" append_text \"Normal Client\\n\"\n"
" }\n"
" append_text \" - currently allowed input: \"\n"
" set sk 0\n"
" set sm 0\n"
" set sb 0\n"
" if {[regexp -nocase {K} $input]} {\n"
" append_text \"Keystroke\"\n"
" set sk 1\n"
" }\n"
" if {[regexp -nocase {M} $input]} {\n"
" if {$sk} {\n"
" append_text \", \"\n"
" }\n"
" append_text \"Mouse-Motion\"\n"
" set sm 1\n"
" }\n"
" if {[regexp -nocase {B} $input]} {\n"
" if {$sk || $sm} {\n"
" append_text \", \"\n"
" }\n"
" append_text \"Button-Click\"\n"
" set sb 1\n"
" }\n"
" if {! $sk && ! $sm && ! $sb} {\n"
" append_text \"None\"\n"
" }\n"
" append_text \"\\n\"\n"
" }\n"
" if {$cid == \"\"} {\n"
" append_text \"Invalid client info string: $client\\n\"\n"
" return\n"
" }\n"
"\n"
" regsub -all {_} $input \"\" input\n"
" set menu_var(client) \"$input\"\n"
" set item_bool(client) 0\n"
"\n"
" insert_client_action_window $input\n"
" set rc [entry_dialog client 1]\n"
"\n"
" cleanup_text_window\n"
"\n"
" set val $menu_var(client)\n"
" #puts \"rc: $rc val: $val\"\n"
"\n"
" if {! $rc} {\n"
" return;\n"
" } elseif {[regexp -nocase {(disconnect|close)} $val]} {\n"
" disconnect_dialog $client\n"
" } else {\n"
" regsub -all -nocase {[^KMB]} $val \"\" \n"
" set item_bool(client_input) 0\n"
" push_new_value \"client_input\" \"client_input\" \"$cid:$val\" 0\n"
" }\n"
"}\n"
"\n"
"proc disconnect_dialog {client} {\n"
" set cid \"\"\n"
" set host \"\"\n"
" set msg \"\\n\"\n"
" append msg \"*** Client info string: $client\\n\"\n"
" if {[regexp {^(.*):(.*)/(.*)-(.*)$} $client m0 m1 m2 m3 m4]} {\n"
" if {$m4 == \"ro\"} {\n"
" set view \"(viewonly)\"\n"
" } else {\n"
" set view \"(interactive)\"\n"
" }\n"
" set host $m1\n"
" set cid $m3\n"
" append msg \"*** Host: $m1, Port: $m2 Id: $m3 $view\\n\"\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} $client m0 m1 m2 m3 m4 m5 m6]} {\n"
" set cid $m1\n"
" set ip $m2\n"
" set port $m3\n"
" set host $m4\n"
" regsub {\\..*$} $host \"\" host\n"
" set input $m5\n"
" set logvo $m6\n"
" append_text \"Host: $host, Port: $port, IP: $ip, Id: $cid\\n\"\n"
" }\n"
" if {$cid == \"\"} {\n"
" append_text \"Invalid client info string: $client\\n\"\n"
@ -1740,7 +2053,7 @@
" }\n"
" append msg \"*** To *DISCONNECT* this client press \\\"OK\\\", otherwise press \\\"Skip\\\"\\n\"\n"
" bell\n"
" if [warning_dialog $msg \"current\"] {\n"
" if {[warning_dialog $msg \"current\"]} {\n"
" push_new_value \"disconnect\" \"disconnect\" $cid 1\n"
" } else {\n"
" append_text \"disconnect cancelled.\\n\"\n"
@ -1762,7 +2075,7 @@
" continue\n"
" }\n"
" set name [$casc entrycget $i -label]\n"
" if {[regexp {^#} $name]} {\n"
" if {[regexp {^num-clients} $name]} {\n"
" continue\n"
" }\n"
" if {[regexp {^refresh-list} $name]} {\n"
@ -1789,12 +2102,20 @@
" $subm add separator\n"
" set count 0\n"
" foreach client [split $list \",\"] {\n"
" regsub {:[0-9][0-9]*/} $client {/} lab\n"
" $subm add command -label \"$client\" \\\n"
" -command \"disconnect_dialog $client\"\n"
" if {[regexp {^(.*):(.*):(.*):(.*):(.*):(.*)$} \\\n"
" $client m0 m1 m2 m3 m4 m5 m6]} {\n"
" # id:ip:port:hostname:input:loginvo\n"
" set host $m4\n"
" regsub {\\..*$} $host \"\" host\n"
" set clabel \"$host $m1\"\n"
" } else {\n"
" regsub {:.*$} $client \"\" clabel\n"
" }\n"
" $subm add command -label \"$clabel\" \\\n"
" -command \"client_dialog $client\"\n"
" incr count\n"
" }\n"
" $subm entryconfigure 0 -label \"#clients: $count\"\n"
" $subm entryconfigure 0 -label \"num-clients: $count\"\n"
"}\n"
"\n"
"proc set_widgets {} {\n"
@ -2082,7 +2403,7 @@
" pack $df -side top -fill x\n"
"\n"
" # text area\n"
" text .text -height 11 -relief ridge -font $ffont\n"
" text .text -height 12 -relief ridge -font $ffont\n"
" set text_area .text\n"
" pack .text -side top -fill both -expand 1\n"
"\n"
@ -2628,7 +2949,7 @@
"\n"
"set_template\n"
"\n"
"wm title . \"tkx11vnc\"\n"
"set_name \"tkx11vnc\"\n"
"make_widgets;\n"
"\n"
"menu_bindings;\n"

@ -2,7 +2,7 @@
.TH X11VNC "1" "February 2005" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.7.1pre, lastmod: 2005-02-08
version: 0.7.1pre, lastmod: 2005-02-10
.SH SYNOPSIS
.B x11vnc
[OPTION]...
@ -250,6 +250,21 @@ out with the "#" character in the usual way.
.IP
Same as \fB-allow\fR 127.0.0.1
.PP
\fB-input\fR \fIstring\fR
.IP
Fine tuning of allowed user input. If \fIstring\fR does
not contain a comma "," the tuning applies only to
normal clients. Otherwise the part before "," is
for normal clients and the part after for view-only
clients. "K" is for Keystroke input, "M" for
Mouse-motion input, and "B" for Button-click input.
Their presence in the string enables that type of input.
E.g. "\fB-input\fR \fIM\fR" means normal users can only move
the mouse and "\fB-input\fR \fIKMB,M\fR" lets normal users do
anything and enables view-only users to move the mouse.
This option is ignored when a global \fB-viewonly\fR is in
effect (all input is discarded).
.PP
\fB-viewpasswd\fR \fIstring\fR
.IP
Supply a 2nd password for view-only logins. The \fB-passwd\fR
@ -394,7 +409,8 @@ the switch succeeds (i.e. a user logs in). To make
it switch immediately regardless if the display can
be reopened or not prefix the username with the +
character. E.g. "\fB-users\fR \fI+bob\fR" or "\fB-users\fR \fI+nobody\fR".
The latter is probably the only use of this option
The latter (i.e. switching immediately to user
"nobody") is probably the only use of this option
that increases security. To switch to a user *before*
connections to the display are made or any files opened
use the "=" character: "\fB-users\fR \fI=username\fR".
@ -402,7 +418,7 @@ use the "=" character: "\fB-users\fR \fI=username\fR".
The special user "guess" means to examine the utmpx
database looking for a user attached to the display
number and try him/her. To limit the list of guesses,
use: "\fB-users\fR \fIguess=bob,fred\fR". Be especially careful
use: "\fB-users\fR \fIguess=bob,betty\fR". Be especially careful
using this mode.
.PP
\fB-noshm\fR
@ -1143,6 +1159,13 @@ localhost enable \fB-localhost\fR mode
.IP
nolocalhost disable \fB-localhost\fR mode
.IP
input:str set \fB-input\fR to "str", empty to disable.
.IP
client_input:str set the K, M, B \fB-input\fR on a per-client
basis. select which client as for
disconnect, e.g. client_input:host:MB
or client_input:0x2:K
.IP
accept:cmd set \fB-accept\fR "cmd" (empty to disable).
.IP
gone:cmd set \fB-gone\fR "cmd" (empty to disable).
@ -1424,13 +1447,13 @@ nosolid blackout xinerama noxinerama xrandr noxrandr
xrandr_mode padgeom quiet q noquiet modtweak nomodtweak
xkb noxkb skip_keycodes add_keysyms noadd_keysyms
clear_mods noclear_mods clear_keys noclear_keys
remap repeat norepeat fb nofb bell nobell sel nosel
primary noprimary cursorshape nocursorshape cursorpos
nocursorpos cursor show_cursor noshow_cursor
nocursor xfixes noxfixes alphacut alphafrac
alpharemove noalpharemove alphablend noalphablend
xwarp xwarppointer noxwarp noxwarppointer buttonmap
dragging nodragging pointer_mode pm input_skip speeds
remap repeat norepeat fb nofb bell nobell sel
nosel primary noprimary cursorshape nocursorshape
cursorpos nocursorpos cursor show_cursor noshow_cursor
nocursor xfixes noxfixes alphacut alphafrac alpharemove
noalpharemove alphablend noalphablend xwarp xwarppointer
noxwarp noxwarppointer buttonmap dragging nodragging
pointer_mode pm input_skip input client_input speeds
debug_pointer dp nodebug_pointer nodp debug_keyboard dk
nodebug_keyboard nodk deferupdate defer wait rfbwait
nap nonap sb screen_blank fs gaps grow fuzz snapfb
@ -1482,10 +1505,13 @@ x11vnc. Normally access to the X display is protected.
Note that if they can modify VNC_CONNECT, they could
also run their own x11vnc and have complete control
of the desktop. If the "\fB-connect\fR \fI/path/to/file\fR"
channel is being used, obviously anyone who can write
to /path/to/file can remotely control x11vnc. So be
sure to protect the X display and that file's write
permissions.
channel is being used, obviously anyone who can
write to /path/to/file can remotely control x11vnc.
So be sure to protect the X display and that file's
write permissions.
.IP
To disable the VNC_CONNECT property channel completely
use \fB-novncconnect.\fR
.PP
\fB-unsafe\fR
.IP

@ -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;