From faadd484489efddd182d6d0df43d8ecfdbff29ff Mon Sep 17 00:00:00 2001 From: Christian Beier Date: Wed, 9 Nov 2011 20:00:16 +0100 Subject: Rename 'classes' dir to 'webclients'. --- classes/Makefile.am | 5 - classes/VncViewer.jar | Bin 35462 -> 0 bytes classes/index.vnc | 37 - classes/javaviewer.pseudo_proxy.patch | 141 - classes/novnc/LICENSE.txt | 33 - classes/novnc/README.md | 93 - classes/novnc/favicon.ico | 1 - classes/novnc/images/clipboard.png | Bin 501 -> 0 bytes classes/novnc/images/connect.png | Bin 404 -> 0 bytes classes/novnc/images/ctrlaltdel.png | Bin 317 -> 0 bytes classes/novnc/images/disconnect.png | Bin 1378 -> 0 bytes classes/novnc/images/drag.png | Bin 963 -> 0 bytes classes/novnc/images/favicon.ico | Bin 1150 -> 0 bytes classes/novnc/images/favicon.png | Bin 453 -> 0 bytes classes/novnc/images/keyboard.png | Bin 1283 -> 0 bytes classes/novnc/images/mouse_left.png | Bin 511 -> 0 bytes classes/novnc/images/mouse_middle.png | Bin 517 -> 0 bytes classes/novnc/images/mouse_none.png | Bin 497 -> 0 bytes classes/novnc/images/mouse_right.png | Bin 513 -> 0 bytes classes/novnc/images/screen_320x460.png | Bin 12778 -> 0 bytes classes/novnc/images/screen_57x57.png | Bin 1807 -> 0 bytes classes/novnc/images/screen_700x700.png | Bin 17930 -> 0 bytes classes/novnc/images/settings.png | Bin 2495 -> 0 bytes classes/novnc/include/Orbitron700.ttf | Bin 38580 -> 0 bytes classes/novnc/include/Orbitron700.woff | Bin 17472 -> 0 bytes classes/novnc/include/base.css | 380 -- classes/novnc/include/base64.js | 147 - classes/novnc/include/black.css | 45 - classes/novnc/include/blue.css | 27 - classes/novnc/include/des.js | 273 - classes/novnc/include/display.js | 671 --- classes/novnc/include/input.js | 1884 ------- classes/novnc/include/logo.js | 1 - classes/novnc/include/playback.js | 90 - classes/novnc/include/rfb.js | 1613 ------ classes/novnc/include/ui.js | 629 --- classes/novnc/include/util.js | 276 - classes/novnc/include/vnc.js | 42 - classes/novnc/include/web-socket-js/README.txt | 109 - .../novnc/include/web-socket-js/WebSocketMain.swf | Bin 175746 -> 0 bytes classes/novnc/include/web-socket-js/swfobject.js | 4 - classes/novnc/include/web-socket-js/web_socket.js | 341 -- classes/novnc/include/websock.js | 347 -- classes/novnc/include/webutil.js | 148 - classes/novnc/vnc.html | 180 - classes/novnc/vnc_auto.html | 116 - classes/ssl/Makefile.am | 2 - classes/ssl/README | 338 -- classes/ssl/SignedUltraViewerSSL.jar | Bin 113117 -> 0 bytes classes/ssl/SignedVncViewer.jar | Bin 89208 -> 0 bytes classes/ssl/UltraViewerSSL.jar | Bin 110040 -> 0 bytes classes/ssl/VncViewer.jar | Bin 86228 -> 0 bytes classes/ssl/index.vnc | 26 - classes/ssl/onetimekey | 65 - classes/ssl/proxy.vnc | 73 - classes/ssl/ss_vncviewer | 3676 ------------- ...-vncviewer-cursor-colors+no-tab-traversal.patch | 111 - .../tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 2600 --------- classes/ssl/ultra.vnc | 28 - classes/ssl/ultraproxy.vnc | 28 - classes/ssl/ultrasigned.vnc | 28 - classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch | 5494 -------------------- 62 files changed, 20102 deletions(-) delete mode 100644 classes/Makefile.am delete mode 100644 classes/VncViewer.jar delete mode 100644 classes/index.vnc delete mode 100644 classes/javaviewer.pseudo_proxy.patch delete mode 100644 classes/novnc/LICENSE.txt delete mode 100644 classes/novnc/README.md delete mode 120000 classes/novnc/favicon.ico delete mode 100644 classes/novnc/images/clipboard.png delete mode 100644 classes/novnc/images/connect.png delete mode 100644 classes/novnc/images/ctrlaltdel.png delete mode 100644 classes/novnc/images/disconnect.png delete mode 100644 classes/novnc/images/drag.png delete mode 100644 classes/novnc/images/favicon.ico delete mode 100644 classes/novnc/images/favicon.png delete mode 100644 classes/novnc/images/keyboard.png delete mode 100644 classes/novnc/images/mouse_left.png delete mode 100644 classes/novnc/images/mouse_middle.png delete mode 100644 classes/novnc/images/mouse_none.png delete mode 100644 classes/novnc/images/mouse_right.png delete mode 100644 classes/novnc/images/screen_320x460.png delete mode 100644 classes/novnc/images/screen_57x57.png delete mode 100644 classes/novnc/images/screen_700x700.png delete mode 100644 classes/novnc/images/settings.png delete mode 100644 classes/novnc/include/Orbitron700.ttf delete mode 100644 classes/novnc/include/Orbitron700.woff delete mode 100644 classes/novnc/include/base.css delete mode 100644 classes/novnc/include/base64.js delete mode 100644 classes/novnc/include/black.css delete mode 100644 classes/novnc/include/blue.css delete mode 100644 classes/novnc/include/des.js delete mode 100644 classes/novnc/include/display.js delete mode 100644 classes/novnc/include/input.js delete mode 100644 classes/novnc/include/logo.js delete mode 100644 classes/novnc/include/playback.js delete mode 100644 classes/novnc/include/rfb.js delete mode 100644 classes/novnc/include/ui.js delete mode 100644 classes/novnc/include/util.js delete mode 100644 classes/novnc/include/vnc.js delete mode 100644 classes/novnc/include/web-socket-js/README.txt delete mode 100644 classes/novnc/include/web-socket-js/WebSocketMain.swf delete mode 100644 classes/novnc/include/web-socket-js/swfobject.js delete mode 100644 classes/novnc/include/web-socket-js/web_socket.js delete mode 100644 classes/novnc/include/websock.js delete mode 100644 classes/novnc/include/webutil.js delete mode 100644 classes/novnc/vnc.html delete mode 100644 classes/novnc/vnc_auto.html delete mode 100644 classes/ssl/Makefile.am delete mode 100644 classes/ssl/README delete mode 100644 classes/ssl/SignedUltraViewerSSL.jar delete mode 100644 classes/ssl/SignedVncViewer.jar delete mode 100644 classes/ssl/UltraViewerSSL.jar delete mode 100644 classes/ssl/VncViewer.jar delete mode 100644 classes/ssl/index.vnc delete mode 100755 classes/ssl/onetimekey delete mode 100644 classes/ssl/proxy.vnc delete mode 100755 classes/ssl/ss_vncviewer delete mode 100644 classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch delete mode 100644 classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch delete mode 100644 classes/ssl/ultra.vnc delete mode 100644 classes/ssl/ultraproxy.vnc delete mode 100644 classes/ssl/ultrasigned.vnc delete mode 100644 classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch (limited to 'classes') diff --git a/classes/Makefile.am b/classes/Makefile.am deleted file mode 100644 index c5497a8..0000000 --- a/classes/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -EXTRA_DIST=VncViewer.jar index.vnc javaviewer.pseudo_proxy.patch - -SUBDIRS = ssl -DIST_SUBDIRS = ssl - diff --git a/classes/VncViewer.jar b/classes/VncViewer.jar deleted file mode 100644 index 602fdb9..0000000 Binary files a/classes/VncViewer.jar and /dev/null differ diff --git a/classes/index.vnc b/classes/index.vnc deleted file mode 100644 index 34ad25d..0000000 --- a/classes/index.vnc +++ /dev/null @@ -1,37 +0,0 @@ - - - - - -$USER's $DESKTOP desktop ($DISPLAY) - - - - - - -
-
- -If the above Java applet does not work, you can also try the new JavaScript-only noVNC viewer. You will need a HTML5-capable browser though. - -
- -
- -
-
-
-LibVNCServer/LibVNCClient Homepage - diff --git a/classes/javaviewer.pseudo_proxy.patch b/classes/javaviewer.pseudo_proxy.patch deleted file mode 100644 index 4d2f36e..0000000 --- a/classes/javaviewer.pseudo_proxy.patch +++ /dev/null @@ -1,141 +0,0 @@ -diff -ru vnc_javasrc/OptionsFrame.java proxy_vnc_javasrc/OptionsFrame.java ---- vnc_javasrc/OptionsFrame.java Fri Jul 5 08:17:23 2002 -+++ proxy_vnc_javasrc/OptionsFrame.java Thu Aug 22 23:24:44 2002 -@@ -70,6 +70,12 @@ - - Label[] labels = new Label[names.length]; - Choice[] choices = new Choice[names.length]; -+ -+ Label proxyHostLabel; -+ TextField proxyHostEdit; -+ Label proxyPortLabel; -+ TextField proxyPortEdit; -+ - Button closeButton; - VncViewer viewer; - -@@ -93,6 +99,9 @@ - boolean shareDesktop; - boolean viewOnly; - -+ String proxyHost; -+ int proxyPort; -+ - // - // Constructor. Set up the labels and choices from the names and values - // arrays. -@@ -126,6 +135,32 @@ - } - } - -+ // TODO: find a way to set these to defaults from browser -+ proxyPort = viewer.readIntParameter("Use Proxy Port", -1); -+ if(proxyPort>-1) { -+ proxyHost = viewer.readParameter("Use Proxy Host", false); -+ if(proxyHost == null) -+ proxyHost = viewer.host; -+ -+ proxyHostLabel = new Label("Proxy Host"); -+ gbc.gridwidth = 1; -+ gridbag.setConstraints(proxyHostLabel,gbc); -+ add(proxyHostLabel); -+ proxyHostEdit = new TextField(); -+ gbc.gridwidth = GridBagConstraints.REMAINDER; -+ gridbag.setConstraints(proxyHostEdit,gbc); -+ add(proxyHostEdit); -+ -+ proxyPortLabel = new Label("Proxy Port"); -+ gbc.gridwidth = 1; -+ gridbag.setConstraints(proxyPortLabel,gbc); -+ add(proxyPortLabel); -+ proxyPortEdit = new TextField(); -+ gbc.gridwidth = GridBagConstraints.REMAINDER; -+ gridbag.setConstraints(proxyPortEdit,gbc); -+ add(proxyPortEdit); -+ } -+ - closeButton = new Button("Close"); - gbc.gridwidth = GridBagConstraints.REMAINDER; - gridbag.setConstraints(closeButton, gbc); -@@ -161,6 +196,11 @@ - } - } - -+ if(proxyPort>-1) { -+ proxyPortEdit.setText(Integer.toString(proxyPort)); -+ proxyHostEdit.setText(proxyHost); -+ } -+ - // Make the booleans and encodings array correspond to the state of the GUI - - setEncodings(); -@@ -361,8 +401,12 @@ - // - - public void actionPerformed(ActionEvent evt) { -- if (evt.getSource() == closeButton) -+ if (evt.getSource() == closeButton) { - setVisible(false); -+ proxyHost = proxyHostEdit.getText(); -+ proxyPort = Integer.parseInt(proxyPortEdit.getText()); -+ System.err.println("proxy is " + proxyHost + ":" + proxyPort); -+ } - } - - // -diff -ru vnc_javasrc/RfbProto.java proxy_vnc_javasrc/RfbProto.java ---- vnc_javasrc/RfbProto.java Sun Aug 4 18:39:35 2002 -+++ proxy_vnc_javasrc/RfbProto.java Thu Aug 22 22:53:53 2002 -@@ -119,12 +119,51 @@ - viewer = v; - host = h; - port = p; -- sock = new Socket(host, port); -+ if(viewer.options.proxyPort>-1) -+ sock = new Socket(viewer.options.proxyHost, viewer.options.proxyPort); -+ else -+ sock = new Socket(host, port); - is = new DataInputStream(new BufferedInputStream(sock.getInputStream(), - 16384)); - os = sock.getOutputStream(); -+ if(viewer.options.proxyPort>-1) -+ negotiateProxy(host,port); - } - -+ // this is inefficient as hell, but only used once per connection -+ String readLine() { -+ byte[] ba = new byte[1]; -+ String s = new String(""); -+ -+ ba[0]=0; -+ try { -+ while(ba[0] != 0xa) { -+ ba[0] = (byte)is.readUnsignedByte(); -+ s += new String(ba); -+ } -+ } catch(Exception e) { -+ e.printStackTrace(); -+ } -+ return s; -+ } -+ -+ void negotiateProxy(String realHost,int realPort) throws IOException { -+ String line; -+ -+ // this would be the correct way, but we want to trick strict proxies. -+ // line = "CONNECT " + realHost + ":" + realPort + " HTTP/1.1\r\nHost: " + realHost + ":" + realPort + "\r\n\r\n"; -+ line = "GET " + realHost + ":" + realPort + "/proxied.connection HTTP/1.0\r\nPragma: No-Cache\r\nProxy-Connection: Keep-Alive\r\n\r\n"; -+ os.write(line.getBytes()); -+ -+ line = readLine(); -+ System.err.println("Proxy said: " + line); -+ if(!(line.substring(0,7)+line.substring(8,12)).equalsIgnoreCase("HTTP/1. 200")) { -+ IOException e = new IOException(line); -+ throw e; -+ } -+ while(!line.equals("\r\n") && !line.equals("\n")) -+ line = readLine(); -+ } - - void close() { - try { diff --git a/classes/novnc/LICENSE.txt b/classes/novnc/LICENSE.txt deleted file mode 100644 index 755ace3..0000000 --- a/classes/novnc/LICENSE.txt +++ /dev/null @@ -1,33 +0,0 @@ -noVNC is Copyright (C) 2011 Joel Martin - -Some portions of noVNC are copyright to their individual authors. -Please refer to the individual source files and/or to the noVNC commit -history: https://github.com/kanaka/noVNC/commits/master - -noVNC is licensed under the LGPL (GNU Lesser General Public License) -version 3 with the following exceptions (all LGPL-3 compatible): - - include/input.js : LGPL-2 or any later version - - include/base64.js : Dual GPL-2 or LGPL-2.1 - - include/des.js : Various BSD style licenses - - include/web-socket-js/ : New BSD license. Source code at - http://github.com/gimite/web-socket-js - - include/Orbitron* : SIL Open Font License 1.1 - (Copyright 2009 Matt McInerney) - - images/ : Creative Commons Attribution-ShareAlike - http://creativecommons.org/licenses/by-sa/3.0/ - -The license texts are included at: - docs/LICENSE.LGPL-3 and - docs/LICENSE.GPL-3 - docs/LICENSE.OFL-1.1 - -Or alternatively the license texts may be found here: - http://www.gnu.org/licenses/lgpl.html and - http://www.gnu.org/licenses/gpl.html - http://scripts.sil.org/OFL diff --git a/classes/novnc/README.md b/classes/novnc/README.md deleted file mode 100644 index 4672969..0000000 --- a/classes/novnc/README.md +++ /dev/null @@ -1,93 +0,0 @@ -## noVNC: HTML5 VNC Client - - -### Description - -noVNC is a VNC client implemented using HTML5 technologies, -specifically Canvas and WebSockets (supports 'wss://' encryption). -noVNC is licensed under the -[LGPLv3](http://www.gnu.org/licenses/lgpl.html). - -Special thanks to [Sentry Data Systems](http://www.sentryds.com) for -sponsoring ongoing development of this project (and for employing me). - -There are many companies/projects that have integrated noVNC into -their products including: [Sentry Data Systems](http://www.sentryds.com), [Ganeti Web Manager](http://code.osuosl.org/projects/ganeti-webmgr), [Archipel](http://archipelproject.org), [openQRM](http://www.openqrm.com/), [OpenNode](http://www.opennodecloud.com/), [OpenStack](http://www.openstack.org), [Broadway (HTML5 GDK/GTK+ backend)](http://blogs.gnome.org/alexl/2011/03/15/gtk-html-backend-update/), [OpenNebula](http://opennebula.org/), [CloudSigma](http://www.cloudsigma.com/), [Zentyal (formerly eBox)](http://www.zentyal.org/), and [SlapOS](http://www.slapos.org). See [this wiki page](https://github.com/kanaka/noVNC/wiki/ProjectsCompanies-using-noVNC) for more info and links. - -Notable commits, announcements and news are posted to -@noVNC - - -### Screenshots - -Running in Chrome before and after connecting: - -  - -See more screenshots here. - - -### Browser Requirements - -* HTML5 Canvas (with createImageData): Chrome, Firefox 3.6+, iOS - Safari, Opera 11+, Internet Explorer 9+, etc. - -* HTML5 WebSockets: For browsers that do not have builtin - WebSockets support, the project includes - web-socket-js, - a WebSockets emulator using Adobe Flash. iOS 4.2+ has built-in - WebSocket support. - -* Fast Javascript Engine: noVNC avoids using new Javascript - functionality so it will run on older browsers, but decode and - rendering happen in Javascript, so a slow Javascript engine will - mean noVNC is painfully slow. - -* I maintain a more detailed browser compatibility list here. - - -### Server Requirements - -Unless you are using a VNC server with support for WebSockets -connections (only my [fork of libvncserver](http://github.com/kanaka/libvncserver) -currently), you need to use a WebSockets to TCP socket proxy. There is -a python proxy included ('websockify'). One advantage of using the -proxy is that it has builtin support for SSL/TLS encryption (i.e. -"wss://"). - -There a few reasons why a proxy is required: - - 1. WebSockets is not a pure socket protocol. There is an initial HTTP - like handshake to allow easy hand-off by web servers and allow - some origin policy exchange. Also, each WebSockets frame begins - with 0 ('\x00') and ends with 255 ('\xff'). - - 2. Javascript itself does not have the ability to handle pure byte - arrays. The python proxy encodes the data as base64 so that the - Javascript client can decode the data as an integer array. - - -### Quick Start - -* Use the launch script to start a mini-webserver and the WebSockets - proxy (websockify). The `--vnc` option is used to specify the location of - a running VNC server: - - `./utils/launch.sh --vnc localhost:5901` - -* Point your browser to the cut-and-paste URL that is output by the - launch script. Enter a password if the VNC server has one - configured. Hit the Connect button and enjoy! - - -### Other Pages - -* [Advanced Usage](https://github.com/kanaka/noVNC/wiki/Advanced-usage). Generating an SSL - certificate, starting a VNC server, advanced websockify usage, etc. - -* [Integrating noVNC](https://github.com/kanaka/noVNC/wiki/Integration) into existing projects. - -* [Troubleshooting noVNC](https://github.com/kanaka/noVNC/wiki/Troubleshooting) problems. - - diff --git a/classes/novnc/favicon.ico b/classes/novnc/favicon.ico deleted file mode 120000 index 45399c8..0000000 --- a/classes/novnc/favicon.ico +++ /dev/null @@ -1 +0,0 @@ -images/favicon.ico \ No newline at end of file diff --git a/classes/novnc/images/clipboard.png b/classes/novnc/images/clipboard.png deleted file mode 100644 index 24df33c..0000000 Binary files a/classes/novnc/images/clipboard.png and /dev/null differ diff --git a/classes/novnc/images/connect.png b/classes/novnc/images/connect.png deleted file mode 100644 index 79e71ad..0000000 Binary files a/classes/novnc/images/connect.png and /dev/null differ diff --git a/classes/novnc/images/ctrlaltdel.png b/classes/novnc/images/ctrlaltdel.png deleted file mode 100644 index 31922e5..0000000 Binary files a/classes/novnc/images/ctrlaltdel.png and /dev/null differ diff --git a/classes/novnc/images/disconnect.png b/classes/novnc/images/disconnect.png deleted file mode 100644 index 8832f5e..0000000 Binary files a/classes/novnc/images/disconnect.png and /dev/null differ diff --git a/classes/novnc/images/drag.png b/classes/novnc/images/drag.png deleted file mode 100644 index 433f896..0000000 Binary files a/classes/novnc/images/drag.png and /dev/null differ diff --git a/classes/novnc/images/favicon.ico b/classes/novnc/images/favicon.ico deleted file mode 100644 index c999634..0000000 Binary files a/classes/novnc/images/favicon.ico and /dev/null differ diff --git a/classes/novnc/images/favicon.png b/classes/novnc/images/favicon.png deleted file mode 100644 index e2bdb19..0000000 Binary files a/classes/novnc/images/favicon.png and /dev/null differ diff --git a/classes/novnc/images/keyboard.png b/classes/novnc/images/keyboard.png deleted file mode 100644 index f797952..0000000 Binary files a/classes/novnc/images/keyboard.png and /dev/null differ diff --git a/classes/novnc/images/mouse_left.png b/classes/novnc/images/mouse_left.png deleted file mode 100644 index 1de7a48..0000000 Binary files a/classes/novnc/images/mouse_left.png and /dev/null differ diff --git a/classes/novnc/images/mouse_middle.png b/classes/novnc/images/mouse_middle.png deleted file mode 100644 index 81fbd9b..0000000 Binary files a/classes/novnc/images/mouse_middle.png and /dev/null differ diff --git a/classes/novnc/images/mouse_none.png b/classes/novnc/images/mouse_none.png deleted file mode 100644 index 93dbf57..0000000 Binary files a/classes/novnc/images/mouse_none.png and /dev/null differ diff --git a/classes/novnc/images/mouse_right.png b/classes/novnc/images/mouse_right.png deleted file mode 100644 index 355b25d..0000000 Binary files a/classes/novnc/images/mouse_right.png and /dev/null differ diff --git a/classes/novnc/images/screen_320x460.png b/classes/novnc/images/screen_320x460.png deleted file mode 100644 index 172ec55..0000000 Binary files a/classes/novnc/images/screen_320x460.png and /dev/null differ diff --git a/classes/novnc/images/screen_57x57.png b/classes/novnc/images/screen_57x57.png deleted file mode 100644 index e2085f2..0000000 Binary files a/classes/novnc/images/screen_57x57.png and /dev/null differ diff --git a/classes/novnc/images/screen_700x700.png b/classes/novnc/images/screen_700x700.png deleted file mode 100644 index ae67768..0000000 Binary files a/classes/novnc/images/screen_700x700.png and /dev/null differ diff --git a/classes/novnc/images/settings.png b/classes/novnc/images/settings.png deleted file mode 100644 index a43f5e1..0000000 Binary files a/classes/novnc/images/settings.png and /dev/null differ diff --git a/classes/novnc/include/Orbitron700.ttf b/classes/novnc/include/Orbitron700.ttf deleted file mode 100644 index e28729d..0000000 Binary files a/classes/novnc/include/Orbitron700.ttf and /dev/null differ diff --git a/classes/novnc/include/Orbitron700.woff b/classes/novnc/include/Orbitron700.woff deleted file mode 100644 index 61db630..0000000 Binary files a/classes/novnc/include/Orbitron700.woff and /dev/null differ diff --git a/classes/novnc/include/base.css b/classes/novnc/include/base.css deleted file mode 100644 index 0a62a1b..0000000 --- a/classes/novnc/include/base.css +++ /dev/null @@ -1,380 +0,0 @@ -body { - margin:0; - padding:0; - font-family: Helvetica; - /*Background image with light grey curve.*/ - background-color:#494949; - background-repeat:no-repeat; - background-position:right bottom; - height:100%; -} - -html { - height:100%; -} - -#noVNC_controls ul { - list-style: none; - margin: 0px; - padding: 0px; -} -#noVNC_controls li { - padding-bottom:8px; -} - -#noVNC_host { - width:150px; -} -#noVNC_port { - width: 80px; -} -#noVNC_password { - width: 150px; -} -#noVNC_encrypt { -} -#noVNC_connectTimeout { - width: 30px; -} -#noVNC_path { - width: 100px; -} -#noVNC_connect_button { - width: 110px; - float:right; -} - - -#noVNC_view_drag_button { - display: none; -} -#sendCtrlAltDelButton { - display: none; -} -#noVNC_mobile_buttons { - display: none; -} - -.noVNC-buttons-left { - float: left; - padding-left:10px; - padding-top:4px; -} - -.noVNC-buttons-right { - float:right; - right: 0px; - padding-right:10px; - padding-top:4px; -} - -#noVNC_status_bar { - margin-top: 0px; - padding: 0px; -} - -#noVNC_status_bar div { - font-size: 12px; - padding-top: 4px; - width:100%; -} - -#noVNC_status { - height:20px; - text-align: center; -} -#noVNC_settings_menu { - margin: 3px; - text-align: left; -} -#noVNC_settings_menu ul { - list-style: none; - margin: 0px; - padding: 0px; -} - -#noVNC_apply { - float:right; -} - -.noVNC_status_normal { - background: #eee; -} -.noVNC_status_error { - background: #f44; -} -.noVNC_status_warn { - background: #ff4; -} - -/* Do not set width/height for VNC_screen or VNC_canvas or incorrect - * scaling will occur. Canvas resizes to remote VNC settings */ -#noVNC_screen_pad { - margin: 0px; - padding: 0px; - height: 44px; -} -#noVNC_screen { - text-align: center; - display: table; - width:100%; - height:100%; - background-color:#313131; - border-bottom-right-radius: 800px 600px; - /*border-top-left-radius: 800px 600px;*/ -} - -#noVNC_container, #noVNC_canvas { - margin: 0px; - padding: 0px; -} - -#noVNC_canvas { - left: 0px; -} - -#VNC_clipboard_clear_button { - float:right; -} -#VNC_clipboard_text { - font-size: 11px; -} - -#noVNC_clipboard_clear_button { - float:right; -} - -/*Bubble contents divs*/ -#noVNC_settings { - display:none; - margin-top:77px; - right:20px; - position:fixed; -} - -#noVNC_controls { - margin-top:77px; - right:12px; - position:fixed; -} -#noVNC_controls.top:after { - right:15px; -} - -#noVNC_clipboard { - display:none; - margin-top:77px; - right:30px; - position:fixed; -} -#noVNC_clipboard.top:after { - right:85px; -} - -#keyboardinput { - width:1px; - height:1px; - background-color:#fff; - color:#fff; - border:0; - position: relative; - left: -40px; - z-index: -1; -} - -.noVNC_status_warn { - background-color:yellow; -} - -/* - * Advanced Styling - */ - -/* Control bar */ -#noVNC-control-bar { - position:fixed; - background: #b2bdcd; /* Old browsers */ - background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ - background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ - - display:block; - height:44px; - left:0; - top:0; - width:100%; - z-index:200; -} - -.noVNC_status_button { - padding: 4px 4px; - vertical-align: middle; - border:1px solid #869dbc; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - background: #b2bdcd; /* Old browsers */ - background: -moz-linear-gradient(top, #b2bdcd 0%, #899cb3 49%, #7e93af 51%, #6e84a3 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#b2bdcd), color-stop(49%,#899cb3), color-stop(51%,#7e93af), color-stop(100%,#6e84a3)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#b2bdcd', endColorstr='#6e84a3',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #b2bdcd 0%,#899cb3 49%,#7e93af 51%,#6e84a3 100%); /* W3C */ - /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ -} - -.noVNC_status_button_selected { - padding: 4px 4px; - vertical-align: middle; - border:1px solid #4366a9; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - background: #779ced; /* Old browsers */ - background: -moz-linear-gradient(top, #779ced 0%, #3970e0 49%, #2160dd 51%, #2463df 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#779ced), color-stop(49%,#3970e0), color-stop(51%,#2160dd), color-stop(100%,#2463df)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#779ced', endColorstr='#2463df',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #779ced 0%,#3970e0 49%,#2160dd 51%,#2463df 100%); /* W3C */ - /*box-shadow:inset 0.4px 0.4px 0.4px #000000;*/ -} - - -/*Settings Bubble*/ -.triangle-right { - position:relative; - padding:15px; - margin:1em 0 3em; - color:#fff; - background:#fff; /* default background for browsers without gradient support */ - /* css3 */ - /*background:-webkit-gradient(linear, 0 0, 0 100%, from(#2e88c4), to(#075698)); - background:-moz-linear-gradient(#2e88c4, #075698); - background:-o-linear-gradient(#2e88c4, #075698); - background:linear-gradient(#2e88c4, #075698);*/ - -webkit-border-radius:10px; - -moz-border-radius:10px; - border-radius:10px; - color:#000; - border:2px solid #E0E0E0; -} - -.triangle-right.top:after { - border-color: transparent #E0E0E0; - border-width: 20px 20px 0 0; - bottom: auto; - left: auto; - right: 50px; - top: -20px; -} - -.triangle-right:after { - content:""; - position:absolute; - bottom:-20px; /* value = - border-top-width - border-bottom-width */ - left:50px; /* controls horizontal position */ - border-width:20px 0 0 20px; /* vary these values to change the angle of the vertex */ - border-style:solid; - border-color:#E0E0E0 transparent; - /* reduce the damage in FF3.0 */ - display:block; - width:0; -} - -.triangle-right.top:after { - top:-40px; /* value = - border-top-width - border-bottom-width */ - right:50px; /* controls horizontal position */ - bottom:auto; - left:auto; - border-width:40px 40px 0 0; /* vary these values to change the angle of the vertex */ - border-color:transparent #E0E0E0; -} - -/*Default noVNC logo.*/ -/* From: http://fonts.googleapis.com/css?family=Orbitron:700 */ -@font-face { - font-family: 'Orbitron'; - font-style: normal; - font-weight: 700; - src: local('?'), url('Orbitron700.woff') format('woff'), - url('Orbitron700.ttf') format('truetype'); -} - -#noVNC_logo { - margin-top: 170px; - margin-left: 10px; - color:yellow; - text-align:left; - font-family: 'Orbitron', 'OrbitronTTF', sans-serif; - line-height:90%; - text-shadow: - 5px 5px 0 #000, - -1px -1px 0 #000, - 1px -1px 0 #000, - -1px 1px 0 #000, - 1px 1px 0 #000; -} - - -#noVNC_logo span{ - color:green; -} - -/* ---------------------------------------- - * Media sizing - * ---------------------------------------- - */ - - -.noVNC_status_button { - font-size: 12px; -} - -#noVNC_clipboard_text { - width: 500px; -} - -#noVNC_logo { - font-size: 180px; -} - -@media screen and (min-width: 481px) and (max-width: 640px) { - .noVNC_status_button { - font-size: 10px; - } - #noVNC_clipboard_text { - width: 410px; - } - #noVNC_logo { - font-size: 150px; - } -} - -@media screen and (min-width: 321px) and (max-width: 480px) { - .noVNC_status_button { - font-size: 10px; - } - #noVNC_clipboard_text { - width: 250px; - } - #noVNC_logo { - font-size: 110px; - } -} - -@media screen and (max-width: 320px) { - .noVNC_status_button { - font-size: 9px; - } - #noVNC_clipboard_text { - width: 220px; - } - #noVNC_logo { - font-size: 90px; - } -} diff --git a/classes/novnc/include/base64.js b/classes/novnc/include/base64.js deleted file mode 100644 index c68b33a..0000000 --- a/classes/novnc/include/base64.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Modified from: - * http://lxr.mozilla.org/mozilla/source/extensions/xml-rpc/src/nsXmlRpcClient.js#956 - */ - -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla XML-RPC Client component. - * - * The Initial Developer of the Original Code is - * Digital Creations 2, Inc. - * Portions created by the Initial Developer are Copyright (C) 2000 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Martijn Pieters (original author) - * Samuel Sieb - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -/*jslint white: false, bitwise: false, plusplus: false */ -/*global console */ - -var Base64 = { - -/* Convert data (an array of integers) to a Base64 string. */ -toBase64Table : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/', -base64Pad : '=', - -encode: function (data) { - "use strict"; - var result = '', - chrTable = Base64.toBase64Table.split(''), - pad = Base64.base64Pad, - length = data.length, - i; - // Convert every three bytes to 4 ascii characters. - for (i = 0; i < (length - 2); i += 3) { - result += chrTable[data[i] >> 2]; - result += chrTable[((data[i] & 0x03) << 4) + (data[i+1] >> 4)]; - result += chrTable[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)]; - result += chrTable[data[i+2] & 0x3f]; - } - - // Convert the remaining 1 or 2 bytes, pad out to 4 characters. - if (length%3) { - i = length - (length%3); - result += chrTable[data[i] >> 2]; - if ((length%3) === 2) { - result += chrTable[((data[i] & 0x03) << 4) + (data[i+1] >> 4)]; - result += chrTable[(data[i+1] & 0x0f) << 2]; - result += pad; - } else { - result += chrTable[(data[i] & 0x03) << 4]; - result += pad + pad; - } - } - - return result; -}, - -/* Convert Base64 data to a string */ -toBinaryTable : [ - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, - -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, - 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, - 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, - -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, - 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 -], - -decode: function (data, offset) { - "use strict"; - offset = typeof(offset) !== 'undefined' ? offset : 0; - var binTable = Base64.toBinaryTable, - pad = Base64.base64Pad, - result, result_length, idx, i, c, padding, - leftbits = 0, // number of bits decoded, but yet to be appended - leftdata = 0, // bits decoded, but yet to be appended - data_length = data.indexOf('=') - offset; - - if (data_length < 0) { data_length = data.length - offset; } - - /* Every four characters is 3 resulting numbers */ - result_length = (data_length >> 2) * 3 + Math.floor((data_length%4)/1.5); - result = new Array(result_length); - - // Convert one by one. - for (idx = 0, i = offset; i < data.length; i++) { - c = binTable[data.charCodeAt(i) & 0x7f]; - padding = (data.charAt(i) === pad); - // Skip illegal characters and whitespace - if (c === -1) { - console.error("Illegal character '" + data.charCodeAt(i) + "'"); - continue; - } - - // Collect data into leftdata, update bitcount - leftdata = (leftdata << 6) | c; - leftbits += 6; - - // If we have 8 or more bits, append 8 bits to the result - if (leftbits >= 8) { - leftbits -= 8; - // Append if not padding. - if (!padding) { - result[idx++] = (leftdata >> leftbits) & 0xff; - } - leftdata &= (1 << leftbits) - 1; - } - } - - // If there are any bits left, the base64 string was corrupted - if (leftbits) { - throw {name: 'Base64-Error', - message: 'Corrupted base64 string'}; - } - - return result; -} - -}; /* End of Base64 namespace */ diff --git a/classes/novnc/include/black.css b/classes/novnc/include/black.css deleted file mode 100644 index 8f80f66..0000000 --- a/classes/novnc/include/black.css +++ /dev/null @@ -1,45 +0,0 @@ -#keyboardinput { - background-color:#000; -} - -#noVNC-control-bar { - background: #4c4c4c; /* Old browsers */ - background: -moz-linear-gradient(top, #4c4c4c 0%, #2c2c2c 50%, #000000 51%, #131313 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4c4c4c), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(100%,#131313)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* IE10+ */ - background: linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */ -} - -.triangle-right { - border:2px solid #fff; - background:#000; - color:#fff; -} - -.noVNC_status_button { - font-size: 12px; - vertical-align: middle; - border:1px solid #4c4c4c; - - background: #4c4c4c; /* Old browsers */ - background: -moz-linear-gradient(top, #4c4c4c 0%, #2c2c2c 50%, #000000 51%, #131313 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#4c4c4c), color-stop(50%,#2c2c2c), color-stop(51%,#000000), color-stop(100%,#131313)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4c4c4c', endColorstr='#131313',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #4c4c4c 0%,#2c2c2c 50%,#000000 51%,#131313 100%); /* W3C */ -} - -.noVNC_status_button_selected { - background: #9dd53a; /* Old browsers */ - background: -moz-linear-gradient(top, #9dd53a 0%, #a1d54f 50%, #80c217 51%, #7cbc0a 100%); /* FF3.6+ */ - background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#9dd53a), color-stop(50%,#a1d54f), color-stop(51%,#80c217), color-stop(100%,#7cbc0a)); /* Chrome,Safari4+ */ - background: -webkit-linear-gradient(top, #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* Chrome10+,Safari5.1+ */ - background: -o-linear-gradient(top, #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* Opera11.10+ */ - background: -ms-linear-gradient(top, #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* IE10+ */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#9dd53a', endColorstr='#7cbc0a',GradientType=0 ); /* IE6-9 */ - background: linear-gradient(top, #9dd53a 0%,#a1d54f 50%,#80c217 51%,#7cbc0a 100%); /* W3C */ -} diff --git a/classes/novnc/include/blue.css b/classes/novnc/include/blue.css deleted file mode 100644 index a8baf70..0000000 --- a/classes/novnc/include/blue.css +++ /dev/null @@ -1,27 +0,0 @@ - -#noVNC-control-bar { - background-color:#04073d; - background-image: -webkit-gradient( - linear, - left bottom, - left top, - color-stop(0.54, rgb(10,15,79)), - color-stop(0.5, rgb(4,7,61)) - ); - background-image: -moz-linear-gradient( - center bottom, - rgb(10,15,79) 54%, - rgb(4,7,61) 50% - ); -} - -.triangle-right { - border:2px solid #fff; - background:#04073d; - color:#fff; -} - -#keyboardinput { - background-color:#04073d; -} - diff --git a/classes/novnc/include/des.js b/classes/novnc/include/des.js deleted file mode 100644 index 1f95285..0000000 --- a/classes/novnc/include/des.js +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Ported from Flashlight VNC ActionScript implementation: - * http://www.wizhelp.com/flashlight-vnc/ - * - * Full attribution follows: - * - * ------------------------------------------------------------------------- - * - * This DES class has been extracted from package Acme.Crypto for use in VNC. - * The unnecessary odd parity code has been removed. - * - * These changes are: - * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. - * - * 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. - * - - * DesCipher - the DES encryption method - * - * The meat of this code is by Dave Zimmerman , and is: - * - * Copyright (c) 1996 Widget Workshop, Inc. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this software - * and its documentation for NON-COMMERCIAL or COMMERCIAL purposes and - * without fee is hereby granted, provided that this copyright notice is kept - * intact. - * - * WIDGET WORKSHOP MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY - * OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED - * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A - * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. WIDGET WORKSHOP SHALL NOT BE LIABLE - * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR - * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. - * - * THIS SOFTWARE IS NOT DESIGNED OR INTENDED FOR USE OR RESALE AS ON-LINE - * CONTROL EQUIPMENT IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE - * PERFORMANCE, SUCH AS IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT - * NAVIGATION OR COMMUNICATION SYSTEMS, AIR TRAFFIC CONTROL, DIRECT LIFE - * SUPPORT MACHINES, OR WEAPONS SYSTEMS, IN WHICH THE FAILURE OF THE - * SOFTWARE COULD LEAD DIRECTLY TO DEATH, PERSONAL INJURY, OR SEVERE - * PHYSICAL OR ENVIRONMENTAL DAMAGE ("HIGH RISK ACTIVITIES"). WIDGET WORKSHOP - * SPECIFICALLY DISCLAIMS ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR - * HIGH RISK ACTIVITIES. - * - * - * The rest is: - * - * Copyright (C) 1996 by Jef Poskanzer . All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Visit the ACME Labs Java page for up-to-date versions of this and other - * fine Java utilities: http://www.acme.com/java/ - */ - -"use strict"; -/*jslint white: false, bitwise: false, plusplus: false */ - -function DES(passwd) { - -// Tables, permutations, S-boxes, etc. -var PC2 = [13,16,10,23, 0, 4, 2,27,14, 5,20, 9,22,18,11, 3, - 25, 7,15, 6,26,19,12, 1,40,51,30,36,46,54,29,39, - 50,44,32,47,43,48,38,55,33,52,45,41,49,35,28,31 ], - totrot = [ 1, 2, 4, 6, 8,10,12,14,15,17,19,21,23,25,27,28], - z = 0x0, a,b,c,d,e,f, SP1,SP2,SP3,SP4,SP5,SP6,SP7,SP8, - keys = []; - -a=1<<16; b=1<<24; c=a|b; d=1<<2; e=1<<10; f=d|e; -SP1 = [c|e,z|z,a|z,c|f,c|d,a|f,z|d,a|z,z|e,c|e,c|f,z|e,b|f,c|d,b|z,z|d, - z|f,b|e,b|e,a|e,a|e,c|z,c|z,b|f,a|d,b|d,b|d,a|d,z|z,z|f,a|f,b|z, - a|z,c|f,z|d,c|z,c|e,b|z,b|z,z|e,c|d,a|z,a|e,b|d,z|e,z|d,b|f,a|f, - c|f,a|d,c|z,b|f,b|d,z|f,a|f,c|e,z|f,b|e,b|e,z|z,a|d,a|e,z|z,c|d]; -a=1<<20; b=1<<31; c=a|b; d=1<<5; e=1<<15; f=d|e; -SP2 = [c|f,b|e,z|e,a|f,a|z,z|d,c|d,b|f,b|d,c|f,c|e,b|z,b|e,a|z,z|d,c|d, - a|e,a|d,b|f,z|z,b|z,z|e,a|f,c|z,a|d,b|d,z|z,a|e,z|f,c|e,c|z,z|f, - z|z,a|f,c|d,a|z,b|f,c|z,c|e,z|e,c|z,b|e,z|d,c|f,a|f,z|d,z|e,b|z, - z|f,c|e,a|z,b|d,a|d,b|f,b|d,a|d,a|e,z|z,b|e,z|f,b|z,c|d,c|f,a|e]; -a=1<<17; b=1<<27; c=a|b; d=1<<3; e=1<<9; f=d|e; -SP3 = [z|f,c|e,z|z,c|d,b|e,z|z,a|f,b|e,a|d,b|d,b|d,a|z,c|f,a|d,c|z,z|f, - b|z,z|d,c|e,z|e,a|e,c|z,c|d,a|f,b|f,a|e,a|z,b|f,z|d,c|f,z|e,b|z, - c|e,b|z,a|d,z|f,a|z,c|e,b|e,z|z,z|e,a|d,c|f,b|e,b|d,z|e,z|z,c|d, - b|f,a|z,b|z,c|f,z|d,a|f,a|e,b|d,c|z,b|f,z|f,c|z,a|f,z|d,c|d,a|e]; -a=1<<13; b=1<<23; c=a|b; d=1<<0; e=1<<7; f=d|e; -SP4 = [c|d,a|f,a|f,z|e,c|e,b|f,b|d,a|d,z|z,c|z,c|z,c|f,z|f,z|z,b|e,b|d, - z|d,a|z,b|z,c|d,z|e,b|z,a|d,a|e,b|f,z|d,a|e,b|e,a|z,c|e,c|f,z|f, - b|e,b|d,c|z,c|f,z|f,z|z,z|z,c|z,a|e,b|e,b|f,z|d,c|d,a|f,a|f,z|e, - c|f,z|f,z|d,a|z,b|d,a|d,c|e,b|f,a|d,a|e,b|z,c|d,z|e,b|z,a|z,c|e]; -a=1<<25; b=1<<30; c=a|b; d=1<<8; e=1<<19; f=d|e; -SP5 = [z|d,a|f,a|e,c|d,z|e,z|d,b|z,a|e,b|f,z|e,a|d,b|f,c|d,c|e,z|f,b|z, - a|z,b|e,b|e,z|z,b|d,c|f,c|f,a|d,c|e,b|d,z|z,c|z,a|f,a|z,c|z,z|f, - z|e,c|d,z|d,a|z,b|z,a|e,c|d,b|f,a|d,b|z,c|e,a|f,b|f,z|d,a|z,c|e, - c|f,z|f,c|z,c|f,a|e,z|z,b|e,c|z,z|f,a|d,b|d,z|e,z|z,b|e,a|f,b|d]; -a=1<<22; b=1<<29; c=a|b; d=1<<4; e=1<<14; f=d|e; -SP6 = [b|d,c|z,z|e,c|f,c|z,z|d,c|f,a|z,b|e,a|f,a|z,b|d,a|d,b|e,b|z,z|f, - z|z,a|d,b|f,z|e,a|e,b|f,z|d,c|d,c|d,z|z,a|f,c|e,z|f,a|e,c|e,b|z, - b|e,z|d,c|d,a|e,c|f,a|z,z|f,b|d,a|z,b|e,b|z,z|f,b|d,c|f,a|e,c|z, - a|f,c|e,z|z,c|d,z|d,z|e,c|z,a|f,z|e,a|d,b|f,z|z,c|e,b|z,a|d,b|f]; -a=1<<21; b=1<<26; c=a|b; d=1<<1; e=1<<11; f=d|e; -SP7 = [a|z,c|d,b|f,z|z,z|e,b|f,a|f,c|e,c|f,a|z,z|z,b|d,z|d,b|z,c|d,z|f, - b|e,a|f,a|d,b|e,b|d,c|z,c|e,a|d,c|z,z|e,z|f,c|f,a|e,z|d,b|z,a|e, - b|z,a|e,a|z,b|f,b|f,c|d,c|d,z|d,a|d,b|z,b|e,a|z,c|e,z|f,a|f,c|e, - z|f,b|d,c|f,c|z,a|e,z|z,z|d,c|f,z|z,a|f,c|z,z|e,b|d,b|e,z|e,a|d]; -a=1<<18; b=1<<28; c=a|b; d=1<<6; e=1<<12; f=d|e; -SP8 = [b|f,z|e,a|z,c|f,b|z,b|f,z|d,b|z,a|d,c|z,c|f,a|e,c|e,a|f,z|e,z|d, - c|z,b|d,b|e,z|f,a|e,a|d,c|d,c|e,z|f,z|z,z|z,c|d,b|d,b|e,a|f,a|z, - a|f,a|z,c|e,z|e,z|d,c|d,z|e,a|f,b|e,z|d,b|d,c|z,c|d,b|z,a|z,b|f, - z|z,c|f,a|d,b|d,c|z,b|e,b|f,z|z,c|f,a|e,a|e,z|f,z|f,a|d,b|z,c|e]; - -// Set the key. -function setKeys(keyBlock) { - var i, j, l, m, n, o, pc1m = [], pcr = [], kn = [], - raw0, raw1, rawi, KnLi; - - for (j = 0, l = 56; j < 56; ++j, l-=8) { - l += l<-5 ? 65 : l<-3 ? 31 : l<-1 ? 63 : l===27 ? 35 : 0; // PC1 - m = l & 0x7; - pc1m[j] = ((keyBlock[l >>> 3] & (1<>> 10; - keys[KnLi] |= (raw1 & 0x00000fc0) >>> 6; - ++KnLi; - keys[KnLi] = (raw0 & 0x0003f000) << 12; - keys[KnLi] |= (raw0 & 0x0000003f) << 16; - keys[KnLi] |= (raw1 & 0x0003f000) >>> 4; - keys[KnLi] |= (raw1 & 0x0000003f); - ++KnLi; - } -} - -// Encrypt 8 bytes of text -function enc8(text) { - var i = 0, b = text.slice(), fval, keysi = 0, - l, r, x; // left, right, accumulator - - // Squash 8 bytes to 2 ints - l = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; - r = b[i++]<<24 | b[i++]<<16 | b[i++]<<8 | b[i++]; - - x = ((l >>> 4) ^ r) & 0x0f0f0f0f; - r ^= x; - l ^= (x << 4); - x = ((l >>> 16) ^ r) & 0x0000ffff; - r ^= x; - l ^= (x << 16); - x = ((r >>> 2) ^ l) & 0x33333333; - l ^= x; - r ^= (x << 2); - x = ((r >>> 8) ^ l) & 0x00ff00ff; - l ^= x; - r ^= (x << 8); - r = (r << 1) | ((r >>> 31) & 1); - x = (l ^ r) & 0xaaaaaaaa; - l ^= x; - r ^= x; - l = (l << 1) | ((l >>> 31) & 1); - - for (i = 0; i < 8; ++i) { - x = (r << 28) | (r >>> 4); - x ^= keys[keysi++]; - fval = SP7[x & 0x3f]; - fval |= SP5[(x >>> 8) & 0x3f]; - fval |= SP3[(x >>> 16) & 0x3f]; - fval |= SP1[(x >>> 24) & 0x3f]; - x = r ^ keys[keysi++]; - fval |= SP8[x & 0x3f]; - fval |= SP6[(x >>> 8) & 0x3f]; - fval |= SP4[(x >>> 16) & 0x3f]; - fval |= SP2[(x >>> 24) & 0x3f]; - l ^= fval; - x = (l << 28) | (l >>> 4); - x ^= keys[keysi++]; - fval = SP7[x & 0x3f]; - fval |= SP5[(x >>> 8) & 0x3f]; - fval |= SP3[(x >>> 16) & 0x3f]; - fval |= SP1[(x >>> 24) & 0x3f]; - x = l ^ keys[keysi++]; - fval |= SP8[x & 0x0000003f]; - fval |= SP6[(x >>> 8) & 0x3f]; - fval |= SP4[(x >>> 16) & 0x3f]; - fval |= SP2[(x >>> 24) & 0x3f]; - r ^= fval; - } - - r = (r << 31) | (r >>> 1); - x = (l ^ r) & 0xaaaaaaaa; - l ^= x; - r ^= x; - l = (l << 31) | (l >>> 1); - x = ((l >>> 8) ^ r) & 0x00ff00ff; - r ^= x; - l ^= (x << 8); - x = ((l >>> 2) ^ r) & 0x33333333; - r ^= x; - l ^= (x << 2); - x = ((r >>> 16) ^ l) & 0x0000ffff; - l ^= x; - r ^= (x << 16); - x = ((r >>> 4) ^ l) & 0x0f0f0f0f; - l ^= x; - r ^= (x << 4); - - // Spread ints to bytes - x = [r, l]; - for (i = 0; i < 8; i++) { - b[i] = (x[i>>>2] >>> (8*(3 - (i%4)))) % 256; - if (b[i] < 0) { b[i] += 256; } // unsigned - } - return b; -} - -// Encrypt 16 bytes of text using passwd as key -function encrypt(t) { - return enc8(t.slice(0,8)).concat(enc8(t.slice(8,16))); -} - -setKeys(passwd); // Setup keys -return {'encrypt': encrypt}; // Public interface - -} // function DES diff --git a/classes/novnc/include/display.js b/classes/novnc/include/display.js deleted file mode 100644 index 2cf262d..0000000 --- a/classes/novnc/include/display.js +++ /dev/null @@ -1,671 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-3 (see LICENSE.txt) - * - * See README.md for usage and integration instructions. - */ - -/*jslint browser: true, white: false, bitwise: false */ -/*global Util, Base64, changeCursor */ - -function Display(defaults) { -"use strict"; - -var that = {}, // Public API methods - conf = {}, // Configuration attributes - - // Private Display namespace variables - c_ctx = null, - c_forceCanvas = false, - - // Predefine function variables (jslint) - imageDataGet, rgbxImageData, cmapImageData, - setFillColor, rescale, - - // The full frame buffer (logical canvas) size - fb_width = 0, - fb_height = 0, - // The visible "physical canvas" viewport - viewport = {'x': 0, 'y': 0, 'w' : 0, 'h' : 0 }, - cleanRect = {'x1': 0, 'y1': 0, 'x2': -1, 'y2': -1}, - - c_prevStyle = "", - tile = null, - tile16x16 = null, - tile_x = 0, - tile_y = 0; - - -// Configuration attributes -Util.conf_defaults(conf, that, defaults, [ - ['target', 'wo', 'dom', null, 'Canvas element for rendering'], - ['context', 'ro', 'raw', null, 'Canvas 2D context for rendering (read-only)'], - ['logo', 'rw', 'raw', null, 'Logo to display when cleared: {"width": width, "height": height, "data": data}'], - ['true_color', 'rw', 'bool', true, 'Use true-color pixel data'], - ['colourMap', 'rw', 'arr', [], 'Colour map array (when not true-color)'], - ['scale', 'rw', 'float', 1.0, 'Display area scale factor 0.0 - 1.0'], - ['viewport', 'rw', 'bool', false, 'Use a viewport set with viewportChange()'], - ['width', 'rw', 'int', null, 'Display area width'], - ['height', 'rw', 'int', null, 'Display area height'], - - ['render_mode', 'ro', 'str', '', 'Canvas rendering mode (read-only)'], - - ['prefer_js', 'rw', 'str', null, 'Prefer Javascript over canvas methods'], - ['cursor_uri', 'rw', 'raw', null, 'Can we render cursor using data URI'] - ]); - -// Override some specific getters/setters -that.get_context = function () { return c_ctx; }; - -that.set_scale = function(scale) { rescale(scale); }; - -that.set_width = function (val) { that.resize(val, fb_height); }; -that.get_width = function() { return fb_width; }; - -that.set_height = function (val) { that.resize(fb_width, val); }; -that.get_height = function() { return fb_height; }; - - - -// -// Private functions -// - -// Create the public API interface -function constructor() { - Util.Debug(">> Display.constructor"); - - var c, func, i, curDat, curSave, - has_imageData = false, UE = Util.Engine; - - if (! conf.target) { throw("target must be set"); } - - if (typeof conf.target === 'string') { - throw("target must be a DOM element"); - } - - c = conf.target; - - if (! c.getContext) { throw("no getContext method"); } - - if (! c_ctx) { c_ctx = c.getContext('2d'); } - - Util.Debug("User Agent: " + navigator.userAgent); - if (UE.gecko) { Util.Debug("Browser: gecko " + UE.gecko); } - if (UE.webkit) { Util.Debug("Browser: webkit " + UE.webkit); } - if (UE.trident) { Util.Debug("Browser: trident " + UE.trident); } - if (UE.presto) { Util.Debug("Browser: presto " + UE.presto); } - - that.clear(); - - // Check canvas features - if ('createImageData' in c_ctx) { - conf.render_mode = "canvas rendering"; - } else { - throw("Canvas does not support createImageData"); - } - if (conf.prefer_js === null) { - Util.Info("Prefering javascript operations"); - conf.prefer_js = true; - } - - // Initialize cached tile imageData - tile16x16 = c_ctx.createImageData(16, 16); - - /* - * Determine browser support for setting the cursor via data URI - * scheme - */ - curDat = []; - for (i=0; i < 8 * 8 * 4; i += 1) { - curDat.push(255); - } - try { - curSave = c.style.cursor; - changeCursor(conf.target, curDat, curDat, 2, 2, 8, 8); - if (c.style.cursor) { - if (conf.cursor_uri === null) { - conf.cursor_uri = true; - } - Util.Info("Data URI scheme cursor supported"); - } else { - if (conf.cursor_uri === null) { - conf.cursor_uri = false; - } - Util.Warn("Data URI scheme cursor not supported"); - } - c.style.cursor = curSave; - } catch (exc2) { - Util.Error("Data URI scheme cursor test exception: " + exc2); - conf.cursor_uri = false; - } - - Util.Debug("<< Display.constructor"); - return that ; -} - -rescale = function(factor) { - var c, tp, x, y, - properties = ['transform', 'WebkitTransform', 'MozTransform', null]; - c = conf.target; - tp = properties.shift(); - while (tp) { - if (typeof c.style[tp] !== 'undefined') { - break; - } - tp = properties.shift(); - } - - if (tp === null) { - Util.Debug("No scaling support"); - return; - } - - - if (typeof(factor) === "undefined") { - factor = conf.scale; - } else if (factor > 1.0) { - factor = 1.0; - } else if (factor < 0.1) { - factor = 0.1; - } - - if (conf.scale === factor) { - //Util.Debug("Display already scaled to '" + factor + "'"); - return; - } - - conf.scale = factor; - x = c.width - c.width * factor; - y = c.height - c.height * factor; - c.style[tp] = "scale(" + conf.scale + ") translate(-" + x + "px, -" + y + "px)"; -}; - -setFillColor = function(color) { - var rgb, newStyle; - if (conf.true_color) { - rgb = color; - } else { - rgb = conf.colourMap[color[0]]; - } - newStyle = "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")"; - if (newStyle !== c_prevStyle) { - c_ctx.fillStyle = newStyle; - c_prevStyle = newStyle; - } -}; - - -// -// Public API interface functions -// - -// Shift and/or resize the visible viewport -that.viewportChange = function(deltaX, deltaY, width, height) { - var c = conf.target, v = viewport, cr = cleanRect, - saveImg = null, saveStyle, x1, y1, vx2, vy2, w, h; - - if (!conf.viewport) { - Util.Debug("Setting viewport to full display region"); - deltaX = -v.w; // Clamped later if out of bounds - deltaY = -v.h; // Clamped later if out of bounds - width = fb_width; - height = fb_height; - } - - if (typeof(deltaX) === "undefined") { deltaX = 0; } - if (typeof(deltaY) === "undefined") { deltaY = 0; } - if (typeof(width) === "undefined") { width = v.w; } - if (typeof(height) === "undefined") { height = v.h; } - - // Size change - - if (width > fb_width) { width = fb_width; } - if (height > fb_height) { height = fb_height; } - - if ((v.w !== width) || (v.h !== height)) { - // Change width - if ((width < v.w) && (cr.x2 > v.x + width -1)) { - cr.x2 = v.x + width - 1; - } - v.w = width; - - // Change height - if ((height < v.h) && (cr.y2 > v.y + height -1)) { - cr.y2 = v.y + height - 1; - } - v.h = height; - - - if (v.w > 0 && v.h > 0 && c.width > 0 && c.height > 0) { - saveImg = c_ctx.getImageData(0, 0, - (c.width < v.w) ? c.width : v.w, - (c.height < v.h) ? c.height : v.h); - } - - c.width = v.w; - c.height = v.h; - - if (saveImg) { - c_ctx.putImageData(saveImg, 0, 0); - } - } - - vx2 = v.x + v.w - 1; - vy2 = v.y + v.h - 1; - - - // Position change - - if ((deltaX < 0) && ((v.x + deltaX) < 0)) { - deltaX = - v.x; - } - if ((vx2 + deltaX) >= fb_width) { - deltaX -= ((vx2 + deltaX) - fb_width + 1); - } - - if ((v.y + deltaY) < 0) { - deltaY = - v.y; - } - if ((vy2 + deltaY) >= fb_height) { - deltaY -= ((vy2 + deltaY) - fb_height + 1); - } - - if ((deltaX === 0) && (deltaY === 0)) { - //Util.Debug("skipping viewport change"); - return; - } - Util.Debug("viewportChange deltaX: " + deltaX + ", deltaY: " + deltaY); - - v.x += deltaX; - vx2 += deltaX; - v.y += deltaY; - vy2 += deltaY; - - // Update the clean rectangle - if (v.x > cr.x1) { - cr.x1 = v.x; - } - if (vx2 < cr.x2) { - cr.x2 = vx2; - } - if (v.y > cr.y1) { - cr.y1 = v.y; - } - if (vy2 < cr.y2) { - cr.y2 = vy2; - } - - if (deltaX < 0) { - // Shift viewport left, redraw left section - x1 = 0; - w = - deltaX; - } else { - // Shift viewport right, redraw right section - x1 = v.w - deltaX; - w = deltaX; - } - if (deltaY < 0) { - // Shift viewport up, redraw top section - y1 = 0; - h = - deltaY; - } else { - // Shift viewport down, redraw bottom section - y1 = v.h - deltaY; - h = deltaY; - } - - // Copy the valid part of the viewport to the shifted location - saveStyle = c_ctx.fillStyle; - c_ctx.fillStyle = "rgb(255,255,255)"; - if (deltaX !== 0) { - //that.copyImage(0, 0, -deltaX, 0, v.w, v.h); - //that.fillRect(x1, 0, w, v.h, [255,255,255]); - c_ctx.drawImage(c, 0, 0, v.w, v.h, -deltaX, 0, v.w, v.h); - c_ctx.fillRect(x1, 0, w, v.h); - } - if (deltaY !== 0) { - //that.copyImage(0, 0, 0, -deltaY, v.w, v.h); - //that.fillRect(0, y1, v.w, h, [255,255,255]); - c_ctx.drawImage(c, 0, 0, v.w, v.h, 0, -deltaY, v.w, v.h); - c_ctx.fillRect(0, y1, v.w, h); - } - c_ctx.fillStyle = saveStyle; -}; - - -// Return a map of clean and dirty areas of the viewport and reset the -// tracking of clean and dirty areas. -// -// Returns: {'cleanBox': {'x': x, 'y': y, 'w': w, 'h': h}, -// 'dirtyBoxes': [{'x': x, 'y': y, 'w': w, 'h': h}, ...]} -that.getCleanDirtyReset = function() { - var v = viewport, c = cleanRect, cleanBox, dirtyBoxes = [], - vx2 = v.x + v.w - 1, vy2 = v.y + v.h - 1; - - - // Copy the cleanRect - cleanBox = {'x': c.x1, 'y': c.y1, - 'w': c.x2 - c.x1 + 1, 'h': c.y2 - c.y1 + 1}; - - if ((c.x1 >= c.x2) || (c.y1 >= c.y2)) { - // Whole viewport is dirty - dirtyBoxes.push({'x': v.x, 'y': v.y, 'w': v.w, 'h': v.h}); - } else { - // Redraw dirty regions - if (v.x < c.x1) { - // left side dirty region - dirtyBoxes.push({'x': v.x, 'y': v.y, - 'w': c.x1 - v.x + 1, 'h': v.h}); - } - if (vx2 > c.x2) { - // right side dirty region - dirtyBoxes.push({'x': c.x2 + 1, 'y': v.y, - 'w': vx2 - c.x2, 'h': v.h}); - } - if (v.y < c.y1) { - // top/middle dirty region - dirtyBoxes.push({'x': c.x1, 'y': v.y, - 'w': c.x2 - c.x1 + 1, 'h': c.y1 - v.y}); - } - if (vy2 > c.y2) { - // bottom/middle dirty region - dirtyBoxes.push({'x': c.x1, 'y': c.y2 + 1, - 'w': c.x2 - c.x1 + 1, 'h': vy2 - c.y2}); - } - } - - // Reset the cleanRect to the whole viewport - cleanRect = {'x1': v.x, 'y1': v.y, - 'x2': v.x + v.w - 1, 'y2': v.y + v.h - 1}; - - return {'cleanBox': cleanBox, 'dirtyBoxes': dirtyBoxes}; -}; - -// Translate viewport coordinates to absolute coordinates -that.absX = function(x) { - return x + viewport.x; -} -that.absY = function(y) { - return y + viewport.y; -} - - -that.resize = function(width, height) { - c_prevStyle = ""; - - fb_width = width; - fb_height = height; - - rescale(conf.scale); - that.viewportChange(); -}; - -that.clear = function() { - - if (conf.logo) { - that.resize(conf.logo.width, conf.logo.height); - that.blitStringImage(conf.logo.data, 0, 0); - } else { - that.resize(640, 20); - c_ctx.clearRect(0, 0, viewport.w, viewport.h); - } - - // No benefit over default ("source-over") in Chrome and firefox - //c_ctx.globalCompositeOperation = "copy"; -}; - -that.fillRect = function(x, y, width, height, color) { - setFillColor(color); - c_ctx.fillRect(x - viewport.x, y - viewport.y, width, height); -}; - -that.copyImage = function(old_x, old_y, new_x, new_y, w, h) { - var x1 = old_x - viewport.x, y1 = old_y - viewport.y, - x2 = new_x - viewport.x, y2 = new_y - viewport.y; - c_ctx.drawImage(conf.target, x1, y1, w, h, x2, y2, w, h); -}; - - -// Start updating a tile -that.startTile = function(x, y, width, height, color) { - var data, rgb, red, green, blue, i; - tile_x = x; - tile_y = y; - if ((width === 16) && (height === 16)) { - tile = tile16x16; - } else { - tile = c_ctx.createImageData(width, height); - } - data = tile.data; - if (conf.prefer_js) { - if (conf.true_color) { - rgb = color; - } else { - rgb = conf.colourMap[color[0]]; - } - red = rgb[0]; - green = rgb[1]; - blue = rgb[2]; - for (i = 0; i < (width * height * 4); i+=4) { - data[i ] = red; - data[i + 1] = green; - data[i + 2] = blue; - data[i + 3] = 255; - } - } else { - that.fillRect(x, y, width, height, color); - } -}; - -// Update sub-rectangle of the current tile -that.subTile = function(x, y, w, h, color) { - var data, p, rgb, red, green, blue, width, j, i, xend, yend; - if (conf.prefer_js) { - data = tile.data; - width = tile.width; - if (conf.true_color) { - rgb = color; - } else { - rgb = conf.colourMap[color[0]]; - } - red = rgb[0]; - green = rgb[1]; - blue = rgb[2]; - xend = x + w; - yend = y + h; - for (j = y; j < yend; j += 1) { - for (i = x; i < xend; i += 1) { - p = (i + (j * width) ) * 4; - data[p ] = red; - data[p + 1] = green; - data[p + 2] = blue; - data[p + 3] = 255; - } - } - } else { - that.fillRect(tile_x + x, tile_y + y, w, h, color); - } -}; - -// Draw the current tile to the screen -that.finishTile = function() { - if (conf.prefer_js) { - c_ctx.putImageData(tile, tile_x - viewport.x, tile_y - viewport.y) - } - // else: No-op, if not prefer_js then already done by setSubTile -}; - -rgbxImageData = function(x, y, width, height, arr, offset) { - var img, i, j, data, v = viewport; - /* - if ((x - v.x >= v.w) || (y - v.y >= v.h) || - (x - v.x + width < 0) || (y - v.y + height < 0)) { - // Skipping because outside of viewport - return; - } - */ - img = c_ctx.createImageData(width, height); - data = img.data; - for (i=0, j=offset; i < (width * height * 4); i=i+4, j=j+4) { - data[i ] = arr[j ]; - data[i + 1] = arr[j + 1]; - data[i + 2] = arr[j + 2]; - data[i + 3] = 255; // Set Alpha - } - c_ctx.putImageData(img, x - v.x, y - v.y); -}; - -cmapImageData = function(x, y, width, height, arr, offset) { - var img, i, j, data, rgb, cmap; - img = c_ctx.createImageData(width, height); - data = img.data; - cmap = conf.colourMap; - for (i=0, j=offset; i < (width * height * 4); i+=4, j+=1) { - rgb = cmap[arr[j]]; - data[i ] = rgb[0]; - data[i + 1] = rgb[1]; - data[i + 2] = rgb[2]; - data[i + 3] = 255; // Set Alpha - } - c_ctx.putImageData(img, x - viewport.x, y - viewport.y); -}; - -that.blitImage = function(x, y, width, height, arr, offset) { - if (conf.true_color) { - rgbxImageData(x, y, width, height, arr, offset); - } else { - cmapImageData(x, y, width, height, arr, offset); - } -}; - -that.blitStringImage = function(str, x, y) { - var img = new Image(); - img.onload = function () { - c_ctx.drawImage(img, x - viewport.x, y - viewport.y); - }; - img.src = str; -}; - -that.changeCursor = function(pixels, mask, hotx, hoty, w, h) { - if (conf.cursor_uri === false) { - Util.Warn("changeCursor called but no cursor data URI support"); - return; - } - - if (conf.true_color) { - changeCursor(conf.target, pixels, mask, hotx, hoty, w, h); - } else { - changeCursor(conf.target, pixels, mask, hotx, hoty, w, h, conf.colourMap); - } -}; - -that.defaultCursor = function() { - conf.target.style.cursor = "default"; -}; - -return constructor(); // Return the public API interface - -} // End of Display() - - -/* Set CSS cursor property using data URI encoded cursor file */ -function changeCursor(target, pixels, mask, hotx, hoty, w, h, cmap) { - "use strict"; - var cur = [], rgb, IHDRsz, RGBsz, ANDsz, XORsz, url, idx, alpha, x, y; - //Util.Debug(">> changeCursor, x: " + hotx + ", y: " + hoty + ", w: " + w + ", h: " + h); - - // Push multi-byte little-endian values - cur.push16le = function (num) { - this.push((num ) & 0xFF, - (num >> 8) & 0xFF ); - }; - cur.push32le = function (num) { - this.push((num ) & 0xFF, - (num >> 8) & 0xFF, - (num >> 16) & 0xFF, - (num >> 24) & 0xFF ); - }; - - IHDRsz = 40; - RGBsz = w * h * 4; - XORsz = Math.ceil( (w * h) / 8.0 ); - ANDsz = Math.ceil( (w * h) / 8.0 ); - - // Main header - cur.push16le(0); // 0: Reserved - cur.push16le(2); // 2: .CUR type - cur.push16le(1); // 4: Number of images, 1 for non-animated ico - - // Cursor #1 header (ICONDIRENTRY) - cur.push(w); // 6: width - cur.push(h); // 7: height - cur.push(0); // 8: colors, 0 -> true-color - cur.push(0); // 9: reserved - cur.push16le(hotx); // 10: hotspot x coordinate - cur.push16le(hoty); // 12: hotspot y coordinate - cur.push32le(IHDRsz + RGBsz + XORsz + ANDsz); - // 14: cursor data byte size - cur.push32le(22); // 18: offset of cursor data in the file - - - // Cursor #1 InfoHeader (ICONIMAGE/BITMAPINFO) - cur.push32le(IHDRsz); // 22: Infoheader size - cur.push32le(w); // 26: Cursor width - cur.push32le(h*2); // 30: XOR+AND height - cur.push16le(1); // 34: number of planes - cur.push16le(32); // 36: bits per pixel - cur.push32le(0); // 38: Type of compression - - cur.push32le(XORsz + ANDsz); // 43: Size of Image - // Gimp leaves this as 0 - - cur.push32le(0); // 46: reserved - cur.push32le(0); // 50: reserved - cur.push32le(0); // 54: reserved - cur.push32le(0); // 58: reserved - - // 62: color data (RGBQUAD icColors[]) - for (y = h-1; y >= 0; y -= 1) { - for (x = 0; x < w; x += 1) { - idx = y * Math.ceil(w / 8) + Math.floor(x/8); - alpha = (mask[idx] << (x % 8)) & 0x80 ? 255 : 0; - - if (cmap) { - idx = (w * y) + x; - rgb = cmap[pixels[idx]]; - cur.push(rgb[2]); // blue - cur.push(rgb[1]); // green - cur.push(rgb[0]); // red - cur.push(alpha); // alpha - } else { - idx = ((w * y) + x) * 4; - cur.push(pixels[idx + 2]); // blue - cur.push(pixels[idx + 1]); // green - cur.push(pixels[idx ]); // red - cur.push(alpha); // alpha - } - } - } - - // XOR/bitmask data (BYTE icXOR[]) - // (ignored, just needs to be right size) - for (y = 0; y < h; y += 1) { - for (x = 0; x < Math.ceil(w / 8); x += 1) { - cur.push(0x00); - } - } - - // AND/bitmask data (BYTE icAND[]) - // (ignored, just needs to be right size) - for (y = 0; y < h; y += 1) { - for (x = 0; x < Math.ceil(w / 8); x += 1) { - cur.push(0x00); - } - } - - url = "data:image/x-icon;base64," + Base64.encode(cur); - target.style.cursor = "url(" + url + ") " + hotx + " " + hoty + ", default"; - //Util.Debug("<< changeCursor, cur.length: " + cur.length); -} diff --git a/classes/novnc/include/input.js b/classes/novnc/include/input.js deleted file mode 100644 index 3124d08..0000000 --- a/classes/novnc/include/input.js +++ /dev/null @@ -1,1884 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-2 or any later version (see LICENSE.txt) - */ - -/*jslint browser: true, white: false, bitwise: false */ -/*global window, Util */ - - -// -// Keyboard event handler -// - -function Keyboard(defaults) { -"use strict"; - -var that = {}, // Public API methods - conf = {}, // Configuration attributes - - keyDownList = []; // List of depressed keys - // (even if they are happy) - -// Configuration attributes -Util.conf_defaults(conf, that, defaults, [ - ['target', 'wo', 'dom', document, 'DOM element that captures keyboard input'], - ['focused', 'rw', 'bool', true, 'Capture and send key events'], - - ['onKeyPress', 'rw', 'func', null, 'Handler for key press/release'] - ]); - - -// -// Private functions -// - -// From the event keyCode return the keysym value for keys that need -// to be suppressed otherwise they may trigger unintended browser -// actions -function getKeysymSpecial(evt) { - var keysym = null; - - switch ( evt.keyCode ) { - // These generate a keyDown and keyPress in Firefox and Opera - case 8 : keysym = 0xFF08; break; // BACKSPACE - case 13 : keysym = 0xFF0D; break; // ENTER - - // This generates a keyDown and keyPress in Opera - case 9 : keysym = 0xFF09; break; // TAB - default : break; - } - - if (evt.type === 'keydown') { - switch ( evt.keyCode ) { - case 27 : keysym = 0xFF1B; break; // ESCAPE - case 46 : keysym = 0xFFFF; break; // DELETE - - case 36 : keysym = 0xFF50; break; // HOME - case 35 : keysym = 0xFF57; break; // END - case 33 : keysym = 0xFF55; break; // PAGE_UP - case 34 : keysym = 0xFF56; break; // PAGE_DOWN - case 45 : keysym = 0xFF63; break; // INSERT - // '-' during keyPress - case 37 : keysym = 0xFF51; break; // LEFT - case 38 : keysym = 0xFF52; break; // UP - case 39 : keysym = 0xFF53; break; // RIGHT - case 40 : keysym = 0xFF54; break; // DOWN - case 16 : keysym = 0xFFE1; break; // SHIFT - case 17 : keysym = 0xFFE3; break; // CONTROL - //case 18 : keysym = 0xFFE7; break; // Left Meta (Mac Option) - case 18 : keysym = 0xFFE9; break; // Left ALT (Mac Command) - - case 112 : keysym = 0xFFBE; break; // F1 - case 113 : keysym = 0xFFBF; break; // F2 - case 114 : keysym = 0xFFC0; break; // F3 - case 115 : keysym = 0xFFC1; break; // F4 - case 116 : keysym = 0xFFC2; break; // F5 - case 117 : keysym = 0xFFC3; break; // F6 - case 118 : keysym = 0xFFC4; break; // F7 - case 119 : keysym = 0xFFC5; break; // F8 - case 120 : keysym = 0xFFC6; break; // F9 - case 121 : keysym = 0xFFC7; break; // F10 - case 122 : keysym = 0xFFC8; break; // F11 - case 123 : keysym = 0xFFC9; break; // F12 - - default : break; - } - } - - if ((!keysym) && (evt.ctrlKey || evt.altKey)) { - if ((typeof(evt.which) !== "undefined") && (evt.which > 0)) { - keysym = evt.which; - } else { - // IE9 always - // Firefox and Opera when ctrl/alt + special - Util.Warn("which not set, using keyCode"); - keysym = evt.keyCode; - } - - /* Remap symbols */ - switch (keysym) { - case 186 : keysym = 59; break; // ; (IE) - case 187 : keysym = 61; break; // = (IE) - case 188 : keysym = 44; break; // , (Mozilla, IE) - case 109 : // - (Mozilla, Opera) - if (Util.Engine.gecko || Util.Engine.presto) { - keysym = 45; } - break; - case 189 : keysym = 45; break; // - (IE) - case 190 : keysym = 46; break; // . (Mozilla, IE) - case 191 : keysym = 47; break; // / (Mozilla, IE) - case 192 : keysym = 96; break; // ` (Mozilla, IE) - case 219 : keysym = 91; break; // [ (Mozilla, IE) - case 220 : keysym = 92; break; // \ (Mozilla, IE) - case 221 : keysym = 93; break; // ] (Mozilla, IE) - case 222 : keysym = 39; break; // ' (Mozilla, IE) - } - - /* Remap shifted and unshifted keys */ - if (!!evt.shiftKey) { - switch (keysym) { - case 48 : keysym = 41 ; break; // ) (shifted 0) - case 49 : keysym = 33 ; break; // ! (shifted 1) - case 50 : keysym = 64 ; break; // @ (shifted 2) - case 51 : keysym = 35 ; break; // # (shifted 3) - case 52 : keysym = 36 ; break; // $ (shifted 4) - case 53 : keysym = 37 ; break; // % (shifted 5) - case 54 : keysym = 94 ; break; // ^ (shifted 6) - case 55 : keysym = 38 ; break; // & (shifted 7) - case 56 : keysym = 42 ; break; // * (shifted 8) - case 57 : keysym = 40 ; break; // ( (shifted 9) - - case 59 : keysym = 58 ; break; // : (shifted `) - case 61 : keysym = 43 ; break; // + (shifted ;) - case 44 : keysym = 60 ; break; // < (shifted ,) - case 45 : keysym = 95 ; break; // _ (shifted -) - case 46 : keysym = 62 ; break; // > (shifted .) - case 47 : keysym = 63 ; break; // ? (shifted /) - case 96 : keysym = 126; break; // ~ (shifted `) - case 91 : keysym = 123; break; // { (shifted [) - case 92 : keysym = 124; break; // | (shifted \) - case 93 : keysym = 125; break; // } (shifted ]) - case 39 : keysym = 34 ; break; // " (shifted ') - } - } else if ((keysym >= 65) && (keysym <=90)) { - /* Remap unshifted A-Z */ - keysym += 32; - } else if (evt.keyLocation === 3) { - // numpad keys - switch (keysym) { - case 96 : keysym = 48; break; // 0 - case 97 : keysym = 49; break; // 1 - case 98 : keysym = 50; break; // 2 - case 99 : keysym = 51; break; // 3 - case 100: keysym = 52; break; // 4 - case 101: keysym = 53; break; // 5 - case 102: keysym = 54; break; // 6 - case 103: keysym = 55; break; // 7 - case 104: keysym = 56; break; // 8 - case 105: keysym = 57; break; // 9 - case 109: keysym = 45; break; // - - case 110: keysym = 46; break; // . - case 111: keysym = 47; break; // / - } - } - } - - return keysym; -} - -/* Translate DOM keyPress event to keysym value */ -function getKeysym(evt) { - var keysym, msg; - - if (typeof(evt.which) !== "undefined") { - // WebKit, Firefox, Opera - keysym = evt.which; - } else { - // IE9 - Util.Warn("which not set, using keyCode"); - keysym = evt.keyCode; - } - - if ((keysym > 255) && (keysym < 0xFF00)) { - msg = "Mapping character code " + keysym; - // Map Unicode outside Latin 1 to X11 keysyms - keysym = unicodeTable[keysym]; - if (typeof(keysym) === 'undefined') { - keysym = 0; - } - Util.Debug(msg + " to " + keysym); - } - - return keysym; -} - -function show_keyDownList(kind) { - var c; - var msg = "keyDownList (" + kind + "):\n"; - for (c = 0; c < keyDownList.length; c++) { - msg = msg + " " + c + " - keyCode: " + keyDownList[c].keyCode + - " - which: " + keyDownList[c].which + "\n"; - } - Util.Debug(msg); -} - -function copyKeyEvent(evt) { - var members = ['type', 'keyCode', 'charCode', 'which', - 'altKey', 'ctrlKey', 'shiftKey', - 'keyLocation', 'keyIdentifier'], i, obj = {}; - for (i = 0; i < members.length; i++) { - if (typeof(evt[members[i]]) !== "undefined") { - obj[members[i]] = evt[members[i]]; - } - } - return obj; -} - -function pushKeyEvent(fevt) { - keyDownList.push(fevt); -} - -function getKeyEvent(keyCode, pop) { - var i, fevt = null; - for (i = keyDownList.length-1; i >= 0; i--) { - if (keyDownList[i].keyCode === keyCode) { - if ((typeof(pop) !== "undefined") && (pop)) { - fevt = keyDownList.splice(i, 1)[0]; - } else { - fevt = keyDownList[i]; - } - break; - } - } - return fevt; -} - -function ignoreKeyEvent(evt) { - // Blarg. Some keys have a different keyCode on keyDown vs keyUp - if (evt.keyCode === 229) { - // French AZERTY keyboard dead key. - // Lame thing is that the respective keyUp is 219 so we can't - // properly ignore the keyUp event - return true; - } - return false; -} - - -// -// Key Event Handling: -// -// There are several challenges when dealing with key events: -// - The meaning and use of keyCode, charCode and which depends on -// both the browser and the event type (keyDown/Up vs keyPress). -// - We cannot automatically determine the keyboard layout -// - The keyDown and keyUp events have a keyCode value that has not -// been translated by modifier keys. -// - The keyPress event has a translated (for layout and modifiers) -// character code but the attribute containing it differs. keyCode -// contains the translated value in WebKit (Chrome/Safari), Opera -// 11 and IE9. charCode contains the value in WebKit and Firefox. -// The which attribute contains the value on WebKit, Firefox and -// Opera 11. -// - The keyDown/Up keyCode value indicates (sort of) the physical -// key was pressed but only for standard US layout. On a US -// keyboard, the '-' and '_' characters are on the same key and -// generate a keyCode value of 189. But on an AZERTY keyboard even -// though they are different physical keys they both still -// generate a keyCode of 189! -// - To prevent a key event from propagating to the browser and -// causing unwanted default actions (such as closing a tab, -// opening a menu, shifting focus, etc) we must suppress this -// event in both keyDown and keyPress because not all key strokes -// generate on a keyPress event. Also, in WebKit and IE9 -// suppressing the keyDown prevents a keyPress but other browsers -// still generated a keyPress even if keyDown is suppressed. -// -// For safe key events, we wait until the keyPress event before -// reporting a key down event. For unsafe key events, we report a key -// down event when the keyDown event fires and we suppress any further -// actions (including keyPress). -// -// In order to report a key up event that matches what we reported -// for the key down event, we keep a list of keys that are currently -// down. When the keyDown event happens, we add the key event to the -// list. If it is a safe key event, then we update the which attribute -// in the most recent item on the list when we received a keyPress -// event (keyPress should immediately follow keyDown). When we -// received a keyUp event we search for the event on the list with -// a matching keyCode and we report the character code using the value -// in the 'which' attribute that was stored with that key. -// - -function onKeyDown(e) { - if (! conf.focused) { - return true; - } - var fevt = null, evt = (e ? e : window.event), - keysym = null, suppress = false; - //Util.Debug("onKeyDown kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which); - - fevt = copyKeyEvent(evt); - - keysym = getKeysymSpecial(evt); - // Save keysym decoding for use in keyUp - fevt.keysym = keysym; - if (keysym) { - // If it is a key or key combination that might trigger - // browser behaviors or it has no corresponding keyPress - // event, then send it immediately - if (conf.onKeyPress && !ignoreKeyEvent(evt)) { - Util.Debug("onKeyPress down, keysym: " + keysym + - " (onKeyDown key: " + evt.keyCode + - ", which: " + evt.which + ")"); - conf.onKeyPress(keysym, 1, evt); - } - suppress = true; - } - - if (! ignoreKeyEvent(evt)) { - // Add it to the list of depressed keys - pushKeyEvent(fevt); - //show_keyDownList('down'); - } - - if (suppress) { - // Suppress bubbling/default actions - Util.stopEvent(e); - return false; - } else { - // Allow the event to bubble and become a keyPress event which - // will have the character code translated - return true; - } -} - -function onKeyPress(e) { - if (! conf.focused) { - return true; - } - var evt = (e ? e : window.event), - kdlen = keyDownList.length, keysym = null; - //Util.Debug("onKeyPress kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which); - - if (((evt.which !== "undefined") && (evt.which === 0)) || - (getKeysymSpecial(evt))) { - // Firefox and Opera generate a keyPress event even if keyDown - // is suppressed. But the keys we want to suppress will have - // either: - // - the which attribute set to 0 - // - getKeysymSpecial() will identify it - Util.Debug("Ignoring special key in keyPress"); - Util.stopEvent(e); - return false; - } - - keysym = getKeysym(evt); - - // Modify the the which attribute in the depressed keys list so - // that the keyUp event will be able to have the character code - // translation available. - if (kdlen > 0) { - keyDownList[kdlen-1].keysym = keysym; - } else { - Util.Warn("keyDownList empty when keyPress triggered"); - } - - //show_keyDownList('press'); - - // Send the translated keysym - if (conf.onKeyPress && (keysym > 0)) { - Util.Debug("onKeyPress down, keysym: " + keysym + - " (onKeyPress key: " + evt.keyCode + - ", which: " + evt.which + ")"); - conf.onKeyPress(keysym, 1, evt); - } - - // Stop keypress events just in case - Util.stopEvent(e); - return false; -} - -function onKeyUp(e) { - if (! conf.focused) { - return true; - } - var fevt = null, evt = (e ? e : window.event), keysym; - //Util.Debug("onKeyUp kC:" + evt.keyCode + " cC:" + evt.charCode + " w:" + evt.which); - - fevt = getKeyEvent(evt.keyCode, true); - - if (fevt) { - keysym = fevt.keysym; - } else { - Util.Warn("Key event (keyCode = " + evt.keyCode + - ") not found on keyDownList"); - keysym = 0; - } - - //show_keyDownList('up'); - - if (conf.onKeyPress && (keysym > 0)) { - //Util.Debug("keyPress up, keysym: " + keysym + - // " (key: " + evt.keyCode + ", which: " + evt.which + ")"); - Util.Debug("onKeyPress up, keysym: " + keysym + - " (onKeyPress key: " + evt.keyCode + - ", which: " + evt.which + ")"); - conf.onKeyPress(keysym, 0, evt); - } - Util.stopEvent(e); - return false; -} - -// -// Public API interface functions -// - -that.grab = function() { - //Util.Debug(">> Keyboard.grab"); - var c = conf.target; - - Util.addEvent(c, 'keydown', onKeyDown); - Util.addEvent(c, 'keyup', onKeyUp); - Util.addEvent(c, 'keypress', onKeyPress); - - //Util.Debug("<< Keyboard.grab"); -}; - -that.ungrab = function() { - //Util.Debug(">> Keyboard.ungrab"); - var c = conf.target; - - Util.removeEvent(c, 'keydown', onKeyDown); - Util.removeEvent(c, 'keyup', onKeyUp); - Util.removeEvent(c, 'keypress', onKeyPress); - - //Util.Debug(">> Keyboard.ungrab"); -}; - -return that; // Return the public API interface - -} // End of Keyboard() - - -// -// Mouse event handler -// - -function Mouse(defaults) { -"use strict"; - -var that = {}, // Public API methods - conf = {}; // Configuration attributes - -// Configuration attributes -Util.conf_defaults(conf, that, defaults, [ - ['target', 'ro', 'dom', document, 'DOM element that captures mouse input'], - ['focused', 'rw', 'bool', true, 'Capture and send mouse clicks/movement'], - ['scale', 'rw', 'float', 1.0, 'Viewport scale factor 0.0 - 1.0'], - - ['onMouseButton', 'rw', 'func', null, 'Handler for mouse button click/release'], - ['onMouseMove', 'rw', 'func', null, 'Handler for mouse movement'], - ['touchButton', 'rw', 'int', 1, 'Button mask (1, 2, 4) for touch devices (0 means ignore clicks)'] - ]); - - -// -// Private functions -// - -function onMouseButton(e, down) { - var evt, pos, bmask; - if (! conf.focused) { - return true; - } - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - if (e.touches || e.changedTouches) { - // Touch device - bmask = conf.touchButton; - // If bmask is set - } else if (evt.which) { - /* everything except IE */ - bmask = 1 << evt.button; - } else { - /* IE including 9 */ - bmask = (evt.button & 0x1) + // Left - (evt.button & 0x2) * 2 + // Right - (evt.button & 0x4) / 2; // Middle - } - //Util.Debug("mouse " + pos.x + "," + pos.y + " down: " + down + - // " bmask: " + bmask + "(evt.button: " + evt.button + ")"); - if (bmask > 0 && conf.onMouseButton) { - Util.Debug("onMouseButton " + (down ? "down" : "up") + - ", x: " + pos.x + ", y: " + pos.y + ", bmask: " + bmask); - conf.onMouseButton(pos.x, pos.y, down, bmask); - } - Util.stopEvent(e); - return false; -} - -function onMouseDown(e) { - onMouseButton(e, 1); -} - -function onMouseUp(e) { - onMouseButton(e, 0); -} - -function onMouseWheel(e) { - var evt, pos, bmask, wheelData; - if (! conf.focused) { - return true; - } - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - wheelData = evt.detail ? evt.detail * -1 : evt.wheelDelta / 40; - if (wheelData > 0) { - bmask = 1 << 3; - } else { - bmask = 1 << 4; - } - //Util.Debug('mouse scroll by ' + wheelData + ':' + pos.x + "," + pos.y); - if (conf.onMouseButton) { - conf.onMouseButton(pos.x, pos.y, 1, bmask); - conf.onMouseButton(pos.x, pos.y, 0, bmask); - } - Util.stopEvent(e); - return false; -} - -function onMouseMove(e) { - var evt, pos; - if (! conf.focused) { - return true; - } - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - //Util.Debug('mouse ' + evt.which + '/' + evt.button + ' up:' + pos.x + "," + pos.y); - if (conf.onMouseMove) { - conf.onMouseMove(pos.x, pos.y); - } - Util.stopEvent(e); - return false; -} - -function onMouseDisable(e) { - var evt, pos; - if (! conf.focused) { - return true; - } - evt = (e ? e : window.event); - pos = Util.getEventPosition(e, conf.target, conf.scale); - /* Stop propagation if inside canvas area */ - if ((pos.x >= 0) && (pos.y >= 0) && - (pos.x < conf.target.offsetWidth) && - (pos.y < conf.target.offsetHeight)) { - //Util.Debug("mouse event disabled"); - Util.stopEvent(e); - return false; - } - //Util.Debug("mouse event not disabled"); - return true; -} - -// -// Public API interface functions -// - -that.grab = function() { - //Util.Debug(">> Mouse.grab"); - var c = conf.target; - - if ('ontouchstart' in document.documentElement) { - Util.addEvent(c, 'touchstart', onMouseDown); - Util.addEvent(c, 'touchend', onMouseUp); - Util.addEvent(c, 'touchmove', onMouseMove); - } else { - Util.addEvent(c, 'mousedown', onMouseDown); - Util.addEvent(c, 'mouseup', onMouseUp); - Util.addEvent(c, 'mousemove', onMouseMove); - Util.addEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', - onMouseWheel); - } - - /* Work around right and middle click browser behaviors */ - Util.addEvent(document, 'click', onMouseDisable); - Util.addEvent(document.body, 'contextmenu', onMouseDisable); - - //Util.Debug("<< Mouse.grab"); -}; - -that.ungrab = function() { - //Util.Debug(">> Mouse.ungrab"); - var c = conf.target; - - if ('ontouchstart' in document.documentElement) { - Util.removeEvent(c, 'touchstart', onMouseDown); - Util.removeEvent(c, 'touchend', onMouseUp); - Util.removeEvent(c, 'touchmove', onMouseMove); - } else { - Util.removeEvent(c, 'mousedown', onMouseDown); - Util.removeEvent(c, 'mouseup', onMouseUp); - Util.removeEvent(c, 'mousemove', onMouseMove); - Util.removeEvent(c, (Util.Engine.gecko) ? 'DOMMouseScroll' : 'mousewheel', - onMouseWheel); - } - - /* Work around right and middle click browser behaviors */ - Util.removeEvent(document, 'click', onMouseDisable); - Util.removeEvent(document.body, 'contextmenu', onMouseDisable); - - //Util.Debug(">> Mouse.ungrab"); -}; - -return that; // Return the public API interface - -} // End of Mouse() - - -/* - * Browser keypress to X11 keysym for Unicode characters > U+00FF - */ -unicodeTable = { - 0x0104 : 0x01a1, - 0x02D8 : 0x01a2, - 0x0141 : 0x01a3, - 0x013D : 0x01a5, - 0x015A : 0x01a6, - 0x0160 : 0x01a9, - 0x015E : 0x01aa, - 0x0164 : 0x01ab, - 0x0179 : 0x01ac, - 0x017D : 0x01ae, - 0x017B : 0x01af, - 0x0105 : 0x01b1, - 0x02DB : 0x01b2, - 0x0142 : 0x01b3, - 0x013E : 0x01b5, - 0x015B : 0x01b6, - 0x02C7 : 0x01b7, - 0x0161 : 0x01b9, - 0x015F : 0x01ba, - 0x0165 : 0x01bb, - 0x017A : 0x01bc, - 0x02DD : 0x01bd, - 0x017E : 0x01be, - 0x017C : 0x01bf, - 0x0154 : 0x01c0, - 0x0102 : 0x01c3, - 0x0139 : 0x01c5, - 0x0106 : 0x01c6, - 0x010C : 0x01c8, - 0x0118 : 0x01ca, - 0x011A : 0x01cc, - 0x010E : 0x01cf, - 0x0110 : 0x01d0, - 0x0143 : 0x01d1, - 0x0147 : 0x01d2, - 0x0150 : 0x01d5, - 0x0158 : 0x01d8, - 0x016E : 0x01d9, - 0x0170 : 0x01db, - 0x0162 : 0x01de, - 0x0155 : 0x01e0, - 0x0103 : 0x01e3, - 0x013A : 0x01e5, - 0x0107 : 0x01e6, - 0x010D : 0x01e8, - 0x0119 : 0x01ea, - 0x011B : 0x01ec, - 0x010F : 0x01ef, - 0x0111 : 0x01f0, - 0x0144 : 0x01f1, - 0x0148 : 0x01f2, - 0x0151 : 0x01f5, - 0x0171 : 0x01fb, - 0x0159 : 0x01f8, - 0x016F : 0x01f9, - 0x0163 : 0x01fe, - 0x02D9 : 0x01ff, - 0x0126 : 0x02a1, - 0x0124 : 0x02a6, - 0x0130 : 0x02a9, - 0x011E : 0x02ab, - 0x0134 : 0x02ac, - 0x0127 : 0x02b1, - 0x0125 : 0x02b6, - 0x0131 : 0x02b9, - 0x011F : 0x02bb, - 0x0135 : 0x02bc, - 0x010A : 0x02c5, - 0x0108 : 0x02c6, - 0x0120 : 0x02d5, - 0x011C : 0x02d8, - 0x016C : 0x02dd, - 0x015C : 0x02de, - 0x010B : 0x02e5, - 0x0109 : 0x02e6, - 0x0121 : 0x02f5, - 0x011D : 0x02f8, - 0x016D : 0x02fd, - 0x015D : 0x02fe, - 0x0138 : 0x03a2, - 0x0156 : 0x03a3, - 0x0128 : 0x03a5, - 0x013B : 0x03a6, - 0x0112 : 0x03aa, - 0x0122 : 0x03ab, - 0x0166 : 0x03ac, - 0x0157 : 0x03b3, - 0x0129 : 0x03b5, - 0x013C : 0x03b6, - 0x0113 : 0x03ba, - 0x0123 : 0x03bb, - 0x0167 : 0x03bc, - 0x014A : 0x03bd, - 0x014B : 0x03bf, - 0x0100 : 0x03c0, - 0x012E : 0x03c7, - 0x0116 : 0x03cc, - 0x012A : 0x03cf, - 0x0145 : 0x03d1, - 0x014C : 0x03d2, - 0x0136 : 0x03d3, - 0x0172 : 0x03d9, - 0x0168 : 0x03dd, - 0x016A : 0x03de, - 0x0101 : 0x03e0, - 0x012F : 0x03e7, - 0x0117 : 0x03ec, - 0x012B : 0x03ef, - 0x0146 : 0x03f1, - 0x014D : 0x03f2, - 0x0137 : 0x03f3, - 0x0173 : 0x03f9, - 0x0169 : 0x03fd, - 0x016B : 0x03fe, - 0x1E02 : 0x1001e02, - 0x1E03 : 0x1001e03, - 0x1E0A : 0x1001e0a, - 0x1E80 : 0x1001e80, - 0x1E82 : 0x1001e82, - 0x1E0B : 0x1001e0b, - 0x1EF2 : 0x1001ef2, - 0x1E1E : 0x1001e1e, - 0x1E1F : 0x1001e1f, - 0x1E40 : 0x1001e40, - 0x1E41 : 0x1001e41, - 0x1E56 : 0x1001e56, - 0x1E81 : 0x1001e81, - 0x1E57 : 0x1001e57, - 0x1E83 : 0x1001e83, - 0x1E60 : 0x1001e60, - 0x1EF3 : 0x1001ef3, - 0x1E84 : 0x1001e84, - 0x1E85 : 0x1001e85, - 0x1E61 : 0x1001e61, - 0x0174 : 0x1000174, - 0x1E6A : 0x1001e6a, - 0x0176 : 0x1000176, - 0x0175 : 0x1000175, - 0x1E6B : 0x1001e6b, - 0x0177 : 0x1000177, - 0x0152 : 0x13bc, - 0x0153 : 0x13bd, - 0x0178 : 0x13be, - 0x203E : 0x047e, - 0x3002 : 0x04a1, - 0x300C : 0x04a2, - 0x300D : 0x04a3, - 0x3001 : 0x04a4, - 0x30FB : 0x04a5, - 0x30F2 : 0x04a6, - 0x30A1 : 0x04a7, - 0x30A3 : 0x04a8, - 0x30A5 : 0x04a9, - 0x30A7 : 0x04aa, - 0x30A9 : 0x04ab, - 0x30E3 : 0x04ac, - 0x30E5 : 0x04ad, - 0x30E7 : 0x04ae, - 0x30C3 : 0x04af, - 0x30FC : 0x04b0, - 0x30A2 : 0x04b1, - 0x30A4 : 0x04b2, - 0x30A6 : 0x04b3, - 0x30A8 : 0x04b4, - 0x30AA : 0x04b5, - 0x30AB : 0x04b6, - 0x30AD : 0x04b7, - 0x30AF : 0x04b8, - 0x30B1 : 0x04b9, - 0x30B3 : 0x04ba, - 0x30B5 : 0x04bb, - 0x30B7 : 0x04bc, - 0x30B9 : 0x04bd, - 0x30BB : 0x04be, - 0x30BD : 0x04bf, - 0x30BF : 0x04c0, - 0x30C1 : 0x04c1, - 0x30C4 : 0x04c2, - 0x30C6 : 0x04c3, - 0x30C8 : 0x04c4, - 0x30CA : 0x04c5, - 0x30CB : 0x04c6, - 0x30CC : 0x04c7, - 0x30CD : 0x04c8, - 0x30CE : 0x04c9, - 0x30CF : 0x04ca, - 0x30D2 : 0x04cb, - 0x30D5 : 0x04cc, - 0x30D8 : 0x04cd, - 0x30DB : 0x04ce, - 0x30DE : 0x04cf, - 0x30DF : 0x04d0, - 0x30E0 : 0x04d1, - 0x30E1 : 0x04d2, - 0x30E2 : 0x04d3, - 0x30E4 : 0x04d4, - 0x30E6 : 0x04d5, - 0x30E8 : 0x04d6, - 0x30E9 : 0x04d7, - 0x30EA : 0x04d8, - 0x30EB : 0x04d9, - 0x30EC : 0x04da, - 0x30ED : 0x04db, - 0x30EF : 0x04dc, - 0x30F3 : 0x04dd, - 0x309B : 0x04de, - 0x309C : 0x04df, - 0x06F0 : 0x10006f0, - 0x06F1 : 0x10006f1, - 0x06F2 : 0x10006f2, - 0x06F3 : 0x10006f3, - 0x06F4 : 0x10006f4, - 0x06F5 : 0x10006f5, - 0x06F6 : 0x10006f6, - 0x06F7 : 0x10006f7, - 0x06F8 : 0x10006f8, - 0x06F9 : 0x10006f9, - 0x066A : 0x100066a, - 0x0670 : 0x1000670, - 0x0679 : 0x1000679, - 0x067E : 0x100067e, - 0x0686 : 0x1000686, - 0x0688 : 0x1000688, - 0x0691 : 0x1000691, - 0x060C : 0x05ac, - 0x06D4 : 0x10006d4, - 0x0660 : 0x1000660, - 0x0661 : 0x1000661, - 0x0662 : 0x1000662, - 0x0663 : 0x1000663, - 0x0664 : 0x1000664, - 0x0665 : 0x1000665, - 0x0666 : 0x1000666, - 0x0667 : 0x1000667, - 0x0668 : 0x1000668, - 0x0669 : 0x1000669, - 0x061B : 0x05bb, - 0x061F : 0x05bf, - 0x0621 : 0x05c1, - 0x0622 : 0x05c2, - 0x0623 : 0x05c3, - 0x0624 : 0x05c4, - 0x0625 : 0x05c5, - 0x0626 : 0x05c6, - 0x0627 : 0x05c7, - 0x0628 : 0x05c8, - 0x0629 : 0x05c9, - 0x062A : 0x05ca, - 0x062B : 0x05cb, - 0x062C : 0x05cc, - 0x062D : 0x05cd, - 0x062E : 0x05ce, - 0x062F : 0x05cf, - 0x0630 : 0x05d0, - 0x0631 : 0x05d1, - 0x0632 : 0x05d2, - 0x0633 : 0x05d3, - 0x0634 : 0x05d4, - 0x0635 : 0x05d5, - 0x0636 : 0x05d6, - 0x0637 : 0x05d7, - 0x0638 : 0x05d8, - 0x0639 : 0x05d9, - 0x063A : 0x05da, - 0x0640 : 0x05e0, - 0x0641 : 0x05e1, - 0x0642 : 0x05e2, - 0x0643 : 0x05e3, - 0x0644 : 0x05e4, - 0x0645 : 0x05e5, - 0x0646 : 0x05e6, - 0x0647 : 0x05e7, - 0x0648 : 0x05e8, - 0x0649 : 0x05e9, - 0x064A : 0x05ea, - 0x064B : 0x05eb, - 0x064C : 0x05ec, - 0x064D : 0x05ed, - 0x064E : 0x05ee, - 0x064F : 0x05ef, - 0x0650 : 0x05f0, - 0x0651 : 0x05f1, - 0x0652 : 0x05f2, - 0x0653 : 0x1000653, - 0x0654 : 0x1000654, - 0x0655 : 0x1000655, - 0x0698 : 0x1000698, - 0x06A4 : 0x10006a4, - 0x06A9 : 0x10006a9, - 0x06AF : 0x10006af, - 0x06BA : 0x10006ba, - 0x06BE : 0x10006be, - 0x06CC : 0x10006cc, - 0x06D2 : 0x10006d2, - 0x06C1 : 0x10006c1, - 0x0492 : 0x1000492, - 0x0493 : 0x1000493, - 0x0496 : 0x1000496, - 0x0497 : 0x1000497, - 0x049A : 0x100049a, - 0x049B : 0x100049b, - 0x049C : 0x100049c, - 0x049D : 0x100049d, - 0x04A2 : 0x10004a2, - 0x04A3 : 0x10004a3, - 0x04AE : 0x10004ae, - 0x04AF : 0x10004af, - 0x04B0 : 0x10004b0, - 0x04B1 : 0x10004b1, - 0x04B2 : 0x10004b2, - 0x04B3 : 0x10004b3, - 0x04B6 : 0x10004b6, - 0x04B7 : 0x10004b7, - 0x04B8 : 0x10004b8, - 0x04B9 : 0x10004b9, - 0x04BA : 0x10004ba, - 0x04BB : 0x10004bb, - 0x04D8 : 0x10004d8, - 0x04D9 : 0x10004d9, - 0x04E2 : 0x10004e2, - 0x04E3 : 0x10004e3, - 0x04E8 : 0x10004e8, - 0x04E9 : 0x10004e9, - 0x04EE : 0x10004ee, - 0x04EF : 0x10004ef, - 0x0452 : 0x06a1, - 0x0453 : 0x06a2, - 0x0451 : 0x06a3, - 0x0454 : 0x06a4, - 0x0455 : 0x06a5, - 0x0456 : 0x06a6, - 0x0457 : 0x06a7, - 0x0458 : 0x06a8, - 0x0459 : 0x06a9, - 0x045A : 0x06aa, - 0x045B : 0x06ab, - 0x045C : 0x06ac, - 0x0491 : 0x06ad, - 0x045E : 0x06ae, - 0x045F : 0x06af, - 0x2116 : 0x06b0, - 0x0402 : 0x06b1, - 0x0403 : 0x06b2, - 0x0401 : 0x06b3, - 0x0404 : 0x06b4, - 0x0405 : 0x06b5, - 0x0406 : 0x06b6, - 0x0407 : 0x06b7, - 0x0408 : 0x06b8, - 0x0409 : 0x06b9, - 0x040A : 0x06ba, - 0x040B : 0x06bb, - 0x040C : 0x06bc, - 0x0490 : 0x06bd, - 0x040E : 0x06be, - 0x040F : 0x06bf, - 0x044E : 0x06c0, - 0x0430 : 0x06c1, - 0x0431 : 0x06c2, - 0x0446 : 0x06c3, - 0x0434 : 0x06c4, - 0x0435 : 0x06c5, - 0x0444 : 0x06c6, - 0x0433 : 0x06c7, - 0x0445 : 0x06c8, - 0x0438 : 0x06c9, - 0x0439 : 0x06ca, - 0x043A : 0x06cb, - 0x043B : 0x06cc, - 0x043C : 0x06cd, - 0x043D : 0x06ce, - 0x043E : 0x06cf, - 0x043F : 0x06d0, - 0x044F : 0x06d1, - 0x0440 : 0x06d2, - 0x0441 : 0x06d3, - 0x0442 : 0x06d4, - 0x0443 : 0x06d5, - 0x0436 : 0x06d6, - 0x0432 : 0x06d7, - 0x044C : 0x06d8, - 0x044B : 0x06d9, - 0x0437 : 0x06da, - 0x0448 : 0x06db, - 0x044D : 0x06dc, - 0x0449 : 0x06dd, - 0x0447 : 0x06de, - 0x044A : 0x06df, - 0x042E : 0x06e0, - 0x0410 : 0x06e1, - 0x0411 : 0x06e2, - 0x0426 : 0x06e3, - 0x0414 : 0x06e4, - 0x0415 : 0x06e5, - 0x0424 : 0x06e6, - 0x0413 : 0x06e7, - 0x0425 : 0x06e8, - 0x0418 : 0x06e9, - 0x0419 : 0x06ea, - 0x041A : 0x06eb, - 0x041B : 0x06ec, - 0x041C : 0x06ed, - 0x041D : 0x06ee, - 0x041E : 0x06ef, - 0x041F : 0x06f0, - 0x042F : 0x06f1, - 0x0420 : 0x06f2, - 0x0421 : 0x06f3, - 0x0422 : 0x06f4, - 0x0423 : 0x06f5, - 0x0416 : 0x06f6, - 0x0412 : 0x06f7, - 0x042C : 0x06f8, - 0x042B : 0x06f9, - 0x0417 : 0x06fa, - 0x0428 : 0x06fb, - 0x042D : 0x06fc, - 0x0429 : 0x06fd, - 0x0427 : 0x06fe, - 0x042A : 0x06ff, - 0x0386 : 0x07a1, - 0x0388 : 0x07a2, - 0x0389 : 0x07a3, - 0x038A : 0x07a4, - 0x03AA : 0x07a5, - 0x038C : 0x07a7, - 0x038E : 0x07a8, - 0x03AB : 0x07a9, - 0x038F : 0x07ab, - 0x0385 : 0x07ae, - 0x2015 : 0x07af, - 0x03AC : 0x07b1, - 0x03AD : 0x07b2, - 0x03AE : 0x07b3, - 0x03AF : 0x07b4, - 0x03CA : 0x07b5, - 0x0390 : 0x07b6, - 0x03CC : 0x07b7, - 0x03CD : 0x07b8, - 0x03CB : 0x07b9, - 0x03B0 : 0x07ba, - 0x03CE : 0x07bb, - 0x0391 : 0x07c1, - 0x0392 : 0x07c2, - 0x0393 : 0x07c3, - 0x0394 : 0x07c4, - 0x0395 : 0x07c5, - 0x0396 : 0x07c6, - 0x0397 : 0x07c7, - 0x0398 : 0x07c8, - 0x0399 : 0x07c9, - 0x039A : 0x07ca, - 0x039B : 0x07cb, - 0x039C : 0x07cc, - 0x039D : 0x07cd, - 0x039E : 0x07ce, - 0x039F : 0x07cf, - 0x03A0 : 0x07d0, - 0x03A1 : 0x07d1, - 0x03A3 : 0x07d2, - 0x03A4 : 0x07d4, - 0x03A5 : 0x07d5, - 0x03A6 : 0x07d6, - 0x03A7 : 0x07d7, - 0x03A8 : 0x07d8, - 0x03A9 : 0x07d9, - 0x03B1 : 0x07e1, - 0x03B2 : 0x07e2, - 0x03B3 : 0x07e3, - 0x03B4 : 0x07e4, - 0x03B5 : 0x07e5, - 0x03B6 : 0x07e6, - 0x03B7 : 0x07e7, - 0x03B8 : 0x07e8, - 0x03B9 : 0x07e9, - 0x03BA : 0x07ea, - 0x03BB : 0x07eb, - 0x03BC : 0x07ec, - 0x03BD : 0x07ed, - 0x03BE : 0x07ee, - 0x03BF : 0x07ef, - 0x03C0 : 0x07f0, - 0x03C1 : 0x07f1, - 0x03C3 : 0x07f2, - 0x03C2 : 0x07f3, - 0x03C4 : 0x07f4, - 0x03C5 : 0x07f5, - 0x03C6 : 0x07f6, - 0x03C7 : 0x07f7, - 0x03C8 : 0x07f8, - 0x03C9 : 0x07f9, - 0x23B7 : 0x08a1, - 0x2320 : 0x08a4, - 0x2321 : 0x08a5, - 0x23A1 : 0x08a7, - 0x23A3 : 0x08a8, - 0x23A4 : 0x08a9, - 0x23A6 : 0x08aa, - 0x239B : 0x08ab, - 0x239D : 0x08ac, - 0x239E : 0x08ad, - 0x23A0 : 0x08ae, - 0x23A8 : 0x08af, - 0x23AC : 0x08b0, - 0x2264 : 0x08bc, - 0x2260 : 0x08bd, - 0x2265 : 0x08be, - 0x222B : 0x08bf, - 0x2234 : 0x08c0, - 0x221D : 0x08c1, - 0x221E : 0x08c2, - 0x2207 : 0x08c5, - 0x223C : 0x08c8, - 0x2243 : 0x08c9, - 0x21D4 : 0x08cd, - 0x21D2 : 0x08ce, - 0x2261 : 0x08cf, - 0x221A : 0x08d6, - 0x2282 : 0x08da, - 0x2283 : 0x08db, - 0x2229 : 0x08dc, - 0x222A : 0x08dd, - 0x2227 : 0x08de, - 0x2228 : 0x08df, - 0x2202 : 0x08ef, - 0x0192 : 0x08f6, - 0x2190 : 0x08fb, - 0x2191 : 0x08fc, - 0x2192 : 0x08fd, - 0x2193 : 0x08fe, - 0x25C6 : 0x09e0, - 0x2592 : 0x09e1, - 0x2409 : 0x09e2, - 0x240C : 0x09e3, - 0x240D : 0x09e4, - 0x240A : 0x09e5, - 0x2424 : 0x09e8, - 0x240B : 0x09e9, - 0x2518 : 0x09ea, - 0x2510 : 0x09eb, - 0x250C : 0x09ec, - 0x2514 : 0x09ed, - 0x253C : 0x09ee, - 0x23BA : 0x09ef, - 0x23BB : 0x09f0, - 0x2500 : 0x09f1, - 0x23BC : 0x09f2, - 0x23BD : 0x09f3, - 0x251C : 0x09f4, - 0x2524 : 0x09f5, - 0x2534 : 0x09f6, - 0x252C : 0x09f7, - 0x2502 : 0x09f8, - 0x2003 : 0x0aa1, - 0x2002 : 0x0aa2, - 0x2004 : 0x0aa3, - 0x2005 : 0x0aa4, - 0x2007 : 0x0aa5, - 0x2008 : 0x0aa6, - 0x2009 : 0x0aa7, - 0x200A : 0x0aa8, - 0x2014 : 0x0aa9, - 0x2013 : 0x0aaa, - 0x2026 : 0x0aae, - 0x2025 : 0x0aaf, - 0x2153 : 0x0ab0, - 0x2154 : 0x0ab1, - 0x2155 : 0x0ab2, - 0x2156 : 0x0ab3, - 0x2157 : 0x0ab4, - 0x2158 : 0x0ab5, - 0x2159 : 0x0ab6, - 0x215A : 0x0ab7, - 0x2105 : 0x0ab8, - 0x2012 : 0x0abb, - 0x215B : 0x0ac3, - 0x215C : 0x0ac4, - 0x215D : 0x0ac5, - 0x215E : 0x0ac6, - 0x2122 : 0x0ac9, - 0x2018 : 0x0ad0, - 0x2019 : 0x0ad1, - 0x201C : 0x0ad2, - 0x201D : 0x0ad3, - 0x211E : 0x0ad4, - 0x2032 : 0x0ad6, - 0x2033 : 0x0ad7, - 0x271D : 0x0ad9, - 0x2663 : 0x0aec, - 0x2666 : 0x0aed, - 0x2665 : 0x0aee, - 0x2720 : 0x0af0, - 0x2020 : 0x0af1, - 0x2021 : 0x0af2, - 0x2713 : 0x0af3, - 0x2717 : 0x0af4, - 0x266F : 0x0af5, - 0x266D : 0x0af6, - 0x2642 : 0x0af7, - 0x2640 : 0x0af8, - 0x260E : 0x0af9, - 0x2315 : 0x0afa, - 0x2117 : 0x0afb, - 0x2038 : 0x0afc, - 0x201A : 0x0afd, - 0x201E : 0x0afe, - 0x22A4 : 0x0bc2, - 0x230A : 0x0bc4, - 0x2218 : 0x0bca, - 0x2395 : 0x0bcc, - 0x22A5 : 0x0bce, - 0x25CB : 0x0bcf, - 0x2308 : 0x0bd3, - 0x22A3 : 0x0bdc, - 0x22A2 : 0x0bfc, - 0x2017 : 0x0cdf, - 0x05D0 : 0x0ce0, - 0x05D1 : 0x0ce1, - 0x05D2 : 0x0ce2, - 0x05D3 : 0x0ce3, - 0x05D4 : 0x0ce4, - 0x05D5 : 0x0ce5, - 0x05D6 : 0x0ce6, - 0x05D7 : 0x0ce7, - 0x05D8 : 0x0ce8, - 0x05D9 : 0x0ce9, - 0x05DA : 0x0cea, - 0x05DB : 0x0ceb, - 0x05DC : 0x0cec, - 0x05DD : 0x0ced, - 0x05DE : 0x0cee, - 0x05DF : 0x0cef, - 0x05E0 : 0x0cf0, - 0x05E1 : 0x0cf1, - 0x05E2 : 0x0cf2, - 0x05E3 : 0x0cf3, - 0x05E4 : 0x0cf4, - 0x05E5 : 0x0cf5, - 0x05E6 : 0x0cf6, - 0x05E7 : 0x0cf7, - 0x05E8 : 0x0cf8, - 0x05E9 : 0x0cf9, - 0x05EA : 0x0cfa, - 0x0E01 : 0x0da1, - 0x0E02 : 0x0da2, - 0x0E03 : 0x0da3, - 0x0E04 : 0x0da4, - 0x0E05 : 0x0da5, - 0x0E06 : 0x0da6, - 0x0E07 : 0x0da7, - 0x0E08 : 0x0da8, - 0x0E09 : 0x0da9, - 0x0E0A : 0x0daa, - 0x0E0B : 0x0dab, - 0x0E0C : 0x0dac, - 0x0E0D : 0x0dad, - 0x0E0E : 0x0dae, - 0x0E0F : 0x0daf, - 0x0E10 : 0x0db0, - 0x0E11 : 0x0db1, - 0x0E12 : 0x0db2, - 0x0E13 : 0x0db3, - 0x0E14 : 0x0db4, - 0x0E15 : 0x0db5, - 0x0E16 : 0x0db6, - 0x0E17 : 0x0db7, - 0x0E18 : 0x0db8, - 0x0E19 : 0x0db9, - 0x0E1A : 0x0dba, - 0x0E1B : 0x0dbb, - 0x0E1C : 0x0dbc, - 0x0E1D : 0x0dbd, - 0x0E1E : 0x0dbe, - 0x0E1F : 0x0dbf, - 0x0E20 : 0x0dc0, - 0x0E21 : 0x0dc1, - 0x0E22 : 0x0dc2, - 0x0E23 : 0x0dc3, - 0x0E24 : 0x0dc4, - 0x0E25 : 0x0dc5, - 0x0E26 : 0x0dc6, - 0x0E27 : 0x0dc7, - 0x0E28 : 0x0dc8, - 0x0E29 : 0x0dc9, - 0x0E2A : 0x0dca, - 0x0E2B : 0x0dcb, - 0x0E2C : 0x0dcc, - 0x0E2D : 0x0dcd, - 0x0E2E : 0x0dce, - 0x0E2F : 0x0dcf, - 0x0E30 : 0x0dd0, - 0x0E31 : 0x0dd1, - 0x0E32 : 0x0dd2, - 0x0E33 : 0x0dd3, - 0x0E34 : 0x0dd4, - 0x0E35 : 0x0dd5, - 0x0E36 : 0x0dd6, - 0x0E37 : 0x0dd7, - 0x0E38 : 0x0dd8, - 0x0E39 : 0x0dd9, - 0x0E3A : 0x0dda, - 0x0E3F : 0x0ddf, - 0x0E40 : 0x0de0, - 0x0E41 : 0x0de1, - 0x0E42 : 0x0de2, - 0x0E43 : 0x0de3, - 0x0E44 : 0x0de4, - 0x0E45 : 0x0de5, - 0x0E46 : 0x0de6, - 0x0E47 : 0x0de7, - 0x0E48 : 0x0de8, - 0x0E49 : 0x0de9, - 0x0E4A : 0x0dea, - 0x0E4B : 0x0deb, - 0x0E4C : 0x0dec, - 0x0E4D : 0x0ded, - 0x0E50 : 0x0df0, - 0x0E51 : 0x0df1, - 0x0E52 : 0x0df2, - 0x0E53 : 0x0df3, - 0x0E54 : 0x0df4, - 0x0E55 : 0x0df5, - 0x0E56 : 0x0df6, - 0x0E57 : 0x0df7, - 0x0E58 : 0x0df8, - 0x0E59 : 0x0df9, - 0x0587 : 0x1000587, - 0x0589 : 0x1000589, - 0x055D : 0x100055d, - 0x058A : 0x100058a, - 0x055C : 0x100055c, - 0x055B : 0x100055b, - 0x055E : 0x100055e, - 0x0531 : 0x1000531, - 0x0561 : 0x1000561, - 0x0532 : 0x1000532, - 0x0562 : 0x1000562, - 0x0533 : 0x1000533, - 0x0563 : 0x1000563, - 0x0534 : 0x1000534, - 0x0564 : 0x1000564, - 0x0535 : 0x1000535, - 0x0565 : 0x1000565, - 0x0536 : 0x1000536, - 0x0566 : 0x1000566, - 0x0537 : 0x1000537, - 0x0567 : 0x1000567, - 0x0538 : 0x1000538, - 0x0568 : 0x1000568, - 0x0539 : 0x1000539, - 0x0569 : 0x1000569, - 0x053A : 0x100053a, - 0x056A : 0x100056a, - 0x053B : 0x100053b, - 0x056B : 0x100056b, - 0x053C : 0x100053c, - 0x056C : 0x100056c, - 0x053D : 0x100053d, - 0x056D : 0x100056d, - 0x053E : 0x100053e, - 0x056E : 0x100056e, - 0x053F : 0x100053f, - 0x056F : 0x100056f, - 0x0540 : 0x1000540, - 0x0570 : 0x1000570, - 0x0541 : 0x1000541, - 0x0571 : 0x1000571, - 0x0542 : 0x1000542, - 0x0572 : 0x1000572, - 0x0543 : 0x1000543, - 0x0573 : 0x1000573, - 0x0544 : 0x1000544, - 0x0574 : 0x1000574, - 0x0545 : 0x1000545, - 0x0575 : 0x1000575, - 0x0546 : 0x1000546, - 0x0576 : 0x1000576, - 0x0547 : 0x1000547, - 0x0577 : 0x1000577, - 0x0548 : 0x1000548, - 0x0578 : 0x1000578, - 0x0549 : 0x1000549, - 0x0579 : 0x1000579, - 0x054A : 0x100054a, - 0x057A : 0x100057a, - 0x054B : 0x100054b, - 0x057B : 0x100057b, - 0x054C : 0x100054c, - 0x057C : 0x100057c, - 0x054D : 0x100054d, - 0x057D : 0x100057d, - 0x054E : 0x100054e, - 0x057E : 0x100057e, - 0x054F : 0x100054f, - 0x057F : 0x100057f, - 0x0550 : 0x1000550, - 0x0580 : 0x1000580, - 0x0551 : 0x1000551, - 0x0581 : 0x1000581, - 0x0552 : 0x1000552, - 0x0582 : 0x1000582, - 0x0553 : 0x1000553, - 0x0583 : 0x1000583, - 0x0554 : 0x1000554, - 0x0584 : 0x1000584, - 0x0555 : 0x1000555, - 0x0585 : 0x1000585, - 0x0556 : 0x1000556, - 0x0586 : 0x1000586, - 0x055A : 0x100055a, - 0x10D0 : 0x10010d0, - 0x10D1 : 0x10010d1, - 0x10D2 : 0x10010d2, - 0x10D3 : 0x10010d3, - 0x10D4 : 0x10010d4, - 0x10D5 : 0x10010d5, - 0x10D6 : 0x10010d6, - 0x10D7 : 0x10010d7, - 0x10D8 : 0x10010d8, - 0x10D9 : 0x10010d9, - 0x10DA : 0x10010da, - 0x10DB : 0x10010db, - 0x10DC : 0x10010dc, - 0x10DD : 0x10010dd, - 0x10DE : 0x10010de, - 0x10DF : 0x10010df, - 0x10E0 : 0x10010e0, - 0x10E1 : 0x10010e1, - 0x10E2 : 0x10010e2, - 0x10E3 : 0x10010e3, - 0x10E4 : 0x10010e4, - 0x10E5 : 0x10010e5, - 0x10E6 : 0x10010e6, - 0x10E7 : 0x10010e7, - 0x10E8 : 0x10010e8, - 0x10E9 : 0x10010e9, - 0x10EA : 0x10010ea, - 0x10EB : 0x10010eb, - 0x10EC : 0x10010ec, - 0x10ED : 0x10010ed, - 0x10EE : 0x10010ee, - 0x10EF : 0x10010ef, - 0x10F0 : 0x10010f0, - 0x10F1 : 0x10010f1, - 0x10F2 : 0x10010f2, - 0x10F3 : 0x10010f3, - 0x10F4 : 0x10010f4, - 0x10F5 : 0x10010f5, - 0x10F6 : 0x10010f6, - 0x1E8A : 0x1001e8a, - 0x012C : 0x100012c, - 0x01B5 : 0x10001b5, - 0x01E6 : 0x10001e6, - 0x01D2 : 0x10001d1, - 0x019F : 0x100019f, - 0x1E8B : 0x1001e8b, - 0x012D : 0x100012d, - 0x01B6 : 0x10001b6, - 0x01E7 : 0x10001e7, - 0x01D2 : 0x10001d2, - 0x0275 : 0x1000275, - 0x018F : 0x100018f, - 0x0259 : 0x1000259, - 0x1E36 : 0x1001e36, - 0x1E37 : 0x1001e37, - 0x1EA0 : 0x1001ea0, - 0x1EA1 : 0x1001ea1, - 0x1EA2 : 0x1001ea2, - 0x1EA3 : 0x1001ea3, - 0x1EA4 : 0x1001ea4, - 0x1EA5 : 0x1001ea5, - 0x1EA6 : 0x1001ea6, - 0x1EA7 : 0x1001ea7, - 0x1EA8 : 0x1001ea8, - 0x1EA9 : 0x1001ea9, - 0x1EAA : 0x1001eaa, - 0x1EAB : 0x1001eab, - 0x1EAC : 0x1001eac, - 0x1EAD : 0x1001ead, - 0x1EAE : 0x1001eae, - 0x1EAF : 0x1001eaf, - 0x1EB0 : 0x1001eb0, - 0x1EB1 : 0x1001eb1, - 0x1EB2 : 0x1001eb2, - 0x1EB3 : 0x1001eb3, - 0x1EB4 : 0x1001eb4, - 0x1EB5 : 0x1001eb5, - 0x1EB6 : 0x1001eb6, - 0x1EB7 : 0x1001eb7, - 0x1EB8 : 0x1001eb8, - 0x1EB9 : 0x1001eb9, - 0x1EBA : 0x1001eba, - 0x1EBB : 0x1001ebb, - 0x1EBC : 0x1001ebc, - 0x1EBD : 0x1001ebd, - 0x1EBE : 0x1001ebe, - 0x1EBF : 0x1001ebf, - 0x1EC0 : 0x1001ec0, - 0x1EC1 : 0x1001ec1, - 0x1EC2 : 0x1001ec2, - 0x1EC3 : 0x1001ec3, - 0x1EC4 : 0x1001ec4, - 0x1EC5 : 0x1001ec5, - 0x1EC6 : 0x1001ec6, - 0x1EC7 : 0x1001ec7, - 0x1EC8 : 0x1001ec8, - 0x1EC9 : 0x1001ec9, - 0x1ECA : 0x1001eca, - 0x1ECB : 0x1001ecb, - 0x1ECC : 0x1001ecc, - 0x1ECD : 0x1001ecd, - 0x1ECE : 0x1001ece, - 0x1ECF : 0x1001ecf, - 0x1ED0 : 0x1001ed0, - 0x1ED1 : 0x1001ed1, - 0x1ED2 : 0x1001ed2, - 0x1ED3 : 0x1001ed3, - 0x1ED4 : 0x1001ed4, - 0x1ED5 : 0x1001ed5, - 0x1ED6 : 0x1001ed6, - 0x1ED7 : 0x1001ed7, - 0x1ED8 : 0x1001ed8, - 0x1ED9 : 0x1001ed9, - 0x1EDA : 0x1001eda, - 0x1EDB : 0x1001edb, - 0x1EDC : 0x1001edc, - 0x1EDD : 0x1001edd, - 0x1EDE : 0x1001ede, - 0x1EDF : 0x1001edf, - 0x1EE0 : 0x1001ee0, - 0x1EE1 : 0x1001ee1, - 0x1EE2 : 0x1001ee2, - 0x1EE3 : 0x1001ee3, - 0x1EE4 : 0x1001ee4, - 0x1EE5 : 0x1001ee5, - 0x1EE6 : 0x1001ee6, - 0x1EE7 : 0x1001ee7, - 0x1EE8 : 0x1001ee8, - 0x1EE9 : 0x1001ee9, - 0x1EEA : 0x1001eea, - 0x1EEB : 0x1001eeb, - 0x1EEC : 0x1001eec, - 0x1EED : 0x1001eed, - 0x1EEE : 0x1001eee, - 0x1EEF : 0x1001eef, - 0x1EF0 : 0x1001ef0, - 0x1EF1 : 0x1001ef1, - 0x1EF4 : 0x1001ef4, - 0x1EF5 : 0x1001ef5, - 0x1EF6 : 0x1001ef6, - 0x1EF7 : 0x1001ef7, - 0x1EF8 : 0x1001ef8, - 0x1EF9 : 0x1001ef9, - 0x01A0 : 0x10001a0, - 0x01A1 : 0x10001a1, - 0x01AF : 0x10001af, - 0x01B0 : 0x10001b0, - 0x20A0 : 0x10020a0, - 0x20A1 : 0x10020a1, - 0x20A2 : 0x10020a2, - 0x20A3 : 0x10020a3, - 0x20A4 : 0x10020a4, - 0x20A5 : 0x10020a5, - 0x20A6 : 0x10020a6, - 0x20A7 : 0x10020a7, - 0x20A8 : 0x10020a8, - 0x20A9 : 0x10020a9, - 0x20AA : 0x10020aa, - 0x20AB : 0x10020ab, - 0x20AC : 0x20ac, - 0x2070 : 0x1002070, - 0x2074 : 0x1002074, - 0x2075 : 0x1002075, - 0x2076 : 0x1002076, - 0x2077 : 0x1002077, - 0x2078 : 0x1002078, - 0x2079 : 0x1002079, - 0x2080 : 0x1002080, - 0x2081 : 0x1002081, - 0x2082 : 0x1002082, - 0x2083 : 0x1002083, - 0x2084 : 0x1002084, - 0x2085 : 0x1002085, - 0x2086 : 0x1002086, - 0x2087 : 0x1002087, - 0x2088 : 0x1002088, - 0x2089 : 0x1002089, - 0x2202 : 0x1002202, - 0x2205 : 0x1002205, - 0x2208 : 0x1002208, - 0x2209 : 0x1002209, - 0x220B : 0x100220B, - 0x221A : 0x100221A, - 0x221B : 0x100221B, - 0x221C : 0x100221C, - 0x222C : 0x100222C, - 0x222D : 0x100222D, - 0x2235 : 0x1002235, - 0x2245 : 0x1002248, - 0x2247 : 0x1002247, - 0x2262 : 0x1002262, - 0x2263 : 0x1002263, - 0x2800 : 0x1002800, - 0x2801 : 0x1002801, - 0x2802 : 0x1002802, - 0x2803 : 0x1002803, - 0x2804 : 0x1002804, - 0x2805 : 0x1002805, - 0x2806 : 0x1002806, - 0x2807 : 0x1002807, - 0x2808 : 0x1002808, - 0x2809 : 0x1002809, - 0x280a : 0x100280a, - 0x280b : 0x100280b, - 0x280c : 0x100280c, - 0x280d : 0x100280d, - 0x280e : 0x100280e, - 0x280f : 0x100280f, - 0x2810 : 0x1002810, - 0x2811 : 0x1002811, - 0x2812 : 0x1002812, - 0x2813 : 0x1002813, - 0x2814 : 0x1002814, - 0x2815 : 0x1002815, - 0x2816 : 0x1002816, - 0x2817 : 0x1002817, - 0x2818 : 0x1002818, - 0x2819 : 0x1002819, - 0x281a : 0x100281a, - 0x281b : 0x100281b, - 0x281c : 0x100281c, - 0x281d : 0x100281d, - 0x281e : 0x100281e, - 0x281f : 0x100281f, - 0x2820 : 0x1002820, - 0x2821 : 0x1002821, - 0x2822 : 0x1002822, - 0x2823 : 0x1002823, - 0x2824 : 0x1002824, - 0x2825 : 0x1002825, - 0x2826 : 0x1002826, - 0x2827 : 0x1002827, - 0x2828 : 0x1002828, - 0x2829 : 0x1002829, - 0x282a : 0x100282a, - 0x282b : 0x100282b, - 0x282c : 0x100282c, - 0x282d : 0x100282d, - 0x282e : 0x100282e, - 0x282f : 0x100282f, - 0x2830 : 0x1002830, - 0x2831 : 0x1002831, - 0x2832 : 0x1002832, - 0x2833 : 0x1002833, - 0x2834 : 0x1002834, - 0x2835 : 0x1002835, - 0x2836 : 0x1002836, - 0x2837 : 0x1002837, - 0x2838 : 0x1002838, - 0x2839 : 0x1002839, - 0x283a : 0x100283a, - 0x283b : 0x100283b, - 0x283c : 0x100283c, - 0x283d : 0x100283d, - 0x283e : 0x100283e, - 0x283f : 0x100283f, - 0x2840 : 0x1002840, - 0x2841 : 0x1002841, - 0x2842 : 0x1002842, - 0x2843 : 0x1002843, - 0x2844 : 0x1002844, - 0x2845 : 0x1002845, - 0x2846 : 0x1002846, - 0x2847 : 0x1002847, - 0x2848 : 0x1002848, - 0x2849 : 0x1002849, - 0x284a : 0x100284a, - 0x284b : 0x100284b, - 0x284c : 0x100284c, - 0x284d : 0x100284d, - 0x284e : 0x100284e, - 0x284f : 0x100284f, - 0x2850 : 0x1002850, - 0x2851 : 0x1002851, - 0x2852 : 0x1002852, - 0x2853 : 0x1002853, - 0x2854 : 0x1002854, - 0x2855 : 0x1002855, - 0x2856 : 0x1002856, - 0x2857 : 0x1002857, - 0x2858 : 0x1002858, - 0x2859 : 0x1002859, - 0x285a : 0x100285a, - 0x285b : 0x100285b, - 0x285c : 0x100285c, - 0x285d : 0x100285d, - 0x285e : 0x100285e, - 0x285f : 0x100285f, - 0x2860 : 0x1002860, - 0x2861 : 0x1002861, - 0x2862 : 0x1002862, - 0x2863 : 0x1002863, - 0x2864 : 0x1002864, - 0x2865 : 0x1002865, - 0x2866 : 0x1002866, - 0x2867 : 0x1002867, - 0x2868 : 0x1002868, - 0x2869 : 0x1002869, - 0x286a : 0x100286a, - 0x286b : 0x100286b, - 0x286c : 0x100286c, - 0x286d : 0x100286d, - 0x286e : 0x100286e, - 0x286f : 0x100286f, - 0x2870 : 0x1002870, - 0x2871 : 0x1002871, - 0x2872 : 0x1002872, - 0x2873 : 0x1002873, - 0x2874 : 0x1002874, - 0x2875 : 0x1002875, - 0x2876 : 0x1002876, - 0x2877 : 0x1002877, - 0x2878 : 0x1002878, - 0x2879 : 0x1002879, - 0x287a : 0x100287a, - 0x287b : 0x100287b, - 0x287c : 0x100287c, - 0x287d : 0x100287d, - 0x287e : 0x100287e, - 0x287f : 0x100287f, - 0x2880 : 0x1002880, - 0x2881 : 0x1002881, - 0x2882 : 0x1002882, - 0x2883 : 0x1002883, - 0x2884 : 0x1002884, - 0x2885 : 0x1002885, - 0x2886 : 0x1002886, - 0x2887 : 0x1002887, - 0x2888 : 0x1002888, - 0x2889 : 0x1002889, - 0x288a : 0x100288a, - 0x288b : 0x100288b, - 0x288c : 0x100288c, - 0x288d : 0x100288d, - 0x288e : 0x100288e, - 0x288f : 0x100288f, - 0x2890 : 0x1002890, - 0x2891 : 0x1002891, - 0x2892 : 0x1002892, - 0x2893 : 0x1002893, - 0x2894 : 0x1002894, - 0x2895 : 0x1002895, - 0x2896 : 0x1002896, - 0x2897 : 0x1002897, - 0x2898 : 0x1002898, - 0x2899 : 0x1002899, - 0x289a : 0x100289a, - 0x289b : 0x100289b, - 0x289c : 0x100289c, - 0x289d : 0x100289d, - 0x289e : 0x100289e, - 0x289f : 0x100289f, - 0x28a0 : 0x10028a0, - 0x28a1 : 0x10028a1, - 0x28a2 : 0x10028a2, - 0x28a3 : 0x10028a3, - 0x28a4 : 0x10028a4, - 0x28a5 : 0x10028a5, - 0x28a6 : 0x10028a6, - 0x28a7 : 0x10028a7, - 0x28a8 : 0x10028a8, - 0x28a9 : 0x10028a9, - 0x28aa : 0x10028aa, - 0x28ab : 0x10028ab, - 0x28ac : 0x10028ac, - 0x28ad : 0x10028ad, - 0x28ae : 0x10028ae, - 0x28af : 0x10028af, - 0x28b0 : 0x10028b0, - 0x28b1 : 0x10028b1, - 0x28b2 : 0x10028b2, - 0x28b3 : 0x10028b3, - 0x28b4 : 0x10028b4, - 0x28b5 : 0x10028b5, - 0x28b6 : 0x10028b6, - 0x28b7 : 0x10028b7, - 0x28b8 : 0x10028b8, - 0x28b9 : 0x10028b9, - 0x28ba : 0x10028ba, - 0x28bb : 0x10028bb, - 0x28bc : 0x10028bc, - 0x28bd : 0x10028bd, - 0x28be : 0x10028be, - 0x28bf : 0x10028bf, - 0x28c0 : 0x10028c0, - 0x28c1 : 0x10028c1, - 0x28c2 : 0x10028c2, - 0x28c3 : 0x10028c3, - 0x28c4 : 0x10028c4, - 0x28c5 : 0x10028c5, - 0x28c6 : 0x10028c6, - 0x28c7 : 0x10028c7, - 0x28c8 : 0x10028c8, - 0x28c9 : 0x10028c9, - 0x28ca : 0x10028ca, - 0x28cb : 0x10028cb, - 0x28cc : 0x10028cc, - 0x28cd : 0x10028cd, - 0x28ce : 0x10028ce, - 0x28cf : 0x10028cf, - 0x28d0 : 0x10028d0, - 0x28d1 : 0x10028d1, - 0x28d2 : 0x10028d2, - 0x28d3 : 0x10028d3, - 0x28d4 : 0x10028d4, - 0x28d5 : 0x10028d5, - 0x28d6 : 0x10028d6, - 0x28d7 : 0x10028d7, - 0x28d8 : 0x10028d8, - 0x28d9 : 0x10028d9, - 0x28da : 0x10028da, - 0x28db : 0x10028db, - 0x28dc : 0x10028dc, - 0x28dd : 0x10028dd, - 0x28de : 0x10028de, - 0x28df : 0x10028df, - 0x28e0 : 0x10028e0, - 0x28e1 : 0x10028e1, - 0x28e2 : 0x10028e2, - 0x28e3 : 0x10028e3, - 0x28e4 : 0x10028e4, - 0x28e5 : 0x10028e5, - 0x28e6 : 0x10028e6, - 0x28e7 : 0x10028e7, - 0x28e8 : 0x10028e8, - 0x28e9 : 0x10028e9, - 0x28ea : 0x10028ea, - 0x28eb : 0x10028eb, - 0x28ec : 0x10028ec, - 0x28ed : 0x10028ed, - 0x28ee : 0x10028ee, - 0x28ef : 0x10028ef, - 0x28f0 : 0x10028f0, - 0x28f1 : 0x10028f1, - 0x28f2 : 0x10028f2, - 0x28f3 : 0x10028f3, - 0x28f4 : 0x10028f4, - 0x28f5 : 0x10028f5, - 0x28f6 : 0x10028f6, - 0x28f7 : 0x10028f7, - 0x28f8 : 0x10028f8, - 0x28f9 : 0x10028f9, - 0x28fa : 0x10028fa, - 0x28fb : 0x10028fb, - 0x28fc : 0x10028fc, - 0x28fd : 0x10028fd, - 0x28fe : 0x10028fe, - 0x28ff : 0x10028ff -}; \ No newline at end of file diff --git a/classes/novnc/include/logo.js b/classes/novnc/include/logo.js deleted file mode 100644 index befa598..0000000 --- a/classes/novnc/include/logo.js +++ /dev/null @@ -1 +0,0 @@ -noVNC_logo = {"width": 640, "height": 435, "data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAoAAAAGzCAYAAAC/y6a9AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAStAAAErQBBHTWggAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7N13fBvlwQfw3522ZMm2vPdIGCFkA4GyoYyGsCmjk+7dQksHL2/H2/dtC4W2tLTlfelu2VA2lEILFCgQIHEGJCQkdjzkLdmWZGvfvX8oOkmJEy/pNO73/Xz44DtLzz2RT7qfnnXC8uXLZUxDlqfdnUYQhIP+bjbPn+5xhypzrmUf6rGzOc5cjzVduXN9/nTPyfRrMt/jzOcY05U5n3L2f95s/34LPW4m/p6FbLp/73xe+5nKnWuZs/07ZOOcnusx5nucbJU727LneuxslDmdTBxn/2NmusyEuZS7kHMxG/XP5Gf3TOVmQzY+u/PhPMnkMcSsH5WIiIiI8goDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHGMAASERERaQwDIBEREZHG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"}; diff --git a/classes/novnc/include/playback.js b/classes/novnc/include/playback.js deleted file mode 100644 index 22a00a3..0000000 --- a/classes/novnc/include/playback.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-3 (see LICENSE.LGPL-3) - */ - -"use strict"; -/*jslint browser: true, white: false */ -/*global Util, VNC_frame_data, finish */ - -var rfb, mode, test_state, frame_idx, frame_length, - iteration, iterations, istart_time, - - // Pre-declarations for jslint - send_array, next_iteration, queue_next_packet, do_packet; - -// Override send_array -send_array = function (arr) { - // Stub out send_array -}; - -next_iteration = function () { - if (iteration === 0) { - frame_length = VNC_frame_data.length; - test_state = 'running'; - } else { - rfb.disconnect(); - } - - if (test_state !== 'running') { return; } - - iteration += 1; - if (iteration > iterations) { - finish(); - return; - } - - frame_idx = 0; - istart_time = (new Date()).getTime(); - rfb.connect('test', 0, "bogus"); - - queue_next_packet(); - -}; - -queue_next_packet = function () { - var frame, foffset, toffset, delay; - if (test_state !== 'running') { return; } - - frame = VNC_frame_data[frame_idx]; - while ((frame_idx < frame_length) && (frame.charAt(0) === "}")) { - //Util.Debug("Send frame " + frame_idx); - frame_idx += 1; - frame = VNC_frame_data[frame_idx]; - } - - if (frame === 'EOF') { - Util.Debug("Finished, found EOF"); - next_iteration(); - return; - } - if (frame_idx >= frame_length) { - Util.Debug("Finished, no more frames"); - next_iteration(); - return; - } - - if (mode === 'realtime') { - foffset = frame.slice(1, frame.indexOf('{', 1)); - toffset = (new Date()).getTime() - istart_time; - delay = foffset - toffset; - if (delay < 1) { - delay = 1; - } - - setTimeout(do_packet, delay); - } else { - setTimeout(do_packet, 1); - } -}; - -do_packet = function () { - //Util.Debug("Processing frame: " + frame_idx); - var frame = VNC_frame_data[frame_idx]; - rfb.recv_message({'data' : frame.slice(frame.indexOf('{', 1) + 1)}); - frame_idx += 1; - - queue_next_packet(); -}; - diff --git a/classes/novnc/include/rfb.js b/classes/novnc/include/rfb.js deleted file mode 100644 index b7aa3f6..0000000 --- a/classes/novnc/include/rfb.js +++ /dev/null @@ -1,1613 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-3 (see LICENSE.txt) - * - * See README.md for usage and integration instructions. - */ - -/*jslint white: false, browser: true, bitwise: false, plusplus: false */ -/*global window, Util, Display, Keyboard, Mouse, Websock, Websock_native, Base64, DES */ - - -function RFB(defaults) { -"use strict"; - -var that = {}, // Public API methods - conf = {}, // Configuration attributes - - // Pre-declare private functions used before definitions (jslint) - init_vars, updateState, fail, handle_message, - init_msg, normal_msg, framebufferUpdate, print_stats, - - pixelFormat, clientEncodings, fbUpdateRequest, fbUpdateRequests, - keyEvent, pointerEvent, clientCutText, - - extract_data_uri, scan_tight_imgQ, - keyPress, mouseButton, mouseMove, - - checkEvents, // Overridable for testing - - - // - // Private RFB namespace variables - // - rfb_host = '', - rfb_port = 5900, - rfb_password = '', - rfb_path = '', - - rfb_state = 'disconnected', - rfb_version = 0, - rfb_max_version= 3.8, - rfb_auth_scheme= '', - - - // In preference order - encodings = [ - ['COPYRECT', 0x01 ], - ['TIGHT_PNG', -260 ], - ['HEXTILE', 0x05 ], - ['RRE', 0x02 ], - ['RAW', 0x00 ], - ['DesktopSize', -223 ], - ['Cursor', -239 ], - - // Psuedo-encoding settings - ['JPEG_quality_lo', -32 ], - //['JPEG_quality_hi', -23 ], - ['compress_lo', -255 ] - //['compress_hi', -247 ] - ], - - encHandlers = {}, - encNames = {}, - encStats = {}, // [rectCnt, rectCntTot] - - ws = null, // Websock object - display = null, // Display object - keyboard = null, // Keyboard input handler object - mouse = null, // Mouse input handler object - sendTimer = null, // Send Queue check timer - connTimer = null, // connection timer - disconnTimer = null, // disconnection timer - msgTimer = null, // queued handle_message timer - - // Frame buffer update state - FBU = { - rects : 0, - subrects : 0, // RRE - lines : 0, // RAW - tiles : 0, // HEXTILE - bytes : 0, - x : 0, - y : 0, - width : 0, - height : 0, - encoding : 0, - subencoding : -1, - background : null, - imgQ : [] // TIGHT_PNG image queue - }, - - fb_Bpp = 4, - fb_depth = 3, - fb_width = 0, - fb_height = 0, - fb_name = "", - - scan_imgQ_rate = 40, // 25 times per second or so - last_req_time = 0, - rre_chunk_sz = 100, - - timing = { - last_fbu : 0, - fbu_total : 0, - fbu_total_cnt : 0, - full_fbu_total : 0, - full_fbu_cnt : 0, - - fbu_rt_start : 0, - fbu_rt_total : 0, - fbu_rt_cnt : 0 - }, - - test_mode = false, - - def_con_timeout = Websock_native ? 2 : 5, - - /* Mouse state */ - mouse_buttonMask = 0, - mouse_arr = [], - viewportDragging = false, - viewportDragPos = {}; - -// Configuration attributes -Util.conf_defaults(conf, that, defaults, [ - ['target', 'wo', 'dom', null, 'VNC display rendering Canvas object'], - ['focusContainer', 'wo', 'dom', document, 'DOM element that captures keyboard input'], - - ['encrypt', 'rw', 'bool', false, 'Use TLS/SSL/wss encryption'], - ['true_color', 'rw', 'bool', true, 'Request true color pixel data'], - ['local_cursor', 'rw', 'bool', false, 'Request locally rendered cursor'], - ['shared', 'rw', 'bool', true, 'Request shared mode'], - - ['connectTimeout', 'rw', 'int', def_con_timeout, 'Time (s) to wait for connection'], - ['disconnectTimeout', 'rw', 'int', 3, 'Time (s) to wait for disconnection'], - - ['viewportDrag', 'rw', 'bool', false, 'Move the viewport on mouse drags'], - - ['check_rate', 'rw', 'int', 217, 'Timing (ms) of send/receive check'], - ['fbu_req_rate', 'rw', 'int', 1413, 'Timing (ms) of frameBufferUpdate requests'], - - // Callback functions - ['onUpdateState', 'rw', 'func', function() { }, - 'onUpdateState(rfb, state, oldstate, statusMsg): RFB state update/change '], - ['onPasswordRequired', 'rw', 'func', function() { }, - 'onPasswordRequired(rfb): VNC password is required '], - ['onClipboard', 'rw', 'func', function() { }, - 'onClipboard(rfb, text): RFB clipboard contents received'], - ['onBell', 'rw', 'func', function() { }, - 'onBell(rfb): RFB Bell message received '], - ['onFBUReceive', 'rw', 'func', function() { }, - 'onFBUReceive(rfb, fbu): RFB FBU received but not yet processed '], - ['onFBUComplete', 'rw', 'func', function() { }, - 'onFBUComplete(rfb, fbu): RFB FBU received and processed '], - - // These callback names are deprecated - ['updateState', 'rw', 'func', function() { }, - 'obsolete, use onUpdateState'], - ['clipboardReceive', 'rw', 'func', function() { }, - 'obsolete, use onClipboard'] - ]); - - -// Override/add some specific configuration getters/setters -that.set_local_cursor = function(cursor) { - if ((!cursor) || (cursor in {'0':1, 'no':1, 'false':1})) { - conf.local_cursor = false; - } else { - if (display.get_cursor_uri()) { - conf.local_cursor = true; - } else { - Util.Warn("Browser does not support local cursor"); - } - } -}; - -// These are fake configuration getters -that.get_display = function() { return display; }; - -that.get_keyboard = function() { return keyboard; }; - -that.get_mouse = function() { return mouse; }; - - - -// -// Setup routines -// - -// Create the public API interface and initialize values that stay -// constant across connect/disconnect -function constructor() { - var i, rmode; - Util.Debug(">> RFB.constructor"); - - // Create lookup tables based encoding number - for (i=0; i < encodings.length; i+=1) { - encHandlers[encodings[i][1]] = encHandlers[encodings[i][0]]; - encNames[encodings[i][1]] = encodings[i][0]; - encStats[encodings[i][1]] = [0, 0]; - } - // Initialize display, mouse, keyboard, and websock - try { - display = new Display({'target': conf.target}); - } catch (exc) { - Util.Error("Display exception: " + exc); - updateState('fatal', "No working Display"); - } - keyboard = new Keyboard({'target': conf.focusContainer, - 'onKeyPress': keyPress}); - mouse = new Mouse({'target': conf.target, - 'onMouseButton': mouseButton, - 'onMouseMove': mouseMove}); - - rmode = display.get_render_mode(); - - ws = new Websock(); - ws.on('message', handle_message); - ws.on('open', function() { - if (rfb_state === "connect") { - updateState('ProtocolVersion', "Starting VNC handshake"); - } else { - fail("Got unexpected WebSockets connection"); - } - }); - ws.on('close', function() { - if (rfb_state === 'disconnect') { - updateState('disconnected', 'VNC disconnected'); - } else if (rfb_state === 'ProtocolVersion') { - fail('Failed to connect to server'); - } else if (rfb_state in {'failed':1, 'disconnected':1}) { - Util.Error("Received onclose while disconnected"); - } else { - fail('Server disconnected'); - } - }); - ws.on('error', function(e) { - fail("WebSock error: " + e); - }); - - - init_vars(); - - /* Check web-socket-js if no builtin WebSocket support */ - if (Websock_native) { - Util.Info("Using native WebSockets"); - updateState('loaded', 'noVNC ready: native WebSockets, ' + rmode); - } else { - Util.Warn("Using web-socket-js bridge. Flash version: " + - Util.Flash.version); - if ((! Util.Flash) || - (Util.Flash.version < 9)) { - updateState('fatal', "WebSockets or Adobe Flash<\/a> is required"); - } else if (document.location.href.substr(0, 7) === "file://") { - updateState('fatal', - "'file://' URL is incompatible with Adobe Flash"); - } else { - updateState('loaded', 'noVNC ready: WebSockets emulation, ' + rmode); - } - } - - Util.Debug("<< RFB.constructor"); - return that; // Return the public API interface -} - -function connect() { - Util.Debug(">> RFB.connect"); - - var uri = ""; - if (conf.encrypt) { - uri = "wss://"; - } else { - uri = "ws://"; - } - uri += rfb_host + ":" + rfb_port + "/" + rfb_path; - Util.Info("connecting to " + uri); - ws.open(uri); - - Util.Debug("<< RFB.connect"); -} - -// Initialize variables that are reset before each connection -init_vars = function() { - var i; - - /* Reset state */ - ws.init(); - - FBU.rects = 0; - FBU.subrects = 0; // RRE and HEXTILE - FBU.lines = 0; // RAW - FBU.tiles = 0; // HEXTILE - FBU.imgQ = []; // TIGHT_PNG image queue - mouse_buttonMask = 0; - mouse_arr = []; - - // Clear the per connection encoding stats - for (i=0; i < encodings.length; i+=1) { - encStats[encodings[i][1]][0] = 0; - } -}; - -// Print statistics -print_stats = function() { - var i, s; - Util.Info("Encoding stats for this connection:"); - for (i=0; i < encodings.length; i+=1) { - s = encStats[encodings[i][1]]; - if ((s[0] + s[1]) > 0) { - Util.Info(" " + encodings[i][0] + ": " + - s[0] + " rects"); - } - } - Util.Info("Encoding stats since page load:"); - for (i=0; i < encodings.length; i+=1) { - s = encStats[encodings[i][1]]; - if ((s[0] + s[1]) > 0) { - Util.Info(" " + encodings[i][0] + ": " + - s[1] + " rects"); - } - } -}; - -// -// Utility routines -// - - -/* - * Page states: - * loaded - page load, equivalent to disconnected - * disconnected - idle state - * connect - starting to connect (to ProtocolVersion) - * normal - connected - * disconnect - starting to disconnect - * failed - abnormal disconnect - * fatal - failed to load page, or fatal error - * - * RFB protocol initialization states: - * ProtocolVersion - * Security - * Authentication - * password - waiting for password, not part of RFB - * SecurityResult - * ClientInitialization - not triggered by server message - * ServerInitialization (to normal) - */ -updateState = function(state, statusMsg) { - var func, cmsg, oldstate = rfb_state; - - if (state === oldstate) { - /* Already here, ignore */ - Util.Debug("Already in state '" + state + "', ignoring."); - return; - } - - /* - * These are disconnected states. A previous connect may - * asynchronously cause a connection so make sure we are closed. - */ - if (state in {'disconnected':1, 'loaded':1, 'connect':1, - 'disconnect':1, 'failed':1, 'fatal':1}) { - if (sendTimer) { - clearInterval(sendTimer); - sendTimer = null; - } - - if (msgTimer) { - clearInterval(msgTimer); - msgTimer = null; - } - - if (display && display.get_context()) { - keyboard.ungrab(); - mouse.ungrab(); - display.defaultCursor(); - if ((Util.get_logging() !== 'debug') || - (state === 'loaded')) { - // Show noVNC logo on load and when disconnected if - // debug is off - display.clear(); - } - } - - ws.close(); - } - - if (oldstate === 'fatal') { - Util.Error("Fatal error, cannot continue"); - } - - if ((state === 'failed') || (state === 'fatal')) { - func = Util.Error; - } else { - func = Util.Warn; - } - - if ((oldstate === 'failed') && (state === 'disconnected')) { - // Do disconnect action, but stay in failed state. - rfb_state = 'failed'; - } else { - rfb_state = state; - } - - cmsg = typeof(statusMsg) !== 'undefined' ? (" Msg: " + statusMsg) : ""; - func("New state '" + rfb_state + "', was '" + oldstate + "'." + cmsg); - - if (connTimer && (rfb_state !== 'connect')) { - Util.Debug("Clearing connect timer"); - clearInterval(connTimer); - connTimer = null; - } - - if (disconnTimer && (rfb_state !== 'disconnect')) { - Util.Debug("Clearing disconnect timer"); - clearInterval(disconnTimer); - disconnTimer = null; - } - - switch (state) { - case 'normal': - if ((oldstate === 'disconnected') || (oldstate === 'failed')) { - Util.Error("Invalid transition from 'disconnected' or 'failed' to 'normal'"); - } - - break; - - - case 'connect': - - connTimer = setTimeout(function () { - fail("Connect timeout"); - }, conf.connectTimeout * 1000); - - init_vars(); - connect(); - - // WebSocket.onopen transitions to 'ProtocolVersion' - break; - - - case 'disconnect': - - if (! test_mode) { - disconnTimer = setTimeout(function () { - fail("Disconnect timeout"); - }, conf.disconnectTimeout * 1000); - } - - print_stats(); - - // WebSocket.onclose transitions to 'disconnected' - break; - - - case 'failed': - if (oldstate === 'disconnected') { - Util.Error("Invalid transition from 'disconnected' to 'failed'"); - } - if (oldstate === 'normal') { - Util.Error("Error while connected."); - } - if (oldstate === 'init') { - Util.Error("Error while initializing."); - } - - // Make sure we transition to disconnected - setTimeout(function() { updateState('disconnected'); }, 50); - - break; - - - default: - // No state change action to take - - } - - if ((oldstate === 'failed') && (state === 'disconnected')) { - // Leave the failed message - conf.updateState(that, state, oldstate); // Obsolete - conf.onUpdateState(that, state, oldstate); - } else { - conf.updateState(that, state, oldstate, statusMsg); // Obsolete - conf.onUpdateState(that, state, oldstate, statusMsg); - } -}; - -fail = function(msg) { - updateState('failed', msg); - return false; -}; - -handle_message = function() { - //Util.Debug(">> handle_message ws.rQlen(): " + ws.rQlen()); - //Util.Debug("ws.rQslice(0,20): " + ws.rQslice(0,20) + " (" + ws.rQlen() + ")"); - if (ws.rQlen() === 0) { - Util.Warn("handle_message called on empty receive queue"); - return; - } - switch (rfb_state) { - case 'disconnected': - case 'failed': - Util.Error("Got data while disconnected"); - break; - case 'normal': - if (normal_msg() && ws.rQlen() > 0) { - // true means we can continue processing - // Give other events a chance to run - if (msgTimer === null) { - Util.Debug("More data to process, creating timer"); - msgTimer = setTimeout(function () { - msgTimer = null; - handle_message(); - }, 10); - } else { - Util.Debug("More data to process, existing timer"); - } - } - break; - default: - init_msg(); - break; - } -}; - - -function genDES(password, challenge) { - var i, passwd = []; - for (i=0; i < password.length; i += 1) { - passwd.push(password.charCodeAt(i)); - } - return (new DES(passwd)).encrypt(challenge); -} - -function flushClient() { - if (mouse_arr.length > 0) { - //send(mouse_arr.concat(fbUpdateRequests())); - ws.send(mouse_arr); - setTimeout(function() { - ws.send(fbUpdateRequests()); - }, 50); - - mouse_arr = []; - return true; - } else { - return false; - } -} - -// overridable for testing -checkEvents = function() { - var now; - if (rfb_state === 'normal' && !viewportDragging) { - if (! flushClient()) { - now = new Date().getTime(); - if (now > last_req_time + conf.fbu_req_rate) { - last_req_time = now; - ws.send(fbUpdateRequests()); - } - } - } - setTimeout(checkEvents, conf.check_rate); -}; - -keyPress = function(keysym, down) { - var arr; - arr = keyEvent(keysym, down); - arr = arr.concat(fbUpdateRequests()); - ws.send(arr); -}; - -mouseButton = function(x, y, down, bmask) { - if (down) { - mouse_buttonMask |= bmask; - } else { - mouse_buttonMask ^= bmask; - } - - if (conf.viewportDrag) { - if (down && !viewportDragging) { - viewportDragging = true; - viewportDragPos = {'x': x, 'y': y}; - - // Skip sending mouse events - return; - } else { - viewportDragging = false; - } - } - - mouse_arr = mouse_arr.concat( - pointerEvent(display.absX(x), display.absY(y)) ); - flushClient(); -}; - -mouseMove = function(x, y) { - //Util.Debug('>> mouseMove ' + x + "," + y); - var deltaX, deltaY; - - if (viewportDragging) { - //deltaX = x - viewportDragPos.x; // drag viewport - deltaX = viewportDragPos.x - x; // drag frame buffer - //deltaY = y - viewportDragPos.y; // drag viewport - deltaY = viewportDragPos.y - y; // drag frame buffer - viewportDragPos = {'x': x, 'y': y}; - - display.viewportChange(deltaX, deltaY); - - // Skip sending mouse events - return; - } - - mouse_arr = mouse_arr.concat( - pointerEvent(display.absX(x), display.absY(y)) ); -}; - - -// -// Server message handlers -// - -// RFB/VNC initialisation message handler -init_msg = function() { - //Util.Debug(">> init_msg [rfb_state '" + rfb_state + "']"); - - var strlen, reason, length, sversion, cversion, - i, types, num_types, challenge, response, bpp, depth, - big_endian, red_max, green_max, blue_max, red_shift, - green_shift, blue_shift, true_color, name_length; - - //Util.Debug("ws.rQ (" + ws.rQlen() + ") " + ws.rQslice(0)); - switch (rfb_state) { - - case 'ProtocolVersion' : - if (ws.rQlen() < 12) { - return fail("Incomplete protocol version"); - } - sversion = ws.rQshiftStr(12).substr(4,7); - Util.Info("Server ProtocolVersion: " + sversion); - switch (sversion) { - case "003.003": rfb_version = 3.3; break; - case "003.006": rfb_version = 3.3; break; // UltraVNC - case "003.007": rfb_version = 3.7; break; - case "003.008": rfb_version = 3.8; break; - default: - return fail("Invalid server version " + sversion); - } - if (rfb_version > rfb_max_version) { - rfb_version = rfb_max_version; - } - - if (! test_mode) { - sendTimer = setInterval(function() { - // Send updates either at a rate of one update - // every 50ms, or whatever slower rate the network - // can handle. - ws.flush(); - }, 50); - } - - cversion = "00" + parseInt(rfb_version,10) + - ".00" + ((rfb_version * 10) % 10); - ws.send_string("RFB " + cversion + "\n"); - updateState('Security', "Sent ProtocolVersion: " + cversion); - break; - - case 'Security' : - if (rfb_version >= 3.7) { - // Server sends supported list, client decides - num_types = ws.rQshift8(); - if (ws.rQwait("security type", num_types, 1)) { return false; } - if (num_types === 0) { - strlen = ws.rQshift32(); - reason = ws.rQshiftStr(strlen); - return fail("Security failure: " + reason); - } - rfb_auth_scheme = 0; - types = ws.rQshiftBytes(num_types); - Util.Debug("Server security types: " + types); - for (i=0; i < types.length; i+=1) { - if ((types[i] > rfb_auth_scheme) && (types[i] < 3)) { - rfb_auth_scheme = types[i]; - } - } - if (rfb_auth_scheme === 0) { - return fail("Unsupported security types: " + types); - } - - ws.send([rfb_auth_scheme]); - } else { - // Server decides - if (ws.rQwait("security scheme", 4)) { return false; } - rfb_auth_scheme = ws.rQshift32(); - } - updateState('Authentication', - "Authenticating using scheme: " + rfb_auth_scheme); - init_msg(); // Recursive fallthrough (workaround JSLint complaint) - break; - - // Triggered by fallthough, not by server message - case 'Authentication' : - //Util.Debug("Security auth scheme: " + rfb_auth_scheme); - switch (rfb_auth_scheme) { - case 0: // connection failed - if (ws.rQwait("auth reason", 4)) { return false; } - strlen = ws.rQshift32(); - reason = ws.rQshiftStr(strlen); - return fail("Auth failure: " + reason); - case 1: // no authentication - if (rfb_version >= 3.8) { - updateState('SecurityResult'); - return; - } - // Fall through to ClientInitialisation - break; - case 2: // VNC authentication - if (rfb_password.length === 0) { - // Notify via both callbacks since it is kind of - // a RFB state change and a UI interface issue. - updateState('password', "Password Required"); - conf.onPasswordRequired(that); - return; - } - if (ws.rQwait("auth challenge", 16)) { return false; } - challenge = ws.rQshiftBytes(16); - //Util.Debug("Password: " + rfb_password); - //Util.Debug("Challenge: " + challenge + - // " (" + challenge.length + ")"); - response = genDES(rfb_password, challenge); - //Util.Debug("Response: " + response + - // " (" + response.length + ")"); - - //Util.Debug("Sending DES encrypted auth response"); - ws.send(response); - updateState('SecurityResult'); - return; - default: - fail("Unsupported auth scheme: " + rfb_auth_scheme); - return; - } - updateState('ClientInitialisation', "No auth required"); - init_msg(); // Recursive fallthrough (workaround JSLint complaint) - break; - - case 'SecurityResult' : - if (ws.rQwait("VNC auth response ", 4)) { return false; } - switch (ws.rQshift32()) { - case 0: // OK - // Fall through to ClientInitialisation - break; - case 1: // failed - if (rfb_version >= 3.8) { - length = ws.rQshift32(); - if (ws.rQwait("SecurityResult reason", length, 8)) { - return false; - } - reason = ws.rQshiftStr(length); - fail(reason); - } else { - fail("Authentication failed"); - } - return; - case 2: // too-many - return fail("Too many auth attempts"); - } - updateState('ClientInitialisation', "Authentication OK"); - init_msg(); // Recursive fallthrough (workaround JSLint complaint) - break; - - // Triggered by fallthough, not by server message - case 'ClientInitialisation' : - ws.send([conf.shared ? 1 : 0]); // ClientInitialisation - updateState('ServerInitialisation', "Authentication OK"); - break; - - case 'ServerInitialisation' : - if (ws.rQwait("server initialization", 24)) { return false; } - - /* Screen size */ - fb_width = ws.rQshift16(); - fb_height = ws.rQshift16(); - - /* PIXEL_FORMAT */ - bpp = ws.rQshift8(); - depth = ws.rQshift8(); - big_endian = ws.rQshift8(); - true_color = ws.rQshift8(); - - red_max = ws.rQshift16(); - green_max = ws.rQshift16(); - blue_max = ws.rQshift16(); - red_shift = ws.rQshift8(); - green_shift = ws.rQshift8(); - blue_shift = ws.rQshift8(); - ws.rQshiftStr(3); // padding - - Util.Info("Screen: " + fb_width + "x" + fb_height + - ", bpp: " + bpp + ", depth: " + depth + - ", big_endian: " + big_endian + - ", true_color: " + true_color + - ", red_max: " + red_max + - ", green_max: " + green_max + - ", blue_max: " + blue_max + - ", red_shift: " + red_shift + - ", green_shift: " + green_shift + - ", blue_shift: " + blue_shift); - - /* Connection name/title */ - name_length = ws.rQshift32(); - fb_name = ws.rQshiftStr(name_length); - - display.set_true_color(conf.true_color); - display.resize(fb_width, fb_height); - keyboard.grab(); - mouse.grab(); - - if (conf.true_color) { - fb_Bpp = 4; - fb_depth = 3; - } else { - fb_Bpp = 1; - fb_depth = 1; - } - - response = pixelFormat(); - response = response.concat(clientEncodings()); - response = response.concat(fbUpdateRequests()); - timing.fbu_rt_start = (new Date()).getTime(); - ws.send(response); - - /* Start pushing/polling */ - setTimeout(checkEvents, conf.check_rate); - setTimeout(scan_tight_imgQ, scan_imgQ_rate); - - if (conf.encrypt) { - updateState('normal', "Connected (encrypted) to: " + fb_name); - } else { - updateState('normal', "Connected (unencrypted) to: " + fb_name); - } - break; - } - //Util.Debug("<< init_msg"); -}; - - -/* Normal RFB/VNC server message handler */ -normal_msg = function() { - //Util.Debug(">> normal_msg"); - - var ret = true, msg_type, length, text, - c, first_colour, num_colours, red, green, blue; - - if (FBU.rects > 0) { - msg_type = 0; - } else { - msg_type = ws.rQshift8(); - } - switch (msg_type) { - case 0: // FramebufferUpdate - ret = framebufferUpdate(); // false means need more data - break; - case 1: // SetColourMapEntries - Util.Debug("SetColourMapEntries"); - ws.rQshift8(); // Padding - first_colour = ws.rQshift16(); // First colour - num_colours = ws.rQshift16(); - for (c=0; c < num_colours; c+=1) { - red = ws.rQshift16(); - //Util.Debug("red before: " + red); - red = parseInt(red / 256, 10); - //Util.Debug("red after: " + red); - green = parseInt(ws.rQshift16() / 256, 10); - blue = parseInt(ws.rQshift16() / 256, 10); - display.set_colourMap([red, green, blue], first_colour + c); - } - Util.Debug("colourMap: " + display.get_colourMap()); - Util.Info("Registered " + num_colours + " colourMap entries"); - //Util.Debug("colourMap: " + display.get_colourMap()); - break; - case 2: // Bell - Util.Debug("Bell"); - conf.onBell(that); - break; - case 3: // ServerCutText - Util.Debug("ServerCutText"); - if (ws.rQwait("ServerCutText header", 7, 1)) { return false; } - ws.rQshiftBytes(3); // Padding - length = ws.rQshift32(); - if (ws.rQwait("ServerCutText", length, 8)) { return false; } - - text = ws.rQshiftStr(length); - conf.clipboardReceive(that, text); // Obsolete - conf.onClipboard(that, text); - break; - default: - fail("Disconnected: illegal server message type " + msg_type); - Util.Debug("ws.rQslice(0,30):" + ws.rQslice(0,30)); - break; - } - //Util.Debug("<< normal_msg"); - return ret; -}; - -framebufferUpdate = function() { - var now, hdr, fbu_rt_diff, ret = true; - - if (FBU.rects === 0) { - //Util.Debug("New FBU: ws.rQslice(0,20): " + ws.rQslice(0,20)); - if (ws.rQwait("FBU header", 3)) { - ws.rQunshift8(0); // FBU msg_type - return false; - } - ws.rQshift8(); // padding - FBU.rects = ws.rQshift16(); - //Util.Debug("FramebufferUpdate, rects:" + FBU.rects); - FBU.bytes = 0; - timing.cur_fbu = 0; - if (timing.fbu_rt_start > 0) { - now = (new Date()).getTime(); - Util.Info("First FBU latency: " + (now - timing.fbu_rt_start)); - } - } - - while (FBU.rects > 0) { - if (rfb_state !== "normal") { - return false; - } - if (ws.rQwait("FBU", FBU.bytes)) { return false; } - if (FBU.bytes === 0) { - if (ws.rQwait("rect header", 12)) { return false; } - /* New FramebufferUpdate */ - - hdr = ws.rQshiftBytes(12); - FBU.x = (hdr[0] << 8) + hdr[1]; - FBU.y = (hdr[2] << 8) + hdr[3]; - FBU.width = (hdr[4] << 8) + hdr[5]; - FBU.height = (hdr[6] << 8) + hdr[7]; - FBU.encoding = parseInt((hdr[8] << 24) + (hdr[9] << 16) + - (hdr[10] << 8) + hdr[11], 10); - - conf.onFBUReceive(that, - {'x': FBU.x, 'y': FBU.y, - 'width': FBU.width, 'height': FBU.height, - 'encoding': FBU.encoding, - 'encodingName': encNames[FBU.encoding]}); - - if (encNames[FBU.encoding]) { - // Debug: - /* - var msg = "FramebufferUpdate rects:" + FBU.rects; - msg += " x: " + FBU.x + " y: " + FBU.y; - msg += " width: " + FBU.width + " height: " + FBU.height; - msg += " encoding:" + FBU.encoding; - msg += "(" + encNames[FBU.encoding] + ")"; - msg += ", ws.rQlen(): " + ws.rQlen(); - Util.Debug(msg); - */ - } else { - fail("Disconnected: unsupported encoding " + - FBU.encoding); - return false; - } - } - - timing.last_fbu = (new Date()).getTime(); - - ret = encHandlers[FBU.encoding](); - - now = (new Date()).getTime(); - timing.cur_fbu += (now - timing.last_fbu); - - if (ret) { - encStats[FBU.encoding][0] += 1; - encStats[FBU.encoding][1] += 1; - } - - if (FBU.rects === 0) { - if (((FBU.width === fb_width) && - (FBU.height === fb_height)) || - (timing.fbu_rt_start > 0)) { - timing.full_fbu_total += timing.cur_fbu; - timing.full_fbu_cnt += 1; - Util.Info("Timing of full FBU, cur: " + - timing.cur_fbu + ", total: " + - timing.full_fbu_total + ", cnt: " + - timing.full_fbu_cnt + ", avg: " + - (timing.full_fbu_total / - timing.full_fbu_cnt)); - } - if (timing.fbu_rt_start > 0) { - fbu_rt_diff = now - timing.fbu_rt_start; - timing.fbu_rt_total += fbu_rt_diff; - timing.fbu_rt_cnt += 1; - Util.Info("full FBU round-trip, cur: " + - fbu_rt_diff + ", total: " + - timing.fbu_rt_total + ", cnt: " + - timing.fbu_rt_cnt + ", avg: " + - (timing.fbu_rt_total / - timing.fbu_rt_cnt)); - timing.fbu_rt_start = 0; - } - } - if (! ret) { - return ret; // false ret means need more data - } - } - - conf.onFBUComplete(that, - {'x': FBU.x, 'y': FBU.y, - 'width': FBU.width, 'height': FBU.height, - 'encoding': FBU.encoding, - 'encodingName': encNames[FBU.encoding]}); - - return true; // We finished this FBU -}; - -// -// FramebufferUpdate encodings -// - -encHandlers.RAW = function display_raw() { - //Util.Debug(">> display_raw (" + ws.rQlen() + " bytes)"); - - var cur_y, cur_height; - - if (FBU.lines === 0) { - FBU.lines = FBU.height; - } - FBU.bytes = FBU.width * fb_Bpp; // At least a line - if (ws.rQwait("RAW", FBU.bytes)) { return false; } - cur_y = FBU.y + (FBU.height - FBU.lines); - cur_height = Math.min(FBU.lines, - Math.floor(ws.rQlen()/(FBU.width * fb_Bpp))); - display.blitImage(FBU.x, cur_y, FBU.width, cur_height, - ws.get_rQ(), ws.get_rQi()); - ws.rQshiftBytes(FBU.width * cur_height * fb_Bpp); - FBU.lines -= cur_height; - - if (FBU.lines > 0) { - FBU.bytes = FBU.width * fb_Bpp; // At least another line - } else { - FBU.rects -= 1; - FBU.bytes = 0; - } - //Util.Debug("<< display_raw (" + ws.rQlen() + " bytes)"); - return true; -}; - -encHandlers.COPYRECT = function display_copy_rect() { - //Util.Debug(">> display_copy_rect"); - - var old_x, old_y; - - if (ws.rQwait("COPYRECT", 4)) { return false; } - old_x = ws.rQshift16(); - old_y = ws.rQshift16(); - display.copyImage(old_x, old_y, FBU.x, FBU.y, FBU.width, FBU.height); - FBU.rects -= 1; - FBU.bytes = 0; - return true; -}; - -encHandlers.RRE = function display_rre() { - //Util.Debug(">> display_rre (" + ws.rQlen() + " bytes)"); - var color, x, y, width, height, chunk; - - if (FBU.subrects === 0) { - if (ws.rQwait("RRE", 4+fb_Bpp)) { return false; } - FBU.subrects = ws.rQshift32(); - color = ws.rQshiftBytes(fb_Bpp); // Background - display.fillRect(FBU.x, FBU.y, FBU.width, FBU.height, color); - } - while ((FBU.subrects > 0) && (ws.rQlen() >= (fb_Bpp + 8))) { - color = ws.rQshiftBytes(fb_Bpp); - x = ws.rQshift16(); - y = ws.rQshift16(); - width = ws.rQshift16(); - height = ws.rQshift16(); - display.fillRect(FBU.x + x, FBU.y + y, width, height, color); - FBU.subrects -= 1; - } - //Util.Debug(" display_rre: rects: " + FBU.rects + - // ", FBU.subrects: " + FBU.subrects); - - if (FBU.subrects > 0) { - chunk = Math.min(rre_chunk_sz, FBU.subrects); - FBU.bytes = (fb_Bpp + 8) * chunk; - } else { - FBU.rects -= 1; - FBU.bytes = 0; - } - //Util.Debug("<< display_rre, FBU.bytes: " + FBU.bytes); - return true; -}; - -encHandlers.HEXTILE = function display_hextile() { - //Util.Debug(">> display_hextile"); - var subencoding, subrects, color, cur_tile, - tile_x, x, w, tile_y, y, h, xy, s, sx, sy, wh, sw, sh, - rQ = ws.get_rQ(), rQi = ws.get_rQi(); - - if (FBU.tiles === 0) { - FBU.tiles_x = Math.ceil(FBU.width/16); - FBU.tiles_y = Math.ceil(FBU.height/16); - FBU.total_tiles = FBU.tiles_x * FBU.tiles_y; - FBU.tiles = FBU.total_tiles; - } - - /* FBU.bytes comes in as 1, ws.rQlen() at least 1 */ - while (FBU.tiles > 0) { - FBU.bytes = 1; - if (ws.rQwait("HEXTILE subencoding", FBU.bytes)) { return false; } - subencoding = rQ[rQi]; // Peek - if (subencoding > 30) { // Raw - fail("Disconnected: illegal hextile subencoding " + subencoding); - //Util.Debug("ws.rQslice(0,30):" + ws.rQslice(0,30)); - return false; - } - subrects = 0; - cur_tile = FBU.total_tiles - FBU.tiles; - tile_x = cur_tile % FBU.tiles_x; - tile_y = Math.floor(cur_tile / FBU.tiles_x); - x = FBU.x + tile_x * 16; - y = FBU.y + tile_y * 16; - w = Math.min(16, (FBU.x + FBU.width) - x); - h = Math.min(16, (FBU.y + FBU.height) - y); - - /* Figure out how much we are expecting */ - if (subencoding & 0x01) { // Raw - //Util.Debug(" Raw subencoding"); - FBU.bytes += w * h * fb_Bpp; - } else { - if (subencoding & 0x02) { // Background - FBU.bytes += fb_Bpp; - } - if (subencoding & 0x04) { // Foreground - FBU.bytes += fb_Bpp; - } - if (subencoding & 0x08) { // AnySubrects - FBU.bytes += 1; // Since we aren't shifting it off - if (ws.rQwait("hextile subrects header", FBU.bytes)) { return false; } - subrects = rQ[rQi + FBU.bytes-1]; // Peek - if (subencoding & 0x10) { // SubrectsColoured - FBU.bytes += subrects * (fb_Bpp + 2); - } else { - FBU.bytes += subrects * 2; - } - } - } - - /* - Util.Debug(" tile:" + cur_tile + "/" + (FBU.total_tiles - 1) + - " (" + tile_x + "," + tile_y + ")" + - " [" + x + "," + y + "]@" + w + "x" + h + - ", subenc:" + subencoding + - "(last: " + FBU.lastsubencoding + "), subrects:" + - subrects + - ", ws.rQlen():" + ws.rQlen() + ", FBU.bytes:" + FBU.bytes + - " last:" + ws.rQslice(FBU.bytes-10, FBU.bytes) + - " next:" + ws.rQslice(FBU.bytes-1, FBU.bytes+10)); - */ - if (ws.rQwait("hextile", FBU.bytes)) { return false; } - - /* We know the encoding and have a whole tile */ - FBU.subencoding = rQ[rQi]; - rQi += 1; - if (FBU.subencoding === 0) { - if (FBU.lastsubencoding & 0x01) { - /* Weird: ignore blanks after RAW */ - Util.Debug(" Ignoring blank after RAW"); - } else { - display.fillRect(x, y, w, h, FBU.background); - } - } else if (FBU.subencoding & 0x01) { // Raw - display.blitImage(x, y, w, h, rQ, rQi); - rQi += FBU.bytes - 1; - } else { - if (FBU.subencoding & 0x02) { // Background - FBU.background = rQ.slice(rQi, rQi + fb_Bpp); - rQi += fb_Bpp; - } - if (FBU.subencoding & 0x04) { // Foreground - FBU.foreground = rQ.slice(rQi, rQi + fb_Bpp); - rQi += fb_Bpp; - } - - display.startTile(x, y, w, h, FBU.background); - if (FBU.subencoding & 0x08) { // AnySubrects - subrects = rQ[rQi]; - rQi += 1; - for (s = 0; s < subrects; s += 1) { - if (FBU.subencoding & 0x10) { // SubrectsColoured - color = rQ.slice(rQi, rQi + fb_Bpp); - rQi += fb_Bpp; - } else { - color = FBU.foreground; - } - xy = rQ[rQi]; - rQi += 1; - sx = (xy >> 4); - sy = (xy & 0x0f); - - wh = rQ[rQi]; - rQi += 1; - sw = (wh >> 4) + 1; - sh = (wh & 0x0f) + 1; - - display.subTile(sx, sy, sw, sh, color); - } - } - display.finishTile(); - } - ws.set_rQi(rQi); - FBU.lastsubencoding = FBU.subencoding; - FBU.bytes = 0; - FBU.tiles -= 1; - } - - if (FBU.tiles === 0) { - FBU.rects -= 1; - } - - //Util.Debug("<< display_hextile"); - return true; -}; - - -encHandlers.TIGHT_PNG = function display_tight_png() { - //Util.Debug(">> display_tight_png"); - var ctl, cmode, clength, getCLength, color, img; - //Util.Debug(" FBU.rects: " + FBU.rects); - //Util.Debug(" starting ws.rQslice(0,20): " + ws.rQslice(0,20) + " (" + ws.rQlen() + ")"); - - FBU.bytes = 1; // compression-control byte - if (ws.rQwait("TIGHT compression-control", FBU.bytes)) { return false; } - - // Get 'compact length' header and data size - getCLength = function (arr) { - var header = 1, data = 0; - data += arr[0] & 0x7f; - if (arr[0] & 0x80) { - header += 1; - data += (arr[1] & 0x7f) << 7; - if (arr[1] & 0x80) { - header += 1; - data += arr[2] << 14; - } - } - return [header, data]; - }; - - ctl = ws.rQpeek8(); - switch (ctl >> 4) { - case 0x08: cmode = "fill"; break; - case 0x09: cmode = "jpeg"; break; - case 0x0A: cmode = "png"; break; - default: throw("Illegal basic compression received, ctl: " + ctl); - } - switch (cmode) { - // fill uses fb_depth because TPIXELs drop the padding byte - case "fill": FBU.bytes += fb_depth; break; // TPIXEL - case "jpeg": FBU.bytes += 3; break; // max clength - case "png": FBU.bytes += 3; break; // max clength - } - - if (ws.rQwait("TIGHT " + cmode, FBU.bytes)) { return false; } - - //Util.Debug(" ws.rQslice(0,20): " + ws.rQslice(0,20) + " (" + ws.rQlen() + ")"); - //Util.Debug(" cmode: " + cmode); - - // Determine FBU.bytes - switch (cmode) { - case "fill": - ws.rQshift8(); // shift off ctl - color = ws.rQshiftBytes(fb_depth); - FBU.imgQ.push({ - 'type': 'fill', - 'img': {'complete': true}, - 'x': FBU.x, - 'y': FBU.y, - 'width': FBU.width, - 'height': FBU.height, - 'color': color}); - break; - case "jpeg": - case "png": - clength = getCLength(ws.rQslice(1, 4)); - FBU.bytes = 1 + clength[0] + clength[1]; // ctl + clength size + jpeg-data - if (ws.rQwait("TIGHT " + cmode, FBU.bytes)) { return false; } - - // We have everything, render it - //Util.Debug(" png, ws.rQlen(): " + ws.rQlen() + ", clength[0]: " + clength[0] + ", clength[1]: " + clength[1]); - ws.rQshiftBytes(1 + clength[0]); // shift off ctl + compact length - img = new Image(); - //img.onload = scan_tight_imgQ; - FBU.imgQ.push({ - 'type': 'img', - 'img': img, - 'x': FBU.x, - 'y': FBU.y}); - img.src = "data:image/" + cmode + - extract_data_uri(ws.rQshiftBytes(clength[1])); - img = null; - break; - } - FBU.bytes = 0; - FBU.rects -= 1; - //Util.Debug(" ending ws.rQslice(0,20): " + ws.rQslice(0,20) + " (" + ws.rQlen() + ")"); - //Util.Debug("<< display_tight_png"); - return true; -}; - -extract_data_uri = function(arr) { - //var i, stra = []; - //for (i=0; i< arr.length; i += 1) { - // stra.push(String.fromCharCode(arr[i])); - //} - //return "," + escape(stra.join('')); - return ";base64," + Base64.encode(arr); -}; - -scan_tight_imgQ = function() { - var data, imgQ, ctx; - ctx = display.get_context(); - if (rfb_state === 'normal') { - imgQ = FBU.imgQ; - while ((imgQ.length > 0) && (imgQ[0].img.complete)) { - data = imgQ.shift(); - if (data['type'] === 'fill') { - display.fillRect(data.x, data.y, data.width, data.height, data.color); - } else { - ctx.drawImage(data.img, data.x, data.y); - } - } - setTimeout(scan_tight_imgQ, scan_imgQ_rate); - } -}; - -encHandlers.DesktopSize = function set_desktopsize() { - Util.Debug(">> set_desktopsize"); - fb_width = FBU.width; - fb_height = FBU.height; - display.resize(fb_width, fb_height); - timing.fbu_rt_start = (new Date()).getTime(); - // Send a new non-incremental request - ws.send(fbUpdateRequests()); - - FBU.bytes = 0; - FBU.rects -= 1; - - Util.Debug("<< set_desktopsize"); - return true; -}; - -encHandlers.Cursor = function set_cursor() { - var x, y, w, h, pixelslength, masklength; - //Util.Debug(">> set_cursor"); - x = FBU.x; // hotspot-x - y = FBU.y; // hotspot-y - w = FBU.width; - h = FBU.height; - - pixelslength = w * h * fb_Bpp; - masklength = Math.floor((w + 7) / 8) * h; - - FBU.bytes = pixelslength + masklength; - if (ws.rQwait("cursor encoding", FBU.bytes)) { return false; } - - //Util.Debug(" set_cursor, x: " + x + ", y: " + y + ", w: " + w + ", h: " + h); - - display.changeCursor(ws.rQshiftBytes(pixelslength), - ws.rQshiftBytes(masklength), - x, y, w, h); - - FBU.bytes = 0; - FBU.rects -= 1; - - //Util.Debug("<< set_cursor"); - return true; -}; - -encHandlers.JPEG_quality_lo = function set_jpeg_quality() { - Util.Error("Server sent jpeg_quality pseudo-encoding"); -}; - -encHandlers.compress_lo = function set_compress_level() { - Util.Error("Server sent compress level pseudo-encoding"); -}; - -/* - * Client message routines - */ - -pixelFormat = function() { - //Util.Debug(">> pixelFormat"); - var arr; - arr = [0]; // msg-type - arr.push8(0); // padding - arr.push8(0); // padding - arr.push8(0); // padding - - arr.push8(fb_Bpp * 8); // bits-per-pixel - arr.push8(fb_depth * 8); // depth - arr.push8(0); // little-endian - arr.push8(conf.true_color ? 1 : 0); // true-color - - arr.push16(255); // red-max - arr.push16(255); // green-max - arr.push16(255); // blue-max - arr.push8(0); // red-shift - arr.push8(8); // green-shift - arr.push8(16); // blue-shift - - arr.push8(0); // padding - arr.push8(0); // padding - arr.push8(0); // padding - //Util.Debug("<< pixelFormat"); - return arr; -}; - -clientEncodings = function() { - //Util.Debug(">> clientEncodings"); - var arr, i, encList = []; - - for (i=0; i> fbUpdateRequest"); - if (typeof(x) === "undefined") { x = 0; } - if (typeof(y) === "undefined") { y = 0; } - if (typeof(xw) === "undefined") { xw = fb_width; } - if (typeof(yw) === "undefined") { yw = fb_height; } - var arr; - arr = [3]; // msg-type - arr.push8(incremental); - arr.push16(x); - arr.push16(y); - arr.push16(xw); - arr.push16(yw); - //Util.Debug("<< fbUpdateRequest"); - return arr; -}; - -// Based on clean/dirty areas, generate requests to send -fbUpdateRequests = function() { - var cleanDirty = display.getCleanDirtyReset(), - arr = [], i, cb, db; - - cb = cleanDirty.cleanBox; - if (cb.w > 0 && cb.h > 0) { - // Request incremental for clean box - arr = arr.concat(fbUpdateRequest(1, cb.x, cb.y, cb.w, cb.h)); - } - for (i = 0; i < cleanDirty.dirtyBoxes.length; i++) { - db = cleanDirty.dirtyBoxes[i]; - // Force all (non-incremental for dirty box - arr = arr.concat(fbUpdateRequest(0, db.x, db.y, db.w, db.h)); - } - return arr; -}; - - - -keyEvent = function(keysym, down) { - //Util.Debug(">> keyEvent, keysym: " + keysym + ", down: " + down); - var arr; - arr = [4]; // msg-type - arr.push8(down); - arr.push16(0); - arr.push32(keysym); - //Util.Debug("<< keyEvent"); - return arr; -}; - -pointerEvent = function(x, y) { - //Util.Debug(">> pointerEvent, x,y: " + x + "," + y + - // " , mask: " + mouse_buttonMask); - var arr; - arr = [5]; // msg-type - arr.push8(mouse_buttonMask); - arr.push16(x); - arr.push16(y); - //Util.Debug("<< pointerEvent"); - return arr; -}; - -clientCutText = function(text) { - //Util.Debug(">> clientCutText"); - var arr, i, n; - arr = [6]; // msg-type - arr.push8(0); // padding - arr.push8(0); // padding - arr.push8(0); // padding - arr.push32(text.length); - n = text.length; - for (i=0; i < n; i+=1) { - arr.push(text.charCodeAt(i)); - } - //Util.Debug("<< clientCutText:" + arr); - return arr; -}; - - - -// -// Public API interface functions -// - -that.connect = function(host, port, password, path) { - //Util.Debug(">> connect"); - - rfb_host = host; - rfb_port = port; - rfb_password = (password !== undefined) ? password : ""; - rfb_path = (path !== undefined) ? path : ""; - - if ((!rfb_host) || (!rfb_port)) { - return fail("Must set host and port"); - } - - updateState('connect'); - //Util.Debug("<< connect"); - -}; - -that.disconnect = function() { - //Util.Debug(">> disconnect"); - updateState('disconnect', 'Disconnecting'); - //Util.Debug("<< disconnect"); -}; - -that.sendPassword = function(passwd) { - rfb_password = passwd; - rfb_state = "Authentication"; - setTimeout(init_msg, 1); -}; - -that.sendCtrlAltDel = function() { - if (rfb_state !== "normal") { return false; } - Util.Info("Sending Ctrl-Alt-Del"); - var arr = []; - arr = arr.concat(keyEvent(0xFFE3, 1)); // Control - arr = arr.concat(keyEvent(0xFFE9, 1)); // Alt - arr = arr.concat(keyEvent(0xFFFF, 1)); // Delete - arr = arr.concat(keyEvent(0xFFFF, 0)); // Delete - arr = arr.concat(keyEvent(0xFFE9, 0)); // Alt - arr = arr.concat(keyEvent(0xFFE3, 0)); // Control - arr = arr.concat(fbUpdateRequests()); - ws.send(arr); -}; - -// Send a key press. If 'down' is not specified then send a down key -// followed by an up key. -that.sendKey = function(code, down) { - if (rfb_state !== "normal") { return false; } - var arr = []; - if (typeof down !== 'undefined') { - Util.Info("Sending key code (" + (down ? "down" : "up") + "): " + code); - arr = arr.concat(keyEvent(code, down ? 1 : 0)); - } else { - Util.Info("Sending key code (down + up): " + code); - arr = arr.concat(keyEvent(code, 1)); - arr = arr.concat(keyEvent(code, 0)); - } - arr = arr.concat(fbUpdateRequests()); - ws.send(arr); -}; - -that.clipboardPasteFrom = function(text) { - if (rfb_state !== "normal") { return; } - //Util.Debug(">> clipboardPasteFrom: " + text.substr(0,40) + "..."); - ws.send(clientCutText(text)); - //Util.Debug("<< clipboardPasteFrom"); -}; - -// Override internal functions for testing -that.testMode = function(override_send) { - test_mode = true; - that.recv_message = ws.testMode(override_send); - - checkEvents = function () { /* Stub Out */ }; - that.connect = function(host, port, password) { - rfb_host = host; - rfb_port = port; - rfb_password = password; - updateState('ProtocolVersion', "Starting VNC handshake"); - }; -}; - - -return constructor(); // Return the public API interface - -} // End of RFB() diff --git a/classes/novnc/include/ui.js b/classes/novnc/include/ui.js deleted file mode 100644 index 74a0005..0000000 --- a/classes/novnc/include/ui.js +++ /dev/null @@ -1,629 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-3 (see LICENSE.txt) - * - * See README.md for usage and integration instructions. - */ - -"use strict"; -/*jslint white: false, browser: true */ -/*global window, $D, Util, WebUtil, RFB, Display */ - -var UI = { - -rfb_state : 'loaded', -settingsOpen : false, -connSettingsOpen : true, -clipboardOpen: false, -keyboardVisible: false, - -// Render default UI and initialize settings menu -load: function() { - var html = '', i, sheet, sheets, llevels; - - // Stylesheet selection dropdown - sheet = WebUtil.selectStylesheet(); - sheets = WebUtil.getStylesheets(); - for (i = 0; i < sheets.length; i += 1) { - UI.addOption($D('noVNC_stylesheet'),sheets[i].title, sheets[i].title); - } - - // Logging selection dropdown - llevels = ['error', 'warn', 'info', 'debug']; - for (i = 0; i < llevels.length; i += 1) { - UI.addOption($D('noVNC_logging'),llevels[i], llevels[i]); - } - - // Settings with immediate effects - UI.initSetting('logging', 'warn'); - WebUtil.init_logging(UI.getSetting('logging')); - - UI.initSetting('stylesheet', 'default'); - WebUtil.selectStylesheet(null); - // call twice to get around webkit bug - WebUtil.selectStylesheet(UI.getSetting('stylesheet')); - - /* Populate the controls if defaults are provided in the URL */ - UI.initSetting('host', ''); - UI.initSetting('port', ''); - UI.initSetting('password', ''); - UI.initSetting('encrypt', false); - UI.initSetting('true_color', true); - UI.initSetting('cursor', false); - UI.initSetting('shared', true); - UI.initSetting('connectTimeout', 2); - UI.initSetting('path', ''); - - UI.rfb = RFB({'target': $D('noVNC_canvas'), - 'onUpdateState': UI.updateState, - 'onClipboard': UI.clipReceive}); - UI.updateVisualState(); - - // Unfocus clipboard when over the VNC area - //$D('VNC_screen').onmousemove = function () { - // var keyboard = UI.rfb.get_keyboard(); - // if ((! keyboard) || (! keyboard.get_focused())) { - // $D('VNC_clipboard_text').blur(); - // } - // }; - - // Show mouse selector buttons on touch screen devices - if ('ontouchstart' in document.documentElement) { - // Show mobile buttons - $D('noVNC_mobile_buttons').style.display = "inline"; - UI.setMouseButton(); - // Remove the address bar - setTimeout(function() { window.scrollTo(0, 1); }, 100); - UI.forceSetting('clip', true); - $D('noVNC_clip').disabled = true; - } else { - UI.initSetting('clip', false); - } - - //iOS Safari does not support CSS position:fixed. - //This detects iOS devices and enables javascript workaround. - if ((navigator.userAgent.match(/iPhone/i)) || - (navigator.userAgent.match(/iPod/i)) || - (navigator.userAgent.match(/iPad/i))) { - //UI.setOnscroll(); - //UI.setResize(); - } - - $D('noVNC_host').focus(); - - UI.setViewClip(); - Util.addEvent(window, 'resize', UI.setViewClip); - - Util.addEvent(window, 'beforeunload', function () { - if (UI.rfb_state === 'normal') { - return "You are currently connected."; - } - } ); - -}, - -// Read form control compatible setting from cookie -getSetting: function(name) { - var val, ctrl = $D('noVNC_' + name); - val = WebUtil.readCookie(name); - if (ctrl.type === 'checkbox') { - if (val.toLowerCase() in {'0':1, 'no':1, 'false':1}) { - val = false; - } else { - val = true; - } - } - return val; -}, - -// Update cookie and form control setting. If value is not set, then -// updates from control to current cookie setting. -updateSetting: function(name, value) { - - var i, ctrl = $D('noVNC_' + name); - // Save the cookie for this session - if (typeof value !== 'undefined') { - WebUtil.createCookie(name, value); - } - - // Update the settings control - value = UI.getSetting(name); - - if (ctrl.type === 'checkbox') { - ctrl.checked = value; - - } else if (typeof ctrl.options !== 'undefined') { - for (i = 0; i < ctrl.options.length; i += 1) { - if (ctrl.options[i].value === value) { - ctrl.selectedIndex = i; - break; - } - } - } else { - /*Weird IE9 error leads to 'null' appearring - in textboxes instead of ''.*/ - if (value === null) { - value = ""; - } - ctrl.value = value; - } -}, - -// Save control setting to cookie -saveSetting: function(name) { - var val, ctrl = $D('noVNC_' + name); - if (ctrl.type === 'checkbox') { - val = ctrl.checked; - } else if (typeof ctrl.options !== 'undefined') { - val = ctrl.options[ctrl.selectedIndex].value; - } else { - val = ctrl.value; - } - WebUtil.createCookie(name, val); - //Util.Debug("Setting saved '" + name + "=" + val + "'"); - return val; -}, - -// Initial page load read/initialization of settings -initSetting: function(name, defVal) { - var val; - - // Check Query string followed by cookie - val = WebUtil.getQueryVar(name); - if (val === null) { - val = WebUtil.readCookie(name, defVal); - } - UI.updateSetting(name, val); - //Util.Debug("Setting '" + name + "' initialized to '" + val + "'"); - return val; -}, - -// Force a setting to be a certain value -forceSetting: function(name, val) { - UI.updateSetting(name, val); - return val; -}, - - -// Show the clipboard panel -toggleClipboardPanel: function() { - //Close settings if open - if (UI.settingsOpen == true) { - UI.settingsApply(); - UI.closeSettingsMenu(); - } - //Close connection settings if open - if (UI.connSettingsOpen == true) { - UI.toggleConnectPanel(); - } - //Toggle Clipboard Panel - if (UI.clipboardOpen == true) { - $D('noVNC_clipboard').style.display = "none"; - $D('clipboardButton').className = "noVNC_status_button"; - UI.clipboardOpen = false; - } else { - $D('noVNC_clipboard').style.display = "block"; - $D('clipboardButton').className = "noVNC_status_button_selected"; - UI.clipboardOpen = true; - } -}, - -// Show the connection settings panel/menu -toggleConnectPanel: function() { - //Close connection settings if open - if (UI.settingsOpen == true) { - UI.settingsApply(); - UI.closeSettingsMenu(); - $D('connectButton').className = "noVNC_status_button"; - } - if (UI.clipboardOpen == true) { - UI.toggleClipboardPanel(); - } - - //Toggle Connection Panel - if (UI.connSettingsOpen == true) { - $D('noVNC_controls').style.display = "none"; - $D('connectButton').className = "noVNC_status_button"; - UI.connSettingsOpen = false; - } else { - $D('noVNC_controls').style.display = "block"; - $D('connectButton').className = "noVNC_status_button_selected"; - UI.connSettingsOpen = true; - $D('noVNC_host').focus(); - } -}, - -// Toggle the settings menu: -// On open, settings are refreshed from saved cookies. -// On close, settings are applied -toggleSettingsPanel: function() { - if (UI.settingsOpen) { - UI.settingsApply(); - UI.closeSettingsMenu(); - } else { - UI.updateSetting('encrypt'); - UI.updateSetting('true_color'); - if (UI.rfb.get_display().get_cursor_uri()) { - UI.updateSetting('cursor'); - } else { - UI.updateSetting('cursor', false); - $D('noVNC_cursor').disabled = true; - } - UI.updateSetting('clip'); - UI.updateSetting('shared'); - UI.updateSetting('connectTimeout'); - UI.updateSetting('path'); - UI.updateSetting('stylesheet'); - UI.updateSetting('logging'); - - UI.openSettingsMenu(); - } -}, - -// Open menu -openSettingsMenu: function() { - if (UI.clipboardOpen == true) { - UI.toggleClipboardPanel(); - } - //Close connection settings if open - if (UI.connSettingsOpen == true) { - UI.toggleConnectPanel(); - } - $D('noVNC_settings').style.display = "block"; - $D('settingsButton').className = "noVNC_status_button_selected"; - UI.settingsOpen = true; -}, - -// Close menu (without applying settings) -closeSettingsMenu: function() { - $D('noVNC_settings').style.display = "none"; - $D('settingsButton').className = "noVNC_status_button"; - UI.settingsOpen = false; -}, - -// Save/apply settings when 'Apply' button is pressed -settingsApply: function() { - //Util.Debug(">> settingsApply"); - UI.saveSetting('encrypt'); - UI.saveSetting('true_color'); - if (UI.rfb.get_display().get_cursor_uri()) { - UI.saveSetting('cursor'); - } - UI.saveSetting('clip'); - UI.saveSetting('shared'); - UI.saveSetting('connectTimeout'); - UI.saveSetting('path'); - UI.saveSetting('stylesheet'); - UI.saveSetting('logging'); - - // Settings with immediate (non-connected related) effect - WebUtil.selectStylesheet(UI.getSetting('stylesheet')); - WebUtil.init_logging(UI.getSetting('logging')); - UI.setViewClip(); - UI.setViewDrag(UI.rfb.get_viewportDrag()); - //Util.Debug("<< settingsApply"); -}, - - - -setPassword: function() { - UI.rfb.sendPassword($D('noVNC_password').value); - //Reset connect button. - $D('noVNC_connect_button').value = "Connect"; - $D('noVNC_connect_button').onclick = UI.Connect; - //Hide connection panel. - UI.toggleConnectPanel(); - return false; -}, - -sendCtrlAltDel: function() { - UI.rfb.sendCtrlAltDel(); -}, - -setMouseButton: function(num) { - var b, blist = [0, 1,2,4], button; - - if (typeof num === 'undefined') { - // Disable mouse buttons - num = -1; - } - if (UI.rfb) { - UI.rfb.get_mouse().set_touchButton(num); - } - - for (b = 0; b < blist.length; b++) { - button = $D('noVNC_mouse_button' + blist[b]); - if (blist[b] === num) { - button.style.display = ""; - } else { - button.style.display = "none"; - /* - button.style.backgroundColor = "black"; - button.style.color = "lightgray"; - button.style.backgroundColor = ""; - button.style.color = ""; - */ - } - } -}, - -updateState: function(rfb, state, oldstate, msg) { - var s, sb, c, d, cad, vd, klass; - UI.rfb_state = state; - s = $D('noVNC_status'); - sb = $D('noVNC_status_bar'); - switch (state) { - case 'failed': - case 'fatal': - klass = "noVNC_status_error"; - break; - case 'normal': - klass = "noVNC_status_normal"; - break; - case 'disconnected': - $D('noVNC_logo').style.display = "block"; - case 'loaded': - klass = "noVNC_status_normal"; - break; - case 'password': - UI.toggleConnectPanel(); - - $D('noVNC_connect_button').value = "Send Password"; - $D('noVNC_connect_button').onclick = UI.setPassword; - $D('noVNC_password').focus(); - - klass = "noVNC_status_warn"; - break; - default: - klass = "noVNC_status_warn"; - break; - } - - if (typeof(msg) !== 'undefined') { - s.setAttribute("class", klass); - sb.setAttribute("class", klass); - s.innerHTML = msg; - } - - UI.updateVisualState(); -}, - -// Disable/enable controls depending on connection state -updateVisualState: function() { - var connected = UI.rfb_state === 'normal' ? true : false; - - //Util.Debug(">> updateVisualState"); - $D('noVNC_encrypt').disabled = connected; - $D('noVNC_true_color').disabled = connected; - if (UI.rfb && UI.rfb.get_display() && - UI.rfb.get_display().get_cursor_uri()) { - $D('noVNC_cursor').disabled = connected; - } else { - UI.updateSetting('cursor', false); - $D('noVNC_cursor').disabled = true; - } - $D('noVNC_shared').disabled = connected; - $D('noVNC_connectTimeout').disabled = connected; - $D('noVNC_path').disabled = connected; - - if (connected) { - UI.setViewClip(); - UI.setMouseButton(1); - $D('showKeyboard').style.display = "inline"; - $D('sendCtrlAltDelButton').style.display = "inline"; - } else { - UI.setMouseButton(); - $D('showKeyboard').style.display = "none"; - $D('sendCtrlAltDelButton').style.display = "none"; - } - // State change disables viewport dragging. - // It is enabled (toggled) by direct click on the button - UI.setViewDrag(false); - - switch (UI.rfb_state) { - case 'fatal': - case 'failed': - case 'loaded': - case 'disconnected': - $D('connectButton').style.display = ""; - $D('disconnectButton').style.display = "none"; - break; - default: - $D('connectButton').style.display = "none"; - $D('disconnectButton').style.display = ""; - break; - } - - //Util.Debug("<< updateVisualState"); -}, - - -clipReceive: function(rfb, text) { - Util.Debug(">> UI.clipReceive: " + text.substr(0,40) + "..."); - $D('noVNC_clipboard_text').value = text; - Util.Debug("<< UI.clipReceive"); -}, - - -connect: function() { - var host, port, password, path; - - UI.closeSettingsMenu(); - UI.toggleConnectPanel(); - - host = $D('noVNC_host').value; - port = $D('noVNC_port').value; - password = $D('noVNC_password').value; - path = $D('noVNC_path').value; - if ((!host) || (!port)) { - throw("Must set host and port"); - } - - UI.rfb.set_encrypt(UI.getSetting('encrypt')); - UI.rfb.set_true_color(UI.getSetting('true_color')); - UI.rfb.set_local_cursor(UI.getSetting('cursor')); - UI.rfb.set_shared(UI.getSetting('shared')); - UI.rfb.set_connectTimeout(UI.getSetting('connectTimeout')); - - UI.rfb.connect(host, port, password, path); - //Close dialog. - setTimeout(UI.setBarPosition, 100); - $D('noVNC_logo').style.display = "none"; -}, - -disconnect: function() { - UI.closeSettingsMenu(); - UI.rfb.disconnect(); - - $D('noVNC_logo').style.display = "block"; - UI.connSettingsOpen = false; - UI.toggleConnectPanel(); -}, - -displayBlur: function() { - UI.rfb.get_keyboard().set_focused(false); - UI.rfb.get_mouse().set_focused(false); -}, - -displayFocus: function() { - UI.rfb.get_keyboard().set_focused(true); - UI.rfb.get_mouse().set_focused(true); -}, - -clipClear: function() { - $D('noVNC_clipboard_text').value = ""; - UI.rfb.clipboardPasteFrom(""); -}, - -clipSend: function() { - var text = $D('noVNC_clipboard_text').value; - Util.Debug(">> UI.clipSend: " + text.substr(0,40) + "..."); - UI.rfb.clipboardPasteFrom(text); - Util.Debug("<< UI.clipSend"); -}, - - -// Enable/disable and configure viewport clipping -setViewClip: function(clip) { - var display, cur_clip, pos, new_w, new_h; - - if (UI.rfb) { - display = UI.rfb.get_display(); - } else { - return; - } - - cur_clip = display.get_viewport(); - - if (typeof(clip) !== 'boolean') { - // Use current setting - clip = UI.getSetting('clip'); - } - - if (clip && !cur_clip) { - // Turn clipping on - UI.updateSetting('clip', true); - } else if (!clip && cur_clip) { - // Turn clipping off - UI.updateSetting('clip', false); - display.set_viewport(false); - $D('noVNC_canvas').style.position = 'static'; - display.viewportChange(); - } - if (UI.getSetting('clip')) { - // If clipping, update clipping settings - $D('noVNC_canvas').style.position = 'absolute'; - pos = Util.getPosition($D('noVNC_canvas')); - new_w = window.innerWidth - pos.x; - new_h = window.innerHeight - pos.y; - display.set_viewport(true); - display.viewportChange(0, 0, new_w, new_h); - } -}, - -// Toggle/set/unset the viewport drag/move button -setViewDrag: function(drag) { - var vmb = $D('noVNC_view_drag_button'); - if (!UI.rfb) { return; } - - if (UI.rfb_state === 'normal' && - UI.rfb.get_display().get_viewport()) { - vmb.style.display = "inline"; - } else { - vmb.style.display = "none"; - } - - if (typeof(drag) === "undefined") { - // If not specified, then toggle - drag = !UI.rfb.get_viewportDrag(); - } - if (drag) { - vmb.className = "noVNC_status_button_selected"; - UI.rfb.set_viewportDrag(true); - } else { - vmb.className = "noVNC_status_button"; - UI.rfb.set_viewportDrag(false); - } -}, - -// On touch devices, show the OS keyboard -showKeyboard: function() { - if(UI.keyboardVisible == false) { - $D('keyboardinput').focus(); - UI.keyboardVisible = true; - $D('showKeyboard').className = "noVNC_status_button_selected"; - } else if(UI.keyboardVisible == true) { - $D('keyboardinput').blur(); - $D('showKeyboard').className = "noVNC_status_button"; - UI.keyboardVisible = false; - } -}, - -keyInputBlur: function() { - $D('showKeyboard').className = "noVNC_status_button"; - //Weird bug in iOS if you change keyboardVisible - //here it does not actually occur so next time - //you click keyboard icon it doesnt work. - setTimeout("UI.setKeyboard()",100) -}, - -setKeyboard: function() { - UI.keyboardVisible = false; -}, - -// iOS < Version 5 does not support position fixed. Javascript workaround: -setOnscroll: function() { - window.onscroll = function() { - UI.setBarPosition(); - }; -}, - -setResize: function () { - window.onResize = function() { - UI.setBarPosition(); - }; -}, - -//Helper to add options to dropdown. -addOption: function(selectbox,text,value ) -{ - var optn = document.createElement("OPTION"); - optn.text = text; - optn.value = value; - selectbox.options.add(optn); -}, - -setBarPosition: function() { - $D('noVNC-control-bar').style.top = (window.pageYOffset) + 'px'; - $D('noVNC_mobile_buttons').style.left = (window.pageXOffset) + 'px'; - - var vncwidth = $D('noVNC_screen').style.offsetWidth; - $D('noVNC-control-bar').style.width = vncwidth + 'px'; -} - -}; - - - - diff --git a/classes/novnc/include/util.js b/classes/novnc/include/util.js deleted file mode 100644 index 0a9e0e0..0000000 --- a/classes/novnc/include/util.js +++ /dev/null @@ -1,276 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-3 (see LICENSE.txt) - * - * See README.md for usage and integration instructions. - */ - -"use strict"; -/*jslint bitwise: false, white: false */ -/*global window, console, document, navigator, ActiveXObject */ - -// Globals defined here -var Util = {}; - - -/* - * Make arrays quack - */ - -Array.prototype.push8 = function (num) { - this.push(num & 0xFF); -}; - -Array.prototype.push16 = function (num) { - this.push((num >> 8) & 0xFF, - (num ) & 0xFF ); -}; -Array.prototype.push32 = function (num) { - this.push((num >> 24) & 0xFF, - (num >> 16) & 0xFF, - (num >> 8) & 0xFF, - (num ) & 0xFF ); -}; - -/* - * ------------------------------------------------------ - * Namespaced in Util - * ------------------------------------------------------ - */ - -/* - * Logging/debug routines - */ - -Util._log_level = 'warn'; -Util.init_logging = function (level) { - if (typeof level === 'undefined') { - level = Util._log_level; - } else { - Util._log_level = level; - } - if (typeof window.console === "undefined") { - if (typeof window.opera !== "undefined") { - window.console = { - 'log' : window.opera.postError, - 'warn' : window.opera.postError, - 'error': window.opera.postError }; - } else { - window.console = { - 'log' : function(m) {}, - 'warn' : function(m) {}, - 'error': function(m) {}}; - } - } - - Util.Debug = Util.Info = Util.Warn = Util.Error = function (msg) {}; - switch (level) { - case 'debug': Util.Debug = function (msg) { console.log(msg); }; - case 'info': Util.Info = function (msg) { console.log(msg); }; - case 'warn': Util.Warn = function (msg) { console.warn(msg); }; - case 'error': Util.Error = function (msg) { console.error(msg); }; - case 'none': - break; - default: - throw("invalid logging type '" + level + "'"); - } -}; -Util.get_logging = function () { - return Util._log_level; -}; -// Initialize logging level -Util.init_logging(); - - -// Set configuration default for Crockford style function namespaces -Util.conf_default = function(cfg, api, defaults, v, mode, type, defval, desc) { - var getter, setter; - - // Default getter function - getter = function (idx) { - if ((type in {'arr':1, 'array':1}) && - (typeof idx !== 'undefined')) { - return cfg[v][idx]; - } else { - return cfg[v]; - } - }; - - // Default setter function - setter = function (val, idx) { - if (type in {'boolean':1, 'bool':1}) { - if ((!val) || (val in {'0':1, 'no':1, 'false':1})) { - val = false; - } else { - val = true; - } - } else if (type in {'integer':1, 'int':1}) { - val = parseInt(val, 10); - } else if (type === 'func') { - if (!val) { - val = function () {}; - } - } - if (typeof idx !== 'undefined') { - cfg[v][idx] = val; - } else { - cfg[v] = val; - } - }; - - // Set the description - api[v + '_description'] = desc; - - // Set the getter function - if (typeof api['get_' + v] === 'undefined') { - api['get_' + v] = getter; - } - - // Set the setter function with extra sanity checks - if (typeof api['set_' + v] === 'undefined') { - api['set_' + v] = function (val, idx) { - if (mode in {'RO':1, 'ro':1}) { - throw(v + " is read-only"); - } else if ((mode in {'WO':1, 'wo':1}) && - (typeof cfg[v] !== 'undefined')) { - throw(v + " can only be set once"); - } - setter(val, idx); - }; - } - - // Set the default value - if (typeof defaults[v] !== 'undefined') { - defval = defaults[v]; - } else if ((type in {'arr':1, 'array':1}) && - (! (defval instanceof Array))) { - defval = []; - } - // Coerce existing setting to the right type - //Util.Debug("v: " + v + ", defval: " + defval + ", defaults[v]: " + defaults[v]); - setter(defval); -}; - -// Set group of configuration defaults -Util.conf_defaults = function(cfg, api, defaults, arr) { - var i; - for (i = 0; i < arr.length; i++) { - Util.conf_default(cfg, api, defaults, arr[i][0], arr[i][1], - arr[i][2], arr[i][3], arr[i][4]); - } -} - - -/* - * Cross-browser routines - */ - -// Get DOM element position on page -Util.getPosition = function (obj) { - var x = 0, y = 0; - if (obj.offsetParent) { - do { - x += obj.offsetLeft; - y += obj.offsetTop; - obj = obj.offsetParent; - } while (obj); - } - return {'x': x, 'y': y}; -}; - -// Get mouse event position in DOM element -Util.getEventPosition = function (e, obj, scale) { - var evt, docX, docY, pos; - //if (!e) evt = window.event; - evt = (e ? e : window.event); - evt = (evt.changedTouches ? evt.changedTouches[0] : evt.touches ? evt.touches[0] : evt); - if (evt.pageX || evt.pageY) { - docX = evt.pageX; - docY = evt.pageY; - } else if (evt.clientX || evt.clientY) { - docX = evt.clientX + document.body.scrollLeft + - document.documentElement.scrollLeft; - docY = evt.clientY + document.body.scrollTop + - document.documentElement.scrollTop; - } - pos = Util.getPosition(obj); - if (typeof scale === "undefined") { - scale = 1; - } - return {'x': (docX - pos.x) / scale, 'y': (docY - pos.y) / scale}; -}; - - -// Event registration. Based on: http://www.scottandrew.com/weblog/articles/cbs-events -Util.addEvent = function (obj, evType, fn){ - if (obj.attachEvent){ - var r = obj.attachEvent("on"+evType, fn); - return r; - } else if (obj.addEventListener){ - obj.addEventListener(evType, fn, false); - return true; - } else { - throw("Handler could not be attached"); - } -}; - -Util.removeEvent = function(obj, evType, fn){ - if (obj.detachEvent){ - var r = obj.detachEvent("on"+evType, fn); - return r; - } else if (obj.removeEventListener){ - obj.removeEventListener(evType, fn, false); - return true; - } else { - throw("Handler could not be removed"); - } -}; - -Util.stopEvent = function(e) { - if (e.stopPropagation) { e.stopPropagation(); } - else { e.cancelBubble = true; } - - if (e.preventDefault) { e.preventDefault(); } - else { e.returnValue = false; } -}; - - -// Set browser engine versions. Based on mootools. -Util.Features = {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)}; - -Util.Engine = { - 'presto': (function() { - return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925)); }()), - 'trident': (function() { - return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4); }()), - 'webkit': (function() { - try { return (navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); } catch (e) { return false; } }()), - //'webkit': (function() { - // return ((typeof navigator.taintEnabled !== "unknown") && navigator.taintEnabled) ? false : ((Util.Features.xpath) ? ((Util.Features.query) ? 525 : 420) : 419); }()), - 'gecko': (function() { - return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18); }()) -}; -if (Util.Engine.webkit) { - // Extract actual webkit version if available - Util.Engine.webkit = (function(v) { - var re = new RegExp('WebKit/([0-9\.]*) '); - v = (navigator.userAgent.match(re) || ['', v])[1]; - return parseFloat(v, 10); - })(Util.Engine.webkit); -} - -Util.Flash = (function(){ - var v, version; - try { - v = navigator.plugins['Shockwave Flash'].description; - } catch(err1) { - try { - v = new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version'); - } catch(err2) { - v = '0 r0'; - } - } - version = v.match(/\d+/g); - return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0}; -}()); diff --git a/classes/novnc/include/vnc.js b/classes/novnc/include/vnc.js deleted file mode 100644 index f938be7..0000000 --- a/classes/novnc/include/vnc.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * noVNC: HTML5 VNC client - * Copyright (C) 2011 Joel Martin - * Licensed under LGPL-3 (see LICENSE.txt) - * - * See README.md for usage and integration instructions. - */ - -/*jslint evil: true */ -/*global window, document, INCLUDE_URI */ - -/* - * Load supporting scripts - */ -function get_INCLUDE_URI() { - return (typeof INCLUDE_URI !== "undefined") ? INCLUDE_URI : "include/"; -} - -(function () { - "use strict"; - - var extra = "", start, end; - - start = " - - - - - -
- -
- -
- - - - - - -
-
- - -
- - - - - -
- - -
- -
- -
- - -
- -
    -
  • Encrypt
  • -
  • True Color
  • -
  • Local Cursor
  • -
  • Clip to window
  • -
  • Shared Mode
  • -
  • Connect Timeout (s)
  • -
  • Path
  • -
    - -
  • -
  • - - -
  • -
  • -
    -
  • -
-
-
- - -
-
    -
  • -
  • -
  • -
  • -
-
- -
- - -
-
- -
-
Loading
-
- -

no
VNC

- - -
- - Canvas not supported. - -
- -
- - - - diff --git a/classes/novnc/vnc_auto.html b/classes/novnc/vnc_auto.html deleted file mode 100644 index a500b79..0000000 --- a/classes/novnc/vnc_auto.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - noVNC - - - - - - - -
-
- - - -
Loading
- -
-
- - Canvas not supported. - -
- - - - - - diff --git a/classes/ssl/Makefile.am b/classes/ssl/Makefile.am deleted file mode 100644 index fd1c201..0000000 --- a/classes/ssl/Makefile.am +++ /dev/null @@ -1,2 +0,0 @@ -EXTRA_DIST=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README ss_vncviewer onetimekey UltraViewerSSL.jar SignedUltraViewerSSL.jar ultra.vnc ultrasigned.vnc ultraproxy.vnc - diff --git a/classes/ssl/README b/classes/ssl/README deleted file mode 100644 index b244cf1..0000000 --- a/classes/ssl/README +++ /dev/null @@ -1,338 +0,0 @@ -This directory contains a patched Java applet VNC viewer that is SSL -enabled. - -The patches in the *.patch files are relative to the source tarball: - - tightvnc-1.3dev7_javasrc.tar.gz - -currently (4/06) available here: - - http://prdownloads.sourceforge.net/vnc-tight/tightvnc-1.3dev7_javasrc.tar.gz?download - -It also includes some simple patches to: - - - fix richcursor colors - - - make the Java Applet cursor (not the cursor drawn to the canvas - framebuffer) invisible when it is inside the canvas. - - - allow Tab (and some other) keystrokes to be sent to the vnc - server instead of doing widget traversal. - - -This SSL applet should work with any VNC viewer that has an SSL tunnel in -front of it. It has been tested on x11vnc and using the stunnel tunnel -to other VNC servers. - -By default this Vnc Viewer will only do SSL. To do unencrypted traffic -see the "DisableSSL" applet parameter (e.g. set it to Yes in index.vnc). - -Proxies: they are a general problem with java socket applets (a socket -connection does not go through the proxy). See the info in the proxy.vnc -file for a workaround. It uses SignedVncViewer.jar which is simply -a signed version of VncViewer.jar. The basic idea is the user clicks -"Yes" to trust the applet and then it can connect directly to the proxy -and issue a CONNECT request. - -This applet has been tested on versions 1.4.2 and 1.5.0 of the Sun -Java plugin. It may not work on older releases or different vendor VM's. -Send full Java Console output for failures. - ---------------------------------------------------------------- -Tips: - -When doing single-port proxy connections (e.g. both VNC and HTTPS -thru port 5900) it helps to move through the 'do you trust this site' -dialogs quickly. x11vnc has to wait to see if the traffic is VNC or -HTTP and this can cause timeouts if you don't move thru them quickly. - -You may have to restart your browser completely if it gets into a -weird state. For one case we saw the JVM requesting VncViewer.class -even when no such file exists. - - ---------------------------------------------------------------- -Extras: - -ss_vncviewer (not Java): - - Wrapper script for native VNC viewer to connect to x11vnc in - SSL mode. Script launches stunnel(8) and then connects to it - via localhost which in turn is then redirected to x11vnc via an - SSL tunnel. stunnel(8) must be installed and available in PATH. - - -Running Java SSL VncViewer from the command line: - - From this directory: - - java -cp ./VncViewer.jar VncViewer HOST PORT - - substitute and with the actual values. - You can add any other parameters, e.g.: ignoreProxy yes - ---------------------------------------------------------------- -UltraVNC: - -The UltraVNC java viewer has also been patched to support SSL. Various -bugs in the UltraVNC java viewer were also fixed. This viewer can be -useful because is support UltraVNC filetransfer, and so it works on -Unix, etc. - -UltraViewerSSL.jar -SignedUltraViewerSSL.jar -ultra.vnc -ultraproxy.vnc -ultravnc-102-JavaViewer-ssl-etc.patch - ---------------------------------------------------------------- -Applet Parameters: - -Some additional applet parameters can be set via the URL, e.g. - - http://host:5800/?param=value - http://host:5800/ultra.vnc?param=value - https://host:5900/ultra.vnc?param=value - -etc. If running java from command line as show above, it comes -in as java ... VncViewer param value ... - -There is a limitation with libvncserver that param and value can -only be alphanumeric, underscore, "+" (for space), or "." - -We have added some applet parameters to the stock VNC java -viewers. Here are the applet parameters: - -Both TightVNC and UltraVNC Java viewers: - - HOST - string, default: none. - The Hostname to connect to. - - PORT - number, default: 0 - The VNC server port to connect to. - - Open New Window - yes/no, default: no - Run applet in separate frame. - - Show Controls - yes/no, default: yes - Show Controls button panel. - - Show Offline Desktop - yes/no, default: no - Do we continue showing desktop on remote disconnect? - - Defer screen updates - number, default: 20 - Milliseconds delay - - Defer cursor updates - number, default: 10 - Milliseconds delay - - Defer update requests - number, default: 50 - Milliseconds delay - - PASSWORD - string, default: none - VNC session password in plain text. - - ENCPASSWORD - string, default: none - VNC session password in encrypted in DES with KNOWN FIXED - key. It is a hex string. This is like the ~/.vnc/passwd format. - - - The following are added by x11vnc and/or ssvnc project - - VNCSERVERPORT - number, default: 0 - Like PORT, but if there is a firewall this is the Actual VNC - server port. PORT might be a redir port on the firewall. - - DisableSSL - yes/no, default: no - Do unencrypted connection, no SSL. - - httpsPort - number, default: none - When checking for proxy, use this at the url port number. - - CONNECT - string, default: none - Sets to host:port for the CONNECT line to a Web proxy. - The Web proxy should connect us to it. - - GET - yes/no, default: no - Set to do a special HTTP GET (/request.https.vnc.connection) - to the vnc server that will cause it to switch to VNC instead. - This is to speedup/make more robust, the single port HTTPS and VNC - mode of x11vnc (e.g. both services thru port 5900, etc) - - urlPrefix - string, default: none - set to a string that will be prefixed to all URL's when contacting - the VNC server. Idea is a special proxy will use this to indicate - internal hostname, etc. - - oneTimeKey - string, default: none - set a special hex "key" to correspond to an SSL X.509 cert+key. - See the 'onetimekey' helper script. Can also be PROMPT to prompt - the user to paste the hex key string in. - - This provides a Client-Side cert+key that the client will use to - authenticate itself by SSL To the VNC Server. - - This is to try to work around the problem that the Java applet - cannot keep an SSL keystore on disk, etc. E.g. if they log - into an HTTPS website via password they are authenticated and - encrypted, then the website can safely put oneTimeKey=... on the - URL. The Vncviewer authenticates the VNC server with this key. - - Note that there is currently a problem in that if x11vnc requires - Client Certificates the user cannot download the index.vnc HTML - and VncViewer.jar from the same x11vnc. Those need to come from - a different x11vnc or from a web server. - - Note that the HTTPS website can also put the VNC Password - (e.g. a temporary/one-time one) in the parameter PASSWORD. - The Java Applet will automatically supply this VNC password - instead of prompting. - - serverCert - string, default: none - set a special hex "cert" to correspond to an SSL X.509 cert - See the 'onetimekey -certonly' helper script. - - This provides a Server-Side cert that the client will authenticate - the VNC Server against by SSL. - - This is to try to work around the problem that the Java applet - cannot keep an SSL keystore on disk, etc. E.g. if they log - into an HTTPS website via password they are authenticated and - encrypted, then the website can safely put serverCert=... on the - URL. - - Of course the VNC Server is sending this string to the Java - Applet, so this is only reasonable security if the VNC Viewer - already trusts the HTTPS retrieval of the URL + serverCert param - that it gets. This should be done over HTTPS not HTTP. - - proxyHost - string, default: none - Do not try to guess the proxy's hostname, use the value in - proxyHost. Does not imply forceProxy (below.) - - proxyPort - string, default: none - Do not try to guess the proxy's port number, use the value in - proxyPort. Does not imply forceProxy (below.) - - forceProxy - yes/no, default: no - Assume there is a proxy and force its use. - - If a string other than "yes" or "no" is given, it implies "yes" - and uses the string for proxyHost and proxyPort (see above). - In this case the string must be of the form "hostname+port". - Note that it is "+" and not ":" before the port number. - - ignoreProxy - yes/no, default: no - Don't check for a proxy, assume there is none. - - trustAllVncCerts - yes/no, default: no - Automatically trust any cert received from the VNC server - (obviously this could be dangerous and lead to man in the - middle attack). Do not ask the user to verify any of these - certs from the VNC server. - - trustUrlVncCert - yes/no, default: no - Automatically trust any cert that the web browsers has accepted. - E.g. the user said "Yes" or "Continue" to a web browser dialog - regarding a certificate. If we get the same cert (chain) from - the VNC server we trust it without prompting the user. - - debugCerts - yes/no, default: no - Print out every cert in the Server, TrustUrl, TrustAll chains. - - -TightVNC Java viewer only: - - Offer Relogin - yes/no, default: yes - "Offer Relogin" set to "No" disables "Login again" - - SocketFactory - string, default: none - set Java Socket class factory. - -UltraVNC Java viewer only: - - None. - - The following are added by x11vnc and/or ssvnc project - - ftpDropDown - string, default: none - Sets the file transfer "drives" dropdown to the "." separated - list. Use "+" for space. The default is - - My+Documents.Desktop.Home - - for 3 entries in the dropdown in addition to the "drives" - (e.g. C:\) These items should be expanded properly by the VNC - Server. x11vnc will prepend $HOME to them, which is normally - what one wants. To include a "/" use "_2F_". Another example: - - Home.Desktop.bin_2F_linux - - If an item is prefixed with "TOP_" then the item is inserted at - the top of the drop down rather than being appended to the end. - E.g. to try to initially load the user homedir instead of /: - - TOP_Home.My+Documents.Desktop - - If ftpDropDown is set to the empty string, "", then no special - locations, [Desktop] etc., are placed in the drop down. Only the - ultravnc "drives" will appear. - - ftpOnly - yes/no, default: no - The VNC viewer only shows the filetransfer panel, no desktop - is displayed. - - graftFtp - yes/no, default: no - As ftpOnly, the VNC viewer only shows the filetransfer panel, - no desktop is displayed, however it is "grafted" onto an existing - SSVNC unix vncviewer. The special SSVNC vncviewer merges the two - channels. - - dsmActive - yes/no, default: no - Special usage mode with the SSVNC unix vncviewer. The UltraVNC - DSM encryption is active. Foolishly, UltraVNC DSM encryption - *MODIFIES* the VNC protocol when active (it is not a pure tunnel). - This option indicates to modify the VNC protocol to make this work. - Usually only used with graftFtp and SSVNC unix vncviewer. - - delayAuthPanel - yes/no, default: no - This is another special usage mode with the SSVNC unix vncviewer. - A login panel is delayed (not shown at startup.) Could be useful - for non SSVNC usage too. - - ignoreMSLogonCheck - yes/no, default: no - Similar to delayAuthPanel, do not put up a popup asking for - Windows username, etc. diff --git a/classes/ssl/SignedUltraViewerSSL.jar b/classes/ssl/SignedUltraViewerSSL.jar deleted file mode 100644 index 6c18737..0000000 Binary files a/classes/ssl/SignedUltraViewerSSL.jar and /dev/null differ diff --git a/classes/ssl/SignedVncViewer.jar b/classes/ssl/SignedVncViewer.jar deleted file mode 100644 index 95c0b0b..0000000 Binary files a/classes/ssl/SignedVncViewer.jar and /dev/null differ diff --git a/classes/ssl/UltraViewerSSL.jar b/classes/ssl/UltraViewerSSL.jar deleted file mode 100644 index 45259fd..0000000 Binary files a/classes/ssl/UltraViewerSSL.jar and /dev/null differ diff --git a/classes/ssl/VncViewer.jar b/classes/ssl/VncViewer.jar deleted file mode 100644 index 9453c6f..0000000 Binary files a/classes/ssl/VncViewer.jar and /dev/null differ diff --git a/classes/ssl/index.vnc b/classes/ssl/index.vnc deleted file mode 100644 index ec520dc..0000000 --- a/classes/ssl/index.vnc +++ /dev/null @@ -1,26 +0,0 @@ - - - - -$USER's $DESKTOP desktop ($DISPLAY) - - - - -$PARAMS - -
-
x11vnc site - diff --git a/classes/ssl/onetimekey b/classes/ssl/onetimekey deleted file mode 100755 index bf57c8f..0000000 --- a/classes/ssl/onetimekey +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh -# -# usage: onetimekey path/to/mycert.pem -# onetimekey -certonly path/to/mycert.pem -# -# Takes an openssl cert+key pem file and turns into a long string -# for the x11vnc SSL VNC Java Viewer. -# -# The Java applet URL parameter can be oneTimeKey= where str is -# the output of this program, or can be oneTimeKey=PROMPT in which -# case the applet will ask you to paste in the string. -# -# The problem trying to be solved here is it is difficult to get -# the Java applet to have or use a keystore with the key saved -# in it. Also, as the name implies, an HTTPS server can create -# a one time key to send to the applet (the user has already -# logged in via password to the HTTPS server). -# -# Note oneTimeKey is to provide a CLIENT Certificate for the viewer -# to authenticate itself to the VNC Server. -# -# There is also the serverCert= Applet parameter. This is -# a cert to authenticate the VNC server against. To create that -# string with this tool specify -certonly as the first argument. - -certonly="" -if [ "X$1" = "X-certonly" ]; then - shift - certonly=1 -fi - -in=$1 -der=/tmp/1time$$.der -touch $der -chmod 600 $der - -openssl pkcs8 -topk8 -nocrypt -in "$in" -out "$der" -outform der - -pbinhex=/tmp/pbinhex.$$ -cat > $pbinhex < - - - - - - -$USER's $DESKTOP desktop ($DISPLAY) - - - - -$PARAMS - -
-x11vnc site - diff --git a/classes/ssl/ss_vncviewer b/classes/ssl/ss_vncviewer deleted file mode 100755 index 7e793ff..0000000 --- a/classes/ssl/ss_vncviewer +++ /dev/null @@ -1,3676 +0,0 @@ -#!/bin/sh -# -# ss_vncviewer: wrapper for vncviewer to use an stunnel SSL tunnel -# or an SSH tunnel. -# -# Copyright (c) 2006-2009 by Karl J. Runge -# -# ss_vncviewer 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. -# -# ss_vncviewer 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 ss_vncviewer; if not, write to the Free Software -# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA -# or see . -# -# -# You must have stunnel(8) installed on the system and in your PATH -# (however, see the -ssh option below, in which case you will need ssh(1) -# installed) Note: stunnel is usually installed in an "sbin" subdirectory. -# -# You should have "x11vnc -ssl ..." or "x11vnc -stunnel ..." -# already running as the VNC server on the remote machine. -# (or use stunnel on the server side for any other VNC server) -# -# -# Usage: ss_vncviewer [cert-args] host:display -# -# e.g.: ss_vncviewer snoopy:0 -# ss_vncviewer snoopy:0 -encodings "copyrect tight zrle hextile" -# -# [cert-args] can be: -# -# -verify /path/to/cacert.pem -# -mycert /path/to/mycert.pem -# -crl /path/to/my_crl.pem (or directory) -# -proxy host:port -# -# -verify specifies a CA cert PEM file (or a self-signed one) for -# authenticating the VNC server. -# -# -mycert specifies this client's cert+key PEM file for the VNC server to -# authenticate this client. -# -# -proxy try host:port as a Web proxy to use the CONNECT method -# to reach the VNC server (e.g. your firewall requires a proxy). -# -# For the "double proxy" case use -proxy host1:port1,host2:port2 -# (the first CONNECT is done through host1:port1 to host2:port2 -# and then a 2nd CONNECT to the destination VNC server.) -# -# Use socks://host:port, socks4://host:port, or socks5://host,port -# to force usage of a SOCKS proxy. Also repeater://host:port and -# sslrepeater://host:port. -# -# -showcert Only fetch the certificate using the 'openssl s_client' -# command (openssl(1) must in installed). On ssvnc 1.0.27 and -# later the bundled command 'ultravnc_dsm_helper' is used. -# -# 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): -# -# -2nd Run the vncviewer a 2nd time if the first connections fails. -# -# -ssh Use ssh instead of stunnel SSL. ssh(1) must be installed and you -# must be able to log into the remote machine via ssh. -# -# In this case "host:display" may be of the form "user@host:display" -# where "user@host" is used for the ssh login (see ssh(1) manpage). -# -# If -proxy is supplied it can be of the forms: "gwhost" "gwhost:port" -# "user@gwhost" or "user@gwhost:port". "gwhost" is an incoming ssh -# gateway machine (the VNC server is not running there), an ssh -L -# redir is used to "host" in "host:display" from "gwhost". Any "user@" -# part must be in the -proxy string (not in "host:display"). -# -# Under -proxy use "gwhost:port" if connecting to any ssh port -# other than the default (22). (even for the non-gateway case, -# -proxy must be used to specify a non-standard ssh port) -# -# A "double ssh" can be specified via a -proxy string with the two -# hosts separated by a comma: -# -# [user1@]host1[:port1],[user2@]host2[:port2] -# -# in which case a ssh to host1 and thru it via a -L redir a 2nd -# ssh is established to host2. -# -# Examples: -# -# ss_vncviewer -ssh bob@bobs-home.net:0 -# ss_vncviewer -ssh -sshcmd 'x11vnc -localhost' bob@bobs-home.net:0 -# -# ss_vncviewer -ssh -proxy fred@mygate.com:2022 mymachine:0 -# ss_vncviewer -ssh -proxy bob@bobs-home.net:2222 localhost:0 -# -# ss_vncviewer -ssh -proxy fred@gw-host,fred@peecee localhost:0 -# -# -sshcmd cmd Run "cmd" via ssh instead of the default "sleep 15" -# e.g. -sshcmd 'x11vnc -display :0 -localhost -rfbport 5900' -# -# -sshargs "args" pass "args" to the ssh process, e.g. -L/-R port redirs. -# -# -sshssl Tunnel the SSL connection thru a SSH connection. The tunnel as -# under -ssh is set up and the SSL connection goes thru it. Use -# this if you want to have and end-to-end SSL connection but must -# go thru a SSH gateway host (e.g. not the vnc server). Or use -# this if you need to tunnel additional services via -R and -L -# (see -sshargs above). -# -# ss_vncviewer -sshssl -proxy fred@mygate.com mymachine:0 -# -# -listen (or -reverse) set up a reverse connection. -# -# -alpha turn on cursor alphablending hack if you are using the -# enhanced tightvnc vncviewer. -# -# -grab turn on XGrabServer hack if you are using the enhanced tightvnc -# vncviewer (e.g. for fullscreen mode in some windowmanagers like -# fvwm that do not otherwise work in fullscreen mode) -# -# -# set VNCVIEWERCMD to whatever vncviewer command you want to use. -# -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. -# - -# turn on verbose debugging output -if [ "X$SS_DEBUG" != "X" -a "X$SS_DEBUG" != "X0" ]; then - set -xv -fi - -PATH=$PATH:/usr/sbin:/usr/local/sbin:/dist/sbin; export PATH - -localhost="localhost" -if uname | grep Darwin >/dev/null; then - localhost="127.0.0.1" -fi - -# work out which stunnel to use (debian installs as stunnel4) -stunnel_set_here="" -if [ "X$STUNNEL" = "X" ]; then - check_stunnel=1 - if [ "X$SSVNC_BASEDIRNAME" != "X" ]; then - if [ -x "$SSVNC_BASEDIRNAME/stunnel" ]; then - type stunnel > /dev/null 2>&1 - if [ $? = 0 ]; then - # found ours - STUNNEL=stunnel - check_stunnel=0 - fi - fi - fi - if [ "X$check_stunnel" = "X1" ]; then - type stunnel4 > /dev/null 2>&1 - if [ $? = 0 ]; then - STUNNEL=stunnel4 - else - STUNNEL=stunnel - fi - fi - stunnel_set_here=1 -fi - -help() { - tail -n +2 "$0" | sed -e '/^$/ q' -} - -secondtry="" -gotalpha="" -use_ssh="" -use_sshssl="" -direct_connect="" -ssh_sleep=15 - -# sleep longer in -listen mode: -if echo "$*" | grep '.*-listen' > /dev/null; then - ssh_sleep=1800 -fi - - -ssh_cmd="" -# env override of ssh_cmd: -if [ "X$SS_VNCVIEWER_SSH_CMD" != "X" ]; then - ssh_cmd="$SS_VNCVIEWER_SSH_CMD" -fi - -ssh_args="" -showcert="" -reverse="" - -ciphers="" -anondh="ALL:RC4+RSA:+SSLv2:@STRENGTH" -anondh_set="" -stunnel_debug="6" -if [ "X$SS_DEBUG" != "X" -o "X$SSVNC_VENCRYPT_DEBUG" != "X" -o "X$SSVNC_STUNNEL_DEBUG" != "X" ]; then - stunnel_debug="7" -fi - -if [ "X$1" = "X-viewerflavor" ]; then - # special case, try to guess which viewer: - # - if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then - echo "unknown" - exit 0 - fi - if echo "$VNCVIEWERCMD" | grep -i chicken.of > /dev/null; then - echo "cotvnc" - exit 0 - fi - if echo "$VNCVIEWERCMD" | grep -i ultra > /dev/null; then - echo "ultravnc" - exit 0 - fi - # OK, run it for help output... - str=`$VNCVIEWERCMD -h 2>&1 | head -n 5` - if echo "$str" | grep -i 'TightVNC.viewer' > /dev/null; then - echo "tightvnc" - elif echo "$str" | grep -i 'VNC viewer version 3' > /dev/null; then - echo "realvnc3" - elif echo "$str" | grep -i 'VNC viewer .*Edition 4' > /dev/null; then - echo "realvnc4" - elif echo "$str" | grep -i 'RealVNC.Ltd' > /dev/null; then - echo "realvnc4" - else - echo "unknown" - fi - exit 0 -fi -if [ "X$1" = "X-viewerhelp" ]; then - $VNCVIEWERCMD -h 2>&1 - exit 0 -fi - -# grab our cmdline options: -while [ "X$1" != "X" ] -do - case $1 in - "-verify") shift; verify="$1" - ;; - "-mycert") shift; mycert="$1" - ;; - "-crl") shift; crl="$1" - ;; - "-proxy") shift; proxy="$1" - ;; - "-ssh") use_ssh=1 - ;; - "-sshssl") use_ssh=1 - use_sshssl=1 - ;; - "-sshcmd") shift; ssh_cmd="$1" - ;; - "-sshargs") shift; ssh_args="$1" - ;; - "-anondh") ciphers="ciphers=$anondh" - ULTRAVNC_DSM_HELPER_SHOWCERT_ADH=1 - export ULTRAVNC_DSM_HELPER_SHOWCERT_ADH - anondh_set=1 - ;; - "-ciphers") shift; ciphers="ciphers=$1" - ;; - "-alpha") gotalpha=1 - ;; - "-showcert") showcert=1 - ;; - "-listen") reverse=1 - ;; - "-reverse") reverse=1 - ;; - "-2nd") secondtry=1 - ;; - "-grab") VNCVIEWER_GRAB_SERVER=1; export VNCVIEWER_GRAB_SERVER - ;; - "-x11cursor") VNCVIEWER_X11CURSOR=1; export VNCVIEWER_X11CURSOR - ;; - "-rawlocal") VNCVIEWER_RAWLOCAL=1; export VNCVIEWER_RAWLOCAL - ;; - "-scale") shift; SSVNC_SCALE="$1"; export SSVNC_SCALE - ;; - "-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 - ;; - "-ssvnc_extra_opts") shift; VNCVIEWERCMD_EXTRA_OPTS="$1"; export VNCVIEWERCMD_EXTRA_OPTS - ;; - "-rfbversion") shift; VNCVIEWER_RFBVERSION="$1"; export VNCVIEWER_RFBVERSION - ;; - "-nobell") VNCVIEWER_NOBELL=1; export VNCVIEWER_NOBELL - ;; - "-popupfix") VNCVIEWER_POPUP_FIX=1; export VNCVIEWER_POPUP_FIX - ;; - "-realvnc4") VNCVIEWER_IS_REALVNC4=1; export VNCVIEWER_IS_REALVNC4 - ;; - "-h"*) help; exit 0 - ;; - "--h"*) help; exit 0 - ;; - *) break - ;; - esac - shift -done - -# maxconn is something we added to stunnel, this disables it: -if [ "X$SS_VNCVIEWER_NO_MAXCONN" != "X" ]; then - STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` -elif echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then - STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` -elif [ "X$reverse" != "X" ]; then - STUNNEL_EXTRA_OPTS=`echo "$STUNNEL_EXTRA_OPTS" | sed -e 's/maxconn/#maxconn/'` -else - # new way (our patches). other than the above, we set these: - if [ "X$SKIP_STUNNEL_ONCE" = "X" ]; then - STUNNEL_ONCE=1; export STUNNEL_ONCE - fi - if [ "X$SKIP_STUNNEL_MAX_CLIENTS" = "X" ]; then - STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS - fi -fi -# always set this one: -if [ "X$SKIP_STUNNEL_NO_SYSLOG" = "X" ]; then - STUNNEL_NO_SYSLOG=1; export STUNNEL_NO_SYSLOG -fi - -# this is the -t ssh option (gives better keyboard response thru SSH tunnel) -targ="-t" -if [ "X$SS_VNCVIEWER_NO_T" != "X" ]; then - targ="" -fi - -# set the alpha blending env. hack: -if [ "X$gotalpha" = "X1" ]; then - VNCVIEWER_ALPHABLEND=1 - export VNCVIEWER_ALPHABLEND -else - NO_ALPHABLEND=1 - export NO_ALPHABLEND -fi - -if [ "X$reverse" != "X" ]; then - ssh_sleep=1800 - if [ "X$proxy" != "X" ]; then - # check proxy usage under reverse connection: - if [ "X$use_ssh" = "X" -a "X$use_sshssl" = "X" ]; then - echo "" - if echo "$proxy" | egrep -i "(repeater|vencrypt)://" > /dev/null; then - : - else - echo "*Warning*: SSL -listen and a Web proxy does not make sense." - sleep 2 - fi - elif echo "$proxy" | grep "," > /dev/null; then - : - else - echo "" - echo "*Warning*: -listen and a single proxy/gateway does not make sense." - sleep 2 - fi - - # we now try to PPROXY_LOOP_THYSELF, set this var to disable that. - #SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE - fi -fi -if [ "X$ssh_cmd" = "X" ]; then - # if no remote ssh cmd, sleep a bit: - ssh_cmd="sleep $ssh_sleep" -fi - -# this should be a host:display: -# -orig="$1" -shift - -dL="-L" -if uname -sr | egrep 'SunOS 5\.[5-8]' > /dev/null; then - dL="-h" -fi - -have_uvnc_dsm_helper_showcert="" -if [ "X$showcert" = "X1" -a "X$SSVNC_USE_S_CLIENT" = "X" -a "X$reverse" = "X" ]; then - if type ultravnc_dsm_helper >/dev/null 2>&1; then - if ultravnc_dsm_helper -help 2>&1 | grep -w showcert >/dev/null; then - have_uvnc_dsm_helper_showcert=1 - fi - fi -fi -have_uvnc_dsm_helper_ipv6="" -if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - if type ultravnc_dsm_helper >/dev/null 2>&1; then - if ultravnc_dsm_helper -help 2>&1 | grep -iw ipv6 >/dev/null; then - have_uvnc_dsm_helper_ipv6=1 - fi - fi -fi - -rchk() { - # a kludge to set $RANDOM if we are not bash: - if [ "X$BASH_VERSION" = "X" ]; then - RANDOM=`date +%S``sh -c 'echo $$'``ps -elf 2>&1 | sum 2>&1 | awk '{print $1}'` - fi -} -rchk - -# a portable, but not absolutely safe, tmp file creator -mytmp() { - tf=$1 - if type mktemp > /dev/null 2>&1; then - # if we have mktemp(1), use it: - tf2="$tf.XXXXXX" - tf2=`mktemp "$tf2"` - if [ "X$tf2" != "X" -a -f "$tf2" ]; then - if [ "X$DEBUG_MKTEMP" != "X" ]; then - echo "mytmp-mktemp: $tf2" 1>&2 - fi - echo "$tf2" - return - fi - fi - # fallback to multiple cmds: - rm -rf "$tf" || exit 1 - if [ -d "$tf" ]; then - echo "tmp file $tf still exists as a directory." - exit 1 - elif [ $dL "$tf" ]; then - echo "tmp file $tf still exists as a symlink." - exit 1 - elif [ -f "$tf" ]; then - echo "tmp file $tf still exists." - exit 1 - fi - touch "$tf" || exit 1 - chmod 600 "$tf" || exit 1 - rchk - if [ "X$DEBUG_MKTEMP" != "X" ]; then - echo "mytmp-touch: $tf" 1>&2 - fi - echo "$tf" -} - -# set up special case of ultravnc single click III mode: -if echo "$proxy" | egrep "^sslrepeater://" > /dev/null; then - pstr=`echo "$proxy" | sed -e 's,sslrepeater://,,'` - pstr1=`echo "$pstr" | sed -e 's/+.*$//'` - pstr2=`echo "$pstr" | sed -e 's/^[^+]*+//'` - SSVNC_REPEATER="SCIII=$pstr2"; export SSVNC_REPEATER - orig=$pstr1 - echo - echo "reset: SSVNC_REPEATER=$SSVNC_REPEATER orig=$orig proxy=''" - proxy="" -fi -if echo "$proxy" | egrep "vencrypt://" > /dev/null; then - vtmp="/tmp/ss_handshake${RANDOM}.$$.txt" - vtmp=`mytmp "$vtmp"` - SSVNC_PREDIGESTED_HANDSHAKE="$vtmp" - export SSVNC_PREDIGESTED_HANDSHAKE - if [ "X$SSVNC_USE_OURS" = "X" ]; then - NEED_VENCRYPT_VIEWER_BRIDGE=1 - fi -fi -if [ "X$SSVNC_USE_OURS" = "X" ]; then - VNCVIEWERCMD_EXTRA_OPTS="" -fi - - -# check -ssh and -mycert/-verify conflict: -if [ "X$use_ssh" = "X1" -a "X$use_sshssl" = "X" ]; then - if [ "X$mycert" != "X" -o "X$verify" != "X" ]; then - echo "-mycert and -verify cannot be used in -ssh mode" - exit 1 - fi -fi - -# direct mode Vnc:// means show no warnings. -# direct mode vnc:// will show warnings. -if echo "$orig" | grep '^V[Nn][Cc]://' > /dev/null; then - SSVNC_NO_ENC_WARN=1 - export SSVNC_NO_ENC_WARN - orig=`echo "$orig" | sed -e 's/^...:/vnc:/'` -fi - -# interprest the pseudo URL proto:// strings: -if echo "$orig" | grep '^vnc://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vnc://,,'` - verify="" - mycert="" - crl="" - use_ssh="" - use_sshssl="" - direct_connect=1 -elif echo "$orig" | grep '^vncs://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vncs://,,'` -elif echo "$orig" | grep '^vncssl://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vncssl://,,'` -elif echo "$orig" | grep '^vnc+ssl://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vnc.ssl://,,'` -elif echo "$orig" | grep '^vncssh://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vncssh://,,'` - use_ssh=1 -elif echo "$orig" | grep '^vnc+ssh://' > /dev/null; then - orig=`echo "$orig" | sed -e 's,vnc.ssh://,,'` - use_ssh=1 -fi - -if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - verify="" - mycert="" - crl="" - use_ssh="" - use_sshssl="" - direct_connect=1 - if echo "$SSVNC_ULTRA_DSM" | grep 'noultra:' > /dev/null; then - SSVNC_NO_ULTRA_DSM=1; export SSVNC_NO_ULTRA_DSM - fi -fi - -# rsh mode is an internal/secret thing only I use. -rsh="" -if echo "$orig" | grep '^rsh://' > /dev/null; then - use_ssh=1 - rsh=1 - orig=`echo "$orig" | sed -e 's,rsh://,,'` -elif echo "$orig" | grep '^rsh:' > /dev/null; then - use_ssh=1 - rsh=1 - orig=`echo "$orig" | sed -e 's,rsh:,,'` -fi - -# play around with host:display port: -if echo "$orig" | grep ':[0-9][0-9]*$' > /dev/null; then - : -else - # add or assume :0 if no ':' - if [ "X$reverse" = "X" ]; then - orig="$orig:0" - elif [ "X$orig" = "X" ]; then - orig=":0" - fi -fi - -# extract host and disp number: - -# try to see if it is ipv6 address: -ipv6=0 -if echo "$orig" | grep '\[' > /dev/null; then - # ipv6 [fe80::219:dbff:fee5:3f92%eth1]:5900 - host=`echo "$orig" | sed -e 's/\].*$//' -e 's/\[//'` - disp=`echo "$orig" | sed -e 's/^.*\]://'` - ipv6=1 -elif echo "$orig" | grep ':..*:' > /dev/null; then - # ipv6 fe80::219:dbff:fee5:3f92%eth1:5900 - host=`echo "$orig" | sed -e 's/:[^:]*$//'` - disp=`echo "$orig" | sed -e 's/^.*://'` - ipv6=1 -else - # regular host:port - host=`echo "$orig" | awk -F: '{print $1}'` - disp=`echo "$orig" | awk -F: '{print $2}'` -fi - -if [ "X$reverse" != "X" -a "X$STUNNEL_LISTEN" = "X" -a "X$host" != "X" ]; then - STUNNEL_LISTEN=$host - echo "set STUNNEL_LISTEN=$STUNNEL_LISTEN" -fi - -if [ "X$host" = "X" ]; then - host=$localhost -fi - -if [ "X$SSVNC_IPV6" = "X0" ]; then - # disable checking for it. - ipv6=0 -#elif [ "X$reverse" != "X" -a "X$ipv6" = "X1" ]; then -# ipv6=0 -elif [ "X$ipv6" = "X1" ]; then - : -elif echo "$host" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then - : -else - # regular hostname, can't be sure... - gout="" - if type getent > /dev/null 2>/dev/null; then - gout=`getent hosts "$host" 2>/dev/null` - fi - if echo "$gout" | grep ':.*:' > /dev/null; then - if echo "$gout" | grep '^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' > /dev/null; then - : - else - echo "ipv6: "`echo "$gout" | grep ':.*:' | head -n 1` - ipv6=1 - fi - fi - if [ "X$ipv6" = "X0" ]; then - hout="" - if type host > /dev/null 2>/dev/null; then - host "$host" >/dev/null 2>&1 - host "$host" >/dev/null 2>&1 - hout=`host "$host" 2>/dev/null` - fi - if echo "$hout" | grep -i 'has ipv6 address' > /dev/null; then - if echo "$hout" | grep -i 'has address' > /dev/null; then - : - else - echo "ipv6: "`echo "$hout" | grep -i 'has ipv6 address' | head -n 1` - ipv6=1 - fi - fi - fi - if [ "X$ipv6" = "X0" ]; then - dout="" - if type dig > /dev/null 2>/dev/null; then - dout=`dig -t any "$host" 2>/dev/null` - fi - if echo "$dout" | grep -i "^$host" | grep '[ ]AAAA[ ]' > /dev/null; then - if echo "$dout" | grep -i "^$host" | grep '[ ]A[ ]' > /dev/null; then - : - else - echo "ipv6: "`echo "$dout" | grep -i '[ ]AAAA[ ]' | head -n 1` - ipv6=1 - fi - fi - fi - if [ "X$ipv6" = "X0" ]; then - sout=`env LOOKUP="$host" \ - perl -e ' eval {use Socket}; exit 0 if $@; - eval {use Socket6}; exit 0 if $@; - @res = getaddrinfo($ENV{LOOKUP}, "daytime", AF_UNSPEC, SOCK_STREAM); - $ipv4 = 0; - $ipv6 = 0; - $ip6 = ""; - while (scalar(@res) >= 5) { - ($family, $socktype, $proto, $saddr, $canon, @res) = @res; - $ipv4 = 1 if $family == AF_INET; - $ipv6 = 1 if $family == AF_INET6; - if ($family == AF_INET6 && $ip6 eq "") { - my ($host, $port) = getnameinfo($saddr, NI_NUMERICHOST | NI_NUMERICSERV); - $ip6 = $host; - } - } - if (! $ipv4 && $ipv6) { - print "AF_INET6_ONLY: $ENV{LOOKUP}: $ip6\n"; - } - exit 0; - ' 2>/dev/null` - if echo "$sout" | grep AF_INET6_ONLY > /dev/null; then - echo "$sout" - ipv6=1 - fi - fi -fi -if [ "X$ipv6" = "X1" ]; then - echo "ipv6: addr=$host disp=$disp" -fi -if [ "X$disp" = "X" ]; then - port="" # probably -listen mode. -elif [ $disp -lt 0 ]; then - # negative means use |n| without question: - port=`expr 0 - $disp` -elif [ $disp -lt 200 ]; then - # less than 200 means 5900+n - if [ "X$reverse" = "X" ]; then - port=`expr $disp + 5900` - else - port=`expr $disp + 5500` - fi -else - # otherwise use the number directly, e.g. 443, 2345 - port=$disp -fi - -if [ "X$ipv6" = "X1" -a "X$direct_connect" = "X1" ]; then - if [ "X$proxy" = "X" -a "X$reverse" = "X" ]; then - if [ "X$SSVNC_ULTRA_DSM" != "X" -a "X$have_uvnc_dsm_helper_ipv6" = "X1" ]; then - : - elif [ "X$SSVNC_NO_IPV6_PROXY" != "X" ]; then - : - elif [ "X$SSVNC_NO_IPV6_PROXY_DIRECT" != "X" ]; then - : - elif [ "X$SSVNC_USE_OURS" = "X1" ]; then - # requires 1.0.27 and later ssvncviewer binary - : - else - proxy="ipv6://$host:$port" - echo "direct connect: set proxy=$proxy" - fi - fi -fi - -# (possibly) tell the vncviewer to only listen on lo: -if [ "X$reverse" != "X" ]; then - if [ "X$direct_connect" = "X" -o "X$proxy" != "X" -o "X$STUNNEL_LISTEN" != "X" ]; then - VNCVIEWER_LISTEN_LOCALHOST=1 - export VNCVIEWER_LISTEN_LOCALHOST - fi -fi - -# try to find an open listening port via netstat(1): -inuse="" -if uname | grep Linux > /dev/null; then - inuse=`netstat -ant | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*://'` -elif uname | grep SunOS > /dev/null; then - inuse=`netstat -an -f inet -P tcp | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $1}' | sed 's/^.*\.//'` -elif uname | egrep -i 'bsd|darwin' > /dev/null; then - inuse=`netstat -ant -f inet | egrep 'LISTEN|WAIT|ESTABLISH|CLOSE' | awk '{print $4}' | sed 's/^.*\.//'` -# add others... -fi - -# this is a crude attempt for unique ports tags, etc. -date_sec=`date +%S` - -# these are special cases of no vnc, e.g. sleep or xmessage. -# these are for using ssvnc as a general port redirector. -if echo "$VNCVIEWERCMD" | grep '^sleep[ ][ ]*[0-9][0-9]*' > /dev/null; then - if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then - p=`echo "$VNCVIEWERCMD" | awk '{print $3}'` - if [ "X$p" != "X" ]; then - SS_VNCVIEWER_LISTEN_PORT=$p - fi - fi - p2=`echo "$VNCVIEWERCMD" | awk '{print $2}'` - VNCVIEWERCMD="eval sleep $p2; echo Local " -elif echo "$VNCVIEWERCMD" | grep '^xmessage[ ][ ]*[0-9][0-9]*' > /dev/null; then - if [ "X$SS_VNCVIEWER_LISTEN_PORT" = "X" ]; then - p=`echo "$VNCVIEWERCMD" | awk '{print $2}'` - SS_VNCVIEWER_LISTEN_PORT=$p - fi -fi - -# utility to find a free port to listen on. -findfree() { - try0=$1 - try=$try0 - use0="" - - if [ "X$SS_VNCVIEWER_LISTEN_PORT" != "X" ]; then - echo "$SS_VNCVIEWER_LISTEN_PORT" - return - fi - if [ $try -ge 6000 ]; then - fmax=`expr $try + 1000` - else - fmax=6000 - fi - - while [ $try -lt $fmax ] - do - if [ "X$inuse" = "X" ]; then - break - fi - if echo "$inuse" | grep -w $try > /dev/null; then - : - else - use0=$try - break - fi - try=`expr $try + 1` - done - if [ "X$use0" = "X" ]; then - use0=`expr $date_sec + $try0` - fi - - echo $use0 -} - -# utility for exiting; kills some helper processes, -# removes files, etc. -final() { - echo "" - if [ "X$tmp_cfg" != "X" ]; then - rm -f $tmp_cfg - fi - if [ "X$SS_VNCVIEWER_RM" != "X" ]; then - rm -f $SS_VNCVIEWER_RM 2>/dev/null - fi - if [ "X$tcert" != "X" ]; then - rm -f $tcert - fi - if [ "X$pssh" != "X" ]; then - echo "Terminating background ssh process" - echo kill -TERM "$pssh" - kill -TERM "$pssh" 2>/dev/null - sleep 1 - kill -KILL "$pssh" 2>/dev/null - pssh="" - fi - if [ "X$stunnel_pid" != "X" ]; then - echo "Terminating background stunnel process" - echo kill -TERM "$stunnel_pid" - kill -TERM "$stunnel_pid" 2>/dev/null - sleep 1 - kill -KILL "$stunnel_pid" 2>/dev/null - stunnel_pid="" - fi - if [ "X$dsm_pid" != "X" ]; then - echo "Terminating background ultravnc_dsm_helper process" - echo kill -TERM "$dsm_pid" - kill -TERM "$dsm_pid" 2>/dev/null - sleep 1 - kill -KILL "$dsm_pid" 2>/dev/null - stunnel_pid="" - fi - if [ "X$tail_pid" != "X" ]; then - kill -TERM $tail_pid - fi - if [ "X$tail_pid2" != "X" ]; then - kill -TERM $tail_pid2 - fi -} - -if [ "X$reverse" = "X" ]; then - # normal connections try 5930-5999: - if [ "X$showcert" = "X" ]; then - use=`findfree 5930` - else - # move away from normal place for (possibly many) -showcert - pstart=`date +%S` - pstart=`expr 6130 + $pstart + $pstart` - use=`findfree $pstart` - fi - if [ $use -ge 5900 ]; then - N=`expr $use - 5900` - else - N=$use - fi -else - # reverse connections: - p2=`expr $port + 30` - use=`findfree $p2` - if [ $use -ge 5500 ]; then - N=`expr $use - 5500` - else - N=$use - fi -fi - -# this is for my special use of ss_vncip -> vncip viewer. -if echo "$0" | grep vncip > /dev/null; then - VNCVIEWERCMD="$VNCIPCMD" -fi - -if echo "$VNCVIEWERCMD" | egrep -i '^(xmessage|sleep )' > /dev/null; then - : -elif [ "X$VNCVIEWERCMD_EXTRA_OPTS" != "X" ]; then - VNCVIEWERCMD="$VNCVIEWERCMD $VNCVIEWERCMD_EXTRA_OPTS" -fi - -# trick for the undocumented rsh://host:port method. -rsh_setup() { - if echo "$ssh_host" | grep '@' > /dev/null; then - ul=`echo "$ssh_host" | awk -F@ '{print $1}'` - ul="-l $ul" - ssh_host=`echo "$ssh_host" | awk -F@ '{print $2}'` - else - ul="" - fi - ssh_cmd=`echo "$ssh_cmd" | sed -e 's/ -localhost/ /g'` -} - -# trick for the undocumented rsh://host:port method. -rsh_viewer() { - trap "final" 0 2 15 - if [ "X$PORT" = "X" ]; then - exit 1 - elif [ $PORT -ge 5900 ]; then - vdpy=`expr $PORT - 5900` - else - vdpy=":$PORT" - fi - stty sane - echo "$VNCVIEWERCMD" "$@" $ssh_host:$vdpy - echo "" - $VNCVIEWERCMD "$@" $ssh_host:$vdpy - if [ $? != 0 ]; then - sleep 2 - $VNCVIEWERCMD "$@" $ssh_host:$vdpy - fi -} - -check_perl() { - if type "$1" > /dev/null 2>&1; then - : - elif [ ! -x "$1" ]; then - echo "" - echo "*******************************************************" - echo "** Problem finding the Perl command '$1': **" - echo "" - type "perl" - echo "" - echo "** Perhaps you need to install the Perl package. **" - echo "*******************************************************" - echo "" - sleep 5 - fi -} - -# this is the PPROXY tool. used only here for now... -pcode() { - tf=$1 - PPROXY_PROXY=$proxy; export PPROXY_PROXY - PPROXY_DEST="$host:$port"; export PPROXY_DEST - check_perl /usr/bin/perl - - cod='#!/usr/bin/perl - -# A hack to glue stunnel to a Web or SOCKS proxy, UltraVNC repeater for -# client connections. -# Also acts as a VeNCrypt bridge (by redirecting to stunnel.) - -use IO::Socket::INET; - -my $have_inet6 = ""; -eval "use IO::Socket::INET6;"; -$have_inet6 = 1 if $@ eq ""; - -#my $have_sock6 = ""; -#eval "use Socket; use Socket6;"; -#$have_sock6 = 1 if $@ eq ""; - -if (exists $ENV{PPROXY_LOOP_THYSELF}) { - # used for reverse vnc, run a repeating outer loop. - print STDERR "PPROXY_LOOP: $ENV{PPROXY_LOOP_THYSELF}\n"; - my $rm = $ENV{PPROXY_REMOVE}; - my $lp = $ENV{PPROXY_LOOP_THYSELF}; - delete $ENV{PPROXY_REMOVE}; - delete $ENV{PPROXY_LOOP_THYSELF}; - $ENV{PPROXY_LOOP_THYSELF_MASTER} = $$; - my $pid = $$; - my $dbg = 0; - my $c = 0; - use POSIX ":sys_wait_h"; - while (1) { - $pid = fork(); - last if ! defined $pid; - if ($pid eq "0") { - last; - } - $c++; - print STDERR "\nPPROXY_LOOP: pid=$$ child=$pid count=$c\n"; - while (1) { - waitpid(-1, WNOHANG); - fsleep(0.25); - if (! kill 0, $pid) { - print STDERR "PPROXY_LOOP: child=$pid gone.\n"; - last; - } - print STDERR "PPROXY_LOOP: child=$pid alive.\n" if $dbg; - if (! -f $lp) { - print STDERR "PPROXY_LOOP: flag file $lp gone, killing $pid\n"; - kill TERM, $pid; - fsleep(0.1); - wait; - last; - } - print STDERR "PPROXY_LOOP: file exists $lp\n" if $dbg; - } - last if ! -f $lp; - fsleep(0.25); - } - if ($pid ne "0") { - unlink($0) if $rm; - exit 0; - } -} - -if (exists $ENV{PPROXY_SLEEP} && $ENV{PPROXY_SLEEP} > 0) { - print STDERR "PPROXY_PID: $$\n"; - sleep $ENV{PPROXY_SLEEP}; -} - -foreach my $var (qw( - PPROXY_DEST - PPROXY_KILLPID - PPROXY_LISTEN - PPROXY_PROXY - PPROXY_REMOVE - PPROXY_REPEATER - PPROXY_REVERSE - PPROXY_SLEEP - PPROXY_SOCKS - PPROXY_VENCRYPT - PPROXY_VENCRYPT_VIEWER_BRIDGE - )) { - if (0 || $ENV{SS_DEBUG} || $ENV{SSVNC_VENCRYPT_DEBUG}) { - print STDERR "$var: $ENV{$var}\n"; - } -} - -if ($ENV{PPROXY_SOCKS} ne "" && $ENV{PPROXY_PROXY} !~ m,^socks5?://,i) { - if ($ENV{PPROXY_SOCKS} eq "5") { - $ENV{PPROXY_PROXY} = "socks5://$ENV{PPROXY_PROXY}"; - } else { - $ENV{PPROXY_PROXY} = "socks://$ENV{PPROXY_PROXY}"; - } -} - -my $rfbSecTypeAnonTls = 18; -my $rfbSecTypeVencrypt = 19; - -my $rfbVencryptPlain = 256; -my $rfbVencryptTlsNone = 257; -my $rfbVencryptTlsVnc = 258; -my $rfbVencryptTlsPlain = 259; -my $rfbVencryptX509None = 260; -my $rfbVencryptX509Vnc = 261; -my $rfbVencryptX509Plain = 262; - -my $handshake_file = ""; -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; -} - -my $listen_handle = ""; -my $sock = ""; -my $parent = $$; - -my $initial_data = ""; - -if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { - my ($from, $to) = split(/,/, $ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}); - do_vencrypt_viewer_bridge($from, $to); - exit 0; -} - -my ($first, $second, $third) = split(/,/, $ENV{PPROXY_PROXY}, 3); -my ($mode_1st, $mode_2nd, $mode_3rd) = ("", "", ""); - -($first, $mode_1st) = url_parse($first); - -my ($proxy_host, $proxy_port) = ($first, ""); -if ($proxy_host =~ /^(.*):(\d+)$/) { - $proxy_host = $1; - $proxy_port = $2; -} -my $connect = $ENV{PPROXY_DEST}; - -if ($second ne "") { - ($second, $mode_2nd) = url_parse($second); -} - -if ($third ne "") { - ($third, $mode_3rd) = url_parse($third); -} - - -print STDERR "\n"; -print STDERR "PPROXY v0.4: a tool for Web, SOCKS, and UltraVNC proxies and for\n"; -print STDERR "PPROXY v0.4: IPv6 and VNC VeNCrypt bridging.\n"; -print STDERR "proxy_host: $proxy_host\n"; -print STDERR "proxy_port: $proxy_port\n"; -print STDERR "proxy_connect: $connect\n"; -print STDERR "pproxy_params: $ENV{PPROXY_PROXY}\n"; -print STDERR "pproxy_listen: $ENV{PPROXY_LISTEN}\n"; -print STDERR "pproxy_reverse: $ENV{PPROXY_REVERSE}\n"; -print STDERR "io_socket_inet6: $have_inet6\n"; -print STDERR "\n"; -if (! $have_inet6) { - print STDERR "PPROXY: To enable IPv6 connections, install the IO::Socket::INET6 perl module.\n\n"; -} - -if (1) { - print STDERR "pproxy 1st: $first\t- $mode_1st\n"; - print STDERR "pproxy 2nd: $second\t- $mode_2nd\n"; - print STDERR "pproxy 3rd: $third\t- $mode_3rd\n"; - print STDERR "\n"; -} - -sub pdie { - my $msg = shift; - kill_proxy_pids(); - die "$msg"; -} - -if ($ENV{PPROXY_REVERSE} ne "") { - my ($rhost, $rport) = ($ENV{PPROXY_REVERSE}, ""); - if ($rhost =~ /^(.*):(\d+)$/) { - $rhost = $1; - $rport = $2; - } - $rport = 5900 unless $rport; - my $emsg = ""; - $listen_handle = IO::Socket::INET->new( - PeerAddr => $rhost, - PeerPort => $rport, - Proto => "tcp" - ); - $emsg = $!; - if (! $listen_handle && $have_inet6) { - eval {$listen_handle = IO::Socket::INET6->new( - PeerAddr => $rhost, - PeerPort => $rport, - Proto => "tcp" - );}; - $emsg .= " / $!"; - } - if (! $listen_handle) { - pdie "pproxy: $emsg -- PPROXY_REVERSE\n"; - } - print STDERR "PPROXY_REVERSE: connected to $rhost $rport\n"; - -} elsif ($ENV{PPROXY_LISTEN} ne "") { - my $listen_sock = ""; - my $maxtry = 12; - my $sleep = 5; - my $p2 = ""; - my $emsg = ""; - for (my $i=0; $i < $maxtry; $i++) { - my ($if, $p) = ("", $ENV{PPROXY_LISTEN}); - if ($p =~ /^(.*):(\d+)$/) { - $if = $1; - $p = $2; - } - $p2 = "*:$p"; - if ($if eq "") { - $if = "localhost"; - } - print STDERR "pproxy interface: $if\n"; - - $emsg = ""; - if (($if eq "INADDR_ANY6" || $if eq "::") && $have_inet6) { - eval {$listen_sock = IO::Socket::INET6->new( - Listen => 2, - ReuseAddr => 1, - Domain => AF_INET6, - LocalAddr => "::", - LocalPort => $p, - Proto => "tcp" - );}; - $p2 = ":::$p"; - } elsif ($if =~ /^INADDR_ANY/) { - $listen_sock = IO::Socket::INET->new( - Listen => 2, - ReuseAddr => 1, - LocalPort => $p, - Proto => "tcp" - ); - } elsif (($if eq "INADDR_LOOPBACK6" || $if eq "::1") && $have_inet6) { - $p2 = "::1:$p"; - eval {$listen_sock = IO::Socket::INET6->new( - Listen => 2, - ReuseAddr => 1, - Domain => AF_INET6, - LocalAddr => "::1", - LocalPort => $p, - Proto => "tcp" - );}; - $p2 = "::1:$p"; - } else { - $p2 = "$if:$p"; - $listen_sock = IO::Socket::INET->new( - Listen => 2, - ReuseAddr => 1, - LocalAddr => $if, - LocalPort => $p, - Proto => "tcp" - ); - $emsg = $!; - - if (! $listen_sock && $have_inet6) { - print STDERR "PPROXY_LISTEN: retry with INET6\n"; - eval {$listen_sock = IO::Socket::INET6->new( - Listen => 2, - ReuseAddr => 1, - Domain => AF_INET6, - LocalAddr => $if, - LocalPort => $p, - Proto => "tcp" - );}; - $emsg .= " / $!"; - } - } - if (! $listen_sock) { - if ($i < $maxtry - 1) { - warn "pproxy: $emsg $!\n"; - warn "Could not listen on port $p2, retrying in $sleep seconds... (Ctrl-C to quit)\n"; - sleep $sleep; - } - } else { - last; - } - } - if (! $listen_sock) { - pdie "pproxy: $emsg -- PPROXY_LISTEN\n"; - } - print STDERR "pproxy: listening on $p2\n"; - my $ip; - ($listen_handle, $ip) = $listen_sock->accept(); - my $err = $!; - close $listen_sock; - if (! $listen_handle) { - pdie "pproxy: $err\n"; - } - - if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) { - my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; - if ($sml ne "" && $sml ne "0") { - setpgrp(0, 0); - if (fork()) { - close $viewer_sock; - wait; - exit 0; - } - if (fork()) { - close $viewer_sock; - exit 0; - } - setpgrp(0, 0); - $parent = $$; - } - } -} - -$sock = IO::Socket::INET->new( - PeerAddr => $proxy_host, - PeerPort => $proxy_port, - Proto => "tcp" -); - -my $err = ""; - -if (! $sock && $have_inet6) { - $err = $!; - - print STDERR "pproxy: $!\n"; - - eval {$sock = IO::Socket::INET6->new( - PeerAddr => $proxy_host, - PeerPort => $proxy_port, - Proto => "tcp" - );}; - $err .= " / $!"; -} - -if (! $sock && ($proxy_host =~ /^::ffff:(\d+\.\d+\.\d+\.\d+)$/i || $proxy_host =~ /^::ffff:([\da-f]+:[\da-f]+)$/i)) { - print STDERR "pproxy: $!\n"; - my $ipv4_addr = $1; - if ($ipv4_addr =~ /:/) { - my ($a, $b) = split(/:/, $ipv4_addr); - $a = hex($a); - $b = hex($b); - $ipv4_addr = sprintf("%d.", ($a & 0xff00) >> 8); - $ipv4_addr .= sprintf("%d.", ($a & 0x00ff)); - $ipv4_addr .= sprintf("%d.", ($b & 0xff00) >> 8); - $ipv4_addr .= sprintf("%d", ($b & 0x00ff)); - } - - print STDERR "pproxy: re-trying with ipv4 addr: $ipv4_addr\n"; - - eval {$sock = IO::Socket::INET->new( - PeerAddr => $ipv4_addr, - PeerPort => $proxy_port, - Proto => "tcp" - );}; - $err .= " / $!"; -} - -if (! $sock) { - unlink($0) if $ENV{PPROXY_REMOVE}; - pdie "pproxy: $err\n"; -} - -unlink($0) if $ENV{PPROXY_REMOVE}; - -if ($ENV{PPROXY_PROXY} =~ /^vencrypt:/ && $ENV{PPROXY_VENCRYPT_REVERSE}) { - print STDERR "\nPPROXY: vencrypt+reverse: swapping listen socket with connect socket.\n"; - my $tmp_swap = $sock; - $sock = $listen_handle; - $listen_handle = $tmp_swap; -} - -$cur_proxy = $first; -setmode($mode_1st); - -if ($second ne "") { - connection($second, 1); - - setmode($mode_2nd); - $cur_proxy = $second; - - if ($third ne "") { - connection($third, 2); - setmode($mode_3rd); - $cur_proxy = $third; - connection($connect, 3); - } else { - connection($connect, 2); - } -} else { - connection($connect, 1); -} - -sub kill_proxy_pids() { - if ($ENV{PPROXY_VENCRYPT_VIEWER_BRIDGE}) { - return; - } - if ($ENV{PPROXY_KILLPID}) { - foreach my $p (split(/,/, $ENV{PPROXY_KILLPID})) { - if ($p =~ /^(\+|-)/) { - $p = $parent + $p; - } - print STDERR "kill TERM, $p (PPROXY_KILLPID)\n"; - kill "TERM", $p; - } - } -} - -sub xfer { - my($in, $out) = @_; - $RIN = $WIN = $EIN = ""; - $ROUT = ""; - vec($RIN, fileno($in), 1) = 1; - vec($WIN, fileno($in), 1) = 1; - $EIN = $RIN | $WIN; - - while (1) { - my $nf = 0; - while (! $nf) { - $nf = select($ROUT=$RIN, undef, undef, undef); - } - my $len = sysread($in, $buf, 8192); - if (! defined($len)) { - next if $! =~ /^Interrupted/; - print STDERR "pproxy[$$]: $!\n"; - last; - } elsif ($len == 0) { - print STDERR "pproxy[$$]: Input is EOF.\n"; - last; - } - my $offset = 0; - my $quit = 0; - while ($len) { - my $written = syswrite($out, $buf, $len, $offset); - if (! defined $written) { - print STDERR "pproxy[$$]: Output is EOF. $!\n"; - $quit = 1; - last; - } - $len -= $written; - $offset += $written; - } - last if $quit; - } - close($out); - close($in); - print STDERR "pproxy[$$]: finished xfer.\n"; -} - -sub handler { - print STDERR "pproxy[$$]: got SIGTERM.\n"; - close $listen_handle if $listen_handle; - close $sock if $sock; - exit; -} - -sub xfer_both { - $child = fork; - - if (! defined $child) { - kill_proxy_pids(); - exit 1; - } - - $SIG{TERM} = "handler"; - - if ($child) { - if ($listen_handle) { - print STDERR "pproxy parent[$$] listen_handle -> socket\n"; - xfer($listen_handle, $sock); - } else { - print STDERR "pproxy parent[$$] STDIN -> socket\n"; - xfer(STDIN, $sock); - } - select(undef, undef, undef, 0.25); - if (kill 0, $child) { - select(undef, undef, undef, 0.9); - if (kill 0, $child) { - print STDERR "pproxy[$$]: kill TERM child $child\n"; - kill "TERM", $child; - } else { - print STDERR "pproxy[$$]: child $child gone.\n"; - } - } - } else { - select(undef, undef, undef, 0.05); - if ($listen_handle) { - print STDERR "pproxy child [$$] socket -> listen_handle\n"; - if ($initial_data ne "") { - my $len = length $initial_data; - print STDERR "pproxy child [$$] sending initial_data, length $len\n\n"; - syswrite($listen_handle, $initial_data, $len); - } else { - print STDERR "\n"; - } - xfer($sock, $listen_handle); - } else { - print STDERR "pproxy child [$$] socket -> STDOUT\n"; - if ($initial_data ne "") { - my $len = length $initial_data; - print STDERR "pproxy child [$$] sending initial_data, length $len\n\n"; - syswrite(STDOUT, $initial_data, $len); - } else { - print STDERR "\n"; - } - xfer($sock, STDOUT); - } - select(undef, undef, undef, 0.25); - if (kill 0, $parent) { - select(undef, undef, undef, 0.8); - if (kill 0, $parent) { - print STDERR "pproxy[$$]: kill TERM parent $parent\n"; - kill "TERM", $parent; - } else { - print STDERR "pproxy[$$]: parent $parent gone.\n"; - } - } - } - - kill_proxy_pids(); -} - -xfer_both(); - -exit; - -sub fsleep { - select(undef, undef, undef, shift); -} - -sub url_parse { - my $hostport = shift; - my $mode = "http"; - if ($hostport =~ m,^socks4?://(\S*)$,i) { - $mode = "socks4"; - $hostport = $1; - } elsif ($hostport =~ m,^socks5://(\S*)$,i) { - $mode = "socks5"; - $hostport = $1; - } elsif ($hostport =~ m,^https?://(\S*)$,i) { - $mode = "http"; - $hostport = $1; - } elsif ($hostport =~ m,^ipv6://(\S*)$,i) { - $mode = "ipv6"; - $hostport = $1; - } elsif ($hostport =~ m,^repeater://(\S*)\+(\S*)$,i) { - # ultravnc repeater proxy. - $hostport = $1; - $mode = "repeater:$2"; - if ($hostport !~ /:\d+$/) { - $hostport .= ":5900"; - } - } elsif ($hostport =~ m,^vencrypt://(\S*)$,i) { - # vencrypt handshake. - $hostport = $1; - my $m = "connect"; - if ($hostpost =~ /^(\S+)\+(\S+)$/) { - $hostport = $1; - $mode = $2; - } - $mode = "vencrypt:$m"; - if ($hostport !~ /:\d+$/) { - $hostport .= ":5900"; - } - } - return ($hostport, $mode); -} - -sub setmode { - my $mode = shift; - $ENV{PPROXY_REPEATER} = ""; - $ENV{PPROXY_VENCRYPT} = ""; - if ($mode =~ /^socks/) { - if ($mode =~ /^socks5/) { - $ENV{PPROXY_SOCKS} = 5; - } else { - $ENV{PPROXY_SOCKS} = 1; - } - } elsif ($mode =~ /^ipv6/i) { - $ENV{PPROXY_SOCKS} = 0; - } elsif ($mode =~ /^repeater:(.*)/) { - $ENV{PPROXY_REPEATER} = $1; - $ENV{PPROXY_SOCKS} = ""; - } elsif ($mode =~ /^vencrypt:(.*)/) { - $ENV{PPROXY_VENCRYPT} = $1; - $ENV{PPROXY_SOCKS} = ""; - } else { - $ENV{PPROXY_SOCKS} = ""; - } -} - -sub connection { - my ($CONNECT, $w) = @_; - - my $con = ""; - my $msg = ""; - - if ($ENV{PPROXY_SOCKS} eq "5") { - # SOCKS5 - my ($h, $p) = ($CONNECT, ""); - if ($h =~ /^(.*):(\d+)$/) { - $h = $1; - $p = $2; - } - $con .= pack("C", 0x05); - $con .= pack("C", 0x01); - $con .= pack("C", 0x00); - - $msg = "SOCKS5 via $cur_proxy to $h:$p\n\n"; - print STDERR "proxy_request$w: $msg"; - - syswrite($sock, $con, length($con)); - - my ($n1, $n2, $n3, $n4, $n5, $n6); - my ($r1, $r2, $r3, $r4, $r5, $r6); - my ($s1, $s2, $s3, $s4, $s5, $s6); - - $n1 = sysread($sock, $r1, 1); - $n2 = sysread($sock, $r2, 1); - - $s1 = unpack("C", $r1); - $s2 = unpack("C", $r2); - if ($s1 != 0x05 || $s2 != 0x00) { - print STDERR "SOCKS5 fail s1=$s1 s2=$s2 n1=$n1 n2=$n2\n"; - close $sock; - exit(1); - } - - $con = ""; - $con .= pack("C", 0x05); - $con .= pack("C", 0x01); - $con .= pack("C", 0x00); - $con .= pack("C", 0x03); - $con .= pack("C", length($h)); - $con .= $h; - $con .= pack("C", $p >> 8); - $con .= pack("C", $p & 0xff); - - syswrite($sock, $con, length($con)); - - $n1 = sysread($sock, $r1, 1); - $n2 = sysread($sock, $r2, 1); - $n3 = sysread($sock, $r3, 1); - $n4 = sysread($sock, $r4, 1); - $s1 = unpack("C", $r1); - $s2 = unpack("C", $r2); - $s3 = unpack("C", $r3); - $s4 = unpack("C", $r4); - - if ($s4 == 0x1) { - sysread($sock, $r5, 4 + 2); - } elsif ($s4 == 0x3) { - sysread($sock, $r5, 1); - $s5 = unpack("C", $r5); - sysread($sock, $r6, $s5 + 2); - } elsif ($s4 == 0x4) { - sysread($sock, $r5, 16 + 2); - } - - if ($s1 != 0x5 || $s2 != 0x0 || $s3 != 0x0) { - print STDERR "SOCKS5 failed: s1=$s1 s2=$s2 s3=$s3 s4=$s4 n1=$n1 n2=$n2 n3=$n3 n4=$n4\n"; - close $sock; - exit(1); - } - - } elsif ($ENV{PPROXY_SOCKS} eq "1") { - # SOCKS4 SOCKS4a - my ($h, $p) = ($CONNECT, ""); - if ($h =~ /^(.*):(\d+)$/) { - $h = $1; - $p = $2; - } - $con .= pack("C", 0x04); - $con .= pack("C", 0x01); - $con .= pack("n", $p); - - my $SOCKS_4a = 0; - if ($h eq "localhost" || $h eq "127.0.0.1") { - $con .= pack("C", 127); - $con .= pack("C", 0); - $con .= pack("C", 0); - $con .= pack("C", 1); - } elsif ($h =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { - $con .= pack("C", $1); - $con .= pack("C", $2); - $con .= pack("C", $3); - $con .= pack("C", $4); - } else { - $con .= pack("C", 0); - $con .= pack("C", 0); - $con .= pack("C", 0); - $con .= pack("C", 3); - $SOCKS_4a = 1; - } - - $con .= "nobody"; - $con .= pack("C", 0); - - $msg = "SOCKS4 via $cur_proxy to $h:$p\n\n"; - if ($SOCKS_4a) { - $con .= $h; - $con .= pack("C", 0); - $msg =~ s/SOCKS4/SOCKS4a/; - } - print STDERR "proxy_request$w: $msg"; - syswrite($sock, $con, length($con)); - - my $ok = 1; - for (my $i = 0; $i < 8; $i++) { - my $c; - sysread($sock, $c, 1); - my $s = unpack("C", $c); - if ($i == 0) { - $ok = 0 if $s != 0x0; - } elsif ($i == 1) { - $ok = 0 if $s != 0x5a; - } - } - if (! $ok) { - print STDERR "SOCKS4 failed.\n"; - close $sock; - exit(1); - } - } elsif ($ENV{PPROXY_SOCKS} eq "0") { - # hack for ipv6 "proxy", nothing to do, assume INET6 call worked. - ; - } elsif ($ENV{PPROXY_REPEATER} ne "") { - my $rep = $ENV{PPROXY_REPEATER}; - print STDERR "repeater: $rep\n"; - $rep .= pack("x") x 250; - syswrite($sock, $rep, 250); - - my $rfb = ""; - - my $ok = 1; - for (my $i = 0; $i < 12; $i++) { - my $c; - last if $ENV{PPROXY_GENERIC_REPEATER}; - sysread($sock, $c, 1); - print STDERR $c; - $rfb .= $c; - } - if ($rfb ne "" && $rfb !~ /^RFB 000\.000/) { - $initial_data = $rfb; - $rfb =~ s/\n//g; - print STDERR "detected non-UltraVNC repeater; forwarding \"$rfb\"\nlength: ", length($initial_data), "\n"; - } - } elsif ($ENV{PPROXY_VENCRYPT} ne "") { - my $vencrypt = $ENV{PPROXY_VENCRYPT}; - vencrypt_dialog($vencrypt); - - } else { - # Web Proxy: - $con = "CONNECT $CONNECT HTTP/1.1\r\n"; - $con .= "Host: $CONNECT\r\n"; - $con .= "Connection: close\r\n\r\n"; - $msg = $con; - - print STDERR "proxy_request$w: via $cur_proxy:\n$msg"; - syswrite($sock, $con, length($con)); - - my $rep = ""; - my $n = 0; - while ($rep !~ /\r\n\r\n/ && $n < 30000) { - my $c; - sysread($sock, $c, 1); - print STDERR $c; - $rep .= $c; - $n++; - } - if ($rep !~ m,HTTP/.* 200,) { - print STDERR "HTTP CONNECT failed.\n"; - close $sock; - exit(1); - } - } -} - -sub vdie { - append_handshake("done\n"); - close $sock; - kill_proxy_pids(); - exit(1); -} - -sub anontls_handshake { - my ($vmode, $db) = @_; - - print STDERR "\nPPROXY: Doing ANONTLS Handshake\n"; - - my $psec = pack("C", $rfbSecTypeAnonTls); - syswrite($sock, $psec, 1); - - append_handshake("done\n"); -} - -sub vencrypt_handshake { - - my ($vmode, $db) = @_; - - print STDERR "\nPPROXY: Doing VeNCrypt Handshake\n"; - - my $psec = pack("C", $rfbSecTypeVencrypt); - - if (exists $ENV{SSVNC_TEST_SEC_TYPE}) { - my $fake = $ENV{SSVNC_TEST_SEC_TYPE}; - print STDERR "PPROXY: sending sec-type: $fake\n"; - $psec = pack("C", $fake); - } - - syswrite($sock, $psec, 1); - - my $vmajor; - my $vminor; - sysread($sock, $vmajor, 1); - sysread($sock, $vminor, 1); - - vdie if $vmajor eq "" || $vminor eq ""; - - $vmajor = unpack("C", $vmajor); - $vminor = unpack("C", $vminor); - print STDERR "server vencrypt version $vmajor.$vminor\n" if $db; - - if (exists $ENV{SSVNC_TEST_SEC_TYPE}) { - print STDERR "PPROXY: continuing on in test mode.\n"; - } else { - vdie if $vmajor ne 0; - vdie if $vminor < 2; - } - - $vmajor = pack("C", 0); - $vminor = pack("C", 2); - append_handshake("subversion=0.2\n"); - - syswrite($sock, $vmajor, 1); - syswrite($sock, $vminor, 1); - - my $result; - sysread($sock, $result, 1); - print STDERR "result empty\n" if $db && $result eq ""; - - vdie if $result eq ""; - $result = unpack("C", $result); - print STDERR "result=$result\n" if $db; - - vdie if $result ne 0; - - my $nsubtypes; - sysread($sock, $nsubtypes, 1); - - vdie if $nsubtypes eq ""; - $nsubtypes = unpack("C", $nsubtypes); - print STDERR "nsubtypes=$nsubtypes\n" if $db; - - my %subtypes; - - for (my $i = 0; $i < $nsubtypes; $i++) { - my $subtype = ""; - sysread($sock, $subtype, 4); - vdie if length($subtype) != 4; - - # XXX fix 64bit. - $subtype = unpack("N", $subtype); - print STDERR "subtype: $subtype\n" if $db; - $subtypes{$subtype} = 1; - append_handshake("sst$i=$subtype\n"); - } - - my $subtype = 0; - if (exists $subtypes{$rfbVencryptX509None}) { - $subtype = $rfbVencryptX509None; - print STDERR "selected rfbVencryptX509None\n" if $db; - } elsif (exists $subtypes{$rfbVencryptX509Vnc}) { - $subtype = $rfbVencryptX509Vnc; - print STDERR "selected rfbVencryptX509Vnc\n" if $db; - } elsif (exists $subtypes{$rfbVencryptX509Plain}) { - $subtype = $rfbVencryptX509Plain; - print STDERR "selected rfbVencryptX509Plain\n" if $db; - } elsif (exists $subtypes{$rfbVencryptTlsNone}) { - $subtype = $rfbVencryptTlsNone; - print STDERR "selected rfbVencryptTlsNone\n" if $db; - } elsif (exists $subtypes{$rfbVencryptTlsVnc}) { - $subtype = $rfbVencryptTlsVnc; - print STDERR "selected rfbVencryptTlsVnc\n" if $db; - } elsif (exists $subtypes{$rfbVencryptTlsPlain}) { - $subtype = $rfbVencryptTlsPlain; - print STDERR "selected rfbVencryptTlsPlain\n" if $db; - } - - if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) { - my $fake = $ENV{SSVNC_TEST_SEC_SUBTYPE}; - print STDERR "PPROXY: sending sec-subtype: $fake\n"; - $subtype = $fake; - } - - append_handshake("subtype=$subtype\n"); - - my $pst = pack("N", $subtype); - syswrite($sock, $pst, 4); - - if (exists $ENV{SSVNC_TEST_SEC_SUBTYPE}) { - print STDERR "PPROXY: continuing on in test mode.\n"; - } else { - vdie if $subtype == 0; - } - - my $ok; - sysread($sock, $ok, 1); - $ok = unpack("C", $ok); - print STDERR "ok=$ok\n" if $db; - - append_handshake("done\n"); - - vdie if $ok == 0; -} - -sub vencrypt_dialog { - my $vmode = shift; - my $db = 0; - - $db = 1 if exists $ENV{SS_DEBUG}; - $db = 1 if exists $ENV{SSVNC_VENCRYPT_DEBUG}; - - append_handshake("mode=$vmode\n"); - - my $server_rfb = ""; - #syswrite($sock, $rep, 250); - for (my $i = 0; $i < 12; $i++) { - my $c; - sysread($sock, $c, 1); - $server_rfb .= $c; - print STDERR $c; - } - print STDERR "server_rfb: $server_rfb\n" if $db; - append_handshake("server=$server_rfb"); - - my $minor = ""; - if ($server_rfb =~ /^RFB 003\.(\d+)/) { - $minor = $1; - } else { - vdie; - } - my $viewer_rfb = "RFB 003.008\n"; - if ($minor < 7) { - vdie; - } elsif ($minor == 7) { - $viewer_rfb = "RFB 003.007\n"; - } - 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); - - print STDERR "nsec: $nsec\n" if $db; - vdie if $nsec eq 0 || $nsec > 100; - - my %sectypes = (); - - for (my $i = 0; $i < $nsec; $i++) { - my $sec; - sysread($sock, $sec, 1); - vdie if $sec eq ""; - $sec = unpack("C", $sec); - print STDERR "sec: $sec\n" if $db; - $sectypes{$sec} = 1; - } - - if (exists $sectypes{$rfbSecTypeVencrypt}) { - print STDERR "found rfbSecTypeVencrypt\n" if $db; - append_handshake("sectype=$rfbSecTypeVencrypt\n"); - vencrypt_handshake($vmode, $db); - } elsif (exists $sectypes{$rfbSecTypeAnonTls}) { - print STDERR "found rfbSecTypeAnonTls\n" if $db; - append_handshake("sectype=$rfbSecTypeAnonTls\n"); - anontls_handshake($vmode, $db); - } else { - print STDERR "No supported sec-type found\n" if $db; - vdie; - } -} - -sub append_handshake { - my $str = shift; - if ($handshake_file) { - if (open(HSF, ">>$handshake_file")) { - print HSF $str; - close HSF; - } - } -} - -sub do_vencrypt_viewer_bridge { - my ($listen, $connect) = @_; - print STDERR "\npproxy: starting vencrypt_viewer_bridge[$$]: $listen \-> $connect\n"; - my $db = 0; - my $backwards = 0; - if ($listen < 0) { - $backwards = 1; - $listen = -$listen; - } - if ($handshake_file eq "") { - die "pproxy: vencrypt_viewer_bridge[$$]: no SSVNC_PREDIGESTED_HANDSHAKE\n"; - } - my $listen_sock; - my $maxtry = 12; - my $sleep = 5; - for (my $i=0; $i < $maxtry; $i++) { - $listen_sock = IO::Socket::INET->new( - Listen => 2, - ReuseAddr => 1, - LocalAddr => "127.0.0.1", - LocalPort => $listen, - Proto => "tcp" - ); - if (! $listen_sock) { - if ($i < $maxtry - 1) { - warn "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; - warn "Could not listen on port $listen, retrying in $sleep seconds... (Ctrl-C to quit)\n"; - sleep $sleep; - } - } else { - last; - } - } - if (! $listen_sock) { - die "pproxy: vencrypt_viewer_bridge[$$]: $!\n"; - } - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: listening on port $listen\n\n"; - my ($viewer_sock, $ip) = $listen_sock->accept(); - my $err = $!; - close $listen_sock; - if (! $viewer_sock) { - die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; - } - if ($ENV{PPROXY_LOOP_THYSELF_MASTER}) { - my $sml = $ENV{SSVNC_MULTIPLE_LISTEN}; - if ($sml ne "" && $sml ne "0") { - setpgrp(0, 0); - if (fork()) { - close $viewer_sock; - wait; - exit 0; - } - if (fork()) { - close $viewer_sock; - exit 0; - } - setpgrp(0, 0); - $parent = $$; - } - } - print STDERR "vencrypt_viewer_bridge[$$]: viewer_sock $viewer_sock\n" if $db; - - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: connecting to 127.0.0.1:$connect\n"; - my $server_sock = IO::Socket::INET->new( - PeerAddr => "127.0.0.1", - PeerPort => $connect, - Proto => "tcp" - ); - print STDERR "vencrypt_viewer_bridge[$$]: server_sock $server_sock\n" if $db; - if (! $server_sock) { - my $err = $!; - die "pproxy: vencrypt_viewer_bridge[$$]: $err\n"; - } - - if ($backwards) { - print STDERR "vencrypt_viewer_bridge[$$]: reversing roles of viewer and server.\n"; - my $t = $viewer_sock; - $viewer_sock = $server_sock; - $server_sock = $t; - } - - my %hs = (); - my $dt = 0.2; - my $slept = 0.0; - while ($slept < 20.0) { - select(undef, undef, undef, $dt); - $slept += $dt; - if (-f $handshake_file && open(HSF, "<$handshake_file")) { - my $done = 0; - %hs = (); - my $str = ""; - while () { - print STDERR "vencrypt_viewer_bridge[$$]: $_" if $ENV{VENCRYPT_VIEWER_BRIDGE_DEBUG}; - $str .= "vencrypt_viewer_bridge[$$]: $_"; - chomp; - if ($_ eq "done") { - $done = 1; - } else { - my ($k, $v) = split(/=/, $_, 2); - if ($k ne "" && $v ne "") { - $hs{$k} = $v; - } - } - } - close HSF; - if ($done) { - print STDERR "\n" . $str; - last; - } - } - } - if (! exists $hs{server}) { - $hs{server} = "RFB 003.008"; - } - if (! exists $hs{sectype}) { - unlink($handshake_file); - die "pproxy: vencrypt_viewer_bridge[$$]: no sectype.\n"; - } - syswrite($viewer_sock, "$hs{server}\n", length($hs{server}) + 1); - my $viewer_rfb = ""; - for (my $i = 0; $i < 12; $i++) { - my $c; - sysread($viewer_sock, $c, 1); - $viewer_rfb .= $c; - print STDERR $c; - } - my $viewer_major = 3; - my $viewer_minor = 8; - if ($viewer_rfb =~ /RFB (\d+)\.(\d+)/) { - $viewer_major = $1; - $viewer_minor = $2; - } - my $u0 = pack("C", 0); - my $u1 = pack("C", 1); - my $u2 = pack("C", 2); - if ($hs{sectype} == $rfbSecTypeAnonTls) { - unlink($handshake_file); - print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeAnonTls\n"; - if ($viewer_major > 3 || $viewer_minor >= 7) { - ; # setup ok, proceed to xfer. - } else { - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; - my $n; - sysread($server_sock, $n, 1); - $n = unpack("C", $n); - if ($n == 0) { - die "pproxy: vencrypt_viewer_bridge[$$]: nsectypes == $n.\n"; - } - my %types; - for (my $i = 0; $i < $n; $i++) { - my $t; - sysread($server_sock, $t, 1); - $t = unpack("C", $t); - $types{$t} = 1; - } - my $use = 1; # None - if (exists $types{1}) { - $use = 1; # None - } elsif (exists $types{2}) { - $use = 2; # VncAuth - } else { - die "pproxy: vencrypt_viewer_bridge[$$]: no valid sectypes" . join(",", keys %types) . "\n"; - } - - # send 4 bytes sectype to viewer: - # (note this should be MSB, network byte order...) - my $up = pack("C", $use); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $up, 1); - # and tell server the one we selected: - syswrite($server_sock, $up, 1); - if ($use == 1) { - # even None has security result, so read it here and discard it. - my $sr = ""; - sysread($server_sock, $sr, 4); - } - } - } elsif ($hs{sectype} == $rfbSecTypeVencrypt) { - print STDERR "\npproxy: vencrypt_viewer_bridge[$$]: rfbSecTypeVencrypt\n"; - if (! exists $hs{subtype}) { - unlink($handshake_file); - die "pproxy: vencrypt_viewer_bridge[$$]: no subtype.\n"; - } - my $fake_type = "None"; - my $plain = 0; - my $sub_type = $hs{subtype}; - if ($sub_type == $rfbVencryptTlsNone) { - $fake_type = "None"; - } elsif ($sub_type == $rfbVencryptTlsVnc) { - $fake_type = "VncAuth"; - } elsif ($sub_type == $rfbVencryptTlsPlain) { - $fake_type = "None"; - $plain = 1; - } elsif ($sub_type == $rfbVencryptX509None) { - $fake_type = "None"; - } elsif ($sub_type == $rfbVencryptX509Vnc) { - $fake_type = "VncAuth"; - } elsif ($sub_type == $rfbVencryptX509Plain) { - $fake_type = "None"; - $plain = 1; - } - if ($plain) { - if (!open(W, ">$handshake_file")) { - unlink($handshake_file); - die "pproxy: vencrypt_viewer_bridge[$$]: $handshake_file $!\n"; - } - print W <<"END"; - - proc print_out {} { - global user pass env - - if [info exists env(SSVNC_UP_DEBUG)] { - toplevel .b - button .b.b -text "user=\$user pass=\$pass" -command {destroy .b} - pack .b.b - update - tkwait window .b - } - - if [info exists env(SSVNC_UP_FILE)] { - set fh "" - catch {set fh [open \$env(SSVNC_UP_FILE) w]} - if {\$fh != ""} { - puts \$fh user=\$user\\npass=\$pass - flush \$fh - close \$fh - return - } - } - puts stdout user=\$user\\npass=\$pass - flush stdout - } - - proc center_win {w} { - update - set W [winfo screenwidth \$w] - set W [expr \$W + 1] - wm geometry \$w +\$W+0 - update - set x [expr [winfo screenwidth \$w]/2 - [winfo width \$w]/2] - set y [expr [winfo screenheight \$w]/2 - [winfo height \$w]/2] - - wm geometry \$w +\$x+\$y - wm deiconify \$w - update - } - - wm withdraw . - - global env - set up {} - if [info exists env(SSVNC_UNIXPW)] { - set rm 0 - set up \$env(SSVNC_UNIXPW) - if [regexp {^rm:} \$up] { - set rm 1 - regsub {^rm:} \$up {} up - } - if [file exists \$up] { - set fh "" - set f \$up - catch {set fh [open \$up r]} - if {\$fh != ""} { - gets \$fh u - gets \$fh p - close \$fh - set up "\$u@\$p" - } - if {\$rm} { - catch {file delete \$f} - } - } - } elseif [info exists env(SSVNC_VENCRYPT_USERPASS)] { - set up \$env(SSVNC_VENCRYPT_USERPASS) - } - #puts stderr up=\$up - if {\$up != ""} { - if [regexp {@} \$up] { - global user pass - set user \$up - set pass \$up - regsub {@.*\$} \$user "" user - regsub {^[^@]*@} \$pass "" pass - print_out - exit - } - } - - wm title . {VeNCrypt Viewer Bridge User/Pass} - - set user {} - set pass {} - - label .l -text {SSVNC VeNCrypt Viewer Bridge} - - frame .f0 - frame .f0.fL - label .f0.fL.la -text {Username: } - label .f0.fL.lb -text {Password: } - - pack .f0.fL.la .f0.fL.lb -side top - - frame .f0.fR - entry .f0.fR.ea -width 24 -textvariable user - entry .f0.fR.eb -width 24 -textvariable pass -show * - - pack .f0.fR.ea .f0.fR.eb -side top -fill x - - pack .f0.fL -side left - pack .f0.fR -side right -expand 1 -fill x - - button .no -text Cancel -command {destroy .} - button .ok -text Done -command {print_out; destroy .} - - center_win . - pack .l .f0 .no .ok -side top -fill x - update - wm deiconify . - - bind .f0.fR.ea {focus .f0.fR.eb} - bind .f0.fR.eb {print_out; destroy .} - focus .f0.fR.ea - - wm resizable . 1 0 - wm minsize . [winfo reqwidth .] [winfo reqheight .] -END - close W; - - #system("cat $handshake_file"); - my $w = "wish"; - if ($ENV{WISH}) { - $w = $ENV{WISH}; - } - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: prompt VencryptPlain user and passwd.\n"; - my $res = ""; - if (`uname` =~ /Darwin/) { - my $mtmp = `mktemp /tmp/hsup.XXXXXX`; - chomp $mtmp; - system("env SSVNC_UP_FILE=$mtmp $w $handshake_file"); - $res = `cat $mtmp`; - unlink $mtmp; - } else { - $res = `$w $handshake_file`; - } - my $user = ""; - my $pass = ""; - if ($res =~ /user=(\S*)/) { - $user = $1; - } - if ($res =~ /pass=(\S*)/) { - $pass = $1; - } - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: sending VencryptPlain user and passwd.\n"; - my $ulen = pack("C", length($user)); - my $plen = pack("C", length($pass)); - # (note this should be MSB, network byte order...) - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $ulen, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $u0, 1); - syswrite($server_sock, $plen, 1); - syswrite($server_sock, $user, length($user)); - syswrite($server_sock, $pass, length($pass)); - } - unlink($handshake_file); - - my $ft = 0; - if ($fake_type eq "None") { - $ft = 1; - } elsif ($fake_type eq "VncAuth") { - $ft = 2; - } else { - die "pproxy: vencrypt_viewer_bridge[$$]: unknown fake type: $fake_type\n"; - } - my $fp = pack("C", $ft); - if ($viewer_major > 3 || $viewer_minor >= 7) { - syswrite($viewer_sock, $u1, 1); - syswrite($viewer_sock, $fp, 1); - my $cr; - sysread($viewer_sock, $cr, 1); - $cr = unpack("C", $cr); - if ($cr != $ft) { - die "pproxy: vencrypt_viewer_bridge[$$]: client selected wrong type: $cr / $ft\n"; - } - } else { - print STDERR "pproxy: vencrypt_viewer_bridge[$$]: faking RFB version 3.3 to viewer.\n"; - # send 4 bytes sect type to viewer: - # (note this should be MSB, network byte order...) - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $u0, 1); - syswrite($viewer_sock, $fp, 1); - if ($ft == 1) { - # even None has security result, so read it here and discard it. - my $sr = ""; - sysread($server_sock, $sr, 4); - } - } - } - - $listen_handle = $viewer_sock; - $sock = $server_sock; - - xfer_both(); -} -' - # ' - # xpg_echo will expand \n \r, etc. - # try to unset and then test for it. - if type shopt > /dev/null 2>&1; then - shopt -u xpg_echo >/dev/null 2>&1 - fi - v='print STDOUT "abc\n";' - echo "$v" > $tf - chmod 700 $tf - - lc=`wc -l $tf | awk '{print $1}'` - if [ "X$lc" = "X1" ]; then - echo "$cod" > $tf - else - printf "%s" "$cod" > $tf - echo "" >> $tf - fi - # prime perl - perl -e 'use IO::Socket::INET; select(undef, undef, undef, 0.01)' >/dev/null 2>&1 -} - -# make_tcert is no longer invoked via the ssvnc gui (Listen mode). -# make_tcert is for testing only now via -mycert BUILTIN -make_tcert() { - tcert="/tmp/ss_vnc_viewer_tcert${RANDOM}.$$" - tcert=`mytmp "$tcert"` - cat > $tcert < Advanced -> Private SSH KnownHosts file' (or set" - echo "** Warning: SSVNC_KNOWN_HOSTS_FILE directly) to a per-connection known hosts" - echo "** Warning: file. That file holds the 'localhost' cert for this specific" - echo "** Warning: connection. This yields a both secure and convenient solution." - echo "" -} - -space_expand() { - str=`echo "$1" | sed -e 's/%SPACE/ /g' -e 's/%TAB/\t/g'` - echo "$str" -} - -# handle ssh case: -# -if [ "X$use_ssh" = "X1" ]; then - # - # USING SSH - # - ssh_port="22" - ssh_host="$host" - vnc_host="$localhost" - ssh_UKHF="" - localhost_extra="" - # let user override ssh via $SSH - ssh=${SSH:-"ssh -x"} - - sshword=`echo "$ssh" | awk '{print $1}'` - if [ "X$sshword" != "X" ]; then - if [ -x "$sshword" ]; then - : - elif type "$sshword" > /dev/null 2>&1; then - : - else - echo "" - echo "*********************************************************" - echo "** Problem finding the SSH command '$sshword': **" - echo "" - type "$sshword" - echo "" - echo "** Perhaps you need to install the SSH client package. **" - echo "*********************************************************" - echo "" - sleep 5 - fi - fi - - ssh_NHAFL="-o NoHostAuthenticationForLocalhost=yes" - if [ "X$SSVNC_SSH_LOCALHOST_AUTH" = "X1" ]; then - ssh_NHAFL="" - fi - if [ "X$SSVNC_KNOWN_HOSTS_FILE" != "X" ]; then - ssh_NHAFL="" - - ssh_UKHF="-o UserKnownHostsFile=$SSVNC_KNOWN_HOSTS_FILE" - ssh_args="$ssh_args $ssh_UKHF" - if [ ! -f "$SSVNC_KNOWN_HOSTS_FILE" ]; then - touch "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 - fi - chmod 600 "$SSVNC_KNOWN_HOSTS_FILE" >/dev/null 2>&1 - fi - did_ssh_NHAFL="" - - if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then - SSVNC_LIM_ACCEPT_PRELOAD="$SSVNC_BASEDIR/$SSVNC_UNAME/$SSVNC_LIM_ACCEPT_PRELOAD" - fi - if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ]; then - echo "" - echo "SSVNC_LIM_ACCEPT_PRELOAD=$SSVNC_LIM_ACCEPT_PRELOAD" - fi - - if [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" -a -f "$SSVNC_LIM_ACCEPT_PRELOAD" ]; then - plvar=LD_PRELOAD - if uname | grep Darwin >/dev/null; then - plvar="DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES" - fi - ssh="env $plvar=$SSVNC_LIM_ACCEPT_PRELOAD $ssh" - else - SSVNC_LIM_ACCEPT_PRELOAD="" - fi - - ssh_vencrypt_proxy="" - # We handle vencrypt for SSH+SSL mode. - if echo "$proxy" | grep 'vencrypt://' > /dev/null; then - proxynew="" - for part in `echo "$proxy" | tr ',' ' '` - do - if echo "$part" | egrep -i '^vencrypt://' > /dev/null; then - ssh_vencrypt_proxy=$part - else - if [ "X$proxynew" = "X" ]; then - proxynew="$part" - else - proxynew="$proxynew,$part" - fi - fi - done - proxy=$proxynew - fi - Kecho ssh_vencrypt_proxy=$ssh_vencrypt_proxy - - # note that user must supply http:// for web proxy in SSH and SSH+SSL. - # No xxxx:// implies ssh server+port. - # - if echo "$proxy" | egrep '(http|https|socks|socks4|socks5)://' > /dev/null; then - # Handle Web or SOCKS proxy(ies) for the initial connect. - Kecho host=$host - Kecho port=$port - pproxy="" - sproxy1="" - sproxy_rest="" - for part in `echo "$proxy" | tr ',' ' '` - do - Kecho proxy_part=$part - if [ "X$part" = "X" ]; then - continue - elif echo "$part" | egrep -i '^(http|https|socks|socks4|socks5)://' > /dev/null; then - pproxy="$pproxy,$part" - else - if [ "X$sproxy1" = "X" ]; then - sproxy1="$part" - else - sproxy_rest="$sproxy_rest,$part" - fi - fi - done - pproxy=`echo "$pproxy" | sed -e 's/^,,*//' -e 's/,,*/,/g'` - sproxy_rest=`echo "$sproxy_rest" | sed -e 's/^,,*//' -e 's/,,*/,/g'` - - Kecho pproxy=$pproxy - Kecho sproxy1=$sproxy1 - Kecho sproxy_rest=$sproxy_rest - - sproxy1_host="" - sproxy1_port="" - sproxy1_user="" - - if [ "X$sproxy1" != "X" ]; then - # XXX fix ipv6 ip adder here and below. - sproxy1_host=`echo "$sproxy1" | awk -F: '{print $1}'` - sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'` - sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'` - if [ "X$sproxy1_host" = "X" ]; then - sproxy1_host=$sproxy1_user - sproxy1_user="" - else - sproxy1_user="${sproxy1_user}@" - fi - sproxy1_port=`echo "$sproxy1" | awk -F: '{print $2}'` - if [ "X$sproxy1_port" = "X" ]; then - sproxy1_port="22" - fi - else - sproxy1_host=`echo "$host" | awk -F: '{print $1}'` - sproxy1_user=`echo "$sproxy1_host" | awk -F@ '{print $1}'` - sproxy1_host=`echo "$sproxy1_host" | awk -F@ '{print $2}'` - if [ "X$sproxy1_host" = "X" ]; then - sproxy1_host=$sproxy1_user - sproxy1_user="" - else - sproxy1_user="${sproxy1_user}@" - fi - sproxy1_port=`echo "$host" | awk -F: '{print $2}'` - if [ "X$sproxy1_port" = "X" ]; then - sproxy1_port="22" - fi - fi - - Kecho sproxy1_host=$sproxy1_host - Kecho sproxy1_port=$sproxy1_port - Kecho sproxy1_user=$sproxy1_user - - ptmp="/tmp/ss_vncviewer_ssh${RANDOM}.$$.pl" - ptmp=`mytmp "$ptmp"` - PPROXY_REMOVE=1; export PPROXY_REMOVE - proxy=$pproxy - port_save=$port - host_save=$host - if [ "X$sproxy1_host" != "X" ]; then - host=$sproxy1_host - fi - if [ "X$sproxy1_port" != "X" ]; then - port=$sproxy1_port - fi - host=`echo "$host" | sed -e 's/^.*@//'` - port=`echo "$port" | sed -e 's/^.*://'` - pcode "$ptmp" - port=$port_save - host=$host_save - - nd=`findfree 6600` - PPROXY_LISTEN=$nd; export PPROXY_LISTEN - # XXX no reverse forever PPROXY_LOOP_THYSELF ... - $ptmp & - sleep 1 - if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then - NHAFL_warning - ssh_args="$ssh_args $ssh_NHAFL" - did_ssh_NHAFL=1 - fi - sleep 1 - if [ "X$sproxy1" = "X" ]; then - u="" - if echo "$host" | grep '@' > /dev/null; then - u=`echo "$host" | sed -e 's/@.*$/@/'` - fi - - proxy="${u}$localhost:$nd" - else - proxy="${sproxy1_user}$localhost:$nd" - fi - localhost_extra=".2" - if [ "X$sproxy_rest" != "X" ]; then - proxy="$proxy,$sproxy_rest" - fi - Kecho proxy=$proxy - fi - - if echo "$proxy" | grep "," > /dev/null; then - - proxy1=`echo "$proxy" | awk -F, '{print $1}'` - proxy2=`echo "$proxy" | awk -F, '{print $2}'` - - # user1@gw1.com:port1,user2@ws2:port2 - ssh_host1=`echo "$proxy1" | awk -F: '{print $1}'` - ssh_port1=`echo "$proxy1" | awk -F: '{print $2}'` - if [ "X$ssh_port1" != "X" ]; then - ssh_port1="-p $ssh_port1" - fi - ssh_host2=`echo "$proxy2" | awk -F: '{print $1}'` - ssh_user2=`echo "$ssh_host2" | awk -F@ '{print $1}'` - ssh_host2=`echo "$ssh_host2" | awk -F@ '{print $2}'` - if [ "X$ssh_host2" = "X" ]; then - ssh_host2=$ssh_user2 - ssh_user2="" - else - ssh_user2="${ssh_user2}@" - fi - ssh_port2=`echo "$proxy2" | awk -F: '{print $2}'` - if [ "X$ssh_port2" = "X" ]; then - ssh_port2="22" - fi - proxport=`findfree 3500` - if [ "X$ssh_NHAFL" != "X" -a "X$did_ssh_NHAFL" != "X1" ]; then - NHAFL_warning - did_ssh_NHAFL=1 - sleep 1 - fi - echo - echo "Running 1st ssh proxy:" - ukhf="" - if [ "X$ssh_UKHF" != "X" ]; then - ukhf="$ssh_UKHF$localhost_extra" - fi - if echo "$ssh_host1" | grep '%' > /dev/null; then - uath=`space_expand "$ssh_host1"` - else - uath="$ssh_host1" - fi - echo "$ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 \"$uath\" \"sleep 30\"" - echo "" - $ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 "$uath" "sleep 30" - ssh_args="$ssh_args $ssh_NHAFL" - sleep 1 - stty sane - proxy="${ssh_user2}$localhost:$proxport" - fi - - if [ "X$proxy" != "X" ]; then - ssh_port=`echo "$proxy" | awk -F: '{print $2}'` - if [ "X$ssh_port" = "X" ]; then - ssh_port="22" - fi - ssh_host=`echo "$proxy" | awk -F: '{print $1}'` - vnc_host="$host" - fi - - echo "" - echo "Running ssh:" - sz=`echo "$ssh_cmd" | wc -c` - if [ "$sz" -gt 300 ]; then - info="..." - else - info="$ssh_cmd" - fi - - C="" - if [ "X$SS_VNCVIEWER_USE_C" != "X" ]; then - C="-C" - fi - - getport="" - teeport="" - if echo "$ssh_cmd" | egrep "(PORT=|P=) " > /dev/null; then - getport=1 - if echo "$ssh_cmd" | egrep "P= " > /dev/null; then - teeport=1 - fi - - PORT="" - ssh_cmd=`echo "$ssh_cmd" | sed -e 's/PORT=[ ]*//' -e 's/P=//'` - SSVNC_NO_ENC_WARN=1 - if [ "X$use_sshssl" = "X" ]; then - direct_connect=1 - fi - fi - if [ "X$getport" != "X" ]; then - ssh_redir="-D ${use}" - elif [ "X$reverse" = "X" ]; then - ssh_redir="-L ${use}:${vnc_host}:${port}" - else - ssh_redir="-R ${port}:${vnc_host}:${use}" - fi - pmark=`sh -c 'echo $$'` - - # the -t option actually speeds up typing response via VNC!! - if [ "X$ssh_port" = "X22" ]; then - ssh_port="" - else - ssh_port="-p $ssh_port" - fi - - if echo "$ssh_host" | grep '%' > /dev/null; then - uath=`space_expand "$ssh_host"` - else - uath="$ssh_host" - fi - if [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then - echo "$ssh -x $ssh_port $targ $C $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x $ssh_port $targ $C $ssh_args "$uath" "$ssh_cmd" - exit $? - - elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then - echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" - rc=$? - - elif [ "X$getport" != "X" ]; then - tport=/tmp/ss_vncviewer_tport${RANDOM}.$$ - tport=`mytmp "$tport"` - tport2=/tmp/ss_vncviewer_tport2${RANDOM}.$$ - tport2=`mytmp "$tport2"` - - if [ "X$rsh" != "X1" ]; then - if echo "$ssh_cmd" | grep "sudo " > /dev/null; then - echo "" - echo "Initial ssh with 'sudo id' to prime sudo so hopefully the next one" - echo "will require no password..." - echo "" - targ="-t" - $ssh -x $ssh_port $targ $ssh_args "$uath" "sudo id; tty" - echo "" - fi - echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" > $tport 2> $tport2 - if [ "X$teeport" = "X1" ]; then - tail -f $tport 1>&2 & - tail_pid=$! - tail -f $tport2 1>&2 & - tail_pid2=$! - fi - rc=$? - else - rsh_setup - echo "rsh $ul \"$ssh_host\" \"$ssh_cmd\"" - echo "" - rsh $ul "$ssh_host" "$ssh_cmd" > $tport & - sleep 1 - rc=0 - fi - - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP - fi - - stty sane - i=0 - if type perl > /dev/null 2>&1; then - imax=50 - sleepit="perl -e 'select(undef, undef, undef, 0.20)'" - else - imax=10 - sleepit="sleep 1" - fi - while [ $i -lt $imax ]; do - #echo $sleepit - eval $sleepit - PORT=`grep "^PORT=" $tport | tr '\r' ' ' | head -n 1 | sed -e 's/PORT=//' -e 's/\r//g' -e 's/ *$//'` - if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then - break - fi - vnss=`sed -e 's/\r//g' $tport $tport2 | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1 | awk '{print $NF}'` - if [ "X$vnss" != "X" ]; then - PORT=`echo "$vnss" | awk -F: '{print $2}'` - if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then - if [ $PORT -lt 100 ]; then - PORT=`expr $PORT + 5900` - fi - fi - if echo "$PORT" | grep '^[0-9][0-9]*$' > /dev/null; then - vnss=`sed -e 's/\r//g' $tport | egrep -i '^(New.* desktop is|A VNC server is already running).*:[0-9[0-9]*$' | head -n 1` - echo "vncserver string: $vnss" 1>&2 - break - fi - fi - i=`expr $i + 1` - done - - echo "found: PORT='$PORT'" 1>&2 - lh6="" - if [ "X$SSVNC_PORT_IPV6" != "X" ]; then - lh6=1 - elif egrep 'Info: listening on IPv6 only|Info: listening only on IPv6' $tport > /dev/null; then - lh6=1 - fi - if [ "X$lh6" = "X1" ]; then - echo "set SOCKS5 localhost to ::1" 1>&2 - fi - rm -f $tport $tport2 - if [ "X$rsh" = "X1" ]; then - rsh_viewer "$@" - exit $? - fi - PPROXY_SOCKS=5 - if [ "X$SSVNC_SOCKS5" != "X" ]; then - PPROXY_SOCKS=5 - elif [ "X$SSVNC_SOCKS4" != "X" ]; then - PPROXY_SOCKS=1 - fi - export PPROXY_SOCKS - if [ "X$lh6" = "X" ]; then - host="$localhost" - else - host="::1" - fi - port="$PORT" - proxy="$localhost:$use" - - else - if [ "X$rsh" != "X1" ]; then - echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args \"$uath\" \"$info\"" - echo "" - $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args "$uath" "$ssh_cmd" - rc=$? - else - rsh_setup - echo "rsh $ul \"$ssh_host\" \"$ssh_cmd\"" - echo "" - rsh $ul "$ssh_host" "$ssh_cmd" & - sleep 1 - PORT=$port - rsh_viewer "$@" - exit $? - fi - fi - - if [ "$rc" != "0" ]; then - echo "" - echo "ssh to \"$uath\" failed." - exit 1 - fi - stty sane - - c=0 - pssh="" - while [ $c -lt 40 ] - do - p=`expr $pmark + $c` - pout=`ps -p "$p" 2>/dev/null | grep -v '^[ ]*PID' | sed -e 's/-L.*$//' -e 's/-x .*$//'` - if echo "$pout" | grep "ssh" > /dev/null; then - if echo "$pout" | egrep -i 'ssh.*(-add|-agent|-ask|-keygen|-argv0|vnc)' >/dev/null; then - : - elif echo "$pout" | egrep -i 'scp|sshd' >/dev/null; then - : - else - pssh=$p - break - fi - fi - c=`expr $c + 1` - done - if [ "X$getport" != "X" ]; then - : - elif [ "X$SSVNC_LIM_ACCEPT_PRELOAD" != "X" ] ; then - sleep 2 - elif [ "X$ssh_cmd" = "Xsleep $ssh_sleep" ] ; then - #echo T sleep 1 - sleep 1 - elif echo "$ssh_cmd" | grep '^sleep ' >/dev/null; then - #echo T sleep 2 - sleep 2 - else - # let any command get started a bit. - #echo T sleep 5 - sleep 5 - fi - echo "" - #reset - stty sane - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP - fi - echo "ssh_pid='$pssh'"; echo - if [ "X$use_sshssl" = "X" -a "X$getport" = "X" ]; then - if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then - (sh -c "$SSVNC_EXTRA_COMMAND") & - echo "($SSVNC_EXTRA_COMMAND) &"; echo - fi - echo "Running viewer:" - - trap "final" 0 2 15 - if [ "X$reverse" = "X" ]; then - echo "$VNCVIEWERCMD" "$@" $localhost:$N - echo "" - $VNCVIEWERCMD "$@" $localhost:$N - if [ $? != 0 ]; then - echo "vncviewer command failed: $?" - if [ "X$secondtry" = "X1" ]; then - sleep 2 - $VNCVIEWERCMD "$@" $localhost:$N - fi - fi - else - echo "" - echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." - echo "" - N2=$N - if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then - N2=`echo "$N2" | sed -e 's/://g'` - if [ $N2 -le 200 ]; then - N2=`expr $N2 + 5500` - fi - fi - echo "$VNCVIEWERCMD" "$@" -listen $N2 - echo "" - $VNCVIEWERCMD "$@" -listen $N2 - fi - - exit $? - else - use2=`findfree 5960` - host0=$host - port0=$port - host=$localhost - port=$use - use=$use2 - N=`expr $use - 5900` - if [ "X$getport" != "X" ]; then - host="$host0" - port="$port0" - else - proxy="" - fi - if [ "X$ssh_vencrypt_proxy" != "X" ]; then - ssh_vencrypt_proxy="vencrypt://$host:$port" - if [ "X$proxy" = "X" ]; then - proxy=$ssh_vencrypt_proxy - else - proxy="$proxy,$ssh_vencrypt_proxy" - fi - Kecho "proxy_now=$proxy" - unset PPROXY_LISTEN - fi - fi -fi - -if [ "X$stunnel_set_here" = "X1" -a "X$showcert" = "X" ]; then - if type $STUNNEL > /dev/null 2>&1; then - : - else - echo "" - echo "***************************************************************" - echo "** Problem finding the Stunnel command '$STUNNEL': **" - echo "" - type $STUNNEL - echo "" - echo "** Perhaps you need to install the stunnel/stunnel4 package. **" - echo "***************************************************************" - echo "" - sleep 5 - fi -fi - -# create the stunnel config file: -if [ "X$verify" != "X" ]; then - if [ -d $verify ]; then - verify="CApath = $verify" - else - verify="CAfile = $verify" - fi - verify="$verify -verify = 2" -fi -if [ "X$SSVNC_STUNNEL_VERIFY3" != "X" ]; then - verify=`echo "$verify" | sed -e 's/verify = 2/verify = 3/'` -fi -if [ "X$mycert" != "X" ]; then - cert="cert = $mycert" -fi -if [ "X$crl" != "X" ]; then - if [ -d $crl ]; then - crl="CRLpath = $crl" - else - crl="CRLfile = $crl" - fi -fi - -if [ "X$showcert" = "X1" ]; then - if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then - : - elif [ "X$SSVNC_NO_IPV6_PROXY" != "X" ]; then - : - elif [ "X$ipv6" = "X1" -a "X$proxy" = "X" ]; then - proxy="ipv6://$host:$port" - fi -fi - -if [ "X$direct_connect" != "X" -a "X$STUNNEL_LISTEN" != "X" ]; then - proxy=reverse_direct -fi - -ptmp="" -if [ "X$proxy" != "X" ]; then - ptmp="/tmp/ss_vncviewer${RANDOM}.$$.pl" - ptmp=`mytmp "$ptmp"` - PPROXY_REMOVE=1; export PPROXY_REMOVE - pcode "$ptmp" - if [ "X$showcert" != "X1" -a "X$direct_connect" = "X" ]; then - if uname | egrep 'Darwin|SunOS' >/dev/null; then - vout=`echo "$proxy" | grep -i vencrypt` - if [ "X$vout" != "X" -a "X$reverse" = "X1" ]; then - # need to exec for reverse vencrypt - connect="exec = $ptmp" - else - # on mac and solaris we need to listen on socket instead of stdio: - nd=`findfree 6700` - PPROXY_LISTEN=$nd - export PPROXY_LISTEN - if [ "X$reverse" = "X" ]; then - $ptmp & - fi - sleep 2 - host="$localhost" - port="$nd" - connect="connect = $localhost:$nd" - fi - else - # otherwise on unix we can exec it: - connect="exec = $ptmp" - fi - else - connect="exec = $ptmp" - fi -else - connect="connect = $host:$port" -fi - -# handle showcert case: -# -if [ "X$showcert" = "X1" ]; then - if [ "X$proxy" != "X" ]; then - PPROXY_LISTEN=$use - export PPROXY_LISTEN - if [ "X$SS_DEBUG" != "X" ]; then - $ptmp & - else - $ptmp 2>/dev/null & - fi - sleep 1 - more_sleep=1 - if uname | grep Linux > /dev/null; then - if netstat -ant | grep LISTEN | grep "127.0.0.1:$use" > /dev/null; then - more_sleep="" - fi - elif uname | grep SunOS > /dev/null; then - if netstat -an -f inet -P tcp | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then - more_sleep="" - fi - elif uname | egrep -i 'bsd|darwin' > /dev/null; then - if netstat -ant -f inet | grep LISTEN | grep "127.0.0.1.$use" > /dev/null; then - more_sleep="" - fi - fi - if [ "X$more_sleep" = "X1" ]; then - sleep 1 - fi - host="$localhost" - port="$use" - fi - cipher_args="" - if [ "X$ciphers" != "X" ]; then - cipher_args=`echo "$ciphers" | sed -e 's/ciphers=/-cipher /'` - fi - if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then - : - elif type openssl > /dev/null 2>&1; then - : - else - echo "" - echo "********************************************************" - echo "** Problem finding the OpenSSL command 'openssl': **" - echo "" - type openssl 2>&1 - echo "" - echo "** Perhaps you need to install the 'openssl' package. **" - echo "********************************************************" - echo "" - fi - #echo "openssl s_client $cipher_args -connect $host:$port" - if [ "X$reverse" = "X" ]; then - if type host > /dev/null 2>/dev/null; then - host $host >/dev/null 2>&1 - host $host >/dev/null 2>&1 - fi - timeout=15 - if [ "X$SSVNC_FETCH_TIMEOUT" != "X" ]; then - timeout=$SSVNC_FETCH_TIMEOUT - fi - if [ "X$have_uvnc_dsm_helper_showcert" = "X1" ]; then - if type pkill >/dev/null 2>&1; then - (sleep $timeout; if kill -0 $$; then pkill -TERM -f "ultravnc_dsm_helper.*$host.*$port"; fi) >/dev/null 2>&1 & - fi - ultravnc_dsm_helper showcert $host:$port 2>&1 - else - if type pkill >/dev/null 2>&1; then - (sleep $timeout; if kill -0 $$; then pkill -TERM -f "openssl.*s_client.*$host.*$port"; fi) >/dev/null 2>&1 & - fi - openssl s_client $cipher_args -prexit -connect $host:$port 2>&1 < /dev/null - fi - rc=$? - else - tcert="" - if [ "X$mycert" = "X" ]; then - tcert=`make_tcert` - cert_args="-cert $tcert -CAfile $tcert" - else - cert_args="-cert $mycert -CAfile $mycert" - fi - tmp_out=/tmp/showcert_out${RANDOM}.$$ - tmp_out=`mytmp "$tmp_out"` - tmp_err=/tmp/showcert_err${RANDOM}.$$ - tmp_err=`mytmp "$tmp_err"` - - #echo "openssl s_server $cipher_args $cert_args -accept $port -verify 2 > $tmp_out 2> $tmp_err" 1>&2 - - # assume we have perl: - check_perl perl - - perl -e " - \$p = open(O, \"|openssl s_server $cipher_args $cert_args -accept $port -verify 2 1>$tmp_out 2> $tmp_err\"); - exit 1 unless \$p; - while (1) { - sleep 1; - if (!open(F, \"<$tmp_out\")) { - kill \$p; - exit 1; - } - while () { - if (/RFB 00/) { - fsleep(0.25); - print O \"RFB 000.000\\n\"; - fsleep(1.00); - kill \$p; - fsleep(0.25); - exit 0; - } - } - close F; - } - sub fsleep { - select(undef, undef, undef, shift); - } - "; - - echo "" - cat $tmp_out - echo "" - echo "----2----" - cat $tmp_err - if grep BEGIN.CERTIFICATE $tmp_out >/dev/null; then - rc=0 - else - rc=1 - fi - - rm -f $tmp_out $tmp_err - fi - if [ "X$SSVNC_PREDIGESTED_HANDSHAKE" != "X" ]; then - rm -f $SSVNC_PREDIGESTED_HANDSHAKE - fi - if [ "X$SSVNC_SHOWCERT_EXIT_0" = "X1" ]; then - exit 0 - else - exit $rc - fi -fi - -# handle direct connect case: -# -if [ "X$direct_connect" != "X" ]; then - if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - SSVNC_NO_ENC_WARN=1 - echo "" - echo "Using UltraVNC DSM Plugin key for encryption:" - echo "" - ustr=`echo "$SSVNC_ULTRA_DSM" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo " $ustr PORT HOST:PORT" - echo "" - elif [ "X$getport" = "X" ]; then - echo "" - echo "Running viewer for direct connection:" - if echo X"$@" | grep chatonly > /dev/null; then - : - else - echo "" - echo "** WARNING: THERE WILL BE NO SSL OR SSH ENCRYPTION **" - echo "" - fi - fi - x="" - if [ "X$SSVNC_NO_ENC_WARN" != "X" ]; then - if [ "X$getport" = "X" ]; then - sleep 1 - fi - elif type printf > /dev/null 2>&1; then - printf "Are you sure you want to continue? [y]/n " - read x - else - echo -n "Are you sure you want to continue? [y]/n " - read x - fi - if [ "X$x" = "Xn" ]; then - exit 1 - fi - echo "" - if [ "X$ptmp" != "X" ]; then - if [ "X$reverse" = "X" ]; then - PPROXY_LISTEN=$use - export PPROXY_LISTEN - else - if [ "X$proxy" = "Xreverse_direct" ]; then - PPROXY_LISTEN="$STUNNEL_LISTEN:`expr 5500 + $disp`" - PPROXY_DEST="$localhost:$use" - PPROXY_PROXY="ipv6://$localhost:$use" # not always ipv6.. - export PPROXY_LISTEN PPROXY_DEST PPROXY_PROXY - pps=1 - else - PPROXY_REVERSE="$localhost:$use" - export PPROXY_LISTEN - pps=3 - fi - if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then - PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself.${RANDOM}.$$"` - export PPROXY_LOOP_THYSELF - pps=2 - fi - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - pps=`expr $pps + $SSVNC_EXTRA_SLEEP` - fi - PPROXY_SLEEP=$pps; export PPROXY_SLEEP; - PPROXY_KILLPID=+1; export PPROXY_KILLPID; - fi - - $ptmp & - - if [ "X$reverse" = "X" ]; then - #sleep 2 - #echo T sleep 1 - sleep 1 - fi - host="$localhost" - disp="$N" - port=`expr $disp + 5900` - fi - if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "T sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP - fi - if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then - (sh -c "$SSVNC_EXTRA_COMMAND") & - echo "($SSVNC_EXTRA_COMMAND) &"; echo - fi - if [ "X$reverse" = "X" ]; then - hostdisp="$host:$disp" - if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - if [ "X$SSVNC_USE_OURS" = "X1" ]; then - hostdisp="exec=$SSVNC_ULTRA_DSM 0 $host:$port" - else - pf=`findfree 5970` - cmd="$SSVNC_ULTRA_DSM -$pf $host:$port" - pf=`expr $pf - 5900` - hostdisp="$localhost:$pf" - ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo "Running:" - echo - echo "$ustr &" - echo - $cmd & - dsm_pid=$! - sleep 2 - fi - fi - hostdisp2=`echo "$hostdisp" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo "$VNCVIEWERCMD" "$@" "$hostdisp2" - trap "final" 0 2 15 - echo "" - $VNCVIEWERCMD "$@" "$hostdisp" - if [ $? != 0 ]; then - echo "vncviewer command failed: $?" - if [ "X$secondtry" = "X1" ]; then - sleep 2 - $VNCVIEWERCMD "$@" "$hostdisp" - fi - fi - else - echo "" - echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." - echo "" - trap "final" 0 2 15 - if [ "X$SSVNC_ULTRA_DSM" != "X" ]; then - if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then - echo "NOTE: The ultravnc_dsm_helper only runs once. So after the first LISTEN" - echo " ends you must restart the Listening mode. You may also need to" - echo " Press Ctrl-C to stop the viewer and restart for another connection." - echo "" - fi - #SSVNC_LISTEN_ONCE=1; export SSVNC_LISTEN_ONCE - VNCVIEWER_LISTEN_LOCALHOST=1 - export VNCVIEWER_LISTEN_LOCALHOST - dport=`expr 5500 + $disp` - cmd="$SSVNC_ULTRA_DSM $dport $localhost:$use" - ustr=`echo "$cmd" | sed -e 's/pw=[^ ]*/pw=******/g'` - echo "Running:" - echo - echo "$ustr &" - echo - if [ "X$SSVNC_LISTEN_ONCE" = "X1" ]; then - $cmd & - dsm_pid=$! - else - while [ 1 ]; do $cmd; sleep 1; done & - dsm_pid=$! - fi - sleep 2 - disp=$use - if [ $disp -ge 5500 ]; then - disp=`expr $disp - 5500` - fi - fi - disp2=$disp - if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then - disp2=`echo "$disp2" | sed -e 's/://g'` - if [ $disp2 -le 200 ]; then - disp2=`expr $disp2 + 5500` - fi - fi - echo "$VNCVIEWERCMD" "$@" -listen $disp2 - echo "" - $VNCVIEWERCMD "$@" -listen $disp2 - if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then - rm -f $PPROXY_LOOP_THYSELF - fi - fi - exit $? -fi - -tmp_cfg=/tmp/ss_vncviewer${RANDOM}.$$ -tmp_cfg=`mytmp "$tmp_cfg"` - -stunnel_exec="" -if [ "X$SSVNC_USE_OURS" != "X1" ]; then - : -elif echo $STUNNEL_EXTRA_SVC_OPTS | grep '#stunnel-exec' > /dev/null; then - stunnel_exec="#" -fi - -if [ "X$reverse" = "X" ]; then - - if echo "$proxy" | grep "^repeater://" > /dev/null; then - if [ "X$cert" = "XBUILTIN" ]; then - ttcert=`make_tcert` - cert="cert = $ttcert" - fi - # Note for listen mode, an empty cert will cause stunnel to fail. - # The ssvnc gui will have already taken care of this. - fi - - cat > "$tmp_cfg" < /dev/null; then - hloc="$localhost:" - pv=`findfree 5570` - proxy="vencrypt:$pv:$port" - port=$pv - if [ "X$anondh_set" = "X1" ]; then - # not needed for ANONDH in this mode - #ciphers="ciphers = ADH:@STRENGTH" - : - fi - fi - cat > "$tmp_cfg" < /dev/null 2>&1 - $STUNNEL "$tmp_cfg" < /dev/tty > /dev/tty & - stunnel_pid=$! - echo "" - - # pause here to let the user supply a possible passphrase for the - # mycert key: - if [ "X$mycert" != "X" ]; then - nsl=10 - dsl=0 - if [ ! -f $mycert ]; then - dsl=0 - elif grep -i 'Proc-Type.*ENCRYPTED' "$mycert" > /dev/null 2>/dev/null; then - dsl=1 - fi - if [ "X$dsl" = "X1" ]; then - echo "" - echo "(** pausing $nsl secs for possible certificate passphrase dialog **)" - echo "" - sleep $nsl - echo "(** done pausing for passphrase **)" - echo "" - fi - fi - #echo T sleep 1 - sleep 1 - rm -f "$tmp_cfg" -fi - - -echo "" -if [ "X$SSVNC_EXTRA_SLEEP" != "X" ]; then - echo "sleep $SSVNC_EXTRA_SLEEP" - sleep $SSVNC_EXTRA_SLEEP -fi -if [ "X$SSVNC_EXTRA_COMMAND" != "X" ]; then - (sh -c "$SSVNC_EXTRA_COMMAND") & - echo "($SSVNC_EXTRA_COMMAND) &"; echo -fi - -if [ "X$reverse" = "X" ]; then - if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then - port1=`expr 5900 + $N` # stunnel port - port2=`findfree 5970` # bridge port (viewer connects to it.) - N=`expr $port2 - 5900` - env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="$port2,$port1" $ptmp & - sleep 1 - fi - echo "Running viewer:" - vnc_hp=$localhost:$N - if [ "X$stunnel_exec" != "X" ]; then - vnc_hp="exec=$STUNNEL $tmp_cfg" - fi - echo "$VNCVIEWERCMD" "$@" "$vnc_hp" - trap "final" 0 2 15 - echo "" - $VNCVIEWERCMD "$@" "$vnc_hp" - if [ $? != 0 ]; then - echo "vncviewer command failed: $?" - if [ "X$secondtry" = "X1" ]; then - sleep 2 - $VNCVIEWERCMD "$@" "$vnc_hp" - fi - fi -else - echo "Running viewer:" - echo "" - echo "NOTE: Press Ctrl-C to terminate viewer LISTEN mode." - echo "" - trap "final" 0 2 15 - N2=$N - N2_trim=`echo "$N2" | sed -e 's/://g'` - if [ $N2_trim -le 200 ]; then - N2_trim=`expr $N2_trim + 5500` - fi - if [ "X$proxy" != "X" ]; then - if echo "$proxy" | grep -i '^vencrypt:' > /dev/null; then - pstunnel=`echo "$proxy" | awk -F: '{print $2}'` - plisten=`echo "$proxy" | awk -F: '{print $3}'` - IF=INADDR_ANY - if [ "X$STUNNEL_LISTEN" != "X" ]; then - IF=$STUNNEL_LISTEN - fi - PPROXY_VENCRYPT_REVERSE=1; export PPROXY_VENCRYPT_REVERSE - PPROXY_LISTEN="$IF:$plisten"; export PPROXY_LISTEN - PPROXY_PROXY="vencrypt://$localhost:$pstunnel"; export PPROXY_PROXY - PPROXY_DEST="$localhost:$pstunnel"; export PPROXY_DEST - STUNNEL_ONCE=1; export STUNNEL_ONCE - STUNNEL_MAX_CLIENTS=1; export STUNNEL_MAX_CLIENTS - if [ "X$NEED_VENCRYPT_VIEWER_BRIDGE" = "X1" -a "X$ptmp" != "X" ] ; then - port1=`expr 5500 + $N2` - port2=`findfree 5580` - N2=`expr $port2 - 5500` - N2_trim=`echo "$N2" | sed -e 's/://g'` - if [ $N2_trim -le 200 ]; then - N2_trim=`expr $N2_trim + 5500` - fi - if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then - PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself1.${RANDOM}.$$"` - export PPROXY_LOOP_THYSELF - PPROXY_LOOP_THYSELF0=$PPROXY_LOOP_THYSELF - fi - env PPROXY_REMOVE=0 PPROXY_SLEEP=0 PPROXY_VENCRYPT_VIEWER_BRIDGE="-$port1,$port2" $ptmp & - sleep 1 - fi - else - PPROXY_REVERSE="$localhost:$port"; export PPROXY_REVERSE - PPROXY_SLEEP=1; export PPROXY_SLEEP; - fi - PPROXY_KILLPID=+1; export PPROXY_KILLPID; - if [ "X$SSVNC_LISTEN_ONCE" != "X1" ]; then - PPROXY_LOOP_THYSELF=`mytmp "/tmp/pproxy_loop_thyself2.${RANDOM}.$$"` - export PPROXY_LOOP_THYSELF - fi - $ptmp & - # Important to have no extra pids generated between here and VNCVIEWERCMD - fi - if [ "X$VNCVIEWER_IS_REALVNC4" = "X1" ]; then - N2=$N2_trim - fi - echo "$VNCVIEWERCMD" "$@" -listen $N2 - echo "" - $VNCVIEWERCMD "$@" -listen $N2 - - if [ "X$PPROXY_LOOP_THYSELF" != "X" ]; then - rm -f $PPROXY_LOOP_THYSELF - fi - if [ "X$PPROXY_LOOP_THYSELF0" != "X" ]; then - rm -f $PPROXY_LOOP_THYSELF0 - fi -fi - -sleep 1 diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch deleted file mode 100644 index bc10f3c..0000000 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch +++ /dev/null @@ -1,111 +0,0 @@ ---- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 -+++ vnc_javasrc/VncCanvas.java 2010-11-30 21:01:15.000000000 -0500 -@@ -28,13 +28,14 @@ - import java.lang.*; - import java.util.zip.*; - -+import java.util.Collections; - - // - // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. - // - - class VncCanvas extends Canvas -- implements KeyListener, MouseListener, MouseMotionListener { -+ implements KeyListener, MouseListener, MouseMotionListener, MouseWheelListener { - - VncViewer viewer; - RfbProto rfb; -@@ -81,6 +82,20 @@ - cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6)); - cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF); - -+ // kludge to not show any Java cursor in the canvas since we are -+ // showing the soft cursor (should be a user setting...) -+ Cursor dot = Toolkit.getDefaultToolkit().createCustomCursor( -+ Toolkit.getDefaultToolkit().createImage(new byte[4]), new Point(0,0), -+ "dot"); -+ this.setCursor(dot); -+ -+ // while we are at it... get rid of the keyboard traversals that -+ // make it so we can't type a Tab character: -+ this.setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+ this.setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, -+ Collections.EMPTY_SET); -+ - colors = new Color[256]; - for (int i = 0; i < 256; i++) - colors[i] = new Color(cm8.getRGB(i)); -@@ -169,6 +184,7 @@ - inputEnabled = true; - addMouseListener(this); - addMouseMotionListener(this); -+ addMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(true); - } -@@ -177,6 +193,7 @@ - inputEnabled = false; - removeMouseListener(this); - removeMouseMotionListener(this); -+ removeMouseWheelListener(this); - if (viewer.showControls) { - viewer.buttonPanel.enableRemoteAccessControls(false); - } -@@ -1190,6 +1207,9 @@ - public void mouseDragged(MouseEvent evt) { - processLocalMouseEvent(evt, true); - } -+ public void mouseWheelMoved(MouseWheelEvent evt) { -+ processLocalMouseWheelEvent(evt); -+ } - - public void processLocalKeyEvent(KeyEvent evt) { - if (viewer.rfb != null && rfb.inNormalProtocol) { -@@ -1221,6 +1241,19 @@ - evt.consume(); - } - -+ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { -+ if (viewer.rfb != null && rfb.inNormalProtocol) { -+ synchronized(rfb) { -+ try { -+ rfb.writeWheelEvent(evt); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ } -+ rfb.notify(); -+ } -+ } -+ } -+ - public void processLocalMouseEvent(MouseEvent evt, boolean moved) { - if (viewer.rfb != null && rfb.inNormalProtocol) { - if (moved) { -@@ -1387,9 +1420,9 @@ - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | -- (pixBuf[i * 4 + 1] & 0xFF) << 16 | -- (pixBuf[i * 4 + 2] & 0xFF) << 8 | -- (pixBuf[i * 4 + 3] & 0xFF); -+ (pixBuf[i * 4 + 2] & 0xFF) << 16 | -+ (pixBuf[i * 4 + 1] & 0xFF) << 8 | -+ (pixBuf[i * 4 + 0] & 0xFF); - } - } else { - result = 0; // Transparent pixel -@@ -1403,9 +1436,9 @@ - result = cm8.getRGB(pixBuf[i]); - } else { - result = 0xFF000000 | -- (pixBuf[i * 4 + 1] & 0xFF) << 16 | -- (pixBuf[i * 4 + 2] & 0xFF) << 8 | -- (pixBuf[i * 4 + 3] & 0xFF); -+ (pixBuf[i * 4 + 2] & 0xFF) << 16 | -+ (pixBuf[i * 4 + 1] & 0xFF) << 8 | -+ (pixBuf[i * 4 + 0] & 0xFF); - } - } else { - result = 0; // Transparent pixel diff --git a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch deleted file mode 100644 index 801234a..0000000 --- a/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch +++ /dev/null @@ -1,2600 +0,0 @@ -diff -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile ---- vnc_javasrc.orig/Makefile 2004-03-04 08:34:25.000000000 -0500 -+++ vnc_javasrc/Makefile 2010-05-18 20:56:26.000000000 -0400 -@@ -4,6 +4,7 @@ - - CP = cp - JC = javac -+JC_ARGS = -target 1.4 -source 1.4 - JAR = jar - ARCHIVE = VncViewer.jar - MANIFEST = MANIFEST.MF -@@ -15,25 +16,29 @@ - DesCipher.class CapabilityInfo.class CapsContainer.class \ - RecordingFrame.class SessionRecorder.class AuthUnixLoginPanel.class \ - SocketFactory.class HTTPConnectSocketFactory.class \ -- HTTPConnectSocket.class ReloginPanel.class -+ HTTPConnectSocket.class ReloginPanel.class \ -+ SSLSocketToMe.class -+ -+SSL_CLASSES = SSLSocketToMe*.class TrustDialog.class - - SOURCES = VncViewer.java RfbProto.java AuthPanel.java VncCanvas.java \ - OptionsFrame.java ClipboardFrame.java ButtonPanel.java \ - DesCipher.java CapabilityInfo.java CapsContainer.java \ - RecordingFrame.java SessionRecorder.java AuthUnixLoginPanel.java \ - SocketFactory.java HTTPConnectSocketFactory.java \ -- HTTPConnectSocket.java ReloginPanel.java -+ HTTPConnectSocket.java ReloginPanel.java \ -+ SSLSocketToMe.java - - all: $(CLASSES) $(ARCHIVE) - - $(CLASSES): $(SOURCES) -- $(JC) -target 1.1 -O $(SOURCES) -+ $(JC) $(JC_ARGS) -O $(SOURCES) - - $(ARCHIVE): $(CLASSES) $(MANIFEST) -- $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) -+ $(JAR) cfm $(ARCHIVE) $(MANIFEST) $(CLASSES) $(SSL_CLASSES) - - install: $(CLASSES) $(ARCHIVE) -- $(CP) $(CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) -+ $(CP) $(CLASSES) $(SSL_CLASSES) $(ARCHIVE) $(PAGES) $(INSTALL_DIR) - - export:: $(CLASSES) $(ARCHIVE) $(PAGES) - @$(ExportJavaClasses) -diff -Naur vnc_javasrc.orig/RfbProto.java vnc_javasrc/RfbProto.java ---- vnc_javasrc.orig/RfbProto.java 2004-03-04 08:34:25.000000000 -0500 -+++ vnc_javasrc/RfbProto.java 2010-11-30 22:05:12.000000000 -0500 -@@ -199,7 +199,21 @@ - host = h; - port = p; - -- if (viewer.socketFactory == null) { -+ if (! viewer.disableSSL) { -+ System.out.println("new SSLSocketToMe"); -+ SSLSocketToMe ssl; -+ try { -+ ssl = new SSLSocketToMe(host, port, v); -+ } catch (Exception e) { -+ throw new IOException(e.getMessage()); -+ } -+ -+ try { -+ sock = ssl.connectSock(); -+ } catch (Exception es) { -+ throw new IOException(es.getMessage()); -+ } -+ } else if (viewer.socketFactory == null) { - sock = new Socket(host, port); - } else { - try { -@@ -255,7 +269,7 @@ - || (b[10] < '0') || (b[10] > '9') || (b[11] != '\n')) - { - throw new Exception("Host " + host + " port " + port + -- " is not an RFB server"); -+ " is not an RFB server: " + b); - } - - serverMajor = (b[4] - '0') * 100 + (b[5] - '0') * 10 + (b[6] - '0'); -@@ -892,6 +906,38 @@ - final static int ALT_MASK = InputEvent.ALT_MASK; - - -+ void writeWheelEvent(MouseWheelEvent evt) throws IOException { -+ -+ eventBufLen = 0; -+ -+ int x = evt.getX(); -+ int y = evt.getY(); -+ -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; -+ -+ int ptrmask; -+ -+ int clicks = evt.getWheelRotation(); -+ System.out.println("writeWheelEvent: clicks: " + clicks); -+ if (clicks > 0) { -+ ptrmask = 16; -+ } else if (clicks < 0) { -+ ptrmask = 8; -+ } else { -+ return; -+ } -+ -+ eventBuf[eventBufLen++] = (byte) PointerEvent; -+ eventBuf[eventBufLen++] = (byte) ptrmask; -+ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (x & 0xff); -+ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (y & 0xff); -+ -+ os.write(eventBuf, 0, eventBufLen); -+ } -+ - // - // Write a pointer event message. We may need to send modifier key events - // around it to set the correct modifier state. -@@ -992,6 +1038,19 @@ - boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); - - int key; -+ if (viewer.debugKeyboard) { -+ System.out.println("----------------------------------------"); -+ System.out.println("evt.getKeyChar: " + evt.getKeyChar()); -+ System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); -+ System.out.println("evt.getKeyCode: " + evt.getKeyCode()); -+ System.out.println("evt.getID: " + evt.getID()); -+ System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); -+ System.out.println("evt.isActionKey: " + evt.isActionKey()); -+ System.out.println("evt.isControlDown: " + evt.isControlDown()); -+ System.out.println("evt.getModifiers: " + evt.getModifiers()); -+ System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); -+ System.out.println("evt.paramString: " + evt.paramString()); -+ } - if (evt.isActionKey()) { - - // -@@ -1025,6 +1084,13 @@ - return; - } - -+ if(key == 0xffc2 && viewer.mapF5_to_atsign) { -+ if (viewer.debugKeyboard) { -+ System.out.println("Mapping: F5 -> AT "); -+ } -+ key = 0x40; -+ } -+ - } else { - - // -@@ -1036,6 +1102,7 @@ - - key = keyChar; - -+ - if (key < 0x20) { - if (evt.isControlDown()) { - key += 0x60; -@@ -1121,6 +1188,16 @@ - int oldModifiers = 0; - - void writeModifierKeyEvents(int newModifiers) { -+ if(viewer.forbid_Ctrl_Alt) { -+ if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { -+ int orig = newModifiers; -+ newModifiers &= ~ALT_MASK; -+ newModifiers &= ~CTRL_MASK; -+ if (viewer.debugKeyboard) { -+ System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); -+ } -+ } -+ } - if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) - writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); - -diff -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 2010-07-10 19:18:06.000000000 -0400 -@@ -0,0 +1,2067 @@ -+/* -+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. -+ * -+ * Copyright (c) 2006 Karl J. Runge -+ * 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; 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. -+ * -+ */ -+ -+import java.net.*; -+import java.io.*; -+import javax.net.ssl.*; -+import java.util.*; -+ -+import java.security.*; -+import java.security.cert.*; -+import java.security.spec.*; -+import java.security.cert.Certificate; -+import java.security.cert.CertificateFactory; -+ -+import java.awt.*; -+import java.awt.event.*; -+ -+public class SSLSocketToMe { -+ -+ /* basic member data: */ -+ String host; -+ int port; -+ VncViewer viewer; -+ -+ boolean debug = true; -+ boolean debug_certs = false; -+ -+ /* sockets */ -+ SSLSocket socket = null; -+ SSLSocketFactory factory; -+ -+ /* fallback for Proxy connection */ -+ boolean proxy_in_use = false; -+ boolean proxy_failure = false; -+ public DataInputStream is = null; -+ public OutputStream os = null; -+ -+ /* strings from user WRT proxy: */ -+ String proxy_auth_string = null; -+ String proxy_dialog_host = null; -+ int proxy_dialog_port = 0; -+ -+ Socket proxySock; -+ DataInputStream proxy_is; -+ OutputStream proxy_os; -+ -+ /* trust contexts */ -+ SSLContext trustloc_ctx; -+ SSLContext trustall_ctx; -+ SSLContext trustsrv_ctx; -+ SSLContext trusturl_ctx; -+ SSLContext trustone_ctx; -+ -+ /* corresponding trust managers */ -+ TrustManager[] trustAllCerts; -+ TrustManager[] trustSrvCert; -+ TrustManager[] trustUrlCert; -+ TrustManager[] trustOneCert; -+ -+ /* client-side SSL auth key (oneTimeKey=...) */ -+ KeyManager[] mykey = null; -+ -+ boolean user_wants_to_see_cert = true; -+ String cert_fail = null; -+ -+ /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ -+ java.security.cert.Certificate[] trustallCerts = null; -+ java.security.cert.Certificate[] trustsrvCerts = null; -+ java.security.cert.Certificate[] trusturlCerts = null; -+ -+ /* utility to decode hex oneTimeKey=... and serverCert=... */ -+ byte[] hex2bytes(String s) { -+ byte[] bytes = new byte[s.length()/2]; -+ for (int i=0; i 127) { -+ val -= 256; -+ } -+ Integer I = new Integer(val); -+ bytes[i] = Byte.decode(I.toString()).byteValue(); -+ -+ } catch (Exception e) { -+ ; -+ } -+ } -+ return bytes; -+ } -+ -+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception { -+ host = h; -+ port = p; -+ viewer = v; -+ -+ debug_certs = v.debugCerts; -+ -+ /* we will first try default factory for certification: */ -+ -+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); -+ -+ dbg("SSL startup: " + host + " " + port); -+ -+ -+ /* create trust managers to be used if initial handshake fails: */ -+ -+ trustAllCerts = new TrustManager[] { -+ /* -+ * this one accepts everything. Only used if user -+ * has disabled checking (trustAllVncCerts=yes) -+ * or when we grab the cert to show it to them in -+ * a dialog and ask them to manually verify/accept it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ dbg("ALL: an untrusted connect to grab cert."); -+ } -+ } -+ }; -+ -+ trustUrlCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet and stored in -+ * trusturlCerts. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (URL)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trusturlCerts' */ -+ if (trusturlCerts == null) { -+ throw new CertificateException( -+ "No Trust url Certs array."); -+ } -+ if (trusturlCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust url Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trusturlCerts.length) { -+ throw new CertificateException( -+ "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trusturlCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("URL: cert mismatch at i=" + i); -+ dbg("URL: cert mismatch cert" + certs[i]); -+ dbg("URL: cert mismatch url" + trusturlCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("URL: cert info at i=" + i); -+ dbg("URL: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("URL: cert info url" + trusturlCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != URL Cert Chain."); -+ } -+ dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustSrvCert = new TrustManager[] { -+ /* -+ * this one accepts cert given to us in the serverCert -+ * Applet Parameter we were started with. It is -+ * currently a fatal error if the VNC Server's cert -+ * doesn't match it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (SRV)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustsrvCerts' */ -+ if (trustsrvCerts == null) { -+ throw new CertificateException( -+ "No Trust srv Certs array."); -+ } -+ if (trustsrvCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust srv Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustsrvCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustsrvCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("SRV: cert mismatch at i=" + i); -+ dbg("SRV: cert mismatch cert" + certs[i]); -+ dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("SRV: cert info at i=" + i); -+ dbg("SRV: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("SRV: cert info srv" + trustsrvCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != serverCert Applet Parameter Cert Chain."); -+ } -+ dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustOneCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet we stored in -+ * trustallCerts that user has accepted or applet -+ * parameter trustAllVncCerts=yes is set. This is -+ * for when we reconnect after the user has manually -+ * accepted the trustall cert in the dialog (or set -+ * trustAllVncCerts=yes applet param.) -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (ONE)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustallCerts' */ -+ if (trustallCerts == null) { -+ throw new CertificateException( -+ "No Trust All Server Certs array."); -+ } -+ if (trustallCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust All Server Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustallCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustallCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("ONE: cert mismatch at i=" + i); -+ dbg("ONE: cert mismatch cert" + certs[i]); -+ dbg("ONE: cert mismatch all" + trustallCerts[i]); -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("ONE: cert info at i=" + i); -+ dbg("ONE: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("ONE: cert info all" + trustallCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != TRUSTALL Cert Chain."); -+ } -+ dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ /* -+ * The above TrustManagers are used: -+ * -+ * 1) to retrieve the server cert in case of failure to -+ * display it to the user in a dialog. -+ * 2) to subsequently connect to the server if user agrees. -+ */ -+ -+ /* -+ * build oneTimeKey cert+key if supplied in applet parameter: -+ */ -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { -+ ClientCertDialog d = new ClientCertDialog(); -+ viewer.oneTimeKey = d.queryUser(); -+ } -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { -+ int idx = viewer.oneTimeKey.indexOf(","); -+ -+ String onetimekey = viewer.oneTimeKey.substring(0, idx); -+ byte[] key = hex2bytes(onetimekey); -+ String onetimecert = viewer.oneTimeKey.substring(idx+1); -+ byte[] cert = hex2bytes(onetimecert); -+ -+ KeyFactory kf = KeyFactory.getInstance("RSA"); -+ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); -+ PrivateKey ff = kf.generatePrivate (keysp); -+ if (debug_certs) { -+ dbg("one time key " + ff); -+ } -+ -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ Certificate[] certs = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ if (debug_certs) { -+ dbg("one time cert" + tmpcert); -+ } -+ certs[0] = tmpcert; -+ } else { -+ certs = (Certificate[]) c.toArray(); -+ } -+ -+ KeyStore ks = KeyStore.getInstance("JKS"); -+ ks.load(null, null); -+ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); -+ String da = KeyManagerFactory.getDefaultAlgorithm(); -+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); -+ kmf.init(ks, "".toCharArray()); -+ -+ mykey = kmf.getKeyManagers(); -+ } -+ -+ /* -+ * build serverCert cert if supplied in applet parameter: -+ */ -+ if (viewer.serverCert != null) { -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ byte[] cert = hex2bytes(viewer.serverCert); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ trustsrvCerts = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ trustsrvCerts[0] = tmpcert; -+ } else { -+ trustsrvCerts = (Certificate[]) c.toArray(); -+ } -+ } -+ -+ /* the trust loc certs context: */ -+ try { -+ trustloc_ctx = SSLContext.getInstance("SSL"); -+ -+ /* -+ * below is a failed attempt to get jvm's default -+ * trust manager using null (below) makes it so -+ * for HttpsURLConnection the server cannot be -+ * verified (no prompting.) -+ */ -+ if (false) { -+ boolean didit = false; -+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); -+ tmf.init((KeyStore) null); -+ TrustManager [] tml = tmf.getTrustManagers(); -+ for (int i = 0; i < tml.length; i++) { -+ TrustManager tm = tml[i]; -+ if (tm instanceof X509TrustManager) { -+ TrustManager tm1[] = new TrustManager[1]; -+ tm1[0] = tm; -+ trustloc_ctx.init(mykey, tm1, null); -+ didit = true; -+ break; -+ } -+ } -+ if (!didit) { -+ trustloc_ctx.init(mykey, null, null); -+ } -+ } else { -+ /* we have to set trust manager to null */ -+ trustloc_ctx.init(mykey, null, null); -+ } -+ -+ } catch (Exception e) { -+ String msg = "SSL trustloc_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust all certs context: */ -+ try { -+ trustall_ctx = SSLContext.getInstance("SSL"); -+ trustall_ctx.init(mykey, trustAllCerts, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustall_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust url certs context: */ -+ try { -+ trusturl_ctx = SSLContext.getInstance("SSL"); -+ trusturl_ctx.init(mykey, trustUrlCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trusturl_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust srv certs context: */ -+ try { -+ trustsrv_ctx = SSLContext.getInstance("SSL"); -+ trustsrv_ctx.init(mykey, trustSrvCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustsrv_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust the one cert from server context: */ -+ try { -+ trustone_ctx = SSLContext.getInstance("SSL"); -+ trustone_ctx.init(mykey, trustOneCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustone_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ } -+ -+ /* -+ * we call this early on to 1) check for a proxy, 2) grab -+ * Browser/JVM accepted HTTPS cert. -+ */ -+ public void check_for_proxy_and_grab_vnc_server_cert() { -+ -+ trusturlCerts = null; -+ proxy_in_use = false; -+ -+ if (viewer.ignoreProxy) { -+ /* applet param says skip it. */ -+ /* the downside is we do not set trusturlCerts for comparison later... */ -+ /* nor do we autodetect x11vnc for GET=1. */ -+ return; -+ } -+ -+ dbg("------------------------------------------------"); -+ dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); -+ -+ dbg("TRYING HTTPS:"); -+ String ustr = "https://" + host + ":"; -+ if (viewer.httpsPort != null) { -+ ustr += viewer.httpsPort; -+ } else { -+ ustr += port; -+ } -+ ustr += viewer.urlPrefix + "/check.https.proxy.connection"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTPS URL connection to host:port */ -+ URL url = new URL(ustr); -+ HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); -+ -+ if (mykey != null) { -+ /* with oneTimeKey (mykey) we can't use the default SSL context */ -+ if (trustsrvCerts != null) { -+ dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); -+ } else if (trustloc_ctx != null) { -+ dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); -+ } -+ } -+ -+ https.setUseCaches(false); -+ https.setRequestMethod("GET"); -+ https.setRequestProperty("Pragma", "No-Cache"); -+ https.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ https.setDoInput(true); -+ -+ dbg("trying https.connect()"); -+ https.connect(); -+ -+ dbg("trying https.getServerCertificates()"); -+ trusturlCerts = https.getServerCertificates(); -+ -+ if (trusturlCerts == null) { -+ dbg("set trusturlCerts to null!"); -+ } else { -+ dbg("set trusturlCerts to non-null"); -+ } -+ -+ if (https.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTPS proxy is in use. There may be connection problems."); -+ } -+ -+ dbg("trying https.getContent()"); -+ Object output = https.getContent(); -+ dbg("trying https.disconnect()"); -+ https.disconnect(); -+ if (! viewer.GET) { -+ String header = https.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (1), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ -+ } catch(Exception e) { -+ dbg("HttpsURLConnection: " + e.getMessage()); -+ } -+ -+ if (proxy_in_use) { -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } else if (trusturlCerts != null && !viewer.forceProxy) { -+ /* Allow user to require HTTP check? use forceProxy for now. */ -+ dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } -+ -+ /* -+ * XXX need to remember scenario where this extra check -+ * gives useful info. User's Browser proxy settings? -+ */ -+ dbg("TRYING HTTP:"); -+ ustr = "http://" + host + ":" + port; -+ ustr += viewer.urlPrefix + "/index.vnc"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ -+ URL url = new URL(ustr); -+ HttpURLConnection http = (HttpURLConnection) -+ url.openConnection(); -+ -+ http.setUseCaches(false); -+ http.setRequestMethod("GET"); -+ http.setRequestProperty("Pragma", "No-Cache"); -+ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ http.setDoInput(true); -+ -+ dbg("trying http.connect()"); -+ http.connect(); -+ -+ if (http.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTP proxy is in use. There may be connection problems."); -+ } -+ dbg("trying http.getContent()"); -+ Object output = http.getContent(); -+ dbg("trying http.disconnect()"); -+ http.disconnect(); -+ if (! viewer.GET) { -+ String header = http.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (2), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ } catch(Exception e) { -+ dbg("HttpURLConnection: " + e.getMessage()); -+ } -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ } -+ -+ public Socket connectSock() throws IOException { -+ /* -+ * first try a https connection to detect a proxy, and -+ * grab the VNC server cert at the same time: -+ */ -+ check_for_proxy_and_grab_vnc_server_cert(); -+ -+ boolean srv_cert = false; -+ -+ if (trustsrvCerts != null) { -+ /* applet parameter suppled serverCert */ -+ dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); -+ factory = trustsrv_ctx.getSocketFactory(); -+ srv_cert = true; -+ } else if (viewer.trustAllVncCerts) { -+ /* trust all certs (no checking) */ -+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); -+ factory = trustall_ctx.getSocketFactory(); -+ } else if (trusturlCerts != null) { -+ /* trust certs the Browser/JVM accepted in check_for_proxy... */ -+ dbg("using trusturl_ctx"); -+ factory = trusturl_ctx.getSocketFactory(); -+ } else { -+ /* trust the local defaults */ -+ dbg("using trustloc_ctx"); -+ factory = trustloc_ctx.getSocketFactory(); -+ } -+ -+ socket = null; -+ -+ try { -+ if (proxy_in_use && viewer.forceProxy) { -+ throw new Exception("forcing proxy (forceProxy)"); -+ } else if (viewer.CONNECT != null) { -+ throw new Exception("forcing CONNECT"); -+ } -+ -+ int timeout = 6; -+ if (timeout > 0) { -+ socket = (SSLSocket) factory.createSocket(); -+ InetSocketAddress inetaddr = new InetSocketAddress(host, port); -+ dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); -+ socket.connect(inetaddr, timeout * 1000); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ } catch (Exception esock) { -+ dbg("socket error: " + esock.getMessage()); -+ if (proxy_in_use || viewer.CONNECT != null) { -+ proxy_failure = true; -+ if (proxy_in_use) { -+ dbg("HTTPS proxy in use. Trying to go with it."); -+ } else { -+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); -+ } -+ try { -+ socket = proxy_socket(factory); -+ } catch (Exception e) { -+ dbg("proxy_socket error: " + e.getMessage()); -+ } -+ } else { -+ /* n.b. socket is left in error state to cause ex. below. */ -+ } -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The Server Connection Verified OK on 1st try."); -+ -+ java.security.cert.Certificate[] currentTrustedCerts; -+ BrowserCertsDialog bcd; -+ -+ SSLSession sess = socket.getSession(); -+ currentTrustedCerts = sess.getPeerCertificates(); -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-1 keeping socket."); -+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy."); -+ } -+ socket = null; -+ throw new SSLHandshakeException("no current certs"); -+ } -+ -+ String serv = ""; -+ try { -+ CertInfo ci = new CertInfo(currentTrustedCerts[0]); -+ serv = ci.get_certinfo("CN"); -+ } catch (Exception e) { -+ ; -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.serverCert != null && trustsrvCerts != null) { -+ dbg("viewer.serverCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.trustUrlVncCert) { -+ dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else { -+ /* have a dialog with the user: */ -+ bcd = new BrowserCertsDialog(serv, host + ":" + port); -+ dbg("browser certs dialog begin."); -+ bcd.queryUser(); -+ dbg("browser certs dialog finished."); -+ -+ if (bcd.showCertDialog) { -+ String msg = "user wants to see cert"; -+ dbg(msg); -+ user_wants_to_see_cert = true; -+ if (cert_fail == null) { -+ cert_fail = "user-view"; -+ } -+ throw new SSLHandshakeException(msg); -+ } else { -+ user_wants_to_see_cert = false; -+ dbg("browser certs dialog: user said yes, accept it"); -+ } -+ } -+ -+ } catch (SSLHandshakeException eh) { -+ dbg("SSLHandshakeException: could not automatically verify Server."); -+ dbg("msg: " + eh.getMessage()); -+ -+ -+ /* send a cleanup string just in case: */ -+ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; -+ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!"); -+ } -+ -+ /* reload */ -+ -+ socket = null; -+ -+ String reason = null; -+ -+ if (srv_cert) { -+ /* for serverCert usage we make this a fatal error. */ -+ throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); -+ /* see below in TrustDialog were we describe this case to user anyway */ -+ } -+ -+ /* -+ * Reconnect, trusting any cert, so we can grab -+ * the cert to show it to the user in a dialog -+ * for him to manually accept. This connection -+ * is not used for anything else. -+ */ -+ factory = trustall_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ if (debug_certs) { -+ dbg("trusturlCerts: " + trusturlCerts); -+ dbg("trustsrvCerts: " + trustsrvCerts); -+ } -+ if (trusturlCerts == null && cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); -+ -+ /* grab the cert: */ -+ try { -+ SSLSession sess = socket.getSession(); -+ trustallCerts = sess.getPeerCertificates(); -+ } catch (Exception e) { -+ throw new Exception("Could not get " + -+ "Peer Certificate"); -+ } -+ if (debug_certs) { -+ dbg("trustallCerts: " + trustallCerts); -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); -+ } else if (! browser_cert_match()) { -+ /* -+ * close socket now, we will reopen after -+ * dialog if user agrees to use the cert. -+ */ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!"); -+ } -+ socket = null; -+ -+ /* dialog with user to accept cert or not: */ -+ -+ TrustDialog td= new TrustDialog(host, port, -+ trustallCerts); -+ -+ if (cert_fail == null) { -+ ; -+ } else if (cert_fail.equals("user-view")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " You Asked to View the Certificate."; -+ } else if (cert_fail.equals("server-cert-mismatch")) { -+ /* this is now fatal error, see above. */ -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Certificate\n" -+ + " specified in the supplied 'serverCert' Applet Parameter."; -+ } else if (cert_fail.equals("cert-mismatch")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Website's\n" -+ + " HTTPS Certificate (that you previously accepted; either\n" -+ + " manually or automatically via Certificate Authority.)"; -+ } else if (cert_fail.equals("missing-certs")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " Not all Certificates could be obtained to check."; -+ } -+ -+ if (! td.queryUser(reason)) { -+ String msg = "User decided against it."; -+ dbg(msg); -+ throw new IOException(msg); -+ } -+ } -+ -+ } catch (Exception ehand2) { -+ dbg("** Could not TrustAll Verify Server!"); -+ -+ throw new IOException(ehand2.getMessage()); -+ } -+ -+ /* reload again: */ -+ -+ if (socket != null) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!!"); -+ } -+ socket = null; -+ } -+ -+ /* -+ * Now connect a 3rd time, using the cert -+ * retrieved during connection 2 (sadly, that -+ * the user likely blindly agreed to...) -+ */ -+ -+ factory = trustone_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ try { -+ socket.startHandshake(); -+ dbg("TrustAll/TrustOne Server Connection Verified #3."); -+ -+ } catch (Exception ehand3) { -+ dbg("** Could not TrustAll/TrustOne Verify Server #3."); -+ -+ throw new IOException(ehand3.getMessage()); -+ } -+ } -+ -+ /* we have socket (possibly null) at this point, so proceed: */ -+ -+ /* handle x11vnc GET=1, if applicable: */ -+ if (socket != null && viewer.GET) { -+ String str = "GET "; -+ str += viewer.urlPrefix; -+ str += "/request.https.vnc.connection"; -+ str += " HTTP/1.0\r\n"; -+ str += "Pragma: No-Cache\r\n"; -+ str += "\r\n"; -+ -+ System.out.println("sending: " + str); -+ OutputStream os = socket.getOutputStream(); -+ String type = "os"; -+ -+ if (type == "os") { -+ os.write(str.getBytes()); -+ os.flush(); -+ System.out.println("used OutputStream"); -+ } else if (type == "bs") { -+ BufferedOutputStream bs = new BufferedOutputStream(os); -+ bs.write(str.getBytes()); -+ bs.flush(); -+ System.out.println("used BufferedOutputStream"); -+ } else if (type == "ds") { -+ DataOutputStream ds = new DataOutputStream(os); -+ ds.write(str.getBytes()); -+ ds.flush(); -+ System.out.println("used DataOutputStream"); -+ } -+ if (false) { -+ String rep = ""; -+ DataInputStream is = new DataInputStream( -+ new BufferedInputStream(socket.getInputStream(), 16384)); -+ while (true) { -+ rep += readline(is); -+ if (rep.indexOf("\r\n\r\n") >= 0) { -+ break; -+ } -+ } -+ System.out.println("rep: " + rep); -+ } -+ } -+ -+ dbg("SSL returning socket to caller."); -+ dbg(""); -+ -+ /* could be null, let caller handle that. */ -+ return (Socket) socket; -+ } -+ -+ boolean browser_cert_match() { -+ String msg = "Browser URL accept previously accepted cert"; -+ -+ if (user_wants_to_see_cert) { -+ return false; -+ } -+ -+ if (viewer.serverCert != null || trustsrvCerts != null) { -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (trustallCerts != null && trusturlCerts != null) { -+ if (trustallCerts.length == trusturlCerts.length) { -+ boolean ok = true; -+ /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ -+ for (int i = 0; i < trusturlCerts.length; i++) { -+ if (! trustallCerts[i].equals(trusturlCerts[i])) { -+ dbg("BCM: cert mismatch at i=" + i); -+ dbg("BCM: cert mismatch url" + trusturlCerts[i]); -+ dbg("BCM: cert mismatch all" + trustallCerts[i]); -+ ok = false; -+ } -+ } -+ if (ok) { -+ System.out.println(msg); -+ if (cert_fail == null) { -+ cert_fail = "did-not-fail"; -+ } -+ return true; -+ } else { -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ return false; -+ } -+ } -+ } -+ if (cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ return false; -+ } -+ -+ private void dbg(String s) { -+ if (debug) { -+ System.out.println(s); -+ } -+ } -+ -+ private int gint(String s) { -+ int n = -1; -+ try { -+ Integer I = new Integer(s); -+ n = I.intValue(); -+ } catch (Exception ex) { -+ return -1; -+ } -+ return n; -+ } -+ -+ /* this will do the proxy CONNECT negotiation and hook us up. */ -+ -+ 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); -+ -+ /* we loop here a few times trying for the password case */ -+ for (int k=0; k < 2; k++) { -+ dbg("proxy_in_use psocket: " + k); -+ -+ if (proxySock != null) { -+ try { -+ proxySock.close(); -+ } catch (Exception e) { -+ dbg("proxy socket is grumpy."); -+ } -+ } -+ -+ 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 via proxy: " + 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("some proxy socket problem: " + e.getMessage()); -+ } -+ -+ /* read the rest of the HTTP headers */ -+ 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("")) { -+ /* we only try once for the non-password case: */ -+ break; -+ } -+ } -+ } -+ -+ public SSLSocket proxy_socket(SSLSocketFactory factory) { -+ Properties props = null; -+ String proxyHost = null; -+ int proxyPort = 0; -+ String proxyHost_nossl = null; -+ int proxyPort_nossl = 0; -+ String str; -+ -+ /* see if we can guess the proxy info from Properties: */ -+ try { -+ props = System.getProperties(); -+ } catch (Exception e) { -+ /* sandboxed applet might not be able to read it. */ -+ dbg("props failed: " + e.getMessage()); -+ } -+ if (viewer.proxyHost != null) { -+ dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); -+ proxyHost = viewer.proxyHost; -+ if (viewer.proxyPort != null) { -+ proxyPort = gint(viewer.proxyPort); -+ } else { -+ proxyPort = 8080; -+ } -+ -+ } else if (props != null) { -+ dbg("\n---------------\nAll props:"); -+ props.list(System.out); -+ dbg("\n---------------\n\n"); -+ -+ /* scrape throught properties looking for proxy info: */ -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (s2.indexOf("proxy.https.host") >= 0) { -+ proxyHost = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.https.port") >= 0) { -+ proxyPort = gint(v2); -+ continue; -+ } -+ if (s2.indexOf("proxy.http.host") >= 0) { -+ proxyHost_nossl = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.http.port") >= 0) { -+ proxyPort_nossl = gint(v2); -+ continue; -+ } -+ } -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (proxyHost != null && proxyPort > 0) { -+ break; -+ } -+ -+ // look for something like: javaplugin.proxy.config.list = http=10.0.2.1:8082 -+ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { -+ continue; -+ } -+ if (v2.indexOf("http") < 0) { -+ continue; -+ } -+ -+ String[] pieces = v.split("[,;]"); -+ for (int i = 0; i < pieces.length; i++) { -+ String p = pieces[i]; -+ int j = p.indexOf("https"); -+ if (j < 0) { -+ j = p.indexOf("http"); -+ if (j < 0) { -+ continue; -+ } -+ } -+ j = p.indexOf("=", j); -+ if (j < 0) { -+ continue; -+ } -+ p = p.substring(j+1); -+ String [] hp = p.split(":"); -+ if (hp.length != 2) { -+ continue; -+ } -+ if (hp[0].length() > 1 && hp[1].length() > 1) { -+ -+ proxyPort = gint(hp[1]); -+ if (proxyPort < 0) { -+ continue; -+ } -+ proxyHost = new String(hp[0]); -+ break; -+ } -+ } -+ } -+ } -+ if (proxyHost != null) { -+ if (proxyHost_nossl != null && proxyPort_nossl > 0) { -+ dbg("Using http proxy info instead of https."); -+ proxyHost = proxyHost_nossl; -+ proxyPort = proxyPort_nossl; -+ } -+ } -+ -+ if (proxy_in_use) { -+ if (proxy_dialog_host != null && proxy_dialog_port > 0) { -+ proxyHost = proxy_dialog_host; -+ proxyPort = proxy_dialog_port; -+ } -+ if (proxyHost != null) { -+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); -+ } else { -+ /* ask user to help us: */ -+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); -+ pd.queryUser(); -+ proxyHost = pd.getHost(); -+ proxyPort = pd.getPort(); -+ proxy_dialog_host = new String(proxyHost); -+ proxy_dialog_port = proxyPort; -+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); -+ } -+ -+ proxy_helper(proxyHost, proxyPort); -+ if (proxySock == null) { -+ return null; -+ } -+ } else if (viewer.CONNECT != null) { -+ dbg("viewer.CONNECT psocket:"); -+ proxySock = psocket(host, port); -+ if (proxySock == null) { -+ dbg("1-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ -+ if (viewer.CONNECT != null) { -+ String hp = viewer.CONNECT; -+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n\r\n"; -+ -+ dbg("requesting2: " + req2); -+ -+ try { -+ proxy_os.write(req2.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied2: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ } catch(Exception e) { -+ dbg("proxy socket problem-2: " + e.getMessage()); -+ } -+ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line2: " + line.trim()); -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } -+ } -+ -+ Socket sslsock = null; -+ try { -+ sslsock = factory.createSocket(proxySock, host, port, true); -+ } catch(Exception e) { -+ dbg("sslsock prob: " + e.getMessage()); -+ dbg("3 sadly, returning a null socket"); -+ } -+ -+ return (SSLSocket) sslsock; -+ } -+ -+ Socket psocket(String h, int p) { -+ Socket psock = null; -+ try { -+ psock = new Socket(h, p); -+ proxy_is = new DataInputStream(new BufferedInputStream( -+ psock.getInputStream(), 16384)); -+ proxy_os = psock.getOutputStream(); -+ } catch(Exception e) { -+ dbg("psocket prob: " + e.getMessage()); -+ return null; -+ } -+ -+ return psock; -+ } -+ -+ String readline(DataInputStream i) { -+ byte[] ba = new byte[1]; -+ String s = new String(""); -+ ba[0] = 0; -+ try { -+ while (ba[0] != 0xa) { -+ ba[0] = (byte) i.readUnsignedByte(); -+ s += new String(ba); -+ } -+ } catch (Exception e) { -+ ; -+ } -+ return s; -+ } -+} -+ -+class TrustDialog implements ActionListener { -+ String msg, host, text; -+ int port; -+ java.security.cert.Certificate[] trustallCerts = null; -+ boolean viewing_cert = false; -+ boolean trust_this_session = false; -+ -+ /* -+ * 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, cancel, viewcert; -+ TextArea textarea; -+ Checkbox accept, deny; -+ Dialog dialog; -+ -+ String s1 = "Accept this certificate temporarily for this session"; -+ String s2 = "Do not accept this certificate and do not connect to" -+ + " this VNC server"; -+ String ln = "\n---------------------------------------------------\n\n"; -+ -+ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { -+ host = h; -+ port = p; -+ trustallCerts = s; -+ -+ msg = "VNC Server " + host + ":" + port + " Not Verified"; -+ } -+ -+ public boolean queryUser(String reason) { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame(msg); -+ -+ dialog = new Dialog(frame, true); -+ -+ String infostr = ""; -+ if (trustallCerts.length == 1) { -+ CertInfo ci = new CertInfo(trustallCerts[0]); -+ infostr = ci.get_certinfo("all"); -+ } -+ if (reason != null) { -+ reason += "\n\n"; -+ } -+ -+ text = "\n" -++ "Unable to verify the identity of\n" -++ "\n" -++ " " + host + ":" + port + "\n" -++ "\n" -++ infostr -++ "\n" -++ "as a trusted VNC server.\n" -++ "\n" -++ reason -++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" -++ "is due to one of the following:\n" -++ "\n" -++ " - Your requesting to View the Certificate before accepting.\n" -++ "\n" -++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" -++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" -++ "\n" -++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" -++ " the Apache Web server has a certificate *different* from the VNC server's.\n" -++ "\n" -++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" -++ " obtained by this applet to compare the VNC Server Certificate against.\n" -++ "\n" -++ " - The VNC Server's Certificate does not match the one specified in the\n" -++ " supplied 'serverCert' Java Applet Parameter.\n" -++ "\n" -++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" -++ " to connect to. (Wouldn't that be exciting!!)\n" -++ "\n" -++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" -++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" -++ "automatically authenticate this VNC Server.\n" -++ "\n" -++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" -++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" -++ "certificate (except for the Apache portal case above where they don't match.)\n" -++ "\n" -++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" -++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" -++ "and thereby see no dialog from this VNC Viewer applet.\n" -+; -+ -+ /* the accept / do-not-accept radio buttons: */ -+ CheckboxGroup checkbox = new CheckboxGroup(); -+ accept = new Checkbox(s1, true, checkbox); -+ deny = new Checkbox(s2, false, checkbox); -+ -+ /* put the checkboxes in a panel: */ -+ Panel check = new Panel(); -+ check.setLayout(new GridLayout(2, 1)); -+ -+ check.add(accept); -+ check.add(deny); -+ -+ /* make the 3 buttons: */ -+ ok = new Button("OK"); -+ cancel = new Button("Cancel"); -+ viewcert = new Button("View Certificate"); -+ -+ ok.addActionListener(this); -+ cancel.addActionListener(this); -+ viewcert.addActionListener(this); -+ -+ /* put the buttons in their own panel: */ -+ Panel buttonrow = new Panel(); -+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); -+ buttonrow.add(viewcert); -+ buttonrow.add(ok); -+ buttonrow.add(cancel); -+ -+ /* label at the top: */ -+ Label label = new Label(msg, Label.CENTER); -+ label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ -+ /* textarea in the middle */ -+ textarea = new TextArea(text, 38, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ -+ /* put the two panels in their own panel at bottom: */ -+ Panel bot = new Panel(); -+ bot.setLayout(new GridLayout(2, 1)); -+ bot.add(check); -+ bot.add(buttonrow); -+ -+ /* now arrange things inside the dialog: */ -+ dialog.setLayout(new BorderLayout()); -+ -+ dialog.add("North", label); -+ dialog.add("South", bot); -+ dialog.add("Center", textarea); -+ -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ -+ return trust_this_session; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ -+ if (evt.getSource() == viewcert) { -+ /* View Certificate button clicked */ -+ if (viewing_cert) { -+ /* show the original info text: */ -+ textarea.setText(text); -+ viewcert.setLabel("View Certificate"); -+ viewing_cert = false; -+ } else { -+ int i; -+ /* show all (likely just one) certs: */ -+ textarea.setText(""); -+ for (i=0; i < trustallCerts.length; i++) { -+ int j = i + 1; -+ textarea.append("Certificate[" + -+ j + "]\n\n"); -+ textarea.append( -+ trustallCerts[i].toString()); -+ textarea.append(ln); -+ } -+ viewcert.setLabel("View Info"); -+ viewing_cert = true; -+ -+ textarea.setCaretPosition(0); -+ } -+ -+ } else if (evt.getSource() == ok) { -+ /* OK button clicked */ -+ if (accept.getState()) { -+ trust_this_session = true; -+ } else { -+ trust_this_session = false; -+ } -+ //dialog.dispose(); -+ dialog.hide(); -+ -+ } else if (evt.getSource() == cancel) { -+ /* Cancel button clicked */ -+ trust_this_session = false; -+ -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+ -+ String get_certinfo() { -+ String all = ""; -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ int i; -+ if (trustallCerts.length < 1) { -+ all = ""; -+ return all; -+ } -+ String cert = trustallCerts[0].toString(); -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cert.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cert.indexOf(", ", f); -+ t2 = cert.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cert.substring(f, t); -+ all = all + " " + sub + "\n"; -+ } -+ } -+ } -+ return all; -+ } -+} -+ -+class ProxyDialog implements ActionListener { -+ String guessedHost = null; -+ String guessedPort = 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 entry; -+ String reply = ""; -+ -+ ProxyDialog (String h, int p) { -+ guessedHost = h; -+ try { -+ guessedPort = Integer.toString(p); -+ } catch (Exception e) { -+ guessedPort = "8080"; -+ } -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Need Proxy host:port"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); -+ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ String guess = ""; -+ if (guessedHost != null) { -+ guess = guessedHost + ":" + guessedPort; -+ } -+ entry.setText(guess); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return; -+ } -+ -+ public String getHost() { -+ int i = reply.indexOf(":"); -+ if (i < 0) { -+ return "unknown"; -+ } -+ String h = reply.substring(0, i); -+ return h; -+ } -+ -+ public int getPort() { -+ int i = reply.indexOf(":"); -+ int p = 8080; -+ if (i < 0) { -+ return p; -+ } -+ i++; -+ String ps = reply.substring(i); -+ try { -+ Integer I = new Integer(ps); -+ p = I.intValue(); -+ } catch (Exception e) { -+ ; -+ } -+ return p; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+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; -+ Dialog dialog; -+ TextField entry; -+ String reply = ""; -+ -+ ClientCertDialog() { -+ ; -+ } -+ -+ public String queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Enter SSL Client Cert+Key String"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return reply; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class BrowserCertsDialog implements ActionListener { -+ Button yes, no; -+ Dialog dialog; -+ String vncServer; -+ String hostport; -+ public boolean showCertDialog = true; -+ -+ BrowserCertsDialog(String serv, String hp) { -+ vncServer = serv; -+ hostport = hp; -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Use Browser/JVM Certs?"); -+ -+ dialog = new Dialog(frame, true); -+ -+ String m = ""; -+m += "\n"; -+m += "This VNC Viewer applet does not have its own keystore to track\n"; -+m += "SSL certificates, and so cannot authenticate the certificate\n"; -+m += "of the VNC Server:\n"; -+m += "\n"; -+m += " " + hostport + "\n\n " + vncServer + "\n"; -+m += "\n"; -+m += "on its own.\n"; -+m += "\n"; -+m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; -+m += "has previously accepted the same certificate. You may have set\n"; -+m += "this up permanently or just for this session, or the server\n"; -+m += "certificate was signed by a CA cert that your Web Browser or\n"; -+m += "Java VM Plugin has.\n"; -+m += "\n"; -+m += "If the VNC Server connection times out while you are reading this\n"; -+m += "dialog, then restart the connection and try again.\n"; -+m += "\n"; -+m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; -+m += "\n"; -+ -+ TextArea textarea = new TextArea(m, 22, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ yes = new Button("Yes"); -+ yes.addActionListener(this); -+ no = new Button("No, Let Me See the Certificate."); -+ no.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", textarea); -+ dialog.add("Center", yes); -+ dialog.add("South", no); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til Yes or No pressed. */ -+ System.out.println("done show()"); -+ return; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == yes) { -+ showCertDialog = false; -+ //dialog.dispose(); -+ dialog.hide(); -+ } else if (evt.getSource() == no) { -+ showCertDialog = true; -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ System.out.println("done actionPerformed()"); -+ } -+} -+ -+class CertInfo { -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ java.security.cert.Certificate cert; -+ String certString = ""; -+ -+ CertInfo(java.security.cert.Certificate c) { -+ cert = c; -+ certString = cert.toString(); -+ } -+ -+ String get_certinfo(String which) { -+ int i; -+ String cs = new String(certString); -+ String all = ""; -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cs.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cs.indexOf(", ", f); -+ t2 = cs.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cs.substring(f, t); -+ all = all + " " + sub + "\n"; -+ if (which.equals(fields[i])) { -+ return sub; -+ } -+ } -+ } -+ } -+ if (which.equals("all")) { -+ return all; -+ } else { -+ return ""; -+ } -+ } -+} -+ -+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= 2) { -+ proxyPort = new String(pieces[1]); -+ } else { -+ proxyPort = new String("8080"); -+ } -+ } -+ } -+ str = readParameter("proxyHost", false); -+ if (str != null) { -+ proxyHost = new String(str); -+ } -+ str = readParameter("proxyPort", false); -+ if (str != null) { -+ proxyPort = new String(str); -+ } -+ if (proxyHost != null && proxyPort == null) { -+ proxyPort = new String("8080"); -+ } -+ -+ ignoreProxy = false; -+ str = readParameter("ignoreProxy", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ignoreProxy = true; -+ } -+ -+ trustAllVncCerts = false; -+ str = readParameter("trustAllVncCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustAllVncCerts = true; -+ } -+ trustUrlVncCert = false; -+ str = readParameter("trustUrlVncCert", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustUrlVncCert = true; -+ } -+ debugCerts = false; -+ str = readParameter("debugCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugCerts = true; -+ } -+ debugKeyboard = false; -+ str = readParameter("debugKeyboard", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugKeyboard = true; -+ } -+ mapF5_to_atsign = false; -+ str = readParameter("mapF5_to_atsign", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ mapF5_to_atsign = true; -+ } -+ forbid_Ctrl_Alt = false; -+ str = readParameter("forbid_Ctrl_Alt", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ forbid_Ctrl_Alt = true; -+ } - } - - public String readParameter(String name, boolean required) { diff --git a/classes/ssl/ultra.vnc b/classes/ssl/ultra.vnc deleted file mode 100644 index 3c57445..0000000 --- a/classes/ssl/ultra.vnc +++ /dev/null @@ -1,28 +0,0 @@ - - - - -$USER's $DESKTOP desktop ($DISPLAY) - - - - - - -$PARAMS - -
-x11vnc site - diff --git a/classes/ssl/ultraproxy.vnc b/classes/ssl/ultraproxy.vnc deleted file mode 100644 index fd842c4..0000000 --- a/classes/ssl/ultraproxy.vnc +++ /dev/null @@ -1,28 +0,0 @@ - - - - -$USER's $DESKTOP desktop ($DISPLAY) - - - - - - -$PARAMS - -
-x11vnc site - diff --git a/classes/ssl/ultrasigned.vnc b/classes/ssl/ultrasigned.vnc deleted file mode 100644 index a711655..0000000 --- a/classes/ssl/ultrasigned.vnc +++ /dev/null @@ -1,28 +0,0 @@ - - - - -$USER's $DESKTOP desktop ($DISPLAY) - - - - - - -$PARAMS - -
-x11vnc site - diff --git a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch deleted file mode 100644 index 3309860..0000000 --- a/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch +++ /dev/null @@ -1,5494 +0,0 @@ -diff -Naur JavaViewer.orig/ButtonPanel.java JavaViewer/ButtonPanel.java ---- JavaViewer.orig/ButtonPanel.java 2004-12-12 20:51:02.000000000 -0500 -+++ JavaViewer/ButtonPanel.java 2007-05-31 15:40:45.000000000 -0400 -@@ -43,30 +43,36 @@ - viewer = v; - - setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); -- disconnectButton = new Button("Disconnect"); -+ if (v.ftpOnly) { -+ disconnectButton = new Button("Quit"); -+ } else { -+ disconnectButton = new Button("Close"); -+ } - disconnectButton.setEnabled(false); - add(disconnectButton); - disconnectButton.addActionListener(this); -- optionsButton = new Button("Options"); -- add(optionsButton); -- optionsButton.addActionListener(this); -- clipboardButton = new Button("Clipboard"); -- clipboardButton.setEnabled(false); -- add(clipboardButton); -- clipboardButton.addActionListener(this); -- if (viewer.rec != null) { -- recordButton = new Button("Record"); -- add(recordButton); -- recordButton.addActionListener(this); -- } -- ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); -- ctrlAltDelButton.setEnabled(false); -- add(ctrlAltDelButton); -- ctrlAltDelButton.addActionListener(this); -- refreshButton = new Button("Refresh"); -- refreshButton.setEnabled(false); -- add(refreshButton); -- refreshButton.addActionListener(this); -+ if (!v.ftpOnly) { -+ optionsButton = new Button("Options"); -+ add(optionsButton); -+ optionsButton.addActionListener(this); -+ clipboardButton = new Button("Clipboard"); -+ clipboardButton.setEnabled(false); -+ add(clipboardButton); -+ clipboardButton.addActionListener(this); -+ if (viewer.rec != null) { -+ recordButton = new Button("Record"); -+ add(recordButton); -+ recordButton.addActionListener(this); -+ } -+ ctrlAltDelButton = new Button("Send Ctrl-Alt-Del"); -+ ctrlAltDelButton.setEnabled(false); -+ add(ctrlAltDelButton); -+ ctrlAltDelButton.addActionListener(this); -+ refreshButton = new Button("Refresh"); -+ refreshButton.setEnabled(false); -+ add(refreshButton); -+ refreshButton.addActionListener(this); -+ } - ftpButton = new Button("File Transfer"); - ftpButton.setEnabled(false); - add(ftpButton); -@@ -79,9 +85,10 @@ - - public void enableButtons() { - disconnectButton.setEnabled(true); -+ ftpButton.setEnabled(true); -+ if (viewer.ftpOnly) {return;} - clipboardButton.setEnabled(true); - refreshButton.setEnabled(true); -- ftpButton.setEnabled(true); - } - - // -@@ -89,6 +96,9 @@ - // - - public void disableButtonsOnDisconnect() { -+ ftpButton.setEnabled(false); -+ if (viewer.ftpOnly) {return;} -+ - remove(disconnectButton); - disconnectButton = new Button("Hide desktop"); - disconnectButton.setEnabled(true); -@@ -99,7 +109,6 @@ - clipboardButton.setEnabled(false); - ctrlAltDelButton.setEnabled(false); - refreshButton.setEnabled(false); -- ftpButton.setEnabled(false); - - validate(); - } -@@ -110,6 +119,7 @@ - // - - public void enableRemoteAccessControls(boolean enable) { -+ if (viewer.ftpOnly) {return;} - ctrlAltDelButton.setEnabled(enable); - } - -@@ -163,9 +173,19 @@ - } - else if (evt.getSource() == ftpButton) - { -- viewer.ftp.setVisible(!viewer.ftp.isVisible()); -+// begin runge/x11vnc -+ if (viewer.ftpOnly) { -+ viewer.vncFrame.setVisible(false); -+ } -+ viewer.ftp.setSavedLocations(); -+ if (viewer.ftp.isVisible()) { -+ viewer.ftp.doClose(); -+ } else { -+ viewer.ftp.doOpen(); -+ } -+// end runge/x11vnc - viewer.rfb.readServerDriveList(); -- -+ - } - } - } -diff -Naur JavaViewer.orig/FTPFrame.java JavaViewer/FTPFrame.java ---- JavaViewer.orig/FTPFrame.java 2005-03-15 23:53:14.000000000 -0500 -+++ JavaViewer/FTPFrame.java 2009-01-13 09:48:30.000000000 -0500 -@@ -24,8 +24,17 @@ - import java.io.*; - import java.util.ArrayList; - import java.util.Vector; -+import java.util.Date; - import javax.swing.*; - -+import java.nio.ByteBuffer; -+import java.nio.CharBuffer; -+import java.nio.charset.*; -+ -+// begin runge/x11vnc -+import java.util.Arrays; -+// end runge/x11vnc -+ - - /* - * Created on Feb 25, 2004 -@@ -74,12 +83,31 @@ - public javax.swing.JTextField connectionStatus = null; - public boolean updateDriveList; - private Vector remoteList = null; -+ private Vector remoteListInfo = null; - private Vector localList = null; -+ private Vector localListInfo = null; - private File currentLocalDirectory = null; // Holds the current local Directory - private File currentRemoteDirectory = null; // Holds the current remote Directory - private File localSelection = null; // Holds the currently selected local file - private String remoteSelection = null; // Holds the currently selected remote file - public String selectedTable = null; -+ -+// begin runge/x11vnc -+ private javax.swing.JButton viewButton = null; -+ private javax.swing.JButton refreshButton = null; -+ public File saveLocalDirectory = null; -+ public long saveLocalDirectoryTime = 0; -+ public int saveLocalDirectoryCount = 0; -+ public String saveRemoteDirectory = null; -+ public long saveRemoteDirectoryTime = 0; -+ public int saveRemoteDirectoryCount = 0; -+ private boolean localCurrentIsDir = true; -+ private int lastRemoteIndex = -1; -+ private int lastLocalIndex = -1; -+ private boolean doingShortcutDir = false; -+ private boolean gotShortcutDir = false; -+ private boolean ignore_events = false; -+// end runge/x11vnc - - // sf@2004 - Separate directories and files for better lisibility - private ArrayList DirsList; -@@ -125,11 +153,61 @@ - - void refreshRemoteLocation() - { -+ -+//System.out.println("refreshRemoteLocation1"); - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); -+System.out.println("refreshRemoteLocation '" + remoteLocation.getText() + "'"); // runge/x11vnc - viewer.rfb.readServerDirectory(remoteLocation.getText()); - } - -+// begin runge/x11vnc -+ public void setSavedLocations() { -+ saveLocalDirectory = currentLocalDirectory; -+ saveLocalDirectoryTime = System.currentTimeMillis(); -+ saveLocalDirectoryCount = 0; -+ -+ if (remoteLocation != null) { -+ saveRemoteDirectory = remoteLocation.getText(); -+System.out.println("RemoteSave '" + saveRemoteDirectory + "'"); -+ } -+ saveRemoteDirectoryTime = System.currentTimeMillis(); -+ saveRemoteDirectoryCount = 0; -+ } -+ -+ private File saveLocalHack(File dir) { -+ saveLocalDirectoryCount++; -+//System.out.println("L " + saveLocalDirectoryCount + " dt: " + (System.currentTimeMillis() - saveLocalDirectoryTime) + " - " + saveLocalDirectory); -+ if (System.currentTimeMillis() > saveLocalDirectoryTime + 2000 || saveLocalDirectoryCount > 2) { -+ saveLocalDirectory = null; -+ } -+ if (saveLocalDirectory != null) { -+ currentLocalDirectory = saveLocalDirectory; -+ localLocation.setText(saveLocalDirectory.toString()); -+ return saveLocalDirectory; -+ } else { -+ return dir; -+ } -+ } -+ -+ private String saveRemoteHack(String indrive) { -+ saveRemoteDirectoryCount++; -+//System.out.println("R " + saveRemoteDirectoryCount + " - " + saveRemoteDirectory); -+ if (saveRemoteDirectory != null && saveRemoteDirectoryCount > 1) { -+ saveRemoteDirectory = null; -+ } -+ if (saveRemoteDirectory != null) { -+ if (! saveRemoteDirectory.equals("")) { -+System.out.println("saveRemoteHack setText + refreshRemoteLocation '" + saveRemoteDirectory + "'"); -+ return saveRemoteDirectory; -+ } -+ } -+ return indrive; -+ } -+// end runge/x11vnc -+ -+ - /* - * Prints the list of drives on the remote directory and returns a String[]. - * str takes as string like A:fC:lD:lE:lF:lG:cH:c -@@ -143,6 +221,9 @@ - int size = str.length(); - String driveType = null; - String[] drive = new String[str.length() / 3]; -+ int idx = 0, C_drive = -1, O_drive = -1; -+ -+System.out.println("ComboBox: Str '" + str + "'"); - - // Loop through the string to create a String[] - for (int i = 0; i < size; i = i + 3) { -@@ -150,26 +231,68 @@ - driveType = str.substring(i + 2, i + 3); - if (driveType.compareTo("f") == 0) - drive[i / 3] += "\\ Floppy"; -- if (driveType.compareTo("l") == 0) -+ if (driveType.compareTo("l") == 0) { - drive[i / 3] += "\\ Local Disk"; -+ if (drive[i/3].substring(0,1).toUpperCase().equals("C")) { -+ C_drive = idx; -+ } else if (O_drive < 0) { -+ O_drive = idx; -+ } -+ } - if (driveType.compareTo("c") == 0) - drive[i / 3] += "\\ CD-ROM"; - if (driveType.compareTo("n") == 0) - drive[i / 3] += "\\ Network"; - - remoteDrivesComboBox.addItem(drive[i / 3]); -+System.out.println("ComboBox: Add " + idx + " '" + drive[i/3] + "'"); -+ idx++; -+ } -+ -+ // runge -+ if (viewer.ftpDropDown != null) { -+ String[] dd = viewer.ftpDropDown.split("\\."); -+ for (int i=0; i < dd.length; i++) { -+ if (!dd[i].equals("")) { -+ String s = dd[i]; -+ if (s.startsWith("TOP_")) { -+ s = s.substring(4); -+ remoteDrivesComboBox.insertItemAt(" [" + s + "]", 0); -+ } else { -+ remoteDrivesComboBox.addItem(" [" + s + "]"); -+ } -+ } -+ } -+ } else { -+ remoteDrivesComboBox.addItem(" [My Documents]"); -+ remoteDrivesComboBox.addItem(" [Desktop]"); -+ remoteDrivesComboBox.addItem(" [Home]"); - } -+ - //sf@ - Select Drive C:as default if possible - boolean bFound = false; -- for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) -- { -- if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) -- { -- remoteDrivesComboBox.setSelectedIndex(i); -+ -+ if (false) { -+ for(int i = 0; i < remoteDrivesComboBox.getItemCount() ; i++) { -+ if(remoteDrivesComboBox.getItemAt(i).toString().substring(0,1).toUpperCase().equals("C")) { -+ remoteDrivesComboBox.setSelectedIndex(i); -+ bFound = true; -+ } -+ } -+ } else { -+ if (C_drive >= 0) { -+ remoteDrivesComboBox.setSelectedIndex(C_drive); -+ bFound = true; -+System.out.println("ComboBox: C_drive index: " + C_drive); -+ } else if (O_drive >= 0) { -+ remoteDrivesComboBox.setSelectedIndex(O_drive); - bFound = true; -+System.out.println("ComboBox: Other_drive index: " + O_drive); - } - } -+ - if (!bFound) remoteDrivesComboBox.setSelectedIndex(0); -+ - updateDriveList = false; - return drive; - } -@@ -185,6 +308,8 @@ - stopButton.setVisible(true); - stopButton.setEnabled(true); - receiveButton.setEnabled(false); -+ viewButton.setEnabled(false); // runge/x11vnc -+ refreshButton.setEnabled(false); - remoteTopButton.setEnabled(false); - sendButton.setEnabled(false); - remoteFileTable.setEnabled(false); -@@ -207,6 +332,8 @@ - stopButton.setVisible(false); - stopButton.setEnabled(false); - receiveButton.setEnabled(true); -+ viewButton.setEnabled(true); // runge/x11vnc -+ refreshButton.setEnabled(true); - remoteTopButton.setEnabled(true); - sendButton.setEnabled(true); - remoteFileTable.setEnabled(true); -@@ -221,10 +348,11 @@ - /* - * Print Directory prints out all the contents of a directory - */ -- void printDirectory(ArrayList a) { -+ void printDirectory(ArrayList a, ArrayList b) { - - for (int i = 0; i < a.size(); i++) { - remoteList.addElement(a.get(i)); -+ remoteListInfo.addElement(b.get(i)); - } - remoteFileTable.setListData(remoteList); - } -@@ -235,10 +363,12 @@ - * @return void - */ - private void initialize() { -+ ignore_events = true; - this.setSize(794, 500); - this.setContentPane(getJContentPane()); -+ ignore_events = false; - updateDriveList = true; -- } -+ } - /** - * This method initializes jContentPane. This is the main content pane - * -@@ -253,6 +383,33 @@ - jContentPane.add(getRemotePanel(), java.awt.BorderLayout.EAST); - jContentPane.add(getLocalPanel(), java.awt.BorderLayout.WEST); - jContentPane.add(getButtonPanel(), java.awt.BorderLayout.CENTER); -+ -+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); -+ AbstractAction escapeAction = new AbstractAction() { -+ public void actionPerformed(ActionEvent actionEvent) { -+ System.out.println("Escape Pressed"); -+ if (viewer.ftpOnly) { -+ System.out.println("exiting..."); -+ System.exit(0); -+ } else { -+ doClose(); -+ } -+ } -+ }; -+ jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); -+ jContentPane.getInputMap().put(stroke, "escapeAction"); -+ jContentPane.getActionMap().put("escapeAction", escapeAction); -+ -+ stroke = KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_MASK); -+ AbstractAction resetAction = new AbstractAction() { -+ public void actionPerformed(ActionEvent actionEvent) { -+ System.out.println("Ctrl-R Pressed"); -+ doReset(); -+ } -+ }; -+ jContentPane.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "resetAction"); -+ jContentPane.getInputMap().put(stroke, "resetAction"); -+ jContentPane.getActionMap().put("resetAction", resetAction); - } - return jContentPane; - } -@@ -270,6 +427,7 @@ - topPanelLocal.add(getLocalMachineLabel(), java.awt.BorderLayout.CENTER); - topPanelLocal.add(getLocalTopButton(), java.awt.BorderLayout.EAST); - topPanelLocal.setBackground(java.awt.Color.lightGray); -+//System.out.println("getTopPanelLocal"); - } - return topPanelLocal; - } -@@ -288,6 +446,7 @@ - topPanelRemote.add(getRemoteMachineLabel(), java.awt.BorderLayout.CENTER); - topPanelRemote.add(getRemoteTopButton(), java.awt.BorderLayout.EAST); - topPanelRemote.setBackground(java.awt.Color.lightGray); -+//System.out.println("getTopPanelRemote"); - } - return topPanelRemote; - } -@@ -301,6 +460,7 @@ - if (topPanelCenter == null) { - topPanelCenter = new javax.swing.JPanel(); - topPanelCenter.add(getDummyButton(), null); -+//System.out.println("getTopPanelCenter"); - } - return topPanelCenter; - } -@@ -328,6 +488,7 @@ - topPanel.add(getRemoteTopButton(), null); - topPanel.setBackground(java.awt.Color.lightGray); - */ -+//System.out.println("getTopPanel"); - } - return topPanel; - } -@@ -348,6 +509,7 @@ - statusPanel.add(getJProgressBar(), null); - statusPanel.add(getConnectionStatus(), null); - statusPanel.setBackground(java.awt.Color.lightGray); -+//System.out.println("getStatusPanel"); - - } - return statusPanel; -@@ -368,6 +530,7 @@ - remotePanel.add(getRemoteScrollPane(), null); - remotePanel.add(getRemoteStatus(), null); - remotePanel.setBackground(java.awt.Color.lightGray); -+//System.out.println("getRemotePanel"); - } - return remotePanel; - } -@@ -390,6 +553,7 @@ - localPanel.setComponentOrientation( - java.awt.ComponentOrientation.UNKNOWN); - localPanel.setName("localPanel"); -+//System.out.println("getLocalPanel"); - } - return localPanel; - } -@@ -405,12 +569,15 @@ - buttonPanel = new javax.swing.JPanel(); - buttonPanel.setLayout(null); - buttonPanel.add(getReceiveButton(), null); -+ buttonPanel.add(getRefreshButton(), null); // runge/x11vnc -+ buttonPanel.add(getViewButton(), null); // runge/x11vnc - buttonPanel.add(getNewFolderButton(), null); - buttonPanel.add(getCloseButton(), null); - buttonPanel.add(getDeleteButton(), null); - buttonPanel.add(getSendButton(), null); - buttonPanel.add(getStopButton(), null); - buttonPanel.setBackground(java.awt.Color.lightGray); -+//System.out.println("getButtonPanel"); - } - return buttonPanel; - } -@@ -422,10 +589,11 @@ - private javax.swing.JButton getSendButton() { - if (sendButton == null) { - sendButton = new javax.swing.JButton(); -- sendButton.setBounds(20, 30, 97, 25); -+ sendButton.setBounds(15, 30, 107, 25); // runge/x11vnc - sendButton.setText("Send >>"); - sendButton.setName("sendButton"); - sendButton.addActionListener(this); -+//System.out.println("getSendButton"); - - } - return sendButton; -@@ -438,7 +606,7 @@ - private javax.swing.JButton getReceiveButton() { - if (receiveButton == null) { - receiveButton = new javax.swing.JButton(); -- receiveButton.setBounds(20, 60, 97, 25); -+ receiveButton.setBounds(15, 60, 107, 25); // runge/x11vnc - receiveButton.setText("<< Receive"); - receiveButton.setName("receiveButton"); - receiveButton.addActionListener(this); -@@ -453,7 +621,7 @@ - private javax.swing.JButton getDeleteButton() { - if (deleteButton == null) { - deleteButton = new javax.swing.JButton(); -- deleteButton.setBounds(20, 110, 97, 25); -+ deleteButton.setBounds(15, 110, 107, 25); // runge/x11vnc - deleteButton.setText("Delete File"); - deleteButton.setName("deleteButton"); - deleteButton.addActionListener(this); -@@ -468,7 +636,7 @@ - private javax.swing.JButton getNewFolderButton() { - if (newFolderButton == null) { - newFolderButton = new javax.swing.JButton(); -- newFolderButton.setBounds(20, 140, 97, 25); -+ newFolderButton.setBounds(15, 140, 107, 25); // runge/x11vnc - newFolderButton.setText("New Folder"); - newFolderButton.setName("newFolderButton"); - newFolderButton.addActionListener(this); -@@ -476,6 +644,39 @@ - return newFolderButton; - } - -+// begin runge/x11vnc -+ /** -+ * This method initializes refreshButton -+ * -+ * @return javax.swing.JButton -+ */ -+ private javax.swing.JButton getRefreshButton() { -+ if (refreshButton == null) { -+ refreshButton = new javax.swing.JButton(); -+ refreshButton.setBounds(15, 170, 107, 25); -+ refreshButton.setText("Refresh"); -+ refreshButton.setName("refreshButton"); -+ refreshButton.addActionListener(this); -+ } -+ return refreshButton; -+ } -+ /** -+ * This method initializes viewButton -+ * -+ * @return javax.swing.JButton -+ */ -+ private javax.swing.JButton getViewButton() { -+ if (viewButton == null) { -+ viewButton = new javax.swing.JButton(); -+ viewButton.setBounds(15, 200, 107, 25); -+ viewButton.setText("View File"); -+ viewButton.setName("viewButton"); -+ viewButton.addActionListener(this); -+ } -+ return viewButton; -+ } -+// end runge/x11vnc -+ - /** - * This method initializes stopButton - * -@@ -486,7 +687,7 @@ - if (stopButton == null) - { - stopButton = new javax.swing.JButton(); -- stopButton.setBounds(20, 200, 97, 25); -+ stopButton.setBounds(15, 230, 107, 25); // runge/x11vnc - stopButton.setText("Stop"); - stopButton.setName("stopButton"); - stopButton.addActionListener(this); -@@ -503,8 +704,12 @@ - private javax.swing.JButton getCloseButton() { - if (closeButton == null) { - closeButton = new javax.swing.JButton(); -- closeButton.setBounds(20, 325, 97, 25); -- closeButton.setText("Close"); -+ closeButton.setBounds(15, 325, 107, 25); // runge/x11vnc -+ if (viewer.ftpOnly) { -+ closeButton.setText("Quit"); -+ } else { -+ closeButton.setText("Close"); -+ } - closeButton.setName("closeButton"); - closeButton.addActionListener(this); - } -@@ -551,6 +756,7 @@ - //Select the second entry (e.g. C:\) - // localDrivesComboBox.setSelectedIndex(1); - localDrivesComboBox.addActionListener(this); -+//System.out.println("getLocalDrivesComboBox"); - } - updateDriveList = false; - return localDrivesComboBox; -@@ -567,6 +773,7 @@ - remoteDrivesComboBox.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - remoteDrivesComboBox.addActionListener(this); -+//System.out.println("getRemoteDrivesComboBox"); - - } - return remoteDrivesComboBox; -@@ -587,6 +794,7 @@ - localMachineLabel.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 11)); - localMachineLabel.setEditable(false); -+//System.out.println("getLocalMachineLabel"); - } - return localMachineLabel; - } -@@ -622,6 +830,7 @@ - localTopButton.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); - localTopButton.addActionListener(this); -+//System.out.println("getLocalTopButton"); - } - return localTopButton; - } -@@ -638,6 +847,7 @@ - remoteTopButton.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); - remoteTopButton.addActionListener(this); -+//System.out.println("getRemoteTopButton"); - } - return remoteTopButton; - } -@@ -650,9 +860,24 @@ - private javax.swing.JList getLocalFileTable() { - if (localFileTable == null) { - localList = new Vector(0); -+ localListInfo = new Vector(0); - localFileTable = new JList(localList); -+ MouseMotionListener mlisten = new MouseMotionAdapter() { -+ public void mouseMoved(MouseEvent e) { -+ int index = localFileTable.locationToIndex(e.getPoint()); -+ if (index == lastLocalIndex) { -+ return; -+ } else if (index < 0) { -+ return; -+ } -+ lastLocalIndex = index; -+ connectionStatus.setText((String) localListInfo.get(index)); -+ } -+ }; - localFileTable.addMouseListener(this); -+ localFileTable.addMouseMotionListener(mlisten); - localFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); -+//System.out.println("getLocalFileTable"); - } - return localFileTable; - } -@@ -669,6 +894,7 @@ - localScrollPane.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - localScrollPane.setName("localFileList"); -+//System.out.println("getLocalScrollPane"); - } - return localScrollPane; - } -@@ -680,10 +906,25 @@ - private javax.swing.JList getRemoteFileTable() { - if (remoteFileTable == null) { - remoteList = new Vector(0); -+ remoteListInfo = new Vector(0); - remoteFileTable = new JList(remoteList); -+ MouseMotionListener mlisten = new MouseMotionAdapter() { -+ public void mouseMoved(MouseEvent e) { -+ int index = remoteFileTable.locationToIndex(e.getPoint()); -+ if (index == lastRemoteIndex) { -+ return; -+ } else if (index < 0) { -+ return; -+ } -+ lastRemoteIndex = index; -+ connectionStatus.setText((String) remoteListInfo.get(index)); -+ } -+ }; - remoteFileTable.addMouseListener(this); -+ remoteFileTable.addMouseMotionListener(mlisten); - remoteFileTable.setSelectedValue("C:\\", false); - remoteFileTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); -+//System.out.println("getRemoteFileTable"); - - } - return remoteFileTable; -@@ -698,6 +939,7 @@ - remoteScrollPane = new javax.swing.JScrollPane(); - remoteScrollPane.setViewportView(getRemoteFileTable()); - remoteScrollPane.setPreferredSize(new java.awt.Dimension(325, 418)); -+//System.out.println("getRemoteScrollPane"); - } - return remoteScrollPane; - } -@@ -716,6 +958,7 @@ - remoteLocation.setBackground(new Color(255,255,238)); - remoteLocation.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); -+//System.out.println("getRemoteLocation"); - } - return remoteLocation; - } -@@ -732,6 +975,7 @@ - localLocation.setBackground( new Color(255,255,238)); - localLocation.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); -+//System.out.println("getLocalLocation"); - } - return localLocation; - } -@@ -748,6 +992,7 @@ - localStatus.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - localStatus.setEditable(false); -+//System.out.println("getLocalStatus"); - } - return localStatus; - } -@@ -764,6 +1009,7 @@ - remoteStatus.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); - remoteStatus.setEditable(false); -+//System.out.println("getRemoteStatus"); - } - return remoteStatus; - } -@@ -777,9 +1023,10 @@ - historyComboBox = new javax.swing.JComboBox(); - historyComboBox.setFont( - new java.awt.Font("Dialog", java.awt.Font.BOLD, 10)); -- historyComboBox.insertItemAt(new String("Pulldown to view history ..."),0); -+ historyComboBox.insertItemAt(new String("Pulldown to view history; Press Escape to Close/Quit; Press Ctrl-R to Reset Panel."),0); - historyComboBox.setSelectedIndex(0); - historyComboBox.addActionListener(this); -+//System.out.println("getHistoryComboBox"); - } - return historyComboBox; - } -@@ -791,6 +1038,7 @@ - private javax.swing.JProgressBar getJProgressBar() { - if (jProgressBar == null) { - jProgressBar = new javax.swing.JProgressBar(); -+//System.out.println("getJProgressBar"); - } - return jProgressBar; - } -@@ -806,6 +1054,7 @@ - connectionStatus.setBackground(java.awt.Color.lightGray); - connectionStatus.setFont( - new java.awt.Font("Dialog", java.awt.Font.PLAIN, 10)); -+//System.out.println("getConnectionStatus"); - } - connectionStatus.setEditable(false); - return connectionStatus; -@@ -815,7 +1064,12 @@ - * Implements Action listener. - */ - public void actionPerformed(ActionEvent evt) { -- System.out.println(evt.getSource()); -+// System.out.println(evt.getSource()); -+ -+ if (ignore_events) { -+ System.out.println("ignore_events: " + evt.getSource()); -+ return; -+ } - - if (evt.getSource() == closeButton) - { // Close Button -@@ -829,15 +1083,27 @@ - { - doReceive(); - } -+// begin runge/x11vnc -+ else if (evt.getSource() == viewButton) -+ { -+ doView(); -+ } -+// end runge/x11vnc - else if (evt.getSource() == localDrivesComboBox) - { - changeLocalDrive(); - } - else if (evt.getSource() == remoteDrivesComboBox) - { -+//System.out.println("remoteDrivesComboBox"); // runge/x11vnc - changeRemoteDrive(); -- remoteList.clear(); -- remoteFileTable.setListData(remoteList); -+ -+ // are these really needed? changeRemoteDrive() does them at the end. -+ if (false) { -+ remoteList.clear(); -+ remoteListInfo.clear(); -+ remoteFileTable.setListData(remoteList); -+ } - } - else if (evt.getSource() == localTopButton) - { -@@ -845,12 +1111,17 @@ - } - else if (evt.getSource() == remoteTopButton) - { -+//System.out.println("remoteTopButton"); // runge/x11vnc - changeRemoteDrive(); - } - else if(evt.getSource() == deleteButton) - { - doDelete(); - } -+ else if(evt.getSource() == refreshButton) -+ { -+ doRefresh(); -+ } - else if(evt.getSource()==newFolderButton) - { - doNewFolder(); -@@ -864,7 +1135,7 @@ - - private void doNewFolder() - { -- String name = JOptionPane.showInputDialog(null,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); -+ String name = JOptionPane.showInputDialog(jContentPane,"Enter new directory name", "Create New Directory", JOptionPane.QUESTION_MESSAGE); - if(selectedTable.equals("remote")) - { - name = remoteLocation.getText()+name; -@@ -880,34 +1151,106 @@ - historyComboBox.setSelectedIndex(0); - } - } -- private void doClose() -+ public void doClose() - { -+ if (viewer.ftpOnly) { -+ viewer.disconnect(); -+ return; -+ } - try { - this.setVisible(false); -- viewer.rfb.writeFramebufferUpdateRequest( -- 0, -- 0, -- viewer.rfb.framebufferWidth, -- viewer.rfb.framebufferHeight, -- true); -+ viewer.rfb.writeFramebufferUpdateRequest(0, 0, viewer.rfb.framebufferWidth, -+ viewer.rfb.framebufferHeight, true); -+ -+ if (false) { -+ this.dispose(); -+ jContentPane = null; -+ } - } catch (IOException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } -+ private void unSwing() { -+ jContentPane = null; -+ topPanel = null; -+ topPanelLocal = null; -+ topPanelRemote = null; -+ topPanelCenter = null; -+ statusPanel = null; -+ remotePanel = null; -+ localPanel = null; -+ buttonPanel = null; -+ sendButton = null; -+ receiveButton = null; -+ deleteButton = null; -+ newFolderButton = null; -+ stopButton = null; -+ closeButton = null; -+ dummyButton = null; -+ localDrivesComboBox = null; -+ remoteDrivesComboBox = null; -+ localMachineLabel = null; -+ remoteMachineLabel = null; -+ localTopButton = null; -+ remoteTopButton = null; -+ localScrollPane = null; -+ localFileTable = null; -+ remoteScrollPane = null; -+ remoteFileTable = null; -+ remoteLocation = null; -+ localLocation = null; -+ localStatus = null; -+ remoteStatus = null; -+ historyComboBox = null; -+ jProgressBar = null; -+ connectionStatus = null; -+ viewButton = null; -+ refreshButton = null; -+ } -+ -+ public void doReset() -+ { -+ try { -+ this.setVisible(false); -+ this.dispose(); -+ jContentPane = null; -+ try {Thread.sleep(500);} catch (InterruptedException e) {} -+ viewer.ftp_init(); -+ } catch (Exception e) { -+ // TODO Auto-generated catch block -+ e.printStackTrace(); -+ } -+ } - -+ public void doOpen() -+ { -+ try { -+ this.setVisible(true); -+ if (false) { -+ this.initialize(); -+ } -+ } catch (Exception e) { -+ // TODO Auto-generated catch block -+ e.printStackTrace(); -+ } -+ } - private void doDelete() - { -- System.out.println("Delete Button Pressed"); -+// System.out.println("Delete Button Pressed"); - //Call this method to delete a file at server - if(selectedTable.equals("remote")) - { -- String sFileName = ((String) this.remoteFileTable.getSelectedValue()); -+ Object selected = this.remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be deleted - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - -@@ -916,7 +1259,7 @@ - // sf@2004 - Delete prompt - if (remoteList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Remote Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -926,18 +1269,22 @@ - } - else - { -- String sFileName = ((String) this.localFileTable.getSelectedValue()); -+ Object selected = this.localFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be deleted - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Deletion is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - // sf@2004 - Delete prompt - if (localList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "Are you sure you want to delete the file \n< " + sFileName + " >\n on Local Machine ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -952,21 +1299,25 @@ - - private void doReceive() - { -- System.out.println("Received Button Pressed"); -+// System.out.println("Received Button Pressed"); - -- String sFileName = ((String) this.remoteFileTable.getSelectedValue()); -+ Object selected = this.remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be transfered - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - - // sf@2004 - Overwrite prompt - if (localList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Local Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -979,23 +1330,101 @@ - viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); - } - -+// begin runge/x11vnc -+ private void doRefresh() -+ { -+ System.out.println("Refreshing Local and Remote."); -+ refreshLocalLocation(); -+ refreshRemoteLocation(); -+ } -+ -+ private void doView() -+ { -+// System.out.println("View Button Pressed"); -+ -+ if (selectedTable == null) { -+ return; -+ } -+ if (selectedTable.equals("remote")) { -+ viewRemote(); -+ } else if (selectedTable.equals("local")) { -+ viewLocal(); -+ } -+ } -+ -+ private File doReceiveTmp() -+ { -+ -+ if (remoteFileTable == null) { -+ return null; -+ } -+ Object selected = this.remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return null; -+ } -+ String sFileName = ((String) selected); -+ -+ if (sFileName == null) { -+ return null; -+ } -+ -+ // sf@2004 - Directory can't be transfered -+ if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) -+ { -+ return null; -+ } -+ -+ File tmp = null; -+ try { -+ tmp = File.createTempFile("ULTRAFTP", ".txt"); -+ } catch (Exception e) { -+ return null; -+ } -+ -+ //updateHistory("Downloaded " + localSelection.toString()); -+ String remoteFileName = this.remoteLocation.getText(); -+ remoteFileName+= ((String) this.remoteFileTable.getSelectedValue()).substring(1); -+ System.out.println("remoteFileName: " + remoteFileName); -+if (false) { -+ char[] b = remoteFileName.toCharArray(); -+ for (int n = 0; n < b.length; n++) { -+ System.out.print(Integer.toHexString(b[n]) + " "); -+ } -+ System.out.println(""); -+ for (int n = 0; n < b.length; n++) { -+ System.out.print(b[n]); -+ } -+ System.out.println(""); -+} -+ -+ String localDestinationPath = tmp.getAbsolutePath(); -+ viewer.rfb.requestRemoteFile(remoteFileName,localDestinationPath); -+ System.out.println("ReceiveTmp: " + localDestinationPath); -+ return tmp; -+ } -+// end runge/x11vnc -+ - private void doSend() - { -- System.out.println("Send Button Pressed"); -+// System.out.println("Send Button Pressed"); - -- String sFileName = ((String) this.localFileTable.getSelectedValue()); -+ Object selected = this.localFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sFileName = ((String) selected); - - // sf@2004 - Directory can't be transfered - if (sFileName.substring(0, 2).equals(" [") && sFileName.substring((sFileName.length() - 1), sFileName.length()).equals("]")) - { -- JOptionPane.showMessageDialog(null, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); -+ JOptionPane.showMessageDialog(jContentPane, (String)"Directory Transfer is not yet available in this version...", "FileTransfer Info", JOptionPane.INFORMATION_MESSAGE); - return; - } - - // sf@2004 - Overwrite prompt - if (remoteList.contains(sFileName)) - { -- int r = JOptionPane.showConfirmDialog(null, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); -+ int r = JOptionPane.showConfirmDialog(jContentPane, "The file < " + sFileName + " >\n already exists on Remote Machine\n Are you sure you want to overwrite it ?", "File Transfer Warning", JOptionPane.YES_NO_OPTION); - if (r == JOptionPane.NO_OPTION) - return; - } -@@ -1013,6 +1442,7 @@ - // - private void doStop() - { -+ System.out.println("** Current Transfer Aborted **"); - viewer.rfb.fAbort = true; - } - /** -@@ -1024,6 +1454,14 @@ - System.out.println("History: " + message); - historyComboBox.insertItemAt(new String(message), 0); - } -+ -+ public void receivedRemoteDirectoryName(String str) { -+ if (doingShortcutDir) { -+ if (str.length() > 1) { -+ remoteLocation.setText(str); -+ } -+ } -+ } - - /** - * This method updates the file table to the current selection of the remoteComboBox -@@ -1034,11 +1472,44 @@ - remoteSelection = null; - - if (!updateDriveList) { -- String drive = remoteDrivesComboBox.getSelectedItem().toString().substring(0,1)+ ":\\"; -- viewer.rfb.readServerDirectory(drive); -- remoteLocation.setText(drive); -+//System.out.println("changeRemoteDrive-A " + drive); // begin runge/x11vnc -+ Object selected = remoteDrivesComboBox.getSelectedItem(); -+ if (selected != null) { -+ String instr = selected.toString(); -+ if (instr != null) { -+System.out.println("changeRemoteDrive: instr='" + instr + "'"); -+ String drive = instr.substring(0,1)+ ":\\"; -+ if (instr.startsWith(" [")) { -+ int idx = instr.lastIndexOf(']'); -+ if (idx > 2) { -+ drive = instr.substring(2, idx); -+ } else { -+ drive = instr.substring(2); -+ } -+ if (drive.equals("Home")) { -+ drive = ""; -+ } -+ drive += "\\"; -+ doingShortcutDir = true; -+ } else { -+ doingShortcutDir = false; -+ drive = saveRemoteHack(drive); -+ } -+ gotShortcutDir = false; -+ viewer.rfb.readServerDirectory(drive); -+ if (!gotShortcutDir) { -+ remoteLocation.setText(drive); -+ } -+ } else { -+System.out.println("changeRemoteDrive: instr null"); -+ } -+ } else { -+System.out.println("changeRemoteDrive: selection null"); -+ } -+//System.out.println("changeRemoteDrive-B " + drive); // end runge/x11vnc - } - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); - } - /** -@@ -1048,6 +1519,7 @@ - private void changeLocalDrive() - { - File currentDrive = new File(localDrivesComboBox.getSelectedItem().toString()); -+System.out.println("changeLocalDrive " + currentDrive.toString()); // runge/x11vnc - if(currentDrive.canRead()) - { - localSelection = null; -@@ -1057,9 +1529,11 @@ - else - { - localList.clear(); -+ localListInfo.clear(); - localStatus.setText("WARNING: Drive " + localDrivesComboBox.getSelectedItem().toString()); - connectionStatus.setText(" > WARNING - Local Drive unavailable (possibly restricted access or media not present)"); - } -+ - } - /** - * Determines which FileTable was double-clicked and updates the table -@@ -1098,10 +1572,18 @@ - selectedTable = "remote"; - localFileTable.setBackground(new Color(238, 238, 238)); - remoteFileTable.setBackground(new Color(255, 255, 255)); -- String name = (remoteFileTable.getSelectedValue().toString()).substring(1); -+ Object selected = remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String selstr = selected.toString(); -+ if (selstr == null) { -+ return; -+ } -+ String name = selstr.substring(1); - if( !name.substring(0, 2).equals(" [")) - remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); -- -+ - } - - /* -@@ -1115,10 +1597,38 @@ - localFileTable.setBackground(new Color(255, 255, 255)); - File currentSelection = new File(currentLocalDirectory, getTrimmedSelection()); - -- if(currentSelection.isFile()) -+// begin runge/x11vnc -+ // localSelection = currentSelection.getAbsoluteFile(); -+ if(currentSelection.isFile()) { - localSelection = currentSelection.getAbsoluteFile(); -+ localCurrentIsDir = false; -+ } else { -+ localCurrentIsDir = true; -+ } -+// end runge/x11vnc - - } -+ -+// begin runge/x11vnc -+ private void viewRemote() { -+ File tmp = doReceiveTmp(); -+ if (tmp == null) { -+ return; -+ } -+ TextViewer tv = new TextViewer("Remote: " + remoteSelection, tmp, true); -+ } -+ private void viewLocal() { -+ if (localSelection == null) { -+ return; -+ } -+ if (localCurrentIsDir) { -+ return; -+ } -+ File loc = new File(localSelection.toString()); -+ TextViewer tv = new TextViewer("Local: " + localSelection.toString(), loc, false); -+ } -+// end runge/x11vnc -+ - /** - * Updates the Remote File Table based on selection. Called from mouseClicked handler - */ -@@ -1126,20 +1636,29 @@ - String name = null; - String action = null; - String drive = null; -- name = (remoteFileTable.getSelectedValue().toString()).substring(1); -+ Object selected = remoteFileTable.getSelectedValue(); -+ if (selected == null) { -+ return; -+ } -+ String sname = selected.toString(); -+ if (sname == null) { -+ return; -+ } -+ name = sname.substring(1); - - if (name.equals("[..]")) - { - action = "up"; - remoteSelection = null; - drive = remoteLocation.getText().substring(0, remoteLocation.getText().length() - 1); -- // JOptionPane.showMessageDialog(null, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); -+ // JOptionPane.showMessageDialog(jContentPane, (String)drive, "FileTransfer DEBUG", JOptionPane.INFORMATION_MESSAGE); - int index = drive.lastIndexOf("\\"); - drive = drive.substring(0, index + 1); - - remoteLocation.setText(drive); - viewer.rfb.readServerDirectory(drive); - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); - } - else if (!name.substring(0, 2).equals(" [") && !name.substring((name.length() - 1), name.length()).equals("]")) -@@ -1149,6 +1668,7 @@ - remoteSelection = remoteLocation.getText() + name.substring(0, name.length()); - drive = remoteLocation.getText(); - // ?? -+ viewRemote(); // runge/x11vnc - } - else - { -@@ -1159,10 +1679,12 @@ - remoteLocation.setText(drive); - viewer.rfb.readServerDirectory(drive); - remoteList.clear(); -+ remoteListInfo.clear(); - remoteFileTable.setListData(remoteList); - } - //remoteLocation.setText(drive); - } -+ - /** - * Updates the Local File Table based on selection. Called from MouseClicked handler - */ -@@ -1188,6 +1710,7 @@ - else if (currentSelection.isFile()) - { - localSelection = currentSelection.getAbsoluteFile(); -+ viewLocal(); // runge/x11vnc - } - else if (currentSelection.isDirectory()) - { -@@ -1201,13 +1724,22 @@ - * - */ - private String getTrimmedSelection(){ -- String currentSelection = (localFileTable.getSelectedValue().toString()).substring(1); -- if(currentSelection.substring(0,1).equals("[") && -- currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ -- return currentSelection.substring(1,currentSelection.length()-1); -- } else { -- return currentSelection; -- } -+ String currentSelection = ""; -+ Object selected = localFileTable.getSelectedValue(); -+ if (selected == null) { -+ return currentSelection; -+ } -+ String selstr = selected.toString(); -+ if (selstr == null) { -+ return currentSelection; -+ } -+ currentSelection = selstr.substring(1); -+ if(currentSelection.substring(0,1).equals("[") && -+ currentSelection.substring(currentSelection.length()-1,currentSelection.length()).equals("]")){ -+ return currentSelection.substring(1,currentSelection.length()-1); -+ } else { -+ return currentSelection; -+ } - } - - /* -@@ -1241,36 +1773,148 @@ - return null; - } - -+ String timeStr(long t) { -+ Date date = new Date(t); -+ return date.toString(); -+ } -+ String dotPast(double f, int n) { -+ String fs = "" + f; -+ int i = fs.lastIndexOf(".") + n; -+ if (i >= 0) { -+ int len = fs.length(); -+ if (i >= len) { -+ i = len-1; -+ } -+ fs = fs.substring(0, i); -+ } -+ return fs; -+ } -+ String sizeStr(int s) { -+ if (s < 0) { -+ return s + "? B"; -+ } else if (s < 1024) { -+ return s + " B"; -+ } else if (s < 1024 * 1024) { -+ double k = s / 1024.0; -+ String ks = dotPast(k, 3); -+ -+ return s + " (" + ks + " KB)"; -+ } else { -+ double m = s / (1024.0*1024.0); -+ String ms = dotPast(m, 3); -+ return s + " (" + ms + " MB)"; -+ } -+ } -+ -+ int max_char(String text) { -+ int maxc = 0; -+ char chars[] = text.toCharArray(); -+ for (int n = 0; n < chars.length; n++) { -+ if ((int) chars[n] > maxc) { -+ maxc = (int) chars[n]; -+ } -+ } -+ return maxc; -+ } - - /* - * Navigates the local file structure up or down one directory - */ - public void changeLocalDirectory(File dir) - { -- currentLocalDirectory = dir; // Updates Global -+ dir = saveLocalHack(dir); // runge/x11vnc -+ -+ if (dir == null) { -+ connectionStatus.setText("Error changing local directory."); -+ historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); -+ historyComboBox.setSelectedIndex(0); -+ return; -+ } -+ - File allFiles[] = dir.listFiles(); // Reads files - String[] contents = dir.list(); - -+ if (contents == null || allFiles == null) { -+ connectionStatus.setText("Error changing local directory."); -+ historyComboBox.insertItemAt(new String("> Error changing local directory."), 0); -+ historyComboBox.setSelectedIndex(0); -+ return; -+ } -+ -+ currentLocalDirectory = dir; // Updates Global -+// begin runge/x11vnc -+System.out.println("changeLocalDirectory: " + dir.toString()); -+ if (contents != null) { -+ java.util.Arrays.sort(contents, String.CASE_INSENSITIVE_ORDER); -+ for (int i = 0; i < contents.length; i++) { -+ allFiles[i] = new File(dir, contents[i]); -+ } -+ } else { -+ return; -+ } -+// end runge/x11vnc -+ - localList.clear(); -+ localListInfo.clear(); - localList.addElement(" [..]"); -+ localListInfo.addElement(" [..]"); -+ -+ ArrayList DirInfo = new ArrayList(); -+ ArrayList FilInfo = new ArrayList(); -+ -+ Charset charset = Charset.forName("ISO-8859-1"); -+ CharsetDecoder decoder = charset.newDecoder(); -+ CharsetEncoder encoder = charset.newEncoder(); - - // Populate the Lists - for (int i = 0; i < contents.length; i++) - { -- if (allFiles[i].isDirectory()) -+ String f1 = contents[i]; -+ -+if (false) { -+ -+System.out.println("max_char: " + max_char(f1) + " " + f1); -+ if (max_char(f1) > 255) { -+ try { -+System.out.println("bbuf1"); -+ ByteBuffer bbuf = encoder.encode(CharBuffer.wrap(f1.toCharArray())); -+System.out.println("bbuf2"); -+ CharBuffer cbuf = decoder.decode(bbuf); -+System.out.println("bbuf3"); -+ f1 = cbuf.toString(); -+System.out.println("did bbuf: " + f1); -+ } catch (Exception e) { -+ ; -+ } -+ } -+} -+ -+ String f2 = f1; -+ if (f2.length() < 24) { -+ for (int ik = f2.length(); ik < 24; ik++) { -+ f2 = f2 + " "; -+ } -+ } -+ String s = f2 + " \tLastmod: " + timeStr(allFiles[i].lastModified()) + " \t\tSize: " + sizeStr((int) allFiles[i].length()); -+ if (allFiles[i].isDirectory()) { - // localList.addElement("[" + contents[i] + "]"); -- DirsList.add(" [" + contents[i] + "]"); // sf@2004 -- else -- { -+ DirsList.add(" [" + f1 + "]"); // sf@2004 -+ DirInfo.add(s); -+ } else { - // localList.addElement(contents[i]); -- FilesList.add(" " + contents[i]); // sf@2004 -+ FilesList.add(" " + f1); // sf@2004 -+ FilInfo.add(s); - } - } - // sf@2004 -- for (int i = 0; i < DirsList.size(); i++) -+ for (int i = 0; i < DirsList.size(); i++) { - localList.addElement(DirsList.get(i)); -- for (int i = 0; i < FilesList.size(); i++) -+ localListInfo.addElement(DirInfo.get(i)); -+ } -+ for (int i = 0; i < FilesList.size(); i++) { - localList.addElement(FilesList.get(i)); -+ localListInfo.addElement(FilInfo.get(i)); -+ } - - FilesList.clear(); - DirsList.clear(); -@@ -1296,3 +1940,147 @@ - } - - } // @jve:visual-info decl-index=0 visual-constraint="10,10" -+ -+// begin runge/x11vnc -+class TextViewer extends JFrame implements ActionListener { -+ -+ JTextArea textArea = new JTextArea(35, 80); -+ File file = null; -+ JButton refreshButton; -+ JButton dismissButton; -+ Timer tim = null; -+ int rcnt = 0; -+ int tms = 250; -+ boolean delete_it = false; -+ TextViewer me; -+ -+ public TextViewer(String s, File f, boolean d) { -+ -+ delete_it = d; -+ file = f; -+ me = this; -+ -+ JScrollPane scrollPane = new JScrollPane(textArea, -+ JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, -+ JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); -+ -+ textArea.setEditable(false); -+ textArea.setFont(new Font("Monospaced", Font.PLAIN, 12)); -+ -+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, InputEvent.SHIFT_MASK); -+ AbstractAction escapeAction = new AbstractAction() { -+ public void actionPerformed(ActionEvent actionEvent) { -+ cleanse(); -+ me.dispose(); -+ } -+ }; -+ textArea.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(stroke, "escapeAction"); -+ textArea.getInputMap().put(stroke, "escapeAction"); -+ textArea.getActionMap().put("escapeAction", escapeAction); -+ -+ refreshButton = new JButton(); -+ refreshButton.setText("Reload"); -+ refreshButton.setName("refreshButton"); -+ refreshButton.addActionListener(this); -+ -+ dismissButton = new JButton(); -+ dismissButton.setText("Dismiss"); -+ dismissButton.setName("dismissButton"); -+ dismissButton.addActionListener(this); -+ -+ JPanel buttons = new JPanel(); -+ buttons.setLayout(new BorderLayout()); -+ buttons.add(refreshButton, BorderLayout.WEST); -+ buttons.add(dismissButton, BorderLayout.EAST); -+ -+ JPanel content = new JPanel(); -+ content.setLayout(new BorderLayout()); -+ content.add(scrollPane, BorderLayout.CENTER); -+ content.add(buttons, BorderLayout.SOUTH); -+ -+ ActionListener tsk = new ActionListener() { -+ public void actionPerformed(ActionEvent evt) { -+ // System.out.println("tsk"); -+ refresh(); -+ } -+ }; -+ tim = new Timer(tms, tsk); -+ tim.start(); -+ -+ this.setContentPane(content); -+ this.setTitle("TextViewer - " + s); -+ this.pack(); -+ this.setVisible(true); -+ } -+ -+ private void refresh() { -+ -+ rcnt++; -+ if (rcnt * tms > 3000 && tim != null) { -+ tim.stop(); -+ tim = null; -+ } -+ BufferedReader input = null; -+ StringBuffer contents = new StringBuffer(); -+ try { -+ if (input == null) { -+ input = new BufferedReader(new FileReader(file)); -+ } -+ String line = null; -+ int i = 0; -+ while (( line = input.readLine()) != null) { -+ if (i == 0) { -+ // System.out.println("read"); -+ } -+ i++; -+ contents.append(line); -+ contents.append(System.getProperty("line.separator")); -+ } -+ } catch (Exception e) { -+ ; -+ } finally { -+ try { -+ if (input != null) { -+ input.close(); -+ input = null; -+ } -+ } catch (Exception e) { -+ ; -+ } -+ } -+ -+ textArea.setText(contents.toString()); -+ textArea.setCaretPosition(0); -+ } -+ -+ public void actionPerformed(ActionEvent evt) { -+ -+ if (evt.getSource() == refreshButton) { -+ refresh(); -+ } -+ if (evt.getSource() == dismissButton) { -+ cleanse(); -+ this.dispose(); -+ } -+ } -+ -+ private void cleanse() { -+ if (delete_it && file != null) { -+ try { -+ file.delete(); -+ file = null; -+ } catch (Exception e) { -+ ; -+ } -+ } -+ } -+ -+ protected void finalize() throws Throwable { -+ try { -+ cleanse(); -+ } finally { -+ super.finalize(); -+ } -+ } -+} -+// end runge/x11vnc -diff -Naur JavaViewer.orig/Makefile JavaViewer/Makefile ---- JavaViewer.orig/Makefile 2006-05-29 09:06:32.000000000 -0400 -+++ JavaViewer/Makefile 2010-05-18 20:53:32.000000000 -0400 -@@ -4,6 +4,7 @@ - - CP = cp - JC = javac -+JC_ARGS = -target 1.4 -source 1.4 - JAR = jar - ARCHIVE = VncViewer.jar - PAGES = index.vnc shared.vnc noshared.vnc hextile.vnc zlib.vnc tight.vnc -@@ -20,7 +21,7 @@ - all: $(CLASSES) $(ARCHIVE) - - $(CLASSES): $(SOURCES) -- $(JC) -O $(SOURCES) -+ $(JC) $(JC_ARGS) -O $(SOURCES) - - $(ARCHIVE): $(CLASSES) - $(JAR) cf $(ARCHIVE) $(CLASSES) -diff -Naur JavaViewer.orig/OptionsFrame.java JavaViewer/OptionsFrame.java ---- JavaViewer.orig/OptionsFrame.java 2005-11-21 18:50:16.000000000 -0500 -+++ JavaViewer/OptionsFrame.java 2007-05-13 22:18:30.000000000 -0400 -@@ -144,7 +144,10 @@ - choices[jpegQualityIndex].select("6"); - choices[cursorUpdatesIndex].select("Enable"); - choices[useCopyRectIndex].select("Yes"); -- choices[eightBitColorsIndex].select("64"); -+// begin runge/x11vnc -+// choices[eightBitColorsIndex].select("64"); -+ choices[eightBitColorsIndex].select("Full"); -+// end runge/x11vnc - choices[mouseButtonIndex].select("Normal"); - choices[viewOnlyIndex].select("No"); - choices[shareDesktopIndex].select("Yes"); -diff -Naur JavaViewer.orig/RfbProto.java JavaViewer/RfbProto.java ---- JavaViewer.orig/RfbProto.java 2006-05-24 15:14:40.000000000 -0400 -+++ JavaViewer/RfbProto.java 2010-11-30 22:13:58.000000000 -0500 -@@ -31,6 +31,7 @@ - import java.net.Socket; - import java.util.*; - import java.util.zip.*; -+import java.text.DateFormat; - - - class RfbProto { -@@ -86,8 +87,11 @@ - - // sf@2004 - FileTransfer part - ArrayList remoteDirsList; -+ ArrayList remoteDirsListInfo; - ArrayList remoteFilesList; -+ ArrayList remoteFilesListInfo; - ArrayList a; -+ ArrayList b; - boolean fFTInit = true; // sf@2004 - boolean fFTAllowed = true; - boolean fAbort = false; -@@ -199,6 +203,10 @@ - // playback. - int numUpdatesInSession; - -+// begin runge/x11vnc -+ int readServerDriveListCnt = -1; -+ long readServerDriveListTime = 0; -+// end runge/x11vnc - // - // Constructor. Make TCP connection to RFB server. - // -@@ -207,7 +215,27 @@ - viewer = v; - host = h; - port = p; -- sock = new Socket(host, port); -+// begin runge/x11vnc -+// sock = new Socket(host, port); -+ if (! viewer.disableSSL) { -+ System.out.println("new SSLSocketToMe"); -+ SSLSocketToMe ssl; -+ try { -+ ssl = new SSLSocketToMe(host, port, v); -+ } catch (Exception e) { -+ throw new IOException(e.getMessage()); -+ } -+ -+ try { -+ sock = ssl.connectSock(); -+ } catch (Exception es) { -+ throw new IOException(es.getMessage()); -+ } -+ } else { -+ sock = new Socket(host, port); -+ } -+// end runge/x11vnc -+ - is = - new DataInputStream( - new BufferedInputStream(sock.getInputStream(), 16384)); -@@ -215,9 +243,12 @@ - osw = new OutputStreamWriter(sock.getOutputStream()); - inDirectory2 = false; - a = new ArrayList(); -+ b = new ArrayList(); - // sf@2004 - remoteDirsList = new ArrayList(); -+ remoteDirsListInfo = new ArrayList(); - remoteFilesList = new ArrayList(); -+ remoteFilesListInfo = new ArrayList(); - - sendFileSource = ""; - } -@@ -420,7 +451,13 @@ - // - - int readServerMessageType() throws IOException { -- int msgType = is.readUnsignedByte(); -+ int msgType; -+ try { -+ msgType = is.readUnsignedByte(); -+ } catch (Exception e) { -+ viewer.disconnect(); -+ return -1; -+ } - - // If the session is being recorded: - if (rec != null) { -@@ -600,6 +637,7 @@ - contentParamT = is.readUnsignedByte(); - contentParamT = contentParamT << 8; - contentParam = contentParam | contentParamT; -+//System.out.println("FTM: contentType " + contentType + " contentParam " + contentParam); - if (contentType == rfbRDrivesList || contentType == rfbDirPacket) - { - readDriveOrDirectory(contentParam); -@@ -610,7 +648,7 @@ - } - else if (contentType == rfbFilePacket) - { -- receiveFileChunk(); -+ receiveFileChunk(); - } - else if (contentType == rfbEndOfFile) - { -@@ -618,6 +656,10 @@ - } - else if (contentType == rfbAbortFileTransfer) - { -+ System.out.println("rfbAbortFileTransfer: fFileReceptionRunning=" -+ + fFileReceptionRunning + " fAbort=" -+ + fAbort + " fFileReceptionError=" -+ + fFileReceptionError); - if (fFileReceptionRunning) - { - endOfReceiveFile(false); // Error -@@ -626,6 +668,11 @@ - { - // sf@2004 - Todo: Add TestPermission - // System.out.println("File Transfer Aborted!"); -+ -+ // runge: seems like we must at least read the remaining -+ // 8 bytes of the header, right? -+ int size = is.readInt(); -+ int length = is.readInt(); - } - - } -@@ -645,6 +692,7 @@ - { - System.out.println("ContentType: " + contentType); - } -+//System.out.println("FTM: done"); - } - - //Refactored from readRfbFileTransferMsg() -@@ -662,6 +710,7 @@ - - //Refactored from readRfbFileTransferMsg() - public void readDriveOrDirectory(int contentParam) throws IOException { -+//System.out.println("RDOD: " + contentParam + " " + inDirectory2); - if (contentParam == rfbADrivesList) - { - readFTPMsgDriveList(); -@@ -688,13 +737,21 @@ - - // Internally used. Write an Rfb message to the server - void writeRfbFileTransferMsg( -- int contentType, -- int contentParam, -- long size, // 0 : compression not supported - 1 : compression supported -- long length, -- String text) throws IOException -+ int contentType, -+ int contentParam, -+ long size, // 0 : compression not supported - 1 : compression supported -+ long length, -+ String text) throws IOException - { - byte b[] = new byte[12]; -+ byte byteArray[]; -+ -+ if (viewer.dsmActive) { -+ // need to send the rfbFileTransfer msg type twice for the plugin... -+ byte b2[] = new byte[1]; -+ b2[0] = (byte) rfbFileTransfer; -+ os.write(b2); -+ } - - b[0] = (byte) rfbFileTransfer; - b[1] = (byte) contentType; -@@ -702,7 +759,7 @@ - - byte by = 0; - long c = 0; -- length++; -+ - c = size & 0xFF000000; - by = (byte) (c >>> 24); - b[4] = by; -@@ -716,6 +773,32 @@ - by = (byte) c; - b[7] = by; - -+ if (text != null) { -+ byte byteArray0[] = text.getBytes(); -+ int maxc = max_char(text); -+ if (maxc > 255) { -+ System.out.println("writeRfbFileTransferMsg: using getBytes(\"UTF-8\")"); -+ byteArray0 = text.getBytes("UTF-8"); -+ } else if (maxc > 127) { -+ System.out.println("writeRfbFileTransferMsg: using getBytes(\"ISO-8859-1\")"); -+ byteArray0 = text.getBytes("ISO-8859-1"); -+ } -+ byteArray = new byte[byteArray0.length + 1]; -+ for (int i = 0; i < byteArray0.length; i++) { -+ byteArray[i] = byteArray0[i]; -+ } -+ byteArray[byteArray.length - 1] = 0; -+System.out.println("writeRfbFileTransferMsg: length: " + length + " -> byteArray.length: " + byteArray.length); -+ -+ // will equal length for ascii, ISO-8859-1, more for UTF-8 -+ length = byteArray.length; -+ -+ //length++; // used to not include null byte at end. -+ } else { -+ String moo = "moo"; -+ byteArray = moo.getBytes(); -+ } -+ - c = length & 0xFF000000; - by = (byte) (c >>> 24); - b[8] = by; -@@ -729,29 +812,91 @@ - by = (byte) c; - b[11] = by; - os.write(b); -+ -+//System.out.println("size: " + size + " length: " + length + " text: " + text); - - - if (text != null) - { -- byte byteArray[] = text.getBytes(); -- byte byteArray2[] = new byte[byteArray.length + 1]; -- for (int i = 0; i < byteArray.length; i++) { -- byteArray2[i] = byteArray[i]; -+ os.write(byteArray); -+ } -+ } -+ -+ int max_char(String text) { -+ int maxc = 0; -+ char chars[] = text.toCharArray(); -+ for (int n = 0; n < chars.length; n++) { -+ if ((int) chars[n] > maxc) { -+ maxc = (int) chars[n]; - } -- byteArray2[byteArray2.length - 1] = 0; -- os.write(byteArray2); - } -- -+ return maxc; - } - -+ String guess_encoding(char[] chars) { -+ boolean saw_high_char = false; -+ -+ for (int i = 0; i < chars.length; i++) { -+ if (chars[i] == '\0') { -+ break; -+ } -+ if (chars[i] >= 128) { -+ saw_high_char = true; -+ break; -+ } -+ } -+ if (!saw_high_char) { -+ return "ASCII"; -+ } -+ char prev = 1; -+ boolean valid_utf8 = true; -+ int n = 0; -+ for (int i = 0; i < chars.length; i++) { -+ if (chars[i] == '\0') { -+ break; -+ } -+ char c = chars[i]; -+ if (prev < 128 && c >= 128) { -+ if (c >> 5 == 0x6) { -+ n = 1; -+ } else if (c >> 4 == 0xe) { -+ n = 2; -+ } else if (c >> 3 == 0x1e) { -+ n = 3; -+ } else if (c >> 2 == 0x3e) { -+ n = 4; -+ } else { -+ valid_utf8 = false; -+ break; -+ } -+ } else { -+ if (n > 0) { -+ if (c < 128) { -+ valid_utf8 = false; -+ break; -+ } -+ n--; -+ } -+ } -+ -+ prev = c; -+ } -+ if (valid_utf8) { -+ return "UTF-8"; -+ } else { -+ return "ISO-8859-1"; -+ } -+ } -+ -+ - //Internally used. Write an rfb message to the server for sending files ONLY - int writeRfbFileTransferMsgForSendFile( -- int contentType, -- int contentParam, -- long size, -- long length, -- String source -- ) throws IOException -+ int contentType, -+ int contentParam, -+ long size, -+ long length, -+ String source -+ ) throws IOException - { - File f = new File(source); - fis = new FileInputStream(f); -@@ -768,50 +913,47 @@ - - while (bytesRead!=-1) - { -- counter += bytesRead; -- myDeflater.setInput(byteBuffer, 0, bytesRead); -- myDeflater.finish(); -- compressedSize = myDeflater.deflate(CompressionBuffer); -- myDeflater.reset(); -- // If the compressed data is larger than the original one, we're dealing with -- // already compressed data -- if (compressedSize > bytesRead) -- fCompress = false; -- this.writeRfbFileTransferMsg( -- contentType, -- contentParam, -- (fCompress ? 1 : 0), -- (fCompress ? compressedSize-1 : bytesRead-1), -- null -- ); -- // Todo: Test write error ! -- os.write( -- fCompress ? CompressionBuffer : byteBuffer, -- 0, -- fCompress ? compressedSize : bytesRead -- ); -- -- // Todo: test read error ! -- bytesRead = fis.read(byteBuffer); -- -- // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); -- viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); -- viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); -- -- if (fAbort == true) -- { -- fAbort = false; -- fError = true; -- break; -- } -- try -- { -- Thread.sleep(5); -- } -- catch(InterruptedException e) -- { -- System.err.println("Interrupted"); -- } -+ counter += bytesRead; -+ myDeflater.setInput(byteBuffer, 0, bytesRead); -+ myDeflater.finish(); -+ compressedSize = myDeflater.deflate(CompressionBuffer); -+ myDeflater.reset(); -+ // If the compressed data is larger than the original one, we're dealing with -+ // already compressed data -+ if (compressedSize > bytesRead) -+ fCompress = false; -+ this.writeRfbFileTransferMsg( -+ contentType, -+ contentParam, -+ (fCompress ? 1 : 0), -+// RUNGE (fCompress ? compressedSize-1 : bytesRead-1), -+ (fCompress ? compressedSize : bytesRead), -+ null -+ ); -+ // Todo: Test write error ! -+ os.write(fCompress ? CompressionBuffer : byteBuffer, 0, fCompress ? compressedSize : bytesRead); -+ -+ // Todo: test read error ! -+ bytesRead = fis.read(byteBuffer); -+ -+ // viewer.ftp.connectionStatus.setText("Sent: "+ counter + " bytes of "+ f.length() + " bytes"); -+ viewer.ftp.jProgressBar.setValue((int)((counter * 100) / f.length())); -+ viewer.ftp.connectionStatus.setText(">>> Sending File: " + source + " - Size: " + f.length() + " bytes - Progress: " + ((counter * 100) / f.length()) + "%"); -+ -+ if (fAbort == true) -+ { -+ fAbort = false; -+ fError = true; -+ break; -+ } -+ try -+ { -+ Thread.sleep(5); -+ } -+ catch(InterruptedException e) -+ { -+ System.err.println("Interrupted"); -+ } - } - - writeRfbFileTransferMsg(fError ? rfbAbortFileTransfer : rfbEndOfFile, 0, 0, 0, null); -@@ -831,24 +973,30 @@ - { - System.out.print((char) is.readUnsignedByte()); - } -+ System.out.println(""); -+ -+ if (size == rfbRErrorCmd || size == -1) { -+ viewer.ftp.enableButtons(); -+ viewer.ftp.connectionStatus.setText("Remote file not available for writing."); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for writing."), 0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); -+ return; -+ } - -- int ret = writeRfbFileTransferMsgForSendFile( -- rfbFilePacket, -- 0, -- 0, -- 0, -- sendFileSource); -+ int ret = writeRfbFileTransferMsgForSendFile(rfbFilePacket, 0, 0, 0, sendFileSource); - - viewer.ftp.refreshRemoteLocation(); - if (ret != 1) - { - viewer.ftp.connectionStatus.setText(" > Error - File NOT sent"); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) + "> was not correctly sent (aborted by user or error)",0); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + sendFileSource) -+ + "> was not correctly sent (aborted or error). Data may still be buffered/in transit. Wait for remote listing...",0); - } - else - { - viewer.ftp.connectionStatus.setText(" > File sent"); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) + "> was sent to Remote Machine",0); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > File: <" + sendFileSource) -+ + "> was sent to Remote Machine. Note: data may still be buffered/in transit. Wait for remote listing...",0); - } - viewer.ftp.historyComboBox.setSelectedIndex(0); - viewer.ftp.enableButtons(); -@@ -907,7 +1055,7 @@ - //Handles acknowledgement that the file has been deleted on the server - void deleteRemoteFileFeedback() throws IOException - { -- is.readInt(); -+ int ret = is.readInt(); - int length = is.readInt(); - String f = ""; - for (int i = 0; i < length; i++) -@@ -916,7 +1064,11 @@ - } - - viewer.ftp.refreshRemoteLocation(); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); -+ if (ret == -1) { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Delete File On Remote Machine: "),0); -+ } else { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Deleted File On Remote Machine: " + f.substring(0, f.length()-1)),0); -+ } - viewer.ftp.historyComboBox.setSelectedIndex(0); - } - -@@ -926,12 +1078,7 @@ - try - { - String temp = text; -- writeRfbFileTransferMsg( -- rfbCommand, -- rfbCFileDelete, -- 0, -- temp.length(), -- temp); -+ writeRfbFileTransferMsg(rfbCommand, rfbCFileDelete, 0, temp.length(), temp); - } - catch (IOException e) - { -@@ -943,7 +1090,7 @@ - // Handles acknowledgement that the directory has been created on the server - void createRemoteDirectoryFeedback() throws IOException - { -- is.readInt(); -+ int ret = is.readInt(); - int length = is.readInt(); - String f=""; - for (int i = 0; i < length; i++) -@@ -951,7 +1098,11 @@ - f += (char)is.readUnsignedByte(); - } - viewer.ftp.refreshRemoteLocation(); -- viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); -+ if (ret == -1) { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR Could not Create Directory on Remote Machine."),0); -+ } else { -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Created Directory on Remote Machine: " + f.substring(0, f.length()-1)),0); -+ } - viewer.ftp.historyComboBox.setSelectedIndex(0); - } - -@@ -961,12 +1112,7 @@ - try - { - String temp = text; -- writeRfbFileTransferMsg( -- rfbCommand, -- rfbCDirCreate, -- 0, -- temp.length(), -- temp); -+ writeRfbFileTransferMsg(rfbCommand, rfbCDirCreate, 0, temp.length(), temp); - } - catch (IOException e) - { -@@ -979,15 +1125,13 @@ - { - try - { -+//System.out.println("requestRemoteFile text: " + text); -+//System.out.println("requestRemoteFile leng: " + text.length()); - String temp = text; - receivePath = localPath; - -- writeRfbFileTransferMsg( -- rfbFileTransferRequest, -- 0, -- 1, // 0 : compression not supported - 1 : compression supported -- temp.length(), -- temp); -+ // 0 : compression not supported - 1 : compression supported -+ writeRfbFileTransferMsg(rfbFileTransferRequest, 0, 1, temp.length(), temp); - } - catch (IOException e) - { -@@ -1004,6 +1148,9 @@ - viewer.ftp.disableButtons(); - int size = is.readInt(); - int length = is.readInt(); -+ -+//System.out.println("receiveFileHeader size: " + size); -+//System.out.println("receiveFileHeader leng: " + length); - - String tempName = ""; - for (int i = 0; i < length; i++) -@@ -1011,6 +1158,15 @@ - tempName += (char) is.readUnsignedByte(); - } - -+ if (size == rfbRErrorCmd || size == -1) { -+ fFileReceptionRunning = false; -+ viewer.ftp.enableButtons(); -+ viewer.ftp.connectionStatus.setText("Remote file not available for reading."); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - Remote file not available for reading."), 0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); -+ return; -+ } -+ - // sf@2004 - Read the high part of file size (not yet in rfbFileTransferMsg for - // backward compatibility reasons...) - int sizeH = is.readInt(); -@@ -1021,7 +1177,16 @@ - fileSize=0; - fileChunkCounter = 0; - String fileName = receivePath; -- fos = new FileOutputStream(fileName); -+ try { -+ fos = new FileOutputStream(fileName); -+ } catch (Exception e) { -+ fFileReceptionRunning = false; -+ writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > ERROR opening Local File: <" + fileName ),0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); -+ viewer.ftp.enableButtons(); -+ return; -+ } - writeRfbFileTransferMsg(rfbFileHeader, 0, 0, 0, null); - } - -@@ -1085,7 +1250,13 @@ - fAbort = false; - fFileReceptionError = true; - writeRfbFileTransferMsg(rfbAbortFileTransfer, 0, 0, 0, null); -- -+ -+ //runge for use with x11vnc/libvncserver, no rfbAbortFileTransfer reply sent. -+ try {Thread.sleep(500);} catch (InterruptedException e) {} -+ viewer.ftp.enableButtons(); -+ viewer.ftp.refreshLocalLocation(); -+ viewer.ftp.connectionStatus.setText(" > Error - File NOT received"); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > Error - File: <" + receivePath + "> not correctly received from Remote Machine (aborted by user or error)") ,0); - } - // sf@2004 - For old FT protocole only - /* -@@ -1104,7 +1275,7 @@ - int length = is.readInt(); - fileSize=0; - fos.close(); -- -+ - viewer.ftp.refreshLocalLocation(); - if (fReceptionOk && !fFileReceptionError) - { -@@ -1132,12 +1303,7 @@ - try - { - String temp = text; -- writeRfbFileTransferMsg( -- rfbDirContentRequest, -- rfbRDirContent, -- 0, -- temp.length(), -- temp); -+ writeRfbFileTransferMsg(rfbDirContentRequest, rfbRDirContent, 0, temp.length(), temp); - } - catch (IOException e) - { -@@ -1197,11 +1363,80 @@ - str += temp; - } - } -+ // runge -+ viewer.ftp.receivedRemoteDirectoryName(str); - // viewer.ftp.changeRemoteDirectory(str); - - } - } - -+ int zogswap(int n) { -+ long l = n; -+ if (l < 0) { -+ l += 0x100000000L; -+ } -+ l = l & 0xFFFFFFFF; -+ l = (l >> 24) | ((l & 0x00ff0000) >> 8) | ((l & 0x0000ff00) << 8) | (l << 24); -+ return (int) l; -+ } -+ -+ int windozeToUnix(int L, int H) { -+ long L2 = zogswap(L); -+ long H2 = zogswap(H); -+ long unix = (H2 << 32) + L2; -+ unix -= 11644473600L * 10000000L; -+ unix /= 10000000L; -+ //System.out.println("unix time: " + unix + " H2: " + H2 + " L2: " + L2); -+ return (int) unix; -+ } -+ -+ String timeStr(int t, int h) { -+ if (h == 0) { -+ // x11vnc/libvncserver unix -+ t = zogswap(t); -+ } else { -+ // ultra (except if h==0 by chance) -+ t = windozeToUnix(t, h); -+ } -+ long tl = (long) t; -+ Date date = new Date(tl * 1000); -+ if (true) { -+ return date.toString(); -+ } else { -+ return DateFormat.getDateTimeInstance().format(date); -+ } -+ } -+ -+ String dotPast(double f, int n) { -+ String fs = "" + f; -+ int i = fs.lastIndexOf(".") + n; -+ if (i >= 0) { -+ int len = fs.length(); -+ if (i >= len) { -+ i = len-1; -+ } -+ fs = fs.substring(0, i); -+ } -+ return fs; -+ } -+ String sizeStr(int s) { -+ s = zogswap(s); -+ if (s < 0) { -+ return s + "? B"; -+ } else if (s < 1024) { -+ return s + " B"; -+ } else if (s < 1024 * 1024) { -+ double k = s / 1024.0; -+ String ks = dotPast(k, 3); -+ -+ return s + " (" + ks + " KB)"; -+ } else { -+ double m = s / (1024.0*1024.0); -+ String ms = dotPast(m, 3); -+ return s + " (" + ms + " MB)"; -+ } -+ } -+ - //Internally used to receive directory content from server - //Here, the server sends one file/directory with it's attributes - void readFTPMsgDirectoryListContent() throws IOException -@@ -1217,17 +1452,32 @@ - dwReserved0, - dwReserved1; - long ftCreationTime, ftLastAccessTime, ftLastWriteTime; -+ int ftCreationTimeL, ftLastAccessTimeL, ftLastWriteTimeL; -+ int ftCreationTimeH, ftLastAccessTimeH, ftLastWriteTimeH; - char cFileName, cAlternateFileName; - int length = 0; - is.readInt(); - length = is.readInt(); -+ -+ char[] chars = new char[4*length]; -+ int char_cnt = 0; -+ for (int i = 0; i < chars.length; i++) { -+ chars[i] = '\0'; -+ } -+ - dwFileAttributes = is.readInt(); - length -= 4; -- ftCreationTime = is.readLong(); -+ //ftCreationTime = is.readLong(); -+ ftCreationTimeL = is.readInt(); -+ ftCreationTimeH = is.readInt(); - length -= 8; -- ftLastAccessTime = is.readLong(); -+ //ftLastAccessTime = is.readLong(); -+ ftLastAccessTimeL = is.readInt(); -+ ftLastAccessTimeH = is.readInt(); - length -= 8; -- ftLastWriteTime = is.readLong(); -+ //ftLastWriteTime = is.readLong(); -+ ftLastWriteTimeL = is.readInt(); -+ ftLastWriteTimeH = is.readInt(); - length -= 8; - nFileSizeHigh = is.readInt(); - length -= 4; -@@ -1239,10 +1489,12 @@ - length -= 4; - cFileName = (char) is.readUnsignedByte(); - length--; -+ chars[char_cnt++] = cFileName; - while (cFileName != '\0') - { - fileName += cFileName; - cFileName = (char) is.readUnsignedByte(); -+ chars[char_cnt++] = cFileName; - length--; - } - cAlternateFileName = (char) is.readByte(); -@@ -1253,7 +1505,28 @@ - cAlternateFileName = (char) is.readUnsignedByte(); - length--; - } -- if (dwFileAttributes == 268435456 -+ String guessed = guess_encoding(chars); -+ if (!guessed.equals("ASCII")) { -+ System.out.println("guess: " + guessed + "\t" + fileName); -+ } -+ if (guessed.equals("UTF-8")) { -+ try { -+ byte[] bytes = new byte[char_cnt-1]; -+ for (int i=0; i < char_cnt-1; i++) { -+ bytes[i] = (byte) chars[i]; -+ } -+ String newstr = new String(bytes, "UTF-8"); -+ fileName = newstr; -+ } catch (Exception e) { -+ System.out.println("failed to convert bytes to UTF-8 based string"); -+ } -+ } -+ for (int i = 0; i < char_cnt; i++) { -+ //System.out.println("char[" + i + "]\t" + (int) chars[i]); -+ } -+ if (fileName.length() <= 0) { -+ ; -+ } else if (dwFileAttributes == 268435456 - || dwFileAttributes == 369098752 - || dwFileAttributes == 285212672 - || dwFileAttributes == 271056896 -@@ -1263,11 +1536,74 @@ - || dwFileAttributes == 369623040) - { - fileName = " [" + fileName + "]"; -- remoteDirsList.add(fileName); // sf@2004 -- } -- else -- { -- remoteFilesList.add(" " + fileName); // sf@2004 -+// begin runge/x11vnc -+// remoteDirsList.add(fileName); // sf@2004 -+ int i = -1; -+ String t1 = fileName.toLowerCase(); -+ for (int j = 0; j < remoteDirsList.size(); j++) { -+ String t = (String) remoteDirsList.get(j); -+ String t2 = t.toLowerCase(); -+ if (t1.compareTo(t2) < 0) { -+ i = j; -+ break; -+ } -+ } -+ //String s = "Lastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " " + fileName; -+ String f2 = fileName; -+ if (f2.length() < 24) { -+ for (int ik = f2.length(); ik < 24; ik++) { -+ f2 = f2 + " "; -+ } -+ } -+ String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); -+ //s = fileName + " Lastmod: " + zogswap(ftLastWriteTimeL); -+ if (i >= 0) { -+ remoteDirsList.add(i, fileName); -+ remoteDirsListInfo.add(i, s); -+ } else { -+ remoteDirsList.add(fileName); -+ remoteDirsListInfo.add(s); -+ } -+// end runge/x11vnc -+ } else { -+// begin runge/x11vnc -+// remoteFilesList.add(" " + fileName); // sf@2004 -+ -+ fileName = " " + fileName; -+ int i = -1; -+ String t1 = fileName.toLowerCase(); -+ for (int j = 0; j < remoteFilesList.size(); j++) { -+ String t = (String) remoteFilesList.get(j); -+ String t2 = t.toLowerCase(); -+ if (t1.compareTo(t2) < 0) { -+ i = j; -+ break; -+ } -+ } -+ String f2 = fileName; -+ if (f2.length() < 24) { -+ for (int ik = f2.length(); ik < 24; ik++) { -+ f2 = f2 + " "; -+ } -+ } -+ -+if (false) { -+System.out.println("fileName: " + f2); -+System.out.println("ftLastWriteTimeL: " + ftLastWriteTimeL); -+System.out.println("ftLastWriteTimeH: " + ftLastWriteTimeH); -+System.out.println("nFileSizeLow: " + nFileSizeLow); -+} -+ -+ String s = f2 + " \tLastmod: " + timeStr(ftLastWriteTimeL, ftLastWriteTimeH) + " \t\tSize: " + sizeStr(nFileSizeLow); -+ //s = fileName + " Lastmod: " + ftLastWriteTimeL + "/" + zogswap(ftLastWriteTimeL) + " Size: " + nFileSizeLow + "/" + zogswap(nFileSizeLow); -+ if (i >= 0) { -+ remoteFilesList.add(i, fileName); -+ remoteFilesListInfo.add(i, s); -+ } else { -+ remoteFilesList.add(fileName); -+ remoteFilesListInfo.add(s); -+ } -+// end runge/x11vnc - } - - // a.add(fileName); -@@ -1282,14 +1618,32 @@ - - // sf@2004 - a.clear(); -- for (int i = 0; i < remoteDirsList.size(); i++) -+ b.clear(); -+ for (int i = 0; i < remoteDirsList.size(); i++) { - a.add(remoteDirsList.get(i)); -- for (int i = 0; i < remoteFilesList.size(); i++) -+ b.add(remoteDirsListInfo.get(i)); -+ } -+ for (int i = 0; i < remoteFilesList.size(); i++) { - a.add(remoteFilesList.get(i)); -+ -+ b.add(remoteFilesListInfo.get(i)); -+ } - remoteDirsList.clear(); -+ remoteDirsListInfo.clear(); - remoteFilesList.clear(); -+ remoteFilesListInfo.clear(); - -- viewer.ftp.printDirectory(a); -+// begin runge/x11vnc -+ // Hack for double listing at startup... probably libvncserver bug.. -+ readServerDriveListCnt++; -+ if (readServerDriveListCnt == 2) { -+ if (System.currentTimeMillis() - readServerDriveListTime < 2000) { -+//System.out.println("readServerDriveListCnt skip " + readServerDriveListCnt); -+ return; -+ } -+ } -+// end runge/x11vnc -+ viewer.ftp.printDirectory(a, b); - } - - //Internally used to signify the drive requested is not ready -@@ -1299,6 +1653,8 @@ - System.out.println("Remote Drive unavailable"); - viewer.ftp.connectionStatus.setText(" > WARNING - Remote Drive unavailable (possibly restricted access or media not present)"); - viewer.ftp.remoteStatus.setText("WARNING: Remote Drive unavailable"); -+ viewer.ftp.historyComboBox.insertItemAt(new String(" > WARNING: Remote Drive unavailable."), 0); -+ viewer.ftp.historyComboBox.setSelectedIndex(0); - } - - //Call this method to request the list of drives on the server. -@@ -1306,12 +1662,11 @@ - { - try - { -- viewer.rfb.writeRfbFileTransferMsg( -- RfbProto.rfbDirContentRequest, -- RfbProto.rfbRDrivesList, -- 0, -- 0, -- null); -+ viewer.rfb.writeRfbFileTransferMsg(RfbProto.rfbDirContentRequest, RfbProto.rfbRDrivesList, 0, 0, null); -+// begin runge/x11vnc -+ readServerDriveListCnt = 0; -+ readServerDriveListTime = System.currentTimeMillis(); -+// end runge/x11vnc - } - catch (IOException e) - { -@@ -1355,21 +1710,21 @@ - int h, - boolean incremental) - throws IOException { -- if (!viewer.ftp.isVisible()) { -- byte[] b = new byte[10]; -+ if (!viewer.ftp.isVisible()) { -+ byte[] b = new byte[10]; - -- b[0] = (byte) FramebufferUpdateRequest; -- b[1] = (byte) (incremental ? 1 : 0); -- b[2] = (byte) ((x >> 8) & 0xff); -- b[3] = (byte) (x & 0xff); -- b[4] = (byte) ((y >> 8) & 0xff); -- b[5] = (byte) (y & 0xff); -- b[6] = (byte) ((w >> 8) & 0xff); -- b[7] = (byte) (w & 0xff); -- b[8] = (byte) ((h >> 8) & 0xff); -- b[9] = (byte) (h & 0xff); -+ b[0] = (byte) FramebufferUpdateRequest; -+ b[1] = (byte) (incremental ? 1 : 0); -+ b[2] = (byte) ((x >> 8) & 0xff); -+ b[3] = (byte) (x & 0xff); -+ b[4] = (byte) ((y >> 8) & 0xff); -+ b[5] = (byte) (y & 0xff); -+ b[6] = (byte) ((w >> 8) & 0xff); -+ b[7] = (byte) (w & 0xff); -+ b[8] = (byte) ((h >> 8) & 0xff); -+ b[9] = (byte) (h & 0xff); - -- os.write(b); -+ os.write(b); - } - } - -@@ -1482,7 +1837,13 @@ - b[6] = (byte) ((text.length() >> 8) & 0xff); - b[7] = (byte) (text.length() & 0xff); - -- System.arraycopy(text.getBytes(), 0, b, 8, text.length()); -+ if (false && max_char(text) > 255) { -+ System.arraycopy(text.getBytes("UTF-8"), 0, b, 8, text.length()); -+ } else if (max_char(text) > 127) { -+ System.arraycopy(text.getBytes("ISO-8859-1"), 0, b, 8, text.length()); -+ } else { -+ System.arraycopy(text.getBytes(), 0, b, 8, text.length()); -+ } - - os.write(b); - // } -@@ -1506,6 +1867,37 @@ - final static int META_MASK = InputEvent.META_MASK; - final static int ALT_MASK = InputEvent.ALT_MASK; - -+ void writeWheelEvent(MouseWheelEvent evt) throws IOException { -+ eventBufLen = 0; -+ -+ int x = evt.getX(); -+ int y = evt.getY(); -+ -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; -+ -+ int ptrmask; -+ -+ int clicks = evt.getWheelRotation(); -+ System.out.println("writeWheelEvent: clicks: " + clicks); -+ if (clicks > 0) { -+ ptrmask = 16; -+ } else if (clicks < 0) { -+ ptrmask = 8; -+ } else { -+ return; -+ } -+ -+ eventBuf[eventBufLen++] = (byte) PointerEvent; -+ eventBuf[eventBufLen++] = (byte) ptrmask; -+ eventBuf[eventBufLen++] = (byte) ((x >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (x & 0xff); -+ eventBuf[eventBufLen++] = (byte) ((y >> 8) & 0xff); -+ eventBuf[eventBufLen++] = (byte) (y & 0xff); -+ -+ os.write(eventBuf, 0, eventBufLen); -+ } -+ - // - // Write a pointer event message. We may need to send modifier key events - // around it to set the correct modifier state. -@@ -1610,6 +2002,21 @@ - - boolean down = (evt.getID() == KeyEvent.KEY_PRESSED); - -+ if (viewer.debugKeyboard) { -+ System.out.println("----------------------------------------"); -+ System.out.println("evt.getKeyChar: " + evt.getKeyChar()); -+ System.out.println("getKeyText: " + KeyEvent.getKeyText(evt.getKeyCode())); -+ System.out.println("evt.getKeyCode: " + evt.getKeyCode()); -+ System.out.println("evt.getID: " + evt.getID()); -+ System.out.println("evt.getKeyLocation: " + evt.getKeyLocation()); -+ System.out.println("evt.isActionKey: " + evt.isActionKey()); -+ System.out.println("evt.isControlDown: " + evt.isControlDown()); -+ System.out.println("evt.getModifiers: " + evt.getModifiers()); -+ System.out.println("getKeyModifiersText: " + KeyEvent.getKeyModifiersText(evt.getModifiers())); -+ System.out.println("evt.paramString: " + evt.paramString()); -+ } -+ -+ - int key; - if (evt.isActionKey()) { - -@@ -1685,6 +2092,9 @@ - default : - return; - } -+ if (key == 0xffc2 && viewer.mapF5_to_atsign) { -+ key = 0x40; -+ } - - } else { - -@@ -1794,6 +2204,16 @@ - int oldModifiers = 0; - - void writeModifierKeyEvents(int newModifiers) { -+ if(viewer.forbid_Ctrl_Alt) { -+ if ((newModifiers & CTRL_MASK) != 0 && (newModifiers & ALT_MASK) != 0) { -+ int orig = newModifiers; -+ newModifiers &= ~ALT_MASK; -+ newModifiers &= ~CTRL_MASK; -+ if (viewer.debugKeyboard) { -+ System.out.println("Ctrl+Alt modifiers: " + orig + " -> " + newModifiers); -+ } -+ } -+ } - if ((newModifiers & CTRL_MASK) != (oldModifiers & CTRL_MASK)) - writeKeyEvent(0xffe3, (newModifiers & CTRL_MASK) != 0); - -diff -Naur JavaViewer.orig/SSLSocketToMe.java JavaViewer/SSLSocketToMe.java ---- JavaViewer.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 -+++ JavaViewer/SSLSocketToMe.java 2010-07-10 19:18:06.000000000 -0400 -@@ -0,0 +1,2067 @@ -+/* -+ * SSLSocketToMe.java: add SSL encryption to Java VNC Viewer. -+ * -+ * Copyright (c) 2006 Karl J. Runge -+ * 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; 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. -+ * -+ */ -+ -+import java.net.*; -+import java.io.*; -+import javax.net.ssl.*; -+import java.util.*; -+ -+import java.security.*; -+import java.security.cert.*; -+import java.security.spec.*; -+import java.security.cert.Certificate; -+import java.security.cert.CertificateFactory; -+ -+import java.awt.*; -+import java.awt.event.*; -+ -+public class SSLSocketToMe { -+ -+ /* basic member data: */ -+ String host; -+ int port; -+ VncViewer viewer; -+ -+ boolean debug = true; -+ boolean debug_certs = false; -+ -+ /* sockets */ -+ SSLSocket socket = null; -+ SSLSocketFactory factory; -+ -+ /* fallback for Proxy connection */ -+ boolean proxy_in_use = false; -+ boolean proxy_failure = false; -+ public DataInputStream is = null; -+ public OutputStream os = null; -+ -+ /* strings from user WRT proxy: */ -+ String proxy_auth_string = null; -+ String proxy_dialog_host = null; -+ int proxy_dialog_port = 0; -+ -+ Socket proxySock; -+ DataInputStream proxy_is; -+ OutputStream proxy_os; -+ -+ /* trust contexts */ -+ SSLContext trustloc_ctx; -+ SSLContext trustall_ctx; -+ SSLContext trustsrv_ctx; -+ SSLContext trusturl_ctx; -+ SSLContext trustone_ctx; -+ -+ /* corresponding trust managers */ -+ TrustManager[] trustAllCerts; -+ TrustManager[] trustSrvCert; -+ TrustManager[] trustUrlCert; -+ TrustManager[] trustOneCert; -+ -+ /* client-side SSL auth key (oneTimeKey=...) */ -+ KeyManager[] mykey = null; -+ -+ boolean user_wants_to_see_cert = true; -+ String cert_fail = null; -+ -+ /* cert(s) we retrieve from Web server, VNC server, or serverCert param: */ -+ java.security.cert.Certificate[] trustallCerts = null; -+ java.security.cert.Certificate[] trustsrvCerts = null; -+ java.security.cert.Certificate[] trusturlCerts = null; -+ -+ /* utility to decode hex oneTimeKey=... and serverCert=... */ -+ byte[] hex2bytes(String s) { -+ byte[] bytes = new byte[s.length()/2]; -+ for (int i=0; i 127) { -+ val -= 256; -+ } -+ Integer I = new Integer(val); -+ bytes[i] = Byte.decode(I.toString()).byteValue(); -+ -+ } catch (Exception e) { -+ ; -+ } -+ } -+ return bytes; -+ } -+ -+ SSLSocketToMe(String h, int p, VncViewer v) throws Exception { -+ host = h; -+ port = p; -+ viewer = v; -+ -+ debug_certs = v.debugCerts; -+ -+ /* we will first try default factory for certification: */ -+ -+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault(); -+ -+ dbg("SSL startup: " + host + " " + port); -+ -+ -+ /* create trust managers to be used if initial handshake fails: */ -+ -+ trustAllCerts = new TrustManager[] { -+ /* -+ * this one accepts everything. Only used if user -+ * has disabled checking (trustAllVncCerts=yes) -+ * or when we grab the cert to show it to them in -+ * a dialog and ask them to manually verify/accept it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) { -+ /* empty */ -+ dbg("ALL: an untrusted connect to grab cert."); -+ } -+ } -+ }; -+ -+ trustUrlCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet and stored in -+ * trusturlCerts. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (URL)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trusturlCerts' */ -+ if (trusturlCerts == null) { -+ throw new CertificateException( -+ "No Trust url Certs array."); -+ } -+ if (trusturlCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust url Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trusturlCerts.length) { -+ throw new CertificateException( -+ "certs.length != trusturlCerts.length " + certs.length + " " + trusturlCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trusturlCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("URL: cert mismatch at i=" + i); -+ dbg("URL: cert mismatch cert" + certs[i]); -+ dbg("URL: cert mismatch url" + trusturlCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("URL: cert info at i=" + i); -+ dbg("URL: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("URL: cert info url" + trusturlCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != URL Cert Chain."); -+ } -+ dbg("URL: trusturlCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustSrvCert = new TrustManager[] { -+ /* -+ * this one accepts cert given to us in the serverCert -+ * Applet Parameter we were started with. It is -+ * currently a fatal error if the VNC Server's cert -+ * doesn't match it. -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (SRV)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustsrvCerts' */ -+ if (trustsrvCerts == null) { -+ throw new CertificateException( -+ "No Trust srv Certs array."); -+ } -+ if (trustsrvCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust srv Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustsrvCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustsrvCerts.length " + certs.length + " " + trustsrvCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustsrvCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("SRV: cert mismatch at i=" + i); -+ dbg("SRV: cert mismatch cert" + certs[i]); -+ dbg("SRV: cert mismatch srv" + trustsrvCerts[i]); -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("SRV: cert info at i=" + i); -+ dbg("SRV: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("SRV: cert info srv" + trustsrvCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != serverCert Applet Parameter Cert Chain."); -+ } -+ dbg("SRV: trustsrvCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ trustOneCert = new TrustManager[] { -+ /* -+ * this one accepts only the retrieved server -+ * cert by SSLSocket by this applet we stored in -+ * trustallCerts that user has accepted or applet -+ * parameter trustAllVncCerts=yes is set. This is -+ * for when we reconnect after the user has manually -+ * accepted the trustall cert in the dialog (or set -+ * trustAllVncCerts=yes applet param.) -+ */ -+ new X509TrustManager() { -+ public java.security.cert.X509Certificate[] -+ getAcceptedIssuers() { -+ return null; -+ } -+ public void checkClientTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ throw new CertificateException("No Clients (ONE)"); -+ } -+ public void checkServerTrusted( -+ java.security.cert.X509Certificate[] certs, -+ String authType) throws CertificateException { -+ /* we want to check 'certs' against 'trustallCerts' */ -+ if (trustallCerts == null) { -+ throw new CertificateException( -+ "No Trust All Server Certs array."); -+ } -+ if (trustallCerts.length < 1) { -+ throw new CertificateException( -+ "No Trust All Server Certs."); -+ } -+ if (certs == null) { -+ throw new CertificateException( -+ "No this-certs array."); -+ } -+ if (certs.length < 1) { -+ throw new CertificateException( -+ "No this-certs Certs."); -+ } -+ if (certs.length != trustallCerts.length) { -+ throw new CertificateException( -+ "certs.length != trustallCerts.length " + certs.length + " " + trustallCerts.length); -+ } -+ boolean ok = true; -+ for (int i = 0; i < certs.length; i++) { -+ if (! trustallCerts[i].equals(certs[i])) { -+ ok = false; -+ dbg("ONE: cert mismatch at i=" + i); -+ dbg("ONE: cert mismatch cert" + certs[i]); -+ dbg("ONE: cert mismatch all" + trustallCerts[i]); -+ } -+ if (debug_certs) { -+ dbg("\n***********************************************"); -+ dbg("ONE: cert info at i=" + i); -+ dbg("ONE: cert info cert" + certs[i]); -+ dbg("==============================================="); -+ dbg("ONE: cert info all" + trustallCerts[i]); -+ dbg("***********************************************"); -+ } -+ } -+ if (!ok) { -+ throw new CertificateException( -+ "Server Cert Chain != TRUSTALL Cert Chain."); -+ } -+ dbg("ONE: trustallCerts[i] matches certs[i] i=0:" + (certs.length-1)); -+ } -+ } -+ }; -+ -+ /* -+ * The above TrustManagers are used: -+ * -+ * 1) to retrieve the server cert in case of failure to -+ * display it to the user in a dialog. -+ * 2) to subsequently connect to the server if user agrees. -+ */ -+ -+ /* -+ * build oneTimeKey cert+key if supplied in applet parameter: -+ */ -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.equals("PROMPT")) { -+ ClientCertDialog d = new ClientCertDialog(); -+ viewer.oneTimeKey = d.queryUser(); -+ } -+ if (viewer.oneTimeKey != null && viewer.oneTimeKey.indexOf(",") > 0) { -+ int idx = viewer.oneTimeKey.indexOf(","); -+ -+ String onetimekey = viewer.oneTimeKey.substring(0, idx); -+ byte[] key = hex2bytes(onetimekey); -+ String onetimecert = viewer.oneTimeKey.substring(idx+1); -+ byte[] cert = hex2bytes(onetimecert); -+ -+ KeyFactory kf = KeyFactory.getInstance("RSA"); -+ PKCS8EncodedKeySpec keysp = new PKCS8EncodedKeySpec ( key ); -+ PrivateKey ff = kf.generatePrivate (keysp); -+ if (debug_certs) { -+ dbg("one time key " + ff); -+ } -+ -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ Certificate[] certs = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ if (debug_certs) { -+ dbg("one time cert" + tmpcert); -+ } -+ certs[0] = tmpcert; -+ } else { -+ certs = (Certificate[]) c.toArray(); -+ } -+ -+ KeyStore ks = KeyStore.getInstance("JKS"); -+ ks.load(null, null); -+ ks.setKeyEntry("onetimekey", ff, "".toCharArray(), certs); -+ String da = KeyManagerFactory.getDefaultAlgorithm(); -+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(da); -+ kmf.init(ks, "".toCharArray()); -+ -+ mykey = kmf.getKeyManagers(); -+ } -+ -+ /* -+ * build serverCert cert if supplied in applet parameter: -+ */ -+ if (viewer.serverCert != null) { -+ CertificateFactory cf = CertificateFactory.getInstance("X.509"); -+ byte[] cert = hex2bytes(viewer.serverCert); -+ Collection c = cf.generateCertificates(new ByteArrayInputStream(cert)); -+ trustsrvCerts = new Certificate[c.toArray().length]; -+ if (c.size() == 1) { -+ Certificate tmpcert = cf.generateCertificate(new ByteArrayInputStream(cert)); -+ trustsrvCerts[0] = tmpcert; -+ } else { -+ trustsrvCerts = (Certificate[]) c.toArray(); -+ } -+ } -+ -+ /* the trust loc certs context: */ -+ try { -+ trustloc_ctx = SSLContext.getInstance("SSL"); -+ -+ /* -+ * below is a failed attempt to get jvm's default -+ * trust manager using null (below) makes it so -+ * for HttpsURLConnection the server cannot be -+ * verified (no prompting.) -+ */ -+ if (false) { -+ boolean didit = false; -+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); -+ tmf.init((KeyStore) null); -+ TrustManager [] tml = tmf.getTrustManagers(); -+ for (int i = 0; i < tml.length; i++) { -+ TrustManager tm = tml[i]; -+ if (tm instanceof X509TrustManager) { -+ TrustManager tm1[] = new TrustManager[1]; -+ tm1[0] = tm; -+ trustloc_ctx.init(mykey, tm1, null); -+ didit = true; -+ break; -+ } -+ } -+ if (!didit) { -+ trustloc_ctx.init(mykey, null, null); -+ } -+ } else { -+ /* we have to set trust manager to null */ -+ trustloc_ctx.init(mykey, null, null); -+ } -+ -+ } catch (Exception e) { -+ String msg = "SSL trustloc_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust all certs context: */ -+ try { -+ trustall_ctx = SSLContext.getInstance("SSL"); -+ trustall_ctx.init(mykey, trustAllCerts, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustall_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust url certs context: */ -+ try { -+ trusturl_ctx = SSLContext.getInstance("SSL"); -+ trusturl_ctx.init(mykey, trustUrlCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trusturl_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust srv certs context: */ -+ try { -+ trustsrv_ctx = SSLContext.getInstance("SSL"); -+ trustsrv_ctx.init(mykey, trustSrvCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustsrv_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ -+ /* the trust the one cert from server context: */ -+ try { -+ trustone_ctx = SSLContext.getInstance("SSL"); -+ trustone_ctx.init(mykey, trustOneCert, new -+ java.security.SecureRandom()); -+ -+ } catch (Exception e) { -+ String msg = "SSL trustone_ctx FAILED."; -+ dbg(msg); -+ throw new Exception(msg); -+ } -+ } -+ -+ /* -+ * we call this early on to 1) check for a proxy, 2) grab -+ * Browser/JVM accepted HTTPS cert. -+ */ -+ public void check_for_proxy_and_grab_vnc_server_cert() { -+ -+ trusturlCerts = null; -+ proxy_in_use = false; -+ -+ if (viewer.ignoreProxy) { -+ /* applet param says skip it. */ -+ /* the downside is we do not set trusturlCerts for comparison later... */ -+ /* nor do we autodetect x11vnc for GET=1. */ -+ return; -+ } -+ -+ dbg("------------------------------------------------"); -+ dbg("Into check_for_proxy_and_grab_vnc_server_cert():"); -+ -+ dbg("TRYING HTTPS:"); -+ String ustr = "https://" + host + ":"; -+ if (viewer.httpsPort != null) { -+ ustr += viewer.httpsPort; -+ } else { -+ ustr += port; -+ } -+ ustr += viewer.urlPrefix + "/check.https.proxy.connection"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTPS URL connection to host:port */ -+ URL url = new URL(ustr); -+ HttpsURLConnection https = (HttpsURLConnection) url.openConnection(); -+ -+ if (mykey != null) { -+ /* with oneTimeKey (mykey) we can't use the default SSL context */ -+ if (trustsrvCerts != null) { -+ dbg("passing trustsrv_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustsrv_ctx.getSocketFactory()); -+ } else if (trustloc_ctx != null) { -+ dbg("passing trustloc_ctx to HttpsURLConnection to provide client cert."); -+ https.setSSLSocketFactory(trustloc_ctx.getSocketFactory()); -+ } -+ } -+ -+ https.setUseCaches(false); -+ https.setRequestMethod("GET"); -+ https.setRequestProperty("Pragma", "No-Cache"); -+ https.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ https.setDoInput(true); -+ -+ dbg("trying https.connect()"); -+ https.connect(); -+ -+ dbg("trying https.getServerCertificates()"); -+ trusturlCerts = https.getServerCertificates(); -+ -+ if (trusturlCerts == null) { -+ dbg("set trusturlCerts to null!"); -+ } else { -+ dbg("set trusturlCerts to non-null"); -+ } -+ -+ if (https.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTPS proxy is in use. There may be connection problems."); -+ } -+ -+ dbg("trying https.getContent()"); -+ Object output = https.getContent(); -+ dbg("trying https.disconnect()"); -+ https.disconnect(); -+ if (! viewer.GET) { -+ String header = https.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (1), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ -+ } catch(Exception e) { -+ dbg("HttpsURLConnection: " + e.getMessage()); -+ } -+ -+ if (proxy_in_use) { -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } else if (trusturlCerts != null && !viewer.forceProxy) { -+ /* Allow user to require HTTP check? use forceProxy for now. */ -+ dbg("SKIPPING HTTP PROXY CHECK: got trusturlCerts, assuming proxy info is correct."); -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ return; -+ } -+ -+ /* -+ * XXX need to remember scenario where this extra check -+ * gives useful info. User's Browser proxy settings? -+ */ -+ dbg("TRYING HTTP:"); -+ ustr = "http://" + host + ":" + port; -+ ustr += viewer.urlPrefix + "/index.vnc"; -+ dbg("ustr is: " + ustr); -+ -+ try { -+ /* prepare for an HTTP URL connection to the same host:port (but not httpsPort) */ -+ URL url = new URL(ustr); -+ HttpURLConnection http = (HttpURLConnection) -+ url.openConnection(); -+ -+ http.setUseCaches(false); -+ http.setRequestMethod("GET"); -+ http.setRequestProperty("Pragma", "No-Cache"); -+ http.setRequestProperty("Proxy-Connection", "Keep-Alive"); -+ http.setDoInput(true); -+ -+ dbg("trying http.connect()"); -+ http.connect(); -+ -+ if (http.usingProxy()) { -+ proxy_in_use = true; -+ dbg("An HTTP proxy is in use. There may be connection problems."); -+ } -+ dbg("trying http.getContent()"); -+ Object output = http.getContent(); -+ dbg("trying http.disconnect()"); -+ http.disconnect(); -+ if (! viewer.GET) { -+ String header = http.getHeaderField("VNC-Server"); -+ if (header != null && header.startsWith("x11vnc")) { -+ dbg("detected x11vnc server (2), setting GET=1"); -+ viewer.GET = true; -+ } -+ } -+ } catch(Exception e) { -+ dbg("HttpURLConnection: " + e.getMessage()); -+ } -+ dbg("exit check_for_proxy_and_grab_vnc_server_cert():"); -+ dbg("------------------------------------------------"); -+ } -+ -+ public Socket connectSock() throws IOException { -+ /* -+ * first try a https connection to detect a proxy, and -+ * grab the VNC server cert at the same time: -+ */ -+ check_for_proxy_and_grab_vnc_server_cert(); -+ -+ boolean srv_cert = false; -+ -+ if (trustsrvCerts != null) { -+ /* applet parameter suppled serverCert */ -+ dbg("viewer.trustSrvCert-0 using trustsrv_ctx"); -+ factory = trustsrv_ctx.getSocketFactory(); -+ srv_cert = true; -+ } else if (viewer.trustAllVncCerts) { -+ /* trust all certs (no checking) */ -+ dbg("viewer.trustAllVncCerts-0 using trustall_ctx"); -+ factory = trustall_ctx.getSocketFactory(); -+ } else if (trusturlCerts != null) { -+ /* trust certs the Browser/JVM accepted in check_for_proxy... */ -+ dbg("using trusturl_ctx"); -+ factory = trusturl_ctx.getSocketFactory(); -+ } else { -+ /* trust the local defaults */ -+ dbg("using trustloc_ctx"); -+ factory = trustloc_ctx.getSocketFactory(); -+ } -+ -+ socket = null; -+ -+ try { -+ if (proxy_in_use && viewer.forceProxy) { -+ throw new Exception("forcing proxy (forceProxy)"); -+ } else if (viewer.CONNECT != null) { -+ throw new Exception("forcing CONNECT"); -+ } -+ -+ int timeout = 6; -+ if (timeout > 0) { -+ socket = (SSLSocket) factory.createSocket(); -+ InetSocketAddress inetaddr = new InetSocketAddress(host, port); -+ dbg("Using timeout of " + timeout + " secs to: " + host + ":" + port); -+ socket.connect(inetaddr, timeout * 1000); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ } catch (Exception esock) { -+ dbg("socket error: " + esock.getMessage()); -+ if (proxy_in_use || viewer.CONNECT != null) { -+ proxy_failure = true; -+ if (proxy_in_use) { -+ dbg("HTTPS proxy in use. Trying to go with it."); -+ } else { -+ dbg("viewer.CONNECT reverse proxy in use. Trying to go with it."); -+ } -+ try { -+ socket = proxy_socket(factory); -+ } catch (Exception e) { -+ dbg("proxy_socket error: " + e.getMessage()); -+ } -+ } else { -+ /* n.b. socket is left in error state to cause ex. below. */ -+ } -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The Server Connection Verified OK on 1st try."); -+ -+ java.security.cert.Certificate[] currentTrustedCerts; -+ BrowserCertsDialog bcd; -+ -+ SSLSession sess = socket.getSession(); -+ currentTrustedCerts = sess.getPeerCertificates(); -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-1 keeping socket."); -+ } else if (currentTrustedCerts == null || currentTrustedCerts.length < 1) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy."); -+ } -+ socket = null; -+ throw new SSLHandshakeException("no current certs"); -+ } -+ -+ String serv = ""; -+ try { -+ CertInfo ci = new CertInfo(currentTrustedCerts[0]); -+ serv = ci.get_certinfo("CN"); -+ } catch (Exception e) { -+ ; -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-2 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.serverCert != null && trustsrvCerts != null) { -+ dbg("viewer.serverCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else if (viewer.trustUrlVncCert) { -+ dbg("viewer.trustUrlVncCert-1 skipping browser certs dialog"); -+ user_wants_to_see_cert = false; -+ } else { -+ /* have a dialog with the user: */ -+ bcd = new BrowserCertsDialog(serv, host + ":" + port); -+ dbg("browser certs dialog begin."); -+ bcd.queryUser(); -+ dbg("browser certs dialog finished."); -+ -+ if (bcd.showCertDialog) { -+ String msg = "user wants to see cert"; -+ dbg(msg); -+ user_wants_to_see_cert = true; -+ if (cert_fail == null) { -+ cert_fail = "user-view"; -+ } -+ throw new SSLHandshakeException(msg); -+ } else { -+ user_wants_to_see_cert = false; -+ dbg("browser certs dialog: user said yes, accept it"); -+ } -+ } -+ -+ } catch (SSLHandshakeException eh) { -+ dbg("SSLHandshakeException: could not automatically verify Server."); -+ dbg("msg: " + eh.getMessage()); -+ -+ -+ /* send a cleanup string just in case: */ -+ String getoutstr = "GET /index.vnc HTTP/1.0\r\nConnection: close\r\n\r\n"; -+ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!"); -+ } -+ -+ /* reload */ -+ -+ socket = null; -+ -+ String reason = null; -+ -+ if (srv_cert) { -+ /* for serverCert usage we make this a fatal error. */ -+ throw new IOException("Fatal: VNC Server's Cert does not match Applet Parameter 'serverCert=...'"); -+ /* see below in TrustDialog were we describe this case to user anyway */ -+ } -+ -+ /* -+ * Reconnect, trusting any cert, so we can grab -+ * the cert to show it to the user in a dialog -+ * for him to manually accept. This connection -+ * is not used for anything else. -+ */ -+ factory = trustall_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ if (debug_certs) { -+ dbg("trusturlCerts: " + trusturlCerts); -+ dbg("trustsrvCerts: " + trustsrvCerts); -+ } -+ if (trusturlCerts == null && cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ -+ try { -+ socket.startHandshake(); -+ -+ dbg("The TrustAll Server Cert-grab Connection (trivially) Verified OK."); -+ -+ /* grab the cert: */ -+ try { -+ SSLSession sess = socket.getSession(); -+ trustallCerts = sess.getPeerCertificates(); -+ } catch (Exception e) { -+ throw new Exception("Could not get " + -+ "Peer Certificate"); -+ } -+ if (debug_certs) { -+ dbg("trustallCerts: " + trustallCerts); -+ } -+ -+ if (viewer.trustAllVncCerts) { -+ dbg("viewer.trustAllVncCerts-3. skipping dialog, trusting everything."); -+ } else if (! browser_cert_match()) { -+ /* -+ * close socket now, we will reopen after -+ * dialog if user agrees to use the cert. -+ */ -+ try { -+ OutputStream os = socket.getOutputStream(); -+ os.write(getoutstr.getBytes()); -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!"); -+ } -+ socket = null; -+ -+ /* dialog with user to accept cert or not: */ -+ -+ TrustDialog td= new TrustDialog(host, port, -+ trustallCerts); -+ -+ if (cert_fail == null) { -+ ; -+ } else if (cert_fail.equals("user-view")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " You Asked to View the Certificate."; -+ } else if (cert_fail.equals("server-cert-mismatch")) { -+ /* this is now fatal error, see above. */ -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Certificate\n" -+ + " specified in the supplied 'serverCert' Applet Parameter."; -+ } else if (cert_fail.equals("cert-mismatch")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " The VNC Server's Certificate does not match the Website's\n" -+ + " HTTPS Certificate (that you previously accepted; either\n" -+ + " manually or automatically via Certificate Authority.)"; -+ } else if (cert_fail.equals("missing-certs")) { -+ reason = "Reason for this Dialog:\n\n" -+ + " Not all Certificates could be obtained to check."; -+ } -+ -+ if (! td.queryUser(reason)) { -+ String msg = "User decided against it."; -+ dbg(msg); -+ throw new IOException(msg); -+ } -+ } -+ -+ } catch (Exception ehand2) { -+ dbg("** Could not TrustAll Verify Server!"); -+ -+ throw new IOException(ehand2.getMessage()); -+ } -+ -+ /* reload again: */ -+ -+ if (socket != null) { -+ try { -+ socket.close(); -+ } catch (Exception e) { -+ dbg("socket is grumpy!!!"); -+ } -+ socket = null; -+ } -+ -+ /* -+ * Now connect a 3rd time, using the cert -+ * retrieved during connection 2 (sadly, that -+ * the user likely blindly agreed to...) -+ */ -+ -+ factory = trustone_ctx.getSocketFactory(); -+ if (proxy_failure) { -+ socket = proxy_socket(factory); -+ } else { -+ socket = (SSLSocket) factory.createSocket(host, port); -+ } -+ -+ try { -+ socket.startHandshake(); -+ dbg("TrustAll/TrustOne Server Connection Verified #3."); -+ -+ } catch (Exception ehand3) { -+ dbg("** Could not TrustAll/TrustOne Verify Server #3."); -+ -+ throw new IOException(ehand3.getMessage()); -+ } -+ } -+ -+ /* we have socket (possibly null) at this point, so proceed: */ -+ -+ /* handle x11vnc GET=1, if applicable: */ -+ if (socket != null && viewer.GET) { -+ String str = "GET "; -+ str += viewer.urlPrefix; -+ str += "/request.https.vnc.connection"; -+ str += " HTTP/1.0\r\n"; -+ str += "Pragma: No-Cache\r\n"; -+ str += "\r\n"; -+ -+ System.out.println("sending: " + str); -+ OutputStream os = socket.getOutputStream(); -+ String type = "os"; -+ -+ if (type == "os") { -+ os.write(str.getBytes()); -+ os.flush(); -+ System.out.println("used OutputStream"); -+ } else if (type == "bs") { -+ BufferedOutputStream bs = new BufferedOutputStream(os); -+ bs.write(str.getBytes()); -+ bs.flush(); -+ System.out.println("used BufferedOutputStream"); -+ } else if (type == "ds") { -+ DataOutputStream ds = new DataOutputStream(os); -+ ds.write(str.getBytes()); -+ ds.flush(); -+ System.out.println("used DataOutputStream"); -+ } -+ if (false) { -+ String rep = ""; -+ DataInputStream is = new DataInputStream( -+ new BufferedInputStream(socket.getInputStream(), 16384)); -+ while (true) { -+ rep += readline(is); -+ if (rep.indexOf("\r\n\r\n") >= 0) { -+ break; -+ } -+ } -+ System.out.println("rep: " + rep); -+ } -+ } -+ -+ dbg("SSL returning socket to caller."); -+ dbg(""); -+ -+ /* could be null, let caller handle that. */ -+ return (Socket) socket; -+ } -+ -+ boolean browser_cert_match() { -+ String msg = "Browser URL accept previously accepted cert"; -+ -+ if (user_wants_to_see_cert) { -+ return false; -+ } -+ -+ if (viewer.serverCert != null || trustsrvCerts != null) { -+ if (cert_fail == null) { -+ cert_fail = "server-cert-mismatch"; -+ } -+ } -+ if (trustallCerts != null && trusturlCerts != null) { -+ if (trustallCerts.length == trusturlCerts.length) { -+ boolean ok = true; -+ /* check toath trustallCerts (socket) equals trusturlCerts (browser) */ -+ for (int i = 0; i < trusturlCerts.length; i++) { -+ if (! trustallCerts[i].equals(trusturlCerts[i])) { -+ dbg("BCM: cert mismatch at i=" + i); -+ dbg("BCM: cert mismatch url" + trusturlCerts[i]); -+ dbg("BCM: cert mismatch all" + trustallCerts[i]); -+ ok = false; -+ } -+ } -+ if (ok) { -+ System.out.println(msg); -+ if (cert_fail == null) { -+ cert_fail = "did-not-fail"; -+ } -+ return true; -+ } else { -+ if (cert_fail == null) { -+ cert_fail = "cert-mismatch"; -+ } -+ return false; -+ } -+ } -+ } -+ if (cert_fail == null) { -+ cert_fail = "missing-certs"; -+ } -+ return false; -+ } -+ -+ private void dbg(String s) { -+ if (debug) { -+ System.out.println(s); -+ } -+ } -+ -+ private int gint(String s) { -+ int n = -1; -+ try { -+ Integer I = new Integer(s); -+ n = I.intValue(); -+ } catch (Exception ex) { -+ return -1; -+ } -+ return n; -+ } -+ -+ /* this will do the proxy CONNECT negotiation and hook us up. */ -+ -+ 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); -+ -+ /* we loop here a few times trying for the password case */ -+ for (int k=0; k < 2; k++) { -+ dbg("proxy_in_use psocket: " + k); -+ -+ if (proxySock != null) { -+ try { -+ proxySock.close(); -+ } catch (Exception e) { -+ dbg("proxy socket is grumpy."); -+ } -+ } -+ -+ 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 via proxy: " + 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("some proxy socket problem: " + e.getMessage()); -+ } -+ -+ /* read the rest of the HTTP headers */ -+ 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("")) { -+ /* we only try once for the non-password case: */ -+ break; -+ } -+ } -+ } -+ -+ public SSLSocket proxy_socket(SSLSocketFactory factory) { -+ Properties props = null; -+ String proxyHost = null; -+ int proxyPort = 0; -+ String proxyHost_nossl = null; -+ int proxyPort_nossl = 0; -+ String str; -+ -+ /* see if we can guess the proxy info from Properties: */ -+ try { -+ props = System.getProperties(); -+ } catch (Exception e) { -+ /* sandboxed applet might not be able to read it. */ -+ dbg("props failed: " + e.getMessage()); -+ } -+ if (viewer.proxyHost != null) { -+ dbg("Using supplied proxy " + viewer.proxyHost + " " + viewer.proxyPort + " applet parameters."); -+ proxyHost = viewer.proxyHost; -+ if (viewer.proxyPort != null) { -+ proxyPort = gint(viewer.proxyPort); -+ } else { -+ proxyPort = 8080; -+ } -+ -+ } else if (props != null) { -+ dbg("\n---------------\nAll props:"); -+ props.list(System.out); -+ dbg("\n---------------\n\n"); -+ -+ /* scrape throught properties looking for proxy info: */ -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (s2.indexOf("proxy.https.host") >= 0) { -+ proxyHost = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.https.port") >= 0) { -+ proxyPort = gint(v2); -+ continue; -+ } -+ if (s2.indexOf("proxy.http.host") >= 0) { -+ proxyHost_nossl = v2; -+ continue; -+ } -+ if (s2.indexOf("proxy.http.port") >= 0) { -+ proxyPort_nossl = gint(v2); -+ continue; -+ } -+ } -+ -+ for (Enumeration e = props.propertyNames(); e.hasMoreElements(); ) { -+ String s = (String) e.nextElement(); -+ String v = System.getProperty(s); -+ String s2 = s.toLowerCase(); -+ String v2 = v.toLowerCase(); -+ -+ if (proxyHost != null && proxyPort > 0) { -+ break; -+ } -+ -+ // look for something like: javaplugin.proxy.config.list = http=10.0.2.1:8082 -+ if (s2.indexOf("proxy") < 0 && v2.indexOf("proxy") < 0) { -+ continue; -+ } -+ if (v2.indexOf("http") < 0) { -+ continue; -+ } -+ -+ String[] pieces = v.split("[,;]"); -+ for (int i = 0; i < pieces.length; i++) { -+ String p = pieces[i]; -+ int j = p.indexOf("https"); -+ if (j < 0) { -+ j = p.indexOf("http"); -+ if (j < 0) { -+ continue; -+ } -+ } -+ j = p.indexOf("=", j); -+ if (j < 0) { -+ continue; -+ } -+ p = p.substring(j+1); -+ String [] hp = p.split(":"); -+ if (hp.length != 2) { -+ continue; -+ } -+ if (hp[0].length() > 1 && hp[1].length() > 1) { -+ -+ proxyPort = gint(hp[1]); -+ if (proxyPort < 0) { -+ continue; -+ } -+ proxyHost = new String(hp[0]); -+ break; -+ } -+ } -+ } -+ } -+ if (proxyHost != null) { -+ if (proxyHost_nossl != null && proxyPort_nossl > 0) { -+ dbg("Using http proxy info instead of https."); -+ proxyHost = proxyHost_nossl; -+ proxyPort = proxyPort_nossl; -+ } -+ } -+ -+ if (proxy_in_use) { -+ if (proxy_dialog_host != null && proxy_dialog_port > 0) { -+ proxyHost = proxy_dialog_host; -+ proxyPort = proxy_dialog_port; -+ } -+ if (proxyHost != null) { -+ dbg("Lucky us! we figured out the Proxy parameters: " + proxyHost + " " + proxyPort); -+ } else { -+ /* ask user to help us: */ -+ ProxyDialog pd = new ProxyDialog(proxyHost, proxyPort); -+ pd.queryUser(); -+ proxyHost = pd.getHost(); -+ proxyPort = pd.getPort(); -+ proxy_dialog_host = new String(proxyHost); -+ proxy_dialog_port = proxyPort; -+ dbg("User said host: " + pd.getHost() + " port: " + pd.getPort()); -+ } -+ -+ proxy_helper(proxyHost, proxyPort); -+ if (proxySock == null) { -+ return null; -+ } -+ } else if (viewer.CONNECT != null) { -+ dbg("viewer.CONNECT psocket:"); -+ proxySock = psocket(host, port); -+ if (proxySock == null) { -+ dbg("1-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ -+ if (viewer.CONNECT != null) { -+ String hp = viewer.CONNECT; -+ String req2 = "CONNECT " + hp + " HTTP/1.1\r\n" -+ + "Host: " + hp + "\r\n\r\n"; -+ -+ dbg("requesting2: " + req2); -+ -+ try { -+ proxy_os.write(req2.getBytes()); -+ String reply = readline(proxy_is); -+ -+ dbg("proxy replied2: " + reply.trim()); -+ -+ if (reply.indexOf("HTTP/1.") < 0 && reply.indexOf(" 200") < 0) { -+ proxySock.close(); -+ proxySock = psocket(proxyHost, proxyPort); -+ if (proxySock == null) { -+ dbg("2-b sadly, returning a null socket"); -+ return null; -+ } -+ } -+ } catch(Exception e) { -+ dbg("proxy socket problem-2: " + e.getMessage()); -+ } -+ -+ while (true) { -+ String line = readline(proxy_is); -+ dbg("proxy line2: " + line.trim()); -+ if (line.equals("\r\n") || line.equals("\n")) { -+ break; -+ } -+ } -+ } -+ -+ Socket sslsock = null; -+ try { -+ sslsock = factory.createSocket(proxySock, host, port, true); -+ } catch(Exception e) { -+ dbg("sslsock prob: " + e.getMessage()); -+ dbg("3 sadly, returning a null socket"); -+ } -+ -+ return (SSLSocket) sslsock; -+ } -+ -+ Socket psocket(String h, int p) { -+ Socket psock = null; -+ try { -+ psock = new Socket(h, p); -+ proxy_is = new DataInputStream(new BufferedInputStream( -+ psock.getInputStream(), 16384)); -+ proxy_os = psock.getOutputStream(); -+ } catch(Exception e) { -+ dbg("psocket prob: " + e.getMessage()); -+ return null; -+ } -+ -+ return psock; -+ } -+ -+ String readline(DataInputStream i) { -+ byte[] ba = new byte[1]; -+ String s = new String(""); -+ ba[0] = 0; -+ try { -+ while (ba[0] != 0xa) { -+ ba[0] = (byte) i.readUnsignedByte(); -+ s += new String(ba); -+ } -+ } catch (Exception e) { -+ ; -+ } -+ return s; -+ } -+} -+ -+class TrustDialog implements ActionListener { -+ String msg, host, text; -+ int port; -+ java.security.cert.Certificate[] trustallCerts = null; -+ boolean viewing_cert = false; -+ boolean trust_this_session = false; -+ -+ /* -+ * 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, cancel, viewcert; -+ TextArea textarea; -+ Checkbox accept, deny; -+ Dialog dialog; -+ -+ String s1 = "Accept this certificate temporarily for this session"; -+ String s2 = "Do not accept this certificate and do not connect to" -+ + " this VNC server"; -+ String ln = "\n---------------------------------------------------\n\n"; -+ -+ TrustDialog (String h, int p, java.security.cert.Certificate[] s) { -+ host = h; -+ port = p; -+ trustallCerts = s; -+ -+ msg = "VNC Server " + host + ":" + port + " Not Verified"; -+ } -+ -+ public boolean queryUser(String reason) { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame(msg); -+ -+ dialog = new Dialog(frame, true); -+ -+ String infostr = ""; -+ if (trustallCerts.length == 1) { -+ CertInfo ci = new CertInfo(trustallCerts[0]); -+ infostr = ci.get_certinfo("all"); -+ } -+ if (reason != null) { -+ reason += "\n\n"; -+ } -+ -+ text = "\n" -++ "Unable to verify the identity of\n" -++ "\n" -++ " " + host + ":" + port + "\n" -++ "\n" -++ infostr -++ "\n" -++ "as a trusted VNC server.\n" -++ "\n" -++ reason -++ "In General not being able to verify the VNC Server and/or your seeing this Dialog\n" -++ "is due to one of the following:\n" -++ "\n" -++ " - Your requesting to View the Certificate before accepting.\n" -++ "\n" -++ " - The VNC server is using a Self-Signed Certificate or a Certificate\n" -++ " Authority not recognized by your Web Browser or Java Plugin runtime.\n" -++ "\n" -++ " - The use of an Apache SSL portal scheme employing CONNECT proxying AND\n" -++ " the Apache Web server has a certificate *different* from the VNC server's.\n" -++ "\n" -++ " - No previously accepted Certificate (via Web Broswer/Java Plugin) could be\n" -++ " obtained by this applet to compare the VNC Server Certificate against.\n" -++ "\n" -++ " - The VNC Server's Certificate does not match the one specified in the\n" -++ " supplied 'serverCert' Java Applet Parameter.\n" -++ "\n" -++ " - A Man-In-The-Middle attack impersonating as the VNC server that you wish\n" -++ " to connect to. (Wouldn't that be exciting!!)\n" -++ "\n" -++ "By safely copying the VNC server's Certificate (or using a common Certificate\n" -++ "Authority certificate) you can configure your Web Browser and Java Plugin to\n" -++ "automatically authenticate this VNC Server.\n" -++ "\n" -++ "If you do so, then you will only have to click \"Yes\" when this VNC Viewer\n" -++ "applet asks you whether to trust your Browser/Java Plugin's acceptance of the\n" -++ "certificate (except for the Apache portal case above where they don't match.)\n" -++ "\n" -++ "You can also set the applet parameter 'trustUrlVncCert=yes' to automatically\n" -++ "accept certificates already accepted/trusted by your Web Browser/Java Plugin,\n" -++ "and thereby see no dialog from this VNC Viewer applet.\n" -+; -+ -+ /* the accept / do-not-accept radio buttons: */ -+ CheckboxGroup checkbox = new CheckboxGroup(); -+ accept = new Checkbox(s1, true, checkbox); -+ deny = new Checkbox(s2, false, checkbox); -+ -+ /* put the checkboxes in a panel: */ -+ Panel check = new Panel(); -+ check.setLayout(new GridLayout(2, 1)); -+ -+ check.add(accept); -+ check.add(deny); -+ -+ /* make the 3 buttons: */ -+ ok = new Button("OK"); -+ cancel = new Button("Cancel"); -+ viewcert = new Button("View Certificate"); -+ -+ ok.addActionListener(this); -+ cancel.addActionListener(this); -+ viewcert.addActionListener(this); -+ -+ /* put the buttons in their own panel: */ -+ Panel buttonrow = new Panel(); -+ buttonrow.setLayout(new FlowLayout(FlowLayout.LEFT)); -+ buttonrow.add(viewcert); -+ buttonrow.add(ok); -+ buttonrow.add(cancel); -+ -+ /* label at the top: */ -+ Label label = new Label(msg, Label.CENTER); -+ label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ -+ /* textarea in the middle */ -+ textarea = new TextArea(text, 38, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ -+ /* put the two panels in their own panel at bottom: */ -+ Panel bot = new Panel(); -+ bot.setLayout(new GridLayout(2, 1)); -+ bot.add(check); -+ bot.add(buttonrow); -+ -+ /* now arrange things inside the dialog: */ -+ dialog.setLayout(new BorderLayout()); -+ -+ dialog.add("North", label); -+ dialog.add("South", bot); -+ dialog.add("Center", textarea); -+ -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ -+ return trust_this_session; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ -+ if (evt.getSource() == viewcert) { -+ /* View Certificate button clicked */ -+ if (viewing_cert) { -+ /* show the original info text: */ -+ textarea.setText(text); -+ viewcert.setLabel("View Certificate"); -+ viewing_cert = false; -+ } else { -+ int i; -+ /* show all (likely just one) certs: */ -+ textarea.setText(""); -+ for (i=0; i < trustallCerts.length; i++) { -+ int j = i + 1; -+ textarea.append("Certificate[" + -+ j + "]\n\n"); -+ textarea.append( -+ trustallCerts[i].toString()); -+ textarea.append(ln); -+ } -+ viewcert.setLabel("View Info"); -+ viewing_cert = true; -+ -+ textarea.setCaretPosition(0); -+ } -+ -+ } else if (evt.getSource() == ok) { -+ /* OK button clicked */ -+ if (accept.getState()) { -+ trust_this_session = true; -+ } else { -+ trust_this_session = false; -+ } -+ //dialog.dispose(); -+ dialog.hide(); -+ -+ } else if (evt.getSource() == cancel) { -+ /* Cancel button clicked */ -+ trust_this_session = false; -+ -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+ -+ String get_certinfo() { -+ String all = ""; -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ int i; -+ if (trustallCerts.length < 1) { -+ all = ""; -+ return all; -+ } -+ String cert = trustallCerts[0].toString(); -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cert.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cert.indexOf(", ", f); -+ t2 = cert.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cert.substring(f, t); -+ all = all + " " + sub + "\n"; -+ } -+ } -+ } -+ return all; -+ } -+} -+ -+class ProxyDialog implements ActionListener { -+ String guessedHost = null; -+ String guessedPort = 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 entry; -+ String reply = ""; -+ -+ ProxyDialog (String h, int p) { -+ guessedHost = h; -+ try { -+ guessedPort = Integer.toString(p); -+ } catch (Exception e) { -+ guessedPort = "8080"; -+ } -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Need Proxy host:port"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter your https Proxy info as host:port", Label.CENTER); -+ //label.setFont(new Font("Helvetica", Font.BOLD, 16)); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ String guess = ""; -+ if (guessedHost != null) { -+ guess = guessedHost + ":" + guessedPort; -+ } -+ entry.setText(guess); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return; -+ } -+ -+ public String getHost() { -+ int i = reply.indexOf(":"); -+ if (i < 0) { -+ return "unknown"; -+ } -+ String h = reply.substring(0, i); -+ return h; -+ } -+ -+ public int getPort() { -+ int i = reply.indexOf(":"); -+ int p = 8080; -+ if (i < 0) { -+ return p; -+ } -+ i++; -+ String ps = reply.substring(i); -+ try { -+ Integer I = new Integer(ps); -+ p = I.intValue(); -+ } catch (Exception e) { -+ ; -+ } -+ return p; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+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; -+ Dialog dialog; -+ TextField entry; -+ String reply = ""; -+ -+ ClientCertDialog() { -+ ; -+ } -+ -+ public String queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Enter SSL Client Cert+Key String"); -+ -+ dialog = new Dialog(frame, true); -+ -+ -+ Label label = new Label("Please Enter the SSL Client Cert+Key String 308204c0...,...522d2d0a", Label.CENTER); -+ entry = new TextField(30); -+ ok = new Button("OK"); -+ ok.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", label); -+ dialog.add("Center", entry); -+ dialog.add("South", ok); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til OK or Cancel pressed. */ -+ return reply; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == ok) { -+ reply = entry.getText(); -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ } -+} -+ -+class BrowserCertsDialog implements ActionListener { -+ Button yes, no; -+ Dialog dialog; -+ String vncServer; -+ String hostport; -+ public boolean showCertDialog = true; -+ -+ BrowserCertsDialog(String serv, String hp) { -+ vncServer = serv; -+ hostport = hp; -+ } -+ -+ public void queryUser() { -+ -+ /* create and display the dialog for unverified cert. */ -+ -+ Frame frame = new Frame("Use Browser/JVM Certs?"); -+ -+ dialog = new Dialog(frame, true); -+ -+ String m = ""; -+m += "\n"; -+m += "This VNC Viewer applet does not have its own keystore to track\n"; -+m += "SSL certificates, and so cannot authenticate the certificate\n"; -+m += "of the VNC Server:\n"; -+m += "\n"; -+m += " " + hostport + "\n\n " + vncServer + "\n"; -+m += "\n"; -+m += "on its own.\n"; -+m += "\n"; -+m += "However, it has noticed that your Web Browser and/or Java VM Plugin\n"; -+m += "has previously accepted the same certificate. You may have set\n"; -+m += "this up permanently or just for this session, or the server\n"; -+m += "certificate was signed by a CA cert that your Web Browser or\n"; -+m += "Java VM Plugin has.\n"; -+m += "\n"; -+m += "If the VNC Server connection times out while you are reading this\n"; -+m += "dialog, then restart the connection and try again.\n"; -+m += "\n"; -+m += "Should this VNC Viewer applet now connect to the above VNC server?\n"; -+m += "\n"; -+ -+ TextArea textarea = new TextArea(m, 22, 64, -+ TextArea.SCROLLBARS_VERTICAL_ONLY); -+ textarea.setEditable(false); -+ yes = new Button("Yes"); -+ yes.addActionListener(this); -+ no = new Button("No, Let Me See the Certificate."); -+ no.addActionListener(this); -+ -+ dialog.setLayout(new BorderLayout()); -+ dialog.add("North", textarea); -+ dialog.add("Center", yes); -+ dialog.add("South", no); -+ dialog.pack(); -+ dialog.resize(dialog.preferredSize()); -+ -+ dialog.show(); /* block here til Yes or No pressed. */ -+ System.out.println("done show()"); -+ return; -+ } -+ -+ public synchronized void actionPerformed(ActionEvent evt) { -+ System.out.println(evt.getActionCommand()); -+ if (evt.getSource() == yes) { -+ showCertDialog = false; -+ //dialog.dispose(); -+ dialog.hide(); -+ } else if (evt.getSource() == no) { -+ showCertDialog = true; -+ //dialog.dispose(); -+ dialog.hide(); -+ } -+ System.out.println("done actionPerformed()"); -+ } -+} -+ -+class CertInfo { -+ String fields[] = {"CN", "OU", "O", "L", "C"}; -+ java.security.cert.Certificate cert; -+ String certString = ""; -+ -+ CertInfo(java.security.cert.Certificate c) { -+ cert = c; -+ certString = cert.toString(); -+ } -+ -+ String get_certinfo(String which) { -+ int i; -+ String cs = new String(certString); -+ String all = ""; -+ -+ /* -+ * For now we simply scrape the cert string, there must -+ * be an API for this... perhaps optionValue? -+ */ -+ for (i=0; i < fields.length; i++) { -+ int f, t, t1, t2; -+ String sub, mat = fields[i] + "="; -+ -+ f = cs.indexOf(mat, 0); -+ if (f > 0) { -+ t1 = cs.indexOf(", ", f); -+ t2 = cs.indexOf("\n", f); -+ if (t1 < 0 && t2 < 0) { -+ continue; -+ } else if (t1 < 0) { -+ t = t2; -+ } else if (t2 < 0) { -+ t = t1; -+ } else if (t1 < t2) { -+ t = t1; -+ } else { -+ t = t2; -+ } -+ if (t > f) { -+ sub = cs.substring(f, t); -+ all = all + " " + sub + "\n"; -+ if (which.equals(fields[i])) { -+ return sub; -+ } -+ } -+ } -+ } -+ if (which.equals("all")) { -+ return all; -+ } else { -+ return ""; -+ } -+ } -+} -+ -+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) - { - viewer.options.oldEightBitColors = viewer.options.eightBitColors; -@@ -237,6 +265,9 @@ - } - else - { -+// begin runge/x11vnc -+ viewer.options.oldEightBitColors = viewer.options.eightBitColors; -+// end runge/x11vnc - rfb.writeSetPixelFormat( - 32, - 24, -@@ -376,12 +407,14 @@ - // Start/stop session recording if necessary. - viewer.checkRecordingStatus(); - -- rfb.writeFramebufferUpdateRequest( -- 0, -- 0, -- rfb.framebufferWidth, -- rfb.framebufferHeight, -- false); -+ if (!viewer.graftFtp) { -+ rfb.writeFramebufferUpdateRequest( -+ 0, -+ 0, -+ rfb.framebufferWidth, -+ rfb.framebufferHeight, -+ false); -+ } - - // - // main dispatch loop -@@ -390,6 +423,9 @@ - while (true) { - // Read message type from the server. - int msgType = rfb.readServerMessageType(); -+ if (viewer.ftpOnly && msgType != RfbProto.rfbFileTransfer) { -+ System.out.println("msgType:" + msgType); -+ } - - // Process the message depending on its type. - switch (msgType) { -@@ -1332,6 +1368,9 @@ - public void mouseDragged(MouseEvent evt) { - processLocalMouseEvent(evt, true); - } -+ public void mouseWheelMoved(MouseWheelEvent evt) { -+ processLocalMouseWheelEvent(evt); -+ } - - public void processLocalKeyEvent(KeyEvent evt) { - if (viewer.rfb != null && rfb.inNormalProtocol) { -@@ -1367,6 +1406,19 @@ - evt.consume(); - } - -+ public void processLocalMouseWheelEvent(MouseWheelEvent evt) { -+ if (viewer.rfb != null && rfb.inNormalProtocol) { -+ synchronized(rfb) { -+ try { -+ rfb.writeWheelEvent(evt); -+ } catch (Exception e) { -+ e.printStackTrace(); -+ } -+ rfb.notify(); -+ } -+ } -+ } -+ - public void processLocalMouseEvent(MouseEvent evt, boolean moved) { - if (viewer.rfb != null && rfb.inNormalProtocol) { - if (moved) { -@@ -1532,9 +1584,14 @@ - else - { - result = -- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -- << 16 | (pixBuf[i * 4 + 2] & 0xFF) -- << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+// begin runge/x11vnc -+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -+// << 16 | (pixBuf[i * 4 + 2] & 0xFF) -+// << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) -+ << 16 | (pixBuf[i * 4 + 1] & 0xFF) -+ << 8 | (pixBuf[i * 4 + 0] & 0xFF); -+// end runge/x11vnc - } - } else { - result = 0; // Transparent pixel -@@ -1565,9 +1622,14 @@ - else - { - result = -- 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -- << 16 | (pixBuf[i * 4 + 2] & 0xFF) -- << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+// begin runge/x11vnc -+// 0xFF000000 | (pixBuf[i * 4 + 1] & 0xFF) -+// << 16 | (pixBuf[i * 4 + 2] & 0xFF) -+// << 8 | (pixBuf[i * 4 + 3] & 0xFF); -+ 0xFF000000 | (pixBuf[i * 4 + 2] & 0xFF) -+ << 16 | (pixBuf[i * 4 + 1] & 0xFF) -+ << 8 | (pixBuf[i * 4 + 0] & 0xFF); -+// end runge/x11vnc - } - } else { - result = 0; // Transparent pixel -diff -Naur JavaViewer.orig/VncViewer.java JavaViewer/VncViewer.java ---- JavaViewer.orig/VncViewer.java 2006-05-24 15:14:40.000000000 -0400 -+++ JavaViewer/VncViewer.java 2010-03-27 18:00:28.000000000 -0400 -@@ -41,6 +41,7 @@ - import java.io.*; - import java.net.*; - import javax.swing.*; -+import java.util.Date; - - public class VncViewer extends java.applet.Applet - implements java.lang.Runnable, WindowListener { -@@ -80,11 +81,11 @@ - GridBagLayout gridbag; - ButtonPanel buttonPanel; - AuthPanel authenticator; -- VncCanvas vc; -+ VncCanvas vc = null; - OptionsFrame options; - ClipboardFrame clipboard; - RecordingFrame rec; -- FTPFrame ftp; // KMC: FTP Frame declaration -+ FTPFrame ftp = null; // KMC: FTP Frame declaration - - // Control session recording. - Object recordingSync; -@@ -96,7 +97,7 @@ - - // Variables read from parameter values. - String host; -- int port; -+ int port, vncserverport; - String passwordParam; - String encPasswordParam; - boolean showControls; -@@ -115,28 +116,75 @@ - int i; - // mslogon support 2 end - -+// begin runge/x11vnc -+boolean disableSSL; -+boolean GET; -+String CONNECT; -+String urlPrefix; -+String httpsPort; -+String oneTimeKey; -+String serverCert; -+String ftpDropDown; -+String proxyHost; -+String proxyPort; -+boolean forceProxy; -+boolean ignoreProxy; -+boolean trustAllVncCerts; -+boolean trustUrlVncCert; -+boolean debugCerts; -+boolean debugKeyboard; -+boolean mapF5_to_atsign; -+boolean forbid_Ctrl_Alt; -+ -+boolean ignoreMSLogonCheck; -+boolean delayAuthPanel; -+boolean ftpOnly; -+boolean graftFtp; -+boolean dsmActive; -+ -+boolean gotAuth; -+int authGot; -+// end runge/x11vnc -+ -+ - // - // init() - // - -+public void ftp_init() { -+ boolean show = false; -+ if (ftp != null) { -+ show = true; -+ } -+ ftp = null; -+ -+ ftp = new FTPFrame(this); // KMC: FTPFrame creation -+ -+ if (show) { -+ ftp.doOpen(); -+ rfb.readServerDriveList(); -+ } -+} -+ - public void init() { - - readParameters(); - - if (inSeparateFrame) { -- vncFrame = new Frame("Ultr@VNC"); -- if (!inAnApplet) { -- vncFrame.add("Center", this); -- } -- vncContainer = vncFrame; -+ vncFrame = new Frame("Ultr@VNC"); -+ if (!inAnApplet) { -+ vncFrame.add("Center", this); -+ } -+ vncContainer = vncFrame; - } else { -- vncContainer = this; -+ vncContainer = this; - } - - recordingSync = new Object(); - - options = new OptionsFrame(this); - clipboard = new ClipboardFrame(this); -+ - // authenticator = new AuthPanel(false); // mslogon support : go to connectAndAuthenticate() - if (RecordingFrame.checkSecurity()) - rec = new RecordingFrame(this); -@@ -147,10 +195,11 @@ - cursorUpdatesDef = null; - eightBitColorsDef = null; - -- if (inSeparateFrame) -+ if (inSeparateFrame && vncFrame != null) - vncFrame.addWindowListener(this); - -- ftp = new FTPFrame(this); // KMC: FTPFrame creation -+ ftp_init(); -+ - rfbThread = new Thread(this); - rfbThread.start(); - } -@@ -186,6 +235,30 @@ - gbc.weightx = 1.0; - gbc.weighty = 1.0; - -+ if (ftpOnly) { -+ if (showControls) { -+ buttonPanel.enableButtons(); -+ } -+ ActionListener taskPerformer = new ActionListener() { -+ public void actionPerformed(ActionEvent evt) { -+ vncFrame.setVisible(false); -+ ftp.setSavedLocations(); -+ if (ftp.isVisible()) { -+ ftp.doClose(); -+ } else { -+ ftp.doOpen(); -+ } -+ rfb.readServerDriveList(); -+ } -+ }; -+ Timer t = new Timer(300, taskPerformer); -+ t.setRepeats(false); -+ t.start(); -+ -+ vc.processNormalProtocol(); -+ return; -+ } -+ - // Add ScrollPanel to applet mode - - // Create a panel which itself is resizeable and can hold -@@ -286,6 +359,24 @@ - - void connectAndAuthenticate() throws Exception { - -+ if (graftFtp) { -+ rfb = new RfbProto(host, port, this); -+ rfb.desktopName = "ftponly"; -+ rfb.framebufferWidth = 12; -+ rfb.framebufferHeight = 12; -+ rfb.bitsPerPixel = 32; -+ rfb.depth = 24; -+ rfb.trueColour = true; -+ rfb.redMax = 255; -+ rfb.greenMax = 255; -+ rfb.blueMax = 255; -+ rfb.redShift = 16; -+ rfb.greenShift = 8; -+ rfb.blueShift = 0; -+ rfb.inNormalProtocol = true; -+ return; -+ } -+ - // If "ENCPASSWORD" parameter is set, decrypt the password into - // the passwordParam string. - -@@ -336,7 +427,22 @@ - // - - -- prologueDetectAuthProtocol() ; -+// begin runge/x11vnc -+ gotAuth = false; -+ if (delayAuthPanel) { -+ if (tryAuthenticate(null, null)) { -+ if (inSeparateFrame) { -+ vncFrame.pack(); -+ vncFrame.show(); -+ } -+ return; -+ } -+ } -+// prologueDetectAuthProtocol() ; -+ if (ignoreMSLogonCheck == false) { -+ prologueDetectAuthProtocol() ; -+ } -+// end runge/x11vnc - - authenticator = new AuthPanel(mslogon); - -@@ -371,6 +477,7 @@ - //mslogon support end - } - -+ int tries = 0; - while (true) { - // Wait for user entering a password, or a username and a password - synchronized(authenticator) { -@@ -390,6 +497,13 @@ - break; - //mslogon support end - -+// begin runge/x11vnc -+ gotAuth = false; -+ if (++tries > 2) { -+ throw new Exception("Incorrect password entered " + tries + " times."); -+ } -+// end runge/x11vnc -+ - // Retry on authentication failure. - authenticator.retry(); - } -@@ -405,9 +519,11 @@ - - void prologueDetectAuthProtocol() throws Exception { - -- rfb = new RfbProto(host, port, this); -+ if (!gotAuth) { -+ rfb = new RfbProto(host, port, this); - -- rfb.readVersionMsg(); -+ rfb.readVersionMsg(); -+ } - - System.out.println("RFB server supports protocol version " + - rfb.serverMajor + "." + rfb.serverMinor); -@@ -431,16 +547,36 @@ - - boolean tryAuthenticate(String us, String pw) throws Exception { - -- rfb = new RfbProto(host, port, this); -+ int authScheme; - -- rfb.readVersionMsg(); -+ if (!gotAuth) { -+ rfb = new RfbProto(host, port, this); - -- System.out.println("RFB server supports protocol version " + -- rfb.serverMajor + "." + rfb.serverMinor); -+ rfb.readVersionMsg(); - -- rfb.writeVersionMsg(); -+ System.out.println("RFB server supports protocol version: " + -+ rfb.serverMajor + "." + rfb.serverMinor); - -- int authScheme = rfb.readAuthScheme(); -+ rfb.writeVersionMsg(); -+ -+ authScheme = rfb.readAuthScheme(); -+ -+ gotAuth = true; -+ authGot = authScheme; -+ } else { -+ authScheme = authGot; -+ } -+// begin runge/x11vnc -+ if (delayAuthPanel && pw == null) { -+ if (authScheme == RfbProto.NoAuth) { -+ System.out.println("No authentication needed"); -+ return true; -+ } else { -+ return false; -+ } -+ } -+System.out.println("as: " + authScheme); -+// end runge/x11vnc - - switch (authScheme) { - -@@ -629,6 +765,10 @@ - - void doProtocolInitialisation() throws IOException { - -+ if (graftFtp) { -+ return; -+ } -+ - rfb.writeClientInit(); - - rfb.readServerInit(); -@@ -774,9 +914,28 @@ - fatalError("HOST parameter not specified"); - } - } -+ Date d = new Date(); -+ System.out.println("-\nSSL VNC Java Applet starting. " + d); - -- String str = readParameter("PORT", true); -- port = Integer.parseInt(str); -+ port = 0; -+ String str = readParameter("PORT", false); -+ if (str != null) { -+ port = Integer.parseInt(str); -+ } -+ // When there is a proxy VNCSERVERPORT may be inaccessible (inside firewall). -+ vncserverport = 0; -+ str = readParameter("VNCSERVERPORT", false); -+ if (str != null) { -+ vncserverport = Integer.parseInt(str); -+ } -+ if (port == 0 && vncserverport == 0) { -+ fatalError("Neither PORT nor VNCSERVERPORT parameters specified"); -+ } -+ if (port == 0) { -+ // Nevertheless, fall back to vncserverport if we have to. -+ System.out.println("using vncserverport: '" + vncserverport + "' for PORT."); -+ port = vncserverport; -+ } - - if (inAnApplet) { - str = readParameter("Open New Window", false); -@@ -804,6 +963,158 @@ - deferScreenUpdates = readIntParameter("Defer screen updates", 20); - deferCursorUpdates = readIntParameter("Defer cursor updates", 10); - deferUpdateRequests = readIntParameter("Defer update requests", 50); -+ -+// begin runge/x11vnc -+ // SSL -+ disableSSL = false; -+ str = readParameter("DisableSSL", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) -+ disableSSL = true; -+ -+ httpsPort = readParameter("httpsPort", false); -+ -+ // Extra GET, CONNECT string: -+ CONNECT = readParameter("CONNECT", false); -+ if (CONNECT != null) { -+ CONNECT = CONNECT.replaceAll(" ", ":"); -+ } -+ -+ GET = false; -+ str = readParameter("GET", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ GET = true; -+ } -+ if (str != null && str.equalsIgnoreCase("1")) { -+ GET = true; -+ } -+ -+ urlPrefix = readParameter("urlPrefix", false); -+ if (urlPrefix != null) { -+ urlPrefix = urlPrefix.replaceAll("%2F", "/"); -+ urlPrefix = urlPrefix.replaceAll("%2f", "/"); -+ urlPrefix = urlPrefix.replaceAll("_2F_", "/"); -+ if (urlPrefix.indexOf("/") != 0) { -+ urlPrefix = "/" + urlPrefix; -+ } -+ } else { -+ urlPrefix = ""; -+ } -+ System.out.println("urlPrefix: '" + urlPrefix + "'"); -+ -+ ftpDropDown = readParameter("ftpDropDown", false); -+ if (ftpDropDown != null) { -+ ftpDropDown = ftpDropDown.replaceAll("%2F", "/"); -+ ftpDropDown = ftpDropDown.replaceAll("%2f", "/"); -+ ftpDropDown = ftpDropDown.replaceAll("_2F_", "/"); -+ ftpDropDown = ftpDropDown.replaceAll("%20", " "); -+ System.out.println("ftpDropDown: '" + ftpDropDown + "'"); -+ } -+ -+ -+ oneTimeKey = readParameter("oneTimeKey", false); -+ if (oneTimeKey != null) { -+ System.out.println("oneTimeKey is set."); -+ } -+ -+ serverCert = readParameter("serverCert", false); -+ if (serverCert != null) { -+ System.out.println("serverCert is set."); -+ } -+ -+ forceProxy = false; -+ proxyHost = null; -+ proxyPort = null; -+ str = readParameter("forceProxy", false); -+ if (str != null) { -+ if (str.equalsIgnoreCase("Yes")) { -+ forceProxy = true; -+ } else if (str.equalsIgnoreCase("No")) { -+ forceProxy = false; -+ } else { -+ forceProxy = true; -+ String[] pieces = str.split(" "); -+ proxyHost = new String(pieces[0]); -+ if (pieces.length >= 2) { -+ proxyPort = new String(pieces[1]); -+ } else { -+ proxyPort = new String("8080"); -+ } -+ } -+ } -+ str = readParameter("proxyHost", false); -+ if (str != null) { -+ proxyHost = new String(str); -+ } -+ str = readParameter("proxyPort", false); -+ if (str != null) { -+ proxyPort = new String(str); -+ } -+ if (proxyHost != null && proxyPort == null) { -+ proxyPort = new String("8080"); -+ } -+ -+ ignoreProxy = false; -+ str = readParameter("ignoreProxy", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ignoreProxy = true; -+ } -+ -+ trustAllVncCerts = false; -+ str = readParameter("trustAllVncCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustAllVncCerts = true; -+ } -+ trustUrlVncCert = false; -+ str = readParameter("trustUrlVncCert", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ trustUrlVncCert = true; -+ } -+ debugCerts = false; -+ str = readParameter("debugCerts", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugCerts = true; -+ } -+ debugKeyboard = false; -+ str = readParameter("debugKeyboard", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ debugKeyboard = true; -+ } -+ mapF5_to_atsign = false; -+ str = readParameter("mapF5_to_atsign", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ mapF5_to_atsign = true; -+ } -+ forbid_Ctrl_Alt = false; -+ str = readParameter("forbid_Ctrl_Alt", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ forbid_Ctrl_Alt = true; -+ } -+ ignoreMSLogonCheck = false; -+ str = readParameter("ignoreMSLogonCheck", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ignoreMSLogonCheck = true; -+ } -+ ftpOnly = false; -+ str = readParameter("ftpOnly", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ ftpOnly = true; -+ } -+ graftFtp = false; -+ str = readParameter("graftFtp", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ graftFtp = true; -+ } -+ dsmActive = false; -+ str = readParameter("dsmActive", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ dsmActive = true; -+ } -+ delayAuthPanel = false; -+ str = readParameter("delayAuthPanel", false); -+ if (str != null && str.equalsIgnoreCase("Yes")) { -+ delayAuthPanel = true; -+ } -+// end runge/x11vnc - } - - public String readParameter(String name, boolean required) { -- cgit v1.2.3