From 61383c508e9a12c879bd94c77885e0ec0d7c47f8 Mon Sep 17 00:00:00 2001 From: runge Date: Thu, 18 Jun 2009 22:32:16 -0400 Subject: [PATCH] classes/ssl: java viewer now handles auth-basic proxy logins. misc/enhanced_tightvnc_viewer: update ssvnc. --- classes/ssl/SignedUltraViewerSSL.jar | Bin 103589 -> 107370 bytes classes/ssl/SignedVncViewer.jar | Bin 79617 -> 83396 bytes classes/ssl/UltraViewerSSL.jar | Bin 100714 -> 104365 bytes classes/ssl/VncViewer.jar | Bin 76830 -> 80481 bytes classes/ssl/ss_vncviewer | 45 +- ...ghtvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 343 +- .../ssl/ultravnc-102-JavaViewer-ssl-etc.patch | 343 +- x11vnc/ChangeLog | 4 + x11vnc/README | 2847 +++++------ x11vnc/misc/enhanced_tightvnc_viewer/README | 68 +- .../Windows/README.txt | 2 +- .../enhanced_tightvnc_viewer/bin/ssvnc_cmd | 10 + .../bin/util/ss_vncviewer | 45 +- .../bin/util/ssvnc.tcl | 181 +- .../misc/enhanced_tightvnc_viewer/build.unix | 18 +- .../man/man1/ssvncviewer.1 | 67 +- .../src/patches/tight-vncviewer-full.patch | 4466 ++++++++++++++--- 17 files changed, 6163 insertions(+), 2276 deletions(-) diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar index d8297b3b87197fc060562ea06420eae4ec7407d5..2ca5b78bcc1976e33e24f6e69dbbc7a49fc0785e 100644 GIT binary patch delta 27343 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 E#6!UjkN$yYb!67G{#Zni^9!-SBsXn5%~t0z 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 B<^li! delta 23217 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 delta 20884 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 QaU6fd+%NGHsiUC(0Jgzp2mk;8 diff --git a/classes/ssl/ss_vncviewer b/classes/ssl/ss_vncviewer index 2231108..ec004c7 100755 --- a/classes/ssl/ss_vncviewer +++ b/classes/ssl/ss_vncviewer @@ -46,8 +46,8 @@ # -showcert Only fetch the certificate using the 'openssl s_client' # command (openssl(1) must in installed). # -# See http://www.karlrunge.com/x11vnc/#faq-ssl-ca for details on SSL -# certificates with VNC. +# See http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca for details on +# SSL certificates with VNC. # # A few other args (not related to SSL and certs): # @@ -115,6 +115,15 @@ # VNCIPCMD=${VNCVIEWERCMD:-vncip} VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer} +if [ "X$SSVNC_TURBOVNC" != "X" ]; then + if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then + : + else + if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then + VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc" + fi + fi +fi # # Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc. # @@ -268,6 +277,12 @@ do ;; "-onelisten") SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE ;; + "-sendclipboard") VNCVIEWER_SEND_CLIPBOARD=1; export VNCVIEWER_SEND_CLIPBOARD + ;; + "-sendalways") VNCVIEWER_SEND_ALWAYS=1; export VNCVIEWER_SEND_ALWAYS + ;; + "-recvtext") shift; VNCVIEWER_RECV_TEXT="$1"; export VNCVIEWER_RECV_TEXT + ;; "-escape") shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE ;; "-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS @@ -751,6 +766,19 @@ if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE}) { $handshake_file = $ENV{SSVNC_PREDIGESTED_HANDSHAKE}; } +my $have_gettimeofday = 0; +eval "use Time::HiRes"; +if ($@ eq "") { + $have_gettimeofday = 1; +} +sub gettime { + my $t = "0.0"; + if ($have_gettimeofday) { + $t = Time::HiRes::gettimeofday(); + } + return $t; +} + sub append_handshake { my $str = shift; if ($handshake_file) { @@ -1324,12 +1352,19 @@ sub vencrypt_dialog { } elsif ($minor == 7) { $viewer_rfb = "RFB 003.007\n"; } - syswrite($sock, $viewer_rfb, 12); - append_handshake("viewer=$viewer_rfb"); - my $nsec; + my $t1 = gettime(); + my $t0 = gettime(); + syswrite($sock, $viewer_rfb, 12); sysread($sock, $nsec, 1); + + $t1 = gettime(); + $t1 = sprintf("%.6f", $t1 - $t0); + + append_handshake("viewer=$viewer_rfb"); + append_handshake("latency=$t1\n"); + vdie if $nsec eq ""; $nsec = unpack("C", $nsec); diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch index 88185b7..1844eec 100644 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch +++ b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch @@ -73,8 +73,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java --- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_javasrc/SSLSocketToMe.java 2008-04-15 12:54:51.000000000 -0400 -@@ -0,0 +1,1456 @@ ++++ vnc_javasrc/SSLSocketToMe.java 2009-06-18 09:47:22.000000000 -0400 +@@ -0,0 +1,1717 @@ +/* + * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. + * @@ -130,6 +130,7 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + public DataInputStream is = null; + public OutputStream os = null; + ++ String proxy_auth_string = null; + String proxy_dialog_host = null; + int proxy_dialog_port = 0; + @@ -648,9 +649,9 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + user_wants_to_see_cert = false; + } else { + bcd = new BrowserCertsDialog(serv, host + ":" + port); -+ dbg("bcd START"); ++ dbg("browser certs dialog START"); + bcd.queryUser(); -+ dbg("bcd DONE"); ++ dbg("browser certs dialog DONE"); + if (bcd.showCertDialog) { + String msg = "user wants to see cert"; + dbg(msg); @@ -658,14 +659,17 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new SSLHandshakeException(msg); + } else { + user_wants_to_see_cert = false; -+ dbg("bcd: user said yes, accept it"); ++ dbg("browser certs dialog: user said yes, accept it"); + } + } + + } catch (SSLHandshakeException eh) { + dbg("Could not automatically verify Server."); + dbg("msg: " + eh.getMessage()); ++ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; + ++ OutputStream os = socket.getOutputStream(); ++ os.write(getoutstr.getBytes()); + socket.close(); + socket = null; + @@ -701,6 +705,8 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + * close socket now, we will reopen after + * dialog if user agrees to use the cert. + */ ++ os = socket.getOutputStream(); ++ os.write(getoutstr.getBytes()); + socket.close(); + socket = null; + @@ -722,6 +728,15 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + throw new IOException(ehand2.getMessage()); + } + ++ if (socket != null) { ++ try { ++ socket.close(); ++ } catch (Exception e) { ++ ; ++ } ++ socket = null; ++ } ++ + /* + * Now connect a 3rd time, using the cert + * retrieved during connection 2 (that the user @@ -806,6 +821,95 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + return n; + } + ++ private void proxy_helper(String proxyHost, int proxyPort) { ++ ++ boolean proxy_auth = false; ++ String proxy_auth_basic_realm = ""; ++ String hp = host + ":" + port; ++ dbg("proxy_helper: " + proxyHost + ":" + proxyPort + " hp: " + hp); ++ ++ for (int k=0; k < 2; k++) { ++ dbg("proxy_in_use psocket:"); ++ ++ if (proxySock != null) { ++ try { ++ proxySock.close(); ++ } catch (Exception e) { ++ ; ++ } ++ } ++ ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("1-a sadly, returning a null socket"); ++ return; ++ } ++ ++ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" ++ + "Host: " + hp + "\r\n"; ++ ++ dbg("requesting: " + req1); ++ ++ if (proxy_auth) { ++ if (proxy_auth_string == null) { ++ ProxyPasswdDialog pp = new ProxyPasswdDialog(proxyHost, proxyPort, proxy_auth_basic_realm); ++ pp.queryUser(); ++ proxy_auth_string = pp.getAuth(); ++ } ++ //dbg("auth1: " + proxy_auth_string); ++ String auth2 = Base64Coder.encodeString(proxy_auth_string); ++ //dbg("auth2: " + auth2); ++ req1 += "Proxy-Authorization: Basic " + auth2 + "\r\n"; ++ //dbg("req1: " + req1); ++ dbg("added Proxy-Authorization: Basic ... to request"); ++ } ++ req1 += "\r\n"; ++ ++ try { ++ proxy_os.write(req1.getBytes()); ++ String reply = readline(proxy_is); ++ ++ dbg("proxy replied: " + reply.trim()); ++ ++ if (reply.indexOf("HTTP/1.") == 0 && reply.indexOf(" 407 ") > 0) { ++ proxy_auth = true; ++ proxySock.close(); ++ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { ++ proxySock.close(); ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("2-a sadly, returning a null socket"); ++ return; ++ } ++ } ++ } catch(Exception e) { ++ dbg("sock prob: " + e.getMessage()); ++ } ++ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line: " + line.trim()); ++ if (proxy_auth) { ++ String uc = line.toLowerCase(); ++ if (uc.indexOf("proxy-authenticate:") == 0) { ++ if (uc.indexOf(" basic ") >= 0) { ++ int idx = uc.indexOf(" realm"); ++ if (idx >= 0) { ++ proxy_auth_basic_realm = uc.substring(idx+1); ++ } ++ } ++ } ++ } ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ if (!proxy_auth || proxy_auth_basic_realm.equals("")) { ++ break; ++ } ++ } ++ } ++ + public SSLSocket proxy_socket(SSLSocketFactory factory) { + Properties props = null; + String proxyHost = null; @@ -912,44 +1016,10 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); + } + -+ dbg("proxy_in_use psocket:"); -+ proxySock = psocket(proxyHost, proxyPort); ++ proxy_helper(proxyHost, proxyPort); + if (proxySock == null) { -+ dbg("1-a sadly, returning a null socket"); + return null; + } -+ String hp = host + ":" + port; -+ -+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n\r\n"; -+ -+ dbg("requesting1: " + req1); -+ -+ try { -+ proxy_os.write(req1.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied1: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-a sadly, returning a null socket"); -+ return null; -+ } -+ } -+ } catch(Exception e) { -+ dbg("sock prob1: " + e.getMessage()); -+ } -+ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line1: " + line.trim()); -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } + } else if (viewer.CONNECT != null) { + dbg("viewer.CONNECT psocket:"); + proxySock = psocket(host, port); @@ -991,7 +1061,6 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + break; + } + } -+ + } + + Socket sslsock = null; @@ -1351,6 +1420,77 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } +} + ++class ProxyPasswdDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ String guessedUser = null; ++ String guessedPasswd = null; ++ String realm = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry1; ++ TextField entry2; ++ String reply1 = ""; ++ String reply2 = ""; ++ ++ ProxyPasswdDialog (String h, int p, String realm) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ this.realm = realm; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Proxy Requires Username and Password"); ++ ++ dialog = new Dialog(frame, true); ++ ++ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); ++ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); ++ entry1 = new TextField(30); ++ entry2 = new TextField(30); ++ entry2.setEchoChar('*'); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry1); ++ dialog.add("South", entry2); ++ dialog.add("East", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getAuth() { ++ return reply1 + ":" + reply2; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply1 = entry1.getText(); ++ reply2 = entry2.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ +class ClientCertDialog implements ActionListener { + + Button ok; @@ -1531,6 +1671,127 @@ diff -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSL + } + } +} ++ ++class Base64Coder { ++ ++ // Mapping table from 6-bit nibbles to Base64 characters. ++ private static char[] map1 = new char[64]; ++ static { ++ int i=0; ++ for (char c='A'; c<='Z'; c++) map1[i++] = c; ++ for (char c='a'; c<='z'; c++) map1[i++] = c; ++ for (char c='0'; c<='9'; c++) map1[i++] = c; ++ map1[i++] = '+'; map1[i++] = '/'; } ++ ++ // Mapping table from Base64 characters to 6-bit nibbles. ++ private static byte[] map2 = new byte[128]; ++ static { ++ for (int i=0; iin. ++ * @return A character array with the Base64 encoded data. ++ */ ++ public static char[] encode (byte[] in, int iLen) { ++ int oDataLen = (iLen*4+2)/3; // output length without padding ++ int oLen = ((iLen+2)/3)*4; // output length including padding ++ char[] out = new char[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++] & 0xff; ++ int i1 = ip < iLen ? in[ip++] & 0xff : 0; ++ int i2 = ip < iLen ? in[ip++] & 0xff : 0; ++ int o0 = i0 >>> 2; ++ int o1 = ((i0 & 3) << 4) | (i1 >>> 4); ++ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); ++ int o3 = i2 & 0x3F; ++ out[op++] = map1[o0]; ++ out[op++] = map1[o1]; ++ out[op] = op < oDataLen ? map1[o2] : '='; op++; ++ out[op] = op < oDataLen ? map1[o3] : '='; op++; } ++ return out; } ++ ++ /** ++ * Decodes a string from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return A String containing the decoded data. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static String decodeString (String s) { ++ return new String(decode(s)); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (String s) { ++ return decode(s.toCharArray()); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * No blanks or line breaks are allowed within the Base64 encoded data. ++ * @param in a character array containing the Base64 encoded data. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (char[] in) { ++ int iLen = in.length; ++ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); ++ while (iLen > 0 && in[iLen-1] == '=') iLen--; ++ int oLen = (iLen*3) / 4; ++ byte[] out = new byte[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++]; ++ int i1 = in[ip++]; ++ int i2 = ip < iLen ? in[ip++] : 'A'; ++ int i3 = ip < iLen ? in[ip++] : 'A'; ++ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int b0 = map2[i0]; ++ int b1 = map2[i1]; ++ int b2 = map2[i2]; ++ int b3 = map2[i3]; ++ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int o0 = ( b0 <<2) | (b1>>>4); ++ int o1 = ((b1 & 0xf)<<4) | (b2>>>2); ++ int o2 = ((b2 & 3)<<6) | b3; ++ out[op++] = (byte)o0; ++ if (op 0) { ++ proxy_auth = true; ++ proxySock.close(); ++ } else if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { ++ proxySock.close(); ++ proxySock = psocket(proxyHost, proxyPort); ++ if (proxySock == null) { ++ dbg("2-a sadly, returning a null socket"); ++ return; ++ } ++ } ++ } catch(Exception e) { ++ dbg("sock prob: " + e.getMessage()); ++ } ++ ++ while (true) { ++ String line = readline(proxy_is); ++ dbg("proxy line: " + line.trim()); ++ if (proxy_auth) { ++ String uc = line.toLowerCase(); ++ if (uc.indexOf("proxy-authenticate:") == 0) { ++ if (uc.indexOf(" basic ") >= 0) { ++ int idx = uc.indexOf(" realm"); ++ if (idx >= 0) { ++ proxy_auth_basic_realm = uc.substring(idx+1); ++ } ++ } ++ } ++ } ++ if (line.equals("\r\n") || line.equals("\n")) { ++ break; ++ } ++ } ++ if (!proxy_auth || proxy_auth_basic_realm.equals("")) { ++ break; ++ } ++ } ++ } ++ + public SSLSocket proxy_socket(SSLSocketFactory factory) { + Properties props = null; + String proxyHost = null; @@ -3483,44 +3587,10 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); + } + -+ dbg("proxy_in_use psocket:"); -+ proxySock = psocket(proxyHost, proxyPort); ++ proxy_helper(proxyHost, proxyPort); + if (proxySock == null) { -+ dbg("1-a sadly, returning a null socket"); + return null; + } -+ String hp = host + ":" + port; -+ -+ String req1 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n\r\n"; -+ -+ dbg("requesting1: " + req1); -+ -+ try { -+ proxy_os.write(req1.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied1: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-a sadly, returning a null socket"); -+ return null; -+ } -+ } -+ } catch(Exception e) { -+ dbg("sock prob1: " + e.getMessage()); -+ } -+ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line1: " + line.trim()); -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } + } else if (viewer.CONNECT != null) { + dbg("viewer.CONNECT psocket:"); + proxySock = psocket(host, port); @@ -3562,7 +3632,6 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + break; + } + } -+ + } + + Socket sslsock = null; @@ -3922,6 +3991,77 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } +} + ++class ProxyPasswdDialog implements ActionListener { ++ String guessedHost = null; ++ String guessedPort = null; ++ String guessedUser = null; ++ String guessedPasswd = null; ++ String realm = null; ++ /* ++ * this is the gui to show the user the cert and info and ask ++ * them if they want to continue using this cert. ++ */ ++ ++ Button ok; ++ Dialog dialog; ++ TextField entry1; ++ TextField entry2; ++ String reply1 = ""; ++ String reply2 = ""; ++ ++ ProxyPasswdDialog (String h, int p, String realm) { ++ guessedHost = h; ++ try { ++ guessedPort = Integer.toString(p); ++ } catch (Exception e) { ++ guessedPort = "8080"; ++ } ++ this.realm = realm; ++ } ++ ++ public void queryUser() { ++ ++ /* create and display the dialog for unverified cert. */ ++ ++ Frame frame = new Frame("Proxy Requires Username and Password"); ++ ++ dialog = new Dialog(frame, true); ++ ++ //Label label = new Label("Please Enter your Web Proxy Username in the top Entry and Password in the bottom Entry", Label.CENTER); ++ TextArea label = new TextArea("Please Enter your Web Proxy\nUsername in the Top Entry and\nPassword in the Bottom Entry,\nand then press OK.", 4, 20, TextArea.SCROLLBARS_NONE); ++ entry1 = new TextField(30); ++ entry2 = new TextField(30); ++ entry2.setEchoChar('*'); ++ ok = new Button("OK"); ++ ok.addActionListener(this); ++ ++ dialog.setLayout(new BorderLayout()); ++ dialog.add("North", label); ++ dialog.add("Center", entry1); ++ dialog.add("South", entry2); ++ dialog.add("East", ok); ++ dialog.pack(); ++ dialog.resize(dialog.preferredSize()); ++ ++ dialog.show(); /* block here til OK or Cancel pressed. */ ++ return; ++ } ++ ++ public String getAuth() { ++ return reply1 + ":" + reply2; ++ } ++ ++ public synchronized void actionPerformed(ActionEvent evt) { ++ System.out.println(evt.getActionCommand()); ++ if (evt.getSource() == ok) { ++ reply1 = entry1.getText(); ++ reply2 = entry2.getText(); ++ //dialog.dispose(); ++ dialog.hide(); ++ } ++ } ++} ++ +class ClientCertDialog implements ActionListener { + + Button ok; @@ -4102,6 +4242,127 @@ diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java + } + } +} ++ ++class Base64Coder { ++ ++ // Mapping table from 6-bit nibbles to Base64 characters. ++ private static char[] map1 = new char[64]; ++ static { ++ int i=0; ++ for (char c='A'; c<='Z'; c++) map1[i++] = c; ++ for (char c='a'; c<='z'; c++) map1[i++] = c; ++ for (char c='0'; c<='9'; c++) map1[i++] = c; ++ map1[i++] = '+'; map1[i++] = '/'; } ++ ++ // Mapping table from Base64 characters to 6-bit nibbles. ++ private static byte[] map2 = new byte[128]; ++ static { ++ for (int i=0; iin. ++ * @return A character array with the Base64 encoded data. ++ */ ++ public static char[] encode (byte[] in, int iLen) { ++ int oDataLen = (iLen*4+2)/3; // output length without padding ++ int oLen = ((iLen+2)/3)*4; // output length including padding ++ char[] out = new char[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++] & 0xff; ++ int i1 = ip < iLen ? in[ip++] & 0xff : 0; ++ int i2 = ip < iLen ? in[ip++] & 0xff : 0; ++ int o0 = i0 >>> 2; ++ int o1 = ((i0 & 3) << 4) | (i1 >>> 4); ++ int o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); ++ int o3 = i2 & 0x3F; ++ out[op++] = map1[o0]; ++ out[op++] = map1[o1]; ++ out[op] = op < oDataLen ? map1[o2] : '='; op++; ++ out[op] = op < oDataLen ? map1[o3] : '='; op++; } ++ return out; } ++ ++ /** ++ * Decodes a string from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return A String containing the decoded data. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static String decodeString (String s) { ++ return new String(decode(s)); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * @param s a Base64 String to be decoded. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (String s) { ++ return decode(s.toCharArray()); } ++ ++ /** ++ * Decodes a byte array from Base64 format. ++ * No blanks or line breaks are allowed within the Base64 encoded data. ++ * @param in a character array containing the Base64 encoded data. ++ * @return An array containing the decoded data bytes. ++ * @throws IllegalArgumentException if the input is not valid Base64 encoded data. ++ */ ++ public static byte[] decode (char[] in) { ++ int iLen = in.length; ++ if (iLen%4 != 0) throw new IllegalArgumentException ("Length of Base64 encoded input string is not a multiple of 4."); ++ while (iLen > 0 && in[iLen-1] == '=') iLen--; ++ int oLen = (iLen*3) / 4; ++ byte[] out = new byte[oLen]; ++ int ip = 0; ++ int op = 0; ++ while (ip < iLen) { ++ int i0 = in[ip++]; ++ int i1 = in[ip++]; ++ int i2 = ip < iLen ? in[ip++] : 'A'; ++ int i3 = ip < iLen ? in[ip++] : 'A'; ++ if (i0 > 127 || i1 > 127 || i2 > 127 || i3 > 127) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int b0 = map2[i0]; ++ int b1 = map2[i1]; ++ int b2 = map2[i2]; ++ int b3 = map2[i3]; ++ if (b0 < 0 || b1 < 0 || b2 < 0 || b3 < 0) ++ throw new IllegalArgumentException ("Illegal character in Base64 encoded data."); ++ int o0 = ( b0 <<2) | (b1>>>4); ++ int o1 = ((b1 & 0xf)<<4) | (b2>>>2); ++ int o2 = ((b2 & 3)<<6) | b3; ++ out[op++] = (byte)o0; ++ if (op + * classes/ssl: java viewer now handles auth-basic proxy logins. + * misc/enhanced_tightvnc_viewer: update ssvnc. + 2009-06-14 Karl Runge * x11vnc: Add X11VNC_REFLECT_PASSWORD env. var. for -reflect mode. Message to user about compiz problems suggesting -noxdamage. diff --git a/x11vnc/README b/x11vnc/README index 5426bf6..2c9af6b 100644 --- a/x11vnc/README +++ b/x11vnc/README @@ -2,7 +2,7 @@ Copyright (C) 2002-2009 Karl J. Runge All rights reserved. -x11vnc README file Date: Sun Jun 14 13:03:59 EDT 2009 +x11vnc README file Date: Thu Jun 18 21:59:34 EDT 2009 The following information is taken from these URLs: @@ -55,7 +55,7 @@ x11vnc: a VNC server for real X displays solutions to many problems; and interesting applications, but nevertheless please feel free to [24]contact me if you have problems or questions (and if I save you time by giving you some of my time, - please consider a [25]paypal donation). Please check the [26]FAQ + please consider a [25]paypal donation.) Please check the [26]FAQ first; I realize this page is massive, but you can often use your browser's find-in-page action using a keyword to find the answer to your problem or question. @@ -127,13 +127,13 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick The VNC protocol is in most cases better suited for remote connections with low bandwidth and high latency than is the X11 protocol because it involves far fewer "roundtrips" (an exception is the [38]cached - pixmap data on the viewing-end provided by X). Also, with no state + pixmap data on the viewing-end provided by X.) Also, with no state maintained the viewing-end can crash, be rebooted, or relocated and the applications and desktop continue running. Not so with X11. So the standard Xvnc/vncserver program is very useful, I use it for things like: - * Desktop conferencing with other users (e.g. codereviews). + * Desktop conferencing with other users (e.g. codereviews.) * Long running apps/tasks I want to be able to view from many places. * Motif, GNOME, and similar applications that would yield very poor @@ -164,7 +164,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick running there. You can use ssh, or even rlogin, telnet, or any other method to do this. We do this because the x11vnc process needs to be run on the same machine the X server process is running on (otherwise - things would be extremely slow). + things would be extremely slow.) Step 2. In that far-away.east shell (with command prompt "far-away>" in this example) run x11vnc directed at the far-away.east X session @@ -174,18 +174,18 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick You could have also set the environment variable DISPLAY=:0 instead of using "-display :0". This step attaches x11vnc to the far-away.east:0 - X display (i.e. no viewer clients yet). + X display (i.e. no viewer clients yet.) Common Gotcha: To get X11 permissions right, you may also need to set the XAUTHORITY environment variable (or use the [42]-auth option) to point to the correct MIT-MAGIC-COOKIE file (e.g. - /home/joe/.Xauthority). If x11vnc does not have the authority to + /home/joe/.Xauthority.) If x11vnc does not have the authority to connect to the display it exits immediately. More on how to fix this [43]below. If you suspect an X11 permissions problem do this simple test: while sitting at the physical X display open a terminal window - (gnome-terminal, xterm, etc). You should be able to run x11vnc + (gnome-terminal, xterm, etc.) You should be able to run x11vnc successfully in that terminal without any need for command line options. If that works OK then you know X11 permissions are the only thing preventing it from working when you try to start x11vnc via a @@ -213,7 +213,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick for PDA's like the Palm Pilot! You can use any of them to connect to x11vnc (see the above VNC links under "Background:" on how to obtain a viewer for your platform or see [46]this FAQ. For Solaris, vncviewer - is available in the [47]Companion CD package SFWvnc). + is available in the [47]Companion CD package SFWvnc.) In this example we'll use the Unix vncviewer program on sitting-here by typing the following command in a second terminal window: @@ -224,14 +224,14 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick allowing interaction with the far-away.east:0 X11 desktop. Pretty nifty! When finished, exit the viewer: the remote x11vnc process will shutdown automatically (or you can use the [48]-forever option to have - it wait for additional viewer connections). + it wait for additional viewer connections.) Common Gotcha: Nowadays there will likely be a host-level [49]firewall on the x11vnc side that is blocking remote access to the VNC port - (e.g. 5900). You will either have to open up that port (or a range of + (e.g. 5900.) You will either have to open up that port (or a range of ports) in your firewall administration tool, or try the [50]SSH tunnelling method below (even still the firewall must allow in the SSH - port, 22). + port, 22.) Shortcut: Of course if you left x11vnc running on far-away.east:0 in a @@ -243,7 +243,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick Super Shortcut: Here is a potentially very easy way to get all of it working. * Have x11vnc (0.9.3 or later) available to run on the remote host - (i.e. in $PATH). + (i.e. in $PATH.) * Download and unpack a [55]SSVNC bundle (1.0.19 or later, e.g. [56]ssvnc_no_windows-1.0.19.tar.gz) on the Viewer-side machine. * Start the SSVNC Terminal Services mode GUI: ./ssvnc/bin/tsvnc @@ -258,10 +258,10 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick SSH into the remote host; i.e. that you have a Unix account there and the SSH server is running. On Unix and MacOS X it is assumed that the ssh client command is available on the local machine (on Windows a - plink binary is included in the SSVNC bundle). Finally, it is assumed + plink binary is included in the SSVNC bundle.) Finally, it is assumed that you are already logged into an X session on the remote machine, e.g. your workstation (otherwise, a virtual X server, e.g. Xvfb, will - be [58]started for you). + be [58]started for you.) In some cases the remote SSH server will not run commands with the same $PATH that you normally have in your shell there. In this case @@ -276,7 +276,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick has the user sitting at "far-away.east:0" and invites one or more other people to view and interact with his desktop. Perhaps the user gives a demo or presentation this way (using the telephone for vocal - communication). A "Remote Help Desk" mode would be similar: a + communication.) A "Remote Help Desk" mode would be similar: a technician connects remotely to the user's desktop to interactively solve a problem the user is having. @@ -293,7 +293,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick The above example had no security or privacy at all. When logging into remote machines (certainly when going over the internet) it is best to use ssh, or use a VPN (for a VPN, Virtual Private Network, the above - example should be pretty safe). + example should be pretty safe.) For x11vnc one can tunnel the VNC protocol through an encrypted ssh channel. It would look something like running the following commands: @@ -314,12 +314,12 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick link, so you need to force the issue with -encodings "copyrect tight ...". Nowadays, not all viewers use the -encodings option, try "-PreferredEncoding=ZRLE" (although the newer viewers seem to - autodetect well when to use raw or not). + autodetect well when to use raw or not.) Note that "x11vnc -localhost ..." limits incoming vncviewer connections to only those from the same machine. This is very natural for ssh tunnelling (the redirection appears to come from the same - machine). Use of a [60]VNC password is also strongly recommended. + machine.) Use of a [60]VNC password is also strongly recommended. Note also the -t we used above (force allocate pseudoterminal), it actually seems to improve interactive typing response via VNC! @@ -335,7 +335,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick Some VNC viewers will do the ssh tunnelling for you automatically, the TightVNC Unix vncviewer does this when the "-via far-away.east" option is supplied to it (this requires x11vnc to be already running on - far-away.east or having it started by [61]inetd(8)). See the 3rd + far-away.east or having it started by [61]inetd(8).) See the 3rd script example [62]below for more info. SSVNC: You may also want to look at the [63]Enhanced TightVNC Viewer @@ -362,20 +362,20 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick sitting-here> ssh -t -L 5900:OtherHost:5900 gateway.east Where gateway.east is the internet hostname (or IP) of the gateway - machine (SSH server). 'OtherHost' might be, e.g., freds-pc or + machine (SSH server.) 'OtherHost' might be, e.g., freds-pc or 192.168.2.33 (it is OK for these to be private hostnames or private IP - addresses, the host in -L is relative to the remote server side). + addresses, the host in -L is relative to the remote server side.) Once logged in, you'll need to do a second login (ssh, rsh, etc.) to the workstation machine 'OtherHost' and then start up x11vnc on it (if - it isn't already running). (The "[65]-connect gateway:59xx" option may - be another alternative here with the viewer already in -listen mode). + it isn't already running.) (The "[65]-connect gateway:59xx" option may + be another alternative here with the viewer already in -listen mode.) For an automatic way to use a gateway and have all the network traffic encrypted (including inside the firewall) see [66]Chaining SSH's. These gateway access modes also can be done automatically for you via the "Proxy/Gateway" setting in [67]SSVNC (including the Chaining SSH's - case, "Double Proxy"). + case, "Double Proxy".) Firewalls/Routers: @@ -391,7 +391,7 @@ to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick Firewall/Router to, say, the SSH port (22) on an inside machine (how to do this depends on your particular Firewall/Router, often the router config URL is http://192.168.100.1 See [68]www.portforward.com - for more info). This way you reach these computers from anywhere on + for more info.) This way you reach these computers from anywhere on the Internet and use x11vnc to view X sessions running on them. Suppose you configured the Firewall/Router to redirect these ports to @@ -409,10 +409,10 @@ nc -localhost -display :0' Where far-away.east means the hostname (or IP) that the Router/Firewall is using (for home setups this is usually the IP gotten from your ISP via DHCP, the site [69]http://www.whatismyip.com/ - is a convenient way to determine what it is). + is a convenient way to determine what it is.) It is a good idea to add some obscurity to accessing your system via - SSH by using some high random port (e.g. 12300 in the above example). + SSH by using some high random port (e.g. 12300 in the above example.) If you can't remember it, or are otherwise not worried about port scanners detecting the presence of your SSH server and there is just one internal PC involved you could map 22: @@ -443,7 +443,7 @@ nc -localhost -display :0' "far-away.east:0" to reach jills-pc and "far-away.east:1" to reach freds-pc. We assume above that x11vnc is using port 5900 (and any Host-Level-firewalls on jills-pc has been configured to let that port - in). + in.) For a home system one likely does not have a hostname and would have to use the IP address, say, "24.56.78.93:0". E.g.: @@ -553,10 +553,10 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. Very Important: It is up to YOU to tell x11vnc to use password protection (-rfbauth or -passwdfile), it will NOT do it for you automatically or force you to (use [80]-usepw if you want to be forced - to). The same goes for encrypting the channel between the viewer and + to.) The same goes for encrypting the channel between the viewer and x11vnc: it is up to you to use ssh, stunnel, [81]-ssl mode, a VPN, etc. (use the [82]Enhanced TightVNC Viewer (SSVNC) GUI if you want to - be forced to use SSL or SSH). For additional safety, also look into + be forced to use SSL or SSH.) For additional safety, also look into the -allow and -localhost [83]options and building x11vnc with [84]tcp_wrappers support to limit host access. @@ -568,7 +568,7 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. [85]stunnel (also [86]stunnel.mirt.net) or using the built-in (Mar/2006) [87]-ssl openssl mode. A SSL-enabled Java applet VNC Viewer is also provided in the x11vnc package (and https can be used to - download it). + download it.) Although not as ubiquitous as ssh, SSL tunnelling still provides a useful alternative. See [88]this FAQ on -ssl and -stunnel modes for @@ -576,7 +576,7 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. The [89]Enhanced TightVNC Viewer (SSVNC) bundles contain some convenient utilities to automatically set up an SSL tunnel from the - viewer-side (i.e. to connect to "x11vnc -ssl ..."). And many other + viewer-side (i.e. to connect to "x11vnc -ssl ...".) And many other enhancements too. _________________________________________________________________ @@ -611,11 +611,11 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. More tools: Here is a ssh/rsh wrapper script rx11vnc that attempts to automatically do the above Steps 1-3 for you (provided you have - ssh/rsh login permission on the machine x11vnc is to be run on). The + ssh/rsh login permission on the machine x11vnc is to be run on.) The above example would be: "rx11vnc far-away.east:0" typed into a shell on sitting-here.west. Also included is an experimental script rx11vnc.pl that attempts to tunnel the vnc traffic through an ssh port - redirection (and does not assume port 5900 is free). Have a look at + redirection (and does not assume port 5900 is free.) Have a look at them to see what they do and customize as needed: * [100]rx11vnc wrapper script * [101]rx11vnc.pl wrapper script to tunnel traffic thru ssh @@ -646,7 +646,7 @@ vncviewer -via $host localhost:0 # must be TightVNC vncviewer. Or do make install, it will probably install to /usr/local/bin (run ./configure --help for information on customizing your configuration, - e.g. --prefix=/my/place). You can now run it via typing "x11vnc", + e.g. --prefix=/my/place.) You can now run it via typing "x11vnc", "x11vnc -help | more", "x11vnc -forever -shared -display :0", etc. @@ -677,7 +677,7 @@ $MAKE libvncserver's choice of AM_CFLAGS. See the [105]build scripts below for more ideas. Scripts similar to the above have been shown to work with vendor C compilers on HP-UX (ccom: HP92453-01) and Tru64 (Compaq - C V6.5-011). + C V6.5-011.) You can find information on [106]Misc. Build problems here. @@ -685,7 +685,7 @@ $MAKE Building on Solaris, FreeBSD, etc: Depending on your version of Solaris or other Unix OS the jpeg and/or zlib libraries may be in - non-standard places (e.g. /usr/local, /usr/sfw, /opt/sfw, etc). + non-standard places (e.g. /usr/local, /usr/sfw, /opt/sfw, etc.) Note: If configure cannot find these two libraries then TightVNC and ZRLE encoding support will be disabled, and you don't want that!!! The @@ -700,12 +700,12 @@ $MAKE (The only thing this misses is /usr/X11/lib/libXrandr.so.2, which is for the little used -xrandr option, see the script below to pick it up - as well). + as well.) libjpeg is included in Solaris 9 and later (/usr/sfw/include and /usr/sfw/lib), and zlib in Solaris 8 and later (/usr/include and - /usr/lib). So on Solaris 9 you can pick up everything with something + /usr/lib.) So on Solaris 9 you can pick up everything with something like this: env PATH=/usr/local/bin:/usr/ccs/bin:$PATH sh -c './configure --with-jpeg=/us r/sfw; make' @@ -797,7 +797,7 @@ ls -l ./x11vnc/x11vnc Building on FreeBSD, OpenBSD, ...: The jpeg libraries seem to be in /usr/local or /usr/pkg on these OS's. You won't need the openwin stuff - in the above script (but you may need /usr/X11R6/...). Also starting + in the above script (but you may need /usr/X11R6/....) Also starting with the 0.7.1 x11vnc release, this usually works: ./configure --with-jpeg=/usr/local make @@ -805,14 +805,14 @@ ls -l ./x11vnc/x11vnc Building on HP-UX: For jpeg and zlib you will need to do the same sort of thing as described above for Solaris. You set CPPFLAGS and - LDFLAGS to find them (see below for an example). You do not need to do + LDFLAGS to find them (see below for an example.) You do not need to do any of the above /usr/openwin stuff. Also, HP-UX does not seem to support -R, so get rid of the -R items in LDFLAGS. Because of this, at runtime you may need to set LD_LIBRARY_PATH or SHLIB_PATH to indicate the directory paths so the libraries can be found. It is a good idea to have static archives, e.g. libz.a and libjpeg.a for the nonstandard libraries so that they get bolted into the x11vnc binary (and so won't - get "lost"). + get "lost".) Here is what we recently did to build x11vnc 0.7.2 on HP-UX 11.11 ./configure --with-jpeg=$HOME/hpux/jpeg --with-zlib=$HOME/hpux/zlib @@ -852,7 +852,7 @@ make However, if your system has the Mac OS X build package for X11 apps you will not need to supply the "--without-x" option (in this case the resulting x11vnc would be able to export both the native Mac OS X - display and windows displayed in the XDarwin X server). Be sure to + display and windows displayed in the XDarwin X server.) Be sure to include the ./configure option to find libjpeg on your system. @@ -892,7 +892,7 @@ make To aid testing of the [117]built-in SSL/TLS support for x11vnc, a number of VNC Viewer packages for Unix, Mac OS X, and Windows have been created that provide SSL Support for the TightVNC Viewer (this is - done by [118]wrapper scripts and a GUI that starts [119]STUNNEL). It + done by [118]wrapper scripts and a GUI that starts [119]STUNNEL.) It should be pretty convenient for automatic SSL and SSH connections. It is described in detail at and can be downloaded from the [120]Enhanced TightVNC Viewer (SSVNC) page. The SSVNC Unix viewer also supports @@ -917,6 +917,12 @@ make connected client, all encodings are safe on all platforms. Note that some features (e.g. scroll detection and -ncache) may be disabled or run with reduced functionality in -threads mode. + * Automatically tries to work around an [124]Xorg server bug + involving infinitely repeating keys when turning off key + repeating. Use [125]-repeat if the automatic workaround fails. + * Improved reliability of the Single Port SSL VNC and HTTPS java + viewer applet delivery mechanism. + * The [126]-clip mode works under [127]-rawfb. Here are some features that appeared in the 0.9.7 release: @@ -926,38 +932,38 @@ make case the special file /dev/vcsa2 is used to retrieve vt2's current text. Text and colors are shown, but no graphics. * Support for less than 8 bits per pixel framebuffers (e.g. 4 or 1 - bpp) in the [124]-rawfb mode. + bpp) in the [128]-rawfb mode. * The SSL enabled UltraVNC Java viewer applet now has a [Home] entry in the "drives" drop down menu. This menu can be configured with the ftpDropDown applet parameter. All of the applet parameters are documented in classes/ssl/README. - * Experimental support for [125]VirtualGL's [126]TurboVNC (an + * Experimental support for [129]VirtualGL's [130]TurboVNC (an enhanced TightVNC for fast LAN high framerate usage.) * The CUPS Terminal Services helper mode has been improved. - * Improvements to the [127]-ncache_cr that allows smooth opaque + * Improvements to the [131]-ncache_cr that allows smooth opaque window motions using the 'copyrect' encoding when using - [128]-ncache mode. - * The [129]-rmflag option enables a way to indicate to other + [132]-ncache mode. + * The [133]-rmflag option enables a way to indicate to other processes x11vnc has exited. * Reverse connections using anonymous Diffie Hellman SSL encryption now work. Here are some features that appeared in the 0.9.6 release: - * Support for [130]VeNCrypt SSL/TLS encrypted connections. It is - enabled by default in the [131]-ssl mode. VNC Viewers like + * Support for [134]VeNCrypt SSL/TLS encrypted connections. It is + enabled by default in the [135]-ssl mode. VNC Viewers like vinagre, gvncviewer/gtk-vnc, the vencrypt package, and others support this encryption mode. It can also be used with the - [132]-unixpw option to enable Unix username and password + [136]-unixpw option to enable Unix username and password authentication (VeNCrypt's "*Plain" modes.) A similar but older VNC security type "ANONTLS" (used by vino) is supported as well. - See the [133]-vencrypt and [134]-anontls options for additional + See the [137]-vencrypt and [138]-anontls options for additional control. The difference between x11vnc's normal -ssl mode and VeNCrypt is that the former wraps the entire VNC connection in SSL (like HTTPS does for HTTP, i.e. "vncs://") while VeNCrypt switches on the SSL/TLS at a certain point during the VNC handshake. Use - [135]-sslonly to disable both VeNCrypt and ANONTLS (vino). - * The "[136]-ssl ANON" option enables Anonymous Diffie-Hellman (ADH) + [139]-sslonly to disable both VeNCrypt and ANONTLS (vino.) + * The "[140]-ssl ANON" option enables Anonymous Diffie-Hellman (ADH) key exchange for x11vnc's normal SSL/TLS operation. Note that Anonymous Diffie-Hellman uses encryption for privacy, but provides no authentication and so is susceptible to Man-In-The-Middle @@ -965,17 +971,17 @@ make SAVE", etc. and have the VNC viewer verify the cert.) The ANONTLS mode (vino) only supports ADH. VeNCrypt mode supports both ADH and regular X509 SSL certificates modes. For these ADH is enabled by - default. See [137]-vencrypt and [138]-anontls for how to disable + default. See [141]-vencrypt and [142]-anontls for how to disable ADH. * For x11vnc's SSL/TLS modes, one can now specify a Certificate - Revocation List (CRL) with the [139]-sslCRL option. This will only + Revocation List (CRL) with the [143]-sslCRL option. This will only be useful for wide deployments: say a company-wide x11vnc SSL access deployment using a central Certificate Authority (CA) via - [140]-sslGenCA and [141]-sslGenCert. This way if a user has his + [144]-sslGenCA and [145]-sslGenCert. This way if a user has his laptop lost or stolen, you only have to revoke his key instead of creating a new Certificate Authority and redeploying new keys to all users. - * The default SSL/TLS mode, "[142]-ssl" (no pem file parameter + * The default SSL/TLS mode, "[146]-ssl" (no pem file parameter supplied), is now the same as "-ssl SAVE" and will save the generated self-signed cert in "~/.vnc/certs/server.pem". Previously "-ssl" would create a temporary self-signed cert that @@ -985,48 +991,48 @@ make same x11vnc server. Use "-ssl TMP" to regain the previous behavior. Use "-ssl SAVE_NOPROMPT" to avoid being prompted about using passphrase when the certificate is created. - * The option [143]-http_oneport enables single-port HTTP connections + * The option [147]-http_oneport enables single-port HTTP connections via the Java VNC Viewer. So, for example, the web browser URL "http://myhost.org:5900" works the same as "http://myhost.org:5800", but with the convenience of only involving one port instead of two. This works for both unencrypted - connections and for SSH tunnels (see [144]-httpsredir if the - tunnel port differs). Note that HTTPS single-port operation in - [145]-ssl SSL encrypted mode has been available since x11vnc + connections and for SSH tunnels (see [148]-httpsredir if the + tunnel port differs.) Note that HTTPS single-port operation in + [149]-ssl SSL encrypted mode has been available since x11vnc version 0.8.3. - * For the [146]-avahi/[147]-zeroconf Service Advertizing mode, if + * For the [150]-avahi/[151]-zeroconf Service Advertizing mode, if x11vnc was not compiled with the avahi-client library, then an external helper program, either avahi-publish(1) (on Unix) or dns-sd(1) (on Mac OS X), is used instead. - * The "[148]-rfbport PROMPT" option will prompt the user via the GUI + * The "[152]-rfbport PROMPT" option will prompt the user via the GUI to select the VNC port (e.g. 5901) to listen on, and a few other basic settings. This enables a handy GUI mode for naive users: x11vnc -gui tray=setpass -rfbport PROMPT -logfile $HOME/.x11vnc.log.%VNCDISP LAY suitable for putting in a launcher or menu, e.g. - [149]x11vnc.desktop. The [150]-logfile expansion is new too. In + [153]x11vnc.desktop. The [154]-logfile expansion is new too. In the GUI, the tray=setpass Properties panel has been improved. - * The [151]-solid solid background color option now works for the + * The [155]-solid solid background color option now works for the Mac OS X console. - * The [152]-reopen option instructs x11vnc to try to reopen the X + * The [156]-reopen option instructs x11vnc to try to reopen the X display if it is prematurely closed by, say, the display manager - (e.g. [153]GDM). + (e.g. [157]GDM.) Here are some features that appeared in the 0.9.5 release: - * Symmetric key [154]encryption ciphers. ARC4, AES-128, AES-256, + * Symmetric key [158]encryption ciphers. ARC4, AES-128, AES-256, blowfish, and 3des are supported. Salt and initialization vector seeding is provided. These compliment the more widely used SSL and - SSH encryption access methods. [155]SSVNC also supports these + SSH encryption access methods. [159]SSVNC also supports these encryption modes. * Scaling differently along the X- and Y-directions. E.g. - "[156]-scale 1280x1024" or "-scale 0.8x0.75" Also, - "[157]-geometry WxH" is an alias for "-scale WxH" + "[160]-scale 1280x1024" or "-scale 0.8x0.75" Also, + "[161]-geometry WxH" is an alias for "-scale WxH" * By having SSVNC version 1.0.21 or later available in your $PATH, - the [158]-chatwindow option allows a UltraVNC Text Chat window to + the [162]-chatwindow option allows a UltraVNC Text Chat window to appear on the local X11 console/display (this way the remote viewer can chat with the person at the physical display; e.g. - helpdesk mode). This also works on the Mac OS X console if the + helpdesk mode.) This also works on the Mac OS X console if the Xquartz X11 server (enabled by default on leopard) is running for the chatwindow. * The HTTP Java viewer applet jar, classes/VncViewer.jar, has been @@ -1035,46 +1041,46 @@ LAY Here are some features that appeared in the 0.9.4 release: - * Improvements to the [159]-find and [160]-create X session finding + * Improvements to the [163]-find and [164]-create X session finding or creating modes: new desktop types and service redirection options. Personal cupsd daemon and SSH port redirection helper for - use with [161]SSVNC's Terminal Services feature. - * Reverse VNC connections via [162]-connect work in the [163]-find, - [164]-create and related [165]-display WAIT:... modes. + use with [165]SSVNC's Terminal Services feature. + * Reverse VNC connections via [166]-connect work in the [167]-find, + [168]-create and related [169]-display WAIT:... modes. * Reverse VNC connections (either normal or SSL) can use a Web Proxy or a SOCKS proxy, or a SSH connection, or even a CGI URL to make - the outgoing connection. See: [166]-proxy. Forward connections can - also use: [167]-ssh. - * Reverse VNC connections via the [168]UltraVNC repeater proxy + the outgoing connection. See: [170]-proxy. Forward connections can + also use: [171]-ssh. + * Reverse VNC connections via the [172]UltraVNC repeater proxy (either normal or SSL) are supported. Use either the - "[169]-connect repeater=ID:NNNN+host:port" or "[170]-connect - repeater://host:port+ID:NNNN" notation. The [171]SSVNC VNC viewer + "[173]-connect repeater=ID:NNNN+host:port" or "[174]-connect + repeater://host:port+ID:NNNN" notation. The [175]SSVNC VNC viewer also supports the UltraVNC repeater. * Support for indexed colormaps (PseudoColor) with depths other than 8 (from 1 to 16 now work) for non-standard hardware. Option - "[172]-advertise_truecolor" to handle some workaround in this + "[176]-advertise_truecolor" to handle some workaround in this mode. * Support for the ZYWRLE encoding, this is the RealVNC ZRLE encoding extended to do motion video and photo regions more efficiently by way of a Wavelet based transformation. - * The [173]-finddpy and [174]-listdpy utilities help to debug and - configure the [175]-find, [176]-create, and [177]-display WAIT:... + * The [177]-finddpy and [178]-listdpy utilities help to debug and + configure the [179]-find, [180]-create, and [181]-display WAIT:... modes. * Some automatic detection of screen resizes are handled even if the - [178]-xrandr option is not supplied. - * The [179]-autoport options gives more control over the VNC port + [182]-xrandr option is not supplied. + * The [183]-autoport options gives more control over the VNC port x11vnc chooses. - * The [180]-ping secs can be used to help keep idle connections + * The [184]-ping secs can be used to help keep idle connections alive. * Pasting of the selection/clipboard into remote applications (e.g. Java) has been improved. * Fixed a bug if a client disconnects during the 'speed-estimation' phase. * To unset Caps_Lock, Num_Lock and raise all keys in the X server - use [181]-clear_all. + use [185]-clear_all. * Usage with dvorak keyboards has been improved. See also: - [182]-xkb. - * The [183]Java Viewer applet source code is now included in the + [186]-xkb. + * The [187]Java Viewer applet source code is now included in the x11vnc-0.9.*.tar.gz tarball. This means you can now build the Java viewer applet jar files from source. If you stopped shipping the Java viewer applet jar files due to lack of source code, you can @@ -1082,15 +1088,15 @@ LAY Here are some features that appeared in the 0.9.3 release: - * [184]Viewer-side pixmap caching. A large area of pixels (at least + * [188]Viewer-side pixmap caching. A large area of pixels (at least 2-3 times as big as the framebuffer itself; the bigger the better... default is 10X) is placed below the framebuffer to act as a buffer/cache area for pixel data. The VNC CopyRect encoding is used to move it around, so any viewer can take advantage of it. Until we start modifying viewers you will be able to see the cache - area if you scroll down (this makes it easier to debug!). For + area if you scroll down (this makes it easier to debug!) For testing the default is "-ncache 10". The unix Enhanced TightVNC - Viewer [185]ssvnc has a nice [186]-ycrop option to help hide the + Viewer [189]ssvnc has a nice [190]-ycrop option to help hide the pixel cache area from view. @@ -1103,30 +1109,30 @@ LAY * If UltraVNC file transfer or chat is detected, then VNC clients are "pinged" more often to prevent these side channels from becoming serviced too infrequently. - * In [187]-unixpw mode in the username and password dialog no text + * In [191]-unixpw mode in the username and password dialog no text will be echoed if the first character sent is "Escape". This enables a convenience feature in SSVNC to send the username and password automatically. Here are some features that appeared in the 0.9.1 release: - * The [188]UltraVNC Java viewer has been enhanced to support SSL (as - the TightVNC viewer had been previously). The UltraVNC Java + * The [192]UltraVNC Java viewer has been enhanced to support SSL (as + the TightVNC viewer had been previously.) The UltraVNC Java supports ultravnc filetransfer, and so can be used as a VNC viewer on Unix that supports ultravnc filetransfer. It is in the classes/ssl/UltraViewerSSL.jar file (that is pointed to by - ultra.vnc). The signed applet SignedUltraViewerSSL.jar version + ultra.vnc.) The signed applet SignedUltraViewerSSL.jar version (pointed to by ultrasigned.vnc) will be needed to access the local drive if you are using it for file transfer via a Web browser. Some other bugs in the UltraVNC Java viewer were fixed and a few improvements to the UI made. * A new Unix username login mode for VNC Viewers authenticated via a - Client SSL Certificate: "[189]-users sslpeer=". The emailAddress + Client SSL Certificate: "[193]-users sslpeer=". The emailAddress subject field is inspected for username@hostname and then acts as though "-users +username" has been supplied. This way the Unix username is identified by (i.e. simply extracted from) the Client - SSL Certificate. This could be useful with [190]-find, - [191]-create and [192]-svc modes if you are also have set up and + SSL Certificate. This could be useful with [194]-find, + [195]-create and [196]-svc modes if you are also have set up and use VNC Client SSL Certificate authentication. * For external display finding/creating programs (e.g. WAIT:cmd=...) if the VNC Viewer is authenticated via a Client SSL Certificate, @@ -1135,41 +1141,41 @@ LAY Here are some features that appeared in the 0.9 release: - * [193]VNC Service advertising via mDNS / ZeroConf / BonJour with - the [194]Avahi client library. Enable via "[195]-avahi" or - "[196]-zeroconf". + * [197]VNC Service advertising via mDNS / ZeroConf / BonJour with + the [198]Avahi client library. Enable via "[199]-avahi" or + "[200]-zeroconf". * Implementations of UltraVNC's TextChat, SingleWindow, and - ServerInput extensions (requires ultravnc viewer or [197]ssvnc - Unix viewer). They toggle the selection of a single window - ([198]-id), and disable (friendly) user input and viewing (monitor + ServerInput extensions (requires ultravnc viewer or [201]ssvnc + Unix viewer.) They toggle the selection of a single window + ([202]-id), and disable (friendly) user input and viewing (monitor blank) at the VNC server. - * Short aliases "[199]-find", "[200]-create", "[201]-svc", and - "[202]-xdmsvc" for commonly used FINDCREATEDISPLAY usage modes. + * Short aliases "[203]-find", "[204]-create", "[205]-svc", and + "[206]-xdmsvc" for commonly used FINDCREATEDISPLAY usage modes. * Reverse VNC connections (viewer listening) now work in SSL - ([203]-ssl) mode. + ([207]-ssl) mode. * New options to control the Monitor power state and keyboard/mouse - grabbing: [204]-forcedpms, [205]-clientdpms, [206]-noserverdpms, - and [207]-grabalways. + grabbing: [208]-forcedpms, [209]-clientdpms, [210]-noserverdpms, + and [211]-grabalways. * A simple way to emulate inetd(8) to some degree via the - "[208]-loopbg" option. - * Monitor the accuracy of XDAMAGE and apply "[209]-noxdamage" if it - is not working well. OpenGL applications like like [210]beryl and + "[212]-loopbg" option. + * Monitor the accuracy of XDAMAGE and apply "[213]-noxdamage" if it + is not working well. OpenGL applications like like [214]beryl and MythTv have been shown to make XDAMAGE not work properly. * For Java SSL connections involving a router/firewall port - redirection, an option [211]-httpsredir to spare the user from + redirection, an option [215]-httpsredir to spare the user from needing to include &PORT=NNN in the browser URL. Here are some features that appeared in the 0.8.4 release: - * Native [212]Mac OS X Aqua/Quartz support. (i.e. OSXvnc + * Native [216]Mac OS X Aqua/Quartz support. (i.e. OSXvnc alternative; some activities are faster) - * A [213]new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY + * A [217]new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY -unixpw ..." that will Create a new X session (either virtual or real and with or without a display manager, e.g. kdm) for the user if it cannot find the user's X session display via the FINDDISPLAY - method. See the [214]-svc and the [215]-xdmsvc aliases. - * x11vnc can act as a VNC [216]reflector/repeater using the - "[217]-reflect host:N" option. Instead of polling an X display, + method. See the [218]-svc and the [219]-xdmsvc aliases. + * x11vnc can act as a VNC [220]reflector/repeater using the + "[221]-reflect host:N" option. Instead of polling an X display, the remote VNC Server host:N is connected to and re-exported via VNC. This is intended for use in broadcasting a display to many (e.g. > 16; classroom or large demo) VNC viewers where bandwidth @@ -1177,16 +1183,16 @@ LAY number of repeaters. * Wireframe copyrect detection for local user activity (e.g. someone sitting at the physical display moving windows) Use - [218]-nowireframelocal to disable. - * The "[219]-N" option couples the VNC Display number to the X + [222]-nowireframelocal to disable. + * The "[223]-N" option couples the VNC Display number to the X Display number. E.g. if your X DISPLAY is :2 then the VNC display - will be :2 (i.e. using port 5902). If that port is taken x11vnc + will be :2 (i.e. using port 5902.) If that port is taken x11vnc will exit. - * Option [220]-nodpms to avoid problems with programs like KDE's + * Option [224]-nodpms to avoid problems with programs like KDE's kdesktop_lock that keep restarting the screen saver every few seconds. * To automatically fix the common mouse motion problem on XINERAMA - (multi-headed) displays, the [221]-xwarppointer option is enabled + (multi-headed) displays, the [225]-xwarppointer option is enabled by default when XINERAMA is active. If you have a Mac please try out the native Mac OS X support, build @@ -1196,62 +1202,62 @@ LAY Here are some features that appeared in the 0.8.3 release: - * The [222]-ssl option provides SSL encryption and authentication - natively via the [223]www.openssl.org library. One can use from a + * The [226]-ssl option provides SSL encryption and authentication + natively via the [227]www.openssl.org library. One can use from a simple self-signed certificate server certificate up to full CA and client certificate authentication schemes. - * Similar to -ssl, the [224]-stunnel option starts up a SSL tunnel + * Similar to -ssl, the [228]-stunnel option starts up a SSL tunnel server stunnel (that must be installed separately on the system: - [225]www.stunnel.org [226]stunnel.mirt.net ) to allow only + [229]www.stunnel.org [230]stunnel.mirt.net ) to allow only encrypted SSL connections from the network. - * The [227]-sslverify option allows for authenticating VNC clients + * The [231]-sslverify option allows for authenticating VNC clients via their certificates in either -ssl or -stunnel modes. * Certificate creation and management tools are provide in the - [228]-sslGenCert, [229]-sslGenCA, and [230]related options. + [232]-sslGenCert, [233]-sslGenCA, and [234]related options. * An SSL enabled Java applet VNC Viewer applet is provided by x11vnc in classes/ssl/VncViewer.jar. In addition to normal HTTP, the applet may be loaded into the web browser via HTTPS (HTTP over - SSL). (one can use the VNC port, e.g. https://host:5900/, or also - the separate [231]-https port option). A wrapper shell script - [232]ss_vncviewer is also provided that sets up a stunnel - client-side tunnel on Unix systems. See [233]Enhanced TightVNC + SSL.) (one can use the VNC port, e.g. https://host:5900/, or also + the separate [235]-https port option.) A wrapper shell script + [236]ss_vncviewer is also provided that sets up a stunnel + client-side tunnel on Unix systems. See [237]Enhanced TightVNC Viewer (SSVNC) for other SSL/SSH viewer possibilities. - * The [234]-unixpw option supports Unix username and password - authentication (a simpler variant is the [235]-unixpw_nis option + * The [238]-unixpw option supports Unix username and password + authentication (a simpler variant is the [239]-unixpw_nis option that works in environments where the encrypted passwords are - readable, e.g. NIS). The [236]-ssl or [237]-localhost + - [238]-stunnel options are enforced in this mode to prevent + readable, e.g. NIS.) The [240]-ssl or [241]-localhost + + [242]-stunnel options are enforced in this mode to prevent password sniffing. As a convenience, these requirements are lifted - if a SSH tunnel can be deduced (but -localhost still applies). - * Coupling [239]-unixpw with "[240]-display WAIT:cmd=FINDDISPLAY" or + if a SSH tunnel can be deduced (but -localhost still applies.) + * Coupling [243]-unixpw with "[244]-display WAIT:cmd=FINDDISPLAY" or "-display WAIT:cmd=FINDCREATEDISPLAY" provides a way to allow a user to login with their UNIX password and have their display - connected to [241]automatically. See the [242]-svc and the - [243]-xdmsvc aliases. - * Hooks are provided in the [244]-unixpw_cmd and "[245]-passwdfile + connected to [245]automatically. See the [246]-svc and the + [247]-xdmsvc aliases. + * Hooks are provided in the [248]-unixpw_cmd and "[249]-passwdfile cmd:,custom:..." options to allow you to supply your own authentication and password lookup programs. * x11vnc can be configured and built to not depend on X11 libraries - "./configure --without-x" for [246]-rawfb only operation (e.g. - embedded linux console devices). - * The [247]-rotate option enables you to rotate or reflect the + "./configure --without-x" for [250]-rawfb only operation (e.g. + embedded linux console devices.) + * The [251]-rotate option enables you to rotate or reflect the screen before exporting via VNC. This is intended for use on handhelds and other devices where the rotation orientation is not "natural". - * The "[248]-ultrafilexfer" alias is provided and improved UltraVNC + * The "[252]-ultrafilexfer" alias is provided and improved UltraVNC filetransfer rates have been achieved. - * Under the "[249]-connect_or_exit host" option x11vnc will exit + * Under the "[253]-connect_or_exit host" option x11vnc will exit immediately unless the reverse connection to host succeeds. The "-rfbport 0" option disables TCP listening for connections (useful - for this mode). - * The "[250]-rawfb rand" and "-rawfb none" options are useful for + for this mode.) + * The "[254]-rawfb rand" and "-rawfb none" options are useful for testing automation scripts, etc., without requiring a full desktop. - * Reduced spewing of information at startup, use "[251]-verbose" + * Reduced spewing of information at startup, use "[255]-verbose" (also "-v") to turn it back on for debugging or if you are going to send me a problem report. - Here are some [252]Previous Release Notes + Here are some [256]Previous Release Notes _________________________________________________________________ Some Notes: @@ -1278,14 +1284,14 @@ LAY protocol.) I suggest using xsetroot, dtstyle or similar utility to set a solid background while using x11vnc. You can turn the pretty background image back on when you are using the display directly. - Update: As of Feb/2005 x11vnc has the [253]-solid [color] option that + Update: As of Feb/2005 x11vnc has the [257]-solid [color] option that works on recent GNOME, KDE, and CDE and also on classic X (background - image is on the root window). Update: As of Oct/2007 x11vnc has the - [254]-ncache option that does a reasonable job caching the background + image is on the root window.) Update: As of Oct/2007 x11vnc has the + [258]-ncache option that does a reasonable job caching the background (and other) pixmap data on the viewer side. - I also find the [255]TightVNC encoding gives the best response for my - usage (Unix <-> Unix over cable modem). One needs a tightvnc-aware + I also find the [259]TightVNC encoding gives the best response for my + usage (Unix <-> Unix over cable modem.) One needs a tightvnc-aware vncviewer to take advantage of this encoding. TCP port issues: Notice the lines @@ -1293,20 +1299,20 @@ LAY PORT=5900 in the output. 5900 is the default VNC listening port (just like 6000 - is X11's default listening port). Had port 5900 been taken by some + is X11's default listening port.) Had port 5900 been taken by some other application, x11vnc would have next tried 5901. That would mean the viewer command above should be changed to vncviewer - far-away.east:1. You can force the port with the "[256]-rfbport NNNN" + far-away.east:1. You can force the port with the "[260]-rfbport NNNN" option where NNNN is the desired port number. If that port is already - taken, x11vnc will exit immediately. The "[257]-N" option will try to + taken, x11vnc will exit immediately. The "[261]-N" option will try to match the VNC display number to the X display. (also see the "SunRay Gotcha" note below) Options: x11vnc has (far too) many features that may be activated - via its [258]command line options. Useful options are, e.g., -scale to + via its [262]command line options. Useful options are, e.g., -scale to do server-side scaling, and -rfbauth passwd-file to use VNC password protection (the vncpasswd or storepasswd programs, or the x11vnc - [259]-storepasswd option can be used to create the password file). + [263]-storepasswd option can be used to create the password file.) Algorithm: How does x11vnc do it? Rather brute-forcedly: it continuously polls the X11 framebuffer for changes using @@ -1334,7 +1340,7 @@ LAY first testing out the programs. You get an interesting recursive/feedback effect where vncviewer images keep popping up each one contained in the previous one and slightly shifted a bit by the - window manager decorations. There will be an [260]even more + window manager decorations. There will be an [264]even more interesting effect if -scale is used. Also, if the XKEYBOARD is supported and the XBell "beeps" once, you get an infinite loop of beeps going off. Although all of this is mildly exciting it is not @@ -1344,8 +1350,8 @@ LAY Sun Ray Notes: - You can run x11vnc on your (connected or disconnected) [261]SunRay - session. Here are some [262]notes on SunRay usage with x11vnc. + You can run x11vnc on your (connected or disconnected) [265]SunRay + session. Here are some [266]notes on SunRay usage with x11vnc. _________________________________________________________________ @@ -1356,16 +1362,16 @@ LAY large areas) slow. Experiment with interacting a bit differently than you normally do to minimize the effects (e.g. do fullpage paging rather than line-by-line scrolling, and move windows in a - single, quick motion). Recent work has provided the - [263]-scrollcopyrect and [264]-wireframe speedups using the + single, quick motion.) Recent work has provided the + [267]-scrollcopyrect and [268]-wireframe speedups using the CopyRect VNC encoding and other things, but they only speed up some activities, not all. * A rate limiting factor for x11vnc performance is that graphics hardware is optimized for writing, not reading (x11vnc reads the - video framebuffer for the screen image data). The difference can + video framebuffer for the screen image data.) The difference can be a factor of 10 to 1000, and so it usually takes about 0.5-1 sec to read in the whole video hardware framebuffer (e.g. 5MB for - 1280x1024 at depth 24 with a read rate of 5-10MB/sec). So whenever + 1280x1024 at depth 24 with a read rate of 5-10MB/sec.) So whenever activity changes most of the screen (e.g. moving or iconifying a large window) there is a delay of 0.5-1 sec while x11vnc reads the changed regions in. @@ -1373,14 +1379,14 @@ LAY bottleneck on a fast LAN (whereas on slower links the reduced network bandwidth becomes the bottleneck.) Note: A quick way to get a 2X speedup of this for x11vnc is to - switch your X server from depth 24 (32bpp) to depth 16 (16bpp). + switch your X server from depth 24 (32bpp) to depth 16 (16bpp.) You get a 4X speedup going to 8bpp, but the lack of color cells is usually unacceptable. To get a sense of the read and write speeds of your video card, you can run benchmarks like: "x11perf -getimage500", "x11perf -putimage500", "x11perf -shmput500" and for XFree86 displays with direct graphics access the "dga" command (press "b" to run the - benchmark and then after a few seconds press "q" to quit). Even + benchmark and then after a few seconds press "q" to quit.) Even this "dd if=/dev/fb0 of=/dev/null" often gives a good estimate. x11vnc also prints out its estimate: 28/02/2009 11:11:07 Autoprobing TCP port @@ -1397,7 +1403,7 @@ LAY On XFree86/Xorg it is actually possible to increase the framebuffer read speed considerably (10-100 times) by using the Shadow Framebuffer (a copy of the framebuffer is kept in main - memory and this can be read much more quickly). To do this one + memory and this can be read much more quickly.) To do this one puts the line Option "ShadowFB" "true" in the Device section of the /etc/X11/XF86Config or /etc/X11/xorg.conf file. Note that this disables 2D acceleration at the physical display and so that might @@ -1405,7 +1411,7 @@ LAY display. Nevertheless this could be handy in some circumstances, e.g. if the slower speed while sitting at the physical display was acceptable (this seems to be true for most video cards these - days). Unfortunately it does not seem shadowfb can be turned on + days.) Unfortunately it does not seem shadowfb can be turned on and off dynamically... Another amusing thing one can do is use Xvfb as the X server, e.g. "xinit $HOME/.xinitrc -- /usr/X11R6/bin/Xvfb :1 -screen 0 @@ -1416,37 +1422,37 @@ LAY but we mention it because it may be of use for special purpose applications. You may need to use the "-cc 4" option to force Xvfb to use a TrueColor visual instead of DirectColor. See also the - description of the [265]-create option that does all of this + description of the [269]-create option that does all of this automatically for you. Also, a faster and more accurate way is to use the "dummy" - XFree86/Xorg device driver (or our Xdummy wrapper script). See - [266]this FAQ for details. + XFree86/Xorg device driver (or our Xdummy wrapper script.) See + [270]this FAQ for details. * Somewhat surprisingly, the X11 mouse (cursor) shape is write-only and cannot be queried from the X server. So traditionally in x11vnc the cursor shape stays fixed at an arrow. (see the "-cursor - X" and "-cursor some" [267]options, however, for a partial hack - for the root window, etc.). However, on Solaris using the SUN_OVL + X" and "-cursor some" [271]options, however, for a partial hack + for the root window, etc.) However, on Solaris using the SUN_OVL overlay extension, x11vnc can show the correct mouse cursor when - the [268]-overlay option is also supplied. A similar thing is done + the [272]-overlay option is also supplied. A similar thing is done on IRIX as well when -overlay is supplied. More generally, as of Dec/2004 x11vnc supports the new XFIXES extension (in Xorg and Solaris 10) to query the X server for the exact cursor shape, this works pretty well except that cursors with transparency (alpha channel) need to approximated to solid - RGB values (some cursors look worse than others). + RGB values (some cursors look worse than others.) * Audio from applications is of course not redirected (separate - redirectors do exist, e.g. esd, see [269]the FAQ on this below.) + redirectors do exist, e.g. esd, see [273]the FAQ on this below.) The XBell() "beeps" will work if the X server supports the XKEYBOARD extension. (Note that on Solaris XKEYBOARD is disabled - by default. Passing +kb to Xsun enables it). - * The scroll detection algorithm for the [270]-scrollcopyrect option + by default. Passing +kb to Xsun enables it.) + * The scroll detection algorithm for the [274]-scrollcopyrect option can give choppy or bunched up transient output and occasionally painting errors. * Using -threads can expose some bugs/crashes in libvncserver. - Please feel free to [271]contact me if you have any questions, + Please feel free to [275]contact me if you have any questions, problems, or comments about x11vnc, etc. - Also, some people ask if they can make a donation, see [272]this link + Also, some people ask if they can make a donation, see [276]this link for that. References @@ -1574,155 +1580,159 @@ References 121. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-enc 122. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads 123. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect - 124. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 125. http://www.virtualgl.org/ - 126. http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc - 127. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_cr - 128. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache - 129. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rmflag - 130. http://sourceforge.net/projects/vencrypt/ - 131. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 132. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 133. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt - 134. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls - 135. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslonly - 136. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 124. http://bugs.freedesktop.org/show_bug.cgi?id=21454 + 125. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-repeat + 126. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clip + 127. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 128. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 129. http://www.virtualgl.org/ + 130. http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc + 131. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_cr + 132. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache + 133. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rmflag + 134. http://sourceforge.net/projects/vencrypt/ + 135. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 136. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw 137. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt 138. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls - 139. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCRL - 140. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA - 141. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert - 142. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 143. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-http_oneport - 144. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir - 145. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 146. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi - 147. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf - 148. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport - 149. http://www.karlrunge.com/x11vnc/x11vnc.desktop - 150. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-o - 151. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid - 152. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reopen - 153. http://www.karlrunge.com/x11vnc/faq.html#infaq_gdm - 154. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-enc - 155. http://www.karlrunge.com/x11vnc/ssvnc.html - 156. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale - 157. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-geometry - 158. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-chatwindow - 159. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 160. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 161. http://www.karlrunge.com/x11vnc/ssvnc.html - 162. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect + 139. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslonly + 140. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 141. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vencrypt + 142. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-anontls + 143. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslCRL + 144. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA + 145. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert + 146. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 147. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-http_oneport + 148. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir + 149. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 150. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi + 151. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf + 152. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport + 153. http://www.karlrunge.com/x11vnc/x11vnc.desktop + 154. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-o + 155. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid + 156. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reopen + 157. http://www.karlrunge.com/x11vnc/faq.html#infaq_gdm + 158. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-enc + 159. http://www.karlrunge.com/x11vnc/ssvnc.html + 160. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale + 161. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-geometry + 162. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-chatwindow 163. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find 164. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 165. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 166. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy - 167. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssh - 168. http://www.uvnc.com/addons/repeater.html - 169. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect - 170. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 171. http://www.karlrunge.com/x11vnc/ssvnc.html - 172. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-advertise_truecolor - 173. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-finddpy - 174. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-listdpy - 175. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 176. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 177. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 178. http://www.karlrunge.com/x11vnc/faq.html#faq-xrandr - 179. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-autoport - 180. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ping - 181. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all - 182. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb - 183. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers - 184. http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching - 185. http://www.karlrunge.com/x11vnc/ssvnc.html - 186. http://www.karlrunge.com/x11vnc/ssvnc.html#ycrop - 187. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 188. http://www.ultravnc.com/ - 189. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 190. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 191. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 192. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 193. http://www.karlrunge.com/x11vnc/faq.html#faq-avahi - 194. http://www.avahi.org/ - 195. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi - 196. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf - 197. http://www.karlrunge.com/x11vnc/ssvnc.html - 198. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 199. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 200. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 201. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 202. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 203. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 204. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-forcedpms - 205. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clientdpms - 206. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms - 207. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-grabalways - 208. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop - 209. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage - 210. http://www.karlrunge.com/x11vnc/faq.html#faq-beryl - 211. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir - 212. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx - 213. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 214. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 215. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 216. http://www.karlrunge.com/x11vnc/faq.html#faq-reflect - 217. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect - 218. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nowireframelocal - 219. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N - 220. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodpms - 221. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer - 222. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 223. http://www.openssl.org/ - 224. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel - 225. http://www.stunnel.org/ - 226. http://stunnel.mirt.net/ - 227. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify - 228. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert - 229. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA - 230. http://www.karlrunge.com/x11vnc/ssl.html - 231. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-https - 232. http://www.karlrunge.com/x11vnc/faq.html#infaq_ss_vncviewer - 233. http://www.karlrunge.com/x11vnc/ssvnc.html - 234. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 235. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_nis - 236. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 237. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost - 238. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel - 239. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 240. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 241. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin - 242. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 243. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 244. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_cmd - 245. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-passwdfile - 246. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 247. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rotate - 248. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer - 249. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect_or_exit + 165. http://www.karlrunge.com/x11vnc/ssvnc.html + 166. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect + 167. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 168. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 169. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 170. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy + 171. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssh + 172. http://www.uvnc.com/addons/repeater.html + 173. http://www.karlrunge.com/x11vnc/faq.html#faq-reverse-connect + 174. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 175. http://www.karlrunge.com/x11vnc/ssvnc.html + 176. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-advertise_truecolor + 177. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-finddpy + 178. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-listdpy + 179. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 180. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 181. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 182. http://www.karlrunge.com/x11vnc/faq.html#faq-xrandr + 183. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-autoport + 184. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ping + 185. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all + 186. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb + 187. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers + 188. http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching + 189. http://www.karlrunge.com/x11vnc/ssvnc.html + 190. http://www.karlrunge.com/x11vnc/ssvnc.html#ycrop + 191. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 192. http://www.ultravnc.com/ + 193. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 194. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 195. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 196. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 197. http://www.karlrunge.com/x11vnc/faq.html#faq-avahi + 198. http://www.avahi.org/ + 199. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi + 200. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf + 201. http://www.karlrunge.com/x11vnc/ssvnc.html + 202. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 203. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 204. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 205. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 206. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 207. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 208. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-forcedpms + 209. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clientdpms + 210. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms + 211. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-grabalways + 212. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop + 213. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage + 214. http://www.karlrunge.com/x11vnc/faq.html#faq-beryl + 215. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir + 216. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx + 217. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 218. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 219. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 220. http://www.karlrunge.com/x11vnc/faq.html#faq-reflect + 221. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect + 222. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nowireframelocal + 223. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N + 224. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodpms + 225. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer + 226. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 227. http://www.openssl.org/ + 228. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel + 229. http://www.stunnel.org/ + 230. http://stunnel.mirt.net/ + 231. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslverify + 232. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCert + 233. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sslGenCA + 234. http://www.karlrunge.com/x11vnc/ssl.html + 235. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-https + 236. http://www.karlrunge.com/x11vnc/faq.html#infaq_ss_vncviewer + 237. http://www.karlrunge.com/x11vnc/ssvnc.html + 238. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 239. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_nis + 240. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 241. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost + 242. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-stunnel + 243. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 244. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 245. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin + 246. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 247. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 248. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw_cmd + 249. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-passwdfile 250. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 251. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-v, - 252. http://www.karlrunge.com/x11vnc/prevrels.html - 253. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid - 254. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache - 255. http://www.tightvnc.com/ - 256. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport - 257. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N - 258. http://www.karlrunge.com/x11vnc/x11vnc_opts.html - 259. http://www.karlrunge.com/x11vnc/faq.html#faq-passwd - 260. http://www.karlrunge.com/x11vnc/recurse_x11vnc.jpg - 261. http://www.sun.com/sunray/index.html - 262. http://www.karlrunge.com/x11vnc/sunray.html - 263. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 264. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 265. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 266. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb - 267. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor - 268. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-overlay - 269. http://www.karlrunge.com/x11vnc/faq.html#faq-sound - 270. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 271. mailto:xvml@karlrunge.com - 272. http://www.karlrunge.com/x11vnc/faq.html#faq-thanks + 251. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rotate + 252. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer + 253. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect_or_exit + 254. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 255. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-v, + 256. http://www.karlrunge.com/x11vnc/prevrels.html + 257. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid + 258. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache + 259. http://www.tightvnc.com/ + 260. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport + 261. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N + 262. http://www.karlrunge.com/x11vnc/x11vnc_opts.html + 263. http://www.karlrunge.com/x11vnc/faq.html#faq-passwd + 264. http://www.karlrunge.com/x11vnc/recurse_x11vnc.jpg + 265. http://www.sun.com/sunray/index.html + 266. http://www.karlrunge.com/x11vnc/sunray.html + 267. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 268. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 269. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 270. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb + 271. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor + 272. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-overlay + 273. http://www.karlrunge.com/x11vnc/faq.html#faq-sound + 274. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 275. mailto:xvml@karlrunge.com + 276. http://www.karlrunge.com/x11vnc/faq.html#faq-thanks ======================================================================= http://www.karlrunge.com/x11vnc/faq.html: @@ -1744,7 +1754,7 @@ http://www.karlrunge.com/x11vnc/faq.html: [5]Q-3: I just built x11vnc successfully, but when I use it my keystrokes and mouse button clicks are ignored (I am able to move the - mouse though). + mouse though.) [6]Q-4: Help, I need to run x11vnc on Solaris 2.5.1 (or other old Unix/Linux) and it doesn't compile! @@ -1810,7 +1820,7 @@ http://www.karlrunge.com/x11vnc/faq.html: [Color Issues] [24]Q-22: The X display I run x11vnc on is only 8 bits per pixel (bpp) - PseudoColor (i.e. only 256 distinct colors). The x11vnc colors may + PseudoColor (i.e. only 256 distinct colors.) The x11vnc colors may start out OK, but after a while they are incorrect in certain windows. [25]Q-23: Color problems: Why are the colors for some windows @@ -1828,7 +1838,7 @@ http://www.karlrunge.com/x11vnc/faq.html: using the -id windowid option to view a single application window? [29]Q-27: My X display is depth 24 at 24bpp (instead of the normal - depth 24 at 32bpp). I'm having lots of color and visual problems with + depth 24 at 32bpp.) I'm having lots of color and visual problems with x11vnc and/or vncviewer. What's up? [Xterminals] @@ -1904,7 +1914,7 @@ http://www.karlrunge.com/x11vnc/faq.html: different user? [49]Q-47: I use a screen-lock when I leave my workstation (e.g. - xscreensaver or xlock). When I remotely access my workstation desktop + xscreensaver or xlock.) When I remotely access my workstation desktop via x11vnc I can unlock the desktop fine, but I am worried people will see my activities on the physical monitor. What can I do to prevent this, or at least make it more difficult? @@ -1944,7 +1954,7 @@ http://www.karlrunge.com/x11vnc/faq.html: [60]Q-58: How can I use x11vnc to connect to an X login screen like xdm, GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into - an X session yet). + an X session yet.) [61]Q-59: Can I run x11vnc out of inetd(8)? How about xinetd(8)? @@ -1969,7 +1979,7 @@ http://www.karlrunge.com/x11vnc/faq.html: proxy or SSH? [68]Q-66: Can I use x11vnc as a replacement for Xvnc? (i.e. not for a - real display, but for a virtual one I keep around). + real display, but for a virtual one I keep around.) [69]Q-67: How can I use x11vnc on "headless" machines? Why might I want to? @@ -1995,7 +2005,7 @@ http://www.karlrunge.com/x11vnc/faq.html: [76]Q-74: When I drag windows around with the mouse or scroll up and down things really bog down (unless I do the drag in a single, quick - motion). Is there anything to do to improve things? + motion.) Is there anything to do to improve things? [77]Q-75: Why not do something like wireframe animations to avoid the windows "lurching" when being moved or resized? @@ -2044,7 +2054,7 @@ http://www.karlrunge.com/x11vnc/faq.html: (i.e. greater than)! Strangely, typing ">" works OK!! [89]Q-87: Extra Character Inserted, E.g.: When I try to type a "<" - (i.e. less than) instead I get "<," (i.e. an extra comma). + (i.e. less than) instead I get "<," (i.e. an extra comma.) [90]Q-88: I'm using an "international" keyboard (e.g. German "de", or Danish "dk") and the -modtweak mode works well if the VNC viewer is @@ -2089,16 +2099,16 @@ http://www.karlrunge.com/x11vnc/faq.html: vncviewer scrollbars, what I can do? [100]Q-98: Does x11vnc support server-side framebuffer scaling? (E.g. - to make the desktop smaller). + to make the desktop smaller.) [101]Q-99: Does x11vnc work with Xinerama? (i.e. multiple monitors - joined together to form one big, single screen). + joined together to form one big, single screen.) [102]Q-100: Can I use x11vnc on a multi-headed display that is not Xinerama (i.e. separate screens :0.0, :0.1, ... for each monitor)? [103]Q-101: Can x11vnc show only a portion of the display? (E.g. for a - special purpose application or a very large screen). + special purpose application or a very large screen.) [104]Q-102: Does x11vnc support the XRANDR (X Resize, Rotate and Reflection) extension? Whenever I rotate or resize the screen x11vnc @@ -2106,7 +2116,7 @@ http://www.karlrunge.com/x11vnc/faq.html: [105]Q-103: Independent of any XRANDR, can I have x11vnc rotate and/or reflect the screen that the VNC viewers see? (e.g. for a handheld - whose screen is rotated 90 degrees). + whose screen is rotated 90 degrees.) [106]Q-104: Why is the view in my VNC viewer completely black? Or why is everything flashing around randomly? @@ -2114,7 +2124,7 @@ http://www.karlrunge.com/x11vnc/faq.html: [107]Q-105: I use Linux Virtual Consoles (VC's) to implement 'Fast User Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those - keystrokes to switch between their sessions). How come the view in a + keystrokes to switch between their sessions.) How come the view in a VNC viewer connecting to x11vnc is either completely black or otherwise all messed up unless the X session x11vnc is attached to is in the active VC? @@ -2208,9 +2218,9 @@ http://www.karlrunge.com/x11vnc/faq.html: For the former error, you need to specify the X display to connect to (it also needs to be on the same machine the x11vnc process is to run - on). Set your DISPLAY environment variable (or use the [131]-display + on.) Set your DISPLAY environment variable (or use the [131]-display option) to specify it. Nearly always the correct value will be ":0" - (in fact, x11vnc will now assume :0 if given no other information). + (in fact, x11vnc will now assume :0 if given no other information.) For the latter error, you need to set up the X11 permissions @@ -2218,9 +2228,9 @@ http://www.karlrunge.com/x11vnc/faq.html: To make sure X11 permissions are the problem do this simple test: while sitting at the physical X display open a terminal window - (gnome-terminal, xterm, etc). You should be able to run x11vnc + (gnome-terminal, xterm, etc.) You should be able to run x11vnc successfully without any need for special steps or command line - options in that terminal (i.e. just type "x11vnc"). If that works OK + options in that terminal (i.e. just type "x11vnc".) If that works OK then you know X11 permissions are the only thing preventing it from working when you try to start x11vnc via, say, a remote shell. @@ -2231,7 +2241,7 @@ http://www.karlrunge.com/x11vnc/faq.html: /home/joe/.Xauthority or /var/gdm/:0.Xauth or /var/lib/kdm/A:0-crWk72K or /tmp/.gdmzndVlR, etc, etc.), or simply be sure you run x11vnc as the correct user (i.e. the user who is logged into the X session you - wish to view). + wish to view.) Note: The MIT cookie file contains the secret key that allows x11vnc to connect to the desired X display. @@ -2240,7 +2250,7 @@ http://www.karlrunge.com/x11vnc/faq.html: created for X forwarding that will cause problems. (Under some circumstances even su(1) and telnet(1) can set XAUTHORITY. See also the gdm parameter NeverPlaceCookiesOnNFS that sets XAUTHORITY to a - random filename in /tmp for the whole X session). + random filename in /tmp for the whole X session.) Running x11vnc as root is often not enough: you need to know where the MIT-MAGIC-COOKIE file for the desired X display is. @@ -2250,7 +2260,7 @@ http://www.karlrunge.com/x11vnc/faq.html: (this is for the display manager gdm and requires root permission to read the gdm cookie file, see [134]this faq for other display manager - cookie file names). + cookie file names.) Note as of Feb/2007 you can also try the [135]-find option instead of "-display ..." and see if that finds your display and Xauthority. @@ -2258,10 +2268,10 @@ http://www.karlrunge.com/x11vnc/faq.html: Less safe, but to avoid figuring out where the correct XAUTHORITY file is, if the person sitting at the physical X session types "xhost +localhost" then one should be able to attach x11vnc to the session - (from the same machine). The person could then type "xhost -localhost" + (from the same machine.) The person could then type "xhost -localhost" after x11vnc has connected to go back to the default permissions. Also, for some situations the "-users lurk=" option may soon be of use - (please read the documentation on the [136]-users option). + (please read the documentation on the [136]-users option.) To test out your X11 permissions from a remote shell, set DISPLAY and possibly XAUTHORITY (see your shell's man page, bash(1), tcsh(1), on @@ -2271,22 +2281,22 @@ http://www.karlrunge.com/x11vnc/faq.html: color visuals info) that means the X11 permissions are set up properly: xdpyinfo successfully connected to DISPLAY! You could also type xclock and make sure no errors are reported (a clock should - appear on the X display, press Ctrl-C to stop it). If these work, then + appear on the X display, press Ctrl-C to stop it.) If these work, then typing "x11vnc" in the same environment should also work. Important: if you cannot get your X11 permissions so that the xdpyinfo or xclock tests work, x11vnc also will not work (all of these X clients must be allowed to connect to the X server to function - properly). + properly.) Firewalls: Speaking of permissions, it should go without saying that the host-level [137]firewall will need to be configured to allow connections in on a port. E.g. 5900 (default VNC port) or 22 (default - SSH port for tunnelling VNC). Most systems these days have firewalls + SSH port for tunnelling VNC.) Most systems these days have firewalls turned on by default, so you will actively have to do something to poke a hole in the firewall at the desired port number. See your system administration tool for Firewall settings (Yast, Firestarter, - etc.). + etc.) Q-2: I can't get x11vnc and/or libvncserver to compile. @@ -2369,7 +2379,7 @@ libssl.so libcrypto.so libcrypt.so (either one you downloaded or built on another machine) there is a chance it won't work because that x11vnc binary requires libssl0.9.7 but the system only has libssl0.9.8 (which evidently is incompatible - with 0.9.7 and has a different SONAME). Your distro should allow you + with 0.9.7 and has a different SONAME.) Your distro should allow you do have both runtimes installed on your system: % dpkg -l libssl0.9.7 libssl0.9.8 ... @@ -2377,12 +2387,12 @@ libssl.so libcrypto.so libcrypt.so ii libssl0.9.8 0.9.8a-7ubuntu SSL shared libraries (in fact it should have installed both by default if it knew what it - was doing). See [139]here too. + was doing.) See [139]here too. Q-3: I just built x11vnc successfully, but when I use it my keystrokes and mouse button clicks are ignored (I am able to move the mouse - though). + though.) This is most likely due to you not having a working build environment for the XTEST client library libXtst.so. The library is probably @@ -2394,28 +2404,28 @@ libssl.so libcrypto.so libcrypt.so checking for XTestFakeKeyEvent in -lXtst... no The solution is to add the necessary build environment package (and - the library package if that is missing too). On Debian the build + the library package if that is missing too.) On Debian the build package is libxtst-dev. Other distros/OS's may have it in another package. x11vnc will build without support for this library (e.g. perhaps one - wants a view-only x11vnc on a stripped down or embedded system...). - And at runtime it will also continue to run even if the X server it + wants a view-only x11vnc on a stripped down or embedded system...) And + at runtime it will also continue to run even if the X server it connects to does not support XTEST. In both cases it cannot inject keystrokes or button clicks since XTEST is needed for that (it can - still move the mouse pointer using the X API XWarpPointer()). + still move the mouse pointer using the X API XWarpPointer().) You will see a warning message something like this at run time: 20/03/2005 22:33:09 WARNING: XTEST extension not available (either missing fr om 20/03/2005 22:33:09 display or client library libXtst missing at build time -). +.) 20/03/2005 22:33:09 MOST user input (pointer and keyboard) will be DISCARDE D. 20/03/2005 22:33:09 If display does have XTEST, be sure to build x11vnc wit h 20/03/2005 22:33:09 a working libXtst build environment (e.g. libxtst-dev, - 20/03/2005 22:33:09 or other packages). + 20/03/2005 22:33:09 or other packages.) 20/03/2005 22:33:09 No XTEST extension, switching to -xwarppointer mode for 20/03/2005 22:33:09 pointer motion input. @@ -2445,7 +2455,7 @@ h We have heard that since Dec/2004 a Solaris 2.6 built x11vnc will run on Solaris Solaris 2.5 and 2.5.1 (since a workaround for XConvertCase - is provided). + is provided.) In any event, here is a workaround for Solaris 2.5.1 (and perhaps earlier and perhaps non-Solaris): @@ -2480,7 +2490,7 @@ typedef unsigned int in_addr_t; [141]SunOS 4.x Please let us know if you had to use the above workaround (and whether - it worked or not). If there is enough demand we will try to push clean + it worked or not.) If there is enough demand we will try to push clean compilations back to earlier Solaris, Linux, etc, releases. @@ -2490,7 +2500,7 @@ typedef unsigned int in_addr_t; Hopefully the [142]build steps above and [143]FAQ provide enough info for a painless compile for most environments. Please report problems with the x11vnc configure, make, etc. on your system (if your system - is known to compile other GNU packages successfully). + is known to compile other GNU packages successfully.) There are precompiled x11vnc binaries built by other groups that are available at the following locations: @@ -2519,7 +2529,7 @@ typedef unsigned int in_addr_t; As a general note, the x11vnc program is simple enough you don't really need to install a package: the binary will in most cases work as is and from any location (as long as your system libraries are not - too old, etc). So, for Linux distributions that are not one of the + too old, etc.) So, for Linux distributions that are not one of the above, the x11vnc binary from the above packages has a good chance of working. You can "install" it by just copying the x11vnc binary to the desired directory in your PATH. Tip on extracting files from a Debian @@ -2570,7 +2580,7 @@ typedef unsigned int in_addr_t; x11vnc -wait 50 -localhost -rfbauth $HOME/.vnc/passwd -display :0 $* a similar thing can be done via aliases in your shell (bash, tcsh, - csh, etc..). + csh, etc..) Or as of Jun/2004 you can use the simple $HOME/.x11vncrc config file support. If that file exists, each line is taken as a command line @@ -2617,7 +2627,7 @@ display :0 at the physical X display (not remotely), using something like "x11vnc -display :0 -gui tray=setpass" might be something for them that they are accustomed to in a Desktop environment (it prompts for an initial - password, etc). This is a basic "Share My Desktop" usage mode. + password, etc.) This is a basic "Share My Desktop" usage mode. As of Nov/2008 in x11vnc 0.9.6 there is a desktop menu item (x11vnc.desktop) that runs this command: @@ -2632,7 +2642,7 @@ LAY default VNC port (5900)? Use something like, e.g., "x11vnc -rfbport 5901" to force it to use - port 5901 (this is VNC display :1). If something else is using that + port 5901 (this is VNC display :1.) If something else is using that port x11vnc will exit immediately. If you do not supply the -rfbport option, it will autoprobe starting at 5900 and work its way up to 5999 looking for a free port to listen on. In that case, watch for the @@ -2641,7 +2651,7 @@ LAY The "[171]-N" option will try to match the VNC display number to the X display (e.g. X11 DISPLAY of :5 (port 6005) will have VNC display :5 - (port 5905)). + (port 5905).) Also see the "[172]-autoport n" option to indicated at which value the auto probing should start at. @@ -2672,7 +2682,7 @@ LAY vncviewer third-machine.net:50 Or maybe two ports would be involved, e.g. the viewer goes to display - :51 (5951). It depends on the relay software being used. + :51 (5951.) It depends on the relay software being used. What software to run on third-machine? A TCP relay of some sort could be used... Try a google search on "tcp relay" or "ip relay". However, @@ -2681,7 +2691,7 @@ LAY Also, if you are not the admin of third-machine you'd have to convince the owner to allow you to install this software (and he would likely - need to open his server's firewall to allow the port through). + need to open his server's firewall to allow the port through.) It is recommended that [175]SSL is used for encryption (e.g. "[176]-ssl SAVE") when going over the internet. @@ -2692,10 +2702,10 @@ LAY Once that CGI script is set up on the website, both users go to, say, http://somesite.com/vncxfer (or maybe a "/cgi-bin" directory or ".cgi" - suffix must be used). Previously, both have agreed on the same session + suffix must be used.) Previously, both have agreed on the same session name (say by phone or email) , e.g. "5cows", and put that into the entry form on the vncxfer starting page (hopefully separated by a few - seconds, so the relay helper can fully start up at the first request). + seconds, so the relay helper can fully start up at the first request.) The page returned tells them the hostname and port number and possible command to use for forward (VNC Viewer) and reverse (VNC Server, i.e. @@ -2711,7 +2721,7 @@ LAY servers are not configured to do this, so you would need to ask the admin to do this for you. Nearly all free webspace sites, e.g. www.zendurl.com, will not allow your CGI script to be an open relay - like this. (If you find one that does allow this, let me know!). + like this. (If you find one that does allow this, let me know!) Maybe someday a clever trick will be thought up to relax the listening port requirement (e.g. use HTTP/CGI itself for the transfer... it is @@ -2745,12 +2755,12 @@ LAY vncviewer -encodings "copyrect tight zrle hextile" localhost:0 (we assume the old-style -encodings option needs to be used. See - [180]here for details.). + [180]here for details.) If the SSH machine has been configured (see sshd_config(5)) with the option GatewayPorts=yes, then the tunnel set up by the VNC Server will be reachable directly by the VNC viewer (as long as the SSH machine's - firewall does not block the port, 5933 in this example). So in that + firewall does not block the port, 5933 in this example.) So in that case the Viewer side does not need to run any ssh command, but rather only runs: vncviewer third-machine.net:33 @@ -2762,7 +2772,7 @@ LAY be run on the VNC Server side: x11vnc -ssh user@third-machine.net:33 ... - (the SSH passphrase may need to be supplied). + (the SSH passphrase may need to be supplied.) To automate on the VNC Viewer side, the user can use the [183]Enhanced TightVNC Viewer (SSVNC) by: @@ -2775,7 +2785,7 @@ LAY side doesn't need to create a SSH tunnel. In SSVNC the Viewer user could instead select 'Use SSL' and then, e.g., on the Server side supply "-ssl SAVE" to x11vnc. Then end-to-end SSL encryption would be - used (in addition to the SSH encryption on the Server-side leg). + used (in addition to the SSH encryption on the Server-side leg.) Q-13: Can I make x11vnc more quiet and also go into the background @@ -2830,7 +2840,7 @@ LAY There are some options. They are enabled by adding something like -Dxxxx=1 to the CPPFLAGS environment variable before running configure - (see the [191]build notes for general background). + (see the [191]build notes for general background.) /* * Mar/2006 * Build-time customization via CPPFLAGS. @@ -2842,7 +2852,7 @@ LAY * -DNOREPEAT=0 to have -repeat on by default. * -DADDKEYSYMS=0 to have -noadd_keysyms the default. * - * -DREMOTE_DEFAULT=0 to disable remote-control on by default (-yesremote). + * -DREMOTE_DEFAULT=0 to disable remote-control on by default (-yesremote.) * -DREMOTE_CONTROL=0 to disable remote-control mechanism completely. * -DEXTERNAL_COMMANDS=0 to disable the running of all external commands. * -DFILEXFER=0 disable filexfer. @@ -2917,7 +2927,7 @@ LAY * [198]x2x * [199]zvnc (MorphOS) - All of them will work with x11vnc (except x2x where it is not needed). + All of them will work with x11vnc (except x2x where it is not needed.) Q-20: I am running Win2VNC on my Windows machine and "x11vnc -nofb" on @@ -2927,17 +2937,17 @@ LAY Is the default visual of the X display you run x11vnc on low color (e.g. 8 bit per pixel PseudoColor)? (you can run xdpyinfo to check, - look in the "screen" section). There seems to be a bug in Win2VNC in + look in the "screen" section.) There seems to be a bug in Win2VNC in that it cannot deal correctly with colormaps (PseudoColor is the most - common example of a visual with a colormap). + common example of a visual with a colormap.) If so, there are a couple options. 1) Can you set the default visual on your display to be depth 24 TrueColor? Sun machines often have 8+24 overlay/multi-depth visuals, and you can make the default visual depth - 24 TrueColor (see fbconfig(1) and Xsun(1)). 2) As of Feb/2004 x11vnc + 24 TrueColor (see fbconfig(1) and Xsun(1).) 2) As of Feb/2004 x11vnc has the [200]-visual option to allow you to force the framebuffer visual to whatever you want (this usually messes up the colors unless - you are very clever). In this case, the option provides a convenient + you are very clever.) In this case, the option provides a convenient workaround for the Win2VNC bug: x11vnc -nofb -visual TrueColor -display :0 ... @@ -2957,13 +2967,13 @@ LAY [Color Issues] Q-22: The X display I run x11vnc on is only 8 bits per pixel (bpp) - PseudoColor (i.e. only 256 distinct colors). The x11vnc colors may + PseudoColor (i.e. only 256 distinct colors.) The x11vnc colors may start out OK, but after a while they are incorrect in certain windows. Use the [202]-flashcmap option to have x11vnc watch for changes in the colormap, and propagate those changes back to connected clients. This can be slow (since the whole screen must be updated over the network - whenever the colormap changes). This flashing colormap behavior often + whenever the colormap changes.) This flashing colormap behavior often happens if an application installs its own private colormap when the mouse is in its window. "netscape -install" is a well-known historical example of this. Consider reconfiguring the system to 16 bpp or depth @@ -2973,7 +2983,7 @@ LAY for flashing the colormap. Everything is dynamically transformed to depth 24 at 32 bpp using the colormaps. There may be painting errors however (see the following FAQ for tips on reducing and correcting - them). + them.) In some rare cases (SCO unixware) the [204]-notruecolor option has corrected colors on 8bpp displays. The red, green, and blue masks were @@ -2991,28 +3001,28 @@ LAY On some hardware (Sun/SPARC and SGI), the [206]-overlay option discussed a couple paragraphs down may solve this for you (you may - want to skip to it directly). On other hardware the less robust - [207]-8to24 option may help (also discussed below). + want to skip to it directly.) On other hardware the less robust + [207]-8to24 option may help (also discussed below.) Run xdpyinfo(1) to see what the default visual is and what the depths of the other visuals are. Does the default visual have a depth of 8 but there are other visuals of depth 24? If it does, can you possibly re-configure your X server to make a depth 24 visual the default? If you can do it, this will save you a lot of grief WRT colors and x11vnc - (and for general usage too!). Here is how I do this on an old + (and for general usage too!) Here is how I do this on an old Sparcstation 20 running Solaris 9 with SX graphics xinit -- -dev /dev/fb defclass TrueColor defdepth 24 and it works nicely (note: to log into console from the dtlogin window, select "Options -> Command Line Login", then login and enter - the above command). See the -dev section of the Xsun(1) manpage for a + the above command.) See the -dev section of the Xsun(1) manpage for a description of the above arguments. If you have root permission, a more permanent and convenient thing to do is to record the arguments in a line like: :0 Local local_uid@console root /usr/openwin/bin/Xsun -dev /dev/fb defclass TrueColor defdepth 24 - in /etc/dt/config/Xservers (copy /usr/dt/config/Xservers). Also look + in /etc/dt/config/Xservers (copy /usr/dt/config/Xservers.) Also look at the fbconfig(1) and related manpages (e.g. ffbconfig, m64config, pgxconfig, SUNWjfb_config, etc ...) for hardware framebuffer settings that may achieve the same effect. @@ -3020,7 +3030,7 @@ TrueColor defdepth 24 In general for non-Sun machines, look at the "-cc class" and related options in your X server manpage (perhaps Xserver(1)), it may allow modifying the default visual (e.g. "-cc 4", see for the - visual class numbers). On XFree86 some video card drivers (e.g. Matrox + visual class numbers.) On XFree86 some video card drivers (e.g. Matrox mga) have settings like Option "Overlay" "24,8" to support multi-depth overlays. For these, use the "-cc 4" X server command line option to get a depth 24 default visual. @@ -3045,12 +3055,12 @@ TrueColor defdepth 24 Misc. notes on -overlay mode: An amusing by-product of -overlay mode is that the mouse cursor shape is correct! (i.e. XFIXES is not - needed). The -overlay mode may be somewhat slower than normal mode due + needed.) The -overlay mode may be somewhat slower than normal mode due to the extra framebuffer manipulations that must be performed. Also, on Solaris there is a bug in that for some popup menus, the windows they overlap will have painting errors (flashing colors) while the popup is up (a workaround is to disable SaveUnders by passing -su to - Xsun, e.g. in your /etc/dt/config/Xservers file). + Xsun, e.g. in your /etc/dt/config/Xservers file.) The -8to24 mode: The [209]-8to24 x11vnc option (Jan/2006) is a kludge @@ -3090,11 +3100,11 @@ TrueColor defdepth 24 Colors still not working correctly? Run xwininfo on the application with the incorrect colors to verify that the depth of its visual is - different from the default visual depth (gotten from xdpyinfo). One + different from the default visual depth (gotten from xdpyinfo.) One possible workaround in this case is to use the [213]-id option to point x11vnc at the application window itself. If the application is complicated (lots of toplevel windows and popup menus) this may not be - acceptable, and may even crash x11vnc (but not the application). + acceptable, and may even crash x11vnc (but not the application.) It is theoretically possible to solve this problem in general (see xwd(1) for example), but it does not seem trivial or sufficiently fast @@ -3116,7 +3126,7 @@ TrueColor defdepth 24 The only workaround so far is to restart the X server with the "-cc 4" option to force TrueColor as the default visual (DirectColor is "-cc - 5"; see /usr/include/X11/X.h). The only place we have seen this is + 5"; see /usr/include/X11/X.h.) The only place we have seen this is with the virtual framebuffer server Xvfb on Xorg 7.2. So in that case you probably should restart it with something like this: "Xvfb :1 -cc 4 -screen 0 1280x1024x24". It should be possible for x11vnc to handle @@ -3134,7 +3144,7 @@ TrueColor defdepth 24 Run the xwininfo program in a terminal. It will ask you to click on the desired application window. After clicking, it will print out much - information, including the window id (e.g. 0x6000010). Also, the + information, including the window id (e.g. 0x6000010.) Also, the visual and depth of the window printed out is often useful in debugging x11vnc [216]color problems. @@ -3156,24 +3166,24 @@ TrueColor defdepth 24 you should be able to see these transient windows. If things are not working and you still want to do the single window - polling, try the [218]-sid windowid option ("shifted" windowid). + polling, try the [218]-sid windowid option ("shifted" windowid.) Q-27: My X display is depth 24 at 24bpp (instead of the normal depth - 24 at 32bpp). I'm having lots of color and visual problems with x11vnc + 24 at 32bpp.) I'm having lots of color and visual problems with x11vnc and/or vncviewer. What's up? First off, depth 24 at 24bpp (bpp=bits-per-pixel) is fairly uncommon and can cause problems in general. It also can be slower than depth 24 at 32bpp. You might want to switch to 32bpp (for XFree86 see the - "-fbbpp 32", DefaultFbBpp, FbBpp and related options). Perhaps you + "-fbbpp 32", DefaultFbBpp, FbBpp and related options.) Perhaps you have 24bpp because the video memory of the machine is low and the screen wouldn't fit in video RAM at 32bpp. For this case depth 16 at 16bpp might be an acceptable option. In any event x11vnc should handle depth 24 at 24bpp (although performance may be slower, and you may need to use the ZRLE encoding - instead of Tight). There are some caveats involving the viewer + instead of Tight.) There are some caveats involving the viewer however: The RealVNC Unix viewer cannot handle 24bpp from the server, it will @@ -3185,7 +3195,7 @@ TrueColor defdepth 24 correctly with the Tight encoding. The colors and screen ultimately get messed up. So you have to use a different encoding with the TightVNC vncviewer, try "zlib", "hextile", or one of the other - encodings (e.g. vncviewer -encodings "zlib hextile" ...). I have not + encodings (e.g. vncviewer -encodings "zlib hextile" ....) I have not checked the TightVNC or UltraVNC Windows viewers. It appears the older RealVNC Unix viewers (e.g. 3.3.3 and 3.3.7) can @@ -3220,7 +3230,7 @@ TrueColor defdepth 24 machine. Use the [221]-display option to point the display to that of the Xterminal (you'll of course need basic X11 permission to do that) and finally supply the [222]-noshm option (this enables the polling - over the network). + over the network.) If the Xterminal's X display is open to the network for connections, you might use something like "-display xterm123:0". If you are trying @@ -3230,7 +3240,7 @@ TrueColor defdepth 24 permissions need to allow the connection. The response will likely be sluggish (maybe only one "frame" per - second). This mode is not recommended except for "quick checks" of + second.) This mode is not recommended except for "quick checks" of hard to get to X servers. Use something like "-wait 150" to cut down on the polling rate. You may also need [223]-flipbyteorder if the colors get messed up due to endian byte order differences. @@ -3256,7 +3266,7 @@ TrueColor defdepth 24 copied to the Xterminal. If $HOME/.Xauthority is exported via NFS (this is insecure of course, but has been going on for decades), then x11vnc can simply pick it up via NFS (you may need to use the - [224]-auth option to point to the correct file). Other options include + [224]-auth option to point to the correct file.) Other options include copying the auth file using scp, or something like: central-server> xauth nextract - xterm123:0 | ssh xterm123 xauth nmerge - @@ -3280,7 +3290,7 @@ TrueColor defdepth 24 to set something up. It can be done!!! Some Xterminal projects have actually enabled "run locally" facilities for the running of an occasional app more efficiently locally on the Xterminal box (e.g. - realplayer). + realplayer.) Not recommended, but as a last resort, you could have x11vnc [226]poll the Xterminal Display over the network. For this you would run a @@ -3305,14 +3315,14 @@ TrueColor defdepth 24 drawing is done more inefficiently over the network. Something to consider, especially on a busy network. (BTW, this has all of the above permission, etc, problems: both vncviewer and x11vnc are X - client apps desired to be run on the Xterminal box). + client apps desired to be run on the Xterminal box.) [Sun Rays] Q-30: I'm having trouble using x11vnc with my Sun Ray session. The [227]Sun Ray technology is a bit like "VNC done in hardware" (the - Sun Ray terminal device, DTU, playing the role of the vncviewer). + Sun Ray terminal device, DTU, playing the role of the vncviewer.) Completely independent of that, the SunRay user's session is still an X server that speaks the X11 protocol and so x11vnc simply talks to the X server part to export the SunRay desktop to any place in the @@ -3336,7 +3346,7 @@ TrueColor defdepth 24 you cannot use the remote control, then you will have to kill the x11vnc process This can be done via: "kill NNNNN" (where NNNNN is the x11vnc process id number found from ps(1)), or "pkill x11vnc", or - "killall x11vnc" (Linux only). + "killall x11vnc" (Linux only.) If you have not put x11vnc in the background via the [233]-bg option or shell & operator, then simply press Ctrl-C in the shell where @@ -3381,7 +3391,7 @@ TrueColor defdepth 24 You may already have one in $HOME/.vnc/passwd if you have used, say, the vncserver program from the regular RealVNC or TightVNC packages - (i.e. launching the Xvnc server). Otherwise, you could use the + (i.e. launching the Xvnc server.) Otherwise, you could use the vncpasswd(1) program from those packages. As of Jun/2004 x11vnc supports the -storepasswd "pass" "file" @@ -3398,7 +3408,7 @@ TrueColor defdepth 24 you will be prompted for a password to save to ~/.vnc/passwd (your keystrokes when entering the password will not be echoed to the - screen). If you supply one argument, e.g. "x11vnc -storepasswd + screen.) If you supply one argument, e.g. "x11vnc -storepasswd ~/.mypass", the password you are prompted for will be stored in that file. @@ -3408,7 +3418,7 @@ TrueColor defdepth 24 You can use the [244]-usepw option to automatically use any password file you have in ~/.vnc/passwd or ~/.vnc/passwdfile (the latter is - used with the -passwdfile option). + used with the -passwdfile option.) x11vnc -usepw -display :0 ... @@ -3448,13 +3458,13 @@ TrueColor defdepth 24 [247]-passwdfile option to specify a file containing plain text passwords. Presumably this file is readable only by you, and ideally it is located on the machine x11vnc is run on (to avoid being snooped - on over the network). The first line of this file is the full-access + on over the network.) The first line of this file is the full-access password. If there is a second line in the file and it is non-blank, it is taken as the view-only password. (use "__EMPTY__" to supply an - empty one). + empty one.) View-only passwords currently do not work for the [248]-rfbauth - password option (standard VNC password storing mechanism). FWIW, note + password option (standard VNC password storing mechanism.) FWIW, note that although the output (usually placed in $HOME/.vnc/passwd) by the vncpasswd or storepasswd programs (or from x11vnc -storepasswd) looks encrypted they are really just obscured to avoid "casual" password @@ -3501,7 +3511,7 @@ TrueColor defdepth 24 They can be relaxed if you want to provide encryption other than stunnel or [255]-ssl (the constraint is automatically relaxed if SSH_CONNECTION is set and indicates you have ssh-ed in, however the - -localhost requirement is still enforced). + -localhost requirement is still enforced.) The two -unixpw modes have been tested on Linux, Solaris, Mac OS X, HP-UX, Tru64, FreeBSD, OpenBSD, and NetBSD. Additional testing is @@ -3542,7 +3552,7 @@ TrueColor defdepth 24 should not be trusted over the network, but on the local machine it should be accurate: otherwise root has been compromised and so there are more serious problems! Unfortunately recent Linux distros seem to - provide a random string (MD5 hash?) instead of the username). An + provide a random string (MD5 hash?) instead of the username.) An example script passed in via -accept scriptname that deduces the Unix username and limits who can be accepted might look something like this: @@ -3595,7 +3605,7 @@ exit 1 # reject it For "[266]-passwdfile cmd:command" the command is run and it returns a password list (like a password file, see the [267]-passwdfile - read:filename mode). Perhaps a dynamic, one-time password is retrieved + read:filename mode.) Perhaps a dynamic, one-time password is retrieved from a server this way. For "[268]-passwdfile custom:command" one gets complete control over @@ -3686,7 +3696,7 @@ exit 1 # reject it "[281]-allow host1,..." option to allow only specific hosts in. This option is useful if you want to insure that no one can even begin - a dialog with x11vnc from untrusted network interfaces (e.g. ppp0). + a dialog with x11vnc from untrusted network interfaces (e.g. ppp0.) The option [282]-localhost now implies "-listen localhost" since that is what most people expect it to do. @@ -3697,7 +3707,7 @@ exit 1 # reject it To do this specify "[283]-allow localhost". Unlike [284]-localhost this will leave x11vnc listening on all interfaces (but of course only - allowing in local connections, e.g. ssh redirs). Then you can later + allowing in local connections, e.g. ssh redirs.) Then you can later run "x11vnc -R allowonce:somehost" or use to gui to permit a one-shot connection from a remote host. @@ -3724,10 +3734,10 @@ exit 1 # reject it Yes, look at the "[286]-accept command" option, it allows you to specify an external command that is run for each new client. (use - quotes around the command if it contains spaces, etc.). If the - external command returns 0 (success) the client is accepted, otherwise - with any other return code the client is rejected. See below how to - also accept clients view-only. + quotes around the command if it contains spaces, etc.) If the external + command returns 0 (success) the client is accepted, otherwise with any + other return code the client is rejected. See below how to also accept + clients view-only. The external command will have the RFB_CLIENT_IP environment variable set to the client's numerical IP address, RFB_CLIENT_PORT its port @@ -3748,9 +3758,9 @@ exit 1 # reject it The popup window times out after 120 seconds, to change this behavior use "-accept popup:N" where N is the number of seconds (use 0 for no - timeout). More tricks: "-accept popupmouse" will only take mouse click + timeout.) More tricks: "-accept popupmouse" will only take mouse click responses, while "-accept popupkey" will only take keystroke responses - (popup takes both). After any of the 3 popup keywords you can supply a + (popup takes both.) After any of the 3 popup keywords you can supply a position of the window: +N+M, (the default is to center the window) e.g. -accept popupmouse+10+10. @@ -3766,12 +3776,12 @@ exit 1 # reject it associates the three actions: yes(accept), no(reject), and view(accept-view-only), with the numerical return (i.e. exit()) codes. Use "*" instead of a number to set the default action (e.g. in case - the external command returns an unexpected return code). + the external command returns an unexpected return code.) Here is an example -accept script called accept_or_lock. It uses xmessage and xlock (replace with your screen lock command, maybe it is "xscreensaver-command -lock", or kdesktop_lock, or "dtaction - LockDisplay"). It will prompt the user at the X display whether to + LockDisplay".) It will prompt the user at the X display whether to accept, reject, or accept view-only the client, but if the prompt times out after 60 seconds the screen is locked and the VNC client is accepted. This allows the remote access when no one is at the display. @@ -3780,7 +3790,7 @@ exit 1 # reject it # accept_or_lock: prompt user at X display whether to accept an incoming # VNC connection. If timeout expires, screen is locked # and the VNC viewer is accepted (allows remote access -# when no one is sitting at the display). +# when no one is sitting at the display.) # # usage: x11vnc ... -forever -accept 'yes:0,no:*,view:4 accept_or_lock' # @@ -3811,12 +3821,12 @@ exit 1 command" option. This is for the user's convenience only: the return code of the command is not interpreted by x11vnc. The same environment variables are set as in "-accept command" (except that RFB_MODE will - be "gone"). + be "gone".) As of Jan/2006 the "[291]-afteraccept command" option will run the command only after the VNC client has been accepted and authenticated. Like -gone the return code is not interpreted. RFB_MODE will be - "afteraccept"). + "afteraccept".) Q-46: I start x11vnc as root because it is launched via inetd(8) or a @@ -3836,7 +3846,7 @@ exit 1 Q-47: I use a screen-lock when I leave my workstation (e.g. - xscreensaver or xlock). When I remotely access my workstation desktop + xscreensaver or xlock.) When I remotely access my workstation desktop via x11vnc I can unlock the desktop fine, but I am worried people will see my activities on the physical monitor. What can I do to prevent this, or at least make it more difficult? @@ -3844,7 +3854,7 @@ exit 1 Probably most work environments would respect your privacy if you powered off the monitor. Also remember if people have physical access to your workstation they basically can do anything they want with it - (e.g. install a backdoor for later use, etc). + (e.g. install a backdoor for later use, etc.) In any event, as of Jun/2004 there is an experimental utility to make it more difficult for nosey people to see your x11vnc activities. The @@ -3853,7 +3863,7 @@ exit 1 the display monitor in the DPMS "off" state, if the DPMS state ever changes immediately start up the screen-lock program. The x11vnc user will notice something is happening and think about what to do next - (while the screen is in a locked state). + (while the screen is in a locked state.) This works (or at least has a chance of working) because if the intruder moves the mouse or presses a key on the keyboard, the monitor @@ -3866,7 +3876,7 @@ exit 1 The blockdpy utility is launched by the [294]-accept option and told to exit via the [295]-gone option (the vnc client user should - obviously re-lock the screen before disconnecting!). Instructions can + obviously re-lock the screen before disconnecting!) Instructions can be found in the source code for the utility at the above link. Roughly it is something like this: x11vnc ... -accept "blockdpy -bg -f $HOME/.bdpy" -gone "touch $HOME/.bdpy" @@ -3961,7 +3971,7 @@ exec @ARGV; * Log into the remote machine by pressing 'Open' and supplying username, password, etc. * In that SSH shell, start up x11vnc by typing the command: x11vnc - -display :0 plus any other desired options (e.g. -localhost). + -display :0 plus any other desired options (e.g. -localhost.) * Finally, start up your VNC Viewer in Windows and enter 'localhost:0' as the VNC server. @@ -3989,7 +3999,7 @@ exec @ARGV; "[312]-connect localhost" option to establish the reverse connection. In this case a Remote port redirection (not Local) is needed for port 5500 instead of 5900 (i.e. 'Source port: 5500' and - 'Destination: localhost:5500' for a Remote connection). + 'Destination: localhost:5500' for a Remote connection.) Q-51: How can I tunnel my connection to x11vnc via an encrypted SSL @@ -4000,14 +4010,14 @@ exec @ARGV; provide an encrypted channel without the need for Unix users, passwords, and key passphrases required for ssh (and at the other extreme SSL can also provide a complete signed certificate chain of - trust). On the other hand, since SSH is usually installed everywhere + trust.) On the other hand, since SSH is usually installed everywhere and firewalls often let its port through, ssh is frequently the path - of least resistance (it also nicely manages public keys for you). + of least resistance (it also nicely manages public keys for you.) Update: As of Feb/2006 x11vnc has the options [315]-ssl, [316]-stunnel, and [317]-sslverify to provide integrated SSL schemes. They are discussed [318]in the Next FAQ (you probably want to skip to - it now). + it now.) We include these non-built-in method descriptions below for historical reference. They are handy because can be used to create SSL tunnels to @@ -4056,10 +4066,10 @@ exec @ARGV; easily, and so can the [322]Enhanced TightVNC Viewer (SSVNC) package. Be sure to use a VNC password because unlike ssh by default the - encrypted SSL channel provides no authentication (only privacy). With + encrypted SSL channel provides no authentication (only privacy.) With some extra configuration one could also set up certificates to provide authentication of either or both sides as well (and hence avoid - man-in-the-middle attacks). See the stunnel and openssl documentation + man-in-the-middle attacks.) See the stunnel and openssl documentation and also [323]the key management section for details. stunnel has also been ported to Windows, and there are likely others @@ -4067,7 +4077,7 @@ exec @ARGV; found at the stunnel site and in this [324]article The article also shows the detailed steps to set up all the authentication certificates. (for both server and clients, see also the [325]x11vnc - utilities that do this). The default Windows client setup (no certs) + utilities that do this.) The default Windows client setup (no certs) is simpler and only 4 files are needed in a folder: stunnel.exe, stunnel.conf, libssl32.dll, libeay32.dll. We used an stunnel.conf containing: @@ -4124,13 +4134,12 @@ connect = 5900 SSL VNC Viewers: Regarding VNC viewers that "natively" do SSL unfortunately there do - not seem to be many. UltraVNC has an encryption plugin, but we have - not tried it (it does not seem to be SSL, however the [327]SingleClick - UltraVNC Java Viewer is SSL and is compatible with x11vnc's [328]-ssl - option and stunnel.) Commercial versions of VNC seem to have some SSL - built in, but we haven't tried those either and they probably wouldn't - work since the SSL negotiation is likely embedded in the VNC protocol - unlike our case where it is external. + not seem to be many. The [327]SingleClick UltraVNC Java Viewer is SSL + and is compatible with x11vnc's [328]-ssl option and stunnel.) + Commercial versions of VNC seem to have some SSL-like encryption built + in, but we haven't tried those either and they probably wouldn't work + since their (proprietary) SSL-like negotiation is likely embedded in + the VNC protocol unlike our case where it is external. Note: as of Mar/2006 libvncserver/x11vnc provides a [329]SSL-enabled Java applet that can be served up via the [330]-httpdir or [331]-http @@ -4160,13 +4169,13 @@ connect = 5900 SSL tunnels provide an encrypted channel without the need for Unix users, passwords, and key passphrases required for ssh (and at the other extreme SSL can also provide a complete signed certificate chain - of trust). On the other hand, since SSH is usually installed + of trust.) On the other hand, since SSH is usually installed everywhere and firewalls often let its port through, ssh is frequently the path of least resistance. Built-in SSL x11vnc options: - As of Feb/2006 the x11vnc [339]-ssl option automate the SSL tunnel + As of Feb/2006 the x11vnc [339]-ssl option automates the SSL tunnel creation on the x11vnc server side. An [340]SSL-enabled Java Viewer applet is also provided that can be served via HTTP or HTTPS to automate SSL on the client side. @@ -4174,9 +4183,9 @@ connect = 5900 The [341]-ssl mode uses the [342]www.openssl.org library if available at build time. - The mode requires an SSL certificate and key (i.e. .pem file). These + The mode requires an SSL certificate and key (i.e. .pem file.) These are usually created via the openssl(1) program (in fact in for "-ssl" - (same as "-ssl SAME") it will run openssl for you automatically). So + (same as "-ssl SAVE") it will run openssl for you automatically.) So the SSL is not completely "built-in" since this external tool need to be installed, but at least x11vnc runs it for you automatically. @@ -4219,23 +4228,22 @@ connect = 5900 As seen above, the PEM (privacy enhanced mail) file does not need to be supplied if the openssl(1) command is available in PATH, in that - case a self-signed, temporary certificate good only for the single - x11vnc session is created (this may take a while on very slow - machines). + case a self-signed, certificate good the current and subsequent x11vnc + sessions is created (this may take a while on very slow machines.) In general, the PEM file contains both the Certificate (i.e. public key) and the Private Key. Because of the latter, the file should be protected from being read by untrusted users. The best way to do this is to encrypt the key with a passphrase (note however this requires - supplying the passphrase each time x11vnc is started up). + supplying the passphrase each time x11vnc is started up.) See the discussion on [348]x11vnc Key Management for some utilities provided for creating and managing certificates and keys and even for creating your own Certificate Authority (CA) for signing VNC server and client certificates. This may be done by importing the certificate into Web Browser or Java plugin keystores, or pointing stunnel to it. - The wrapper script [349]ss_vncviewer provides an example on unix - (-verify option). + The wrapper script [349]ss_vncviewer provides an example on unix (see + the -verify option.) Here are some notes on the simpler default (non-CA) operation. To have x11vnc save the generated certificate and key, use the "SAVE" keyword @@ -4244,14 +4252,14 @@ connect = 5900 (this is the same as the default: "-ssl".) This way it will be saved in the default directory ~/.vnc/certs/ as server.crt (the certificate - only) and server.pem (both certificate and private key). This opens up + only) and server.pem (both certificate and private key.) This opens up the possibility of copying the server.crt to machines where the VNC Viewer will be run to enable authenticating the x11vnc SSL VNC server to the clients. When authentication takes place this way (or via the more sophisticated CA signing described [350]here), then Man-In-The-Middle-Attacks are prevented. Otherwise, the SSL encryption only provides protection against passive network traffic "sniffing" - (i.e. you are not protected against M-I-T-M attacks). Nowadays, most + (i.e. you are not protected against M-I-T-M attacks.) Nowadays, most people seem mostly concerned mainly about passive sniffing (and the default x11vnc SSL mode protects against it.) Note that there are hacker tools like dsniff/webmitm and cain that implement SSL @@ -4301,9 +4309,9 @@ connect = 5900 That indicates stunnel is listening on port 5900 for incoming SSL-wrapped VNC connections from viewers. x11vnc is listening for local connections on port 5950 in this case (remote viewers cannot - connect to it directly). For -stunnel to work the stunnel command must + connect to it directly.) For -stunnel to work the stunnel command must be installed on the machine and available in PATH (note stunnel is - often installed in sbin directories rather than bin). Note that the + often installed in sbin directories rather than bin.) Note that the default "-stunnel" by itself creates a temporary cert (as in "-ssl TMP".) @@ -4313,12 +4321,12 @@ connect = 5900 Notes on using "native" VNC Viewers with SSL: There aren't any native VNC Viewers that do SSL (ask your VNC viewer - developer to add the feature). So a tunnel must be setup that you + developer to add the feature.) So a tunnel must be setup that you point the VNC Viewer to. This is often STUNNEL. You can do this - [354]manually, or use the [355]ss_vncviewer script on Unix, or the + [354]manually, or use the [355]ss_vncviewer script on Unix, or our [356]Enhanced TightVNC Viewer (SSVNC) package on Unix, Windows, or MacOSX. See the next section for Java Web browser SSL VNC Viewers (you - only need a Java-enabled Web browser for it to work). + only need a Java-enabled Web browser for it to work.) Notes on the SSL enabled Java VNC Viewer provided in x11vnc classes/ssl/VncViewer.jar: @@ -4340,9 +4348,9 @@ connect = 5900 The Java viewer uses SSL to communicate securely with x11vnc. Note that the applet can optionally also be downloaded into your web - browser via HTTPS (which is HTTP over SSL). This way the HTML page and + browser via HTTPS (which is HTTP over SSL.) This way the HTML page and the Java applet itself are also delivered securely with SSL (as - opposed to only the VNC traffic being encrypted with SSL). + opposed to only the VNC traffic being encrypted with SSL.) For this case the output will be something like this: x11vnc -ssl SAVE -http @@ -4373,10 +4381,10 @@ connect = 5900 The https service provided thru the actual VNC port (5900 in the above example) can occasionally be slow or unreliable (it has to read some - input and try to guess if the connection is VNC or HTTP). If it is + input and try to guess if the connection is VNC or HTTP.) If it is unreliable for you and you still want to serve the Java applet via https, use the [362]-https option to get an additional port dedicated - to https (its URL will also be printed in the output). + to https (its URL will also be printed in the output.) Another possibility is to add the GET applet parameter: https://far-away.east:5900/?GET=1 @@ -4404,20 +4412,20 @@ connect = 5900 Unfortunately, it can be a little tricky getting the SSL VNC Java Viewer working with x11vnc. Here are some tips to getting working the first time (afterwards you can incrementally customize with more - complex settings). + complex settings.) * First try it on the LAN: Do NOT try to have it work the first time going through firewalls, Web proxies, home router port redirections, or Apache portal. Just try a direct connection over your LAN first (if you only have 1 machine and no LAN, just do a - direct connection to the same machine: localhost). If the LAN + direct connection to the same machine: localhost.) If the LAN machine you run x11vnc on has its own host-level firewall (most linux machine come with that on by default), disable it or at least let tcp ports 5800-6000 through. * First try HTTP to download the Java Applet: x11vnc can serve both the Java Applet jar file and VNC out of the same port (both - tunneled through SSL, see below). But it can lead to timing and + tunneled through SSL, see below.) But it can lead to timing and other problems. So first try HTTP instead of HTTPS to download the - Applet jar file (VncViewer.jar). That is to say try + Applet jar file (VncViewer.jar.) That is to say try http://hostname:5800 in your web browser first before trying https://hostname:5900. x11vnc will print out the ports and URLs it is using, so use the HTTP one it prints out. @@ -4440,7 +4448,7 @@ connect = 5900 * No inetd, Please: Even if you intend to deploy via inetd or xinetd eventually, get that working later (and remember do not use something like "-ssl TMP" that creates a new temporary SSL - certificate for every new socket connection). + certificate for every new socket connection.) * Nothing Fancy: Do not try fancy stuff like -svc, -create, -unixpw, "-users unixpw=", "-users sslpeer=", -sslverify, etc. Just get the simplest connection working first and then incrementally add what @@ -4461,9 +4469,9 @@ connect = 5900 (some users do it this way), the main thing is that the VNC traffic is encrypted with SSL. If you are having trouble even with the above baseline test case feel free to contact me (please send the Full - x11vnc output, not just part of it, and the complete x11vnc command - line, and the URL(s) entered in the browser, and anything else you can - think of.) + x11vnc output, not just part of it; the complete x11vnc command line; + the URL(s) entered in the browser; the full Java Console output; and + anything else you can think of.) Next, you can add the features you want one by one testing it still works each time. I suggest first turning on the HTTPS applet download @@ -4473,10 +4481,10 @@ connect = 5900 Next, turn on inetd if you intend to use that (this can be tricky too, be sure to use -oa logfile and inspect it carefully if there are - problems). If you are going to use non-standard ports (e.g. "-rfbport + problems.) If you are going to use non-standard ports (e.g. "-rfbport 443" as root), work on that next. Then enable the firewall, router port redirection channel (you will somehow need to be outside to do - that, maybe test that through another VNC session). + that, maybe test that through another VNC session.) Then, if you plan to use them, enable "fancy stuff" like "-svc" or "-unixpw", etc, etc. Be sure to add a password either "-rfbauth" or @@ -4491,7 +4499,7 @@ connect = 5900 port, you will need to apply the PORT applet parameter to indicate to the applet the Internet facing port number (otherwise by default the internal machine's port, say 5900, is sent and that of course is - rejected at the firewall/router). For example: + rejected at the firewall/router.) For example: https://far-away.east:443/?GET=1&PORT=443 So in this example the user configures his router to redirect @@ -4530,17 +4538,18 @@ connect = 5900 Note that sometimes if you pause too long at one of the above dialogs then x11vnc may exceed a timeout and assume the current socket connection is VNC instead of the HTTPS it actually is (but since you - have paused too long at the dialog the GET request comes too late). + have paused too long at the dialog the GET request comes too late.) Often hitting Reload and going through the dialogs more quickly will let you connect. The Java VM dialogs are the most important ones to NOT linger at. If you see in the x11vnc output a request for - VncViewer.class instead of VncViewer.jar it is too late... you may - need to restart the Web browser to get it to try for the jar again. - You can use the [370]-https option if you want a dedicated port for - HTTPS connections instead of sharing the VNC port. + VncViewer.class instead of VncViewer.jar it is too late... you will + need to completely restart the Web browser to get it to try for the + jar again. You can use the [370]-https option if you want a dedicated + port for HTTPS connections instead of sharing the VNC port. To see example x11vnc output for a successful https://host:5900/ - connection with the Java Applet see [371]This Page. + connection with the Java Applet see [371]This Page. And here is a + newer example [372]including the Java Console output. All of the x11vnc Java Viewer applet parameters are described in the file classes/ssl/README @@ -4551,13 +4560,13 @@ connect = 5900 If you want to use a native VNC Viewer with the SSL enabled x11vnc you will need to run an external SSL tunnel on the Viewer side. There do not seem to be any native SSL VNC Viewers outside of our x11vnc and - [372]SSVNC packages. The basic ideas of doing this were discussed - [373]for external tunnel utilities here. + [373]SSVNC packages. The basic ideas of doing this were discussed + [374]for external tunnel utilities here. - The [374]ss_vncviewer script provided with x11vnc and SSVNC can set up + The [375]ss_vncviewer script provided with x11vnc and SSVNC can set up the stunnel tunnel automatically on unix as long as the stunnel command is installed on the Viewer machine and available in PATH (and - vncviewer too of course). Note that on a Debian based system you will + vncviewer too of course.) Note that on a Debian based system you will need to install the package stunnel4 not stunnel. You can set the environment variables STUNNEL and VNCVIEWERCMD to point to the correct programs if you want to override the defaults. @@ -4580,20 +4589,22 @@ connect = 5900 The third one requires that the x11vnc server authenticate itself to the client against the certificate in the file ./server.crt (e.g. one created by "x11vnc -ssl SAVE" and safely copied to the VNC viewer - machine). The fourth one is for VNC Viewer authentication, it uses - ./client.pem to authenticate itself to x11vnc. One can supply both - -verify and -mycert simultaneously. + machine.) + + The fourth one is for VNC Viewer authentication, it uses ./client.pem + to authenticate itself to x11vnc. One can supply both -verify and + -mycert simultaneously. The fifth one shows that Web proxies can be used if that is the only way to get out of the firewall. If the "double proxy" situation arises - separate the two by commas. See [375]this page for more information on + separate the two by commas. See [376]this page for more information on how Web proxies come into play. - If one uses a Certificate Authority (CA) scheme described [376]here, + If one uses a Certificate Authority (CA) scheme described [377]here, the wrapper script would use the CA cert instead of the server cert: 3') ss_vncviewer -verify ./cacert.crt far-away.east:0 - Update Jul/2006: we now provide an [377]Enhanced TightVNC Viewer + Update Jul/2006: we now provide an [378]Enhanced TightVNC Viewer (SSVNC) package that starts up STUNNEL automatically along with some other features. All binaries (stunnel, vncviewer, and some utilities) are provided in the package. It works on Unix, Mac OS X, and Windows. @@ -4603,12 +4614,12 @@ connect = 5900 tunneling when going through a Web Proxy? The SSL enabled Java VNC Viewer and firewall Proxies: - SSL/https aside, there is a general problem with Firewall Proxies and - Java Applets that open sockets. The applet is downloaded successfully - (through the browser) using http and the proxy, but when the applet - tries to reconnect to the originating host (the only one allowed by - security) it does not use the proxy channel. So it cannot reconnect to - the server the applet came from! + SSL and HTTPS aside, there is a general problem with Firewall Proxies + and Java Applets that open sockets. The applet is downloaded + successfully (through the browser) using HTTP and the proxy, but when + the applet tries to reconnect to the originating host (the only one + allowed by security) it does not use the proxy channel. So it cannot + reconnect to the server the applet came from! We have found a convenient workaround: in the directory where VncViewer.jar resides there is a digitally signed version of the same @@ -4618,9 +4629,9 @@ connect = 5900 You should say "Yes". If you do, the applet will be run in a mode where it can try to determine the firewall proxy host name and port - (it will ask you for them if it cannot find them). This way it can + (it will ask you for them if it cannot find them.) This way it can connect directly to the Proxy and then request the CONNECT method to - be redirected to the originating host (the x11vnc VNC Server). SSL is + be redirected to the originating host (the x11vnc VNC Server.) SSL is then layered over this socket. To do this you should use the proxy.vnc HTML file like via this URL in @@ -4637,7 +4648,7 @@ connect = 5900 port 443 (HTTPS) and 563 (SNEWS) by default. In this case, the only thing to do is run x11vnc on that low port, e.g. "-rfbport 443", (or use a port redirection on, say, a firewall or router port 443 to the - internal machine). + internal machine.) If you do such a redirection to an internal machine and x11vnc is not listening on port 443, you will probably need to edit proxy.vnc. @@ -4656,17 +4667,20 @@ connect = 5900 https://yourmachine.com/proxy.vnc?PORT=443 this is cleaner because it avoids editing the file, but requires more - parameters in the URL. See also the [378]-httpsredir option that will - try to automate this for you. To use the GET [379]trick discussed - above, do: + parameters in the URL. See also the [379]-httpsredir x11vnc option + that will try to automate this for you. To use the GET [380]trick + discussed above, do: https://yourmachine.com/proxy.vnc?GET=1&PORT=443 All of the x11vnc Java Viewer applet parameters are described in the file classes/ssl/README + Here is an example of Java Console and x11vnc output for the [381]Web + proxy case. + - Note that both the [380]ss_vncviewer stunnel Unix wrapper script and - [381]Enhanced TightVNC Viewer (SSVNC) can use Web proxies as well even + Note that both the [382]ss_vncviewer stunnel Unix wrapper script and + [383]Enhanced TightVNC Viewer (SSVNC) can use Web proxies as well even though they do not involve a Web browser. @@ -4674,7 +4688,7 @@ connect = 5900 SSL from the Internet with a Web browser to x11vnc running on their workstations behind a firewall? Yes. You will need to configure apache to forward these connections. - It is discussed [382]here. This provides a clean alternative to the + It is discussed [384]here. This provides a clean alternative to the traditional method where the user uses SSH to log in through the gateway to create the encrypted port redirection to x11vnc running on her desktop. @@ -4682,7 +4696,7 @@ connect = 5900 Q-56: Can I create and use my own SSL Certificate Authority (CA) with x11vnc? - Yes, see [383]this page for how to do this and the utility commands + Yes, see [385]this page for how to do this and the utility commands x11vnc provides to create and manage many types of certificates and private keys. @@ -4701,21 +4715,21 @@ connect = 5900 need to have sufficient permissions to connect to the X display. Here are some ideas: - * Use the description under "Continuously" in the [384]FAQ on x11vnc + * Use the description under "Continuously" in the [386]FAQ on x11vnc and Display Managers - * Use the description in the [385]FAQ on x11vnc and inetd(8) - * Use the description in the [386]FAQ on Unix user logins and + * Use the description in the [387]FAQ on x11vnc and inetd(8) + * Use the description in the [388]FAQ on Unix user logins and inetd(8) * Start x11vnc from your $HOME/.xsession (or $HOME/.xinitrc or autostart script or ...) - * Although less reliable, see the [387]x11vnc_loop rc.local hack + * Although less reliable, see the [389]x11vnc_loop rc.local hack below. The display manager scheme will not be specific to which user has the X session unless a test is specifically put into the display startup - script (often named Xsetup). The inetd(8) scheme may or may not be + script (often named Xsetup.) The inetd(8) scheme may or may not be specific to which user has the X session (and it may not be able to do - all users via the XAUTHORITY permission issues). + all users via the XAUTHORITY permission issues.) The .xsession/.xinitrc scheme is obviously is specific to a particular user and only when they are logged into X. If you do not know what a @@ -4730,20 +4744,20 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg X startup scripts (traditionally .xsession/.xinitrc) may have to be in a different directory or have a different basename. One user recommends the description under 'Running Scripts Automatically' at - [388]this link. + [390]this link. - Firewalls: note all methods will require the host-level [389]firewall + Firewalls: note all methods will require the host-level [391]firewall to be configured to allow connections in on a port. E.g. 5900 (default - VNC port) or 22 (default SSH port for tunnelling VNC). Most systems + VNC port) or 22 (default SSH port for tunnelling VNC.) Most systems these days have firewalls turned on by default, so you will actively have to do something to poke a hole in the firewall at the desired port number. See your system administration tool for Firewall settings - (Yast, Firestarter, etc.). + (Yast, Firestarter, etc.) Q-58: How can I use x11vnc to connect to an X login screen like xdm, GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X - session yet). + session yet.) _________________________________________________________________ One time only: If the X login screen is running and you just want to @@ -4754,13 +4768,13 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg while running x11vnc as root, e.g. for the gnome display manager, gdm: x11vnc -auth /var/gdm/:0.Xauth -display :0 - (the [390]-auth option sets the XAUTHORITY variable for you). + (the [392]-auth option sets the XAUTHORITY variable for you.) There will be a similar thing for xdm using however a different auth directory path (perhaps something like /var/lib/xdm/authdir/authfiles/A:0-XQvaJk for xdm or /var/lib/kdm/A:0-crWk72 (or /var/run/xauth/A:0-qQPftr, etc. etc) for - kdm, where the random characters in the basename will vary). Read your + kdm, where the random characters in the basename will vary.) Read your system docs to find out where the display manager cookie files are kept. @@ -4776,14 +4790,14 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg (or /etc/gdm/gdm.conf, etc.) avoids this. Otherwise, just restart x11vnc and then reconnect your viewer. Other display managers (kdm, etc) may also have a similar problem. One user reports having to alter - "gdm.conf-custom" as well. Update Nov/2008: See also the [391]-reopen + "gdm.conf-custom" as well. Update Nov/2008: See also the [393]-reopen option for another possible workaround. Note: Solaris: For dtlogin in addition to the above sort of trick (BTW, the auth file should be in /var/dt), you'll also need to add something like Dtlogin*grabServer:False to the Xconfig file (/etc/dt/config/Xconfig or /usr/dt/config/Xconfig on Solaris, see - [392]the example at the end of this FAQ). Then restart dtlogin, e.g.: + [394]the example at the end of this FAQ.) Then restart dtlogin, e.g.: /etc/init.d/dtlogin stop; /etc/init.d/dtlogin start or reboot. _________________________________________________________________ @@ -4795,8 +4809,8 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg script. Please consider the security implications of this! The VNC display for - the X session always accessible (but hopefully password protected). - Add [393]-localhost if you only plan to access via a [394]SSH tunnel. + the X session always accessible (but hopefully password protected.) + Add [395]-localhost if you only plan to access via a [396]SSH tunnel. The name of the display manager startup script file depends on desktop used and seem to be: @@ -4827,7 +4841,7 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg -forever -bg where you should customize the exact command to your needs (e.g. - [395]-localhost for SSH tunnel-only access; [396]-ssl SAVE for SSL + [397]-localhost for SSH tunnel-only access; [398]-ssl SAVE for SSL access; etc.) Happy, happy, joy, joy: Note that we do not need to specify -display @@ -4835,12 +4849,12 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg and XAUTHORITY environment variables for the Xsetup script!!! You may also want to force the VNC port with something like "-rfbport - 5900" (or [397]-N) to avoid autoselecting one if 5900 is already + 5900" (or [399]-N) to avoid autoselecting one if 5900 is already taken. _________________________________________________________________ Fedora/gdm: Here is an example of what we did on a vanilla install of - Fedora-C3 (seems to use gdm by default). Add a line like this to + Fedora-C3 (seems to use gdm by default.) Add a line like this to /etc/X11/gdm/Init/:0 /usr/local/bin/x11vnc -rfbauth /etc/x11vnc.passwd -forever -bg -o /var/log/x1 1vnc.log @@ -4849,9 +4863,9 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg etc.) in the [daemon] section: KillInitClients=false - Then restart: /usr/sbin/gdm-restart (or reboot). The + Then restart: /usr/sbin/gdm-restart (or reboot.) The KillInitClients=false setting is important: without it x11vnc will be - killed immediately after the user logs in. Here are [398]full details + killed immediately after the user logs in. Here are [400]full details on how to configure gdm _________________________________________________________________ @@ -4873,13 +4887,13 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg /usr/local/bin/x11vnc -forever -o /var/log/x11vnc.log -bg (tweaked to your local setup and preferences, a password via -rfbauth, - etc. would be a very good idea). + etc. would be a very good idea.) Restart the X server and dtlogin: /etc/init.d/dtlogin stop /etc/init.d/dtlogin start - (or reboot or maybe just restart the X session). + (or reboot or maybe just restart the X session.) _________________________________________________________________ KDM: One user running the kdm display manager reports putting this @@ -4893,22 +4907,22 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg If you do not want to deal with any display manager startup scripts, here is a kludgey script that can be run manually or out of a boot - file like rc.local: [399]x11vnc_loop It will need some local + file like rc.local: [401]x11vnc_loop It will need some local customization before running. Because the XAUTHORITY auth file must be guessed by this script, use of the display manager script method - described above is greatly preferred. There is also the [400]-loop + described above is greatly preferred. There is also the [402]-loop option that does something similar. If the machine is a traditional Xterminal you may want to read - [401]this FAQ. + [403]this FAQ. - Firewalls: note all methods will require the host-level [402]firewall + Firewalls: note all methods will require the host-level [404]firewall to be configured to allow connections in on a port. E.g. 5900 (default - VNC port) or 22 (default SSH port for tunnelling VNC). Most systems + VNC port) or 22 (default SSH port for tunnelling VNC.) Most systems these days have firewalls turned on by default, so you will actively have to do something to poke a hole in the firewall at the desired port number. See your system administration tool for Firewall settings - (Yast, Firestarter, etc.). + (Yast, Firestarter, etc.) Q-59: Can I run x11vnc out of inetd(8)? How about xinetd(8)? @@ -4918,9 +4932,9 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg 5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_sh - where the shell script /usr/local/bin/x11vnc_sh uses the [403]-inetd + where the shell script /usr/local/bin/x11vnc_sh uses the [405]-inetd option and looks something like (you'll need to customize to your - settings). + settings.) #!/bin/sh /usr/local/bin/x11vnc -inetd -display :0 -auth /home/fred/.Xauthority \ -rfbauth /home/fred/.vnc/passwd -o /var/log/x11vnc_sh.log @@ -4928,23 +4942,23 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg Important: Note that you must redirect the standard error output to a log file (e.g. -o logfile) or "2>/dev/null" for proper operation via inetd (otherwise the standard error also goes to the VNC vncviewer, - and that confuses it greatly, causing it to abort). If you do not use + and that confuses it greatly, causing it to abort.) If you do not use a wrapper script as above but rather call x11vnc directly in /etc/inetd.conf and do not redirect stderr to a file, then you must - specify the -q (aka [404]-quiet) option: "/usr/local/bin/x11vnc -q + specify the -q (aka [406]-quiet) option: "/usr/local/bin/x11vnc -q -inetd ...". When you supply both -q and -inet and no "-o logfile" then stderr will automatically be closed (to prevent, e.g. library - stderr messages leaking out to the viewer). The recommended practice + stderr messages leaking out to the viewer.) The recommended practice is to use "-o logfile" to collect the output in a file or wrapper script with "2>logfile" redirection because the errors and warnings printed out are very useful in troubleshooting problems. - Note also the need to set XAUTHORITY via [405]-auth to point to the + Note also the need to set XAUTHORITY via [407]-auth to point to the MIT-COOKIE auth file to get permission to connect to the X display (setting and exporting the XAUTHORITY variable accomplishes the same - thing). See the x11vnc_loop file in the previous question for more + thing.) See the x11vnc_loop file in the previous question for more ideas on what that auth file may be, etc. The scheme described in the - [406]FAQ on Unix user logins and inetd(8) works around the XAUTHORITY + [408]FAQ on Unix user logins and inetd(8) works around the XAUTHORITY issue nicely. Note: On Solaris you cannot have the bare number 5900 in @@ -4956,8 +4970,8 @@ x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg users on the machine. Perhaps /var/log is a better place. Be sure to look at your /etc/hosts.allow and /etc/hosts.deny settings - to limit the machines that can connect to this service (your - desktop!). For the above example with /etc/hosts.allow: + to limit the machines that can connect to this service (your desktop!) + For the above example with /etc/hosts.allow: x11vnc_sh : 123.45.67.89 A really safe way to do things is to limit the above inetd to @@ -5029,9 +5043,9 @@ exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 it automatically? Yes, as of Feb/2007 x11vnc supports mDNS / Zeroconf advertising of its - service via the Avahi client library. Use the option [407]-avahi (same - as [408]-mdns or [409]-zeroconf) to enable it. Depending on your setup - you may need to install [410]Avahi (including the development/build + service via the Avahi client library. Use the option [409]-avahi (same + as [410]-mdns or [411]-zeroconf) to enable it. Depending on your setup + you may need to install [412]Avahi (including the development/build packages), enable the server: avahi-daemon and avahi-dnsconfd, and possibly open up UDP port 5353 on your firewall. @@ -5047,7 +5061,7 @@ exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 It appears SuSE 10.1 comes with avahi (or you can add packages, e.g. avahi-0.6.5-27) but not the development package (you can use the - OpenSuSE avahi-devel rpm). Unfortunately, you may need to disable + OpenSuSE avahi-devel rpm.) Unfortunately, you may need to disable another Zeroconf daemon "/etc/init.d/mdnsd stop", before doing "/etc/init.d/avahi-daemon start" and "/etc/init.d/avahi-dnsconfd start". We also had to comment out the browse-domains line in @@ -5060,36 +5074,36 @@ exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 machine and then connect to it? How about starting an X session if one cannot be found? - The easiest way to do this is via [411]inetd(8) using the [412]-unixpw - and [413]-display WAIT options. The reason inetd(8) makes this easier + The easiest way to do this is via [413]inetd(8) using the [414]-unixpw + and [415]-display WAIT options. The reason inetd(8) makes this easier is that it starts a new x11vnc process for each new user connection. Otherwise a wrapper would have to listen for connections and spawn new - x11vnc's (see [414]this example and also the [415]-loopbg option). + x11vnc's (see [416]this example and also the [417]-loopbg option.) Also with inetd(8) users always connect to a fixed VNC display, say hostname:0, and do not need to memorize a special VNC display number just for their personal use, etc. - Update: Use the [416]-find, [417]-create, [418]-svc, and [419]-xdmsvc + Update: Use the [418]-find, [419]-create, [420]-svc, and [421]-xdmsvc options that are shorthand for common FINDCREATEDISPLAY usage modes (e.g. terminal services) described below. (i.e. just use "-svc" instead of "-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb -unixpw -users unixpw= -ssl SAVE") - The [420]-display WAIT option makes x11vnc wait until a VNC viewer is + The [422]-display WAIT option makes x11vnc wait until a VNC viewer is connected before attaching to the X display. Additionally it can be used to run an external command that returns the DISPLAY and XAUTHORITY data. We provide some useful builtin ones (FINDDISPLAY and FINDCREATEDISPLAY below), but in principle one could supply "-display WAIT:cmd=/path/to/find_display" where the script find_display might - look something like [421]this. + look something like [423]this. A default script somewhat like the above is used under "-display - WAIT:cmd=FINDDISPLAY" (same as [422]-find) (use - "WAIT:cmd=FINDDISPLAY-print" to print out the gnarly script). The + WAIT:cmd=FINDDISPLAY" (same as [424]-find) (use + "WAIT:cmd=FINDDISPLAY-print" to print out the gnarly script.) The format for any such command is that it returns DISPLAY=:disp as the first line and any remaining lines are either XAUTHORITY=file or raw - xauth data (the above example does the latter). If applicable (-unixpw + xauth data (the above example does the latter.) If applicable (-unixpw mode), the program is run as the Unix user name who logged in. On Linux if the virtual terminal is known the program should append @@ -5097,10 +5111,10 @@ exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 Or if you only know the X server process ID and suspect a chvt will be needed append ",XPID=n". - Tip: Note that the [423]-find option is an alias for "-display + Tip: Note that the [425]-find option is an alias for "-display WAIT:cmd=FINDDISPLAY". Use it! - The [424]-unixpw option allows [425]UNIX password logins. It + The [426]-unixpw option allows [427]UNIX password logins. It conveniently knows the Unix username whose X display should be found. Here are a couple /etc/inetd.conf examples for this: 5900 stream tcp nowait nobody /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd @@ -5114,43 +5128,43 @@ xpw= Note the very long lines have been split. An alternative is to use a wrapper script, e.g. /usr/local/bin/x11vnc.sh that has all of the - options. (see also the [426]-svc alias). + options. (see also the [428]-svc alias.) In the first one x11vnc is run as user "nobody" and stays user nobody during the whole session. The permissions of the log files and certs directory will need to be set up to allow "nobody" to use them. In the second one x11vnc is run as root and switches to the user that - logs in due to the "[427]-users unixpw=" option. + logs in due to the "[429]-users unixpw=" option. - Note that [428]SSL is required for this mode because otherwise the + Note that [430]SSL is required for this mode because otherwise the Unix password would be passed in clear text over the network. In general -unixpw is not required for this sort of scheme, but it is convenient because it determines exactly who the Unix user is whose display should be sought. Otherwise the find_display script would have to use some method to work out DISPLAY, XAUTHORITY, etc (perhaps you - use multiple inetd ports and hardwire usernames for different ports). + use multiple inetd ports and hardwire usernames for different ports.) - If you really want to disable the SSL or SSH [429]-localhost + If you really want to disable the SSL or SSH [431]-localhost constraints (this is not recommended unless you really know what you are doing: Unix passwords sent in clear text is a very bad idea...) - read the [430]-unixpw documentation. + read the [432]-unixpw documentation. A inetd(8) scheme for a fixed user that doesn't use SSL or unix passwds could be: /usr/local/bin/x11vnc -inetd -users =fred -find -rfbauth /home/fred/.vnc/passwd -o /var/log/x11vnc.log - The "[431]-users =fred" option will cause x11vnc to switch to user + The "[433]-users =fred" option will cause x11vnc to switch to user fred and then find his X display. A recently (Nov/2006) added extension to FINDDISPLAY is FINDCREATEDISPLAY where if it does not find a display via the FINDDISPLAY method it will create an X server session for the user - (i.e. desktop/terminal server). This is the only time x11vnc actually + (i.e. desktop/terminal server.) This is the only time x11vnc actually tries to start up an X server. By default it will only try to start up - virtual (non-hardware) X servers: first [432]Xdummy and if that is not + virtual (non-hardware) X servers: first [434]Xdummy and if that is not available then Xvfb. Note that Xdummy requires root permission and only works on Linux whereas Xvfb works just about everywhere. @@ -5160,19 +5174,19 @@ xpw= -display WAIT:cmd=FINDCREATEDISPLAY -prog /usr/local/bin/x11vnc Where the very long lines have been split. This will allow direct SSL - (e.g. [433]ss_vncviewer) access and also Java Web browers access via: + (e.g. [435]ss_vncviewer) access and also Java Web browers access via: https://hostname:5900/. - Tip: Note that the [434]-create option is an alias for "-display + Tip: Note that the [436]-create option is an alias for "-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb". - Tip: Note that [435]-svc is a short hand for the long "-ssl SAVE + Tip: Note that [437]-svc is a short hand for the long "-ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY" part. Unlike -create, this alias also sets up SSL encryption and Unix password login. Tip: In addition to the usual unixpw parameters, the user can specify - after his username (following a ":" see [436]-display WAIT for + after his username (following a ":" see [438]-display WAIT for details) for FINDCREATEDISPLAY they can add "geom=WxH" or "geom=WxHxD" to specify the width, height, and optionally the color depth. E.g. "fred:geom=800x600" at the login: prompt. Also if the env. var @@ -5181,12 +5195,12 @@ xpw= You can set the env. var X11VNC_SKIP_DISPLAY to a comma separated list of displays to ignore in the FINDDISPLAY process (to force creation of - new displays in some cases). + new displays in some cases.) If you do not plan on using the Java Web browser applet you can remove the -http (and -prog) option since this will speed up logging-in by a few seconds (x11vnc will not have to wait to see if a connection is - HTTPS or VNC). + HTTPS or VNC.) For reference, xinetd format in the file, say, /etc/xinetd.d/x11vnc: service x11vnc @@ -5209,8 +5223,8 @@ service x11vnc WAIT:cmd=FINDCREATEDISPLAY-X,Xvfb,Xdummy". The "X" one means to try to start up a real, hardware X server, e.g. startx(1) (if there is already a real X server running this may only work on Linux and the - chvt program may [437]need to be run to switch to the correct Linux - virtual terminal). x11vnc will try to run chvt automatically if it can + chvt program may [439]need to be run to switch to the correct Linux + virtual terminal.) x11vnc will try to run chvt automatically if it can determine which VT should be switched to. If you want to present the user with a xdm/gdm/kdm display manager @@ -5221,7 +5235,7 @@ service x11vnc manager (xdm/gdm/kdm) on the same machine, then use "Xvfb.xdmcp" instead of "Xvfb", etc. The user will have to supply his username and password one more time (but he gets to select his desktop - type so that can be useful). For this to work, you will need to + type so that can be useful.) For this to work, you will need to enable localhost XDMCP (udp port 177) for the display manager. This seems to be: @@ -5232,11 +5246,11 @@ service x11vnc Unless you are also providing XDMCP service to xterminals or other machines, make sure that the host access list only allows local connections (the name of this file is often Xaccess and it is usually - setup by default to do just that). Nowadays, host level firewalling + setup by default to do just that.) Nowadays, host level firewalling will also typically block UDP (port 177 for XDMCP) by default effectively limiting the UDP connections to localhost. - Tip: Note that [438]-xdmsvc is a short hand for the long "-ssl SAVE + Tip: Note that [440]-xdmsvc is a short hand for the long "-ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp" part. E.g.: service x11vnc @@ -5252,7 +5266,7 @@ service x11vnc disable = no } - (or "-svc" instead of "-xdmsvc" for no XDMCP). + (or "-svc" instead of "-xdmsvc" for no XDMCP.) Local access: To access your virtual X display locally (i.e. while @@ -5290,7 +5304,7 @@ t:5 Summary: The "-display WAIT:cmd=FINDCREATEDISPLAY" scheme can be used to provide a "desktop service" (i.e. terminal service) on the machine: you always get some desktop there, either a real hardware X server or - a virtual one (depending on how you set things up). So it provides + a virtual one (depending on how you set things up.) So it provides simple "terminal services" based on Unix username and password. The created X server sessions (virtual or real hardware) will remain running after you disconnect the VNC viewer and will be found again on @@ -5303,15 +5317,15 @@ t:5 Q-62: Can I have x11vnc restart itself after it terminates? One could do this in a shell script, but now there is an option - [439]-loop that makes it easier. Of course when x11vnc restarts it + [441]-loop that makes it easier. Of course when x11vnc restarts it needs to have permissions to connect to the (potentially new) X display. This mode could be useful if the X server restarts often. Use e.g. "-loop5000" to sleep 5000 ms between restarts. Also "-loop2000,5" to sleep 2000 ms and only restart 5 times. - One can also use the [440]-loopbg to emulate inetd(8) to some degree, + One can also use the [442]-loopbg to emulate inetd(8) to some degree, where each connected process runs in the background. It could be - combined, say, with the [441]-svc option to provide simple terminal + combined, say, with the [443]-svc option to provide simple terminal services without using inetd(8). @@ -5319,13 +5333,13 @@ t:5 web browser? To have x11vnc serve up a Java VNC viewer applet to any web browsers - that connect to it, run x11vnc with this [442]option: + that connect to it, run x11vnc with this [444]option: -httpdir /path/to/the/java/classes/dir (this directory will contain the files index.vnc and, for example, VncViewer.jar) Note that libvncserver contains the TightVNC Java classes jar file for your convenience. (it is the file - classes/VncViewer.jar in the source tree). + classes/VncViewer.jar in the source tree.) You will see output something like this: 14/05/2004 11:13:56 Autoprobing selected port 5900 @@ -5338,7 +5352,7 @@ t:5 then you can connect to that URL with any Java enabled browser. Feel free to customize the default index.vnc file in the classes directory. - As of May/2005 the [443]-http option will try to guess where the Java + As of May/2005 the [445]-http option will try to guess where the Java classes jar file is by looking in expected locations and ones relative to the x11vnc binary. @@ -5347,7 +5361,7 @@ t:5 either the java or appletviewer commands to run the program. java -cp ./VncViewer.jar VncViewer HOST far-away.east PORT 5900 - Proxies: See the [444]discussion here if the web browser must use a + Proxies: See the [446]discussion here if the web browser must use a web proxy to connect to the internet. It is tricky to get Java applets to work in this case: a signed applet must be used so it can connect to the proxy and ask for the redirection to the VNC server. One way to @@ -5363,36 +5377,36 @@ t:5 As of Mar/2004 x11vnc supports reverse connections. On Unix one starts the VNC viewer in listen mode: "vncviewer -listen" (see your documentation for Windows, etc), and then starts up x11vnc with the - [445]-connect option. To connect immediately at x11vnc startup time + [447]-connect option. To connect immediately at x11vnc startup time use the "-connect host:port" option (use commas for a list of hosts to - connect to). The ":port" is optional (default is VNC listening port is - 5500). + connect to.) The ":port" is optional (default is VNC listening port is + 5500.) If a file is specified instead: -connect /path/to/some/file then that file is checked periodically (about once a second) for new hosts to connect to. - The [446]-remote control option (aka -R) can also be used to do this + The [448]-remote control option (aka -R) can also be used to do this during an active x11vnc session, e.g.: x11vnc -display :0 -R connect:hostname.domain - Use the "[447]-connect_or_exit" option to have x11vnc exit if the + Use the "[449]-connect_or_exit" option to have x11vnc exit if the reverse connection fails. Also, note the "-rfbport 0" option disables TCP listening for connections (potentially useful for reverse - connection mode, assuming you do not want any "forward" connections). + connection mode, assuming you do not want any "forward" connections.) Note that as of Mar/2006 x11vnc requires password authentication for reverse connections as well as for forward ones (assuming password - auth has been enabled, e.g. via -rfbauth, -passwdfile, etc). Many VNC + auth has been enabled, e.g. via -rfbauth, -passwdfile, etc.) Many VNC servers do not require any password for reverse connections. To regain the old behavior supply this option "-env X11VNC_REVERSE_CONNECTION_NO_AUTH=1" to x11vnc. Vncconnect command: To use the vncconnect(1) program (from the core - VNC package at www.realvnc.com) specify the [448]-vncconnect option to - x11vnc (Note: as of Dec/2004 -vncconnect is now the default). + VNC package at www.realvnc.com) specify the [450]-vncconnect option to + x11vnc (Note: as of Dec/2004 -vncconnect is now the default.) vncconnect(1) must be pointed to the same X11 DISPLAY as x11vnc (since - it uses X properties to communicate with x11vnc). If you do not have + it uses X properties to communicate with x11vnc.) If you do not have or do not want to get the vncconnect(1) program, the following script (named "Vncconnect") may work if your xprop(1) supports the -set option: @@ -5408,12 +5422,12 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" proxy or SSH? Yes, as of Oct/2007 x11vnc supports reverse connections through - proxies: use the "[449]-proxy host:port" option. The default is to + proxies: use the "[451]-proxy host:port" option. The default is to assume the proxy is a Web proxy. Note that most Web proxies only allow proxy destination connections to ports 443 (HTTPS) and 563 (SNEWS) and so this might not be too useful unless the proxy has been modified (AllowCONNECT apache setting) or the VNC viewer listens on one of - those ports (or the router does a port redir). A web proxy may also be + those ports (or the router does a port redir.) A web proxy may also be specified via "-proxy http://host:port" For SOCKS4 and SOCKS4a proxies use this format "-proxy @@ -5428,11 +5442,11 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" connections. An experimental mode is "-proxy http://host:port/..." where the URL - (e.g. a CGI script) is retrieved via the GET method. See [450]-proxy + (e.g. a CGI script) is retrieved via the GET method. See [452]-proxy for more info. Another experimental mode is "-proxy ssh://user@host" in which case a - SSH tunnel is used for the proxying. See [451]-proxy for more info. + SSH tunnel is used for the proxying. See [453]-proxy for more info. Up to 3 proxies may be chained together by listing them by commas e.g.: "-proxy http://host1:port1,socks5://host2:port2" in case one @@ -5441,10 +5455,10 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" Q-66: Can I use x11vnc as a replacement for Xvnc? (i.e. not for a real - display, but for a virtual one I keep around). + display, but for a virtual one I keep around.) You can, but you would not be doing this for performance reasons (for - virtual X sessions via VNC, Xvnc should give the fastest response). + virtual X sessions via VNC, Xvnc should give the fastest response.) You may want to do this because Xvnc is buggy and crashes, does not support an X server extension you desire, or you want to take advantage of one of x11vnc's unending number of options and features. @@ -5452,13 +5466,13 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" One way to achieve this is to have a Xvfb(1) virtual framebuffer X server running in the background and have x11vnc attached to it. Another method, faster and more accurate, is to use the "dummy" Device - Driver in XFree86/Xorg (see below). + Driver in XFree86/Xorg (see below.) In either case, one can view this desktop both remotely and also - [452]locally using vncviewer. Make sure vncviewer's "-encodings raw" + [454]locally using vncviewer. Make sure vncviewer's "-encodings raw" is in effect for local viewing (compression seems to slow things down - locally). For local viewing you set up a "bare" window manager that - just starts up vncviewer and nothing else ([453]See how below). + locally.) For local viewing you set up a "bare" window manager that + just starts up vncviewer and nothing else ([455]See how below.) Here is one way to start up Xvfb: xinit -- /usr/X11R6/bin/Xvfb :1 -cc 4 -screen 0 1024x768x16 @@ -5467,30 +5481,30 @@ xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" x11vnc -display :1 ... Then have the remote vncviewer attach to x11vnc's VNC display (e.g. :0 - which is port 5900). + which is port 5900.) The "-cc 4" Xvfb option is to force it to use a TrueColor visual instead of DirectColor (this works around a recent bug in the Xorg - Xvfb server). + Xvfb server.) One good thing about Xvfb is that the virtual framebuffer exists in main memory (rather than in the video hardware), and so x11vnc can "screen scrape" it very efficiently (more than, say, 100X faster than - normal video hardware). + normal video hardware.) - Update Nov/2006: See the [454]FINDCREATEDISPLAY discussion of the - "[455]-display WAIT:cmd=FINDDISPLAY" option where virtual (Xvfb or + Update Nov/2006: See the [456]FINDCREATEDISPLAY discussion of the + "[457]-display WAIT:cmd=FINDDISPLAY" option where virtual (Xvfb or Xdummy, or even real ones by changing an option) X servers are started automatically for new users connecting. This provides a "desktop service" for the machine. You either get your real X session or your virtual (Xvfb/Xdummy) one whenever you connect to the machine - (inetd(8) is a nice way to provide this service). The [456]-find, - [457]-create, [458]-svc, and [459]-xdmsvc aliases can also come in + (inetd(8) is a nice way to provide this service.) The [458]-find, + [459]-create, [460]-svc, and [461]-xdmsvc aliases can also come in handy here. There are some annoyances WRT Xvfb however. The default keyboard mapping seems to be very poor. One should run x11vnc with - [460]-add_keysyms option to have keysyms added automatically. Also, to + [462]-add_keysyms option to have keysyms added automatically. Also, to add the Shift_R and Control_R modifiers something like this is needed: #!/bin/sh xmodmap -e "keycode any = Shift_R" @@ -5502,8 +5516,8 @@ xmodmap -e "keycode any = Alt_R" xmodmap -e "keycode any = Meta_L" xmodmap -e "add Mod1 = Alt_L Alt_R Meta_L" - (note: these are applied automatically in the [461]FINDCREATEDISPLAY - mode of x11vnc). Perhaps the Xvfb options -xkbdb or -xkbmap could be + (note: these are applied automatically in the [463]FINDCREATEDISPLAY + mode of x11vnc.) Perhaps the Xvfb options -xkbdb or -xkbmap could be used to get a better default keyboard mapping... Dummy Driver: A user points out a faster and more accurate method is @@ -5517,11 +5531,11 @@ xmodmap -e "add Mod1 = Alt_L Alt_R Meta_L" The main drawback to this method (besides requiring extra configuration and possibly root permission) is that it also does the - Linux Virtual Console/Terminal (VC/VT) [462]switching even though it - does not need to (since it doesn't use a real framebuffer). There are + Linux Virtual Console/Terminal (VC/VT) [464]switching even though it + does not need to (since it doesn't use a real framebuffer.) There are some "dual headed" (actually multi-headed/multi-user) patches to the X server that turn off the VT usage in the X server. Update: As of - Jul/2005 we have an LD_PRELOAD script [463]Xdummy that allows you to + Jul/2005 we have an LD_PRELOAD script [465]Xdummy that allows you to use a stock (i.e. unpatched) Xorg or XFree86 server with the "dummy" driver and not have any VT switching problems! Currently Xdummy needs to be run as root, but with some luck that may be relaxed in the @@ -5538,7 +5552,7 @@ startx -- /path/to/Xdummy :1 In general, one can use these sorts of schemes to use x11vnc to export other virtual X sessions, say Xnest or even Xvnc itself (useful for - testing x11vnc). + testing x11vnc.) Local access: You use a VNC viewer to access the display remotely; to access your virtual X display locally (i.e. while sitting at the same @@ -5549,7 +5563,7 @@ x11vnc -display :5 -rfbport 5905 -bg vncviewer -geometry +0+0 -encodings raw -passwd $HOME/.vnc/passwd localhost:5 The display numbers (VNC and X) will likely be different (you could - also try [464]-find), and you may not need the -passwd. Recent RealVNC + also try [466]-find), and you may not need the -passwd. Recent RealVNC viewers might be this: #!/bin/sh x11vnc -display :5 -rfbport 5905 -bg @@ -5565,7 +5579,7 @@ t:5 For the general replacement of Xvnc by Xvfb+x11vnc, one user describes - a similar setup he created [465]here. + a similar setup he created [467]here. Q-67: How can I use x11vnc on "headless" machines? Why might I want @@ -5579,22 +5593,22 @@ t:5 An X server can be started on the headless machine (sometimes this requires configuring the X server to not fail if it cannot detect a - keyboard or mouse, see the next paragraph). Then you can export that X - display via x11vnc (e.g. see [466]this FAQ) and access it from + keyboard or mouse, see the next paragraph.) Then you can export that X + display via x11vnc (e.g. see [468]this FAQ) and access it from anywhere on the network via a VNC viewer. Some tips on getting X servers to start on machines without keyboard or mouse: For XFree86/Xorg the Option "AllowMouseOpenFail" "true" "ServerFlags" config file option is useful. On Solaris Xsun the +nkeyboard and +nmouse options are useful (put them in the server - command line args in /etc/dt/config/Xservers). There are patches + command line args in /etc/dt/config/Xservers.) There are patches available for Xsun at lease back to Solaris 8 that support this. See Xserver(1) for more info. Although this usage may sound strange it can be quite useful for a GUI (or other) testing or QA setups: the engineers do not need to walk to lab machines running different hardware, OS's, versions, etc (or have - many different machines in their office). They just connect to the + many different machines in their office.) They just connect to the various test machines over the network via VNC. The advantage to testing this way instead of using Xvnc or even Xvfb is that the test is done using the real X server, fonts, video hardware, etc. that will @@ -5604,10 +5618,10 @@ t:5 cards as it can hold to provide multiple simultaneous access or testing on different kinds of video hardware. - See also the [467]FINDCREATEDISPLAY discussion of the "[468]-display + See also the [469]FINDCREATEDISPLAY discussion of the "[470]-display WAIT:cmd=FINDDISPLAY" option where virtual Xvfb or Xdummy, or real X servers are started automatically for new users connecting. The - [469]-find, [470]-create, [471]-svc, and [472]-xdmsvc aliases can also + [471]-find, [472]-create, [473]-svc, and [474]-xdmsvc aliases can also come in handy here. [Resource Usage and Performance] @@ -5621,7 +5635,7 @@ t:5 Solaris machine using the default of only 100 slots. You (or the owner or root) can clean them out with ipcrm(1). x11vnc tries hard to release its slots, but it, and other programs, are not always able to - (e.g. if kill -9'd). + (e.g. if kill -9'd.) Sometimes x11vnc will notice the problem with shm segments and tries to get by with fewer, only giving a warning like this: @@ -5630,10 +5644,10 @@ t:5 19/03/2004 10:10:58 error creating tile-row shm for len=4 19/03/2004 10:10:58 reverting to single_copytile mode - Here is a shell script [473]shm_clear to list and prompt for removal - of your unattached shm segments (attached ones are skipped). I use it + Here is a shell script [475]shm_clear to list and prompt for removal + of your unattached shm segments (attached ones are skipped.) I use it while debugging x11vnc (I use "shm_clear -y" to assume "yes" for each - prompt). If x11vnc is regularly not cleaning up its shm segments, + prompt.) If x11vnc is regularly not cleaning up its shm segments, please contact me so we can work to improve the situation. Longer term, on Solaris you can put something like this in @@ -5641,7 +5655,7 @@ t:5 set shmsys:shminfo_shmmax = 0x2000000 set shmsys:shminfo_shmmni = 0x1000 - to sweep the problem under the rug (4096 slots). On Linux, examine + to sweep the problem under the rug (4096 slots.) On Linux, examine /proc/sys/kernel/shmmni; you can modify the value by writing to that file. @@ -5664,44 +5678,44 @@ ied) in /etc/system. See the next paragraph for more workarounds. To minimize the number of shm segments used by x11vnc try using the - [474]-onetile option (corresponds to only 3 shm segments used, and - adding -fs 1.0 knocks it down to 2). If you are having much trouble + [476]-onetile option (corresponds to only 3 shm segments used, and + adding -fs 1.0 knocks it down to 2.) If you are having much trouble with shm segments, consider disabling shm completely via the - [475]-noshm option. Performance will be somewhat degraded but when + [477]-noshm option. Performance will be somewhat degraded but when done over local machine sockets it should be acceptable (see an - [476]earlier question discussing -noshm). + [478]earlier question discussing -noshm.) Q-69: How can I make x11vnc use less system resources? - The [477]-nap (now on by default; use -nonap to disable) and - "[478]-wait n" (where n is the sleep between polls in milliseconds, + The [479]-nap (now on by default; use -nonap to disable) and + "[480]-wait n" (where n is the sleep between polls in milliseconds, the default is 30 or so) option are good places to start. In addition, - something like "[479]-sb 15" will cause x11vnc to go into a deep-sleep - mode after 15 seconds of no activity (instead of the default 60). + something like "[481]-sb 15" will cause x11vnc to go into a deep-sleep + mode after 15 seconds of no activity (instead of the default 60.) Reducing the X server bits per pixel depth (e.g. to 16bpp or even 8bpp) will further decrease memory I/O and network I/O. The ShadowFB X server setting will make x11vnc's screen polling less severe. Using - the [480]-onetile option will use less memory and use fewer shared - memory slots (add [481]-fs 1.0 for one less slot). + the [482]-onetile option will use less memory and use fewer shared + memory slots (add [483]-fs 1.0 for one less slot.) Q-70: How can I make x11vnc use MORE system resources? - You can try [482]-threads (note this mode can be unstable and/or + You can try [484]-threads (note this mode can be unstable and/or crash; and as of May/2008 is strongly discouraged, see the option description) or dial down the wait time (e.g. -wait 1) and possibly - dial down [483]-defer as well. Note that if you try to increase the + dial down [485]-defer as well. Note that if you try to increase the "frame rate" too much you can bog down the server end with the extra work it needs to do compressing the framebuffer data, etc. That said, it is possible to "stream" video via x11vnc if the video window is small enough. E.g. a 256x192 xawtv TV capture window (using - the x11vnc [484]-id option) can be streamed over a LAN or wireless at + the x11vnc [486]-id option) can be streamed over a LAN or wireless at a reasonable frame rate. If the graphics card's framebuffer read rate - is [485]faster than normal then the video window size and frame rate - can be much higher. The use of [486]TurboVNC and/or TurboJPEG can make + is [487]faster than normal then the video window size and frame rate + can be much higher. The use of [488]TurboVNC and/or TurboJPEG can make the frame rate somewhat higher still (but most of this hinges on the graphics card's read rate.) @@ -5717,19 +5731,19 @@ ied) (reduces amount of data needed to be polled, compressed, and sent) * Use a smaller desktop size (e.g. 1024x768 instead of 1280x1024) * Make sure the desktop background is a solid color (the background - is resent every time it is re-exposed). Consider using the - [487]-solid [color] option to try to do this automatically. + is resent every time it is re-exposed.) Consider using the + [489]-solid [color] option to try to do this automatically. * Configure your window manager or desktop "theme" to not use fancy images, shading, and gradients for the window decorations, etc. Disable window animations, etc. Maybe your desktop has a "low bandwidth" theme you can easily switch into and out of. Also in Firefox disable eye-candy, e.g.: Edit -> Preferences -> Advanced - -> Use Smooth Scrolling (deselect it). + -> Use Smooth Scrolling (deselect it.) * Avoid small scrolls of large windows using the Arrow keys or scrollbar. Try to use PageUp/PageDown instead. (not so much of a - problem in x11vnc 0.7.2 if [488]-scrollcopyrect is active and - detecting scrolls for the application). - * If the [489]-wireframe option is not available (earlier than + problem in x11vnc 0.7.2 if [490]-scrollcopyrect is active and + detecting scrolls for the application.) + * If the [491]-wireframe option is not available (earlier than x11vnc 0.7.2 or you have disabled it via -nowireframe) then Disable Opaque Moves and Resizes in the window manager/desktop. * However if -wireframe is active (on by default in x11vnc 0.7.2) @@ -5737,10 +5751,10 @@ ied) manager! This seems counter-intuitive, but because x11vnc detects the move/resize events early there is a huge speedup over a slow link when Opaque Moves and Resizes are enabled. (e.g. CopyRect - encoding will be used). + encoding will be used.) * Turn off Anti-aliased fonts on your system, web browser, terminal windows, etc. AA fonts do not compress as well as traditional - fonts (sometimes 10X less). + fonts (sometimes 10X less.) * On Firefox/Mozilla (and anything else) turn off "Smooth Scroll" animations. In Firefox put in the URL "about:config" and set general.smoothScroll to false. @@ -5752,16 +5766,16 @@ ied) noticed. VNC viewer parameters: - * Use a [490]TightVNC enabled viewer! (Actually, RealVNC 4.x viewer + * Use a [492]TightVNC enabled viewer! (Actually, RealVNC 4.x viewer with ZRLE encoding is not too bad either; some claim it is - faster). + faster.) * Make sure the tight (or zrle) encoding is being used (look at vncviewer and x11vnc outputs) * Request 8 bits per pixel using -bgr233 (up to 4X speedup over depth 24 TrueColor (32bpp), but colors will be off) * RealVNC 4.x viewer has some extremely low color modes (only 64 and - even 8 colors). [491]SSVNC does too. The colors are poor, but it - is usually noticeably faster than bgr233 (256 colors). + even 8 colors.) [493]SSVNC does too. The colors are poor, but it + is usually noticeably faster than bgr233 (256 colors.) * Try increasing the TightVNC -compresslevel (compresses more on server side before sending, but uses more CPU) * Try reducing the TightVNC -quality (increases JPEG compression, @@ -5774,39 +5788,39 @@ ied) file. x11vnc parameters: - * Make sure the [492]-wireframe option is active (it should be on by + * Make sure the [494]-wireframe option is active (it should be on by default) and you have Opaque Moves/Resizes Enabled in the window manager. - * Make sure the [493]-scrollcopyrect option is active (it should be - on by default). This detects scrolls in many (but not all) + * Make sure the [495]-scrollcopyrect option is active (it should be + on by default.) This detects scrolls in many (but not all) applications an applies the CopyRect encoding for a big speedup. * Enforce a solid background when VNC viewers are connected via - [494]-solid - * Specify [495]-speeds modem to force the wireframe and + [496]-solid + * Specify [497]-speeds modem to force the wireframe and scrollcopyrect heuristic parameters (and any future ones) to those of a dialup modem connection (or supply the rd,bw,lat numerical - values that characterize your link). + values that characterize your link.) * If wireframe and scrollcopyrect aren't working, try using the more - drastic [496]-nodragging (no screen updates when dragging mouse, + drastic [498]-nodragging (no screen updates when dragging mouse, but sometimes you miss visual feedback) - * Set [497]-fs 1.0 (disables fullscreen updates) - * Try increasing [498]-wait or [499]-defer (reduces the maximum + * Set [499]-fs 1.0 (disables fullscreen updates) + * Try increasing [500]-wait or [501]-defer (reduces the maximum "frame rate", but won't help much for large screen changes) - * Try the [500]-progressive pixelheight mode with the block + * Try the [502]-progressive pixelheight mode with the block pixelheight 100 or so (delays sending vertical blocks since they may change while viewer is receiving earlier ones) - * If you just want to watch one (simple) window use [501]-id (cuts + * If you just want to watch one (simple) window use [503]-id (cuts down extraneous polling and updates, but can be buggy or insufficient) - * Set [502]-nosel (disables all clipboard selection exchange) - * Use [503]-nocursor and [504]-nocursorpos (repainting the remote + * Set [504]-nosel (disables all clipboard selection exchange) + * Use [505]-nocursor and [506]-nocursorpos (repainting the remote cursor position and shape takes resources and round trips) * On very slow links (e.g. <= 28.8) you may need to increase the - [505]-readtimeout n setting if it sometimes takes more than 20sec + [507]-readtimeout n setting if it sometimes takes more than 20sec to paint the full screen, etc. - * Do not use [506]-fixscreen to automatically refresh the whole + * Do not use [508]-fixscreen to automatically refresh the whole screen, tap three Alt_L's then the screen has painting errors - (rare problem). + (rare problem.) Example for the KDE desktop: @@ -5861,23 +5875,23 @@ ied) Yes, as of Mar/2005 x11vnc will use the X DAMAGE extension by default if it is available on the display. This requires libXdamage to be available in the build environment as well (recent Linux distros and - Solaris 10 have it). + Solaris 10 have it.) The DAMAGE extension enables the X server to report changed regions of the screen back to x11vnc. So x11vnc doesn't have to guess where the changes are (by polling every pixel of the entire screen every 2-4 - seconds). The use of X DAMAGE dramatically reduces the load when the - screen is not changing very much (i.e. most of the time). It also + seconds.) The use of X DAMAGE dramatically reduces the load when the + screen is not changing very much (i.e. most of the time.) It also noticeably improves updates, especially for very small changed areas - (e.g. clock ticking, cursor flashing, typing, etc). + (e.g. clock ticking, cursor flashing, typing, etc.) Note that the DAMAGE extension does not speed up the actual reading of pixels from the video card framebuffer memory, by, say, mirroring them - in main memory. So reading the fb is still painfully [507]slow (e.g. + in main memory. So reading the fb is still painfully [509]slow (e.g. 5MB/sec), and so even using X DAMAGE when large changes occur on the screen the bulk of the time is still spent retrieving them. Not ideal, but use of the ShadowFB XFree86/Xorg option speeds up the reading - considerably (at the cost of h/w acceleration). + considerably (at the cost of h/w acceleration.) Unfortunately the current Xorg DAMAGE extension implementation can at times be overly conservative and report very large rectangles as @@ -5885,81 +5899,81 @@ ied) been modified. This behavior is often the fault of the window manager (e.g. it redraws the entire, unseen, frame window underneath the application window when it gains focus), or the application itself - (e.g. does large, unnecessary repaints). + (e.g. does large, unnecessary repaints.) To work around this deficiency, x11vnc currently only trusts small DAMAGE rectangles to contain real damage. The larger rectangles are only used as hints to focus the traditional scanline polling (i.e. if a scanline doesn't intersect a recent DAMAGE rectangle, the scan is - skipped). You can use the "[508]-xd_area A" option to adjust the size + skipped.) You can use the "[510]-xd_area A" option to adjust the size of the trusted DAMAGE rectangles. The default is 20000 pixels (e.g. a - 140x140 square, etc). Use "-xd_area 0" to disable the cutoff and trust + 140x140 square, etc.) Use "-xd_area 0" to disable the cutoff and trust all DAMAGE rectangles. - The option "[509]-xd_mem f" may also be of use in tuning the - algorithm. To disable using DAMAGE entirely use "[510]-noxdamage". + The option "[511]-xd_mem f" may also be of use in tuning the + algorithm. To disable using DAMAGE entirely use "[512]-noxdamage". Q-73: My OpenGL application shows no screen updates unless I supply the -noxdamage option to x11vnc. One user reports in his environment (MythTV using the NVIDIA OpenGL drivers) he gets no updates after the initial screen is drawn unless - he uses the "[511]-noxdamage" option. + he uses the "[513]-noxdamage" option. This seems to be a bug in the X DAMAGE implementation of that driver. You may have to use -noxdamage as well. A way to autodetect this will be tried, probably the best it will do is automatically stop using X DAMAGE. - A developer for [512]MiniMyth reports that the 'alphapulse' tag of the + A developer for [514]MiniMyth reports that the 'alphapulse' tag of the theme G.A.N.T. can also cause problems, and should be avoided when using VNC. - Update: see [513]this FAQ too. + Update: see [515]this FAQ too. Q-74: When I drag windows around with the mouse or scroll up and down things really bog down (unless I do the drag in a single, quick - motion). Is there anything to do to improve things? + motion.) Is there anything to do to improve things? - This problem is primarily due to [514]slow hardware read rates from + This problem is primarily due to [516]slow hardware read rates from video cards: as you scroll or move a large window around the screen changes are much too rapid for x11vnc to keep up them (it can usually only read the video card at about 5-10 MB/sec, so it can take a good fraction of a second to read the changes induce from moving a large window, if this to be done a number of times in succession the window - or scroll appears to "lurch" forward). See the description in the - [515]-pointer_mode option for more info. The next bottleneck is + or scroll appears to "lurch" forward.) See the description in the + [517]-pointer_mode option for more info. The next bottleneck is compressing all of these changes and sending them out to connected viewers, however the VNC protocol is pretty much self-adapting with respect to that (updates are only packaged and sent when viewers ask - for them). + for them.) As of Jan/2004 there are some improvements to libvncserver. The default should now be much better than before and dragging small windows around should no longer be a huge pain. If for some reason these changes make matters worse, you can go back to the old way via - the "[516]-pointer_mode 1" option. + the "[518]-pointer_mode 1" option. - Also added was the [517]-nodragging option that disables all screen + Also added was the [519]-nodragging option that disables all screen updates while dragging with the mouse (i.e. mouse motion with a button - held down). This gives the snappiest response, but might be undesired + held down.) This gives the snappiest response, but might be undesired in some circumstances when you want to see the visual feedback while - dragging (e.g. menu traversal or text selection). + dragging (e.g. menu traversal or text selection.) - As of Dec/2004 the [518]-pointer_mode n option was introduced. n=1 is + As of Dec/2004 the [520]-pointer_mode n option was introduced. n=1 is the original mode, n=2 an improvement, etc.. See the -pointer_mode n help for more info. - Also, in some circumstances the [519]-threads option can improve + Also, in some circumstances the [521]-threads option can improve response considerably. Be forewarned that if more than one vncviewer is connected at the same time then libvncserver may not be thread safe (try to get the viewers to use different VNC encodings, e.g. tight and - ZRLE). This option can be unstable and so as of Feb/2008 it is + ZRLE.) This option can be unstable and so as of Feb/2008 it is disabled by default. Set env. X11VNC_THREADED=1 to re-enable. - As of Apr/2005 two new options (see the [520]wireframe FAQ and - [521]scrollcopyrect FAQ below) provide schemes to sweep this problem + As of Apr/2005 two new options (see the [522]wireframe FAQ and + [523]scrollcopyrect FAQ below) provide schemes to sweep this problem under the rug for window moves or resizes and for some (but not all) window scrolls. These are the preferred way of avoiding the "lurching" problem, contact me if they are not working. Note on SuSE and some @@ -5983,8 +5997,8 @@ EndSection the window move/resize stops, it returns to normal processing: you should only see the window appear in the new position. This spares you from interacting with a "lurching" window between all of the - intermediate steps. BTW the lurching is due to [522]slow video card - read rates (see [523]here too). A displacement, even a small one, of a + intermediate steps. BTW the lurching is due to [524]slow video card + read rates (see [525]here too.) A displacement, even a small one, of a large window requires a non-negligible amount of time, a good fraction of a second, to read in from the hardware framebuffer. @@ -5992,8 +6006,8 @@ EndSection for -wireframe to do any good. The mode is currently on by default because most people are afflicted - with the problem. It can be disabled with the [524]-nowireframe option - (aka -nowf). Why might one want to turn off the wireframing? Since + with the problem. It can be disabled with the [526]-nowireframe option + (aka -nowf.) Why might one want to turn off the wireframing? Since x11vnc is merely guessing when windows are being moved/resized, it may guess poorly for your window-manager or desktop, or even for the way you move the pointer. If your window-manager or desktop already does @@ -6014,12 +6028,12 @@ EndSection worse. First it assumes that the move/resize will occur with a mouse button - pressed, held down and dragged (of course this is only mostly true). + pressed, held down and dragged (of course this is only mostly true.) Next it will only consider a window for wireframing if the mouse pointer is initially "close enough" to the edges of the window frame, e.g. you have grabbed the title bar or a resizer edge (this requirement can be disabled and it also not applied if a modifier key, - e.g. Alt, is pressed). If these are true, it will wait an amount of + e.g. Alt, is pressed.) If these are true, it will wait an amount of time to see if the window starts moving or resizing. If it does, it starts drawing the wireframe "outline" of where the window would be. When the mouse button is released, or a timeout occurs, it goes back @@ -6038,13 +6052,13 @@ EndSection * Maximum time to show a wireframe animation. * Minimum time between sending wireframe outlines. - See the [525]"-wireframe tweaks" option for more details. On a slow + See the [527]"-wireframe tweaks" option for more details. On a slow link, e.g. dialup modem, the parameters may be automatically adjusted for better response. CopyRect encoding: In addition to the above there is the - [526]"-wirecopyrect mode" option. It is also on by default. This + [528]"-wirecopyrect mode" option. It is also on by default. This instructs x11vnc to not only show the wireframe animation, but to also instruct all connected VNC viewers to locally translate the window image data from the original position to the new position on the @@ -6059,7 +6073,7 @@ EndSection only apply the CopyRect if the window is appears to be on the top of the window stack and is not obstructed by other windows; and "always" to always try to apply the CopyRect (obstructed regions are usually - clipped off and not translated). + clipped off and not translated.) Note that some desktops (KDE and xfce) appear to mess with the window stacking in ways that are not yet clear. In these cases x11vnc works @@ -6070,7 +6084,7 @@ EndSection Also, the CopyRect encoding may give incorrect results under -scale (depending on the scale factor the CopyRect operation is often only approximate: the correctly scaled framebuffer will be slightly - different from the translated one). x11vnc will try to push a + different from the translated one.) x11vnc will try to push a "cleanup" update after the CopyRect if -scale is in effect. Use -nowirecopyrect if this or other painting errors are unacceptable. @@ -6081,7 +6095,7 @@ EndSection Another nice idea for a hack! As of May/2005 x11vnc will by default apply heuristics to try to detect if the window that has the input focus is scrolling its contents (but only when x11vnc is feeding user - input, keystroke or pointer, to the X server). So, when detected, + input, keystroke or pointer, to the X server.) So, when detected, scrolls induced by dragging on a scrollbar or by typing (e.g. Up or Down arrows, hitting Return in a terminal window, etc), will show up much more quickly than via the standard x11vnc screen polling update @@ -6092,12 +6106,12 @@ EndSection requiring the image data to be transmitted over the network. For fast links the speedup is primarily due to x11vnc not having to read the scrolled framebuffer data from the X server (recall that reading from - the hardware framebuffer is [527]slow). + the hardware framebuffer is [529]slow.) To do this x11vnc uses the RECORD X extension to snoop the X11 protocol between the X client with the focus window and the X server. This extension is usually present on most X servers (but SuSE disables - it for some reason). On XFree86/Xorg it can be enabled via Load + it for some reason.) On XFree86/Xorg it can be enabled via Load "record" in the Module section of the config file if it isn't already: Section "Module" ... @@ -6111,7 +6125,7 @@ EndSection These catch a lot of scrolls, e.g. in mozilla/firefox and in terminal windows like gnome-terminal and xterm. Unfortunately the toolkits KDE applications use make scroll detection less effective (only rarely are - they detected: i.e. Konqueror and Konsole don't work). An interesting + they detected: i.e. Konqueror and Konsole don't work.) An interesting project, that may be the direction x11vnc takes, is to record all of the X11 protocol from all clients and try to "tee" the stream into a modified Xvfb watching for CopyRect and other VNC speedups. A @@ -6119,11 +6133,11 @@ EndSection the X server display: if one falls too far behind it could become a mess... - The initial implementation of [528]-scrollcopyrect option is useful in + The initial implementation of [530]-scrollcopyrect option is useful in that it detects many scrolls and thus gives a much nicer working - environment (especially when combined with the [529]-wireframe - [530]-wirecopyrect [531]options, which are also on by default; and if - you are willing to enable the ShadowFB things are very fast). The fact + environment (especially when combined with the [531]-wireframe + [532]-wirecopyrect [533]options, which are also on by default; and if + you are willing to enable the ShadowFB things are very fast.) The fact that there aren't long delays or lurches during scrolling is the primary improvement. @@ -6144,7 +6158,7 @@ EndSection did not have time to detect a screen change just before the scroll (most common is the terminal undraws the block cursor before scrolling the text up: in the viewer you temporarily see multiple - block cursors). Another issue is with things like more(1): scroll + block cursors.) Another issue is with things like more(1): scroll detection for 5-6 lines happens nicely, but then it can't keep up and so there is a long pause for the standard polling method to deliver the remaining updates. @@ -6155,10 +6169,10 @@ EndSection One can tap the Alt_L key (Left "Alt" key) 3 times in a row to signal x11vnc to refresh the screen to all viewers. Your VNC-viewer may have its own screen refresh hot-key or button. See - also: [532]-fixscreen + also: [534]-fixscreen * Some applications, notably OpenOffice, do XCopyArea scrolls in weird ways that assume ancestor window clipping is taking place. - See the [533]-scr_skip option for ways to tweak this on a + See the [535]-scr_skip option for ways to tweak this on a per-application basis. * Selecting text while dragging the mouse may be slower, especially if the Button-down event happens near the window's edge. This is @@ -6166,7 +6180,7 @@ EndSection RECORD and has to wait for a timeout to occur before it does the update. * For reasons not yet understood the RECORD extension can stop - responding (and hence scrolls are missed). As a workaround x11vnc + responding (and hence scrolls are missed.) As a workaround x11vnc attempts to reset the RECORD connection every 60 seconds or so. Another workaround is to type 4 Super_L (Left Super/Windows-Flag key) in a row to reset RECORD. Work is in progress to try to fix @@ -6175,7 +6189,7 @@ EndSection because it fails to detect scrolls in it. Sometimes clicking inside the application window or selecting some text in it to force the focus helps. - * When using the [534]-scale option there will be a quick CopyRect + * When using the [536]-scale option there will be a quick CopyRect scroll, but it needs to be followed by a slower "cleanup" update. This is because for a fixed finite screen resolution (e.g. 75 dpi) scaling and copyrect-ing are not exactly independent. Scaling @@ -6188,7 +6202,7 @@ EndSection If you find the -scrollcopyrect behavior too approximate or distracting you can go back to the standard polling-only update method - with the [535]-noscrollcopyrect (or -noscr for short). If you find + with the [537]-noscrollcopyrect (or -noscr for short.) If you find some extremely bad and repeatable behavior for -scrollcopyrect please report a bug. @@ -6213,9 +6227,9 @@ EndSection that pixel data is needed again it does not have to be retransmitted over the network. - As of Dec/2006 in the [536]0.9 development tarball there is an + As of Dec/2006 in the [538]0.9 development tarball there is an experimental client-side caching implementation enabled by the - "[537]-ncache n" option. In fact, during the test period it was on by + "[539]-ncache n" option. In fact, during the test period it was on by default with n set to 10. To disable it use "-noncache". It is a simple scheme where a (very large) lower portion of the @@ -6225,7 +6239,7 @@ EndSection out of the actual display area. It gives an excellent speedup for iconifying/deiconifying and moving windows and re-posting of menus (often it doesn't feel like VNC at all: there is no delay waiting for - the pixel data to fill in). + the pixel data to fill in.) This scheme is nice because it does all of this within the existing VNC protocol, and so it works with all VNC viewers. @@ -6242,17 +6256,17 @@ EndSection there is a bug: you can scroll down in your viewer and see a strange "history" of windows on your desktop. This is working as intended. One will need to try to adjust the size of his VNC Viewer window so the - cache area cannot be seen. [538]SSVNC (see below) can do this + cache area cannot be seen. [540]SSVNC (see below) can do this automatically. At some point LibVNCServer may implement a "rfbFBCrop" pseudoencoding that viewers can use to learn which portion of the framebuffer to actually show to the users (with the hidden part used for caching, or perhaps something else, maybe double buffering or other offscreen - rendering...). + rendering...) The Enhanced TightVNC Viewer (SSVNC) Unix viewer has a nice - [539]-ycrop option to help hide the pixel cache area from view. It + [541]-ycrop option to help hide the pixel cache area from view. It will turn on automatically if the framebuffer appears to be very tall (height more than twice the width), or you can supply the actual value for the height. If the screen is resized by scaling, etc, the ycrop @@ -6283,7 +6297,7 @@ EndSection an additional factor of 2 in memory use. However, even in the smallest usage mode with n equal 2 and - [540]-ncache_no_rootpixmap set (this requires only 2X additional + [542]-ncache_no_rootpixmap set (this requires only 2X additional framebuffer memory) there is still a noticable improvement for many activities, although it is not as dramatic as with, say n equal 12 and rootpixmap (desktop background) caching enabled. @@ -6294,7 +6308,7 @@ EndSection be tuned to use less, or the VNC community will extend the protocol to allow caching and replaying of compressed blobs of data. - Another option to experiment with is "[541]-ncache_cr". By specifying + Another option to experiment with is "[543]-ncache_cr". By specifying it, x11vnc will try to do smooth opaque window moves instead of its wireframe. This can give a very nice effect (note: on Unix the realvnc viewer seems to be smoother than the tightvnc viewer), but can lead to @@ -6306,7 +6320,7 @@ EndSection window. Normally, the wireframe must be sent and this involves compressing and sending the lines that give rise to the moving box effect (note that real framebuffer data is sent to "erase" the white - lines of the box). + lines of the box.) If you experience painting errors you can can tap the Alt_L key (Left "Alt" key) 3 times in a row to signal x11vnc to refresh the screen to @@ -6351,24 +6365,24 @@ EndSection As of Feb/2009 (development tarball) there is an experimental kludge to let you build x11vnc using TurboVNC's modified TightVNC encoding. - [542]TurboVNC is part of the [543]VirtualGL project. It does two main + [544]TurboVNC is part of the [545]VirtualGL project. It does two main things to speed up the TightVNC encoding: * It eliminates bottlenecks, overheads, wait-times in the TightVNC encoding implementation and instead only worries about sending very well (and quickly) compressed JPEG data. * A fast proprietary JPEG implemention is used (Intel IPP on x86) - instead of the usual libjpeg implementation. [544]TurboJPEG is an + instead of the usual libjpeg implementation. [546]TurboJPEG is an interface library, libturbojpeg, provided by the project that achieves this. TurboVNC works very well over LAN and evidently fast Broadband too. When using it with x11vnc in such a situation you may want to dial - down the delays, e.g. "[545]-wait 5" and "[546]-defer 5" (or even a + down the delays, e.g. "[547]-wait 5" and "[548]-defer 5" (or even a smaller setting) to poll and pump things out more quickly. See the instructions in "x11vnc/misc/turbovnc/README" for how to build x11vnc with TurboVNC support. You will also need to download the - [547]TurboJPEG software. + [549]TurboJPEG software. In brief, the steps look like this: cd x11vnc-x.y.z/x11vnc/misc/turbovnc @@ -6380,22 +6394,22 @@ EndSection where you replace "/DIR" with the directory containing libturbojpeg.so you downloaded separately. If it works out well enough TurboVNC support will be integrated into x11vnc and more of its tuning features - will be implemented. Support for TurboVNC in [548]SSVNC viewer has + will be implemented. Support for TurboVNC in [550]SSVNC viewer has been added as an experiment as well. If you try either one, let us know how it went. There also may be some Linux.i686 and Darwin.i386 x11vnc binaries with - TurboVNC support in the [549]misc. bins directory. For other platforms + TurboVNC support in the [551]misc. bins directory. For other platforms you will need to compile yourself. On relatively cheap and old hardware (Althon64 X2 5000+ / GeForce - 6200) x11vnc and [550]SSVNC, both TurboVNC enabled, were able to + 6200) x11vnc and [552]SSVNC, both TurboVNC enabled, were able to sustain 13.5 frames/sec (fps) and 15 Megapixels/sec using the VirtualGL supplied OpenGL benchmark program glxspheres. VirtualGL on - higher-end hardware can sustain [551]20-30 fps with the glxspheres + higher-end hardware can sustain [553]20-30 fps with the glxspheres benchmark. - Potential Slowdown: As we describe [552]elsewhere, unless you use + Potential Slowdown: As we describe [554]elsewhere, unless you use x11vnc with an X server using, say, NVidia proprietary drivers (or a virtual X server like Xvfb or Xdummy, or in ShadowFB mode), then the read rate from the graphics card can be rather slow (e.g. 10 MB/sec) @@ -6435,23 +6449,23 @@ EndSection this is because the cursor shape is often downloaded to the graphics hardware (video card), but I could be mistaken. - A simple kludge is provided by the "[553]-cursor X" option that + A simple kludge is provided by the "[555]-cursor X" option that changes the cursor when the mouse is on the root background (or any - window has the same cursor as the root background). Note that desktops + window has the same cursor as the root background.) Note that desktops like GNOME or KDE often cover up the root background, so this won't - work for those cases. Also see the "[554]-cursor some" option for + work for those cases. Also see the "[556]-cursor some" option for additional kludges. Note that as of Aug/2004 on Solaris using the SUN_OVL overlay extension and IRIX, x11vnc can show the correct mouse cursor when the - [555]-overlay option is supplied. See [556]this FAQ for more info. + [557]-overlay option is supplied. See [558]this FAQ for more info. Also as of Dec/2004 XFIXES X extension support has been added to allow exact extraction of the mouse cursor shape. XFIXES fixes the problem of the cursor-shape being write-only: x11vnc can now query the X server for the current shape and send it back to the connected viewers. XFIXES is available on recent Linux Xorg based distros and - [557]Solaris 10. + [559]Solaris 10. The only XFIXES issue is the handling of alpha channel transparency in cursors. If a cursor has any translucency then in general it must be @@ -6459,7 +6473,7 @@ EndSection situations where the cursor transparency can also handled exactly: when the VNC Viewer requires the cursor shape be drawn into the VNC framebuffer or if you apply a patch to your VNC Viewer to extract - hidden alpha channel data under 32bpp. [558]Details can be found here. + hidden alpha channel data under 32bpp. [560]Details can be found here. Q-80: When using XFIXES cursorshape mode, some of the cursors look @@ -6492,18 +6506,18 @@ EndSection for most cursor themes and you don't have to worry about it. In case it still looks bad for your cursor theme, there are (of - course!) some tunable parameters. The "[559]-alphacut n" option lets + course!) some tunable parameters. The "[561]-alphacut n" option lets you set the threshold "n" (between 0 and 255): cursor pixels with alpha values below n will be considered completely transparent while values equal to or above n will be completely opaque. The default is - 240. The "[560]-alphafrac f" option tries to correct individual + 240. The "[562]-alphafrac f" option tries to correct individual cursors that did not fare well with the default -alphacut value: if a cursor has less than fraction f (between 0.0 and 1.0) of its pixels selected by the default -alphacut, the threshold is lowered until f of its pixels are selected. The default fraction is 0.33. - Finally, there is an option [561]-alpharemove that is useful for - themes where many cursors are light colored (e.g. "whiteglass"). + Finally, there is an option [563]-alpharemove that is useful for + themes where many cursors are light colored (e.g. "whiteglass".) XFIXES returns the cursor data with the RGB values pre-multiplied by the alpha value. If the white cursors look too grey, specify -alpharemove to brighten them by having x11vnc divide out the alpha @@ -6527,13 +6541,13 @@ EndSection channel (i.e. RGBA data) for Rich Cursors. So x11vnc can now send the alpha channel data to libvncserver. However, this data will only be used for VNC clients that do not support the CursorShapeUpdates VNC - extension (or have disabled it). It can be disabled for all clients - with the [562]-nocursorshape x11vnc option. In this case the cursor is + extension (or have disabled it.) It can be disabled for all clients + with the [564]-nocursorshape x11vnc option. In this case the cursor is drawn, correctly blended with the background, into the VNC framebuffer before being sent out to the client. So the alpha blending is done on - the x11vnc side. Use the [563]-noalphablend option to disable this + the x11vnc side. Use the [565]-noalphablend option to disable this behavior (always approximate transparent cursors with opaque RGB - values). + values.) The CursorShapeUpdates VNC extension complicates matters because the cursor shape is sent to the VNC viewers supporting it, and the viewers @@ -6545,17 +6559,17 @@ EndSection viewer to make this work for CursorShapeUpdates under some circumstances. This hack is outside of the VNC protocol. It requires the screens on both sides to be depth 24 at 32bpp (it uses the extra 8 - bits to secretly hide the cursor alpha channel data). Not only does it + bits to secretly hide the cursor alpha channel data.) Not only does it require depth 24 at 32bpp, but it also currently requires the client and server to be of the same endianness (otherwise the hidden alpha data gets reset to zero by a libvncserver translation function; we can - fix this at some point if there is interest). The patch is for the + fix this at some point if there is interest.) The patch is for the TightVNC 1.3dev5 Unix vncviewer and it enables the TightVNC viewer to do the cursor alpha blending locally. The patch code should give an example on how to change the Windows TightVNC viewer to achieve the - same thing (send me the patch if you get that working). + same thing (send me the patch if you get that working.) - This patch is applied to the [564]Enhanced TightVNC Viewer (SSVNC) + This patch is applied to the [566]Enhanced TightVNC Viewer (SSVNC) package we provide. [Mouse Pointer] @@ -6563,9 +6577,9 @@ EndSection Q-82: Why does the mouse arrow just stay in one corner in my vncviewer, whereas my cursor (that does move) is just a dot? - This default takes advantage of a [565]tightvnc extension + This default takes advantage of a [567]tightvnc extension (CursorShapeUpdates) that allows specifying a cursor image shape for - the local VNC viewer. You may disable it with the [566]-nocursor + the local VNC viewer. You may disable it with the [568]-nocursor option to x11vnc if your viewer does not have this extension. Note: as of Aug/2004 this should be fixed: the default for @@ -6579,25 +6593,25 @@ EndSection clients (i.e. passive viewers can see the mouse cursor being moved around by another viewer)? - Use the [567]-cursorpos option when starting x11vnc. A VNC viewer must + Use the [569]-cursorpos option when starting x11vnc. A VNC viewer must support the Cursor Positions Updates for the user to see the mouse - motions (the TightVNC viewers support this). As of Aug/2004 -cursorpos - is the default. See also [568]-nocursorpos and [569]-nocursorshape. + motions (the TightVNC viewers support this.) As of Aug/2004 -cursorpos + is the default. See also [570]-nocursorpos and [571]-nocursorshape. Q-84: Is it possible to swap the mouse buttons (e.g. left-handed operation), or arbitrarily remap them? How about mapping button clicks to keystrokes, e.g. to partially emulate Mouse wheel scrolling? - You can remap the mouse buttons via something like: [570]-buttonmap - 13-31 (or perhaps 12-21). Also, note that xmodmap(1) lets you directly + You can remap the mouse buttons via something like: [572]-buttonmap + 13-31 (or perhaps 12-21.) Also, note that xmodmap(1) lets you directly adjust the X server's button mappings, but in some circumstances it might be more desirable to have x11vnc do it. One user had an X server with only one mouse button(!) and was able to map all of the VNC client mouse buttons to it via: -buttonmap 123-111. - Note that the [571]-debug_pointer option prints out much info for + Note that the [573]-debug_pointer option prints out much info for every mouse/pointer event and is handy in solving problems. To map mouse button clicks to keystrokes you can use the alternate @@ -6619,22 +6633,22 @@ EndSection Exactly what keystroke "scrolling" events they should be bound to depends on one's taste. If this method is too approximate, one could - consider not using [572]-buttonmap but rather configuring the X server + consider not using [574]-buttonmap but rather configuring the X server to think it has a mouse with 5 buttons even though the physical mouse - does not. (e.g. 'Option "ZAxisMapping" "4 5"'). + does not. (e.g. 'Option "ZAxisMapping" "4 5"'.) Note that when a keysym-mapped mouse button is clicked down this immediately generates the key-press and key-release events (for each - keysym in turn if the mapping has a sequence of keysyms). When the + keysym in turn if the mapping has a sequence of keysyms.) When the mouse button goes back up nothing is generated. If you include modifier keys like Shift_L instead of key-press immediately followed by key-release the state of the modifier key is - toggled (however the initial state of the modifier key is ignored). So + toggled (however the initial state of the modifier key is ignored.) So to map the right button to type my name 'Karl Runge' I could use this: -buttonmap 3-:Shift_L+k+Shift_L+a+r+l+space+Shift_L+r+Shift_L+u+n+g+e: - (yes, this is getting a little silly). + (yes, this is getting a little silly.) BTW, Coming the other way around, if the machine you are sitting at does not have a mouse wheel, but the remote machine does (or at least @@ -6643,35 +6657,35 @@ EndSection you just tap those two keys to get the mouse wheel scrolls (this is more useful than the Up and Down arrow keys because a mouse wheel - "click" usually gives a multi-line scroll). + "click" usually gives a multi-line scroll.) [Keyboard Issues] Q-85: How can I get my AltGr and Shift modifiers to work between keyboards for different languages? - The option [573]-modtweak should help here. It is a mode that monitors + The option [575]-modtweak should help here. It is a mode that monitors the state of the Shift and AltGr Modifiers and tries to deduce the correct keycode to send, possibly by sending fake modifier key presses and releases in addition to the actual keystroke. Update: As of Jul/2004 -modtweak is now the default (use -nomodtweak - to get the old behavior). This was done because it was noticed on + to get the old behavior.) This was done because it was noticed on newer XFree86 setups even on bland "us" keyboards like "pc104 us" XFree86 included a "ghost" key with both "<" and ">" it. This key does - not exist on the keyboard (see [574]this FAQ for more info). Without + not exist on the keyboard (see [576]this FAQ for more info.) Without -modtweak there was then an ambiguity in the reverse map keysym => keycode, making it so the "<" symbol could not be typed. - Also see the [575]FAQ about the -xkb option for a more powerful method + Also see the [577]FAQ about the -xkb option for a more powerful method of modifier tweaking for use on X servers with the XKEYBOARD extension. When trying to resolve keyboard mapping problems, note that the - [576]-debug_keyboard option prints out much info for every keystroke + [578]-debug_keyboard option prints out much info for every keystroke and so can be useful debugging things. Note that one user had a strange setup and none of the above helped. - His solution was to disable all of the above and use [577]-nomodtweak. + His solution was to disable all of the above and use [579]-nomodtweak. This is the simplest form of keystroke insertion and it actually solved the problem. Try it if the other options don't help. @@ -6682,11 +6696,11 @@ EndSection Does your keyboard have a single key with both "<" and ">" on it? Even if it doesn't, your X server may think your keyboard has such a key (e.g. pc105 in the XF86Config file when it should be something else, - say pc104). + say pc104.) - Short Cut: Try the [578]-xkb or [579]-sloppy_keys options and see if + Short Cut: Try the [580]-xkb or [581]-sloppy_keys options and see if that helps the situation. The discussion below is a bit outdated (e.g. - [580]-modtweak is now the default) but it is useful reference for + [582]-modtweak is now the default) but it is useful reference for various tricks and so is kept. @@ -6719,7 +6733,7 @@ EndSection (If the numerical values are different for your setup, substitute the ones that correspond to your display. The above xmodmap scheme can often be used to work around other ambiguous keysym to keycode - mappings). + mappings.) Alternatively, here are some x11vnc options to try to work around the problem: @@ -6729,25 +6743,25 @@ EndSection -remap less-comma These are convenient in that they do not modify the actual X server - settings. The former ([581]-modtweak) is a mode that monitors the + settings. The former ([583]-modtweak) is a mode that monitors the state of the Shift and AltGr modifiers and tries to deduce the correct keycode sequence to send. Since Jul/2004 -modtweak is now the default. - The latter ([582]-remap less-comma) is an immediate remapping of the + The latter ([584]-remap less-comma) is an immediate remapping of the keysym less to the keysym comma when it comes in from a client (so - when Shift is down the comma press will yield "<"). + when Shift is down the comma press will yield "<".) - See also the [583]FAQ about the -xkb option as a possible workaround + See also the [585]FAQ about the -xkb option as a possible workaround using the XKEYBOARD extension. - Note that the [584]-debug_keyboard option prints out much info for + Note that the [586]-debug_keyboard option prints out much info for every keystroke to aid debugging keyboard problems. Q-87: Extra Character Inserted, E.g.: When I try to type a "<" (i.e. - less than) instead I get "<," (i.e. an extra comma). + less than) instead I get "<," (i.e. an extra comma.) This is likely because you press "Shift" then "<" but then released - the Shift key before releasing the "<". Because of a [585]keymapping + the Shift key before releasing the "<". Because of a [587]keymapping ambiguity the last event "< up" is interpreted as "," because that key unshifted is the comma. @@ -6755,9 +6769,9 @@ EndSection characters: in general it can happen whenever the Shift key is released early. - This should not happen in [586]-xkb mode, because it works hard to + This should not happen in [588]-xkb mode, because it works hard to resolve the ambiguities. If you do not want to use -xkb, try the - option [587]-sloppy_keys to attempt a similar type of algorithm. + option [589]-sloppy_keys to attempt a similar type of algorithm. One user had this problem for Italian and German keyboards with the key containing ":" and "." When he typed ":" he would get an extra "." @@ -6785,16 +6799,16 @@ EndSection In both cases no AltGr is sent to the VNC server, but we know AltGr is needed on the physical international keyboard to type a "@". - This all worked fine with x11vnc running with the [588]-modtweak + This all worked fine with x11vnc running with the [590]-modtweak option (it figures out how to adjust the Modifier keys (Shift or - AltGr) to get the "@"). However it fails under recent versions of - XFree86 (and the X.org fork). These run the XKEYBOARD extension by + AltGr) to get the "@".) However it fails under recent versions of + XFree86 (and the X.org fork.) These run the XKEYBOARD extension by default and make heavy use of it to handle international keyboards. To make a long story short, on these newer XFree86 setups the traditional X keymap lookup x11vnc uses is no longer accurate. x11vnc can't find the keysym "@" anywhere in the keymapping! (even though it - is in the XKEYBOARD extended keymapping). + is in the XKEYBOARD extended keymapping.) How to Solve: As of Jul/2004 x11vnc has two changes: * -modtweak (tweak Modifier keys) is now the default (use @@ -6802,17 +6816,17 @@ EndSection * there is a new option -xkb to use the XKEYBOARD extension API to do the Modifier key tweaking. - The [589]-xkb option seems to fix all of the missing keys: "@", "<", + The [591]-xkb option seems to fix all of the missing keys: "@", "<", ">", etc.: it is recommended that you try it if you have this sort of problem. Let us know if there are any remaining problems (see the next - paragraph for some known problems). If you specify the -debug_keyboard + paragraph for some known problems.) If you specify the -debug_keyboard (aka -dk) option twice you will get a huge amount of keystroke - debugging output (send it along with any problems you report). + debugging output (send it along with any problems you report.) Update: as of Jun/2005 x11vnc will try to automatically enable - [590]-xkb if it appears that would be beneficial (e.g. if it sees any + [592]-xkb if it appears that would be beneficial (e.g. if it sees any of "@", "<", ">", "[" and similar keys are mapped in a way that needs - the -xkb to access them). To disable this automatic check use -noxkb. + the -xkb to access them.) To disable this automatic check use -noxkb. Known problems: * One user had to disable a "ghost" Mode_switch key that was causing @@ -6825,34 +6839,34 @@ EndSection was attached to keycode 93 (no physical key generates this keycode) while ISO_Level3_Shift was attached to keycode 113. The keycode skipping option was used to disable the ghost key: - [591]-skip_keycodes 93 + [593]-skip_keycodes 93 * In implementing -xkb we noticed that some characters were still not getting through, e.g. "~" and "^". This is not really an XKEYBOARD problem. What was happening was the VNC viewer was sending the keysyms asciitilde and asciicircum to x11vnc, but on the X server with the international keyboard those keysyms were not mapped to any keys. So x11vnc had to skip them (Note: as of - May/2005 they are added by default see -add_keysyms below). + May/2005 they are added by default see -add_keysyms below.) The way these characters are typically entered on international keyboards is by "dead" (aka "mute") keys. E.g. to enter "~" at the physical display the keysym dead_tilde is pressed and released (this usually involves holding AltGr down while another key is pressed) and then space is pressed. (this can also be used get characters with the "~" symbol on top, e.g. "ã" by typing "a" - instead of space). + instead of space.) What to do? In general the VNC protocol has not really solved this problem: what should be done if the VNC viewer sends a keysym not recognized by the VNC server side? Workarounds can possibly be - created using the [592]-remap x11vnc option: + created using the [594]-remap x11vnc option: -remap asciitilde-dead_tilde,asciicircum-dead_circumflex etc. Use -remap filename if the list is long. Please send us your workarounds for this problem on your keyboard. Perhaps we can have x11vnc adjust automatically at some point. Also see the - [593]-add_keysyms option in the next paragraph. - Update: for convenience "[594]-remap DEAD" does many of these + [595]-add_keysyms option in the next paragraph. + Update: for convenience "[596]-remap DEAD" does many of these mappings at once. - * To complement the above workaround using the [595]-remap, an - option [596]-add_keysyms was added. This option instructs x11vnc + * To complement the above workaround using the [597]-remap, an + option [598]-add_keysyms was added. This option instructs x11vnc to bind any unknown Keysyms coming in from VNC viewers to unused Keycodes in the X server. This modifies the global state of the X server. When x11vnc exits it removes the extra keymappings it @@ -6871,7 +6885,7 @@ EndSection Short answer: disable key autorepeating by running the command "xset r off" on the Xserver where x11vnc is run (restore via "xset r on") or - use the new (Jul/2004) [597]-norepeat x11vnc option. You will still + use the new (Jul/2004) [599]-norepeat x11vnc option. You will still have autorepeating because that is taken care of on your VNC viewer side. @@ -6888,15 +6902,15 @@ EndSection Even without inducing changes in large regions of the screen, this problem could arise when accessing x11vnc via a dialup modem or - otherwise high latency link (e.g. > 250 ms latency). + otherwise high latency link (e.g. > 250 ms latency.) Look at the output of "xset q" for the "auto repeat delay" setting. Is it low (e.g. < 300 ms)? If you turn off autorepeat completely: "xset r off", does the problem go away? The workaround is to manually apply "xset r off" and "xset r on" as - needed, or to use the [598]-norepeat (which has since Dec/2004 been - made the default). Note that with X server autorepeat turned off the + needed, or to use the [600]-norepeat (which has since Dec/2004 been + made the default.) Note that with X server autorepeat turned off the VNC viewer side of the connection will (nearly always) do its own autorepeating so there is no big loss here, unless someone is also working at the physical display and misses his autorepeating. @@ -6906,7 +6920,7 @@ EndSection keystrokes!! Are you using x11vnc to log in to an X session via display manager? - (as described in [599]this FAQ) If so, x11vnc is starting before your + (as described in [601]this FAQ) If so, x11vnc is starting before your session and it disables autorepeat when you connect, but then after you log in your session startup (GNOME, KDE, ...) could be resetting the autorepeat to be on. Or it could be something inside your desktop @@ -6967,12 +6981,12 @@ EndSection desktop manages these "warps". If the viewer is not notified it cannot know it needs to release the modifiers. - You can also use the [600]-clear_mods option to try to clear all of + You can also use the [602]-clear_mods option to try to clear all of the modifier keys at x11vnc startup. You will still have to be careful that you do not leave the modifier key pressed down during your session. It is difficult to prevent this problem from occurring (short - of using [601]-remap to prevent sending all of the problem modifier - keys, which would make the destkop pretty unusable). + of using [603]-remap to prevent sending all of the problem modifier + keys, which would make the destkop pretty unusable.) During a session these x11vnc remote control commands can also help: x11vnc -R clear_mods @@ -6983,23 +6997,23 @@ EndSection A similar problem can occur if you accidentally press the Caps_Lock or Num_Lock down. When these are locked on the remote side it can sometimes lead to strange desktop behavior (e.g. cannot drag or click - on windows). As above you may not notice this because the lock isn't - down on the local (Viewer) side. See [602]this FAQ on lock keys - problem. These options may help avoid the problem: [603]-skip_lockkeys - and [604]-capslock. See also [605]-clear_all. + on windows.) As above you may not notice this because the lock isn't + down on the local (Viewer) side. See [604]this FAQ on lock keys + problem. These options may help avoid the problem: [605]-skip_lockkeys + and [606]-capslock. See also [607]-clear_all. Q-92: The machine where I run x11vnc has an AltGr key, but the local machine where I run the VNC viewer does not. Is there a way I can map a local unused key to send an AltGr? How about a Compose key as well? - Something like "[606]-remap Super_R-Mode_switch" x11vnc option may + Something like "[608]-remap Super_R-Mode_switch" x11vnc option may work. Note that Super_R is the "Right Windoze(tm) Flaggie" key; you may want to choose another. The -debug_keyboard option comes in handy - in finding keysym names (so does xev(1)). + in finding keysym names (so does xev(1).) For Compose how about "-remap Menu-Multi_key" (note that Multi_key is - the official name for Compose). To do both at the same time: "-remap + the official name for Compose.) To do both at the same time: "-remap Super_R-Mode_switch,Menu-Multi_key" or use "-remap filename" to specify remappings from a file. @@ -7012,11 +7026,11 @@ EndSection Here are a couple ideas. The first one is to simply use xmodmap(1) to adjust the Sun X server. Perhaps xmodmap -e "keysym Alt_L = Meta_L Alt_L" will do the trick. (there are other ways to do it, one user - used: xmodmap -e "keycode 26 = Meta_L" for his setup). + used: xmodmap -e "keycode 26 = Meta_L" for his setup.) Since xmodmap(1) modifies the X server mappings you may not want to do - this (because it affects local work on that machine). Something like - the [607]-remap Alt_L-Meta_L to x11vnc may be sufficient for ones + this (because it affects local work on that machine.) Something like + the [609]-remap Alt_L-Meta_L to x11vnc may be sufficient for ones needs, and does not modify the X server environment. Note that you cannot send Alt_L in this case, maybe -remap Super_L-Meta_L would be a better choice if the Super_L key is typically unused in Unix. @@ -7036,7 +7050,7 @@ EndSection and similar triple mappings (with two in the AltGr/Mode_switch group) of a keysum to a single keycode. - Use the [608]-nomodtweak option as a workaround. You can also use + Use the [610]-nomodtweak option as a workaround. You can also use xmodmap to correct these mappings in the server, e.g.: xmodmap -e "keycode 47 = 3 numbersign" @@ -7050,7 +7064,7 @@ EndSection This can be done directly in some X servers using AccessX and Pointer_EnableKeys, but is a bit awkward. It may be more convenient to - have x11vnc do the remapping. This can be done via the [609]-remap + have x11vnc do the remapping. This can be done via the [611]-remap option using the fake "keysyms" Button1, Button2, etc. as the "to" keys (i.e. the ones after the "-") @@ -7059,7 +7073,7 @@ EndSection button "paste" because (using XFree86/Xorg Emulate3Buttons) you have to click both buttons on the touch pad at the same time. This remapping: - [610]-remap Super_R-Button2 + [612]-remap Super_R-Button2 maps the Super_R "flag" key press to the Button2 click, thereby making X pasting a bit easier. @@ -7078,20 +7092,20 @@ EndSection Caps_Lock in the viewer your local machine goes into the Caps_Lock on state and sends keysym "A" say when you press "a". x11vnc will then fake things up so that Shift is held down to generate "A". The - [611]-skip_lockkeys option should help to accomplish this. For finer - grain control use something like: "[612]-remap Caps_Lock-None". + [613]-skip_lockkeys option should help to accomplish this. For finer + grain control use something like: "[614]-remap Caps_Lock-None". - Also try the [613]-nomodtweak and [614]-capslock options. + Also try the [615]-nomodtweak and [616]-capslock options. Another useful option that turns off any Lock keys on the remote side - at startup and end is the [615]-clear_all option. During a session you + at startup and end is the [617]-clear_all option. During a session you can run these remote control commands to modify the Lock keys: x11vnc -R clear_locks x11vnc -R clear_all the former will try to unset any Lock keys, the latter will do same and also try to make it so no key is pressed down (e.g. "stuck" Alt_L, - etc). + etc.) [Screen Related Issues and Features] Q-97: The remote display is larger (in number of pixels) than the @@ -7104,26 +7118,26 @@ EndSection view. For quick scrolling, also make sure Backing Store is enabled on the machine vncviewer is run on. (XFree86/Xorg disables it by default for some reason, add Option "backingstore" to XF86Config on the - vncviewer side). + vncviewer side.) BTW, contact me if you are having problems with vncviewer in - fullscreen mode with your window manager (i.e. no keyboard response). + fullscreen mode with your window manager (i.e. no keyboard response.) I have a workaround for vncviewer using XGrabServer(). There may also be scaling viewers out there (e.g. TightVNC or UltraVNC on Windows) that automatically shrink or expand the remote framebuffer to fit the local display. Especially for hand-held devices. See also - [616]the next FAQ on x11vnc scaling. + [618]the next FAQ on x11vnc scaling. Q-98: Does x11vnc support server-side framebuffer scaling? (E.g. to - make the desktop smaller). + make the desktop smaller.) As of Jun/2004 x11vnc provides basic server-side scaling. It is a global scaling of the desktop, not a per-client setting. To enable it - use the "[617]-scale fraction" option. "fraction" can either be a + use the "[619]-scale fraction" option. "fraction" can either be a floating point number (e.g. -scale 0.75) or the alternative m/n - fraction notation (e.g. -scale 3/4). Note that if fraction is greater + fraction notation (e.g. -scale 3/4.) Note that if fraction is greater than one the display is magnified. Extra resources (CPU, memory I/O, and memory) are required to do the @@ -7142,16 +7156,16 @@ EndSection features will be recognizable. BTW, "no blending" mode is forced on when scaling 8bpp PseudoColor displays (because blending an indexed colormap is a bad idea and leads to random colors, use :fb to force it - on). + on.) One can also use the ":nb" with an integer scale factor (say "-scale 2:nb") to use x11vnc as a screen magnifier for vision impaired - [618]applications. Since with integer scale factors the framebuffers + [620]applications. Since with integer scale factors the framebuffers become huge and scaling operations time consuming, be sure to use ":nb" for the fastest response. In general for a scaled display if you are using a TightVNC viewer you - may want to turn off jpeg encoding (e.g. vncviewer -nojpeg host:0). + may want to turn off jpeg encoding (e.g. vncviewer -nojpeg host:0.) There appears to be a noise enhancement effect, especially for regions containing font/text: the scaling can introduce some pixel artifacts that evidently causes the tight encoding algorithm to incorrectly @@ -7161,7 +7175,7 @@ EndSection readability of text when using -scale to shrink the display size. Also note that scaling may actually slow down the transfer of text regions because after being scaled they do not compress as well. (this can - often be a significant slowdown, e.g. 10X). + often be a significant slowdown, e.g. 10X.) Another issue is that it appears VNC viewers require the screen width to be a multiple of 4. When scaling x11vnc will round the width to the @@ -7172,33 +7186,33 @@ EndSection If one desires per-client scaling for something like 1:1 from a workstation and 1:2 from a smaller device (e.g. handheld), currently the only option is to run two (or more) x11vnc processes with - different scalings listening on separate ports ([619]-rfbport option, - etc.). + different scalings listening on separate ports ([621]-rfbport option, + etc.) Update: As of May/2006 x11vnc also supports the UltraVNC server-side scaling. This is a per-client scaling by factors 1/2, 1/3, ... and so may be useful for PDA's ("-scale 1/2", etc. will give similar results - except that it applies to all clients). You may need to supply + except that it applies to all clients.) You may need to supply "-rfbversion 3.6" for this to be recognized by UltraVNC viewers. BTW, whenever you run two or more x11vnc's on the same X display and - use the [620]GUI, then to avoid all of the x11vnc's simultaneously - answering the gui you will need to use something like [621]"-connect + use the [622]GUI, then to avoid all of the x11vnc's simultaneously + answering the gui you will need to use something like [623]"-connect file1 -gui ..." with different connect files for each x11vnc you want - to control via the gui (or remote-control). The "-connect file1" usage + to control via the gui (or remote-control.) The "-connect file1" usage gives separate communication channels between a x11vnc process and the gui process. Otherwise they all share the same X property channels: VNC_CONNECT and X11VNC_REMOTE. Update: As of Mar/2005 x11vnc now scales the mouse cursor with the same scale factor as the screen. If you don't want that, use the - [622]"-scale_cursor frac" option to set the cursor scaling to a + [624]"-scale_cursor frac" option to set the cursor scaling to a different factor (e.g. use "-scale_cursor 1" to keep the cursor at its - natural unscaled size). + natural unscaled size.) Q-99: Does x11vnc work with Xinerama? (i.e. multiple monitors joined - together to form one big, single screen). + together to form one big, single screen.) Yes, it should generally work because it simply polls the big effective screen. @@ -7211,30 +7225,30 @@ EndSection them. As of Jun/2008: Use "-clip xinerama0" to clip to the first xinerama - sub-screen (if xinerama is active). xinerama1 for the 2nd sub-screen, + sub-screen (if xinerama is active.) xinerama1 for the 2nd sub-screen, etc. This way you don't need to figure out the WxH+X+Y of the desired xinerama sub-screen. screens are sorted in increasing distance from - the (0,0) origin (I.e. not the Xserver's order). + the (0,0) origin (I.e. not the Xserver's order.) There are a couple potential issues with Xinerama however. If the screen is not rectangular (e.g. 1280x1024 and 1024x768 monitors joined together), then there will be "non-existent" areas on the screen. The X server will return "garbage" image data for these areas and so they - may be distracting to the viewer. The [623]-blackout x11vnc option + may be distracting to the viewer. The [625]-blackout x11vnc option allows you to blacken-out rectangles by manually specifying their WxH+X+Y geometries. If your system has the libXinerama library, the - [624]-xinerama x11vnc option can be used to have it automatically + [626]-xinerama x11vnc option can be used to have it automatically determine the rectangles to be blackened out. (Note on 8bpp - PseudoColor displays the fill color may not be black). Update: - [625]-xinerama is now on by default. + PseudoColor displays the fill color may not be black.) Update: + [627]-xinerama is now on by default. Some users have reported that the mouse does not behave properly for their Xinerama display: i.e. the mouse cannot be moved to all regions - of the large display. If this happens try using the [626]-xwarppointer + of the large display. If this happens try using the [628]-xwarppointer option. This instructs x11vnc to fake mouse pointer motions using the XWarpPointer function instead of the XTestFakeMotionEvent XTEST function. (This may be due to a bug in the X server for XTEST when - Xinerama is enabled). Update: As of Dec/2006 [627]-xwarppointer will + Xinerama is enabled.) Update: As of Dec/2006 [629]-xwarppointer will be applied automatically if Xinerama is detected. To disable use: -noxwarppointer @@ -7257,23 +7271,23 @@ EndSection Note: if you are running on Solaris 8 or earlier you can easily hit up against the maximum of 6 shm segments per process (for Xsun in this case) from running multiple x11vnc processes. You should modify - /etc/system as mentioned in another [628]FAQ to increase the limit. It - is probably also a good idea to run with the [629]-onetile option in + /etc/system as mentioned in another [630]FAQ to increase the limit. It + is probably also a good idea to run with the [631]-onetile option in this case (to limit each x11vnc to 3 shm segments), or even - [630]-noshm to use no shm segments. + [632]-noshm to use no shm segments. Q-101: Can x11vnc show only a portion of the display? (E.g. for a - special purpose application or a very large screen). + special purpose application or a very large screen.) - As of Mar/2005 x11vnc has the "[631]-clip WxH+X+Y" option to select a + As of Mar/2005 x11vnc has the "[633]-clip WxH+X+Y" option to select a rectangle of width W, height H and offset (X, Y). Thus the VNC screen will be the clipped sub-region of the display and be only WxH in size. - One user used -clip to split up a large [632]Xinerama screen into two + One user used -clip to split up a large [634]Xinerama screen into two more managable smaller screens. This also works to view a sub-region of a single application window if - the [633]-id or [634]-sid options are used. The offset is measured + the [635]-id or [636]-sid options are used. The offset is measured from the upper left corner of the selected window. @@ -7282,7 +7296,7 @@ EndSection just seems to crash. As of Dec/2004 x11vnc supports XRANDR. You enable it with the - [635]-xrandr option to make x11vnc monitor XRANDR events and also trap + [637]-xrandr option to make x11vnc monitor XRANDR events and also trap X server errors if the screen change occurred in the middle of an X call like XGetImage. Once it traps the screen change it will create a new framebuffer using the new screen. @@ -7291,10 +7305,10 @@ EndSection (Windows TightVNC viewer and RealVNC 4.0 windows and Unix viewers do) then the viewer will automatically resize. Otherwise, the new framebuffer is fit as best as possible into the original viewer size - (portions of the screen may be clipped, unused, etc). For these - viewers you can try the [636]-padgeom option to make the region big + (portions of the screen may be clipped, unused, etc.) For these + viewers you can try the [638]-padgeom option to make the region big enough to hold all resizes and rotations. We have fixed this problem - for the TightVNC Viewer on Unix: [637]SSVNC + for the TightVNC Viewer on Unix: [639]SSVNC If you specify "-xrandr newfbsize" then vnc viewers that do not support NewFBSize will be disconnected before the resize. If you @@ -7304,9 +7318,9 @@ EndSection Q-103: Independent of any XRANDR, can I have x11vnc rotate and/or reflect the screen that the VNC viewers see? (e.g. for a handheld - whose screen is rotated 90 degrees). + whose screen is rotated 90 degrees.) - As of Jul/2006 there is the [638]-rotate option allow this. E.g's: + As of Jul/2006 there is the [640]-rotate option allow this. E.g's: "-rotate +90", "-rotate -90", "-rotate x", etc. @@ -7319,14 +7333,14 @@ EndSection Q-105: I use Linux Virtual Consoles (VC's) to implement 'Fast User Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those - keystrokes to switch between their sessions). How come the view in a + keystrokes to switch between their sessions.) How come the view in a VNC viewer connecting to x11vnc is either completely black or otherwise all messed up unless the X session x11vnc is attached to is in the active VC? This seems to have to do with how applications (the X server processes in this case) must "play nicely" if they are not on the active VC - (sometimes called VT for virtual terminal). That is, they should not + (sometimes called VT for virtual terminal.) That is, they should not read from the keyboard or mouse or manage the video display unless they have the active VC. Given that it appears the XGetImage() call must ultimately retrieve the framebuffer data from the video hardware @@ -7334,7 +7348,7 @@ EndSection X session had active control of the VC. There does not seem to be an easy way to work around this. Even xwd(1) - doesn't work in this case (try it). Something would need to be done at + doesn't work in this case (try it.) Something would need to be done at a lower level, say in the XFree86/Xorg X server. Also, using the Shadow Framebuffer (a copy of the video framebuffer is kept in main memory) does not appear to fix the problem. @@ -7371,20 +7385,20 @@ EndSection This may be a bug in kdesktop_lock. For now the only workaround is to disable the screensaver. You can try using another one such as - straight xscreensaver (see the instructions [639]here for how to - disable kdesktop_lock). If you have more info on this or see it + straight xscreensaver (see the instructions [641]here for how to + disable kdesktop_lock.) If you have more info on this or see it outside of KDE please let us know. Update: It appears this is due to kdesktop_lock enabling the screen saver when the Monitor is in DPMS low-power state (e.g. standby, - suspend, or off). In Nov/2006 the x11vnc [640]-nodpms option was added + suspend, or off.) In Nov/2006 the x11vnc [642]-nodpms option was added as a workaround. Normally it is a good thing that the monitor powers down (since x11vnc can still poll the framebuffer in this state), but if you experience the kdesktop_lock problem you can specify the "-nodpms" option to keep the Monitor out of low power state while VNC clients are connected. This is basically the same as typing "xset dpms force on" periodically. (if you don't want to do these things just - disable the screensaver). Feel free to file a bug against + disable the screensaver.) Feel free to file a bug against kdesktop_lock with KDE. Q-108: I am running the beryl 3D window manager (or compiz, MythTv, @@ -7393,16 +7407,16 @@ EndSection This appears to be because the 3D OpenGL/GLX hardware screen updates do not get reported via the XDAMAGE mechanism. So this is a bug in - [641]beryl/compiz or XDAMAGE/Xorg or the (possibly 3rd party) video + [643]beryl/compiz or XDAMAGE/Xorg or the (possibly 3rd party) video card driver. - As a workaround apply the [642]-noxdamage option. As of Feb/2007 + As a workaround apply the [644]-noxdamage option. As of Feb/2007 x11vnc will try to autodetect the problem and disable XDAMAGE if is appears to be missing a lot of updates. But if you know you are using - beryl you might as well always supply -noxdamage. Thanks to [643]this + beryl you might as well always supply -noxdamage. Thanks to [645]this user who reported the problem and discovered the workaround. - A developer for [644]MiniMyth reports that the 'alphapulse' tag of the + A developer for [646]MiniMyth reports that the 'alphapulse' tag of the theme G.A.N.T. can also cause problems, and should be avoided when using VNC. @@ -7422,10 +7436,10 @@ EndSection * Fullscreen mode The way VMWare does Fullscreen mode on Linux is to display the Guest - desktop in a separate Virtual Console (e.g. VC 8) (see [645]this FAQ - on VC's for background). Unfortunately, this Fullscreen VC is not an X - server. So x11vnc cannot access it (however, [646]see this discussion - of -rawfb for a possible workaround). x11vnc works fine with "Normal X + desktop in a separate Virtual Console (e.g. VC 8) (see [647]this FAQ + on VC's for background.) Unfortunately, this Fullscreen VC is not an X + server. So x11vnc cannot access it (however, [648]see this discussion + of -rawfb for a possible workaround.) x11vnc works fine with "Normal X application window" and "Quick-Switch mode" because these use X. Update: It appears the in VMWare 5.x the Fullscreen mode is X, so @@ -7445,19 +7459,19 @@ EndSection improve response. One can also cut the display depth (e.g. to 16bpp) in this 2nd X session to improve video performance. This 2nd X session emulates Fullscreen mode to some degree and can be viewed via x11vnc - as long as the VMWare X session [647]is in the active VC. + as long as the VMWare X session [649]is in the active VC. Also note that with a little bit of playing with "xwininfo -all -children" output one can extract the (non-toplevel) window-id of the of the Guest desktop only when VMWare is running as a normal X application. Then one can export just the guest desktop (i.e. without - the VMWare menu buttons) by use of the [648]-id windowid option. The + the VMWare menu buttons) by use of the [650]-id windowid option. The caveats are the X session VMWare is in must be in the active VC and the window must be fully visible, so this mode is not terribly convenient, but could be useful in some circumstances (e.g. running VMWare on a very powerful server machine in a server room that happens to have a video card, (but need not have a monitor, Keyboard or - mouse)). + mouse).) @@ -7467,10 +7481,10 @@ EndSection controlled) via VNC with x11vnc? As of Apr/2005 there is support for this. Two options were added: - "[649]-rawfb string" (to indicate the raw frame buffer device, file, - etc. and its parameters) and "[650]-pipeinput command" (to provide an + "[651]-rawfb string" (to indicate the raw frame buffer device, file, + etc. and its parameters) and "[652]-pipeinput command" (to provide an external program that will inject or otherwise process mouse and - keystroke input). Some useful [651]-pipeinput schemes, VID, CONSOLE, + keystroke input.) Some useful [653]-pipeinput schemes, VID, CONSOLE, and UINPUT, have since been built into x11vnc for convenience. This non-X mode for x11vnc is somewhat experimental because it is so @@ -7483,7 +7497,7 @@ EndSection The format for the -rawfb string is: -rawfb :@xx[-][://][+] - There are also some useful aliases (e.g. "console"). Some examples: + There are also some useful aliases (e.g. "console".) Some examples: -rawfb shm:210337933@800x600x32:ff/ff00/ff0000 -rawfb map:/dev/fb0@1024x768x16 @@ -7507,12 +7521,12 @@ EndSection So the type can be "shm" for shared memory objects, and "map" or "file" for file objects. "map" uses mmap(2) to map the file into memory and is preferred over "file" (that uses the slower lseek(2) - access method). Only use file if map isn't working. BTW, "mmap" is an + access method.) Only use file if map isn't working. BTW, "mmap" is an alias for "map" and if you do not supply a type and the file exists, map is assumed (see the -help output and below for some exceptions to - this). The "snap:" setting applies the [652]-snapfb option with + this.) The "snap:" setting applies the [654]-snapfb option with "file:" type reading (this is useful for exporting webcams or TV tuner - video; see [653]the next FAQ for more info). + video; see [655]the next FAQ for more info.) Also, if the string is of the form "setup:cmd" then cmd is run and the first line of its output retrieved and used as the rawfb string. This @@ -7536,19 +7550,19 @@ EndSection bits per pixel (bpp) of the framebuffer. This is the @WxHxB field. For the case of the Linux framebuffer device, /dev/fb0, the fbset(8) may be of use (but may not always be accurate for what is currently - viewable). In general some guessing may be required, especially for + viewable.) In general some guessing may be required, especially for the bpp. Update: in "-rawfb console" mode x11vnc will use the linuxfb - API to try to guess (it is still not always accurate). Also try + API to try to guess (it is still not always accurate.) Also try "-rawfb vtN" for the N-th Linux text console (aka virtual terminal.) If the number of Bytes Per Line is not WxHxB/8 (i.e. the framebuffer lines are padded) you can specify this information after WxHxB via "-BPL", e.g. @800x600x16-2048 Based on the bpp x11vnc will try to guess the red, green, and blue - masks (these indicate which bits correspond to each color). It if gets + masks (these indicate which bits correspond to each color.) It if gets it wrong you can specify them manually via the optional ":R/G/B" field. E.g. ":0xff0000/0x00ff00/0x0000ff" (this is the default for - 32bpp). + 32bpp.) Finally, the framebuffer may not begin at the beginning of the memory object, so use the optional "+offset" parameter to indicate where the @@ -7557,16 +7571,16 @@ EndSection screen to either shm or a mapped file. The format of these is XWD and so the initial header should be skipped. BTW, since XWD is not strictly RGB the view will only be approximate, but usable. Of course - for the case of Xvfb x11vnc can poll it much better via the [654]X + for the case of Xvfb x11vnc can poll it much better via the [656]X API, but you get the idea. By default in -rawfb mode x11vnc will actually close any X display it happened to open. This is basically to shake out bugs (e.g it will - crash rather than mysteriously interacting with the X display). If you + crash rather than mysteriously interacting with the X display.) If you want x11vnc to keep the X display open while polling the raw framebuffer prefix a "+" sign at the beginning of the string (e.g. +file:/dev/urandom@64x64x8) This could be convenient for keeping the - remote control channel active (it uses X properties). The "-connect + remote control channel active (it uses X properties.) The "-connect /path/to/file" mechanism could also be used for remote control to avoid the X property channel. Rare usage, but if you also supply -noviewonly in this "+" mode then the mouse and keyboard input are @@ -7585,28 +7599,28 @@ minal #2) The Linux console, /dev/fb0, etc needs to have its driver enabled in the kernel. Some of the drivers are video card specific and accelerated. The console is either the Text consoles (usually - tty1-tty6), or X graphical display (usually starting at tty7). In + tty1-tty6), or X graphical display (usually starting at tty7.) In addition to the text console other graphical ones may be viewed and interacted with as well, e.g. DirectFB or SVGAlib apps, VMWare non-X - fullscreen, or [655]Qt-embedded apps (PDAs/Handhelds). By default the + fullscreen, or [657]Qt-embedded apps (PDAs/Handhelds.) By default the pipeinput mechanisms UINPUT and CONSOLE (keystrokes only) are automatically attempted in this mode under "-rawfb console". The Video4Linux Capture device, /dev/video0, etc is either a Webcam or a TV capture device and needs to have its driver enabled in the - kernel. See [656]this FAQ for details. If specified via "-rawfb Video" + kernel. See [658]this FAQ for details. If specified via "-rawfb Video" then the pipeinput method "VID" is applied (it lets you change video - parameters dynamically via keystrokes). + parameters dynamically via keystrokes.) The last two, /dev/urandom and /dev/zero are just for fun, but are also useful in testing. - All of the above [657]-rawfb options are just for viewing the raw + All of the above [659]-rawfb options are just for viewing the raw framebuffer (although some of the aliases do imply keystroke and mouse - pipeinput methods). That may be enough for certain applications of - this feature (e.g. suppose a [658]video camera mapped its framebuffer - into memory and you just wanted to look at it via VNC). + pipeinput methods.) That may be enough for certain applications of + this feature (e.g. suppose a [660]video camera mapped its framebuffer + into memory and you just wanted to look at it via VNC.) To handle the pointer and keyboard input from the viewer users the "-pipeinput cmd" option was added to indicate a helper program to process the user input. The input is streamed to it and looks @@ -7633,7 +7647,7 @@ minal #2) framebuffer. In the libvncserver CVS a simple example program x11vnc/misc/slide.pl is provided that demonstrates a simple jpeg "slideshow" application. Also the builtin "-pipeinput VID" mode does - this for webcams and TV capture devices (/dev/video0). + this for webcams and TV capture devices (/dev/video0.) The -pipeinput program is run with these environment variables set: X11VNC_PID, X11VNC_PROG, X11VNC_CMDLINE, X11VNC_RAWFB_STR to aid its @@ -7643,7 +7657,7 @@ minal #2) keystrokes into the Linux console (e.g. the virtual consoles: /dev/tty1, /dev/tty2, etc) in x11vnc/misc/vcinject.pl. It is based on the vncterm/LinuxVNC.c program also in the libvncserver CVS. So to - view and interact with VC #2 (assuming it is the [659]active VC) one + view and interact with VC #2 (assuming it is the [661]active VC) one can run something like: x11vnc -rawfb map:/dev/fb0@1024x768x16 -pipeinput './vcinject.pl 2' @@ -7665,7 +7679,7 @@ minal #2) If the rawfb string begins with "console" the framebuffer device /dev/fb0 is opened (this requires the appropriate kernel modules to be installed) and so is /dev/tty0. The latter is used to inject - keystrokes (not all are supported, but the basic ones are). You + keystrokes (not all are supported, but the basic ones are.) You will need to be root to inject keystrokes. /dev/tty0 refers to the active VT, to indicate one explicitly, use "console2", etc. using the VT number. @@ -7676,7 +7690,7 @@ minal #2) and mouse input and so it preferred when accessing graphical (e.g. Qt-embedded) linux console apps. See -pipeinput UINPUT below for more information on this mode (you may want to also use the - -nodragging and -cursor none options). Use "console0", etc or + -nodragging and -cursor none options.) Use "console0", etc or -pipeinput CONSOLE to force the /dev/ttyN method. Note you can change VT remotely using the chvt(1) command. @@ -7698,7 +7712,7 @@ minal #2) better to use the more accurate and faster LinuxVNC program. The advantage x11vnc -rawfb might have is that it can allow interaction with a non-text application, e.g. one based on SVGAlib or - [660]Qt-embedded Also, for example the [661]VMWare Fullscreen mode is + [662]Qt-embedded Also, for example the [663]VMWare Fullscreen mode is actually viewable under -rawfb and can be interacted with if uinput is enabled. @@ -7762,9 +7776,9 @@ minal #2) Q-112: Can I export via VNC a Webcam or TV tuner framebuffer using x11vnc? - Yes, this is possible to some degree with the [662]-rawfb option. + Yes, this is possible to some degree with the [664]-rawfb option. There is no X11 involved: snapshots from the video capture device are - used for the screen image data. See the [663]previous FAQ on -rawfb + used for the screen image data. See the [665]previous FAQ on -rawfb for background. For best results, use x11vnc version 0.8.1 or later. Roughly, one would do something like this: @@ -7774,9 +7788,9 @@ minal #2) video device. This is true for video4Linux on Linux kernel 2.6 and later (it won't work for 2.4, you'll need a separate program to snapshot to a file that you point -rawfb to; ask me if it is not clear - what to do). + what to do.) - The "snap:" enforces [664]-snapfb mode which appears to be necessary. + The "snap:" enforces [666]-snapfb mode which appears to be necessary. The read pointer for video capture devices cannot be repositioned (which would be needed for scanline polling), but you can read a full frame of data from the device. @@ -7794,11 +7808,11 @@ minal #2) (e.g. size and brightness) via x11vnc. See the description below. Without Video4Linux you will need to initialize the settings of the video device using something like xawtv or spcaview (and then hope the - settings persist until x11vnc reopens the device). + settings persist until x11vnc reopens the device.) Many video4linux drivers tend to set the framebuffer to be 24bpp (as - opposed to 32bpp). Since this can cause problems with VNC viewers, - etc, the [665]-24to32 option will be automatically imposed when in + opposed to 32bpp.) Since this can cause problems with VNC viewers, + etc, the [667]-24to32 option will be automatically imposed when in 24bpp. Note that by its very nature, video capture involves rapid change in @@ -7806,7 +7820,7 @@ minal #2) wavering in brightness is always happening. This can lead to much network bandwidth consumption for the VNC traffic and also local CPU and I/O resource usage. You may want to experiment with "dialing down" - the framerate via the [666]-wait, [667]-slow_fb, or [668]-defer + the framerate via the [668]-wait, [669]-slow_fb, or [670]-defer options. Decreasing the window size and bpp also helps. @@ -7840,15 +7854,15 @@ minal #2) Related to the bpp above, the pixel format can be set via the fmt=XXX, where XXX can be one of: GREY, HI240, RGB555, RGB565, - RGB24, and RGB32 (with bpp 8, 8, 16, 16, 24, and 32 respectively). - See http://www.linuxtv.org for more info (V4L api). + RGB24, and RGB32 (with bpp 8, 8, 16, 16, 24, and 32 respectively.) + See http://www.linuxtv.org for more info (V4L api.) For TV/rf tuner cards one can set the tuning mode via tun=XXX where XXX can be one of PAL, NTSC, SECAM, or AUTO. One can switch the input channel by the inp=XXX setting, where XXX is the name of the input channel (Television, Composite1, S-Video, - etc). Use the name that is in the information about the device that + etc.) Use the name that is in the information about the device that is printed at startup. For input channels with tuners (e.g. Television) one can change @@ -7895,16 +7909,16 @@ minal #2) format to HI240, RGB565, RGB24, RGB32, RGB555, and GREY respectively. See -rawfb video for details. - See also the [669]-freqtab option to supply your own xawtv channel to + See also the [671]-freqtab option to supply your own xawtv channel to frequency mappings for your country (only ntsc-cable-us is built into - x11vnc). + x11vnc.) Q-113: Can I connect via VNC to a Qt-embedded/Qtopia application running on my handheld or PC using the Linux console framebuffer (i.e. not X11)? - Yes, the basic method for this is the [670]-rawfb scheme where the + Yes, the basic method for this is the [672]-rawfb scheme where the Linux console framebuffer (usually /dev/fb0) is polled and the uinput driver is used to inject keystrokes and mouse input. Often you will just have to type: @@ -7917,14 +7931,14 @@ minal #2) x11vnc -rawfb /dev/fb0@640x480x16 Also, to force usage of the uinput injection method use "-pipeinput - UINPUT". See the [671]-pipeinput description for tunable parameters, + UINPUT". See the [673]-pipeinput description for tunable parameters, etc. One problem with the x11vnc uinput scheme is that it cannot guess the mouse motion "acceleration" used by the windowing application (e.g. - QWS or X11). For X11 and Qt-embedded the acceleration is usually 2 + QWS or X11.) For X11 and Qt-embedded the acceleration is usually 2 (i.e. a dx of 1 from the mouse yields a 2 pixel displacement of the - mouse cursor). The default x11vnc uses is 2, since that is often used. + mouse cursor.) The default x11vnc uses is 2, since that is often used. However for one Qt-embedded system we needed to do: x11vnc -rawfb console -pipeinput UINPUT:accel=4.0 @@ -7933,7 +7947,7 @@ minal #2) Even with the correct acceleration setting there is still some drift (probably because of the mouse threshold where the acceleration kicks in) and so x11vnc needs to reposition the cursor from 0,0 about 5 - times a second. See the [672]-pipeinput UINPUT option for tuning + times a second. See the [674]-pipeinput UINPUT option for tuning parameters that can be set (there are some experimental thresh=N tuning parameters as well) @@ -7945,7 +7959,7 @@ minal #2) environment be sure to run strip(1) on it and also consider configuring with, e.g. "env CPPFLAGS='-DSMALL_FOOTPRINT=1' ./configure ..." to remove rarely used features and large texts (use 2 or 3 - instead of 1 to remove more). Currently (Jul/2006) this can lower the + instead of 1 to remove more.) Currently (Jul/2006) this can lower the size of the x11vnc from 1.1MB to 0.6-0.7MB. The x11vnc uinput method applies to nearly anything on the Linux @@ -7953,7 +7967,7 @@ minal #2) fbcon driver, SVGAlib applications can also be viewed and interacted with. Even a Linux X session can be viewed and interacted with without using X11 (and x11vnc does not have to terminate when the X server - restarts!). The Linux Text consoles (F1-F6) also work. + restarts!) The Linux Text consoles (F1-F6) also work. Note that Qt-embedded supplies its own VNC graphics driver, but it cannot do both the Linux console framebuffer and VNC at the same time, @@ -7968,7 +7982,7 @@ minal #2) Q-114: Now that non-X11 devices can be exported via VNC using x11vnc, can I build it with no dependencies on X11 header files and libraries? - Yes, as of Jul/2006 x11vnc enables building for [673]-rawfb only + Yes, as of Jul/2006 x11vnc enables building for [675]-rawfb only support. Just do something like when building: ./configure --without-x (plus any other flags) make @@ -7984,11 +7998,11 @@ minal #2) Yes, since Nov/2006 in the development tree (x11vnc-0.8.4 tarball) there is support for native Mac OS X Aqua/Quartz displays using the - [674]-rawfb mechanism described above. The mouse and keyboard input is + [676]-rawfb mechanism described above. The mouse and keyboard input is achieved via Mac OS X API's. - So you can use x11vnc as an alternative to [675]OSXvnc (aka Vine - Server), or [676]Apple Remote Desktop (ARD). Perhaps there is some + So you can use x11vnc as an alternative to [677]OSXvnc (aka Vine + Server), or [678]Apple Remote Desktop (ARD). Perhaps there is some x11vnc feature you'd like to use on Mac OS X, etc. For a number of activities (e.g. window drags) it seems to be faster than OSXvnc. @@ -7997,14 +8011,14 @@ minal #2) X11: x11vnc will also work (as it has for years) with a X11 server (XDarwin) running on Mac OS X (people often install this software to display remote X11 apps on their Mac OS X system, or use some old - favorites locally such as xterm). However in this case x11vnc will - only work reasonably in single window [677]-id windowid mode (and the - window may need to have mouse focus). + favorites locally such as xterm.) However in this case x11vnc will + only work reasonably in single window [679]-id windowid mode (and the + window may need to have mouse focus.) If you do not have the DISPLAY env. variable set, x11vnc will assume native Aqua/Quartz on Mac OS X, however if DISPLAY is set it will assume an X11 connection. Use "-rawfb console" to force the native - display (or unset DISPLAY). + display (or unset DISPLAY.) Update: Leopard sets DISPLAY by default in all sessions. Since it starts with the string "/tmp/" x11vnc will use that to know if it @@ -8016,9 +8030,9 @@ minal #2) ./configure --without-x make - Win2VNC/x2vnc: One handy use is to use the [678]-nofb mode to + Win2VNC/x2vnc: One handy use is to use the [680]-nofb mode to redirect mouse and keyboard input to a nearby Mac (i.e. one to the - side of your desk) via [679]x2vnc or Win2VNC. See [680]this FAQ for + side of your desk) via [681]x2vnc or Win2VNC. See [682]this FAQ for more info. Options: Here are the Mac OS X specific x11vnc options: @@ -8029,7 +8043,7 @@ minal #2) -macnowait For the native Mac OS X server, do not wait for the user to switch back to his display. -macwheel n For the native Mac OS X server, set the mouse wheel - speed to n (default 5). + speed to n (default 5.) -macnoswap For the native Mac OS X server, do not swap mouse buttons 2 and 3. -macnoresize For the native Mac OS X server, do not resize or rese @@ -8050,7 +8064,7 @@ ct PasteBoard/Clipboard: There is a bug that the Clipboard (called PasteBoard on Mac it appears) exchange will not take place unless x11vnc was started from inside the Aqua display (e.g. started inside a - Terminal app window). Otherwise it cannot connect to the PasteBoard + Terminal app window.) Otherwise it cannot connect to the PasteBoard server. So Clipboard exchange won't work for our standard "ssh in" startup scheme. @@ -8085,20 +8099,20 @@ rm -f $tmp where you should customize the x11vnc command line to your needs and the full path to the binary. Save it in a file e.g. "start_x11vnc" and then after you SSH in just type "./start_x11vnc" (or have ssh run the - command for you). Then once you are connected via VNC, iconify the - Terminal windows (you can't delete them since that will kill x11vnc). + command for you.) Then once you are connected via VNC, iconify the + Terminal windows (you can't delete them since that will kill x11vnc.) Q-116: Can x11vnc be used as a VNC reflector/repeater to improve performance for the case of a large number of simultaneous VNC viewers (e.g. classroom broadcasting or a large demo)? - Yes, as of Feb/2007 there is the "[681]-reflect host:N" option to + Yes, as of Feb/2007 there is the "[683]-reflect host:N" option to connect to the VNC server "host:N" (either another x11vnc or any other VNC server) and re-export it. VNC viewers then connect to the x11vnc(s) running -reflect. The -reflect option is the same as: "-rawfb vnc:host:N". See the - [682]-rawfb description under "VNC HOST" for more details. + [684]-rawfb description under "VNC HOST" for more details. You can replace "host:N" with "listen" or "listen:port" for reverse connections. @@ -8150,27 +8164,27 @@ rm -f $tmp framebuffer writes (e.g. jpeg image region) then the repeater may block waiting for that large write to finish before going onto the next client (however, if the write is small enough, the kernel will - buffer it and the server can go on to service the next client). + buffer it and the server can go on to service the next client.) The x11vnc -reflect implementation uses the libvncclient library in the LibVNCServer project to handle the connection to "S". It is not currently very efficient since it simply does its normal framebuffer polling scheme on the libvncclient framebuffer (which it then - re-exports via VNC to its clients C). However, CopyRect and + re-exports via VNC to its clients C.) However, CopyRect and CursorShape encodings are preserved in the reflection and that helps. Dragging windows with the mouse can be a problem (especially if S is - not doing wireframing somehow, consider [683]-nodragging if the + not doing wireframing somehow, consider [685]-nodragging if the problem is severe) For a really fast reflector/repeater it would have to be implemented from scratch with performance in mind. See these other projects: - [684]http://sourceforge.net/projects/vnc-reflector/, - [685]http://www.tightvnc.com/projector/ (closed source?), + [686]http://sourceforge.net/projects/vnc-reflector/, + [687]http://www.tightvnc.com/projector/ (closed source?), Automation via Reverse Connections: Instead of having the R's connect directly to S and then the C's connect directly to the R they should use, some convenience can be achieved by using reverse - connections (the x11vnc "[686]"-connect host1,host2,..." option). + connections (the x11vnc "[688]"-connect host1,host2,..." option.) Suppose all the clients "C" are started up in Listen mode: client1> vncviewer -listen client2> vncviewer -listen @@ -8190,7 +8204,7 @@ rm -f $tmp vncserver> x11vnc -display :0 -connect repeater1,repeater2,...repeater8 (or instruct a non-x11vnc VNC server to reverse connect to the - repeaters). For a classroom broadcasting setup one might have the + repeaters.) For a classroom broadcasting setup one might have the first two sets of commands start automatically at bootup or when someone logs in, and then start everything up with the S server. One may even be able to script the forward connection bootstrap case, let @@ -8208,7 +8222,7 @@ rm -f $tmp Usually the OS install will have to be a network-install in order to have networking up during the install. Otherwise, you may have a (slim) chance to configure the networking manually (ifconfig(8) and - route(8)). + route(8).) To avoid library dependencies problems in the typical minimal (e.g. busybox) installation OS it is a good idea to build a statically @@ -8229,7 +8243,7 @@ rm -f $tmp If the Solaris install is an older X-based one, there will be a menu for you to get a terminal window. From that window you might be able to retrieve x11vnc.static via wget, scp, or ftp. Remember to do "chmod - 755 ./x11vnc.static" and then find the -auth file as in [687]this FAQ. + 755 ./x11vnc.static" and then find the -auth file as in [689]this FAQ. If it is a Linux install that uses an X server (e.g. SuSE and probably Fedora), then you can often get a shell by pressing Ctrl-Alt-F2 or @@ -8238,8 +8252,8 @@ rm -f $tmp wget http://192.168.0.22/x11vnc.static chmod 755 ./x11vnc.static - Find the name of the auth file as in [688]this FAQ. (maybe run "ps - wwwwaux | grep auth"). Then run it like this: + Find the name of the auth file as in [690]this FAQ. (maybe run "ps + wwwwaux | grep auth".) Then run it like this: ./x11vnc.static -forever -nopw -display :0 -auth /tmp/wherever/the/authfile then press Alt-F7 to go back to the X install. You should now be able @@ -8247,7 +8261,7 @@ rm -f $tmp the display being :1, etc. If there is a firewall blocking incoming connections during the - install, use the [689]"-connect hostname" option option for a reverse + install, use the [691]"-connect hostname" option option for a reverse connection to the hostname running the VNC viewer in listen mode. Debian based installs are either console-text or console-framebuffer @@ -8295,12 +8309,12 @@ rm -f $tmp As of Jan/2004 x11vnc supports the "CutText" part of the rfb protocol. Furthermore, x11vnc is able to hold the PRIMARY and CLIPBOARD - selection (Xvnc does not seem to do this). If you don't want the - Clipboard/Selection exchanged use the [690]-nosel option. If you don't + selection (Xvnc does not seem to do this.) If you don't want the + Clipboard/Selection exchanged use the [692]-nosel option. If you don't want the PRIMARY selection to be polled for changes use the - [691]-noprimary option. (with a similar thing for CLIPBOARD). You can - also fine-tune it a bit with the [692]-seldir dir option and also - [693]-input. + [693]-noprimary option. (with a similar thing for CLIPBOARD.) You can + also fine-tune it a bit with the [694]-seldir dir option and also + [695]-input. You may need to watch out for desktop utilities such as KDE's "Klipper" that do odd things with the selection, clipboard, and @@ -8312,7 +8326,7 @@ rm -f $tmp Yes, it is possible with a number of tools that record VNC and transform it to swf format or others. One such popular tool is - [694]pyvnc2swf. There are a number of [695]tutorials (broken link?) on + [696]pyvnc2swf. There are a number of [697]tutorials (broken link?) on how to do this. Another option is to use the vnc2mpg that comes in the LibVNCServer package. An important thing to remember when doing this is that tuning @@ -8325,19 +8339,19 @@ rm -f $tmp and UltraVNC file transfer implementations that were added to libvncserver. This currently works with TightVNC and UltraVNC viewers (and Windows viewers only support filetransfer it appears... but they - do work to some degree under Wine on Linux). + do work to some degree under Wine on Linux.) - The [696]SSVNC Unix VNC viewer supports UltraVNC file transfer by use + The [698]SSVNC Unix VNC viewer supports UltraVNC file transfer by use of a Java helper program. TightVNC file transfer is off by default, if you want to enable it use - the [697]-tightfilexfer option. + the [699]-tightfilexfer option. UltraVNC file transfer is off by default, to enable it use something like "-rfbversion 3.6 -permitfiletransfer" options (UltraVNC incorrectly uses the RFB protocol version to determine if its features are available, so x11vnc has to pretend to - be version 3.6). As of Sep/2006 "-ultrafilexfer" is an alias for these + be version 3.6.) As of Sep/2006 "-ultrafilexfer" is an alias for these two options. Note that running as RFB version 3.6 may confuse other VNC Viewers. @@ -8349,12 +8363,12 @@ rm -f $tmp implemented, you cannot do Tightvnc file transfer in -unixpw mode. However, UltraVNC file transfer does work in -unixpw (but if a client tries it do a filetransfer during the login process it will be - disconnected). + disconnected.) IMPORTANT: please understand if -ultrafilexfer or -tightfilexfer is specified and you run x11vnc as root for, say, inetd or display manager (gdm, kdm, ...) access and you do not have it switch users via - the [698]-users option, then VNC Viewers that connect are able to do + the [700]-users option, then VNC Viewers that connect are able to do filetransfer reads and writes as *root*. The UltraVNC and TightVNC settings can be toggled on and off inside @@ -8373,7 +8387,7 @@ rm -f $tmp these extensions you will need to supply this option to x11vnc: -rfbversion 3.6 - Or use [699]-ultrafilexfer which is an alias for the above option and + Or use [701]-ultrafilexfer which is an alias for the above option and "-permitfiletransfer". UltraVNC evidently treats any other RFB version number as non-UltraVNC. @@ -8385,14 +8399,14 @@ rm -f $tmp * 1/n Server Scaling * rfbEncodingUltra compression encoding - The [700]SSVNC Unix VNC viewer supports these UltraVNC extensions. + The [702]SSVNC Unix VNC viewer supports these UltraVNC extensions. - To disable SingleWindow and ServerInput use [701]-noultraext (the - others are managed by LibVNCServer). See this option too: - [702]-noserverdpms. + To disable SingleWindow and ServerInput use [703]-noultraext (the + others are managed by LibVNCServer.) See this option too: + [704]-noserverdpms. - Also, the [703]UltraVNC repeater proxy is supported for use with - reverse connections: "[704]-connect repeater://host:port+ID:NNNN". Use + Also, the [705]UltraVNC repeater proxy is supported for use with + reverse connections: "[706]-connect repeater://host:port+ID:NNNN". Use it for both plaintext and SSL connections. This mode can send any string before switching to the VNC protocol, and so could be used with other proxy/gateway tools. @@ -8403,17 +8417,17 @@ rm -f $tmp reverse vnc connection from their Unix desktop to a helpdesk operator's VNC Viewer. - Yes, UltraVNC's [705]Single Click (SC) mode can be emulated fairly + Yes, UltraVNC's [707]Single Click (SC) mode can be emulated fairly well on Unix. We use the term "helpdesk" below, but it could be any sort of remote assistance you want to set up, e.g. something for Unix-using friends - or family to use. This includes [706]Mac OS X. + or family to use. This includes [708]Mac OS X. Assume you create a helpdesk directory "hd" on your website: http://www.mysite.com/hd (any website that you can upload files to should work, although remember the user will be running the programs - you place there). + you place there.) In that "hd" subdirectory copy an x11vnc binary to be run on the Unix user's machine (e.g. Linux, etc) and also create a file named "vnc" @@ -8458,13 +8472,13 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc and then press Enter. You could have this instruction on a web page or in an email you send him, etc. This requires that the wget is installed on the user's Unix machine (he might only have curl or lynx, - see below for more info). + see below for more info.) So I guess this is about 3-4 clicks (start a terminal and paste) and pressing "Enter" instead of "single click"... - See [707]this page for some variations on this method, e.g. how to add + See [709]this page for some variations on this method, e.g. how to add a password, SSL Certificates, etc. @@ -8476,11 +8490,11 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc A bit of obscurity security could be put in with a -passwd, -rfbauth options, etc. (note that x11vnc will require a password even for - reverse connections). More info [708]here. + reverse connections.) More info [710]here. Firewalls: If the helpdesk (you) with the vncviewer is behind a - NAT/Firewall/Router the [709]router will have to be configured to + NAT/Firewall/Router the [711]router will have to be configured to redirect a port (i.e. 5500 or maybe different one if you like) to the vncviewer machine. If the vncviewer machine also has its own host-level firewall, you will have to open up the port there as well. @@ -8488,9 +8502,9 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc NAT-2-NAT: There is currently no way to go "NAT-2-NAT", i.e. both User and Helpdesk workstations behind NAT'ing Firewall/Routers without configuring a router to do a port redirection (i.e. on your side, the - HelpDesk). To avoid modifying either firewall/router, one would need + HelpDesk.) To avoid modifying either firewall/router, one would need some public (IP address reachable on the internet) redirection/proxy - service. Perhaps such a thing exists. [710]http://sc.uvnc.com provides + service. Perhaps such a thing exists. [712]http://sc.uvnc.com provides this service for their UltraVNC Single Click users. @@ -8502,7 +8516,7 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc above wget line) and prompt the user if he wants to run it. This may be tricky to set up (which is probably a good thing to not have the web browser readily run arbitrary programs downloaded from the - internet...). + internet...) One command-line free way, tested with KDE, is to name the file vnc.sh and then instruct the user to right-click on the link and do "Save @@ -8526,7 +8540,7 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc As of Apr/2007 x11vnc supports reverse connections in SSL and so we can do this. On the Helpdesk side (Viewer) you will need STUNNEL or - better use the [711]Enhanced TightVNC Viewer (SSVNC) package we + better use the [713]Enhanced TightVNC Viewer (SSVNC) package we provide that automates all of the SSL for you. To do this create a file named "vncs" in the website "hd" directory @@ -8556,20 +8570,20 @@ chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc with the hostnames or IP addresses customized to your case. - The only change from the "vnc" above is the addition of the [712]-ssl + The only change from the "vnc" above is the addition of the [714]-ssl option to x11vnc. This will create a temporary SSL cert: openssl(1) will need to be installed on the user's end. A fixed SSL cert file could be used to avoid this (and provide some authentication; more - info [713]here.) + info [715]here.) The naive user will be doing this: wget -qO - http://www.mysite.com/hd/vncs | sh - - (or perhaps even use https:// if available). + (or perhaps even use https:// if available.) But before that, the helpdesk operator needs to have "vncviewer -listen" running as before, however he needs an SSL tunnel at his end. - The easiest way to do this is use [714]Enhanced TightVNC Viewer + The easiest way to do this is use [716]Enhanced TightVNC Viewer (SSVNC). Start it, and select Options -> 'Reverse VNC Connection (-listen)'. Then UN-select 'Verify All Certs' (this can be enabled later if you want; you'll need the x11vnc SSL certificate), and click @@ -8588,9 +8602,9 @@ connect = localhost:5501 stunnel ./stunnel.cfg and then start the "vncviewer -listen 1" (i.e. 1 to correspond to the - 5501 port). Note that this assumes the stunnel install created a + 5501 port.) Note that this assumes the stunnel install created a Server SSL cert+key, usually /etc/stunnel/stunnel.pem (not all distros - will do this). Also, that file is by default only readable by root, so + will do this.) Also, that file is by default only readable by root, so stunnel needs to be run as root. If your system does not have a key installed or you do not want to run stunnel as root (or change the permissions on the file), you can use x11vnc to create one for you for @@ -8599,7 +8613,7 @@ connect = localhost:5501 answer the prompts with whatever you want; you can take the default for all of them if you like. The openssl(1) package must be installed. - See [715]this link and [716]this one too for more info on SSL certs. + See [717]this link and [718]this one too for more info on SSL certs. This creates $HOME/.vnc/certs/server-self:mystunnel.pem, then you would change the "stunnel.cfg" to look something like: foreground = yes @@ -8620,7 +8634,7 @@ connect = localhost:5501 then all bets are off!. More SSL variations and info about certificates can be found - [717]here. + [719]here. OpenSSL libssl.so.0.9.7 problems: @@ -8630,7 +8644,7 @@ connect = localhost:5501 distros are currently a bit of a mess regarding which version of libssl is installed. - You will find the [718]details here. + You will find the [720]details here. Q-123: Can I (temporarily) mount my local (viewer-side) Windows/Samba @@ -8639,7 +8653,7 @@ connect = localhost:5501 You will have to use an external network redirection for this. Filesystem mounting is not part of the VNC protocol. - We show a simple [719]Samba example here. + We show a simple [721]Samba example here. First you will need a tunnel to redirect the SMB requests from the remote machine to the one you sitting at. We use an ssh tunnel: @@ -8652,11 +8666,11 @@ connect = localhost:5501 Port 139 is the Windows Service port. For Windows systems instead of Samba, you may need to use the actual IP address of the Window machine instead of "localhost" in the -R option (since the Windows service - does not listen on localhost by default). + does not listen on localhost by default.) Note that we use 1139 instead of 139 on the remote side because 139 would require root permission to listen on (and you may have a samba - server running on it already). + server running on it already.) The ssh -C is to enable compression, which might speed up the data transfers. @@ -8672,15 +8686,15 @@ connect = localhost:5501 far-away> smbmount //haystack/pub /home/fred/smb-haystack-pub -o username=fre d,ip=127.0.0.1,port=1139 - (The 2nd command may need to be run as root). Then run "df" or "ls -l + (The 2nd command may need to be run as root.) Then run "df" or "ls -l /home/fred/smb-haystack-pub" to see if it is mounted properly. Consult the smbmount(8) and related documentation (it may require some - fiddling to get write permissions correct, etc.). To unmount: + fiddling to get write permissions correct, etc.) To unmount: far-away> smbumount /home/fred/smb-haystack-pub At some point we hope to fold some automation for SMB ssh redir setup - into the [720]Enhanced TightVNC Viewer (SSVNC) package we provide (as - of Sep 2006 it is there for testing). + into the [722]Enhanced TightVNC Viewer (SSVNC) package we provide (as + of Sep 2006 it is there for testing.) Q-124: Can I redirect CUPS print jobs from the remote desktop where @@ -8689,10 +8703,10 @@ d,ip=127.0.0.1,port=1139 You will have to use an external network redirection for this. Printing is not part of the VNC protocol. - We show a simple Unix to Unix [721]CUPS example here. Non-CUPS port + We show a simple Unix to Unix [723]CUPS example here. Non-CUPS port redirections (e.g. LPD) should also be possible, but may be a bit more tricky. If you are viewing on Windows SMB and don't have a local cups - server it may be trickier still (see below). + server it may be trickier still (see below.) First you will need a tunnel to redirect the print requests from the remote machine to the one you sitting at. We use an ssh tunnel: @@ -8709,7 +8723,7 @@ d,ip=127.0.0.1,port=1139 Note that we use 6631 instead of 631 on the remote side because 631 would require root permission to listen on (and you likely have a cups - server running on it already). + server running on it already.) Now the tricky part: to get applications to notice your cups server/printer on localhost:6631. @@ -8720,8 +8734,8 @@ d,ip=127.0.0.1,port=1139 Printing -> Printing Manager, and then supply admin password, and then Add Printer/Class, and then fill in the inquisitive wizard. Most important is the "Remote IPP server" panel where you put in localhost - for Host and 6631 for Port). The main setting you want to convey is - the host is localhost and the port is non-standard (e.g. 6631). Some + for Host and 6631 for Port.) The main setting you want to convey is + the host is localhost and the port is non-standard (e.g. 6631.) Some configuration utilities will take an Internet Printing Protocol (IPP) URI, e.g. http://localhost:6631/printers/, ipp://localhost:6631/printers/printer-name, @@ -8740,7 +8754,7 @@ d,ip=127.0.0.1,port=1139 operation. Unfortunately, running applications may need to be restarted to notice - the new printers (libcups does not track changes in client.conf). + the new printers (libcups does not track changes in client.conf.) Depending on circumstances, a running application may actually notice the new printers without restarting (e.g. no print dialog has taken place yet, or there are no CUPS printers configured on the remote @@ -8748,7 +8762,7 @@ d,ip=127.0.0.1,port=1139 Cups client software that is older (1.1) does not support appending the port number, and for newer ones there is a bug preventing it from - always working (fixed in 1.2.3). Kludges like these at the command + always working (fixed in 1.2.3.) Kludges like these at the command line will work: far-away> env CUPS_SERVER=localhost IPP_PORT=6631 lpstat -p -d far-away> env CUPS_SERVER=localhost IPP_PORT=6631 lpr -P myprinter file.ps @@ -8756,7 +8770,7 @@ d,ip=127.0.0.1,port=1139 but are somewhat awkward since you have to retroactively set the env. var IPP_PORT. Its value cannot be broadcast to already running apps - (like the $HOME/.cups/client.conf trick sometimes does). A common + (like the $HOME/.cups/client.conf trick sometimes does.) A common workaround for an already running app is to somehow get it to "Print To File", e.g. file.ps and then use something like the lpr example above. Also, the option "-h host:port" works with CUPS lp(1) and @@ -8766,13 +8780,13 @@ d,ip=127.0.0.1,port=1139 this with the smbspool(8) command, or configure the remote CUPS via lpadmin(8), etc, to use a printer URI something like smb://machine:port/printer (this may have some name resolution - problems WRT localhost). Also, as with SMB mounting, the port redir + problems WRT localhost.) Also, as with SMB mounting, the port redir (-R) to the Windows machine must use the actual IP address instead of "localhost". At some point we hope to fold some automation for CUPS ssh redir setup - into the [722]Enhanced TightVNC Viewer (SSVNC) package we provide (as - of Sep 2006 it is there for testing). + into the [724]Enhanced TightVNC Viewer (SSVNC) package we provide (as + of Sep 2006 it is there for testing.) Q-125: How can I hear the sound (audio) from the remote applications @@ -8783,7 +8797,7 @@ d,ip=127.0.0.1,port=1139 We show a simple Unix to Unix esd example here (artsd should be possible too, we have also verified the esd Windows port works for the - method described below). + method described below.) First you will need a tunnel to redirect the audio from the remote machine to the one you sitting at. We use an ssh tunnel: @@ -8796,7 +8810,7 @@ way.east 'x11vnc -localhost -display :0' Port 16001 is the default ESD uses. So when an application on the remote desktop makes a sound it will connect to this tunnel and be redirected to port 16001 on the local machine (sitting-here in this - example). The -C option is an attempt to compress the audio a little + example.) The -C option is an attempt to compress the audio a little bit. So we next need a local (sitting-here) esd daemon running that will @@ -8804,7 +8818,7 @@ way.east 'x11vnc -localhost -display :0' sitting-here> esd -promiscuous -port 16001 -tcp -bind 127.0.0.1 See the esd(1) man page for the meaning of the options (the above are - not very secure). (This method also works with the EsounD windows port + not very secure.) (This method also works with the EsounD windows port esd.exe) To test this sound tunnel, we use the esdplay program to play a simple @@ -8821,11 +8835,11 @@ way.east 'x11vnc -localhost -display :0' Then you could try playing some sounds inside xmms. You could also set the environment variable ESPEAKER=localhost:16001 to not need to supply the -s option all the time. (for reasons not clear, sometimes - esddsp can figure it out on its own). All the script esddsp does is to + esddsp can figure it out on its own.) All the script esddsp does is to set ESPEAKER and LD_PRELOAD for you so that when the application opens the sound device (usually /dev/dsp) its interactions with the device will be intercepted and sent to the esd daemon running on sitting-here - (that in turn writes them to the real, local /dev/dsp). + (that in turn writes them to the real, local /dev/dsp.) Redirecting All sound: @@ -8837,7 +8851,7 @@ way.east 'x11vnc -localhost -display :0' Here is one way to redirect all sound. The idea is we run the entire desktop with sound directed to localhost:16001. When we are sitting at far-away.east we run "esd -promiscuous -port 16001 -tcp -bind - 127.0.0.1" on far-away.east (to be able to hear the sound). However, + 127.0.0.1" on far-away.east (to be able to hear the sound.) However, when we are sitting at sitting-here.west we kill that esd process and run that same esd command on sitting-here.west and start up the above ssh tunnel. This is a little awkward, but with some scripts one would @@ -8852,7 +8866,7 @@ or: esddsp -s localhost:16001 startkde where the last part is whatever command starts your desktop (even - fvwm2). This causes the environment variables ESPEAKER and LD_PRELOAD + fvwm2.) This causes the environment variables ESPEAKER and LD_PRELOAD to be set appropriately and every application (processes with the desktop as an ancestor) will use them. If this scheme works well you can make it less klunky by adding the command to your ~/.xsession, @@ -8872,8 +8886,8 @@ or: the applications will fail to run because LD_PRELOAD will point to libraries of the wrong wordsize. * At some point we hope to fold some automation for esd or artsd ssh - redir setup into the [723]Enhanced TightVNC Viewer (SSVNC) package - we provide (as of Sep/2006 it is there for testing). + redir setup into the [725]Enhanced TightVNC Viewer (SSVNC) package + we provide (as of Sep/2006 it is there for testing.) Q-126: Why don't I hear the "Beeps" in my X session (e.g. when typing @@ -8884,23 +8898,23 @@ or: in Solaris, see Xserver(1) for how to turn it on via +kb), and so you won't hear them if the extension is not present. - If you don't want to hear the beeps use the [724]-nobell option. If + If you don't want to hear the beeps use the [726]-nobell option. If you want to hear the audio from the remote applications, consider - trying a [725]redirector such as esd. + trying a [727]redirector such as esd. Q-127: Does x11vnc work with IPv6? - Currently the only way to do this is via [726]inetd. You configure + Currently the only way to do this is via [728]inetd. You configure x11vnc to be run from inetd or xinetd and instruct it to listen on an IPv6 address. For xinetd the setting "flags = IPv6" will be needed. Unfortunately this will be inefficient if multiple VNC Viewers are connected at the same time (there will be a separate x11vnc for each - connection). Some sort of ipv4-to-ipv6 redirector tool (perhaps even a + connection.) Some sort of ipv4-to-ipv6 redirector tool (perhaps even a perl script) could be useful to avoid this. - Also note that not all VNC Viewers are [727]IPv6 enabled, so a + Also note that not all VNC Viewers are [729]IPv6 enabled, so a redirector could even be needed on the client side. @@ -9289,362 +9303,364 @@ References 369. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpport 370. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-https 371. http://www.karlrunge.com/x11vnc/ssl-output.html - 372. http://www.karlrunge.com/x11vnc/ssvnc.html - 373. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext - 374. http://www.karlrunge.com/x11vnc/ss_vncviewer - 375. http://www.karlrunge.com/x11vnc/ssl-portal.html - 376. http://www.karlrunge.com/x11vnc/ssl.html - 377. http://www.karlrunge.com/x11vnc/ssvnc.html - 378. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir - 379. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers - 380. http://www.karlrunge.com/x11vnc/faq.html#ss_vncviewer - 381. http://www.karlrunge.com/x11vnc/ssvnc.html - 382. http://www.karlrunge.com/x11vnc/ssl-portal.html - 383. http://www.karlrunge.com/x11vnc/ssl.html - 384. http://www.karlrunge.com/x11vnc/faq.html#infaq_display-manager-continuously - 385. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd - 386. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin - 387. http://www.karlrunge.com/x11vnc/faq.html#infaq_x11vnc_loop - 388. http://club.mandriva.com/xwiki/bin/view/KB/XwinXset - 389. http://www.karlrunge.com/x11vnc/index.html#firewalls - 390. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-auth - 391. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reopen - 392. http://www.karlrunge.com/x11vnc/faq.html#infaq_dtlogin_solaris - 393. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost - 394. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 372. http://www.karlrunge.com/x11vnc/java_console_direct.html + 373. http://www.karlrunge.com/x11vnc/ssvnc.html + 374. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext + 375. http://www.karlrunge.com/x11vnc/ss_vncviewer + 376. http://www.karlrunge.com/x11vnc/ssl-portal.html + 377. http://www.karlrunge.com/x11vnc/ssl.html + 378. http://www.karlrunge.com/x11vnc/ssvnc.html + 379. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpsredir + 380. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-viewers + 381. http://www.karlrunge.com/x11vnc/java_console_proxy.html + 382. http://www.karlrunge.com/x11vnc/faq.html#ss_vncviewer + 383. http://www.karlrunge.com/x11vnc/ssvnc.html + 384. http://www.karlrunge.com/x11vnc/ssl-portal.html + 385. http://www.karlrunge.com/x11vnc/ssl.html + 386. http://www.karlrunge.com/x11vnc/faq.html#infaq_display-manager-continuously + 387. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd + 388. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin + 389. http://www.karlrunge.com/x11vnc/faq.html#infaq_x11vnc_loop + 390. http://club.mandriva.com/xwiki/bin/view/KB/XwinXset + 391. http://www.karlrunge.com/x11vnc/index.html#firewalls + 392. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-auth + 393. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reopen + 394. http://www.karlrunge.com/x11vnc/faq.html#infaq_dtlogin_solaris 395. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost - 396. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 397. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N - 398. http://www.jirka.org/gdm-documentation/x241.html - 399. http://www.karlrunge.com/x11vnc/x11vnc_loop - 400. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop - 401. http://www.karlrunge.com/x11vnc/faq.html#faq-xterminal-xauth - 402. http://www.karlrunge.com/x11vnc/index.html#firewalls - 403. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-inetd - 404. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-q, - 405. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-auth - 406. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin - 407. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi - 408. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-mdns - 409. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf - 410. http://www.avahi.org/ - 411. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd - 412. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 413. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 414. http://www.karlrunge.com/x11vnc/faq.html#infaq_stunnel-inetd - 415. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop - 416. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 417. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 418. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 419. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 420. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 421. http://www.karlrunge.com/x11vnc/find_display.html - 422. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 423. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 424. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 425. http://www.karlrunge.com/x11vnc/faq.html#faq-unix-passwords - 426. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 427. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 428. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-int - 429. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost - 430. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw - 431. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 432. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb - 433. http://www.karlrunge.com/x11vnc/faq.html#ss_vncviewer - 434. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 435. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 436. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 437. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc - 438. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 439. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop - 440. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop - 441. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 442. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpdir - 443. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-http - 444. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-java-viewer-proxy - 445. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 446. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remote - 447. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect_or_exit - 448. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vncconnect - 449. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy - 450. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy + 396. http://www.karlrunge.com/x11vnc/index.html#tunnelling + 397. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost + 398. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl + 399. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-N + 400. http://www.jirka.org/gdm-documentation/x241.html + 401. http://www.karlrunge.com/x11vnc/x11vnc_loop + 402. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop + 403. http://www.karlrunge.com/x11vnc/faq.html#faq-xterminal-xauth + 404. http://www.karlrunge.com/x11vnc/index.html#firewalls + 405. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-inetd + 406. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-q, + 407. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-auth + 408. http://www.karlrunge.com/x11vnc/faq.html#faq-userlogin + 409. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-avahi + 410. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-mdns + 411. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-zeroconf + 412. http://www.avahi.org/ + 413. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd + 414. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 415. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 416. http://www.karlrunge.com/x11vnc/faq.html#infaq_stunnel-inetd + 417. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop + 418. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 419. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 420. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 421. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 422. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 423. http://www.karlrunge.com/x11vnc/find_display.html + 424. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 425. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 426. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 427. http://www.karlrunge.com/x11vnc/faq.html#faq-unix-passwords + 428. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 429. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 430. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-int + 431. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-localhost + 432. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-unixpw + 433. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 434. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb + 435. http://www.karlrunge.com/x11vnc/faq.html#ss_vncviewer + 436. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 437. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 438. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 439. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc + 440. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 441. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop + 442. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-loop + 443. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 444. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-httpdir + 445. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-http + 446. http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-java-viewer-proxy + 447. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 448. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remote + 449. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect_or_exit + 450. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-vncconnect 451. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy - 452. http://www.karlrunge.com/x11vnc/faq.html#infaq_localaccess - 453. http://www.karlrunge.com/x11vnc/faq.html#infaq_localaccess - 454. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 455. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 456. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 457. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 458. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 459. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 460. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-add_keysyms - 461. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 462. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc - 463. http://www.karlrunge.com/x11vnc/Xdummy - 464. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 465. http://www.karlrunge.com/x11vnc/xdm_one_shot.html - 466. http://www.karlrunge.com/x11vnc/faq.html#infaq_display-manager-continuously - 467. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay - 468. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT - 469. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find - 470. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create - 471. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc - 472. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc - 473. http://www.karlrunge.com/x11vnc/shm_clear - 474. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-onetile - 475. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noshm - 476. http://www.karlrunge.com/x11vnc/faq.html#faq-noshm - 477. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nap - 478. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait - 479. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sb - 480. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-onetile - 481. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fs - 482. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads - 483. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer - 484. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 485. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow - 486. http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc - 487. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid - 488. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 489. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 490. http://www.tightvnc.com/ - 491. http://www.karlrunge.com/x11vnc/ssvnc.html - 492. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 493. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 494. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid - 495. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-speeds - 496. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodragging - 497. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fs - 498. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait - 499. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer - 500. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-progressive - 501. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 502. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosel - 503. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursor - 504. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorpos - 505. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-readtimeout - 506. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fixscreen - 507. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow - 508. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xd_area - 509. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xd_mem - 510. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage - 511. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage - 512. http://minimyth.org/ - 513. http://www.karlrunge.com/x11vnc/faq.html#faq-beryl - 514. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow - 515. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pointer_mode - 516. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pointer_mode - 517. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodragging + 452. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy + 453. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-proxy + 454. http://www.karlrunge.com/x11vnc/faq.html#infaq_localaccess + 455. http://www.karlrunge.com/x11vnc/faq.html#infaq_localaccess + 456. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 457. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 458. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 459. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 460. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 461. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 462. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-add_keysyms + 463. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 464. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc + 465. http://www.karlrunge.com/x11vnc/Xdummy + 466. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 467. http://www.karlrunge.com/x11vnc/xdm_one_shot.html + 468. http://www.karlrunge.com/x11vnc/faq.html#infaq_display-manager-continuously + 469. http://www.karlrunge.com/x11vnc/faq.html#infaq_findcreatedisplay + 470. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-display_WAIT + 471. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-find + 472. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-create + 473. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-svc + 474. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xdmsvc + 475. http://www.karlrunge.com/x11vnc/shm_clear + 476. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-onetile + 477. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noshm + 478. http://www.karlrunge.com/x11vnc/faq.html#faq-noshm + 479. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nap + 480. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait + 481. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sb + 482. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-onetile + 483. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fs + 484. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads + 485. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer + 486. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 487. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow + 488. http://www.karlrunge.com/x11vnc/faq.html#faq-turbovnc + 489. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid + 490. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 491. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 492. http://www.tightvnc.com/ + 493. http://www.karlrunge.com/x11vnc/ssvnc.html + 494. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 495. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 496. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-solid + 497. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-speeds + 498. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodragging + 499. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fs + 500. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait + 501. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer + 502. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-progressive + 503. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 504. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosel + 505. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursor + 506. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorpos + 507. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-readtimeout + 508. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fixscreen + 509. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow + 510. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xd_area + 511. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xd_mem + 512. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage + 513. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage + 514. http://minimyth.org/ + 515. http://www.karlrunge.com/x11vnc/faq.html#faq-beryl + 516. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow + 517. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pointer_mode 518. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pointer_mode - 519. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads - 520. http://www.karlrunge.com/x11vnc/faq.html#faq-wireframe - 521. http://www.karlrunge.com/x11vnc/faq.html#faq-scrollcopyrect - 522. http://www.karlrunge.com/x11vnc/faq.html#faq-pointer-mode - 523. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow - 524. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 525. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 519. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodragging + 520. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pointer_mode + 521. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-threads + 522. http://www.karlrunge.com/x11vnc/faq.html#faq-wireframe + 523. http://www.karlrunge.com/x11vnc/faq.html#faq-scrollcopyrect + 524. http://www.karlrunge.com/x11vnc/faq.html#faq-pointer-mode + 525. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow 526. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 527. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow - 528. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 529. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe - 530. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wirecopyrect - 531. http://www.karlrunge.com/x11vnc/faq.html#faq-wireframe - 532. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fixscreen - 533. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scr_skip - 534. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale - 535. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect - 536. http://www.karlrunge.com/x11vnc/index.html#beta-test - 537. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache - 538. http://www.karlrunge.com/x11vnc/ssvnc.html - 539. http://www.karlrunge.com/x11vnc/ssvnc.html#ycrop - 540. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_no_rootpixmap - 541. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_cr - 542. http://www.virtualgl.org/About/TurboVNC - 543. http://www.virtualgl.org/ - 544. http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=166100 - 545. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait - 546. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer - 547. http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=166100 - 548. http://www.karlrunge.com/x11vnc/ssvnc.html - 549. http://www.karlrunge.com/x11vnc/bins + 527. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 528. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 529. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow + 530. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 531. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wireframe + 532. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wirecopyrect + 533. http://www.karlrunge.com/x11vnc/faq.html#faq-wireframe + 534. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-fixscreen + 535. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scr_skip + 536. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale + 537. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scrollcopyrect + 538. http://www.karlrunge.com/x11vnc/index.html#beta-test + 539. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache + 540. http://www.karlrunge.com/x11vnc/ssvnc.html + 541. http://www.karlrunge.com/x11vnc/ssvnc.html#ycrop + 542. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_no_rootpixmap + 543. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ncache_cr + 544. http://www.virtualgl.org/About/TurboVNC + 545. http://www.virtualgl.org/ + 546. http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=166100 + 547. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait + 548. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer + 549. http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=166100 550. http://www.karlrunge.com/x11vnc/ssvnc.html - 551. http://www.virtualgl.org/About/Reports - 552. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow - 553. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor - 554. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor - 555. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-overlay - 556. http://www.karlrunge.com/x11vnc/faq.html#infaq_the-overlay-mode - 557. http://www.karlrunge.com/x11vnc/index.html#solaris10-build - 558. http://www.karlrunge.com/x11vnc/faq.html#faq-xfixes-alpha-hacks - 559. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-alphacut - 560. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-alphafrac - 561. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-alpharemove - 562. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorshape - 563. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noalphablend - 564. http://www.karlrunge.com/x11vnc/ssvnc.html - 565. http://www.tightvnc.com/ - 566. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursor - 567. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursorpos - 568. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorpos - 569. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorshape - 570. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-buttonmap - 571. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-debug_pointer + 551. http://www.karlrunge.com/x11vnc/bins + 552. http://www.karlrunge.com/x11vnc/ssvnc.html + 553. http://www.virtualgl.org/About/Reports + 554. http://www.karlrunge.com/x11vnc/index.html#fb_read_slow + 555. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor + 556. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursor + 557. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-overlay + 558. http://www.karlrunge.com/x11vnc/faq.html#infaq_the-overlay-mode + 559. http://www.karlrunge.com/x11vnc/index.html#solaris10-build + 560. http://www.karlrunge.com/x11vnc/faq.html#faq-xfixes-alpha-hacks + 561. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-alphacut + 562. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-alphafrac + 563. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-alpharemove + 564. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorshape + 565. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noalphablend + 566. http://www.karlrunge.com/x11vnc/ssvnc.html + 567. http://www.tightvnc.com/ + 568. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursor + 569. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-cursorpos + 570. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorpos + 571. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nocursorshape 572. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-buttonmap - 573. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak - 574. http://www.karlrunge.com/x11vnc/faq.html#faq-greaterless - 575. http://www.karlrunge.com/x11vnc/faq.html#faq-xkbmodtweak - 576. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-debug_keyboard - 577. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak - 578. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb - 579. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sloppy_keys - 580. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak - 581. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak - 582. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 583. http://www.karlrunge.com/x11vnc/faq.html#faq-xkbmodtweak - 584. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-debug_keyboard - 585. http://www.karlrunge.com/x11vnc/faq.html#faq-greaterless - 586. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb - 587. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sloppy_keys - 588. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak - 589. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb - 590. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb - 591. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-skip_keycodes - 592. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 593. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-add_keysyms + 573. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-debug_pointer + 574. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-buttonmap + 575. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak + 576. http://www.karlrunge.com/x11vnc/faq.html#faq-greaterless + 577. http://www.karlrunge.com/x11vnc/faq.html#faq-xkbmodtweak + 578. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-debug_keyboard + 579. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak + 580. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb + 581. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sloppy_keys + 582. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak + 583. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak + 584. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap + 585. http://www.karlrunge.com/x11vnc/faq.html#faq-xkbmodtweak + 586. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-debug_keyboard + 587. http://www.karlrunge.com/x11vnc/faq.html#faq-greaterless + 588. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb + 589. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-sloppy_keys + 590. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-modtweak + 591. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb + 592. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xkb + 593. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-skip_keycodes 594. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 595. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 596. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-add_keysyms - 597. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-norepeat - 598. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-norepeat - 599. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager - 600. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_mods - 601. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 602. http://www.karlrunge.com/x11vnc/faq.html#faq-remap-capslock - 603. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-skip_lockkeys - 604. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-capslock - 605. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all - 606. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 607. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 608. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nomodtweak + 595. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-add_keysyms + 596. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap + 597. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap + 598. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-add_keysyms + 599. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-norepeat + 600. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-norepeat + 601. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager + 602. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_mods + 603. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap + 604. http://www.karlrunge.com/x11vnc/faq.html#faq-remap-capslock + 605. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-skip_lockkeys + 606. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-capslock + 607. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all + 608. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap 609. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 610. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 611. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-skip_lockkeys + 610. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nomodtweak + 611. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap 612. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap - 613. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nomodtweak - 614. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-capslock - 615. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all - 616. http://www.karlrunge.com/x11vnc/faq.html#faq-scaling - 617. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale - 618. http://people.pwf.cam.ac.uk/ssb22/setup/vnc-magnification.html - 619. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport - 620. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-gui - 621. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 622. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale_cursor - 623. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-blackout - 624. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xinerama - 625. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xinerama - 626. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer - 627. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer - 628. http://www.karlrunge.com/x11vnc/faq.html#faq-solshm - 629. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-onetile - 630. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noshm - 631. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clip - 632. http://www.karlrunge.com/x11vnc/faq.html#faq-xinerama - 633. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 634. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 635. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xrandr - 636. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-padgeom - 637. http://www.karlrunge.com/x11vnc/ssvnc.html - 638. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rotate - 639. http://www.jwz.org/xscreensaver/man1.html - 640. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodpms - 641. http://www.beryl-project.org/ - 642. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage - 643. http://www.dslinux.org/blogs/pepsiman/?p=73 - 644. http://minimyth.org/ - 645. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc - 646. http://www.karlrunge.com/x11vnc/faq.html#faq-rawfb + 613. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-skip_lockkeys + 614. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-remap + 615. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nomodtweak + 616. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-capslock + 617. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clear_all + 618. http://www.karlrunge.com/x11vnc/faq.html#faq-scaling + 619. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale + 620. http://people.pwf.cam.ac.uk/ssb22/setup/vnc-magnification.html + 621. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rfbport + 622. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-gui + 623. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 624. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-scale_cursor + 625. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-blackout + 626. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xinerama + 627. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xinerama + 628. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer + 629. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xwarppointer + 630. http://www.karlrunge.com/x11vnc/faq.html#faq-solshm + 631. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-onetile + 632. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noshm + 633. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-clip + 634. http://www.karlrunge.com/x11vnc/faq.html#faq-xinerama + 635. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 636. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 637. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-xrandr + 638. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-padgeom + 639. http://www.karlrunge.com/x11vnc/ssvnc.html + 640. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rotate + 641. http://www.jwz.org/xscreensaver/man1.html + 642. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodpms + 643. http://www.beryl-project.org/ + 644. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noxdamage + 645. http://www.dslinux.org/blogs/pepsiman/?p=73 + 646. http://minimyth.org/ 647. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc - 648. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 649. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 650. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput - 651. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput - 652. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-snapfb - 653. http://www.karlrunge.com/x11vnc/faq.html#faq-video - 654. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb - 655. http://www.karlrunge.com/x11vnc/faq.html#faq-qt-embedded - 656. http://www.karlrunge.com/x11vnc/faq.html#faq-video - 657. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 648. http://www.karlrunge.com/x11vnc/faq.html#faq-rawfb + 649. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc + 650. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 651. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 652. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput + 653. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput + 654. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-snapfb + 655. http://www.karlrunge.com/x11vnc/faq.html#faq-video + 656. http://www.karlrunge.com/x11vnc/faq.html#faq-xvfb + 657. http://www.karlrunge.com/x11vnc/faq.html#faq-qt-embedded 658. http://www.karlrunge.com/x11vnc/faq.html#faq-video - 659. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc - 660. http://www.karlrunge.com/x11vnc/faq.html#faq-qt-embedded - 661. http://www.karlrunge.com/x11vnc/faq.html#faq-vmware - 662. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 663. http://www.karlrunge.com/x11vnc/faq.html#faq-rawfb - 664. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-snapfb - 665. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-24to32 - 666. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait - 667. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-slow_fb - 668. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer - 669. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-freqtab - 670. http://www.karlrunge.com/x11vnc/faq.html#faq-rawfb - 671. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput - 672. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput - 673. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 674. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 675. http://www.testplant.com/products/vine_server/OS_X - 676. http://www.apple.com/remotedesktop/ - 677. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 678. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id - 679. http://fredrik.hubbe.net/x2vnc.html - 680. http://www.karlrunge.com/x11vnc/faq.html#faq-win2vnc - 681. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect - 682. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb - 683. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodragging - 684. http://sourceforge.net/projects/vnc-reflector/ - 685. http://www.tightvnc.com/projector/ - 686. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 687. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager - 688. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager - 689. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 690. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosel - 691. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noprimary - 692. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-seldir - 693. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-input - 694. http://www.unixuser.org/~euske/vnc2swf/ - 695. http://wolphination.com/linux/2006/06/30/how-to-record-videos-of-your-desktop/ - 696. http://www.karlrunge.com/x11vnc/ssvnc.html - 697. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-tightfilexfer - 698. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users - 699. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer - 700. http://www.karlrunge.com/x11vnc/ssvnc.html - 701. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noultraext - 702. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms - 703. http://www.uvnc.com/addons/repeater.html - 704. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect - 705. http://www.uvnc.com/addons/singleclick.html - 706. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx - 707. http://www.karlrunge.com/x11vnc/single-click.html - 708. http://www.karlrunge.com/x11vnc/single-click.html - 709. http://www.karlrunge.com/x11vnc/index.html#firewalls - 710. http://sc.uvnc.com/ - 711. http://www.karlrunge.com/x11vnc/ssvnc.html - 712. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl - 713. http://www.karlrunge.com/x11vnc/single-click.html - 714. http://www.karlrunge.com/x11vnc/ssvnc.html + 659. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 660. http://www.karlrunge.com/x11vnc/faq.html#faq-video + 661. http://www.karlrunge.com/x11vnc/faq.html#faq-linuxvc + 662. http://www.karlrunge.com/x11vnc/faq.html#faq-qt-embedded + 663. http://www.karlrunge.com/x11vnc/faq.html#faq-vmware + 664. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 665. http://www.karlrunge.com/x11vnc/faq.html#faq-rawfb + 666. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-snapfb + 667. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-24to32 + 668. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-wait + 669. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-slow_fb + 670. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-defer + 671. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-freqtab + 672. http://www.karlrunge.com/x11vnc/faq.html#faq-rawfb + 673. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput + 674. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-pipeinput + 675. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 676. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 677. http://www.testplant.com/products/vine_server/OS_X + 678. http://www.apple.com/remotedesktop/ + 679. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 680. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id + 681. http://fredrik.hubbe.net/x2vnc.html + 682. http://www.karlrunge.com/x11vnc/faq.html#faq-win2vnc + 683. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-reflect + 684. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-rawfb + 685. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nodragging + 686. http://sourceforge.net/projects/vnc-reflector/ + 687. http://www.tightvnc.com/projector/ + 688. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 689. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager + 690. http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager + 691. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 692. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nosel + 693. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noprimary + 694. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-seldir + 695. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-input + 696. http://www.unixuser.org/~euske/vnc2swf/ + 697. http://wolphination.com/linux/2006/06/30/how-to-record-videos-of-your-desktop/ + 698. http://www.karlrunge.com/x11vnc/ssvnc.html + 699. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-tightfilexfer + 700. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-users + 701. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ultrafilexfer + 702. http://www.karlrunge.com/x11vnc/ssvnc.html + 703. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noultraext + 704. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-noserverdpms + 705. http://www.uvnc.com/addons/repeater.html + 706. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-connect + 707. http://www.uvnc.com/addons/singleclick.html + 708. http://www.karlrunge.com/x11vnc/faq.html#faq-macosx + 709. http://www.karlrunge.com/x11vnc/single-click.html + 710. http://www.karlrunge.com/x11vnc/single-click.html + 711. http://www.karlrunge.com/x11vnc/index.html#firewalls + 712. http://sc.uvnc.com/ + 713. http://www.karlrunge.com/x11vnc/ssvnc.html + 714. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-ssl 715. http://www.karlrunge.com/x11vnc/single-click.html - 716. http://www.karlrunge.com/x11vnc/ssl.html + 716. http://www.karlrunge.com/x11vnc/ssvnc.html 717. http://www.karlrunge.com/x11vnc/single-click.html - 718. http://www.karlrunge.com/x11vnc/single-click.html#libssl-problems - 719. http://www.samba.org/ - 720. http://www.karlrunge.com/x11vnc/ssvnc.html - 721. http://www.cups.org/ + 718. http://www.karlrunge.com/x11vnc/ssl.html + 719. http://www.karlrunge.com/x11vnc/single-click.html + 720. http://www.karlrunge.com/x11vnc/single-click.html#libssl-problems + 721. http://www.samba.org/ 722. http://www.karlrunge.com/x11vnc/ssvnc.html - 723. http://www.karlrunge.com/x11vnc/ssvnc.html - 724. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nobell - 725. http://www.karlrunge.com/x11vnc/faq.html#faq-sound - 726. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd - 727. http://jungla.dit.upm.es/~acosta/paginas/vncIPv6.html + 723. http://www.cups.org/ + 724. http://www.karlrunge.com/x11vnc/ssvnc.html + 725. http://www.karlrunge.com/x11vnc/ssvnc.html + 726. http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-nobell + 727. http://www.karlrunge.com/x11vnc/faq.html#faq-sound + 728. http://www.karlrunge.com/x11vnc/faq.html#faq-inetd + 729. http://jungla.dit.upm.es/~acosta/paginas/vncIPv6.html ======================================================================= http://www.karlrunge.com/x11vnc/chainingssh.html: @@ -10660,9 +10676,9 @@ http://www.karlrunge.com/x11vnc/ssl-portal.html: Background: The typical way to allow access to x11vnc (or any other VNC server) - running on workstations inside a firewall is via SSH. The user - somewhere out on the Internet logs in to the SSH gateway machine and - uses port forwarding (e.g. ssh -t -L 5900:myworkstation:5900 + running on multiple workstations inside a firewall is via SSH. The + user somewhere out on the Internet logs in to the SSH gateway machine + and uses port forwarding (e.g. ssh -t -L 5900:myworkstation:5900 user@gateway) to set up the encrypted channel that VNC is then tunneled through. Next he starts up the VNC viewer on the machine where he is sitting directed to the local tunnel port (e.g. @@ -10695,8 +10711,11 @@ http://www.karlrunge.com/x11vnc/ssl-portal.html: ([2]ss_vncviewer) can also take advantage of the method described here with its -proxy option. - This apache solution may be too much for you, see [3]below for some - simpler non-SSH encrypted setups. + Simpler Solutions: This apache solution may be too much for you. It is + mainly intended for automatically redirecting to multiple workstations + inside the firewall. If you only have one inside machine that you want + to access, the method described here is overly complicated. See + [3]below for some simpler (non-SSH) encrypted setups. There are numerous ways to achieve this with Apache. We present one of the simplest ones here. diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/README b/x11vnc/misc/enhanced_tightvnc_viewer/README index 2b56a83..a9080da 100644 --- a/x11vnc/misc/enhanced_tightvnc_viewer/README +++ b/x11vnc/misc/enhanced_tightvnc_viewer/README @@ -1,6 +1,6 @@ Enhanced TightVNC Viewer (SSVNC: SSL/SSH VNC viewer) -Copyright (c) 2006-2008 Karl J. Runge +Copyright (c) 2006-2009 Karl J. Runge All rights reserved. These bundles provide 1) An enhanced TightVNC Viewer on Unix, 2) Binaries @@ -108,7 +108,8 @@ The enhanced TightVNC viewer features are: "Terminal Services" mode (uses x11vnc on the remote side). - (the following features only apply to the bundled Unix tightvnc viewer) + (the following features only apply to the bundled Unix tightvnc viewer + including MacOS X) - rfbNewFBSize VNC support (screen resizing) @@ -119,10 +120,22 @@ The enhanced TightVNC viewer features are: - Support for the ZYWRLE encoding, a wavelet based extension to ZRLE to improve compression of motion video and photo regions. + - TurboVNC support (VirtualGL's modified TightVNC encoding; + requires TurboJPEG library) + + - Pipelined Updates of the framebuffer as in TurboVNC (asks for + the next update before the current one has finished downloading; + this gives some speedup on high latency connections.) + - Cursor alphablending with x11vnc at 32bpp (-alpha option) - Option "-unixpw ..." for use with "x11vnc -unixpw" login dialogs. + - VeNCrypt SSL/TLS VNC encryption support (used by VeNCrypt, + QEMU, ggi, libvirt/virt-manager/xen, vinagre/gvncviewer/gtk-vnc) + + - ANONTLS SSL/TLS VNC encryption support (used by vino) + - Support for UltraVNC extensions: Single Window, Disable Server-side Input, 1/n Server side scaling, Text Chat (shell terminal UI). Both UltraVNC and x11vnc servers support these @@ -141,6 +154,11 @@ The enhanced TightVNC viewer features are: - Support for UltraVNC DSM Encryption Plugin mode. (ARC4 and AESV2, and MSRC4) + - Support for UltraVNC MS-Logon authentication (NOTE: the UltraVNC + MS-Logon key exchange implementation is very weak; an eavesdropper + on the network can recover your Windows password easily; you + need to use an additional encrypted tunnel with MS-Logon.) + - Support for symmetric encryption (including blowfish and 3des ciphers) to Non-UltraVNC Servers. Any server using the same encryption method will work, e.g.: x11vnc -enc blowfish:./my.key @@ -174,12 +192,18 @@ The enhanced TightVNC viewer features are: - Scrollbar width setting: -sbwidth n, the default is very thin, 2 pixels, for less distracting -ycrop usage. + - Selection text sending and receiving can be fine-tuned with the + -sendclipboard, -sendalways, and -recvtext options. + + - TightVNC compression and quality levels are automatically set + based on observed network latency (n.b. not bandwidth.) + - Improvements to the Popup menu, all of these can now be changed dynamically via the menu: ViewOnly, Toggle Bell, CursorShape updates, X11 Cursor, Cursor Alphablending, Toggle Tight/ZRLE, Toggle JPEG, FullColor/16bpp/8bpp (256/64/8 colors), Greyscale for low color modes, Scaling the Viewer resolution, Escape Keys, - and others, including UltraVNC extensions. + Pipeline Updates, and others, including UltraVNC extensions. - Maintains its own BackingStore if the X server does not @@ -220,7 +244,7 @@ Unix and Mac OS X: Unpack the archive: - % gzip -dc ssvnc-1.0.21.tar.gz | tar xvf - + % gzip -dc ssvnc-1.0.22.tar.gz | tar xvf - Run the GUI: @@ -228,7 +252,7 @@ Unix and Mac OS X: % ./ssvnc/MacOSX/ssvnc (for Mac OS X) - The smaller file "ssvnc_no_windows-1.0.21.tar.gz" + The smaller file "ssvnc_no_windows-1.0.22.tar.gz" could have been used as well. On MacOSX you could also click on the SSVNC app icon in the Finder. @@ -274,8 +298,8 @@ Unix/MacOSX Install: For the conventional source tarball it will compile and install, e.g.: - gzip -dc ssvnc-1.0.21.src.tar.gz | tar xvf - - cd ssvnc-1.0.21 + gzip -dc ssvnc-1.0.22.src.tar.gz | tar xvf - + cd ssvnc-1.0.22 make config make all make PREFIX=/my/install/dir install @@ -287,7 +311,7 @@ Windows: Unzip, using WinZip or a similar utility, the zip file: - ssvnc-1.0.21.zip + ssvnc-1.0.22.zip Run the GUI, e.g.: @@ -299,7 +323,7 @@ Windows: select Open, and then OK to launch it. - The smaller file "ssvnc_windows_only-1.0.21.zip" + The smaller file "ssvnc_windows_only-1.0.22.zip" could have been used as well. You can make a Windows shortcut to this program if you want to. @@ -439,6 +463,30 @@ Most Mac OS X and Unix OS come with the main components installed. See the README.src for a more detailed description of dependencies. +TurboVNC Support: +---------------- + +TurboVNC is supported in an experimental way. To it build via the +build.unix script described in the next section, do something like: + + env TURBOVNC='-L/DIR -Xlinker --rpath=/DIR -lturbojpeg' ./build.unix + +where you replace /DIR with the directory where the libturbojpeg.so +(http://sourceforge.net/project/showfiles.php?group_id=117509&package_id=166100) +is installed. + +You may not need to set rpath if libturbojpeg.so is installed in a +standard location or you use LD_LIBRARY_PATH to point to it. + +See the turbovnc/README in the vnc_unixsrc/vncviewer directory for +more info. You can find it in the ssvnc source tarball and also +in: + + src/zips/vnc_unixsrc_vncviewer.patched.tar + +More TurboVNC features will be enabled in the future. + + If you need to Build: -------------------- @@ -685,7 +733,7 @@ For more help on other options and usage patterns run these: See also: http://www.karlrunge.com/x11vnc - http://www.karlrunge.com/x11vnc/#faq + http://www.karlrunge.com/x11vnc/faq.html x11vnc -h | more http://www.stunnel.org diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/Windows/README.txt b/x11vnc/misc/enhanced_tightvnc_viewer/Windows/README.txt index cd05820..4d816d2 100644 --- a/x11vnc/misc/enhanced_tightvnc_viewer/Windows/README.txt +++ b/x11vnc/misc/enhanced_tightvnc_viewer/Windows/README.txt @@ -37,7 +37,7 @@ and also: You can use x11vnc to create certificates if you like: - http://www.karlrunge.com/x11vnc/#faq-ssl-ca + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca Misc: diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd b/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd index 08cae7f..8c3f054 100755 --- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd +++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd @@ -249,6 +249,16 @@ if [ $use_ours = 1 ]; then SSVNC_USE_OURS=1; export SSVNC_USE_OURS + if [ "X$SSVNC_TURBOVNC" != "X" ]; then + if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then + : + else + if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then + VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc" + fi + fi + fi + if [ "X$base" = "Xtightvncviewer" ]; then $VNCVIEWERCMD -encodings 'copyrect tight zrle zlib hextile' "$@" else diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer index 2231108..ec004c7 100755 --- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer +++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer @@ -46,8 +46,8 @@ # -showcert Only fetch the certificate using the 'openssl s_client' # command (openssl(1) must in installed). # -# See http://www.karlrunge.com/x11vnc/#faq-ssl-ca for details on SSL -# certificates with VNC. +# See http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca for details on +# SSL certificates with VNC. # # A few other args (not related to SSL and certs): # @@ -115,6 +115,15 @@ # VNCIPCMD=${VNCVIEWERCMD:-vncip} VNCVIEWERCMD=${VNCVIEWERCMD:-vncviewer} +if [ "X$SSVNC_TURBOVNC" != "X" ]; then + if echo "$VNCVIEWERCMD" | grep '\.turbovnc' > /dev/null; then + : + else + if type "$VNCVIEWERCMD.turbovnc" > /dev/null 2>/dev/null; then + VNCVIEWERCMD="$VNCVIEWERCMD.turbovnc" + fi + fi +fi # # Same for STUNNEL, e.g. set it to /path/to/stunnel or stunnel4, etc. # @@ -268,6 +277,12 @@ do ;; "-onelisten") SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE ;; + "-sendclipboard") VNCVIEWER_SEND_CLIPBOARD=1; export VNCVIEWER_SEND_CLIPBOARD + ;; + "-sendalways") VNCVIEWER_SEND_ALWAYS=1; export VNCVIEWER_SEND_ALWAYS + ;; + "-recvtext") shift; VNCVIEWER_RECV_TEXT="$1"; export VNCVIEWER_RECV_TEXT + ;; "-escape") shift; VNCVIEWER_ESCAPE="$1"; export VNCVIEWER_ESCAPE ;; "-ssvnc_encodings") shift; VNCVIEWER_ENCODINGS="$1"; export VNCVIEWER_ENCODINGS @@ -751,6 +766,19 @@ if (exists $ENV{SSVNC_PREDIGESTED_HANDSHAKE}) { $handshake_file = $ENV{SSVNC_PREDIGESTED_HANDSHAKE}; } +my $have_gettimeofday = 0; +eval "use Time::HiRes"; +if ($@ eq "") { + $have_gettimeofday = 1; +} +sub gettime { + my $t = "0.0"; + if ($have_gettimeofday) { + $t = Time::HiRes::gettimeofday(); + } + return $t; +} + sub append_handshake { my $str = shift; if ($handshake_file) { @@ -1324,12 +1352,19 @@ sub vencrypt_dialog { } elsif ($minor == 7) { $viewer_rfb = "RFB 003.007\n"; } - syswrite($sock, $viewer_rfb, 12); - append_handshake("viewer=$viewer_rfb"); - my $nsec; + my $t1 = gettime(); + my $t0 = gettime(); + syswrite($sock, $viewer_rfb, 12); sysread($sock, $nsec, 1); + + $t1 = gettime(); + $t1 = sprintf("%.6f", $t1 - $t0); + + append_handshake("viewer=$viewer_rfb"); + append_handshake("latency=$t1\n"); + vdie if $nsec eq ""; $nsec = unpack("C", $nsec); diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl index 78672ed..354d610 100755 --- a/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl +++ b/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl @@ -472,7 +472,7 @@ proc help {} { steps of setting up a Certificate Authority (CA) to sign the VNC server and/or VNC client Certs, that can be used instead and avoids the need to manually verify every cert while still authenticating every connection. - More info: http://www.karlrunge.com/x11vnc/#faq-ssl-ca + More info: http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-ca See the cmdline option -cacert file below in 'SSL Certificates' for setting a default ServerCert/CA Cert. @@ -662,7 +662,7 @@ proc help {} { See also these links for more information: - http://www.karlrunge.com/x11vnc/#faq-ssl-tunnel-ext + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext http://www.stunnel.org http://www.tightvnc.com } @@ -828,8 +828,8 @@ proc help {} { See the ss_vncviewer description and x11vnc FAQ for info on proxies: - http://www.karlrunge.com/x11vnc/#ss_vncviewer - http://www.karlrunge.com/x11vnc/#faq-ssl-java-viewer-proxy + http://www.karlrunge.com/x11vnc/faq.html#ss_vncviewer + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-java-viewer-proxy SSH Proxies/Gateways: @@ -1719,7 +1719,7 @@ proc help_certs {} { See the x11vnc and STUNNEL documentation for how to create and use PEM certificate files: - http://www.karlrunge.com/x11vnc/#faq-ssl-tunnel-ext + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-ext http://www.karlrunge.com/x11vnc/ssl.html http://www.stunnel.org @@ -1903,7 +1903,7 @@ set msg { x11vnc has an experiment Client-Side caching scheme "-ncache n" that can give nice speedups. But there are some drawbacks because the cache-region is visible and uses much RAM. - http://www.karlrunge.com/x11vnc/#faq-client-caching + http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching X11VNC Options: @@ -2644,7 +2644,8 @@ proc set_defaults {} { global defs env global mycert svcert crtdir crlfil - global use_alpha use_grab use_ssl use_ssh use_sshssl use_viewonly use_fullscreen use_bgr233 + global use_alpha use_turbovnc use_grab use_ssl use_ssh use_sshssl use_viewonly use_fullscreen use_bgr233 + global use_send_clipboard use_send_always global disable_all_encryption global use_nojpeg use_raise_on_beep use_compresslevel use_quality use_x11_macosx global compresslevel_text quality_text @@ -2683,6 +2684,9 @@ proc set_defaults {} { set defs(use_raise_on_beep) 0 set defs(use_bgr233) 0 set defs(use_alpha) 0 + set defs(use_send_clipboard) 0 + set defs(use_send_always) 0 + set defs(use_turbovnc) 0 set defs(server_vencrypt) 0 set defs(server_anondh) 0 set defs(use_grab) 0 @@ -2825,6 +2829,7 @@ proc set_defaults {} { proc do_viewer_windows {n} { global use_alpha use_grab use_x11cursor use_nobell use_ssh use_sshssl use_viewonly use_fullscreen use_bgr233 global use_nojpeg use_raise_on_beep use_compresslevel use_quality + global use_send_clipboard use_send_always global change_vncviewer change_vncviewer_path vncviewer_realvnc4 global use_listen disable_ssl_workarounds disable_ssl_workarounds_type env @@ -5543,6 +5548,7 @@ proc reset_stunnel_extra_opts {} { set env(SSVNC_MULTIPLE_LISTEN) $ssvnc_multiple_listen0 } set env(SSVNC_ULTRA_DSM) "" + set env(SSVNC_TURBOVNC) "" } proc launch_unix {hp} { @@ -5988,6 +5994,15 @@ proc launch_unix {hp} { if {$use_alpha} { set cmd "$cmd -alpha" } + if {$use_send_clipboard} { + set cmd "$cmd -sendclipboard" + } + if {$use_send_always} { + set cmd "$cmd -sendalways" + } + if {$use_turbovnc} { + set env(SSVNC_TURBOVNC) 1 + } if {$use_grab} { set cmd "$cmd -grab" } @@ -8045,7 +8060,7 @@ proc create_cert {{name ""}} { For more information see: http://www.karlrunge.com/x11vnc/ssl.html - http://www.karlrunge.com/x11vnc/#faq-ssl-tunnel-int + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tunnel-int The first one describes how to use x11vnc to create Certificate Authority (CA) certificates in addition to self-signed ones. @@ -10300,9 +10315,9 @@ proc ts_xlogin_dialog {} { not x11vnc. Note that the GDM display manager has a setting KillInitClients in - gdm.conf that will kill x11vnc right after you log in, and so you - would have to repeat the whole process ('Connect' button) to attach to - your session. See http://www.karlrunge.com/x11vnc/#faq-display-manager + gdm.conf that will kill x11vnc right after you log in, and so you would + have to repeat the whole process ('Connect' button) to attach to your + session. See http://www.karlrunge.com/x11vnc/faq.html#faq-display-manager for more info. } .xlog.f.t insert end $msg @@ -10444,7 +10459,7 @@ proc ts_ncache_dialog {} { for the caching region. So 10 means use 10 times the RAM to store pixmaps. The default is 8. - More info: http://www.karlrunge.com/x11vnc/#faq-client-caching + More info: http://www.karlrunge.com/x11vnc/faq.html#faq-client-caching } .nche.f.t insert end $msg @@ -10505,7 +10520,7 @@ proc ts_x11vnc_opts_dialog {} { -repeat -cursor -wmdt -nowireframe -ncache_cr -speeds - More info: http://www.karlrunge.com/x11vnc/#faq-cmdline-opts + More info: http://www.karlrunge.com/x11vnc/faq.html#faq-cmdline-opts } # In Auto Port put a starting port for x11vnc to try autoprobing # instead of the default 5900. It starts at the value you supply and @@ -10571,7 +10586,7 @@ proc ts_filexfer_dialog {} { The defaults for the SSVNC viewer package are TightVNC on Windows and UltraVNC on Unix. - For more info see: http://www.karlrunge.com/x11vnc/#faq-filexfer + For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-filexfer } .xfer.f.t insert end $msg @@ -10673,7 +10688,7 @@ proc ts_cups_dialog {} { http://localhost:port/printers/printername - For more info see: http://www.karlrunge.com/x11vnc/#faq-cups + For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-cups } # The "Manage 'ServerName' in .cups/client.conf for me" setting is usually @@ -10946,7 +10961,7 @@ proc cups_dialog {} { that knows about your Windows printer, you might have better luck with that instead of using SMB. Set 'Local CUPS Server' to it. - For more info see: http://www.karlrunge.com/x11vnc/#faq-cups + For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-cups } .cups.f.t insert end $msg @@ -11058,7 +11073,7 @@ proc ts_sound_dialog {} { And esd's LD_PRELOAD is broken on 64+32bit Linux (x86_64). And so this mode is not working well currently... - For more info see: http://www.karlrunge.com/x11vnc/#faq-sound + For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-sound } @@ -11187,7 +11202,7 @@ proc sound_dialog {} { a numerical port to specify non-localhost connections, e.g. to another nearby machine. - For more info see: http://www.karlrunge.com/x11vnc/#faq-sound + For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-sound } .snd.f.t insert end $msg @@ -11972,7 +11987,7 @@ proc smb_dialog {} { the share, become root and umount the shares manually ("smbumount /path/to/share", etc.) - For more info see: http://www.karlrunge.com/x11vnc/#faq-smb-shares + For more info see: http://www.karlrunge.com/x11vnc/faq.html#faq-smb-shares } set msg2 { @@ -12244,6 +12259,29 @@ proc help_ssvncviewer_opts {} { Use the x11vnc alpha hack for translucent cursors (requires Unix, 32bpp and same endianness) + TurboVNC: + + If available on your platform, use a ssvncviewer compiled with + TurboVNC support. This is based on the the VirtualGL project: + http://www.sourceforge.net/projects/virtualgl You will need + to install the VirtualGL's TurboJPEG library too. + + Currently (May/2009) only Linux.i686, Linux.x86_64, and + Darwin.i386 have vncviewer.turbovnc binaries shipped in the + ssvnc bundles. See the build instructions for how you might + compile your own. + + Send CLIPBOARD not PRIMARY: + + When sending locally selected text to the VNC server side, + send the CLIPBOARD selection instead of the PRIMARY selection. + + Send Selection Every time: + + Send selected text to the VNC server side every time the mouse + focus enters the main VNC Viewer window instead only when it + appears to have changed since the last send. + Scaling: Use viewer-side (i.e. local) scaling of the VNC screen. Supply @@ -12293,24 +12331,61 @@ proc help_ssvncviewer_opts {} { These are environment variables one may set to affect the options of the SSVNC vncviewer: - VNCVIEWER_ALPHABLEND (-alpha, see Cursor Alphablending above) - VNCVIEWER_POPUP_FIX (-popupfix, warp popup to mouse location) - VNCVIEWER_GRAB_SERVER (-graball, see Use XGrabServer above) - VNCVIEWER_YCROP (-ycrop, see Y Crop above) - VNCVIEWER_SBWIDTH (-sbwidth, see ScrollBar Width above) - VNCVIEWER_RFBVERSION (-rfbversion, e.g. 3.6) - VNCVIEWER_ENCODINGS (-encodings, e.g. "copyrect zrle hextile") - VNCVIEWER_NOBELL (-nobell) - VNCVIEWER_X11CURSOR (-x11cursor, see Use X11 Cursor above) - VNCVIEWER_RAWLOCAL (-rawlocal, see Use Raw Local above) - VNCVIEWER_ESCAPE (-escape, see Escape Keys above) - SSVNC_MULTIPLE_LISTEN (-multilisten, see Mulitple LISTEN above) - SSVNC_UNIXPW (-unixpw) - SSVNC_UNIXPW_NOESC (do not send escape in -unixpw mode) - SSVNC_SCALE (-scale, see Scaling above) - SSVNC_NOSOLID (do not do solid region speedup in - scaling mode.) - SSVNC_PRESERVE_ENCODING (do not switch to ZRLE when scaling) + VNCVIEWER_ALPHABLEND (-alpha, see Cursor Alphablending above) + VNCVIEWER_POPUP_FIX (-popupfix, warp popup to mouse location) + VNCVIEWER_GRAB_SERVER (-graball, see Use XGrabServer above) + VNCVIEWER_YCROP (-ycrop, see Y Crop above) + VNCVIEWER_SBWIDTH (-sbwidth, see ScrollBar Width above) + VNCVIEWER_RFBVERSION (-rfbversion, e.g. 3.6) + VNCVIEWER_ENCODINGS (-encodings, e.g. "copyrect zrle hextile") + VNCVIEWER_NOBELL (-nobell) + VNCVIEWER_X11CURSOR (-x11cursor, see Use X11 Cursor above) + VNCVIEWER_RAWLOCAL (-rawlocal, see Use Raw Local above) + VNCVIEWER_ESCAPE (-escape, see Escape Keys above) + VNCVIEWER_ULTRADSM (-ultradsm) + VNCVIEWER_SEND_CLIPBOARD (-sendclipboard) + VNCVIEWER_SEND_ALWAYS (-sendalways) + VNCVIEWER_RECV_TEXT (-recvtext clipboard/primary/both) + VNCVIEWER_NO_CUTBUFFER (do not send CUTBUFFER0 as fallback) + + SSVNC_MULTIPLE_LISTEN (-multilisten, see Multiple LISTEN above) + SSVNC_TURBOVNC (see TurboVNC above) + SSVNC_UNIXPW (-unixpw) + SSVNC_UNIXPW_NOESC (do not send escape in -unixpw mode) + SSVNC_SCALE (-scale, see Scaling above) + SSVNC_NOSOLID (do not do solid region speedup in + scaling mode.) + SSVNC_PRESERVE_ENCODING (do not switch to ZRLE when scaling) + + Misc (special usage or debugging): + + SSVNC_NO_ULTRA_DSM + SSVNC_ULTRA_FTP_JAR + SSVNC_SCALE_STATS + SSVNC_DEBUG_RELEASE + SSVNC_DEBUG_ESCAPE_KEYS + SSVNC_NO_MAYBE_SYNC + SSVNC_MAX_LISTEN + SSVNC_LISTEN_ONCE + SSVNC_EXIT_DEBUG + SSVNC_DEBUG_CHAT + SSVNC_NO_MESSAGE_POPUP + SSVNC_SET_SECURITY_TYPE + SSVNC_PREDIGESTED_HANDSHAKE + SSVNC_SKIP_RFB_PROTOCOL_VERSION + SSVNC_DEBUG_SEC_TYPES + SSVNC_DEBUG_MSLOGON + SSVNC_DEBUG_RECTS + SSVNC_DEBUG_CHAT + SSVNC_DELAY_SYNC + SSVNC_DEBUG_SELECTION + SSVNC_REPEATER + SSVNC_VENCRYPT_DEBUG + SSVNC_STUNNEL_DEBUG + SSVNC_TEST_SEC_TYPE + SSVNC_LIM_ACCEPT_PRELOAD + SSVNC_EXTRA_SLEEP + SSVNC_SOCKS5 } .av.f.t insert end $msg @@ -12660,10 +12735,17 @@ proc ultra_dsm_dialog {} { set msg { On Unix with the provided SSVNC vncviewer, you can connect to an UltraVNC - server that is using one of its encryption plugins: MSRC4, ARC4, or AESV2. + server that is using one of its DSM encryption plugins: MSRC4, ARC4, AESV2. + More info at: http://www.uvnc.com/features/encryption.html + + IMPORTANT: The UltraVNC DSM implementation contains unfixed errors + that could allow an eavesdropper to recover the session key or traffic + relatively easily. They often do not provide strong encryption, but + only provide basic obscurity instead. Do not use them with critical data. See the bottom of this help text for how to use symmetric encryption with - NON-UltraVNC servers (for example, x11vnc 0.9.5 or later). + Non-UltraVNC servers (for example, x11vnc 0.9.5 or later). This mode does + not suffer the shortcomings of the UltraVNC DSM implementation. You will need to specify the corresponding UltraVNC encryption key (created by you using an UltraVNC server or viewer). It is usually called 'rc4.key' @@ -14070,7 +14152,8 @@ proc set_advanced_options {} { proc set_ssvncviewer_options {} { global is_windows darwin_cotvnc - global use_ssh use_sshssl use_x11cursor use_rawlocal use_popupfix use_alpha use_grab use_nobell + global use_ssh use_sshssl use_x11cursor use_rawlocal use_popupfix use_alpha use_turbovnc use_grab use_nobell + global use_send_clipboard use_send_always global ssvnc_scale ssvnc_escape global server_vencrypt server_anondh @@ -14131,7 +14214,22 @@ proc set_ssvncviewer_options {} { incr i checkbutton .os.b$i -anchor w -variable use_alpha -text \ - "Cursor alphablending (32bpp required)" + "Cursor Alphablending (32bpp required)" + lappend darwinlist .os.b$i; if {$darwin_cotvnc} {.os.b$i configure -state disabled} + incr i + + checkbutton .os.b$i -anchor w -variable use_turbovnc -text \ + "TurboVNC (if available on platform)" + lappend darwinlist .os.b$i; if {$darwin_cotvnc} {.os.b$i configure -state disabled} + incr i + + checkbutton .os.b$i -anchor w -variable use_send_clipboard -text \ + "Send CLIPBOARD not PRIMARY" + lappend darwinlist .os.b$i; if {$darwin_cotvnc} {.os.b$i configure -state disabled} + incr i + + checkbutton .os.b$i -anchor w -variable use_send_always -text \ + "Send Selection Every time" lappend darwinlist .os.b$i; if {$darwin_cotvnc} {.os.b$i configure -state disabled} incr i @@ -14678,6 +14776,7 @@ proc disable_encryption {} { proc set_options {} { global use_alpha use_grab use_ssh use_sshssl use_viewonly use_fullscreen use_bgr233 global use_nojpeg use_raise_on_beep use_compresslevel use_quality use_x11_macosx + global use_send_clipboard use_send_always global compresslevel_text quality_text global env is_windows darwin_cotvnc uname global use_listen diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/build.unix b/x11vnc/misc/enhanced_tightvnc_viewer/build.unix index d4899f2..bd258ed 100755 --- a/x11vnc/misc/enhanced_tightvnc_viewer/build.unix +++ b/x11vnc/misc/enhanced_tightvnc_viewer/build.unix @@ -137,8 +137,11 @@ do if [ "X$SSVNC_BUILD_STATIC" = "X" ]; then break fi - for dir in /usr/lib /lib /usr/local/lib /usr/pkg/lib /usr/sfw/lib /usr/openwin/lib + for dir in $SSVNC_STATIC_DIRS /usr/lib /lib /usr/local/lib /usr/pkg/lib /usr/sfw/lib /usr/openwin/lib do + if [ "X$dir" = "X" ]; then + continue + fi if [ "$name" = "Linux.x86_64" -o "$name" = "Linux.ppc64" ] ; then dir64=`echo "$dir" | sed -e 's,lib,lib64,'` if [ "X$SSVNC_BUILD_NO_LINUX64" != "X" ]; then @@ -149,7 +152,9 @@ do fi try="$dir/$liba" if [ -f $try ]; then - cp -p "$try" $libs + echo cp -p "$try" $libs + cp -p "$try" $libs + break fi done done @@ -279,7 +284,11 @@ if [ "X$SSVNC_BUILD_SKIP_VIEWER" = "X" ]; then make depend echo $PATH - make all + if [ "X$TURBOVNC" = "X" ]; then + make all + else + make CCOPTIONS="-DTURBOVNC $CPPFLAGS_OS" EXTRA_LIBRARIES="$TURBOVNC" all + fi ls -l vncviewer/vncviewer cd "$start" src=$tmp/vnc_unixsrc/vncviewer/vncviewer @@ -298,6 +307,9 @@ if [ "X$SSVNC_BUILD_SKIP_VIEWER" = "X" ]; then if [ `uname` = "Darwin" ]; then suff=".x11" fi + if [ "X$TURBOVNC" != "X" ]; then + suff="$suff.turbovnc" + fi echo cp -p $src $dest/vncviewer$suff sleep 1 cp -p $src $dest/vncviewer$suff || exit 1 diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/man/man1/ssvncviewer.1 b/x11vnc/misc/enhanced_tightvnc_viewer/man/man1/ssvncviewer.1 index 6cdc70d..10698f5 100644 --- a/x11vnc/misc/enhanced_tightvnc_viewer/man/man1/ssvncviewer.1 +++ b/x11vnc/misc/enhanced_tightvnc_viewer/man/man1/ssvncviewer.1 @@ -5,13 +5,13 @@ .\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de .\" Copyright (C) 2000,2001 Red Hat, Inc. .\" Copyright (C) 2001-2003 Constantin Kaplinsky -.\" Copyright (C) 2006-2008 Karl J. Runge +.\" Copyright (C) 2006-2009 Karl J. Runge .\" .\" You may distribute under the terms of the GNU General Public .\" License as specified in the file LICENCE.TXT that comes with the .\" TightVNC distribution. .\" -.TH ssvncviewer 1 "December 2008" "" "SSVNC" +.TH ssvncviewer 1 "June 2009" "" "SSVNC" .SH NAME ssvncviewer \- an X viewer client for VNC .SH SYNOPSIS @@ -300,6 +300,24 @@ Disable bell. Prefer raw encoding for localhost, default is no, i.e. assumes you have a SSH tunnel instead. .TP +\fB\-sendclipboard\fR +Send the X CLIPBOARD selection (i.e. Ctrl+C, +Ctrl+V) instead of the X PRIMARY selection (mouse +select and middle button paste.) +.TP +\fB\-sendalways\fR +Whenever the mouse enters the VNC viewer main +window, send the selection to the VNC server even if +it has not changed. This is like the Xt resource +translation SelectionToVNC(always) +.TP +\fB\-recvtext\fR +str When cut text is received from the VNC server, +ssvncviewer will set both the X PRIMARY and the +X CLIPBOARD local selections. To control which +is set, specify 'str' as 'primary', 'clipboard', +or 'both' (the default.) +.TP \fB\-graball\fR Grab the entire X server when in fullscreen mode, needed by some old window managers like fvwm2. @@ -396,6 +414,18 @@ THAT supply -ultradsm to tell THIS viewer to modify the RFB data sent so as to work with the UltraVNC Server. For some reason, each RFB msg type must be sent twice under DSM. .TP +\fB\-mslogon\fR \fIuser\fR +Use Windows MS Logon to an UltraVNC server. Supply the +username or "1" to be prompted. The default is to +autodetect the UltraVNC MS Logon server and prompt for +the username and password. + +IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman +exchange is very weak and can be brute forced to recover +your username and password in a few hours or seconds of CPU +time. To be safe, be sure to use an additional encrypted +tunnel (e.g. SSL or SSH) for the entire VNC session. +.TP \fB\-chatonly\fR Try to be a client that only does UltraVNC text chat. This mode is used by x11vnc to present a chat window on the physical @@ -412,6 +442,12 @@ then exit. You can save them to a file and customize them (e.g. the keybindings and Popup menu) Then point to the file via XENVIRONMENT or XAPPLRESDIR. .TP +\fB\-pipeline\fR +Like TurboVNC, request the next framebuffer update as soon +as possible instead of waiting until the end of the current +framebuffer update coming in. Helps 'pipeline' the updates. +This is currently the default, use \fB-nopipeline\fR to disable. +.TP \fB\-escape \fR\fIstr\fR This sets the 'Escape Keys' modifier sequence and enables escape keys mode. When the modifier keys escape sequence @@ -487,8 +523,10 @@ Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. Quality Level ~ -quality (both Tight and ZYWRLE) Compress Level ~ -compresslevel Disable JPEG: ~ -nojpeg (Tight) - Full Color ~ as many colors as local screen allows. - Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes. + Pipeline Updates ~ -pipeline + + Full Color as many colors as local screen allows. + Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. 16 bit color (BGR565) ~ -16bpp / -bgr565 8 bit color (BGR233) ~ -bgr233 256 colors ~ -bgr233 default # of colors. @@ -503,16 +541,19 @@ Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. UltraVNC Extensions: - Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. - Text Chat Ultravnc ext. Do Text Chat. - File Transfer Ultravnc ext. File xfer via Java helper. - Single Window Ultravnc ext. Grab a single window. - (click on the window you want). - Disable Remote Input Ultravnc ext. Try to prevent input and - viewing of monitor at physical display. + Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. + Text Chat Ultravnc ext. Do Text Chat. + File Transfer Ultravnc ext. File xfer via Java helper. + Single Window Ultravnc ext. Grab and view a single window. + (select then click on the window you want). + Disable Remote Input Ultravnc ext. Try to prevent input and + viewing of monitor at physical display. + + Note: the Ultravnc extensions only apply to servers that support + them. x11vnc/libvncserver supports some of them. - Note: the Ultravnc extensions only apply to servers that - support them. x11vnc/libvncserver supports some of them. + Send Clipboard not Primary ~ -sendclipboard + Send Selection Every time ~ -sendalways .SH ENCODINGS The server supplies information in whatever format is desired by the diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch index f0fd036..5af9ea9 100644 --- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch +++ b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch @@ -664,7 +664,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncview + diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/vncviewer/argsresources.c --- vnc_unixsrc.orig/vncviewer/argsresources.c 2007-02-04 17:10:31.000000000 -0500 -+++ vnc_unixsrc/vncviewer/argsresources.c 2008-12-30 19:22:59.000000000 -0500 ++++ vnc_unixsrc/vncviewer/argsresources.c 2009-05-31 17:50:18.000000000 -0400 @@ -31,9 +31,9 @@ char *fallback_resources[] = { @@ -739,10 +739,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ : SendRFBEvent()\\n\ -@@ -58,23 +110,112 @@ +@@ -58,23 +110,123 @@ "*serverDialog.dialog.value.translations: #override\\n\ Return: ServerDialogDone()", ++ "*userDialog.dialog.label: Username:", ++ "*userDialog.dialog.value:", ++ "*userDialog.dialog.value.translations: #override\\n\ ++ Return: UserDialogDone()", ++ + "*scaleDialog.dialog.label: Scale: Enter 'none' (same as '1' or '1.0'),\\na geometry WxH (e.g. 1280x1024), or\\na fraction (e.g. 0.75 or 3/4).\\nUse 'fit' for full screen size.\\nUse 'auto' to match window size.\\nCurrent value:", + "*scaleDialog.dialog.value:", + "*scaleDialog.dialog.value.translations: #override\\n\ @@ -835,6 +840,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + "*scaleN.buttonForm.Command.borderWidth: 0", + "*scaleN.buttonForm.Toggle.borderWidth: 0", + ++ "*turboVNC.title: TurboVNC", ++ "*turboVNC*background: grey", ++ "*turboVNC*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", ++ "*turboVNC.buttonForm.Command.borderWidth: 0", ++ "*turboVNC.buttonForm.Toggle.borderWidth: 0", ++ + "*quality.title: quality", + "*quality*background: grey", + "*quality*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", @@ -852,12 +863,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v : SendRFBEvent() HidePopup()", - "*popupButtonCount: 8", -+ "*popupButtonCount: 38", -+ "*popupButtonBreak: 19", ++ "*popupButtonCount: 42", ++ "*popupButtonBreak: 21", "*popup*button1.label: Dismiss popup", "*popup*button1.translations: #override\\n\ -@@ -84,7 +225,7 @@ +@@ -84,7 +236,7 @@ "*popup*button2.translations: #override\\n\ ,: Quit()", @@ -866,7 +877,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v "*popup*button3.type: toggle", "*popup*button3.translations: #override\\n\ : SetFullScreenState()\\n\ -@@ -105,16 +246,332 @@ +@@ -105,16 +257,418 @@ "*popup*button7.label: Send ctrl-alt-del", "*popup*button7.translations: #override\\n\ ,: SendRFBEvent(keydown,Control_L)\ @@ -945,109 +956,195 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + : SetNOJPEGState()\\n\ + ,: toggle() ToggleJPEG() HidePopup()", + -+ "*popup*button20.label: Full Color", -+ "*popup*button20.type: toggle", ++ "*popup*button20.label: TurboVNC Settings", + "*popup*button20.translations: #override\\n\ -+ : SetFullColorState()\\n\ -+ ,: toggle() ToggleFullColor() HidePopup()", ++ ,: HidePopup() ShowTurboVNC()", + -+ "*popup*button21.label: Grey Scale (16 & 8-bpp)", ++ "*popup*button21.label: Pipeline Updates", + "*popup*button21.type: toggle", + "*popup*button21.translations: #override\\n\ -+ : SetGreyScaleState()\\n\ -+ ,: toggle() ToggleGreyScale() HidePopup()", ++ : SetPipelineUpdates()\\n\ ++ ,: toggle() TogglePipelineUpdates() HidePopup()", + -+ "*popup*button22.label: 16 bit color (BGR565)", ++ "*popup*button22.label: Full Color", + "*popup*button22.type: toggle", + "*popup*button22.translations: #override\\n\ -+ : Set16bppState()\\n\ -+ ,: toggle() Toggle16bpp() HidePopup()", ++ : SetFullColorState()\\n\ ++ ,: toggle() ToggleFullColor() HidePopup()", + -+ "*popup*button23.label: 8 bit color (BGR233)", ++ "*popup*button23.label: Grey Scale (16 & 8-bpp)", + "*popup*button23.type: toggle", + "*popup*button23.translations: #override\\n\ -+ : Set8bppState()\\n\ -+ ,: toggle() Toggle8bpp() HidePopup()", ++ : SetGreyScaleState()\\n\ ++ ,: toggle() ToggleGreyScale() HidePopup()", + -+ "*popup*button24.label: - 256 colors", ++ "*popup*button24.label: 16 bit color (BGR565)", + "*popup*button24.type: toggle", + "*popup*button24.translations: #override\\n\ -+ : Set256ColorsState()\\n\ -+ ,: toggle() Toggle256Colors() HidePopup()", ++ : Set16bppState()\\n\ ++ ,: toggle() Toggle16bpp() HidePopup()", + -+ "*popup*button25.label: - 64 colors", ++ "*popup*button25.label: 8 bit color (BGR233)", + "*popup*button25.type: toggle", + "*popup*button25.translations: #override\\n\ -+ : Set64ColorsState()\\n\ -+ ,: toggle() Toggle64Colors() HidePopup()", ++ : Set8bppState()\\n\ ++ ,: toggle() Toggle8bpp() HidePopup()", + -+ "*popup*button26.label: - 8 colors", ++ "*popup*button26.label: - 256 colors", + "*popup*button26.type: toggle", + "*popup*button26.translations: #override\\n\ -+ : Set8ColorsState()\\n\ -+ ,: toggle() Toggle8Colors() HidePopup()", ++ : Set256ColorsState()\\n\ ++ ,: toggle() Toggle256Colors() HidePopup()", + -+ "*popup*button27.label: Scale Viewer", ++ "*popup*button27.label: - 64 colors", ++ "*popup*button27.type: toggle", + "*popup*button27.translations: #override\\n\ -+ ,: HidePopup() SetScale()", ++ : Set64ColorsState()\\n\ ++ ,: toggle() Toggle64Colors() HidePopup()", + -+ "*popup*button28.label: Escape Keys: Toggle", ++ "*popup*button28.label: - 8 colors", + "*popup*button28.type: toggle", + "*popup*button28.translations: #override\\n\ ++ : Set8ColorsState()\\n\ ++ ,: toggle() Toggle8Colors() HidePopup()", ++ ++ "*popup*button29.label: Scale Viewer", ++ "*popup*button29.translations: #override\\n\ ++ ,: HidePopup() SetScale()", ++ ++ "*popup*button30.label: Escape Keys: Toggle", ++ "*popup*button30.type: toggle", ++ "*popup*button30.translations: #override\\n\ + : SetEscapeKeysState()\\n\ + , : toggle() ToggleEscapeActive() HidePopup()", + -+ "*popup*button29.label: Escape Keys: Help+Set", -+ "*popup*button29.translations: #override\\n\ ++ "*popup*button31.label: Escape Keys: Help+Set", ++ "*popup*button31.translations: #override\\n\ + , : HidePopup() SetEscapeKeys()", + -+ "*popup*button30.label: Set Y Crop (y-max)", -+ "*popup*button30.translations: #override\\n\ ++ "*popup*button32.label: Set Y Crop (y-max)", ++ "*popup*button32.translations: #override\\n\ + ,: HidePopup() SetYCrop()", + -+ "*popup*button31.label: Set Scrollbar Width", -+ "*popup*button31.translations: #override\\n\ ++ "*popup*button33.label: Set Scrollbar Width", ++ "*popup*button33.translations: #override\\n\ + ,: HidePopup() SetScbar()", + -+ "*popup*button32.label: XGrabServer", -+ "*popup*button32.type: toggle", -+ "*popup*button32.translations: #override\\n\ ++ "*popup*button34.label: XGrabServer", ++ "*popup*button34.type: toggle", ++ "*popup*button34.translations: #override\\n\ + : SetXGrabState()\\n\ + ,: toggle() ToggleXGrab() HidePopup()", + -+ "*popup*button33.label: UltraVNC Extensions:", -+ "*popup*button33.translations: #override\\n\ ++ "*popup*button35.label: UltraVNC Extensions:", ++ "*popup*button35.translations: #override\\n\ + ,: HidePopup()", + -+ "*popup*button34.label: - Set 1/n Server Scale", -+ "*popup*button34.translations: #override\\n\ ++ "*popup*button36.label: - Set 1/n Server Scale", ++ "*popup*button36.translations: #override\\n\ + ,: HidePopup() ShowScaleN()", + -+ "*popup*button35.label: - Text Chat", -+ "*popup*button35.type: toggle", -+ "*popup*button35.translations: #override\\n\ ++ "*popup*button37.label: - Text Chat", ++ "*popup*button37.type: toggle", ++ "*popup*button37.translations: #override\\n\ + : SetTextChatState()\\n\ + ,: toggle() ToggleTextChat() HidePopup()", + -+ "*popup*button36.label: - File Transfer", -+ "*popup*button36.type: toggle", -+ "*popup*button36.translations: #override\\n\ ++ "*popup*button38.label: - File Transfer", ++ "*popup*button38.type: toggle", ++ "*popup*button38.translations: #override\\n\ + : SetFileXferState()\\n\ + ,: toggle() ToggleFileXfer() HidePopup()", + -+ "*popup*button37.label: - Single Window", -+ "*popup*button37.type: toggle", -+ "*popup*button37.translations: #override\\n\ ++ "*popup*button39.label: - Single Window", ++ "*popup*button39.type: toggle", ++ "*popup*button39.translations: #override\\n\ + : SetSingleWindowState()\\n\ + ,: toggle() ToggleSingleWindow() HidePopup()", + -+ "*popup*button38.label: - Disable Remote Input", -+ "*popup*button38.type: toggle", -+ "*popup*button38.translations: #override\\n\ ++ "*popup*button40.label: - Disable Remote Input", ++ "*popup*button40.type: toggle", ++ "*popup*button40.translations: #override\\n\ + : SetServerInputState()\\n\ + ,: toggle() ToggleServerInput() HidePopup()", + -+// "*popup*button3x.label:", ++ "*popup*button41.label: Send Clipboard not Primary", ++ "*popup*button41.type: toggle", ++ "*popup*button41.translations: #override\\n\ ++ : SetSendClipboard()\\n\ ++ ,: toggle() ToggleSendClipboard() HidePopup()", ++ ++ "*popup*button42.label: Send Selection Every time", ++ "*popup*button42.type: toggle", ++ "*popup*button42.translations: #override\\n\ ++ : SetSendAlways()\\n\ ++ ,: toggle() ToggleSendAlways() HidePopup()", ++ ++ "*turboVNC*button0.label: Dismiss", ++ "*turboVNC*button0.translations: #override\\n\ ++ ,: HideTurboVNC()", ++ ++ "*turboVNC*button1.label: High Quality (LAN)", ++ "*turboVNC*button1.translations: #override\\n\ ++ ,: SetTurboVNC(1)", ++ ++ "*turboVNC*button2.label: Medium Quality", ++ "*turboVNC*button2.translations: #override\\n\ ++ ,: SetTurboVNC(2)", ++ ++ "*turboVNC*button3.label: Low Quality (WAN)", ++ "*turboVNC*button3.translations: #override\\n\ ++ ,: SetTurboVNC(3)", ++ ++ "*turboVNC*button4.label: Lossless (Gigabit)", ++ "*turboVNC*button4.translations: #override\\n\ ++ ,: SetTurboVNC(4)", ++ ++ "*turboVNC*button5.label: Lossless Zlib (WAN)", ++ "*turboVNC*button5.translations: #override\\n\ ++ ,: SetTurboVNC(5)", ++ ++ "*turboVNC*button6.label: Subsampling:", ++ ++ "*turboVNC*button7.label: - None", ++ "*turboVNC*button7.translations: #override\\n\ ++ ,: SetTurboVNC(6)", ++ ++ "*turboVNC*button8.label: - 2X", ++ "*turboVNC*button8.translations: #override\\n\ ++ ,: SetTurboVNC(7)", ++ ++ "*turboVNC*button9.label: - 4X", ++ "*turboVNC*button9.translations: #override\\n\ ++ ,: SetTurboVNC(8)", ++ ++ "*turboVNC*button10.label: - Gray", ++ "*turboVNC*button10.translations: #override\\n\ ++ ,: SetTurboVNC(9)", ++ ++ "*turboVNC*button11.label: Lossless Refresh", ++ "*turboVNC*button11.translations: #override\\n\ ++ ,: SetTurboVNC(10)", ++ ++ "*turboVNC*button12.label: Lossy Refresh", ++ "*turboVNC*button12.translations: #override\\n\ ++ ,: SendRFBEvent(fbupdate)", ++ ++ "*turboVNC*buttonNone.label: Not Compiled with\\nTurboVNC Support.", ++ "*turboVNC*buttonNone.translations: #override\\n\ ++ ,: HideTurboVNC()", ++ ++ "*qualLabel.label: JPEG Image Quality:", ++ "*qualBar.length: 100", ++ "*qualBar.width: 130", ++ "*qualBar.orientation: horizontal", ++ "*qualBar.translations: #override\\n\ ++ : StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ ++ : MoveThumb() NotifyThumb()\\n\ ++ : StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ ++ : MoveThumb() NotifyThumb()", ++ ++ "*qualText.label: 000", + + "*scaleN*button0.label: Dismiss", + "*scaleN*button0.translations: #override\\n\ @@ -1204,7 +1301,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v NULL }; -@@ -124,7 +581,7 @@ +@@ -124,7 +678,7 @@ * from a dialog box. */ @@ -1213,7 +1310,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v int vncServerPort = 0; -@@ -135,6 +592,7 @@ +@@ -135,6 +689,7 @@ */ AppData appData; @@ -1221,13 +1318,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v static XtResource appDataResourceList[] = { {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool), -@@ -155,14 +613,38 @@ +@@ -155,14 +710,41 @@ {"userLogin", "UserLogin", XtRString, sizeof(String), XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0}, + {"unixPW", "UnixPW", XtRString, sizeof(String), + XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0}, + ++ {"msLogon", "MSLogon", XtRString, sizeof(String), ++ XtOffsetOf(AppData, msLogon), XtRImmediate, (XtPointer) 0}, ++ + {"repeaterUltra", "RepeaterUltra", XtRString, sizeof(String), + XtOffsetOf(AppData, repeaterUltra), XtRImmediate, (XtPointer) 0}, + @@ -1262,7 +1362,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"nColours", "NColours", XtRInt, sizeof(int), XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256}, -@@ -179,9 +661,12 @@ +@@ -179,9 +761,12 @@ {"requestedDepth", "RequestedDepth", XtRInt, sizeof(int), XtOffsetOf(AppData, requestedDepth), XtRImmediate, (XtPointer) 0}, @@ -1276,7 +1376,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int), XtOffsetOf(AppData, wmDecorationWidth), XtRImmediate, (XtPointer) 4}, -@@ -191,6 +676,9 @@ +@@ -191,6 +776,9 @@ {"popupButtonCount", "PopupButtonCount", XtRInt, sizeof(int), XtOffsetOf(AppData, popupButtonCount), XtRImmediate, (XtPointer) 0}, @@ -1286,16 +1386,22 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"debug", "Debug", XtRBool, sizeof(Bool), XtOffsetOf(AppData, debug), XtRImmediate, (XtPointer) False}, -@@ -207,7 +695,7 @@ +@@ -206,11 +794,13 @@ + {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int), XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20}, ++ /* hardwired compress -1 vs . 7 */ {"compressLevel", "CompressionLevel", XtRInt, sizeof(int), -- XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1}, -+ XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) 7}, + XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1}, ++ /* hardwired quality was 6 */ {"qualityLevel", "QualityLevel", XtRInt, sizeof(int), - XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6}, -@@ -218,14 +706,63 @@ +- XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6}, ++ XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) -1}, + + {"enableJPEG", "EnableJPEG", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, enableJPEG), XtRImmediate, (XtPointer) True}, +@@ -218,14 +808,85 @@ {"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool), XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True}, @@ -1352,20 +1458,43 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"scale", "Scale", XtRString, sizeof(String), + XtOffsetOf(AppData, scale), XtRImmediate, (XtPointer) 0}, + -+ {"escapeKeys", "escapeKeys", XtRString, sizeof(String), ++ {"pipelineUpdates", "PipelineUpdates", XtRBool, sizeof(Bool), ++ XtOffsetOf(AppData, pipelineUpdates), XtRImmediate, (XtPointer) ++#ifdef TURBOVNC ++ True}, ++#else ++#if 0 ++ False}, ++#else ++ True}, ++#endif ++#endif ++ ++ {"sendClipboard", "SendClipboard", XtRBool, sizeof(Bool), ++ XtOffsetOf(AppData, sendClipboard), XtRImmediate, (XtPointer) False}, ++ ++ {"sendAlways", "SendAlways", XtRBool, sizeof(Bool), ++ XtOffsetOf(AppData, sendAlways), XtRImmediate, (XtPointer) False}, ++ ++ {"recvText", "RecvText", XtRString, sizeof(String), ++ XtOffsetOf(AppData, recvText), XtRImmediate, (XtPointer) 0}, ++ ++ {"escapeKeys", "EscapeKeys", XtRString, sizeof(String), + XtOffsetOf(AppData, escapeKeys), XtRImmediate, (XtPointer) 0}, + + {"escapeActive", "EscapeActive", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, escapeActive), XtRImmediate, (XtPointer) False} ++ + /* check commas */ }; -@@ -242,8 +779,25 @@ +@@ -242,8 +903,26 @@ {"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"}, {"-passwd", "*passwordFile", XrmoptionSepArg, 0}, {"-user", "*userLogin", XrmoptionSepArg, 0}, + {"-unixpw", "*unixPW", XrmoptionSepArg, 0}, ++ {"-mslogon", "*msLogon", XrmoptionSepArg, 0}, + {"-repeater", "*repeaterUltra", XrmoptionSepArg, 0}, + {"-ultradsm", "*ultraDSM", XrmoptionNoArg, "True"}, + {"-rfbversion", "*rfbVersion", XrmoptionSepArg, 0}, @@ -1388,7 +1517,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"}, {"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"}, {"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"}, -@@ -253,8 +807,22 @@ +@@ -253,8 +932,27 @@ {"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"}, {"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"}, {"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"}, @@ -1409,17 +1538,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"-termchat", "*termChat", XrmoptionNoArg, "True"}, + {"-chatonly", "*chatOnly", XrmoptionNoArg, "True"}, + {"-scale", "*scale", XrmoptionSepArg, 0}, -+ {"-escapekeys", "*escapeKeys", XrmoptionSepArg, 0} ++ {"-escape", "*escapeKeys", XrmoptionSepArg, 0}, ++ {"-sendclipboard", "*sendClipboard", XrmoptionNoArg, "True"}, ++ {"-sendalways", "*sendAlways", XrmoptionNoArg, "True"}, ++ {"-recvtext", "*recvText", XrmoptionSepArg, 0}, ++ {"-pipeline", "*pipelineUpdates", XrmoptionNoArg, "True"}, ++ {"-nopipeline", "*pipelineUpdates", XrmoptionNoArg, "False"} }; int numCmdLineOptions = XtNumber(cmdLineOptions); -@@ -267,16 +835,88 @@ +@@ -267,16 +965,98 @@ static XtActionsRec actions[] = { {"SendRFBEvent", SendRFBEvent}, {"ShowPopup", ShowPopup}, + {"Noop", Noop}, {"HidePopup", HidePopup}, + {"HideScaleN", HideScaleN}, ++ {"HideTurboVNC", HideTurboVNC}, + {"HideQuality", HideQuality}, + {"HideCompress", HideCompress}, {"ToggleFullScreen", ToggleFullScreen}, @@ -1431,6 +1566,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"SelectionFromVNC", SelectionFromVNC}, {"SelectionToVNC", SelectionToVNC}, {"ServerDialogDone", ServerDialogDone}, ++ {"UserDialogDone", UserDialogDone}, + {"YCropDialogDone", YCropDialogDone}, + {"ScbarDialogDone", ScbarDialogDone}, + {"ScaleNDialogDone", ScaleNDialogDone}, @@ -1457,6 +1593,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"ToggleBell", ToggleBell}, + {"ToggleRawLocal", ToggleRawLocal}, + {"ToggleServerInput", ToggleServerInput}, ++ {"TogglePipelineUpdates", TogglePipelineUpdates}, ++ {"ToggleSendClipboard", ToggleSendClipboard}, ++ {"ToggleSendAlways", ToggleSendAlways}, + {"ToggleSingleWindow", ToggleSingleWindow}, + {"ToggleTextChat", ToggleTextChat}, + {"ToggleFileXfer", ToggleFileXfer}, @@ -1466,9 +1605,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"SetYCrop", SetYCrop}, + {"SetScbar", SetScbar}, + {"ShowScaleN", ShowScaleN}, ++ {"ShowTurboVNC", ShowTurboVNC}, + {"ShowQuality", ShowQuality}, + {"ShowCompress", ShowCompress}, + {"SetScaleN", SetScaleN}, ++ {"SetTurboVNC", SetTurboVNC}, + {"SetQuality", SetQuality}, + {"SetCompress", SetCompress}, + {"Set8bppState", Set8bppState}, @@ -1491,6 +1632,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"SetBellState", SetBellState}, + {"SetRawLocalState", SetRawLocalState}, + {"SetServerInputState", SetServerInputState}, ++ {"SetPipelineUpdates", SetPipelineUpdates}, ++ {"SetSendClipboard", SetSendClipboard}, ++ {"SetSendAlways", SetSendAlways}, + {"SetSingleWindowState", SetSingleWindowState}, + {"SetTextChatState", SetTextChatState}, + {"SetFileXferState", SetFileXferState}, @@ -1502,7 +1646,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v }; -@@ -302,11 +942,14 @@ +@@ -302,11 +1082,14 @@ void usage(void) { @@ -1519,7 +1663,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v " %s [] -listen []\n" " %s -help\n" "\n" -@@ -332,10 +975,302 @@ +@@ -332,10 +1115,339 @@ " -autopass\n" "\n" "Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n" @@ -1623,8 +1767,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " -rawlocal Prefer raw encoding for localhost, default is\n" + " no, i.e. assumes you have a SSH tunnel instead.\n" + "\n" ++ " -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C,\n" ++ " Ctrl+V) instead of the X PRIMARY selection (mouse\n" ++ " select and middle button paste.)\n" ++ "\n" ++ " -sendalways Whenever the mouse enters the VNC viewer main\n" ++ " window, send the selection to the VNC server even if\n" ++ " it has not changed. This is like the Xt resource\n" ++ " translation SelectionToVNC(always)\n" ++ "\n" ++ " -recvtext str When cut text is received from the VNC server,\n" ++ " ssvncviewer will set both the X PRIMARY and the\n" ++ " X CLIPBOARD local selections. To control which\n" ++ " is set, specify 'str' as 'primary', 'clipboard',\n" ++ " or 'both' (the default.)\n" ++ "\n" + " -graball Grab the entire X server when in fullscreen mode,\n" + " needed by some old window managers like fvwm2.\n" ++ "\n" + " -popupfix Warp the popup back to the pointer position,\n" + " needed by some old window managers like fvwm2.\n" + "\n" @@ -1707,6 +1867,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " RFB data sent so as to work with the UltraVNC Server. For\n" + " some reason, each RFB msg type must be sent twice under DSM.\n" + "\n" ++ " -mslogon user Use Windows MS Logon to an UltraVNC server. Supply the\n" ++ " username or \"1\" to be prompted. The default is to\n" ++ " autodetect the UltraVNC MS Logon server and prompt for\n" ++ " the username and password.\n" ++ "\n" ++ " IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman\n" ++ " exchange is very weak and can be brute forced to recover\n" ++ " your username and password in a few hours or seconds of CPU\n" ++ " time. To be safe, be sure to use an additional encrypted\n" ++ " tunnel (e.g. SSL or SSH) for the entire VNC session.\n" ++ "\n" + " -chatonly Try to be a client that only does UltraVNC text chat. This\n" + " mode is used by x11vnc to present a chat window on the\n" + " physical X11 console (i.e. chat with the person at the\n" @@ -1721,6 +1892,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " keybindings and Popup menu) Then point to the file via\n" + " XENVIRONMENT or XAPPLRESDIR.\n" + "\n" ++ " -pipeline Like TurboVNC, request the next framebuffer update as soon\n" ++ " as possible instead of waiting until the end of the current\n" ++ " framebuffer update coming in. Helps 'pipeline' the updates.\n" ++ " This is currently the default, use -nopipeline to disable.\n" ++ "\n" + " -escape str This sets the 'Escape Keys' modifier sequence and enables\n" + " escape keys mode. When the modifier keys escape sequence\n" + " is held down, the next keystroke is interpreted locally\n" @@ -1788,6 +1964,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " Quality Level ~ -quality (both Tight and ZYWRLE)\n" + " Compress Level ~ -compresslevel\n" + " Disable JPEG: ~ -nojpeg (Tight)\n" ++ " Pipeline Updates ~ -pipeline\n" ++ "\n" + " Full Color as many colors as local screen allows.\n" + " Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.\n" + " 16 bit color (BGR565) ~ -16bpp / -bgr565\n" @@ -1815,6 +1993,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " Note: the Ultravnc extensions only apply to servers that support\n" + " them. x11vnc/libvncserver supports some of them.\n" + "\n" ++ " Send Clipboard not Primary ~ -sendclipboard\n" ++ " Send Selection Every time ~ -sendalways\n" ++ "\n" + "\n", programName, programName, programName, programName, programName, programName, programName); exit(1); } @@ -1824,7 +2005,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v /* -@@ -347,73 +1282,191 @@ +@@ -347,73 +1459,214 @@ void GetArgsAndResources(int argc, char **argv) { @@ -1906,6 +2087,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + if (appData.escapeKeys != NULL) { + appData.escapeActive = True; + } ++ if (getenv("VNCVIEWER_SEND_CLIPBOARD")) { ++ appData.sendClipboard = True; ++ } ++ if (getenv("VNCVIEWER_SEND_ALWAYS")) { ++ appData.sendAlways = True; ++ } ++ if (getenv("VNCVIEWER_RECV_TEXT")) { ++ char *s = getenv("VNCVIEWER_RECV_TEXT"); ++ if (!strcasecmp(s, "clipboard")) { ++ appData.recvText = strdup("clipboard"); ++ } else if (!strcasecmp(s, "primary")) { ++ appData.recvText = strdup("primary"); ++ } else if (!strcasecmp(s, "both")) { ++ appData.recvText = strdup("both"); ++ } ++ } ++ if (getenv("VNCVIEWER_PIPELINE_UPDATES")) { ++ appData.pipelineUpdates = True; ++ } else if (getenv("VNCVIEWER_NO_PIPELINE_UPDATES")) { ++ appData.pipelineUpdates = False; ++ } + + if (appData.useBGR233 && appData.useBGR565) { + appData.useBGR233 = 0; @@ -2014,7 +2216,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + + if (argc == 1) { + vncServerName = DoServerDialog(); -+ appData.passwordDialog = True; ++ if (!isatty(0)) { ++ appData.passwordDialog = True; ++ } + } else if (argc != 2) { + usage(); + } else { @@ -2474,22 +2678,26 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer +#undef FillRectangle diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cp_it vnc_unixsrc/vncviewer/cp_it --- vnc_unixsrc.orig/vncviewer/cp_it 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/cp_it 2007-03-24 10:05:16.000000000 -0400 -@@ -0,0 +1,14 @@ ++++ vnc_unixsrc/vncviewer/cp_it 2009-03-06 20:02:05.000000000 -0500 +@@ -0,0 +1,18 @@ +#!/bin/sh + +dest=/dist/bin/vncviewerz-1.3dev5-resize +suc "cp -p $dest $dest.back; mv $dest $dest.unlink; mv $dest.back $dest; rm $dest.unlink" +strip ./vncviewer -+cat ./vncviewer > $dest ++cat ./vncviewer > $dest +touch -r ./vncviewer $dest +yy=/dist/src/apps/VNC/etc/libvncserver_cvs/expts/etv/ssvnc/bin/Linux.i686/vncviewer +mv $yy $yy.unlink +cp -p ./vncviewer $yy ++mv $yy.turbovnc $yy.unlink.turbovnc +cp -p ./vncviewer $HOME/etv_col/Linux.i686 -+chmod 755 $yy -+rm -f $yy.unlink -+ls -l ./vncviewer $dest $yy $HOME/etv_col/Linux.i686/vncviewer ++cp -p ./vncviewer.turbovnc $yy.turbovnc ++cp -p ./vncviewer.turbovnc $HOME/etv_col/Linux.i686/vncviewer.turbovnc ++chmod 755 $yy* ++ ++rm -f $yy.unlink* ++ls -l ./vncviewer* $dest $yy* $HOME/etv_col/Linux.i686/vncviewer* diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c --- vnc_unixsrc.orig/vncviewer/cursor.c 2003-01-15 04:46:52.000000000 -0500 +++ vnc_unixsrc/vncviewer/cursor.c 2008-10-18 09:35:02.000000000 -0400 @@ -3400,8 +3608,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe - diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncviewer/desktop.c --- vnc_unixsrc.orig/vncviewer/desktop.c 2004-05-28 13:29:29.000000000 -0400 -+++ vnc_unixsrc/vncviewer/desktop.c 2008-12-30 19:33:58.000000000 -0500 -@@ -28,28 +28,473 @@ ++++ vnc_unixsrc/vncviewer/desktop.c 2009-03-26 23:27:45.000000000 -0400 +@@ -28,28 +28,487 @@ #include #endif @@ -3500,11 +3708,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + frac_y = frac_x; + } + -+ if (fx != NULL) { -+ *fx = frac_x; -+ } -+ if (fy != NULL) { -+ *fy = frac_y; ++ if (frac_y > 0.0 && frac_x > 0.0) { ++ if (fx != NULL) { ++ *fx = frac_x; ++ } ++ if (fy != NULL) { ++ *fy = frac_y; ++ } ++ } else { ++ if (appData.scale) { ++ fprintf(stderr, "Invalid scale string: '%s'\n", appData.scale); ++ } else { ++ fprintf(stderr, "Invalid scale string.\n"); ++ } ++ appData.scale = NULL; + } +} + @@ -3581,7 +3798,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + frac_x = frac_y = 1.0; + } else { + get_scale_values(&frac_x, &frac_y); -+ if (frac_x < 0.0) { ++ if (frac_x < 0.0 || frac_y < 0.0) { + create_image(); + return; + } @@ -3778,16 +3995,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + } else { + double frac_x = -1.0, frac_y = -1.0; + ++ get_scale_values(&frac_x, &frac_y); ++ ++ if (frac_x < 0.0 || frac_y < 0.0) { ++ fprintf(stderr, "Cannot figure out scale factor!\n"); ++ goto bork; ++ } ++ + scale_factor_x = 0.0; + scale_factor_y = 0.0; + scale_x = 0; + scale_y = 0; + -+ get_scale_values(&frac_x, &frac_y); + -+ if (frac_x < 0.0) { -+ fprintf(stderr, "Cannot figure out scale factor!\n"); -+ } else { ++ if (1) { + int w, h, hyc; + + w = scale_round(si.framebufferWidth, frac_x); @@ -3828,6 +4049,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + } + } + } ++ bork: + try_create_image(); +} + @@ -3879,7 +4101,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview /* * DesktopInitBeforeRealization creates the "desktop" widget and the viewport -@@ -59,91 +504,1012 @@ +@@ -59,91 +518,1016 @@ void DesktopInitBeforeRealization() { @@ -3896,8 +4118,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + + if (appData.scale != NULL) { + get_scale_values(&frac_x, &frac_y); -+ w = scale_round(w, frac_x); -+ h = scale_round(h, frac_y); ++ if (frac_x > 0.0 && frac_y > 0.0) { ++ w = scale_round(w, frac_x); ++ h = scale_round(h, frac_y); ++ } else { ++ appData.scale = NULL; ++ } + } - form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel, @@ -3974,8 +4200,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + } + + create_image(); -+} -+ + } + +static Widget scrollbar_y = NULL; + +static int xsst = 2; @@ -3995,8 +4221,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + float t = 0.0; + XtVaSetValues(w, XtNtopOfThumb, &t, NULL); + } - } - ++} ++ +static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) { + float top = *((float *) call_data); + Position x, y; @@ -4278,7 +4504,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview +#else +#define nfix(i, n) ( i < 0 ? 0 : ( (i >= n) ? (n - 1) : i ) ) +#endif -+ + +- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); +int scale_round(int len, double fac) { + double eps = 0.000001; + @@ -4351,8 +4578,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + /* try to avoid problems with bleeding... */ + sbdy = (int) (2.0 * fmax * sbdy); + } - -- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); ++ + //fprintf(stderr, "scale_rect: %dx%d+%d+%d\n", *pw, *ph, *px, *py); + + *px = (int) (*px * factor_x); @@ -4954,7 +5180,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview /* * HandleBasicDesktopEvent - deal with expose and leave events. -@@ -152,41 +1518,392 @@ +@@ -152,41 +1536,404 @@ static void HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) { @@ -4996,13 +5222,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + if (y + height < si.framebufferHeight) height++; + } + } -+ -+ if (x + width > si.framebufferWidth) { -+ width = si.framebufferWidth - x; -+ if (width <= 0) { -+ break; -+ } -+ } - if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) { - ev->xexpose.width = si.framebufferWidth - ev->xexpose.x; @@ -5017,6 +5236,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview - SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y, - ev->xexpose.width, ev->xexpose.height, False); - break; ++ if (x + width > si.framebufferWidth) { ++ width = si.framebufferWidth - x; ++ if (width <= 0) { ++ break; ++ } ++ } ++ + if (y + height > si.framebufferHeight) { + height = si.framebufferHeight - y; + if (height <= 0) { @@ -5087,6 +5313,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + if (appData.fullScreen) { + fs_grab(1); + } ++ break; ++ case ClientMessage: ++ if (ev->xclient.window == XtWindow(desktop) && ev->xclient.message_type == XA_INTEGER && ++ ev->xclient.format == 8 && !strcmp(ev->xclient.data.b, "SendRFBUpdate")) { ++ SendIncrementalFramebufferUpdateRequest(); ++ } + break; } + check_things(); @@ -5212,7 +5444,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + fs = 1; + FullScreenOff(); + } -+ rescale_image(); ++ if (1) { ++ double fx, fy; ++ get_scale_values(&fx, &fy); ++ if (fx > 0.0 && fy > 0.0) { ++ rescale_image(); ++ } ++ } + if (fs) { + FullScreenOn(); + } @@ -5369,7 +5607,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview /* * SendRFBEvent is an action which sends an RFB event. It can be used in two -@@ -201,127 +1918,322 @@ +@@ -201,127 +1948,322 @@ * button2 down, 3 for both, etc). */ @@ -5800,7 +6038,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } -@@ -329,26 +2241,185 @@ +@@ -329,26 +2271,194 @@ * CreateDotCursor. */ @@ -5867,23 +6105,31 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1); + XFreePixmap(dpy, src); + XFreePixmap(dpy, msk); - -- return cursor; ++ + return cursor; +} +#endif + +int skip_maybe_sync = 0; +void maybe_sync(int width, int height) { -+ static int singles = 0; -+ if (skip_maybe_sync) { ++ static int singles = 0, always_skip = -1; ++ int singles_max = 32; ++ ++ if (always_skip < 0) { ++ if (getenv("SSVNC_NO_MAYBE_SYNC")) { ++ always_skip = 1; ++ } else { ++ always_skip = 0; ++ } ++ } ++ if (skip_maybe_sync || always_skip) { + return; + } + if (width > 1 || height > 1) { + XSync(dpy, False); + singles = 0; + } else { -+ if (++singles >= 32) { ++ if (++singles >= singles_max) { + singles = 0; + XSync(dpy, False); + } @@ -5983,7 +6229,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + dst -= Bpl; + } + } -+ + +- return cursor; + if (image_scale && !did2) { + im = image; + Bpp = im->bits_per_pixel / 8; @@ -6002,7 +6249,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } -@@ -359,38 +2430,37 @@ +@@ -359,38 +2469,37 @@ void CopyDataToScreen(char *buf, int x, int y, int width, int height) { @@ -6070,7 +6317,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } -@@ -401,62 +2471,297 @@ +@@ -401,62 +2510,297 @@ static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height) { @@ -6424,10 +6671,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncviewer/dialogs.c --- vnc_unixsrc.orig/vncviewer/dialogs.c 2000-10-26 15:19:19.000000000 -0400 -+++ vnc_unixsrc/vncviewer/dialogs.c 2008-11-16 12:09:19.000000000 -0500 -@@ -26,6 +26,393 @@ ++++ vnc_unixsrc/vncviewer/dialogs.c 2009-04-15 14:12:13.000000000 -0400 +@@ -25,7 +25,395 @@ + #include static Bool serverDialogDone = False; ++static Bool userDialogDone = False; static Bool passwordDialogDone = False; +static Bool ycropDialogDone = False; +static Bool scaleDialogDone = False; @@ -6819,7 +7068,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview void ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -@@ -44,11 +431,19 @@ +@@ -44,11 +432,19 @@ toplevel, NULL); dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); @@ -6839,7 +7088,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview serverDialogDone = False; while (!serverDialogDone) { -@@ -56,6 +451,7 @@ +@@ -56,6 +452,7 @@ } valueString = XawDialogGetValueString(dialog); @@ -6847,7 +7096,58 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview vncServerName = XtNewString(valueString); XtPopdown(pshell); -@@ -80,11 +476,19 @@ +@@ -63,6 +460,50 @@ + } + + void ++UserDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) ++{ ++ userDialogDone = True; ++} ++ ++char * ++DoUserDialog() ++{ ++ Widget pshell, dialog; ++ char *userName; ++ char *valueString; ++ ++ pshell = XtVaCreatePopupShell("userDialog", transientShellWidgetClass, ++ toplevel, NULL); ++ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); ++ ++ dialog_over(pshell); ++ ++ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, ++ HeightOfScreen(XtScreen(pshell))*2/5); ++ XtPopup(pshell, XtGrabNonexclusive); ++ XtRealizeWidget(pshell); ++ ++ if (appData.popupFix) { ++ popupFixer(pshell); ++ } ++ //dialog_input(pshell); ++ wm_delete(pshell, "UserDialogDone()"); ++ ++ userDialogDone = False; ++ ++ while (!userDialogDone) { ++ XtAppProcessEvent(appContext, XtIMAll); ++ } ++ ++ valueString = XawDialogGetValueString(dialog); ++ rmNL(valueString); ++ userName = XtNewString(valueString); ++ ++ XtPopdown(pshell); ++ return userName; ++} ++ ++void + PasswordDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params) + { +@@ -80,11 +521,19 @@ toplevel, NULL); dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); @@ -6867,7 +7167,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview passwordDialogDone = False; while (!passwordDialogDone) { -@@ -92,6 +496,7 @@ +@@ -92,6 +541,7 @@ } valueString = XawDialogGetValueString(dialog); @@ -8247,7 +8547,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe /* diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/misc.c --- vnc_unixsrc.orig/vncviewer/misc.c 2003-01-15 02:58:32.000000000 -0500 -+++ vnc_unixsrc/vncviewer/misc.c 2008-10-14 22:32:04.000000000 -0400 ++++ vnc_unixsrc/vncviewer/misc.c 2009-03-26 23:10:56.000000000 -0400 @@ -33,12 +33,14 @@ Dimension dpyWidth, dpyHeight; @@ -8346,7 +8646,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/ + /* switched to not scaled */ + double frac_x, frac_y; + get_scale_values(&frac_x, &frac_y); -+ if (frac_x > 0.0) { ++ if (frac_x > 0.0 && frac_y > 0.0) { + w = scale_round(w, frac_x); + h = scale_round(h, frac_y); + } @@ -8642,14 +8942,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c --- vnc_unixsrc.orig/vncviewer/popup.c 2000-06-11 08:00:53.000000000 -0400 -+++ vnc_unixsrc/vncviewer/popup.c 2008-11-10 10:03:59.000000000 -0500 -@@ -25,22 +25,56 @@ ++++ vnc_unixsrc/vncviewer/popup.c 2009-04-15 15:44:22.000000000 -0400 +@@ -25,22 +25,59 @@ #include #include +#include #include ++#include ++#include ++ Widget popup, fullScreenToggle; +void popupFixer(Widget wid) { @@ -8706,7 +9009,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer } -@@ -52,42 +86,546 @@ +@@ -52,42 +89,755 @@ }; void @@ -8823,6 +9126,131 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer + } +} + ++Widget turbovncW; ++ ++static Widget turboButtons[32]; ++ ++Widget qualtext, qualslider; ++ ++void UpdateQualSlider(void) { ++#ifdef TURBOVNC ++ char text[16]; ++ XawScrollbarSetThumb(qualslider, (float)appData.qualityLevel/100., 0.); ++ sprintf(text, "%3d", appData.qualityLevel); ++ XtVaSetValues(qualtext, XtNlabel, text, NULL); ++#endif ++} ++ ++void qualScrollProc(Widget w, XtPointer client, XtPointer p) { ++#ifdef TURBOVNC ++ float size, val; int qual, pos=(int)p; ++ XtVaGetValues(w, XtNshown, &size, XtNtopOfThumb, &val, 0); ++ if(pos<0) val-=.1; else val+=.1; ++ qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; ++ XawScrollbarSetThumb(w, val, 0.); ++ appData.qualityLevel=qual; ++ UpdateQual(); ++#endif ++} ++ ++void qualJumpProc(Widget w, XtPointer client, XtPointer p) { ++#ifdef TURBOVNC ++ float val=*(float *)p; int qual; ++ qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; ++ appData.qualityLevel=qual; ++ UpdateQual(); ++#endif ++} ++ ++void UpdateSubsampButtons(void) { ++#ifdef TURBOVNC ++ int i; ++ for (i=7; i <= 10; i++) { ++ XtVaSetValues(turboButtons[i], XtNstate, 0, NULL); ++ } ++ if (appData.subsampLevel==TVNC_1X) { ++ i = 7; ++ } else if (appData.subsampLevel==TVNC_2X) { ++ i = 8; ++ } else if (appData.subsampLevel==TVNC_4X) { ++ i = 9; ++ } else if (appData.subsampLevel==TVNC_GRAY) { ++ i = 10; ++ } else { ++ return; ++ } ++ XtVaSetValues(turboButtons[i], XtNstate, 1, NULL); ++#endif ++} ++ ++void ++ShowTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) ++{ ++ UpdateSubsampButtons(); ++ UpdateQualSlider(); ++ if (appData.popupFix) { ++ popupFixer(turbovncW); ++ } else { ++ XtMoveWidget(turbovncW, event->xbutton.x_root, event->xbutton.y_root); ++ XtPopup(turbovncW, XtGrabNone); ++ } ++ if (appData.grabAll) { ++ XRaiseWindow(dpy, XtWindow(turbovncW)); ++ } ++ XSetWMProtocols(dpy, XtWindow(turbovncW), &wmDeleteWindow, 1); ++ XtOverrideTranslations(turbovncW, XtParseTranslationTable ("WM_PROTOCOLS: HideTurboVNC()")); ++} ++ ++void ++HideTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) ++{ ++ XtPopdown(turbovncW); ++} ++ ++void ++CreateTurboVNC() { ++ Widget buttonForm, button, prevButton = NULL; ++ Widget label; ++ int i; ++ char buttonName[32]; ++ String buttonType; ++ ++ turbovncW = XtVaCreatePopupShell("turboVNC", transientShellWidgetClass, toplevel, NULL); ++ ++ buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, turbovncW, NULL); ++ ++ for (i = 0; i <= 12; i++) { ++ sprintf(buttonName, "button%d", i); ++#ifndef TURBOVNC ++ if (i == 0) { ++ sprintf(buttonName, "buttonNone"); ++ } else if (i > 0) { ++ return; ++ } ++#endif ++ XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, ++ "Button", resources, 1, NULL); ++ ++ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, ++ buttonForm, NULL); ++ turboButtons[i] = button; ++ XtVaSetValues(button, XtNfromVert, prevButton, ++ XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); ++ prevButton = button; ++ } ++ ++ label = XtCreateManagedWidget("qualLabel", toggleWidgetClass, buttonForm, NULL, 0); ++ XtVaSetValues(label, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); ++ ++ qualslider = XtCreateManagedWidget("qualBar", scrollbarWidgetClass, buttonForm, NULL, 0); ++ XtVaSetValues(qualslider, XtNfromVert, label, XtNleft, XawChainLeft, NULL); ++ XtAddCallback(qualslider, XtNscrollProc, qualScrollProc, NULL) ; ++ XtAddCallback(qualslider, XtNjumpProc, qualJumpProc, NULL) ; ++ ++ qualtext = XtCreateManagedWidget("qualText", labelWidgetClass, buttonForm, NULL, 0); ++ XtVaSetValues(qualtext, XtNfromVert, label, XtNfromHoriz, qualslider, XtNright, XawChainRight, NULL); ++} ++ +Widget qualityW; + +void @@ -9270,24 +9698,108 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer + + XtSetKeyboardFocus(chat, entry); +} -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewer/popup_ad ---- vnc_unixsrc.orig/vncviewer/popup_ad 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/popup_ad 2008-02-17 13:32:34.000000000 -0500 -@@ -0,0 +1,20 @@ -+#!/usr/bin/perl + -+$ok = 0; ++Widget msgwin, msgtext; + -+open(A, ") { -+ if (/popupButtonCount:/) { -+ $on = 1; -+ } elsif (/^\s*NULL/) { -+ $on = 0; -+ } -+ next unless $on; -+ chomp; ++ XawTextSetInsertionPoint(msgtext, pos); ++ beg = XawTextGetInsertionPoint(msgtext); ++ end = beg; ++ ++ txt.firstPos = 0; ++ txt.length = strlen(in); ++ txt.ptr = in; ++ txt.format = FMT8BIT; ++ ++ XawTextReplace(msgtext, beg, end, &txt); ++ XawTextSetInsertionPoint(msgtext, beg + txt.length); ++ ++ pos = XawTextGetInsertionPoint(msgtext); ++} ++ ++static msg_visible = 0; ++ ++void msg_dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { ++ XtPopdown(msgwin); ++ msg_visible = 0; ++ XSync(dpy, False); ++ usleep(200 * 1000); ++} ++ ++void CreateMsg(char *msg, int wait) { ++ ++ Widget myform, dismiss; ++ char *p; ++ int i, n, run, wmax = 0; ++ Dimension w, h; ++ ++ n = 0; ++ run = 0; ++ p = msg; ++ while (*p != '\0') { ++ if (*p == '\n') { ++ run = 0; ++ n++; ++ } ++ run++; ++ if (run > wmax) wmax = run; ++ p++; ++ } ++ h = (Dimension) (n+2) * 14; ++ w = (Dimension) (wmax+10) * 8; ++ ++ msgwin = XtVaCreatePopupShell("Message", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL); ++ ++ myform = XtVaCreateManagedWidget("myform", formWidgetClass, msgwin, NULL); ++ ++ msgtext = XtVaCreateManagedWidget("msgtext", asciiTextWidgetClass, myform, ++ XtNresize, XawtextResizeBoth, XtNresizable, True, XtNwrap, XawtextWrapWord, ++ XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollAlways, ++ XtNwidth, w, XtNheight, h, XtNdisplayCaret, False, ++ XtNeditType, XawtextAppend, XtNtype, XawAsciiString, ++ XtNuseStringInPlace, False, NULL); ++ ++ dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "OK", XtNfromVert, msgtext, NULL); ++ ++ AppendMsg(""); ++ AppendMsg(msg); ++ ++ XtAddCallback(dismiss, XtNcallback, msg_dismiss_proc, NULL); ++ ++ XtRealizeWidget(msgwin); ++ ++ XtPopup(msgwin, XtGrabNone); ++ ++ XSync(dpy, False); ++ msg_visible = 1; ++ while (wait && msg_visible) { ++ if (0) fprintf(stderr, "mv: %d\n", msg_visible); ++ XtAppProcessEvent(appContext, XtIMAll); ++ } ++} +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewer/popup_ad +--- vnc_unixsrc.orig/vncviewer/popup_ad 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/popup_ad 2008-02-17 13:32:34.000000000 -0500 +@@ -0,0 +1,20 @@ ++#!/usr/bin/perl ++ ++$ok = 0; ++ ++open(A, ") { ++ if (/popupButtonCount:/) { ++ $on = 1; ++ } elsif (/^\s*NULL/) { ++ $on = 0; ++ } ++ next unless $on; ++ chomp; + last if /NULL/; + $_ =~ s/^\s*"//; + $_ =~ s/",//; @@ -9296,7 +9808,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewe +} diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncviewer/rfbproto.c --- vnc_unixsrc.orig/vncviewer/rfbproto.c 2008-09-05 19:51:24.000000000 -0400 -+++ vnc_unixsrc/vncviewer/rfbproto.c 2008-12-08 10:53:56.000000000 -0500 ++++ vnc_unixsrc/vncviewer/rfbproto.c 2009-05-31 13:29:44.000000000 -0400 @@ -23,6 +23,7 @@ * rfbproto.c - functions to deal with client side of RFB protocol. */ @@ -9360,7 +9872,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie static void ReadConnFailedReason(void); static long ReadCompactLen (void); -@@ -67,6 +109,13 @@ +@@ -67,6 +109,19 @@ static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, int compressedLen); @@ -9368,23 +9880,62 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie +extern double scale_factor_x; +extern double scale_factor_y; + ++extern int skip_maybe_sync; ++ +int sent_FBU = 0; +int skip_XtUpdate = 0; +int skip_XtUpdateAll = 0; ++ ++static double dt_out = 0.0; ++double latency = 0.0; ++double connect_time = 0.0; int rfbsock; char *desktopName; -@@ -177,6 +226,9 @@ +@@ -75,6 +130,14 @@ + char *serverCutText = NULL; + Bool newServerCutText = False; + ++/* ultravnc mslogon */ ++#define rfbUltraVncMsLogon 0xfffffffa ++static Bool AuthUltraVncMsLogon(void); ++extern void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); ++extern void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key); ++extern void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key); ++extern unsigned int urandom(void); ++ + int endianTest = 1; + + static Bool tightVncProtocol = False; +@@ -177,8 +240,27 @@ sig_rfbEncodingPointerPos, "Pointer position update"); CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor, sig_rfbEncodingLastRect, "LastRect protocol extension"); + + CapsAdd(encodingCaps, rfbEncodingNewFBSize, rfbTightVncVendor, + sig_rfbEncodingNewFBSize, "New FB size protocol extension"); ++ ++#ifdef TURBOVNC ++ CapsAdd(encodingCaps, rfbJpegQualityLevel1, rfbTurboVncVendor, ++ sig_rfbEncodingNewFBSize, "TurboJPEG quality level"); ++ CapsAdd(encodingCaps, rfbJpegSubsamp1X, rfbTurboVncVendor, ++ sig_rfbEncodingNewFBSize, "TurboJPEG subsampling level"); ++#endif } ++static char msgbuf[10000]; ++extern void CreateMsg(char *msg, int wait); ++ ++static void wmsg(char *msg, int wait) { ++ fprintf(stderr, "%s", msg); ++ if (!isatty(0) && !getenv("SSVNC_NO_MESSAGE_POPUP")) { ++ CreateMsg(msg, wait); ++ } ++} -@@ -187,23 +239,158 @@ + /* + * ConnectToRFBServer. +@@ -187,24 +269,167 @@ Bool ConnectToRFBServer(const char *hostname, int port) { @@ -9473,7 +10024,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + rfbsock = sfd[1]; + } + if (rfbsock < 0) { -+ fprintf(stderr,"Unable to connect to exec'd command: %s\n", cmd); ++ sprintf(msgbuf,"Unable to connect to exec'd command: %s\n", cmd); ++ wmsg(msgbuf, 1); + return False; + } + } else if (strstr(hostname, "fd=") == hostname) { @@ -9486,20 +10038,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + free(thost); + + if (rfbsock < 0) { -+ fprintf(stderr,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); ++ sprintf(msgbuf,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); ++ wmsg(msgbuf, 1); + return False; + } + + } else { + if (!StringToIPAddr(hostname, &host)) { -+ fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname); ++ sprintf(msgbuf,"Couldn't convert '%s' to host address\n", hostname); ++ wmsg(msgbuf, 1); + return False; + } + + rfbsock = ConnectToTcpAddr(host, port); + + if (rfbsock < 0) { -+ fprintf(stderr,"Unable to connect to VNC server (%s:%d)\n", hostname, port); ++ sprintf(msgbuf,"Unable to connect to VNC server (%s:%d)\n", hostname, port); ++ wmsg(msgbuf, 1); + return False; + } + } @@ -9521,7 +10076,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + char *reason = (char *) malloc(reasonLen+1); + memset(reason, 0, reasonLen+1); + ReadFromRFBServer(reason, reasonLen); -+ fprintf(stderr, "Reason: %s\n", reason); ++ sprintf(msgbuf, "Reason: %s\n", reason); ++ wmsg(msgbuf, 1); + free(reason); + } } @@ -9538,6 +10094,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + + if (type == rfbSecTypeAnonTls) str = "rfbSecTypeAnonTls"; + if (type == rfbSecTypeVencrypt) str = "rfbSecTypeVencrypt"; ++ ++ if (type == rfbUltraVncMsLogon) str = "rfbUltraVncMsLogon"; + return str; +} + @@ -9553,9 +10111,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return str; +} ++extern void ProcessXtEvents(void); /* * InitialiseRFBConnection. -@@ -212,211 +399,493 @@ + */ +@@ -212,211 +437,559 @@ Bool InitialiseRFBConnection(void) { @@ -9570,7 +10130,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + FILE *pd; + char *hsfile = NULL; + char *hsparam[128]; ++ char *envsetsec = getenv("SSVNC_SET_SECURITY_TYPE"); + char line[128]; ++ double dt = 0.0; - /* if the connection is immediately closed, don't report anything, so - that pmw's monitor can make test connections */ @@ -9590,6 +10152,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } - errorMessageOnReadFailure = True; ++ skip_XtUpdateAll = 1; ++ ProcessXtEvents(); ++ skip_XtUpdateAll = 0; ++ + if (getenv("SSVNC_PREDIGESTED_HANDSHAKE")) { + double start = dnow(); + hsfile = getenv("SSVNC_PREDIGESTED_HANDSHAKE"); @@ -9643,9 +10209,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - fprintf(stderr,"Not a valid VNC server\n"); - return False; - } ++ dt = dnow(); + if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) { + return False; + } ++ if (getenv("PRINT_DELAY1")) fprintf(stderr, "delay1: %.3f ms\n", (dnow() - dt) * 1000); ++ dt = 0.0; - viewer_major = rfbProtocolMajorVersion; - if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) { @@ -9698,12 +10267,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } + if (se == NULL) { -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "***************************************************************\n"); -+ fprintf(stderr, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); -+ fprintf(stderr, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); -+ fprintf(stderr, "***************************************************************\n"); -+ fprintf(stderr, "\n"); ++ msgbuf[0] = '\0'; ++ strcat(msgbuf, "\n"); ++ strcat(msgbuf, "***************************************************************\n"); ++ strcat(msgbuf, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); ++ strcat(msgbuf, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); ++ strcat(msgbuf, "***************************************************************\n"); ++ strcat(msgbuf, "\n"); ++ wmsg(msgbuf, 0); + } + if (strstr(pv, "ID:") == pv) { + goto check_ID_string; @@ -9712,7 +10283,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + goto ultra_vnc_nonsense; + } + } -+ fprintf(stderr,"Not a valid VNC server: '%s'\n", pv); ++ sprintf(msgbuf, "Not a valid VNC server: '%s'\n", pv); ++ wmsg(msgbuf, 1); + return False; + } @@ -9736,7 +10308,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return False; + } + if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { -+ fprintf(stderr,"Not a valid VNC server: '%s'\n", pv); ++ sprintf(msgbuf,"Not a valid VNC server: '%s'\n", pv); ++ wmsg(msgbuf, 1); + return False; + } + } @@ -9812,35 +10385,56 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - (unsigned long)si.nameLength); - return False; - } -+ fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); ++ if (appData.msLogon) { ++ if (server_minor == 4) { ++ fprintf(stderr,"Setting RFB version to 3.4 for UltraVNC MS Logon.\n\n"); ++ viewer_minor = 4; ++ } ++ } - if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; ++ fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); + +- desktopName[si.nameLength] = 0; + if (hsfile) { + int k = 0; + while (hsparam[k] != NULL) { + char *str = hsparam[k++]; ++ if (strstr(str, "latency=") == str) { ++ latency = 1000. * atof(str + strlen("latency=")); ++ } ++ } ++ k = 0; ++ while (hsparam[k] != NULL) { ++ char *str = hsparam[k++]; + int v1, v2; + if (sscanf(str, "viewer=RFB %d.%d\n", &v1, &v2) == 2) { + viewer_major = v1; + viewer_minor = v2; -+ fprintf(stderr, "\nPre-Handshake set protocol version to: %d.%d\n", viewer_major, viewer_minor); ++ fprintf(stderr, "\nPre-Handshake set protocol version to: %d.%d Latency: %.2f ms\n", viewer_major, viewer_minor, latency); + goto end_of_proto_msg; + } + } + } + sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); -- desktopName[si.nameLength] = 0; +- fprintf(stderr,"Desktop name \"%s\"\n",desktopName); ++ usleep(100*1000); ++ dt = dnow(); + if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) { + return False; + } -- fprintf(stderr,"Desktop name \"%s\"\n",desktopName); -+ end_of_proto_msg: - - fprintf(stderr,"VNC server default format:\n"); - PrintPixelFormat(&si.format); -+ if (getenv("SSVNC_SET_SECURITY_TYPE")) { ++ end_of_proto_msg: + +- if (tightVncProtocol) { +- /* Read interaction capabilities (protocol 3.7t) */ +- if (!ReadInteractionCaps()) +- return False; +- } ++ if (envsetsec) { + secType = atoi(getenv("SSVNC_SET_SECURITY_TYPE")); + goto sec_type; + } @@ -9861,23 +10455,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } -- if (tightVncProtocol) { -- /* Read interaction capabilities (protocol 3.7t) */ -- if (!ReadInteractionCaps()) -- return False; -- } +- return True; + /* Read or select the security type. */ ++ dt_out = 0.0; ++ ++ skip_XtUpdateAll = 1; + if (viewer_minor >= 7) { + secType = SelectSecurityType(); + } else { + secType = ReadSecurityType(); + } -+ fprintf(stderr, "Security-Type: %d (%s)\n", (int) secType, pr_sec_type(secType)); ++ skip_XtUpdateAll = 0; ++ ++ if (dt > 0.0 && dt_out > dt) { ++ latency = (dt_out - dt) * 1000; ++ } ++ ++ fprintf(stderr, "Security-Type: %d (%s) Latency: %.2f ms\n", (int) secType, pr_sec_type(secType), latency); + if (secType == rfbSecTypeInvalid) { + return False; + } - -- return True; ++ + sec_type: + + if (hsfile) { @@ -9916,10 +10514,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + usleep(300*1000); + } + if (subsectype == rfbVencryptTlsNone || subsectype == rfbVencryptTlsVnc || subsectype == rfbVencryptTlsPlain) { -+ fprintf(stderr, "\nWARNING: Anonymous Diffie-Hellman TLS used (%s),\n", pr_sec_subtype(subsectype)); -+ fprintf(stderr, "WARNING: there will be *NO* Authentication of the VNC Server.\n"); -+ fprintf(stderr, "WARNING: I.e. a Man-In-The-Middle attack is possible.\n"); -+ fprintf(stderr, "WARNING: Configure the server to use X509 certs and verify them.\n\n"); ++ char tmp[1000], line[100]; ++ tmp[0] = '\0'; ++ strcat(tmp, "\n"); ++ sprintf(line, "WARNING: Anonymous Diffie-Hellman TLS used (%s),\n", pr_sec_subtype(subsectype)); ++ strcat(tmp, line); ++ strcat(tmp, "WARNING: there will be *NO* Authentication of the VNC Server.\n"); ++ strcat(tmp, "WARNING: I.e. a Man-In-The-Middle attack is possible.\n"); ++ strcat(tmp, "WARNING: Configure the server to use X509 certs and verify them.\n\n"); ++ wmsg(tmp, 1); + } + if (subsectype == rfbVencryptTlsPlain || subsectype == rfbVencryptX509Plain) { + fprintf(stderr, "\nVeNCrypt Plain (username + passwd) selected.\n\n"); @@ -9949,7 +10552,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (authResult == rfbVncAuthOK) { + fprintf(stderr, "VNC authentication succeeded (%d) for rfbSecTypeNone (RFB 3.8)\n", authResult); + } else { -+ fprintf(stderr, "VNC authentication failed (%d) for rfbSecTypeNone (RFB 3.8)\n\n", authResult); ++ sprintf(msgbuf, "VNC authentication failed (%d) for rfbSecTypeNone (RFB 3.8)\n\n", authResult); ++ wmsg(msgbuf, 1); + return False; + } + } @@ -9970,11 +10574,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return False; + } + break; ++ case rfbUltraVncMsLogon: ++ if (!AuthUltraVncMsLogon()) { ++ return False; ++ } ++ break; + default: /* should never happen */ -+ fprintf(stderr, "Internal error: Invalid security type: %d\n", secType); ++ sprintf(msgbuf, "Internal error: Invalid security type: %d\n", secType); ++ wmsg(msgbuf, 1); + return False; + } + ++ connect_time = dnow(); ++ + ci.shared = (appData.shareDesktop ? 1 : 0); + + if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) { @@ -10046,6 +10658,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) { + return rfbSecTypeInvalid; + } ++ dt_out = dnow(); - secType = Swap32IfLE(secType); + secType = Swap32IfLE(secType); @@ -10064,9 +10677,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - (int)secType); - return rfbSecTypeInvalid; - } -+ if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) { -+ fprintf(stderr, "Unknown security type from RFB server: %d\n", -+ (int)secType); ++ if (secType == rfbSecTypeNone) { ++ ; /* OK */ ++ } else if (secType == rfbSecTypeVncAuth) { ++ ; /* OK */ ++ } else if (secType == rfbUltraVncMsLogon) { ++ ; /* OK */ ++ } else { ++ sprintf(msgbuf, "Unknown security type from RFB server: %d\n", (int)secType); ++ wmsg(msgbuf, 1); + return rfbSecTypeInvalid; + } @@ -10107,10 +10726,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + CARD8 secType = rfbSecTypeInvalid; + int i, j; + -+ /* Read the list of secutiry types. */ ++ /* Read the list of security types. */ + if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) { + return rfbSecTypeInvalid; + } ++ dt_out = dnow(); - secTypes = malloc(nSecTypes); - if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) @@ -10156,10 +10776,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "sec-type[%d] %d\n", j, (int) secTypes[j]); + } + } - -- free(secTypes); ++ + /* Find out if the server supports TightVNC protocol extensions */ + for (j = 0; j < (int)nSecTypes; j++) { ++ if (getenv("SSVNC_NO_SEC_TYPE_TIGHT")) { ++ break; ++ } ++#ifdef TURBOVNC ++ break; ++#endif + if (secTypes[j] == rfbSecTypeTight) { + free(secTypes); + secType = rfbSecTypeTight; @@ -10188,15 +10813,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } -- if (secType == rfbSecTypeInvalid) -- fprintf(stderr, "Server did not offer supported security type\n"); +- free(secTypes); + if (secType == rfbSecTypeInvalid) { + fprintf(stderr, "Server did not offer supported security type:\n"); + for (j = 0; j < (int)nSecTypes; j++) { + fprintf(stderr, " sectype[%d] %d\n", j, (int) secTypes[j]); + } + } -+ + +- if (secType == rfbSecTypeInvalid) +- fprintf(stderr, "Server did not offer supported security type\n"); + free(secTypes); - return (int)secType; @@ -10204,7 +10830,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -451,6 +920,9 @@ +@@ -451,6 +1024,9 @@ return True; } @@ -10214,7 +10840,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie /* * Negotiate authentication scheme (protocol version 3.7t) -@@ -459,56 +931,61 @@ +@@ -459,58 +1035,384 @@ static Bool PerformAuthenticationTight(void) { @@ -10313,229 +10939,561 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - fprintf(stderr, "No suitable authentication schemes offered by server\n"); - return False; -+ fprintf(stderr, "No suitable authentication schemes offered by server\n"); ++ sprintf(msgbuf, "No suitable authentication schemes offered by server\n"); ++ wmsg(msgbuf, 1); + return False; } - -@@ -519,80 +996,104 @@ - static Bool - AuthenticateVNC(void) - { -- CARD32 authScheme, authResult; -- CARD8 challenge[CHALLENGESIZE]; -- char *passwd; -- char buffer[64]; -- char* cstatus; -- int len; -+ CARD32 authScheme, authResult; -+ CARD8 challenge[CHALLENGESIZE]; ++#if 0 ++unsigned char encPasswd[8]; ++unsigned char encPasswd_MSLOGON[32]; ++char clearPasswd_MSLOGIN[256]; ++static Bool old_ultravnc_mslogon_code(void) { + char *passwd = NULL; -+ char buffer[64]; -+ char* cstatus; -+ int len; -+ int restart = 0; - -- fprintf(stderr, "Performing standard VNC authentication\n"); -+ fprintf(stderr, "\nPerforming standard VNC authentication\n"); - -- if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) -- return False; -+ if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) { -+ return False; ++ CARD8 challenge_mslogon[CHALLENGESIZE_MSLOGON]; ++ ++ /* code from the old uvnc way (1.0.2?) that would go into AuthenticateVNC() template */ ++ ++ if (appData.msLogon != NULL) { ++ if (!strcmp(appData.msLogon, "1")) { ++ char tmp[256]; ++ fprintf(stderr, "\nUltraVNC MS Logon Username[@Domain]: "); ++ if (fgets(tmp, 256, stdin) == NULL) { ++ exit(1); ++ } ++ appData.msLogon = strdup(tmp); ++ } ++ passwd = getpass("UltraVNC MS Logon Password: "); ++ if (! passwd) { ++ exit(1); ++ } ++ fprintf(stderr, "\n"); ++ ++ UvncEncryptPasswd_MSLOGON(encPasswd_MSLOGON, passwd); + } - -- if (appData.passwordFile) { -- passwd = vncDecryptPasswdFromFile(appData.passwordFile); -- if (!passwd) { -- fprintf(stderr, "Cannot read valid password from file \"%s\"\n", -- appData.passwordFile); -- return False; -- } -- } else if (appData.autoPass) { -- passwd = buffer; -- cstatus = fgets(buffer, sizeof buffer, stdin); -- if (cstatus == NULL) -- buffer[0] = '\0'; -- else -- { -- len = strlen(buffer); -- if (len > 0 && buffer[len - 1] == '\n') -- buffer[len - 1] = '\0'; -- } -- } else if (appData.passwordDialog) { -- passwd = DoPasswordDialog(); -- } else { -- passwd = getpass("Password: "); -- } -+ if (restart_session_pw != NULL) { -+ passwd = restart_session_pw; -+ restart_session_pw = NULL; -+ restart = 1; -+ } else if (appData.passwordFile) { -+ passwd = vncDecryptPasswdFromFile(appData.passwordFile); -+ if (!passwd) { -+ fprintf(stderr, "Cannot read valid password from file \"%s\"\n", -+ appData.passwordFile); ++ if (appData.msLogon) { ++ if (!ReadFromRFBServer((char *)challenge_mslogon, CHALLENGESIZE_MSLOGON)) { + return False; + } -+ } else if (appData.autoPass) { -+ passwd = buffer; -+ cstatus = fgets(buffer, sizeof buffer, stdin); -+ if (cstatus == NULL) { -+ buffer[0] = '\0'; -+ } else { -+ len = strlen(buffer); -+ if (len > 0 && buffer[len - 1] == '\n') { -+ buffer[len - 1] = '\0'; -+ } -+ } -+ } else if (getenv("VNCVIEWER_PASSWORD")) { -+ passwd = strdup(getenv("VNCVIEWER_PASSWORD")); -+ putenv("VNCVIEWER_PASSWORD=none"); -+ } else if (appData.passwordDialog) { -+ passwd = DoPasswordDialog(); -+ } else { -+ passwd = getpass("VNC Password: "); + } - -- if (!passwd || strlen(passwd) == 0) { -- fprintf(stderr, "Reading password failed\n"); -- return False; -- } -- if (strlen(passwd) > 8) { -- passwd[8] = '\0'; -- } -+ if (restart) { -+#define EN0 0 -+#define DE1 1 -+ unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; -+ deskey(s_fixedkey, DE1); -+ des(passwd, passwd); -+ } else { -+ if (!passwd || strlen(passwd) == 0) { -+ fprintf(stderr, "Reading password failed\n\n"); ++ if (appData.msLogon) { ++ int i; ++ char tmp[256]; ++ char *q, *domain = "."; ++ for (i=0; i < 32; i++) { ++ challenge_mslogon[i] = encPasswd_MSLOGON[i] ^ challenge_mslogon[i]; ++ } ++ q = strchr(appData.msLogon, '@'); ++ if (q) { ++ *q = '\0'; ++ domain = strdup(q+1); ++ } ++ memset(tmp, 0, sizeof(tmp)); ++ strcat(tmp, appData.msLogon); ++ if (!WriteExact(rfbsock, tmp, 256)) { + return False; + } -+ if (strlen(passwd) > 8) { -+ passwd[8] = '\0'; ++ memset(tmp, 0, sizeof(tmp)); ++ strcat(tmp, domain); ++ if (!WriteExact(rfbsock, tmp, 256)) { ++ return False; ++ } ++ memset(tmp, 0, sizeof(tmp)); ++ strcat(tmp, passwd); ++ if (!WriteExact(rfbsock, tmp, CHALLENGESIZE_MSLOGON)) { ++ return False; + } + } -+ vncEncryptBytes(challenge, passwd); -+ - -- vncEncryptBytes(challenge, passwd); - -- /* Lose the password from memory */ -- memset(passwd, '\0', strlen(passwd)); -+// /* Lose the password from memory */ -+// memset(passwd, '\0', strlen(passwd)); - -- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) -- return False; -+ if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) { -+ return False; -+ } - -- if (!ReadFromRFBServer((char *)&authResult, 4)) -- return False; -+ if (!ReadFromRFBServer((char *)&authResult, 4)) { ++} ++#endif ++ ++static void hexprint(char *label, char *data, int len) { ++ int i; ++ fprintf(stderr, "%s: ", label); ++ for (i=0; i < len; i++) { ++ unsigned char c = (unsigned char) data[i]; ++ fprintf(stderr, "%02x ", (int) c); ++ if ((i+1) % 20 == 0) { ++ fprintf(stderr, "\n%s: ", label); ++ } ++ } ++ fprintf(stderr, "\n"); ++} ++ ++#define DH_MAX_BITS 31 ++static unsigned long long max_dh = ((unsigned long long) 1) << DH_MAX_BITS; ++ ++static unsigned long long bytes_to_uint64(char *bytes) { ++ unsigned long long result = 0; ++ int i; ++ ++ for (i=0; i < 8; i++) { ++ result <<= 8; ++ result += (unsigned char) bytes[i]; ++ } ++ return result; ++} ++ ++static void uint64_to_bytes(unsigned long long n, char *bytes) { ++ int i; ++ ++ for (i=0; i < 8; i++) { ++ bytes[i] = (unsigned char) (n >> (8 * (7 - i))); ++ } ++} ++ ++static void try_invert(char *wireuser, char *wirepass, unsigned long long actual_key) { ++ return; ++} ++ ++ ++static unsigned long long XpowYmodN(unsigned long long x, unsigned long long y, unsigned long long N) { ++ unsigned long long result = 1; ++ unsigned long long oneShift63 = ((unsigned long long) 1) << 63; ++ int i; ++ ++ for (i = 0; i < 64; y <<= 1, i++) { ++ result = result * result % N; ++ if (y & oneShift63) { ++ result = result * x % N; ++ } ++ } ++ return result; ++} ++ ++/* ++ * UltraVNC MS-Logon authentication (for v1.0.5 and later.) ++ */ ++ ++/* ++ * NOTE: The UltraVNC MS-Logon username and password exchange is ++ * VERY insecure. It can be brute forced in ~2e+9 operations. ++ * It's not clear we should support it... It is only worth using ++ * in an environment where no one is sniffing the network, in which ++ * case all of this DH exchange secrecy is unnecessary... ++ */ ++ ++static Bool AuthUltraVncMsLogon(void) { ++ CARD32 authResult; ++ char gen[8], mod[8], pub[8], rsp[8]; ++ char user[256], passwd[64], *gpw; ++ unsigned char key[8]; ++ unsigned long long ugen, umod, ursp, upub, uprv, ukey; ++ double now = dnow(); ++ int db = 0; ++ ++ if (getenv("SSVNC_DEBUG_MSLOGON")) { ++ db = atoi(getenv("SSVNC_DEBUG_MSLOGON")); ++ } ++ ++ fprintf(stderr, "\nAuthUltraVncMsLogon()\n"); ++ ++ if (!ReadFromRFBServer(gen, sizeof(gen))) { ++ return False; ++ } ++ if (db) hexprint("gen", gen, sizeof(gen)); ++ ++ if (!ReadFromRFBServer(mod, sizeof(mod))) { ++ return False; ++ } ++ if (db) hexprint("mod", mod, sizeof(mod)); ++ ++ if (!ReadFromRFBServer(rsp, sizeof(rsp))) { ++ return False; ++ } ++ if (db) hexprint("rsp", rsp, sizeof(rsp)); ++ ++ ugen = bytes_to_uint64(gen); ++ umod = bytes_to_uint64(mod); ++ ursp = bytes_to_uint64(rsp); ++ ++ if (db) { ++ fprintf(stderr, "ugen: 0x%016llx %12llu\n", ugen, ugen); ++ fprintf(stderr, "umod: 0x%016llx %12llu\n", umod, umod); ++ fprintf(stderr, "ursp: 0x%016llx %12llu\n", ursp, ursp); ++ } ++ ++ if (ugen > max_dh) { ++ fprintf(stderr, "ugen: too big: 0x%016llx\n", ugen); ++ return False; ++ } ++ ++ if (umod > max_dh) { ++ fprintf(stderr, "umod: too big: 0x%016llx\n", umod); ++ return False; ++ } ++ ++ /* make a random long long: */ ++ uprv = 0xffffffff * (now - (unsigned int) now); ++ uprv << 32; ++ uprv |= (unsigned long long) urandom(); ++ uprv = uprv % max_dh; ++ ++ if (db) fprintf(stderr, "uprv: 0x%016llx %12llu\n", uprv, uprv); ++ ++ upub = XpowYmodN(ugen, uprv, umod); ++ ++ if (db) fprintf(stderr, "upub: 0x%016llx %12llu\n", upub, upub); ++ ++ uint64_to_bytes(upub, pub); ++ ++ if (db) hexprint("pub", pub, sizeof(pub)); ++ ++ if (!WriteExact(rfbsock, (char *)pub, sizeof(pub))) { ++ return False; ++ } ++ if (db) fprintf(stderr, "wrote pub.\n"); ++ ++ if (ursp > max_dh) { ++ fprintf(stderr, "ursp: too big: 0x%016llx\n", ursp); ++ return False; ++ } ++ ++ ukey = XpowYmodN(ursp, uprv, umod); ++ ++ if (db) fprintf(stderr, "ukey: 0x%016llx %12llu\n", ukey, ukey); ++ ++ if (1) { ++ char tmp[10000]; ++ tmp[0] = '\0'; ++ strcat(tmp, "\n"); ++ strcat(tmp, "WARNING: The UltraVNC Diffie-Hellman Key is short (key < 2e+9, i.e. 31 bits)\n"); ++ strcat(tmp, "WARNING: and so an eavesdropper could recover your MS-Logon username and\n"); ++ strcat(tmp, "WARNING: password via brute force in a few hours to a few seconds of CPU time\n"); ++ strcat(tmp, "WARNING: depending on the method used. If this connection is not being\n"); ++ strcat(tmp, "WARNING: tunnelled through a separate SSL or SSH encrypted tunnel, consider\n"); ++ strcat(tmp, "WARNING: things carefully before proceeding... Do not enter an important\n"); ++ strcat(tmp, "WARNING: username+password when prompted below if there is a risk of an\n"); ++ strcat(tmp, "WARNING: eavesdropper sniffing this connection. You've been warned!\n"); ++ wmsg(tmp, 1); ++ } ++ ++ uint64_to_bytes(ukey, (char *) key); ++ ++ if (appData.msLogon == NULL || !strcmp(appData.msLogon, "1")) { ++ char tmp[256], *q, *s; ++ fprintf(stderr, "\nUltraVNC MS-Logon Username[@Domain]: "); ++ if (!isatty(0)) { ++ s = DoUserDialog(); ++ } else { ++ if (fgets(tmp, 256, stdin) == NULL) { ++ exit(1); ++ } ++ s = strdup(tmp); ++ } ++ q = strchr(s, '\n'); ++ if (q) *q = '\0'; ++ appData.msLogon = strdup(s); ++ } ++ ++ if (!isatty(0)) { ++ gpw = DoPasswordDialog(); ++ } else { ++ gpw = getpass("UltraVNC MS-Logon Password: "); ++ } ++ if (! gpw) { ++ return False; ++ } ++ fprintf(stderr, "\n"); ++ ++ memset(user, 0, sizeof(user)); ++ strncpy(user, appData.msLogon, 255); ++ ++ memset(passwd, 0, sizeof(passwd)); ++ strncpy(passwd, gpw, 63); ++ ++ if (db > 1) { ++ fprintf(stderr, "user='%s'\n", user); ++ fprintf(stderr, "pass='%s'\n", passwd); ++ } ++ ++ UvncEncryptBytes2((unsigned char *) user, sizeof(user), key); ++ UvncEncryptBytes2((unsigned char *) passwd, sizeof(passwd), key); ++ ++ if (getenv("TRY_INVERT")) { ++ try_invert(user, passwd, ukey); ++ exit(0); ++ } ++ ++ if (db) { ++ hexprint("user", user, sizeof(user)); ++ hexprint("pass", passwd, sizeof(passwd)); ++ } ++ ++ if (!WriteExact(rfbsock, user, sizeof(user))) { ++ return False; ++ } ++ if (db) fprintf(stderr, "wrote user.\n"); ++ ++ if (!WriteExact(rfbsock, passwd, sizeof(passwd))) { ++ return False; ++ } ++ if (db) fprintf(stderr, "wrote passwd.\n"); ++ ++ if (!ReadFromRFBServer((char *) &authResult, 4)) { + return False; + } - -- authResult = Swap32IfLE(authResult); + authResult = Swap32IfLE(authResult); - -- switch (authResult) { -- case rfbVncAuthOK: -- fprintf(stderr, "VNC authentication succeeded\n"); -- break; -- case rfbVncAuthFailed: -- fprintf(stderr, "VNC authentication failed\n"); -- return False; -- case rfbVncAuthTooMany: -- fprintf(stderr, "VNC authentication failed - too many tries\n"); -- return False; -- default: -- fprintf(stderr, "Unknown VNC authentication result: %d\n", -- (int)authResult); -- return False; -- } ++ ++ if (db) fprintf(stderr, "authResult: %d\n", (int) authResult); ++ + switch (authResult) { + case rfbVncAuthOK: -+ fprintf(stderr, "VNC authentication succeeded\n\n"); ++ fprintf(stderr, "UVNC MS-Logon authentication succeeded.\n\n"); + break; + case rfbVncAuthFailed: -+ fprintf(stderr, "VNC authentication failed.\n"); ++ fprintf(stderr, "UVNC MS-Logon authentication failed.\n"); + if (viewer_minor >= 8) { + printFailureReason(); ++ } else { ++ sprintf(msgbuf, "UVNC MS-Logon authentication failed.\n"); ++ wmsg(msgbuf, 1); + } + fprintf(stderr, "\n"); + return False; + case rfbVncAuthTooMany: -+ fprintf(stderr, "VNC authentication failed - too many tries\n\n"); ++ sprintf(msgbuf, "UVNC MS-Logon authentication failed - too many tries.\n\n"); ++ wmsg(msgbuf, 1); + return False; + default: -+ fprintf(stderr, "Unknown VNC authentication result: %d\n\n", ++ sprintf(msgbuf, "Unknown UVNC MS-Logon authentication result: %d\n\n", + (int)authResult); ++ wmsg(msgbuf, 1); + return False; + } - -- return True; ++ + return True; - } ++} /* -@@ -602,68 +1103,71 @@ + * Standard VNC authentication. +@@ -519,80 +1421,113 @@ static Bool - AuthenticateUnixLogin(void) + AuthenticateVNC(void) { -- CARD32 loginLen, passwdLen, authResult; -- char *login; +- CARD32 authScheme, authResult; +- CARD8 challenge[CHALLENGESIZE]; - char *passwd; -- struct passwd *ps; -- -- fprintf(stderr, "Performing Unix login-style authentication\n"); -- -- if (appData.userLogin) { -- login = appData.userLogin; -- } else { -- ps = getpwuid(getuid()); -- login = ps->pw_name; -- } -+ CARD32 loginLen, passwdLen, authResult; -+ char *login; -+ char *passwd; -+ struct passwd *ps; -+ -+ fprintf(stderr, "\nPerforming Unix login-style authentication\n"); -+ -+ if (appData.userLogin) { -+ login = appData.userLogin; +- char buffer[64]; +- char* cstatus; +- int len; ++ CARD32 authScheme, authResult; ++ CARD8 challenge[CHALLENGESIZE]; ++ char *passwd = NULL; ++ char buffer[64]; ++ char* cstatus; ++ int len; ++ int restart = 0; + +- fprintf(stderr, "Performing standard VNC authentication\n"); ++ fprintf(stderr, "\nPerforming standard VNC authentication\n"); + +- if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) +- return False; ++ if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) { ++ return False; ++ } ++ ++ if (restart_session_pw != NULL) { ++ passwd = restart_session_pw; ++ restart_session_pw = NULL; ++ restart = 1; ++ } else if (appData.passwordFile) { ++ passwd = vncDecryptPasswdFromFile(appData.passwordFile); ++ if (!passwd) { ++ sprintf(msgbuf, "Cannot read valid password from file \"%s\"\n", appData.passwordFile); ++ wmsg(msgbuf, 1); ++ return False; ++ } ++ } else if (appData.autoPass) { ++ passwd = buffer; ++ cstatus = fgets(buffer, sizeof buffer, stdin); ++ if (cstatus == NULL) { ++ buffer[0] = '\0'; ++ } else { ++ len = strlen(buffer); ++ if (len > 0 && buffer[len - 1] == '\n') { ++ buffer[len - 1] = '\0'; ++ } ++ } ++ } else if (getenv("VNCVIEWER_PASSWORD")) { ++ passwd = strdup(getenv("VNCVIEWER_PASSWORD")); ++ } else if (appData.passwordDialog) { ++ passwd = DoPasswordDialog(); + } else { -+ ps = getpwuid(getuid()); -+ login = ps->pw_name; ++ passwd = getpass("VNC Password: "); + } -- fprintf(stderr, "Using user name \"%s\"\n", login); -+ fprintf(stderr, "Using user name \"%s\"\n", login); - -- if (appData.passwordDialog) { +- if (appData.passwordFile) { +- passwd = vncDecryptPasswdFromFile(appData.passwordFile); +- if (!passwd) { +- fprintf(stderr, "Cannot read valid password from file \"%s\"\n", +- appData.passwordFile); +- return False; +- } +- } else if (appData.autoPass) { +- passwd = buffer; +- cstatus = fgets(buffer, sizeof buffer, stdin); +- if (cstatus == NULL) +- buffer[0] = '\0'; +- else +- { +- len = strlen(buffer); +- if (len > 0 && buffer[len - 1] == '\n') +- buffer[len - 1] = '\0'; +- } +- } else if (appData.passwordDialog) { - passwd = DoPasswordDialog(); - } else { - passwd = getpass("Password: "); - } ++ if (getenv("VNCVIEWER_PASSWORD")) { ++ putenv("VNCVIEWER_PASSWORD=none"); ++ } + - if (!passwd || strlen(passwd) == 0) { - fprintf(stderr, "Reading password failed\n"); - return False; - } -+ if (appData.passwordDialog) { -+ passwd = DoPasswordDialog(); +- if (strlen(passwd) > 8) { +- passwd[8] = '\0'; +- } ++ if (restart) { ++#define EN0 0 ++#define DE1 1 ++ unsigned char s_fixedkey[8] = {23,82,107,6,35,78,88,7}; ++ deskey(s_fixedkey, DE1); ++ des(passwd, passwd); + } else { -+ passwd = getpass("VNC Password: "); ++ if (!passwd || strlen(passwd) == 0) { ++ sprintf(msgbuf, "Reading password failed\n\n"); ++ wmsg(msgbuf, 1); ++ return False; ++ } ++ if (strlen(passwd) > 8) { ++ passwd[8] = '\0'; ++ } + } -+ if (!passwd || strlen(passwd) == 0) { -+ fprintf(stderr, "Reading password failed\n"); + +- vncEncryptBytes(challenge, passwd); ++ vncEncryptBytes(challenge, passwd); ++ + +- /* Lose the password from memory */ +- memset(passwd, '\0', strlen(passwd)); + +- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) +- return False; ++// /* Lose the password from memory */ ++// memset(passwd, '\0', strlen(passwd)); + +- if (!ReadFromRFBServer((char *)&authResult, 4)) +- return False; ++ if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) { ++ return False; ++ } + +- authResult = Swap32IfLE(authResult); ++ if (!ReadFromRFBServer((char *)&authResult, 4)) { ++ return False; ++ } + +- switch (authResult) { +- case rfbVncAuthOK: +- fprintf(stderr, "VNC authentication succeeded\n"); +- break; +- case rfbVncAuthFailed: +- fprintf(stderr, "VNC authentication failed\n"); +- return False; +- case rfbVncAuthTooMany: +- fprintf(stderr, "VNC authentication failed - too many tries\n"); +- return False; +- default: +- fprintf(stderr, "Unknown VNC authentication result: %d\n", +- (int)authResult); +- return False; +- } ++ authResult = Swap32IfLE(authResult); + +- return True; ++ switch (authResult) { ++ case rfbVncAuthOK: ++ fprintf(stderr, "VNC authentication succeeded\n\n"); ++ break; ++ case rfbVncAuthFailed: ++ fprintf(stderr, "VNC authentication failed.\n"); ++ if (viewer_minor >= 8) { ++ printFailureReason(); ++ } else { ++ sprintf(msgbuf, "VNC authentication failed.\n"); ++ wmsg(msgbuf, 1); ++ } ++ fprintf(stderr, "\n"); ++ return False; ++ case rfbVncAuthTooMany: ++ sprintf(msgbuf, "VNC authentication failed - too many tries\n\n"); ++ wmsg(msgbuf, 1); ++ return False; ++ default: ++ sprintf(msgbuf, "Unknown VNC authentication result: %d\n\n", (int)authResult); ++ wmsg(msgbuf, 1); ++ return False; ++ } ++ ++ return True; + } + + /* +@@ -602,68 +1537,74 @@ + static Bool + AuthenticateUnixLogin(void) + { +- CARD32 loginLen, passwdLen, authResult; +- char *login; +- char *passwd; +- struct passwd *ps; +- +- fprintf(stderr, "Performing Unix login-style authentication\n"); +- +- if (appData.userLogin) { +- login = appData.userLogin; +- } else { +- ps = getpwuid(getuid()); +- login = ps->pw_name; +- } ++ CARD32 loginLen, passwdLen, authResult; ++ char *login; ++ char *passwd; ++ struct passwd *ps; ++ ++ fprintf(stderr, "\nPerforming Unix login-style authentication\n"); ++ ++ if (appData.userLogin) { ++ login = appData.userLogin; ++ } else { ++ ps = getpwuid(getuid()); ++ login = ps->pw_name; ++ } + +- fprintf(stderr, "Using user name \"%s\"\n", login); ++ fprintf(stderr, "Using user name \"%s\"\n", login); + +- if (appData.passwordDialog) { +- passwd = DoPasswordDialog(); +- } else { +- passwd = getpass("Password: "); +- } +- if (!passwd || strlen(passwd) == 0) { +- fprintf(stderr, "Reading password failed\n"); +- return False; +- } ++ if (appData.passwordDialog) { ++ passwd = DoPasswordDialog(); ++ } else { ++ passwd = getpass("VNC Password: "); ++ } ++ if (!passwd || strlen(passwd) == 0) { ++ fprintf(stderr, "Reading password failed\n"); + return False; + } @@ -10594,14 +11552,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "Authentication succeeded\n\n"); + break; + case rfbVncAuthFailed: -+ fprintf(stderr, "Authentication failed\n\n"); ++ sprintf(msgbuf, "Authentication failed\n\n"); ++ wmsg(msgbuf, 1); + return False; + case rfbVncAuthTooMany: -+ fprintf(stderr, "Authentication failed - too many tries\n\n"); ++ sprintf(msgbuf, "Authentication failed - too many tries\n\n"); ++ wmsg(msgbuf, 1); + return False; + default: -+ fprintf(stderr, "Unknown authentication result: %d\n\n", ++ sprintf(msgbuf, "Unknown authentication result: %d\n\n", + (int)authResult); ++ wmsg(msgbuf, 1); + return False; + } @@ -10610,7 +11571,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -675,19 +1179,20 @@ +@@ -675,19 +1616,20 @@ static Bool ReadInteractionCaps(void) { @@ -10643,7 +11604,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -700,17 +1205,18 @@ +@@ -700,19 +1642,67 @@ static Bool ReadCapabilityList(CapsContainer *caps, int count) { @@ -10668,22 +11629,77 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - return True; + return True; ++} ++ ++ ++/* used to have !tunnelSpecified */ ++ ++static int guess_compresslevel(void) { ++ int n; ++ if (latency > 200.0) { ++ n = 8; ++ } else if (latency > 100.0) { ++ n = 7; ++ } else if (latency > 60.0) { ++ n = 6; ++ } else if (latency > 15.0) { ++ n = 4; ++ } else if (latency > 8.0) { ++ n = 2; ++ } else if (latency > 0.0) { ++ n = 1; ++ } else { ++ /* no latency measurement */ ++ n = 3; ++ } ++ return n; } ++static int guess_qualitylevel(void) { ++ int n; ++ if (latency > 200.0) { ++ n = 4; ++ } else if (latency > 100.0) { ++ n = 5; ++ } else if (latency > 60.0) { ++ n = 6; ++ } else if (latency > 15.0) { ++ n = 7; ++ } else if (latency > 8.0) { ++ n = 8; ++ } else if (latency > 0.0) { ++ n = 9; ++ } else { ++ /* no latency measurement */ ++ n = 6; ++ } ++#ifdef TURBOVNC ++ n *= 10; ++#endif ++ return n; ++} -@@ -729,6 +1235,11 @@ + /* + * SetFormatAndEncodings. +@@ -729,6 +1719,17 @@ Bool requestCompressLevel = False; Bool requestQualityLevel = False; Bool requestLastRectEncoding = False; + Bool requestNewFBSizeEncoding = True; + Bool requestTextChatEncoding = True; ++ Bool requestSubsampLevel = False; + int dsm = 0; ++ int tQL, tQLmax = 9; ++ static int qlmsg = 0, clmsg = 0; ++#ifdef TURBOVNC ++ tQLmax = 100; ++#endif + +// fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU); spf.type = rfbSetPixelFormat; spf.format = myFormat; -@@ -736,12 +1247,18 @@ +@@ -736,12 +1737,18 @@ spf.format.greenMax = Swap16IfLE(spf.format.greenMax); spf.format.blueMax = Swap16IfLE(spf.format.blueMax); @@ -10702,7 +11718,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie if (appData.encodingsString) { char *encStr = appData.encodingsString; int encStrLen; -@@ -754,11 +1271,17 @@ +@@ -754,50 +1761,102 @@ encStrLen = strlen(encStr); } @@ -10720,17 +11736,30 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } else if (strncasecmp(encStr,"tight",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); requestLastRectEncoding = True; - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) -@@ -767,16 +1290,33 @@ - requestQualityLevel = True; +- if (appData.compressLevel >= 0 && appData.compressLevel <= 9) +- requestCompressLevel = True; +- if (appData.enableJPEG) +- requestQualityLevel = True; ++ if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { ++ requestCompressLevel = True; ++ } ++ if (appData.enableJPEG) { ++ requestQualityLevel = True; ++ } ++#ifdef TURBOVNC ++ requestSubsampLevel = True; ++#endif } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); - } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) - requestCompressLevel = True; +- if (appData.compressLevel >= 0 && appData.compressLevel <= 9) +- requestCompressLevel = True; - } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { ++ if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { ++ requestCompressLevel = True; ++ } + } else if (strncasecmp(encStr,"corre",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { @@ -10739,11 +11768,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); +#if DO_ZYWRLE + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); -+ requestQualityLevel = True; -+ if (appData.qualityLevel < 3) { ++ int qlevel = appData.qualityLevel; ++ if (qlevel < 0 || qlevel > tQLmax) qlevel = guess_qualitylevel(); ++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); ++ requestQualityLevel = True; ++ if (qlevel < 3) { + zywrle_level = 3; -+ } else if (appData.qualityLevel < 6) { ++ } else if (qlevel < 6) { + zywrle_level = 2; + } else { + zywrle_level = 1; @@ -10757,7 +11788,47 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } encStr = nextEncStr; -@@ -797,7 +1337,7 @@ + } while (encStr && se->nEncodings < MAX_ENCODINGS); + + if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { +- encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + +- rfbEncodingCompressLevel0); ++ ; ++ } else if (se->nEncodings < MAX_ENCODINGS) { ++ appData.compressLevel = guess_compresslevel(); ++ if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); + } ++ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); + + if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { +- if (appData.qualityLevel < 0 || appData.qualityLevel > 9) +- appData.qualityLevel = 5; +- encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + +- rfbEncodingQualityLevel0); ++ if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { ++ appData.qualityLevel = guess_qualitylevel(); ++ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); ++ } ++ } else if (se->nEncodings < MAX_ENCODINGS) { ++ appData.qualityLevel = guess_qualitylevel(); ++ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); ++ } ++#ifdef TURBOVNC ++ tQL = appData.qualityLevel / 10; ++ if (tQL < 0) tQL = 1; ++ if (tQL > 9) tQL = 9; ++ encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); ++ if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { ++ if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { ++ appData.subsampLevel = TVNC_1X; ++ } ++ encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); + } ++#else ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); ++#endif + if (appData.useRemoteCursor) { if (se->nEncodings < MAX_ENCODINGS) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); @@ -10766,23 +11837,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); if (se->nEncodings < MAX_ENCODINGS) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); -@@ -806,10 +1346,14 @@ +@@ -806,10 +1865,16 @@ if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); } +- } +- else { + + if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) { + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); + } - } - else { ++ ++ } else { ++ /* DIFFERENT CASE */ ++ if (SameMachine(rfbsock)) { - if (!tunnelSpecified) { + if (!tunnelSpecified && appData.useRawLocal) { fprintf(stderr,"Same machine: preferring raw encoding\n"); encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); } else { -@@ -818,13 +1362,15 @@ +@@ -818,44 +1883,84 @@ } encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); @@ -10798,20 +11873,59 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { -+ if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { - encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + - rfbEncodingCompressLevel0); - } else if (!tunnelSpecified) { -@@ -835,7 +1381,7 @@ - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); - } - +- encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + +- rfbEncodingCompressLevel0); +- } else if (!tunnelSpecified) { +- /* If -tunnel option was provided, we assume that server machine is +- not in the local network so we use default compression level for +- tight encoding instead of fast compression. Thus we are +- requesting level 1 compression only if tunneling is not used. */ +- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); +- } +- - if (appData.enableJPEG) { +- if (appData.qualityLevel < 0 || appData.qualityLevel > 9) +- appData.qualityLevel = 5; +- encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + +- rfbEncodingQualityLevel0); ++ if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { ++ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); ++ } else { ++ /* ++ * OUT OF DATE: If -tunnel option was provided, we assume that server machine is ++ * not in the local network so we use default compression level for ++ * tight encoding instead of fast compression. Thus we are ++ * requesting level 1 compression only if tunneling is not used. ++ */ ++ appData.compressLevel = guess_compresslevel(); ++ if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); ++ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); ++ } ++ + if (!dsm && appData.enableJPEG) { - if (appData.qualityLevel < 0 || appData.qualityLevel > 9) - appData.qualityLevel = 5; - encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + -@@ -844,18 +1390,35 @@ ++ if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { ++ appData.qualityLevel = guess_qualitylevel(); ++ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); ++ } ++ ++#ifdef TURBOVNC ++ requestSubsampLevel = True; ++ tQL = appData.qualityLevel / 10; ++ if (tQL < 0) tQL = 1; ++ if (tQL > 9) tQL = 9; ++ encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); ++ if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { ++ if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { ++ appData.subsampLevel = TVNC_1X; ++ } ++ encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); ++ } ++#else ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); ++#endif ++ + } if (appData.useRemoteCursor) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); @@ -10850,7 +11964,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie return True; } -@@ -868,31 +1431,86 @@ +@@ -868,31 +1973,86 @@ Bool SendIncrementalFramebufferUpdateRequest() { @@ -10950,7 +12064,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -903,19 +1521,36 @@ +@@ -903,19 +2063,36 @@ Bool SendPointerEvent(int x, int y, int buttonMask) { @@ -10963,19 +12077,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return True; + } + } -+ -+ pe.type = rfbPointerEvent; -+ pe.buttonMask = buttonMask; -+ -+ if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { -+ x /= scale_factor_x; -+ } -+ if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { -+ y /= scale_factor_y; -+ } -+ -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; - pe.type = rfbPointerEvent; - pe.buttonMask = buttonMask; @@ -10988,6 +12089,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - pe.x = Swap16IfLE(x); - pe.y = Swap16IfLE(y); - return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); ++ pe.type = rfbPointerEvent; ++ pe.buttonMask = buttonMask; ++ ++ if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { ++ x /= scale_factor_x; ++ } ++ if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { ++ y /= scale_factor_y; ++ } ++ ++ if (x < 0) x = 0; ++ if (y < 0) y = 0; ++ + if (!appData.useX11Cursor) { + SoftCursorMove(x, y); + } @@ -10999,7 +12113,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -926,12 +1561,20 @@ +@@ -926,12 +2103,20 @@ Bool SendKeyEvent(CARD32 key, Bool down) { @@ -11025,7 +12139,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -942,281 +1585,943 @@ +@@ -942,281 +2127,1024 @@ Bool SendClientCutText(char *str, int len) { @@ -11036,15 +12150,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + free(serverCutText); + } + serverCutText = NULL; - -- if (serverCutText) -- free(serverCutText); -- serverCutText = NULL; -- -- cct.type = rfbClientCutText; -- cct.length = Swap32IfLE(len); -- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && -- WriteExact(rfbsock, str, len)); ++ + if (appData.fileActive) { + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { + // ultravnc java viewer lets this one through. @@ -11055,7 +12161,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (appData.viewOnly) { + return True; + } -+ + +- if (serverCutText) +- free(serverCutText); +- serverCutText = NULL; +- +- cct.type = rfbClientCutText; +- cct.length = Swap32IfLE(len); +- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && +- WriteExact(rfbsock, str, len)); + cct.type = rfbClientCutText; + cct.length = Swap32IfLE(len); + currentMsg = rfbClientCutText; @@ -11397,10 +12511,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (hdr[1] == rfbDirPacket && hdr[3] == rfbADirectory) { + + } - -- /* If RichCursor encoding is used, we should prevent collisions -- between framebuffer updates and cursor drawing operations. */ -- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); ++ + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len1 %u\n", len); + if (len > 0) { @@ -11450,7 +12561,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len); -- switch (rect.encoding) { +- /* If RichCursor encoding is used, we should prevent collisions +- between framebuffer updates and cursor drawing operations. */ +- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); +#if 0 + if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd) +#else @@ -11483,7 +12596,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len); + } + } -+ + +- switch (rect.encoding) { + read_no_more: + + if (filexfer_sock < 0) { @@ -11639,27 +12753,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; -- } -- break; -- } + msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); + msg.scme.nColours = Swap16IfLE(msg.scme.nColours); - -- case rfbEncodingHextile: -- { -- switch (myFormat.bitsPerPixel) { -- case 8: -- if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 16: -- if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 32: -- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; ++ + for (i = 0; i < msg.scme.nColours; i++) { + if (!ReadFromRFBServer((char *)rgb, 6)) { + return False; @@ -11682,19 +12778,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - } + } -- case rfbEncodingZlib: +- case rfbEncodingHextile: - { - switch (myFormat.bitsPerPixel) { - case 8: -- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 16: -- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 32: -- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; + case rfbFramebufferUpdate: @@ -11710,6 +12806,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + int area_zrle = 0; + int area_raw = 0; + static int rdb = -1; ++ static int delay_sync = -1; ++ static int delay_sync_env = -1; ++ int try_delay_sync = 0; ++ int cnt_pseudo = 0; ++ int cnt_image = 0; + + if (db) fprintf(stderr, "FBU-0: %.6f\n", dnow()); + if (rdb < 0) { @@ -11720,13 +12821,53 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } } - break; -- } +- } ++ if (delay_sync < 0) { ++ if (getenv("SSVNC_DELAY_SYNC")) { ++ delay_sync = atoi(getenv("SSVNC_DELAY_SYNC")); ++ delay_sync_env = delay_sync; ++ } else { ++ delay_sync = 0; ++ } ++ } ++ ++ int skip_incFBU = 0; ++ sent_FBU = -1; -- case rfbEncodingTight: +- case rfbEncodingZlib: - { - switch (myFormat.bitsPerPixel) { - case 8: -- if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- return False; +- break; +- case 16: +- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- return False; +- break; +- case 32: +- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- return False; +- break; ++ if (appData.pipelineUpdates) { ++ /* turbovnc speed idea */ ++ XEvent ev; ++ memset(&ev, 0, sizeof(ev)); ++ ev.xclient.type = ClientMessage; ++ ev.xclient.window = XtWindow(desktop); ++ ev.xclient.message_type = XA_INTEGER; ++ ev.xclient.format = 8; ++ strcpy(ev.xclient.data.b, "SendRFBUpdate"); ++ XSendEvent(dpy, XtWindow(desktop), False, 0, &ev); + } +- break; +- } + +- case rfbEncodingTight: +- { +- switch (myFormat.bitsPerPixel) { +- case 8: +- if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 16: @@ -11737,9 +12878,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; -+ int skip_incFBU = 0; -+ sent_FBU = -1; -+ + if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) { + return False; } @@ -11756,6 +12894,44 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - /* Now we may discard "soft cursor locks". */ - SoftCursorUnlockScreen(); - } ++ if (rdb) fprintf(stderr, "Begin rect loop %d\n", msg.fu.nRects); ++ ++ if (delay_sync) { ++ try_delay_sync = 1; ++ } else { ++ if (delay_sync_env != -1 && delay_sync_env == 0) { ++ ; ++ } else if (appData.yCrop > 0) { ++ ; ++ } else if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { ++ ; ++ } else if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { ++ ; ++ } else { ++ static int msg = 0; ++ /* fullScreen? */ ++ /* useXserverBackingStore? */ ++ /* useX11Cursor & etc? */ ++ /* scrollbars? */ ++ if (!msg) { ++ fprintf(stderr, "enabling 'delay_sync' mode for faster local drawing,\ndisable via env SSVNC_DELAY_SYNC=0 if there are painting errors.\n"); ++ msg = 1; ++ } ++ try_delay_sync = 1; ++ } ++ } ++ if (try_delay_sync) { ++ skip_maybe_sync = 1; ++ } ++#define STOP_DELAY_SYNC \ ++ if (try_delay_sync) { \ ++ if (cnt_image && skip_maybe_sync) { \ ++ XSync(dpy, False); \ ++ } \ ++ try_delay_sync = 0; \ ++ skip_maybe_sync = 0; \ ++ } ++ + for (i = 0; i < msg.fu.nRects; i++) { + if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) { + return False; @@ -11771,8 +12947,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + rect.r.w = Swap16IfLE(rect.r.w); + rect.r.h = Swap16IfLE(rect.r.h); + ++ if (rdb > 1) fprintf(stderr, "nRects: %d i=%d enc: %d %dx%d+%d+%d\n", msg.fu.nRects, i, rect.encoding, rect.r.w, rect.r.h, rect.r.x, rect.r.y); + + if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { ++ cnt_pseudo++; ++ STOP_DELAY_SYNC ++ + if (db) fprintf(stderr, "FBU-Cur1 %.6f\n", dnow()); + if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) { + return False; @@ -11782,6 +12962,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + + if (rect.encoding == rfbEncodingPointerPos) { ++ cnt_pseudo++; ++ STOP_DELAY_SYNC + if (db) fprintf(stderr, "FBU-Pos1 %.6f\n", dnow()); + if (0) fprintf(stderr, "CursorPos: %d %d / %d %d\n", rect.r.x, rect.r.y, rect.r.w, rect.r.h); + if (ultra_scale > 0) { @@ -11798,6 +12980,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + continue; + } + if (rect.encoding == rfbEncodingNewFBSize) { ++ cnt_pseudo++; ++ STOP_DELAY_SYNC + if (appData.chatOnly) { + continue; + } @@ -11809,6 +12993,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + continue; + } + if (rdb) fprintf(stderr,"Rect: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); ++ cnt_image++; + + if (appData.ultraDSM) { + /* @@ -11862,6 +13047,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + + if (db) fprintf(stderr, "FBU-SCL2 %.6f\n", dnow()); + ++ + switch (rect.encoding) { + + case rfbEncodingRaw: @@ -11892,6 +13078,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + { + rfbCopyRect cr; + ++ STOP_DELAY_SYNC ++ XSync(dpy, False); ++ + if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) { + return False; + } @@ -12155,7 +13344,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (db) fprintf(stderr, "FBU-SUL2 %.6f\n", dnow()); + } + ++ if (try_delay_sync) { ++ skip_maybe_sync = 0; ++ } ++ + if (1 || area_copyrect) { ++ /* we always do this now for some reason... */ + if (db) fprintf(stderr, "FBU-XSN1 %.6f\n", dnow()); + XSync(dpy, False); + if (db) fprintf(stderr, "FBU-XSN2 %.6f\n", dnow()); @@ -12192,7 +13386,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #ifdef MITSHM /* if using shared memory PutImage, make sure that the X server has -@@ -1224,59 +2529,165 @@ +@@ -1224,59 +3152,168 @@ mainly to avoid copyrect using invalid screen contents - not sure if we'd need it otherwise. */ @@ -12203,11 +13397,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } else #endif + { ++ /* we do it always now. */ + XSync(dpy, False); + } + + if (skip_XtUpdate || skip_incFBU) { + ; ++ } else if (appData.pipelineUpdates) { ++ ; + } else if (!SendIncrementalFramebufferUpdateRequest()) { + return False; + } @@ -12223,20 +13420,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie { - Window toplevelWin; + Window toplevelWin; - -- XBell(dpy, 0); ++ + if (appData.useBell) { + XBell(dpy, 0); + } -- if (appData.raiseOnBeep) { -- toplevelWin = XtWindow(toplevel); -- XMapRaised(dpy, toplevelWin); +- XBell(dpy, 0); + if (appData.raiseOnBeep) { + toplevelWin = XtWindow(toplevel); + XMapRaised(dpy, toplevelWin); + } -+ + +- if (appData.raiseOnBeep) { +- toplevelWin = XtWindow(toplevel); +- XMapRaised(dpy, toplevelWin); + break; } @@ -12391,7 +13588,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -1296,26 +2707,47 @@ +@@ -1296,26 +3333,93 @@ #define CONCAT2(a,b) a##b #define CONCAT2E(a,b) CONCAT2(a,b) @@ -12400,13 +13597,41 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + +static unsigned char* frameBuffer = NULL; +static int frameBufferLen = 0; ++ ++#ifdef TURBOVNC ++#include "turbovnc/turbojpeg.h" ++tjhandle tjhnd=NULL; ++static char *compressedData = NULL; ++static char *uncompressedData = NULL; ++#define CopyDataToImage CopyDataToScreen ++static void turbovnc_FillRectangle(XGCValues *gcv, int rx, int ry, int rw, int rh) { ++ if (!appData.useXserverBackingStore) { ++ FillScreen(rx, ry, rw, rh, gcv->foreground); ++ } else { ++ XChangeGC(dpy, gc, GCForeground, gcv); ++ XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); ++ } ++} ++static void CopyImageToScreen(int x, int y, int w, int h) { ++ put_image(x, y, x, y, w, h, 0); ++} ++#endif + #define BPP 8 #include "rre.c" #include "corre.c" #include "hextile.c" #include "zlib.c" ++// ++#ifdef TURBOVNC ++#undef FillRectangle ++#define FillRectangle turbovnc_FillRectangle ++#include "turbovnc/tight.c" ++#undef FillRectangle ++#else #include "tight.c" ++#endif ++// +#include "zrle.c" #undef BPP + @@ -12415,7 +13640,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #include "corre.c" #include "hextile.c" #include "zlib.c" ++// ++#ifdef TURBOVNC ++#undef FillRectangle ++#define FillRectangle turbovnc_FillRectangle ++#include "turbovnc/tight.c" ++#undef FillRectangle ++#else #include "tight.c" ++#endif ++// +#include "zrle.c" +#define REALBPP 15 +#include "zrle.c" @@ -12426,7 +13660,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #include "corre.c" #include "hextile.c" #include "zlib.c" ++// ++#ifdef TURBOVNC ++#undef FillRectangle ++#define FillRectangle turbovnc_FillRectangle ++#include "turbovnc/tight.c" ++#undef FillRectangle ++#else #include "tight.c" ++#endif ++// +#include "zrle.c" +#define REALBPP 24 +#include "zrle.c" @@ -12439,7 +13682,49 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #undef BPP /* -@@ -1358,9 +2790,9 @@ +@@ -1325,23 +3429,27 @@ + static void + ReadConnFailedReason(void) + { +- CARD32 reasonLen; +- char *reason = NULL; ++ CARD32 reasonLen; ++ char *reason = NULL; + +- if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { +- reasonLen = Swap32IfLE(reasonLen); +- if ((reason = malloc(reasonLen)) != NULL && +- ReadFromRFBServer(reason, reasonLen)) { +- fprintf(stderr,"VNC connection failed: %.*s\n", (int)reasonLen, reason); +- free(reason); +- return; +- } +- } ++ if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { ++ reasonLen = Swap32IfLE(reasonLen); ++ if ((reason = malloc(reasonLen)) != NULL && ++ ReadFromRFBServer(reason, reasonLen)) { ++ int len = reasonLen < sizeof(msgbuf) - 10 ? (int) reasonLen : sizeof(msgbuf) - 10; ++ sprintf(msgbuf,"VNC connection failed: %.*s\n", len, reason); ++ wmsg(msgbuf, 1); ++ free(reason); ++ return; ++ } ++ } + +- fprintf(stderr, "VNC connection failed\n"); ++ sprintf(msgbuf, "VNC connection failed\n"); ++ wmsg(msgbuf, 1); + +- if (reason != NULL) +- free(reason); ++ if (reason != NULL) { ++ free(reason); ++ } + } + + /* +@@ -1358,9 +3466,9 @@ " %s significant bit in each byte is leftmost on the screen.\n", (format->bigEndian ? "Most" : "Least")); } else { @@ -12451,7 +13736,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie (format->bigEndian ? "Most" : "Least")); } if (format->trueColour) { -@@ -1462,4 +2894,3 @@ +@@ -1462,4 +3570,3 @@ cinfo->src = &jpegSrcManager; } @@ -12522,98 +13807,504 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/r } + +#undef FillRectangle -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c ---- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400 -+++ vnc_unixsrc/vncviewer/shm.c 2008-10-10 12:26:07.000000000 -0400 -@@ -33,68 +33,97 @@ +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/selection.c vnc_unixsrc/vncviewer/selection.c +--- vnc_unixsrc.orig/vncviewer/selection.c 2004-03-03 04:11:52.000000000 -0500 ++++ vnc_unixsrc/vncviewer/selection.c 2009-05-31 18:35:25.000000000 -0400 +@@ -43,13 +43,16 @@ + unsigned long* length, int* format); + static void LoseSelection(Widget w, Atom *selection); + +-static Bool iAmSelectionOwner = False; ++static Bool PrimarySelectionOwner = False; ++static Bool ClipboardSelectionOwner = False; + static Time prevSelectionTime = 0L; + static Time cutBufferTime = 0L; + + #define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (INT32)((a) - (b)) > 0)) + + ++static Atom clipboard_atom = None; ++ + /* + * InitialiseSelection() must be called after realizing widgets (because + * otherwise XtGetSelectionValue() fails). We register events on the root +@@ -62,22 +65,28 @@ + * available. + */ + +-void +-InitialiseSelection() +-{ ++static int dbg_sel = -1; ++ ++void InitialiseSelection() { + #if XtSpecificationRelease >= 6 +- XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); ++ XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); + #else +- _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); ++ _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); + #endif +- XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); ++ XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); + +- XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, +- NULL); ++ XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, NULL); + +- XtGetSelectionValue(toplevel, XA_PRIMARY, ++ clipboard_atom = XInternAtom(dpy, "CLIPBOARD", False); ++ ++ XtGetSelectionValue(toplevel, XA_PRIMARY, + XInternAtom(dpy, "TIMESTAMP", False), + GetInitialSelectionTimeCallback, NULL, CurrentTime); ++ ++ if (dbg_sel < 0) { ++ dbg_sel = 0; ++ if (getenv("SSVNC_DEBUG_SELECTION")) dbg_sel = 1; ++ } + } + + +@@ -93,13 +102,15 @@ + Atom* selection, Atom* type, XtPointer value, + unsigned long* length, int* format) + { +- if (value && *format == 32 && *length == 1) +- prevSelectionTime = *(CARD32 *)value; +- else +- prevSelectionTime = 0L; +- +- if (value) +- XtFree(value); ++ if (value && *format == 32 && *length == 1) { ++ prevSelectionTime = *(CARD32 *)value; ++ } else { ++ prevSelectionTime = 0L; ++ } ++ ++ if (value) { ++ XtFree(value); ++ } + } + + +@@ -121,26 +132,29 @@ void - ShmCleanup() + SelectionToVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) { -- fprintf(stderr,"ShmCleanup called\n"); -- if (needShmCleanup) { -- shmdt(shminfo.shmaddr); -- shmctl(shminfo.shmid, IPC_RMID, 0); -- needShmCleanup = False; +- Bool always = False; ++ Bool always = appData.sendAlways; ++ Atom sendsel = XA_PRIMARY; + +- if (*num_params != 0) { +- if (strcmp(params[0],"always") == 0) { +- always = True; +- } else if (strcmp(params[0],"new") == 0) { +- always = False; +- } else { +- fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); +- return; +- } - } -+ fprintf(stderr,"ShmCleanup called\n"); -+ if (needShmCleanup) { -+ shmdt(shminfo.shmaddr); -+ shmctl(shminfo.shmid, IPC_RMID, 0); -+ needShmCleanup = False; +- +- if (always) { +- XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, +- TimeFromEvent(event)); +- } else { +- XtGetSelectionValue(w, XA_PRIMARY, XInternAtom(dpy, "TIMESTAMP", False), +- GetSelectionTimeCallback, NULL, TimeFromEvent(event)); +- } ++ if (*num_params != 0) { ++ if (strcmp(params[0],"always") == 0) { ++ always = True; ++ } else if (strcmp(params[0],"new") == 0) { ++ always = False; ++ } else { ++ fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); ++ return; ++ } + } -+} ++ if (appData.sendClipboard && clipboard_atom != None) { ++ sendsel = clipboard_atom; ++ } ++ if (dbg_sel) fprintf(stderr, "SelectionToVNC %s\n", sendsel == XA_PRIMARY ? "PRIMARY" : "CLIPBOARD"); + -+Bool UsingShm() { -+ return needShmCleanup; ++ if (always) { ++ XtGetSelectionValue(w, sendsel, XA_STRING, GetSelectionCallback, NULL, TimeFromEvent(event)); ++ } else { ++ XtGetSelectionValue(w, sendsel, XInternAtom(dpy, "TIMESTAMP", False), GetSelectionTimeCallback, NULL, TimeFromEvent(event)); ++ } } - static int - ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) - { -- caughtShmError = True; -- return 0; -+ caughtShmError = True; -+ return 0; + +@@ -158,10 +172,12 @@ + int len = *length; + char *str = (char *)value; + +- if (str) +- SendClientCutText(str, len); +- else +- SendCutBuffer(); ++ if (str) { ++ if (dbg_sel) fprintf(stderr, "SendClientCutText len: %d\n", len); ++ SendClientCutText(str, len); ++ } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { ++ SendCutBuffer(); ++ } } -+int scale_round(int len, double fac); -+extern int scale_x, scale_y; -+extern double scale_factor_x, scale_factor_y; -+ - XImage * --CreateShmImage() -+CreateShmImage(int do_ycrop) + +@@ -180,26 +196,23 @@ + Atom* type, XtPointer value, unsigned long* length, + int* format) { -- XImage *image; -- XErrorHandler oldXErrorHandler; -- -- if (!XShmQueryExtension(dpy)) -- return NULL; +- if (value && *format == 32 && *length == 1) { ++ if (value && *format == 32 && *length == 1) { ++ Time t = *(CARD32 *)value; + +- Time t = *(CARD32 *)value; - -- image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, -- si.framebufferWidth, si.framebufferHeight); -- if (!image) return NULL; +- if (TIME_LATER(t, prevSelectionTime)) { +- prevSelectionTime = t; +- XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, +- CurrentTime); +- } - -- shminfo.shmid = shmget(IPC_PRIVATE, -- image->bytes_per_line * image->height, -- IPC_CREAT|0777); +- } else { - -- if (shminfo.shmid == -1) { -- XDestroyImage(image); -- return NULL; +- if (TIME_LATER(cutBufferTime, prevSelectionTime)) { +- prevSelectionTime = cutBufferTime; +- SendCutBuffer(); +- } - } - -- shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0); +- if (value) +- XtFree(value); ++ if (TIME_LATER(t, prevSelectionTime)) { ++ prevSelectionTime = t; ++ XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, CurrentTime); ++ } ++ } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { ++ if (TIME_LATER(cutBufferTime, prevSelectionTime)) { ++ prevSelectionTime = cutBufferTime; ++ SendCutBuffer(); ++ } ++ } ++ ++ if (value) { ++ XtFree(value); ++ } + } + + +@@ -209,16 +222,17 @@ + */ + + static void +-SendCutBuffer() +-{ +- char *str; +- int len; ++SendCutBuffer() { ++ char *str; ++ int len; + +- str = XFetchBytes(dpy, &len); +- if (!str) return; ++ if (dbg_sel) fprintf(stderr, "SendCutBuffer len: %d\n", len); + +- SendClientCutText(str, len); +- XFree(str); ++ str = XFetchBytes(dpy, &len); ++ if (!str) return; ++ ++ SendClientCutText(str, len); ++ XFree(str); + } + + +@@ -230,10 +244,11 @@ + static void + CutBufferChange(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) + { +- if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) +- return; ++ if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) { ++ return; ++ } + +- cutBufferTime = ev->xproperty.time; ++ cutBufferTime = ev->xproperty.time; + } + + +@@ -249,36 +264,61 @@ + void + SelectionFromVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) + { +- Bool always = False; +- Time t = TimeFromEvent(event); - -- if (shminfo.shmaddr == (char *)-1) { -- XDestroyImage(image); -- shmctl(shminfo.shmid, IPC_RMID, 0); -- return NULL; +- if (*num_params != 0) { +- if (strcmp(params[0],"always") == 0) { +- always = True; +- } else if (strcmp(params[0],"new") == 0) { +- always = False; +- } else { +- fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); +- return; +- } - } - -- shminfo.readOnly = True; +- if (t == CurrentTime) { +- fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " +- "event with time field\n"); +- return; +- } - -- oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); -- XShmAttach(dpy, &shminfo); -- XSync(dpy, False); -- XSetErrorHandler(oldXErrorHandler); +- if (!serverCutText || (!always && !newServerCutText)) +- return; - -- if (caughtShmError) { -- XDestroyImage(image); -- shmdt(shminfo.shmaddr); -- shmctl(shminfo.shmid, IPC_RMID, 0); -- return NULL; +- newServerCutText = False; +- +- XStoreBytes(dpy, serverCutText, strlen(serverCutText)); +- if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, +- NULL)) { +- iAmSelectionOwner = True; - } -+ XImage *image; -+ XErrorHandler oldXErrorHandler; -+ int ymax = si.framebufferHeight; -+ int xmax = si.framebufferWidth; ++ Bool always = False; ++ Time t = TimeFromEvent(event); ++ int hold_primary = 0; ++ int hold_clipboard = 0; + -+ if (!XShmQueryExtension(dpy)) { -+ return NULL; -+ } -+ if (!appData.useShm) { -+ return NULL; ++ if (dbg_sel) fprintf(stderr, "SelectionFromVNC\n"); ++ ++ if (*num_params != 0) { ++ if (strcmp(params[0],"always") == 0) { ++ always = True; ++ } else if (strcmp(params[0],"new") == 0) { ++ always = False; ++ } else { ++ fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); ++ return; ++ } ++ } ++ ++ if (t == CurrentTime) { ++ fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " ++ "event with time field\n"); ++ return; ++ } ++ ++ if (!serverCutText || (!always && !newServerCutText)) { ++ return; ++ } ++ ++ newServerCutText = False; ++ ++ XStoreBytes(dpy, serverCutText, strlen(serverCutText)); ++ ++ if (appData.recvText == NULL) { ++ appData.recvText = strdup("both"); ++ } ++ if (!strcasecmp(appData.recvText, "primary")) { ++ hold_primary = 1; ++ } else if (!strcasecmp(appData.recvText, "clipboard")) { ++ hold_clipboard = 1; ++ } else { ++ hold_primary = hold_clipboard = 1; ++ } ++ ++ if (!hold_primary) { ++ ; ++ } else if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, NULL)) { ++ PrimarySelectionOwner = True; ++ if (dbg_sel) fprintf(stderr, "Own PRIMARY\n"); ++ } ++ if (!hold_clipboard || clipboard_atom == None) { ++ ; ++ } else if (XtOwnSelection(desktop, clipboard_atom, t, ConvertSelection, LoseSelection, NULL)) { ++ ClipboardSelectionOwner = True; ++ if (dbg_sel) fprintf(stderr, "Own CLIPBOARD\n"); ++ } + } + + +@@ -293,37 +333,36 @@ + XtPointer* value, unsigned long* length, int* format) + { + +- if (*target == XA_STRING && serverCutText != NULL) { +- *type = XA_STRING; +- *length = strlen(serverCutText); +- *value = (XtPointer)XtMalloc(*length); +- memcpy((char*)*value, serverCutText, *length); +- *format = 8; +- return True; +- } ++ if (*target == XA_STRING && serverCutText != NULL) { ++ *type = XA_STRING; ++ *length = strlen(serverCutText); ++ *value = (XtPointer)XtMalloc(*length); ++ memcpy((char*)*value, serverCutText, *length); ++ *format = 8; ++ return True; ++ } + +- if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, ++ if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, + (XPointer*)value, length, format)) { +- if (*target == XInternAtom(dpy, "TARGETS", False)) { +- /* add STRING to list of standard targets */ +- Atom* targetP; +- Atom* std_targets = (Atom*)*value; +- unsigned long std_length = *length; +- +- *length = std_length + 1; +- *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); +- targetP = *(Atom**)value; +- *targetP++ = XA_STRING; +- memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); +- XtFree((char*)std_targets); +- *type = XA_ATOM; +- *format = 32; +- return True; +- } +- +- return True; +- } +- return False; ++ if (*target == XInternAtom(dpy, "TARGETS", False)) { ++ /* add STRING to list of standard targets */ ++ Atom* targetP; ++ Atom* std_targets = (Atom*)*value; ++ unsigned long std_length = *length; ++ ++ *length = std_length + 1; ++ *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); ++ targetP = *(Atom**)value; ++ *targetP++ = XA_STRING; ++ memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); ++ XtFree((char*)std_targets); ++ *type = XA_ATOM; ++ *format = 32; ++ return True; ++ } ++ return True; ++ } ++ return False; + } + + +@@ -332,7 +371,12 @@ + */ + + static void +-LoseSelection(Widget w, Atom *selection) +-{ +- iAmSelectionOwner = False; ++LoseSelection(Widget w, Atom *selection) { ++ if (*selection == XA_PRIMARY) { ++ if (dbg_sel) fprintf(stderr, "lost PRIMARY\n"); ++ PrimarySelectionOwner = False; ++ } else if (clipboard_atom != None && *selection == clipboard_atom) { ++ if (dbg_sel) fprintf(stderr, "lost CLIPBOARD\n"); ++ ClipboardSelectionOwner = False; ++ } + } +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c +--- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400 ++++ vnc_unixsrc/vncviewer/shm.c 2008-10-10 12:26:07.000000000 -0400 +@@ -33,68 +33,97 @@ + void + ShmCleanup() + { +- fprintf(stderr,"ShmCleanup called\n"); +- if (needShmCleanup) { +- shmdt(shminfo.shmaddr); +- shmctl(shminfo.shmid, IPC_RMID, 0); +- needShmCleanup = False; +- } ++ fprintf(stderr,"ShmCleanup called\n"); ++ if (needShmCleanup) { ++ shmdt(shminfo.shmaddr); ++ shmctl(shminfo.shmid, IPC_RMID, 0); ++ needShmCleanup = False; ++ } ++} ++ ++Bool UsingShm() { ++ return needShmCleanup; + } + + static int + ShmCreationXErrorHandler(Display *dpy, XErrorEvent *error) + { +- caughtShmError = True; +- return 0; ++ caughtShmError = True; ++ return 0; + } + ++int scale_round(int len, double fac); ++extern int scale_x, scale_y; ++extern double scale_factor_x, scale_factor_y; ++ + XImage * +-CreateShmImage() ++CreateShmImage(int do_ycrop) + { +- XImage *image; +- XErrorHandler oldXErrorHandler; +- +- if (!XShmQueryExtension(dpy)) +- return NULL; +- +- image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo, +- si.framebufferWidth, si.framebufferHeight); +- if (!image) return NULL; +- +- shminfo.shmid = shmget(IPC_PRIVATE, +- image->bytes_per_line * image->height, +- IPC_CREAT|0777); +- +- if (shminfo.shmid == -1) { +- XDestroyImage(image); +- return NULL; +- } +- +- shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0); +- +- if (shminfo.shmaddr == (char *)-1) { +- XDestroyImage(image); +- shmctl(shminfo.shmid, IPC_RMID, 0); +- return NULL; +- } +- +- shminfo.readOnly = True; +- +- oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler); +- XShmAttach(dpy, &shminfo); +- XSync(dpy, False); +- XSetErrorHandler(oldXErrorHandler); +- +- if (caughtShmError) { +- XDestroyImage(image); +- shmdt(shminfo.shmaddr); +- shmctl(shminfo.shmid, IPC_RMID, 0); +- return NULL; +- } ++ XImage *image; ++ XErrorHandler oldXErrorHandler; ++ int ymax = si.framebufferHeight; ++ int xmax = si.framebufferWidth; ++ ++ if (!XShmQueryExtension(dpy)) { ++ return NULL; ++ } ++ if (!appData.useShm) { ++ return NULL; + } + if (do_ycrop == -1) { + /* kludge to test for shm prescence */ @@ -12692,7 +14383,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/smake vnc_unixsrc/vncviewer/s +fi diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncviewer/sockets.c --- vnc_unixsrc.orig/vncviewer/sockets.c 2001-01-14 22:54:18.000000000 -0500 -+++ vnc_unixsrc/vncviewer/sockets.c 2008-10-15 08:30:41.000000000 -0400 ++++ vnc_unixsrc/vncviewer/sockets.c 2009-03-30 23:14:48.000000000 -0400 @@ -27,6 +27,7 @@ #include #include @@ -12701,7 +14392,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview #include #include #include -@@ -56,22 +57,366 @@ +@@ -56,31 +57,376 @@ */ static Bool rfbsockReady = False; @@ -12722,11 +14413,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview + if (do_xfrsockId) { + XtRemoveInput(xfrsockId); + } -+} -+ -+static void + } + + static void +-ProcessXtEvents() +xfrsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) -+{ + { +- rfbsockReady = False; +- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, +- rfbsockReadyCallback, NULL); +- while (!rfbsockReady) { +- XtAppProcessEvent(appContext, XtIMAll); +- } + xfrsockReady = True; + XtRemoveInput(xfrsockId); + if (do_rfbsockId) { @@ -12927,8 +14625,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview + } +//fprintf(stderr, "Out CheckFileXfer\n"); + return; - } - ++} ++ +static void check_term_chat(void) { + fd_set fds; + struct timeval tv; @@ -12973,15 +14671,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview + +extern double start_time; + - static void - ProcessXtEvents() - { -- rfbsockReady = False; -- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, -- rfbsockReadyCallback, NULL); -- while (!rfbsockReady) { -- XtAppProcessEvent(appContext, XtIMAll); -- } ++void ProcessXtEvents() ++{ + int y, db = 0; + static int dyn = -1; + static int chat_was_active = 0; @@ -13076,7 +14767,32 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview } Bool -@@ -151,6 +496,8 @@ + ReadFromRFBServer(char *out, unsigned int n) + { ++// double start = dnow(), dn = n; + if (n <= buffered) { + memcpy(out, bufoutptr, n); + bufoutptr += n; + buffered -= n; ++//fprintf(stderr, "R0: %06d\n", (int) dn); + return True; + } + +@@ -119,6 +465,7 @@ + memcpy(out, bufoutptr, n); + bufoutptr += n; + buffered -= n; ++//fprintf(stderr, "R1: %06d %06d %10.2f KB/sec\n", (int) dn, buffered+n, 1e-3 * (buffered+n)/(dnow() - start)); + return True; + + } else { +@@ -146,11 +493,14 @@ + n -= i; + } + ++//fprintf(stderr, "R2: %06d %06d %10.2f KB/sec\n", (int) dn, (int) dn, 1e-3 * (dn)/(dnow() - start)); + return True; + } } @@ -13085,7 +14801,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview /* * Write an exact number of bytes, and don't return until you've sent them. */ -@@ -158,37 +505,81 @@ +@@ -158,37 +508,81 @@ Bool WriteExact(int sock, char *buf, int n) { @@ -13196,7 +14912,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview } -@@ -203,6 +594,8 @@ +@@ -203,6 +597,8 @@ struct sockaddr_in addr; int one = 1; @@ -13205,7 +14921,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = host; -@@ -232,7 +625,22 @@ +@@ -232,7 +628,22 @@ return sock; } @@ -13228,7 +14944,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview /* * FindFreeTcpPort tries to find unused TCP port in the range -@@ -245,6 +653,8 @@ +@@ -245,6 +656,8 @@ int sock, port; struct sockaddr_in addr; @@ -13237,7 +14953,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; -@@ -272,6 +682,8 @@ +@@ -272,6 +685,8 @@ * ListenAtTcpPort starts listening at the given TCP port. */ @@ -13246,82 +14962,949 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview int ListenAtTcpPort(int port) { -@@ -279,10 +691,16 @@ +@@ -279,10 +694,16 @@ struct sockaddr_in addr; int one = 1; + memset(&addr, 0, sizeof(struct sockaddr_in)); + - addr.sin_family = AF_INET; - addr.sin_port = htons(port); - addr.sin_addr.s_addr = INADDR_ANY; - -+ if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) { -+ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); -+ } + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = INADDR_ANY; + ++ if (getenv("VNCVIEWER_LISTEN_LOCALHOST") || use_loopback) { ++ addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ++ } ++ + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + fprintf(stderr,programName); +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c +--- vnc_unixsrc.orig/vncviewer/tight.c 2002-04-30 09:07:31.000000000 -0400 ++++ vnc_unixsrc/vncviewer/tight.c 2008-10-05 15:16:35.000000000 -0400 +@@ -129,14 +129,21 @@ + #endif + + #if (BPP == 8) +- gcv.foreground = (appData.useBGR233) ? +- BGR233ToPixel[fill_colour] : fill_colour; ++ gcv.foreground = (appData.useBGR233) ? BGR233ToPixel[fill_colour] : fill_colour; ++#else ++#if (BPP == 16) ++ gcv.foreground = (appData.useBGR565) ? BGR565ToPixel[fill_colour] : fill_colour; + #else + gcv.foreground = fill_colour; + #endif ++#endif + +- XChangeGC(dpy, gc, GCForeground, &gcv); +- XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); ++ if (!appData.useXserverBackingStore) { ++ FillScreen(rx, ry, rw, rh, gcv.foreground); ++ } else { ++ XChangeGC(dpy, gc, GCForeground, &gcv); ++ XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); ++ } + return True; + } + +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tmake vnc_unixsrc/vncviewer/tmake +--- vnc_unixsrc.orig/vncviewer/tmake 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/tmake 2009-03-08 17:11:49.000000000 -0400 +@@ -0,0 +1,13 @@ ++#!/bin/sh ++TURBOVNC_DIR=/home/runge/turbojpeg ++make clean ++make CCOPTIONS=-DTURBOVNC EXTRA_LIBRARIES="-L$TURBOVNC_DIR -Xlinker --rpath=$TURBOVNC_DIR -Xlinker --rpath=/usr/local/lib -lturbojpeg" ++cp -p vncviewer vncviewer.turbovnc ++strip vncviewer.turbovnc ++ls -l vncviewer.turbovnc ++ldd vncviewer.turbovnc ++ ++echo ++make clean all ++ls -l vncviewer ++ldd vncviewer +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tunnel.c vnc_unixsrc/vncviewer/tunnel.c +--- vnc_unixsrc.orig/vncviewer/tunnel.c 2003-07-31 04:03:49.000000000 -0400 ++++ vnc_unixsrc/vncviewer/tunnel.c 2007-05-08 21:28:01.000000000 -0400 +@@ -132,6 +132,7 @@ + { + char *colonPos; + int len, portOffset; ++ int disp; + + if (tunnelArgIndex >= *pargc - 2) + usage(); +@@ -153,7 +154,14 @@ + if (!len || strspn(colonPos, "-0123456789") != len) { + usage(); + } ++#if 0 + *remotePort = atoi(colonPos) + portOffset; ++#else ++ disp = atoi(colonPos); ++ if (portOffset != 0 && disp >= 100) ++ portOffset = 0; ++ *remotePort = disp + portOffset; ++#endif + } + + sprintf(lastArgv, "localhost::%d", localPort); +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/tight.c vnc_unixsrc/vncviewer/turbovnc/tight.c +--- vnc_unixsrc.orig/vncviewer/turbovnc/tight.c 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/turbovnc/tight.c 2008-08-20 13:35:58.000000000 -0400 +@@ -0,0 +1,613 @@ ++/* ++ * Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. ++ * Copyright (C) 2004 Landmark Graphics Corporation. All Rights Reserved. ++ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++ ++/* ++ * tight.c - handle ``tight'' encoding. ++ * ++ * This file shouldn't be compiled directly. It is included multiple ++ * times by rfbproto.c, each time with a different definition of the ++ * macro BPP. For each value of BPP, this file defines a function ++ * which handles a tight-encoded rectangle with BPP bits per pixel. ++ * ++ */ ++ ++#define TIGHT_MIN_TO_COMPRESS 12 ++ ++#define CARDBPP CONCAT2E(CARD,BPP) ++#define filterPtrBPP CONCAT2E(filterPtr,BPP) ++ ++#define HandleTightBPP CONCAT2E(HandleTight,BPP) ++#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) ++#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) ++#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) ++#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) ++#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) ++#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) ++ ++#if BPP != 8 ++#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) ++#endif ++ ++#ifndef RGB_TO_PIXEL ++ ++#define RGB_TO_PIXEL(bpp,r,g,b) \ ++ (((CARD##bpp)(r) & myFormat.redMax) << myFormat.redShift | \ ++ ((CARD##bpp)(g) & myFormat.greenMax) << myFormat.greenShift | \ ++ ((CARD##bpp)(b) & myFormat.blueMax) << myFormat.blueShift) ++ ++#define RGB24_TO_PIXEL(bpp,r,g,b) \ ++ ((((CARD##bpp)(r) & 0xFF) * myFormat.redMax + 127) / 255 \ ++ << myFormat.redShift | \ ++ (((CARD##bpp)(g) & 0xFF) * myFormat.greenMax + 127) / 255 \ ++ << myFormat.greenShift | \ ++ (((CARD##bpp)(b) & 0xFF) * myFormat.blueMax + 127) / 255 \ ++ << myFormat.blueShift) ++ ++#define RGB24_TO_PIXEL32(r,g,b) \ ++ (((CARD32)(r) & 0xFF) << myFormat.redShift | \ ++ ((CARD32)(g) & 0xFF) << myFormat.greenShift | \ ++ ((CARD32)(b) & 0xFF) << myFormat.blueShift) ++ ++#endif ++ ++extern XImage *image; ++ ++/* Type declarations */ ++ ++typedef void (*filterPtrBPP)(int, int, int); ++ ++/* Prototypes */ ++ ++static int InitFilterCopyBPP (int rw, int rh); ++static int InitFilterPaletteBPP (int rw, int rh); ++static int InitFilterGradientBPP (int rw, int rh); ++static void FilterCopyBPP (int srcx, int srcy, int numRows); ++static void FilterPaletteBPP (int srcx, int srcy, int numRows); ++static void FilterGradientBPP (int srcx, int srcy, int numRows); ++ ++static Bool DecompressJpegRectBPP(int x, int y, int w, int h); ++ ++/* Definitions */ ++ ++static Bool ++HandleTightBPP (int rx, int ry, int rw, int rh) ++{ ++ CARDBPP fill_colour; ++ XGCValues gcv; ++ CARD8 comp_ctl; ++ CARD8 filter_id; ++ filterPtrBPP filterFn; ++ z_streamp zs; ++ int err, stream_id, compressedLen, bitsPixel; ++ int bufferSize, rowSize, numRows; ++ Bool readUncompressed = False; ++ CARDBPP *rawData; ++ ++ if (!ReadFromRFBServer((char *)&comp_ctl, 1)) ++ return False; ++ ++ /* Flush zlib streams if we are told by the server to do so. */ ++ for (stream_id = 0; stream_id < 4; stream_id++) { ++ if ((comp_ctl & 1) && zlibStreamActive[stream_id]) { ++ if (inflateEnd (&zlibStream[stream_id]) != Z_OK && ++ zlibStream[stream_id].msg != NULL) ++ fprintf(stderr, "inflateEnd: %s\n", zlibStream[stream_id].msg); ++ zlibStreamActive[stream_id] = False; ++ } ++ comp_ctl >>= 1; ++ } ++ ++ if ((comp_ctl & rfbTightNoZlib) == rfbTightNoZlib) { ++ comp_ctl &= ~(rfbTightNoZlib); ++ readUncompressed = True; ++ } ++ ++ /* Handle solid rectangles. */ ++ if (comp_ctl == rfbTightFill) { ++#if BPP == 32 ++ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && ++ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { ++ if (!ReadFromRFBServer(buffer, 3)) ++ return False; ++ fill_colour = RGB24_TO_PIXEL32(buffer[0], buffer[1], buffer[2]); ++ } else { ++ if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) ++ return False; ++ } ++#else ++ if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) ++ return False; ++#endif ++ ++#if (BPP == 8) ++ gcv.foreground = (appData.useBGR233) ? ++ BGR233ToPixel[fill_colour] : fill_colour; ++#else ++ gcv.foreground = fill_colour; ++#endif ++ ++ FillRectangle(&gcv, rx, ry, rw, rh); ++ return True; ++ } ++ ++#if BPP == 8 ++ if (comp_ctl == rfbTightJpeg) { ++ fprintf(stderr, "Tight encoding: JPEG is not supported in 8 bpp mode.\n"); ++ return False; ++ } ++#else ++ if (comp_ctl == rfbTightJpeg) { ++ return DecompressJpegRectBPP(rx, ry, rw, rh); ++ } ++#endif ++ ++ /* Quit on unsupported subencoding value. */ ++ if (comp_ctl > rfbTightMaxSubencoding) { ++ fprintf(stderr, "Tight encoding: bad subencoding value received.\n"); ++ return False; ++ } ++ ++ /* ++ * Here primary compression mode handling begins. ++ * Data was processed with optional filter + zlib compression. ++ */ ++ ++ /* First, we should identify a filter to use. */ ++ if ((comp_ctl & rfbTightExplicitFilter) != 0) { ++ if (!ReadFromRFBServer((char*)&filter_id, 1)) ++ return False; ++ ++ switch (filter_id) { ++ case rfbTightFilterCopy: ++ filterFn = FilterCopyBPP; ++ bitsPixel = InitFilterCopyBPP(rw, rh); ++ break; ++ case rfbTightFilterPalette: ++ filterFn = FilterPaletteBPP; ++ bitsPixel = InitFilterPaletteBPP(rw, rh); ++ break; ++ case rfbTightFilterGradient: ++ filterFn = FilterGradientBPP; ++ bitsPixel = InitFilterGradientBPP(rw, rh); ++ break; ++ default: ++ fprintf(stderr, "Tight encoding: unknown filter code received.\n"); ++ return False; ++ } ++ } else { ++ filterFn = FilterCopyBPP; ++ bitsPixel = InitFilterCopyBPP(rw, rh); ++ } ++ if (bitsPixel == 0) { ++ fprintf(stderr, "Tight encoding: error receiving palette.\n"); ++ return False; ++ } ++ ++ /* Determine if the data should be decompressed or just copied. */ ++ rowSize = (rw * bitsPixel + 7) / 8; ++ bufferSize = -1; ++ if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) ++ bufferSize = rh * rowSize; ++ else if (readUncompressed) { ++ bufferSize = (int)ReadCompactLen(); ++ } ++ if (bufferSize != -1) { ++ uncompressedData = (char *)realloc(uncompressedData, bufferSize); ++ if (!uncompressedData) { ++ fprintf(stderr, "Memory allocation error\n"); ++ return False; ++ } ++ if (!ReadFromRFBServer(uncompressedData, bufferSize)) ++ return False; ++ filterFn(rx, ry, rh); ++ if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); ++ if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); ++ ++ return True; ++ } ++ ++ /* Read the length (1..3 bytes) of compressed data following. */ ++ compressedLen = (int)ReadCompactLen(); ++ if (compressedLen <= 0) { ++ fprintf(stderr, "Incorrect data received from the server.\n"); ++ return False; ++ } ++ ++ /* Now let's initialize compression stream if needed. */ ++ stream_id = comp_ctl & 0x03; ++ zs = &zlibStream[stream_id]; ++ if (!zlibStreamActive[stream_id]) { ++ zs->zalloc = Z_NULL; ++ zs->zfree = Z_NULL; ++ zs->opaque = Z_NULL; ++ err = inflateInit(zs); ++ if (err != Z_OK) { ++ if (zs->msg != NULL) ++ fprintf(stderr, "InflateInit error: %s.\n", zs->msg); ++ return False; ++ } ++ zlibStreamActive[stream_id] = True; ++ } ++ ++ /* Read, decode and draw actual pixel data in a loop. */ ++ ++ compressedData = (char *)realloc(compressedData, compressedLen); ++ if (!compressedData) { ++ fprintf(stderr, "Memory allocation error\n"); ++ return False; ++ } ++ uncompressedData = (char *)realloc(uncompressedData, rh * rowSize); ++ if (!uncompressedData) { ++ fprintf(stderr, "Memory allocation error\n"); ++ return False; ++ } ++ ++ if (!ReadFromRFBServer(compressedData, compressedLen)) ++ return False; ++ zs->next_in = (Bytef *)compressedData; ++ zs->avail_in = compressedLen; ++ zs->next_out = (Bytef *)uncompressedData; ++ zs->avail_out = rh * rowSize; ++ ++ err = inflate(zs, Z_SYNC_FLUSH); ++ if (err != Z_OK && err != Z_STREAM_END) { ++ if (zs->msg != NULL) { ++ fprintf(stderr, "Inflate error: %s.\n", zs->msg); ++ } else { ++ fprintf(stderr, "Inflate error: %d.\n", err); ++ } ++ return False; ++ } ++ ++ filterFn(rx, ry, rh); ++ if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); ++ if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); ++ ++ return True; ++} ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Filter stuff. ++ * ++ */ ++ ++/* ++ The following variables are defined in rfbproto.c: ++ static Bool cutZeros; ++ static int rectWidth, rectColors; ++ static CARD8 tightPalette[256*4]; ++ static CARD8 tightPrevRow[2048*3*sizeof(CARD16)]; ++*/ ++ ++static int ++InitFilterCopyBPP (int rw, int rh) ++{ ++ rectWidth = rw; ++ ++#if BPP == 32 ++ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && ++ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { ++ cutZeros = True; ++ return 24; ++ } else { ++ cutZeros = False; ++ } ++#endif ++ ++ return BPP; ++} ++ ++static void ++FilterCopyBPP (int srcx, int srcy, int numRows) ++{ ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ int y; ++#if BPP == 32 ++ int x; ++#endif ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++#if BPP == 32 ++ if (cutZeros) { ++ for (y = 0; y < numRows; y++) { ++ for (x = 0; x < rectWidth; x++) { ++ dst[y*dstw+x] = ++ RGB24_TO_PIXEL32(uncompressedData[(y*rectWidth+x)*3], ++ uncompressedData[(y*rectWidth+x)*3+1], ++ uncompressedData[(y*rectWidth+x)*3+2]); ++ } ++ } ++ return; ++ } ++#endif ++ ++ for (y = 0; y < numRows; y++) ++ memcpy (&dst[y*dstw], &uncompressedData[y*rectWidth], rectWidth * (BPP / 8)); ++} ++ ++static int ++InitFilterGradientBPP (int rw, int rh) ++{ ++ int bits; ++ ++ bits = InitFilterCopyBPP(rw, rh); ++ if (cutZeros) ++ memset(tightPrevRow, 0, rw * 3); ++ else ++ memset(tightPrevRow, 0, rw * 3 * sizeof(CARD16)); ++ ++ return bits; ++} ++ ++#if BPP == 32 ++ ++static void ++FilterGradient24 (int srcx, int srcy, int numRows) ++{ ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ int x, y, c; ++ CARD8 thisRow[2048*3]; ++ CARD8 pix[3]; ++ int est[3]; ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++ for (y = 0; y < numRows; y++) { ++ ++ /* First pixel in a row */ ++ for (c = 0; c < 3; c++) { ++ pix[c] = tightPrevRow[c] + uncompressedData[y*rectWidth*3+c]; ++ thisRow[c] = pix[c]; ++ } ++ dst[y*dstw] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); ++ ++ /* Remaining pixels of a row */ ++ for (x = 1; x < rectWidth; x++) { ++ for (c = 0; c < 3; c++) { ++ est[c] = (int)tightPrevRow[x*3+c] + (int)pix[c] - ++ (int)tightPrevRow[(x-1)*3+c]; ++ if (est[c] > 0xFF) { ++ est[c] = 0xFF; ++ } else if (est[c] < 0x00) { ++ est[c] = 0x00; ++ } ++ pix[c] = (CARD8)est[c] + buffer[(y*rectWidth+x)*3+c]; ++ thisRow[x*3+c] = pix[c]; ++ } ++ dst[y*dstw+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); ++ } ++ ++ memcpy(tightPrevRow, thisRow, rectWidth * 3); ++ } ++} ++ ++#endif ++ ++static void ++FilterGradientBPP (int srcx, int srcy, int numRows) ++{ ++ int x, y, c; ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ CARDBPP *src = (CARDBPP *)uncompressedData; ++ CARD16 *thatRow = (CARD16 *)tightPrevRow; ++ CARD16 thisRow[2048*3]; ++ CARD16 pix[3]; ++ CARD16 max[3]; ++ int shift[3]; ++ int est[3]; ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++#if BPP == 32 ++ if (cutZeros) { ++ FilterGradient24(srcx, srcy, numRows); ++ return; ++ } ++#endif ++ ++ max[0] = myFormat.redMax; ++ max[1] = myFormat.greenMax; ++ max[2] = myFormat.blueMax; ++ ++ shift[0] = myFormat.redShift; ++ shift[1] = myFormat.greenShift; ++ shift[2] = myFormat.blueShift; ++ ++ for (y = 0; y < numRows; y++) { ++ ++ /* First pixel in a row */ ++ for (c = 0; c < 3; c++) { ++ pix[c] = (CARD16)((src[y*rectWidth] >> shift[c]) + thatRow[c] & max[c]); ++ thisRow[c] = pix[c]; ++ } ++ dst[y*dstw] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); ++ ++ /* Remaining pixels of a row */ ++ for (x = 1; x < rectWidth; x++) { ++ for (c = 0; c < 3; c++) { ++ est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; ++ if (est[c] > (int)max[c]) { ++ est[c] = (int)max[c]; ++ } else if (est[c] < 0) { ++ est[c] = 0; ++ } ++ pix[c] = (CARD16)((src[y*rectWidth+x] >> shift[c]) + est[c] & max[c]); ++ thisRow[x*3+c] = pix[c]; ++ } ++ dst[y*dstw+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); ++ } ++ memcpy(thatRow, thisRow, rectWidth * 3 * sizeof(CARD16)); ++ } ++} ++ ++static int ++InitFilterPaletteBPP (int rw, int rh) ++{ ++ int i; ++ CARD8 numColors; ++ CARDBPP *palette = (CARDBPP *)tightPalette; ++ ++ rectWidth = rw; ++ ++ if (!ReadFromRFBServer((char*)&numColors, 1)) ++ return 0; ++ ++ rectColors = (int)numColors; ++ if (++rectColors < 2) ++ return 0; ++ ++#if BPP == 32 ++ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && ++ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { ++ if (!ReadFromRFBServer((char*)&tightPalette, rectColors * 3)) ++ return 0; ++ for (i = rectColors - 1; i >= 0; i--) { ++ palette[i] = RGB24_TO_PIXEL32(tightPalette[i*3], ++ tightPalette[i*3+1], ++ tightPalette[i*3+2]); ++ } ++ return (rectColors == 2) ? 1 : 8; ++ } ++#endif ++ ++ if (!ReadFromRFBServer((char*)&tightPalette, rectColors * (BPP / 8))) ++ return 0; ++ ++ return (rectColors == 2) ? 1 : 8; ++} ++ ++static void ++FilterPaletteBPP (int srcx, int srcy, int numRows) ++{ ++ int x, y, b, w; ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ CARD8 *src = (CARD8 *)uncompressedData; ++ CARDBPP *palette = (CARDBPP *)tightPalette; ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++ if (rectColors == 2) { ++ w = (rectWidth + 7) / 8; ++ for (y = 0; y < numRows; y++) { ++ for (x = 0; x < rectWidth / 8; x++) { ++ for (b = 7; b >= 0; b--) ++ dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; ++ } ++ for (b = 7; b >= 8 - rectWidth % 8; b--) { ++ dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; ++ } ++ } ++ } else { ++ for (y = 0; y < numRows; y++) ++ for (x = 0; x < rectWidth; x++) ++ dst[y*dstw+x] = palette[(int)src[y*rectWidth+x]]; ++ } ++} ++ ++#if BPP != 8 ++ ++/*---------------------------------------------------------------------------- ++ * ++ * JPEG decompression. ++ * ++ */ ++ ++/* ++ The following variables are defined in rfbproto.c: ++ static Bool jpegError; ++ static struct jpeg_source_mgr jpegSrcManager; ++ static JOCTET *jpegBufferPtr; ++ static size_t *jpegBufferLen; ++*/ ++ ++static Bool ++DecompressJpegRectBPP(int x, int y, int w, int h) ++{ ++ int compressedLen; ++ char *dstptr; ++ int ps, flags=0; ++ ++ compressedLen = (int)ReadCompactLen(); ++ if (compressedLen <= 0) { ++ fprintf(stderr, "Incorrect data received from the server.\n"); ++ return False; ++ } ++ ++ compressedData = (char *)realloc(compressedData, compressedLen); ++ if (compressedData == NULL) { ++ fprintf(stderr, "Memory allocation error.\n"); ++ return False; ++ } ++ ++ if (!ReadFromRFBServer(compressedData, compressedLen)) { ++ return False; ++ } ++ ++ if(!tjhnd) { ++ if((tjhnd=tjInitDecompress())==NULL) { ++ fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); ++ return False; ++ } ++ } ++ ++ ps=image->bits_per_pixel/8; ++ if(myFormat.bigEndian && ps==4) flags|=TJ_ALPHAFIRST; ++ if(myFormat.redShift==16 && myFormat.blueShift==0) ++ flags|=TJ_BGR; ++ if(myFormat.bigEndian) flags^=TJ_BGR; ++ ++ dstptr=&image->data[image->bytes_per_line*y+x*ps]; ++ if(tjDecompress(tjhnd, (unsigned char *)compressedData, (unsigned long)compressedLen, ++ (unsigned char *)dstptr, w, image->bytes_per_line, h, ps, flags)==-1) { ++ fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); ++ return False; ++ } ++ ++ if (!appData.doubleBuffer) ++ CopyImageToScreen(x, y, w, h); ++ ++ return True; ++} ++ ++#endif ++ +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h +--- vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h 2008-04-03 04:28:56.000000000 -0400 +@@ -0,0 +1,229 @@ ++/* Copyright (C)2004 Landmark Graphics ++ * Copyright (C)2005, 2006 Sun Microsystems, Inc. ++ * ++ * This library is free software and may be redistributed and/or modified under ++ * the terms of the wxWindows Library License, Version 3.1 or (at your option) ++ * any later version. The full license is in the LICENSE.txt file included ++ * with this distribution. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * wxWindows Library License for more details. ++ */ ++ ++#if (defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)) && defined(_WIN32) && defined(DLLDEFINE) ++#define DLLEXPORT __declspec(dllexport) ++#else ++#define DLLEXPORT ++#endif ++ ++#define DLLCALL ++ ++/* Subsampling */ ++#define NUMSUBOPT 4 ++ ++enum {TJ_444=0, TJ_422, TJ_411, TJ_GRAYSCALE}; ++ ++/* Flags */ ++#define TJ_BGR 1 ++#define TJ_BOTTOMUP 2 ++#define TJ_FORCEMMX 8 /* Force IPP to use MMX code even if SSE available */ ++#define TJ_FORCESSE 16 /* Force IPP to use SSE1 code even if SSE2 available */ ++#define TJ_FORCESSE2 32 /* Force IPP to use SSE2 code (useful if auto-detect is not working properly) */ ++#define TJ_ALPHAFIRST 64 /* BGR buffer is ABGR and RGB buffer is ARGB */ ++#define TJ_FORCESSE3 128 /* Force IPP to use SSE3 code (useful if auto-detect is not working properly) */ ++ ++typedef void* tjhandle; ++ ++#define TJPAD(p) (((p)+3)&(~3)) ++#ifndef max ++ #define max(a,b) ((a)>(b)?(a):(b)) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* API follows */ ++ ++ ++/* ++ tjhandle tjInitCompress(void) ++ ++ Creates a new JPEG compressor instance, allocates memory for the structures, ++ and returns a handle to the instance. Most applications will only ++ need to call this once at the beginning of the program or once for each ++ concurrent thread. Don't try to create a new instance every time you ++ compress an image, because this will cause performance to suffer. ++ ++ RETURNS: NULL on error ++*/ ++DLLEXPORT tjhandle DLLCALL tjInitCompress(void); ++ ++ ++/* ++ int tjCompress(tjhandle j, ++ unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, ++ unsigned char *dstbuf, unsigned long *size, ++ int jpegsubsamp, int jpegqual, int flags) ++ ++ [INPUT] j = instance handle previously returned from a call to ++ tjInitCompress() ++ [INPUT] srcbuf = pointer to user-allocated image buffer containing pixels in ++ RGB(A) or BGR(A) form ++ [INPUT] width = width (in pixels) of the source image ++ [INPUT] pitch = bytes per line of the source image (width*pixelsize if the ++ bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap ++ is padded to the nearest 32-bit boundary, such as is the case for Windows ++ bitmaps. You can also be clever and use this parameter to skip lines, etc., ++ as long as the pitch is greater than 0.) ++ [INPUT] height = height (in pixels) of the source image ++ [INPUT] pixelsize = size (in bytes) of each pixel in the source image ++ RGBA and BGRA: 4, RGB and BGR: 3 ++ [INPUT] dstbuf = pointer to user-allocated image buffer which will receive ++ the JPEG image. Use the macro TJBUFSIZE(width, height) to determine ++ the appropriate size for this buffer based on the image width and height. ++ [OUTPUT] size = pointer to unsigned long which receives the size (in bytes) ++ of the compressed image ++ [INPUT] jpegsubsamp = Specifies either 4:1:1, 4:2:2, or 4:4:4 subsampling. ++ When the image is converted from the RGB to YCbCr colorspace as part of the ++ JPEG compression process, every other Cb and Cr (chrominance) pixel can be ++ discarded to produce a smaller image with little perceptible loss of ++ image clarity (the human eye is more sensitive to small changes in ++ brightness than small changes in color.) ++ ++ TJ_411: 4:1:1 subsampling. Discards every other Cb, Cr pixel in both ++ horizontal and vertical directions. ++ TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in ++ the horizontal direction. ++ TJ_444: no subsampling. ++ TJ_GRAYSCALE: Generate grayscale JPEG image ++ ++ [INPUT] jpegqual = JPEG quality (an integer between 0 and 100 inclusive.) ++ [INPUT] flags = the bitwise OR of one or more of the following ++ ++ TJ_BGR: The components of each pixel in the source image are stored in ++ B,G,R order, not R,G,B ++ TJ_BOTTOMUP: The source image is stored in bottom-up (Windows) order, ++ not top-down ++ TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use MMX code (bypass CPU auto-detection) ++ TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE code (bypass CPU auto-detection) ++ TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) ++ TJ_FORCESSE3: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE3 code (bypass CPU auto-detection) ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjCompress(tjhandle j, ++ unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, ++ unsigned char *dstbuf, unsigned long *size, ++ int jpegsubsamp, int jpegqual, int flags); ++ ++DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height); ++ ++/* ++ tjhandle tjInitDecompress(void) ++ ++ Creates a new JPEG decompressor instance, allocates memory for the ++ structures, and returns a handle to the instance. Most applications will ++ only need to call this once at the beginning of the program or once for each ++ concurrent thread. Don't try to create a new instance every time you ++ decompress an image, because this will cause performance to suffer. ++ ++ RETURNS: NULL on error ++*/ ++DLLEXPORT tjhandle DLLCALL tjInitDecompress(void); ++ ++ ++/* ++ int tjDecompressHeader(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ int *width, int *height) ++ ++ [INPUT] j = instance handle previously returned from a call to ++ tjInitDecompress() ++ [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image ++ to decompress ++ [INPUT] size = size of the JPEG image buffer (in bytes) ++ [OUTPUT] width = width (in pixels) of the JPEG image ++ [OUTPUT] height = height (in pixels) of the JPEG image ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ int *width, int *height); ++ ++ ++/* ++ int tjDecompress(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, ++ int flags) ++ ++ [INPUT] j = instance handle previously returned from a call to ++ tjInitDecompress() ++ [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image ++ to decompress ++ [INPUT] size = size of the JPEG image buffer (in bytes) ++ [INPUT] dstbuf = pointer to user-allocated image buffer which will receive ++ the bitmap image. This buffer should normally be pitch*height ++ bytes in size, although this pointer may also be used to decompress into ++ a specific region of a larger buffer. ++ [INPUT] width = width (in pixels) of the destination image ++ [INPUT] pitch = bytes per line of the destination image (width*pixelsize if the ++ bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap ++ is padded to the nearest 32-bit boundary, such as is the case for Windows ++ bitmaps. You can also be clever and use this parameter to skip lines, etc., ++ as long as the pitch is greater than 0.) ++ [INPUT] height = height (in pixels) of the destination image ++ [INPUT] pixelsize = size (in bytes) of each pixel in the destination image ++ RGBA/RGBx and BGRA/BGRx: 4, RGB and BGR: 3 ++ [INPUT] flags = the bitwise OR of one or more of the following ++ ++ TJ_BGR: The components of each pixel in the destination image should be ++ written in B,G,R order, not R,G,B ++ TJ_BOTTOMUP: The destination image should be stored in bottom-up ++ (Windows) order, not top-down ++ TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use MMX code (bypass CPU auto-detection) ++ TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE code (bypass CPU auto-detection) ++ TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjDecompress(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, ++ int flags); ++ ++ ++/* ++ int tjDestroy(tjhandle h) ++ ++ Frees structures associated with a compression or decompression instance ++ ++ [INPUT] h = instance handle (returned from a previous call to ++ tjInitCompress() or tjInitDecompress() ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjDestroy(tjhandle h); + - sock = socket(AF_INET, SOCK_STREAM, 0); - if (sock < 0) { - fprintf(stderr,programName); -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer/tight.c ---- vnc_unixsrc.orig/vncviewer/tight.c 2002-04-30 09:07:31.000000000 -0400 -+++ vnc_unixsrc/vncviewer/tight.c 2008-10-05 15:16:35.000000000 -0400 -@@ -129,14 +129,21 @@ - #endif - - #if (BPP == 8) -- gcv.foreground = (appData.useBGR233) ? -- BGR233ToPixel[fill_colour] : fill_colour; -+ gcv.foreground = (appData.useBGR233) ? BGR233ToPixel[fill_colour] : fill_colour; -+#else -+#if (BPP == 16) -+ gcv.foreground = (appData.useBGR565) ? BGR565ToPixel[fill_colour] : fill_colour; - #else - gcv.foreground = fill_colour; - #endif -+#endif - -- XChangeGC(dpy, gc, GCForeground, &gcv); -- XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); -+ if (!appData.useXserverBackingStore) { -+ FillScreen(rx, ry, rw, rh, gcv.foreground); -+ } else { -+ XChangeGC(dpy, gc, GCForeground, &gcv); -+ XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); -+ } - return True; - } - -diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tunnel.c vnc_unixsrc/vncviewer/tunnel.c ---- vnc_unixsrc.orig/vncviewer/tunnel.c 2003-07-31 04:03:49.000000000 -0400 -+++ vnc_unixsrc/vncviewer/tunnel.c 2007-05-08 21:28:01.000000000 -0400 -@@ -132,6 +132,7 @@ - { - char *colonPos; - int len, portOffset; -+ int disp; - - if (tunnelArgIndex >= *pargc - 2) - usage(); -@@ -153,7 +154,14 @@ - if (!len || strspn(colonPos, "-0123456789") != len) { - usage(); - } -+#if 0 - *remotePort = atoi(colonPos) + portOffset; -+#else -+ disp = atoi(colonPos); -+ if (portOffset != 0 && disp >= 100) -+ portOffset = 0; -+ *remotePort = disp + portOffset; ++ ++/* ++ char *tjGetErrorStr(void) ++ ++ Returns a descriptive error message explaining why the last command failed ++*/ ++DLLEXPORT char* DLLCALL tjGetErrorStr(void); ++ ++#ifdef __cplusplus ++} +#endif - } - - sprintf(lastArgv, "localhost::%d", localPort); diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vncviewer/vncviewer._man --- vnc_unixsrc.orig/vncviewer/vncviewer._man 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer._man 2008-12-30 19:24:50.000000000 -0500 -@@ -0,0 +1,739 @@ ++++ vnc_unixsrc/vncviewer/vncviewer._man 2009-05-31 18:53:07.000000000 -0400 +@@ -0,0 +1,780 @@ +'\" t +.\" ** The above line should force tbl to be a preprocessor ** +.\" Man page for X vncviewer @@ -13329,13 +15912,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de +.\" Copyright (C) 2000,2001 Red Hat, Inc. +.\" Copyright (C) 2001-2003 Constantin Kaplinsky -+.\" Copyright (C) 2006-2008 Karl J. Runge ++.\" Copyright (C) 2006-2009 Karl J. Runge +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the file LICENCE.TXT that comes with the +.\" TightVNC distribution. +.\" -+.TH ssvncviewer 1 "December 2008" "" "SSVNC" ++.TH ssvncviewer 1 "June 2009" "" "SSVNC" +.SH NAME +ssvncviewer \- an X viewer client for VNC +.SH SYNOPSIS @@ -13624,6 +16207,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +Prefer raw encoding for localhost, default is +no, i.e. assumes you have a SSH tunnel instead. +.TP ++\fB\-sendclipboard\fR ++Send the X CLIPBOARD selection (i.e. Ctrl+C, ++Ctrl+V) instead of the X PRIMARY selection (mouse ++select and middle button paste.) ++.TP ++\fB\-sendalways\fR ++Whenever the mouse enters the VNC viewer main ++window, send the selection to the VNC server even if ++it has not changed. This is like the Xt resource ++translation SelectionToVNC(always) ++.TP ++\fB\-recvtext\fR ++str When cut text is received from the VNC server, ++ssvncviewer will set both the X PRIMARY and the ++X CLIPBOARD local selections. To control which ++is set, specify 'str' as 'primary', 'clipboard', ++or 'both' (the default.) ++.TP +\fB\-graball\fR +Grab the entire X server when in fullscreen mode, +needed by some old window managers like fvwm2. @@ -13720,6 +16321,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +data sent so as to work with the UltraVNC Server. For some +reason, each RFB msg type must be sent twice under DSM. +.TP ++\fB\-mslogon\fR \fIuser\fR ++Use Windows MS Logon to an UltraVNC server. Supply the ++username or "1" to be prompted. The default is to ++autodetect the UltraVNC MS Logon server and prompt for ++the username and password. ++ ++IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman ++exchange is very weak and can be brute forced to recover ++your username and password in a few hours or seconds of CPU ++time. To be safe, be sure to use an additional encrypted ++tunnel (e.g. SSL or SSH) for the entire VNC session. ++.TP +\fB\-chatonly\fR +Try to be a client that only does UltraVNC text chat. This +mode is used by x11vnc to present a chat window on the physical @@ -13736,6 +16349,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +keybindings and Popup menu) Then point to the file via +XENVIRONMENT or XAPPLRESDIR. +.TP ++\fB\-pipeline\fR ++Like TurboVNC, request the next framebuffer update as soon ++as possible instead of waiting until the end of the current ++framebuffer update coming in. Helps 'pipeline' the updates. ++This is currently the default, use \fB-nopipeline\fR to disable. ++.TP +\fB\-escape \fR\fIstr\fR +This sets the 'Escape Keys' modifier sequence and enables +escape keys mode. When the modifier keys escape sequence @@ -13811,8 +16430,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) -+ Full Color ~ as many colors as local screen allows. -+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes. ++ Pipeline Updates ~ -pipeline ++ ++ Full Color as many colors as local screen allows. ++ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. + 16 bit color (BGR565) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. @@ -13827,16 +16448,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn + + UltraVNC Extensions: + -+ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. -+ Text Chat Ultravnc ext. Do Text Chat. -+ File Transfer Ultravnc ext. File xfer via Java helper. -+ Single Window Ultravnc ext. Grab a single window. -+ (click on the window you want). -+ Disable Remote Input Ultravnc ext. Try to prevent input and -+ viewing of monitor at physical display. ++ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. ++ Text Chat Ultravnc ext. Do Text Chat. ++ File Transfer Ultravnc ext. File xfer via Java helper. ++ Single Window Ultravnc ext. Grab and view a single window. ++ (select then click on the window you want). ++ Disable Remote Input Ultravnc ext. Try to prevent input and ++ viewing of monitor at physical display. ++ ++ Note: the Ultravnc extensions only apply to servers that support ++ them. x11vnc/libvncserver supports some of them. + -+ Note: the Ultravnc extensions only apply to servers that -+ support them. x11vnc/libvncserver supports some of them. ++ Send Clipboard not Primary ~ -sendclipboard ++ Send Selection Every time ~ -sendalways + +.SH ENCODINGS +The server supplies information in whatever format is desired by the @@ -14063,7 +16687,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +Karl Runge diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c --- vnc_unixsrc.orig/vncviewer/vncviewer.c 2004-01-13 09:22:05.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer.c 2008-12-30 19:22:19.000000000 -0500 ++++ vnc_unixsrc/vncviewer/vncviewer.c 2009-05-31 16:25:56.000000000 -0400 @@ -22,6 +22,7 @@ */ @@ -14072,7 +16696,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi char *programName; XtAppContext appContext; -@@ -29,11 +30,221 @@ +@@ -29,11 +30,234 @@ Widget toplevel; @@ -14152,10 +16776,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + if (!strcmp(str, ".")) { + char *p; + fprintf(stderr, "\nUnix Username: "); -+ if (fgets(username, N, stdin) == NULL) { -+ exit(1); ++ if (!isatty(0)) { ++ char *u = DoUserDialog(); ++ if (strlen(u) >= 100) { ++ exit(1); ++ } ++ sprintf(username, u); ++ p = DoPasswordDialog(); ++ } else { ++ if (fgets(username, N, stdin) == NULL) { ++ exit(1); ++ } ++ p = getpass("Unix Password: "); + } -+ p = getpass("Unix Password: "); + if (! p) { + exit(1); + } @@ -14164,7 +16797,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + + } else if (!strcmp(str, "-")) { + char *p, *q; -+ p = getpass("unixuser@unixpasswd: "); ++ if (!isatty(0)) { ++ p = DoPasswordDialog(); ++ } else { ++ p = getpass("unixuser@unixpasswd: "); ++ } + if (! p) { + exit(1); + } @@ -14296,7 +16933,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi /* The -listen option is used to make us a daemon process which listens for incoming connections from servers, rather than actively connecting to a -@@ -45,89 +256,1415 @@ +@@ -45,89 +269,1607 @@ listenForIncomingConnections() returns, setting the listenSpecified flag. */ @@ -14488,6 +17125,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi - CreatePopup(); + CreatePopup(); + CreateScaleN(); ++ CreateTurboVNC(); + CreateQuality(); + CreateCompress(); + CreateChat(); @@ -14692,11 +17330,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + appData.escapeActive = True; + } +} -+ + +- Cleanup(); +/* + * ToggleNColors + */ -+ + +- return 0; +static Widget w256 = NULL; +static Widget w64 = NULL; +static Widget w8 = NULL; @@ -14980,6 +17620,44 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + } +} + ++void ++TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.pipelineUpdates) { ++ appData.pipelineUpdates= False; ++ fprintf(stderr, "pipeline-update: off\n"); ++ } else { ++ appData.pipelineUpdates = True; ++ fprintf(stderr, "pipeline-update: on\n"); ++ } ++ /* XXX request one to be sure? */ ++} ++ ++void ++ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.sendClipboard) { ++ appData.sendClipboard= False; ++ fprintf(stderr, "Send CLIPBOARD Selection: off (send PRIMARY instead)\n"); ++ } else { ++ appData.sendClipboard = True; ++ fprintf(stderr, "Send CLIPBOARD Selection: on (do not send PRIMARY)\n"); ++ } ++} ++ ++void ++ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.sendAlways) { ++ appData.sendAlways= False; ++ fprintf(stderr, "Send Selection Always: off\n"); ++ } else { ++ appData.sendAlways = True; ++ fprintf(stderr, "Send Selection Always: on\n"); ++ } ++} ++ ++ +Bool _sw1_ = False; /* XXX this is a weird bug... */ +Bool _sw2_ = False; +Bool _sw3_ = False; @@ -15218,10 +17896,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + if (s[0] != '\0') { + int w = si.framebufferWidth; + int h = si.framebufferHeight; ++ double fx, fy; + int fs = 0; + if (appData.scale != NULL && !strcmp(s, appData.scale)) { + return; + } ++ + if (!strcasecmp(s, "none")) { + appData.scale = NULL; + } else if (!strcmp(s, "1.0")) { @@ -15231,6 +17911,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + } else { + appData.scale = strdup(s); + } ++ if (appData.scale != NULL) { ++ get_scale_values(&fx, &fy); ++ if (fx <= 0.0 || fy <= 0.0) { ++ appData.scale = NULL; ++ return; ++ } ++ } ++ + if (appData.fullScreen) { + fs = 1; + FullScreenOff(); @@ -15329,6 +18017,119 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + } +} + ++void UpdateQual(void) { ++ SetFormatAndEncodings(); ++ UpdateSubsampButtons(); ++ UpdateQualSlider(); ++} ++ ++extern double latency; ++ ++static void LosslessRefresh(void) { ++ String encodings = appData.encodingsString; ++ int compressLevel = appData.compressLevel; ++ int qual = appData.qualityLevel; ++ Bool enableJPEG = appData.enableJPEG; ++ appData.qualityLevel = -1; ++ appData.enableJPEG = False; ++ appData.encodingsString = "tight copyrect"; ++ appData.compressLevel = 1; ++ SetFormatAndEncodings(); ++ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); ++ if (latency > 0.0) { ++ if (0) usleep((int) latency * 1000); ++ } ++ appData.qualityLevel = qual; ++ appData.enableJPEG = enableJPEG; ++ appData.encodingsString = encodings; ++ appData.compressLevel = compressLevel; ++ SetFormatAndEncodings(); ++} ++ ++static void QualHigh(void) { ++ appData.encodingsString = "tight copyrect"; ++ if(appData.useBGR233 || appDataNew.useBGR565) { ++ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); ++ } else { ++ appData.enableJPEG = True; ++ } ++ appData.subsampLevel = TVNC_1X; ++ appData.qualityLevel = 95; ++ UpdateQual(); ++} ++ ++static void QualMed(void) { ++ appData.encodingsString = "tight copyrect"; ++ if(appData.useBGR233 || appDataNew.useBGR565) { ++ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); ++ } else { ++ appData.enableJPEG = True; ++ } ++ appData.subsampLevel = TVNC_2X; ++ appData.qualityLevel = 80; ++ UpdateQual(); ++} ++ ++static void QualLow(void) { ++ appData.encodingsString = "tight copyrect"; ++ if(appData.useBGR233 || appDataNew.useBGR565) { ++ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); ++ } else { ++ appData.enableJPEG = True; ++ } ++ appData.subsampLevel = TVNC_4X; ++ appData.qualityLevel = 30; ++ UpdateQual(); ++} ++ ++static void QualLossless(void) { ++ appData.encodingsString = "tight copyrect"; ++ appData.enableJPEG = False; ++ appData.compressLevel = 0; ++ UpdateQual(); ++} ++ ++static void QualLosslessWAN(void) { ++ appData.encodingsString = "tight copyrect"; ++ appData.enableJPEG = False; ++ appData.compressLevel = 1; ++ UpdateQual(); ++} ++ ++void ++SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (*num_params != 0) { ++ int n = atoi(params[0]); ++ if (0) fprintf(stderr, "SetTurboVNC: %d\n", n); ++ if (n == 1) { ++ QualHigh(); ++ } else if (n == 2) { ++ QualMed(); ++ } else if (n == 3) { ++ QualLow(); ++ } else if (n == 4) { ++ QualLossless(); ++ } else if (n == 5) { ++ QualLosslessWAN(); ++ } else if (n == 6) { ++ appData.subsampLevel = TVNC_1X; ++ UpdateQual(); ++ } else if (n == 7) { ++ appData.subsampLevel = TVNC_2X; ++ UpdateQual(); ++ } else if (n == 8) { ++ appData.subsampLevel = TVNC_4X; ++ UpdateQual(); ++ } else if (n == 9) { ++ appData.subsampLevel = TVNC_GRAY; ++ UpdateQual(); ++ } else if (n == 10) { ++ LosslessRefresh(); ++ } ++ } ++} ++ +void +SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ @@ -15716,8 +18517,37 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + XtVaSetValues(w, XtNstate, False, NULL); + } +} - -- Cleanup(); ++ ++void ++SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (!appData.pipelineUpdates) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ } ++} ++ ++void ++SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (!appData.sendClipboard) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ } ++} ++ ++void ++SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (!appData.sendAlways) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ } ++} ++ +void +SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ @@ -15727,8 +18557,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + XtVaSetValues(w, XtNstate, False, NULL); + } +} - -- return 0; ++ +void +SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ @@ -15750,7 +18579,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi } diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h --- vnc_unixsrc.orig/vncviewer/vncviewer.h 2004-03-11 13:14:40.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer.h 2008-12-30 14:03:39.000000000 -0500 ++++ vnc_unixsrc/vncviewer/vncviewer.h 2009-05-31 16:26:35.000000000 -0400 @@ -28,6 +28,7 @@ #include #include @@ -15768,9 +18597,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi #define FLASH_PORT_OFFSET 5400 #define LISTEN_PORT_OFFSET 5500 -@@ -65,59 +66,95 @@ +@@ -64,60 +65,123 @@ + #define DEFAULT_VIA_CMD \ (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") ++#define TVNC_SAMPOPT 4 ++enum {TVNC_1X=0, TVNC_4X, TVNC_2X, TVNC_GRAY}; -/* argsresources.c */ - @@ -15791,12 +18623,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi - int requestedDepth; - - Bool useShm; -- ++static const char *subsampLevel2str[TVNC_SAMPOPT] = { ++ "1X", "4X", "2X", "Gray" ++}; ++#ifdef TURBOVNC ++#define rfbTightNoZlib 0x0A ++#define rfbTurboVncVendor "TRBO" ++#define rfbJpegQualityLevel1 0xFFFFFE01 ++#define rfbJpegQualityLevel100 0xFFFFFE64 ++#define rfbJpegSubsamp1X 0xFFFFFD00 ++#define rfbJpegSubsamp4X 0xFFFFFD01 ++#define rfbJpegSubsamp2X 0xFFFFFD02 ++#define rfbJpegSubsampGray 0xFFFFFD03 ++#endif + - int wmDecorationWidth; - int wmDecorationHeight; -- ++/* for debugging width, height, etc */ ++//#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues + - char *userLogin; -- + - char *passwordFile; - Bool passwordDialog; - @@ -15804,11 +18651,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi - int copyRectDelay; - - Bool debug; -+/* for debugging width, height, etc */ -+//#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues - +- - int popupButtonCount; - +- - int bumpScrollTime; - int bumpScrollPixels; +/* argsresources.c */ @@ -15850,6 +18695,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi + + char *userLogin; + char *unixPW; ++ char *msLogon; + char *repeaterUltra; + Bool ultraDSM; + char *rfbVersion; @@ -15891,6 +18737,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi + char *scale; + char *escapeKeys; + Bool escapeActive; ++ Bool pipelineUpdates; ++ ++ Bool sendClipboard; ++ Bool sendAlways; ++ char *recvText; ++ ++ /* only for turbovnc mode */ ++ String subsampString; ++ int subsampLevel; ++ Bool doubleBuffer; } AppData; @@ -15905,7 +18761,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern int listenPort, flashPort; extern XrmOptionDescRec cmdLineOptions[]; -@@ -130,10 +167,11 @@ +@@ -130,10 +194,11 @@ /* colour.c */ extern unsigned long BGR233ToPixel[]; @@ -15918,7 +18774,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern void SetVisualAndCmap(); -@@ -157,13 +195,52 @@ +@@ -157,13 +222,52 @@ extern void DesktopInitBeforeRealization(); extern void DesktopInitAfterRealization(); @@ -15971,7 +18827,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern void ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params); extern char *DoServerDialog(); -@@ -181,6 +258,13 @@ +@@ -171,6 +275,10 @@ + Cardinal *num_params); + extern char *DoPasswordDialog(); + ++extern void UserDialogDone(Widget w, XEvent *event, String *params, ++ Cardinal *num_params); ++extern char *DoUserDialog(); ++ + /* fullscreen.c */ + + extern void ToggleFullScreen(Widget w, XEvent *event, String *params, +@@ -181,6 +289,13 @@ extern void FullScreenOn(); extern void FullScreenOff(); @@ -15985,7 +18852,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* listen.c */ extern void listenForIncomingConnections(); -@@ -196,6 +280,8 @@ +@@ -196,6 +311,8 @@ Cardinal *num_params); extern void Quit(Widget w, XEvent *event, String *params, Cardinal *num_params); @@ -15994,7 +18861,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern void Cleanup(); /* popup.c */ -@@ -207,6 +293,20 @@ +@@ -207,6 +324,27 @@ Cardinal *num_params); extern void CreatePopup(); @@ -16002,6 +18869,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi + Cardinal *num_params); +extern void CreateScaleN(); + ++extern void HideTurboVNC(Widget w, XEvent *event, String *params, ++ Cardinal *num_params); ++extern void CreateTurboVNC(); ++extern void UpdateSubsampButtons(); ++extern void UpdateQualSlider(); ++extern void UpdateQual(); ++ +extern void HideQuality(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern void CreateQuality(); @@ -16015,7 +18889,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* rfbproto.c */ extern int rfbsock; -@@ -229,8 +329,19 @@ +@@ -229,8 +367,19 @@ extern Bool SendClientCutText(char *str, int len); extern Bool HandleRFBServerMessage(); @@ -16035,7 +18909,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* selection.c */ extern void InitialiseSelection(); -@@ -241,8 +352,9 @@ +@@ -241,8 +390,9 @@ /* shm.c */ @@ -16046,7 +18920,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* sockets.c */ -@@ -253,8 +365,11 @@ +@@ -253,8 +403,11 @@ extern int FindFreeTcpPort(void); extern int ListenAtTcpPort(int port); extern int ConnectToTcpAddr(unsigned int host, int port); @@ -16058,7 +18932,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern int StringToIPAddr(const char *str, unsigned int *addr); extern Bool SameMachine(int sock); -@@ -271,3 +386,72 @@ +@@ -271,3 +424,80 @@ extern XtAppContext appContext; extern Display* dpy; extern Widget toplevel; @@ -16083,6 +18957,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleEscapeActive(Widget w, XEvent *ev, String *params, Cardinal *num_params); @@ -16094,9 +18971,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void ShowTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params); @@ -16125,6 +19004,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetTermTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); @@ -16133,19 +19015,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void SetEscapeKeysState(Widget w, XEvent *ev, String *params, Cardinal *num_params); diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man --- vnc_unixsrc.orig/vncviewer/vncviewer.man 2004-03-11 13:14:40.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer.man 2008-12-30 19:24:50.000000000 -0500 ++++ vnc_unixsrc/vncviewer/vncviewer.man 2009-05-31 18:53:07.000000000 -0400 @@ -5,38 +5,55 @@ .\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de .\" Copyright (C) 2000,2001 Red Hat, Inc. .\" Copyright (C) 2001-2003 Constantin Kaplinsky -+.\" Copyright (C) 2006-2008 Karl J. Runge ++.\" Copyright (C) 2006-2009 Karl J. Runge .\" .\" You may distribute under the terms of the GNU General Public .\" License as specified in the file LICENCE.TXT that comes with the .\" TightVNC distribution. .\" -.TH vncviewer 1 "January 2003" "" "TightVNC" -+.TH ssvncviewer 1 "December 2008" "" "SSVNC" ++.TH ssvncviewer 1 "June 2009" "" "SSVNC" .SH NAME -vncviewer \- an X viewer client for VNC +ssvncviewer \- an X viewer client for VNC @@ -16198,7 +19080,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc You can use F8 to display a pop\-up utility menu. Press F8 twice to pass single F8 to the remote side. .SH OPTIONS -@@ -168,6 +185,335 @@ +@@ -168,6 +185,376 @@ \fB\-autopass\fR Read a plain-text password from stdin. This option affects only the standard VNC authentication. @@ -16317,6 +19199,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc +Prefer raw encoding for localhost, default is +no, i.e. assumes you have a SSH tunnel instead. +.TP ++\fB\-sendclipboard\fR ++Send the X CLIPBOARD selection (i.e. Ctrl+C, ++Ctrl+V) instead of the X PRIMARY selection (mouse ++select and middle button paste.) ++.TP ++\fB\-sendalways\fR ++Whenever the mouse enters the VNC viewer main ++window, send the selection to the VNC server even if ++it has not changed. This is like the Xt resource ++translation SelectionToVNC(always) ++.TP ++\fB\-recvtext\fR ++str When cut text is received from the VNC server, ++ssvncviewer will set both the X PRIMARY and the ++X CLIPBOARD local selections. To control which ++is set, specify 'str' as 'primary', 'clipboard', ++or 'both' (the default.) ++.TP +\fB\-graball\fR +Grab the entire X server when in fullscreen mode, +needed by some old window managers like fvwm2. @@ -16413,6 +19313,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc +data sent so as to work with the UltraVNC Server. For some +reason, each RFB msg type must be sent twice under DSM. +.TP ++\fB\-mslogon\fR \fIuser\fR ++Use Windows MS Logon to an UltraVNC server. Supply the ++username or "1" to be prompted. The default is to ++autodetect the UltraVNC MS Logon server and prompt for ++the username and password. ++ ++IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman ++exchange is very weak and can be brute forced to recover ++your username and password in a few hours or seconds of CPU ++time. To be safe, be sure to use an additional encrypted ++tunnel (e.g. SSL or SSH) for the entire VNC session. ++.TP +\fB\-chatonly\fR +Try to be a client that only does UltraVNC text chat. This +mode is used by x11vnc to present a chat window on the physical @@ -16429,6 +19341,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc +keybindings and Popup menu) Then point to the file via +XENVIRONMENT or XAPPLRESDIR. +.TP ++\fB\-pipeline\fR ++Like TurboVNC, request the next framebuffer update as soon ++as possible instead of waiting until the end of the current ++framebuffer update coming in. Helps 'pipeline' the updates. ++This is currently the default, use \fB-nopipeline\fR to disable. ++.TP +\fB\-escape \fR\fIstr\fR +This sets the 'Escape Keys' modifier sequence and enables +escape keys mode. When the modifier keys escape sequence @@ -16504,8 +19422,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) -+ Full Color ~ as many colors as local screen allows. -+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes. ++ Pipeline Updates ~ -pipeline ++ ++ Full Color as many colors as local screen allows. ++ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. + 16 bit color (BGR565) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. @@ -16520,21 +19440,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc + + UltraVNC Extensions: + -+ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. -+ Text Chat Ultravnc ext. Do Text Chat. -+ File Transfer Ultravnc ext. File xfer via Java helper. -+ Single Window Ultravnc ext. Grab a single window. -+ (click on the window you want). -+ Disable Remote Input Ultravnc ext. Try to prevent input and -+ viewing of monitor at physical display. ++ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. ++ Text Chat Ultravnc ext. Do Text Chat. ++ File Transfer Ultravnc ext. File xfer via Java helper. ++ Single Window Ultravnc ext. Grab and view a single window. ++ (select then click on the window you want). ++ Disable Remote Input Ultravnc ext. Try to prevent input and ++ viewing of monitor at physical display. + -+ Note: the Ultravnc extensions only apply to servers that -+ support them. x11vnc/libvncserver supports some of them. ++ Note: the Ultravnc extensions only apply to servers that support ++ them. x11vnc/libvncserver supports some of them. ++ ++ Send Clipboard not Primary ~ -sendclipboard ++ Send Selection Every time ~ -sendalways + .SH ENCODINGS The server supplies information in whatever format is desired by the client, in order to make the client as easy as possible to implement. -@@ -238,6 +584,15 @@ +@@ -238,6 +625,15 @@ \-quality and \-nojpeg options above). Tight encoding is usually the best choice for low\-bandwidth network environments (e.g. slow modem connections). @@ -16550,7 +19473,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc .SH RESOURCES X resources that \fBvncviewer\fR knows about, aside from the normal Xt resources, are as follows: -@@ -364,8 +719,8 @@ +@@ -364,8 +760,8 @@ .B %R remote TCP port number. .SH SEE ALSO @@ -16561,7 +19484,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc .SH AUTHORS Original VNC was developed in AT&T Laboratories Cambridge. TightVNC additions was implemented by Constantin Kaplinsky. Many other people -@@ -380,3 +735,5 @@ +@@ -380,3 +776,5 @@ Tim Waugh , .br Constantin Kaplinsky @@ -18833,7 +21756,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zywrletemplate.c vnc_unixsrc/ +#undef ZYWRLE_YUVRGB +#undef ZYWRLE_LOAD_PIXEL +#undef ZYWRLE_SAVE_PIXEL -diff -Naur vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h +diff -Naur -X ./exclude vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h --- vnc_unixsrc.orig/include/rfbproto.h 2004-05-27 03:02:02.000000000 -0400 +++ vnc_unixsrc/include/rfbproto.h 2008-12-07 09:35:32.000000000 -0500 @@ -205,7 +205,22 @@ @@ -19015,3 +21938,142 @@ diff -Naur vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h + rfbSetSWMsg sw; + rfbTextChatMsg tc; } rfbClientToServerMsg; +diff -Naur -X ./exclude vnc_unixsrc.orig/include/vncauth.h vnc_unixsrc/include/vncauth.h +--- vnc_unixsrc.orig/include/vncauth.h 2000-06-11 08:00:53.000000000 -0400 ++++ vnc_unixsrc/include/vncauth.h 2009-03-21 00:37:23.000000000 -0400 +@@ -23,8 +23,11 @@ + + #define MAXPWLEN 8 + #define CHALLENGESIZE 16 ++#define CHALLENGESIZE_MSLOGON 64 + + extern int vncEncryptAndStorePasswd(char *passwd, char *fname); + extern char *vncDecryptPasswdFromFile(char *fname); + extern void vncRandomBytes(unsigned char *bytes); + extern void vncEncryptBytes(unsigned char *bytes, char *passwd); ++ ++extern void vncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); +diff -Naur -X ./exclude vnc_unixsrc.orig/libvncauth/vncauth.c vnc_unixsrc/libvncauth/vncauth.c +--- vnc_unixsrc.orig/libvncauth/vncauth.c 2003-03-01 11:48:06.000000000 -0500 ++++ vnc_unixsrc/libvncauth/vncauth.c 2009-04-12 22:28:08.000000000 -0400 +@@ -30,6 +30,7 @@ + #include + #include + ++#include + + /* + * Make sure we call srandom() only once. +@@ -195,6 +196,44 @@ + return (i < 16) ? 1 : 2; + } + ++unsigned int urandom(void) { ++ unsigned int val = 0; ++ struct stat sb; ++ int fd = -1; ++ if (fd < 0 && stat("/dev/urandom", &sb) == 0) { ++ fd = open("/dev/urandom", O_RDONLY); ++ } ++ if (fd < 0 && stat("/dev/random", &sb) == 0) { ++ fd = open("/dev/random", O_RDONLY); ++ } ++ if (fd < 0 && stat("/proc/loadavg", &sb) == 0) { ++ fd = open("/proc/loadavg", O_RDONLY); ++ } ++ if (fd < 0 && stat("/bin/bash", &sb) == 0) { ++ fd = open("/bin/bash", O_RDONLY); ++ lseek(fd, (off_t) (unsigned int) getpid(), SEEK_SET); ++ } ++ if (fd >= 0) { ++ int i; ++ for (i=0; i < 3; i++) { ++ char buf[2]; ++ if (read(fd, buf, 1) > 0) { ++ unsigned char uc = (unsigned char) buf[0]; ++ if (i==0) { ++ val += uc; ++ } else if (i==1) { ++ val += uc * 256; ++ } else if (i==2) { ++ val += uc * 256 * 256; ++ } ++ } ++ } ++ close(fd); ++ } else { ++ val = (unsigned int) getpid(); ++ } ++ return val; ++} + + /* + * Generate CHALLENGESIZE random bytes for use in challenge-response +@@ -207,11 +246,13 @@ + int i; + unsigned int seed; + +- if (!s_srandom_called) { +- seed = (unsigned int)time(0) ^ (unsigned int)getpid(); +- srandom(seed); +- s_srandom_called = 1; +- } ++ if (!s_srandom_called) { ++ seed = (unsigned int)time(0) ^ (unsigned int)getpid(); ++ seed += urandom(); ++ ++ srandom(seed); ++ s_srandom_called = 1; ++ } + + for (i = 0; i < CHALLENGESIZE; i++) { + bytes[i] = (unsigned char)(random() & 255); +@@ -245,3 +286,48 @@ + des(bytes+i, bytes+i); + } + } ++ ++void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd) { ++ unsigned int i; ++ for (i=0; i < 32; i++) { ++ if (i < strlen(passwd)) { ++ encryptedPasswd[i] = passwd[i]; ++ } else { ++ encryptedPasswd[i] = '\0'; ++ } ++ } ++ deskey(s_fixedkey, EN0); ++ des(encryptedPasswd, encryptedPasswd); ++} ++ ++void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key) { ++ int i, j; ++ deskey(key, EN0); ++ for (i=0; i < 8; i++) { ++ where[i] ^= key[i]; ++ } ++ des(where, where); ++ for (i=8; i < length; i += 8) { ++ for (j=0; j < 8; j++) { ++ where[i+j] ^= where[i+j-8]; ++ } ++ des(where+i, where+i); ++ } ++} ++ ++void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key) { ++ int i, j; ++ deskey(key, DE1); ++ for (i = length - 8; i > 0; i -= 8) { ++ des(where + i, where + i); ++ for (j=0; j < 8; j++) { ++ where[i+j] ^= where[i+j-8]; ++ } ++ } ++ /* i=0 */ ++ des(where, where); ++ for (i=0; i < 8; i++) { ++ where[i] ^= key[i]; ++ } ++} ++