From 190a5509f43ef39f4814eca62901ceb8810c5e01 Mon Sep 17 00:00:00 2001 From: JosePereira Date: Sun, 6 May 2012 20:08:57 +0100 Subject: [PATCH] New droidvncgrab lib This library allows one to compile droidVNCserver without having AOSP. Screen grabbing is performed by this library, which is compiled against AOSP. --- droidvncgrab/Android.mk | 24 + droidvncgrab/README | 1 + droidvncgrab/droidVncGrab.cpp | 83 + droidvncgrab/droidVncGrab.h | 36 + droidvncgrab/screenFormat.h | 26 + droidvncgrab/vnc/.droidvncserver.c.swp | Bin 0 -> 16384 bytes droidvncgrab/vnc/Android.mk | 94 + droidvncgrab/vnc/adb_method.c | 284 + droidvncgrab/vnc/adb_method.h | 66 + droidvncgrab/vnc/common.h | 97 + droidvncgrab/vnc/displaybinder.cpp | 75 + droidvncgrab/vnc/displaybinder.h | 42 + droidvncgrab/vnc/droidvncserver.c | 513 + droidvncgrab/vnc/framebuffer_method.c | 136 + droidvncgrab/vnc/framebuffer_method.h | 36 + droidvncgrab/vnc/gralloc_method.c | 245 + droidvncgrab/vnc/gralloc_method.h | 31 + droidvncgrab/vnc/gui.c | 131 + droidvncgrab/vnc/gui.h | 33 + droidvncgrab/vnc/input.c | 325 + droidvncgrab/vnc/input.h | 36 + .../vnc/libvncserver-kanaka/.cvsignore | 30 + .../vnc/libvncserver-kanaka/.gitignore | 73 + droidvncgrab/vnc/libvncserver-kanaka/AUTHORS | 50 + .../vnc/libvncserver-kanaka/CMakeLists.txt | 253 + droidvncgrab/vnc/libvncserver-kanaka/COPYING | 340 + .../vnc/libvncserver-kanaka/ChangeLog | 767 + droidvncgrab/vnc/libvncserver-kanaka/INSTALL | 182 + .../vnc/libvncserver-kanaka/Makefile.am | 27 + droidvncgrab/vnc/libvncserver-kanaka/NEWS | 147 + droidvncgrab/vnc/libvncserver-kanaka/README | 439 + .../vnc/libvncserver-kanaka/README.cvs | 22 + .../vnc/libvncserver-kanaka/README.md | 42 + droidvncgrab/vnc/libvncserver-kanaka/TODO | 26 + .../VisualNaCro/.cvsignore | 22 + .../VisualNaCro/.gitignore | 5 + .../libvncserver-kanaka/VisualNaCro/AUTHORS | 2 + .../libvncserver-kanaka/VisualNaCro/ChangeLog | 15 + .../VisualNaCro/Makefile.am | 51 + .../vnc/libvncserver-kanaka/VisualNaCro/NEWS | 10 + .../libvncserver-kanaka/VisualNaCro/README | 88 + .../VisualNaCro/autogen.sh | 55 + .../VisualNaCro/configure.ac | 252 + .../VisualNaCro/default8x16.h | 261 + .../libvncserver-kanaka/VisualNaCro/nacro.c | 799 + .../libvncserver-kanaka/VisualNaCro/nacro.h | 120 + .../VisualNaCro/recorder.pl | 282 + .../vnc/libvncserver-kanaka/acinclude.m4 | 7001 +++++ .../vnc/libvncserver-kanaka/autogen.sh | 57 + droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl | 60 + .../libvncserver-kanaka/classes/.cvsignore | 3 + .../libvncserver-kanaka/classes/Makefile.am | 5 + .../libvncserver-kanaka/classes/VncViewer.jar | Bin 0 -> 35462 bytes .../vnc/libvncserver-kanaka/classes/index.vnc | 18 + .../classes/javaviewer.pseudo_proxy.patch | 141 + .../classes/ssl/Makefile.am | 2 + .../libvncserver-kanaka/classes/ssl/README | 338 + .../classes/ssl/SignedUltraViewerSSL.jar | Bin 0 -> 112662 bytes .../classes/ssl/SignedVncViewer.jar | Bin 0 -> 88734 bytes .../classes/ssl/UltraViewerSSL.jar | Bin 0 -> 109588 bytes .../classes/ssl/VncViewer.jar | Bin 0 -> 85754 bytes .../libvncserver-kanaka/classes/ssl/index.vnc | 26 + .../classes/ssl/onetimekey | 65 + .../libvncserver-kanaka/classes/ssl/proxy.vnc | 73 + .../classes/ssl/ss_vncviewer | 3513 +++ ...iewer-cursor-colors+no-tab-traversal.patch | 57 + ...ghtvnc-1.3dev7_javasrc-vncviewer-ssl.patch | 2429 ++ .../libvncserver-kanaka/classes/ssl/ultra.vnc | 28 + .../classes/ssl/ultraproxy.vnc | 28 + .../classes/ssl/ultrasigned.vnc | 28 + .../ssl/ultravnc-102-JavaViewer-ssl-etc.patch | 5365 ++++ .../client_examples/.cvsignore | 9 + .../client_examples/Makefile.am | 33 + .../client_examples/SDLvncviewer.c | 553 + .../client_examples/backchannel.c | 99 + .../client_examples/ppmtest.c | 97 + .../client_examples/scrap.c | 558 + .../client_examples/scrap.h | 18 + .../client_examples/vnc2mpg.c | 435 + .../vnc/libvncserver-kanaka/configure.ac | 894 + .../vnc/libvncserver-kanaka/consolefont2c.pl | 38 + .../libvncserver-kanaka/contrib/.cvsignore | 6 + .../libvncserver-kanaka/contrib/Makefile.am | 7 + .../vnc/libvncserver-kanaka/contrib/zippy.c | 179 + .../cvs_update_anonymously | 13 + .../libvncserver-kanaka/examples/.cvsignore | 18 + .../libvncserver-kanaka/examples/1instance.c | 141 + .../libvncserver-kanaka/examples/Makefile.am | 22 + .../examples/backchannel.c | 113 + .../libvncserver-kanaka/examples/blooptest.c | 2 + .../vnc/libvncserver-kanaka/examples/camera.c | 152 + .../examples/colourmaptest.c | 32 + .../libvncserver-kanaka/examples/example.c | 336 + .../libvncserver-kanaka/examples/example.dsp | 93 + .../examples/filetransfer.c | 11 + .../libvncserver-kanaka/examples/fontsel.c | 73 + .../vnc/libvncserver-kanaka/examples/mac.c | 551 + .../libvncserver-kanaka/examples/pnmshow.c | 121 + .../libvncserver-kanaka/examples/pnmshow24.c | 94 + .../vnc/libvncserver-kanaka/examples/radon.h | 195 + .../libvncserver-kanaka/examples/regiontest.c | 3 + .../vnc/libvncserver-kanaka/examples/rotate.c | 92 + .../examples/rotatetemplate.c | 52 + .../vnc/libvncserver-kanaka/examples/simple.c | 10 + .../libvncserver-kanaka/examples/simple15.c | 24 + .../examples/storepasswd.c | 46 + .../vnc/libvncserver-kanaka/examples/vncev.c | 128 + .../vnc/libvncserver-kanaka/index.html | 191 + .../libvncclient/.cvsignore | 5 + .../libvncclient/Makefile.am | 15 + .../libvncserver-kanaka/libvncclient/corre.c | 70 + .../libvncserver-kanaka/libvncclient/cursor.c | 179 + .../libvncclient/hextile.c | 127 + .../libvncserver-kanaka/libvncclient/listen.c | 171 + .../libvncclient/lzoconf.h | 451 + .../libvncclient/minilzo.c | 2935 ++ .../libvncclient/minilzo.h | 100 + .../libvncclient/rfbproto.c | 2123 ++ .../libvncserver-kanaka/libvncclient/rre.c | 68 + .../libvncclient/sockets.c | 616 + .../libvncserver-kanaka/libvncclient/tight.c | 688 + .../libvncserver-kanaka/libvncclient/tls.c | 496 + .../libvncserver-kanaka/libvncclient/tls.h | 51 + .../libvncserver-kanaka/libvncclient/ultra.c | 210 + .../libvncclient/vncviewer.c | 375 + .../libvncserver-kanaka/libvncclient/zlib.c | 162 + .../libvncserver-kanaka/libvncclient/zrle.c | 427 + .../libvncserver-config.in | 78 + .../vnc/libvncserver-kanaka/libvncserver.dsp | 220 + .../vnc/libvncserver-kanaka/libvncserver.dsw | 101 + .../libvncserver/.cvsignore | 5 + .../libvncserver/Makefile.am | 64 + .../libvncserver-kanaka/libvncserver/auth.c | 375 + .../libvncserver-kanaka/libvncserver/cargs.c | 227 + .../libvncserver-kanaka/libvncserver/corre.c | 360 + .../libvncserver-kanaka/libvncserver/cursor.c | 756 + .../libvncserver/cutpaste.c | 38 + .../libvncserver-kanaka/libvncserver/d3des.c | 436 + .../libvncserver-kanaka/libvncserver/d3des.h | 56 + .../libvncserver-kanaka/libvncserver/draw.c | 61 + .../libvncserver-kanaka/libvncserver/font.c | 196 + .../libvncserver/hextile.c | 342 + .../libvncserver-kanaka/libvncserver/httpd.c | 631 + .../libvncserver/lzoconf.h | 451 + .../libvncserver-kanaka/libvncserver/main.c | 1182 + .../libvncserver-kanaka/libvncserver/md5.c | 448 + .../libvncserver-kanaka/libvncserver/md5.h | 148 + .../libvncserver/minilzo.c | 2935 ++ .../libvncserver/minilzo.h | 100 + .../libvncserver/private.h | 44 + .../libvncserver/rfbregion.c | 886 + .../libvncserver/rfbserver.c | 3383 +++ .../libvncserver-kanaka/libvncserver/rre.c | 329 + .../libvncserver-kanaka/libvncserver/scale.c | 420 + .../libvncserver-kanaka/libvncserver/scale.h | 10 + .../libvncserver-kanaka/libvncserver/selbox.c | 300 + .../libvncserver/sockets.c | 822 + .../libvncserver-kanaka/libvncserver/stats.c | 479 + .../libvncserver/tableinit24.c | 157 + .../libvncserver/tableinitcmtemplate.c | 84 + .../libvncserver/tableinittctemplate.c | 142 + .../libvncserver/tabletrans24template.c | 281 + .../libvncserver/tabletranstemplate.c | 117 + .../libvncserver-kanaka/libvncserver/tight.c | 2053 ++ .../tightvnc-filetransfer/.cvsignore | 3 + .../tightvnc-filetransfer/filelistinfo.c | 133 + .../tightvnc-filetransfer/filelistinfo.h | 65 + .../tightvnc-filetransfer/filetransfermsg.c | 636 + .../tightvnc-filetransfer/filetransfermsg.h | 54 + .../handlefiletransferrequest.c | 993 + .../handlefiletransferrequest.h | 47 + .../tightvnc-filetransfer/rfbtightproto.h | 456 + .../tightvnc-filetransfer/rfbtightserver.c | 546 + .../libvncserver/translate.c | 477 + .../libvncserver-kanaka/libvncserver/ultra.c | 248 + .../libvncserver/vncauth.c | 208 + .../libvncserver/websockets.c | 568 + .../libvncserver-kanaka/libvncserver/zlib.c | 331 + .../libvncserver-kanaka/libvncserver/zrle.c | 260 + .../libvncserver/zrleencodetemplate.c | 322 + .../libvncserver/zrleoutstream.c | 275 + .../libvncserver/zrleoutstream.h | 62 + .../libvncserver/zrlepalettehelper.c | 62 + .../libvncserver/zrlepalettehelper.h | 46 + .../libvncserver/zrletypes.h | 30 + .../libvncserver/zywrletemplate.c | 824 + .../vnc/libvncserver-kanaka/ltmain.sh | 6863 +++++ .../prepare_x11vnc_dist.sh | 136 + .../vnc/libvncserver-kanaka/rfb/.cvsignore | 5 + .../vnc/libvncserver-kanaka/rfb/default8x16.h | 261 + .../vnc/libvncserver-kanaka/rfb/keysym.h | 1638 ++ .../vnc/libvncserver-kanaka/rfb/rfb.h | 1044 + .../vnc/libvncserver-kanaka/rfb/rfbclient.h | 406 + .../libvncserver-kanaka/rfb/rfbconfig.h.cmake | 92 + .../libvncserver-kanaka/rfb/rfbint.h.cmake | 4 + .../vnc/libvncserver-kanaka/rfb/rfbproto.h | 1383 + .../vnc/libvncserver-kanaka/rfb/rfbregion.h | 65 + .../vnc/libvncserver-kanaka/success.html | 45 + .../vnc/libvncserver-kanaka/test/.cvsignore | 9 + .../vnc/libvncserver-kanaka/test/Makefile.am | 16 + .../vnc/libvncserver-kanaka/test/blooptest.c | 2 + .../vnc/libvncserver-kanaka/test/cargstest.c | 29 + .../libvncserver-kanaka/test/copyrecttest.c | 53 + .../vnc/libvncserver-kanaka/test/cursortest.c | 351 + .../libvncserver-kanaka/test/encodingstest.c | 353 + ...htvnc-1.3dev5-vncviewer-alpha-cursor.patch | 143 + .../libvncserver-kanaka/vncterm/.cvsignore | 7 + .../vnc/libvncserver-kanaka/vncterm/ChangeLog | 15 + .../libvncserver-kanaka/vncterm/LinuxVNC.c | 191 + .../libvncserver-kanaka/vncterm/Makefile.am | 25 + .../vnc/libvncserver-kanaka/vncterm/README | 25 + .../vnc/libvncserver-kanaka/vncterm/TODO | 21 + .../libvncserver-kanaka/vncterm/VNCommand.c | 127 + .../libvncserver-kanaka/vncterm/VNConsole.c | 497 + .../libvncserver-kanaka/vncterm/VNConsole.h | 95 + .../vnc/libvncserver-kanaka/vncterm/example.c | 31 + .../vnc/libvncserver-kanaka/vncterm/vga.h | 261 + .../vnc/libvncserver-kanaka/x11vnc/.cvsignore | 5 + .../vnc/libvncserver-kanaka/x11vnc/8to24.c | 2155 ++ .../vnc/libvncserver-kanaka/x11vnc/8to24.h | 45 + .../vnc/libvncserver-kanaka/x11vnc/ChangeLog | 1218 + .../libvncserver-kanaka/x11vnc/Makefile.am | 36 + .../vnc/libvncserver-kanaka/x11vnc/README | 17770 +++++++++++ .../x11vnc/allowed_input_t.h | 46 + .../vnc/libvncserver-kanaka/x11vnc/appshare.c | 2124 ++ .../vnc/libvncserver-kanaka/x11vnc/avahi.c | 409 + .../vnc/libvncserver-kanaka/x11vnc/avahi.h | 43 + .../libvncserver-kanaka/x11vnc/blackout_t.h | 49 + .../vnc/libvncserver-kanaka/x11vnc/cleanup.c | 755 + .../vnc/libvncserver-kanaka/x11vnc/cleanup.h | 59 + .../libvncserver-kanaka/x11vnc/connections.c | 4377 +++ .../libvncserver-kanaka/x11vnc/connections.h | 82 + .../vnc/libvncserver-kanaka/x11vnc/cursor.c | 2025 ++ .../vnc/libvncserver-kanaka/x11vnc/cursor.h | 70 + .../vnc/libvncserver-kanaka/x11vnc/enc.h | 2165 ++ .../vnc/libvncserver-kanaka/x11vnc/enums.h | 54 + .../vnc/libvncserver-kanaka/x11vnc/gui.c | 937 + .../vnc/libvncserver-kanaka/x11vnc/gui.h | 53 + .../vnc/libvncserver-kanaka/x11vnc/help.c | 6226 ++++ .../vnc/libvncserver-kanaka/x11vnc/help.h | 43 + .../vnc/libvncserver-kanaka/x11vnc/inet.c | 878 + .../vnc/libvncserver-kanaka/x11vnc/inet.h | 58 + .../vnc/libvncserver-kanaka/x11vnc/keyboard.c | 3418 +++ .../vnc/libvncserver-kanaka/x11vnc/keyboard.h | 62 + .../vnc/libvncserver-kanaka/x11vnc/linuxfb.c | 393 + .../vnc/libvncserver-kanaka/x11vnc/linuxfb.h | 42 + .../vnc/libvncserver-kanaka/x11vnc/macosx.c | 738 + .../vnc/libvncserver-kanaka/x11vnc/macosx.h | 63 + .../vnc/libvncserver-kanaka/x11vnc/macosxCG.c | 662 + .../vnc/libvncserver-kanaka/x11vnc/macosxCG.h | 62 + .../libvncserver-kanaka/x11vnc/macosxCGP.c | 221 + .../libvncserver-kanaka/x11vnc/macosxCGP.h | 49 + .../libvncserver-kanaka/x11vnc/macosxCGS.c | 602 + .../libvncserver-kanaka/x11vnc/macosxCGS.h | 45 + .../x11vnc/misc/.cvsignore | 3 + .../libvncserver-kanaka/x11vnc/misc/LICENSE | 31 + .../x11vnc/misc/Makefile.am | 3 + .../libvncserver-kanaka/x11vnc/misc/README | 46 + .../libvncserver-kanaka/x11vnc/misc/Xdummy | 1930 ++ .../x11vnc/misc/blockdpy.c | 352 + .../x11vnc/misc/connect_switch | 696 + .../x11vnc/misc/desktop.cgi | 1550 + .../x11vnc/misc/dtVncPopup | 109 + .../misc/enhanced_tightvnc_viewer/COPYING | 340 + .../misc/enhanced_tightvnc_viewer/README | 756 + .../Windows/README.txt | 72 + .../Windows/sshvnc.bat | 1 + .../Windows/tsvnc.bat | 1 + .../Windows/util/connect_br.tcl | 1271 + .../Windows/util/info/esound/download.url | 1 + .../Windows/util/info/openssl/download.url | 1 + .../Windows/util/info/openssl/location.url | 1 + .../Windows/util/info/plink/download.url | 1 + .../Windows/util/info/plink/licence.url | 1 + .../Windows/util/info/stunnel/download.url | 1 + .../Windows/util/info/stunnel/location.url | 2 + .../Windows/util/info/vncviewer/download.url | 1 + .../Windows/util/info/vncviewer/location.url | 1 + .../Windows/util/stunnel-client.conf | 43 + .../Windows/util/stunnel-server.conf | 34 + .../Windows/util/w98/location.url | 1 + .../bin/Darwin.Power.Macintosh/.cpover | 7 + .../bin/Darwin.Power.Macintosh/vncviewer.sh | 39 + .../bin/Darwin.i386/.cpover | 6 + .../misc/enhanced_tightvnc_viewer/bin/sshvnc | 7 + .../misc/enhanced_tightvnc_viewer/bin/ssvnc | 289 + .../enhanced_tightvnc_viewer/bin/ssvnc_cmd | 286 + .../misc/enhanced_tightvnc_viewer/bin/tsvnc | 7 + .../bin/util/ss_vncviewer | 3635 +++ .../bin/util/ssvnc.tcl | 19041 ++++++++++++ .../bin/util/stunnel-server.conf | 38 + .../misc/enhanced_tightvnc_viewer/build.unix | 482 + .../enhanced_tightvnc_viewer/filelist.txt | 280 + .../enhanced_tightvnc_viewer/man/man1/ssvnc.1 | 233 + .../man/man1/ssvncviewer.1 | 829 + .../misc/enhanced_tightvnc_viewer/src/README | 7 + .../src/patches/README | 6 + .../src/patches/_bundle | 103 + .../src/patches/_getpatches | 14 + .../src/patches/_vncpatchapplied | 6 + .../src/patches/stunnel-maxconn.patch | 44 + .../src/patches/tight-vncviewer-full.patch | 24370 ++++++++++++++++ .../patches/tight-vncviewer-fullscreen.patch | 42 + .../patches/tight-vncviewer-newfbsize.patch | 286 + .../enhanced_tightvnc_viewer/src/zips/README | 16 + .../enhanced_tightvnc_viewer/ssvnc.desktop | 11 + .../libvncserver-kanaka/x11vnc/misc/inet6to4 | 420 + .../libvncserver-kanaka/x11vnc/misc/panner.pl | 117 + .../libvncserver-kanaka/x11vnc/misc/ranfb.pl | 157 + .../libvncserver-kanaka/x11vnc/misc/rx11vnc | 133 + .../x11vnc/misc/rx11vnc.pl | 199 + .../libvncserver-kanaka/x11vnc/misc/shm_clear | 97 + .../libvncserver-kanaka/x11vnc/misc/slide.pl | 112 + .../x11vnc/misc/turbovnc/Makefile.am | 8 + .../x11vnc/misc/turbovnc/README | 159 + .../x11vnc/misc/turbovnc/apply_turbovnc | 46 + .../x11vnc/misc/turbovnc/convert | 79 + .../x11vnc/misc/turbovnc/convert_rfbserver | 56 + .../x11vnc/misc/turbovnc/tight.c | 1502 + .../x11vnc/misc/turbovnc/turbojpeg.h | 229 + .../x11vnc/misc/turbovnc/undo_turbovnc | 25 + .../x11vnc/misc/ultravnc_repeater.pl | 736 + .../x11vnc/misc/vcinject.pl | 113 + .../x11vnc/misc/x11vnc_loop | 89 + .../libvncserver-kanaka/x11vnc/misc/x11vnc_pw | 24 + .../vnc/libvncserver-kanaka/x11vnc/nox11.h | 6671 +++++ .../libvncserver-kanaka/x11vnc/nox11_funcs.h | 2822 ++ .../vnc/libvncserver-kanaka/x11vnc/options.c | 507 + .../vnc/libvncserver-kanaka/x11vnc/options.h | 397 + .../vnc/libvncserver-kanaka/x11vnc/params.h | 103 + .../vnc/libvncserver-kanaka/x11vnc/pm.c | 297 + .../vnc/libvncserver-kanaka/x11vnc/pm.h | 40 + .../vnc/libvncserver-kanaka/x11vnc/pointer.c | 1215 + .../vnc/libvncserver-kanaka/x11vnc/pointer.h | 47 + .../vnc/libvncserver-kanaka/x11vnc/rates.c | 725 + .../vnc/libvncserver-kanaka/x11vnc/rates.h | 55 + .../vnc/libvncserver-kanaka/x11vnc/remote.c | 6287 ++++ .../vnc/libvncserver-kanaka/x11vnc/remote.h | 50 + .../vnc/libvncserver-kanaka/x11vnc/scan.c | 3677 +++ .../vnc/libvncserver-kanaka/x11vnc/scan.h | 60 + .../vnc/libvncserver-kanaka/x11vnc/screen.c | 4605 +++ .../vnc/libvncserver-kanaka/x11vnc/screen.h | 68 + .../x11vnc/scrollevent_t.h | 47 + .../libvncserver-kanaka/x11vnc/selection.c | 548 + .../libvncserver-kanaka/x11vnc/selection.h | 55 + .../vnc/libvncserver-kanaka/x11vnc/solid.c | 1429 + .../vnc/libvncserver-kanaka/x11vnc/solid.h | 47 + .../vnc/libvncserver-kanaka/x11vnc/sslcmds.c | 908 + .../vnc/libvncserver-kanaka/x11vnc/sslcmds.h | 49 + .../libvncserver-kanaka/x11vnc/sslhelper.c | 4338 +++ .../libvncserver-kanaka/x11vnc/sslhelper.h | 73 + .../vnc/libvncserver-kanaka/x11vnc/ssltools.h | 2492 ++ .../vnc/libvncserver-kanaka/x11vnc/tkx11vnc | 7334 +++++ .../vnc/libvncserver-kanaka/x11vnc/tkx11vnc.h | 7350 +++++ .../vnc/libvncserver-kanaka/x11vnc/uinput.c | 1559 + .../vnc/libvncserver-kanaka/x11vnc/uinput.h | 58 + .../vnc/libvncserver-kanaka/x11vnc/unixpw.c | 2226 ++ .../vnc/libvncserver-kanaka/x11vnc/unixpw.h | 64 + .../vnc/libvncserver-kanaka/x11vnc/user.c | 3153 ++ .../vnc/libvncserver-kanaka/x11vnc/user.h | 49 + .../libvncserver-kanaka/x11vnc/userinput.c | 10199 +++++++ .../libvncserver-kanaka/x11vnc/userinput.h | 77 + .../vnc/libvncserver-kanaka/x11vnc/util.c | 762 + .../vnc/libvncserver-kanaka/x11vnc/util.h | 156 + .../vnc/libvncserver-kanaka/x11vnc/v4l.c | 1785 ++ .../vnc/libvncserver-kanaka/x11vnc/v4l.h | 42 + .../libvncserver-kanaka/x11vnc/win_utils.c | 771 + .../libvncserver-kanaka/x11vnc/win_utils.h | 59 + .../libvncserver-kanaka/x11vnc/winattr_t.h | 66 + .../vnc/libvncserver-kanaka/x11vnc/x11vnc.1 | 6732 +++++ .../vnc/libvncserver-kanaka/x11vnc/x11vnc.c | 5902 ++++ .../libvncserver-kanaka/x11vnc/x11vnc.desktop | 10 + .../vnc/libvncserver-kanaka/x11vnc/x11vnc.h | 663 + .../libvncserver-kanaka/x11vnc/x11vnc_defs.c | 230 + .../vnc/libvncserver-kanaka/x11vnc/xdamage.c | 840 + .../vnc/libvncserver-kanaka/x11vnc/xdamage.h | 64 + .../vnc/libvncserver-kanaka/x11vnc/xevents.c | 2155 ++ .../vnc/libvncserver-kanaka/x11vnc/xevents.h | 66 + .../vnc/libvncserver-kanaka/x11vnc/xinerama.c | 556 + .../vnc/libvncserver-kanaka/x11vnc/xinerama.h | 50 + .../vnc/libvncserver-kanaka/x11vnc/xkb_bell.c | 167 + .../vnc/libvncserver-kanaka/x11vnc/xkb_bell.h | 44 + .../vnc/libvncserver-kanaka/x11vnc/xrandr.c | 306 + .../vnc/libvncserver-kanaka/x11vnc/xrandr.h | 94 + .../vnc/libvncserver-kanaka/x11vnc/xrecord.c | 2084 ++ .../vnc/libvncserver-kanaka/x11vnc/xrecord.h | 68 + .../libvncserver-kanaka/x11vnc/xwrappers.c | 1482 + .../libvncserver-kanaka/x11vnc/xwrappers.h | 121 + droidvncgrab/vnc/linux/uinput.h | 67 + droidvncgrab/vnc/suinput.c | 225 + droidvncgrab/vnc/suinput.h | 96 + droidvncgrab/vnc/update_screen.c | 211 + 392 files changed, 285403 insertions(+) create mode 100755 droidvncgrab/Android.mk create mode 100644 droidvncgrab/README create mode 100755 droidvncgrab/droidVncGrab.cpp create mode 100755 droidvncgrab/droidVncGrab.h create mode 100644 droidvncgrab/screenFormat.h create mode 100644 droidvncgrab/vnc/.droidvncserver.c.swp create mode 100755 droidvncgrab/vnc/Android.mk create mode 100755 droidvncgrab/vnc/adb_method.c create mode 100755 droidvncgrab/vnc/adb_method.h create mode 100755 droidvncgrab/vnc/common.h create mode 100755 droidvncgrab/vnc/displaybinder.cpp create mode 100755 droidvncgrab/vnc/displaybinder.h create mode 100755 droidvncgrab/vnc/droidvncserver.c create mode 100755 droidvncgrab/vnc/framebuffer_method.c create mode 100755 droidvncgrab/vnc/framebuffer_method.h create mode 100644 droidvncgrab/vnc/gralloc_method.c create mode 100644 droidvncgrab/vnc/gralloc_method.h create mode 100755 droidvncgrab/vnc/gui.c create mode 100755 droidvncgrab/vnc/gui.h create mode 100755 droidvncgrab/vnc/input.c create mode 100755 droidvncgrab/vnc/input.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/.gitignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/AUTHORS create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/COPYING create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/ChangeLog create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/INSTALL create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/NEWS create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/README.cvs create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/README.md create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/TODO create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/autogen.sh create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/VncViewer.jar create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedUltraViewerSSL.jar create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedVncViewer.jar create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/UltraViewerSSL.jar create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/VncViewer.jar create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/proxy.vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/configure.ac create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/backchannel.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/example.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow24.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/index.html create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/vncviewer.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/font.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/ltmain.sh create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/success.html create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/tightvnc-1.3dev5-vncviewer-alpha-cursor.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cursor.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cursor.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/enc.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/enums.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/gui.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/gui.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/help.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/help.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/inet.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/inet.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/keyboard.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/keyboard.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/linuxfb.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/linuxfb.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosx.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosx.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosxCG.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosxCG.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosxCGP.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosxCGP.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosxCGS.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/macosxCGS.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/.cvsignore create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/LICENSE create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/Xdummy create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/blockdpy.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/connect_switch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/desktop.cgi create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/dtVncPopup create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/COPYING create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/README.txt create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/sshvnc.bat create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/tsvnc.bat create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/connect_br.tcl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/esound/download.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/openssl/download.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/openssl/location.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/plink/download.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/plink/licence.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/stunnel/download.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/stunnel/location.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/vncviewer/download.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/info/vncviewer/location.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/stunnel-client.conf create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/stunnel-server.conf create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/Windows/util/w98/location.url create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/Darwin.Power.Macintosh/.cpover create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/Darwin.Power.Macintosh/vncviewer.sh create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/Darwin.i386/.cpover create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/sshvnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/ssvnc_cmd create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/tsvnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ss_vncviewer create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/ssvnc.tcl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/bin/util/stunnel-server.conf create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/build.unix create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/filelist.txt create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/man/man1/ssvnc.1 create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/man/man1/ssvncviewer.1 create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_bundle create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_getpatches create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/_vncpatchapplied create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/stunnel-maxconn.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-fullscreen.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-newfbsize.patch create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/src/zips/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/enhanced_tightvnc_viewer/ssvnc.desktop create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/inet6to4 create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/panner.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/ranfb.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/rx11vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/rx11vnc.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/shm_clear create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/slide.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/Makefile.am create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/README create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/apply_turbovnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/convert create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/convert_rfbserver create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/tight.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/turbojpeg.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/turbovnc/undo_turbovnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/ultravnc_repeater.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/vcinject.pl create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/x11vnc_loop create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/misc/x11vnc_pw create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/nox11.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/nox11_funcs.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/options.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/options.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/params.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/pm.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/pm.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/pointer.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/pointer.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/rates.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/rates.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/remote.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/remote.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/scan.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/scan.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/screen.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/screen.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/scrollevent_t.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/selection.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/selection.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/solid.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/solid.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/sslcmds.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/sslcmds.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/sslhelper.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/sslhelper.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ssltools.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/tkx11vnc create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/tkx11vnc.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/uinput.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/uinput.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/unixpw.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/unixpw.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/user.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/user.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/userinput.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/userinput.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/util.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/util.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/v4l.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/v4l.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/win_utils.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/win_utils.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/winattr_t.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/x11vnc.1 create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/x11vnc.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/x11vnc.desktop create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/x11vnc.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/x11vnc_defs.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xdamage.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xdamage.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xevents.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xevents.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xinerama.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xinerama.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xkb_bell.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xkb_bell.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xrandr.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xrandr.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xrecord.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xrecord.h create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xwrappers.c create mode 100755 droidvncgrab/vnc/libvncserver-kanaka/x11vnc/xwrappers.h create mode 100755 droidvncgrab/vnc/linux/uinput.h create mode 100755 droidvncgrab/vnc/suinput.c create mode 100755 droidvncgrab/vnc/suinput.h create mode 100755 droidvncgrab/vnc/update_screen.c diff --git a/droidvncgrab/Android.mk b/droidvncgrab/Android.mk new file mode 100755 index 0000000..83ff374 --- /dev/null +++ b/droidvncgrab/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES = \ + droidVncGrab.cpp + +#LOCAL_CFLAGS += -DPLATFORM_SDK_VERSION=$(PLATFORM_SDK_VERSION) + +LOCAL_C_INCLUDES += $(LOCAL_PATH) + +LOCAL_PRELINK_MODULE:=false #override prelink map +LOCAL_MODULE:= droidvncgrab_sdk$(PLATFORM_SDK_VERSION) +LOCAL_MODULE_TAGS:= optional + +ifeq ($(PLATFORM_SDK_VERSION),9) +LOCAL_SHARED_LIBRARIES := libsurfaceflinger_client libui libbinder libutils libcutils #libcrypto libssl libhardware +else ifeq ($(PLATFORM_SDK_VERSION),15) +LOCAL_SHARED_LIBRARIES := libgui libui libbinder libcutils +else +#add here more sdk versions +LOCAL_SHARED_LIBRARIES := libsurfaceflinger_client libui libbinder libutils libcutils #libcrypto libssl libhardware +endif + +include $(BUILD_SHARED_LIBRARY) diff --git a/droidvncgrab/README b/droidvncgrab/README new file mode 100644 index 0000000..28eb82f --- /dev/null +++ b/droidvncgrab/README @@ -0,0 +1 @@ +This diff --git a/droidvncgrab/droidVncGrab.cpp b/droidvncgrab/droidVncGrab.cpp new file mode 100755 index 0000000..95d7a2e --- /dev/null +++ b/droidvncgrab/droidVncGrab.cpp @@ -0,0 +1,83 @@ +/* + droid vnc server - Android VNC server + Copyright (C) 2009 Jose Pereira + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "droidVncGrab.h" +#include "screenFormat.h" + +#include +#include +#include + +#include +#include +#include + +using namespace android; + +ScreenshotClient *screenshotClient=NULL; + +extern "C" screenFormat getScreenFormat() +{ + //get format on PixelFormat struct + PixelFormat f=screenshotClient->getFormat(); + + PixelFormatInfo pf; + getPixelFormatInfo(f,&pf); + + screenFormat format; + + format.bitsPerPixel = pf.bitsPerPixel; + format.width = screenshotClient->getWidth(); + format.height = screenshotClient->getHeight(); + format.size = pf.bitsPerPixel*format.width*format.height/CHAR_BIT; + format.redShift = pf.l_red; + format.redMax = pf.h_red; + format.greenShift = pf.l_green; + format.greenMax = pf.h_green-pf.h_red; + format.blueShift = pf.l_blue; + format.blueMax = pf.h_blue-pf.h_green; + format.alphaShift = pf.l_alpha; + format.alphaMax = pf.h_alpha-pf.h_blue; + + return format; +} + + +extern "C" int initScreenGrab() +{ + int errno; + + L("--Initializing gingerbread access method--\n"); + + screenshotClient=new ScreenshotClient(); + errno=screenshotClient->update(); + if (errno != NO_ERROR) { + L("screen capture failed: %s\n", strerror(-errno)); + return -1; + } + + return 0; +} + +extern "C" unsigned int * getScreenBuffer() +{ + screenshotClient->update(); + return (unsigned int*)screenshotClient->getPixels(); +} + diff --git a/droidvncgrab/droidVncGrab.h b/droidvncgrab/droidVncGrab.h new file mode 100755 index 0000000..76366b3 --- /dev/null +++ b/droidvncgrab/droidVncGrab.h @@ -0,0 +1,36 @@ +/* + droid vnc server - Android VNC server + Copyright (C) 2009 Jose Pereira + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DISPLAY_BINDER +#define DISPLAY_BINDER + +#ifdef __cplusplus +#define L(...) __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); + + +extern "C" { +#endif + unsigned int * updateScreen(); + int initScreenGrab(); +#ifdef __cplusplus +} + +#endif + +#endif diff --git a/droidvncgrab/screenFormat.h b/droidvncgrab/screenFormat.h new file mode 100644 index 0000000..a8d35ff --- /dev/null +++ b/droidvncgrab/screenFormat.h @@ -0,0 +1,26 @@ +#include + + +typedef struct _screenFormat +{ + + uint16_t width; + uint16_t height; + + uint8_t bitsPerPixel; + + uint16_t redMax; + uint16_t greenMax; + uint16_t blueMax; + uint16_t alphaMax; + + uint8_t redShift; + uint8_t greenShift; + uint8_t blueShift; + uint8_t alphaShift; + + uint32_t size; + + uint32_t pad; + +} screenFormat; diff --git a/droidvncgrab/vnc/.droidvncserver.c.swp b/droidvncgrab/vnc/.droidvncserver.c.swp new file mode 100644 index 0000000000000000000000000000000000000000..3264dfcd1b0db9df7fc0797fb4354fff3635ee4d GIT binary patch literal 16384 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 literal 0 HcmV?d00001 diff --git a/droidvncgrab/vnc/Android.mk b/droidvncgrab/vnc/Android.mk new file mode 100755 index 0000000..a83c1e9 --- /dev/null +++ b/droidvncgrab/vnc/Android.mk @@ -0,0 +1,94 @@ + + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +local_c_flags += -Wall -O3 -DLIBVNCSERVER_WITH_WEBSOCKETS -DLIBVNCSERVER_HAVE_LIBPNG + +local_src_files:= \ + input.c \ + gui.c \ + adb_method.c \ + framebuffer_method.c \ + suinput.c \ + droidvncserver.c \ + gralloc_method.c \ + libvncserver-kanaka/libvncserver/scale.c \ + libvncserver-kanaka/libvncserver/main.c \ + libvncserver-kanaka/libvncserver/rfbserver.c \ + libvncserver-kanaka/libvncserver/rfbregion.c \ + libvncserver-kanaka/libvncserver/auth.c \ + libvncserver-kanaka/libvncserver/sockets.c \ + libvncserver-kanaka/libvncserver/stats.c \ + libvncserver-kanaka/libvncserver/corre.c \ + libvncserver-kanaka/libvncserver/hextile.c \ + libvncserver-kanaka/libvncserver/rre.c \ + libvncserver-kanaka/libvncserver/translate.c \ + libvncserver-kanaka/libvncserver/cutpaste.c \ + libvncserver-kanaka/libvncserver/httpd.c \ + libvncserver-kanaka/libvncserver/cursor.c \ + libvncserver-kanaka/libvncserver/font.c \ + libvncserver-kanaka/libvncserver/draw.c \ + libvncserver-kanaka/libvncserver/selbox.c \ + libvncserver-kanaka/libvncserver/minilzo.c \ + libvncserver-kanaka/libvncserver/vncauth.c \ + libvncserver-kanaka/libvncserver/d3des.c \ + libvncserver-kanaka/libvncserver/md5.c \ + libvncserver-kanaka/libvncserver/cargs.c \ + libvncserver-kanaka/libvncserver/ultra.c \ + libvncserver-kanaka/libvncserver/zlib.c \ + libvncserver-kanaka/libvncserver/zrle.c \ + libvncserver-kanaka/libvncserver/zrleoutstream.c \ + libvncserver-kanaka/libvncserver/zrlepalettehelper.c \ + libvncserver-kanaka/libvncserver/tight.c \ + libvncserver-kanaka/libvncserver/zywrletemplate.c \ + libvncserver-kanaka/libvncserver/websockets.c + +ginger_up := displaybinder.cpp + + +local_c_includes := \ + $(LOCAL_PATH) \ + $(LOCAL_PATH)/libvncserver-kanaka/libvncserver \ + $(LOCAL_PATH)/libvncserver-kanaka \ + $(LOCAL_PATH)/libvncserver-kanaka/common \ + $(LOCAL_PATH)/../../zlib \ + $(LOCAL_PATH)/../../jpeg \ + $(LOCAL_PATH)/../../openssl/include \ + $(LOCAL_PATH)/../../libpng \ + +####################################### + +# target +include $(CLEAR_VARS) +LOCAL_SRC_FILES += $(local_src_files) +LOCAL_CFLAGS += $(local_c_flags) -DANDROID_FROYO +LOCAL_C_INCLUDES += $(local_c_includes) + + +LOCAL_MODULE:= androidvncserver_froyo +LOCAL_MODULE_TAGS:= optional + +LOCAL_STATIC_LIBRARIES := libcutils libz libpng jpeg +LOCAL_SHARED_LIBRARIES := libcrypto libssl libhardware + +include $(BUILD_EXECUTABLE) + +####################################### + +# target +include $(CLEAR_VARS) +LOCAL_SRC_FILES += $(local_src_files) $(ginger_up) +LOCAL_CFLAGS += $(local_c_flags) +LOCAL_C_INCLUDES += $(local_c_includes) + + +LOCAL_MODULE:= androidvncserver_gingerup +LOCAL_MODULE_TAGS:= optional + +LOCAL_STATIC_LIBRARIES := libcutils libz libpng jpeg +LOCAL_SHARED_LIBRARIES := libcrypto libssl libhardware libsurfaceflinger_client libui + +include $(BUILD_EXECUTABLE) diff --git a/droidvncgrab/vnc/adb_method.c b/droidvncgrab/vnc/adb_method.c new file mode 100755 index 0000000..7da3e1a --- /dev/null +++ b/droidvncgrab/vnc/adb_method.c @@ -0,0 +1,284 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "adb_method.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +//#include "common.h" + + + +#define A_CNXN 0x4e584e43 +#define A_OKAY 0x59414b4f +#define A_CLSE 0x45534c43 +#define A_WRTE 0x45545257 + + +#define DDMS_RAWIMAGE_VERSION 1 + +char connect_string[] = { +0x43, 0x4e, 0x58, 0x4e, 0x00, 0x00, 0x00, 0x01, +0x00, 0x10, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, +0x32, 0x02, 0x00, 0x00, 0xbc, 0xb1, 0xa7, 0xb1, +0x68, 0x6f, 0x73, 0x74, 0x3a, 0x3a, 0x00 }; + +char framebuffer_string[] = { +0x4f, 0x50, 0x45, 0x4e, 0x01, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, +0xbf, 0x04, 0x00, 0x00, 0xb0, 0xaf, 0xba, 0xb1, +0x66, 0x72, 0x61, 0x6d, 0x65, 0x62, 0x75, 0x66, +0x66, 0x65, 0x72, 0x3a, 0x00 }; + +char okay_string[24]; + +struct fbinfo *fb_info; +struct _message *message,*okay_message; +int sockfd; + +ssize_t write_socket(int fd, const void *buf, size_t count) +{ +// L("--Writing %d \n",count); + + int n = write(fd,buf,count); + + if (n < 0) + perror("ERROR writing to socket"); + + return n; +} + + +void read_socket(int fd, void *buf, size_t count) +{ + int n=0; + + while (count>0) + { + n=read(fd,buf,count); + + if (n < 0) + L("ERROR reading from socket\n"); + + + count-=n; + } + return; +} + +void send_connect_string() +{ + write_socket(sockfd,connect_string,sizeof(connect_string)); + + read_socket(sockfd,message,sizeof(struct _message)); + + if (message->command!=A_CNXN) + L("bad A_CNXN response\n"); + + //lets read, i don't want this + read_socket(sockfd,message,message->data_length); +} + +void send_framebuffer_string(); + +int initADB() +{ + L("--Initializing adb access method--\n"); + int portno; + struct sockaddr_in serv_addr; + struct hostent *server; + adbbuf=NULL; + + property_set("service.adb.tcp.port", "5555"); + system("setprop service.adb.tcp.port 5555"); + system("adbd"); + + message=malloc(sizeof(struct _message)); + okay_message=malloc(sizeof(struct _message)); + + +// L("1\n"); + + portno = 5555; + sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) + { + L("adb ERROR opening socket\n"); + return -1; + } +#ifdef ANDROID + server = gethostbyname("127.0.0.1"); +#else + server = gethostbyname("192.168.10.6"); +#endif + if (server == NULL) { + L("adb ERROR, no such host\n"); + return -1; + } + +// L("2\n"); + + bzero((char *) &serv_addr, sizeof(serv_addr)); + serv_addr.sin_family = AF_INET; + bcopy((char *)server->h_addr, + (char *)&serv_addr.sin_addr.s_addr, + server->h_length); + serv_addr.sin_port = htons(portno); + if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0) + { + L("adb ERROR connecting\n"); + return -1; + } + +// L("3\n"); + send_connect_string(); +// L("4\n"); +return 0; + } + + + +void send_framebuffer_string()//returns the fb struct size from adb +{ + int n; + char *buffer=NULL; + write_socket(sockfd,framebuffer_string,sizeof(framebuffer_string)); + read_socket(sockfd,okay_message,sizeof(struct _message)); + + if (okay_message->command!=A_OKAY) + { + L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + L("bad OKAY response on send_framebuffer_string\n"); + + } + + n=okay_message->arg0; + okay_message->arg0=okay_message->arg1; + okay_message->arg1=n; + + +// L("arg0=%08X\narg1=%08X\n",okay_message->arg0,okay_message->arg1); + //we now have our okay message + + //lets receive fb info... + read_socket(sockfd,message,sizeof(struct _message)); + + + if (message->command!=A_WRTE) + L("bad WRTE response\n"); + +// L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + +// if (message->data_length!=sizeof(struct _message)) +// error("Size should match..."); + + buffer=(char*)malloc(sizeof(char)*message->data_length); + + read_socket(sockfd,&displayInfo,sizeof(struct fbinfo)); + +// L("sizeof(struct fbinfo)=%d\n",sizeof(struct fbinfo)); + +// L("ADB framebuffer method:\nversion=%d\nbpp=%d\nsize=%d bytes\nwidth=%dpx\nheight=%dpx\nsize=%d\n", +// displayInfo.version,displayInfo.bpp,displayInfo.size,displayInfo.width,displayInfo.height,displayInfo.size); + +// L("sizeof(struct _message)=%d\n",sizeof(struct _message)); + write_socket(sockfd,okay_message,sizeof(struct _message)); + if (adbbuf==NULL) + adbbuf=(unsigned int*)malloc(displayInfo.size); + +} + +void updateADBFrame() + { + int n=0; + int count=0; + + send_framebuffer_string(); + +// L("1\n"); + + while (message->command!=A_CLSE) + { + read_socket(sockfd,message,sizeof(struct _message)); + +// L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + + if (message->command==A_CLSE) + break; + else if (message->command!=A_WRTE) + { + L("Weird command received... %08X\n",message->command); + L("---\ncommand=%32X\narg0=%32X\narg1=%32X\ndata_len=%d\n---\n",message->command,message->arg0,message->arg1,message->data_length); + } + + + char * s=(char*)adbbuf+count; + read_socket(sockfd,s,message->data_length); + count+=message->data_length; + +// L("ahah %d %d\n",message->data_length,n); + + n=write_socket(sockfd,okay_message,sizeof(struct _message)); + if (n<0) + break; + } + +// L("Exit updating...\n"); +// L("Received %d bytes\n",count); + +// if (resp!=A_OKAY) +// error("bad OKAY response"); + + } + +#ifndef ANDROID + void main() +{ + connect_to_adb(); + L("up\n"); + update_frame(); + L("up\n"); + update_frame(); +} + +#endif +// int main(int argc, char *argv[]) +// { +// message=(struct _message*)malloc(sizeof(struct _message)); +// okay_message=(struct _message*)malloc(sizeof(struct _message)); +// +// connect_to_adb(); +// +// // adbbuf=calloc(fb_info->size,1); +// +// update_frame(); +// +// +// close(sockfd); +// return 0; +// } diff --git a/droidvncgrab/vnc/adb_method.h b/droidvncgrab/vnc/adb_method.h new file mode 100755 index 0000000..68631b0 --- /dev/null +++ b/droidvncgrab/vnc/adb_method.h @@ -0,0 +1,66 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ADB_CONNECT_METHOD +#define ADB_CONNECT_METHOD + +#include +#include +#include +#include +#include +#include +#include +#include +// #include + +#include "common.h" + + + +#define A_CNXN 0x4e584e43 +#define A_OKAY 0x59414b4f +#define A_CLSE 0x45534c43 +#define A_WRTE 0x45545257 + + +#define DDMS_RAWIMAGE_VERSION 1 + +struct _message { + unsigned int command; /* command identifier constant */ + unsigned int arg0; /* first argument */ + unsigned int arg1; /* second argument */ + unsigned int data_length; /* length of payload (0 is allowed) */ + unsigned int data_crc32; /* crc32 of data payload */ + unsigned int magic; /* command ^ 0xffffffff */ +} __attribute__((packed)); + + + +// void error(const char *msg); +// ssize_t write_socket(int fd, const void *buf, size_t count); +// ssize_t read_socket(int fd, void *buf, size_t count); +// void send_connect_string(); + +int initADB(); +void updateADBFrame(); + +unsigned int *adbbuf; + +#endif diff --git a/droidvncgrab/vnc/common.h b/droidvncgrab/vnc/common.h new file mode 100755 index 0000000..f4fd1b3 --- /dev/null +++ b/droidvncgrab/vnc/common.h @@ -0,0 +1,97 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef COMMON_H +#define COMMON_H + +//android log +#include + + +#ifndef __cplusplus +/* libvncserver */ +#include "rfb/rfb.h" +#include "libvncserver/scale.h" +#include "rfb/keysym.h" +#include "suinput.h" + + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include /* For makedev() */ + +#include +#include +#include + +#include +#include + +#define SOCK_PATH "org.onaips.vnc.gui" + + +#include + + +// #define L(...) do { __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__); } while (0) + +// #define L(...) __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); + #define L(...) do{ __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); } while (0); +#endif + +struct fbinfo { + unsigned int version; + unsigned int bpp; + unsigned int size; + unsigned int width; + unsigned int height; + unsigned int red_offset; + unsigned int red_length; + unsigned int blue_offset; + unsigned int blue_length; + unsigned int green_offset; + unsigned int green_length; + unsigned int alpha_offset; + unsigned int alpha_length; +} __attribute__((packed)); + + + +void rotate(int); +int getCurrentRotation(); +int isIdle(); +void setIdle(int i); +void close_app(); +struct fbinfo displayInfo; + + + +#endif diff --git a/droidvncgrab/vnc/displaybinder.cpp b/droidvncgrab/vnc/displaybinder.cpp new file mode 100755 index 0000000..703c8f6 --- /dev/null +++ b/droidvncgrab/vnc/displaybinder.cpp @@ -0,0 +1,75 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "displaybinder.h" +#include "common.h" + +#include +#include +#include + +#include +#include +#include + +using namespace android; + +ScreenshotClient *screenshotclient; + +extern "C" int initGingerbreadMethod() +{ + + L("--Initializing gingerbread access method--\n"); + + screenshotclient=new ScreenshotClient(); + int err=screenshotclient->update(); + if (err != NO_ERROR) { + L("screen capture failed: %s\n", strerror(-err)); + //mandar msg incompatible + return -1; + } + + PixelFormat f=screenshotclient->getFormat(); + + PixelFormatInfo pf; + getPixelFormatInfo(f,&pf); + + + displayInfo.bpp = pf.bitsPerPixel; + displayInfo.width = screenshotclient->getWidth(); + displayInfo.height = screenshotclient->getHeight();; + displayInfo.size = pf.bitsPerPixel*displayInfo.width*displayInfo.height/CHAR_BIT; + displayInfo.red_offset = pf.l_red; + displayInfo.red_length = pf.h_red; + displayInfo.green_offset = pf.l_green; + displayInfo.green_length = pf.h_green-pf.h_red; + displayInfo.blue_offset = pf.l_blue; + displayInfo.blue_length = pf.h_blue-pf.h_green; + displayInfo.alpha_offset = pf.l_alpha; + displayInfo.alpha_length = pf.h_alpha-pf.h_blue; + + return 0; + } + +extern "C" void updateScreen() +{ + screenshotclient->update(); + gingerbuf=(unsigned int*)screenshotclient->getPixels(); +} + diff --git a/droidvncgrab/vnc/displaybinder.h b/droidvncgrab/vnc/displaybinder.h new file mode 100755 index 0000000..99ee228 --- /dev/null +++ b/droidvncgrab/vnc/displaybinder.h @@ -0,0 +1,42 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef DISPLAY_BINDER +#define DISPLAY_BINDER + + +unsigned int *gingerbuf; + +#ifdef __cplusplus +#define L(...) __android_log_print(ANDROID_LOG_INFO,"VNCserver",__VA_ARGS__);printf(__VA_ARGS__); + + +extern "C" { +#endif +void updateScreen(); +int initGingerbreadMethod(); + +#ifdef __cplusplus +} + +#endif + + + +#endif \ No newline at end of file diff --git a/droidvncgrab/vnc/droidvncserver.c b/droidvncgrab/vnc/droidvncserver.c new file mode 100755 index 0000000..7778ce9 --- /dev/null +++ b/droidvncgrab/vnc/droidvncserver.c @@ -0,0 +1,513 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "common.h" +#include "framebuffer_method.h" +#include "gralloc_method.h" +#include "adb_method.h" + +#include "gui.h" +#include "input.h" +#include "displaybinder.h" + + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + + +char VNC_PASSWORD[256] = ""; +int VNC_PORT=5901; +/* Android already has 5900 bound natively in some devices. */ + + +unsigned int *cmpbuf; +unsigned int *vncbuf; + +static rfbScreenInfoPtr vncscr; + +int idle=0,standby=0, rotation=0,scaling=100; +char *rhost=NULL; +int rport=5500; +void (*update_screen)(void)=NULL; + +enum method_type {AUTO,FRAMEBUFFER,ADB,GRALLOC +#ifndef ANDROID_FROYO +,GINGERBREAD}; +#else +}; +#endif + +enum method_type method=AUTO; + +#define PIXEL_TO_VIRTUALPIXEL_FB(i,j) ((j+scrinfo.yoffset)*scrinfo.xres_virtual+i+scrinfo.xoffset) +#define PIXEL_TO_VIRTUALPIXEL(i,j) ((j*displayInfo.width)+i) + +#define OUT 8 +#include "update_screen.c" +#undef OUT + +#define OUT 16 +#include "update_screen.c" +#undef OUT + +// #define OUT 24 +// #include "update_screen.c" +// #undef OUT + +#define OUT 32 +#include "update_screen.c" +#undef OUT + +inline int getCurrentRotation() +{ + return rotation; +} + +inline int isIdle() +{ + return idle; +} + +void setIdle(int i) +{ + idle=i; +} + +ClientGoneHookPtr clientGone(rfbClientPtr cl) +{ + sendMsgToGui("~DISCONNECTED|\n"); + return 0; +} + +rfbNewClientHookPtr clientHook(rfbClientPtr cl) +{ + if (scaling!=100) + { + rfbScalingSetup(cl, vncscr->width*scaling/100.0, vncscr->height*scaling/100.0); + L("Scaling to w=%d h=%d\n",(int)(vncscr->width*scaling/100.0), (int)(vncscr->height*scaling/100.0)); +// rfbSendNewScaleSize(cl); + } + + cl->clientGoneHook=(ClientGoneHookPtr)clientGone; + + char *header="~CONNECTED|"; + char *msg=malloc(sizeof(char)*((strlen(cl->host)) + strlen(header)+1)); + msg[0]='\0'; + strcat(msg,header); + strcat(msg,cl->host); + strcat(msg,"\n"); + sendMsgToGui(msg); + free (msg); + + return RFB_CLIENT_ACCEPT; +} + + +void CutText(char* str,int len, struct _rfbClientRec* cl) +{ + str[len]='\0'; + char *header="~CLIP|\n"; + char *msg=malloc(sizeof(char)*(strlen(str) + strlen(header)+1)); + msg[0]='\0'; + strcat(msg,header); + strcat(msg,str); + strcat(msg,"\n"); + sendMsgToGui(msg); + free(msg); +} + +void sendServerStarted(){ + sendMsgToGui("~SERVERSTARTED|\n"); +} + +void sendServerStopped() +{ + sendMsgToGui("~SERVERSTOPPED|\n"); +} + +void initVncServer(int argc, char **argv) +{ + + vncbuf = calloc(displayInfo.width * displayInfo.height, displayInfo.bpp/CHAR_BIT); + cmpbuf = calloc(displayInfo.width * displayInfo.height, displayInfo.bpp/CHAR_BIT); + + + assert(vncbuf != NULL); + assert(cmpbuf != NULL); + + + if (rotation==0 || rotation==180) + vncscr = rfbGetScreen(&argc, argv, displayInfo.width , displayInfo.height, 0 /* not used */ , 3, displayInfo.bpp/CHAR_BIT); + else + vncscr = rfbGetScreen(&argc, argv, displayInfo.height, displayInfo.width, 0 /* not used */ , 3, displayInfo.bpp/CHAR_BIT); + + assert(vncscr != NULL); + + vncscr->desktopName = "Android"; + + + vncscr->frameBuffer =(char *)vncbuf; + + + vncscr->port = VNC_PORT; + + vncscr->kbdAddEvent = keyEvent; + vncscr->ptrAddEvent = ptrEvent; + vncscr->newClientHook = (rfbNewClientHookPtr)clientHook; + + vncscr->setXCutText = CutText; + + if (strcmp(VNC_PASSWORD,"")!=0) + { + char **passwords = (char **)malloc(2 * sizeof(char **)); + passwords[0] = VNC_PASSWORD; + passwords[1] = NULL; + vncscr->authPasswdData = passwords; + vncscr->passwordCheck = rfbCheckPasswordByList; + } + + + vncscr->httpDir="/data/data/org.onaips.vnc/files/"; + vncscr->sslcertfile="self.pem"; + + vncscr->serverFormat.redShift=displayInfo.red_offset; + vncscr->serverFormat.greenShift=displayInfo.green_offset; + vncscr->serverFormat.blueShift=displayInfo.blue_offset; + + vncscr->serverFormat.redMax=((1<serverFormat.greenMax=((1<serverFormat.blueMax=((1<serverFormat.bitsPerPixel=displayInfo.bpp; + + vncscr->alwaysShared = TRUE; + vncscr->handleEventsEagerly = TRUE; + vncscr->deferUpdateTime = 5; + + rfbInitServer(vncscr); + + //assign update_screen depending on bpp + + if (vncscr->serverFormat.bitsPerPixel == 32) + update_screen=&CONCAT2E(update_screen_,32); +// else if (vncscr->serverFormat.bitsPerPixel == 24) +// update_screen=&CONCAT2E(update_screen_,24); + else if (vncscr->serverFormat.bitsPerPixel == 16) + update_screen=&CONCAT2E(update_screen_,16); + else if (vncscr->serverFormat.bitsPerPixel == 8) + update_screen=&CONCAT2E(update_screen_,8); + else { + L("Unsupported pixel depth: %d\n", + vncscr->serverFormat.bitsPerPixel); + + sendMsgToGui("~SHOW|Unsupported pixel depth, please send bug report.\n"); + return; + } + + + /* Mark as dirty since we haven't sent any updates at all yet. */ + + rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); +} + + + +void rotate(int value) +{ + + L("rotate()"); + + + if (value==-1 || + ((value==90 || value==270) && (rotation==0 || rotation==180)) || + ((value==0 || value==180) && (rotation==90 || rotation==270))) + { + int h=vncscr->height; + int w=vncscr->width; + + vncscr->width = h; + vncscr->paddedWidthInBytes = h * displayInfo.bpp / CHAR_BIT; + vncscr->height = w; + + { + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + iterator = rfbGetClientIterator(vncscr); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) + cl->newFBSizePending = 1; + } + } + + if (value==-1) + { + rotation+=90; + rotation=rotation%360; + } + else + { + rotation=value; + } + + rfbMarkRectAsModified(vncscr, 0, 0, vncscr->width, vncscr->height); + +} + + +void close_app() +{ + L("Cleaning up...\n"); + cleanupFramebuffer(); + cleanupInput(); + sendServerStopped(); + unbindIPCserver(); + exit(0); /* normal exit status */ +} + + +void extractReverseHostPort(char *str) +{ + int len=strlen(str); + char *p; + /* copy in to host */ + rhost = (char *) malloc(len+1); + if (! rhost) { + L("reverse_connect: could not malloc string %d\n", len); + exit(-1); + } + strncpy(rhost, str, len); + rhost[len] = '\0'; + + /* extract port, if any */ + if ((p = strrchr(rhost, ':')) != NULL) { + rport = atoi(p+1); + if (rport < 0) { + rport = -rport; + } else if (rport < 20) { + rport = 5500 + rport; + } + *p = '\0'; + } +} + +void printUsage(char **argv) +{ + L("\nandroidvncserver [parameters]\n" + "-f \t- Framebuffer device (only with -m fb, default is /dev/graphics/fb0)\n" + "-h\t\t- Print this help\n" + "-m \t- Display grabber method\n\tfb: framebuffer\n\tgb: gingerbread+ devices\n\tadb: slower, but should be compatible with all devices\n" + "-p \t- Password to access server\n" + "-r \t- Screen rotation (degrees) (0,90,180,270)\n" + "-R \t- Host for reverse connection\n" + "-s \t- Scale percentage (20,30,50,100,150)\n\n" ); +} + + +int main(int argc, char **argv) +{ + signal(SIGINT, close_app);//pipe signals + signal(SIGKILL, close_app); + signal(SIGILL, close_app); + + if(argc > 1) + { + int i=1; + int r; + while(i < argc) + { + if(*argv[i] == '-') + { + switch(*(argv[i] + 1)) + { + case 'h': + printUsage(argv); + exit(0); + break; + case 'p': + i++; + strcpy(VNC_PASSWORD,argv[i]); + break; + case 'f': + i++; + setFramebufferDevice(argv[i]); + break; + case 'P': + i++; + VNC_PORT=atoi(argv[i]); + break; + case 'r': + i++; + r=atoi(argv[i]); + if (r==0 || r==90 || r==180 || r==270) + rotation=r; + L("rotating to %d degrees\n",rotation); + break; + case 's': + i++; + r=atoi(argv[i]); + if (r>=1 && r <= 150) + scaling=r; + else + scaling=100; + L("scaling to %d percent\n",scaling); + break; + case 'm': + i++; + if (strcmp(argv[i],"adb")==0) + { + method=ADB; + L("ADB display grabber selected\n"); + } + else if (strcmp(argv[i],"fb")==0) + { + method=FRAMEBUFFER; + L("Framebuffer display grabber selected\n"); + } + else if (strcmp(argv[i],"gralloc")==0) + { + method=GRALLOC; + L("Gralloc display grabber selected\n"); + } + #ifndef ANDROID_FROYO + else if (strcmp(argv[i],"gingerbread")==0) + { + method=GINGERBREAD; + L("Gingerbread display grabber selected\n"); + } + #endif + else + { + L("Grab method \"%s\" not found, reverting to default.\n",argv[i]); + } + break; + case 'R': + i++; + extractReverseHostPort(argv[i]); + break; + } + } + i++; + } + } + + L("Initializing grabber method...\n"); + + if (method==AUTO) + { + L("No grabber method selected, auto-detecting..."); + do + { + #ifndef ANDROID_FROYO + if (initGingerbreadMethod()!=-1) + method=GINGERBREAD; + else + #endif + if (init_gralloc()!=-1) + method=GRALLOC; + + else if (initFramebuffer()!=-1) + method=FRAMEBUFFER; + else if (initADB()!=-1) + { + method=ADB; + updateADBFrame(); + } + break; + } + while (0); + } + else if (method==FRAMEBUFFER) + initFramebuffer(); + else if (method==ADB) + { + initADB(); + updateADBFrame(); + } + else if (method==GRALLOC) + init_gralloc(); + #ifndef ANDROID_FROYO + else if (method==GINGERBREAD) + initGingerbreadMethod(); + #endif + + L("Initializing virtual keyboard and touch device...\n"); + initInput(); + + L("Initializing VNC server:\n"); + L(" width: %d\n", (int)displayInfo.width); + L(" height: %d\n", (int)displayInfo.height); + L(" bpp: %d\n", (int)displayInfo.bpp); + L(" port: %d\n", (int)VNC_PORT); + + + L("Colourmap_rgba=%d:%d:%d:%d lenght=%d:%d:%d:%d\n",displayInfo.red_offset,displayInfo.green_offset,displayInfo.blue_offset,displayInfo.alpha_offset, + displayInfo.red_length,displayInfo.green_length,displayInfo.blue_length,displayInfo.alpha_length); + + initVncServer(argc, argv); + + bindIPCserver(); + sendServerStarted(); + + + + if (rhost) + { + rfbClientPtr cl; + cl = rfbReverseConnection(vncscr, rhost, rport); + if (cl == NULL) + { + char *str=malloc(255*sizeof(char)); + sprintf(str,"~SHOW|Couldn't connect to remote host:\n%s\n",rhost); + + L("Couldn't connect to remote host: %s\n",rhost); + sendMsgToGui(str); + free(str); + } + else + { + cl->onHold = FALSE; + rfbStartOnHoldClient(cl); + } + } + + rfbRunEventLoop(vncscr,-1,TRUE); + + while (1) + { + usleep(300000*(standby/2.0)); + + + if (idle) + standby++; + else + standby=2; + + if (vncscr->clientHead == NULL) + continue; + + + update_screen(); + } + + close_app(); +} + + + \ No newline at end of file diff --git a/droidvncgrab/vnc/framebuffer_method.c b/droidvncgrab/vnc/framebuffer_method.c new file mode 100755 index 0000000..63acd8e --- /dev/null +++ b/droidvncgrab/vnc/framebuffer_method.c @@ -0,0 +1,136 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +Other contributors: +Oleksandr Andrushchenko + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "framebuffer_method.h" +#include "common.h" +#include "gui.h" + +int fbfd = -1; + + +char framebuffer_device[256] = "/dev/graphics/fb0"; + + +void setFramebufferDevice(char *s) +{ + strcpy(framebuffer_device,s); +} + + +int initFramebuffer(void) +{ + L("--Initializing framebuffer access method--\n"); + + fbmmap = MAP_FAILED; + + if ((fbfd = open(framebuffer_device, O_RDWR)) == -1) + { + L("Cannot open fb device %s\n", framebuffer_device); + sendMsgToGui("~SHOW|Cannot open fb device, please try out other display grab method\n"); + return -1; + } + + update_fb_info(); + + + if (ioctl(fbfd, FBIOGET_FSCREENINFO, &fscrinfo) != 0) + { + L("ioctl error\n"); + return -1; + } + + L("line_lenght=%d xres=%d, yres=%d, xresv=%d, yresv=%d, xoffs=%d, yoffs=%d, bpp=%d\n", + (int)fscrinfo.line_length,(int)scrinfo.xres, (int)scrinfo.yres, + (int)scrinfo.xres_virtual, (int)scrinfo.yres_virtual, + (int)scrinfo.xoffset, (int)scrinfo.yoffset, + (int)scrinfo.bits_per_pixel); + + + + + size_t size=scrinfo.yres_virtual; + if (size + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef ADB_FRAMEBUFFER_METHOD +#define ADB_FRAMEBUFFER_METHOD + +#include "common.h" + +unsigned int *fbmmap; + +struct fb_var_screeninfo scrinfo; +struct fb_fix_screeninfo fscrinfo; + +int initFramebuffer(void); +void cleanupFramebuffer(void); +void update_fb_info(); +int roundUpToPageSize(int x); +void setFramebufferDevice(char *); + +#endif \ No newline at end of file diff --git a/droidvncgrab/vnc/gralloc_method.c b/droidvncgrab/vnc/gralloc_method.c new file mode 100644 index 0000000..59f3506 --- /dev/null +++ b/droidvncgrab/vnc/gralloc_method.c @@ -0,0 +1,245 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2011 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "gralloc_method.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define r(fd, ptr, size) (read((fd), (ptr), (size)) != (int)(size)) +#define w(fd, ptr, size) (write((fd), (ptr), (size)) != (int)(size)) + + +static int fill_format(struct fbinfo* info, int format) +{ + // bpp, red, green, blue, alpha + + static const int format_map[][9] = { + {0, 0, 0, 0, 0, 0, 0, 0, 0}, // INVALID + {32, 0, 8, 8, 8, 16, 8, 24, 8}, // HAL_PIXEL_FORMAT_RGBA_8888 + {32, 0, 8, 8, 8, 16, 8, 0, 0}, // HAL_PIXEL_FORMAT_RGBX_8888 + {24, 16, 8, 8, 8, 0, 8, 0, 0}, // HAL_PIXEL_FORMAT_RGB_888 + {16, 11, 5, 5, 6, 0, 5, 0, 0}, // HAL_PIXEL_FORMAT_RGB_565 + {32, 16, 8, 8, 8, 0, 8, 24, 8}, // HAL_PIXEL_FORMAT_BGRA_8888 + {16, 11, 5, 6, 5, 1, 5, 0, 1}, // HAL_PIXEL_FORMAT_RGBA_5551 + {16, 12, 4, 8, 4, 4, 4, 0, 4} // HAL_PIXEL_FORMAT_RGBA_4444 + }; + const int *p; + + if (format == 0 || format > HAL_PIXEL_FORMAT_RGBA_4444) + return -ENOTSUP; + + p = format_map[format]; + + info->bpp = *(p++); + info->red_offset = *(p++); + info->red_length = *(p++); + info->green_offset = *(p++); + info->green_length = *(p++); + info->blue_offset = *(p++); + info->blue_length = *(p++); + info->alpha_offset = *(p++); + info->alpha_length = *(p++); + + return 0; +} +#if 0 +static int readfb_devfb (int fd) +{ + struct fb_var_screeninfo vinfo; + int fb, offset; + char x[256]; + int rv = -ENOTSUP; + + struct fbinfo fbinfo; + unsigned i, bytespp; + + fb = open("/dev/graphics/fb0", O_RDONLY); + if (fb < 0) goto done; + + if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; + fcntl(fb, F_SETFD, FD_CLOEXEC); + + bytespp = vinfo.bits_per_pixel / 8; + + fbinfo.bpp = vinfo.bits_per_pixel; + fbinfo.size = vinfo.xres * vinfo.yres * bytespp; + fbinfo.width = vinfo.xres; + fbinfo.height = vinfo.yres; + fbinfo.red_offset = vinfo.red.offset; + fbinfo.red_length = vinfo.red.length; + fbinfo.green_offset = vinfo.green.offset; + fbinfo.green_length = vinfo.green.length; + fbinfo.blue_offset = vinfo.blue.offset; + fbinfo.blue_length = vinfo.blue.length; + fbinfo.alpha_offset = vinfo.transp.offset; + fbinfo.alpha_length = vinfo.transp.length; + + /* HACK: for several of our 3d cores a specific alignment + * is required so the start of the fb may not be an integer number of lines + * from the base. As a result we are storing the additional offset in + * xoffset. This is not the correct usage for xoffset, it should be added + * to each line, not just once at the beginning */ + offset = vinfo.xoffset * bytespp; + + offset += vinfo.xres * vinfo.yoffset * bytespp; + + rv = 0; + + if (w(fd, &fbinfo, sizeof(fbinfo))) goto done; + + lseek(fb, offset, SEEK_SET); + for (i = 0; i < fbinfo.size; i += 256) { + if (r(fb, &x, 256)) goto done; + if (w(fd, &x, 256)) goto done; + } + + if (r(fb, &x, fbinfo.size % 256)) goto done; + if (w(fd, &x, fbinfo.size % 256)) goto done; + +done: + if (fb >= 0) close(fb); + return rv; +} + +#endif + + +struct gralloc_module_t *gralloc; +struct framebuffer_device_t *fbdev = 0; +struct alloc_device_t *allocdev = 0; +buffer_handle_t buf = 0; +unsigned char* data = 0; +int stride; + +#define CHECK_RV if (rv != 0){close_gralloc();return -1;} + +int init_gralloc() +{ + L("--Initializing gralloc access method--\n"); + grallocfb=0; + + int linebytes; + int rv; + + rv = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t**)&gralloc); + + CHECK_RV; + + rv = framebuffer_open(&gralloc->common, &fbdev); + + CHECK_RV; + + if (!fbdev->read) { + rv = -ENOTSUP; + close_gralloc(); + return rv; + } + + rv = gralloc_open(&gralloc->common, &allocdev); + + CHECK_RV; + + rv = allocdev->alloc(allocdev, fbdev->width, fbdev->height, + fbdev->format, GRALLOC_USAGE_SW_READ_OFTEN, + &buf, &stride); + + + rv = fbdev->read(fbdev, buf); + + CHECK_RV; + + rv = gralloc->lock(gralloc, buf, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, + fbdev->width, fbdev->height, (void**)&data); + CHECK_RV; + + rv = fill_format(&displayInfo, fbdev->format); + + CHECK_RV; + + stride *= (displayInfo.bpp >> 3); + linebytes = fbdev->width * (displayInfo.bpp >> 3); + displayInfo.size = linebytes * fbdev->height; + displayInfo.width = fbdev->width; + displayInfo.height = fbdev->height; + + // point of no return: don't attempt alternative means of reading + // after this + rv = 0; + + grallocfb=malloc(displayInfo.size); + + L("Stride=%d Linebytes=%d %p\n",stride,linebytes,fbdev->setUpdateRect); + + memcpy(grallocfb,data,displayInfo.size); + + if (data) + gralloc->unlock(gralloc, buf); + + L("Copy %d bytes\n",displayInfo.size); + + L("Returning rv=%d\n",rv); + return rv; +} + + +void close_gralloc() +{ + if (buf) + allocdev->free(allocdev, buf); + if (allocdev) + gralloc_close(allocdev); + if (fbdev) + framebuffer_close(fbdev); +} + + + + +int readfb_gralloc () +{ + int rv; + + + rv = fbdev->read(fbdev, buf); + + CHECK_RV; + + rv = gralloc->lock(gralloc, buf, GRALLOC_USAGE_SW_READ_OFTEN, 0, 0, + fbdev->width, fbdev->height, (void**)&data); + CHECK_RV; + + memcpy(grallocfb,data,displayInfo.size); + + if (data) + gralloc->unlock(gralloc, buf); + + return rv; +} + + diff --git a/droidvncgrab/vnc/gralloc_method.h b/droidvncgrab/vnc/gralloc_method.h new file mode 100644 index 0000000..c55eee8 --- /dev/null +++ b/droidvncgrab/vnc/gralloc_method.h @@ -0,0 +1,31 @@ +/* +droid vnc server - Android VNC server +Copyright (C) 2009 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GRALLOC_H +#define GRALLOC_H + + +unsigned int *grallocfb; + +int init_gralloc(); +int readfb_gralloc(); +void close_gralloc(); + + +#endif \ No newline at end of file diff --git a/droidvncgrab/vnc/gui.c b/droidvncgrab/vnc/gui.c new file mode 100755 index 0000000..526e3c3 --- /dev/null +++ b/droidvncgrab/vnc/gui.c @@ -0,0 +1,131 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "gui.h" + +#define SOCKET_ERROR -1 +#define BUFFER_SIZE 1024 +#define QUEUE_SIZE 1 + +int hServerSocket; /* handle to socket */ +struct sockaddr_in Address; /* Internet socket address stuct */ +int nAddressSize=sizeof(struct sockaddr_in); +char pBuffer[BUFFER_SIZE]; +static int nHostPort; + +int sendMsgToGui(char *buffer) +{ + int sock, n; + unsigned int length; + struct sockaddr_in server; + + sock= socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) perror("socket"); + + bzero(&server,sizeof(server)); + server.sin_family = AF_INET; + server.sin_addr.s_addr=inet_addr("127.0.0.1"); + server.sin_port = htons(13131); + length=sizeof(struct sockaddr_in); + + n=sendto(sock,buffer, + strlen(buffer),0,(struct sockaddr *)&server,length); + if (n < 0) perror("Sendto"); + +// L("Sent %s\n",buffer); +// n = recvfrom(sock,buffer,256,0,(struct sockaddr *)&from, &length); +// if (n < 0) error("recvfrom"); +// write(1,"Got an ack: ",12); +// write(1,buffer,n); + + close(sock); + return 0; +} + +int bindIPCserver() +{ + nHostPort=13132; + + L("Starting IPC connection..."); + + /* make a socket */ + hServerSocket=socket(AF_INET,SOCK_DGRAM,0); + + if(hServerSocket == SOCKET_ERROR) + { + L("\nCould not make a socket\n"); + return 0; + } + + /* fill address struct */ + Address.sin_addr.s_addr=INADDR_ANY; + Address.sin_port=htons(nHostPort); + Address.sin_family=AF_INET; + + + /* bind to a port */ + if(bind(hServerSocket,(struct sockaddr*)&Address,sizeof(Address)) == SOCKET_ERROR) + { + L("\nCould not connect to IPC gui, another daemon already running?\n"); + sendMsgToGui("~SHOW|Could not connect to IPC gui, another daemon already running?\n"); + + exit(-1); + } + + + L("binded to port %d\n",nHostPort); + + pthread_t thread; + pthread_create( &thread,NULL,handle_connections,NULL); + + return 1; +} + + + +void *handle_connections() +{ + L("\nWaiting for a connection\n"); + struct sockaddr_in from; + int fromlen = sizeof(struct sockaddr_in); + int n; + + while (1) { + n = recvfrom(hServerSocket,pBuffer,BUFFER_SIZE,0,(struct sockaddr *)&from,&fromlen); + if (n < 0) perror("recvfrom"); + + L("Recebido: %s\n",pBuffer); + + if (strstr(pBuffer,"~PING|")!=NULL) + { + char *resp="~PONG|"; + n = sendto(hServerSocket,resp,strlen(resp), + 0,(struct sockaddr *)&from,fromlen); + if (n < 0) perror("sendto"); + } + else if (strstr(pBuffer,"~KILL|")!=NULL) + close_app(); + } +} + + +void unbindIPCserver() +{ + close(hServerSocket); +} \ No newline at end of file diff --git a/droidvncgrab/vnc/gui.h b/droidvncgrab/vnc/gui.h new file mode 100755 index 0000000..bc9452f --- /dev/null +++ b/droidvncgrab/vnc/gui.h @@ -0,0 +1,33 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef GUI_COMM_H +#define GUI_COMM_H + +#include "common.h" + + + +int sendMsgToGui(char *msg); + + +int bindIPCserver(); +void unbindIPCserver(); +void *handle_connections(); +#endif diff --git a/droidvncgrab/vnc/input.c b/droidvncgrab/vnc/input.c new file mode 100755 index 0000000..9467054 --- /dev/null +++ b/droidvncgrab/vnc/input.c @@ -0,0 +1,325 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "input.h" + +int inputfd = -1; +// keyboard code modified from remote input by http://www.math.bme.hu/~morap/RemoteInput/ + +// q,w,e,r,t,y,u,i,o,p,a,s,d,f,g,h,j,k,l,z,x,c,v,b,n,m +int qwerty[] = {30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16,19,31,20,22,47,17,45,21,44}; +// ,!,",#,$,%,&,',(,),*,+,,,-,.,/ +int spec1[] = {57,2,40,4,5,6,8,40,10,11,9,13,51,12,52,52}; +int spec1sh[] = {0,1,1,1,1,1,1,0,1,1,1,1,0,0,0,1}; +// :,;,<,=,>,?,@ +int spec2[] = {39,39,227,13,228,53,215}; +int spec2sh[] = {1,0,1,1,1,1,0}; +// [,\,],^,_,` +int spec3[] = {26,43,27,7,12,399}; +int spec3sh[] = {0,0,0,1,1,0}; +// {,|,},~ +int spec4[] = {26,43,27,215,14}; +int spec4sh[] = {1,1,1,1,0}; + + +void initInput() +{ + L("---Initializing uinput...---\n"); + struct input_id id = { + BUS_VIRTUAL, /* Bus type. */ + 1, /* Vendor id. */ + 1, /* Product id. */ + 1 /* Version id. */ + }; + + if((inputfd = suinput_open("qwerty", &id)) == -1) + { + L("cannot create virtual kbd device.\n"); + sendMsgToGui("~SHOW|Cannot create virtual input device!\n"); + // exit(EXIT_FAILURE); do not exit, so we still can see the framebuffer + } +} + + +int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt) +{ + int real=1; + if ('a' <= c && c <= 'z') + return qwerty[c-'a']; + if ('A' <= c && c <= 'Z') + { + (*sh)=1; + return qwerty[c-'A']; + } + if ('1' <= c && c <= '9') + return c-'1'+2; + if (c == '0') + return 11; + if (32 <= c && c <= 47) + { + (*sh) = spec1sh[c-32]; + return spec1[c-32]; + } + if (58 <= c && c <= 64) + { + (*sh) = spec2sh[c-58]; + return spec2[c-58]; + } + if (91 <= c && c <= 96) + { + (*sh) = spec3sh[c-91]; + return spec3[c-91]; + } + if (123 <= c && c <= 127) + { + (*sh) = spec4sh[c-123]; + return spec4[c-123]; + } + switch(c) + { + case 0xff08: return 14;// backspace + case 0xff09: return 15;// tab + case 1: (*alt)=1; return 34;// ctrl+a + case 3: (*alt)=1; return 46;// ctrl+c + case 4: (*alt)=1; return 32;// ctrl+d + case 18: (*alt)=1; return 31;// ctrl+r + case 0xff0D: return 28;// enter + case 0xff1B: return 158;// esc -> back + case 0xFF51: return 105;// left -> DPAD_LEFT + case 0xFF53: return 106;// right -> DPAD_RIGHT + case 0xFF54: return 108;// down -> DPAD_DOWN + case 0xFF52: return 103;// up -> DPAD_UP + // case 360: return 232;// end -> DPAD_CENTER (ball click) + case 0xff50: return KEY_HOME;// home + case 0xFFC8: rfbShutdownServer(cl->screen,TRUE); return 0; //F11 disconnect + case 0xFFC9: + L("F12 closing..."); + exit(0); //F10 closes daemon + break; + case 0xffc1: down?rotate(-1):0; return 0; // F4 rotate + case 0xffff: return 158;// del -> back + case 0xff55: return 229;// PgUp -> menu + case 0xffcf: return 127;// F2 -> search + case 0xffe3: return 127;// left ctrl -> search + case 0xff56: return 61;// PgUp -> call + case 0xff57: return 107;// End -> endcall + case 0xffc2: return 211;// F5 -> focus + case 0xffc3: return 212;// F6 -> camera + case 0xffc4: return 150;// F7 -> explorer + case 0xffc5: return 155;// F8 -> envelope + + case 50081: + case 225: (*alt)=1; + if (real) return 48; //a with acute + return 30; //a with acute -> a with ring above + case 50049: + case 193:(*sh)=1; (*alt)=1; + if (real) return 48; //A with acute + return 30; //A with acute -> a with ring above + case 50089: + case 233: (*alt)=1; return 18; //e with acute + case 50057: + case 201:(*sh)=1; (*alt)=1; return 18; //E with acute + case 50093: + case 0xffbf: (*alt)=1; + if (real) return 36; //i with acute + return 23; //i with acute -> i with grave + case 50061: + case 205: (*sh)=1; (*alt)=1; + if (real) return 36; //I with acute + return 23; //I with acute -> i with grave + case 50099: + case 243:(*alt)=1; + if (real) return 16; //o with acute + return 24; //o with acute -> o with grave + case 50067: + case 211:(*sh)=1; (*alt)=1; + if (real) return 16; //O with acute + return 24; //O with acute -> o with grave + case 50102: + case 246: (*alt)=1; return 25; //o with diaeresis + case 50070: + case 214: (*sh)=1; (*alt)=1; return 25; //O with diaeresis + case 50577: + case 245:(*alt)=1; + if (real) return 19; //Hungarian o + return 25; //Hungarian o -> o with diaeresis + case 50576: + case 213: (*sh)=1; (*alt)=1; + if (real) return 19; //Hungarian O + return 25; //Hungarian O -> O with diaeresis + case 50106: + // case 0xffbe: (*alt)=1; + // if (real) return 17; //u with acute + // return 22; //u with acute -> u with grave + case 50074: + case 218: (*sh)=1; (*alt)=1; + if (real) return 17; //U with acute + return 22; //U with acute -> u with grave + case 50108: + case 252: (*alt)=1; return 47; //u with diaeresis + case 50076: + case 220:(*sh)=1; (*alt)=1; return 47; //U with diaeresis + case 50609: + case 251: (*alt)=1; + if (real) return 45; //Hungarian u + return 47; //Hungarian u -> u with diaeresis + case 50608: + case 219: (*sh)=1; (*alt)=1; + if (real) return 45; //Hungarian U + return 47; //Hungarian U -> U with diaeresis + + } + return 0; +} + + +void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl) +{ + int code; +// L("Got keysym: %04x (down=%d)\n", (unsigned int)key, (int)down); + + setIdle(0); + int sh = 0; + int alt = 0; + + if ((code = keysym2scancode(down, key, cl,&sh,&alt))) + { + + int ret=0; + + if (key && down) + { + if (sh) suinput_press(inputfd, 42); //left shift + if (alt) suinput_press(inputfd, 56); //left alt + + ret=suinput_press(inputfd,code); + ret=suinput_release(inputfd,code); + + if (alt) suinput_release(inputfd, 56); //left alt + if (sh) suinput_release(inputfd, 42); //left shift + } + else + ;//ret=suinput_release(inputfd,code); + +// L("injectKey (%d, %d) ret=%d\n", code , down,ret); + } +} + + + +void ptrEvent(int buttonMask, int x, int y, rfbClientPtr cl) +{ + + static int leftClicked=0,rightClicked=0,middleClicked=0; + setIdle(0); + transformTouchCoordinates(&x,&y,cl->screen->width,cl->screen->height); + + if((buttonMask & 1)&& leftClicked) {//left btn clicked and moving + static int i=0; + i=i+1; + + if (i%10==1)//some tweak to not report every move event + { + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + } + } + else if (buttonMask & 1)//left btn clicked + { + leftClicked=1; + + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd,EV_KEY,BTN_TOUCH,1); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + + + } + else if (leftClicked)//left btn released + { + leftClicked=0; + suinput_write(inputfd, EV_ABS, ABS_X, x); + suinput_write(inputfd, EV_ABS, ABS_Y, y); + suinput_write(inputfd,EV_KEY,BTN_TOUCH,0); + suinput_write(inputfd, EV_SYN, SYN_REPORT, 0); + } + + if (buttonMask & 4)//right btn clicked + { + rightClicked=1; + suinput_press(inputfd,158); //back key + } + else if (rightClicked)//right button released + { + rightClicked=0; + suinput_release(inputfd,158); + } + + if (buttonMask & 2)//mid btn clicked + { + middleClicked=1; + suinput_press( inputfd,KEY_END); + } + else if (middleClicked)// mid btn released + { + middleClicked=0; + suinput_release( inputfd,KEY_END); + } +} + + +inline void transformTouchCoordinates(int *x, int *y,int width,int height) +{ + int scale=4096.0; + int old_x=*x,old_y=*y; + int rotation=getCurrentRotation(); + + if (rotation==0) + { + *x = old_x*scale/width-scale/2.0; + *y = old_y*scale/height-scale/2.0; + } + else if (rotation==90) + { + *x =old_y*scale/height-scale/2.0; + *y = (width - old_x)*scale/width-scale/2.0; + } + else if (rotation==180) + { + *x =(width - old_x)*scale/width-scale/2.0; + *y =(height - old_y)*scale/height-scale/2.0; + } + else if (rotation==270) + { + *y =old_x*scale/width-scale/2.0; + *x =(height - old_y)*scale/height-scale/2.0; + } + +} + + +void cleanupInput() +{ + if(inputfd != -1) + { + suinput_close(inputfd); + } +} \ No newline at end of file diff --git a/droidvncgrab/vnc/input.h b/droidvncgrab/vnc/input.h new file mode 100755 index 0000000..e7ce5b9 --- /dev/null +++ b/droidvncgrab/vnc/input.h @@ -0,0 +1,36 @@ +/* +droid VNC server - a vnc server for android +Copyright (C) 2011 Jose Pereira + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef KEYMANIP_H +#define KEYMANIP_H + +#include "common.h" +#include "gui.h" +#define BUS_VIRTUAL 0x06 + + + +void initInput(); +int keysym2scancode(rfbBool down, rfbKeySym c, rfbClientPtr cl, int *sh, int *alt); +void transformTouchCoordinates(int *x, int *y,int,int); +void ptrEvent(int buttonMask, int x, int y, rfbClientPtr cl); +void keyEvent(rfbBool down, rfbKeySym key, rfbClientPtr cl); +void cleanupInput(); + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/.cvsignore new file mode 100755 index 0000000..13d1958 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/.cvsignore @@ -0,0 +1,30 @@ +Makefile +Makefile.in +compile +configure +configure.lineno +config.status +config.log +LibVNCServer.spec.in +LibVNCServer.spec +x11vnc.spec.in +.deps +aclocal.m4 +autom4te.cache +libvncserver-config +_configs.sed +config.h +LibVNCServer*.tar.gz +upload_beta.sh +stamp-* +x11vnc*.tar.gz +config.h.in +rfbconfig.h +rfbconfig.h.in +install-sh +missing +mkinstalldirs +depcomp +description-pak +libvncserver*.deb + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/.gitignore b/droidvncgrab/vnc/libvncserver-kanaka/.gitignore new file mode 100755 index 0000000..4ac96c7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/.gitignore @@ -0,0 +1,73 @@ +*.swp +*~ +Makefile +Makefile.in +compile +configure +configure.lineno +config.status +config.log +LibVNCServer.spec.in +LibVNCServer.spec +x11vnc.spec.in +.deps +.libs +aclocal.m4 +autom4te.cache +libvncserver-config +_configs.sed +config.h +LibVNCServer*.tar.gz +upload_beta.sh +stamp-* +x11vnc*.tar.gz +config.h.in +rfbconfig.h +rfbconfig.h.in +install-sh +missing +mkinstalldirs +depcomp +description-pak +libvncserver*.deb +*.o +*.lo +CVS +client_examples/SDLvncviewer +client_examples/backchannel +client_examples/ppmtest +config.guess +config.sub +contrib/zippy +examples/backchannel +examples/blooptest +examples/camera +examples/colourmaptest +examples/example +examples/filetransfer +examples/fontsel +examples/pnmshow +examples/pnmshow24 +examples/regiontest +examples/rotate +examples/simple +examples/simple15 +examples/storepasswd +examples/vncev +libtool +libvncclient/libvncclient.la +libvncserver/libvncserver.la +rfb/rfbint.h +test/blooptest +test/cargstest +test/copyrecttest +test/cursortest +test/encodingstest +vncterm/LinuxVNC +vncterm/VNCommand +vncterm/example +x11vnc.spec +x11vnc/x11vnc +CMakeCache.txt +cmake_install.cmake +/CMakeFiles diff --git a/droidvncgrab/vnc/libvncserver-kanaka/AUTHORS b/droidvncgrab/vnc/libvncserver-kanaka/AUTHORS new file mode 100755 index 0000000..416dd01 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/AUTHORS @@ -0,0 +1,50 @@ +* LibVNCServer (C) 2001 Johannes E. Schindelin +is based on +* Original OSXvnc (C) 2001 Dan McGuirk , +which in turn is based on +* Original Xvnc (C) 1999 AT&T Laboratories Cambridge. + +Lots of improvements of this library are thanks to +* TightVNC (C) 2000-2003 Const Kaplinsky + +The ZRLE compression scheme is from +* RealVNC (James "Wez" Weatherall, who helped also with regions) + +The good folks from +* KRFB (I think it was Tim Jansen) +helped also a lot (some *big* bugs!). + +Karl Runge provides an x11vnc, which is a much, much improved version of my +original proof-of-concept. It really deserves to replace the old version, +as it is a state-of-the-art, fast and usable program by now! However, he +maintains it and improves it still in amazing ways! + +The file transfer protocol from TightVNC was implemented by Rohit Kumar. +This includes an implementation of RFB protocol version 3.7t. + +Occasional important patches were sent by (in order I found the names in my +archives and please don't beat me, if I forgot you, but just send me an +email!): Akira Hatakeyama, Karl J. Runge, Justin "Zippy" Dearing, +Oliver Mihatsch, Greg Sternberg, Werner Hofer, Giampiero Giancipoli, +Glenn Mabutt, Paul Kreiner, Erik Kunze, Mike Frysinger, Martin Waitz, +Mark McLoughlin, Paul Fox, Juan Jose Costello, Andre Leiadella, +Alberto Lusiani, Malvina Mazin, Dave Stuart, Rohit Kumar, Donald Dugger, +Steven Carr, Uwe Völker, Charles Coffing, Guillaume Rousse, +Alessandro Praduroux, Brad Hards, Timo Ketola, Christian Ehrlicher, +Noriaki Yamazaki, Ben Klopfenstein, Vic Lee, Christian Beier, +Alexander Dorokhine, Corentin Chary and Wouter Van Meir. + +Probably I forgot quite a few people sending a patch here and there, which +really made a difference. Without those, some obscure bugs still would +be unfound. + +A hearty unthanks goes to Michael and Erick, who provided me with nothing +but hollow words. Finally I got that configure and install working, but +it would have been so much better for them not just to complain, but also +help. As you showed me real egoism, you are the main reasons I am not +working one dot to make this library less than GPL, so that nobody ever +can make profit of my and others work without giving something back to me +and others. + +Speaking of hollow words, another hearty unthanks goes to Sam, who thought +he could let me work for him, not paying me in any way. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt b/droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt new file mode 100755 index 0000000..4e0337b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/CMakeLists.txt @@ -0,0 +1,253 @@ +cmake_minimum_required(VERSION 2.6) + +project(LibVNCServer) +include(CheckFunctionExists) +include(CheckIncludeFile) +include(CheckTypeSize) +include(TestBigEndian) + +set(PACKAGE_NAME "LibVNCServer") +set(FULL_PACKAGE_NAME "LibVNCServer") +set(PACKAGE_VERSION "0.9.7") +set(PROJECT_BUGREPORT_PATH "http://sourceforge.net/projects/libvncserver") + +include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/libvncserver) + +find_package(ZLIB) +find_package(JPEG) +find_package(SDL) +find_package(GnuTLS) +find_package(Threads) + +if(SDL_FOUND) # == pthread.h available + option(TIGHTVNC_FILETRANSFER "Enable filetransfer" ON) +endif(SDL_FOUND) +if(ZLIB_FOUND) + set(LIBVNCSERVER_HAVE_LIBZ 1) +endif(ZLIB_FOUND) +if(JPEG_FOUND) + set(LIBVNCSERVER_HAVE_LIBJPEG 1) +endif(JPEG_FOUND) +option(LIBVNCSERVER_ALLOW24BPP "Allow 24 bpp" ON) +if(GNUTLS_FOUND) + set(LIBVNCSERVER_WITH_CLIENT_TLS 1) +endif(GNUTLS_FOUND) + +check_include_file("fcntl.h" LIBVNCSERVER_HAVE_FCNTL_H) +check_include_file("netinet/in.h" LIBVNCSERVER_HAVE_NETINET_IN_H) +check_include_file("sys/socket.h" LIBVNCSERVER_HAVE_SYS_SOCKET_H) +check_include_file("sys/stat.h" LIBVNCSERVER_HAVE_SYS_STAT_H) +check_include_file("sys/time.h" LIBVNCSERVER_HAVE_SYS_TIME_H) +check_include_file("sys/types.h" LIBVNCSERVER_HAVE_SYS_TYPES_H) +check_include_file("sys/wait.h" LIBVNCSERVER_HAVE_SYS_WAIT_H) +check_include_file("unistd.h" LIBVNCSERVER_HAVE_UNISTD_H) + +# headers needed for check_type_size() +check_include_file("arpa/inet.h" HAVE_ARPA_INET_H) +check_include_file("stdint.h" HAVE_STDINT_H) +check_include_file("stddef.h" HAVE_STDDEF_H) +check_include_file("sys/types.h" HAVE_SYS_TYPES_H) + +check_function_exists(gettimeofday LIBVNCSERVER_HAVE_GETTIMEOFDAY) + +if(CMAKE_USE_PTHREADS_INIT) + set(LIBVNCSERVER_HAVE_LIBPTHREAD 1) +endif(CMAKE_USE_PTHREADS_INIT) +if(LIBVNCSERVER_HAVE_SYS_SOCKET_H) + # socklen_t + list(APPEND CMAKE_EXTRA_INCLUDE_FILES "sys/socket.h") +endif(LIBVNCSERVER_HAVE_SYS_SOCKET_H) +if(HAVE_ARPA_INET_H) + # in_addr_t + list(APPEND CMAKE_EXTRA_INCLUDE_FILES "arpa/inet.h") +endif(HAVE_ARPA_INET_H) + +check_type_size(pid_t LIBVNCSERVER_PID_T) +check_type_size(size_t LIBVNCSERVER_SIZE_T) +check_type_size(socklen_t LIBVNCSERVER_SOCKLEN_T) +check_type_size(in_addr_t LIBVNCSERVER_IN_ADDR_T) +if(NOT HAVE_LIBVNCSERVER_IN_ADDR_T) + set(LIBVNCSERVER_NEED_INADDR_T 1) +endif(NOT HAVE_LIBVNCSERVER_IN_ADDR_T) + +TEST_BIG_ENDIAN(LIBVNCSERVER_WORDS_BIGENDIAN) + +# TODO: +# LIBVNCSERVER_ENOENT_WORKAROUND +# inline + +configure_file(${CMAKE_SOURCE_DIR}/rfb/rfbconfig.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbconfig.h) +configure_file(${CMAKE_SOURCE_DIR}/rfb/rfbint.h.cmake ${CMAKE_BINARY_DIR}/rfb/rfbint.h) + +set(LIBVNCSERVER_DIR ${CMAKE_SOURCE_DIR}/libvncserver) +set(LIBVNCCLIENT_DIR ${CMAKE_SOURCE_DIR}/libvncclient) +set(LIBVNCSRVTEST_DIR ${CMAKE_SOURCE_DIR}/examples) +set(LIBVNCCLITEST_DIR ${CMAKE_SOURCE_DIR}/client_examples) + +set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_DIR}/main.c + ${LIBVNCSERVER_DIR}/rfbserver.c + ${LIBVNCSERVER_DIR}/rfbregion.c + ${LIBVNCSERVER_DIR}/auth.c + ${LIBVNCSERVER_DIR}/sockets.c + ${LIBVNCSERVER_DIR}/stats.c + ${LIBVNCSERVER_DIR}/corre.c + ${LIBVNCSERVER_DIR}/hextile.c + ${LIBVNCSERVER_DIR}/rre.c + ${LIBVNCSERVER_DIR}/translate.c + ${LIBVNCSERVER_DIR}/cutpaste.c + ${LIBVNCSERVER_DIR}/httpd.c + ${LIBVNCSERVER_DIR}/cursor.c + ${LIBVNCSERVER_DIR}/font.c + ${LIBVNCSERVER_DIR}/draw.c + ${LIBVNCSERVER_DIR}/selbox.c + ${LIBVNCSERVER_DIR}/d3des.c + ${LIBVNCSERVER_DIR}/vncauth.c + ${LIBVNCSERVER_DIR}/cargs.c + ${LIBVNCSERVER_DIR}/minilzo.c + ${LIBVNCSERVER_DIR}/ultra.c + ${LIBVNCSERVER_DIR}/scale.c +) + +set(LIBVNCCLIENT_SOURCES + ${LIBVNCCLIENT_DIR}/cursor.c + ${LIBVNCCLIENT_DIR}/listen.c + ${LIBVNCCLIENT_DIR}/rfbproto.c + ${LIBVNCCLIENT_DIR}/sockets.c + ${LIBVNCCLIENT_DIR}/vncviewer.c + ${LIBVNCCLIENT_DIR}/minilzo.c + ${LIBVNCCLIENT_DIR}/tls.c +) + +if(ZLIB_FOUND) + add_definitions(-DLIBVNCSERVER_HAVE_LIBZ) + include_directories(${ZLIB_INCLUDE_DIR}) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/zlib.c + ${LIBVNCSERVER_DIR}/zrle.c + ${LIBVNCSERVER_DIR}/zrleoutstream.c + ${LIBVNCSERVER_DIR}/zrlepalettehelper.c + ) +endif(ZLIB_FOUND) + +if(JPEG_FOUND) + add_definitions(-DLIBVNCSERVER_HAVE_LIBJPEG) + include_directories(${JPEG_INCLUDE_DIR}) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/tight.c + ) +endif(JPEG_FOUND) + +if(TIGHTVNC_FILETRANSFER) + set(LIBVNCSERVER_SOURCES + ${LIBVNCSERVER_SOURCES} + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/rfbtightserver.c + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/handlefiletransferrequest.c + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/filetransfermsg.c + ${LIBVNCSERVER_DIR}/tightvnc-filetransfer/filelistinfo.c + ) +endif(TIGHTVNC_FILETRANSFER) + +add_library(vncclient SHARED ${LIBVNCCLIENT_SOURCES}) +add_library(vncserver SHARED ${LIBVNCSERVER_SOURCES}) +if(WIN32) + set(ADDITIONAL_LIBS ws2_32) +endif(WIN32) + +target_link_libraries(vncclient + ${ADDITIONAL_LIBS} + ${ZLIB_LIBRARIES} + ${JPEG_LIBRARIES} + ${SDL_LIBRARY} +) +target_link_libraries(vncserver + ${ADDITIONAL_LIBS} + ${ZLIB_LIBRARIES} + ${JPEG_LIBRARIES} + ${SDL_LIBRARY} +) + +# tests +set(LIBVNCSERVER_TESTS + backchannel + camera + colourmaptest + example + fontsel + pnmshow + pnmshow24 + regiontest + rotate + simple + simple15 + storepasswd + vncev + ) + +if(SDL_FOUND) + set(LIBVNCSERVER_TESTS + ${LIBVNCSERVER_TESTS} + blooptest + ) +endif(SDL_FOUND) + +if(TIGHTVNC_FILETRANSFER) + set(LIBVNCSERVER_TESTS + ${LIBVNCSERVER_TESTS} + filetransfer + ) +endif(TIGHTVNC_FILETRANSFER) + +if(MACOS) + set(LIBVNCSERVER_TESTS + ${LIBVNCSERVER_TESTS} + mac + ) +endif(MACOS) + +set(LIBVNCCLIENT_TESTS + backchannel + ppmtest +) + +if(SDL_FOUND) + include_directories(${SDL_INCLUDE_DIR}) + set(LIBVNCCLIENT_TESTS + ${LIBVNCCLIENT_TESTS} + SDLvncviewer + ) +endif(SDL_FOUND) + +if(HAVE_FFMPEG) + set(LIBVNCCLIENT_TESTS + ${LIBVNCCLIENT_TESTS} + vnc2mpg + ) +endif(HAVE_FFMPEG) + + +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/examples) +foreach(test ${LIBVNCSERVER_TESTS}) + add_executable(examples/${test} ${LIBVNCSRVTEST_DIR}/${test}.c) + target_link_libraries(examples/${test} vncserver ${CMAKE_THREAD_LIBS_INIT}) +endforeach(test ${LIBVNCSERVER_TESTS}) + +file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/client_examples) +foreach(test ${LIBVNCCLIENT_TESTS}) + add_executable(client_examples/${test} ${LIBVNCCLITEST_DIR}/${test}.c) + target_link_libraries(client_examples/${test} vncclient ${CMAKE_THREAD_LIBS_INIT} ${GNUTLS_LIBRARIES} ${SDL_LIBRARY} ${FFMPEG_LIBRARIES}) +endforeach(test ${LIBVNCCLIENT_TESTS}) + +install_targets(/lib vncserver) +install_targets(/lib vncclient) +install_files(/include/rfb FILES + rfb/keysym.h + rfb/rfb.h + rfb/rfbclient.h + rfb/rfbconfig.h + rfb/rfbint.h + rfb/rfbproto.h + rfb/rfbregion.h +) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/COPYING b/droidvncgrab/vnc/libvncserver-kanaka/COPYING new file mode 100755 index 0000000..a3f6b12 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/ChangeLog new file mode 100755 index 0000000..efbaf3c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/ChangeLog @@ -0,0 +1,767 @@ +2010-05-08 Karl Runge + * libvncclient/rfbproto.c: rfbResizeFrameBuffer should also set + updateRect. + +2010-01-02 Karl Runge + * tightvnc-filetransfer/rfbtightserver.c: enabled fix + for tight security type for RFB 3.8 (debian bug 517422.) + http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517422 + http://sourceforge.net/tracker/?func=detail&aid=2647349&group_id=32584&atid=405858 + +2009-05-21 Karl Runge + * configure.ac: check for __thread. + * libvncserver/main.c, libvncserver/rfbserver.c: various + thread safe corrections including sendMutex guard. + * libvncserver/zrle.c, libvncserver/zrleencodetemplate.c: + thread safety via per-client buffers. + * libvncserver/tight.c, libvncserver/zlib.c: thread safety + corrections via thread local storage using __thread. + * rfb/rfb.h: new members for threaded usage. + * tightvnc-filetransfer/rfbtightserver.c: fix (currently disabled) + for tight security type for RFB 3.8 (debian bug 517422.) + NEEDS AUDIT. + +2009-03-12 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: support mouse wheel operations + +2009-03-08 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: support clipboard operations + +2009-03-07 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: force releasing Alt keys whenr + losing focus. This helps when you switch windows by pressing + Alt+Tab (SDLvncviewer would get the "Alt down" event, but not + the "Alt up" one). + +2009-03-07 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: make the viewer resizable + +2009-03-06 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: enable key repeat + +2009-02-03 Mike Frysinger + * autogen.sh, configure.ac, **/Makefile.am: major automake cleanups + +2009-01-04 Karl Runge + * configure.ac, CMakeLists.txt: set LibVNCServer version to 0.9.7 + +2009-01-04 Karl Runge + * prepare_x11vnc_dist.sh: fix SUBDIRS and DIST_SUBDIRS when using + --with-system-libvncserver + +2008-06-03 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: fix update after resize + +2008-02-18 Christian Ehrlicher + * libvncserver/rfbregion.c: please MS Visual C++ + +2008-02-04 Noriaki Yamazaki + * libvncclient/rfbproto.c, libvncclient/zrle.c: Add ZYWRLE + support to LibVNCClient + +2008-02-04 Noriaki Yamazaki + * libvncserver/zywrletemplate.c: Fix mis encode/decode when + width != scanline + +2008-02-02 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: fix buttons (2 & 3 were switched), + fix Tab key, and fix Ctrl+ + +2008-01-29 Christian Ehrlicher + * libvncserver/rfbserver.c: add missing #include + +2008-01-28 Noriaki Yamazaki + * rfb/rfbproto.h, libvncserver/rfbserver.c, libvncserver/scale.c, + libvncserver/zrle.c, libvncserver/zrleencodetemplate.c, + libvncserver/zywrletemplate.c: add (server-side) ZYWRLE support, + and fix a few endian/scale errors + +2008-01-27 Christian Ehrlicher + * CMakeLists, rfb/rfbconfig.h.cmake, rfb/rfbint.h.cmake: + support CMake + +2007-09-04 Karl Runge + * classes/ssl: improve timeouts, port fallback, and connection + time of the SSL Java viewers. + +2007-08-10 Timo Ketola + * libvncclient/rfbproto.c: add missing else (so that GotRect + handling overrides the default operation). + +2007-06-14 Karl Runge + * configure.ac: add a note on what you must do if you want to + re-run autoconf from the LibVNCServer-X.Y.Z.tar.gz tarball. + +2007-05-26 Karl Runge + * configure.ac, Makefile.am, x11vnc/Makefile.am: change + configure to make more of a split between libvncserver and + x11vnc packages. LibVNCServer pkg does not include x11vnc. + +2007-04-06 Brad Hards + * rfb/rfbclient.h: use 'extern "C"' to make it convenient to + include from C++. + +2007-04-05 Alessandro Praduroux + * rfb/rfb.h: do not misplace guards, which makes it possible to + double include rfb.h from C++. + +2007-03-31 Guillaume Rousse + * configure.ac, **/Makefile.am: build shared libraries + +2007-03-20 Karl Runge + * libvncserver/httpd.c: Add "Connection: close" to HTTP replies. + +2007-03-17 Charles Coffing + * libvncserver: fix a locking issue + +2007-02-01 Johannes E. Schindelin + * libvncclient: add updateRect member to rfbClient, to allow + requesting smaller updates than whole-screen. + +2007-01-31 Karl Runge + * libvncclient: add GotCursorShape() and GotCopyRect() hooks. + fix copyrect code in rfbproto.c, add copyrect to default list. + * Makefile.am and prepare_x11vnc_dist.sh: add x11vnc dependence + on libvncclient. + +2006-12-13 Karl Runge + * remove stray "-permitfiletransfer permit file transfer support" + print out. + +2006-11-21 Karl Runge + * configure.ac: add DPMS detection. + +2006-11-13 Karl Runge + * configure.ac: x11vnc warnings for no XTEST or SSL. + * prepare_x11vnc_dist.sh: to 0.8.4 + +2006-11-07 Karl Runge + * configure.ac: clean up -R linker case, add --without-macosx-native + * prepare_x11vnc_dist.sh: have "make rpm" work properly for + x11vnc package. + +2006-07-17 Karl Runge + * configure.ac: move non-X11 tests out of HAVE_X: set + SSL_LIBS and CRYPT_LIBS and some header checks. + +2006-07-12 Karl Runge + * libvncserver: release for CVE-2006-2450 fix. + +2006-07-08 Karl Runge + * configure.ac: add for linux console. + +2006-07-04 Karl Runge + * configure.ac: add getspnam. + +2006-06-08 Karl Runge + * prepare_x11vnc_dist.sh: to 0.8.2 + +2006-05-29 Steven Carr + * Identified and removed some memory leaks associated + with the Encodings RRE, CoRRE, ZLIB, and Ultra. + * KeyboardLedState now has portable masks defined. + * rfb >= 3.7 Security Type Handler list would grow 1 + entry for each new client connection. + +2006-05-16 Steven Carr + * Statistics output now fits in 80-column output + * Corrected Cursor Statistics reporting as messages + +2006-05-15 Steven Carr + * Default to RFB 3.8 + * Add command line options: + -rfbversion X.Y Sets the version thatthe server reports + -permitfiletransfer Permits File Transfer (Default is Deny) + +2006-05-15 Steven Carr + * The great UltraVNC Compatibility Commit! + libvncserver now supports the following messages: + SetSingleWindow - Select a single window to be the source of the + framebuffer. + ServerInput - Disable and blank the servers display + TextChat - TextChat between the remote/local user + (Bandwidth friendly VS the Notepad approach) + FileTransfer - Emulates a Windows Filesystem to the viewer + (Currently does not support Delta Transfers) + (Currently does not support Sending Directories) + UltraZip - Improved UltraZip support + * Improved Statistics SubSystem, now supports all encodings + * RFB 3.8 support! Error Messages are a 'Good Thing' (tm) + * Default to identify as RFB 3.6 to emulate UltraVNC server + (Server now has the ability to set the RFB version reported) + (permits the viewer to identify the server has FileTransfer ability) + * Client Encoding AutoSelection Supported (UltraViewer is speed aware) + * libvncclient has improved server detection/capabilities logic! + +2006-05-13 Karl Runge + * minilzo.c,minilzo.h,lzoconf.h: switch to non-CRLF versions. + * libvncclient/Makefile.am: add minilzo.c, minilzo.h, lzoconf.h + and ultra.c to materials lists. + * libvncserver/scale.c: remove libm dependency with CEIL and + FLOOR macros. + * libvncserver/rfbserver.c: remove C99 declarations. + * vncterm/Makefile.am: fix VPATH build. + +2006-05-06 Karl Runge + * configure.ac: add linux/videodev.h and linux/fb.h detection. + +2006-05-04 Steven Carr + * rfbEncodingSupportedEncodings - What encodings are supported? + * rfbEncodingSupportedMessages - What message types are supported? + This way a client can identify if a particular server supports a + specific message types. + * rfbEncodingServerIdentity - What is the servers version string? + ie: "x11vnc: 0.8.1 lastmod: 2006-04-25 (LibVNCServer 0.9pre)" + +2006-05-03 Steven Carr + * Server Side Scaling is now supported in libvncserver + Both PalmVNC and UltraVNC SetScale messages are supported + +2006-05-02 Steven Carr + * Ultra Encoding added. Tested against UltraVNC V1.01 + * libvncclient/rfbproto.c CopyRectangle() BPP!=8 bug fixed. + * Incompatible pointer usage warnings eliminated (gcc 4.0.1) + +2006-04-27 Johannes E. Schindelin + * examples/{rotate.c, rotatetemplate.c}: add modified pnmshow + which demonstrates fast rotating and flipping. + +2006-04-26 Karl Runge + * all Makefile.am: use -I $(top_srcdir) instead of -I .. so VPATH + builds will work. + * configure.ac: create rfb subdir for rfbint.h under VPATH. + +2006-04-17 Steven Carr + * Added an example camera application to demonstrate another + way to write a server application. + +2006-04-05 Karl Runge + * classes/ssl: SSL Java viewer workarounds for firewall + proxies (signed applet as last resort, proxy.vnc). + include ssl_vncviewer stunnel wrapper script. + +2006-03-28 Steven Carr + * SDLvncviewer.c, rfbproto.c, vncviewer.c, main.c, rfbserver.c, + rfb.h, rfbclient.h, rfbproto.h: add new encoding: KeyboardLedState + +2006-03-28 Karl Runge + * classes/ssl: patch to tightvnc Java viewer for SSL support + plus other fixes (richcursor colors, Tab keysym, etc). + * libvncserver/httpd.c: add missing \r in 200 OK. + +2006-03-27 Steven Carr + * rfbserver.c: Zlib encoding cannot have a limit via + maxRectsPerUpdate + +2006-02-28 Donald Dugger + * rfb.h, sockets.c, main.c: add a flag to handle all pending + input events instead of one at a time. + +2006-02-24 Karl Runge + * x11vnc: -unixpw and -stunnel options. Add clipboard input + to per-client input controls. + +2006-02-24 Rohit Kumar + * main.c, rfbtightserver.c, rfb.h: added method to get + extension specific client data. + +2006-02-22 Rohit Kumar + * auth.c, main.c, rfbtightserver.c, rfb.h: add methods to + unregister extensions and security types. + +2006-02-20 Karl Runge + * main.c, cursor.c, tightvnc-filetransfer: fix some non-gcc + compiler warnings. + +2006-01-14 Karl Runge + * x11vnc: add -8to24 option for some multi-depth displays. + +2006-01-12 Karl Runge + * configure.ac: add switches for most X extensions. + +2006-01-10 Johannes E. Schindelin + * libvncserver/{main.c,rfbserver.c}: fix timely closing of clients; + the client iterator in rfbProcessEvents() has to iterate also + over clients whose sock < 0. Noticed by Karl. + +2006-01-08 Karl Runge + * x11vnc: the big split. (and -afteraccept and -passwdfile read:..) + * examples/pnmshow24.c: fix typo. + +2006-01-08 Karl Runge + * libvncclient/vncviewer.c: fix non-jpeg/libz builds. + * examples/pnmshow24.c: fix non-ALLOW24BPP builds. + * libvncserver/main.c: fix 'static int' defn. + +2006-01-05 Karl Runge + * libvncserver/main.c: rfbRegisterProtocolExtension extMutex was + never initialized. + +2005-12-24 Karl Runge + * x11vnc: enhance -passwdfile features, filetransfer on by default. + +2005-12-19 Dave Stuart + * libvncserver/{main.c,rfbserver.c,cargs.c}, rfb/rfb.h: introduce + deferPtrUpdateTime, which defers the handling of pointer events + for a couple of milliseconds. + +2005-12-19 Johannes E. Schindelin + * client_examples/SDLvncviewer.c, libvncclient/{sockets.c,vncviewer.c}, + libvncserver/{main.c,rfbserver.c,sockets.c}: fix MinGW32 compilation + +2005-12-08 "Mazin, Malvina" + * configure.ac, libvncserver/sockets.c: on Solaris 2.7, write may + return ENOENT when it really means EAGAIN. + +2005-12-07 Giampiero Giancipoli + * libvncclient/vncviewer.c: plug memory leaks + +2005-12-07 Johannes E. Schindelin + * client_examples/SDLvncviewer.c: use unicode to determine the keysym + (much more reliable than the old method) + +2005-11-25 Karl Runge + * configure.ac: disable tightvnc-filetransfer if no libpthread. + add --without-pthread option. + * libvncserver/Makefile.am: enable WITH_TIGHTVNC_FILETRANSFER + conditional. + * libvncserver/rfbserver.c: fix deadlock from + rfbReleaseExtensionIterator(), fix no libz/libjpeg builds. + * libvncserver/{main.c,private.h}, rfb/rfbclient.h, libvncclient/{rfbproto.c, + tight.c,vncviewer.c}: fix no libz/libjpeg builds. + * libvncserver/tightvnc-filetransfer/rfbtightserver.c: fix no + libz/libjpeg builds. rm // comments. + * libvncserver/tightvnc-filetransfer/filetransfermsg{.c,.h}, + libvncserver/auth.c: rm // comments. + * libvncserver/tightvnc-filetransfer/filelistinfo.h: set NAME_MAX if not + defined. + * x11vnc: throttle load if fb update requests not taking place. + +2005-10-22 Karl Runge + * x11vnc: -filexfer file transfer, -slow_fb, -blackout noptr... + +2005-10-06 Johannes E. Schindelin + * many a files: kill BackChannel and CustomClientMessage + support. The new extension mechanism is much more versatile. + To prove this, a new example shows how to implement the back + channel as an extension. Of course, this had to be tested, so + LibVNCClient now has beginnings of an extension mechanism, too. + And an example implementing the client side of the back channel. + +2005-10-03 Johannes E. Schindelin + * libvncserver/rfbserver.c, rfb/rfb.h: add a method to the + extension struct which is called to enable pseudo encodings. + This is a versatile mechanism to enable/disable custom + extensions with custom clients and servers. + +2005-09-28 Rohit Kumar + * examples/filetransfer.c, rfb/rfb.h, configure.ac, + libvncserver/{auth,cargs,main,rfbserver,sockets}.c, + libvncserver/tightvnc-extension/*: + Implement TightVNC's file transfer protocol. + +2005-09-27 Rohit Kumar + * libvncserver/{cargs,sockets,main,rfbserver}.c, + rfb/rfb.h: Provide a generic means to extend the RFB + protocol: rfbRegisterProtocolExtension(extension). This + deprecates the current (very limited) option to override + rfbScreenInfoPtr->processCustomClientMessage(client). + +2005-09-26 Rohit Kumar + * libvncserver/{auth,main,rfbserver}.c, rfb/{rfb,rfbproto}.h: + support VNC protocol version 3.7. This allows to add security + types. + +2005-08-21 Alberto Lusiani + * libvncserver.spec.in: split rpm into libvncserver, -devel and x11vnc + +2005-07-12 Karl Runge + * x11vnc: tweaks for release, fix queue buildup under -viewonly + +2005-07-10 Karl Runge + * x11vnc: -grab_buster for breaking XGrabServer deadlock, fix + scrolls and copyrect for -clip and -id cases. + +2005-07-06 Karl Runge + * x11vnc: -gui tray now embeds in systray; more improvements to gui. + +2005-07-01 Karl Runge + * libvncserver/httpd.c: make sure httpListenSock >=0 in rfbHttpCheckFds + * x11vnc: add simple "-gui tray" mode for small icon like x0rfbserver + had (someday/somehow to auto embed in a tray/dock) + +2005-06-28 Johannes E. Schindelin + * libvncclient/zrle.c: fix handling of raw and fill subtypes + (off-by-one and off-by-many bug) + +2005-06-27 Karl Runge + * libvncserver/main.c: move deferUpdateTime and maxRectsPerUpdate + defaults to before rfbProcessArguments(). + +2005-06-18 Karl Runge + * configure.ac: don't use -R on HP-UX and OSF1. + * x11vnc: don't free the current cursor, close stderr + for -inetd -q and no -o logfile, set DISPLAY for -solid + external calls. + +2005-06-14 Karl Runge + * configure.ac: XReadScreen and XReadDisplay checks. + * libvncserver/cursor.c: fix unsigned long crash for 64bits. + * x11vnc: first round of beta-testing fixes, RFE's. + +2005-06-10 Johannes E. Schindelin + * configure.ac: fix that annoying SUN /usr/ccs location of "ar" + +2005-06-03 Karl Runge + * libvncserver/main.c: remove sraRgnSubtract from copyRegion + * x11vnc: scrollcopyrect under -scale, add -fixscreen. + +2005-05-30 Karl Runge + * libvncserver/main.c: fix copyRect for non-cursor-shape-aware clients. + +2005-05-24 Karl Runge + * x11vnc: scrollcopyrect: GrabServer detection, autorepeat throttling.. + * prepare_x11vnc_dist.sh: grep out new libvncserver-config line. + +2005-05-23 Karl Runge + * configure.ac: malloc(0) is never used, so we don't need the check + +2005-05-15 Johannes E. Schindelin + * acinclude.m4: fix compilation for systems without socklen_t + +2005-05-17 Karl Runge + * x11vnc: more scrolling, -scr_term, -wait_ui, -nowait_bog + +2005-05-15 Johannes E. Schindelin + * almost every file: ANSIfy, fix warnings from Linus' sparse + +2005-05-14 Karl Runge + * x11vnc: more work on -scrollcopyrect and -xkb modes. + +2005-05-13 Johannes E. Schindelin + * libvncserver/{main,rfbserver,sockets}.c: fix memory leaks (valgrind) + +2005-05-07 Johannes E. Schindelin + * libvncserver/rfbserver.c: fix memory leak pointed out by Tim Jansen + * libvncserver/{httpd,main,rfbserver,sockets}.c, rfb/rfb.h: + replace "rfbBool socketInitDone" by "enum rfbSocketState + socketState" + +2005-05-03 Karl Runge + * libvncserver/main.c: fix leak in rfbDoCopyRect/rfbScheduleCopyRect + * configure.ac: guard against empty HAVE_X + +2005-05-02 Karl Runge + * configure.ac: fatal error for x11vnc package if no X present + * configure.ac: give warnings and info about missing libjpeg/libz + * x11vnc: X RECORD heuristics to detect scrolls: -scrollcopyrect, + build customizations, bandwidth/latency estimates. + +2005-04-27 Johannes E. Schindelin + * clear requested region (long standing TODO, pointed out by Karl) + +2005-04-19 Karl Runge + * x11vnc: -wireframe, -wirecopyrect. Back to the 90's with + wireframes to avoid window move/resize lurching. + * safer remote control defaults. -privremote, -safer, -nocmds. + * debug_xevents, debug_xdamage. -noviewonly for rawfb mode. + +2005-04-10 Karl Runge + * configure.ac: add mmap + * x11vnc: -rawfb, -pipeinput, -xtrap, -flag, ... + +2005-04-03 Karl Runge + * configure.ac: add conditional libXTrap checking + * x11vnc: use DEC-XTRAP on old X11R5 for grab control. + -shiftcmap n, -http, fix DAMAGE event leak. + +2005-03-29 Karl Runge + * x11vnc: fix event leaks, build-time customizations, -nolookup + +2005-03-19 Karl Runge + * x11vnc: scale cursors by default, -scale_cursor to tune, + -arrow n, -norepeat n, speed up integer magnification. + +2005-03-12 Karl Runge + * x11vnc: X DAMAGE support, -clip WxH+X+Y, identd. + +2005-03-05 Karl Runge + * autoconf: rpm -> rpmbuild and echo -n -> printf + +2005-03-04 Karl Runge + * libvncserver/{cargs.c,sockets.c}: add -listen option and + rfbScreen member listenInterface. + * rfb/rfb.h: rfbListenOnTCPPort() and rfbListenOnUDPPort() + function prototypes changed to include network interface. + +2005-02-14 Karl Runge + * x11vnc: -users lurk=, -solid for cde, -gui ez,.. beginner mode. + +2005-02-10 Karl Runge + * x11vnc: -input option to fine tune allowed client input, + additions to remote control and gui for this. + +2005-02-09 Karl Runge + * x11vnc: -users, fix -solid on gnome and kde. + * configure.ac: add pwd.h, wait.h, and utmpx.h checks. + +2005-02-06 Karl Runge + * configure.ac: add /usr/sfw on Solaris when XFIXES, add + --with-jpeg=DIR --with-zlib=DIR, workaround bug when + --without-jpeg was supplied. + * prepare_x11vnc_dist.sh: few tweaks for next release + +2005-02-05 Karl Runge + * x11vnc: -solid color, -opts/-? + * tightvnc-1.3dev5-vncviewer-alpha-cursor.patch: create, name + says it all. + +2005-01-23 Karl Runge + * x11vnc: -timeout, -noalphablend. make -R norepeat work. + * sync with new draw cursor mechanism. + +2005-01-20 Karl Runge + * libvncserver/{cursor.c,rfbserver.c}: fixed the "disappearing cursor" + problem + +2005-01-18 Johannes E. Schindelin + * rfb/rfb.h libvncserver/rfbserver.c: pointerClient was still static + * libvncserver/rfbserver.c: do not make requestedRegion empty without + reason. + * almost everything: the cursor handling for clients which don't handle + CursorShape updates was completely broken. It originally was very + complicated for performance reasons, however, in most cases it made + performance even worse, because at idle times there was way too much + checking going on, and furthermore, sometimes unnecessary updates + were inevitable. + The code now is much more elegant: the ClientRec structure knows + exactly where it last painted the cursor, and the ScreenInfo + structure knows where the cursor shall be. + As a consequence there is no more rfbDrawCursor()/rfbUndrawCursor(), + no more dontSendFramebufferUpdate, and no more isCursorDrawn. + It is now possible to have clients which understand CursorShape + updates and clients which don't at the same time. + * libvncserver/cursor.c: rfbSetCursor no longer has the option + freeOld; this is obsolete, as the cursor structure knows what + to free and what not. + +2005-01-15 Karl Runge + * rfb/rfb.h: add alphaSource and alphaPreMultiplied to rfbCursor. + * libvncserver/cursor.c: do cursor alpha blending in rfbDrawCursor() + for non-cursorshapeupdates clients. + * x11vnc: -alphablend, cursors fixes, -snapfb, more tweaks and bug + fixes. + +2004-12-27 Karl Runge + * x11vnc: improve alpha channel handling for XFIXES cursors. + * add more parameters to remote control. + +2004-12-20 Johannes E. Schindelin + * released version 0.7 + +2004-12-19 Karl Runge + * x11vnc: string cleanup, synchronous remote-control option -sync + * libvncserver/cursor.c: zero underCursorBufferLen when cursor freed. + +2004-12-16 Karl Runge + * test/encodingstest.c: fix decl bug in main() + * x11vnc: use XFIXES extension to show the exact cursor shape. + * remote control nearly everything on the fly, -remote/-query + * tcl/tk gui based on the remote control, -gui + * support screen size changes with XRANDR ext., -xrandr, -padgeom + * Misc: -overlay visual support on IRIX, -id pick, -pointer_mode n, + -sb n, RFB_MODE set in env. under -accept/-gone. + +2004-12-02 Johannes E. Schindelin + * make LibVNCServer compile & work on MinGW32 + +2004-11-30 "Leiradella, Andre V Matos Da Cunha" + * libvncclient/sockets.c: return TRUE in every case of success + +2004-08-29 Karl Runge + * x11vnc: yet another pointer input handling algorithm in + check_user_input(), revert to previous with -old_pointer2. + * modifiy prepare_x11vnc_dist.sh to install tightvnc Java viewer + in $prefix/share/x11vnc/classes + +2004-08-29 Johannes E. Schindelin + * */*.[ch]: API changes: global functions/structures should have + * either "rfb", "sra" or "zrle" as prefix, while structure members + * should not... + +2004-08-29 Karl Runge + * x11vnc: changes in cursor shape handling: use rfbSetCursor() + * cursor shape options: -cursor, -cursor (X|some|most) + * -vncconnect the default. + * configure.ac: add more macros for X extensions. + +2004-08-15 Karl Runge + * x11vnc: -overlay to fix colors with Sun 8+24 overlay visuals. + * -sid option. + +2004-08-03 Karl Runge + * x11vnc: manpage and README + * fix XKBlib.h detection on *BSD + +2004-07-31 Karl Runge + * x11vnc: -cursorpos now the default + +2004-07-28 Karl Runge + * x11vnc: -add_keysyms dynamically add missing keysyms to X server + +2004-07-26 Karl Runge + * x11vnc: first pass at doing modtweak via XKEYBOARD extension (-xkb) + * -skip_keycodes; reset modtweaks on event MappingNotify. + * fix bugs wrt PRIMARY handling. + * continuation lines "\" in x11vncrc. + +2004-07-15 Karl Runge + * x11vnc: modtweak is now the default + * check X11/XKBlib.h in configure.ac to work around Solaris 7 bug. + +2004-07-10 Karl Runge + * x11vnc: norepeat to turn off X server autorepeat when clients exist, + let the client side do the autorepeating. + +2004-06-26 Karl Runge + * x11vnc: add "-scale fraction" for global server-side scaling. + +2004-06-17 Karl Runge + * x11vnc: simple ~/.x11vncrc config file support, -rc, -norc + +2004-06-12 Karl Runge + * x11vnc: -clear_mods, -clear_keys, and -storepasswd, + * add RFB_SERVER_IP RFB_SERVER_PORT to -accept env. + +2004-06-07 Johannes E. Schindelin + * libvncserver/cursor.c, rfb/rfb.h: fix cursor trails + * */Makefile.am: stop automake nagging + * libvncclient/*, client_examples/*: streamline API, SDLvncviewer added + * examples/, libvncclient/, test/: moved tests to test/ + +2004-06-05 Karl Runge + * x11vnc: rearrange file for easier maintenance + * add RFB_CLIENT_COUNT to -accept and -gone commands + +2004-05-27 Karl Runge + * x11vnc: -viewpasswd, viewonly passwds. + * some typos in prepare_x11vnc_dist.sh + * libvncserver: fix view-only plain passwd and view-only CutText + +2004-05-25 Johannes E. Schindelin + * moved the library into libvncserver/ + * moved x11vnc into x11vnc/ + +2004-05-21 Karl Runge + * x11vnc: -gone, -passwdfile, -o logfile; add view-only to -accept + +2004-05-08 Karl Runge + * x11vnc: add -accept some-command/xmessage/popup + +2004-05-05 Karl Runge + * x11vnc: mouse button -> keystrokes and keystroke -> mouse button + mappings in -buttonmap and -remap + * shm OS blacklist revert to -onetile + +2004-04-28 Karl Runge + * x11vnc: -auth, more -cursorpos and -nofb work + +2004-04-19 Karl Runge + * x11vnc: -cursorpos, -sigpipe + +2004-04-13 Karl Runge + * x11vnc: do not send selection unless all clients + are in RFB_NORMAL state. + * increase rfbMaxClientWait when threaded to avoid + ReadExact() timeouts for some viewers. + +2004-04-08 Karl Runge + * x11vnc options -blackout, -xinerama, -xwarppointer + * modify configure.ac to pick up -lXinerama + * extend -remap to take mapping list. + * check cargs result for unused args. + +2004-03-22 Johannes E. Schindelin + * fix cargs.c (hopefully for the last time): + arguments were not correctly purged + +2004-03-15 Johannes E. Schindelin + * fix libvncserver-config to again return a linker when + called with --link + +2004-03-10 Karl Runge + * x11vnc options -vncconnect, -connect, -remap, + -debug_pointer, and -debug_keyboard + * support reverse connections, vncconnect(1), etc. + * expt. with user supplied keysym remapping. + * debug output option for pointer and keyboard. + +2004-02-29 Johannes E. Schindelin + * fixed warning of valgrind for regiontest + +2004-02-19 Karl Runge + * x11vnc options -nosel -noprimary -visual. + * add clipboard/selection handling. + * add visual option (mostly for testing and workarounds). + * improve shm cleanup on failures. + +2004-02-04 Johannes E. Schindelin + * Make examples (at least a few) compileable with g++, + as pointed out by Juan Jose Costello + +2004-01-30 Johannes E. Schindelin + * Thanks to Paul Fox from Bright Star Engineering, + a few more memory leaks were fixed. + +2004-01-29 Johannes E. Schindelin + * Honour the check for libz and libjpeg again. + +2004-01-21 Johannes E. Schindelin + * do not send unneccessary updates when drawing a cursor + * ignore SIGPIPE; it is handled by EPIPE + * add an example how to use rfbDoCopyRect + * add experimental progressive updating (off by default) + +2004-01-19 Karl Runge + * handle mouse button number mismatch + * improved pointer input handling during drags, etc. + * somewhat faster copy_tiles() -> copy_tiles() + * x11vnc options -buttonmap -old_pointer -old_copytile + +2004-01-16 Johannes E. Schindelin + * compile fix for cygwin + +2004-01-09 Karl Runge + * x11vnc options -allow, -localhost, -nodragging, -input_skip + * minimize memory usage under -nofb + +2003-12-08 Karl Runge + * add check for XKEYBOARD extension in configure.ac + * support XBell events (disable: "-nobell"), "-nofb" in x11vnc + +2003-11-07 Karl Runge + * support "-inetd", "-noshm", "-flipbyteorder" in x11vnc + +2003-10-26 Johannes E. Schindelin + * released Version 0.6 + +2003-09-11 Mark McLoughlin + + * Makefile.in, */Makefile.in, aclocal.m4, + bootstrap.sh, config.h.in, configure, + depcomp, install-sh, missing, mkinstalldirs, + Removed auto-generated files from CVS. + +2003-09-11 Mark McLoughlin + + * rdr/Exception.h, rdr/FdInStream.cxx, rdr/FdInStream.h, + rdr/FdOutStream.cxx, rdr/FdOutStream.h, rdr/FixedMemOutStream.h, + rdr/InStream.cxx, rdr/InStream.h, rdr/MemInStream.h, + rdr/MemOutStream.h, rdr/NullOutStream.cxx, rdr/NullOutStream.h, + rdr/OutStream.h, rdr/ZlibInStream.cxx, rdr/ZlibInStream.h, + rdr/ZlibOutStream.cxx, rdr/ZlibOutStream.h, rdr/types.h, + zrle.cxx, zrleDecode.h, zrleEncode.h: remove original + C++ ZRLE implementation. Its been ported to C. + + * NEWS: copy the existing ChangeLog to here and make + this a more detailed ChangeLog. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/INSTALL b/droidvncgrab/vnc/libvncserver-kanaka/INSTALL new file mode 100755 index 0000000..b42a17a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/Makefile.am new file mode 100755 index 0000000..7f3f229 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/Makefile.am @@ -0,0 +1,27 @@ +if WITH_X11VNC +X11VNC=x11vnc +endif + +SUBDIRS=libvncserver examples contrib libvncclient vncterm classes client_examples test $(X11VNC) +DIST_SUBDIRS=libvncserver examples contrib libvncclient vncterm classes client_examples test + +bin_SCRIPTS = libvncserver-config + +includedir=$(prefix)/include/rfb +#include_HEADERS=rfb.h rfbconfig.h rfbint.h rfbproto.h keysym.h rfbregion.h + +include_HEADERS=rfb/rfb.h rfb/rfbconfig.h rfb/rfbint.h rfb/rfbproto.h \ + rfb/keysym.h rfb/rfbregion.h rfb/rfbclient.h + +$(PACKAGE)-$(VERSION).tar.gz: dist + +if HAVE_RPM +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE).spec + cp $(PACKAGE)-$(VERSION).tar.gz @RPMSOURCEDIR@ + rpmbuild -ba $(PACKAGE).spec +endif + +t: + $(MAKE) -C test test + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/NEWS b/droidvncgrab/vnc/libvncserver-kanaka/NEWS new file mode 100755 index 0000000..58f9285 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/NEWS @@ -0,0 +1,147 @@ + Mark sent me patches to no longer need C++ for ZRLE encoding! + added --disable-cxx Option for configure + x11vnc changes from Karl Runge: + - Changed all those whimpy printf(...)'s into manly fprintf(stdxxx,...)'s. + + - Added -q switch (quiet) to suppress printing all the debug-looking output. + + - Added -bg switch to fork into background after everything is set up. + (checks for LIBVNCSERVER_HAVE_FORK and LIBVNCSERVER_HAVE_SETSID) + + - Print this string out to stdout: 'PORT=XXXX' (usually XXXX = 5900). + Combining with -bg, easy to write a ssh/rsh wrapper with something like: + port=`ssh $host "x11vnc -bg .."` then run vncviewer based on $port output. + (tunneling the vnc traffic thru ssh a bit more messy, but doable) + + - Quite a bit of code to be more careful when doing 8bpp indexed color, e.g. + not assuming NCOLORS is 256, handling 8bit TrueColor and Direct Color, etc + (I did all this probably in April, not quite clear in my mind now, but + I did test it out a fair amount on my old Sparcstation 20 wrt a user's + questions). + introduce rfbErr for Errors (Erik) + make rfbLog overridable (suggested by Erik) + don't reutrn on EINTR in WriteExact()/ReadExact() (suggested by Erik) + use AX_PREFIX_CONFIG_H to prefix constants in config.h to avoid + name clashes (also suggested by Erik) + transformed Bool, KeySym, Pixel to rfbBool, rfbKeySym, rfbPixel + (as suggested by Erik) + purged exit() calls (suggested by Erik) + fixed bug with maxRectsPerUpdate and Tight Encoding (these are incompatible) + checked sync with TightVNC 1.2.8: + viewonly/full passwords; if given a list, only the first is a full one + vncRandomBytes is a little more secure now + new weights for tight encoding + checked sync with RealVNC 3.3.7 + introduced maxRectsPerUpdate + added first alpha version of LibVNCClient + added simple and simple15 example (really simple examples) + finally got around to fix configure in CVS + long standing http bug (.jar was sent twice) fixed by a friend of Karl named Mike + http options in cargs + when closing a client and no longer listening for new ones, don't crash + fixed a bug with ClientConnectionGone + endianness is checked at configure time + fixed a bug that prevented the first client from being closed + fixed that annoying "libvncserver-config --link" bug + make rfbReverseByte public (for rdp2vnc) + fixed compilation on OS X, IRIX, Solaris + install target for headers is now ${prefix}/include/rfb ("#include ") + renamed "sraRegion.h" to "rfbregion.h" + CARD{8,16,32} are more standard uint{8,16,32}_t now + fixed LinuxVNC colour handling + fixed a bug with pthreads where the connection was not closed + moved vncterm to main package (LinuxVNC included) + portability fixes (IRIX, OSX, Solaris) + more portable way to determine endianness and types of a given size + through autoconf based methods +0.5 + rpm packaging through autoconf + autoconf'ed the whole package (including optional support for zlib, + pthreads and libjpeg as well as zrle/c++) + moved appropriate files to contrib/ and examples/ respectively + fixed long standing cargs bug (Justin "Zippy" Dearing) + Even better x11vnc from Karl J. Runge! (supports different kbd layouts of + client/server) + Better x11vnc from Karl J. Runge! + fixed severe bug (Const Kaplinsky) + got patch from Const Kaplisnky with CursorPosUpdate encoding and some Docs + sync'ed with newest RealVNC (ZRLE encoding) + a HTTP request for tunnelling was added (to fool strict web proxies) + sync'ed with TightVNC 1.2.5 +0.4 + support for NewFB from Const Kaplinsky + memory leaks squashed (localtime pseudo leak is still there :-) + small improvements for OSXvnc (still not working correctly) + synced with TightVNC 1.2.3 + solaris compile cleanups + many x11vnc improvements + added backchannel, an encoding which needs special clients to pass + arbitrary data to the client + changes from Tim Jansen regarding multi threading and client blocking + as well as C++ compliancy + x11vnc can be controlled by starting again with special options if compiling + with LOCAL_CONTROL defined +0.3 + added x11vnc, a x0rfbserver clone + regard deferUpdateTime in processEvents, if usec<0 + initialize deferUpdateTime (memory "leak"!) + changed command line handling (arguments are parsed and then removed) + added very simple example: zippy + added rfbDrawLine, rfbDrawPixel +0.2 + inserted a deferUpdate mechanism (X11 independent). + removed deletion of requestedRegion + added rfbLoadConsoleFont + fixed font colour handling. + added rfbSelectBox + added rfbDrawCharWithClip to allow for clipping and a background colour. + fixed font colours + added rfbFillRect + added IO function to check password. + rfbNewClient now sets the socket in the fd_set (for the select() call) + when compiling the library with HAVE_PTHREADS and an application + which includes "rfb.h" without, the structures got mixed up. + So, the pthreads section is now always at the end, and also + you get a linker error for rfbInitServer when using two different + pthread setups. + fixed two deadlocks: when setting a cursor and when using CopyRect + fixed CopyRect when copying modified regions (they lost the modified + property) + WIN32 target compiles and works for example :-) + fixed CopyRect (was using the wrong order of rectangles...) + should also work with pthreads, because copyrects are + always sent immediately (so that two consecutive copy rects + cannot conflict). + changed rfbUndrawCursor(rfbClientPtr) to (rfbScreenInfoPtr), because + this makes more sense! + flag backgroundLoop in rfbScreenInfo (if having pthreads) + CopyRect & CopyRegion were implemented. + if you use a rfbDoCopyR* function, it copies the data in the + framebuffer. If you prefer to do that yourself, use rfbScheduleCopyR* + instead; this doesn't modify the frameBuffer. + added flag to optionally not send XCursor updates, but only RichCursor, + or if that is not possible, fall back to server side cursor. + This is useful if your cursor has many nice colours. + fixed java viewer on server side: + SendCursorUpdate would send data even before the client pixel format + was set, but the java applet doesn't like the server's format. + fixed two pthread issues: + rfbSendFramebuffer was sent by a ProcessClientMessage function + (unprotected by updateMutex). + cursor coordinates were set without protection by cursorMutex + source is now equivalent to TridiaVNC 1.2.1 + pthreads now work (use iterators!) + cursors are supported (rfbSetCursor automatically undraws cursor) + support for 3 bytes/pixel (slow!) + server side colourmap support + fixed rfbCloseClient not to close the connection (pthreads!) + this is done lazily (and with proper signalling). + cleaned up mac.c (from original OSXvnc); now compiles (untested!) + compiles cleanly on Linux, IRIX, BSD, Apple (Darwin) + fixed prototypes +0.1 + rewrote API to use pseudo-methods instead of required functions. + lots of clean up. + Example can show symbols now. + All encodings + HTTP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/README b/droidvncgrab/vnc/libvncserver-kanaka/README new file mode 100755 index 0000000..49c8a4e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/README @@ -0,0 +1,439 @@ +LibVNCServer: a library for easy implementation of a RDP/VNC server. +Copyright (C) 2001-2003 Johannes E. Schindelin + +If you already used LibVNCServer, you probably want to read NEWS. + +What is it? +----------- + +VNC is a set of programs using the RFB (Remote Frame Buffer) protocol. They +are designed to "export" a frame buffer via net (if you don't know VNC, I +suggest you read "Basics" below). It is already in wide use for +administration, but it is not that easy to program a server yourself. + +This has been changed by LibVNCServer. + +There are two examples included: + - example, a shared scribble sheet + - pnmshow, a program to show PNMs (pictures) over the net. + +The examples are not too well documented, but easy straight forward and a +good starting point. + +Try example: it outputs on which port it listens (default: 5900), so it is +display 0. To view, call + vncviewer :0 +You should see a sheet with a gradient and "Hello World!" written on it. Try +to paint something. Note that everytime you click, there is some bigger blot, +whereas when you drag the mouse while clicked you draw a line. The size of the +blot depends on the mouse button you click. Open a second vncviewer with +the same parameters and watch it as you paint in the other window. This also +works over internet. You just have to know either the name or the IP of your +machine. Then it is + vncviewer machine.where.example.runs.com:0 +or similar for the remote client. Now you are ready to type something. Be sure +that your mouse sits still, because everytime the mouse moves, the cursor is +reset to the position of the pointer! If you are done with that demo, press +the down or up arrows. If your viewer supports it, then the dimensions of the +sheet change. Just press Escape in the viewer. Note that the server still +runs, even if you closed both windows. When you reconnect now, everything you +painted and wrote is still there. You can press "Page Up" for a blank page. + +The demo pnmshow is much simpler: you either provide a filename as argument +or pipe a file through stdin. Note that the file has to be a raw pnm/ppm file, +i.e. a truecolour graphics. Only the Escape key is implemented. This may be +the best starting point if you want to learn how to use LibVNCServer. You +are confronted with the fact that the bytes per pixel can only be 8, 16 or 32. + +Projects using it +---------------------------------------- + +VNC for KDE +http://www.tjansen.de/krfb + +GemsVNC +http://www.elilabs.com/~rj/gemsvnc/ + +VNC for Netware +http://forge.novell.com/modules/xfmod/project/?vncnw + +RDesktop +http://rdesktop.sourceforge.net + +Mail me, if your application is missing! + +How to use +---------- + +To make a server, you just have to initialise a server structure using the +function rfbDefaultScreenInit, like + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(argc,argv,width,height,8,3,bpp); +where byte per pixel should be 1, 2 or 4. If performance doesn't matter, +you may try bpp=3 (internally one cannot use native data types in this +case; if you want to use this, look at pnmshow24). + + +You then can set hooks and io functions (see below) or other +options (see below). + +And you allocate the frame buffer like this: + rfbScreen->frameBuffer = (char*)malloc(width*height*bpp); + +After that, you initialize the server, like + rfbInitServer(rfbScreen); + +You can use a blocking event loop, a background (pthread based) event loop, +or implement your own using the rfbProcessEvents function. + +Making it interactive +--------------------- + +Input is handled by IO functions (see below). + +Whenever you change something in the frame buffer, call rfbMarkRectAsModified. +You should make sure that the cursor is not drawn before drawing yourself +by calling rfbUndrawCursor. You can also draw the cursor using rfbDrawCursor, +but it hardly seems necessary. For cursor details, see below. + +Utility functions +----------------- + +Whenever you draw something, you have to call + rfbMarkRectAsModified(screen,x1,y1,x2,y2). +This tells LibVNCServer to send updates to all connected clients. + +Before you draw something, be sure to call + rfbUndrawCursor(screen). +This tells LibVNCServer to hide the cursor. +Remark: There are vncviewers out there, which know a cursor encoding, so +that network traffic is low, and also the cursor doesn't need to be +drawn the cursor everytime an update is sent. LibVNCServer handles +all the details. Just set the cursor and don't bother any more. + +To set the mouse coordinates (or emulate mouse clicks), call + defaultPtrAddEvent(buttonMask,x,y,cl); +IMPORTANT: do this at the end of your function, because this actually draws +the cursor if no cursor encoding is active. + +What is the difference between rfbScreenInfoPtr and rfbClientPtr? +----------------------------------------------------------------- + +The rfbScreenInfoPtr is a pointer to a rfbScreenInfo structure, which +holds information about the server, like pixel format, io functions, +frame buffer etc. + +The rfbClientPtr is a pointer to an rfbClientRec structure, which holds +information about a client, like pixel format, socket of the +connection, etc. + +A server can have several clients, but needn't have any. So, if you +have a server and three clients are connected, you have one instance +of a rfbScreenInfo and three instances of rfbClientRec's. + +The rfbClientRec structure holds a member + rfbScreenInfoPtr screen +which points to the server and a member + rfbClientPtr next +to the next client. + +The rfbScreenInfo structure holds a member + rfbClientPtr rfbClientHead +which points to the first client. + +So, to access the server from the client structure, you use client->screen. +To access all clients from a server, get screen->rfbClientHead and +iterate using client->next. + +If you change client settings, be sure to use the provided iterator + rfbGetClientIterator(rfbScreen) +with + rfbClientIteratorNext(iterator) +and + rfbReleaseClientIterator +to prevent thread clashes. + +Other options +------------- + +These options have to be set between rfbGetScreen and rfbInitServer. + +If you already have a socket to talk to, just set rfbScreen->inetdSock +(originally this is for inetd handling, but why not use it for your purpose?). + +To also start an HTTP server (running on port 5800+display_number), you have +to set rfbScreen->httpdDir to a directory containing vncviewer.jar and +index.vnc (like the included "classes" directory). + +Hooks and IO functions +---------------------- + +There exist the following IO functions as members of rfbScreen: +kbdAddEvent, kbdReleaseAllKeys, ptrAddEvent and setXCutText + +kbdAddEvent(rfbBool down,rfbKeySym key,rfbClientPtr cl) + is called when a key is pressed. +kbdReleaseAllKeys(rfbClientPtr cl) + is not called at all (maybe in the future). +ptrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) + is called when the mouse moves or a button is pressed. + WARNING: if you want to have proper cursor handling, call + defaultPtrAddEvent(buttonMask,x,y,cl) + in your own function. This sets the coordinates of the cursor. +setXCutText(char* str,int len,rfbClientPtr cl) + is called when the selection changes. + +There are only two hooks: +newClientHook(rfbClientPtr cl) + is called when a new client has connected. +displayHook + is called just before a frame buffer update is sent. + +You can also override the following methods: +getCursorPtr(rfbClientPtr cl) + This could be used to make an animated cursor (if you really want ...) +setTranslateFunction(rfbClientPtr cl) + If you insist on colour maps or something more obscure, you have to + implement this. Default is a trueColour mapping. + +Cursor handling +--------------- + +The screen holds a pointer + rfbCursorPtr cursor +to the current cursor. Whenever you set it, remember that any dynamically +created cursor (like return value from rfbMakeXCursor) is not free'd! + +The rfbCursor structure consists mainly of a mask and a source. The mask +describes, which pixels are drawn for the cursor (a cursor needn't be +rectangular). The source describes, which colour those pixels should have. + +The standard is an XCursor: a cursor with a foreground and a background +colour (stored in backRed,backGreen,backBlue and the same for foreground +in a range from 0-0xffff). Therefore, the arrays "mask" and "source" +contain pixels as single bits stored in bytes in MSB order. The rows are +padded, such that each row begins with a new byte (i.e. a 10x4 +cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits). + +It is however very easy to make a cursor like this: + +char* cur=" " + " xx " + " x " + " "; +char* mask="xxxx" + "xxxx" + "xxxx" + "xxx "; +rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask); + +You can even set "mask" to NULL in this call and LibVNCServer will calculate +a mask for you (dynamically, so you have to free it yourself). + +There is also an array named "richSource" for colourful cursors. They have +the same format as the frameBuffer (i.e. if the server is 32 bit, +a 10x4 cursor has 4x10x4 bytes). + +History +------- + +LibVNCServer is based on Tridia VNC and OSXvnc, which in turn are based on +the original code from ORL/AT&T. + +When I began hacking with computers, my first interest was speed. So, when I +got around assembler, I programmed the floppy to do much of the work, because +it's clock rate was higher than that of my C64. This was my first experience +with client/server techniques. + +When I came around Xwindows (much later), I was at once intrigued by the +elegance of such connectedness between the different computers. I used it +a lot - not the least priority lay on games. However, when I tried it over +modem from home, it was no longer that much fun. + +When I started working with ASP (Application Service Provider) programs, I +tumbled across Tarantella and Citrix. Being a security fanatic, the idea of +running a server on windows didn't appeal to me, so Citrix went down the +basket. However, Tarantella has it's own problems (security as well as the +high price). But at the same time somebody told me about this "great little +administrator's tool" named VNC. Being used to windows programs' sizes, the +surprise was reciprocal inverse to the size of VNC! + +At the same time, the program "rdesktop" (a native Linux client for the +Terminal Services of Windows servers) came to my attention. There where even +works under way to make a protocol converter "rdp2vnc" out of this. However, +my primary goal was a slow connection and rdp2vnc could only speak RRE +encoding, which is not that funny with just 5kB/s. Tim Edmonds, the original +author of rdp2vnc, suggested that I adapt it to Hextile Encoding, which is +better. I first tried that, but had no success at all (crunchy pictures). + +Also, I liked the idea of an HTTP server included and possibly other +encodings like the Tight Encodings from Const Kaplinsky. So I started looking +for libraries implementing a VNC server where I could steal what I can't make. +I found some programs based on the demo server from AT&T, which was also the +basis for rdp2vnc (can only speak Raw and RRE encoding). There were some +rumors that GGI has a VNC backend, but I didn't find any code, so probably +there wasn't a working version anyway. + +All of a sudden, everything changed: I read on freshmeat that "OSXvnc" was +released. I looked at the code and it was not much of a problem to work out +a simple server - using every functionality there is in Xvnc. It became clear +to me that I *had* to build a library out of it, so everybody can use it. +Every change, every new feature can propagate to every user of it. + +It also makes everything easier: + You don't care about the cursor, once set (or use the standard cursor). +You don't care about those sockets. You don't care about encodings. +You just change your frame buffer and inform the library about it. Every once +in a while you call rfbProcessEvents and that's it. + +Basics +------ + +VNC (Virtual network computing) works like this: You set up a server and can +connect to it via vncviewers. The communication uses a protocol named RFB +(Remote Frame Buffer). If the server supports HTTP, you can also connect +using a java enabled browser. In this case, the server sends back a +vncviewer applet with the correct settings. + +There exist several encodings for VNC, which are used to compress the regions +which have changed before they are sent to the client. A client need not be +able to understand every encoding, but at least Raw encoding. Which encoding +it understands is negotiated by the RFB protocol. + +The following encodings are known to me: +Raw, RRE, CoRRE, Hextile, CopyRect from the original AT&T code and +Tight, ZLib, LastRect, XCursor, RichCursor from Const Kaplinsky et al. + +If you are using a modem, you want to try the "new" encodings. Especially +with my 56k modem I like ZLib or Tight with Quality 0. In my tests, it even +beats Tarantella. + +There is the possibility to set a password, which is also negotiated by the +RFB protocol, but IT IS NOT SECURE. Anybody sniffing your net can get the +password. You really should tunnel through SSH. + +Windows or: why do you do that to me? +-------------------------------------------- + +If you love products from Redmod, you better skip this paragraph. +I am always amazed how people react whenever Microsoft(tm) puts in some +features into their products which were around for a long time. Especially +reporters seem to not know dick about what they are reporting about! But +what is everytime annoying again, is that they don't do it right. Every +concept has it's new name (remember what enumerators used to be until +Mickeysoft(tm) claimed that enumerators are what we thought were iterators. +Yeah right, enumerators are also containers. They are not separated. Muddy.) + +There are three packages you want to get hold of: zlib, jpeg and pthreads. +The latter is not strictly necessary, but when you put something like this +into your source: + +#define MUTEX(s) + struct { + int something; + MUTEX(latex); + } + +Microsoft's C++ compiler doesn't do it. It complains that this is an error. +This, however, is how I implemented mutexes in case you don't need pthreads, +and so don't need the mutex. + +You can find the packages at +http://www.gimp.org/win32/extralibs-dev-20001007.zip + +Thanks go to all the GIMP team! + +What are those other targets in the Makefile? +--------------------------------------------- + +OSXvnc-server is the original OSXvnc adapted to use the library, which was in +turn adapted from OSXvnc. As you easily can see, the OSX dependend part is +minimal. + +storepasswd is the original program to save a vnc style password in a file. +Unfortunately, authentication as every vncviewer speaks it means the server +has to know the plain password. You really should tunnel via ssh or use +your own PasswordCheck to build a PIN/TAN system. + +sratest is a test unit. Run it to assert correct behaviour of sraRegion. I +wrote this to test my iterator implementation. + +blooptest is a test of pthreads. It is just the example, but with a background +loop to hunt down thread lockups. + +pnmshow24 is like pnmshow, but it uses 3 bytes/pixel internally, which is not +as efficient as 4 bytes/pixel for translation, because there is no native data +type of that size, so you have to memcpy pixels and be real cautious with +endianness. Anyway, it works. + +fontsel is a test for rfbSelectBox and rfbLoadConsoleFont. If you have Linux +console fonts, you can browse them via VNC. Directory browsing not implemented +yet :-( + +Why I don't feel bad about GPL +------------------------------ + +At the beginning of this projects I would have liked to make it a BSD +license. However, it is based on plenty of GPL'ed code, so it has to be +a GPL. I hear BeeGee complaining: "but that's invasive, every derivative +work, even just linking, makes my software GPL!" + +Yeah. That's right. It is because there are nasty jarheads out there who +would take anybody's work and claim it their own, selling it for much too +much money, stealing freedom and innovation from others, saying they were +the maintainers of innovation, lying, making money with that. + +The people at AT&T worked really well to produce something as clean and lean +as VNC. The managers decided that for their fame, they would release the +program for free. But not only that! They realized that by releasing also +the code for free, VNC would become an evolving little child, conquering +new worlds, making it's parents very proud. As well they can be! To protect +this innovation, they decided to make it GPL, not BSD. The principal +difference is: You can make closed source programs deriving from BSD, not +from GPL. You have to give proper credit with both. + +Now, why not BSD? Well, imagine your child being some famous actor. Along +comes a manager who exploits your child exclusively, that is: nobody else +can profit from the child, it itself included. Got it? + +What reason do you have now to use this library commercially? + +Several: You don't have to give away your product. Then you have effectively +circumvented the GPL, because you have the benefits of other's work and you +don't give back anything and you will be in hell for that. In fact, this +library, as my other projects, is a payback for all the free software I can +use (and sometimes, make better). For example, just now, I am using XEmacs +on top of XFree86, all running under Linux. + +Better: Use a concept like MySQL. This is free software, however, they make +money with it. If you want something implemented, you have the choice: +Ask them to do it (and pay a fair price), or do it yourself, normally giving +back your enhancements to the free world of computing. + +Learn from it: If you like the style this is written, learn how to imitate +it. If you don't like the style, learn how to avoid those things you don't +like. I learnt so much, just from looking at code like Linux, XEmacs, +LilyPond, STL, etc. + +License +------- + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program 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 program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.dfdf + +Contact +------- + +To contact me, mail me: Johannes dot Schindelin at gmx dot de + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/README.cvs b/droidvncgrab/vnc/libvncserver-kanaka/README.cvs new file mode 100755 index 0000000..c76b479 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/README.cvs @@ -0,0 +1,22 @@ +If you check out CVS of LibVNCServer, everything should build as usual: + +./configure && make + +If your machine complains not having the right version of automake (which should +not be necessary, because every needed file is checked in), try + +find -name Makefile.in -exec touch {} \; + +and rerun ./configure && make + +If you want to make changes which require automake or autoconf (i.e. you +check for other headers or add files), you have to have a current +(>2.50) version of autoconf. Also, you need automake. + +Then, just do + sh autogen.sh && make +in LibVNCServer's directory, and you should see plenty of output and +finally have a complete build of LibVNCServer. + +Happy VNC'ing! + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/README.md b/droidvncgrab/vnc/libvncserver-kanaka/README.md new file mode 100755 index 0000000..a454608 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/README.md @@ -0,0 +1,42 @@ +## LibVNCServer with the Tight PNG encoding + +### LibVNCServer + +Copyright (C) 2001-2003 Johannes E. Schindelin + +[LibVNCServer](http://sourceforge.net/projects/libvncserver/) is +a library for easy implementation of a RDP/VNC server. + + +### Tight PNG + +Copyright (C) 2010 Joel Martin + +The [Tight PNG encoding](http://wiki.qemu.org/VNC_Tight_PNG) is +similar to the Tight encoding, but the basic compression (zlib) is +replaced with PNG data. + +This encoding allows for simple, fast clients and bandwidth efficient +clients: + +* The PNG data can be rendered directly by the client so there is + negligible decode work needed in the VNC client itself. +* PNG images are zlib compressed internally (along with other + optimizations) so tightPng is comparable in bandwith to tight. +* PNG images are natively supported in the browsers. This is optimal + for web based VNC clients such as + [noVNC](http://github.com/kanaka/noVNC) + + +### Usage + +See INSTALL for build instructions. To build with the tightPng +encoding, you must also have libpng development libraries install. For +example: + + sudo apt-get install libpng-dev + + +### TODO + +- Handle palette mode (non-truecolor). diff --git a/droidvncgrab/vnc/libvncserver-kanaka/TODO b/droidvncgrab/vnc/libvncserver-kanaka/TODO new file mode 100755 index 0000000..2afffc8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/TODO @@ -0,0 +1,26 @@ +immediate: +---------- + +make SDLvncviewer more versatile + - test for missing keys (especially "[]{}" with ./examples/mac), + - map Apple/Linux/Windows keys onto each other, + - handle selection + - handle scroll wheel +style fixes: use Linux' coding guidelines & ANSIfy tightvnc-filetransfer: + discuss on list +LibVNCClient cleanup: prefix with "rfbClient", and make sure it does + not deliberately die() or exit() anywhere! +java vncviewer doesn't do colour cursors? +MinGW32 doesn't do fcntl on sockets; use setsockopt instead... +make corre work again (libvncclient or libvncserver?) +teach SDLvncviewer about CopyRect... +implement "-record" in libvncclient + +later: +------ + +selectbox: scroll bars +authentification schemes (secure vnc) + IO function ptr exists; now explain how to tunnel and implement a + client address restriction scheme. +VisualNaCro testing diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore new file mode 100755 index 0000000..3eeae3f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.cvsignore @@ -0,0 +1,22 @@ +aclocal.m4 +autom4te.cache +config.guess +config.log +config.status +config.sub +configure +COPYING +.cvsignore +INSTALL +install-sh +Makefile +Makefile.in +missing +mkinstalldirs +nacro.pm +nacro.so +nacro_wrap.c +visualnacro-* +.deps +.in +depcomp diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore new file mode 100755 index 0000000..a7007d3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/.gitignore @@ -0,0 +1,5 @@ +/COPYING +/INSTALL +/nacro.pm +/nacro.so +/nacro_wrap.c diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS new file mode 100755 index 0000000..1081101 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/AUTHORS @@ -0,0 +1,2 @@ +Johannes Schindelin + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog new file mode 100755 index 0000000..78b9858 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/ChangeLog @@ -0,0 +1,15 @@ +2006-10-10: Johannes Schindelin + * implement --compact and --compact-dragging to shut up the + script about mouse movements or drags. + * add 'i', 'c' and 'r' menu keys. + +2006-09-12: Johannes Schindelin + * the reference rectangle is selected with a rubber band, + and can be shown with 'd'. + +2006-06-15: Johannes Schindelin + * added timing: you can record the events with their timestamps now + +2005-01-13: Johannes Schindelin + * started the project + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am new file mode 100755 index 0000000..7b1fe67 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/Makefile.am @@ -0,0 +1,51 @@ +INTERFACE=nacro.h +SRCS=nacro.c +OBJS=nacro.o +ISRCS=nacro_wrap.c +IOBJS=nacro_wrap.o +TARGET=nacro +LIBS= @LIBVNCSERVERLIBS@ + +nacro_CFLAGS= @LIBVNCSERVERCFLAGS@ + +SWIGOPT= + +EXTRA_DIST=autogen.sh $(INTERFACE) $(SRCS) $(ISRCS) nacro.pm recorder.pl + +all: $(LIBPREFIX)$(TARGET)$(SO) + +# the following is borrowed from SWIG + +SWIG= @SWIG@ + +################################################################## +##### PERL 5 ###### +################################################################## + +# You need to set this variable to the Perl5 directory containing the +# files "perl.h", "EXTERN.h" and "XSUB.h". With Perl5.003, it's +# usually something like /usr/local/lib/perl5/arch-osname/5.003/CORE. + +PERL5_INCLUDE= @PERL5EXT@ + +# Extra Perl specific dynamic linking options +PERL5_DLNK = @PERL5DYNAMICLINKING@ +PERL5_CCFLAGS = @PERL5CCFLAGS@ + +# ---------------------------------------------------------------- +# Build a Perl5 dynamically loadable module (C) +# ---------------------------------------------------------------- + +$(ISRCS): $(INTERFACE) + @test -n "$(SWIG)" || (echo "Need SWIG" && exit 1) + $(SWIG) -perl5 $(SWIGOPT) $(INTERFACE) + +$(OBJS): $(SRCS) $(INTERFACE) + $(CC) -c -Dbool=char $(CCSHARED) $(CFLAGS) -o $@ $< $(LIBVNCSERVERCFLAGS) $(INCLUDES) -I$(PERL5_INCLUDE) + +$(IOBJS): $(ISRCS) $(INTERFACE) + $(CC) -c -Dbool=char $(CCSHARED) $(CFLAGS) -o $@ $< $(INCLUDES) $(PERL5_CCFLAGS) -I$(PERL5_INCLUDE) + +$(LIBPREFIX)$(TARGET)$(SO): $(OBJS) $(IOBJS) + $(LDSHARED) $(OBJS) $(IOBJS) $(PERL5_DLNK) $(LIBS) -o $(LIBPREFIX)$(TARGET)$(SO) + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS new file mode 100755 index 0000000..6707d33 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/NEWS @@ -0,0 +1,10 @@ +With --timing, you can actually record action scripts which are meaningful... +Earlier, the events just got garbled, because the GUI could not react as +fast as the events were churned out. + +Clipboard is supported (thanks to Uwe). + +Keys are recorded by their symbols with the --symbolic switch, provided you +have the X11::Keysyms module. + +After pressing Control twice, you can show the last reference image with 'd'. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README new file mode 100755 index 0000000..8c92b32 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/README @@ -0,0 +1,88 @@ +This is VisualNaCro. + +DISCLAIMER: recorder.pl is not yet functional. + +What does it? + + It is a Perl module meant to remote control a VNC server. + + It includes a recorder (written in Perl) to make it easy to + record a macro, which is just a Perl script, and which you can + modify to your heart's content. + + The most important feature, however, is that you can mark a + rectangle which the Perl script will try to find again when you + run it. Thus when you play a game and want to hit a certain button, + you just hit the Ctrl key twice, mark the button, and from then on, + all mouse movements will be repeated relative to that button, even + if the button is somewhere else when you run the script the next + time. + + If you know Tcl Expect, you will recognize this approach. Only this + time, it is not text, but an image which is expected. + +How does it work? + + It acts as a VNC proxy: your Perl script starts its own VNC server. + The script now can intercept inputs and outputs, and act upon them. + In order to write a macro, start + + recorder.pl --script my-macro.pl --timing host:port + + connect with a vncviewer of your choice to :23, where + is the computer on which recorder.pl was started (not necessarily the + same as the VNC server!). Now your actions are recorded into + my_macro.pl, and the images you want to grep for will be saved as + my_macro-1.pnm, my_macro-2.pnm, ... + + In order to finish the script, hit Ctrl twice and say "q". + +Why did I do it? + + Because I could ;-) + + No really, I needed a way to write automated tests. While there + exist a lot of OpenSource programs for web testing, I found none + of them easy to use, and for GUI testing I found xautomation. + + Xautomation has this "visual grep" (or "graphical expect") feature: + given an image it tries to find it on the desktop and returns the + coordinates. Unfortunately, there is no easy way to record macros + with it, and it only works on X11. + + As I know VNC pretty well, and there are VNC servers for every OS + and gadget, I thought it might be cool to have this feature to + control a VNC server. + + Actually, it makes it even easier: with plain X11, for example, you + can not know where on the screen the action is if you don't check + the whole screen. This complex problem is beautifully addressed + in Karl Runge's x11vnc. + + My main purpose is to run regression tests on different browsers, + which I can easily do by starting Xvnc and using VisualNaCro. + +How did I do it? + + I wondered long about how to do it. I couldn't take the same approach + as xautomation: I cannot connect to the VNC server thousand times + per second. So I decided to create an interface of LibVNCServer/ + LibVNCClient for use in a script language. + + Fortunately, this task is made very, very easy by SWIG. As Perl + is one of my favorite script languages, I decided to use this. + But SWIG makes it easy to use the very same interface for other + popular languages, so you are welcome to port VisualNaCro to + the language of your choice! + +Isn't it pronounced "Visual Macro"? + + Yes. But I liked the Visual Na Cro play of acronyms. I'm sorry if + you don't find it funny. + +What's the license? + + GPL. It is based on LibVNCServer/LibVNCClient, so it has to be. + If you want to port this package to use vncreflector, which has a + BSD license, go ahead. + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh new file mode 100755 index 0000000..2d1645d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/autogen.sh @@ -0,0 +1,55 @@ +#! /bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +AUTOMAKE=automake-1.4 +ACLOCAL=aclocal-1.4 + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + AUTOMAKE=automake + ACLOCAL=aclocal +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile VisualNaCro." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile VisualNaCro." + echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +(test -f $srcdir/nacro.h) || { + echo "You must run this script in the top-level VisualNaCro directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +$ACLOCAL $ACLOCAL_FLAGS +#autoheader +$AUTOMAKE --add-missing --copy +autoconf + +echo "Running ./configure --enable-maintainer-mode" "$@" +$srcdir/configure --enable-maintainer-mode "$@" + +echo "Now type 'make' to compile VisualNaCro." diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac new file mode 100755 index 0000000..1f78317 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/configure.ac @@ -0,0 +1,252 @@ +dnl Process this file with autoconf to produce a configure script. +dnl The macros which aren't shipped with the autotools are stored in the +dnl Tools/config directory in .m4 files. + +AC_INIT([VisualNaCro],[0.1],[http://libvncserver.sourceforge.net]) +AC_PREREQ(2.54) +AC_CANONICAL_HOST +AM_INIT_AUTOMAKE + +dnl Checks for programs. +AC_CHECK_PROG(SWIG,swig,swig) +AC_CHECK_PROG(LIBVNCSERVERCONFIG,libvncserver-config,yes,no) +if test "$LIBVNCSERVERCONFIG" != "yes"; then + AC_MSG_ERROR([Need to have libvncserver-config in PATH]) + exit 1 +fi +AC_PROG_CC +AC_PROG_RANLIB +AC_EXEEXT +AC_OBJEXT + +LIBVNCSERVERCFLAGS=`libvncserver-config --cflags` +LIBVNCSERVERLIBS=`libvncserver-config --libs` +AC_SUBST(LIBVNCSERVERCFLAGS) +AC_SUBST(LIBVNCSERVERLIBS) + +dnl Checks for header files. +AC_HEADER_STDC + +dnl How to specify include directories that may be system directories. +# -I should not be used on system directories (GCC) +if test "$GCC" = yes; then + ISYSTEM="-isystem " +else + ISYSTEM="-I" +fi + + +# Set info about shared libraries. +AC_SUBST(SO) +AC_SUBST(LDSHARED) +AC_SUBST(CCSHARED) +AC_SUBST(LINKFORSHARED) + +# SO is the extension of shared libraries `(including the dot!) +AC_MSG_CHECKING(SO) +if test -z "$SO" +then + case $host in + *-*-hp*) SO=.sl;; + *-*-darwin*) SO=.bundle;; + *-*-cygwin* | *-*-mingw*) SO=.dll;; + *) SO=.so;; + esac +fi +AC_MSG_RESULT($SO) + +# LDSHARED is the ld *command* used to create shared library +# -- "ld" on SunOS 4.x.x, "ld -G" on SunOS 5.x, "ld -shared" on IRIX 5 +# (Shared libraries in this instance are shared modules to be loaded into +# Python, as opposed to building Python itself as a shared library.) +AC_MSG_CHECKING(LDSHARED) +if test -z "$LDSHARED" +then + case $host in + *-*-aix*) LDSHARED="\$(srcdir)/ld_so_aix \$(CC)";; + *-*-cygwin* | *-*-mingw*) + if test "$GCC" = yes; then + LDSHARED="dllwrap --driver-name gcc --dlltool dlltool --export-all-symbols --as as --dllname \$(LIBPREFIX)\$(TARGET)\$(SO)" + else + if test "cl" = $CC ; then + # Microsoft Visual C++ (MSVC) + LDSHARED="$CC -nologo -LD" + else + # Unknown compiler try gcc approach + LDSHARED="$CC -shared" + fi + fi ;; + *-*-irix5*) LDSHARED="ld -shared";; + *-*-irix6*) LDSHARED="ld ${SGI_ABI} -shared -all";; + *-*-sunos4*) LDSHARED="ld";; + *-*-solaris*) LDSHARED="ld -G";; + *-*-hp*) LDSHARED="ld -b";; + *-*-osf*) LDSHARED="ld -shared -expect_unresolved \"*\"";; + *-sequent-sysv4) LDSHARED="ld -G";; + *-*-next*) + if test "$ns_dyld" + then LDSHARED='$(CC) $(LDFLAGS) -bundle -prebind' + else LDSHARED='$(CC) $(CFLAGS) -nostdlib -r'; + fi + if test "$with_next_framework" ; then + LDSHARED="$LDSHARED \$(LDLIBRARY)" + fi ;; + *-*-linux*) LDSHARED="gcc -shared";; + *-*-dgux*) LDSHARED="ld -G";; + *-*-freebsd3*) LDSHARED="gcc -shared";; + *-*-freebsd* | *-*-openbsd*) LDSHARED="ld -Bshareable";; + *-*-netbsd*) + if [[ "`$CC -dM -E - /dev/null` + if test "$PERL5DIR" != ""; then + dirs="$PERL5DIR $PERL5DIR/CORE" + PERL5EXT=none + for i in $dirs; do + if test -r $i/perl.h; then + AC_MSG_RESULT($i) + PERL5EXT="$i" + break; + fi + done + if test "$PERL5EXT" = none; then + PERL5EXT="$PERL5DIR/CORE" + AC_MSG_RESULT(could not locate perl.h...using $PERL5EXT) + fi + + AC_MSG_CHECKING(for Perl5 library) + PERL5LIB=`($PERL -e 'use Config; $_=$Config{libperl}; s/^lib//; s/$Config{_a}$//; print $_, "\n"') 2>/dev/null` + if test "$PERL5LIB" = "" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5LIB) + fi + AC_MSG_CHECKING(for Perl5 compiler options) + PERL5CCFLAGS=`($PERL -e 'use Config; print $Config{ccflags}, "\n"' | sed "s/-I/$ISYSTEM/") 2>/dev/null` + if test "$PERL5CCFLAGS" = "" ; then + AC_MSG_RESULT(not found) + else + AC_MSG_RESULT($PERL5CCFLAGS) + fi + else + AC_MSG_RESULT(unable to determine perl5 configuration) + PERL5EXT=$PERL5DIR + fi +else + AC_MSG_RESULT(could not figure out how to run perl5) +fi + +# Cygwin (Windows) needs the library for dynamic linking +case $host in +*-*-cygwin* | *-*-mingw*) PERL5DYNAMICLINKING="-L$PERL5EXT -l$PERL5LIB";; +*)PERL5DYNAMICLINKING="";; +esac + +AC_SUBST(PERL) +AC_SUBST(PERL5EXT) +AC_SUBST(PERL5DYNAMICLINKING) +AC_SUBST(PERL5LIB) +AC_SUBST(PERL5CCFLAGS) + +#---------------------------------------------------------------- +# Miscellaneous +#---------------------------------------------------------------- + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT + +dnl configure.in ends here diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h new file mode 100755 index 0000000..252f411 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/default8x16.h @@ -0,0 +1,261 @@ +static unsigned char default8x16FontData[4096+1]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, +0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00, +0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00, +0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, +0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00, +0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, +0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +static int default8x16FontMetaData[256*5+1]={ +0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; +static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c new file mode 100755 index 0000000..2fc9e36 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.c @@ -0,0 +1,799 @@ +#include +#include +#include +#include + +#include "nacro.h" + +/* for visual grepping */ +typedef struct image_t { + int width,height; + char* buffer; +} image_t; + +/* this is a VNC connection */ +typedef struct private_resource_t { + int listen_port; + rfbScreenInfo* server; + rfbClient* client; + + uint32_t keysym; + rfbBool keydown; + + int x,y; + int buttons; + + char* text_client; + char* text_server; + + image_t* grep_image; + int x_origin,y_origin; + + enum { SLEEP,VISUALGREP,WAITFORUPDATE } state; + result_t result; +} private_resource_t; + +/* resource management */ + +#define MAX_RESOURCE_COUNT 20 + +static private_resource_t resource_pool[MAX_RESOURCE_COUNT]; +static int resource_count=0; + +static private_resource_t* get_resource(int resource) +{ + if(resource>=MAX_RESOURCE_COUNT || resource<0 || resource_pool[resource].client==0) + return NULL; + return resource_pool+resource; +} + +static private_resource_t* get_next_resource(void) +{ + if(resource_countclient=NULL; +} + +/* hooks */ + +static void got_key(rfbBool down,rfbKeySym keysym,rfbClientRec* cl) +{ + private_resource_t* res=(private_resource_t*)cl->screen->screenData; + + res->keydown=down; + res->keysym=keysym; + res->result|=RESULT_KEY; +} + +static void got_mouse(int buttons,int x,int y,rfbClientRec* cl) +{ + private_resource_t* res=(private_resource_t*)cl->screen->screenData; + + res->buttons=buttons; + res->x=x; + res->y=y; + res->result|=RESULT_MOUSE; +} + +static void got_text(char* str,int len,rfbClientRec* cl) +{ + private_resource_t* res=(private_resource_t*)cl->screen->screenData; + + if (res->text_client) + free(res->text_client); + res->text_client=strdup(str); + res->result|=RESULT_TEXT_CLIENT; +} + +static void got_text_from_server(rfbClient* cl, const char *str, int textlen) +{ + private_resource_t* res=(private_resource_t*)cl->clientData; + + if (res->text_server) + free(res->text_server); + res->text_server=strdup(str); + res->result|=RESULT_TEXT_SERVER; +} + +static rfbBool malloc_frame_buffer(rfbClient* cl) +{ + private_resource_t* res=(private_resource_t*)cl->clientData; + + if(!res->server) { + int w=cl->width,h=cl->height; + + res->client->frameBuffer=malloc(w*4*h); + + res->server=rfbGetScreen(NULL,NULL,w,h,8,3,4); + res->server->screenData=res; + res->server->port=res->listen_port; + res->server->frameBuffer=res->client->frameBuffer; + res->server->kbdAddEvent=got_key; + res->server->ptrAddEvent=got_mouse; + res->server->setXCutText=got_text; + rfbInitServer(res->server); + } else { + /* TODO: realloc if necessary */ + /* TODO: resolution change: send NewFBSize */ + /* TODO: if the origin is out of bounds, reset to 0 */ + } +} + +static bool_t do_visual_grep(private_resource_t* res,int x,int y,int w,int h) +{ + rfbClient* cl; + image_t* image; + int x_start,y_start,x_end=x+w-1,y_end=y+h-1; + bool_t found=0; + + if(res==0 || (cl=res->client)==0 || (image=res->grep_image)==0) + return 0; + + x_start=x-image->width; + y_start=y-image->height; + if(x_start<0) x_start=0; + if(y_start<0) y_start=0; + if(x_end+image->width>cl->width) x_end=cl->width-image->width; + if(y_end+image->height>cl->height) y_end=cl->height-image->height; + + /* find image and set x_origin,y_origin if found */ + for(y=y_start;yheight;j++) + for(i=0;matching && iwidth;i++) + if(memcmp(cl->frameBuffer+4*(x+i+cl->width*(y+j)),image->buffer+4*(i+image->width*j),3)) + matching=0; + if(matching) { + private_resource_t* res=(private_resource_t*)cl->clientData; + res->x_origin=x; + res->y_origin=y; + return -1; + } + } + return 0; +} + +static void got_frame_buffer(rfbClient* cl,int x,int y,int w,int h) +{ + private_resource_t* res=(private_resource_t*)cl->clientData; + + assert(res->server); + + if(res->grep_image && do_visual_grep(res,x,y,w,h)) { + res->result|=RESULT_FOUNDIMAGE; + } + if(res->server) { + rfbMarkRectAsModified(res->server,x,y,x+w,y+h); + } + + res->result|=RESULT_SCREEN; +} + +/* init/shutdown functions */ + +resource_t initvnc(const char* server,int server_port,int listen_port) +{ + private_resource_t* res=get_next_resource(); + int dummy=0; + + if(res==0) + return -1; + + /* remember for later */ + res->listen_port=listen_port; + + res->text_client = NULL; + res->text_server = NULL; + + res->client=rfbGetClient(8,3,4); + res->client->clientData=(void*)res; + res->client->GotFrameBufferUpdate=got_frame_buffer; + res->client->MallocFrameBuffer=malloc_frame_buffer; + res->client->GotXCutText=got_text_from_server; + res->client->serverHost=strdup(server); + res->client->serverPort=server_port; + res->client->appData.encodingsString="raw"; + if(!rfbInitClient(res->client,&dummy,NULL)) { + res->client=NULL; + return -1; + } + return res-resource_pool; +} + +void closevnc(resource_t resource) +{ + private_resource_t* res=get_resource(resource); + if(res==0) + return; + + if(res->server) + rfbScreenCleanup(res->server); + + assert(res->client); + + rfbClientCleanup(res->client); + + res->client=NULL; +} + +/* PNM (image) helpers */ + +bool_t savepnm(resource_t resource,const char* filename,int x1,int y1,int x2,int y2) +{ + private_resource_t* res=get_resource(resource); + int i,j,w,h; + uint32_t* buffer; + FILE* f; + + if(res==0 || res->client==0) + return 0; + assert(res->client->format.depth==24); + + w=res->client->width; + h=res->client->height; + buffer=(uint32_t*)res->client->frameBuffer; + + if(res==0 || x1>x2 || y1>y2 || x1<0 || x2>=w || y1<0 || y2>=h) + return FALSE; + + f=fopen(filename,"wb"); + + if(f==0) + return FALSE; + + fprintf(f,"P6\n%d %d\n255\n",1+x2-x1,1+y2-y1); + for(j=y1;j<=y2;j++) + for(i=x1;i<=x2;i++) { + fwrite(buffer+i+j*w,3,1,f); + } + if(fclose(f)) + return FALSE; + return TRUE; +} + +static image_t* loadpnm(const char* filename) +{ + FILE* f=fopen(filename,"rb"); + char buffer[1024]; + int i,j,w,h; + image_t* image; + + if(f==0) + return NULL; + + if(!fgets(buffer,1024,f) || strcmp("P6\n",buffer)) { + fclose(f); + return NULL; + } + + do { + fgets(buffer,1024,f); + if(feof(f)) { + fclose(f); + return NULL; + } + } while(buffer[0]=='#'); + + if( sscanf(buffer,"%d %d",&w,&h)!=2 + || !fgets(buffer,1024,f) || strcmp("255\n",buffer)) { + fclose(f); + return NULL; + } + + image=(image_t*)malloc(sizeof(image_t)); + image->width=w; + image->height=h; + image->buffer=malloc(w*4*h); + if(!image->buffer) { + fclose(f); + free(image); + return NULL; + } + + for(j=0;jbuffer+4*(i+w*j),3,1,f)!=1) { + fprintf(stderr,"Could not read 3 bytes at %d,%d\n",i,j); + fclose(f); + free(image->buffer); + free(image); + return NULL; + } + + fclose(f); + + return image; +} + +static void free_image(image_t* image) +{ + if(image->buffer) + free(image->buffer); + free(image); +} + +static void copy_line(rfbScreenInfo *dest, char *backup, + int x0, int y0, int x1, int y1, int color_offset) +{ + uint8_t *d = (uint8_t *)dest->frameBuffer, *s = (uint8_t *)backup; + int i; + int steps0 = x1 > x0 ? x1 - x0 : x0 - x1; + int steps1 = y1 > y0 ? y1 - y0 : y0 - y1; + + if (steps1 > steps0) + steps0 = steps1; + else if (steps0 == 0) + steps0 = 1; + + for (i = 0; i <= steps0; i++) { + int j, index = 4 * (x0 + i * (x1 - x0) / steps0 + + dest->width * (y0 + i * (y1 - y0) / steps0)); + for (j = 0; j < 4; j++) + d[index + j] = s[index + j] + color_offset; + } + + rfbMarkRectAsModified(dest, x0 - 5, y0 - 5, x1 + 1, y1 + 2); +} + +result_t displaypnm(resource_t resource, const char *filename, + coordinate_t x, coordinate_t y, bool_t border, + timeout_t timeout_in_seconds) +{ + private_resource_t* res = get_resource(resource); + image_t *image; + char* fake_frame_buffer; + char* backup; + int w, h, i, j, w2, h2; + result_t result; + + if (res == NULL || res->server == NULL || + (image = loadpnm(filename)) == NULL) + return 0; + + w = res->server->width; + h = res->server->height; + fake_frame_buffer = malloc(w * 4 * h); + if(!fake_frame_buffer) + return 0; + memcpy(fake_frame_buffer, res->server->frameBuffer, w * 4 * h); + + backup = res->server->frameBuffer; + res->server->frameBuffer = fake_frame_buffer; + + w2 = image->width; + if (x + w2 > w) + w2 = w - x; + h2 = image->height; + if (y + h2 > h) + h2 = h - y; + for (j = 0; j < h2; j++) + memcpy(fake_frame_buffer + 4 * (x + (y + j) * w), + image->buffer + j * 4 * image->width, 4 * w2); + free(image); + if (border) { + copy_line(res->server, backup, x, y, x + w2, y, 0x80); + copy_line(res->server, backup, x, y, x, y + h2, 0x80); + copy_line(res->server, backup, x + w2, y, x + w2, y + h2, 0x80); + copy_line(res->server, backup, x, y + h2, x + w2, y + h2, 0x80); + } + rfbMarkRectAsModified(res->server, + x - 1, y - 1, x + w2 + 1, y + h2 + 1); + + result = waitforinput(resource, timeout_in_seconds); + + res->server->frameBuffer=backup; + free(fake_frame_buffer); + rfbMarkRectAsModified(res->server, + x - 1, y - 1, x + w2 + 1, y + h2 + 1); + + return result; +} + +/* process() and friends */ + +/* this function returns only if res->result in return_mask */ +static result_t private_process(resource_t resource,timeout_t timeout_in_seconds,result_t return_mask) +{ + private_resource_t* res=get_resource(resource); + fd_set fds; + struct timeval tv,tv_start,tv_end; + unsigned long timeout=(unsigned long)(timeout_in_seconds*1000000UL); + int count,max_fd; + + if(res==0) + return 0; + + assert(res->client); + + gettimeofday(&tv_start,NULL); + res->result=0; + + do { + unsigned long timeout_done; + + if(res->server) { + rfbBool loop; + do { + loop=rfbProcessEvents(res->server,res->server->deferUpdateTime); + } while(loop && (res->result&return_mask)==0 + && rfbIsActive(res->server)); + + if(!rfbIsActive(res->server)) + return RESULT_SHUTDOWN; + + if((res->result&return_mask)!=0) + return res->result; + + memcpy((char*)&fds,(const char*)&(res->server->allFds),sizeof(fd_set)); + max_fd=res->server->maxFd; + } else { + FD_ZERO(&fds); + max_fd=0; + } + FD_SET(res->client->sock,&fds); + if(res->client->sock>max_fd) + max_fd=res->client->sock; + + gettimeofday(&tv_end,NULL); + timeout_done=tv_end.tv_usec-tv_start.tv_usec+ + 1000000L*(tv_end.tv_sec-tv_start.tv_sec); + if(timeout_done>=timeout) + return RESULT_TIMEOUT; + + tv.tv_usec=((timeout-timeout_done)%1000000); + tv.tv_sec=(timeout-timeout_done)/1000000; + + count=select(max_fd+1,&fds,NULL,NULL,&tv); + if(count<0) + return 0; + + if(count>0) { + if(FD_ISSET(res->client->sock,&fds)) { + if(!HandleRFBServerMessage(res->client)) { + closevnc(resource); + return 0; + } + if((res->result&return_mask)!=0) + return res->result; + } + } else { + res->result|=RESULT_TIMEOUT; + return res->result; + } + } while(1); + + return RESULT_TIMEOUT; +} + +result_t process(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,RESULT_TIMEOUT); +} + +result_t waitforanything(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,-1); +} + +result_t waitforinput(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,RESULT_KEY|RESULT_MOUSE|RESULT_TIMEOUT); +} + +result_t waitforupdate(resource_t res,timeout_t timeout) +{ + return private_process(res,timeout,RESULT_SCREEN|RESULT_TIMEOUT); +} + +result_t visualgrep(resource_t resource,const char* filename,timeout_t timeout) +{ + private_resource_t* res=get_resource(resource); + image_t* image; + result_t result; + + if(res==0 || res->client==0) + return 0; + + /* load filename and set res->grep_image to this image */ + image=loadpnm(filename); + if(image==0) + return 0; + if(res->grep_image) + free_image(res->grep_image); + res->grep_image=image; + + if(do_visual_grep(res,0,0,res->client->width,res->client->height)) + return RESULT_FOUNDIMAGE; + + result=private_process(resource,timeout,RESULT_FOUNDIMAGE|RESULT_TIMEOUT); + + /* free image */ + if(res->grep_image) { + free_image(res->grep_image); + res->grep_image=NULL; + } + + return result; +} + +/* auxiliary function for alert */ + +#include "default8x16.h" + +static void center_text(rfbScreenInfo* screen,const char* message,int* x,int* y,int* w,int* h) +{ + rfbFontData* font=&default8x16Font; + const char* pointer; + int j,x1,y1,x2,y2,line_count=0; + if(message==0 || screen==0) + return; + rfbWholeFontBBox(font,&x1,&y1,&x2,&y2); + for(line_count=1,pointer=message;*pointer;pointer++) + if(*pointer=='\n') + line_count++; + + *h=(y2-y1)*line_count; + assert(*h>0); + + if(*h>screen->height) + *h=screen->height; + + *x=0; *w=screen->width; *y=(screen->height-*h)/2; + + rfbFillRect(screen,*x,*y,*x+*w,*y+*h,0xff0000); + + for(pointer=message,j=0;jscreen->width) + width=screen->width; + + x_cur=(screen->width-width)/2; + for(;pointer!=eol;pointer++) + x_cur+=rfbDrawCharWithClip(screen,font, + x_cur,y_cur,*pointer, + 0,0,screen->width,screen->height, + 0xffffffff,0xffffffff); + pointer++; + } + rfbMarkRectAsModified(screen,*x,*y,*x+*w,*y+*h); +} + +/* this is an overlay which is shown for a certain time */ + +result_t alert(resource_t resource,const char* message,timeout_t timeout) +{ + private_resource_t* res=get_resource(resource); + char* fake_frame_buffer; + char* backup; + int x,y,w,h; + result_t result; + + if(res == NULL || res->server==NULL) + return -1; + + w=res->server->width; + h=res->server->height; + + fake_frame_buffer=malloc(w*4*h); + if(!fake_frame_buffer) + return -1; + memcpy(fake_frame_buffer,res->server->frameBuffer,w*4*h); + + backup=res->server->frameBuffer; + res->server->frameBuffer=fake_frame_buffer; + center_text(res->server,message,&x,&y,&w,&h); + fprintf(stderr,"%s\n",message); + + result=waitforinput(resource,timeout); + + res->server->frameBuffer=backup; + free(fake_frame_buffer); + rfbMarkRectAsModified(res->server,x,y,x+w,y+h); + + return result; +} +/* inspect last events */ + +keysym_t getkeysym(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->keysym; +} + +bool_t getkeydown(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->keydown; +} + +coordinate_t getx(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->x; +} + +coordinate_t gety(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->y; +} + +buttons_t getbuttons(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->buttons; +} + +const char *gettext_client(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->text_client; +} + +result_t rubberband(resource_t resource, coordinate_t x0, coordinate_t y0) +{ + private_resource_t* res=get_resource(resource); + char* fake_frame_buffer; + char* backup; + int w, h, x, y; + + if(res == NULL || res->server==NULL) + return -1; + + x = res->x; + y = res->y; + w = res->server->width; + h = res->server->height; + fake_frame_buffer = malloc(w * 4 * h); + if(!fake_frame_buffer) + return 0; + memcpy(fake_frame_buffer, res->server->frameBuffer, w * 4 * h); + + backup = res->server->frameBuffer; + res->server->frameBuffer = fake_frame_buffer; + + while (res->buttons) { + result_t r = waitforinput(resource, 1000000L); + if (x == res->x && y == res->y) + continue; + copy_line(res->server, backup, x0, y0, x, y0, 0); + copy_line(res->server, backup, x0, y0, x0, y, 0); + copy_line(res->server, backup, x, y0, x, y, 0); + copy_line(res->server, backup, x0, y, x, y, 0); + x = res->x; + y = res->y; + copy_line(res->server, backup, x0, y0, x, y0, 0x80); + copy_line(res->server, backup, x0, y0, x0, y, 0x80); + copy_line(res->server, backup, x, y0, x, y, 0x80); + copy_line(res->server, backup, x0, y, x, y, 0x80); + } + + copy_line(res->server, backup, x0, y0, x, y0, 0); + copy_line(res->server, backup, x0, y0, x0, y, 0); + copy_line(res->server, backup, x, y0, x, y, 0); + copy_line(res->server, backup, x0, y, x, y, 0); + + res->server->frameBuffer=backup; + free(fake_frame_buffer); + + return RESULT_MOUSE; +} + +const char *gettext_server(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->text_server; +} + +/* send events to the server */ + +bool_t sendkey(resource_t res,keysym_t keysym,bool_t keydown) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + return SendKeyEvent(r->client,keysym,keydown); +} + +bool_t sendascii(resource_t res,const char *string) +{ + timeout_t delay = 0.1; + private_resource_t* r=get_resource(res); + int i; + if(r==NULL) + return 0; + while (*string) { + int keysym = *string; + int need_shift = 0; + + if (keysym >= 8 && keysym < ' ') + keysym += 0xff00; + else if (keysym >= 'A' && keysym <= 'Z') + need_shift = 1; + else if (keysym > '~') { + fprintf(stderr, "String contains non-ASCII " + "character 0x%02x\n", *string); + return FALSE; + } + + if (need_shift) { + if (!SendKeyEvent(r->client,0xffe1,1)) + return FALSE; + waitforinput(r,delay); + } + for (i = 1; i >= 0; i--) { + if (!SendKeyEvent(r->client,keysym,i)) + return FALSE; + waitforinput(r,delay); + } + if (need_shift) { + if (!SendKeyEvent(r->client,0xffe1,0)) + return FALSE; + waitforinput(r,delay); + } + string++; + } + return TRUE; +} + +bool_t sendmouse(resource_t res,coordinate_t x,coordinate_t y,buttons_t buttons) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + return SendPointerEvent(r->client,x,y,buttons); +} + +bool_t sendtext(resource_t res, const char *string) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + return SendClientCutText(r->client, (char *)string, (int)strlen(string)); +} + +bool_t sendtext_to_server(resource_t res, const char *string) +{ + private_resource_t* r=get_resource(res); + if(r==NULL) + return 0; + rfbSendServerCutText(r->server, (char *)string, (int)strlen(string)); + return 1; +} + +/* for visual grepping */ + +coordinate_t getxorigin(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->x_origin; +} + +coordinate_t getyorigin(resource_t res) +{ + private_resource_t* r=get_resource(res); + return r->y_origin; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h new file mode 100755 index 0000000..abd0067 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/nacro.h @@ -0,0 +1,120 @@ +#ifndef NACRO_H +#define NACRO_H + +#ifdef SWIG +%module nacro + +%{ + +/* types used */ + +/* 0=false, every other value=true */ +typedef int bool_t; + +/* a keysym: identical with ASCII for values between 0-127 */ +typedef int keysym_t; + +/* this can be negative, because of a new origin set via visual grep */ +typedef int coordinate_t; + +/* left button is 1<<0, middle button is 1<<1, right button is 1<<2 */ +typedef unsigned char buttons_t; + +/* this is sort of a "file descriptor" for the proxy */ +typedef int resource_t; + +/* the timeout, specified in microseconds, for process() and friends */ +typedef double timeout_t; + +/* the return values of process() and friends */ +typedef int result_t; +/* +%constant int RESULT_TIMEOUT=1; +%constant int RESULT_KEY=2; +%constant int RESULT_MOUSE=4; +%constant int RESULT_TEXT_CLIENT=8; +%constant int RESULT_TEXT_CLIENT=16; +%constant int RESULT_SCREEN=32; +%constant int RESULT_FOUNDIMAGE=64; +%constant int RESULT_SHUTDOWN=128; +*/ + +%} + +#endif // SWIG + +typedef int bool_t; +typedef int keysym_t; +typedef int coordinate_t; +typedef unsigned char buttons_t; +typedef int resource_t; +typedef double timeout_t; +typedef int result_t; +#define RESULT_TIMEOUT 1 +#define RESULT_KEY 2 +#define RESULT_MOUSE 4 +#define RESULT_TEXT_CLIENT 8 +#define RESULT_TEXT_SERVER 16 +#define RESULT_SCREEN 32 +#define RESULT_FOUNDIMAGE 64 +#define RESULT_SHUTDOWN 128 + +/* init/shutdown */ + +resource_t initvnc(const char* server,int serverPort,int listenPort); +void closevnc(resource_t res); + +/* run the event loop for a while: process() and friends: + * process() returns only on timeout, + * waitforanything returns on any event (input, output or timeout), + * waitforupdate() returns only on timeout or screen update, + * waitforinput() returns only on timeout or user input, + * visualgrep() returns only on timeout or if the specified PNM was found + * (in that case, x_origin and y_origin are set to the upper left + * corner of the matched image). */ + +result_t process(resource_t res,timeout_t seconds); +result_t waitforanything(resource_t res,timeout_t seconds); +result_t waitforupdate(resource_t res,timeout_t seconds); +result_t waitforinput(resource_t res,timeout_t seconds); +result_t visualgrep(resource_t res,const char* filename,timeout_t seconds); + +/* inspect last events */ + +keysym_t getkeysym(resource_t res); +bool_t getkeydown(resource_t res); + +coordinate_t getx(resource_t res); +coordinate_t gety(resource_t res); +buttons_t getbuttons(resource_t res); + +const char *gettext_client(resource_t res); +const char *gettext_server(resource_t res); + +/* send events to the server */ + +bool_t sendkey(resource_t res,keysym_t keysym,bool_t keydown); +bool_t sendascii(resource_t res,const char *string); +bool_t sendmouse(resource_t res,coordinate_t x,coordinate_t y,buttons_t buttons); +bool_t sendtext(resource_t res, const char *string); +bool_t sendtext_to_server(resource_t res, const char *string); + +/* for visual grepping */ + +coordinate_t getxorigin(resource_t res); +coordinate_t getyorigin(resource_t res); + +bool_t savepnm(resource_t res,const char* filename,coordinate_t x1, coordinate_t y1, coordinate_t x2, coordinate_t y2); + +result_t displaypnm(resource_t res, const char *filename, coordinate_t x, coordinate_t y, bool_t border, timeout_t timeout); + +/* this displays an overlay which is shown for a certain time */ + +result_t alert(resource_t res,const char* message,timeout_t timeout); + +/* display a rectangular rubber band between (x0, y0) and the current + mouse pointer, as long as a button us pressed. */ + +result_t rubberband(resource_t res, coordinate_t x0, coordinate_t y0); + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl new file mode 100755 index 0000000..01ab3f2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/VisualNaCro/recorder.pl @@ -0,0 +1,282 @@ +#!/usr/bin/perl + +use Getopt::Long; +use nacro; + +$output="my_script"; +$server="localhost"; +$port=5900; +$listen_port=5923; +$timing=0; +$symbolic=0; +$compact=0; +$compact_dragging=0; + +if(!GetOptions( + "script:s" => \$output, + "listen:i" => \$listen_port, + "timing" => \$timing, + "symbolic" => \$symbolic, + "compact" => \$compact, + "compact-dragging" => \$compact_dragging, +) || $#ARGV!=0) { + print STDERR "Usage: $ARGV0 [--script output_name] [--listen listen_port] [--timing]\n\t[--symbolic] [--compact] [--compact-dragging] server[:port]\n"; + exit 2; +} + +$output=~s/\.pl$//; + +if ($timing) { + eval 'use Time::HiRes'; + $timing=0 if $@; + $starttime=-1; +} + +if ($symbolic) { + eval 'use X11::Keysyms qw(%Keysyms)'; + $symbolic=0 if $@; + %sym_name = reverse %Keysyms; +} + +$server=$ARGV[0]; + +if($server=~/^(.*):(\d+)$/) { + $server=$1; + $port=$2; + if($2<100) { + $port+=5900; + } +} + +if($listen_port<100) { + $listen_port+=5900; +} + +# do not overwrite script + +if(stat("$output.pl")) { + print STDERR "Will not overwrite $output.pl\n"; + exit 2; +} + +# start connection +$vnc=nacro::initvnc($server,$port,$listen_port); + +if($vnc<0) { + print STDERR "Could not initialize $server:$port\n"; + exit 1; +} + +open OUT, ">$output.pl"; +print OUT "#!/usr/bin/perl\n"; +print OUT "\n"; +if ($symbolic) { + print OUT "use X11::Keysyms qw(\%sym);\n"; +} +print OUT "use nacro;\n"; +print OUT "\n"; +print OUT "\$x_origin=0; \$y_origin=0;\n"; +print OUT "\$vnc=nacro::initvnc(\"$server\",$port,$listen_port);\n"; + +$mode="passthru"; +$image_counter=1; +$magickey=0; +$x_origin=0; $y_origin=0; + +sub writetiming () { + if ($timing) { + $now=Time::HiRes::time(); + if ($starttime>0) { + print OUT "nacro::process(\$vnc," . ($now - $starttime) . ");\n"; + } + $starttime=$now; + } +} + +$last_button = -1; + +sub handle_mouse { + my $x = shift; + my $y = shift; + my $buttons = shift; + if(nacro::sendmouse($vnc,$x,$y,$buttons)) { + $x-=$x_origin; $y-=$y_origin; + writetiming(); + print OUT "nacro::sendmouse(\$vnc,\$x_origin" + . ($x>=0?"+":"")."$x,\$y_origin" + . ($y>=0?"+":"")."$y,$buttons);\n"; + } +} + +sub toggle_text { + my $text = shift; + if ($text eq "Timing") { + return $text . " is " . ($timing ? "on" : "off"); + } elsif ($text eq "Key presses") { + return $text . " are recorded " . ($symbolic ? "symbolically" + : "numerically"); + } elsif ($text eq "Mouse moves") { + return $text . " are recorded " . ($compact ? "compacted" + : "verbosely"); + } elsif ($text eq "Mouse drags") { + return $text . " are recorded " . ($compact ? "compacted" + : "verbosely"); + } + return $text . ": "; +} + +$menu_message = "VisualNaCro: press 'q' to quit,\n" + . "'i' to display current settings,\n" + . "'c', 'r' to toggle compact mouse movements or drags,\n" + . "'d' to display current reference image,\n" + . "or mark reference rectangle by dragging"; + +while(1) { + $result=nacro::waitforinput($vnc,999999); + if($result==0) { + # server went away + close OUT; + exit 0; + } + + if($mode eq "passthru") { + if($result&$nacro::RESULT_KEY) { + $keysym=nacro::getkeysym($vnc); + $keydown=nacro::getkeydown($vnc); + if(nacro::sendkey($vnc,$keysym,$keydown)) { + writetiming(); + if ($symbolic and exists $sym_name{$keysym}) { + print OUT 'nacro::sendkey($vnc,$sym{'.$sym_name{$keysym}."},$keydown);\n"; + } else { + print OUT "nacro::sendkey(\$vnc,$keysym,$keydown);\n"; + } + } + if($keysym==0xffe3 || $keysym==0xffe4) { + if (!$keydown) { + # Control pressed + $magickey++; + if ($magickey > 1) { + $magickey = 0; + $mode = "menu"; + nacro::alert($vnc, + $menu_message, 10); + } + } + } else { + $magickey=0; + } + } + if($result&$nacro::RESULT_MOUSE) { + $x=nacro::getx($vnc); + $y=nacro::gety($vnc); + $buttons=nacro::getbuttons($vnc); + if ($buttons != $last_buttons) { + if (!$buttons && $compact_dragging) { + handle_mouse($x, $y, $last_buttons); + } + $last_buttons = $buttons; + } else { + if (($buttons && $compact_dragging) || + (!$buttons && $compact)) { + next; + } + } + handle_mouse($x, $y, $buttons); + } + if ($result & $nacro::RESULT_TEXT_CLIENT) { + my $text = nacro::gettext_client($vnc); + if (nacro::sendtext($vnc,$text)) { + writetiming(); + print OUT "nacro::sendtext(\$vnc, q(\Q$text\E));\n"; + print "got text from client: $text\n"; + } + } + if ($result & $nacro::RESULT_TEXT_SERVER) { + my $text = nacro::gettext_server($vnc); + if (nacro::sendtext_to_server($vnc,$text)) { + writetiming(); + print OUT "nacro::sendtext_to_server(\$vnc, q(\Q$text\E));\n"; + print "got text from server: $text\n"; + } + } + } else { + if($result&$nacro::RESULT_KEY) { + $keysym=nacro::getkeysym($vnc); + $keydown=nacro::getkeydown($vnc); + if($keysym==ord('q')) { + # shutdown + close OUT; + nacro::closevnc($vnc); + exit 0; + } elsif ($keysym == ord('d')) { + $pnm=$output.($image_counter - 1).".pnm"; + $res = nacro::displaypnm($vnc, $pnm, + $x_origin, $y_origin, 1, 10); + #0, 0, 1, 10); + if ($res == 0) { + nacro::alert($vnc, "Error displaying " + . $pnm, 10); + } + } elsif ($keysym == ord('i')) { + nacro::alert($vnc, "Current settings:\n" + . "\n" + . "Script: $output\n" + . "Server: $server\n" + . "Listening on port: $port\n" + . toggle_text("Timing") . "\n" + . toggle_text("Key presses") . "\n" + . toggle_text("Mouse moves") . "\n" + . toggle_text("Mouse drags"), 10); + } elsif ($keysym == ord('c')) { + $compact = !$compact; + nacro::alert($vnc, + toggle_text("Mouse moves"), 10); + } elsif ($keysym == ord('r')) { + $compact_dragging = !$compact_dragging; + nacro::alert($vnc, + toggle_text("Mouse drags"), 10); + } else { + nacro::alert($vnc,"Unknown key",10); + } + $mode="passthru"; + } + if($result&$nacro::RESULT_MOUSE) { + $x=nacro::getx($vnc); + $y=nacro::gety($vnc); + $buttons=nacro::getbuttons($vnc); + if(($buttons&1)==1) { + print STDERR "start draggin: $x $y\n"; + $start_x=$x; + $start_y=$y; + nacro::rubberband($vnc, $x, $y); + $x=nacro::getx($vnc); + $y=nacro::gety($vnc); + if($start_x==$x && $start_y==$y) { + # reset + print OUT "\$x_origin=0; \$y_origin=0;\n"; + } else { + if($start_x>$x) { + $dummy=$x; $x=$start_x; $start_x=$dummy; + } + if($start_y>$y) { + $dummy=$y; $y=$start_y; $start_y=$dummy; + } + $pnm=$output.$image_counter.".pnm"; + $image_counter++; + if(!nacro::savepnm($vnc,$pnm,$start_x,$start_y,$x,$y)) { + nacro::alert($vnc,"Saving $pnm failed!",10); + } else { + $x_origin=$start_x; + $y_origin=$start_y; + nacro::alert($vnc,"Got new origin: $x_origin $y_origin",10); + print OUT "if(nacro::visualgrep(\$vnc,\"$pnm\",999999)) {\n" + . "\t\$x_origin=nacro::getxorigin(\$vnc);\n" + . "\t\$y_origin=nacro::getyorigin(\$vnc);\n}\n"; + } + } + $mode="passthru"; + } + } + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 b/droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 new file mode 100755 index 0000000..c69a38d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/acinclude.m4 @@ -0,0 +1,7001 @@ +AH_TEMPLATE(socklen_t, [The type for socklen]) +AC_DEFUN([AC_TYPE_SOCKLEN_T], +[AC_CACHE_CHECK([for socklen_t], ac_cv_type_socklen_t, +[ + AC_TRY_COMPILE( + [#include + #include ], + [socklen_t len = 42; return 0;], + ac_cv_type_socklen_t=yes, + ac_cv_type_socklen_t=no) +]) + if test $ac_cv_type_socklen_t != yes; then + AC_DEFINE(socklen_t, int) + fi +]) + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_compile_check_sizeof.html +dnl +AC_DEFUN([AC_COMPILE_CHECK_SIZEOF], +[changequote(<<, >>)dnl +dnl The name to #define. +define(<>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl +dnl The cache variable name. +define(<>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $1) +AC_CACHE_VAL(AC_CV_NAME, +[for ac_size in 4 8 1 2 16 $2 ; do # List sizes in rough order of prevalence. + AC_TRY_COMPILE([#include "confdefs.h" +#include +$2 +], [switch (0) case 0: case (sizeof ($1) == $ac_size):;], AC_CV_NAME=$ac_size) + if test x$AC_CV_NAME != x ; then break; fi +done +]) +if test x$AC_CV_NAME = x ; then + AC_MSG_ERROR([cannot determine a size for $1]) +fi +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The number of bytes in type $1]) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/ac_create_stdint_h.html +dnl +AC_DEFUN([AC_CREATE_STDINT_H], +[# ------ AC CREATE STDINT H ------------------------------------- +AC_MSG_CHECKING([for stdint-types....]) +ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` +if test "$ac_stdint_h" = "stdint.h" ; then + AC_MSG_RESULT("(are you sure you want them in ./stdint.h?)") +elif test "$ac_stdint_h" = "inttypes.h" ; then + AC_MSG_RESULT("(are you sure you want them in ./inttypes.h?)") +else + AC_MSG_RESULT("(putting them into $ac_stdint_h)") +fi + +inttype_headers=`echo inttypes.h sys/inttypes.h sys/inttypes.h $2 \ +| sed -e 's/,/ /g'` + + ac_cv_header_stdint_x="no-file" + ac_cv_header_stdint_o="no-file" + ac_cv_header_stdint_u="no-file" + for i in stdint.h $inttype_headers ; do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint64_t + _AC_CHECK_TYPE_NEW(uintptr_t,[ac_cv_header_stdint_x=$i],dnl + continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="(uint64_t too)"],[and64=""],[#include<$i>]) + AC_MSG_RESULT(... seen our uintptr_t in $i $and64) + break; + done + if test "$ac_cv_header_stdint_x" = "no-file" ; then + for i in stdint.h $inttype_headers ; do + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],dnl + continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="(uint64_t too)"],[and64=""],[#include<$i>]) + AC_MSG_RESULT(... seen our uint32_t in $i $and64) + break; + done + if test "$ac_cv_header_stdint_o" = "no-file" ; then + for i in sys/types.h $inttype_headers ; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],dnl + continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="(u_int64_t too)"],[and64=""],[#include<$i>]) + AC_MSG_RESULT(... seen our u_int32_t in $i $and64) + break; + done + fi + fi + +# ----------------- DONE inttypes.h checks MAYBE C basic types -------- + +if test "$ac_cv_header_stdint_x" = "no-file" ; then + AC_COMPILE_CHECK_SIZEOF(char) + AC_COMPILE_CHECK_SIZEOF(short) + AC_COMPILE_CHECK_SIZEOF(int) + AC_COMPILE_CHECK_SIZEOF(long) + AC_COMPILE_CHECK_SIZEOF(void*) + ac_cv_header_stdint_test="yes" +else + ac_cv_header_stdint_test="no" +fi + +# ----------------- DONE inttypes.h checks START header ------------- +_ac_stdint_h=AS_TR_CPP(_$ac_stdint_h) +AC_MSG_RESULT(creating $ac_stdint_h : $_ac_stdint_h) +echo "#ifndef" $_ac_stdint_h >$ac_stdint_h +echo "#define" $_ac_stdint_h "1" >>$ac_stdint_h +echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint_h +echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint_h +if test "$GCC" = "yes" ; then + echo "/* generated using a gnu compiler version" `$CC --version` "*/" \ + >>$ac_stdint_h +else + echo "/* generated using $CC */" >>$ac_stdint_h +fi +echo "" >>$ac_stdint_h + +if test "$ac_cv_header_stdint_x" != "no-file" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_x" +elif test "$ac_cv_header_stdint_o" != "no-file" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_o" +elif test "$ac_cv_header_stdint_u" != "no-file" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_u" +else + ac_cv_header_stdint="stddef.h" +fi + +# ----------------- See if int_least and int_fast types are present +unset ac_cv_type_int_least32_t +unset ac_cv_type_int_fast32_t +AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) +AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) + +if test "$ac_cv_header_stdint" != "stddef.h" ; then +if test "$ac_cv_header_stdint" != "stdint.h" ; then +AC_MSG_RESULT(..adding include stddef.h) + echo "#include " >>$ac_stdint_h +fi ; fi +AC_MSG_RESULT(..adding include $ac_cv_header_stdint) + echo "#include <$ac_cv_header_stdint>" >>$ac_stdint_h +echo "" >>$ac_stdint_h + +# ----------------- DONE header START basic int types ------------- +if test "$ac_cv_header_stdint_x" = "no-file" ; then + AC_MSG_RESULT(... need to look at C basic types) +dnl ac_cv_header_stdint_test="yes" # moved up before creating the file +else + AC_MSG_RESULT(... seen good stdint.h inttypes) +dnl ac_cv_header_stdint_test="no" # moved up before creating the file +fi + +if test "$ac_cv_header_stdint_u" != "no-file" ; then + AC_MSG_RESULT(... seen bsd/sysv typedefs) + cat >>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h < 199901L + +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#elif !defined __STRICT_ANSI__ +#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ + +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#endif + +#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ +dnl /* note: all ELF-systems seem to have loff-support which needs 64-bit */ + +#if !defined _NO_LONGLONG +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif +#endif + +#elif defined __alpha || (defined __mips && defined _ABIN32) + +#if !defined _NO_LONGLONG +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef long int64_t; +typedef unsigned long uint64_t; +#endif +#endif + /* compiler/cpu type ... or just ISO C99 */ +#endif +#endif +EOF + +# plus a default 64-bit for systems that are likely to be 64-bit ready + case "$ac_cv_sizeof_x:$ac_cv_sizeof_voidp:$ac_cv_sizeof_long" in + 1:2:8:8) AC_MSG_RESULT(..adding uint64_t default, normal 64-bit system) +cat >>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <>$ac_stdint_h <@/_/g"` +_PKG=`echo ifelse($2, , $PACKAGE, $2)` +_LOW=`echo _$_PKG | sed -e "y:m4_cr_LETTERS-:m4_cr_letters[]_:"` +_UPP=`echo $_PKG | sed -e "y:m4_cr_letters-:m4_cr_LETTERS[]_:" -e "/^@<:@m4_cr_digits@:>@/s/^/_/"` +_INP=`echo ifelse($3, , _, $3)` +if test "$ac_prefix_conf_INP" = "_"; then + for ac_file in : $CONFIG_HEADERS; do test "_$ac_file" = _: && continue + test -f "$ac_prefix_conf_INP" && continue + case $ac_file in + *.h) test -f $ac_file && _INP=$ac_file ;; + *) + esac + done +fi +if test "$_INP" = "_"; then + case "$_OUT" in + */*) _INP=`basename "$_OUT"` + ;; + *-*) _INP=`echo "$_OUT" | sed -e "s/@<:@_symbol@:>@*-//"` + ;; + *) _INP=config.h + ;; + esac +fi +if test -z "$_PKG" ; then + AC_MSG_ERROR([no prefix for _PREFIX_PKG_CONFIG_H]) +else + if test ! -f "$_INP" ; then if test -f "$srcdir/$_INP" ; then + _INP="$srcdir/$_INP" + fi fi + AC_MSG_NOTICE(creating $_OUT - prefix $_UPP for $_INP defines) + if test -f $_INP ; then + echo "s/@%:@undef *\\(@<:@m4_cr_LETTERS[]_@:>@\\)/@%:@undef $_UPP""_\\1/" > _script + # no! these are things like socklen_t, const, vfork + # echo "s/@%:@undef *\\(@<:@m4_cr_letters@:>@\\)/@%:@undef $_LOW""_\\1/" >> _script + echo "s/@%:@def[]ine *\\(@<:@m4_cr_LETTERS[]_@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_UPP""_\\1 \\" >> _script + echo "@%:@def[]ine $_UPP""_\\1 \\2 \\" >> _script + echo "@%:@endif/" >>_script + # no! these are things like socklen_t, const, vfork + # echo "s/@%:@def[]ine *\\(@<:@m4_cr_letters@:>@@<:@_symbol@:>@*\\)\\(.*\\)/@%:@ifndef $_LOW""_\\1 \\" >> _script + # echo "@%:@define $_LOW""_\\1 \\2 \\" >> _script + # echo "@%:@endif/" >> _script + # now executing _script on _DEF input to create _OUT output file + echo "@%:@ifndef $_DEF" >$tmp/pconfig.h + echo "@%:@def[]ine $_DEF 1" >>$tmp/pconfig.h + echo ' ' >>$tmp/pconfig.h + echo /'*' $_OUT. Generated automatically at end of configure. '*'/ >>$tmp/pconfig.h + + sed -f _script $_INP >>$tmp/pconfig.h + echo ' ' >>$tmp/pconfig.h + echo '/* once:' $_DEF '*/' >>$tmp/pconfig.h + echo "@%:@endif" >>$tmp/pconfig.h + if cmp -s $_OUT $tmp/pconfig.h 2>/dev/null; then + AC_MSG_NOTICE([$_OUT is unchanged]) + else + ac_dir=`AS_DIRNAME(["$_OUT"])` + AS_MKDIR_P(["$ac_dir"]) + rm -f "$_OUT" + mv $tmp/pconfig.h "$_OUT" + fi + cp _script _configs.sed + else + AC_MSG_ERROR([input file $_INP does not exist - skip generating $_OUT]) + fi + rm -f conftest.* +fi +m4_popdef([_symbol])dnl +m4_popdef([_script])dnl +AS_VAR_POPDEF([_INP])dnl +AS_VAR_POPDEF([_UPP])dnl +AS_VAR_POPDEF([_LOW])dnl +AS_VAR_POPDEF([_PKG])dnl +AS_VAR_POPDEF([_DEF])dnl +AS_VAR_POPDEF([_OUT])dnl +],[PACKAGE="$PACKAGE"])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- +## Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005 +## Free Software Foundation, Inc. +## Originally by Gordon Matzigkeit , 1996 +## +## This file is free software; the Free Software Foundation gives +## unlimited permission to copy and/or distribute it, with or without +## modifications, as long as this notice is preserved. + +# serial 48 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +_LT_CC_BASENAME([$compiler]) + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_CC_BASENAME(CC) +# ------------------- +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +AC_DEFUN([_LT_CC_BASENAME], +[for cc_temp in $1""; do + case $cc_temp in + compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; + distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$echo "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +]) + + +# _LT_COMPILER_BOILERPLATE +# ------------------------ +# Check for compiler boilerplate output or warnings with +# the simple compiler test code. +AC_DEFUN([_LT_COMPILER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_COMPILER_BOILERPLATE + + +# _LT_LINKER_BOILERPLATE +# ---------------------- +# Check for linker boilerplate output or warnings with +# the simple link test code. +AC_DEFUN([_LT_LINKER_BOILERPLATE], +[ac_outfile=conftest.$ac_objext +printf "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$rm conftest* +])# _LT_LINKER_BOILERPLATE + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat </dev/null 2>&1 && unset CDPATH + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string=`eval $cmd`) 2>/dev/null && + echo_test_string=`eval $cmd` && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) LD="${LD-ld} -64" ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_REQUIRE([LT_AC_PROG_SED]) +AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + $echo "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + $2=yes + fi + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + while (test "X"`$SHELL [$]0 --fallback-echo "X$teststring" 2>/dev/null` \ + = "XX$teststring") >/dev/null 2>&1 && + new_result=`expr "X$teststring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + teststring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# ------------------ +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# --------------------------------------------------------------------- +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext < +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + else + puts (dlerror ()); + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_dlunknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ---------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $echo "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . 2>&AS_MESSAGE_LOG_FD + $rm conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files + $rm out/* && rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var, $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[[45]]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +kfreebsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[[123]]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[[01]]* | freebsdelf3.[[01]]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ + freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + freebsd*) # from 4.6 on + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +interix3*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +knetbsd*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='GNU ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + shlibpath_overrides_runpath=no + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + shlibpath_overrides_runpath=yes + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + if test -z "$LTCFLAGS"; then + eval "`$SHELL ${ofile} --config | grep '^LTCFLAGS='`" + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 DLLs +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +# set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the pathname to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix3*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx*) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the pathname to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# it is assumed to be `libltdl'. LIBLTDL will be prefixed with +# '${top_builddir}/' and LTDLINCL will be prefixed with '${top_srcdir}/' +# (note the single quotes!). If your package is not flat and you're not +# using automake, define top_builddir and top_srcdir appropriately in +# the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that +# AC_CONFIG_SUBDIRS is not called here. If DIRECTORY is not provided, +# and an installed libltdl is not found, it is assumed to be `libltdl'. +# LIBLTDL will be prefixed with '${top_builddir}/'# and LTDLINCL with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and top_srcdir +# appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX]) +])# _LT_AC_LANG_CXX + +# _LT_AC_PROG_CXXCPP +# ------------------ +AC_DEFUN([_LT_AC_PROG_CXXCPP], +[ +AC_REQUIRE([AC_PROG_CXX]) +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +fi +])# _LT_AC_PROG_CXXCPP + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# ------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_DLOPEN_SELF + +# Report which library types will actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case $host_os in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4* | aix5*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([_LT_AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# save warnings/boilerplate of simple test code +_LT_COMPILER_BOILERPLATE +_LT_LINKER_BOILERPLATE + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + $as_unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + $as_unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_CC_BASENAME([$compiler]) + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes ; then + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | $EGREP 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj ${wl}-single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[[12]]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "[[-]]L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + ;; + *) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc*) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC*) + # Portland Group C++ compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + openbsd2*) + # C++ shared libraries are fairly broken + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd='echo' + ;; + osf3*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(archive_cmds_need_lc,$1)=yes + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. We must also pass each convience library through + # to the system linker between allextract/defaultextract. + # The C++ compiler will combine linker options so we + # cannot just pass the convience library names through + # without $wl. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + output_verbose_link_cmd='echo' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + # So that behaviour is only enabled if SCOABSPATH is set to a + # non-empty value in the environment. Most likely only useful for + # creating official distributions of packages. + # This is a hack until libtool officially supports absolute path + # names for shared libraries. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext < conftest.$ac_ext <> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit , 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e 1s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# LTCC compiler flags. +LTCFLAGS=$lt_LTCFLAGS + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$lt_STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext_cmds='$shrext_cmds' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'` + if test -f "$ltmain_in"; then + test -f Makefile && make "$ltmain" + fi +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +linux*) + if test "$host_cpu" = ia64; then + symcode='[[ABCDGIRSTW]]' + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + fi + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris*) + symcode='[[BDRT]]' + ;; +sco3.2v5*) + symcode='[[DT]]' + ;; +sysv4.2uw2*) + symcode='[[DT]]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[[ABDT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext < $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat < conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | kfreebsd*-gnu | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC*) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc* | ecpc*) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgCC*) + # Portland Group C++ compiler. + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx*) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC*) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc*) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + esac + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + interix3*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + darwin*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + case $cc_basename in + xlc*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-qnocommon' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + ;; + esac + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $cc_basename in + icc* | ecc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + ccc*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + case $cc_basename in + f77* | f90* | f95*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; + *) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + unicos*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac + +# +# Check to make sure the static flag actually works. +# +wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_AC_TAGVAR(lt_prog_compiler_static, $1)\" +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $lt_tmp_static_flag, + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/;/^.* __nm__/s/^.* __nm__\([[^ ]]*\) [[^ ]]*/\1 DATA/;/^I /d;/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + # Just being paranoid about ensuring that cc_basename is set. + _LT_CC_BASENAME([$compiler]) + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + interix3*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + linux*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + tmp_addflag= + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + esac + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + $echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared'"$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname,\${SCOABSPATH:+${install_libdir}/}$soname,-retain-symbols-file,$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no; then + runpath_var= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[[012]]|aix4.[[012]].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds its shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi[[45]]*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + _LT_AC_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + case $host_os in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}suppress' + ;; + *) # Darwin 1.3 on + if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + else + case ${MACOSX_DEPLOYMENT_TARGET} in + 10.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' + ;; + 10.*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup' + ;; + esac + fi + ;; + esac + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + if test "$GCC" = yes ; then + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + case $cc_basename in + xlc*) + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}`echo $rpath/$soname` $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin lds + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -qmkshrobj $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-install_name ${wl}$rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + ;; + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | kfreebsd*-gnu | dragonfly*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + case $host_cpu in + hppa*64*|ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + wlarc='${wl}' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + wlarc='' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) + # The compiler driver will combine linker options so we + # cannot just pass the convience library names through + # without $wl, iff we do not link with $LD. + # Luckily, gcc supports the same syntax we need for Sun Studio. + # Supported since Solaris 2.6 (maybe 2.5.1?) + case $wlarc in + '') + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + *) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $echo \"$new_convenience\"` ${wl}-z ${wl}defaultextract' ;; + esac ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' + _LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,\${SCOABSPATH:+${install_libdir}/}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include +# #undef WIN32_LEAN_AND_MEAN +# #include +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +############################################################ +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +############################################################ +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && continue + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +]) +SED=$lt_cv_path_SED +AC_MSG_RESULT([$SED]) +]) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/autogen.sh b/droidvncgrab/vnc/libvncserver-kanaka/autogen.sh new file mode 100755 index 0000000..2e809c6 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/autogen.sh @@ -0,0 +1,57 @@ +#! /bin/sh +# Run this to generate all the initial makefiles, etc. + +set -e + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +AUTOMAKE=automake-1.4 +ACLOCAL=aclocal-1.4 + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + AUTOMAKE=automake + ACLOCAL=aclocal +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have autoconf installed to compile libvncserver." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +($AUTOMAKE --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "You must have automake installed to compile libvncserver." + echo "Get ftp://sourceware.cygnus.com/pub/automake/automake-1.4.tar.gz" + echo "(or a newer version if it is available)" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +(test -f $srcdir/rfb/rfb.h) || { + echo "You must run this script in the top-level libvncserver directory" + exit 1 +} + +if test -z "$*"; then + echo "I am going to run ./configure with no arguments - if you wish " + echo "to pass any to it, please specify them on the $0 command line." +fi + +$ACLOCAL $ACLOCAL_FLAGS +autoheader +$AUTOMAKE --add-missing --copy +autoconf + +echo "Running ./configure --enable-maintainer-mode" "$@" +$srcdir/configure --enable-maintainer-mode "$@" + +echo "Now type 'make' to compile libvncserver." diff --git a/droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl b/droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl new file mode 100755 index 0000000..fc43712 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/bdf2c.pl @@ -0,0 +1,60 @@ +#!/usr/bin/perl + +@encodings=(); +for($i=0;$i<256*5;$i++) { + $encodings[$i]="0"; +} + +$out=""; +$counter=0; +$fontname="default"; + +$i=0; +$searchfor=""; +$nullx="0x"; + +while(<>) { + if(/^FONT (.*)$/) { + $fontname=$1; + $fontname=~y/\"//d; + } elsif(/^ENCODING (.*)$/) { + $glyphindex=$1; + $searchfor="BBX"; + $dwidth=0; + } elsif(/^DWIDTH (.*) (.*)/) { + $dwidth=$1; + } elsif(/^BBX (.*) (.*) (.*) (.*)$/) { + ($width,$height,$x,$y)=($1,$2,$3,$4); + @encodings[$glyphindex*5..($glyphindex*5+4)]=($counter,$width,$height,$x,$y); + if($dwidth != 0) { + $encodings[$glyphindex*5+1]=$dwidth; + } else { + $dwidth=$width; + } + $searchfor="BITMAP"; + } elsif(/^BITMAP/) { + $i=1; + } elsif($i>0) { + if($i>$height) { + $i=0; + $out.=" /* $glyphindex */\n"; + } else { + if(int(($dwidth+7)/8) > int(($width+7)/8)) { + $_ .= "00"x(int(($dwidth+7)/8)-int(($width+7)/8)); + } + $_=substr($_,0,(int(($dwidth+7)/8)*2)); + $counter+=(int(($dwidth+7)/8)); + s/(..)/$nullx$1,/g; + $out.=$_; + $i++; + } + } +} + +print "unsigned char " . $fontname . "FontData[$counter]={\n" . $out; +print "};\nint " . $fontname . "FontMetaData[256*5]={\n"; +for($i=0;$i<256*5;$i++) { + print $encodings[$i] . ","; +} +print "};\nrfbFontData " . $fontname . "Font={" . + $fontname . "FontData, " . $fontname . "FontMetaData};\n"; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore new file mode 100755 index 0000000..22a4e72 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am new file mode 100755 index 0000000..c5497a8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/Makefile.am @@ -0,0 +1,5 @@ +EXTRA_DIST=VncViewer.jar index.vnc javaviewer.pseudo_proxy.patch + +SUBDIRS = ssl +DIST_SUBDIRS = ssl + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/VncViewer.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/VncViewer.jar new file mode 100755 index 0000000000000000000000000000000000000000..602fdb9dd384b1fcc1131e9a91631b440bba2425 GIT binary patch literal 35462 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 D--gW= literal 0 HcmV?d00001 diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc new file mode 100755 index 0000000..63b2f56 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/index.vnc @@ -0,0 +1,18 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + +
+www.TightVNC.com + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch new file mode 100755 index 0000000..4d2f36e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/javaviewer.pseudo_proxy.patch @@ -0,0 +1,141 @@ +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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am new file mode 100755 index 0000000..fd1c201 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/Makefile.am @@ -0,0 +1,2 @@ +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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README new file mode 100755 index 0000000..b244cf1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/README @@ -0,0 +1,338 @@ +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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedUltraViewerSSL.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedUltraViewerSSL.jar new file mode 100755 index 0000000000000000000000000000000000000000..7f1c312a8df7523614e32617a5725184f428f587 GIT binary patch literal 112662 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%0AyiOvVnSPb>365hrFc_fSL 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 literal 0 HcmV?d00001 diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedVncViewer.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/SignedVncViewer.jar new file mode 100755 index 0000000000000000000000000000000000000000..b5b0b7d67842f9676661511171ce66a34f688ac9 GIT binary patch literal 88734 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 literal 0 HcmV?d00001 diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/UltraViewerSSL.jar b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/UltraViewerSSL.jar new file mode 100755 index 0000000000000000000000000000000000000000..e90582a99cd39a21f2c05f7b3966841c8a3ea555 GIT binary patch literal 109588 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�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 ^= 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ΜoZ8+ZL>04G>jY3$8wtf!t@mM1sZp0Md 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 literal 0 HcmV?d00001 diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc new file mode 100755 index 0000000..ec520dc --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/index.vnc @@ -0,0 +1,26 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + +$PARAMS + +
+
x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey new file mode 100755 index 0000000..bf57c8f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/onetimekey @@ -0,0 +1,65 @@ +#!/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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer new file mode 100755 index 0000000..63ddac5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ss_vncviewer @@ -0,0 +1,3513 @@ +#!/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). +# +# 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" + 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 + +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 ':' > /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... + host "$host" >/dev/null 2>&1 + host "$host" >/dev/null 2>&1 + hout=`host "$host" 2>/dev/null` + 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 + if [ "X$ipv6" = "X0" ]; then + dout=`dig -t any "$host" 2>/dev/null` + 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 + proxy="ipv6://$host:$port" + echo "direct connect: set proxy=$proxy" + 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 = $$; + +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 (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 = $!; + + eval {$sock = IO::Socket::INET6->new( + PeerAddr => $proxy_host, + 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\n"; + xfer($sock, $listen_handle); + } else { + print STDERR "pproxy child [$$] socket -> STDOUT\n\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 $ok = 1; + for (my $i = 0; $i < 12; $i++) { + my $c; + sysread($sock, $c, 1); + print STDERR $c; + } + } 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 "" +} + +# 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 + 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 + echo "$ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 \"sleep 30\"" + echo "" + $ssh -f -x $ssh_port1 $targ -e none $ssh_NHAFL $ukhf -L $proxport:$ssh_host2:$ssh_port2 $ssh_host1 "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 [ "X$SS_VNCVIEWER_SSH_ONLY" != "X" ]; then + echo "$ssh -x $ssh_port $targ $C $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x $ssh_port $targ $C $ssh_args $ssh_host "$ssh_cmd" + exit $? + + elif [ "X$SS_VNCVIEWER_NO_F" != "X" ]; then + echo "$ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$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 $ssh_host "sudo id; tty" + echo "" + fi + echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$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 + rm -f $tport $tport2 + if [ "X$rsh" = "X1" ]; then + rsh_viewer "$@" + exit $? + fi + PPROXY_SOCKS=1 + if [ "X$SSVNC_SOCKS5" != "X" ]; then + PPROXY_SOCKS=5 + fi + export PPROXY_SOCKS + host="$localhost" + port="$PORT" + proxy="$localhost:$use" + + else + if [ "X$rsh" != "X1" ]; then + echo "$ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host \"$info\"" + echo "" + $ssh -x -f $ssh_port $targ $C $ssh_redir $ssh_args $ssh_host "$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 $ssh_host 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 + 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$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 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 + host $host >/dev/null 2>&1 + host $host >/dev/null 2>&1 + timeout=15 + if [ "X$SSVNC_FETCH_TIMEOUT" != "X" ]; then + timeout=$SSVNC_FETCH_TIMEOUT + fi + 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 + 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$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$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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch new file mode 100755 index 0000000..db611af --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch @@ -0,0 +1,57 @@ +--- vnc_javasrc.orig/VncCanvas.java 2004-10-10 02:15:54.000000000 -0400 ++++ vnc_javasrc/VncCanvas.java 2006-03-27 22:34:02.000000000 -0500 +@@ -28,6 +28,7 @@ + import java.lang.*; + import java.util.zip.*; + ++import java.util.Collections; + + // + // VncCanvas is a subclass of Canvas which draws a VNC desktop on it. +@@ -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)); +@@ -1387,9 +1402,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 +1418,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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch new file mode 100755 index 0000000..550cc17 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch @@ -0,0 +1,2429 @@ +diff -x VncCanvas.java -Naur vnc_javasrc.orig/Makefile vnc_javasrc/Makefile +--- vnc_javasrc.orig/Makefile 2004-03-04 08:34:25.000000000 -0500 ++++ vnc_javasrc/Makefile 2006-03-26 17:29:25.000000000 -0500 +@@ -15,25 +15,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) -target 1.4 -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 -x VncCanvas.java -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-03-27 17:58:37.000000000 -0400 +@@ -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'); +@@ -992,6 +1006,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 +1052,13 @@ + return; + } + ++ if(key == 0xffc2 && viewer.mapF5_to_atsign) { ++ if (viewer.debugKeyboard) { ++ System.out.println("Mapping: F5 -> AT "); ++ } ++ key = 0x40; ++ } ++ + } else { + + // +@@ -1036,6 +1070,7 @@ + + key = keyChar; + ++ + if (key < 0x20) { + if (evt.isControlDown()) { + key += 0x60; +@@ -1121,6 +1156,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 -x VncCanvas.java -Naur vnc_javasrc.orig/SSLSocketToMe.java vnc_javasrc/SSLSocketToMe.java +--- vnc_javasrc.orig/SSLSocketToMe.java 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_javasrc/SSLSocketToMe.java 2010-03-21 12:53:24.000000000 -0400 +@@ -0,0 +1,2055 @@ ++/* ++ * 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") < 0 && v2.indexOf("proxy") < 0) { ++ continue; ++ } ++ if (v2.indexOf("http") < 0) { ++ continue; ++ } ++ ++ 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; ++ } ++ ++ 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/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc new file mode 100755 index 0000000..3c57445 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultra.vnc @@ -0,0 +1,28 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc new file mode 100755 index 0000000..fd842c4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultraproxy.vnc @@ -0,0 +1,28 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc new file mode 100755 index 0000000..a711655 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultrasigned.vnc @@ -0,0 +1,28 @@ + + + + +$USER's $DESKTOP desktop ($DISPLAY) + + + + + + +$PARAMS + +
+x11vnc site + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch new file mode 100755 index 0000000..4dbffaf --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/classes/ssl/ultravnc-102-JavaViewer-ssl-etc.patch @@ -0,0 +1,5365 @@ +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/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-03-27 17:59:56.000000000 -0400 +@@ -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); + // } +@@ -1610,6 +1971,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 +2061,9 @@ + default : + return; + } ++ if (key == 0xffc2 && viewer.mapF5_to_atsign) { ++ key = 0x40; ++ } + + } else { + +@@ -1794,6 +2173,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-03-21 12:53:24.000000000 -0400 +@@ -0,0 +1,2055 @@ ++/* ++ * 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") < 0 && v2.indexOf("proxy") < 0) { ++ continue; ++ } ++ if (v2.indexOf("http") < 0) { ++ continue; ++ } ++ ++ 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; ++ } ++ ++ 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 +259,9 @@ + } + else + { ++// begin runge/x11vnc ++ viewer.options.oldEightBitColors = viewer.options.eightBitColors; ++// end runge/x11vnc + rfb.writeSetPixelFormat( + 32, + 24, +@@ -376,12 +401,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 +417,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) { +@@ -1532,9 +1562,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 +1600,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) { diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore new file mode 100755 index 0000000..d5dc0d6 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/.cvsignore @@ -0,0 +1,9 @@ +.deps +Makefile +Makefile.in +SDLvncviewer +ppmtest +vnc2mpg +*.avi +*.mpg + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am new file mode 100755 index 0000000..c26c1c9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/Makefile.am @@ -0,0 +1,33 @@ +INCLUDES = -I$(top_srcdir) +LDADD = ../libvncclient/libvncclient.la @WSOCKLIB@ + +if WITH_FFMPEG +FFMPEG_HOME=@with_ffmpeg@ + +if HAVE_MP3LAME +MP3LAME_LIB=-lmp3lame +endif + +vnc2mpg_CFLAGS=-I$(FFMPEG_HOME)/libavformat -I$(FFMPEG_HOME)/libavcodec -I$(FFMPEG_HOME)/libavutil +vnc2mpg_LDADD=$(LDADD) $(FFMPEG_HOME)/libavformat/libavformat.a $(FFMPEG_HOME)/libavcodec/libavcodec.a $(MP3LAME_LIB) -lm + +FFMPEG_CLIENT=vnc2mpg +endif + +if HAVE_LIBSDL +SDLVIEWER=SDLvncviewer + +SDLvncviewer_CFLAGS=$(SDL_CFLAGS) + +if HAVE_X11 +X11_LIB=-lX11 +endif + +# thanks to autoconf, this looks ugly +SDLvncviewer_LDADD=$(LDADD) $(SDL_LIBS) $(X11_LIB) +endif + +noinst_PROGRAMS=ppmtest $(SDLVIEWER) $(FFMPEG_CLIENT) backchannel + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c new file mode 100755 index 0000000..5d23ec7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/SDLvncviewer.c @@ -0,0 +1,553 @@ +#include +#include +#include +#include "scrap.c" + +struct { int sdl; int rfb; } buttonMapping[]={ + {1, rfbButton1Mask}, + {2, rfbButton2Mask}, + {3, rfbButton3Mask}, + {4, rfbButton4Mask}, + {5, rfbButton5Mask}, + {0,0} +}; + +static int enableResizable, viewOnly, listenLoop, buttonMask; +#ifdef SDL_ASYNCBLIT + int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL; +#else + int sdlFlags = SDL_HWSURFACE | SDL_HWACCEL; +#endif +static int realWidth, realHeight, bytesPerPixel, rowStride; +static char *sdlPixels; + +static int rightAltKeyDown, leftAltKeyDown; + +static rfbBool resize(rfbClient* client) { + int width=client->width,height=client->height, + depth=client->format.bitsPerPixel; + + if (enableResizable) + sdlFlags |= SDL_RESIZABLE; + + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = width; client->updateRect.h = height; + rfbBool okay=SDL_VideoModeOK(width,height,depth,sdlFlags); + if(!okay) + for(depth=24;!okay && depth>4;depth/=2) + okay=SDL_VideoModeOK(width,height,depth,sdlFlags); + if(okay) { + SDL_Surface* sdl=SDL_SetVideoMode(width,height,depth,sdlFlags); + rfbClientSetClientData(client, SDL_Init, sdl); + client->width = sdl->pitch / (depth / 8); + if (sdlPixels) { + free(client->frameBuffer); + sdlPixels = NULL; + } + client->frameBuffer=sdl->pixels; + + client->format.bitsPerPixel=depth; + client->format.redShift=sdl->format->Rshift; + client->format.greenShift=sdl->format->Gshift; + client->format.blueShift=sdl->format->Bshift; + client->format.redMax=sdl->format->Rmask>>client->format.redShift; + client->format.greenMax=sdl->format->Gmask>>client->format.greenShift; + client->format.blueMax=sdl->format->Bmask>>client->format.blueShift; + SetFormatAndEncodings(client); + + } else { + SDL_Surface* sdl=rfbClientGetClientData(client, SDL_Init); + rfbClientLog("Could not set resolution %dx%d!\n", + client->width,client->height); + if(sdl) { + client->width=sdl->pitch / (depth / 8); + client->height=sdl->h; + } else { + client->width=0; + client->height=0; + } + return FALSE; + } + SDL_WM_SetCaption(client->desktopName, "SDL"); + return TRUE; +} + +static rfbKeySym SDL_key2rfbKeySym(SDL_KeyboardEvent* e) { + rfbKeySym k = 0; + switch(e->keysym.sym) { + case SDLK_BACKSPACE: k = XK_BackSpace; break; + case SDLK_TAB: k = XK_Tab; break; + case SDLK_CLEAR: k = XK_Clear; break; + case SDLK_RETURN: k = XK_Return; break; + case SDLK_PAUSE: k = XK_Pause; break; + case SDLK_ESCAPE: k = XK_Escape; break; + case SDLK_SPACE: k = XK_space; break; + case SDLK_DELETE: k = XK_Delete; break; + case SDLK_KP0: k = XK_KP_0; break; + case SDLK_KP1: k = XK_KP_1; break; + case SDLK_KP2: k = XK_KP_2; break; + case SDLK_KP3: k = XK_KP_3; break; + case SDLK_KP4: k = XK_KP_4; break; + case SDLK_KP5: k = XK_KP_5; break; + case SDLK_KP6: k = XK_KP_6; break; + case SDLK_KP7: k = XK_KP_7; break; + case SDLK_KP8: k = XK_KP_8; break; + case SDLK_KP9: k = XK_KP_9; break; + case SDLK_KP_PERIOD: k = XK_KP_Decimal; break; + case SDLK_KP_DIVIDE: k = XK_KP_Divide; break; + case SDLK_KP_MULTIPLY: k = XK_KP_Multiply; break; + case SDLK_KP_MINUS: k = XK_KP_Subtract; break; + case SDLK_KP_PLUS: k = XK_KP_Add; break; + case SDLK_KP_ENTER: k = XK_KP_Enter; break; + case SDLK_KP_EQUALS: k = XK_KP_Equal; break; + case SDLK_UP: k = XK_Up; break; + case SDLK_DOWN: k = XK_Down; break; + case SDLK_RIGHT: k = XK_Right; break; + case SDLK_LEFT: k = XK_Left; break; + case SDLK_INSERT: k = XK_Insert; break; + case SDLK_HOME: k = XK_Home; break; + case SDLK_END: k = XK_End; break; + case SDLK_PAGEUP: k = XK_Page_Up; break; + case SDLK_PAGEDOWN: k = XK_Page_Down; break; + case SDLK_F1: k = XK_F1; break; + case SDLK_F2: k = XK_F2; break; + case SDLK_F3: k = XK_F3; break; + case SDLK_F4: k = XK_F4; break; + case SDLK_F5: k = XK_F5; break; + case SDLK_F6: k = XK_F6; break; + case SDLK_F7: k = XK_F7; break; + case SDLK_F8: k = XK_F8; break; + case SDLK_F9: k = XK_F9; break; + case SDLK_F10: k = XK_F10; break; + case SDLK_F11: k = XK_F11; break; + case SDLK_F12: k = XK_F12; break; + case SDLK_F13: k = XK_F13; break; + case SDLK_F14: k = XK_F14; break; + case SDLK_F15: k = XK_F15; break; + case SDLK_NUMLOCK: k = XK_Num_Lock; break; + case SDLK_CAPSLOCK: k = XK_Caps_Lock; break; + case SDLK_SCROLLOCK: k = XK_Scroll_Lock; break; + case SDLK_RSHIFT: k = XK_Shift_R; break; + case SDLK_LSHIFT: k = XK_Shift_L; break; + case SDLK_RCTRL: k = XK_Control_R; break; + case SDLK_LCTRL: k = XK_Control_L; break; + case SDLK_RALT: k = XK_Alt_R; break; + case SDLK_LALT: k = XK_Alt_L; break; + case SDLK_RMETA: k = XK_Meta_R; break; + case SDLK_LMETA: k = XK_Meta_L; break; +#if 0 + /* TODO: find out keysyms */ + case SDLK_LSUPER: k = XK_LSuper; break; /* left "windows" key */ + case SDLK_RSUPER: k = XK_RSuper; break; /* right "windows" key */ + case SDLK_COMPOSE: k = XK_Compose; break; +#endif + case SDLK_MODE: k = XK_Mode_switch; break; + case SDLK_HELP: k = XK_Help; break; + case SDLK_PRINT: k = XK_Print; break; + case SDLK_SYSREQ: k = XK_Sys_Req; break; + case SDLK_BREAK: k = XK_Break; break; + default: break; + } + if (k == 0 && e->keysym.sym >= SDLK_a && e->keysym.sym <= SDLK_z) { + k = XK_a + e->keysym.sym - SDLK_a; + if (e->keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) + k &= ~0x20; + } + if (k == 0) { + if (e->keysym.unicode < 0x100) + k = e->keysym.unicode; + else + rfbClientLog("Unknown keysym: %d\n",e->keysym.sym); + } + + return k; +} + +static uint32_t get(rfbClient *cl, int x, int y) +{ + switch (bytesPerPixel) { + case 1: return ((uint8_t *)cl->frameBuffer)[x + y * cl->width]; + case 2: return ((uint16_t *)cl->frameBuffer)[x + y * cl->width]; + case 4: return ((uint32_t *)cl->frameBuffer)[x + y * cl->width]; + default: + rfbClientErr("Unknown bytes/pixel: %d", bytesPerPixel); + exit(1); + } +} + +static void put(int x, int y, uint32_t v) +{ + switch (bytesPerPixel) { + case 1: ((uint8_t *)sdlPixels)[x + y * rowStride] = v; break; + case 2: ((uint16_t *)sdlPixels)[x + y * rowStride] = v; break; + case 4: ((uint32_t *)sdlPixels)[x + y * rowStride] = v; break; + default: + rfbClientErr("Unknown bytes/pixel: %d", bytesPerPixel); + exit(1); + } +} + +static void resizeRectangleToReal(rfbClient *cl, int x, int y, int w, int h) +{ + int i0 = x * realWidth / cl->width; + int i1 = ((x + w) * realWidth - 1) / cl->width + 1; + int j0 = y * realHeight / cl->height; + int j1 = ((y + h) * realHeight - 1) / cl->height + 1; + int i, j; + + for (j = j0; j < j1; j++) + for (i = i0; i < i1; i++) { + int x0 = i * cl->width / realWidth; + int x1 = ((i + 1) * cl->width - 1) / realWidth + 1; + int y0 = j * cl->height / realHeight; + int y1 = ((j + 1) * cl->height - 1) / realHeight + 1; + uint32_t r = 0, g = 0, b = 0; + + for (y = y0; y < y1; y++) + for (x = x0; x < x1; x++) { + uint32_t v = get(cl, x, y); +#define REDSHIFT cl->format.redShift +#define REDMAX cl->format.redMax +#define GREENSHIFT cl->format.greenShift +#define GREENMAX cl->format.greenMax +#define BLUESHIFT cl->format.blueShift +#define BLUEMAX cl->format.blueMax + r += (v >> REDSHIFT) & REDMAX; + g += (v >> GREENSHIFT) & GREENMAX; + b += (v >> BLUESHIFT) & BLUEMAX; + } + r /= (x1 - x0) * (y1 - y0); + g /= (x1 - x0) * (y1 - y0); + b /= (x1 - x0) * (y1 - y0); + + put(i, j, (r << REDSHIFT) | (g << GREENSHIFT) | + (b << BLUESHIFT)); + } +} + +static void update(rfbClient* cl,int x,int y,int w,int h) { + if (sdlPixels) { + resizeRectangleToReal(cl, x, y, w, h); + w = ((x + w) * realWidth - 1) / cl->width + 1; + h = ((y + h) * realHeight - 1) / cl->height + 1; + x = x * realWidth / cl->width; + y = y * realHeight / cl->height; + w -= x; + h -= y; + } + SDL_UpdateRect(rfbClientGetClientData(cl, SDL_Init), x, y, w, h); +} + +static void setRealDimension(rfbClient *client, int w, int h) +{ + SDL_Surface* sdl; + + if (w < 0) { + const SDL_VideoInfo *info = SDL_GetVideoInfo(); + w = info->current_h; + h = info->current_w; + } + + if (w == realWidth && h == realHeight) + return; + + if (!sdlPixels) { + int size; + + sdlPixels = (char *)client->frameBuffer; + rowStride = client->width; + + bytesPerPixel = client->format.bitsPerPixel / 8; + size = client->width * bytesPerPixel * client->height; + client->frameBuffer = malloc(size); + if (!client->frameBuffer) { + rfbClientErr("Could not allocate %d bytes", size); + exit(1); + } + memcpy(client->frameBuffer, sdlPixels, size); + } + + sdl = rfbClientGetClientData(client, SDL_Init); + if (sdl->w != w || sdl->h != h) { + int depth = sdl->format->BitsPerPixel; + sdl = SDL_SetVideoMode(w, h, depth, sdlFlags); + rfbClientSetClientData(client, SDL_Init, sdl); + sdlPixels = sdl->pixels; + rowStride = sdl->pitch / (depth / 8); + } + + realWidth = w; + realHeight = h; + update(client, 0, 0, client->width, client->height); +} + +static void kbd_leds(rfbClient* cl, int value, int pad) { + /* note: pad is for future expansion 0=unused */ + fprintf(stderr,"Led State= 0x%02X\n", value); + fflush(stderr); +} + +/* trivial support for textchat */ +static void text_chat(rfbClient* cl, int value, char *text) { + switch(value) { + case rfbTextChatOpen: + fprintf(stderr,"TextChat: We should open a textchat window!\n"); + TextChatOpen(cl); + break; + case rfbTextChatClose: + fprintf(stderr,"TextChat: We should close our window!\n"); + break; + case rfbTextChatFinished: + fprintf(stderr,"TextChat: We should close our window!\n"); + break; + default: + fprintf(stderr,"TextChat: Received \"%s\"\n", text); + break; + } + fflush(stderr); +} + +#ifdef __MINGW32__ +#define LOG_TO_FILE +#endif + +#ifdef LOG_TO_FILE +#include +static void +log_to_file(const char *format, ...) +{ + FILE* logfile; + static char* logfile_str=0; + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + if(logfile_str==0) { + logfile_str=getenv("VNCLOG"); + if(logfile_str==0) + logfile_str="vnc.log"; + } + + logfile=fopen(logfile_str,"a"); + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(logfile,buf); + + vfprintf(logfile, format, args); + fflush(logfile); + + va_end(args); + fclose(logfile); +} +#endif + + +static void cleanup(rfbClient* cl) +{ + /* + just in case we're running in listenLoop: + close viewer window by restarting SDL video subsystem + */ + SDL_QuitSubSystem(SDL_INIT_VIDEO); + SDL_InitSubSystem(SDL_INIT_VIDEO); + if(cl) + rfbClientCleanup(cl); +} + + +static rfbBool handleSDLEvent(rfbClient *cl, SDL_Event *e) +{ + switch(e->type) { +#if SDL_MAJOR_VERSION > 1 || SDL_MINOR_VERSION >= 2 + case SDL_VIDEOEXPOSE: + SendFramebufferUpdateRequest(cl, 0, 0, + cl->width, cl->height, FALSE); + break; +#endif + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEMOTION: + { + int x, y, state, i; + if (viewOnly) + break; + + if (e->type == SDL_MOUSEMOTION) { + x = e->motion.x; + y = e->motion.y; + state = e->motion.state; + } + else { + x = e->button.x; + y = e->button.y; + state = e->button.button; + for (i = 0; buttonMapping[i].sdl; i++) + if (state == buttonMapping[i].sdl) { + state = buttonMapping[i].rfb; + if (e->type == SDL_MOUSEBUTTONDOWN) + buttonMask |= state; + else + buttonMask &= ~state; + break; + } + } + if (sdlPixels) { + x = x * cl->width / realWidth; + y = y * cl->height / realHeight; + } + SendPointerEvent(cl, x, y, buttonMask); + buttonMask &= ~(rfbButton4Mask | rfbButton5Mask); + break; + } + case SDL_KEYUP: + case SDL_KEYDOWN: + if (viewOnly) + break; + SendKeyEvent(cl, SDL_key2rfbKeySym(&e->key), + e->type == SDL_KEYDOWN ? TRUE : FALSE); + if (e->key.keysym.sym == SDLK_RALT) + rightAltKeyDown = e->type == SDL_KEYDOWN; + if (e->key.keysym.sym == SDLK_LALT) + leftAltKeyDown = e->type == SDL_KEYDOWN; + break; + case SDL_QUIT: + if(listenLoop) + { + cleanup(cl); + return FALSE; + } + else + { + rfbClientCleanup(cl); + exit(0); + } + case SDL_ACTIVEEVENT: + if (!e->active.gain && rightAltKeyDown) { + SendKeyEvent(cl, XK_Alt_R, FALSE); + rightAltKeyDown = FALSE; + rfbClientLog("released right Alt key\n"); + } + if (!e->active.gain && leftAltKeyDown) { + SendKeyEvent(cl, XK_Alt_L, FALSE); + leftAltKeyDown = FALSE; + rfbClientLog("released left Alt key\n"); + } + + if (e->active.gain && lost_scrap()) { + static char *data = NULL; + static int len = 0; + get_scrap(T('T', 'E', 'X', 'T'), &len, &data); + if (len) + SendClientCutText(cl, data, len); + } + break; + case SDL_SYSWMEVENT: + clipboard_filter(e); + break; + case SDL_VIDEORESIZE: + setRealDimension(cl, e->resize.w, e->resize.h); + break; + default: + rfbClientLog("ignore SDL event: 0x%x\n", e->type); + } + return TRUE; +} + +static void got_selection(rfbClient *cl, const char *text, int len) +{ + put_scrap(T('T', 'E', 'X', 'T'), len, text); +} + + +#ifdef mac +#define main SDLmain +#endif + +int main(int argc,char** argv) { + rfbClient* cl; + int i, j; + SDL_Event e; + +#ifdef LOG_TO_FILE + rfbClientLog=rfbClientErr=log_to_file; +#endif + + for (i = 1, j = 1; i < argc; i++) + if (!strcmp(argv[i], "-viewonly")) + viewOnly = 1; + else if (!strcmp(argv[i], "-resizable")) + enableResizable = 1; + else if (!strcmp(argv[i], "-listen")) { + listenLoop = 1; + argv[i] = "-listennofork"; + ++j; + } + else { + if (i != j) + argv[j] = argv[i]; + j++; + } + argc = j; + + SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE); + SDL_EnableUNICODE(1); + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, + SDL_DEFAULT_REPEAT_INTERVAL); + atexit(SDL_Quit); + signal(SIGINT, exit); + + do { + /* 16-bit: cl=rfbGetClient(5,3,2); */ + cl=rfbGetClient(8,3,4); + cl->MallocFrameBuffer=resize; + cl->canHandleNewFBSize = TRUE; + cl->GotFrameBufferUpdate=update; + cl->HandleKeyboardLedState=kbd_leds; + cl->HandleTextChat=text_chat; + cl->GotXCutText = got_selection; + cl->listenPort = LISTEN_PORT_OFFSET; + if(!rfbInitClient(cl,&argc,argv)) + { + cl = NULL; /* rfbInitClient has already freed the client struct */ + cleanup(cl); + break; + } + + init_scrap(); + + while(1) { + if(SDL_PollEvent(&e)) { + /* + handleSDLEvent() return 0 if user requested window close. + In this case, handleSDLEvent() will have called cleanup(). + */ + if(!handleSDLEvent(cl, &e)) + break; + } + else { + i=WaitForMessage(cl,500); + if(i<0) + { + cleanup(cl); + break; + } + if(i) + if(!HandleRFBServerMessage(cl)) + { + cleanup(cl); + break; + } + } + } + } + while(listenLoop); + + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c new file mode 100755 index 0000000..643754e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/backchannel.c @@ -0,0 +1,99 @@ +/* A simple example of an RFB client */ + +#include +#include +#include +#include +#include + +static void HandleRect(rfbClient* client, int x, int y, int w, int h) { +} + +/* + * The client part of the back channel extension example. + * + */ + +#define rfbBackChannel 155 + +typedef struct backChannelMsg { + uint8_t type; + uint8_t pad1; + uint16_t pad2; + uint32_t size; +} backChannelMsg; + +static void sendMessage(rfbClient* client, char* text) +{ + backChannelMsg msg; + uint32_t length = strlen(text)+1; + + msg.type = rfbBackChannel; + msg.size = rfbClientSwap32IfLE(length); + if(!WriteToRFBServer(client, (char*)&msg, sizeof(msg)) || + !WriteToRFBServer(client, text, length)) { + rfbClientLog("enableBackChannel: write error (%d: %s)", errno, strerror(errno)); + } +} + +static rfbBool handleBackChannelMessage(rfbClient* client, + rfbServerToClientMsg* message) +{ + backChannelMsg msg; + char* text; + + if(message->type != rfbBackChannel) + return FALSE; + + rfbClientSetClientData(client, sendMessage, sendMessage); + + if(!ReadFromRFBServer(client, ((char*)&msg)+1, sizeof(msg)-1)) + return TRUE; + msg.size = rfbClientSwap32IfLE(msg.size); + text = malloc(msg.size); + if(!ReadFromRFBServer(client, text, msg.size)) { + free(text); + return TRUE; + } + + rfbClientLog("got back channel message: %s\n", text); + free(text); + + return TRUE; +} + +static int backChannelEncodings[] = { rfbBackChannel, 0 }; + +static rfbClientProtocolExtension backChannel = { + backChannelEncodings, /* encodings */ + NULL, /* handleEncoding */ + handleBackChannelMessage, /* handleMessage */ + NULL /* next extension */ +}; + +int +main(int argc, char **argv) +{ + rfbClient* client = rfbGetClient(8,3,4); + + client->GotFrameBufferUpdate = HandleRect; + rfbClientRegisterExtension(&backChannel); + + if (!rfbInitClient(client,&argc,argv)) + return 1; + + while (1) { + /* After each idle second, send a message */ + if(WaitForMessage(client,1000000)>0) + HandleRFBServerMessage(client); + else if(rfbClientGetClientData(client, sendMessage)) + sendMessage(client, "Dear Server,\n" + "thank you for understanding " + "back channel messages!"); + } + + rfbClientCleanup(client); + + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c new file mode 100755 index 0000000..0422937 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/ppmtest.c @@ -0,0 +1,97 @@ +/* A simple example of an RFB client */ + +#include +#include +#include +#include +#include + +static void PrintRect(rfbClient* client, int x, int y, int w, int h) { + rfbClientLog("Received an update for %d,%d,%d,%d.\n",x,y,w,h); +} + +static void SaveFramebufferAsPPM(rfbClient* client, int x, int y, int w, int h) { + static time_t t=0,t1; + FILE* f; + int i,j; + rfbPixelFormat* pf=&client->format; + int bpp=pf->bitsPerPixel/8; + int row_stride=client->width*bpp; + + /* save one picture only if the last is older than 2 seconds */ + t1=time(NULL); + if(t1-t>2) + t=t1; + else + return; + + /* assert bpp=4 */ + if(bpp!=4 && bpp!=2) { + rfbClientLog("bpp = %d (!=4)\n",bpp); + return; + } + + f=fopen("framebuffer.ppm","wb"); + if(!f) { + rfbClientErr("Could not open framebuffer.ppm\n"); + return; + } + + fprintf(f,"P6\n# %s\n%d %d\n255\n",client->desktopName,client->width,client->height); + for(j=0;jheight*row_stride;j+=row_stride) + for(i=0;iwidth*bpp;i+=bpp) { + unsigned char* p=client->frameBuffer+j+i; + unsigned int v; + if(bpp==4) + v=*(unsigned int*)p; + else if(bpp==2) + v=*(unsigned short*)p; + else + v=*(unsigned char*)p; + fputc((v>>pf->redShift)*256/(pf->redMax+1),f); + fputc((v>>pf->greenShift)*256/(pf->greenMax+1),f); + fputc((v>>pf->blueShift)*256/(pf->blueMax+1),f); + } + fclose(f); +} + +int +main(int argc, char **argv) +{ + rfbClient* client = rfbGetClient(8,3,4); + time_t t=time(NULL); + + if(argc>1 && !strcmp("-print",argv[1])) { + client->GotFrameBufferUpdate = PrintRect; + argv[1]=argv[0]; argv++; argc--; + } else + client->GotFrameBufferUpdate = SaveFramebufferAsPPM; + + /* The -listen option is used to make us a daemon process which listens for + incoming connections from servers, rather than actively connecting to a + given server. The -tunnel and -via options are useful to create + connections tunneled via SSH port forwarding. We must test for the + -listen option before invoking any Xt functions - this is because we use + forking, and Xt doesn't seem to cope with forking very well. For -listen + option, when a successful incoming connection has been accepted, + listenForIncomingConnections() returns, setting the listenSpecified + flag. */ + + if (!rfbInitClient(client,&argc,argv)) + return 1; + + /* TODO: better wait for update completion */ + while (time(NULL)-t<5) { + static int i=0; + fprintf(stderr,"\r%d",i++); + if(WaitForMessage(client,50)<0) + break; + if(!HandleRFBServerMessage(client)) + break; + } + + rfbClientCleanup(client); + + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c new file mode 100755 index 0000000..c28800c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.c @@ -0,0 +1,558 @@ +/* Handle clipboard text and data in arbitrary formats */ + +#include +#include + +#ifdef WIN32 +#include +#include +#else +#include +#include +#endif +#include "scrap.h" +#include "rfb/rfbconfig.h" + +/* Determine what type of clipboard we are using */ +#if defined(__unix__) && !defined(__QNXNTO__) && defined(LIBVNCSERVER_HAVE_X11) +#define X11_SCRAP +#elif defined(__WIN32__) +#define WIN_SCRAP +#elif defined(__QNXNTO__) +#define QNX_SCRAP +#else +#warning Unknown window manager for clipboard handling +#endif /* scrap type */ + +/* System dependent data types */ +#if defined(X11_SCRAP) +typedef Atom scrap_type; +static Atom XA_TARGETS, XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING; +#elif defined(WIN_SCRAP) +typedef UINT scrap_type; +#elif defined(QNX_SCRAP) +typedef uint32_t scrap_type; +#define Ph_CL_TEXT T('T', 'E', 'X', 'T') +#else +typedef int scrap_type; +#endif /* scrap type */ + +/* System dependent variables */ +#if defined(X11_SCRAP) +static Display *SDL_Display; +static Window SDL_Window; +static void (*Lock_Display)(void); +static void (*Unlock_Display)(void); +static Atom XA_UTF8_STRING; +#elif defined(WIN_SCRAP) +static HWND SDL_Window; +#elif defined(QNX_SCRAP) +static unsigned short InputGroup; +#endif /* scrap type */ + +#define FORMAT_PREFIX "SDL_scrap_0x" + +static scrap_type convert_format(int type) +{ + switch (type) { + case T('T', 'E', 'X', 'T'): +#if defined(X11_SCRAP) + return XA_UTF8_STRING ? XA_UTF8_STRING : XA_STRING; +#elif defined(WIN_SCRAP) + return CF_TEXT; +#elif defined(QNX_SCRAP) + return Ph_CL_TEXT; +#endif /* scrap type */ + default: + { + char format[sizeof(FORMAT_PREFIX)+8+1]; + + sprintf(format, "%s%08lx", FORMAT_PREFIX, + (unsigned long)type); +#if defined(X11_SCRAP) + return XInternAtom(SDL_Display, format, False); +#elif defined(WIN_SCRAP) + return RegisterClipboardFormat(format); +#endif /* scrap type */ + } + } +} + +/* Convert internal data to scrap format */ +static int convert_data(int type, char *dst, const char *src, int srclen) +{ + int dstlen; + + dstlen = 0; + switch (type) { + case T('T', 'E', 'X', 'T'): + if (dst) { + while (--srclen >= 0) { +#if defined(__unix__) + if (*src == '\r') { + *dst++ = '\n'; + ++dstlen; + } + else +#elif defined(__WIN32__) + if (*src == '\r') { + *dst++ = '\r'; + ++dstlen; + *dst++ = '\n'; + ++dstlen; + } + else +#endif + { + *dst++ = *src; + ++dstlen; + } + ++src; + } + *dst = '\0'; + ++dstlen; + } + else { + while (--srclen >= 0) { +#if defined(__unix__) + if (*src == '\r') + ++dstlen; + else +#elif defined(__WIN32__) + if (*src == '\r') { + ++dstlen; + ++dstlen; + } + else +#endif + { + ++dstlen; + } + ++src; + } + ++dstlen; + } + break; + default: + if (dst) { + *(int *)dst = srclen; + dst += sizeof(int); + memcpy(dst, src, srclen); + } + dstlen = sizeof(int)+srclen; + break; + } + return(dstlen); +} + +/* Convert scrap data to internal format */ +static int convert_scrap(int type, char *dst, char *src, int srclen) +{ + int dstlen; + + dstlen = 0; + switch (type) { + case T('T', 'E', 'X', 'T'): + { + if (srclen == 0) + srclen = strlen(src); + if (dst) { + while (--srclen >= 0) { +#if defined(__WIN32__) + if (*src == '\r') + /* drop extraneous '\r' */; + else +#endif + if (*src == '\n') { + *dst++ = '\r'; + ++dstlen; + } + else { + *dst++ = *src; + ++dstlen; + } + ++src; + } + *dst = '\0'; + ++dstlen; + } + else { + while (--srclen >= 0) { +#if defined(__WIN32__) + /* drop extraneous '\r' */; + if (*src != '\r') +#endif + ++dstlen; + ++src; + } + ++dstlen; + } + break; + } + default: + dstlen = *(int *)src; + if (dst) + memcpy(dst, src + sizeof(int), + srclen ? srclen - sizeof(int) : dstlen); + break; + } + return dstlen; +} + +int init_scrap(void) +{ + SDL_SysWMinfo info; + int retval; + + /* Grab the window manager specific information */ + retval = -1; + SDL_SetError("SDL is not running on known window manager"); + + SDL_VERSION(&info.version); + if (SDL_GetWMInfo(&info)) { + /* Save the information for later use */ +#if defined(X11_SCRAP) + if (info.subsystem == SDL_SYSWM_X11) { + SDL_Display = info.info.x11.display; + SDL_Window = info.info.x11.window; + Lock_Display = info.info.x11.lock_func; + Unlock_Display = info.info.x11.unlock_func; + + /* Enable the special window hook events */ + SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE); + SDL_SetEventFilter(clipboard_filter); + + XA_TARGETS = XInternAtom(SDL_Display, "TARGETS", False); + XA_TEXT = XInternAtom(SDL_Display, "TEXT", False); + XA_COMPOUND_TEXT = XInternAtom(SDL_Display, + "COMPOUND_TEXT", False); + XA_UTF8_STRING = XInternAtom(SDL_Display, + "UTF8_STRING", False); + + retval = 0; + } + else + SDL_SetError("SDL is not running on X11"); +#elif defined(WIN_SCRAP) + SDL_Window = info.window; + retval = 0; +#elif defined(QNX_SCRAP) + InputGroup = PhInputGroup(NULL); + retval = 0; +#endif /* scrap type */ + } + return(retval); +} + +int lost_scrap(void) +{ + int retval; + +#if defined(X11_SCRAP) + if (Lock_Display) + Lock_Display(); + retval = (XGetSelectionOwner(SDL_Display, XA_PRIMARY) != SDL_Window); + if (Unlock_Display) + Unlock_Display(); +#elif defined(WIN_SCRAP) + retval = (GetClipboardOwner() != SDL_Window); +#elif defined(QNX_SCRAP) + retval = (PhInputGroup(NULL) != InputGroup); +#endif /* scrap type */ + + return(retval); +} + +void put_scrap(int type, int srclen, const char *src) +{ + scrap_type format; + int dstlen; + char *dst; + + format = convert_format(type); + dstlen = convert_data(type, NULL, src, srclen); + +#if defined(X11_SCRAP) + dst = (char *)malloc(dstlen); + if (dst != NULL) { + if (Lock_Display) + Lock_Display(); + convert_data(type, dst, src, srclen); + XChangeProperty(SDL_Display, DefaultRootWindow(SDL_Display), + XA_CUT_BUFFER0, format, 8, PropModeReplace, + (unsigned char *)dst, dstlen); + free(dst); + if (lost_scrap()) + XSetSelectionOwner(SDL_Display, XA_PRIMARY, + SDL_Window, CurrentTime); + if (Unlock_Display) + Unlock_Display(); + } +#elif defined(WIN_SCRAP) + if (OpenClipboard(SDL_Window)) { + HANDLE hMem; + + hMem = GlobalAlloc((GMEM_MOVEABLE|GMEM_DDESHARE), dstlen); + if (hMem != NULL) { + dst = (char *)GlobalLock(hMem); + convert_data(type, dst, src, srclen); + GlobalUnlock(hMem); + EmptyClipboard(); + SetClipboardData(format, hMem); + } + CloseClipboard(); + } +#elif defined(QNX_SCRAP) +#if (_NTO_VERSION < 620) /* before 6.2.0 releases */ +#define PhClipboardHdr PhClipHeader +#endif + { + PhClipboardHdr clheader = { Ph_CLIPBOARD_TYPE_TEXT, 0, NULL }; + int* cldata; + int status; + + dst = (char *)malloc(dstlen+4); + if (dst != NULL) { + cldata = (int*)dst; + *cldata = type; + convert_data(type, dst+4, src, srclen); + clheader.data = dst; +#if (_NTO_VERSION < 620) /* before 6.2.0 releases */ + if (dstlen > 65535) + /* maximum photon clipboard size :(*/ + clheader.length = 65535; + else +#endif + clheader.length = dstlen+4; + status = PhClipboardCopy(InputGroup, 1, &clheader); + if (status == -1) + fprintf(stderr, + "Photon: copy to clipboard failed!\n"); + free(dst); + } + } +#endif /* scrap type */ +} + +void get_scrap(int type, int *dstlen, char **dst) +{ + scrap_type format; + + *dstlen = 0; + format = convert_format(type); + +#if defined(X11_SCRAP) + { + Window owner; + Atom selection; + Atom seln_type; + int seln_format; + unsigned long nbytes; + unsigned long overflow; + char *src; + + if (Lock_Display) + Lock_Display(); + owner = XGetSelectionOwner(SDL_Display, XA_PRIMARY); + if (Unlock_Display) + Unlock_Display(); + if ((owner == None) || (owner == SDL_Window)) { + owner = DefaultRootWindow(SDL_Display); + selection = XA_CUT_BUFFER0; + } + else { + int selection_response = 0; + SDL_Event event; + + owner = SDL_Window; + if (Lock_Display) + Lock_Display(); + selection = XInternAtom(SDL_Display, "SDL_SELECTION", + False); + XConvertSelection(SDL_Display, XA_PRIMARY, format, + selection, owner, CurrentTime); + if (Unlock_Display) + Unlock_Display(); + while (!selection_response) { + SDL_WaitEvent(&event); + if (event.type == SDL_SYSWMEVENT) { + XEvent xevent = + event.syswm.msg->event.xevent; + + if ((xevent.type == SelectionNotify) && + (xevent.xselection.requestor + == owner)) + selection_response = 1; + } + } + } + if (Lock_Display) + Lock_Display(); + if (XGetWindowProperty(SDL_Display, owner, selection, + 0, INT_MAX/4, False, format, &seln_type, + &seln_format, &nbytes, &overflow, + (unsigned char **)&src) == Success) { + if (seln_type == format) { + *dstlen = convert_scrap(type, NULL, + src, nbytes); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, src, nbytes); + } + XFree(src); + } + } + if (Unlock_Display) + Unlock_Display(); +#elif defined(WIN_SCRAP) + if (IsClipboardFormatAvailable(format) && OpenClipboard(SDL_Window)) { + HANDLE hMem; + char *src; + + hMem = GetClipboardData(format); + if (hMem != NULL) { + src = (char *)GlobalLock(hMem); + *dstlen = convert_scrap(type, NULL, src, 0); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, src, 0); + GlobalUnlock(hMem); + } + CloseClipboard(); + } +#elif defined(QNX_SCRAP) +#if (_NTO_VERSION < 620) /* before 6.2.0 releases */ + { + void* clhandle; + PhClipHeader* clheader; + int* cldata; + + clhandle = PhClipboardPasteStart(InputGroup); + if (clhandle != NULL) { + clheader = PhClipboardPasteType(clhandle, + Ph_CLIPBOARD_TYPE_TEXT); + if (clheader != NULL) { + cldata = clheader->data; + if ((clheader->length>4) && (*cldata == type)) { + *dstlen = convert_scrap(type, NULL, + (char*)clheader->data+4, + clheader->length-4); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, + (char*)clheader->data+4, + clheader->length-4); + } + } + PhClipboardPasteFinish(clhandle); + } + } +#else /* 6.2.0 and 6.2.1 and future releases */ + { + void* clhandle; + PhClipboardHdr* clheader; + int* cldata; + + clheader=PhClipboardRead(InputGroup, Ph_CLIPBOARD_TYPE_TEXT); + if (clheader!=NULL) { + cldata=clheader->data; + if ((clheader->length>4) && (*cldata==type)) { + *dstlen = convert_scrap(type, NULL, + (char*)clheader->data+4, + clheader->length-4); + *dst = (char *)realloc(*dst, *dstlen); + if (*dst == NULL) + *dstlen = 0; + else + convert_scrap(type, *dst, + (char*)clheader->data+4, + clheader->length-4); + } + } + } +#endif +#endif /* scrap type */ +} + +int clipboard_filter(const SDL_Event *event) +{ +#if defined(X11_SCRAP) + /* Post all non-window manager specific events */ + if (event->type != SDL_SYSWMEVENT) + return(1); + + /* Handle window-manager specific clipboard events */ + switch (event->syswm.msg->event.xevent.type) { + /* Copy the selection from XA_CUT_BUFFER0 to the requested property */ + case SelectionRequest: { + XSelectionRequestEvent *req; + XEvent sevent; + int seln_format; + unsigned long nbytes; + unsigned long overflow; + unsigned char *seln_data; + + req = &event->syswm.msg->event.xevent.xselectionrequest; + if (req->target == XA_TARGETS) { + Atom supported[] = { + XA_TEXT, XA_COMPOUND_TEXT, XA_UTF8_STRING, + XA_TARGETS, XA_STRING + }; + XEvent response; + + XChangeProperty(SDL_Display, req->requestor, + req->property, req->target, 32, PropModeReplace, + (unsigned char*)supported, + sizeof(supported) / sizeof(supported[0])); + response.xselection.property=None; + response.xselection.type= SelectionNotify; + response.xselection.display= req->display; + response.xselection.requestor= req->requestor; + response.xselection.selection=req->selection; + response.xselection.target= req->target; + response.xselection.time = req->time; + XSendEvent (SDL_Display, req->requestor,0,0,&response); + XFlush (SDL_Display); + return 1; + } + + sevent.xselection.type = SelectionNotify; + sevent.xselection.display = req->display; + sevent.xselection.selection = req->selection; + sevent.xselection.target = None; + sevent.xselection.property = req->property; + sevent.xselection.requestor = req->requestor; + sevent.xselection.time = req->time; + if (XGetWindowProperty(SDL_Display, + DefaultRootWindow(SDL_Display), XA_CUT_BUFFER0, + 0, INT_MAX/4, False, req->target, + &sevent.xselection.target, &seln_format, + &nbytes, &overflow, &seln_data) == Success) { + if (sevent.xselection.target == req->target) { + if (sevent.xselection.target == XA_STRING && + nbytes > 0 && + seln_data[nbytes-1] == '\0') + --nbytes; + XChangeProperty(SDL_Display, req->requestor, + req->property, sevent.xselection.target, + seln_format, PropModeReplace, + seln_data, nbytes); + sevent.xselection.property = req->property; + } + XFree(seln_data); + } + XSendEvent(SDL_Display,req->requestor,False,0,&sevent); + XSync(SDL_Display, False); + break; + } + } + /* Post the event for X11 clipboard reading above */ +#endif /* X11_SCRAP */ + return(1); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h new file mode 100755 index 0000000..647bd74 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/scrap.h @@ -0,0 +1,18 @@ +/* Handle clipboard text and data in arbitrary formats */ + +/* Miscellaneous defines */ +#define T(A, B, C, D) (int)((A<<24)|(B<<16)|(C<<8)|(D<<0)) + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +extern int init_scrap(void); +extern int lost_scrap(void); +extern void put_scrap(int type, int srclen, const char *src); +extern void get_scrap(int type, int *dstlen, char **dst); +extern int clipboard_filter(const SDL_Event *event); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c new file mode 100755 index 0000000..57fe1a8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/client_examples/vnc2mpg.c @@ -0,0 +1,435 @@ +/* + * Simple movie writer for vnc; based on Libavformat API example from FFMPEG + * + * Copyright (c) 2003 Fabrice Bellard, 2004 Johannes E. Schindelin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#include +#include +#include +#include +#include + +#ifndef M_PI +#define M_PI 3.1415926535897931 +#endif + +#include "avformat.h" +#include + +#define STREAM_FRAME_RATE 25 /* 25 images/s */ + +/**************************************************************/ +/* video output */ + +AVFrame *picture, *tmp_picture; +uint8_t *video_outbuf; +int frame_count, video_outbuf_size; + +/* add a video output stream */ +AVStream *add_video_stream(AVFormatContext *oc, int codec_id, int w, int h) +{ + AVCodecContext *c; + AVStream *st; + + st = av_new_stream(oc, 0); + if (!st) { + fprintf(stderr, "Could not alloc stream\n"); + exit(1); + } + +#if LIBAVFORMAT_BUILD<4629 + c = &st->codec; +#else + c = st->codec; +#endif + c->codec_id = codec_id; + c->codec_type = CODEC_TYPE_VIDEO; + + /* put sample parameters */ + c->bit_rate = 800000; + /* resolution must be a multiple of two */ + c->width = w; + c->height = h; + /* frames per second */ +#if LIBAVCODEC_BUILD<4754 + c->frame_rate = STREAM_FRAME_RATE; + c->frame_rate_base = 1; +#else + c->time_base.den = STREAM_FRAME_RATE; + c->time_base.num = 1; + c->pix_fmt = PIX_FMT_YUV420P; +#endif + c->gop_size = 12; /* emit one intra frame every twelve frames at most */ + if (c->codec_id == CODEC_ID_MPEG2VIDEO) { + /* just for testing, we also add B frames */ + c->max_b_frames = 2; + } + if (c->codec_id == CODEC_ID_MPEG1VIDEO){ + /* needed to avoid using macroblocks in which some coeffs overflow + this doesnt happen with normal video, it just happens here as the + motion of the chroma plane doesnt match the luma plane */ + c->mb_decision=2; + } + /* some formats want stream headers to be seperate */ + if(!strcmp(oc->oformat->name, "mp4") || !strcmp(oc->oformat->name, "mov") || !strcmp(oc->oformat->name, "3gp")) + c->flags |= CODEC_FLAG_GLOBAL_HEADER; + + return st; +} + +AVFrame *alloc_picture(int pix_fmt, int width, int height) +{ + AVFrame *picture; + uint8_t *picture_buf; + int size; + + picture = avcodec_alloc_frame(); + if (!picture) + return NULL; + size = avpicture_get_size(pix_fmt, width, height); + picture_buf = malloc(size); + if (!picture_buf) { + av_free(picture); + return NULL; + } + avpicture_fill((AVPicture *)picture, picture_buf, + pix_fmt, width, height); + return picture; +} + +void open_video(AVFormatContext *oc, AVStream *st) +{ + AVCodec *codec; + AVCodecContext *c; + +#if LIBAVFORMAT_BUILD<4629 + c = &st->codec; +#else + c = st->codec; +#endif + + /* find the video encoder */ + codec = avcodec_find_encoder(c->codec_id); + if (!codec) { + fprintf(stderr, "codec not found\n"); + exit(1); + } + + /* open the codec */ + if (avcodec_open(c, codec) < 0) { + fprintf(stderr, "could not open codec\n"); + exit(1); + } + + video_outbuf = NULL; + if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) { + /* allocate output buffer */ + /* XXX: API change will be done */ + video_outbuf_size = 200000; + video_outbuf = malloc(video_outbuf_size); + } + + /* allocate the encoded raw picture */ + picture = alloc_picture(c->pix_fmt, c->width, c->height); + if (!picture) { + fprintf(stderr, "Could not allocate picture\n"); + exit(1); + } + + /* if the output format is not RGB565, then a temporary RGB565 + picture is needed too. It is then converted to the required + output format */ + tmp_picture = NULL; + if (c->pix_fmt != PIX_FMT_RGB565) { + tmp_picture = alloc_picture(PIX_FMT_RGB565, c->width, c->height); + if (!tmp_picture) { + fprintf(stderr, "Could not allocate temporary picture\n"); + exit(1); + } + } +} + +void write_video_frame(AVFormatContext *oc, AVStream *st) +{ + int out_size, ret; + AVCodecContext *c; + AVFrame *picture_ptr; + +#if LIBAVFORMAT_BUILD<4629 + c = &st->codec; +#else + c = st->codec; +#endif + + if (c->pix_fmt != PIX_FMT_RGB565) { + /* as we only generate a RGB565 picture, we must convert it + to the codec pixel format if needed */ + img_convert((AVPicture *)picture, c->pix_fmt, + (AVPicture *)tmp_picture, PIX_FMT_RGB565, + c->width, c->height); + } + picture_ptr = picture; + + + if (oc->oformat->flags & AVFMT_RAWPICTURE) { + /* raw video case. The API will change slightly in the near + futur for that */ + AVPacket pkt; + av_init_packet(&pkt); + + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index= st->index; + pkt.data= (uint8_t *)picture_ptr; + pkt.size= sizeof(AVPicture); + + ret = av_write_frame(oc, &pkt); + } else { + /* encode the image */ + out_size = avcodec_encode_video(c, video_outbuf, video_outbuf_size, picture_ptr); + /* if zero size, it means the image was buffered */ + if (out_size != 0) { + AVPacket pkt; + av_init_packet(&pkt); + + pkt.pts= c->coded_frame->pts; + if(c->coded_frame->key_frame) + pkt.flags |= PKT_FLAG_KEY; + pkt.stream_index= st->index; + pkt.data= video_outbuf; + pkt.size= out_size; + + /* write the compressed frame in the media file */ + ret = av_write_frame(oc, &pkt); + } else { + ret = 0; + } + } + if (ret != 0) { + fprintf(stderr, "Error while writing video frame\n"); + exit(1); + } + frame_count++; +} + +void close_video(AVFormatContext *oc, AVStream *st) +{ + avcodec_close(st->codec); + av_free(picture->data[0]); + av_free(picture); + if (tmp_picture) { + av_free(tmp_picture->data[0]); + av_free(tmp_picture); + } + av_free(video_outbuf); +} + +static const char *filename; +static AVOutputFormat *fmt; +static AVFormatContext *oc; +static AVStream *video_st; +static double video_pts; + +static int movie_open(int w, int h) { + if (fmt->video_codec != CODEC_ID_NONE) { + video_st = add_video_stream(oc, fmt->video_codec, w, h); + } else + return 1; + + /* set the output parameters (must be done even if no + parameters). */ + if (av_set_parameters(oc, NULL) < 0) { + fprintf(stderr, "Invalid output format parameters\n"); + return 2; + } + + dump_format(oc, 0, filename, 1); + + /* now that all the parameters are set, we can open the audio and + video codecs and allocate the necessary encode buffers */ + if (video_st) + open_video(oc, video_st); + + /* open the output file, if needed */ + if (!(fmt->flags & AVFMT_NOFILE)) { + if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) { + fprintf(stderr, "Could not open '%s'\n", filename); + return 3; + } + } + + /* write the stream header, if any */ + av_write_header(oc); + + return 0; +} + +static int movie_close() { + int i; + + /* close each codec */ + close_video(oc, video_st); + + /* write the trailer, if any */ + av_write_trailer(oc); + + /* free the streams */ + for(i = 0; i < oc->nb_streams; i++) { + av_freep(&oc->streams[i]); + } + + if (!(fmt->flags & AVFMT_NOFILE)) { + /* close the output file */ + url_fclose(&oc->pb); + } + + /* free the stream */ + av_free(oc); + +} + +static rfbBool quit=FALSE; +static void signal_handler(int signal) { + fprintf(stderr,"Cleaning up.\n"); + quit=TRUE; +} + +/**************************************************************/ +/* VNC callback functions */ +static rfbBool resize(rfbClient* client) { + static rfbBool first=TRUE; + if(!first) { + movie_close(); + perror("I don't know yet how to change resolutions!\n"); + } + movie_open(client->width, client->height); + signal(SIGINT,signal_handler); + if(tmp_picture) + client->frameBuffer=tmp_picture->data[0]; + else + client->frameBuffer=picture->data[0]; + return TRUE; +} + +static void update(rfbClient* client,int x,int y,int w,int h) { +} + +/**************************************************************/ +/* media file output */ + +int main(int argc, char **argv) +{ + time_t stop=0; + rfbClient* client; + int i,j; + + /* get a vnc client structure (don't connect yet). */ + client = rfbGetClient(5,3,2); + client->format.redShift=11; client->format.redMax=31; + client->format.greenShift=5; client->format.greenMax=63; + client->format.blueShift=0; client->format.blueMax=31; + + /* initialize libavcodec, and register all codecs and formats */ + av_register_all(); + + if(!strncmp(argv[argc-1],":",1) || + !strncmp(argv[argc-1],"127.0.0.1",9) || + !strncmp(argv[argc-1],"localhost",9)) + client->appData.encodingsString="raw"; + + filename=0; + for(i=1;ii+1 && !strcmp("-o",argv[i])) { + filename=argv[2]; + j+=2; + } else if(argc>i+1 && !strcmp("-t",argv[i])) { + stop=time(0)+atoi(argv[i+1]); + j+=2; + } + if(j>i) { + argc-=j-i; + memmove(argv+i,argv+j,(argc-i)*sizeof(char*)); + i--; + } + } + + + /* auto detect the output format from the name. default is + mpeg. */ + fmt = filename?guess_format(NULL, filename, NULL):0; + if (!fmt) { + printf("Could not deduce output format from file extension: using MPEG.\n"); + fmt = guess_format("mpeg", NULL, NULL); + } + if (!fmt) { + fprintf(stderr, "Could not find suitable output format\n"); + exit(1); + } + + /* allocate the output media context */ + oc = av_alloc_format_context(); + if (!oc) { + fprintf(stderr, "Memory error\n"); + exit(1); + } + oc->oformat = fmt; + snprintf(oc->filename, sizeof(oc->filename), "%s", filename); + + /* add the audio and video streams using the default format codecs + and initialize the codecs */ + video_st = NULL; + + /* open VNC connection */ + client->MallocFrameBuffer=resize; + client->GotFrameBufferUpdate=update; + if(!rfbInitClient(client,&argc,argv)) { + printf("usage: %s [-o output_file] [-t seconds] server:port\n" + "Shoot a movie from a VNC server.\n", argv[0]); + exit(1); + } + if(client->serverPort==-1) + client->vncRec->doNotSleep = TRUE; /* vncrec playback */ + + /* main loop */ + + while(!quit) { + int i=WaitForMessage(client,1000000/STREAM_FRAME_RATE); + if(i<0) { + movie_close(); + return 0; + } + if(i) + if(!HandleRFBServerMessage(client)) + quit=TRUE; + else { + /* compute current audio and video time */ + video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; + + /* write interleaved audio and video frames */ + write_video_frame(oc, video_st); + } + if(stop!=0 && stop]) + + if test "x$with_fbpm" != "xno"; then + AC_CHECK_LIB(Xext, FBPMForceLevel, + [AC_DEFINE(HAVE_FBPM)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_dpms" != "xno"; then + AC_CHECK_LIB(Xext, DPMSForceLevel, + [AC_DEFINE(HAVE_DPMS)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + AC_CHECK_LIB(Xtst, XTestGrabControl, + X_PRELIBS="-lXtst $X_PRELIBS" + [AC_DEFINE(HAVE_XTESTGRABCONTROL) HAVE_XTESTGRABCONTROL="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + + AC_CHECK_LIB(Xtst, XTestFakeKeyEvent, + X_PRELIBS="-lXtst $X_PRELIBS" + [AC_DEFINE(HAVE_XTEST) HAVE_XTEST="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + + if test "x$with_xrecord" != "xno"; then + AC_CHECK_LIB(Xtst, XRecordEnableContextAsync, + X_PRELIBS="-lXtst $X_PRELIBS" + [AC_DEFINE(HAVE_RECORD)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + # we use XTRAP on X11R5, or user can set X11VNC_USE_XTRAP + if test "x$with_xtrap" != "xno"; then + if test ! -z "$X11VNC_USE_XTRAP" -o -z "$HAVE_XTESTGRABCONTROL"; then + AC_CHECK_LIB(XTrap, XETrapSetGrabServer, + X_PRELIBS="$X_PRELIBS -lXTrap" + [AC_DEFINE(HAVE_LIBXTRAP)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + # tru64 uses libXETrap.so + AC_CHECK_LIB(XETrap, XETrapSetGrabServer, + X_PRELIBS="$X_PRELIBS -lXETrap" + [AC_DEFINE(HAVE_LIBXTRAP)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + fi + + if test "x$with_xkeyboard" != "xno"; then + saved_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + AC_CHECK_HEADER(X11/XKBlib.h, HAVE_XKBLIB_H="true", + HAVE_XKBLIB_H="false", [#include ]) + CPPFLAGS="$saved_CPPFLAGS" + if test $HAVE_XKBLIB_H = "true"; then + AC_CHECK_LIB(X11, XkbSelectEvents, + [AC_DEFINE(HAVE_XKEYBOARD)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + fi + + if test "x$with_xinerama" != "xno"; then + AC_CHECK_LIB(Xinerama, XineramaQueryScreens, + X_PRELIBS="$X_PRELIBS -lXinerama" + [AC_DEFINE(HAVE_LIBXINERAMA)], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_xrandr" != "xno"; then + AC_CHECK_LIB(Xrandr, XRRSelectInput, + X_PRELIBS="$X_PRELIBS -lXrandr" + [AC_DEFINE(HAVE_LIBXRANDR) HAVE_LIBXRANDR="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_xfixes" != "xno"; then + AC_CHECK_LIB(Xfixes, XFixesGetCursorImage, + X_PRELIBS="$X_PRELIBS -lXfixes" + [AC_DEFINE(HAVE_LIBXFIXES) HAVE_LIBXFIXES="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test "x$with_xdamage" != "xno"; then + AC_CHECK_LIB(Xdamage, XDamageQueryExtension, + X_PRELIBS="$X_PRELIBS -lXdamage" + [AC_DEFINE(HAVE_LIBXDAMAGE) HAVE_LIBXDAMAGE="true"], , + $X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS) + fi + + if test ! -z "$HAVE_LIBXFIXES" -o ! -z "$HAVE_LIBXDAMAGE"; then + # need /usr/sfw/lib in RPATH for Solaris 10 and later + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) X_EXTRA_LIBS="$X_EXTRA_LIBS -R/usr/sfw/lib" ;; + esac + fi + if test ! -z "$HAVE_LIBXRANDR"; then + # also need /usr/X11/include for Solaris 10 10/08 and later + case `(uname -sr) 2>/dev/null` in + "SunOS 5"*) CPPFLAGS="$CPPFLAGS -I/usr/X11/include" ;; + esac + fi + + X_LIBS="$X_LIBS $X_PRELIBS -lX11 $X_EXTRA_LIBS" + fi + # end x11vnc only. +fi + +AC_SUBST(X_LIBS) +AM_CONDITIONAL(HAVE_X11, test $HAVE_X11 != "false") + +# x11vnc only: +if test "$build_x11vnc" = "yes"; then + +if test "x$HAVE_X11" = "xfalse" -a "x$with_x" != "xno"; then + AC_MSG_ERROR([ +========================================================================== +*** A working X window system build environment is required to build *** +x11vnc. Make sure any required X development packages are installed. +If they are installed in non-standard locations, one can use the +--x-includes=DIR and --x-libraries=DIR configure options or set the +CPPFLAGS and LDFLAGS environment variables to indicate where the X +window system header files and libraries may be found. On 64+32 bit +machines you may need to point to lib64 or lib32 directories to pick up +the correct word size. + +If you want to build x11vnc without X support (e.g. for -rawfb use only +or for native Mac OS X), specify the --without-x configure option. +========================================================================== +]) +fi + +if test "x$HAVE_X11" = "xtrue" -a "x$HAVE_XTEST" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** A working build environment for the XTEST extension was not found *** +(libXtst). An x11vnc built this way will be *ONLY BARELY USABLE*. +You will be able to move the mouse but not click or type. There can +also be deadlocks if an application grabs the X server. + +It is recommended that you install the necessary development packages +for XTEST (perhaps it is named something like libxtst-dev) and run +configure again. +========================================================================== +]) + sleep 5 +fi + +# set some ld -R nonsense +# +uname_s=`(uname -s) 2>/dev/null` +ld_minus_R="yes" +if test "x$uname_s" = "xHP-UX"; then + ld_minus_R="no" +elif test "x$uname_s" = "xOSF1"; then + ld_minus_R="no" +elif test "x$uname_s" = "xDarwin"; then + ld_minus_R="no" +fi + +if test "x$with_v4l" != "xno"; then + AC_CHECK_HEADER(linux/videodev.h, + [AC_DEFINE(HAVE_LINUX_VIDEODEV_H)],,) +fi +if test "x$with_fbdev" != "xno"; then + AC_CHECK_HEADER(linux/fb.h, + [AC_DEFINE(HAVE_LINUX_FB_H)],,) +fi +if test "x$with_uinput" != "xno"; then + AC_CHECK_HEADER(linux/input.h, + [AC_DEFINE(HAVE_LINUX_INPUT_H) HAVE_LINUX_INPUT_H="true"],,) + if test "x$HAVE_LINUX_INPUT_H" = "xtrue"; then + AC_CHECK_HEADER(linux/uinput.h, + [AC_DEFINE(HAVE_LINUX_UINPUT_H)],, [#include ]) + fi +fi + +if test "x$with_macosx_native" != "xno"; then + AC_DEFINE(HAVE_MACOSX_NATIVE_DISPLAY) +fi + +AH_TEMPLATE(HAVE_AVAHI, [Avahi/mDNS client build environment present]) +AC_ARG_WITH(avahi, +[ --without-avahi disable support for Avahi/mDNS] +[ --with-avahi=DIR use avahi include/library files in DIR],,) +if test "x$with_avahi" != "xno"; then + printf "checking for avahi... " + if test ! -z "$with_avahi" -a "x$with_avahi" != "xyes"; then + AVAHI_CFLAGS="-I$with_avahi/include" + AVAHI_LIBS="-L$with_avahi/lib -lavahi-common -lavahi-client" + echo "using $with_avahi" + with_avahi=yes + elif pkg-config --atleast-version=0.6.4 avahi-client >/dev/null 2>&1; then + AVAHI_CFLAGS=`pkg-config --cflags avahi-client` + AVAHI_LIBS=`pkg-config --libs avahi-client` + with_avahi=yes + echo yes + else + with_avahi=no + echo no + fi +fi +if test "x$with_avahi" = "xyes"; then + AC_DEFINE(HAVE_AVAHI) + AC_SUBST(AVAHI_CFLAGS) + AC_SUBST(AVAHI_LIBS) +fi + +fi +# end x11vnc only. + + +AH_TEMPLATE(HAVE_LIBCRYPT, [libcrypt library present]) +AC_ARG_WITH(crypt, +[ --without-crypt disable support for libcrypt],,) +if test "x$with_crypt" != "xno"; then + AC_CHECK_FUNCS([crypt], HAVE_LIBC_CRYPT="true") + if test -z "$HAVE_LIBC_CRYPT"; then + AC_CHECK_LIB(crypt, crypt, + CRYPT_LIBS="-lcrypt" + [AC_DEFINE(HAVE_LIBCRYPT)], ,) + fi +fi +AC_SUBST(CRYPT_LIBS) + +# some OS's need both -lssl and -lcrypto on link line: +AH_TEMPLATE(HAVE_LIBCRYPTO, [openssl libcrypto library present]) +AC_ARG_WITH(crypto, +[ --without-crypto disable support for openssl libcrypto],,) + +AH_TEMPLATE(HAVE_LIBSSL, [openssl libssl library present]) +AC_ARG_WITH(ssl, +[ --without-ssl disable support for openssl libssl] +[ --with-ssl=DIR use openssl include/library files in DIR],,) + +if test "x$with_crypto" != "xno" -a "x$with_ssl" != "xno"; then + if test ! -z "$with_ssl" -a "x$with_ssl" != "xyes"; then + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_ssl/include" + LDFLAGS="$LDFLAGS -L$with_ssl/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + LDFLAGS="$LDFLAGS -Xlinker -R$with_ssl/lib" + else + LDFLAGS="$LDFLAGS -R$with_ssl/lib" + fi + fi + AC_CHECK_LIB(crypto, RAND_file_name, + [AC_DEFINE(HAVE_LIBCRYPTO) HAVE_LIBCRYPTO="true"], ,) + if test ! -z "$with_ssl" -a "x$with_ssl" != "xyes"; then + if test "x$HAVE_LIBCRYPTO" != "xtrue"; then + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi +fi + +AH_TEMPLATE(HAVE_X509_PRINT_EX_FP, [open ssl X509_print_ex_fp available]) +if test "x$with_ssl" != "xno"; then + if test "x$HAVE_LIBCRYPTO" = "xtrue"; then + AC_CHECK_LIB(ssl, SSL_library_init, + SSL_LIBS="-lssl -lcrypto" + [AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], , + -lcrypto) + else + AC_CHECK_LIB(ssl, SSL_library_init, + SSL_LIBS="-lssl" + [AC_DEFINE(HAVE_LIBSSL) HAVE_LIBSSL="true"], ,) + fi +fi +AC_SUBST(SSL_LIBS) + + if test "x$HAVE_LIBSSL" != "xtrue" -a "x$with_ssl" != "xno"; then + AC_MSG_WARN([ +========================================================================== +*** The openssl encryption library libssl.so was not found. *** +An x11vnc built this way will not support SSL encryption. To enable +SSL install the necessary development packages (perhaps it is named +something like libssl-dev) and run configure again. +========================================================================== +]) + sleep 5 + elif test "x$with_ssl" != "xno"; then + AC_CHECK_LIB(ssl, X509_print_ex_fp, + [AC_DEFINE(HAVE_X509_PRINT_EX_FP) HAVE_X509_PRINT_EX_FP="true"], , $SSL_LIBS + ) + fi + + +# Checks for libraries. + +if test ! -z "$with_system_libvncserver" -a "x$with_system_libvncserver" != "xno"; then + printf "checking for system libvncserver... " + vneed="0.9.1" + if test "X$VNEED" != "X"; then + vneed=$VNEED + fi + if test "x$with_system_libvncserver" != "xyes"; then + rflag="" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + rflag="-Xlinker -R$with_system_libvncserver/lib" + else + rflag="-R$with_system_libvncserver/lib" + fi + cmd="$with_system_libvncserver/bin/libvncserver-config" + if $cmd --version 1>/dev/null 2>&1; then + cvers=`$cmd --version 2>/dev/null` + cscore=`echo "$cvers" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + nscore=`echo "$vneed" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + + if test $cscore -lt $nscore; then + echo "no" + with_system_libvncserver=no + AC_MSG_ERROR([ +========================================================================== +*** Need libvncserver version $vneed, have version $cvers *** +You are building with a system installed libvncserver and it is not +new enough. +========================================================================== +]) + else + SYSTEM_LIBVNCSERVER_CFLAGS="-I$with_system_libvncserver/include" + SYSTEM_LIBVNCSERVER_LIBS="-L$with_system_libvncserver/lib $rflag -lvncserver -lvncclient" + echo "using $with_system_libvncserver" + with_system_libvncserver=yes + fi + else + echo " *** cannot run $cmd *** " 1>&2 + with_system_libvncserver=no + echo no + fi + elif libvncserver-config --version 1>/dev/null 2>&1; then + rflag="" + rprefix=`libvncserver-config --prefix` + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + rflag=" -Xlinker -R$rprefix/lib " + else + rflag=" -R$rprefix/lib " + fi + cvers=`libvncserver-config --version 2>/dev/null` + cscore=`echo "$cvers" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + nscore=`echo "$vneed" | tr '.' ' ' | awk '{print 10000 * $1 + 100 * $2 + $3}'` + + if test $cscore -lt $nscore; then + echo "no" + AC_MSG_ERROR([ +========================================================================== +*** Need libvncserver version $vneed, have version $cvers *** +You are building with a system installed libvncserver and it is not +new enough. +========================================================================== +]) + else + SYSTEM_LIBVNCSERVER_CFLAGS=`libvncserver-config --cflags` + SYSTEM_LIBVNCSERVER_LIBS="$rflag"`libvncserver-config --libs` + with_system_libvncserver=yes + echo yes + fi + else + with_system_libvncserver=no + echo no + fi +fi + +if test "x$with_system_libvncserver" = "xyes"; then + AC_DEFINE(HAVE_SYSTEM_LIBVNCSERVER) + AC_SUBST(SYSTEM_LIBVNCSERVER_CFLAGS) + AC_SUBST(SYSTEM_LIBVNCSERVER_LIBS) +fi +AM_CONDITIONAL(HAVE_SYSTEM_LIBVNCSERVER, test "x$with_system_libvncserver" = "xyes") + + +AC_ARG_WITH(jpeg, +[ --without-jpeg disable support for jpeg] +[ --with-jpeg=DIR use jpeg include/library files in DIR],,) + +# At this point: +# no jpeg on command line with_jpeg="" +# -with-jpeg with_jpeg="yes" +# -without-jpeg with_jpeg="no" +# -with-jpeg=/foo/dir with_jpeg="/foo/dir" + +if test "x$with_jpeg" != "xno"; then + if test ! -z "$with_jpeg" -a "x$with_jpeg" != "xyes"; then + # add user supplied directory to flags: + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_jpeg/include" + LDFLAGS="$LDFLAGS -L$with_jpeg/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + # this is not complete... in general a rat's nest. + LDFLAGS="$LDFLAGS -Xlinker -R$with_jpeg/lib" + else + LDFLAGS="$LDFLAGS -R$with_jpeg/lib" + fi + fi + AC_CHECK_HEADER(jpeglib.h, HAVE_JPEGLIB_H="true") + if test "x$HAVE_JPEGLIB_H" = "xtrue"; then + AC_CHECK_LIB(jpeg, jpeg_CreateCompress, , HAVE_JPEGLIB_H="") + fi + if test ! -z "$with_jpeg" -a "x$with_jpeg" != "xyes"; then + if test "x$HAVE_JPEGLIB_H" != "xtrue"; then + # restore old flags on failure: + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi + if test "$build_x11vnc" = "yes"; then + if test "x$HAVE_JPEGLIB_H" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** The libjpeg compression library was not found. *** +This may lead to reduced performance, especially over slow links. +If libjpeg is in a non-standard location use --with-jpeg=DIR to +indicate the header file is in DIR/include/jpeglib.h and the library +in DIR/lib/libjpeg.a. A copy of libjpeg may be obtained from: +ftp://ftp.uu.net/graphics/jpeg/ +========================================================================== +]) + sleep 5 + fi + fi +fi + +AC_ARG_WITH(png, +[ --without-png disable support for png] +[ --with-png=DIR use png include/library files in DIR],,) + +# At this point: +# no png on command line with_png="" +# -with-png with_png="yes" +# -without-png with_png="no" +# -with-png=/foo/dir with_png="/foo/dir" + +if test "x$with_png" != "xno"; then + if test ! -z "$with_png" -a "x$with_png" != "xyes"; then + # add user supplied directory to flags: + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_png/include" + LDFLAGS="$LDFLAGS -L$with_png/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + # this is not complete... in general a rat's nest. + LDFLAGS="$LDFLAGS -Xlinker -R$with_png/lib" + else + LDFLAGS="$LDFLAGS -R$with_png/lib" + fi + fi + AC_CHECK_HEADER(png.h, HAVE_PNGLIB_H="true") + if test "x$HAVE_PNGLIB_H" = "xtrue"; then + AC_CHECK_LIB(png, png_create_write_struct, , HAVE_PNGLIB_H="") + fi + if test ! -z "$with_png" -a "x$with_png" != "xyes"; then + if test "x$HAVE_PNGLIB_H" != "xtrue"; then + # restore old flags on failure: + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi + if test "$build_x11vnc" = "yes"; then + if test "x$HAVE_PNGLIB_H" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** The libpng compression library was not found. *** +This may lead to reduced performance, especially over slow links. +If libpng is in a non-standard location use --with-png=DIR to +indicate the header file is in DIR/include/png.h and the library +in DIR/lib/libpng.a. A copy of libpng may be obtained from: +http://www.libpng.org/pub/png/libpng.html +========================================================================== +]) + sleep 5 + fi + fi +fi + +AC_ARG_WITH(libz, +[ --without-libz disable support for deflate],,) +AC_ARG_WITH(zlib, +[ --without-zlib disable support for deflate] +[ --with-zlib=DIR use zlib include/library files in DIR],,) + +if test "x$with_zlib" != "xno" -a "x$with_libz" != "xno"; then + if test ! -z "$with_zlib" -a "x$with_zlib" != "xyes"; then + saved_CPPFLAGS="$CPPFLAGS" + saved_LDFLAGS="$LDFLAGS" + CPPFLAGS="$CPPFLAGS -I$with_zlib/include" + LDFLAGS="$LDFLAGS -L$with_zlib/lib" + if test "x$ld_minus_R" = "xno"; then + : + elif test "x$GCC" = "xyes"; then + LDFLAGS="$LDFLAGS -Xlinker -R$with_zlib/lib" + else + LDFLAGS="$LDFLAGS -R$with_zlib/lib" + fi + fi + AC_CHECK_HEADER(zlib.h, HAVE_ZLIB_H="true") + if test "x$HAVE_ZLIB_H" = "xtrue"; then + AC_CHECK_LIB(z, deflate, , HAVE_ZLIB_H="") + fi + if test ! -z "$with_zlib" -a "x$with_zlib" != "xyes"; then + if test "x$HAVE_ZLIB_H" != "xtrue"; then + CPPFLAGS="$saved_CPPFLAGS" + LDFLAGS="$saved_LDFLAGS" + fi + fi + if test "$build_x11vnc" = "yes"; then + if test "x$HAVE_ZLIB_H" != "xtrue"; then + AC_MSG_WARN([ +========================================================================== +*** The libz compression library was not found. *** +This may lead to reduced performance, especially over slow links. +If libz is in a non-standard location use --with-zlib=DIR to indicate the +header file is in DIR/include/zlib.h and the library in DIR/lib/libz.a. +A copy of libz may be obtained from: http://www.gzip.org/zlib/ +========================================================================== +]) + sleep 5 + fi + fi +fi + +AC_ARG_WITH(pthread, +[ --without-pthread disable support for libpthread],,) + +if test "x$with_pthread" != "xno"; then + AC_CHECK_HEADER(pthread.h, HAVE_PTHREAD_H="true") + if test ! -z "$HAVE_PTHREAD_H"; then + AC_CHECK_LIB(pthread, pthread_mutex_lock) + AC_CHECK_LIB(pthread, pthread_mutex_lock, HAVE_LIBPTHREAD="true") + fi +fi +AM_CONDITIONAL(HAVE_LIBPTHREAD, test ! -z "$HAVE_LIBPTHREAD") + +AC_MSG_CHECKING([for __thread]) +AC_LINK_IFELSE([AC_LANG_PROGRAM(, [static __thread int p = 0])], + [AC_DEFINE(HAVE_TLS, 1, + Define to 1 if compiler supports __thread) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) + +# tightvnc-filetransfer implemented using threads: +if test -z "$HAVE_LIBPTHREAD"; then + with_tightvnc_filetransfer="" +fi +if test "x$with_tightvnc_filetransfer" = "xyes"; then + AC_DEFINE(WITH_TIGHTVNC_FILETRANSFER) +fi +AM_CONDITIONAL(WITH_TIGHTVNC_FILETRANSFER, test "$with_tightvnc_filetransfer" = "yes") + +# websockets implemented using base64 from resolve +if test "x$HAVE_B64" != "xtrue"; then + with_websockets="" +fi +if test "x$with_websockets" = "xyes"; then + LIBS="$LIBS -lresolv" + AC_DEFINE(WITH_WEBSOCKETS) +fi +AM_CONDITIONAL(WITH_WEBSOCKETS, test "$with_websockets" = "yes") + +AM_CONDITIONAL(HAVE_LIBZ, test ! -z "$HAVE_ZLIB_H") +AM_CONDITIONAL(HAVE_LIBJPEG, test ! -z "$HAVE_JPEGLIB_H") +AM_CONDITIONAL(HAVE_LIBPNG, test ! -z "$HAVE_PNGLIB_H") + + +SDLCONFIG="sdl-config" +AC_ARG_WITH(sdl-config, +[[ --with-sdl-config=FILE + Use the given path to sdl-config when determining + SDL configuration; defaults to "sdl-config"]], +[ + if test "$withval" != "yes" -a "$withval" != ""; then + SDLCONFIG=$withval + fi +]) + +if test -z "$with_sdl"; then + if $SDLCONFIG --version >/dev/null 2>&1; then + with_sdl=yes + SDL_CFLAGS=`$SDLCONFIG --cflags` + SDL_LIBS=`$SDLCONFIG --libs` + else + with_sdl=no + fi +fi +AM_CONDITIONAL(HAVE_LIBSDL, test "x$with_sdl" = "xyes") +AC_SUBST(SDL_CFLAGS) +AC_SUBST(SDL_LIBS) + + +AC_CANONICAL_HOST +MINGW=`echo $host_os | grep mingw32 2>/dev/null` +AM_CONDITIONAL(MINGW, test ! -z "$MINGW" ) +if test ! -z "$MINGW"; then + WSOCKLIB="-lws2_32" +fi +AC_SUBST(WSOCKLIB) + +# Checks for GnuTLS +AH_TEMPLATE(WITH_CLIENT_TLS, [Enable support for gnutls in libvncclient]) +AC_ARG_WITH(gnutls, +[ --without-gnutls disable support for gnutls],,) +AC_ARG_WITH(client-tls, +[ --without-client-tls disable support for gnutls in libvncclient],,) + +if test "x$with_gnutls" != "xno"; then + PKG_CHECK_MODULES(GNUTLS, gnutls >= 2.4.0, , with_client_tls=no) + CFLAGS="$CFLAGS $GNUTLS_CFLAGS" + LIBS="$LIBS $GNUTLS_LIBS" + if test "x$with_client_tls" != "xno"; then + AC_DEFINE(WITH_CLIENT_TLS) + fi +fi + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([arpa/inet.h fcntl.h netdb.h netinet/in.h stdlib.h string.h sys/socket.h sys/time.h sys/timeb.h syslog.h unistd.h]) + +# x11vnc only: +if test "$build_x11vnc" = "yes"; then + AC_CHECK_HEADERS([pwd.h sys/wait.h utmpx.h termios.h sys/ioctl.h sys/stropts.h]) +fi + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_C_BIGENDIAN +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_HEADER_SYS_WAIT +AC_TYPE_SOCKLEN_T +if test ! -d ./rfb; then + echo "creating subdir ./rfb for rfbint.h" + mkdir ./rfb +fi +AC_CREATE_STDINT_H(rfb/rfbint.h) +AC_CACHE_CHECK([for in_addr_t], + vnc_cv_inaddrt, [ + AC_TRY_COMPILE([#include +#include ], + [in_addr_t foo; return 0;], + [inaddrt=yes], + [inaddrt=no]), + ]) +AH_TEMPLATE(NEED_INADDR_T, [Need a typedef for in_addr_t]) +if test $inaddrt = no ; then + AC_DEFINE(NEED_INADDR_T) +fi + +# Checks for library functions. +AC_FUNC_MEMCMP +AC_FUNC_STAT +AC_FUNC_STRFTIME +AC_FUNC_VPRINTF +AC_FUNC_FORK +AC_CHECK_LIB(nsl,gethostbyname) +AC_CHECK_LIB(socket,socket) + +uname_s=`(uname -s) 2>/dev/null` +if test "x$uname_s" = "xHP-UX"; then + # need -lsec for getspnam() + LDFLAGS="$LDFLAGS -lsec" +fi + +AC_CHECK_FUNCS([ftime gethostbyname gethostname gettimeofday inet_ntoa memmove memset mmap mkfifo select socket strchr strcspn strdup strerror strstr]) +# x11vnc only: +if test "$build_x11vnc" = "yes"; then + AC_CHECK_FUNCS([setsid setpgrp getpwuid getpwnam getspnam getuid geteuid setuid setgid seteuid setegid initgroups waitpid setutxent grantpt shmat]) +fi + +# check, if shmget is in cygipc.a +AC_CHECK_LIB(cygipc,shmget) +AM_CONDITIONAL(CYGIPC, test "$HAVE_CYGIPC" = "true") + +# Check if /dev/vcsa1 exists, if so, define LINUX +AM_CONDITIONAL(LINUX, test -c /dev/vcsa1) + +# Check for OS X specific header +AC_CHECK_HEADER(ApplicationServices/ApplicationServices.h, HAVE_OSX="true") +AM_CONDITIONAL(OSX, test "$HAVE_OSX" = "true") + +# On Solaris 2.7, write() returns ENOENT when it really means EAGAIN +AH_TEMPLATE(ENOENT_WORKAROUND, [work around when write() returns ENOENT but does not mean it]) +case `(uname -sr) 2>/dev/null` in + "SunOS 5.7") + AC_DEFINE(ENOENT_WORKAROUND) + ;; +esac + +# Check for rpm SOURCES path +printf "checking for rpm sources path... " +RPMSOURCEDIR="NOT-FOUND" +for directory in packages OpenLinux redhat RedHat rpm RPM "" ; do + if test -d /usr/src/${directory}/SOURCES; then + RPMSOURCEDIR="/usr/src/${directory}/SOURCES/" + fi +done +echo "$RPMSOURCEDIR" +AM_CONDITIONAL(HAVE_RPM, test "$RPMSOURCEDIR" != "NOT-FOUND") +AM_CONDITIONAL(WITH_X11VNC, test "$build_x11vnc" = "yes") +AC_SUBST(RPMSOURCEDIR) + +AC_CONFIG_FILES([Makefile + libvncserver/Makefile + contrib/Makefile + examples/Makefile + vncterm/Makefile + classes/Makefile + classes/ssl/Makefile + libvncclient/Makefile + client_examples/Makefile + test/Makefile + libvncserver-config + LibVNCServer.spec]) +# +# x11vnc only: +# +if test "$build_x11vnc" = "yes"; then + # + # NOTE: if you are using the LibVNCServer-X.Y.Z.tar.gz source + # tarball and nevertheless want to run autoconf (i.e. aclocal, + # autoheader, automake, autoconf) AGAIN (perhaps you have a + # special target system, e.g. embedded) then you will need to + # comment out the following 'AC_CONFIG_FILES' line to avoid + # automake error messages like: + # + # configure.ac:690: required file `x11vnc/Makefile.in' not found + # + AC_CONFIG_FILES([x11vnc/Makefile x11vnc/misc/Makefile x11vnc/misc/turbovnc/Makefile]) +fi + +AC_CONFIG_COMMANDS([chmod-libvncserver-config],[chmod a+x libvncserver-config]) +AC_OUTPUT +chmod a+x ./libvncserver-config + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl b/droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl new file mode 100755 index 0000000..9196649 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/consolefont2c.pl @@ -0,0 +1,38 @@ +#!/usr/bin/perl + +# convert a linux console font (8x16 format) to a font definition +# suitable for processing with LibVNCServer + +#if($#ARGV == 0) { exit; } + +foreach $i (@ARGV) { + $fontname = $i; + $fontname =~ s/\.fnt$//; + $fontname =~ s/^.*\///g; + $fontname =~ y/+/_/; + + print STDERR "$i -> $fontname\n"; + + open IN, "<$i"; + print STDERR read(IN,$x,4096); + close(IN); + + open OUT, ">$fontname.h"; + print OUT "unsigned char ".$fontname."FontData[4096+1]={"; + for($i=0;$i<4096;$i++) { + if(($i%16)==0) { + print OUT "\n"; + } + printf OUT "0x%02x,", ord(substr($x,$i)); + } + + print OUT "\n};\nint ".$fontname."FontMetaData[256*5+1]={\n"; + for($i=0;$i<256;$i++) { + print OUT ($i*16).",8,16,0,0,"; + } + + print OUT "};\nrfbFontData ".$fontname."Font = { ".$fontname."FontData, " + .$fontname."FontMetaData };\n"; + + close OUT; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore new file mode 100755 index 0000000..4bb318a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/contrib/.cvsignore @@ -0,0 +1,6 @@ +Makefile +Makefile.in +x11vnc +zippy +.deps + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am new file mode 100755 index 0000000..637fea7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/contrib/Makefile.am @@ -0,0 +1,7 @@ +INCLUDES = -I$(top_srcdir) +LDADD = ../libvncserver/libvncserver.la @WSOCKLIB@ + +noinst_PROGRAMS=zippy + +zippy_SOURCES=zippy.c + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c b/droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c new file mode 100755 index 0000000..d8a90d7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/contrib/zippy.c @@ -0,0 +1,179 @@ +#include +#include +#include +#include +#include + +static int maxx=400, maxy=400, bpp=4; +/* odd maxx doesn't work (vncviewer bug) */ + +/* Here we create a structure so that every client has it's own pointer */ + +/* turns the framebuffer black */ +void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2); +/* displays a red bar, a green bar, and a blue bar */ +void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2); +void linecount (char* frame_buffer); +/* handles mouse events */ +void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl); +/* handles keyboard events */ +void on_key_press (rfbBool down,rfbKeySym key,rfbClientPtr cl); + +int main (int argc, char **argv) +{ + rfbScreenInfoPtr server; + + if(!rfbProcessSizeArguments(&maxx,&maxy,&bpp,&argc,argv)) + return 1; + + server = rfbGetScreen (&argc, argv, maxx, maxy, 8, 3, bpp); + server->desktopName = "Zippy das wundersquirrel\'s VNC server"; + server->frameBuffer = (char*)malloc(maxx*maxy*bpp); + server->alwaysShared = TRUE; + server->kbdAddEvent = on_key_press; + server->ptrAddEvent = on_mouse_event; + + rfbInitServer (server); + + blank_framebuffer(server->frameBuffer, 0, 0, maxx, maxy); + rfbRunEventLoop (server, -1, FALSE); + free(server->frameBuffer); + rfbScreenCleanup (server); + return 0; +} + +void blank_framebuffer(char* frame_buffer, int x1, int y1, int x2, int y2) +{ + int i; + for (i=0; i < maxx * maxy * bpp; i++) frame_buffer[i]=(char) 0; +} + +void draw_primary_colors (char* frame_buffer, int x1, int y1, int x2, int y2) +{ + int i, j, current_pixel; + for (i=y1; i < y2; i++){ + for (j=x1; j < x2; j++) { + current_pixel = (i*x2 + j) * bpp; + if (i < y2 ) { + frame_buffer[current_pixel+0] = (char) 128; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 0; + } + if (i < y2/3*2) { + frame_buffer[current_pixel+0] = (char) 0; + frame_buffer[current_pixel+1] = (char) 128; + frame_buffer[current_pixel+2] = (char) 0; + } + if (i < y2/3) { + frame_buffer[current_pixel+0] = (char) 0; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 128; + } + } + } + } + +/* Dscho's versions (slower, but works for bpp != 3 or 4) */ +static void draw_primary_colours_generic(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2) +{ + rfbPixelFormat f=s->serverFormat; + int i,j; + for(j=y1;jserverFormat; + int i,j,y3=(y1*2+y2)/3,y4=(y1+y2*2)/3; + /* draw first pixel */ + rfbDrawPixel(s,x1,y1,f.redMax<frameBuffer+(x)*bpp+(y)*s->paddedWidthInBytes + memcpy(ADDR(i,j+y1),ADDR(x1,y1),bpp); + memcpy(ADDR(i,j+y3),ADDR(x1,y3),bpp); + memcpy(ADDR(i,j+y4),ADDR(x1,y4),bpp); + } +} + +static void draw_primary_colours_generic_ultrafast(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2) +{ + rfbPixelFormat f=s->serverFormat; + int y3=(y1*2+y2)/3,y4=(y1+y2*2)/3; + /* fill rectangles */ + rfbFillRect(s,x1,y1,x2,y3,f.redMax<maxy-20; i-=4) + for (j=0; j<4; j++) for (k=0; k < maxx; k++) { + current_pixel = (i*j*maxx + k) * bpp; + if (i%2 == 0) { + frame_buffer[current_pixel+0] = (char) 0; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 128; + } + + if (i%2 == 1) { + frame_buffer[current_pixel+0] = (char) 128; + frame_buffer[current_pixel+1] = (char) 0; + frame_buffer[current_pixel+2] = (char) 0; + } + } + +} + + +void on_key_press (rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if (down) /* or else the action occurs on both the press and depress */ + switch (key) { + + case XK_b: + case XK_B: + blank_framebuffer(cl->screen->frameBuffer, 0, 0, maxx, maxy); + rfbDrawString(cl->screen,&default8x16Font,20,maxy-20,"Hello, World!",0xffffff); + rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy); + rfbLog("Framebuffer blanked\n"); + break; + case XK_p: + case XK_P: + /* draw_primary_colors (cl->screen->frameBuffer, 0, 0, maxx, maxy); */ + draw_primary_colours_generic_ultrafast (cl->screen, 0, 0, maxx, maxy); + rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy); + rfbLog("Primary colors displayed\n"); + break; + case XK_Q: + case XK_q: + rfbLog("Exiting now\n"); + exit(0); + case XK_C: + case XK_c: + rfbDrawString(cl->screen,&default8x16Font,20,100,"Hello, World!",0xffffff); + rfbMarkRectAsModified(cl->screen,0, 0,maxx,maxy); + break; + default: + rfbLog("The %c key was pressed\n", (char) key); + } +} + + +void on_mouse_event (int buttonMask,int x,int y,rfbClientPtr cl) +{ + printf("buttonMask: %i\n" + "x: %i\n" "y: %i\n", buttonMask, x, y); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously b/droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously new file mode 100755 index 0000000..bbe3c77 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/cvs_update_anonymously @@ -0,0 +1,13 @@ +#!/bin/bash + +case "$1" in +#cvs --help-commands 2>&1 | sed "s/[ ][ ]*/ /g" | cut -d " " -f 2 +add|admin|annotate|checkout|commit|diff|edit|editors|export|history|import|\ +init|log|login|logout|pserver|rdiff|release|remove|rtag|server|status|\ +tag|unedit|update|watch|watchers) + cmd="$1"; shift;; +*) cmd=update;; +esac + +cvs -z3 -d :pserver:anonymous@cvs.libvncserver.sf.net:/cvsroot/libvncserver $cmd "$@" + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore new file mode 100755 index 0000000..88ce9f4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/.cvsignore @@ -0,0 +1,18 @@ +Makefile +*test +example +fontsel +pnmshow +pnmshow24 +storepasswd +vncev +Makefile.in +.deps +simple +simple15 +colourmaptest +regiontest +mac +filetransfer +backchannel +rotate diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c new file mode 100755 index 0000000..f6c4315 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/1instance.c @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include +#include +#include + +typedef struct { + char* filename; /* this file is the pipe (set by user) */ + char is_server; /* this is set by open_control_file */ + int fd; /* this is set by open_control_file */ +} single_instance_struct; + +/* returns fd, is_server is set to -1 if server, 0 if client */ +int open_control_file(single_instance_struct* str) +{ + struct stat buf; + + if(stat(str->filename,&buf)) { + mkfifo(str->filename,128|256); + str->is_server=-1; + str->fd=open(str->filename,O_NONBLOCK|O_RDONLY); + } else { + str->fd=open(str->filename,O_NONBLOCK|O_WRONLY); + if(errno==ENXIO) { + str->is_server=-1; + str->fd=open(str->filename,O_NONBLOCK|O_RDONLY); + } else + str->is_server=0; + } + + return(str->fd); +} + +void delete_control_file(single_instance_struct* str) +{ + remove(str->filename); +} + +void close_control_file(single_instance_struct* str) +{ + close(str->fd); +} + +typedef void (*event_dispatcher)(char* message); + +int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs) +{ + struct timeval tv; + fd_set fdset; + int num_fds; + + FD_ZERO(&fdset); + FD_SET(str->fd,&fdset); + tv.tv_sec=0; + tv.tv_usec=usecs; + + num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv); + if(num_fds) { + int reallen; + + reallen=read(str->fd,buffer,len); + if(reallen==0) { + close(str->fd); + str->fd=open(str->filename,O_NONBLOCK|O_RDONLY); + num_fds--; + } + buffer[reallen]=0; +#ifdef DEBUG_1INSTANCE + if(reallen!=0) rfbLog("message received: %s.\n",buffer); +#endif + } + + return(num_fds); +} + +int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs) +{ + char buffer[1024]; + int num_fds; + + if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0]) + dispatcher(buffer); + + return(num_fds); +} + +int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher) +{ + open_control_file(str); + if(str->is_server) { + while(1) + dispatch_event(str,dispatcher,50); + } + + return(str->fd); +} + +void send_message(single_instance_struct* str,char* message) +{ +#ifdef DEBUG_1INSTANCE + int i= +#endif + write(str->fd,message,strlen(message)); +#ifdef DEBUG_1INSTANCE + rfbLog("send: %s => %d(%d)\n",message,i,strlen(message)); +#endif +} + +#ifdef DEBUG_MAIN + +#include +#include + +single_instance_struct str1 = { "/tmp/1instance" }; + +void my_dispatcher(char* message) +{ +#ifdef DEBUG_1INSTANCE + rfbLog("Message arrived: %s.\n",message); +#endif + if(!strcmp(message,"quit")) { + delete_control_file(str1); + exit(0); + } +} + +int main(int argc,char** argv) +{ + int i; + + loop_if_server(str1,my_dispatcher); + + for(i=1;i + +/* + * This is a simple example demonstrating a protocol extension. + * + * The "back channel" permits sending commands between client and server. + * It works by sending plain text messages. + * + * As suggested in the RFB protocol, the back channel is enabled by asking + * for a "pseudo encoding", and enabling the back channel on the client side + * as soon as it gets a back channel message from the server. + * + * This implements the server part. + * + * Note: If you design your own extension and want it to be useful for others, + * too, you should make sure that + * + * - your server as well as your client can speak to other clients and + * servers respectively (i.e. they are nice if they are talking to a + * program which does not know about your extension). + * + * - if the machine is little endian, all 16-bit and 32-bit integers are + * swapped before they are sent and after they are received. + * + */ + +#define rfbBackChannel 155 + +typedef struct backChannelMsg { + uint8_t type; + uint8_t pad1; + uint16_t pad2; + uint32_t size; +} backChannelMsg; + +rfbBool enableBackChannel(rfbClientPtr cl, void** data, int encoding) +{ + if(encoding == rfbBackChannel) { + backChannelMsg msg; + const char* text="Server acknowledges back channel encoding\n"; + uint32_t length = strlen(text)+1; + int n; + + rfbLog("Enabling the back channel\n"); + + msg.type = rfbBackChannel; + msg.size = Swap32IfLE(length); + if((n = rfbWriteExact(cl, (char*)&msg, sizeof(msg))) <= 0 || + (n = rfbWriteExact(cl, text, length)) <= 0) { + rfbLogPerror("enableBackChannel: write"); + } + return TRUE; + } + return FALSE; +} + +static rfbBool handleBackChannelMessage(rfbClientPtr cl, void* data, + const rfbClientToServerMsg* message) +{ + if(message->type == rfbBackChannel) { + backChannelMsg msg; + char* text; + int n; + if((n = rfbReadExact(cl, ((char*)&msg)+1, sizeof(backChannelMsg)-1)) <= 0) { + if(n != 0) + rfbLogPerror("handleBackChannelMessage: read"); + rfbCloseClient(cl); + return TRUE; + } + msg.size = Swap32IfLE(msg.size); + if((text = malloc(msg.size)) == NULL) { + rfbErr("Could not allocate %d bytes\n", msg.size); + return TRUE; + } + if((n = rfbReadExact(cl, text, msg.size)) <= 0) { + if(n != 0) + rfbLogPerror("handleBackChannelMessage: read"); + rfbCloseClient(cl); + return TRUE; + } + rfbLog("got message:\n%s\n", text); + free(text); + return TRUE; + } + return FALSE; +} + +static int backChannelEncodings[] = {rfbBackChannel, 0}; + +static rfbProtocolExtension backChannelExtension = { + NULL, /* newClient */ + NULL, /* init */ + backChannelEncodings, /* pseudoEncodings */ + enableBackChannel, /* enablePseudoEncoding */ + handleBackChannelMessage, /* handleMessage */ + NULL, /* close */ + NULL, /* usage */ + NULL, /* processArgument */ + NULL /* next extension */ +}; + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr server; + + rfbRegisterProtocolExtension(&backChannelExtension); + + server=rfbGetScreen(&argc,argv,400,300,8,3,4); + server->frameBuffer=(char*)malloc(400*300*4); + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c new file mode 100755 index 0000000..f0e411c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/blooptest.c @@ -0,0 +1,2 @@ +#define BACKGROUND_LOOP_TEST +#include "example.c" diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c new file mode 100755 index 0000000..23cb91a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/camera.c @@ -0,0 +1,152 @@ + +/* + * Question: I need to display a live camera image via VNC. Until now I just + * grab an image, set the rect to modified and do a 0.1 s sleep to give the + * system time to transfer the data. + * This is obviously a solution which doesn't scale very well to different + * connection speeds/cpu horsepowers, so I wonder if there is a way for the + * server application to determine if the updates have been sent. This would + * cause the live image update rate to always be the maximum the connection + * supports while avoiding excessive loads. + * + * Thanks in advance, + * + * + * Christian Daschill + * + * + * Answer: Originally, I thought about using seperate threads and using a + * mutex to determine when the frame buffer was being accessed by any client + * so we could determine a safe time to take a picture. The probem is, we + * are lock-stepping everything with framebuffer access. Why not be a + * single-thread application and in-between rfbProcessEvents perform a + * camera snapshot. And this is what I do here. It guarantees that the + * clients have been serviced before taking another picture. + * + * The downside to this approach is that the more clients you have, there is + * less time available for you to service the camera equating to reduced + * frame rate. (or, your clients are on really slow links). Increasing your + * systems ethernet transmit queues may help improve the overall performance + * as the libvncserver should not stall on transmitting to any single + * client. + * + * Another solution would be to provide a seperate framebuffer for each + * client and use mutexes to determine if any particular client is ready for + * a snapshot. This way, your not updating a framebuffer for a slow client + * while it is being transferred. + */ + +#include +#include +#include +#include + + +#define WIDTH 640 +#define HEIGHT 480 +#define BPP 4 + +/* 15 frames per second (if we can) */ +#define PICTURE_TIMEOUT (1.0/15.0) + + +/* + * throttle camera updates +*/ +int TimeToTakePicture() { + static struct timeval now={0,0}, then={0,0}; + double elapsed, dnow, dthen; + + gettimeofday(&now,NULL); + + dnow = now.tv_sec + (now.tv_usec /1000000.0); + dthen = then.tv_sec + (then.tv_usec/1000000.0); + elapsed = dnow - dthen; + + if (elapsed > PICTURE_TIMEOUT) + memcpy((char *)&then, (char *)&now, sizeof(struct timeval)); + return elapsed > PICTURE_TIMEOUT; +} + + + +/* + * simulate grabbing a picture from some device + */ +int TakePicture(unsigned char *buffer) +{ + static int last_line=0, fps=0, fcount=0; + int line=0; + int i,j; + struct timeval now; + + /* + * simulate grabbing data from a device by updating the entire framebuffer + */ + + for(j=0;jHEIGHT) line=HEIGHT-1; + memset(&buffer[(WIDTH * BPP) * line], 0, (WIDTH * BPP)); + + /* frames per second (informational only) */ + fcount++; + if (last_line > line) { + fps = fcount; + fcount = 0; + } + last_line = line; + fprintf(stderr,"%03d/%03d Picture (%03d fps)\r", line, HEIGHT, fps); + + /* success! We have a new picture! */ + return (1==1); +} + + + + +/* + * Single-threaded application that interleaves client servicing with taking + * pictures from the camera. This way, we do not update the framebuffer + * while an encoding is working on it too (banding, and image artifacts). + */ +int main(int argc,char** argv) +{ + long usec; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,WIDTH,HEIGHT,8,3,BPP); + server->desktopName = "Live Video Feed Example"; + server->frameBuffer=(char*)malloc(WIDTH*HEIGHT*BPP); + server->alwaysShared=(1==1); + + /* Initialize the server */ + rfbInitServer(server); + + /* Loop, processing clients and taking pictures */ + while (rfbIsActive(server)) { + if (TimeToTakePicture()) + if (TakePicture((unsigned char *)server->frameBuffer)) + rfbMarkRectAsModified(server,0,0,WIDTH,HEIGHT); + + usec = server->deferUpdateTime*1000; + rfbProcessEvents(server,usec); + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c new file mode 100755 index 0000000..e403164 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/colourmaptest.c @@ -0,0 +1,32 @@ +#include + + +int main(int argc,char** argv) +{ + int i; + uint8_t bytes[256*3]; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,256,256,8,1,1); + + server->serverFormat.trueColour=FALSE; + server->colourMap.count=256; + server->colourMap.is16=FALSE; + for(i=0;i<256;i++) { + bytes[i*3+0]=255-i; /* red */ + bytes[i*3+1]=0; /* green */ + bytes[i*3+2]=i; /* blue */ + } + bytes[128*3+0]=0xff; + bytes[128*3+1]=0; + bytes[128*3+2]=0; + server->colourMap.data.bytes=bytes; + + server->frameBuffer=(char*)malloc(256*256); + for(i=0;i<256*256;i++) + server->frameBuffer[i]=(i/256); + + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/example.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.c new file mode 100755 index 0000000..871ab0c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.c @@ -0,0 +1,336 @@ +/* + * + * This is an example of how to use libvncserver. + * + * libvncserver example + * Copyright (C) 2001 Johannes E. Schindelin + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef WIN32 +#define sleep Sleep +#else +#include +#endif + +#ifdef __IRIX__ +#include +#endif + +#include +#include + +static const int bpp=4; +static int maxx=800, maxy=600; +/* TODO: odd maxx doesn't work (vncviewer bug) */ + +/* This initializes a nice (?) background */ + +static void initBuffer(unsigned char* buffer) +{ + int i,j; + for(j=0;jclientData); +} + +static enum rfbNewClientAction newclient(rfbClientPtr cl) +{ + cl->clientData = (void*)calloc(sizeof(ClientData),1); + cl->clientGoneHook = clientgone; + return RFB_CLIENT_ACCEPT; +} + +/* switch to new framebuffer contents */ + +static void newframebuffer(rfbScreenInfoPtr screen, int width, int height) +{ + unsigned char *oldfb, *newfb; + + maxx = width; + maxy = height; + oldfb = (unsigned char*)screen->frameBuffer; + newfb = (unsigned char*)malloc(maxx * maxy * bpp); + initBuffer(newfb); + rfbNewFramebuffer(screen, (char*)newfb, maxx, maxy, 8, 3, bpp); + free(oldfb); + + /*** FIXME: Re-install cursor. ***/ +} + +/* aux function to draw a line */ + +static void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2) +{ + int i,j; + i=x1-x2; j=y1-y2; + if(i==0 && j==0) { + for(i=0;iy2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; } + for(j=y1;j<=y2;j++) + for(i=0;ix2) { i=y2; y2=y1; y1=i; i=x2; x2=x1; x1=i; } + for(i=x1;i<=x2;i++) + for(j=0;jclientData; + + if(x>=0 && y>=0 && xoldButton==buttonMask) { /* draw a line */ + drawline((unsigned char*)cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp, + x,y,cd->oldx,cd->oldy); + x1=x; y1=y; + if(x1>cd->oldx) x1++; else cd->oldx++; + if(y1>cd->oldy) y1++; else cd->oldy++; + rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy); + } else { /* draw a point (diameter depends on button) */ + int w=cl->screen->paddedWidthInBytes; + x1=x-buttonMask; if(x1<0) x1=0; + x2=x+buttonMask; if(x2>maxx) x2=maxx; + y1=y-buttonMask; if(y1<0) y1=0; + y2=y+buttonMask; if(y2>maxy) y2=maxy; + + for(i=x1*bpp;iscreen->frameBuffer[j*w+i]=(char)0xff; + rfbMarkRectAsModified(cl->screen,x1,y1,x2,y2); + } + + /* we could get a selection like that: + rfbGotXCutText(cl->screen,"Hallo",5); + */ + } else + cd->oldButton=0; + + cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask; + } + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +} + +/* aux function to draw a character to x, y */ + +#include "radon.h" + +/* Here the key events are handled */ + +static void dokey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down) { + if(key==XK_Escape) + rfbCloseClient(cl); + else if(key==XK_F12) + /* close down server, disconnecting clients */ + rfbShutdownServer(cl->screen,TRUE); + else if(key==XK_F11) + /* close down server, but wait for all clients to disconnect */ + rfbShutdownServer(cl->screen,FALSE); + else if(key==XK_Page_Up) { + initBuffer((unsigned char*)cl->screen->frameBuffer); + rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy); + } else if (key == XK_Up) { + if (maxx < 1024) { + if (maxx < 800) { + newframebuffer(cl->screen, 800, 600); + } else { + newframebuffer(cl->screen, 1024, 768); + } + } + } else if(key==XK_Down) { + if (maxx > 640) { + if (maxx > 800) { + newframebuffer(cl->screen, 800, 600); + } else { + newframebuffer(cl->screen, 640, 480); + } + } + } else if(key>=' ' && key<0x100) { + ClientData* cd=cl->clientData; + int x1=cd->oldx,y1=cd->oldy,x2,y2; + cd->oldx+=rfbDrawCharWithClip(cl->screen,&radonFont,cd->oldx,cd->oldy,(char)key,0,0,cl->screen->width,cl->screen->height,0x00ffffff,0x00ffffff); + rfbFontBBox(&radonFont,(char)key,&x1,&y1,&x2,&y2); + rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1); + } + } +} + +/* Example for an XCursor (foreground/background only) */ + +#ifdef JUST_AN_EXAMPLE + +static int exampleXCursorWidth=9,exampleXCursorHeight=7; +static char exampleXCursor[]= + " " + " xx xx " + " xx xx " + " xxx " + " xx xx " + " xx xx " + " "; + +#endif + +/* Example for a rich cursor (full-colour) */ + +static void MakeRichCursor(rfbScreenInfoPtr rfbScreen) +{ + int i,j,w=32,h=32; + rfbCursorPtr c = rfbScreen->cursor; + char bitmap[]= + " " + " xxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxx xxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxx xxxxxxxxx xxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxx xxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxx xxxxxxxxxxxxxx " + " xxxxxxxxxx xxxxxxxxxxxx " + " xxxxxxxxx xxxxxxxxx " + " xxxxxxxxxx xxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxx " + " xxxx xxxxxxxxxxxxx " + " xx x xxxxxxxxxxx " + " xxx xxxxxxxxxxx " + " xxxx xxxxxxxxxxx " + " xxxxxx xxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxx " + " "; + c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); + c->xhot = 16; c->yhot = 24; + + c->richSource = (unsigned char*)malloc(w*h*bpp); + c->cleanupRichSource = TRUE; + for(j=0;jrichSource[j*w*bpp+i*bpp+0]=i*0xff/w; + c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h); + c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h; + c->richSource[j*w*bpp+i*bpp+3]=0; + } + } +} + +/* Initialization */ + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp); + rfbScreen->desktopName = "LibVNCServer Example"; + rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp); + rfbScreen->alwaysShared = TRUE; + rfbScreen->ptrAddEvent = doptr; + rfbScreen->kbdAddEvent = dokey; + rfbScreen->newClientHook = newclient; + rfbScreen->httpDir = "../classes"; + rfbScreen->httpEnableProxyConnect = TRUE; + + initBuffer((unsigned char*)rfbScreen->frameBuffer); + rfbDrawString(rfbScreen,&radonFont,20,100,"Hello, World!",0xffffff); + + /* This call creates a mask and then a cursor: */ + /* rfbScreen->defaultCursor = + rfbMakeXCursor(exampleCursorWidth,exampleCursorHeight,exampleCursor,0); + */ + + MakeRichCursor(rfbScreen); + + /* initialize the server */ + rfbInitServer(rfbScreen); + +#ifndef BACKGROUND_LOOP_TEST +#ifdef USE_OWN_LOOP + { + int i; + for(i=0;rfbIsActive(rfbScreen);i++) { + fprintf(stderr,"%d\r",i); + rfbProcessEvents(rfbScreen,100000); + } + } +#else + /* this is the blocking event loop, i.e. it never returns */ + /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */ + rfbRunEventLoop(rfbScreen,40000,FALSE); +#endif /* OWN LOOP */ +#else +#if !defined(LIBVNCSERVER_HAVE_LIBPTHREAD) +#error "I need pthreads for that." +#endif + + /* this is the non-blocking event loop; a background thread is started */ + rfbRunEventLoop(rfbScreen,-1,TRUE); + fprintf(stderr, "Running background loop...\n"); + /* now we could do some cool things like rendering in idle time */ + while(1) sleep(5); /* render(); */ +#endif /* BACKGROUND_LOOP */ + + free(rfbScreen->frameBuffer); + rfbScreenCleanup(rfbScreen); + + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp new file mode 100755 index 0000000..16788cb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/example.dsp @@ -0,0 +1,93 @@ +# Microsoft Developer Studio Project File - Name="example" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=example - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "example.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "example.mak" CFG="example - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "example - Win32 Release" (basierend auf "Win32 (x86) Console Application") +!MESSAGE "example - Win32 Debug" (basierend auf "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "example - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "zlib" /I "libjpeg" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib zlib.lib /nologo /subsystem:console /machine:I386 /nodefaultlib:"msvcrt.lib" + +!ELSEIF "$(CFG)" == "example - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "zlib" /I "libjpeg" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib zlib.lib /nologo /subsystem:console /debug /machine:I386 /nodefaultlib:"msvcrt.lib" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "example - Win32 Release" +# Name "example - Win32 Debug" +# Begin Group "Sources" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\example.c +# End Source File +# End Group +# End Target +# End Project diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c new file mode 100755 index 0000000..dacf73d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/filetransfer.c @@ -0,0 +1,11 @@ +#include + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4); + server->frameBuffer=(char*)malloc(400*300*4); + rfbRegisterTightVNCFileTransferExtension(); + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c new file mode 100755 index 0000000..85d2624 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/fontsel.c @@ -0,0 +1,73 @@ +#include + +#define FONTDIR "/usr/lib/kbd/consolefonts/" +#define DEFAULTFONT FONTDIR "default8x16" + +static char *fontlist[50]={ +"8x16alt", "b.fnt", "c.fnt", "default8x16", "m.fnt", "ml.fnt", "mod_d.fnt", +"mod_s.fnt", "mr.fnt", "mu.fnt", "r.fnt", "rl.fnt", "ro.fnt", "s.fnt", +"sc.fnt", "scrawl_s.fnt", "scrawl_w.fnt", "sd.fnt", "t.fnt", + NULL +}; + +static rfbScreenInfoPtr rfbScreen = NULL; +static rfbFontDataPtr curFont = NULL; +static void showFont(int index) +{ + char buffer[1024]; + + if(!rfbScreen) return; + + if(curFont) + rfbFreeFont(curFont); + + strcpy(buffer,FONTDIR); + strcat(buffer,fontlist[index]); + curFont = rfbLoadConsoleFont(buffer); + + rfbFillRect(rfbScreen,210,30-20,210+10*16,30-20+256*20/16,0xb77797); + if(curFont) { + int i,j; + for(j=0;j<256;j+=16) + for(i=0;i<16;i++) + rfbDrawCharWithClip(rfbScreen,curFont,210+10*i,30+j*20/16,j+i, + 0,0,640,480,0xffffff,0x000000); + } +} + +int main(int argc,char** argv) +{ + rfbFontDataPtr font; + rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,640,480,8,3,3); + int i,j; + + s->frameBuffer=(char*)malloc(640*480*3); + rfbInitServer(s); + + for(j=0;j<480;j++) + for(i=0;i<640;i++) { + s->frameBuffer[(j*640+i)*3+0]=j*256/480; + s->frameBuffer[(j*640+i)*3+1]=i*256/640; + s->frameBuffer[(j*640+i)*3+2]=(i+j)*256/(480+640); + } + + rfbScreen = s; + font=rfbLoadConsoleFont(DEFAULTFONT); + if(!font) { + rfbErr("Couldn't find %s\n",DEFAULTFONT); + exit(1); + } + + for(j=0;j<0 && rfbIsActive(s);j++) + rfbProcessEvents(s,900000); + + i = rfbSelectBox(s,font,fontlist,10,20,200,300,0xffdfdf,0x602040,2,showFont); + rfbLog("Selection: %d: %s\n",i,(i>=0)?fontlist[i]:"cancelled"); + + rfbFreeFont(font); + free(s->frameBuffer); + rfbScreenCleanup(s); + + return(0); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c new file mode 100755 index 0000000..2d335a4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/mac.c @@ -0,0 +1,551 @@ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * Cut in two parts by Johannes Schindelin (2001): libvncserver and OSXvnc. + * + * + * This file implements every system specific function for Mac OS X. + * + * It includes the keyboard functions: + * + void KbdAddEvent(down, keySym, cl) + rfbBool down; + rfbKeySym keySym; + rfbClientPtr cl; + void KbdReleaseAllKeys() + * + * the mouse functions: + * + void PtrAddEvent(buttonMask, x, y, cl) + int buttonMask; + int x; + int y; + rfbClientPtr cl; + * + */ + +#include +#include +#include +/* zlib doesn't like Byte already defined */ +#undef Byte +#undef TRUE +#undef rfbBool +#include +#include + +#include +#include +#include +#include +#include + +rfbBool rfbNoDimming = FALSE; +rfbBool rfbNoSleep = TRUE; + +static pthread_mutex_t dimming_mutex; +static unsigned long dim_time; +static unsigned long sleep_time; +static mach_port_t master_dev_port; +static io_connect_t power_mgt; +static rfbBool initialized = FALSE; +static rfbBool dim_time_saved = FALSE; +static rfbBool sleep_time_saved = FALSE; + +static int +saveDimSettings(void) +{ + if (IOPMGetAggressiveness(power_mgt, + kPMMinutesToDim, + &dim_time) != kIOReturnSuccess) + return -1; + + dim_time_saved = TRUE; + return 0; +} + +static int +restoreDimSettings(void) +{ + if (!dim_time_saved) + return -1; + + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToDim, + dim_time) != kIOReturnSuccess) + return -1; + + dim_time_saved = FALSE; + dim_time = 0; + return 0; +} + +static int +saveSleepSettings(void) +{ + if (IOPMGetAggressiveness(power_mgt, + kPMMinutesToSleep, + &sleep_time) != kIOReturnSuccess) + return -1; + + sleep_time_saved = TRUE; + return 0; +} + +static int +restoreSleepSettings(void) +{ + if (!sleep_time_saved) + return -1; + + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToSleep, + sleep_time) != kIOReturnSuccess) + return -1; + + sleep_time_saved = FALSE; + sleep_time = 0; + return 0; +} + + +int +rfbDimmingInit(void) +{ + pthread_mutex_init(&dimming_mutex, NULL); + + if (IOMasterPort(bootstrap_port, &master_dev_port) != kIOReturnSuccess) + return -1; + + if (!(power_mgt = IOPMFindPowerManagement(master_dev_port))) + return -1; + + if (rfbNoDimming) { + if (saveDimSettings() < 0) + return -1; + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToDim, 0) != kIOReturnSuccess) + return -1; + } + + if (rfbNoSleep) { + if (saveSleepSettings() < 0) + return -1; + if (IOPMSetAggressiveness(power_mgt, + kPMMinutesToSleep, 0) != kIOReturnSuccess) + return -1; + } + + initialized = TRUE; + return 0; +} + + +int +rfbUndim(void) +{ + int result = -1; + + pthread_mutex_lock(&dimming_mutex); + + if (!initialized) + goto DONE; + + if (!rfbNoDimming) { + if (saveDimSettings() < 0) + goto DONE; + if (IOPMSetAggressiveness(power_mgt, kPMMinutesToDim, 0) != kIOReturnSuccess) + goto DONE; + if (restoreDimSettings() < 0) + goto DONE; + } + + if (!rfbNoSleep) { + if (saveSleepSettings() < 0) + goto DONE; + if (IOPMSetAggressiveness(power_mgt, kPMMinutesToSleep, 0) != kIOReturnSuccess) + goto DONE; + if (restoreSleepSettings() < 0) + goto DONE; + } + + result = 0; + + DONE: + pthread_mutex_unlock(&dimming_mutex); + return result; +} + + +int +rfbDimmingShutdown(void) +{ + int result = -1; + + if (!initialized) + goto DONE; + + pthread_mutex_lock(&dimming_mutex); + if (dim_time_saved) + if (restoreDimSettings() < 0) + goto DONE; + if (sleep_time_saved) + if (restoreSleepSettings() < 0) + goto DONE; + + result = 0; + + DONE: + pthread_mutex_unlock(&dimming_mutex); + return result; +} + +rfbScreenInfoPtr rfbScreen; + +void rfbShutdown(rfbClientPtr cl); + +/* some variables to enable special behaviour */ +int startTime = -1, maxSecsToConnect = 0; +rfbBool disconnectAfterFirstClient = TRUE; + +/* Where do I get the "official" list of Mac key codes? + Ripped these out of a Mac II emulator called Basilisk II + that I found on the net. */ +static int keyTable[] = { + /* The alphabet */ + XK_A, 0, /* A */ + XK_B, 11, /* B */ + XK_C, 8, /* C */ + XK_D, 2, /* D */ + XK_E, 14, /* E */ + XK_F, 3, /* F */ + XK_G, 5, /* G */ + XK_H, 4, /* H */ + XK_I, 34, /* I */ + XK_J, 38, /* J */ + XK_K, 40, /* K */ + XK_L, 37, /* L */ + XK_M, 46, /* M */ + XK_N, 45, /* N */ + XK_O, 31, /* O */ + XK_P, 35, /* P */ + XK_Q, 12, /* Q */ + XK_R, 15, /* R */ + XK_S, 1, /* S */ + XK_T, 17, /* T */ + XK_U, 32, /* U */ + XK_V, 9, /* V */ + XK_W, 13, /* W */ + XK_X, 7, /* X */ + XK_Y, 16, /* Y */ + XK_Z, 6, /* Z */ + XK_a, 0, /* a */ + XK_b, 11, /* b */ + XK_c, 8, /* c */ + XK_d, 2, /* d */ + XK_e, 14, /* e */ + XK_f, 3, /* f */ + XK_g, 5, /* g */ + XK_h, 4, /* h */ + XK_i, 34, /* i */ + XK_j, 38, /* j */ + XK_k, 40, /* k */ + XK_l, 37, /* l */ + XK_m, 46, /* m */ + XK_n, 45, /* n */ + XK_o, 31, /* o */ + XK_p, 35, /* p */ + XK_q, 12, /* q */ + XK_r, 15, /* r */ + XK_s, 1, /* s */ + XK_t, 17, /* t */ + XK_u, 32, /* u */ + XK_v, 9, /* v */ + XK_w, 13, /* w */ + XK_x, 7, /* x */ + XK_y, 16, /* y */ + XK_z, 6, /* z */ + + /* Numbers */ + XK_0, 29, /* 0 */ + XK_1, 18, /* 1 */ + XK_2, 19, /* 2 */ + XK_3, 20, /* 3 */ + XK_4, 21, /* 4 */ + XK_5, 23, /* 5 */ + XK_6, 22, /* 6 */ + XK_7, 26, /* 7 */ + XK_8, 28, /* 8 */ + XK_9, 25, /* 9 */ + + /* Symbols */ + XK_exclam, 18, /* ! */ + XK_at, 19, /* @ */ + XK_numbersign, 20, /* # */ + XK_dollar, 21, /* $ */ + XK_percent, 23, /* % */ + XK_asciicircum, 22, /* ^ */ + XK_ampersand, 26, /* & */ + XK_asterisk, 28, /* * */ + XK_parenleft, 25, /* ( */ + XK_parenright, 29, /* ) */ + XK_minus, 27, /* - */ + XK_underscore, 27, /* _ */ + XK_equal, 24, /* = */ + XK_plus, 24, /* + */ + XK_grave, 10, /* ` */ /* XXX ? */ + XK_asciitilde, 10, /* ~ */ + XK_bracketleft, 33, /* [ */ + XK_braceleft, 33, /* { */ + XK_bracketright, 30, /* ] */ + XK_braceright, 30, /* } */ + XK_semicolon, 41, /* ; */ + XK_colon, 41, /* : */ + XK_apostrophe, 39, /* ' */ + XK_quotedbl, 39, /* " */ + XK_comma, 43, /* , */ + XK_less, 43, /* < */ + XK_period, 47, /* . */ + XK_greater, 47, /* > */ + XK_slash, 44, /* / */ + XK_question, 44, /* ? */ + XK_backslash, 42, /* \ */ + XK_bar, 42, /* | */ + + /* "Special" keys */ + XK_space, 49, /* Space */ + XK_Return, 36, /* Return */ + XK_Delete, 117, /* Delete */ + XK_Tab, 48, /* Tab */ + XK_Escape, 53, /* Esc */ + XK_Caps_Lock, 57, /* Caps Lock */ + XK_Num_Lock, 71, /* Num Lock */ + XK_Scroll_Lock, 107, /* Scroll Lock */ + XK_Pause, 113, /* Pause */ + XK_BackSpace, 51, /* Backspace */ + XK_Insert, 114, /* Insert */ + + /* Cursor movement */ + XK_Up, 126, /* Cursor Up */ + XK_Down, 125, /* Cursor Down */ + XK_Left, 123, /* Cursor Left */ + XK_Right, 124, /* Cursor Right */ + XK_Page_Up, 116, /* Page Up */ + XK_Page_Down, 121, /* Page Down */ + XK_Home, 115, /* Home */ + XK_End, 119, /* End */ + + /* Numeric keypad */ + XK_KP_0, 82, /* KP 0 */ + XK_KP_1, 83, /* KP 1 */ + XK_KP_2, 84, /* KP 2 */ + XK_KP_3, 85, /* KP 3 */ + XK_KP_4, 86, /* KP 4 */ + XK_KP_5, 87, /* KP 5 */ + XK_KP_6, 88, /* KP 6 */ + XK_KP_7, 89, /* KP 7 */ + XK_KP_8, 91, /* KP 8 */ + XK_KP_9, 92, /* KP 9 */ + XK_KP_Enter, 76, /* KP Enter */ + XK_KP_Decimal, 65, /* KP . */ + XK_KP_Add, 69, /* KP + */ + XK_KP_Subtract, 78, /* KP - */ + XK_KP_Multiply, 67, /* KP * */ + XK_KP_Divide, 75, /* KP / */ + + /* Function keys */ + XK_F1, 122, /* F1 */ + XK_F2, 120, /* F2 */ + XK_F3, 99, /* F3 */ + XK_F4, 118, /* F4 */ + XK_F5, 96, /* F5 */ + XK_F6, 97, /* F6 */ + XK_F7, 98, /* F7 */ + XK_F8, 100, /* F8 */ + XK_F9, 101, /* F9 */ + XK_F10, 109, /* F10 */ + XK_F11, 103, /* F11 */ + XK_F12, 111, /* F12 */ + + /* Modifier keys */ + XK_Shift_L, 56, /* Shift Left */ + XK_Shift_R, 56, /* Shift Right */ + XK_Control_L, 59, /* Ctrl Left */ + XK_Control_R, 59, /* Ctrl Right */ + XK_Meta_L, 58, /* Logo Left (-> Option) */ + XK_Meta_R, 58, /* Logo Right (-> Option) */ + XK_Alt_L, 55, /* Alt Left (-> Command) */ + XK_Alt_R, 55, /* Alt Right (-> Command) */ + + /* Weirdness I can't figure out */ +#if 0 + XK_3270_PrintScreen, 105, /* PrintScrn */ + ??? 94, 50, /* International */ + XK_Menu, 50, /* Menu (-> International) */ +#endif +}; + +void +KbdAddEvent(rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl) +{ + int i; + CGKeyCode keyCode = -1; + int found = 0; + + if(((int)cl->clientData)==-1) return; /* viewOnly */ + + rfbUndim(); + + for (i = 0; i < (sizeof(keyTable) / sizeof(int)); i += 2) { + if (keyTable[i] == keySym) { + keyCode = keyTable[i+1]; + found = 1; + break; + } + } + + if (!found) { + rfbErr("warning: couldn't figure out keycode for X keysym %d (0x%x)\n", + (int)keySym, (int)keySym); + } else { + /* Hopefully I can get away with not specifying a CGCharCode. + (Why would you need both?) */ + CGPostKeyboardEvent((CGCharCode)0, keyCode, down); + } +} + +void +PtrAddEvent(buttonMask, x, y, cl) + int buttonMask; + int x; + int y; + rfbClientPtr cl; +{ + CGPoint position; + + if(((int)cl->clientData)==-1) return; /* viewOnly */ + + rfbUndim(); + + position.x = x; + position.y = y; + + CGPostMouseEvent(position, TRUE, 8, + (buttonMask & (1 << 0)) ? TRUE : FALSE, + (buttonMask & (1 << 1)) ? TRUE : FALSE, + (buttonMask & (1 << 2)) ? TRUE : FALSE, + (buttonMask & (1 << 3)) ? TRUE : FALSE, + (buttonMask & (1 << 4)) ? TRUE : FALSE, + (buttonMask & (1 << 5)) ? TRUE : FALSE, + (buttonMask & (1 << 6)) ? TRUE : FALSE, + (buttonMask & (1 << 7)) ? TRUE : FALSE); +} + +rfbBool viewOnly = FALSE, sharedMode = FALSE; + +void +ScreenInit(int argc, char**argv) +{ + int bitsPerSample=CGDisplayBitsPerSample(kCGDirectMainDisplay); + rfbScreen = rfbGetScreen(&argc,argv, + CGDisplayPixelsWide(kCGDirectMainDisplay), + CGDisplayPixelsHigh(kCGDirectMainDisplay), + bitsPerSample, + CGDisplaySamplesPerPixel(kCGDirectMainDisplay),4); + rfbScreen->serverFormat.redShift = bitsPerSample*2; + rfbScreen->serverFormat.greenShift = bitsPerSample*1; + rfbScreen->serverFormat.blueShift = 0; + + gethostname(rfbScreen->thisHost, 255); + rfbScreen->paddedWidthInBytes = CGDisplayBytesPerRow(kCGDirectMainDisplay); + rfbScreen->frameBuffer = + (char *)CGDisplayBaseAddress(kCGDirectMainDisplay); + + /* we cannot write to the frame buffer */ + rfbScreen->cursor = NULL; + + rfbScreen->ptrAddEvent = PtrAddEvent; + rfbScreen->kbdAddEvent = KbdAddEvent; + + if(sharedMode) { + rfbScreen->alwaysShared = TRUE; + } + + rfbInitServer(rfbScreen); +} + +static void +refreshCallback(CGRectCount count, const CGRect *rectArray, void *ignore) +{ + int i; + + if(startTime>0 && time(0)>startTime+maxSecsToConnect) + rfbShutdown(0); + + for (i = 0; i < count; i++) + rfbMarkRectAsModified(rfbScreen, + rectArray[i].origin.x,rectArray[i].origin.y, + rectArray[i].origin.x + rectArray[i].size.width, + rectArray[i].origin.y + rectArray[i].size.height); +} + +void clientGone(rfbClientPtr cl) +{ + rfbShutdown(cl); +} + +enum rfbNewClientAction newClient(rfbClientPtr cl) +{ + if(startTime>0 && time(0)>startTime+maxSecsToConnect) + rfbShutdown(cl); + + if(disconnectAfterFirstClient) + cl->clientGoneHook = clientGone; + + cl->clientData=(void*)((viewOnly)?-1:0); + + return(RFB_CLIENT_ACCEPT); +} + +int main(int argc,char *argv[]) +{ + int i; + + for(i=argc-1;i>0;i--) + if(inewClientHook = newClient; + + /* enter background event loop */ + rfbRunEventLoop(rfbScreen,40,TRUE); + + /* enter OS X loop */ + CGRegisterScreenRefreshCallback(refreshCallback, NULL); + RunApplicationEventLoop(); + + rfbDimmingShutdown(); + + return(0); /* never ... */ +} + +void rfbShutdown(rfbClientPtr cl) +{ + rfbScreenCleanup(rfbScreen); + rfbDimmingShutdown(); + exit(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c new file mode 100755 index 0000000..6268577 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/pnmshow.c @@ -0,0 +1,121 @@ +#include +#include +#include + +#ifndef HAVE_HANDLEKEY +static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down && (key==XK_Escape || key=='q' || key=='Q')) + rfbCloseClient(cl); +} +#endif + +int main(int argc,char** argv) +{ + FILE* in=stdin; + int i,j,k,l,width,height,paddedWidth; + char buffer[1024]; + rfbScreenInfoPtr rfbScreen; + enum { BW, GRAY, TRUECOLOUR } picType=TRUECOLOUR; + int bytesPerPixel,bitsPerPixelInFile; + + if(argc>1) { + in=fopen(argv[1],"rb"); + if(!in) { + printf("Couldn't find file %s.\n",argv[1]); + exit(1); + } + } + + fgets(buffer,1024,in); + if(!strncmp(buffer,"P6",2)) { + picType=TRUECOLOUR; + bytesPerPixel=4; bitsPerPixelInFile=3*8; + } else if(!strncmp(buffer,"P5",2)) { + picType=GRAY; + bytesPerPixel=1; bitsPerPixelInFile=1*8; + } else if(!strncmp(buffer,"P4",2)) { + picType=BW; + bytesPerPixel=1; bitsPerPixelInFile=1; + } else { + printf("Not a ppm.\n"); + exit(2); + } + + /* skip comments */ + do { + fgets(buffer,1024,in); + } while(buffer[0]=='#'); + + /* get width & height */ + sscanf(buffer,"%d %d",&width,&height); + rfbLog("Got width %d and height %d.\n",width,height); + if(picType!=BW) + fgets(buffer,1024,in); + else + width=1+((width-1)|7); + + /* vncviewers have problems with widths which are no multiple of 4. */ + paddedWidth = width; + if(width&3) + paddedWidth+=4-(width&3); + + /* initialize data for vnc server */ + rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,(bitsPerPixelInFile+7)/8,bytesPerPixel); + if(argc>1) + rfbScreen->desktopName = argv[1]; + else + rfbScreen->desktopName = "Picture"; + rfbScreen->alwaysShared = TRUE; + rfbScreen->kbdAddEvent = HandleKey; + + /* enable http */ + rfbScreen->httpDir = "../classes"; + + /* allocate picture and read it */ + rfbScreen->frameBuffer = (char*)malloc(paddedWidth*bytesPerPixel*height); + fread(rfbScreen->frameBuffer,width*bitsPerPixelInFile/8,height,in); + fclose(in); + + if(picType!=TRUECOLOUR) { + rfbScreen->serverFormat.trueColour=FALSE; + rfbScreen->colourMap.count=256; + rfbScreen->colourMap.is16=FALSE; + rfbScreen->colourMap.data.bytes=malloc(256*3); + for(i=0;i<256;i++) + memset(rfbScreen->colourMap.data.bytes+3*i,i,3); + } + + switch(picType) { + case TRUECOLOUR: + /* correct the format to 4 bytes instead of 3 (and pad to paddedWidth) */ + for(j=height-1;j>=0;j--) { + for(i=width-1;i>=0;i--) + for(k=2;k>=0;k--) + rfbScreen->frameBuffer[(j*paddedWidth+i)*4+k]= + rfbScreen->frameBuffer[(j*width+i)*3+k]; + for(i=width*4;iframeBuffer[j*paddedWidth*4+i]=0; + } + break; + case GRAY: + break; + case BW: + /* correct the format from 1 bit to 8 bits */ + for(j=height-1;j>=0;j--) + for(i=width-1;i>=0;i-=8) { + l=(unsigned char)rfbScreen->frameBuffer[(j*width+i)/8]; + for(k=7;k>=0;k--) + rfbScreen->frameBuffer[j*paddedWidth+i+7-k]=(l&(1< +#include +#include + +#ifndef LIBVNCSERVER_ALLOW24BPP +int main() { + printf("I need the ALLOW24BPP LibVNCServer flag to work\n"); + exit(1); +} +#else + +static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down && (key==XK_Escape || key=='q' || key=='Q')) + rfbCloseClient(cl); +} + +int main(int argc,char** argv) +{ + FILE* in=stdin; + int j,width,height,paddedWidth; + char buffer[1024]; + rfbScreenInfoPtr rfbScreen; + + if(argc>1) { + in=fopen(argv[1],"rb"); + if(!in) { + printf("Couldn't find file %s.\n",argv[1]); + exit(1); + } + } + + fgets(buffer,1024,in); + if(strncmp(buffer,"P6",2)) { + printf("Not a ppm.\n"); + exit(2); + } + + /* skip comments */ + do { + fgets(buffer,1024,in); + } while(buffer[0]=='#'); + + /* get width & height */ + sscanf(buffer,"%d %d",&width,&height); + rfbLog("Got width %d and height %d.\n",width,height); + fgets(buffer,1024,in); + + /* vncviewers have problems with widths which are no multiple of 4. */ + paddedWidth = width; + + /* if your vncviewer doesn't have problems with a width + which is not a multiple of 4, you can comment this. */ + if(width&3) + paddedWidth+=4-(width&3); + + /* initialize data for vnc server */ + rfbScreen = rfbGetScreen(&argc,argv,paddedWidth,height,8,3,3); + if(argc>1) + rfbScreen->desktopName = argv[1]; + else + rfbScreen->desktopName = "Picture"; + rfbScreen->alwaysShared = TRUE; + rfbScreen->kbdAddEvent = HandleKey; + + /* enable http */ + rfbScreen->httpDir = "../classes"; + + /* allocate picture and read it */ + rfbScreen->frameBuffer = (char*)malloc(paddedWidth*3*height); + fread(rfbScreen->frameBuffer,width*3,height,in); + fclose(in); + + /* pad to paddedWidth */ + if(width != paddedWidth) { + int padCount = 3*(paddedWidth - width); + for(j=height-1;j>=0;j--) { + memmove(rfbScreen->frameBuffer+3*paddedWidth*j, + rfbScreen->frameBuffer+3*width*j, + 3*width); + memset(rfbScreen->frameBuffer+3*paddedWidth*(j+1)-padCount, + 0,padCount); + } + } + + /* initialize server */ + rfbInitServer(rfbScreen); + + /* run event loop */ + rfbRunEventLoop(rfbScreen,40000,FALSE); + + return(0); +} +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h b/droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h new file mode 100755 index 0000000..b6209a9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/radon.h @@ -0,0 +1,195 @@ +static unsigned char radonFontData[2280]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 32 */ +0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x00,0x00, /* 33 */ +0x00,0x28,0x28,0x28,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 34 */ +0x00,0x44,0x44,0xba,0x44,0x44,0x44,0xba,0x44,0x44,0x00,0x00, /* 35 */ +0x10,0x7e,0x80,0x90,0x80,0x7c,0x02,0x12,0x02,0xfc,0x10,0x00, /* 36 */ +0x00,0x62,0x92,0x94,0x68,0x10,0x2c,0x52,0x92,0x8c,0x00,0x00, /* 37 */ +0x00,0x60,0x90,0x90,0x40,0x20,0x90,0x8a,0x84,0x7a,0x00,0x00, /* 38 */ +0x00,0x10,0x10,0x10,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 39 */ +0x00,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x00,0x00, /* 40 */ +0x00,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x00,0x00, /* 41 */ +0x00,0x10,0x92,0x54,0x10,0x10,0x54,0x92,0x10,0x00,0x00,0x00, /* 42 */ +0x00,0x00,0x10,0x10,0x10,0xd6,0x10,0x10,0x10,0x00,0x00,0x00, /* 43 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x30,0x00, /* 44 */ +0x00,0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, /* 45 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x00,0x00, /* 46 */ +0x00,0x02,0x02,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x00,0x00, /* 47 */ +0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x7c,0x00,0x00, /* 48 */ +0x00,0x08,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 49 */ +0x00,0xfc,0x02,0x02,0x02,0x7c,0x80,0x80,0x00,0xfe,0x00,0x00, /* 50 */ +0x00,0xfc,0x02,0x02,0x02,0x3c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 51 */ +0x00,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0x02,0x02,0x00,0x00, /* 52 */ +0x00,0xfe,0x00,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 53 */ +0x00,0x7c,0x80,0x80,0xbc,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 54 */ +0x00,0xfc,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x00,0x00, /* 55 */ +0x00,0x7c,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x7c,0x00,0x00, /* 56 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x7a,0x02,0x02,0xfc,0x00,0x00, /* 57 */ +0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x00,0x00,0x00, /* 58 */ +0x00,0x00,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x60,0x00,0x00, /* 59 */ +0x00,0x08,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x08,0x00,0x00, /* 60 */ +0x00,0x00,0x00,0x00,0xfe,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, /* 61 */ +0x00,0x10,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x10,0x00,0x00, /* 62 */ +0x00,0xfc,0x02,0x02,0x02,0x1c,0x20,0x20,0x00,0x20,0x00,0x00, /* 63 */ +0x00,0x7c,0x82,0x8a,0x92,0x92,0x92,0x8c,0x80,0x7c,0x00,0x00, /* 64 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x00,0x00, /* 65 */ +0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0xbc,0x00,0x00, /* 66 */ +0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7c,0x00,0x00, /* 67 */ +0x00,0xbc,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0xbc,0x00,0x00, /* 68 */ +0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x7c,0x00,0x00, /* 69 */ +0x00,0x7c,0x80,0x80,0x80,0xb8,0x80,0x80,0x80,0x80,0x00,0x00, /* 70 */ +0x00,0x7c,0x80,0x80,0x80,0x80,0x9a,0x82,0x82,0x7c,0x00,0x00, /* 71 */ +0x00,0x82,0x82,0x82,0x82,0xba,0x82,0x82,0x82,0x82,0x00,0x00, /* 72 */ +0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 73 */ +0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x84,0x78,0x00,0x00, /* 74 */ +0x00,0x82,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 75 */ +0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7e,0x00,0x00, /* 76 */ +0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x82,0x82,0x82,0x00,0x00, /* 77 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 78 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 79 */ +0x00,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x80,0x80,0x00,0x00, /* 80 */ +0x00,0x7c,0x82,0x82,0x82,0x82,0x8a,0x8a,0x82,0x7c,0x00,0x00, /* 81 */ +0x00,0xbc,0x82,0x82,0x82,0xbc,0x82,0x82,0x82,0x82,0x00,0x00, /* 82 */ +0x00,0x7e,0x80,0x80,0x80,0x7c,0x02,0x02,0x02,0xfc,0x00,0x00, /* 83 */ +0x00,0xfe,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 84 */ +0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 85 */ +0x00,0x82,0x82,0x82,0x82,0x82,0x84,0x88,0x90,0xa0,0x00,0x00, /* 86 */ +0x00,0x82,0x82,0x82,0x82,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 87 */ +0x00,0x82,0x82,0x82,0x82,0x7c,0x82,0x82,0x82,0x82,0x00,0x00, /* 88 */ +0x00,0x82,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 89 */ +0x00,0xfc,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0x7e,0x00,0x00, /* 90 */ +0x00,0x1c,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x1c,0x00,0x00, /* 91 */ +0x00,0x80,0x80,0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00, /* 92 */ +0x00,0x38,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x38,0x00,0x00, /* 93 */ +0x00,0x38,0x44,0x44,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 94 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00, /* 95 */ +0x00,0x08,0x08,0x08,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 96 */ +0x00,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 97 */ +0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 98 */ +0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x3c,0x00,0x00, /* 99 */ +0x00,0x00,0x02,0x02,0x3a,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 100 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 101 */ +0x00,0x00,0x0c,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x00,0x00, /* 102 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 103 */ +0x00,0x00,0x40,0x40,0x5c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 104 */ +0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 105 */ +0x00,0x00,0x08,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x30, /* 106 */ +0x00,0x00,0x40,0x40,0x42,0x42,0x5c,0x42,0x42,0x42,0x00,0x00, /* 107 */ +0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00, /* 108 */ +0x00,0x00,0x00,0x00,0x7c,0x82,0x92,0x92,0x92,0x92,0x00,0x00, /* 109 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 110 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 111 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x5c,0x40,0x40, /* 112 */ +0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3a,0x02,0x02, /* 113 */ +0x00,0x00,0x00,0x00,0x0c,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 114 */ +0x00,0x00,0x00,0x00,0x3e,0x40,0x3c,0x02,0x02,0x7c,0x00,0x00, /* 115 */ +0x00,0x00,0x10,0x10,0x10,0x54,0x10,0x10,0x10,0x0c,0x00,0x00, /* 116 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 117 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x44,0x48,0x50,0x00,0x00, /* 118 */ +0x00,0x00,0x00,0x00,0x92,0x92,0x92,0x92,0x82,0x7c,0x00,0x00, /* 119 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x3c,0x42,0x42,0x42,0x00,0x00, /* 120 */ +0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 121 */ +0x00,0x00,0x00,0x00,0x7c,0x02,0x0c,0x30,0x40,0x3e,0x00,0x00, /* 122 */ +0x00,0x1c,0x20,0x20,0x20,0x40,0x20,0x20,0x20,0x1c,0x00,0x00, /* 123 */ +0x00,0x10,0x10,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x00,0x00, /* 124 */ +0x00,0x38,0x04,0x04,0x04,0x02,0x04,0x04,0x04,0x38,0x00,0x00, /* 125 */ +0x00,0x04,0x38,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 126 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 160 */ +0x00,0x10,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 161 */ +0x00,0x00,0x08,0x3e,0x40,0x48,0x48,0x40,0x3e,0x08,0x00,0x00, /* 162 */ +0x00,0x1c,0x20,0x20,0x20,0xa8,0x20,0x20,0x42,0xbc,0x00,0x00, /* 163 */ +0x00,0x00,0x82,0x38,0x44,0x44,0x44,0x38,0x82,0x00,0x00,0x00, /* 164 */ +0x00,0x82,0x82,0x82,0x7c,0x00,0x54,0x10,0x54,0x10,0x00,0x00, /* 165 */ +0x00,0x10,0x10,0x10,0x00,0x00,0x00,0x10,0x10,0x10,0x00,0x00, /* 166 */ +0x00,0x38,0x40,0x38,0x44,0x44,0x44,0x44,0x38,0x04,0x38,0x00, /* 167 */ +0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 168 */ +0x00,0x7c,0x82,0x9a,0xa2,0xa2,0xa2,0x9a,0x82,0x7c,0x00,0x00, /* 169 */ +0x38,0x04,0x34,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00, /* 170 */ +0x00,0x00,0x00,0x24,0x48,0x00,0x48,0x24,0x00,0x00,0x00,0x00, /* 171 */ +0x00,0x00,0x00,0x00,0x00,0xfc,0x02,0x02,0x02,0x00,0x00,0x00, /* 172 */ +0x00,0x00,0x00,0x00,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 173 */ +0x00,0x7c,0x82,0x92,0xaa,0xb2,0xaa,0xaa,0x82,0x7c,0x00,0x00, /* 174 */ +0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 175 */ +0x38,0x44,0x44,0x44,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 176 */ +0x00,0x10,0x10,0xd6,0x10,0x10,0x00,0xfe,0x00,0x00,0x00,0x00, /* 177 */ +0x38,0x04,0x18,0x20,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 178 */ +0x38,0x04,0x38,0x04,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 179 */ +0x18,0x20,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 180 */ +0x00,0x00,0x00,0x00,0x44,0x44,0x44,0x44,0x44,0x58,0x40,0x40, /* 181 */ +0x00,0x79,0xfa,0xfa,0xfa,0x7a,0x02,0x0a,0x0a,0x0a,0x0a,0x00, /* 182 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00, /* 183 */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x10,0x00, /* 184 */ +0x08,0x18,0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00, /* 185 */ +0x38,0x44,0x44,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00, /* 186 */ +0x00,0x00,0x00,0x48,0x24,0x00,0x24,0x48,0x00,0x00,0x00,0x00, /* 187 */ +0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 188 */ +0x20,0xa2,0x22,0x22,0x24,0x08,0x10,0x2e,0x41,0x86,0x08,0x0f, /* 189 */ +0xe0,0x12,0xe2,0x12,0xe4,0x08,0x10,0x29,0x49,0x85,0x01,0x01, /* 190 */ +0x00,0x08,0x00,0x08,0x08,0x70,0x80,0x80,0x80,0x7e,0x00,0x00, /* 191 */ +0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 192 */ +0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 193 */ +0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 194 */ +0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 195 */ +0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 196 */ +0x38,0x44,0x38,0x7c,0x82,0x82,0x82,0xba,0x82,0x82,0x00,0x00, /* 197 */ +0x00,0x77,0x88,0x88,0x88,0x8b,0xa8,0x88,0x88,0x8b,0x00,0x00, /* 198 */ +0x00,0x7c,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x6c,0x10,0x20, /* 199 */ +0x20,0x18,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 200 */ +0x08,0x30,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 201 */ +0x38,0x44,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 202 */ +0x6c,0x00,0x00,0x7c,0x80,0x80,0xb8,0x80,0x80,0x7c,0x00,0x00, /* 203 */ +0x20,0x18,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 204 */ +0x08,0x30,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 205 */ +0x38,0x44,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 206 */ +0x6c,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 207 */ +0x00,0xbc,0x82,0x82,0x82,0xb2,0x82,0x82,0x82,0xbc,0x00,0x00, /* 208 */ +0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x82,0x00,0x00, /* 209 */ +0x20,0x18,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 210 */ +0x08,0x30,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 211 */ +0x38,0x44,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 212 */ +0x32,0x4c,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 213 */ +0x6c,0x00,0x00,0x7c,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 214 */ +0x00,0x00,0x00,0x00,0x44,0x28,0x00,0x28,0x44,0x00,0x00,0x00, /* 215 */ +0x00,0x7a,0x84,0x82,0x8a,0x92,0xa2,0x82,0x42,0xbc,0x00,0x00, /* 216 */ +0x20,0x18,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 217 */ +0x08,0x30,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 218 */ +0x38,0x44,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 219 */ +0x6c,0x00,0x00,0x82,0x82,0x82,0x82,0x82,0x82,0x7c,0x00,0x00, /* 220 */ +0x08,0xb2,0x82,0x82,0x82,0x7c,0x00,0x10,0x10,0x10,0x00,0x00, /* 221 */ +0x00,0x80,0x80,0xbc,0x82,0x82,0x82,0xbc,0x80,0x80,0x00,0x00, /* 222 */ +0x00,0x3c,0x42,0x42,0x42,0x5c,0x42,0x42,0x42,0x9c,0x00,0x00, /* 223 */ +0x20,0x18,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 224 */ +0x08,0x30,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 225 */ +0x38,0x44,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 226 */ +0x32,0x4c,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 227 */ +0x6c,0x00,0x00,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 228 */ +0x18,0x24,0x18,0x00,0x3c,0x02,0x3a,0x42,0x42,0x3c,0x00,0x00, /* 229 */ +0x00,0x00,0x00,0x00,0x6c,0x12,0x52,0x94,0x90,0x6e,0x00,0x00, /* 230 */ +0x00,0x00,0x00,0x00,0x3c,0x40,0x40,0x40,0x40,0x34,0x08,0x10, /* 231 */ +0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 232 */ +0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 233 */ +0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 234 */ +0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x5c,0x40,0x3c,0x00,0x00, /* 235 */ +0x20,0x18,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 236 */ +0x08,0x30,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 237 */ +0x38,0x44,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 238 */ +0x6c,0x00,0x00,0x10,0x00,0x10,0x10,0x10,0x10,0x10,0x00,0x00, /* 239 */ +0x00,0x14,0x08,0x14,0x02,0x3a,0x42,0x42,0x42,0x3c,0x00,0x00, /* 240 */ +0x00,0x32,0x4c,0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00, /* 241 */ +0x20,0x18,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 242 */ +0x08,0x30,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 243 */ +0x38,0x44,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 244 */ +0x32,0x4c,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 245 */ +0x6c,0x00,0x00,0x00,0x3c,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 246 */ +0x00,0x00,0x00,0x00,0x38,0x00,0xfe,0x00,0x38,0x00,0x00,0x00, /* 247 */ +0x00,0x00,0x00,0x00,0x3a,0x44,0x4a,0x52,0x22,0x5c,0x00,0x00, /* 248 */ +0x20,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 249 */ +0x08,0x30,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 250 */ +0x38,0x44,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 251 */ +0x6c,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,0x00, /* 252 */ +0x04,0x18,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x3a,0x02,0x3c, /* 253 */ +0x00,0x80,0x80,0x9c,0xa2,0x82,0xa2,0x9c,0x80,0x80,0x00,0x00, /* 254 */ +}; +static int radonFontMetaData[256*5]={ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,12,0,-2,12,8,12,0,-2,24,8,12,0,-2,36,8,12,0,-2,48,8,12,0,-2,60,8,12,0,-2,72,8,12,0,-2,84,8,12,0,-2,96,8,12,0,-2,108,8,12,0,-2,120,8,12,0,-2,132,8,12,0,-2,144,8,12,0,-2,156,8,12,0,-2,168,8,12,0,-2,180,8,12,0,-2,192,8,12,0,-2,204,8,12,0,-2,216,8,12,0,-2,228,8,12,0,-2,240,8,12,0,-2,252,8,12,0,-2,264,8,12,0,-2,276,8,12,0,-2,288,8,12,0,-2,300,8,12,0,-2,312,8,12,0,-2,324,8,12,0,-2,336,8,12,0,-2,348,8,12,0,-2,360,8,12,0,-2,372,8,12,0,-2,384,8,12,0,-2,396,8,12,0,-2,408,8,12,0,-2,420,8,12,0,-2,432,8,12,0,-2,444,8,12,0,-2,456,8,12,0,-2,468,8,12,0,-2,480,8,12,0,-2,492,8,12,0,-2,504,8,12,0,-2,516,8,12,0,-2,528,8,12,0,-2,540,8,12,0,-2,552,8,12,0,-2,564,8,12,0,-2,576,8,12,0,-2,588,8,12,0,-2,600,8,12,0,-2,612,8,12,0,-2,624,8,12,0,-2,636,8,12,0,-2,648,8,12,0,-2,660,8,12,0,-2,672,8,12,0,-2,684,8,12,0,-2,696,8,12,0,-2,708,8,12,0,-2,720,8,12,0,-2,732,8,12,0,-2,744,8,12,0,-2,756,8,12,0,-2,768,8,12,0,-2,780,8,12,0,-2,792,8,12,0,-2,804,8,12,0,-2,816,8,12,0,-2,828,8,12,0,-2,840,8,12,0,-2,852,8,12,0,-2,864,8,12,0,-2,876,8,12,0,-2,888,8,12,0,-2,900,8,12,0,-2,912,8,12,0,-2,924,8,12,0,-2,936,8,12,0,-2,948,8,12,0,-2,960,8,12,0,-2,972,8,12,0,-2,984,8,12,0,-2,996,8,12,0,-2,1008,8,12,0,-2,1020,8,12,0,-2,1032,8,12,0,-2,1044,8,12,0,-2,1056,8,12,0,-2,1068,8,12,0,-2,1080,8,12,0,-2,1092,8,12,0,-2,1104,8,12,0,-2,1116,8,12,0,-2,1128,8,12,0,-2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1140,8,12,0,-2,1152,8,12,0,-2,1164,8,12,0,-2,1176,8,12,0,-2,1188,8,12,0,-2,1200,8,12,0,-2,1212,8,12,0,-2,1224,8,12,0,-2,1236,8,12,0,-2,1248,8,12,0,-2,1260,8,12,0,-2,1272,8,12,0,-2,1284,8,12,0,-2,1296,8,12,0,-2,1308,8,12,0,-2,1320,8,12,0,-2,1332,8,12,0,-2,1344,8,12,0,-2,1356,8,12,0,-2,1368,8,12,0,-2,1380,8,12,0,-2,1392,8,12,0,-2,1404,8,12,0,-2,1416,8,12,0,-2,1428,8,12,0,-2,1440,8,12,0,-2,1452,8,12,0,-2,1464,8,12,0,-2,1476,8,12,0,-2,1488,8,12,0,-2,1500,8,12,0,-2,1512,8,12,0,-2,1524,8,12,0,-2,1536,8,12,0,-2,1548,8,12,0,-2,1560,8,12,0,-2,1572,8,12,0,-2,1584,8,12,0,-2,1596,8,12,0,-2,1608,8,12,0,-2,1620,8,12,0,-2,1632,8,12,0,-2,1644,8,12,0,-2,1656,8,12,0,-2,1668,8,12,0,-2,1680,8,12,0,-2,1692,8,12,0,-2,1704,8,12,0,-2,1716,8,12,0,-2,1728,8,12,0,-2,1740,8,12,0,-2,1752,8,12,0,-2,1764,8,12,0,-2,1776,8,12,0,-2,1788,8,12,0,-2,1800,8,12,0,-2,1812,8,12,0,-2,1824,8,12,0,-2,1836,8,12,0,-2,1848,8,12,0,-2,1860,8,12,0,-2,1872,8,12,0,-2,1884,8,12,0,-2,1896,8,12,0,-2,1908,8,12,0,-2,1920,8,12,0,-2,1932,8,12,0,-2,1944,8,12,0,-2,1956,8,12,0,-2,1968,8,12,0,-2,1980,8,12,0,-2,1992,8,12,0,-2,2004,8,12,0,-2,2016,8,12,0,-2,2028,8,12,0,-2,2040,8,12,0,-2,2052,8,12,0,-2,2064,8,12,0,-2,2076,8,12,0,-2,2088,8,12,0,-2,2100,8,12,0,-2,2112,8,12,0,-2,2124,8,12,0,-2,2136,8,12,0,-2,2148,8,12,0,-2,2160,8,12,0,-2,2172,8,12,0,-2,2184,8,12,0,-2,2196,8,12,0,-2,2208,8,12,0,-2,2220,8,12,0,-2,2232,8,12,0,-2,2244,8,12,0,-2,2256,8,12,0,-2,2268,8,12,0,-2,0,0,0,0,0,}; +static rfbFontData radonFont={radonFontData, radonFontMetaData}; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c new file mode 100755 index 0000000..91f1a17 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/regiontest.c @@ -0,0 +1,3 @@ +#define SRA_TEST +#include "../libvncserver/rfbregion.c" + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c new file mode 100755 index 0000000..66fca80 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotate.c @@ -0,0 +1,92 @@ +#include +#include +#include + +static int gcd(int x, int y) +{ + if (x == 0) + return y; + return gcd((y % x), x); +} + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + +#define FUNCNAME rfbRotate +#define FUNC(i, j) (h - 1 - j + i * h) +#define SWAPDIMENSIONS +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +#define FUNCNAME rfbRotateCounterClockwise +#define FUNC(i, j) (j + (w - 1 - i) * h) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC +#undef SWAPDIMENSIONS + +#define FUNCNAME rfbFlipHorizontally +#define FUNC(i, j) ((w - 1 - i) + j * w) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +#define FUNCNAME rfbFlipVertically +#define FUNC(i, j) (i + (h - 1 - j) * w) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +#define FUNCNAME rfbRotateHundredAndEighty +#define FUNC(i, j) ((w - 1 - i) + (h - 1 - j) * w) +#define OUT 8 +#include "rotatetemplate.c" +#define OUT 16 +#include "rotatetemplate.c" +#define OUT 32 +#include "rotatetemplate.c" +#undef FUNCNAME +#undef FUNC + +static void HandleKey(rfbBool down,rfbKeySym key,rfbClientPtr cl) +{ + if(down) { + if (key==XK_Escape || key=='q' || key=='Q') + rfbCloseClient(cl); + else if (key == 'r') + rfbRotate(cl->screen); + else if (key == 'R') + rfbRotateCounterClockwise(cl->screen); + else if (key == 'f') + rfbFlipHorizontally(cl->screen); + else if (key == 'F') + rfbFlipVertically(cl->screen); + } +} + +#define HAVE_HANDLEKEY +#include "pnmshow.c" + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c new file mode 100755 index 0000000..57dc052 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/rotatetemplate.c @@ -0,0 +1,52 @@ +#define OUT_T CONCAT3E(uint,OUT,_t) +#define FUNCTION CONCAT2E(FUNCNAME,OUT) + +static void FUNCTION(rfbScreenInfoPtr screen) +{ + OUT_T* buffer = (OUT_T*)screen->frameBuffer; + int i, j, w = screen->width, h = screen->height; + OUT_T* newBuffer = (OUT_T*)malloc(w * h * sizeof(OUT_T)); + + for (j = 0; j < h; j++) + for (i = 0; i < w; i++) + newBuffer[FUNC(i, j)] = buffer[i + j * w]; + + memcpy(buffer, newBuffer, w * h * sizeof(OUT_T)); + free(newBuffer); + +#ifdef SWAPDIMENSIONS + screen->width = h; + screen->paddedWidthInBytes = h * OUT / 8; + screen->height = w; + + { + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + iterator = rfbGetClientIterator(screen); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) + cl->newFBSizePending = 1; + } +#endif + + rfbMarkRectAsModified(screen, 0, 0, screen->width, screen->height); +} + +#if OUT == 32 +void FUNCNAME(rfbScreenInfoPtr screen) { + if (screen->serverFormat.bitsPerPixel == 32) + CONCAT2E(FUNCNAME,32)(screen); + else if (screen->serverFormat.bitsPerPixel == 16) + CONCAT2E(FUNCNAME,16)(screen); + else if (screen->serverFormat.bitsPerPixel == 8) + CONCAT2E(FUNCNAME,8)(screen); + else { + rfbErr("Unsupported pixel depth: %d\n", + screen->serverFormat.bitsPerPixel); + return; + } +} +#endif + +#undef FUNCTION +#undef OUT + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c new file mode 100755 index 0000000..f6e94dc --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple.c @@ -0,0 +1,10 @@ +#include + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4); + server->frameBuffer=(char*)malloc(400*300*4); + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c new file mode 100755 index 0000000..faff4f7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/simple15.c @@ -0,0 +1,24 @@ +/* This example shows how to use 15-bit (which is handled as 16-bit + internally). */ + +#include + +int main(int argc,char** argv) +{ + int i,j; + uint16_t* f; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,5,3,2); + + server->frameBuffer=(char*)malloc(400*300*2); + f=(uint16_t*)server->frameBuffer; + for(j=0;j<300;j++) + for(i=0;i<400;i++) + f[j*400+i]=/* red */ ((j*32/300) << 10) | + /* green */ (((j+400-i)*32/700) << 5) | + /* blue */ ((i*32/400)); + + rfbInitServer(server); + rfbRunEventLoop(server,-1,FALSE); + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c new file mode 100755 index 0000000..7c358d9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/storepasswd.c @@ -0,0 +1,46 @@ +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include + +static void usage(void) +{ + printf("\nusage: storepasswd \n\n"); + + printf("Stores a password in encrypted format.\n"); + printf("The resulting file can be used with the -rfbauth argument to OSXvnc.\n\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + if (argc != 3) + usage(); + + if (rfbEncryptAndStorePasswd(argv[1], argv[2]) != 0) { + printf("storing password failed.\n"); + return 1; + } else { + printf("storing password succeeded.\n"); + return 0; + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c b/droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c new file mode 100755 index 0000000..affac00 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/examples/vncev.c @@ -0,0 +1,128 @@ +/* This program is a simple server to show events coming from the client */ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#ifndef __MINGW32__ +#include +#endif +#include +#include + +#define width 100 +#define height 100 +static char f[width*height]; +static char* keys[0x400]; + +static int hex2number(unsigned char c) +{ + if(c>'f') return(-1); + else if(c>'F') + return(10+c-'a'); + else if(c>'9') + return(10+c-'A'); + else + return(c-'0'); +} + +static void read_keys(void) +{ + int i,j,k; + char buffer[1024]; + FILE* keysyms=fopen("keysym.h","r"); + + memset(keys,0,0x400*sizeof(char*)); + + if(!keysyms) + return; + + while(!feof(keysyms)) { + fgets(buffer,1024,keysyms); + if(!strncmp(buffer,"#define XK_",strlen("#define XK_"))) { + for(i=strlen("#define XK_");buffer[i] && buffer[i]!=' ' + && buffer[i]!='\t';i++); + if(buffer[i]==0) /* don't support wrapped lines */ + continue; + buffer[i]=0; + for(i++;buffer[i] && buffer[i]!='0';i++); + if(buffer[i]==0 || buffer[i+1]!='x') continue; + for(j=0,i+=2;(k=hex2number(buffer[i]))>=0;i++) + j=j*16+k; + if(keys[j&0x3ff]) { + char* x=(char*)malloc(1+strlen(keys[j&0x3ff])+1+strlen(buffer+strlen("#define "))); + strcpy(x,keys[j&0x3ff]); + strcat(x,","); + strcat(x,buffer+strlen("#define ")); + free(keys[j&0x3ff]); + keys[j&0x3ff]=x; + } else + keys[j&0x3ff] = strdup(buffer+strlen("#define ")); + } + + } + fclose(keysyms); +} + +static int lineHeight=16,lineY=height-16; +static void output(rfbScreenInfoPtr s,char* line) +{ + rfbDoCopyRect(s,0,0,width,height-lineHeight,0,-lineHeight); + rfbDrawString(s,&default8x16Font,10,lineY,line,0x01); + rfbLog("%s\n",line); +} + +static void dokey(rfbBool down,rfbKeySym k,rfbClientPtr cl) +{ + char buffer[1024+32]; + + sprintf(buffer,"%s: %s (0x%x)", + down?"down":"up",keys[k&0x3ff]?keys[k&0x3ff]:"",(unsigned int)k); + output(cl->screen,buffer); +} + +static void doptr(int buttonMask,int x,int y,rfbClientPtr cl) +{ + char buffer[1024]; + if(buttonMask) { + sprintf(buffer,"Ptr: mouse button mask 0x%x at %d,%d",buttonMask,x,y); + output(cl->screen,buffer); + } + +} + +static enum rfbNewClientAction newclient(rfbClientPtr cl) +{ + char buffer[1024]; + struct sockaddr_in addr; + unsigned int len=sizeof(addr),ip; + + getpeername(cl->sock,(struct sockaddr*)&addr,&len); + ip=ntohl(addr.sin_addr.s_addr); + sprintf(buffer,"Client connected from ip %d.%d.%d.%d", + (ip>>24)&0xff,(ip>>16)&0xff,(ip>>8)&0xff,ip&0xff); + output(cl->screen,buffer); + return RFB_CLIENT_ACCEPT; +} + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr s=rfbGetScreen(&argc,argv,width,height,8,1,1); + s->colourMap.is16=FALSE; + s->colourMap.count=2; + s->colourMap.data.bytes=(unsigned char*)"\xd0\xd0\xd0\x30\x01\xe0"; + s->serverFormat.trueColour=FALSE; + s->frameBuffer=f; + s->kbdAddEvent=dokey; + s->ptrAddEvent=doptr; + s->newClientHook=newclient; + + memset(f,0,width*height); + read_keys(); + rfbInitServer(s); + + while(1) { + rfbProcessEvents(s,999999); + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/index.html b/droidvncgrab/vnc/libvncserver-kanaka/index.html new file mode 100755 index 0000000..1ee3fc4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/index.html @@ -0,0 +1,191 @@ + + + + LibVNCServer/LibVNCClient + + + +

LibVNCServer/LibVNCClient

+ +
+ + If you have problems updating with CVS, here is a preliminary version. If you are looking for more information + on Karl's wonderful x11vnc, either download it + here, or + look at x11vnc's homepage. +

+ +

News

+ 2005/09/29 LibVNCServer now sports a brand new method to extend the protocol, thanks to Rohit Kumar! He also extended the library to support RFB 3.7. Furthermore, he contributed TightVNC file transfer protocol support to LibVNCServer! +

+ 2005/05/25 LibVNCClient now features ZRLE decoding! +

+ 2005/05/15 Another round of valgrinding completed. This time it is augmented by changes instigated by using Linus' sparse. In the course, the complete sources were converted to ANSI C. +

+ 2005/05/07 The member socketInitDone was renamed to socketState, and no longer contains a bool value. This allows us to quit a server cleanly from the event loop via rfbShutdownServer(), so that the structures can be cleaned up properly. This is demonstrated in examples/example.c. +

+ 2005/01/21 The function rfbMakeMaskFromAlphaSource() applies a Floyd-Steinberg dither to approximate a binary mask from a cursor with alpha channel. A demonstration can be found in test/cursortest.c. +

+ 2005/01/16 Renamed this page to reflect that LibVNCClient is actually very usable. +

+ 2005/01/16 Karl Runge has done awesome work to support cursors with alpha blending! You can try it with x11vnc as in CVS, or wait a few more days for x11vnc to be released officially! +

+ 2005/01/15 Happy new year! It begins with a new macro recorder based on LibVNCServer/LibVNCClient using perl as script language. The macro recorder is itself written in perl, and writes out perl scripts, acting as a VNC proxy, so that you can connect a vncviewer to it, and it records all your input, possibly looking for a certain button, image, word, etc. before continuing. I called it VisualNaCro, and it's in CVS. +

+ 2004/12/20 Just before christmas, a new release! Version 0.7 brings you the first non-beta of LibVNCServer... +

+ 2004/12/02 Finally MinGW32 support. I only had problems with a vncviewer which wouldn't connect to localhost: I use SDLvncviewer... +

+ 2004/12/01 LibVNCClient is getting better and better... Expect a very powerful client soon! +

+ 2004/10/16 LibVNCServer has automated test, thanks to LibVNCClient (included). It doesn't do ZRLE yet, and exposed some bugs, the only remaining of these is CoRRE (not sure yet if it's a bug in the client or the server). +

+ 2004/09/14 Added + + Success stories. +

+ 2004/09/07 The API was cleaned up. The structures and functions now have a prefix (mostly "rfb", sometimes "zrle" or "sra") in order not to clutter the namespace, while the structure's members don't need such a prefix. +

+ 2004/08/17 I finally came around to fix mouse behaviour in QEMU's VNC frontend for Windows 98. Please find the patch here. If mouse behaves strangely, try to wiggle the pointer to a free spot on the desktop, hit Ctrl+Shift and release them. After that, the mouse should behave nicely. +

+ 2004/06/07 After silently being added almost a year ago, libvncclient's API was modified for real use, and three examples were added: ppmtest (a very simple demo), SDLvncviewer, and vnc2mpg (which lets you record your VNC session to a movie). Automated regression tests of the libraries are planned. +

+ 2004/06/02 x11vnc-0.6.1 was released! This reflects the long way the original, small example has gone, improved in many possible ways and having a broad user base. +

+ 2004/05/29 Some patches were created for QEMU, a FAST! emulator by Fabrice Bellard, to control those sessions with a vncviewer. +

+ 2004/02/29 LibVNCServer is listed as a project using Valgrind! +

+ 2003/11/07 Version 0.6 is out! x11vnc performance boosts! You no longer need a c++ compiler in order to have ZRLE coding! LinuxVNC was added (This is to the text console what x11vnc is to X11)! +

+ 2003/02/21 rdp2vnc is in rdesktop's CVS. +

+ 2003/02/19 A preliminary patch for rdesktop (CVS) to make +rdp2vnc, a translator from Windows Terminal Server's protocol to VNC's protocol, +is available. It needs a new version of +libvncserver; try CVS until I release 0.6. +

+ 2003/02/09 Version 0.5 is out! Features include autoconf based configure, rpm package (YMMV), cleanup of directory structure, NEW x11vnc! ZRLE encoding! HTTP tunnelling through LibVNCServer's HTTP support! Many bug fixes! +

+ 2002/07/28 Version 0.4 is out! Biggest feature: NewFB encoding. Quite a few bugfixes also (Thanks to all!). +

+ 2001/12/14 A new version of + rdesktop+vnc is available! + (Includes support for other platforms keyboard mapping with plain rdesktop!) +

+ 2001/10/23 Added a link to my homepage at the end. +

+ 2001/10/18 I released the rdp2vnc extensions as well as + patches for general keyboard handling, working inside Xvnc and + process_text2 (the famous "font:" error) to rdesktop. Please find it on + the + download page. +

+ 2001/10/13 A snapshot of + + LibVNCServer and + + RDP2VNC + is now available. You can also download the + + diff against rdesktop-1.1.0. + rdp2vnc also contains the patches for keyboards other than PC keyboards, + and you can specify "-k fr" again. + +


+ +

Introduction

+ If you don't know VNC, have a look at + the original VNC or at + Tridia VNC, who also have commercial + support for it. + +

+ + Now that you know what it is, maybe you want to make your own server. + If this is not the case, you can ignore the rest of this page an go on + surfing the internet. + +

+ + Now that you want to make a VNC server, that is, a server which speaks + the RFB protocol, you can download this library from + sourceforge. + +

+ + The simplest server looks like this:

+ +

+#include <rfb/rfb.h>
+
+int main(int argc,char** argv)
+{
+  rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4);
+  server->frameBuffer=malloc(400*300*4);
+  rfbInitServer(server);
+  rfbRunEventLoop(server,-1,FALSE);
+  return(0);
+}
+
+
+ + This sample creates a 400x300 frame buffer in true colour. There are + 4 bytes per pixel, because 3 (which are only used instead of all 4) is + such an odd number. Then the server is initialized and a blocking event + loop is started. + +

+ Of course, this program only shows rubbish (whatever is in the frame + buffer you malloc'd), but it proves that writing a server can be + very easy. + +

+ For details (especially if you want to write a real server) look into the + provided examples, pnmshow.c and example.c, and into the README. You find + there documentation for much more complicated servers. + +

+ Serious comments, suggestions, pizzas, etc. go to + me + (delete the RuBBISH). + +

+ Here are some links: + +

+ LibVNCServer is an adapted + OSXvnc-server by + Dan McGuirk, + which is in turn an adapted original + Xvnc. +

+ I use it to to drive a +Windows Terminal Server (RDP) to RFB converter with it. + Much work has been done to make + rdesktop + a good X client to Windows Terminal Services (both NT and 2000, see + rdesktop patches). + Previous work was done by Tim Edmonds + who has set up such a converter named + vdesktop + including a single client server and a multi client server, rdp2vnc. + Unfortunately he used the example code from rfbcounter, which can encode only + RRE, which is not a good compression. +

+ Other people + have used this library as well. +

+ If you want to know about other of my projects, look at + my homepage. +


+ Project hosted on the fantastic + + SourceForge Logo
+ + +Last modified: Mon Jan 17 18:23:00 MESZ 2005 + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore new file mode 100755 index 0000000..d498e83 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/.cvsignore @@ -0,0 +1,5 @@ +.deps +Makefile +Makefile.in +libvncclient.a + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am new file mode 100755 index 0000000..9f42fd3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/Makefile.am @@ -0,0 +1,15 @@ +INCLUDES = -I$(top_srcdir) + +libvncclient_la_SOURCES=cursor.c listen.c rfbproto.c sockets.c vncviewer.c minilzo.c tls.c + +noinst_HEADERS=lzoconf.h minilzo.h tls.h + +rfbproto.o: rfbproto.c corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c + +EXTRA_DIST=corre.c hextile.c rre.c tight.c zlib.c zrle.c ultra.c tls.c + +$(libvncclient_la_OBJECTS): ../rfb/rfbclient.h + +lib_LTLIBRARIES=libvncclient.la + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c new file mode 100755 index 0000000..baf91cc --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/corre.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * corre.c - handle CoRRE encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a CoRRE + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleCoRREBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbRREHeader hdr; + int i; + CARDBPP pix; + uint8_t *ptr; + int x, y, w, h; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader)) + return FALSE; + + hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects); + + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + FillRectangle(client, rx, ry, rw, rh, pix); + + if (!ReadFromRFBServer(client, client->buffer, hdr.nSubrects * (4 + (BPP / 8)))) + return FALSE; + + ptr = (uint8_t *)client->buffer; + + for (i = 0; i < hdr.nSubrects; i++) { + pix = *(CARDBPP *)ptr; + ptr += BPP/8; + x = *ptr++; + y = *ptr++; + w = *ptr++; + h = *ptr++; + + FillRectangle(client, rx+x, ry+y, w, h, pix); + } + + return TRUE; +} + +#undef CARDBPP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c new file mode 100755 index 0000000..a48d7c5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/cursor.c @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2001,2002 Constantin Kaplinsky. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * cursor.c - code to support cursor shape updates (XCursor and + * RichCursor preudo-encodings). + */ + +#include + + +#define OPER_SAVE 0 +#define OPER_RESTORE 1 + +#define RGB24_TO_PIXEL(bpp,r,g,b) \ + ((((uint##bpp##_t)(r) & 0xFF) * client->format.redMax + 127) / 255 \ + << client->format.redShift | \ + (((uint##bpp##_t)(g) & 0xFF) * client->format.greenMax + 127) / 255 \ + << client->format.greenShift | \ + (((uint##bpp##_t)(b) & 0xFF) * client->format.blueMax + 127) / 255 \ + << client->format.blueShift) + + +/********************************************************************* + * HandleCursorShape(). Support for XCursor and RichCursor shape + * updates. We emulate cursor operating on the frame buffer (that is + * why we call it "software cursor"). + ********************************************************************/ + +rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc) +{ + int bytesPerPixel; + size_t bytesPerRow, bytesMaskData; + rfbXCursorColors rgb; + uint32_t colors[2]; + char *buf; + uint8_t *ptr; + int x, y, b; + + bytesPerPixel = client->format.bitsPerPixel / 8; + bytesPerRow = (width + 7) / 8; + bytesMaskData = bytesPerRow * height; + + if (width * height == 0) + return TRUE; + + /* Allocate memory for pixel data and temporary mask data. */ + if(client->rcSource) + free(client->rcSource); + + client->rcSource = malloc(width * height * bytesPerPixel); + if (client->rcSource == NULL) + return FALSE; + + buf = malloc(bytesMaskData); + if (buf == NULL) { + free(client->rcSource); + client->rcSource = NULL; + return FALSE; + } + + /* Read and decode cursor pixel data, depending on the encoding type. */ + + if (enc == rfbEncodingXCursor) { + /* Read and convert background and foreground colors. */ + if (!ReadFromRFBServer(client, (char *)&rgb, sz_rfbXCursorColors)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + colors[0] = RGB24_TO_PIXEL(32, rgb.backRed, rgb.backGreen, rgb.backBlue); + colors[1] = RGB24_TO_PIXEL(32, rgb.foreRed, rgb.foreGreen, rgb.foreBlue); + + /* Read 1bpp pixel data into a temporary buffer. */ + if (!ReadFromRFBServer(client, buf, bytesMaskData)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + /* Convert 1bpp data to byte-wide color indices. */ + ptr = client->rcSource; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + for (b = 7; b >= 0; b--) { + *ptr = buf[y * bytesPerRow + x] >> b & 1; + ptr += bytesPerPixel; + } + } + for (b = 7; b > 7 - width % 8; b--) { + *ptr = buf[y * bytesPerRow + x] >> b & 1; + ptr += bytesPerPixel; + } + } + + /* Convert indices into the actual pixel values. */ + switch (bytesPerPixel) { + case 1: + for (x = 0; x < width * height; x++) + client->rcSource[x] = (uint8_t)colors[client->rcSource[x]]; + break; + case 2: + for (x = 0; x < width * height; x++) + ((uint16_t *)client->rcSource)[x] = (uint16_t)colors[client->rcSource[x * 2]]; + break; + case 4: + for (x = 0; x < width * height; x++) + ((uint32_t *)client->rcSource)[x] = colors[client->rcSource[x * 4]]; + break; + } + + } else { /* enc == rfbEncodingRichCursor */ + + if (!ReadFromRFBServer(client, (char *)client->rcSource, width * height * bytesPerPixel)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + } + + /* Read and decode mask data. */ + + if (!ReadFromRFBServer(client, buf, bytesMaskData)) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + client->rcMask = malloc(width * height); + if (client->rcMask == NULL) { + free(client->rcSource); + client->rcSource = NULL; + free(buf); + return FALSE; + } + + ptr = client->rcMask; + for (y = 0; y < height; y++) { + for (x = 0; x < width / 8; x++) { + for (b = 7; b >= 0; b--) { + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; + } + } + for (b = 7; b > 7 - width % 8; b--) { + *ptr++ = buf[y * bytesPerRow + x] >> b & 1; + } + } + + if (client->GotCursorShape != NULL) { + client->GotCursorShape(client, xhot, yhot, width, height, bytesPerPixel); + } + + free(buf); + + return TRUE; +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c new file mode 100755 index 0000000..8698445 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/hextile.c @@ -0,0 +1,127 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * hextile.c - handle hextile encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles a hextile + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleHextileBPP CONCAT2E(HandleHextile,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleHextileBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + CARDBPP bg, fg; + int i; + uint8_t *ptr; + int x, y, w, h; + int sx, sy, sw, sh; + uint8_t subencoding; + uint8_t nSubrects; + + for (y = ry; y < ry+rh; y += 16) { + for (x = rx; x < rx+rw; x += 16) { + w = h = 16; + if (rx+rw - x < 16) + w = rx+rw - x; + if (ry+rh - y < 16) + h = ry+rh - y; + + if (!ReadFromRFBServer(client, (char *)&subencoding, 1)) + return FALSE; + + if (subencoding & rfbHextileRaw) { + if (!ReadFromRFBServer(client, client->buffer, w * h * (BPP / 8))) + return FALSE; + + CopyRectangle(client, (uint8_t *)client->buffer, x, y, w, h); + + continue; + } + + if (subencoding & rfbHextileBackgroundSpecified) + if (!ReadFromRFBServer(client, (char *)&bg, sizeof(bg))) + return FALSE; + + FillRectangle(client, x, y, w, h, bg); + + if (subencoding & rfbHextileForegroundSpecified) + if (!ReadFromRFBServer(client, (char *)&fg, sizeof(fg))) + return FALSE; + + if (!(subencoding & rfbHextileAnySubrects)) { + continue; + } + + if (!ReadFromRFBServer(client, (char *)&nSubrects, 1)) + return FALSE; + + ptr = (uint8_t*)client->buffer; + + if (subencoding & rfbHextileSubrectsColoured) { + if (!ReadFromRFBServer(client, client->buffer, nSubrects * (2 + (BPP / 8)))) + return FALSE; + + for (i = 0; i < nSubrects; i++) { +#if BPP==8 + GET_PIXEL8(fg, ptr); +#elif BPP==16 + GET_PIXEL16(fg, ptr); +#elif BPP==32 + GET_PIXEL32(fg, ptr); +#else +#error "Invalid BPP" +#endif + sx = rfbHextileExtractX(*ptr); + sy = rfbHextileExtractY(*ptr); + ptr++; + sw = rfbHextileExtractW(*ptr); + sh = rfbHextileExtractH(*ptr); + ptr++; + + FillRectangle(client, x+sx, y+sy, sw, sh, fg); + } + + } else { + if (!ReadFromRFBServer(client, client->buffer, nSubrects * 2)) + return FALSE; + + for (i = 0; i < nSubrects; i++) { + sx = rfbHextileExtractX(*ptr); + sy = rfbHextileExtractY(*ptr); + ptr++; + sw = rfbHextileExtractW(*ptr); + sh = rfbHextileExtractH(*ptr); + ptr++; + + FillRectangle(client, x+sx, y+sy, sw, sh, fg); + } + } + } + } + + return TRUE; +} + +#undef CARDBPP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c new file mode 100755 index 0000000..637abb1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/listen.c @@ -0,0 +1,171 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * listen.c - listen for incoming connections + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#ifdef __MINGW32__ +#define close closesocket +#include +#else +#include +#include +#endif +#include +#include + +/* + * listenForIncomingConnections() - listen for incoming connections from + * servers, and fork a new process to deal with each connection. + */ + +void +listenForIncomingConnections(rfbClient* client) +{ +#ifdef __MINGW32__ + /* FIXME */ + rfbClientErr("listenForIncomingConnections on MinGW32 NOT IMPLEMENTED\n"); + return; +#else + int listenSocket; + fd_set fds; + + client->listenSpecified = TRUE; + + listenSocket = ListenAtTcpPort(client->listenPort); + + if ((listenSocket < 0)) + return; + + rfbClientLog("%s -listen: Listening on port %d\n", + client->programName,client->listenPort); + rfbClientLog("%s -listen: Command line errors are not reported until " + "a connection comes in.\n", client->programName); + + while (TRUE) { + + /* reap any zombies */ + int status, pid; + while ((pid= wait3(&status, WNOHANG, (struct rusage *)0))>0); + + /* TODO: callback for discard any events (like X11 events) */ + + FD_ZERO(&fds); + + FD_SET(listenSocket, &fds); + + select(listenSocket+1, &fds, NULL, NULL, NULL); + + if (FD_ISSET(listenSocket, &fds)) { + client->sock = AcceptTcpConnection(listenSocket); + if (client->sock < 0) + return; + if (!SetNonBlocking(client->sock)) + return; + + /* Now fork off a new process to deal with it... */ + + switch (fork()) { + + case -1: + rfbClientErr("fork\n"); + return; + + case 0: + /* child - return to caller */ + close(listenSocket); + return; + + default: + /* parent - go round and listen again */ + close(client->sock); + break; + } + } + } +#endif +} + + + +/* + * listenForIncomingConnectionsNoFork() - listen for incoming connections + * from servers, but DON'T fork, instead just wait timeout microseconds. + * If timeout is negative, block indefinitly. + * Returns 1 on success (there was an incoming connection on the listen socket + * and we accepted it successfully), -1 on error, 0 on timeout. + */ + +int +listenForIncomingConnectionsNoFork(rfbClient* client, int timeout) +{ + fd_set fds; + struct timeval to; + int r; + + to.tv_sec= timeout / 1000000; + to.tv_usec= timeout % 1000000; + + client->listenSpecified = TRUE; + + if (client->listenSock < 0) + { + client->listenSock = ListenAtTcpPort(client->listenPort); + + if (client->listenSock < 0) + return -1; + + rfbClientLog("%s -listennofork: Listening on port %d\n", + client->programName,client->listenPort); + rfbClientLog("%s -listennofork: Command line errors are not reported until " + "a connection comes in.\n", client->programName); + } + + FD_ZERO(&fds); + + FD_SET(client->listenSock, &fds); + + if (timeout < 0) + r = select(client->listenSock+1, &fds, NULL, NULL, NULL); + else + r = select(client->listenSock+1, &fds, NULL, NULL, &to); + + if (r > 0) + { + client->sock = AcceptTcpConnection(client->listenSock); + if (client->sock < 0) + return -1; + if (!SetNonBlocking(client->sock)) + return -1; + + close(client->listenSock); + return r; + } + + /* r is now either 0 (timeout) or -1 (error) */ + return r; +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h new file mode 100755 index 0000000..96db180 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c new file mode 100755 index 0000000..85771eb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.c @@ -0,0 +1,2935 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +# ifndef __LZOCONF_H +# include +# endif +#endif + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp lzo_memcmp +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy lzo_memcpy +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove lzo_memmove +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset lzo_memset +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#if 0 + +#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#endif + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + +LZO_PUBLIC(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_ptr_t p; + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) + p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); +#else + p = PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ + lzo_ptr_t p, s, n; + + assert(size > 0); + + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); +#if 0 + assert((size & (size - 1)) == 0); + n = ((p + s) & ~s) - p; +#else + n = (((p + s) / size) * size) - p; +#endif + + assert((long)n >= 0); + assert(n <= s); + + return (unsigned)n; +} + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +LZO_PUBLIC(lzo_bool) +lzo_assert(int expr) +{ + return (expr) ? 1 : 0; +} + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +LZO_PUBLIC(const lzo_byte *) +lzo_copyright(void) +{ + return __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +LZO_PUBLIC(int) +lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) + return memcmp(s1,s2,len); +#else + const lzo_byte *p1 = (const lzo_byte *) s1; + const lzo_byte *p2 = (const lzo_byte *) s2; + int d; + + if (len > 0) do + { + d = *p1 - *p2; + if (d != 0) + return d; + p1++; + p2++; + } + while (--len > 0); + return 0; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) + return memcpy(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while (--len > 0); + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) + return memmove(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + + if (p1 < p2) + { + do + *p1++ = *p2++; + while (--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while (--len > 0); + } + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memset(lzo_voidp s, int c, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + return memset(s,c,len); +#else + lzo_byte *p = (lzo_byte *) s; + + if (len > 0) do + *p++ = LZO_BYTE(c); + while (--len > 0); + return s; +#endif +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +static lzo_bool schedule_insns_bug(void); +static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + +static lzo_bool basic_integral_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); +#if defined(__LZO_STRICT_16BIT) + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); +#else + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); +#endif + +#if (USHRT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(short) == 2); +#elif (USHRT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) == 4); +#elif (USHRT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) > 4); +#endif +#if (UINT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(int) == 2); +#elif (UINT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) == 4); +#elif (UINT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) > 4); +#endif +#if (ULONG_MAX == 65535ul) + COMPILE_TIME_ASSERT(sizeof(long) == 2); +#elif (ULONG_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) == 4); +#elif (ULONG_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) > 4); +#endif + +#if defined(SIZEOF_UNSIGNED) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); +#endif +#if defined(SIZEOF_UNSIGNED_LONG) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); +#endif +#if defined(SIZEOF_UNSIGNED_SHORT) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); +#endif +#if !defined(__LZO_IN_MINILZO) +#if defined(SIZEOF_SIZE_T) + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); +#endif +#endif + + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); +#if !defined(__LZO_IN_MINILZO) + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); +#endif + + r &= __lzo_assert(LZO_BYTE(257) == 1); + + return r; +} + +static lzo_bool basic_ptr_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + +#if defined(SIZEOF_CHAR_P) + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); +#endif +#if defined(SIZEOF_PTRDIFF_T) + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); +#endif + + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + + return r; +} + +static lzo_bool ptr_check(void) +{ + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int) sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); + +#if 0 + dict = (lzo_bytepp) wrkmem; +#else + + u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; +#endif + + d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a,0xff,sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) + { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); + } + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) + { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict+1,sizeof(dict[0]),8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) + { + unsigned k = 1; + const unsigned n = (unsigned) sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; + + k += __lzo_align_gap(&x[k],n); + p0 = (lzo_bytep) &x[k]; +#if defined(PTR_LINEAR) + r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); +#else + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); +#endif + + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) &x[1]; + r &= __lzo_assert(PTR_GE(p0,p1)); + + r &= __lzo_assert(k < 1+n); + p1 = (lzo_bytep) &x[1+n]; + r &= __lzo_assert(PTR_LT(p0,p1)); + + if (r == 1) + { + lzo_uint32 v0, v1; +#if 0 + v0 = * (lzo_uint32 *) &x[k]; + v1 = * (lzo_uint32 *) &x[k+n]; +#else + + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k+n]; + v1 = *u.a_lzo_uint32_p; +#endif + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } + } + + return r; +} + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4*sizeof(lzo_full_align_t)]; + } u; + + COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); + COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); + +#if 0 + r &= __lzo_assert((const void *)&u == (const void *)&u.a); + r &= __lzo_assert((const void *)&u == (const void *)&u.b); + r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); + r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); +#endif + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; u.b = 0; + for (i = 0; i < (int) sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); + +#if defined(LZO_BYTE_ORDER) + if (r == 1) + { +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short) (u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); +# else +# error "invalid LZO_BYTE_ORDER" +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_2) + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) + { + unsigned short b[4]; + + for (i = 0; i < 4; i++) + b[i] = * (const unsigned short *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) + { + lzo_uint32 a[4]; + + for (i = 0; i < 4; i++) + a[i] = * (const lzo_uint32 *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); +# endif + } +#endif + +#if defined(LZO_ALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); +#endif + + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); + +#if defined(__LZO_IN_MINLZO) + if (r == 1) + { + lzo_uint32 adler; + adler = lzo_adler32(0, NULL, 0); + adler = lzo_adler32(adler, lzo_copyright(), 200); + r &= __lzo_assert(adler == 0xc76f1751L); + } +#endif + + if (r == 1) + { + r &= __lzo_assert(!schedule_insns_bug()); + } + + if (r == 1) + { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } + + if (r == 1) + { + r &= ptr_check(); + } + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +static lzo_bool schedule_insns_bug(void) +{ +#if defined(__LZO_CHECKER) + return 0; +#else + const int clone[] = {1, 2, 0}; + const int *q; + q = clone; + return (*q) ? 0 : 1; +#endif +} + +static lzo_bool strength_reduce_bug(int *x) +{ + return x[0] != -3 || x[1] != -2 || x[2] != -1; +} + +#undef COMPILE_TIME_ASSERT + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +LZO_EXTERN(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + +LZO_PUBLIC(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +{ + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); +} + +#endif + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *ip __asm__("%esi"); +#else + register const lzo_byte *ip; +#endif + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *m_pos __asm__("%edi"); +#else + register const lzo_byte *m_pos; +#endif + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + +#if defined(__LZO_QUERY_COMPRESS) + if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); +#endif + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +/***** End of minilzo.c *****/ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h new file mode 100755 index 0000000..e3270f9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c new file mode 100755 index 0000000..33307d2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rfbproto.c @@ -0,0 +1,2123 @@ +/* + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rfbproto.c - functions to deal with client side of RFB protocol. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#ifndef WIN32 +#include +#include +#include +#else +#define strncasecmp _strnicmp +#endif +#include +#ifndef WIN32 +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +#include +#endif +#include +#include + +#include "minilzo.h" +#include "tls.h" + +/* + * rfbClientLog prints a time-stamped message to the log file (stderr). + */ + +rfbBool rfbEnableClientLogging=TRUE; + +static void +rfbDefaultClientLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(stderr, "%s", buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); +} + +rfbClientLogProc rfbClientLog=rfbDefaultClientLog; +rfbClientLogProc rfbClientErr=rfbDefaultClientLog; + +/* extensions */ + +rfbClientProtocolExtension* rfbClientExtensions = NULL; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e) +{ + e->next = rfbClientExtensions; + rfbClientExtensions = e; +} + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data) +{ + rfbClientData* clientData = client->clientData; + + while(clientData && clientData->tag != tag) + clientData = clientData->next; + if(clientData == NULL) { + clientData = calloc(sizeof(rfbClientData), 1); + clientData->next = client->clientData; + client->clientData = clientData; + clientData->tag = tag; + } + + clientData->data = data; +} + +void* rfbClientGetClientData(rfbClient* client, void* tag) +{ + rfbClientData* clientData = client->clientData; + + while(clientData) { + if(clientData->tag == tag) + return clientData->data; + clientData = clientData->next; + } + + return NULL; +} + +/* messages */ + +static void FillRectangle(rfbClient* client, int x, int y, int w, int h, uint32_t colour) { + int i,j; + +#define FILL_RECT(BPP) \ + for(j=y*client->width;j<(y+h)*client->width;j+=client->width) \ + for(i=x;iframeBuffer)[j+i]=colour; + + switch(client->format.bitsPerPixel) { + case 8: FILL_RECT(8); break; + case 16: FILL_RECT(16); break; + case 32: FILL_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +static void CopyRectangle(rfbClient* client, uint8_t* buffer, int x, int y, int w, int h) { + int j; + +#define COPY_RECT(BPP) \ + { \ + int rs = w * BPP / 8, rs2 = client->width * BPP / 8; \ + for (j = ((x * (BPP / 8)) + (y * rs2)); j < (y + h) * rs2; j += rs2) { \ + memcpy(client->frameBuffer + j, buffer, rs); \ + buffer += rs; \ + } \ + } + + switch(client->format.bitsPerPixel) { + case 8: COPY_RECT(8); break; + case 16: COPY_RECT(16); break; + case 32: COPY_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +/* TODO: test */ +static void CopyRectangleFromRectangle(rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y) { + int i,j; + +#define COPY_RECT_FROM_RECT(BPP) \ + { \ + uint##BPP##_t* _buffer=((uint##BPP##_t*)client->frameBuffer)+(src_y-dest_y)*client->width+src_x-dest_x; \ + if (dest_y < src_y) { \ + for(j = dest_y*client->width; j < (dest_y+h)*client->width; j += client->width) { \ + if (dest_x < src_x) { \ + for(i = dest_x; i < dest_x+w; i++) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } else { \ + for(i = dest_x+w-1; i >= dest_x; i--) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } \ + } \ + } else { \ + for(j = (dest_y+h-1)*client->width; j >= dest_y*client->width; j-=client->width) { \ + if (dest_x < src_x) { \ + for(i = dest_x; i < dest_x+w; i++) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } else { \ + for(i = dest_x+w-1; i >= dest_x; i--) { \ + ((uint##BPP##_t*)client->frameBuffer)[j+i]=_buffer[j+i]; \ + } \ + } \ + } \ + } \ + } + + switch(client->format.bitsPerPixel) { + case 8: COPY_RECT_FROM_RECT(8); break; + case 16: COPY_RECT_FROM_RECT(16); break; + case 32: COPY_RECT_FROM_RECT(32); break; + default: + rfbClientLog("Unsupported bitsPerPixel: %d\n",client->format.bitsPerPixel); + } +} + +static rfbBool HandleRRE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleRRE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleRRE32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleCoRRE32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleHextile32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltra32(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleUltraZip32(rfbClient* client, int rx, int ry, int rw, int rh); +#ifdef LIBVNCSERVER_HAVE_LIBZ +static rfbBool HandleZlib8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZlib16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZlib32(rfbClient* client, int rx, int ry, int rw, int rh); +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +static rfbBool HandleTight8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTight16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleTight32(rfbClient* client, int rx, int ry, int rw, int rh); + +static long ReadCompactLen (rfbClient* client); + +static void JpegInitSource(j_decompress_ptr cinfo); +static boolean JpegFillInputBuffer(j_decompress_ptr cinfo); +static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes); +static void JpegTermSource(j_decompress_ptr cinfo); +static void JpegSetSrcManager(j_decompress_ptr cinfo, uint8_t *compressedData, + int compressedLen); +#endif +static rfbBool HandleZRLE8(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE15(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE16(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24Up(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE24Down(rfbClient* client, int rx, int ry, int rw, int rh); +static rfbBool HandleZRLE32(rfbClient* client, int rx, int ry, int rw, int rh); +#endif + +/* + * Server Capability Functions + */ +rfbBool +SupportsClient2Server(rfbClient* client, int messageType) +{ + return (client->supportedMessages.client2server[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE); +} + +rfbBool +SupportsServer2Client(rfbClient* client, int messageType) +{ + return (client->supportedMessages.server2client[((messageType & 0xFF)/8)] & (1<<(messageType % 8)) ? TRUE : FALSE); +} + +void +SetClient2Server(rfbClient* client, int messageType) +{ + client->supportedMessages.client2server[((messageType & 0xFF)/8)] |= (1<<(messageType % 8)); +} + +void +SetServer2Client(rfbClient* client, int messageType) +{ + client->supportedMessages.server2client[((messageType & 0xFF)/8)] |= (1<<(messageType % 8)); +} + +void +ClearClient2Server(rfbClient* client, int messageType) +{ + client->supportedMessages.client2server[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8))); +} + +void +ClearServer2Client(rfbClient* client, int messageType) +{ + client->supportedMessages.server2client[((messageType & 0xFF)/8)] &= (!(1<<(messageType % 8))); +} + + +void +DefaultSupportedMessages(rfbClient* client) +{ + memset((char *)&client->supportedMessages,0,sizeof(client->supportedMessages)); + + /* Default client supported messages (universal RFB 3.3 protocol) */ + SetClient2Server(client, rfbSetPixelFormat); + /* SetClient2Server(client, rfbFixColourMapEntries); Not currently supported */ + SetClient2Server(client, rfbSetEncodings); + SetClient2Server(client, rfbFramebufferUpdateRequest); + SetClient2Server(client, rfbKeyEvent); + SetClient2Server(client, rfbPointerEvent); + SetClient2Server(client, rfbClientCutText); + /* technically, we only care what we can *send* to the server + * but, we set Server2Client Just in case it ever becomes useful + */ + SetServer2Client(client, rfbFramebufferUpdate); + SetServer2Client(client, rfbSetColourMapEntries); + SetServer2Client(client, rfbBell); + SetServer2Client(client, rfbServerCutText); +} + +void +DefaultSupportedMessagesUltraVNC(rfbClient* client) +{ + DefaultSupportedMessages(client); + SetClient2Server(client, rfbFileTransfer); + SetClient2Server(client, rfbSetScale); + SetClient2Server(client, rfbSetServerInput); + SetClient2Server(client, rfbSetSW); + SetClient2Server(client, rfbTextChat); + SetClient2Server(client, rfbPalmVNCSetScaleFactor); + /* technically, we only care what we can *send* to the server */ + SetServer2Client(client, rfbResizeFrameBuffer); + SetServer2Client(client, rfbPalmVNCReSizeFrameBuffer); + SetServer2Client(client, rfbFileTransfer); + SetServer2Client(client, rfbTextChat); +} + + +void +DefaultSupportedMessagesTightVNC(rfbClient* client) +{ + DefaultSupportedMessages(client); + SetClient2Server(client, rfbFileTransfer); + SetClient2Server(client, rfbSetServerInput); + SetClient2Server(client, rfbSetSW); + /* SetClient2Server(client, rfbTextChat); */ + /* technically, we only care what we can *send* to the server */ + SetServer2Client(client, rfbFileTransfer); + SetServer2Client(client, rfbTextChat); +} + +#ifndef WIN32 +static rfbBool +IsUnixSocket(const char *name) +{ + struct stat sb; + if(stat(name, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFSOCK) + return TRUE; + return FALSE; +} +#endif + +/* + * ConnectToRFBServer. + */ + +rfbBool +ConnectToRFBServer(rfbClient* client,const char *hostname, int port) +{ + unsigned int host; + + if (client->serverPort==-1) { + /* serverHost is a file recorded by vncrec. */ + const char* magic="vncLog0.0"; + char buffer[10]; + rfbVNCRec* rec = (rfbVNCRec*)malloc(sizeof(rfbVNCRec)); + client->vncRec = rec; + + rec->file = fopen(client->serverHost,"rb"); + rec->tv.tv_sec = 0; + rec->readTimestamp = FALSE; + rec->doNotSleep = FALSE; + + if (!rec->file) { + rfbClientLog("Could not open %s.\n",client->serverHost); + return FALSE; + } + setbuf(rec->file,NULL); + fread(buffer,1,strlen(magic),rec->file); + if (strncmp(buffer,magic,strlen(magic))) { + rfbClientLog("File %s was not recorded by vncrec.\n",client->serverHost); + fclose(rec->file); + return FALSE; + } + client->sock = -1; + return TRUE; + } + +#ifndef WIN32 + if(IsUnixSocket(hostname)) + /* serverHost is a UNIX socket. */ + client->sock = ConnectClientToUnixSock(hostname); + else +#endif + { + /* serverHost is a hostname */ + if (!StringToIPAddr(hostname, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", hostname); + return FALSE; + } + client->sock = ConnectClientToTcpAddr(host, port); + } + + if (client->sock < 0) { + rfbClientLog("Unable to connect to VNC server\n"); + return FALSE; + } + + return SetNonBlocking(client->sock); +} + +/* + * ConnectToRFBRepeater. + */ + +rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort) +{ + unsigned int host; + rfbProtocolVersionMsg pv; + int major,minor; + char tmphost[250]; + + if (!StringToIPAddr(repeaterHost, &host)) { + rfbClientLog("Couldn't convert '%s' to host address\n", repeaterHost); + return FALSE; + } + + client->sock = ConnectClientToTcpAddr(host, repeaterPort); + + if (client->sock < 0) { + rfbClientLog("Unable to connect to VNC repeater\n"); + return FALSE; + } + + if (!SetNonBlocking(client->sock)) + return FALSE; + + if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) + return FALSE; + pv[sz_rfbProtocolVersionMsg] = 0; + + /* UltraVNC repeater always report version 000.000 to identify itself */ + if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2 || major != 0 || minor != 0) { + rfbClientLog("Not a valid VNC repeater (%s)\n",pv); + return FALSE; + } + + rfbClientLog("Connected to VNC repeater, using protocol version %d.%d\n", major, minor); + + snprintf(tmphost, sizeof(tmphost), "%s:%d", destHost, destPort); + if (!WriteToRFBServer(client, tmphost, sizeof(tmphost))) + return FALSE; + + return TRUE; +} + +extern void rfbClientEncryptBytes(unsigned char* bytes, char* passwd); +extern void rfbClientEncryptBytes2(unsigned char *where, const int length, unsigned char *key); + +rfbBool +rfbHandleAuthResult(rfbClient* client) +{ + uint32_t authResult=0, reasonLen=0; + char *reason=NULL; + + if (!ReadFromRFBServer(client, (char *)&authResult, 4)) return FALSE; + + authResult = rfbClientSwap32IfLE(authResult); + + switch (authResult) { + case rfbVncAuthOK: + rfbClientLog("VNC authentication succeeded\n"); + return TRUE; + break; + case rfbVncAuthFailed: + if (client->major==3 && client->minor>7) + { + /* we have an error following */ + if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return FALSE; + reasonLen = rfbClientSwap32IfLE(reasonLen); + reason = malloc(reasonLen+1); + if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return FALSE; } + reason[reasonLen]=0; + rfbClientLog("VNC connection failed: %s\n",reason); + free(reason); + return FALSE; + } + rfbClientLog("VNC authentication failed\n"); + return FALSE; + case rfbVncAuthTooMany: + rfbClientLog("VNC authentication failed - too many tries\n"); + return FALSE; + } + + rfbClientLog("Unknown VNC authentication result: %d\n", + (int)authResult); + return FALSE; +} + +static void +ReadReason(rfbClient* client) +{ + uint32_t reasonLen; + char *reason; + + /* we have an error following */ + if (!ReadFromRFBServer(client, (char *)&reasonLen, 4)) return; + reasonLen = rfbClientSwap32IfLE(reasonLen); + reason = malloc(reasonLen+1); + if (!ReadFromRFBServer(client, reason, reasonLen)) { free(reason); return; } + reason[reasonLen]=0; + rfbClientLog("VNC connection failed: %s\n",reason); + free(reason); +} + +static rfbBool +ReadSupportedSecurityType(rfbClient* client, uint32_t *result, rfbBool subAuth) +{ + uint8_t count=0; + uint8_t loop=0; + uint8_t flag=0; + uint8_t tAuth[256]; + char buf1[500],buf2[10]; + uint32_t authScheme; + + if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; + + if (count==0) + { + rfbClientLog("List of security types is ZERO, expecting an error to follow\n"); + ReadReason(client); + return FALSE; + } + if (count>sizeof(tAuth)) + { + rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); + return FALSE; + } + + rfbClientLog("We have %d security types to read\n", count); + authScheme=0; + /* now, we have a list of available security types to read ( uint8_t[] ) */ + for (loop=0;loopclientAuthSchemes) + { + int i; + for (i=0;client->clientAuthSchemes[i];i++) + { + if (client->clientAuthSchemes[i]==(uint32_t)tAuth[loop]) + { + flag++; + authScheme=tAuth[loop]; + break; + } + } + } + else + { + flag++; + authScheme=tAuth[loop]; + } + if (flag) + { + rfbClientLog("Selecting security type %d (%d/%d in the list)\n", authScheme, loop, count); + /* send back a single byte indicating which security type to use */ + if (!WriteToRFBServer(client, (char *)&tAuth[loop], 1)) return FALSE; + } + } + } + if (authScheme==0) + { + memset(buf1, 0, sizeof(buf1)); + for (loop=0;loop=sizeof(buf1)-1) break; + snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); + strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); + } + rfbClientLog("Unknown authentication scheme from VNC server: %s\n", + buf1); + return FALSE; + } + *result = authScheme; + return TRUE; +} + +static rfbBool +HandleVncAuth(rfbClient *client) +{ + uint8_t challenge[CHALLENGESIZE]; + char *passwd=NULL; + int i; + + if (!ReadFromRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE; + + if (client->serverPort!=-1) { /* if not playing a vncrec file */ + if (client->GetPassword) + passwd = client->GetPassword(client); + + if ((!passwd) || (strlen(passwd) == 0)) { + rfbClientLog("Reading password failed\n"); + return FALSE; + } + if (strlen(passwd) > 8) { + passwd[8] = '\0'; + } + + rfbClientEncryptBytes(challenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + free(passwd); + + if (!WriteToRFBServer(client, (char *)challenge, CHALLENGESIZE)) return FALSE; + } + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +static void +FreeUserCredential(rfbCredential *cred) +{ + if (cred->userCredential.username) free(cred->userCredential.username); + if (cred->userCredential.password) free(cred->userCredential.password); + free(cred); +} + +static rfbBool +HandlePlainAuth(rfbClient *client) +{ + uint32_t ulen, ulensw; + uint32_t plen, plensw; + rfbCredential *cred; + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + cred = client->GetCredential(client, rfbCredentialTypeUser); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + ulen = (cred->userCredential.username ? strlen(cred->userCredential.username) : 0); + ulensw = rfbClientSwap32IfLE(ulen); + plen = (cred->userCredential.password ? strlen(cred->userCredential.password) : 0); + plensw = rfbClientSwap32IfLE(plen); + if (!WriteToRFBServer(client, (char *)&ulensw, 4) || + !WriteToRFBServer(client, (char *)&plensw, 4)) + { + FreeUserCredential(cred); + return FALSE; + } + if (ulen > 0) + { + if (!WriteToRFBServer(client, cred->userCredential.username, ulen)) + { + FreeUserCredential(cred); + return FALSE; + } + } + if (plen > 0) + { + if (!WriteToRFBServer(client, cred->userCredential.password, plen)) + { + FreeUserCredential(cred); + return FALSE; + } + } + + FreeUserCredential(cred); + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +/* Simple 64bit big integer arithmetic implementation */ +/* (x + y) % m, works even if (x + y) > 64bit */ +#define rfbAddM64(x,y,m) ((x+y)%m+(x+y0;x>>=1) + { + if (x&1) r=rfbAddM64(r,y,m); + y=rfbAddM64(y,y,m); + } + return r; +} +/* (x ^ y) % m */ +static uint64_t +rfbPowM64(uint64_t b, uint64_t e, uint64_t m) +{ + uint64_t r; + for(r=1;e>0;e>>=1) + { + if(e&1) r=rfbMulM64(r,b,m); + b=rfbMulM64(b,b,m); + } + return r; +} + +static rfbBool +HandleMSLogonAuth(rfbClient *client) +{ + uint64_t gen, mod, resp, priv, pub, key; + uint8_t username[256], password[64]; + rfbCredential *cred; + + if (!ReadFromRFBServer(client, (char *)&gen, 8)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&mod, 8)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&resp, 8)) return FALSE; + gen = rfbClientSwap64IfLE(gen); + mod = rfbClientSwap64IfLE(mod); + resp = rfbClientSwap64IfLE(resp); + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + rfbClientLog("WARNING! MSLogon security type has very low password encryption! "\ + "Use it only with SSH tunnel or trusted network.\n"); + cred = client->GetCredential(client, rfbCredentialTypeUser); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + memset(username, 0, sizeof(username)); + strncpy((char *)username, cred->userCredential.username, sizeof(username)); + memset(password, 0, sizeof(password)); + strncpy((char *)password, cred->userCredential.password, sizeof(password)); + FreeUserCredential(cred); + + srand(time(NULL)); + priv = ((uint64_t)rand())<<32; + priv |= (uint64_t)rand(); + + pub = rfbPowM64(gen, priv, mod); + key = rfbPowM64(resp, priv, mod); + pub = rfbClientSwap64IfLE(pub); + key = rfbClientSwap64IfLE(key); + + rfbClientEncryptBytes2(username, sizeof(username), (unsigned char *)&key); + rfbClientEncryptBytes2(password, sizeof(password), (unsigned char *)&key); + + if (!WriteToRFBServer(client, (char *)&pub, 8)) return FALSE; + if (!WriteToRFBServer(client, (char *)username, sizeof(username))) return FALSE; + if (!WriteToRFBServer(client, (char *)password, sizeof(password))) return FALSE; + + /* Handle the SecurityResult message */ + if (!rfbHandleAuthResult(client)) return FALSE; + + return TRUE; +} + +/* + * SetClientAuthSchemes. + */ + +void +SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size) +{ + int i; + + if (client->clientAuthSchemes) + { + free(client->clientAuthSchemes); + client->clientAuthSchemes = NULL; + } + if (authSchemes) + { + if (size<0) + { + /* If size<0 we assume the passed-in list is also 0-terminate, so we + * calculate the size here */ + for (size=0;authSchemes[size];size++) ; + } + client->clientAuthSchemes = (uint32_t*)malloc(sizeof(uint32_t)*(size+1)); + for (i=0;iclientAuthSchemes[i] = authSchemes[i]; + client->clientAuthSchemes[size] = 0; + } +} + +/* + * InitialiseRFBConnection. + */ + +rfbBool +InitialiseRFBConnection(rfbClient* client) +{ + rfbProtocolVersionMsg pv; + int major,minor; + uint32_t authScheme; + uint32_t subAuthScheme; + rfbClientInitMsg ci; + + /* if the connection is immediately closed, don't report anything, so + that pmw's monitor can make test connections */ + + if (client->listenSpecified) + errorMessageOnReadFailure = FALSE; + + if (!ReadFromRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE; + pv[sz_rfbProtocolVersionMsg]=0; + + errorMessageOnReadFailure = TRUE; + + pv[sz_rfbProtocolVersionMsg] = 0; + + if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) { + rfbClientLog("Not a valid VNC server (%s)\n",pv); + return FALSE; + } + + + DefaultSupportedMessages(client); + client->major = major; + client->minor = minor; + + /* fall back to viewer supported version */ + if ((major==rfbProtocolMajorVersion) && (minor>rfbProtocolMinorVersion)) + client->minor = rfbProtocolMinorVersion; + + /* UltraVNC uses minor codes 4 and 6 for the server */ + if (major==3 && (minor==4 || minor==6)) { + rfbClientLog("UltraVNC server detected, enabling UltraVNC specific messages\n",pv); + DefaultSupportedMessagesUltraVNC(client); + } + + /* TightVNC uses minor codes 5 for the server */ + if (major==3 && minor==5) { + rfbClientLog("TightVNC server detected, enabling TightVNC specific messages\n",pv); + DefaultSupportedMessagesTightVNC(client); + } + + /* we do not support > RFB3.8 */ + if ((major==3 && minor>8) || major>3) + { + client->major=3; + client->minor=8; + } + + rfbClientLog("VNC server supports protocol version %d.%d (viewer %d.%d)\n", + major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion); + + sprintf(pv,rfbProtocolVersionFormat,client->major,client->minor); + + if (!WriteToRFBServer(client, pv, sz_rfbProtocolVersionMsg)) return FALSE; + + + /* 3.7 and onwards sends a # of security types first */ + if (client->major==3 && client->minor > 6) + { + if (!ReadSupportedSecurityType(client, &authScheme, FALSE)) return FALSE; + } + else + { + if (!ReadFromRFBServer(client, (char *)&authScheme, 4)) return FALSE; + authScheme = rfbClientSwap32IfLE(authScheme); + } + + rfbClientLog("Selected Security Scheme %d\n", authScheme); + client->authScheme = authScheme; + + switch (authScheme) { + + case rfbConnFailed: + ReadReason(client); + return FALSE; + + case rfbNoAuth: + rfbClientLog("No authentication needed\n"); + + /* 3.8 and upwards sends a Security Result for rfbNoAuth */ + if ((client->major==3 && client->minor > 7) || client->major>3) + if (!rfbHandleAuthResult(client)) return FALSE; + + break; + + case rfbVncAuth: + if (!HandleVncAuth(client)) return FALSE; + break; + + case rfbMSLogon: + if (!HandleMSLogonAuth(client)) return FALSE; + break; + + case rfbTLS: +#ifndef LIBVNCSERVER_WITH_CLIENT_TLS + rfbClientLog("TLS support was not compiled in\n"); + return FALSE; +#else + if (!HandleAnonTLSAuth(client)) return FALSE; + /* After the TLS session is established, sub auth types are expected. + * Note that all following reading/writing are through the TLS session from here. + */ + if (!ReadSupportedSecurityType(client, &subAuthScheme, TRUE)) return FALSE; + client->subAuthScheme = subAuthScheme; + + switch (subAuthScheme) { + + case rfbConnFailed: + ReadReason(client); + return FALSE; + + case rfbNoAuth: + rfbClientLog("No sub authentication needed\n"); + /* 3.8 and upwards sends a Security Result for rfbNoAuth */ + if ((client->major==3 && client->minor > 7) || client->major>3) + if (!rfbHandleAuthResult(client)) return FALSE; + break; + + case rfbVncAuth: + if (!HandleVncAuth(client)) return FALSE; + break; + + default: + rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", + (int)subAuthScheme); + return FALSE; + } +#endif + + break; + + case rfbVeNCrypt: +#ifndef LIBVNCSERVER_WITH_CLIENT_TLS + rfbClientLog("TLS support was not compiled in\n"); + return FALSE; +#else + if (!HandleVeNCryptAuth(client)) return FALSE; + + switch (client->subAuthScheme) { + + case rfbVeNCryptTLSNone: + case rfbVeNCryptX509None: + rfbClientLog("No sub authentication needed\n"); + if (!rfbHandleAuthResult(client)) return FALSE; + break; + + case rfbVeNCryptTLSVNC: + case rfbVeNCryptX509VNC: + if (!HandleVncAuth(client)) return FALSE; + break; + + case rfbVeNCryptTLSPlain: + case rfbVeNCryptX509Plain: + if (!HandlePlainAuth(client)) return FALSE; + break; + + default: + rfbClientLog("Unknown sub authentication scheme from VNC server: %d\n", + client->subAuthScheme); + return FALSE; + } +#endif + break; + + default: + rfbClientLog("Unknown authentication scheme from VNC server: %d\n", + (int)authScheme); + return FALSE; + } + + ci.shared = (client->appData.shareDesktop ? 1 : 0); + + if (!WriteToRFBServer(client, (char *)&ci, sz_rfbClientInitMsg)) return FALSE; + + if (!ReadFromRFBServer(client, (char *)&client->si, sz_rfbServerInitMsg)) return FALSE; + + client->si.framebufferWidth = rfbClientSwap16IfLE(client->si.framebufferWidth); + client->si.framebufferHeight = rfbClientSwap16IfLE(client->si.framebufferHeight); + client->si.format.redMax = rfbClientSwap16IfLE(client->si.format.redMax); + client->si.format.greenMax = rfbClientSwap16IfLE(client->si.format.greenMax); + client->si.format.blueMax = rfbClientSwap16IfLE(client->si.format.blueMax); + client->si.nameLength = rfbClientSwap32IfLE(client->si.nameLength); + + client->desktopName = malloc(client->si.nameLength + 1); + if (!client->desktopName) { + rfbClientLog("Error allocating memory for desktop name, %lu bytes\n", + (unsigned long)client->si.nameLength); + return FALSE; + } + + if (!ReadFromRFBServer(client, client->desktopName, client->si.nameLength)) return FALSE; + + client->desktopName[client->si.nameLength] = 0; + + rfbClientLog("Desktop name \"%s\"\n",client->desktopName); + + rfbClientLog("Connected to VNC server, using protocol version %d.%d\n", + client->major, client->minor); + + rfbClientLog("VNC server default format:\n"); + PrintPixelFormat(&client->si.format); + + return TRUE; +} + + +/* + * SetFormatAndEncodings. + */ + +rfbBool +SetFormatAndEncodings(rfbClient* client) +{ + rfbSetPixelFormatMsg spf; + char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4]; + + rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf; + uint32_t *encs = (uint32_t *)(&buf[sz_rfbSetEncodingsMsg]); + int len = 0; + rfbBool requestCompressLevel = FALSE; + rfbBool requestQualityLevel = FALSE; + rfbBool requestLastRectEncoding = FALSE; + rfbClientProtocolExtension* e; + + if (!SupportsClient2Server(client, rfbSetPixelFormat)) return TRUE; + + spf.type = rfbSetPixelFormat; + spf.format = client->format; + spf.format.redMax = rfbClientSwap16IfLE(spf.format.redMax); + spf.format.greenMax = rfbClientSwap16IfLE(spf.format.greenMax); + spf.format.blueMax = rfbClientSwap16IfLE(spf.format.blueMax); + + if (!WriteToRFBServer(client, (char *)&spf, sz_rfbSetPixelFormatMsg)) + return FALSE; + + + if (!SupportsClient2Server(client, rfbSetEncodings)) return TRUE; + + se->type = rfbSetEncodings; + se->nEncodings = 0; + + if (client->appData.encodingsString) { + const char *encStr = client->appData.encodingsString; + int encStrLen; + do { + const char *nextEncStr = strchr(encStr, ' '); + if (nextEncStr) { + encStrLen = nextEncStr - encStr; + nextEncStr++; + } else { + encStrLen = strlen(encStr); + } + + if (strncasecmp(encStr,"raw",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw); + } else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect); +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + } else if (strncasecmp(encStr,"tight",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight); + requestLastRectEncoding = TRUE; + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + if (client->appData.enableJPEG) + requestQualityLevel = TRUE; +#endif +#endif + } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile); +#ifdef LIBVNCSERVER_HAVE_LIBZ + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"zlibhex",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlibHex); + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) + requestCompressLevel = TRUE; + } else if (strncasecmp(encStr,"zrle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE); + requestQualityLevel = TRUE; +#endif + } else if ((strncasecmp(encStr,"ultra",encStrLen) == 0) || (strncasecmp(encStr,"ultrazip",encStrLen) == 0)) { + /* There are 2 encodings used in 'ultra' */ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip); + } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); + } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); + } else { + rfbClientLog("Unknown encoding '%.*s'\n",encStrLen,encStr); + } + + encStr = nextEncStr; + } while (encStr && se->nEncodings < MAX_ENCODINGS); + + if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel + + rfbEncodingCompressLevel0); + } + + if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { + if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9) + client->appData.qualityLevel = 5; + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel + + rfbEncodingQualityLevel0); + } + } + else { + if (SameMachine(client->sock)) { + /* TODO: + if (!tunnelSpecified) { + */ + rfbClientLog("Same machine: preferring raw encoding\n"); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRaw); + /* + } else { + rfbClientLog("Tunneling active: preferring tight encoding\n"); + } + */ + } + + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCopyRect); +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingTight); + requestLastRectEncoding = TRUE; +#endif +#endif + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingHextile); +#ifdef LIBVNCSERVER_HAVE_LIBZ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZlib); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZRLE); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingZYWRLE); +#endif + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltra); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingUltraZip); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCoRRE); + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRRE); + + if (client->appData.compressLevel >= 0 && client->appData.compressLevel <= 9) { + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.compressLevel + + rfbEncodingCompressLevel0); + } else /* if (!tunnelSpecified) */ { + /* If -tunnel option was provided, we assume that server machine is + not in the local network so we use default compression level for + tight encoding instead of fast compression. Thus we are + requesting level 1 compression only if tunneling is not used. */ + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingCompressLevel1); + } + + if (client->appData.enableJPEG) { + if (client->appData.qualityLevel < 0 || client->appData.qualityLevel > 9) + client->appData.qualityLevel = 5; + encs[se->nEncodings++] = rfbClientSwap32IfLE(client->appData.qualityLevel + + rfbEncodingQualityLevel0); + } + } + + + + /* Remote Cursor Support (local to viewer) */ + if (client->appData.useRemoteCursor) { + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingRichCursor); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos); + } + + /* Keyboard State Encodings */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState); + + /* New Frame Buffer Size */ + if (se->nEncodings < MAX_ENCODINGS && client->canHandleNewFBSize) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingNewFBSize); + + /* Last Rect */ + if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect); + + /* Server Capabilities */ + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedMessages); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingSupportedEncodings); + if (se->nEncodings < MAX_ENCODINGS) + encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingServerIdentity); + + + /* client extensions */ + for(e = rfbClientExtensions; e; e = e->next) + if(e->encodings) { + int* enc; + for(enc = e->encodings; *enc; enc++) + encs[se->nEncodings++] = rfbClientSwap32IfLE(*enc); + } + + len = sz_rfbSetEncodingsMsg + se->nEncodings * 4; + + se->nEncodings = rfbClientSwap16IfLE(se->nEncodings); + + if (!WriteToRFBServer(client, buf, len)) return FALSE; + + return TRUE; +} + + +/* + * SendIncrementalFramebufferUpdateRequest. + */ + +rfbBool +SendIncrementalFramebufferUpdateRequest(rfbClient* client) +{ + return SendFramebufferUpdateRequest(client, + client->updateRect.x, client->updateRect.y, + client->updateRect.w, client->updateRect.h, TRUE); +} + + +/* + * SendFramebufferUpdateRequest. + */ + +rfbBool +SendFramebufferUpdateRequest(rfbClient* client, int x, int y, int w, int h, rfbBool incremental) +{ + rfbFramebufferUpdateRequestMsg fur; + + if (!SupportsClient2Server(client, rfbFramebufferUpdateRequest)) return TRUE; + + fur.type = rfbFramebufferUpdateRequest; + fur.incremental = incremental ? 1 : 0; + fur.x = rfbClientSwap16IfLE(x); + fur.y = rfbClientSwap16IfLE(y); + fur.w = rfbClientSwap16IfLE(w); + fur.h = rfbClientSwap16IfLE(h); + + if (!WriteToRFBServer(client, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg)) + return FALSE; + + return TRUE; +} + + +/* + * SendScaleSetting. + */ +rfbBool +SendScaleSetting(rfbClient* client,int scaleSetting) +{ + rfbSetScaleMsg ssm; + + ssm.scale = scaleSetting; + ssm.pad = 0; + + /* favor UltraVNC SetScale if both are supported */ + if (SupportsClient2Server(client, rfbSetScale)) { + ssm.type = rfbSetScale; + if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg)) + return FALSE; + } + + if (SupportsClient2Server(client, rfbPalmVNCSetScaleFactor)) { + ssm.type = rfbPalmVNCSetScaleFactor; + if (!WriteToRFBServer(client, (char *)&ssm, sz_rfbSetScaleMsg)) + return FALSE; + } + + return TRUE; +} + +/* + * TextChatFunctions (UltraVNC) + * Extremely bandwidth friendly method of communicating with a user + * (Think HelpDesk type applications) + */ + +rfbBool TextChatSend(rfbClient* client, char *text) +{ + rfbTextChatMsg chat; + int count = strlen(text); + + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = (uint32_t)count; + chat.length = rfbClientSwap32IfLE(chat.length); + + if (!WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg)) + return FALSE; + + if (count>0) { + if (!WriteToRFBServer(client, text, count)) + return FALSE; + } + return TRUE; +} + +rfbBool TextChatOpen(rfbClient* client) +{ + rfbTextChatMsg chat; + + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatOpen); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +rfbBool TextChatClose(rfbClient* client) +{ + rfbTextChatMsg chat; + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatClose); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +rfbBool TextChatFinish(rfbClient* client) +{ + rfbTextChatMsg chat; + if (!SupportsClient2Server(client, rfbTextChat)) return TRUE; + chat.type = rfbTextChat; + chat.pad1 = 0; + chat.pad2 = 0; + chat.length = rfbClientSwap32IfLE(rfbTextChatFinished); + return (WriteToRFBServer(client, (char *)&chat, sz_rfbTextChatMsg) ? TRUE : FALSE); +} + +/* + * UltraVNC Server Input Disable + * Apparently, the remote client can *prevent* the local user from interacting with the display + * I would think this is extremely helpful when used in a HelpDesk situation + */ +rfbBool PermitServerInput(rfbClient* client, int enabled) +{ + rfbSetServerInputMsg msg; + + if (!SupportsClient2Server(client, rfbSetServerInput)) return TRUE; + /* enabled==1, then server input from local keyboard is disabled */ + msg.type = rfbSetServerInput; + msg.status = (enabled ? 1 : 0); + msg.pad = 0; + return (WriteToRFBServer(client, (char *)&msg, sz_rfbSetServerInputMsg) ? TRUE : FALSE); +} + + +/* + * SendPointerEvent. + */ + +rfbBool +SendPointerEvent(rfbClient* client,int x, int y, int buttonMask) +{ + rfbPointerEventMsg pe; + + if (!SupportsClient2Server(client, rfbPointerEvent)) return TRUE; + + pe.type = rfbPointerEvent; + pe.buttonMask = buttonMask; + if (x < 0) x = 0; + if (y < 0) y = 0; + + pe.x = rfbClientSwap16IfLE(x); + pe.y = rfbClientSwap16IfLE(y); + return WriteToRFBServer(client, (char *)&pe, sz_rfbPointerEventMsg); +} + + +/* + * SendKeyEvent. + */ + +rfbBool +SendKeyEvent(rfbClient* client, uint32_t key, rfbBool down) +{ + rfbKeyEventMsg ke; + + if (!SupportsClient2Server(client, rfbKeyEvent)) return TRUE; + + ke.type = rfbKeyEvent; + ke.down = down ? 1 : 0; + ke.key = rfbClientSwap32IfLE(key); + return WriteToRFBServer(client, (char *)&ke, sz_rfbKeyEventMsg); +} + + +/* + * SendClientCutText. + */ + +rfbBool +SendClientCutText(rfbClient* client, char *str, int len) +{ + rfbClientCutTextMsg cct; + + if (!SupportsClient2Server(client, rfbClientCutText)) return TRUE; + + cct.type = rfbClientCutText; + cct.length = rfbClientSwap32IfLE(len); + return (WriteToRFBServer(client, (char *)&cct, sz_rfbClientCutTextMsg) && + WriteToRFBServer(client, str, len)); +} + + + +/* + * HandleRFBServerMessage. + */ + +rfbBool +HandleRFBServerMessage(rfbClient* client) +{ + rfbServerToClientMsg msg; + + if (client->serverPort==-1) + client->vncRec->readTimestamp = TRUE; + if (!ReadFromRFBServer(client, (char *)&msg, 1)) + return FALSE; + + switch (msg.type) { + + case rfbSetColourMapEntries: + { + /* TODO: + int i; + uint16_t rgb[3]; + XColor xc; + + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbSetColourMapEntriesMsg - 1)) + return FALSE; + + msg.scme.firstColour = rfbClientSwap16IfLE(msg.scme.firstColour); + msg.scme.nColours = rfbClientSwap16IfLE(msg.scme.nColours); + + for (i = 0; i < msg.scme.nColours; i++) { + if (!ReadFromRFBServer(client, (char *)rgb, 6)) + return FALSE; + xc.pixel = msg.scme.firstColour + i; + xc.red = rfbClientSwap16IfLE(rgb[0]); + xc.green = rfbClientSwap16IfLE(rgb[1]); + xc.blue = rfbClientSwap16IfLE(rgb[2]); + xc.flags = DoRed|DoGreen|DoBlue; + XStoreColor(dpy, cmap, &xc); + } + */ + + break; + } + + case rfbFramebufferUpdate: + { + rfbFramebufferUpdateRectHeader rect; + int linesToRead; + int bytesPerLine; + int i; + + if (!ReadFromRFBServer(client, ((char *)&msg.fu) + 1, + sz_rfbFramebufferUpdateMsg - 1)) + return FALSE; + + msg.fu.nRects = rfbClientSwap16IfLE(msg.fu.nRects); + + for (i = 0; i < msg.fu.nRects; i++) { + if (!ReadFromRFBServer(client, (char *)&rect, sz_rfbFramebufferUpdateRectHeader)) + return FALSE; + + rect.encoding = rfbClientSwap32IfLE(rect.encoding); + if (rect.encoding == rfbEncodingLastRect) + break; + + rect.r.x = rfbClientSwap16IfLE(rect.r.x); + rect.r.y = rfbClientSwap16IfLE(rect.r.y); + rect.r.w = rfbClientSwap16IfLE(rect.r.w); + rect.r.h = rfbClientSwap16IfLE(rect.r.h); + + + if (rect.encoding == rfbEncodingXCursor || + rect.encoding == rfbEncodingRichCursor) { + + if (!HandleCursorShape(client, + rect.r.x, rect.r.y, rect.r.w, rect.r.h, + rect.encoding)) { + return FALSE; + } + continue; + } + + if (rect.encoding == rfbEncodingPointerPos) { + if (!client->HandleCursorPos(client,rect.r.x, rect.r.y)) { + return FALSE; + } + continue; + } + + if (rect.encoding == rfbEncodingKeyboardLedState) { + /* OK! We have received a keyboard state message!!! */ + client->KeyboardLedStateEnabled = 1; + if (client->HandleKeyboardLedState!=NULL) + client->HandleKeyboardLedState(client, rect.r.x, 0); + /* stash it for the future */ + client->CurrentKeyboardLedState = rect.r.x; + continue; + } + + if (rect.encoding == rfbEncodingNewFBSize) { + client->width = rect.r.w; + client->height = rect.r.h; + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, rect.r.w, rect.r.h, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", rect.r.w, rect.r.h); + continue; + } + + /* rect.r.w=byte count */ + if (rect.encoding == rfbEncodingSupportedMessages) { + int loop; + if (!ReadFromRFBServer(client, (char *)&client->supportedMessages, sz_rfbSupportedMessages)) + return FALSE; + + /* msgs is two sets of bit flags of supported messages client2server[] and server2client[] */ + /* currently ignored by this library */ + + rfbClientLog("client2server supported messages (bit flags)\n"); + for (loop=0;loop<32;loop+=8) + rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop, + client->supportedMessages.client2server[loop], client->supportedMessages.client2server[loop+1], + client->supportedMessages.client2server[loop+2], client->supportedMessages.client2server[loop+3], + client->supportedMessages.client2server[loop+4], client->supportedMessages.client2server[loop+5], + client->supportedMessages.client2server[loop+6], client->supportedMessages.client2server[loop+7]); + + rfbClientLog("server2client supported messages (bit flags)\n"); + for (loop=0;loop<32;loop+=8) + rfbClientLog("%02X: %04x %04x %04x %04x - %04x %04x %04x %04x\n", loop, + client->supportedMessages.server2client[loop], client->supportedMessages.server2client[loop+1], + client->supportedMessages.server2client[loop+2], client->supportedMessages.server2client[loop+3], + client->supportedMessages.server2client[loop+4], client->supportedMessages.server2client[loop+5], + client->supportedMessages.server2client[loop+6], client->supportedMessages.server2client[loop+7]); + continue; + } + + /* rect.r.w=byte count, rect.r.h=# of encodings */ + if (rect.encoding == rfbEncodingSupportedEncodings) { + char *buffer; + buffer = malloc(rect.r.w); + if (!ReadFromRFBServer(client, buffer, rect.r.w)) + { + free(buffer); + return FALSE; + } + + /* buffer now contains rect.r.h # of uint32_t encodings that the server supports */ + /* currently ignored by this library */ + free(buffer); + continue; + } + + /* rect.r.w=byte count */ + if (rect.encoding == rfbEncodingServerIdentity) { + char *buffer; + buffer = malloc(rect.r.w+1); + if (!ReadFromRFBServer(client, buffer, rect.r.w)) + { + free(buffer); + return FALSE; + } + buffer[rect.r.w]=0; /* null terminate, just in case */ + rfbClientLog("Connected to Server \"%s\"\n", buffer); + free(buffer); + continue; + } + + /* rfbEncodingUltraZip is a collection of subrects. x = # of subrects, and h is always 0 */ + if (rect.encoding != rfbEncodingUltraZip) + { + if ((rect.r.x + rect.r.w > client->width) || + (rect.r.y + rect.r.h > client->height)) + { + rfbClientLog("Rect too large: %dx%d at (%d, %d)\n", + rect.r.w, rect.r.h, rect.r.x, rect.r.y); + return FALSE; + } + + /* UltraVNC with scaling, will send rectangles with a zero W or H + * + if ((rect.encoding != rfbEncodingTight) && + (rect.r.h * rect.r.w == 0)) + { + rfbClientLog("Zero size rect - ignoring (encoding=%d (0x%08x) %dx, %dy, %dw, %dh)\n", rect.encoding, rect.encoding, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + continue; + } + */ + + /* If RichCursor encoding is used, we should prevent collisions + between framebuffer updates and cursor drawing operations. */ + client->SoftCursorLockArea(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + } + + switch (rect.encoding) { + + case rfbEncodingRaw: { + int y=rect.r.y, h=rect.r.h; + + bytesPerLine = rect.r.w * client->format.bitsPerPixel / 8; + linesToRead = RFB_BUFFER_SIZE / bytesPerLine; + + while (h > 0) { + if (linesToRead > h) + linesToRead = h; + + if (!ReadFromRFBServer(client, client->buffer,bytesPerLine * linesToRead)) + return FALSE; + + CopyRectangle(client, (uint8_t *)client->buffer, + rect.r.x, y, rect.r.w,linesToRead); + + h -= linesToRead; + y += linesToRead; + + } + } break; + + case rfbEncodingCopyRect: + { + rfbCopyRect cr; + + if (!ReadFromRFBServer(client, (char *)&cr, sz_rfbCopyRect)) + return FALSE; + + cr.srcX = rfbClientSwap16IfLE(cr.srcX); + cr.srcY = rfbClientSwap16IfLE(cr.srcY); + + /* If RichCursor encoding is used, we should extend our + "cursor lock area" (previously set to destination + rectangle) to the source rectangle as well. */ + client->SoftCursorLockArea(client, + cr.srcX, cr.srcY, rect.r.w, rect.r.h); + + if (client->GotCopyRect != NULL) { + client->GotCopyRect(client, cr.srcX, cr.srcY, rect.r.w, rect.r.h, + rect.r.x, rect.r.y); + } else + CopyRectangleFromRectangle(client, + cr.srcX, cr.srcY, rect.r.w, rect.r.h, + rect.r.x, rect.r.y); + + break; + } + + case rfbEncodingRRE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingCoRRE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleCoRRE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleCoRRE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleCoRRE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingHextile: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleHextile8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleHextile16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleHextile32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + + case rfbEncodingUltra: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleUltra8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleUltra16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleUltra32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + case rfbEncodingUltraZip: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleUltraZip8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleUltraZip16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleUltraZip32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleZlib8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleZlib16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleZlib32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleTight8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (!HandleTight16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 32: + if (!HandleTight32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + break; + } +#endif + case rfbEncodingZRLE: + /* Fail safe for ZYWRLE unsupport VNC server. */ + client->appData.qualityLevel = 9; + /* fall through */ + case rfbEncodingZYWRLE: + { + switch (client->format.bitsPerPixel) { + case 8: + if (!HandleZRLE8(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + case 16: + if (client->si.format.greenMax > 0x1F) { + if (!HandleZRLE16(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else { + if (!HandleZRLE15(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } + break; + case 32: + { + uint32_t maxColor=(client->format.redMax<format.redShift)| + (client->format.greenMax<format.greenShift)| + (client->format.blueMax<format.blueShift); + if ((client->format.bigEndian && (maxColor&0xff)==0) || + (!client->format.bigEndian && (maxColor&0xff000000)==0)) { + if (!HandleZRLE24(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (!client->format.bigEndian && (maxColor&0xff)==0) { + if (!HandleZRLE24Up(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (client->format.bigEndian && (maxColor&0xff000000)==0) { + if (!HandleZRLE24Down(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + } else if (!HandleZRLE32(client, rect.r.x,rect.r.y,rect.r.w,rect.r.h)) + return FALSE; + break; + } + } + break; + } + +#endif + + default: + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleEncoding && e->handleEncoding(client, &rect)) + handled = TRUE; + + if(!handled) { + rfbClientLog("Unknown rect encoding %d\n", + (int)rect.encoding); + return FALSE; + } + } + } + + /* Now we may discard "soft cursor locks". */ + client->SoftCursorUnlockScreen(client); + + client->GotFrameBufferUpdate(client, rect.r.x, rect.r.y, rect.r.w, rect.r.h); + } + + if (!SendIncrementalFramebufferUpdateRequest(client)) + return FALSE; + + if (client->FinishedFrameBufferUpdate) + client->FinishedFrameBufferUpdate(client); + + break; + } + + case rfbBell: + { + client->Bell(client); + + break; + } + + case rfbServerCutText: + { + char *buffer; + + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbServerCutTextMsg - 1)) + return FALSE; + + msg.sct.length = rfbClientSwap32IfLE(msg.sct.length); + + buffer = malloc(msg.sct.length+1); + + if (!ReadFromRFBServer(client, buffer, msg.sct.length)) + return FALSE; + + buffer[msg.sct.length] = 0; + + if (client->GotXCutText) + client->GotXCutText(client, buffer, msg.sct.length); + + free(buffer); + + break; + } + + case rfbTextChat: + { + char *buffer=NULL; + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbTextChatMsg- 1)) + return FALSE; + msg.tc.length = rfbClientSwap32IfLE(msg.sct.length); + switch(msg.tc.length) { + case rfbTextChatOpen: + rfbClientLog("Received TextChat Open\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatOpen, NULL); + break; + case rfbTextChatClose: + rfbClientLog("Received TextChat Close\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatClose, NULL); + break; + case rfbTextChatFinished: + rfbClientLog("Received TextChat Finished\n"); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)rfbTextChatFinished, NULL); + break; + default: + buffer=malloc(msg.tc.length+1); + if (!ReadFromRFBServer(client, buffer, msg.tc.length)) + { + free(buffer); + return FALSE; + } + /* Null Terminate */ + buffer[msg.tc.length]=0; + rfbClientLog("Received TextChat \"%s\"\n", buffer); + if (client->HandleTextChat!=NULL) + client->HandleTextChat(client, (int)msg.tc.length, buffer); + free(buffer); + break; + } + break; + } + + case rfbResizeFrameBuffer: + { + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbResizeFrameBufferMsg -1)) + return FALSE; + client->width = rfbClientSwap16IfLE(msg.rsfb.framebufferWidth); + client->height = rfbClientSwap16IfLE(msg.rsfb.framebufferHeigth); + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; + } + + case rfbPalmVNCReSizeFrameBuffer: + { + if (!ReadFromRFBServer(client, ((char *)&msg) + 1, + sz_rfbPalmVNCReSizeFrameBufferMsg -1)) + return FALSE; + client->width = rfbClientSwap16IfLE(msg.prsfb.buffer_w); + client->height = rfbClientSwap16IfLE(msg.prsfb.buffer_h); + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + client->MallocFrameBuffer(client); + SendFramebufferUpdateRequest(client, 0, 0, client->width, client->height, FALSE); + rfbClientLog("Got new framebuffer size: %dx%d\n", client->width, client->height); + break; + } + + default: + { + rfbBool handled = FALSE; + rfbClientProtocolExtension* e; + + for(e = rfbClientExtensions; !handled && e; e = e->next) + if(e->handleMessage && e->handleMessage(client, &msg)) + handled = TRUE; + + if(!handled) { + char buffer[256]; + rfbClientLog("Unknown message type %d from VNC server\n",msg.type); + ReadFromRFBServer(client, buffer, 256); + return FALSE; + } + } + } + + return TRUE; +} + + +#define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++) + +#define GET_PIXEL16(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \ + ((uint8_t*)&(pix))[1] = *(ptr)++) + +#define GET_PIXEL32(pix, ptr) (((uint8_t*)&(pix))[0] = *(ptr)++, \ + ((uint8_t*)&(pix))[1] = *(ptr)++, \ + ((uint8_t*)&(pix))[2] = *(ptr)++, \ + ((uint8_t*)&(pix))[3] = *(ptr)++) + +/* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also + expands its arguments if they are macros */ + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) + +#define BPP 8 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#undef BPP +#define BPP 16 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#define REALBPP 15 +#include "zrle.c" +#undef BPP +#define BPP 32 +#include "rre.c" +#include "corre.c" +#include "hextile.c" +#include "ultra.c" +#include "zlib.c" +#include "tight.c" +#include "zrle.c" +#define REALBPP 24 +#include "zrle.c" +#define REALBPP 24 +#define UNCOMP 8 +#include "zrle.c" +#define REALBPP 24 +#define UNCOMP -8 +#include "zrle.c" +#undef BPP + + +/* + * PrintPixelFormat. + */ + +void +PrintPixelFormat(rfbPixelFormat *format) +{ + if (format->bitsPerPixel == 1) { + rfbClientLog(" Single bit per pixel.\n"); + rfbClientLog( + " %s significant bit in each byte is leftmost on the screen.\n", + (format->bigEndian ? "Most" : "Least")); + } else { + rfbClientLog(" %d bits per pixel.\n",format->bitsPerPixel); + if (format->bitsPerPixel != 8) { + rfbClientLog(" %s significant byte first in each pixel.\n", + (format->bigEndian ? "Most" : "Least")); + } + if (format->trueColour) { + rfbClientLog(" TRUE colour: max red %d green %d blue %d" + ", shift red %d green %d blue %d\n", + format->redMax, format->greenMax, format->blueMax, + format->redShift, format->greenShift, format->blueShift); + } else { + rfbClientLog(" Colour map (not true colour).\n"); + } + } +} + +/* avoid name clashes with LibVNCServer */ + +#define rfbEncryptBytes rfbClientEncryptBytes +#define rfbEncryptBytes2 rfbClientEncryptBytes2 +#define rfbDes rfbClientDes +#define rfbDesKey rfbClientDesKey +#define rfbUseKey rfbClientUseKey +#define rfbCPKey rfbClientCPKey + +#include "../libvncserver/vncauth.c" +#include "../libvncserver/d3des.c" diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c new file mode 100755 index 0000000..94158c9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/rre.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rre.c - handle RRE encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an RRE + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleRREBPP CONCAT2E(HandleRRE,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleRREBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbRREHeader hdr; + int i; + CARDBPP pix; + rfbRectangle subrect; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader)) + return FALSE; + + hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects); + + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + FillRectangle(client, rx, ry, rw, rh, pix); + + for (i = 0; i < hdr.nSubrects; i++) { + if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix))) + return FALSE; + + if (!ReadFromRFBServer(client, (char *)&subrect, sz_rfbRectangle)) + return FALSE; + + subrect.x = rfbClientSwap16IfLE(subrect.x); + subrect.y = rfbClientSwap16IfLE(subrect.y); + subrect.w = rfbClientSwap16IfLE(subrect.w); + subrect.h = rfbClientSwap16IfLE(subrect.h); + + FillRectangle(client, rx+subrect.x, ry+subrect.y, subrect.w, subrect.h, pix); + } + + return TRUE; +} + +#undef CARDBPP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c new file mode 100755 index 0000000..598dd39 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/sockets.c @@ -0,0 +1,616 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * sockets.c - functions to deal with sockets. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include +#include +#ifdef WIN32 +#undef SOCKET +#include +#define EWOULDBLOCK WSAEWOULDBLOCK +#define close closesocket +#define read(sock,buf,len) recv(sock,buf,len,0) +#define write(sock,buf,len) send(sock,buf,len,0) +#define socklen_t int +#else +#include +#include +#include +#include +#include +#include +#endif +#include "tls.h" + +void PrintInHex(char *buf, int len); + +rfbBool errorMessageOnReadFailure = TRUE; + +/* + * ReadFromRFBServer is called whenever we want to read some data from the RFB + * server. It is non-trivial for two reasons: + * + * 1. For efficiency it performs some intelligent buffering, avoiding invoking + * the read() system call too often. For small chunks of data, it simply + * copies the data out of an internal buffer. For large amounts of data it + * reads directly into the buffer provided by the caller. + * + * 2. Whenever read() would block, it invokes the Xt event dispatching + * mechanism to process X events. In fact, this is the only place these + * events are processed, as there is no XtAppMainLoop in the program. + */ + +rfbBool +ReadFromRFBServer(rfbClient* client, char *out, unsigned int n) +{ +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + char* oout=out; + int nn=n; + rfbClientLog("ReadFromRFBServer %d bytes\n",n); +#endif + if (client->serverPort==-1) { + /* vncrec playing */ + rfbVNCRec* rec = client->vncRec; + struct timeval tv; + + if (rec->readTimestamp) { + rec->readTimestamp = FALSE; + if (!fread(&tv,sizeof(struct timeval),1,rec->file)) + return FALSE; + + tv.tv_sec = rfbClientSwap32IfLE (tv.tv_sec); + tv.tv_usec = rfbClientSwap32IfLE (tv.tv_usec); + + if (rec->tv.tv_sec!=0 && !rec->doNotSleep) { + struct timeval diff; + diff.tv_sec = tv.tv_sec - rec->tv.tv_sec; + diff.tv_usec = tv.tv_usec - rec->tv.tv_usec; + if(diff.tv_usec<0) { + diff.tv_sec--; + diff.tv_usec+=1000000; + } +#ifndef __MINGW32__ + sleep (diff.tv_sec); + usleep (diff.tv_usec); +#else + Sleep (diff.tv_sec * 1000 + diff.tv_usec/1000); +#endif + } + + rec->tv=tv; + } + + return (fread(out,1,n,rec->file)<0?FALSE:TRUE); + } + + if (n <= client->buffered) { + memcpy(out, client->bufoutptr, n); + client->bufoutptr += n; + client->buffered -= n; +#ifdef DEBUG_READ_EXACT + goto hexdump; +#endif + return TRUE; + } + + memcpy(out, client->bufoutptr, client->buffered); + + out += client->buffered; + n -= client->buffered; + + client->bufoutptr = client->buf; + client->buffered = 0; + + if (n <= RFB_BUF_SIZE) { + + while (client->buffered < n) { + int i; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + i = ReadFromTLS(client, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); + } else { +#endif + i = read(client->sock, client->buf + client->buffered, RFB_BUF_SIZE - client->buffered); +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + } +#endif + if (i <= 0) { + if (i < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* TODO: + ProcessXtEvents(); + */ + i = 0; + } else { + rfbClientErr("read (%d: %s)\n",errno,strerror(errno)); + return FALSE; + } + } else { + if (errorMessageOnReadFailure) { + rfbClientLog("VNC server closed connection\n"); + } + return FALSE; + } + } + client->buffered += i; + } + + memcpy(out, client->bufoutptr, n); + client->bufoutptr += n; + client->buffered -= n; + + } else { + + while (n > 0) { + int i; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + i = ReadFromTLS(client, out, n); + } else { +#endif + i = read(client->sock, out, n); +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + } +#endif + if (i <= 0) { + if (i < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + if (errno == EWOULDBLOCK || errno == EAGAIN) { + /* TODO: + ProcessXtEvents(); + */ + i = 0; + } else { + rfbClientErr("read (%s)\n",strerror(errno)); + return FALSE; + } + } else { + if (errorMessageOnReadFailure) { + rfbClientLog("VNC server closed connection\n"); + } + return FALSE; + } + } + out += i; + n -= i; + } + } + +#ifdef DEBUG_READ_EXACT +hexdump: + { int ii; + for(ii=0;iiserverPort==-1) + return TRUE; /* vncrec playing */ + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) { + /* WriteToTLS() will guarantee either everything is written, or error/eof returns */ + i = WriteToTLS(client, buf, n); + if (i <= 0) return FALSE; + + return TRUE; + } +#endif + + while (i < n) { + j = write(client->sock, buf + i, (n - i)); + if (j <= 0) { + if (j < 0) { + if (errno == EWOULDBLOCK || +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + errno == ENOENT || +#endif + errno == EAGAIN) { + FD_ZERO(&fds); + FD_SET(client->sock,&fds); + + if (select(client->sock+1, NULL, &fds, NULL, NULL) <= 0) { + rfbClientErr("select\n"); + return FALSE; + } + j = 0; + } else { + rfbClientErr("write\n"); + return FALSE; + } + } else { + rfbClientLog("write failed\n"); + return FALSE; + } + } + i += j; + } + return TRUE; +} + + + +static int initSockets() { +#ifdef WIN32 + WSADATA trash; + static rfbBool WSAinitted=FALSE; + if(!WSAinitted) { + int i=WSAStartup(MAKEWORD(2,0),&trash); + if(i!=0) { + rfbClientErr("Couldn't init Windows Sockets\n"); + return 0; + } + WSAinitted=TRUE; + } +#endif + return 1; +} + +/* + * ConnectToTcpAddr connects to the given TCP port. + */ + +int +ConnectClientToTcpAddr(unsigned int host, int port) +{ + int sock; + struct sockaddr_in addr; + int one = 1; + + if (!initSockets()) + return -1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = host; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { +#ifdef WIN32 + errno=WSAGetLastError(); +#endif + rfbClientErr("ConnectToTcpAddr: socket (%s)\n",strerror(errno)); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + rfbClientErr("ConnectToTcpAddr: connect\n"); + close(sock); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("ConnectToTcpAddr: setsockopt\n"); + close(sock); + return -1; + } + + return sock; +} + +int +ConnectClientToUnixSock(const char *sockFile) +{ +#ifdef WIN32 + rfbClientErr("Windows doesn't support UNIX sockets\n"); + return -1; +#else + int sock; + struct sockaddr_un addr; + addr.sun_family = AF_UNIX; + strcpy(addr.sun_path, sockFile); + + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr("ConnectToUnixSock: socket (%s)\n",strerror(errno)); + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, sizeof(addr.sun_family) + strlen(addr.sun_path)) < 0) { + rfbClientErr("ConnectToUnixSock: connect\n"); + close(sock); + return -1; + } + + return sock; +#endif +} + + + +/* + * FindFreeTcpPort tries to find unused TCP port in the range + * (TUNNEL_PORT_OFFSET, TUNNEL_PORT_OFFSET + 99]. Returns 0 on failure. + */ + +int +FindFreeTcpPort(void) +{ + int sock, port; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!initSockets()) + return -1; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr(": FindFreeTcpPort: socket\n"); + return 0; + } + + for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) { + addr.sin_port = htons((unsigned short)port); + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) { + close(sock); + return port; + } + } + + close(sock); + return 0; +} + + +/* + * ListenAtTcpPort starts listening at the given TCP port. + */ + +int +ListenAtTcpPort(int port) +{ + int sock; + struct sockaddr_in addr; + int one = 1; + + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (!initSockets()) + return -1; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0) { + rfbClientErr("ListenAtTcpPort: socket\n"); + return -1; + } + + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (const char *)&one, sizeof(one)) < 0) { + rfbClientErr("ListenAtTcpPort: setsockopt\n"); + close(sock); + return -1; + } + + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + rfbClientErr("ListenAtTcpPort: bind\n"); + close(sock); + return -1; + } + + if (listen(sock, 5) < 0) { + rfbClientErr("ListenAtTcpPort: listen\n"); + close(sock); + return -1; + } + + return sock; +} + + +/* + * AcceptTcpConnection accepts a TCP connection. + */ + +int +AcceptTcpConnection(int listenSock) +{ + int sock; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + int one = 1; + + sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen); + if (sock < 0) { + rfbClientErr("AcceptTcpConnection: accept\n"); + return -1; + } + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbClientErr("AcceptTcpConnection: setsockopt\n"); + close(sock); + return -1; + } + + return sock; +} + + +/* + * SetNonBlocking sets a socket into non-blocking mode. + */ + +rfbBool +SetNonBlocking(int sock) +{ +#ifndef __MINGW32__ + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbClientErr("AcceptTcpConnection: fcntl\n"); + return FALSE; + } +#else + rfbClientErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED\n"); +#endif + return TRUE; +} + + +/* + * StringToIPAddr - convert a host string to an IP address. + */ + +rfbBool +StringToIPAddr(const char *str, unsigned int *addr) +{ + struct hostent *hp; + + if (strcmp(str,"") == 0) { + *addr = htonl(INADDR_LOOPBACK); /* local */ + return TRUE; + } + + *addr = inet_addr(str); + + if (*addr != -1) + return TRUE; + + if (!initSockets()) + return -1; + + hp = gethostbyname(str); + + if (hp) { + *addr = *(unsigned int *)hp->h_addr; + return TRUE; + } + + return FALSE; +} + + +/* + * Test if the other end of a socket is on the same machine. + */ + +rfbBool +SameMachine(int sock) +{ + struct sockaddr_in peeraddr, myaddr; + socklen_t addrlen = sizeof(struct sockaddr_in); + + getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen); + getsockname(sock, (struct sockaddr *)&myaddr, &addrlen); + + return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr); +} + + +/* + * Print out the contents of a packet for debugging. + */ + +void +PrintInHex(char *buf, int len) +{ + int i, j; + char c, str[17]; + + str[16] = 0; + + rfbClientLog("ReadExact: "); + + for (i = 0; i < len; i++) + { + if ((i % 16 == 0) && (i != 0)) { + rfbClientLog(" "); + } + c = buf[i]; + str[i % 16] = (((c > 31) && (c < 127)) ? c : '.'); + rfbClientLog("%02x ",(unsigned char)c); + if ((i % 4) == 3) + rfbClientLog(" "); + if ((i % 16) == 15) + { + rfbClientLog("%s\n",str); + } + } + if ((i % 16) != 0) + { + for (j = i % 16; j < 16; j++) + { + rfbClientLog(" "); + if ((j % 4) == 3) rfbClientLog(" "); + } + str[i % 16] = 0; + rfbClientLog("%s\n",str); + } + + fflush(stderr); +} + +int WaitForMessage(rfbClient* client,unsigned int usecs) +{ + fd_set fds; + struct timeval timeout; + int num; + + if (client->serverPort==-1) + /* playing back vncrec file */ + return 1; + + timeout.tv_sec=(usecs/1000000); + timeout.tv_usec=(usecs%1000000); + + FD_ZERO(&fds); + FD_SET(client->sock,&fds); + + num=select(client->sock+1, &fds, NULL, NULL, &timeout); + if(num<0) + rfbClientLog("Waiting for message failed: %d (%s)\n",errno,strerror(errno)); + + return num; +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c new file mode 100755 index 0000000..2f9fbab --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tight.c @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + +/* + * tight.c - handle ``tight'' encoding. + * + * This file shouldn't be compiled directly. It is included multiple + * times by rfbproto.c, each time with a different definition of the + * macro BPP. For each value of BPP, this file defines a function + * which handles a tight-encoded rectangle with BPP bits per pixel. + * + */ + +#define TIGHT_MIN_TO_COMPRESS 12 + +#define CARDBPP CONCAT3E(uint,BPP,_t) +#define filterPtrBPP CONCAT2E(filterPtr,BPP) + +#define HandleTightBPP CONCAT2E(HandleTight,BPP) +#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) +#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) +#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) +#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) +#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) +#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) + +#if BPP != 8 +#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) +#endif + +#ifndef RGB_TO_PIXEL + +#define RGB_TO_PIXEL(bpp,r,g,b) \ + (((CARD##bpp)(r) & client->format.redMax) << client->format.redShift | \ + ((CARD##bpp)(g) & client->format.greenMax) << client->format.greenShift | \ + ((CARD##bpp)(b) & client->format.blueMax) << client->format.blueShift) + +#define RGB24_TO_PIXEL(bpp,r,g,b) \ + ((((CARD##bpp)(r) & 0xFF) * client->format.redMax + 127) / 255 \ + << client->format.redShift | \ + (((CARD##bpp)(g) & 0xFF) * client->format.greenMax + 127) / 255 \ + << client->format.greenShift | \ + (((CARD##bpp)(b) & 0xFF) * client->format.blueMax + 127) / 255 \ + << client->format.blueShift) + +#define RGB24_TO_PIXEL32(r,g,b) \ + (((uint32_t)(r) & 0xFF) << client->format.redShift | \ + ((uint32_t)(g) & 0xFF) << client->format.greenShift | \ + ((uint32_t)(b) & 0xFF) << client->format.blueShift) + +#endif + +/* Type declarations */ + +typedef void (*filterPtrBPP)(rfbClient* client, int, CARDBPP *); + +/* Prototypes */ + +static int InitFilterCopyBPP (rfbClient* client, int rw, int rh); +static int InitFilterPaletteBPP (rfbClient* client, int rw, int rh); +static int InitFilterGradientBPP (rfbClient* client, int rw, int rh); +static void FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); +static void FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *destBuffer); + +#if BPP != 8 +static rfbBool DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h); +#endif + +/* Definitions */ + +static rfbBool +HandleTightBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + CARDBPP fill_colour; + uint8_t comp_ctl; + uint8_t filter_id; + filterPtrBPP filterFn; + z_streamp zs; + char *buffer2; + int err, stream_id, compressedLen, bitsPixel; + int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes; + + if (!ReadFromRFBServer(client, (char *)&comp_ctl, 1)) + return FALSE; + + /* Flush zlib streams if we are told by the server to do so. */ + for (stream_id = 0; stream_id < 4; stream_id++) { + if ((comp_ctl & 1) && client->zlibStreamActive[stream_id]) { + if (inflateEnd (&client->zlibStream[stream_id]) != Z_OK && + client->zlibStream[stream_id].msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->zlibStream[stream_id].msg); + client->zlibStreamActive[stream_id] = FALSE; + } + comp_ctl >>= 1; + } + + /* Handle solid rectangles. */ + if (comp_ctl == rfbTightFill) { +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + if (!ReadFromRFBServer(client, client->buffer, 3)) + return FALSE; + fill_colour = RGB24_TO_PIXEL32(client->buffer[0], client->buffer[1], client->buffer[2]); + } else { + if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour))) + return FALSE; + } +#else + if (!ReadFromRFBServer(client, (char*)&fill_colour, sizeof(fill_colour))) + return FALSE; +#endif + + FillRectangle(client, rx, ry, rw, rh, fill_colour); + + return TRUE; + } + +#if BPP == 8 + if (comp_ctl == rfbTightJpeg) { + rfbClientLog("Tight encoding: JPEG is not supported in 8 bpp mode.\n"); + return FALSE; + } +#else + if (comp_ctl == rfbTightJpeg) { + return DecompressJpegRectBPP(client, rx, ry, rw, rh); + } +#endif + + /* Quit on unsupported subencoding value. */ + if (comp_ctl > rfbTightMaxSubencoding) { + rfbClientLog("Tight encoding: bad subencoding value received.\n"); + return FALSE; + } + + /* + * Here primary compression mode handling begins. + * Data was processed with optional filter + zlib compression. + */ + + /* First, we should identify a filter to use. */ + if ((comp_ctl & rfbTightExplicitFilter) != 0) { + if (!ReadFromRFBServer(client, (char*)&filter_id, 1)) + return FALSE; + + switch (filter_id) { + case rfbTightFilterCopy: + filterFn = FilterCopyBPP; + bitsPixel = InitFilterCopyBPP(client, rw, rh); + break; + case rfbTightFilterPalette: + filterFn = FilterPaletteBPP; + bitsPixel = InitFilterPaletteBPP(client, rw, rh); + break; + case rfbTightFilterGradient: + filterFn = FilterGradientBPP; + bitsPixel = InitFilterGradientBPP(client, rw, rh); + break; + default: + rfbClientLog("Tight encoding: unknown filter code received.\n"); + return FALSE; + } + } else { + filterFn = FilterCopyBPP; + bitsPixel = InitFilterCopyBPP(client, rw, rh); + } + if (bitsPixel == 0) { + rfbClientLog("Tight encoding: error receiving palette.\n"); + return FALSE; + } + + /* Determine if the data should be decompressed or just copied. */ + rowSize = (rw * bitsPixel + 7) / 8; + if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) { + if (!ReadFromRFBServer(client, (char*)client->buffer, rh * rowSize)) + return FALSE; + + buffer2 = &client->buffer[TIGHT_MIN_TO_COMPRESS * 4]; + filterFn(client, rh, (CARDBPP *)buffer2); + + CopyRectangle(client, (uint8_t *)buffer2, rx, ry, rw, rh); + + return TRUE; + } + + /* Read the length (1..3 bytes) of compressed data following. */ + compressedLen = (int)ReadCompactLen(client); + if (compressedLen <= 0) { + rfbClientLog("Incorrect data received from the server.\n"); + return FALSE; + } + + /* Now let's initialize compression stream if needed. */ + stream_id = comp_ctl & 0x03; + zs = &client->zlibStream[stream_id]; + if (!client->zlibStreamActive[stream_id]) { + zs->zalloc = Z_NULL; + zs->zfree = Z_NULL; + zs->opaque = Z_NULL; + err = inflateInit(zs); + if (err != Z_OK) { + if (zs->msg != NULL) + rfbClientLog("InflateInit error: %s.\n", zs->msg); + return FALSE; + } + client->zlibStreamActive[stream_id] = TRUE; + } + + /* Read, decode and draw actual pixel data in a loop. */ + + bufferSize = RFB_BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC; + buffer2 = &client->buffer[bufferSize]; + if (rowSize > bufferSize) { + /* Should be impossible when RFB_BUFFER_SIZE >= 16384 */ + rfbClientLog("Internal error: incorrect buffer size.\n"); + return FALSE; + } + + rowsProcessed = 0; + extraBytes = 0; + + while (compressedLen > 0) { + if (compressedLen > ZLIB_BUFFER_SIZE) + portionLen = ZLIB_BUFFER_SIZE; + else + portionLen = compressedLen; + + if (!ReadFromRFBServer(client, (char*)client->zlib_buffer, portionLen)) + return FALSE; + + compressedLen -= portionLen; + + zs->next_in = (Bytef *)client->zlib_buffer; + zs->avail_in = portionLen; + + do { + zs->next_out = (Bytef *)&client->buffer[extraBytes]; + zs->avail_out = bufferSize - extraBytes; + + err = inflate(zs, Z_SYNC_FLUSH); + if (err == Z_BUF_ERROR) /* Input exhausted -- no problem. */ + break; + if (err != Z_OK && err != Z_STREAM_END) { + if (zs->msg != NULL) { + rfbClientLog("Inflate error: %s.\n", zs->msg); + } else { + rfbClientLog("Inflate error: %d.\n", err); + } + return FALSE; + } + + numRows = (bufferSize - zs->avail_out) / rowSize; + + filterFn(client, numRows, (CARDBPP *)buffer2); + + extraBytes = bufferSize - zs->avail_out - numRows * rowSize; + if (extraBytes > 0) + memcpy(client->buffer, &client->buffer[numRows * rowSize], extraBytes); + + CopyRectangle(client, (uint8_t *)buffer2, rx, ry+rowsProcessed, rw, numRows); + + rowsProcessed += numRows; + } + while (zs->avail_out == 0); + } + + if (rowsProcessed != rh) { + rfbClientLog("Incorrect number of scan lines after decompression.\n"); + return FALSE; + } + + return TRUE; +} + +/*---------------------------------------------------------------------------- + * + * Filter stuff. + * + */ + +static int +InitFilterCopyBPP (rfbClient* client, int rw, int rh) +{ + client->rectWidth = rw; + +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + client->cutZeros = TRUE; + return 24; + } else { + client->cutZeros = FALSE; + } +#endif + + return BPP; +} + +static void +FilterCopyBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + +#if BPP == 32 + int x, y; + + if (client->cutZeros) { + for (y = 0; y < numRows; y++) { + for (x = 0; x < client->rectWidth; x++) { + dst[y*client->rectWidth+x] = + RGB24_TO_PIXEL32(client->buffer[(y*client->rectWidth+x)*3], + client->buffer[(y*client->rectWidth+x)*3+1], + client->buffer[(y*client->rectWidth+x)*3+2]); + } + } + return; + } +#endif + + memcpy (dst, client->buffer, numRows * client->rectWidth * (BPP / 8)); +} + +static int +InitFilterGradientBPP (rfbClient* client, int rw, int rh) +{ + int bits; + + bits = InitFilterCopyBPP(client, rw, rh); + if (client->cutZeros) + memset(client->tightPrevRow, 0, rw * 3); + else + memset(client->tightPrevRow, 0, rw * 3 * sizeof(uint16_t)); + + return bits; +} + +#if BPP == 32 + +static void +FilterGradient24 (rfbClient* client, int numRows, uint32_t *dst) +{ + int x, y, c; + uint8_t thisRow[2048*3]; + uint8_t pix[3]; + int est[3]; + + for (y = 0; y < numRows; y++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = client->tightPrevRow[c] + client->buffer[y*client->rectWidth*3+c]; + thisRow[c] = pix[c]; + } + dst[y*client->rectWidth] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + + /* Remaining pixels of a row */ + for (x = 1; x < client->rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = (int)client->tightPrevRow[x*3+c] + (int)pix[c] - + (int)client->tightPrevRow[(x-1)*3+c]; + if (est[c] > 0xFF) { + est[c] = 0xFF; + } else if (est[c] < 0x00) { + est[c] = 0x00; + } + pix[c] = (uint8_t)est[c] + client->buffer[(y*client->rectWidth+x)*3+c]; + thisRow[x*3+c] = pix[c]; + } + dst[y*client->rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); + } + + memcpy(client->tightPrevRow, thisRow, client->rectWidth * 3); + } +} + +#endif + +static void +FilterGradientBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + int x, y, c; + CARDBPP *src = (CARDBPP *)client->buffer; + uint16_t *thatRow = (uint16_t *)client->tightPrevRow; + uint16_t thisRow[2048*3]; + uint16_t pix[3]; + uint16_t max[3]; + int shift[3]; + int est[3]; + +#if BPP == 32 + if (client->cutZeros) { + FilterGradient24(client, numRows, dst); + return; + } +#endif + + max[0] = client->format.redMax; + max[1] = client->format.greenMax; + max[2] = client->format.blueMax; + + shift[0] = client->format.redShift; + shift[1] = client->format.greenShift; + shift[2] = client->format.blueShift; + + for (y = 0; y < numRows; y++) { + + /* First pixel in a row */ + for (c = 0; c < 3; c++) { + pix[c] = (uint16_t)(((src[y*client->rectWidth] >> shift[c]) + thatRow[c]) & max[c]); + thisRow[c] = pix[c]; + } + dst[y*client->rectWidth] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + + /* Remaining pixels of a row */ + for (x = 1; x < client->rectWidth; x++) { + for (c = 0; c < 3; c++) { + est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; + if (est[c] > (int)max[c]) { + est[c] = (int)max[c]; + } else if (est[c] < 0) { + est[c] = 0; + } + pix[c] = (uint16_t)(((src[y*client->rectWidth+x] >> shift[c]) + est[c]) & max[c]); + thisRow[x*3+c] = pix[c]; + } + dst[y*client->rectWidth+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); + } + memcpy(thatRow, thisRow, client->rectWidth * 3 * sizeof(uint16_t)); + } +} + +static int +InitFilterPaletteBPP (rfbClient* client, int rw, int rh) +{ + uint8_t numColors; +#if BPP == 32 + int i; + CARDBPP *palette = (CARDBPP *)client->tightPalette; +#endif + + client->rectWidth = rw; + + if (!ReadFromRFBServer(client, (char*)&numColors, 1)) + return 0; + + client->rectColors = (int)numColors; + if (++client->rectColors < 2) + return 0; + +#if BPP == 32 + if (client->format.depth == 24 && client->format.redMax == 0xFF && + client->format.greenMax == 0xFF && client->format.blueMax == 0xFF) { + if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * 3)) + return 0; + for (i = client->rectColors - 1; i >= 0; i--) { + palette[i] = RGB24_TO_PIXEL32(client->tightPalette[i*3], + client->tightPalette[i*3+1], + client->tightPalette[i*3+2]); + } + return (client->rectColors == 2) ? 1 : 8; + } +#endif + + if (!ReadFromRFBServer(client, (char*)&client->tightPalette, client->rectColors * (BPP / 8))) + return 0; + + return (client->rectColors == 2) ? 1 : 8; +} + +static void +FilterPaletteBPP (rfbClient* client, int numRows, CARDBPP *dst) +{ + int x, y, b, w; + uint8_t *src = (uint8_t *)client->buffer; + CARDBPP *palette = (CARDBPP *)client->tightPalette; + + if (client->rectColors == 2) { + w = (client->rectWidth + 7) / 8; + for (y = 0; y < numRows; y++) { + for (x = 0; x < client->rectWidth / 8; x++) { + for (b = 7; b >= 0; b--) + dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + } + for (b = 7; b >= 8 - client->rectWidth % 8; b--) { + dst[y*client->rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1]; + } + } + } else { + for (y = 0; y < numRows; y++) + for (x = 0; x < client->rectWidth; x++) + dst[y*client->rectWidth+x] = palette[(int)src[y*client->rectWidth+x]]; + } +} + +#if BPP != 8 + +/*---------------------------------------------------------------------------- + * + * JPEG decompression. + * + */ + +static rfbBool +DecompressJpegRectBPP(rfbClient* client, int x, int y, int w, int h) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + int compressedLen; + uint8_t *compressedData; + CARDBPP *pixelPtr; + JSAMPROW rowPointer[1]; + int dx, dy; + + compressedLen = (int)ReadCompactLen(client); + if (compressedLen <= 0) { + rfbClientLog("Incorrect data received from the server.\n"); + return FALSE; + } + + compressedData = malloc(compressedLen); + if (compressedData == NULL) { + rfbClientLog("Memory allocation error.\n"); + return FALSE; + } + + if (!ReadFromRFBServer(client, (char*)compressedData, compressedLen)) { + free(compressedData); + return FALSE; + } + + cinfo.err = jpeg_std_error(&jerr); + cinfo.client_data = client; + jpeg_create_decompress(&cinfo); + + JpegSetSrcManager(&cinfo, compressedData, compressedLen); + + jpeg_read_header(&cinfo, TRUE); + cinfo.out_color_space = JCS_RGB; + + jpeg_start_decompress(&cinfo); + if (cinfo.output_width != w || cinfo.output_height != h || + cinfo.output_components != 3) { + rfbClientLog("Tight Encoding: Wrong JPEG data received.\n"); + jpeg_destroy_decompress(&cinfo); + free(compressedData); + return FALSE; + } + + rowPointer[0] = (JSAMPROW)client->buffer; + dy = 0; + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, rowPointer, 1); + if (client->jpegError) { + break; + } + pixelPtr = (CARDBPP *)&client->buffer[RFB_BUFFER_SIZE / 2]; + for (dx = 0; dx < w; dx++) { + *pixelPtr++ = + RGB24_TO_PIXEL(BPP, client->buffer[dx*3], client->buffer[dx*3+1], client->buffer[dx*3+2]); + } + CopyRectangle(client, (uint8_t *)&client->buffer[RFB_BUFFER_SIZE / 2], x, y + dy, w, 1); + dy++; + } + + if (!client->jpegError) + jpeg_finish_decompress(&cinfo); + + jpeg_destroy_decompress(&cinfo); + free(compressedData); + + return !client->jpegError; +} + +#else + +static long +ReadCompactLen (rfbClient* client) +{ + long len; + uint8_t b; + + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len = (int)b & 0x7F; + if (b & 0x80) { + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len |= ((int)b & 0x7F) << 7; + if (b & 0x80) { + if (!ReadFromRFBServer(client, (char *)&b, 1)) + return -1; + len |= ((int)b & 0xFF) << 14; + } + } + return len; +} + +/* + * JPEG source manager functions for JPEG decompression in Tight decoder. + */ + +static void +JpegInitSource(j_decompress_ptr cinfo) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegError = FALSE; +} + +static boolean +JpegFillInputBuffer(j_decompress_ptr cinfo) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegError = TRUE; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; + + return TRUE; +} + +static void +JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + if (num_bytes < 0 || num_bytes > client->jpegSrcManager->bytes_in_buffer) { + client->jpegError = TRUE; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + client->jpegSrcManager->next_input_byte = (JOCTET *)client->jpegBufferPtr; + } else { + client->jpegSrcManager->next_input_byte += (size_t) num_bytes; + client->jpegSrcManager->bytes_in_buffer -= (size_t) num_bytes; + } +} + +static void +JpegTermSource(j_decompress_ptr cinfo) +{ + /* nothing to do here. */ +} + +static void +JpegSetSrcManager(j_decompress_ptr cinfo, + uint8_t *compressedData, + int compressedLen) +{ + rfbClient* client=(rfbClient*)cinfo->client_data; + client->jpegBufferPtr = compressedData; + client->jpegBufferLen = (size_t)compressedLen; + + if(client->jpegSrcManager == NULL) + client->jpegSrcManager = malloc(sizeof(struct jpeg_source_mgr)); + client->jpegSrcManager->init_source = JpegInitSource; + client->jpegSrcManager->fill_input_buffer = JpegFillInputBuffer; + client->jpegSrcManager->skip_input_data = JpegSkipInputData; + client->jpegSrcManager->resync_to_restart = jpeg_resync_to_restart; + client->jpegSrcManager->term_source = JpegTermSource; + client->jpegSrcManager->next_input_byte = (JOCTET*)client->jpegBufferPtr; + client->jpegSrcManager->bytes_in_buffer = client->jpegBufferLen; + + cinfo->src = client->jpegSrcManager; +} + +#endif + +#undef CARDBPP + +/* LIBVNCSERVER_HAVE_LIBZ and LIBVNCSERVER_HAVE_LIBJPEG */ +#endif +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c new file mode 100755 index 0000000..206dbda --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.c @@ -0,0 +1,496 @@ +/* + * Copyright (C) 2009 Vic Lee. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include "tls.h" + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + +static const int rfbCertTypePriority[] = { GNUTLS_CRT_X509, 0 }; +static const int rfbProtoPriority[]= { GNUTLS_TLS1_1, GNUTLS_TLS1_0, GNUTLS_SSL3, 0 }; +static const int rfbKXPriority[] = {GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, 0}; +static const int rfbKXAnon[] = {GNUTLS_KX_ANON_DH, 0}; + +#define DH_BITS 1024 +static gnutls_dh_params_t rfbDHParams; + +static rfbBool rfbTLSInitialized = FALSE; + +static rfbBool +InitializeTLS(void) +{ + int ret; + + if (rfbTLSInitialized) return TRUE; + if ((ret = gnutls_global_init()) < 0 || + (ret = gnutls_dh_params_init(&rfbDHParams)) < 0 || + (ret = gnutls_dh_params_generate2(rfbDHParams, DH_BITS)) < 0) + { + rfbClientLog("Failed to initialized GnuTLS: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + rfbClientLog("GnuTLS initialized.\n"); + rfbTLSInitialized = TRUE; + return TRUE; +} + +static ssize_t +PushTLS(gnutls_transport_ptr_t transport, const void *data, size_t len) +{ + rfbClient *client = (rfbClient*)transport; + int ret; + + while (1) + { + ret = write(client->sock, data, len); + if (ret < 0) + { + if (errno == EINTR) continue; + return -1; + } + return ret; + } +} + + +static ssize_t +PullTLS(gnutls_transport_ptr_t transport, void *data, size_t len) +{ + rfbClient *client = (rfbClient*)transport; + int ret; + + while (1) + { + ret = read(client->sock, data, len); + if (ret < 0) + { + if (errno == EINTR) continue; + return -1; + } + return ret; + } +} + +static rfbBool +InitializeTLSSession(rfbClient* client, rfbBool anonTLS) +{ + int ret; + + if (client->tlsSession) return TRUE; + + if ((ret = gnutls_init(&client->tlsSession, GNUTLS_CLIENT)) < 0) + { + rfbClientLog("Failed to initialized TLS session: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + + if ((ret = gnutls_set_default_priority(client->tlsSession)) < 0 || + (ret = gnutls_kx_set_priority(client->tlsSession, anonTLS ? rfbKXAnon : rfbKXPriority)) < 0 || + (ret = gnutls_certificate_type_set_priority(client->tlsSession, rfbCertTypePriority)) < 0 || + (ret = gnutls_protocol_set_priority(client->tlsSession, rfbProtoPriority)) < 0) + { + FreeTLS(client); + rfbClientLog("Failed to set TLS priority: %s.\n", gnutls_strerror(ret)); + return FALSE; + } + + gnutls_transport_set_ptr(client->tlsSession, (gnutls_transport_ptr_t)client); + gnutls_transport_set_push_function(client->tlsSession, PushTLS); + gnutls_transport_set_pull_function(client->tlsSession, PullTLS); + + rfbClientLog("TLS session initialized.\n"); + + return TRUE; +} + +static rfbBool +SetTLSAnonCredential(rfbClient* client) +{ + gnutls_anon_client_credentials anonCred; + int ret; + + if ((ret = gnutls_anon_allocate_client_credentials(&anonCred)) < 0 || + (ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_ANON, anonCred)) < 0) + { + FreeTLS(client); + rfbClientLog("Failed to create anonymous credentials: %s", gnutls_strerror(ret)); + return FALSE; + } + rfbClientLog("TLS anonymous credential created.\n"); + return TRUE; +} + +static rfbBool +HandshakeTLS(rfbClient* client) +{ + int timeout = 15; + int ret; + + while (timeout > 0 && (ret = gnutls_handshake(client->tlsSession)) < 0) + { + if (!gnutls_error_is_fatal(ret)) + { + rfbClientLog("TLS handshake blocking.\n"); + sleep(1); + timeout--; + continue; + } + rfbClientLog("TLS handshake failed: %s.\n", gnutls_strerror(ret)); + FreeTLS(client); + return FALSE; + } + + if (timeout <= 0) + { + rfbClientLog("TLS handshake timeout.\n"); + FreeTLS(client); + return FALSE; + } + + rfbClientLog("TLS handshake done.\n"); + return TRUE; +} + +/* VeNCrypt sub auth. 1 byte auth count, followed by count * 4 byte integers */ +static rfbBool +ReadVeNCryptSecurityType(rfbClient* client, uint32_t *result) +{ + uint8_t count=0; + uint8_t loop=0; + uint8_t flag=0; + uint32_t tAuth[256], t; + char buf1[500],buf2[10]; + uint32_t authScheme; + + if (!ReadFromRFBServer(client, (char *)&count, 1)) return FALSE; + + if (count==0) + { + rfbClientLog("List of security types is ZERO. Giving up.\n"); + return FALSE; + } + if (count>sizeof(tAuth)) + { + rfbClientLog("%d security types are too many; maximum is %d\n", count, sizeof(tAuth)); + return FALSE; + } + + rfbClientLog("We have %d security types to read\n", count); + authScheme=0; + /* now, we have a list of available security types to read ( uint8_t[] ) */ + for (loop=0;loop=sizeof(buf1)-1) break; + snprintf(buf2, sizeof(buf2), (loop>0 ? ", %d" : "%d"), (int)tAuth[loop]); + strncat(buf1, buf2, sizeof(buf1)-strlen(buf1)-1); + } + rfbClientLog("Unknown VeNCrypt authentication scheme from VNC server: %s\n", + buf1); + return FALSE; + } + *result = authScheme; + return TRUE; +} + +static void +FreeX509Credential(rfbCredential *cred) +{ + if (cred->x509Credential.x509CACertFile) free(cred->x509Credential.x509CACertFile); + if (cred->x509Credential.x509CACrlFile) free(cred->x509Credential.x509CACrlFile); + if (cred->x509Credential.x509ClientCertFile) free(cred->x509Credential.x509ClientCertFile); + if (cred->x509Credential.x509ClientKeyFile) free(cred->x509Credential.x509ClientKeyFile); + free(cred); +} + +static gnutls_certificate_credentials_t +CreateX509CertCredential(rfbCredential *cred) +{ + gnutls_certificate_credentials_t x509_cred; + int ret; + + if (!cred->x509Credential.x509CACertFile) + { + rfbClientLog("No CA certificate provided.\n"); + return NULL; + } + + if ((ret = gnutls_certificate_allocate_credentials(&x509_cred)) < 0) + { + rfbClientLog("Cannot allocate credentials: %s.\n", gnutls_strerror(ret)); + return NULL; + } + if ((ret = gnutls_certificate_set_x509_trust_file(x509_cred, + cred->x509Credential.x509CACertFile, GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load CA credentials: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + if (cred->x509Credential.x509ClientCertFile && cred->x509Credential.x509ClientKeyFile) + { + if ((ret = gnutls_certificate_set_x509_key_file(x509_cred, + cred->x509Credential.x509ClientCertFile, cred->x509Credential.x509ClientKeyFile, + GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load client certificate or key: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + } else + { + rfbClientLog("No client certificate or key provided.\n"); + } + if (cred->x509Credential.x509CACrlFile) + { + if ((ret = gnutls_certificate_set_x509_crl_file(x509_cred, + cred->x509Credential.x509CACrlFile, GNUTLS_X509_FMT_PEM)) < 0) + { + rfbClientLog("Cannot load CRL: %s.\n", gnutls_strerror(ret)); + gnutls_certificate_free_credentials (x509_cred); + return NULL; + } + } else + { + rfbClientLog("No CRL provided.\n"); + } + gnutls_certificate_set_dh_params (x509_cred, rfbDHParams); + return x509_cred; +} + +#endif + +rfbBool +HandleAnonTLSAuth(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + + if (!InitializeTLS() || !InitializeTLSSession(client, TRUE)) return FALSE; + + if (!SetTLSAnonCredential(client)) return FALSE; + + if (!HandshakeTLS(client)) return FALSE; + + return TRUE; + +#else + rfbClientLog("TLS is not supported.\n"); + return FALSE; +#endif +} + +rfbBool +HandleVeNCryptAuth(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + uint8_t major, minor, status; + uint32_t authScheme; + rfbBool anonTLS; + gnutls_certificate_credentials_t x509_cred = NULL; + int ret; + + if (!InitializeTLS()) return FALSE; + + /* Read VeNCrypt version */ + if (!ReadFromRFBServer(client, (char *)&major, 1) || + !ReadFromRFBServer(client, (char *)&minor, 1)) + { + return FALSE; + } + rfbClientLog("Got VeNCrypt version %d.%d from server.\n", (int)major, (int)minor); + + if (major != 0 && minor != 2) + { + rfbClientLog("Unsupported VeNCrypt version.\n"); + return FALSE; + } + + if (!WriteToRFBServer(client, (char *)&major, 1) || + !WriteToRFBServer(client, (char *)&minor, 1) || + !ReadFromRFBServer(client, (char *)&status, 1)) + { + return FALSE; + } + + if (status != 0) + { + rfbClientLog("Server refused VeNCrypt version %d.%d.\n", (int)major, (int)minor); + return FALSE; + } + + if (!ReadVeNCryptSecurityType(client, &authScheme)) return FALSE; + if (!ReadFromRFBServer(client, (char *)&status, 1) || status != 1) + { + rfbClientLog("Server refused VeNCrypt authentication %d (%d).\n", authScheme, (int)status); + return FALSE; + } + client->subAuthScheme = authScheme; + + /* Some VeNCrypt security types are anonymous TLS, others are X509 */ + switch (authScheme) + { + case rfbVeNCryptTLSNone: + case rfbVeNCryptTLSVNC: + case rfbVeNCryptTLSPlain: + anonTLS = TRUE; + break; + default: + anonTLS = FALSE; + break; + } + + /* Get X509 Credentials if it's not anonymous */ + if (!anonTLS) + { + rfbCredential *cred; + + if (!client->GetCredential) + { + rfbClientLog("GetCredential callback is not set.\n"); + return FALSE; + } + cred = client->GetCredential(client, rfbCredentialTypeX509); + if (!cred) + { + rfbClientLog("Reading credential failed\n"); + return FALSE; + } + + x509_cred = CreateX509CertCredential(cred); + FreeX509Credential(cred); + if (!x509_cred) return FALSE; + } + + /* Start up the TLS session */ + if (!InitializeTLSSession(client, anonTLS)) return FALSE; + + if (anonTLS) + { + if (!SetTLSAnonCredential(client)) return FALSE; + } + else + { + if ((ret = gnutls_credentials_set(client->tlsSession, GNUTLS_CRD_CERTIFICATE, x509_cred)) < 0) + { + rfbClientLog("Cannot set x509 credential: %s.\n", gnutls_strerror(ret)); + FreeTLS(client); + return FALSE; + } + } + + if (!HandshakeTLS(client)) return FALSE; + + /* TODO: validate certificate */ + + /* We are done here. The caller should continue with client->subAuthScheme + * to do actual sub authentication. + */ + return TRUE; + +#else + rfbClientLog("TLS is not supported.\n"); + return FALSE; +#endif +} + +int +ReadFromTLS(rfbClient* client, char *out, unsigned int n) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + ssize_t ret; + + ret = gnutls_record_recv(client->tlsSession, out, n); + if (ret >= 0) return ret; + if (ret == GNUTLS_E_REHANDSHAKE || ret == GNUTLS_E_AGAIN) + { + errno = EAGAIN; + } else + { + rfbClientLog("Error reading from TLS: %s.\n", gnutls_strerror(ret)); + errno = EINTR; + } + return -1; +#else + rfbClientLog("TLS is not supported.\n"); + errno = EINTR; + return -1; +#endif +} + +int +WriteToTLS(rfbClient* client, char *buf, unsigned int n) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + unsigned int offset = 0; + ssize_t ret; + + while (offset < n) + { + ret = gnutls_record_send(client->tlsSession, buf+offset, (size_t)(n-offset)); + if (ret == 0) continue; + if (ret < 0) + { + if (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED) continue; + rfbClientLog("Error writing to TLS: %s.\n", gnutls_strerror(ret)); + return -1; + } + offset += (unsigned int)ret; + } + return offset; +#else + rfbClientLog("TLS is not supported.\n"); + errno = EINTR; + return -1; +#endif +} + +void FreeTLS(rfbClient* client) +{ +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + if (client->tlsSession) + { + gnutls_deinit(client->tlsSession); + client->tlsSession = NULL; + } +#endif +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h new file mode 100755 index 0000000..48d159b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/tls.h @@ -0,0 +1,51 @@ +#ifndef TLS_H +#define TLS_H + +/* + * Copyright (C) 2009 Vic Lee. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* Handle Anonymous TLS Authentication (18) with the server. + * After authentication, client->tlsSession will be set. + */ +rfbBool HandleAnonTLSAuth(rfbClient* client); + +/* Handle VeNCrypt Authentication (19) with the server. + * The callback function GetX509Credential will be called. + * After authentication, client->tlsSession will be set. + */ +rfbBool HandleVeNCryptAuth(rfbClient* client); + +/* Read desired bytes from TLS session. + * It's a wrapper function over gnutls_record_recv() and return values + * are same as read(), that is, >0 for actual bytes read, 0 for EOF, + * or EAGAIN, EINTR. + * This should be a non-blocking call. Blocking is handled in sockets.c. + */ +int ReadFromTLS(rfbClient* client, char *out, unsigned int n); + +/* Write desired bytes to TLS session. + * It's a wrapper function over gnutls_record_send() and it will be + * blocking call, until all bytes are written or error returned. + */ +int WriteToTLS(rfbClient* client, char *buf, unsigned int n); + +/* Free TLS resources */ +void FreeTLS(rfbClient* client); + +#endif /* TLS_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c new file mode 100755 index 0000000..3be150d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/ultra.c @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * ultrazip.c - handle ultrazip encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zlib + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleUltraZipBPP CONCAT2E(HandleUltraZip,BPP) +#define HandleUltraBPP CONCAT2E(HandleUltra,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleUltraBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int toRead=0; + int inflateResult=0; + int uncompressedBytes = (( rw * rh ) * ( BPP / 8 )); + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + toRead = rfbClientSwap32IfLE(hdr.nBytes); + if (toRead==0) return TRUE; + + if (uncompressedBytes==0) + { + rfbClientLog("ultra error: rectangle has 0 uncomressed bytes ((%dw * %dh) * (%d / 8))\n", rw, rh, BPP); + return FALSE; + } + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < uncompressedBytes) { + if ( client->raw_buffer != NULL ) { + free( client->raw_buffer ); + } + client->raw_buffer_size = uncompressedBytes; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->raw_buffer_size % 4)!=0) + client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + } + + /* allocate enough space to store the incoming compressed packet */ + if ( client->ultra_buffer_size < toRead ) { + if ( client->ultra_buffer != NULL ) { + free( client->ultra_buffer ); + } + client->ultra_buffer_size = toRead; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->ultra_buffer_size % 4)!=0) + client->ultra_buffer_size += (4-(client->ultra_buffer_size % 4)); + client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) + return FALSE; + + /* uncompress the data */ + uncompressedBytes = client->raw_buffer_size; + inflateResult = lzo1x_decompress( + (lzo_byte *)client->ultra_buffer, toRead, + (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, + NULL); + + + if ((rw * rh * (BPP / 8)) != uncompressedBytes) + rfbClientLog("Ultra decompressed too little (%d < %d)", (rw * rh * (BPP / 8)), uncompressedBytes); + + /* Put the uncompressed contents of the update on the screen. */ + if ( inflateResult == LZO_E_OK ) + { + CopyRectangle(client, (unsigned char *)client->raw_buffer, rx, ry, rw, rh); + } + else + { + rfbClientLog("ultra decompress returned error: %d\n", + inflateResult); + return FALSE; + } + return TRUE; +} + + +/* UltraZip is like rre in that it is composed of subrects */ +static rfbBool +HandleUltraZipBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int i=0; + int toRead=0; + int inflateResult=0; + unsigned char *ptr=NULL; + int uncompressedBytes = ry + (rw * 65535); + unsigned int numCacheRects = rx; + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + toRead = rfbClientSwap32IfLE(hdr.nBytes); + + if (toRead==0) return TRUE; + + if (uncompressedBytes==0) + { + rfbClientLog("ultrazip error: rectangle has 0 uncomressed bytes (%dy + (%dw * 65535)) (%d rectangles)\n", ry, rw, rx); + return FALSE; + } + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < (uncompressedBytes + 500)) { + if ( client->raw_buffer != NULL ) { + free( client->raw_buffer ); + } + client->raw_buffer_size = uncompressedBytes + 500; + /* buffer needs to be aligned on 4-byte boundaries */ + if ((client->raw_buffer_size % 4)!=0) + client->raw_buffer_size += (4-(client->raw_buffer_size % 4)); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + } + + + /* allocate enough space to store the incoming compressed packet */ + if ( client->ultra_buffer_size < toRead ) { + if ( client->ultra_buffer != NULL ) { + free( client->ultra_buffer ); + } + client->ultra_buffer_size = toRead; + client->ultra_buffer = (char*) malloc( client->ultra_buffer_size ); + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->ultra_buffer, toRead)) + return FALSE; + + /* uncompress the data */ + uncompressedBytes = client->raw_buffer_size; + inflateResult = lzo1x_decompress( + (lzo_byte *)client->ultra_buffer, toRead, + (lzo_byte *)client->raw_buffer, (lzo_uintp) &uncompressedBytes, NULL); + if ( inflateResult != LZO_E_OK ) + { + rfbClientLog("ultra decompress returned error: %d\n", + inflateResult); + return FALSE; + } + + /* Put the uncompressed contents of the update on the screen. */ + ptr = (unsigned char *)client->raw_buffer; + for (i=0; i +#include +#include +#include +#include +#include "tls.h" + +static void Dummy(rfbClient* client) { +} +static rfbBool DummyPoint(rfbClient* client, int x, int y) { + return TRUE; +} +static void DummyRect(rfbClient* client, int x, int y, int w, int h) { +} + +#ifdef __MINGW32__ +static char* NoPassword(rfbClient* client) { + return strdup(""); +} +#undef SOCKET +#include +#define close closesocket +#else +#include +#include +#endif + +static char* ReadPassword(rfbClient* client) { +#ifdef __MINGW32__ + /* FIXME */ + rfbClientErr("ReadPassword on MinGW32 NOT IMPLEMENTED\n"); + return NoPassword(client); +#else + int i; + char* p=malloc(9); + struct termios save,noecho; + p[0]=0; + if(tcgetattr(fileno(stdin),&save)!=0) return p; + noecho=save; noecho.c_lflag &= ~ECHO; + if(tcsetattr(fileno(stdin),TCSAFLUSH,&noecho)!=0) return p; + fprintf(stderr,"Password: "); + i=0; + while(1) { + int c=fgetc(stdin); + if(c=='\n') + break; + if(i<8) { + p[i]=c; + i++; + p[i]=0; + } + } + tcsetattr(fileno(stdin),TCSAFLUSH,&save); + return p; +#endif +} +static rfbBool MallocFrameBuffer(rfbClient* client) { + if(client->frameBuffer) + free(client->frameBuffer); + client->frameBuffer=malloc(client->width*client->height*client->format.bitsPerPixel/8); + return client->frameBuffer?TRUE:FALSE; +} + +static void initAppData(AppData* data) { + data->shareDesktop=TRUE; + data->viewOnly=FALSE; + data->encodingsString="tight zrle ultra copyrect hextile zlib corre rre raw"; + data->useBGR233=FALSE; + data->nColours=0; + data->forceOwnCmap=FALSE; + data->forceTrueColour=FALSE; + data->requestedDepth=0; + data->compressLevel=3; + data->qualityLevel=5; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + data->enableJPEG=TRUE; +#else + data->enableJPEG=FALSE; +#endif + data->useRemoteCursor=FALSE; +} + +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel, + int bytesPerPixel) { + rfbClient* client=(rfbClient*)calloc(sizeof(rfbClient),1); + if(!client) { + rfbClientErr("Couldn't allocate client structure!\n"); + return NULL; + } + initAppData(&client->appData); + client->endianTest = 1; + client->programName=""; + client->serverHost=strdup(""); + client->serverPort=5900; + + client->destHost = NULL; + client->destPort = 5900; + + client->CurrentKeyboardLedState = 0; + client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; + + /* default: use complete frame buffer */ + client->updateRect.x = -1; + + client->format.bitsPerPixel = bytesPerPixel*8; + client->format.depth = bitsPerSample*samplesPerPixel; + client->appData.requestedDepth=client->format.depth; + client->format.bigEndian = *(char *)&client->endianTest?FALSE:TRUE; + client->format.trueColour = TRUE; + + if (client->format.bitsPerPixel == 8) { + client->format.redMax = 7; + client->format.greenMax = 7; + client->format.blueMax = 3; + client->format.redShift = 0; + client->format.greenShift = 3; + client->format.blueShift = 6; + } else { + client->format.redMax = (1 << bitsPerSample) - 1; + client->format.greenMax = (1 << bitsPerSample) - 1; + client->format.blueMax = (1 << bitsPerSample) - 1; + if(!client->format.bigEndian) { + client->format.redShift = 0; + client->format.greenShift = bitsPerSample; + client->format.blueShift = bitsPerSample * 2; + } else { + if(client->format.bitsPerPixel==8*3) { + client->format.redShift = bitsPerSample*2; + client->format.greenShift = bitsPerSample*1; + client->format.blueShift = 0; + } else { + client->format.redShift = bitsPerSample*3; + client->format.greenShift = bitsPerSample*2; + client->format.blueShift = bitsPerSample; + } + } + } + + client->bufoutptr=client->buf; + client->buffered=0; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + client->raw_buffer_size = -1; + client->decompStreamInited = FALSE; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + memset(client->zlibStreamActive,0,sizeof(rfbBool)*4); + client->jpegSrcManager = NULL; +#endif +#endif + + client->HandleCursorPos = DummyPoint; + client->SoftCursorLockArea = DummyRect; + client->SoftCursorUnlockScreen = Dummy; + client->GotFrameBufferUpdate = DummyRect; + client->FinishedFrameBufferUpdate = NULL; + client->GetPassword = ReadPassword; + client->MallocFrameBuffer = MallocFrameBuffer; + client->Bell = Dummy; + client->CurrentKeyboardLedState = 0; + client->HandleKeyboardLedState = (HandleKeyboardLedStateProc)DummyPoint; + + client->authScheme = 0; + client->subAuthScheme = 0; + client->GetCredential = NULL; +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + client->tlsSession = NULL; +#endif + client->sock = -1; + client->listenSock = -1; + client->clientAuthSchemes = NULL; + return client; +} + +static rfbBool rfbInitConnection(rfbClient* client) +{ + /* Unless we accepted an incoming connection, make a TCP connection to the + given VNC server */ + + if (!client->listenSpecified) { + if (!client->serverHost) + return FALSE; + if (client->destHost) { + if (!ConnectToRFBRepeater(client,client->serverHost,client->serverPort,client->destHost,client->destPort)) + return FALSE; + } else { + if (!ConnectToRFBServer(client,client->serverHost,client->serverPort)) + return FALSE; + } + } + + /* Initialise the VNC connection, including reading the password */ + + if (!InitialiseRFBConnection(client)) + return FALSE; + + client->width=client->si.framebufferWidth; + client->height=client->si.framebufferHeight; + client->MallocFrameBuffer(client); + + if (!SetFormatAndEncodings(client)) + return FALSE; + + if (client->updateRect.x < 0) { + client->updateRect.x = client->updateRect.y = 0; + client->updateRect.w = client->width; + client->updateRect.h = client->height; + } + + if (client->appData.scaleSetting>1) + { + if (!SendScaleSetting(client, client->appData.scaleSetting)) + return FALSE; + if (!SendFramebufferUpdateRequest(client, + client->updateRect.x / client->appData.scaleSetting, + client->updateRect.y / client->appData.scaleSetting, + client->updateRect.w / client->appData.scaleSetting, + client->updateRect.h / client->appData.scaleSetting, + FALSE)) + return FALSE; + } + else + { + if (!SendFramebufferUpdateRequest(client, + client->updateRect.x, client->updateRect.y, + client->updateRect.w, client->updateRect.h, + FALSE)) + return FALSE; + } + + return TRUE; +} + +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv) { + int i,j; + + if(argv && argc && *argc) { + if(client->programName==0) + client->programName=argv[0]; + + for (i = 1; i < *argc; i++) { + j = i; + if (strcmp(argv[i], "-listen") == 0) { + listenForIncomingConnections(client); + break; + } else if (strcmp(argv[i], "-listennofork") == 0) { + listenForIncomingConnectionsNoFork(client, -1); + break; + } else if (strcmp(argv[i], "-play") == 0) { + client->serverPort = -1; + j++; + } else if (i+1<*argc && strcmp(argv[i], "-encodings") == 0) { + client->appData.encodingsString = argv[i+1]; + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-compress") == 0) { + client->appData.compressLevel = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-quality") == 0) { + client->appData.qualityLevel = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-scale") == 0) { + client->appData.scaleSetting = atoi(argv[i+1]); + j+=2; + } else if (i+1<*argc && strcmp(argv[i], "-repeaterdest") == 0) { + char* colon=strchr(argv[i+1],':'); + + if(client->destHost) + free(client->destHost); + client->destPort = 5900; + + client->destHost = strdup(argv[i+1]); + if(colon) { + client->destHost[(int)(colon-argv[i+1])] = '\0'; + client->destPort = atoi(colon+1); + } + j+=2; + } else { + char* colon=strchr(argv[i],':'); + + if(client->serverHost) + free(client->serverHost); + + if(colon) { + client->serverHost = strdup(argv[i]); + client->serverHost[(int)(colon-argv[i])] = '\0'; + client->serverPort = atoi(colon+1); + } else { + client->serverHost = strdup(argv[i]); + } + if(client->serverPort >= 0 && client->serverPort < 5900) + client->serverPort += 5900; + } + /* purge arguments */ + if (j>i) { + *argc-=j-i; + memmove(argv+i,argv+j,(*argc-i)*sizeof(char*)); + i--; + } + } + } + + if(!rfbInitConnection(client)) { + rfbClientCleanup(client); + return FALSE; + } + + return TRUE; +} + +void rfbClientCleanup(rfbClient* client) { +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + int i; + + for ( i = 0; i < 4; i++ ) { + if (client->zlibStreamActive[i] == TRUE ) { + if (inflateEnd (&client->zlibStream[i]) != Z_OK && + client->zlibStream[i].msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->zlibStream[i].msg); + } + } + + if ( client->decompStreamInited == TRUE ) { + if (inflateEnd (&client->decompStream) != Z_OK && + client->decompStream.msg != NULL) + rfbClientLog("inflateEnd: %s\n", client->decompStream.msg ); + } + + if (client->jpegSrcManager) + free(client->jpegSrcManager); +#endif +#endif + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + FreeTLS(client); +#endif + if (client->sock >= 0) + close(client->sock); + if (client->listenSock >= 0) + close(client->listenSock); + free(client->desktopName); + free(client->serverHost); + if (client->destHost) + free(client->destHost); + if (client->clientAuthSchemes) + free(client->clientAuthSchemes); + free(client); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c new file mode 100755 index 0000000..e872d40 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zlib.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/* + * zlib.c - handle zlib encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zlib + * encoded rectangle with BPP bits per pixel. + */ + +#define HandleZlibBPP CONCAT2E(HandleZlib,BPP) +#define CARDBPP CONCAT3E(uint,BPP,_t) + +static rfbBool +HandleZlibBPP (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZlibHeader hdr; + int remaining; + int inflateResult; + int toRead; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed BPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) { + + if ( client->raw_buffer != NULL ) { + + free( client->raw_buffer ); + + } + + client->raw_buffer_size = (( rw * rh ) * ( BPP / 8 )); + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + + } + + if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbZlibHeader)) + return FALSE; + + remaining = rfbClientSwap32IfLE(hdr.nBytes); + + /* Need to initialize the decompressor state. */ + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = 0; + client->decompStream.next_out = ( Bytef * )client->raw_buffer; + client->decompStream.avail_out = client->raw_buffer_size; + client->decompStream.data_type = Z_BINARY; + + /* Initialize the decompression stream structures on the first invocation. */ + if ( client->decompStreamInited == FALSE ) { + + inflateResult = inflateInit( &client->decompStream ); + + if ( inflateResult != Z_OK ) { + rfbClientLog( + "inflateInit returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + client->decompStreamInited = TRUE; + + } + + inflateResult = Z_OK; + + /* Process buffer full of data until no more to process, or + * some type of inflater error, or Z_STREAM_END. + */ + while (( remaining > 0 ) && + ( inflateResult == Z_OK )) { + + if ( remaining > RFB_BUFFER_SIZE ) { + toRead = RFB_BUFFER_SIZE; + } + else { + toRead = remaining; + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->buffer,toRead)) + return FALSE; + + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = toRead; + + /* Need to uncompress buffer full. */ + inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); + + /* We never supply a dictionary for compression. */ + if ( inflateResult == Z_NEED_DICT ) { + rfbClientLog("zlib inflate needs a dictionary!\n"); + return FALSE; + } + if ( inflateResult < 0 ) { + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + /* Result buffer allocated to be at least large enough. We should + * never run out of space! + */ + if (( client->decompStream.avail_in > 0 ) && + ( client->decompStream.avail_out <= 0 )) { + rfbClientLog("zlib inflate ran out of space!\n"); + return FALSE; + } + + remaining -= toRead; + + } /* while ( remaining > 0 ) */ + + if ( inflateResult == Z_OK ) { + + /* Put the uncompressed contents of the update on the screen. */ + CopyRectangle(client, (uint8_t *)client->raw_buffer, rx, ry, rw, rh); + } + else { + + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + + } + + return TRUE; +} + +#undef CARDBPP + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c new file mode 100755 index 0000000..da2db4b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncclient/zrle.c @@ -0,0 +1,427 @@ +/* + * Copyright (C) 2005 Johannes E. Schindelin. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/* + * zrle.c - handle zrle encoding. + * + * This file shouldn't be compiled directly. It is included multiple times by + * rfbproto.c, each time with a different definition of the macro BPP. For + * each value of BPP, this file defines a function which handles an zrle + * encoded rectangle with BPP bits per pixel. + */ + +#ifndef REALBPP +#define REALBPP BPP +#endif + +#if !defined(UNCOMP) || UNCOMP==0 +#define HandleZRLE CONCAT2E(HandleZRLE,REALBPP) +#define HandleZRLETile CONCAT2E(HandleZRLETile,REALBPP) +#elif UNCOMP>0 +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Down) +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Down) +#else +#define HandleZRLE CONCAT3E(HandleZRLE,REALBPP,Up) +#define HandleZRLETile CONCAT3E(HandleZRLETile,REALBPP,Up) +#endif +#define CARDBPP CONCAT3E(uint,BPP,_t) +#define CARDREALBPP CONCAT3E(uint,REALBPP,_t) + +#define ENDIAN_LITTLE 0 +#define ENDIAN_BIG 1 +#define ENDIAN_NO 2 +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#undef END_FIX +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE +# define END_FIX LE +#elif ZYWRLE_ENDIAN == ENDIAN_BIG +# define END_FIX BE +#else +# define END_FIX NE +#endif +#define __RFB_CONCAT3E(a,b,c) CONCAT3E(a,b,c) +#define __RFB_CONCAT2E(a,b) CONCAT2E(a,b) +#undef CPIXEL +#if REALBPP != BPP +#if UNCOMP == 0 +#define CPIXEL REALBPP +#elif UNCOMP>0 +#define CPIXEL CONCAT2E(REALBPP,Down) +#else +#define CPIXEL CONCAT2E(REALBPP,Up) +#endif +#endif +#define PIXEL_T __RFB_CONCAT3E(uint,BPP,_t) +#if BPP!=8 +#define ZYWRLE_DECODE 1 +#include "../libvncserver/zywrletemplate.c" +#endif +#undef CPIXEL + +static int HandleZRLETile(rfbClient* client, + uint8_t* buffer,size_t buffer_length, + int x,int y,int w,int h); + +static rfbBool +HandleZRLE (rfbClient* client, int rx, int ry, int rw, int rh) +{ + rfbZRLEHeader header; + int remaining; + int inflateResult; + int toRead; + int min_buffer_size = rw * rh * (REALBPP / 8) * 2; + + /* First make sure we have a large enough raw buffer to hold the + * decompressed data. In practice, with a fixed REALBPP, fixed frame + * buffer size and the first update containing the entire frame + * buffer, this buffer allocation should only happen once, on the + * first update. + */ + if ( client->raw_buffer_size < min_buffer_size) { + + if ( client->raw_buffer != NULL ) { + + free( client->raw_buffer ); + + } + + client->raw_buffer_size = min_buffer_size; + client->raw_buffer = (char*) malloc( client->raw_buffer_size ); + + } + + if (!ReadFromRFBServer(client, (char *)&header, sz_rfbZRLEHeader)) + return FALSE; + + remaining = rfbClientSwap32IfLE(header.length); + + /* Need to initialize the decompressor state. */ + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = 0; + client->decompStream.next_out = ( Bytef * )client->raw_buffer; + client->decompStream.avail_out = client->raw_buffer_size; + client->decompStream.data_type = Z_BINARY; + + /* Initialize the decompression stream structures on the first invocation. */ + if ( client->decompStreamInited == FALSE ) { + + inflateResult = inflateInit( &client->decompStream ); + + if ( inflateResult != Z_OK ) { + rfbClientLog( + "inflateInit returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + client->decompStreamInited = TRUE; + + } + + inflateResult = Z_OK; + + /* Process buffer full of data until no more to process, or + * some type of inflater error, or Z_STREAM_END. + */ + while (( remaining > 0 ) && + ( inflateResult == Z_OK )) { + + if ( remaining > RFB_BUFFER_SIZE ) { + toRead = RFB_BUFFER_SIZE; + } + else { + toRead = remaining; + } + + /* Fill the buffer, obtaining data from the server. */ + if (!ReadFromRFBServer(client, client->buffer,toRead)) + return FALSE; + + client->decompStream.next_in = ( Bytef * )client->buffer; + client->decompStream.avail_in = toRead; + + /* Need to uncompress buffer full. */ + inflateResult = inflate( &client->decompStream, Z_SYNC_FLUSH ); + + /* We never supply a dictionary for compression. */ + if ( inflateResult == Z_NEED_DICT ) { + rfbClientLog("zlib inflate needs a dictionary!\n"); + return FALSE; + } + if ( inflateResult < 0 ) { + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + } + + /* Result buffer allocated to be at least large enough. We should + * never run out of space! + */ + if (( client->decompStream.avail_in > 0 ) && + ( client->decompStream.avail_out <= 0 )) { + rfbClientLog("zlib inflate ran out of space!\n"); + return FALSE; + } + + remaining -= toRead; + + } /* while ( remaining > 0 ) */ + + if ( inflateResult == Z_OK ) { + void* buf=client->raw_buffer; + int i,j; + + remaining = client->raw_buffer_size-client->decompStream.avail_out; + + for(j=0; jrw)?rw-i:rfbZRLETileWidth; + int subHeight=(j+rfbZRLETileHeight>rh)?rh-j:rfbZRLETileHeight; + int result=HandleZRLETile(client,buf,remaining,rx+i,ry+j,subWidth,subHeight); + + if(result<0) { + rfbClientLog("ZRLE decoding failed (%d)\n",result); +return TRUE; + return FALSE; + } + + buf+=result; + remaining-=result; + } + } + else { + + rfbClientLog( + "zlib inflate returned error: %d, msg: %s\n", + inflateResult, + client->decompStream.msg); + return FALSE; + + } + + return TRUE; +} + +#if REALBPP!=BPP && defined(UNCOMP) && UNCOMP!=0 +#if UNCOMP>0 +#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)>>UNCOMP) +#else +#define UncompressCPixel(pointer) ((*(CARDBPP*)pointer)<<(-(UNCOMP))) +#endif +#else +#define UncompressCPixel(pointer) (*(CARDBPP*)pointer) +#endif + +static int HandleZRLETile(rfbClient* client, + uint8_t* buffer,size_t buffer_length, + int x,int y,int w,int h) { + uint8_t* buffer_copy = buffer; + uint8_t* buffer_end = buffer+buffer_length; + uint8_t type; +#if BPP!=8 + uint8_t zywrle_level = (client->appData.qualityLevel & 0x80) ? + 0 : (3 - client->appData.qualityLevel / 3); +#endif + + if(buffer_length<1) + return -2; + + type = *buffer; + buffer++; + { + if( type == 0 ) /* raw */ +#if BPP!=8 + if( zywrle_level > 0 ){ + CARDBPP* pFrame = (CARDBPP*)client->frameBuffer + y*client->width+x; + int ret; + client->appData.qualityLevel |= 0x80; + ret = HandleZRLETile(client, buffer, buffer_end-buffer, x, y, w, h); + client->appData.qualityLevel &= 0x7F; + if( ret < 0 ){ + return ret; + } + ZYWRLE_SYNTHESIZE( pFrame, pFrame, w, h, client->width, zywrle_level, (int*)client->zlib_buffer ); + buffer += ret; + }else +#endif + { +#if REALBPP!=BPP + int i,j; + + if(1+w*h*REALBPP/8>buffer_length) { + rfbClientLog("expected %d bytes, got only %d (%dx%d)\n",1+w*h*REALBPP/8,buffer_length,w,h); + return -3; + } + + for(j=y*client->width; j<(y+h)*client->width; j+=client->width) + for(i=x; iframeBuffer)[j+i] = UncompressCPixel(buffer); +#else + CopyRectangle(client, buffer, x, y, w, h); + buffer+=w*h*REALBPP/8; +#endif + } + else if( type == 1 ) /* solid */ + { + CARDBPP color = UncompressCPixel(buffer); + + if(1+REALBPP/8>buffer_length) + return -4; + + FillRectangle(client, x, y, w, h, color); + + buffer+=REALBPP/8; + + } + else if( (type >= 2)&&(type <= 127) ) /* packed Palette */ + { + CARDBPP palette[16]; + int i,j,shift, + bpp=(type>4?(type>16?8:4):(type>2?2:1)), + mask=(1<buffer_length) + return -5; + + /* read palette */ + for(i=0; iwidth; j<(y+h)*client->width; j+=client->width) { + for(i=x,shift=8-bpp; iframeBuffer)[j+i] = palette[((*buffer)>>shift)&mask]; + shift-=bpp; + if(shift<0) { + shift=8-bpp; + buffer++; + } + } + if(shift<8-bpp) + buffer++; + } + + } + /* case 17 ... 127: not used, but valid */ + else if( type == 128 ) /* plain RLE */ + { + int i=0,j=0; + while(jbuffer_end) + return -7; + color = UncompressCPixel(buffer); + buffer+=REALBPP/8; + /* read run length */ + length=1; + while(*buffer==0xff) { + if(buffer+1>=buffer_end) + return -8; + length+=*buffer; + buffer++; + } + length+=*buffer; + buffer++; + while(j0) { + ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color; + length--; + i++; + if(i>=w) { + i=0; + j++; + } + } + if(length>0) + rfbClientLog("Warning: possible ZRLE corruption\n"); + } + + } + else if( type == 129 ) /* unused */ + { + return -8; + } + else if( (type >= 130)&&(type <= 255) ) /* palette RLE */ + { + CARDBPP palette[128]; + int i,j; + + if(2+(type-128)*REALBPP/8>buffer_length) + return -9; + + /* read palette */ + for(i=0; i=buffer_end) + return -10; + color = palette[(*buffer)&0x7f]; + length=1; + if(*buffer&0x80) { + if(buffer+1>=buffer_end) + return -11; + buffer++; + /* read run length */ + while(*buffer==0xff) { + if(buffer+1>=buffer_end) + return -8; + length+=*buffer; + buffer++; + } + length+=*buffer; + } + buffer++; + while(j0) { + ((CARDBPP*)client->frameBuffer)[(y+j)*client->width+x+i] = color; + length--; + i++; + if(i>=w) { + i=0; + j++; + } + } + if(length>0) + rfbClientLog("Warning: possible ZRLE corruption\n"); + } + } + } + + return buffer-buffer_copy; +} + +#undef CARDBPP +#undef CARDREALBPP +#undef HandleZRLE +#undef HandleZRLETile +#undef UncompressCPixel +#undef REALBPP + +#endif + +#undef UNCOMP diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in new file mode 100755 index 0000000..ea0bef8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver-config.in @@ -0,0 +1,78 @@ +#!/bin/sh + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +exec_prefix_set=no +includedir=@includedir@ +libdir=@libdir@ + +# if this script is in the same directory as libvncserver-config.in, assume not installed +if [ -f "`dirname "$0"`/libvncserver-config.in" ]; then + dir="`dirname "$0"`" + prefix="`cd "$dir"; pwd`" + includedir="$prefix" + libdir="$prefix/libvncserver/.libs $prefix/libvncclient/.libs" +fi + +usage="\ +Usage: @PACKAGE@-config [--prefix[=DIR]] [--exec-prefix[=DIR]] [--version] [--link] [--libs] [--cflags]" + +if test $# -eq 0; then + echo "${usage}" 1>&2 + exit 1 +fi + +while test $# -gt 0; do + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case $1 in + --prefix=*) + prefix=$optarg + if test $exec_prefix_set = no ; then + exec_prefix=$optarg + fi + ;; + --prefix) + echo $prefix + ;; + --exec-prefix=*) + exec_prefix=$optarg + exec_prefix_set=yes + ;; + --exec-prefix) + echo $exec_prefix + ;; + --version) + echo @VERSION@ + ;; + --cflags) + if [ "$includedir" != /usr/include ]; then + includes=-I"$includedir" + fi + echo "$includes" + ;; + --libs) + libs="" + for dir in $libdir; do + libs="$libs -L$dir" + if [ "`uname`" = "SunOS" ]; then + # why only Solaris?? + libs="$libs -R$dir" + fi + done + echo "$libs" -lvncserver -lvncclient @LIBS@ @WSOCKLIB@ + ;; + --link) + echo @CC@ + ;; + *) + echo "${usage}" 1>&2 + exit 1 + ;; + esac + shift +done + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp new file mode 100755 index 0000000..0dd25b5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsp @@ -0,0 +1,220 @@ +# Microsoft Developer Studio Project File - Name="libvncserver" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** NICHT BEARBEITEN ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libvncserver - Win32 Debug +!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE +!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl +!MESSAGE +!MESSAGE NMAKE /f "libvncserver.mak". +!MESSAGE +!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben +!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel: +!MESSAGE +!MESSAGE NMAKE /f "libvncserver.mak" CFG="libvncserver - Win32 Debug" +!MESSAGE +!MESSAGE Für die Konfiguration stehen zur Auswahl: +!MESSAGE +!MESSAGE "libvncserver - Win32 Release" (basierend auf "Win32 (x86) Static Library") +!MESSAGE "libvncserver - Win32 Debug" (basierend auf "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libvncserver - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "zlib" /I "libjpeg" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x407 /d "NDEBUG" +# ADD RSC /l 0x407 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "libvncserver - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "libvncserver___Win32_Debug" +# PROP BASE Intermediate_Dir "libvncserver___Win32_Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "libvncserver___Win32_Debug" +# PROP Intermediate_Dir "libvncserver___Win32_Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "zlib" /I "libjpeg" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x407 /d "_DEBUG" +# ADD RSC /l 0x407 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "libvncserver - Win32 Release" +# Name "libvncserver - Win32 Debug" +# Begin Group "Sources" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "auth" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\auth.c +# End Source File +# Begin Source File + +SOURCE=.\d3des.c +# End Source File +# Begin Source File + +SOURCE=.\storepasswd.c +# End Source File +# Begin Source File + +SOURCE=.\vncauth.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\cargs.c +# End Source File +# Begin Source File + +SOURCE=.\corre.c +# End Source File +# Begin Source File + +SOURCE=.\cursor.c +# End Source File +# Begin Source File + +SOURCE=.\cutpaste.c +# End Source File +# Begin Source File + +SOURCE=.\draw.c +# End Source File +# Begin Source File + +SOURCE=.\font.c +# End Source File +# Begin Source File + +SOURCE=.\hextile.c +# End Source File +# Begin Source File + +SOURCE=.\httpd.c +# End Source File +# Begin Source File + +SOURCE=.\main.c +# End Source File +# Begin Source File + +SOURCE=.\rfbserver.c +# End Source File +# Begin Source File + +SOURCE=.\rre.c +# End Source File +# Begin Source File + +SOURCE=.\selbox.c +# End Source File +# Begin Source File + +SOURCE=.\sockets.c +# End Source File +# Begin Source File + +SOURCE=.\sraRegion.c +# End Source File +# Begin Source File + +SOURCE=.\stats.c +# End Source File +# Begin Source File + +SOURCE=.\tight.c +# End Source File +# Begin Source File + +SOURCE=.\translate.c +# End Source File +# Begin Source File + +SOURCE=.\zlib.c +# End Source File +# End Group +# Begin Group "Headers" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "auth Nr. 1" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\d3des.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\default8x16.h +# End Source File +# Begin Source File + +SOURCE=.\keysym.h +# End Source File +# Begin Source File + +SOURCE=.\radon.h +# End Source File +# Begin Source File + +SOURCE=.\region.h +# End Source File +# Begin Source File + +SOURCE=.\rfb.h +# End Source File +# Begin Source File + +SOURCE=.\rfbproto.h +# End Source File +# Begin Source File + +SOURCE=.\sraRegion.h +# End Source File +# End Group +# End Target +# End Project diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw new file mode 100755 index 0000000..799cfb4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver.dsw @@ -0,0 +1,101 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNUNG: DIESE ARBEITSBEREICHSDATEI DARF NICHT BEARBEITET ODER GELÖSCHT WERDEN! + +############################################################################### + +Project: "example"=.\example.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libvncserver + End Project Dependency + Begin Project Dependency + Project_Dep_Name libjpeg + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "libjpeg"=.\libjpeg\libjpeg.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libvncserver"=.\libvncserver.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libjpeg + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "rdp2vnc"=\my\rdp2vnc\rdp2vnc\rdp2vnc.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libvncserver + End Project Dependency + Begin Project Dependency + Project_Dep_Name libjpeg + End Project Dependency + Begin Project Dependency + Project_Dep_Name zlib + End Project Dependency +}}} + +############################################################################### + +Project: "zlib"=.\zlib\zlib.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore new file mode 100755 index 0000000..c892af4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/.cvsignore @@ -0,0 +1,5 @@ +.deps +Makefile +Makefile.in +libvncserver.a + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am new file mode 100755 index 0000000..629f990 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/Makefile.am @@ -0,0 +1,64 @@ +INCLUDES = -I$(top_srcdir) + +if WITH_TIGHTVNC_FILETRANSFER +TIGHTVNCFILETRANSFERHDRS=tightvnc-filetransfer/filelistinfo.h \ + tightvnc-filetransfer/filetransfermsg.h \ + tightvnc-filetransfer/handlefiletransferrequest.h \ + tightvnc-filetransfer/rfbtightproto.h + +TIGHTVNCFILETRANSFERSRCS = tightvnc-filetransfer/rfbtightserver.c \ + tightvnc-filetransfer/handlefiletransferrequest.c \ + tightvnc-filetransfer/filetransfermsg.c \ + tightvnc-filetransfer/filelistinfo.c +endif + +if WITH_WEBSOCKETS +WEBSOCKETSSRCS = websockets.c md5.c +endif + +includedir=$(prefix)/include/rfb +#include_HEADERS=rfb.h rfbconfig.h rfbint.h rfbproto.h keysym.h rfbregion.h + +include_HEADERS=../rfb/rfb.h ../rfb/rfbconfig.h ../rfb/rfbint.h \ + ../rfb/rfbproto.h ../rfb/keysym.h ../rfb/rfbregion.h ../rfb/rfbclient.h + +noinst_HEADERS=d3des.h ../rfb/default8x16.h zrleoutstream.h \ + zrlepalettehelper.h zrletypes.h private.h minilzo.h lzoconf.h scale.h \ + $(TIGHTVNCFILETRANSFERHDRS) + +EXTRA_DIST=tableinit24.c tableinittctemplate.c tabletranstemplate.c \ + tableinitcmtemplate.c tabletrans24template.c \ + zrleencodetemplate.c + +if HAVE_LIBZ +ZLIBSRCS = zlib.c zrle.c zrleoutstream.c zrlepalettehelper.c zywrletemplate.c +if HAVE_LIBJPEG +TIGHTSRCS = tight.c +else +if HAVE_LIBPNG +TIGHTSRCS = tight.c +endif +endif +endif + +LIB_SRCS = main.c rfbserver.c rfbregion.c auth.c sockets.c $(WEBSOCKETSSRCS) \ + stats.c corre.c hextile.c rre.c translate.c cutpaste.c \ + httpd.c cursor.c font.c \ + draw.c selbox.c d3des.c vncauth.c cargs.c minilzo.c ultra.c scale.c \ + $(ZLIBSRCS) $(TIGHTSRCS) $(TIGHTVNCFILETRANSFERSRCS) + +libvncserver_la_SOURCES=$(LIB_SRCS) +libvncserver_la_LIBADD=@SSL_LIBS@ @CRYPT_LIBS@ + +lib_LTLIBRARIES=libvncserver.la + +if HAVE_RPM +$(PACKAGE)-$(VERSION).tar.gz: dist + +# Rule to build RPM distribution package +rpm: $(PACKAGE)-$(VERSION).tar.gz libvncserver.spec + cp $(PACKAGE)-$(VERSION).tar.gz @RPMSOURCEDIR@ + rpmbuild -ba libvncserver.spec +endif + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c new file mode 100755 index 0000000..c4c5ff1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/auth.c @@ -0,0 +1,375 @@ +/* + * auth.c - deal with authentication. + * + * This file implements the VNC authentication protocol when setting up an RFB + * connection. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +/* RFB 3.8 clients are well informed */ +void rfbClientSendString(rfbClientPtr cl, char *reason); + + +/* + * Handle security types + */ + +static rfbSecurityHandler* securityHandlers = NULL; + +/* + * This method registers a list of new security types. + * It avoids same security type getting registered multiple times. + * The order is not preserved if multiple security types are + * registered at one-go. + */ +void +rfbRegisterSecurityHandler(rfbSecurityHandler* handler) +{ + rfbSecurityHandler *head = securityHandlers, *next = NULL; + + if(handler == NULL) + return; + + next = handler->next; + + while(head != NULL) { + if(head == handler) { + rfbRegisterSecurityHandler(next); + return; + } + + head = head->next; + } + + handler->next = securityHandlers; + securityHandlers = handler; + + rfbRegisterSecurityHandler(next); +} + +/* + * This method unregisters a list of security types. + * These security types won't be available for any new + * client connection. + */ +void +rfbUnregisterSecurityHandler(rfbSecurityHandler* handler) +{ + rfbSecurityHandler *cur = NULL, *pre = NULL; + + if(handler == NULL) + return; + + if(securityHandlers == handler) { + securityHandlers = securityHandlers->next; + rfbUnregisterSecurityHandler(handler->next); + return; + } + + cur = pre = securityHandlers; + + while(cur) { + if(cur == handler) { + pre->next = cur->next; + break; + } + pre = cur; + cur = cur->next; + } + rfbUnregisterSecurityHandler(handler->next); +} + +/* + * Send the authentication challenge. + */ + +static void +rfbVncAuthSendChallenge(rfbClientPtr cl) +{ + + /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth + (same as rfbVncAuth). Just send the challenge. */ + rfbRandomBytes(cl->authChallenge); + if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { + rfbLogPerror("rfbAuthNewClient: write"); + rfbCloseClient(cl); + return; + } + + /* Dispatch client input to rfbVncAuthProcessResponse. */ + cl->state = RFB_AUTHENTICATION; +} + +/* + * Send the NO AUTHENTICATION. SCARR + */ + +static void +rfbVncAuthNone(rfbClientPtr cl) +{ + uint32_t authResult; + + if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) { + rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n"); + authResult = Swap32IfLE(rfbVncAuthOK); + if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { + rfbLogPerror("rfbAuthProcessClientMessage: write"); + rfbCloseClient(cl); + return; + } + } + cl->state = RFB_INITIALISATION; + return; +} + + +/* + * Advertise the supported security types (protocol 3.7). Here before sending + * the list of security types to the client one more security type is added + * to the list if primaryType is not set to rfbSecTypeInvalid. This security + * type is the standard vnc security type which does the vnc authentication + * or it will be security type for no authentication. + * Different security types will be added by applications using this library. + */ + +static rfbSecurityHandler VncSecurityHandlerVncAuth = { + rfbSecTypeVncAuth, + rfbVncAuthSendChallenge, + NULL +}; + +static rfbSecurityHandler VncSecurityHandlerNone = { + rfbSecTypeNone, + rfbVncAuthNone, + NULL +}; + + +static void +rfbSendSecurityTypeList(rfbClientPtr cl, int primaryType) +{ + /* The size of the message is the count of security types +1, + * since the first byte is the number of types. */ + int size = 1; + rfbSecurityHandler* handler; +#define MAX_SECURITY_TYPES 255 + uint8_t buffer[MAX_SECURITY_TYPES+1]; + + + /* Fill in the list of security types in the client structure. (NOTE: Not really in the client structure) */ + switch (primaryType) { + case rfbSecTypeNone: + rfbRegisterSecurityHandler(&VncSecurityHandlerNone); + break; + case rfbSecTypeVncAuth: + rfbRegisterSecurityHandler(&VncSecurityHandlerVncAuth); + break; + } + + for (handler = securityHandlers; + handler && sizenext) { + buffer[size] = handler->type; + size++; + } + buffer[0] = (unsigned char)size-1; + + /* Send the list. */ + if (rfbWriteExact(cl, (char *)buffer, size) < 0) { + rfbLogPerror("rfbSendSecurityTypeList: write"); + rfbCloseClient(cl); + return; + } + + /* + * if count is 0, we need to send the reason and close the connection. + */ + if(size <= 1) { + /* This means total count is Zero and so reason msg should be sent */ + /* The execution should never reach here */ + char* reason = "No authentication mode is registered!"; + + rfbClientSendString(cl, reason); + return; + } + + /* Dispatch client input to rfbProcessClientSecurityType. */ + cl->state = RFB_SECURITY_TYPE; +} + + + + +/* + * Tell the client what security type will be used (protocol 3.3). + */ +static void +rfbSendSecurityType(rfbClientPtr cl, int32_t securityType) +{ + uint32_t value32; + + /* Send the value. */ + value32 = Swap32IfLE(securityType); + if (rfbWriteExact(cl, (char *)&value32, 4) < 0) { + rfbLogPerror("rfbSendSecurityType: write"); + rfbCloseClient(cl); + return; + } + + /* Decide what to do next. */ + switch (securityType) { + case rfbSecTypeNone: + /* Dispatch client input to rfbProcessClientInitMessage. */ + cl->state = RFB_INITIALISATION; + break; + case rfbSecTypeVncAuth: + /* Begin the standard VNC authentication procedure. */ + rfbVncAuthSendChallenge(cl); + break; + default: + /* Impossible case (hopefully). */ + rfbLogPerror("rfbSendSecurityType: assertion failed"); + rfbCloseClient(cl); + } +} + + + +/* + * rfbAuthNewClient is called right after negotiating the protocol + * version. Depending on the protocol version, we send either a code + * for authentication scheme to be used (protocol 3.3), or a list of + * possible "security types" (protocol 3.7). + */ + +void +rfbAuthNewClient(rfbClientPtr cl) +{ + int32_t securityType = rfbSecTypeInvalid; + + if (!cl->screen->authPasswdData || cl->reverseConnection) { + /* chk if this condition is valid or not. */ + securityType = rfbSecTypeNone; + } else if (cl->screen->authPasswdData) { + securityType = rfbSecTypeVncAuth; + } + + if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion < 7) + { + /* Make sure we use only RFB 3.3 compatible security types. */ + if (securityType == rfbSecTypeInvalid) { + rfbLog("VNC authentication disabled - RFB 3.3 client rejected\n"); + rfbClientConnFailed(cl, "Your viewer cannot handle required " + "authentication methods"); + return; + } + rfbSendSecurityType(cl, securityType); + } else { + /* Here it's ok when securityType is set to rfbSecTypeInvalid. */ + rfbSendSecurityTypeList(cl, securityType); + } +} + +/* + * Read the security type chosen by the client (protocol 3.7). + */ + +void +rfbProcessClientSecurityType(rfbClientPtr cl) +{ + int n; + uint8_t chosenType; + rfbSecurityHandler* handler; + + /* Read the security type. */ + n = rfbReadExact(cl, (char *)&chosenType, 1); + if (n <= 0) { + if (n == 0) + rfbLog("rfbProcessClientSecurityType: client gone\n"); + else + rfbLogPerror("rfbProcessClientSecurityType: read"); + rfbCloseClient(cl); + return; + } + + /* Make sure it was present in the list sent by the server. */ + for (handler = securityHandlers; handler; handler = handler->next) { + if (chosenType == handler->type) { + rfbLog("rfbProcessClientSecurityType: executing handler for type %d\n", chosenType); + handler->handler(cl); + return; + } + } + + rfbLog("rfbProcessClientSecurityType: wrong security type (%d) requested\n", chosenType); + rfbCloseClient(cl); +} + + + +/* + * rfbAuthProcessClientMessage is called when the client sends its + * authentication response. + */ + +void +rfbAuthProcessClientMessage(rfbClientPtr cl) +{ + int n; + uint8_t response[CHALLENGESIZE]; + uint32_t authResult; + + if ((n = rfbReadExact(cl, (char *)response, CHALLENGESIZE)) <= 0) { + if (n != 0) + rfbLogPerror("rfbAuthProcessClientMessage: read"); + rfbCloseClient(cl); + return; + } + + if(!cl->screen->passwordCheck(cl,(const char*)response,CHALLENGESIZE)) { + rfbErr("rfbAuthProcessClientMessage: password check failed\n"); + authResult = Swap32IfLE(rfbVncAuthFailed); + if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { + rfbLogPerror("rfbAuthProcessClientMessage: write"); + } + /* support RFB 3.8 clients, they expect a reason *why* it was disconnected */ + if (cl->protocolMinorVersion > 7) { + rfbClientSendString(cl, "password check failed!"); + } + else + rfbCloseClient(cl); + return; + } + + authResult = Swap32IfLE(rfbVncAuthOK); + + if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { + rfbLogPerror("rfbAuthProcessClientMessage: write"); + rfbCloseClient(cl); + return; + } + + cl->state = RFB_INITIALISATION; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c new file mode 100755 index 0000000..2e973e8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cargs.c @@ -0,0 +1,227 @@ +/* + * This parses the command line arguments. It was seperated from main.c by + * Justin Dearing . + */ + +/* + * LibVNCServer (C) 2001 Johannes E. Schindelin + * Original OSXvnc (C) 2001 Dan McGuirk . + * Original Xvnc (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * see GPL (latest version) for full details + */ + +#include + +extern int rfbStringToAddr(char *str, in_addr_t *iface); + +void +rfbUsage(void) +{ + rfbProtocolExtension* extension; + + fprintf(stderr, "-rfbport port TCP port for RFB protocol\n"); + fprintf(stderr, "-rfbwait time max time in ms to wait for RFB client\n"); + fprintf(stderr, "-rfbauth passwd-file use authentication on RFB protocol\n" + " (use 'storepasswd' to create a password file)\n"); + fprintf(stderr, "-rfbversion 3.x Set the version of the RFB we choose to advertise\n"); + fprintf(stderr, "-permitfiletransfer permit file transfer support\n"); + fprintf(stderr, "-passwd plain-password use authentication \n" + " (use plain-password as password, USE AT YOUR RISK)\n"); + fprintf(stderr, "-deferupdate time time in ms to defer updates " + "(default 40)\n"); + fprintf(stderr, "-deferptrupdate time time in ms to defer pointer updates" + " (default none)\n"); + fprintf(stderr, "-desktop name VNC desktop name (default \"LibVNCServer\")\n"); + fprintf(stderr, "-alwaysshared always treat new clients as shared\n"); + fprintf(stderr, "-nevershared never treat new clients as shared\n"); + fprintf(stderr, "-dontdisconnect don't disconnect existing clients when a " + "new non-shared\n" + " connection comes in (refuse new connection " + "instead)\n"); + fprintf(stderr, "-httpdir dir-path enable http server using dir-path home\n"); + fprintf(stderr, "-httpport portnum use portnum for http connection\n"); + fprintf(stderr, "-enablehttpproxy enable http proxy support\n"); + fprintf(stderr, "-progressive height enable progressive updating for slow links\n"); + fprintf(stderr, "-listen ipaddr listen for connections only on network interface with\n"); + fprintf(stderr, " addr ipaddr. '-listen localhost' and hostname work too.\n"); + + for(extension=rfbGetExtensionIterator();extension;extension=extension->next) + if(extension->usage) + extension->usage(); + rfbReleaseExtensionIterator(); +} + +/* purges COUNT arguments from ARGV at POSITION and decrements ARGC. + POSITION points to the first non purged argument afterwards. */ +void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]) +{ + int amount=(*argc)-(*position)-count; + if(amount) + memmove(argv+(*position),argv+(*position)+count,sizeof(char*)*amount); + (*argc)-=count; +} + +rfbBool +rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]) +{ + int i,i1; + + if(!argc) return TRUE; + + for (i = i1 = 1; i < *argc;) { + if (strcmp(argv[i], "-help") == 0) { + rfbUsage(); + return FALSE; + } else if (strcmp(argv[i], "-rfbport") == 0) { /* -rfbport port */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->port = atoi(argv[++i]); + } else if (strcmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->maxClientWait = atoi(argv[++i]); + } else if (strcmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->authPasswdData = argv[++i]; + + } else if (strcmp(argv[i], "-permitfiletransfer") == 0) { /* -permitfiletransfer */ + rfbScreen->permitFileTransfer = TRUE; + } else if (strcmp(argv[i], "-rfbversion") == 0) { /* -rfbversion 3.6 */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + sscanf(argv[++i],"%d.%d", &rfbScreen->protocolMajorVersion, &rfbScreen->protocolMinorVersion); + } else if (strcmp(argv[i], "-passwd") == 0) { /* -passwd password */ + char **passwds = malloc(sizeof(char**)*2); + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + passwds[0] = argv[++i]; + passwds[1] = NULL; + rfbScreen->authPasswdData = (void*)passwds; + rfbScreen->passwordCheck = rfbCheckPasswordByList; + } else if (strcmp(argv[i], "-deferupdate") == 0) { /* -deferupdate milliseconds */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->deferUpdateTime = atoi(argv[++i]); + } else if (strcmp(argv[i], "-deferptrupdate") == 0) { /* -deferptrupdate milliseconds */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->deferPtrUpdateTime = atoi(argv[++i]); + } else if (strcmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->desktopName = argv[++i]; + } else if (strcmp(argv[i], "-alwaysshared") == 0) { + rfbScreen->alwaysShared = TRUE; + } else if (strcmp(argv[i], "-nevershared") == 0) { + rfbScreen->neverShared = TRUE; + } else if (strcmp(argv[i], "-dontdisconnect") == 0) { + rfbScreen->dontDisconnect = TRUE; + } else if (strcmp(argv[i], "-httpdir") == 0) { /* -httpdir directory-path */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->httpDir = argv[++i]; + } else if (strcmp(argv[i], "-httpport") == 0) { /* -httpport portnum */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->httpPort = atoi(argv[++i]); + } else if (strcmp(argv[i], "-enablehttpproxy") == 0) { + rfbScreen->httpEnableProxyConnect = TRUE; + } else if (strcmp(argv[i], "-progressive") == 0) { /* -httpport portnum */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->progressiveSliceHeight = atoi(argv[++i]); + } else if (strcmp(argv[i], "-listen") == 0) { /* -listen ipaddr */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + if (! rfbStringToAddr(argv[++i], &(rfbScreen->listenInterface))) { + return FALSE; + } +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + } else if (strcmp(argv[i], "-sslkeyfile") == 0) { /* -sslkeyfile sslkeyfile */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->sslkeyfile = argv[++i]; + } else if (strcmp(argv[i], "-sslcertfile") == 0) { /* -sslcertfile sslcertfile */ + if (i + 1 >= *argc) { + rfbUsage(); + return FALSE; + } + rfbScreen->sslcertfile = argv[++i]; +#endif + } else { + rfbProtocolExtension* extension; + int handled=0; + + for(extension=rfbGetExtensionIterator();handled==0 && extension; + extension=extension->next) + if(extension->processArgument) + handled = extension->processArgument(*argc - i, argv + i); + rfbReleaseExtensionIterator(); + + if(handled==0) { + i++; + i1=i; + continue; + } + i+=handled-1; + } + /* we just remove the processed arguments from the list */ + rfbPurgeArguments(argc,&i1,i-i1+1,argv); + i=i1; + } + return TRUE; +} + +rfbBool +rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]) +{ + int i,i1; + + if(!argc) return TRUE; + for (i = i1 = 1; i < *argc-1;) { + if (strcmp(argv[i], "-bpp") == 0) { + *bpp = atoi(argv[++i]); + } else if (strcmp(argv[i], "-width") == 0) { + *width = atoi(argv[++i]); + } else if (strcmp(argv[i], "-height") == 0) { + *height = atoi(argv[++i]); + } else { + i++; + i1=i; + continue; + } + rfbPurgeArguments(argc,&i1,i-i1,argv); + i=i1; + } + return TRUE; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c new file mode 100755 index 0000000..bb07c77 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/corre.c @@ -0,0 +1,360 @@ +/* + * corre.c + * + * Routines to implement Compact Rise-and-Run-length Encoding (CoRRE). This + * code is based on krw's original javatel rfbserver. + */ + +/* + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +/* + * rreBeforeBuf contains pixel data in the client's format. + * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is + * larger than the raw data or if it exceeds rreAfterBufSize then + * raw encoding is used instead. + */ + +static int rreBeforeBufSize = 0; +static char *rreBeforeBuf = NULL; + +static int rreAfterBufSize = 0; +static char *rreAfterBuf = NULL; +static int rreAfterBufLen = 0; + +static int subrectEncode8(uint8_t *data, int w, int h); +static int subrectEncode16(uint16_t *data, int w, int h); +static int subrectEncode32(uint32_t *data, int w, int h); +static uint32_t getBgColour(char *data, int size, int bpp); +static rfbBool rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, int x, int y, + int w, int h); + +void rfbCoRRECleanup(rfbScreenInfoPtr screen) +{ + if (rreBeforeBufSize) { + free(rreBeforeBuf); + rreBeforeBufSize=0; + } + if (rreAfterBufSize) { + free(rreAfterBuf); + rreAfterBufSize=0; + } +} + +/* + * rfbSendRectEncodingCoRRE - send an arbitrary size rectangle using CoRRE + * encoding. + */ + +rfbBool +rfbSendRectEncodingCoRRE(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + if (h > cl->correMaxHeight) { + return (rfbSendRectEncodingCoRRE(cl, x, y, w, cl->correMaxHeight) && + rfbSendRectEncodingCoRRE(cl, x, y + cl->correMaxHeight, w, + h - cl->correMaxHeight)); + } + + if (w > cl->correMaxWidth) { + return (rfbSendRectEncodingCoRRE(cl, x, y, cl->correMaxWidth, h) && + rfbSendRectEncodingCoRRE(cl, x + cl->correMaxWidth, y, + w - cl->correMaxWidth, h)); + } + + rfbSendSmallRectEncodingCoRRE(cl, x, y, w, h); + return TRUE; +} + + + +/* + * rfbSendSmallRectEncodingCoRRE - send a small (guaranteed < 256x256) + * rectangle using CoRRE encoding. + */ + +static rfbBool +rfbSendSmallRectEncodingCoRRE(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + rfbRREHeader hdr; + int nSubrects; + int i; + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height + * (cl->format.bitsPerPixel / 8)); + + if (rreBeforeBufSize < maxRawSize) { + rreBeforeBufSize = maxRawSize; + if (rreBeforeBuf == NULL) + rreBeforeBuf = (char *)malloc(rreBeforeBufSize); + else + rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize); + } + + if (rreAfterBufSize < maxRawSize) { + rreAfterBufSize = maxRawSize; + if (rreAfterBuf == NULL) + rreAfterBuf = (char *)malloc(rreAfterBufSize); + else + rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize); + } + + (*cl->translateFn)(cl->translateLookupTable,&(cl->screen->serverFormat), + &cl->format, fbptr, rreBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + switch (cl->format.bitsPerPixel) { + case 8: + nSubrects = subrectEncode8((uint8_t *)rreBeforeBuf, w, h); + break; + case 16: + nSubrects = subrectEncode16((uint16_t *)rreBeforeBuf, w, h); + break; + case 32: + nSubrects = subrectEncode32((uint32_t *)rreBeforeBuf, w, h); + break; + default: + rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); + return FALSE; + } + + if (nSubrects < 0) { + + /* RRE encoding was too large, use raw */ + + return rfbSendRectEncodingRaw(cl, x, y, w, h); + } + + rfbStatRecordEncodingSent(cl,rfbEncodingCoRRE, + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen, + sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8)); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + > UPDATE_BUF_SIZE) + { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingCoRRE); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.nSubrects = Swap32IfLE(nSubrects); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader); + cl->ublen += sz_rfbRREHeader; + + for (i = 0; i < rreAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > rreAfterBufLen) { + bytesToCopy = rreAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; +} + + + +/* + * subrectEncode() encodes the given multicoloured rectangle as a background + * colour overwritten by single-coloured rectangles. It returns the number + * of subrectangles in the encoded buffer, or -1 if subrect encoding won't + * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The + * single-colour rectangle partition is not optimal, but does find the biggest + * horizontal or vertical rectangle top-left anchored to each consecutive + * coordinate position. + * + * The coding scheme is simply [...] where each + * is []. + */ + +#define DEFINE_SUBRECT_ENCODE(bpp) \ +static int \ +subrectEncode##bpp(uint##bpp##_t *data, int w, int h) { \ + uint##bpp##_t cl; \ + rfbCoRRERectangle subrect; \ + int x,y; \ + int i,j; \ + int hx=0,hy,vx=0,vy; \ + int hyflag; \ + uint##bpp##_t *seg; \ + uint##bpp##_t *line; \ + int hw,hh,vw,vh; \ + int thex,they,thew,theh; \ + int numsubs = 0; \ + int newLen; \ + uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \ + \ + *((uint##bpp##_t*)rreAfterBuf) = bg; \ + \ + rreAfterBufLen = (bpp/8); \ + \ + for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ + } \ + vy = j-1; \ + \ + /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ + * We'll choose the bigger of the two. \ + */ \ + hw = hx-x+1; \ + hh = hy-y+1; \ + vw = vx-x+1; \ + vh = vy-y+1; \ + \ + thex = x; \ + they = y; \ + \ + if ((hw*hh) > (vw*vh)) { \ + thew = hw; \ + theh = hh; \ + } else { \ + thew = vw; \ + theh = vh; \ + } \ + \ + subrect.x = thex; \ + subrect.y = they; \ + subrect.w = thew; \ + subrect.h = theh; \ + \ + newLen = rreAfterBufLen + (bpp/8) + sz_rfbCoRRERectangle; \ + if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ + return -1; \ + \ + numsubs += 1; \ + *((uint##bpp##_t*)(rreAfterBuf + rreAfterBufLen)) = cl; \ + rreAfterBufLen += (bpp/8); \ + memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbCoRRERectangle); \ + rreAfterBufLen += sz_rfbCoRRERectangle; \ + \ + /* \ + * Now mark the subrect as done. \ + */ \ + for (j=they; j < (they+theh); j++) { \ + for (i=thex; i < (thex+thew); i++) { \ + data[j*w+i] = bg; \ + } \ + } \ + } \ + } \ + } \ + \ + return numsubs; \ +} + +DEFINE_SUBRECT_ENCODE(8) +DEFINE_SUBRECT_ENCODE(16) +DEFINE_SUBRECT_ENCODE(32) + + +/* + * getBgColour() gets the most prevalent colour in a byte array. + */ +static uint32_t +getBgColour(char *data, int size, int bpp) +{ + +#define NUMCLRS 256 + + static int counts[NUMCLRS]; + int i,j,k; + + int maxcount = 0; + uint8_t maxclr = 0; + + if (bpp != 8) { + if (bpp == 16) { + return ((uint16_t *)data)[0]; + } else if (bpp == 32) { + return ((uint32_t *)data)[0]; + } else { + rfbLog("getBgColour: bpp %d?\n",bpp); + return 0; + } + } + + for (i=0; i= NUMCLRS) { + rfbLog("getBgColour: unusual colour = %d\n", k); + return 0; + } + counts[k] += 1; + if (counts[k] > maxcount) { + maxcount = counts[k]; + maxclr = ((uint8_t *)data)[j]; + } + } + + return maxclr; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c new file mode 100755 index 0000000..c071dd9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cursor.c @@ -0,0 +1,756 @@ +/* + * cursor.c - support for cursor shape updates. + */ + +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include +#include "private.h" + +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2); + +/* + * Send cursor shape either in X-style format or in client pixel format. + */ + +rfbBool +rfbSendCursorShape(rfbClientPtr cl) +{ + rfbCursorPtr pCursor; + rfbFramebufferUpdateRectHeader rect; + rfbXCursorColors colors; + int saved_ublen; + int bitmapRowBytes, maskBytes, dataBytes; + int i, j; + uint8_t *bitmapData; + uint8_t bitmapByte; + + /* TODO: scale the cursor data to the correct size */ + + pCursor = cl->screen->getCursorPtr(cl); + /*if(!pCursor) return TRUE;*/ + + if (cl->useRichCursorEncoding) { + if(pCursor && !pCursor->richSource) + rfbMakeRichCursorFromXCursor(cl->screen,pCursor); + rect.encoding = Swap32IfLE(rfbEncodingRichCursor); + } else { + if(pCursor && !pCursor->source) + rfbMakeXCursorFromRichCursor(cl->screen,pCursor); + rect.encoding = Swap32IfLE(rfbEncodingXCursor); + } + + /* If there is no cursor, send update with empty cursor data. */ + + if ( pCursor && pCursor->width == 1 && + pCursor->height == 1 && + pCursor->mask[0] == 0 ) { + pCursor = NULL; + } + + if (pCursor == NULL) { + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + rect.r.x = rect.r.y = 0; + rect.r.w = rect.r.h = 0; + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; + } + + /* Calculate data sizes. */ + + bitmapRowBytes = (pCursor->width + 7) / 8; + maskBytes = bitmapRowBytes * pCursor->height; + dataBytes = (cl->useRichCursorEncoding) ? + (pCursor->width * pCursor->height * + (cl->format.bitsPerPixel / 8)) : maskBytes; + + /* Send buffer contents if needed. */ + + if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader + + sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader + + sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) { + return FALSE; /* FIXME. */ + } + + saved_ublen = cl->ublen; + + /* Prepare rectangle header. */ + + rect.r.x = Swap16IfLE(pCursor->xhot); + rect.r.y = Swap16IfLE(pCursor->yhot); + rect.r.w = Swap16IfLE(pCursor->width); + rect.r.h = Swap16IfLE(pCursor->height); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + /* Prepare actual cursor data (depends on encoding used). */ + + if (!cl->useRichCursorEncoding) { + /* XCursor encoding. */ + colors.foreRed = (char)(pCursor->foreRed >> 8); + colors.foreGreen = (char)(pCursor->foreGreen >> 8); + colors.foreBlue = (char)(pCursor->foreBlue >> 8); + colors.backRed = (char)(pCursor->backRed >> 8); + colors.backGreen = (char)(pCursor->backGreen >> 8); + colors.backBlue = (char)(pCursor->backBlue >> 8); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors); + cl->ublen += sz_rfbXCursorColors; + + bitmapData = (uint8_t *)pCursor->source; + + for (i = 0; i < pCursor->height; i++) { + for (j = 0; j < bitmapRowBytes; j++) { + bitmapByte = bitmapData[i * bitmapRowBytes + j]; + cl->updateBuf[cl->ublen++] = (char)bitmapByte; + } + } + } else { + /* RichCursor encoding. */ + int bpp1=cl->screen->serverFormat.bitsPerPixel/8, + bpp2=cl->format.bitsPerPixel/8; + (*cl->translateFn)(cl->translateLookupTable, + &(cl->screen->serverFormat), + &cl->format, (char*)pCursor->richSource, + &cl->updateBuf[cl->ublen], + pCursor->width*bpp1, pCursor->width, pCursor->height); + + cl->ublen += pCursor->width*bpp2*pCursor->height; + } + + /* Prepare transparency mask. */ + + bitmapData = (uint8_t *)pCursor->mask; + + for (i = 0; i < pCursor->height; i++) { + for (j = 0; j < bitmapRowBytes; j++) { + bitmapByte = bitmapData[i * bitmapRowBytes + j]; + cl->updateBuf[cl->ublen++] = (char)bitmapByte; + } + } + + /* Send everything we have prepared in the cl->updateBuf[]. */ + rfbStatRecordEncodingSent(cl, (cl->useRichCursorEncoding ? rfbEncodingRichCursor : rfbEncodingXCursor), + sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen), sz_rfbFramebufferUpdateRectHeader + (cl->ublen - saved_ublen)); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + +/* + * Send cursor position (PointerPos pseudo-encoding). + */ + +rfbBool +rfbSendCursorPos(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingPointerPos); + rect.r.x = Swap16IfLE(cl->screen->cursorX); + rect.r.y = Swap16IfLE(cl->screen->cursorY); + rect.r.w = 0; + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingPointerPos, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + +/* conversion routine for predefined cursors in LSB order */ +unsigned char rfbReverseByte[0x100] = { + /* copied from Xvnc/lib/font/util/utilbitmap.c */ + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap) +{ + int i,t=(width+7)/8*height; + for(i=0;icleanup=TRUE; + cursor->width=width; + cursor->height=height; + /*cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;*/ + cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff; + + cursor->source = (unsigned char*)calloc(w,height); + cursor->cleanupSource = TRUE; + for(j=0,cp=cursorString;j>1,cp++) + if(*cp!=' ') cursor->source[j*w+i/8]|=bit; + + if(maskString) { + cursor->mask = (unsigned char*)calloc(w,height); + for(j=0,cp=maskString;j>1,cp++) + if(*cp!=' ') cursor->mask[j*w+i/8]|=bit; + } else + cursor->mask = (unsigned char*)rfbMakeMaskForXCursor(width,height,(char*)cursor->source); + cursor->cleanupMask = TRUE; + + return(cursor); +} + +char* rfbMakeMaskForXCursor(int width,int height,char* source) +{ + int i,j,w=(width+7)/8; + char* mask=(char*)calloc(w,height); + unsigned char c; + + for(j=0;j=0;i--) { + c=source[j*w+i]; + if(j>0) c|=source[(j-1)*w+i]; + if(j0 && (c&0x80)) + mask[j*w+i-1]|=0x01; + if(i>1); + } + + return(mask); +} + +/* this function dithers the alpha using Floyd-Steinberg */ + +char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource) +{ + int* error=(int*)calloc(sizeof(int),width); + int i,j,currentError=0,maskStride=(width+7)/8; + unsigned char* result=(unsigned char*)calloc(maskStride,height); + + for(j=0;j>(i&7)); + /* alpha was treated as 0xff */ + currentError-=0xff; + } + /* propagate to next row */ + right=currentError/16; + middle=currentError*5/16; + left=currentError*3/16; + currentError-=right+middle+left; + error[i]=right; + if(i>0) { + error[i-1]=middle; + if(i>1) + error[i-2]=left; + } + } + free(error); + return (char *) result; +} + +void rfbFreeCursor(rfbCursorPtr cursor) +{ + if(cursor) { + if(cursor->cleanupRichSource && cursor->richSource) + free(cursor->richSource); + if(cursor->cleanupRichSource && cursor->alphaSource) + free(cursor->alphaSource); + if(cursor->cleanupSource && cursor->source) + free(cursor->source); + if(cursor->cleanupMask && cursor->mask) + free(cursor->mask); + if(cursor->cleanup) + free(cursor); + else { + cursor->cleanup=cursor->cleanupSource=cursor->cleanupMask + =cursor->cleanupRichSource=FALSE; + cursor->source=cursor->mask=cursor->richSource=NULL; + cursor->alphaSource=NULL; + } + } + +} + +/* background and foregroud colour have to be set beforehand */ +void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor) +{ + rfbPixelFormat* format=&rfbScreen->serverFormat; + int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8, + width=cursor->width*bpp; + uint32_t background; + char *back=(char*)&background; + unsigned char bit; + int interp = 0, db = 0; + + if(cursor->source && cursor->cleanupSource) + free(cursor->source); + cursor->source=(unsigned char*)calloc(w,cursor->height); + cursor->cleanupSource=TRUE; + + if(format->bigEndian) { + back+=4-bpp; + } + + /* all zeros means we should interpolate to black+white ourselves */ + if (!cursor->backRed && !cursor->backGreen && !cursor->backBlue && + !cursor->foreRed && !cursor->foreGreen && !cursor->foreBlue) { + if (format->trueColour && (bpp == 1 || bpp == 2 || bpp == 4)) { + interp = 1; + cursor->foreRed = cursor->foreGreen = cursor->foreBlue = 0xffff; + } + } + + background = ((format->redMax * cursor->backRed) / 0xffff) << format->redShift | + ((format->greenMax * cursor->backGreen) / 0xffff) << format->greenShift | + ((format->blueMax * cursor->backBlue) / 0xffff) << format->blueShift; + +#define SETRGB(u) \ + r = (255 * (((format->redMax << format->redShift) & (*u)) >> format->redShift)) / format->redMax; \ + g = (255 * (((format->greenMax << format->greenShift) & (*u)) >> format->greenShift)) / format->greenMax; \ + b = (255 * (((format->blueMax << format->blueShift) & (*u)) >> format->blueShift)) / format->blueMax; + + if (db) fprintf(stderr, "interp: %d\n", interp); + + for(j=0;jheight;j++) { + for(i=0,bit=0x80;iwidth;i++,bit=(bit&1)?0x80:bit>>1) { + if (interp) { + int r = 0, g = 0, b = 0, grey; + unsigned char *p = cursor->richSource+j*width+i*bpp; + if (bpp == 1) { + unsigned char* uc = (unsigned char*) p; + SETRGB(uc); + } else if (bpp == 2) { + unsigned short* us = (unsigned short*) p; + SETRGB(us); + } else if (bpp == 4) { + unsigned int* ui = (unsigned int*) p; + SETRGB(ui); + } + grey = (r + g + b) / 3; + if (grey >= 128) { + cursor->source[j*w+i/8]|=bit; + if (db) fprintf(stderr, "1"); + } else { + if (db) fprintf(stderr, "0"); + } + + } else if(memcmp(cursor->richSource+j*width+i*bpp, back, bpp)) { + cursor->source[j*w+i/8]|=bit; + } + } + if (db) fprintf(stderr, "\n"); + } +} + +void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor) +{ + rfbPixelFormat* format=&rfbScreen->serverFormat; + int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8; + uint32_t background,foreground; + char *back=(char*)&background,*fore=(char*)&foreground; + unsigned char *cp; + unsigned char bit; + + if(cursor->richSource && cursor->cleanupRichSource) + free(cursor->richSource); + cp=cursor->richSource=(unsigned char*)calloc(cursor->width*bpp,cursor->height); + cursor->cleanupRichSource=TRUE; + + if(format->bigEndian) { + back+=4-bpp; + fore+=4-bpp; + } + + background=cursor->backRed<redShift| + cursor->backGreen<greenShift|cursor->backBlue<blueShift; + foreground=cursor->foreRed<redShift| + cursor->foreGreen<greenShift|cursor->foreBlue<blueShift; + + for(j=0;jheight;j++) + for(i=0,bit=0x80;iwidth;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp) + if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp); + else memcpy(cp,back,bpp); +} + +/* functions to draw/hide cursor directly in the frame buffer */ + +void rfbHideCursor(rfbClientPtr cl) +{ + rfbScreenInfoPtr s=cl->screen; + rfbCursorPtr c=s->cursor; + int j,x1,x2,y1,y2,bpp=s->serverFormat.bitsPerPixel/8, + rowstride=s->paddedWidthInBytes; + LOCK(s->cursorMutex); + if(!c) { + UNLOCK(s->cursorMutex); + return; + } + + /* restore what is under the cursor */ + x1=cl->cursorX-c->xhot; + x2=x1+c->width; + if(x1<0) x1=0; + if(x2>=s->width) x2=s->width-1; + x2-=x1; if(x2<=0) { + UNLOCK(s->cursorMutex); + return; + } + y1=cl->cursorY-c->yhot; + y2=y1+c->height; + if(y1<0) y1=0; + if(y2>=s->height) y2=s->height-1; + y2-=y1; if(y2<=0) { + UNLOCK(s->cursorMutex); + return; + } + + /* get saved data */ + for(j=0;jframeBuffer+(y1+j)*rowstride+x1*bpp, + s->underCursorBuffer+j*x2*bpp, + x2*bpp); + + /* Copy to all scaled versions */ + rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2); + + UNLOCK(s->cursorMutex); +} + +void rfbShowCursor(rfbClientPtr cl) +{ + rfbScreenInfoPtr s=cl->screen; + rfbCursorPtr c=s->cursor; + int i,j,x1,x2,y1,y2,i1,j1,bpp=s->serverFormat.bitsPerPixel/8, + rowstride=s->paddedWidthInBytes, + bufSize,w; + rfbBool wasChanged=FALSE; + + if(!c) return; + LOCK(s->cursorMutex); + + bufSize=c->width*c->height*bpp; + w=(c->width+7)/8; + if(s->underCursorBufferLenunderCursorBuffer!=NULL) + free(s->underCursorBuffer); + s->underCursorBuffer=malloc(bufSize); + s->underCursorBufferLen=bufSize; + } + + /* save what is under the cursor */ + i1=j1=0; /* offset in cursor */ + x1=cl->cursorX-c->xhot; + x2=x1+c->width; + if(x1<0) { i1=-x1; x1=0; } + if(x2>=s->width) x2=s->width-1; + x2-=x1; if(x2<=0) { + UNLOCK(s->cursorMutex); + return; /* nothing to do */ + } + + y1=cl->cursorY-c->yhot; + y2=y1+c->height; + if(y1<0) { j1=-y1; y1=0; } + if(y2>=s->height) y2=s->height-1; + y2-=y1; if(y2<=0) { + UNLOCK(s->cursorMutex); + return; /* nothing to do */ + } + + /* save data */ + for(j=0;junderCursorBuffer+j*x2*bpp; + const char* src=s->frameBuffer+(y1+j)*rowstride+x1*bpp; + unsigned int count=x2*bpp; + if(wasChanged || memcmp(dest,src,count)) { + wasChanged=TRUE; + memcpy(dest,src,count); + } + } + + if(!c->richSource) + rfbMakeRichCursorFromXCursor(s,c); + + if (c->alphaSource) { + int rmax, rshift; + int gmax, gshift; + int bmax, bshift; + int amax = 255; /* alphaSource is always 8bits of info per pixel */ + unsigned int rmask, gmask, bmask; + + rmax = s->serverFormat.redMax; + gmax = s->serverFormat.greenMax; + bmax = s->serverFormat.blueMax; + rshift = s->serverFormat.redShift; + gshift = s->serverFormat.greenShift; + bshift = s->serverFormat.blueShift; + + rmask = (rmax << rshift); + gmask = (gmax << gshift); + bmask = (bmax << bshift); + + for(j=0;jmask[], + * using the extracted alpha value instead. + */ + char *dest; + unsigned char *src, *aptr; + unsigned int val, dval, sval; + int rdst, gdst, bdst; /* fb RGB */ + int asrc, rsrc, gsrc, bsrc; /* rich source ARGB */ + + dest = s->frameBuffer + (j+y1)*rowstride + (i+x1)*bpp; + src = c->richSource + (j+j1)*c->width*bpp + (i+i1)*bpp; + aptr = c->alphaSource + (j+j1)*c->width + (i+i1); + + asrc = *aptr; + if (!asrc) { + continue; + } + + if (bpp == 1) { + dval = *((unsigned char*) dest); + sval = *((unsigned char*) src); + } else if (bpp == 2) { + dval = *((unsigned short*) dest); + sval = *((unsigned short*) src); + } else if (bpp == 3) { + unsigned char *dst = (unsigned char *) dest; + dval = 0; + dval |= ((*(dst+0)) << 0); + dval |= ((*(dst+1)) << 8); + dval |= ((*(dst+2)) << 16); + sval = 0; + sval |= ((*(src+0)) << 0); + sval |= ((*(src+1)) << 8); + sval |= ((*(src+2)) << 16); + } else if (bpp == 4) { + dval = *((unsigned int*) dest); + sval = *((unsigned int*) src); + } else { + continue; + } + + /* extract dest and src RGB */ + rdst = (dval & rmask) >> rshift; /* fb */ + gdst = (dval & gmask) >> gshift; + bdst = (dval & bmask) >> bshift; + + rsrc = (sval & rmask) >> rshift; /* richcursor */ + gsrc = (sval & gmask) >> gshift; + bsrc = (sval & bmask) >> bshift; + + /* blend in fb data. */ + if (! c->alphaPreMultiplied) { + rsrc = (asrc * rsrc)/amax; + gsrc = (asrc * gsrc)/amax; + bsrc = (asrc * bsrc)/amax; + } + rdst = rsrc + ((amax - asrc) * rdst)/amax; + gdst = gsrc + ((amax - asrc) * gdst)/amax; + bdst = bsrc + ((amax - asrc) * bdst)/amax; + + val = 0; + val |= (rdst << rshift); + val |= (gdst << gshift); + val |= (bdst << bshift); + + /* insert the cooked pixel into the fb */ + memcpy(dest, &val, bpp); + } + } + } else { + /* now the cursor has to be drawn */ + for(j=0;jmask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80) + memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp, + c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp); + } + + /* Copy to all scaled versions */ + rfbScaledScreenUpdate(s, x1, y1, x1+x2, y1+y2); + + UNLOCK(s->cursorMutex); +} + +/* + * If enableCursorShapeUpdates is FALSE, and the cursor is hidden, make sure + * that if the frameBuffer was transmitted with a cursor drawn, then that + * region gets redrawn. + */ + +void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion) +{ + rfbScreenInfoPtr s = cl->screen; + rfbCursorPtr c = s->cursor; + + if(c) { + int x,y,x2,y2; + + x = cl->cursorX-c->xhot; + y = cl->cursorY-c->yhot; + x2 = x+c->width; + y2 = y+c->height; + + if(sraClipRect2(&x,&y,&x2,&y2,0,0,s->width,s->height)) { + sraRegionPtr rect; + rect = sraRgnCreateRect(x,y,x2,y2); + if(updateRegion) { + sraRgnOr(updateRegion,rect); + } else { + LOCK(cl->updateMutex); + sraRgnOr(cl->modifiedRegion,rect); + UNLOCK(cl->updateMutex); + } + sraRgnDestroy(rect); + } + } +} + +#ifdef DEBUG + +static void rfbPrintXCursor(rfbCursorPtr cursor) +{ + int i,i1,j,w=(cursor->width+7)/8; + unsigned char bit; + for(j=0;jheight;j++) { + for(i=0,i1=0,bit=0x80;i1width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1) + if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' '); + putchar(':'); + for(i=0,i1=0,bit=0x80;i1width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1) + if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' '); + putchar('\n'); + } +} + +#endif + +void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + LOCK(rfbScreen->cursorMutex); + + if(rfbScreen->cursor) { + iterator=rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(iterator))) + if(!cl->enableCursorShapeUpdates) + rfbRedrawAfterHideCursor(cl,NULL); + rfbReleaseClientIterator(iterator); + + if(rfbScreen->cursor->cleanup) + rfbFreeCursor(rfbScreen->cursor); + } + + rfbScreen->cursor = c; + + iterator=rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(iterator))) { + cl->cursorWasChanged = TRUE; + if(!cl->enableCursorShapeUpdates) + rfbRedrawAfterHideCursor(cl,NULL); + } + rfbReleaseClientIterator(iterator); + + UNLOCK(rfbScreen->cursorMutex); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c new file mode 100755 index 0000000..6a9dcb9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/cutpaste.c @@ -0,0 +1,38 @@ +/* + * cutpaste.c - routines to deal with cut & paste buffers / selection. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + + +/* + * rfbSetXCutText sets the cut buffer to be the given string. We also clear + * the primary selection. Ideally we'd like to set it to the same thing, but I + * can't work out how to do that without some kind of helper X client. + */ + +void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len) +{ + rfbSendServerCutText(rfbScreen, str, len); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c new file mode 100755 index 0000000..2df1aab --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.c @@ -0,0 +1,436 @@ +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. Also the bytebit[] array + * has been reversed so that the most significant bit in each byte of the + * key is ignored, not the least significant. + * + * 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. + */ + +/* D3DES (V5.09) - + * + * A portable, public domain, version of the Data Encryption Standard. + * + * Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge. + * Thanks to: Dan Hoey for his excellent Initial and Inverse permutation + * code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis + * Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau, + * for humouring me on. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge. + * (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992. + */ + +#include "d3des.h" + +static void scrunch(unsigned char *, unsigned long *); +static void unscrun(unsigned long *, unsigned char *); +static void desfunc(unsigned long *, unsigned long *); +static void cookey(unsigned long *); + +static unsigned long KnL[32] = { 0L }; +/* +static unsigned long KnR[32] = { 0L }; +static unsigned long Kn3[32] = { 0L }; +static unsigned char Df_Key[24] = { + 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, + 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, + 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 }; +*/ + +static unsigned short bytebit[8] = { + 01, 02, 04, 010, 020, 040, 0100, 0200 }; + +static unsigned long bigbyte[24] = { + 0x800000L, 0x400000L, 0x200000L, 0x100000L, + 0x80000L, 0x40000L, 0x20000L, 0x10000L, + 0x8000L, 0x4000L, 0x2000L, 0x1000L, + 0x800L, 0x400L, 0x200L, 0x100L, + 0x80L, 0x40L, 0x20L, 0x10L, + 0x8L, 0x4L, 0x2L, 0x1L }; + +/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */ + +static unsigned char pc1[56] = { + 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, + 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, + 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, + 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 }; + +static unsigned char totrot[16] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 }; + +static unsigned char pc2[48] = { + 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 }; + +void rfbDesKey(unsigned char *key, + int edf) +{ + register int i, j, l, m, n; + unsigned char pc1m[56], pcr[56]; + unsigned long kn[32]; + + for ( j = 0; j < 56; j++ ) { + l = pc1[j]; + m = l & 07; + pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0; + } + for( i = 0; i < 16; i++ ) { + if( edf == DE1 ) m = (15 - i) << 1; + else m = i << 1; + n = m + 1; + kn[m] = kn[n] = 0L; + for( j = 0; j < 28; j++ ) { + l = j + totrot[i]; + if( l < 28 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 28; j < 56; j++ ) { + l = j + totrot[i]; + if( l < 56 ) pcr[j] = pc1m[l]; + else pcr[j] = pc1m[l - 28]; + } + for( j = 0; j < 24; j++ ) { + if( pcr[pc2[j]] ) kn[m] |= bigbyte[j]; + if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j]; + } + } + cookey(kn); + return; + } + +static void cookey(register unsigned long *raw1) +{ + register unsigned long *cook, *raw0; + unsigned long dough[32]; + register int i; + + cook = dough; + for( i = 0; i < 16; i++, raw1++ ) { + raw0 = raw1++; + *cook = (*raw0 & 0x00fc0000L) << 6; + *cook |= (*raw0 & 0x00000fc0L) << 10; + *cook |= (*raw1 & 0x00fc0000L) >> 10; + *cook++ |= (*raw1 & 0x00000fc0L) >> 6; + *cook = (*raw0 & 0x0003f000L) << 12; + *cook |= (*raw0 & 0x0000003fL) << 16; + *cook |= (*raw1 & 0x0003f000L) >> 4; + *cook++ |= (*raw1 & 0x0000003fL); + } + rfbUseKey(dough); + return; + } + +void rfbCPKey(register unsigned long *into) +{ + register unsigned long *from, *endp; + + from = KnL, endp = &KnL[32]; + while( from < endp ) *into++ = *from++; + return; + } + +void rfbUseKey(register unsigned long *from) +{ + register unsigned long *to, *endp; + + to = KnL, endp = &KnL[32]; + while( to < endp ) *to++ = *from++; + return; + } + +void rfbDes(unsigned char *inblock, + unsigned char *outblock) +{ + unsigned long work[2]; + + scrunch(inblock, work); + desfunc(work, KnL); + unscrun(work, outblock); + return; + } + +static void scrunch(register unsigned char *outof, + register unsigned long *into) +{ + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into++ |= (*outof++ & 0xffL); + *into = (*outof++ & 0xffL) << 24; + *into |= (*outof++ & 0xffL) << 16; + *into |= (*outof++ & 0xffL) << 8; + *into |= (*outof & 0xffL); + return; + } + +static void unscrun(register unsigned long *outof, + register unsigned char *into) +{ + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into++ = (unsigned char)( *outof++ & 0xffL); + *into++ = (unsigned char)((*outof >> 24) & 0xffL); + *into++ = (unsigned char)((*outof >> 16) & 0xffL); + *into++ = (unsigned char)((*outof >> 8) & 0xffL); + *into = (unsigned char)( *outof & 0xffL); + return; + } + +static unsigned long SP1[64] = { + 0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L, + 0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L, + 0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L, + 0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L, + 0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L, + 0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L, + 0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L, + 0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L, + 0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L, + 0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L, + 0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L, + 0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L, + 0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L, + 0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L, + 0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L }; + +static unsigned long SP2[64] = { + 0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L, + 0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L, + 0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L, + 0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L, + 0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L, + 0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L, + 0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L, + 0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L, + 0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L, + 0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L, + 0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L, + 0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L, + 0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L, + 0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L, + 0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L, + 0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L }; + +static unsigned long SP3[64] = { + 0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L, + 0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L, + 0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L, + 0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L, + 0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L, + 0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L, + 0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L, + 0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L, + 0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L, + 0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L, + 0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L, + 0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L, + 0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L, + 0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L, + 0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L, + 0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L }; + +static unsigned long SP4[64] = { + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L, + 0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L, + 0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L, + 0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L, + 0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L, + 0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L, + 0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L, + 0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L, + 0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L, + 0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L, + 0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L, + 0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L, + 0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L }; + +static unsigned long SP5[64] = { + 0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L, + 0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L, + 0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L, + 0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L, + 0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L, + 0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L, + 0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L, + 0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L, + 0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L, + 0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L, + 0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L, + 0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L, + 0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L, + 0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L, + 0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L, + 0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L }; + +static unsigned long SP6[64] = { + 0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L, + 0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L, + 0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L, + 0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L, + 0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L, + 0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L, + 0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L, + 0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L, + 0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L, + 0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L, + 0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L, + 0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L, + 0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L, + 0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L, + 0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L }; + +static unsigned long SP7[64] = { + 0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L, + 0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L, + 0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L, + 0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L, + 0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L, + 0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L, + 0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L, + 0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L, + 0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L, + 0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L, + 0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L, + 0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L, + 0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L, + 0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L, + 0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L, + 0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L }; + +static unsigned long SP8[64] = { + 0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L, + 0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L, + 0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L, + 0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L, + 0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L, + 0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L, + 0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L, + 0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L, + 0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L, + 0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L, + 0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L, + 0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L, + 0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L, + 0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L, + 0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L, + 0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L }; + +static void desfunc(register unsigned long *block, + register unsigned long *keys) +{ + register unsigned long fval, work, right, leftt; + register int round; + + leftt = block[0]; + right = block[1]; + work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL; + right ^= work; + leftt ^= (work << 4); + work = ((leftt >> 16) ^ right) & 0x0000ffffL; + right ^= work; + leftt ^= (work << 16); + work = ((right >> 2) ^ leftt) & 0x33333333L; + leftt ^= work; + right ^= (work << 2); + work = ((right >> 8) ^ leftt) & 0x00ff00ffL; + leftt ^= work; + right ^= (work << 8); + right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL; + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL; + + for( round = 0; round < 8; round++ ) { + work = (right << 28) | (right >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = right ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + leftt ^= fval; + work = (leftt << 28) | (leftt >> 4); + work ^= *keys++; + fval = SP7[ work & 0x3fL]; + fval |= SP5[(work >> 8) & 0x3fL]; + fval |= SP3[(work >> 16) & 0x3fL]; + fval |= SP1[(work >> 24) & 0x3fL]; + work = leftt ^ *keys++; + fval |= SP8[ work & 0x3fL]; + fval |= SP6[(work >> 8) & 0x3fL]; + fval |= SP4[(work >> 16) & 0x3fL]; + fval |= SP2[(work >> 24) & 0x3fL]; + right ^= fval; + } + + right = (right << 31) | (right >> 1); + work = (leftt ^ right) & 0xaaaaaaaaL; + leftt ^= work; + right ^= work; + leftt = (leftt << 31) | (leftt >> 1); + work = ((leftt >> 8) ^ right) & 0x00ff00ffL; + right ^= work; + leftt ^= (work << 8); + work = ((leftt >> 2) ^ right) & 0x33333333L; + right ^= work; + leftt ^= (work << 2); + work = ((right >> 16) ^ leftt) & 0x0000ffffL; + leftt ^= work; + right ^= (work << 16); + work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL; + leftt ^= work; + right ^= (work << 4); + *block++ = right; + *block = leftt; + return; + } + +/* Validation sets: + * + * Single-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef + * Plain : 0123 4567 89ab cde7 + * Cipher : c957 4425 6a5e d31d + * + * Double-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cde7 + * Cipher : 7f1d 0a77 826b 8aff + * + * Double-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7 + * + * Triple-length key, single-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cde7 + * Cipher : de0b 7c06 ae5e 0ed5 + * + * Triple-length key, double-length plaintext - + * Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567 + * Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff + * Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5 + * + * d3des V5.0a rwo 9208.07 18:44 Graven Imagery + **********************************************************************/ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h new file mode 100755 index 0000000..e3761ca --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/d3des.h @@ -0,0 +1,56 @@ +#ifndef D3DES_H +#define D3DES_H + +/* + * This is D3DES (V5.09) by Richard Outerbridge with the double and + * triple-length support removed for use in VNC. + * + * 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. + */ + +/* d3des.h - + * + * Headers and defines for d3des.c + * Graven Imagery, 1992. + * + * Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge + * (GEnie : OUTER; CIS : [71755,204]) + */ + +#define EN0 0 /* MODE == encrypt */ +#define DE1 1 /* MODE == decrypt */ + +extern void rfbDesKey(unsigned char *, int); +/* hexkey[8] MODE + * Sets the internal key register according to the hexadecimal + * key contained in the 8 bytes of hexkey, according to the DES, + * for encryption or decryption according to MODE. + */ + +extern void rfbUseKey(unsigned long *); +/* cookedkey[32] + * Loads the internal key register with the data in cookedkey. + */ + +extern void rfbCPKey(unsigned long *); +/* cookedkey[32] + * Copies the contents of the internal key register into the storage + * located at &cookedkey[0]. + */ + +extern void rfbDes(unsigned char *, unsigned char *); +/* from[8] to[8] + * Encrypts/Decrypts (according to the key currently loaded in the + * internal key register) one block of eight bytes at address 'from' + * into the block at address 'to'. They can be the same. + */ + +/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery + ********************************************************************/ + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c new file mode 100755 index 0000000..7e1ed49 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/draw.c @@ -0,0 +1,61 @@ +#include + +void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col) +{ + int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3; + int i,j; + char* colour=(char*)&col; + + if(!rfbEndianTest) + colour += 4-bpp; + for(j=y1;jframeBuffer+j*rowstride+i*bpp,colour,bpp); + rfbMarkRectAsModified(s,x1,y1,x2,y2); +} + +#define SETPIXEL(x,y) \ + memcpy(s->frameBuffer+(y)*rowstride+(x)*bpp,colour,bpp) + +void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col) +{ + int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3; + char* colour=(char*)&col; + + if(!rfbEndianTest) + colour += 4-bpp; + SETPIXEL(x,y); + rfbMarkRectAsModified(s,x,y,x+1,y+1); +} + +void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col) +{ + int rowstride = s->paddedWidthInBytes, bpp = s->bitsPerPixel>>3; + int i; + char* colour=(char*)&col; + + if(!rfbEndianTest) + colour += 4-bpp; + +#define SWAPPOINTS { i=x1; x1=x2; x2=i; i=y1; y1=y2; y2=i; } + if(abs(x1-x2)y2) + SWAPPOINTS + for(i=y1;i<=y2;i++) + SETPIXEL(x1+(i-y1)*(x2-x1)/(y2-y1),i); + /* TODO: Maybe make this more intelligently? */ + if(x2x2) + SWAPPOINTS + else if(x1==x2) { + rfbDrawPixel(s,x1,y1,col); + return; + } + for(i=x1;i<=x2;i++) + SETPIXEL(i,y1+(i-x1)*(y2-y1)/(x2-x1)); + if(y2 + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,unsigned char c,rfbPixel col) +{ + int i,j,width,height; + unsigned char* data=font->data+font->metaData[c*5]; + unsigned char d=*data; + int rowstride=rfbScreen->paddedWidthInBytes; + int bpp=rfbScreen->serverFormat.bitsPerPixel/8; + char *colour=(char*)&col; + + if(!rfbEndianTest) + colour += 4-bpp; + + width=font->metaData[c*5+1]; + height=font->metaData[c*5+2]; + x+=font->metaData[c*5+3]; + y+=-font->metaData[c*5+4]-height+1; + + for(j=0;j= 0 && y+j < rfbScreen->height && + x+i >= 0 && x+i < rfbScreen->width) + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp,colour,bpp); + d<<=1; + } + /* if((i&7)!=0) data++; */ + } + return(width); +} + +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,const char* string,rfbPixel colour) +{ + while(*string) { + x+=rfbDrawChar(rfbScreen,font,x,y,*string,colour); + string++; + } +} + +/* TODO: these two functions need to be more efficient */ +/* if col==bcol, assume transparent background */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,unsigned char c, + int x1,int y1,int x2,int y2, + rfbPixel col,rfbPixel bcol) +{ + int i,j,width,height; + unsigned char* data=font->data+font->metaData[c*5]; + unsigned char d; + int rowstride=rfbScreen->paddedWidthInBytes; + int bpp=rfbScreen->serverFormat.bitsPerPixel/8,extra_bytes=0; + char* colour=(char*)&col; + char* bcolour=(char*)&bcol; + + if(!rfbEndianTest) { + colour+=4-bpp; + bcolour+=4-bpp; + } + + width=font->metaData[c*5+1]; + height=font->metaData[c*5+2]; + x+=font->metaData[c*5+3]; + y+=-font->metaData[c*5+4]-height+1; + + /* after clipping, x2 will be count of bytes between rows, + * x1 start of i, y1 start of j, width and height will be adjusted. */ + if(y1>y) { y1-=y; data+=(width+7)/8; height-=y1; y+=y1; } else y1=0; + if(x1>x) { x1-=x; data+=x1; width-=x1; x+=x1; extra_bytes+=x1/8; } else x1=0; + if(y2=x1 && x+i=y1 && y+jframeBuffer+(y+j)*rowstride+(x+i)*bpp, + colour,bpp); + } else if(bcol!=col) { + memcpy(rfbScreen->frameBuffer+(y+j)*rowstride+(x+i)*bpp, + bcolour,bpp); + } + } + d<<=1; + } + /* if((i&7)==0) data++; */ + data += extra_bytes; + } + return(width); +} + +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + int x,int y,const char* string, + int x1,int y1,int x2,int y2, + rfbPixel colour,rfbPixel backColour) +{ + while(*string) { + x+=rfbDrawCharWithClip(rfbScreen,font,x,y,*string,x1,y1,x2,y2, + colour,backColour); + string++; + } +} + +int rfbWidthOfString(rfbFontDataPtr font,const char* string) +{ + int i=0; + while(*string) { + i+=font->metaData[*string*5+1]; + string++; + } + return(i); +} + +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c) +{ + return(font->metaData[c*5+1]+font->metaData[c*5+3]); +} + +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2) +{ + *x1+=font->metaData[c*5+3]; + *y1+=-font->metaData[c*5+4]-font->metaData[c*5+2]+1; + *x2=*x1+font->metaData[c*5+1]+1; + *y2=*y1+font->metaData[c*5+2]+1; +} + +#ifndef INT_MAX +#define INT_MAX 0x7fffffff +#endif + +void rfbWholeFontBBox(rfbFontDataPtr font, + int *x1, int *y1, int *x2, int *y2) +{ + int i; + int* m=font->metaData; + + (*x1)=(*y1)=INT_MAX; (*x2)=(*y2)=1-(INT_MAX); + for(i=0;i<256;i++) { + if(m[i*5+1]-m[i*5+3]>(*x2)) + (*x2)=m[i*5+1]-m[i*5+3]; + if(-m[i*5+2]+m[i*5+4]<(*y1)) + (*y1)=-m[i*5+2]+m[i*5+4]; + if(m[i*5+3]<(*x1)) + (*x1)=m[i*5+3]; + if(-m[i*5+4]>(*y2)) + (*y2)=-m[i*5+4]; + } + (*x2)++; + (*y2)++; +} + +rfbFontDataPtr rfbLoadConsoleFont(char *filename) +{ + FILE *f=fopen(filename,"rb"); + rfbFontDataPtr p; + int i; + + if(!f) return NULL; + + p=(rfbFontDataPtr)malloc(sizeof(rfbFontData)); + p->data=(unsigned char*)malloc(4096); + if(1!=fread(p->data,4096,1,f)) { + free(p->data); + free(p); + return NULL; + } + fclose(f); + p->metaData=(int*)malloc(256*5*sizeof(int)); + for(i=0;i<256;i++) { + p->metaData[i*5+0]=i*16; /* offset */ + p->metaData[i*5+1]=8; /* width */ + p->metaData[i*5+2]=16; /* height */ + p->metaData[i*5+3]=0; /* xhot */ + p->metaData[i*5+4]=0; /* yhot */ + } + return(p); +} + +void rfbFreeFont(rfbFontDataPtr f) +{ + free(f->data); + free(f->metaData); + free(f); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c new file mode 100755 index 0000000..52920d8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/hextile.c @@ -0,0 +1,342 @@ +/* + * hextile.c + * + * Routines to implement Hextile Encoding + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h); + + +/* + * rfbSendRectEncodingHextile - send a rectangle using hextile encoding. + */ + +rfbBool +rfbSendRectEncodingHextile(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingHextile); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingHextile, + sz_rfbFramebufferUpdateRectHeader, + sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h); + + switch (cl->format.bitsPerPixel) { + case 8: + return sendHextiles8(cl, x, y, w, h); + case 16: + return sendHextiles16(cl, x, y, w, h); + case 32: + return sendHextiles32(cl, x, y, w, h); + } + + rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel); + return FALSE; +} + + +#define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix)) + +#define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1]) + +#define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \ + cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3]) + + +#define DEFINE_SEND_HEXTILES(bpp) \ + \ + \ +static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \ + int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\ +static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \ + rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \ + \ + \ +/* \ + * rfbSendHextiles \ + */ \ + \ +static rfbBool \ +sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \ + int x, y, w, h; \ + int startUblen; \ + char *fbptr; \ + uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \ + rfbBool mono, solid; \ + rfbBool validBg = FALSE; \ + rfbBool validFg = FALSE; \ + uint##bpp##_t clientPixelData[16*16*(bpp/8)]; \ + \ + for (y = ry; y < ry+rh; y += 16) { \ + for (x = rx; x < rx+rw; x += 16) { \ + w = h = 16; \ + if (rx+rw - x < 16) \ + w = rx+rw - x; \ + if (ry+rh - y < 16) \ + h = ry+rh - y; \ + \ + if ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \ + UPDATE_BUF_SIZE) { \ + if (!rfbSendUpdateBuf(cl)) \ + return FALSE; \ + } \ + \ + fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \ + + (x * (cl->scaledScreen->bitsPerPixel / 8))); \ + \ + (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \ + &cl->format, fbptr, (char *)clientPixelData, \ + cl->scaledScreen->paddedWidthInBytes, w, h); \ + \ + startUblen = cl->ublen; \ + cl->updateBuf[startUblen] = 0; \ + cl->ublen++; \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \ + \ + testColours##bpp(clientPixelData, w * h, \ + &mono, &solid, &newBg, &newFg); \ + \ + if (!validBg || (newBg != bg)) { \ + validBg = TRUE; \ + bg = newBg; \ + cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \ + PUT_PIXEL##bpp(bg); \ + } \ + \ + if (solid) { \ + continue; \ + } \ + \ + cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \ + \ + if (mono) { \ + if (!validFg || (newFg != fg)) { \ + validFg = TRUE; \ + fg = newFg; \ + cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \ + PUT_PIXEL##bpp(fg); \ + } \ + } else { \ + validFg = FALSE; \ + cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \ + } \ + \ + if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \ + /* encoding was too large, use raw */ \ + validBg = FALSE; \ + validFg = FALSE; \ + cl->ublen = startUblen; \ + cl->updateBuf[cl->ublen++] = rfbHextileRaw; \ + (*cl->translateFn)(cl->translateLookupTable, \ + &(cl->screen->serverFormat), &cl->format, fbptr, \ + (char *)clientPixelData, \ + cl->scaledScreen->paddedWidthInBytes, w, h); \ + \ + memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \ + w * h * (bpp/8)); \ + \ + cl->ublen += w * h * (bpp/8); \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \ + w * h * (bpp/8)); \ + } \ + } \ + } \ + \ + return TRUE; \ +} \ + \ + \ +static rfbBool \ +subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \ + uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \ +{ \ + uint##bpp##_t cl2; \ + int x,y; \ + int i,j; \ + int hx=0,hy,vx=0,vy; \ + int hyflag; \ + uint##bpp##_t *seg; \ + uint##bpp##_t *line; \ + int hw,hh,vw,vh; \ + int thex,they,thew,theh; \ + int numsubs = 0; \ + int newLen; \ + int nSubrectsUblen; \ + \ + nSubrectsUblen = cl->ublen; \ + cl->ublen++; \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \ + \ + for (y=0; y 0) && (i >= hx)) { \ + hy += 1; \ + } else { \ + hyflag = 0; \ + } \ + } \ + vy = j-1; \ + \ + /* We now have two possible subrects: (x,y,hx,hy) and \ + * (x,y,vx,vy). We'll choose the bigger of the two. \ + */ \ + hw = hx-x+1; \ + hh = hy-y+1; \ + vw = vx-x+1; \ + vh = vy-y+1; \ + \ + thex = x; \ + they = y; \ + \ + if ((hw*hh) > (vw*vh)) { \ + thew = hw; \ + theh = hh; \ + } else { \ + thew = vw; \ + theh = vh; \ + } \ + \ + if (mono) { \ + newLen = cl->ublen - nSubrectsUblen + 2; \ + } else { \ + newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \ + } \ + \ + if (newLen > (w * h * (bpp/8))) \ + return FALSE; \ + \ + numsubs += 1; \ + \ + if (!mono) PUT_PIXEL##bpp(cl2); \ + \ + cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \ + cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \ + rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \ + \ + /* \ + * Now mark the subrect as done. \ + */ \ + for (j=they; j < (they+theh); j++) { \ + for (i=thex; i < (thex+thew); i++) { \ + data[j*w+i] = bg; \ + } \ + } \ + } \ + } \ + } \ + \ + cl->updateBuf[nSubrectsUblen] = numsubs; \ + \ + return TRUE; \ +} \ + \ + \ +/* \ + * testColours() tests if there are one (solid), two (mono) or more \ + * colours in a tile and gets a reasonable guess at the best background \ + * pixel, and the foreground pixel for mono. \ + */ \ + \ +static void \ +testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \ + uint##bpp##_t *bg, uint##bpp##_t *fg) { \ + uint##bpp##_t colour1 = 0, colour2 = 0; \ + int n1 = 0, n2 = 0; \ + *mono = TRUE; \ + *solid = TRUE; \ + \ + for (; size > 0; size--, data++) { \ + \ + if (n1 == 0) \ + colour1 = *data; \ + \ + if (*data == colour1) { \ + n1++; \ + continue; \ + } \ + \ + if (n2 == 0) { \ + *solid = FALSE; \ + colour2 = *data; \ + } \ + \ + if (*data == colour2) { \ + n2++; \ + continue; \ + } \ + \ + *mono = FALSE; \ + break; \ + } \ + \ + if (n1 > n2) { \ + *bg = colour1; \ + *fg = colour2; \ + } else { \ + *bg = colour2; \ + *fg = colour1; \ + } \ +} + +DEFINE_SEND_HEXTILES(8) +DEFINE_SEND_HEXTILES(16) +DEFINE_SEND_HEXTILES(32) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c new file mode 100755 index 0000000..7e8e923 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/httpd.c @@ -0,0 +1,631 @@ +/* + * httpd.c - a simple HTTP server + */ + +/* + * Copyright (C) 2002 RealVNC Ltd. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +#include +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif +#include + +#ifdef WIN32 +#include +#define close closesocket +#else +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#include +#endif +#include +#endif + +#ifdef USE_LIBWRAP +#include +#endif + +#define connection_close +#ifndef connection_close + +#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\n\r\n" \ + "File Not Found\n" \ + "

File Not Found

\n" + +#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\n\r\n" \ + "Invalid Request\n" \ + "

Invalid request

\n" + +#define OK_STR "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" + +#else + +#define NOT_FOUND_STR "HTTP/1.0 404 Not found\r\nConnection: close\r\n\r\n" \ + "File Not Found\n" \ + "

File Not Found

\n" + +#define INVALID_REQUEST_STR "HTTP/1.0 400 Invalid Request\r\nConnection: close\r\n\r\n" \ + "Invalid Request\n" \ + "

Invalid request

\n" + +#define OK_STR "HTTP/1.0 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" + +#endif + +static void httpProcessInput(rfbScreenInfoPtr screen); +static rfbBool compareAndSkip(char **ptr, const char *str); +static rfbBool parseParams(const char *request, char *result, int max_bytes); +static rfbBool validateString(char *str); + +#define BUF_SIZE 32768 + +static char buf[BUF_SIZE]; +static size_t buf_filled=0; + +/* + * httpInitSockets sets up the TCP socket to listen for HTTP connections. + */ + +void +rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen) +{ + if (rfbScreen->httpInitDone) + return; + + rfbScreen->httpInitDone = TRUE; + + if (!rfbScreen->httpDir) + return; + + if (rfbScreen->httpPort == 0) { + rfbScreen->httpPort = rfbScreen->port-100; + } + + rfbLog("Listening for HTTP connections on TCP port %d\n", rfbScreen->httpPort); + + rfbLog(" URL http://%s:%d\n",rfbScreen->thisHost,rfbScreen->httpPort); + + if ((rfbScreen->httpListenSock = + rfbListenOnTCPPort(rfbScreen->httpPort, rfbScreen->listenInterface)) < 0) { + rfbLogPerror("ListenOnTCPPort"); + return; + } + + /*AddEnabledDevice(httpListenSock);*/ +} + +void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen) { + if(rfbScreen->httpSock>-1) { + close(rfbScreen->httpSock); + FD_CLR(rfbScreen->httpSock,&rfbScreen->allFds); + rfbScreen->httpSock=-1; + } +} + +/* + * httpCheckFds is called from ProcessInputEvents to check for input on the + * HTTP socket(s). If there is input to process, httpProcessInput is called. + */ + +void +rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen) +{ + int nfds; + fd_set fds; + struct timeval tv; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + + if (!rfbScreen->httpDir) + return; + + if (rfbScreen->httpListenSock < 0) + return; + + FD_ZERO(&fds); + FD_SET(rfbScreen->httpListenSock, &fds); + if (rfbScreen->httpSock >= 0) { + FD_SET(rfbScreen->httpSock, &fds); + } + tv.tv_sec = 0; + tv.tv_usec = 0; + nfds = select(max(rfbScreen->httpSock,rfbScreen->httpListenSock) + 1, &fds, NULL, NULL, &tv); + if (nfds == 0) { + return; + } + if (nfds < 0) { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno != EINTR) + rfbLogPerror("httpCheckFds: select"); + return; + } + + if ((rfbScreen->httpSock >= 0) && FD_ISSET(rfbScreen->httpSock, &fds)) { + httpProcessInput(rfbScreen); + } + + if (FD_ISSET(rfbScreen->httpListenSock, &fds)) { + int flags; + if (rfbScreen->httpSock >= 0) close(rfbScreen->httpSock); + + if ((rfbScreen->httpSock = accept(rfbScreen->httpListenSock, + (struct sockaddr *)&addr, &addrlen)) < 0) { + rfbLogPerror("httpCheckFds: accept"); + return; + } +#ifdef __MINGW32__ + rfbErr("O_NONBLOCK on MinGW32 NOT IMPLEMENTED"); +#else +#ifdef USE_LIBWRAP + if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), + STRING_UNKNOWN)) { + rfbLog("Rejected HTTP connection from client %s\n", + inet_ntoa(addr.sin_addr)); +#else + flags = fcntl(rfbScreen->httpSock, F_GETFL); + + if (flags < 0 || fcntl(rfbScreen->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { + rfbLogPerror("httpCheckFds: fcntl"); +#endif + close(rfbScreen->httpSock); + rfbScreen->httpSock = -1; + return; + } + + flags=fcntl(rfbScreen->httpSock,F_GETFL); + if(flags==-1 || + fcntl(rfbScreen->httpSock,F_SETFL,flags|O_NONBLOCK)==-1) { + rfbLogPerror("httpCheckFds: fcntl"); + close(rfbScreen->httpSock); + rfbScreen->httpSock=-1; + return; + } +#endif + + /*AddEnabledDevice(httpSock);*/ + } +} + + +static void +httpCloseSock(rfbScreenInfoPtr rfbScreen) +{ + close(rfbScreen->httpSock); + rfbScreen->httpSock = -1; + buf_filled = 0; +} + +static rfbClientRec cl; + +/* + * httpProcessInput is called when input is received on the HTTP socket. + */ + +static void +httpProcessInput(rfbScreenInfoPtr rfbScreen) +{ + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + char fullFname[512]; + char params[1024]; + char *ptr; + char *fname; + unsigned int maxFnameLen; + FILE* fd; + rfbBool performSubstitutions = FALSE; + char str[256+32]; +#ifndef WIN32 + char* user=getenv("USER"); +#endif + + cl.sock=rfbScreen->httpSock; + + if (strlen(rfbScreen->httpDir) > 255) { + rfbErr("-httpd directory too long\n"); + httpCloseSock(rfbScreen); + return; + } + strcpy(fullFname, rfbScreen->httpDir); + fname = &fullFname[strlen(fullFname)]; + maxFnameLen = 511 - strlen(fullFname); + + buf_filled=0; + + /* Read data from the HTTP client until we get a complete request. */ + while (1) { + ssize_t got; + + if (buf_filled > sizeof (buf)) { + rfbErr("httpProcessInput: HTTP request is too long\n"); + httpCloseSock(rfbScreen); + return; + } + + got = read (rfbScreen->httpSock, buf + buf_filled, + sizeof (buf) - buf_filled - 1); + + if (got <= 0) { + if (got == 0) { + rfbErr("httpd: premature connection close\n"); + } else { + if (errno == EAGAIN) { + return; + } + rfbLogPerror("httpProcessInput: read"); + } + httpCloseSock(rfbScreen); + return; + } + + buf_filled += got; + buf[buf_filled] = '\0'; + + /* Is it complete yet (is there a blank line)? */ + if (strstr (buf, "\r\r") || strstr (buf, "\n\n") || + strstr (buf, "\r\n\r\n") || strstr (buf, "\n\r\n\r")) + break; + } + + + /* Process the request. */ + if(rfbScreen->httpEnableProxyConnect) { + const static char* PROXY_OK_STR = "HTTP/1.0 200 OK\r\nContent-Type: octet-stream\r\nPragma: no-cache\r\n\r\n"; + if(!strncmp(buf, "CONNECT ", 8)) { + if(atoi(strchr(buf, ':')+1)!=rfbScreen->port) { + rfbErr("httpd: CONNECT format invalid.\n"); + rfbWriteExact(&cl,INVALID_REQUEST_STR, strlen(INVALID_REQUEST_STR)); + httpCloseSock(rfbScreen); + return; + } + /* proxy connection */ + rfbLog("httpd: client asked for CONNECT\n"); + rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR)); + rfbNewClientConnection(rfbScreen,rfbScreen->httpSock); + rfbScreen->httpSock = -1; + return; + } + if (!strncmp(buf, "GET ",4) && !strncmp(strchr(buf,'/'),"/proxied.connection HTTP/1.", 27)) { + /* proxy connection */ + rfbLog("httpd: client asked for /proxied.connection\n"); + rfbWriteExact(&cl,PROXY_OK_STR,strlen(PROXY_OK_STR)); + rfbNewClientConnection(rfbScreen,rfbScreen->httpSock); + rfbScreen->httpSock = -1; + return; + } + } + + if (strncmp(buf, "GET ", 4)) { + rfbErr("httpd: no GET line\n"); + httpCloseSock(rfbScreen); + return; + } else { + /* Only use the first line. */ + buf[strcspn(buf, "\n\r")] = '\0'; + } + + if (strlen(buf) > maxFnameLen) { + rfbErr("httpd: GET line too long\n"); + httpCloseSock(rfbScreen); + return; + } + + if (sscanf(buf, "GET %s HTTP/1.", fname) != 1) { + rfbErr("httpd: couldn't parse GET line\n"); + httpCloseSock(rfbScreen); + return; + } + + if (fname[0] != '/') { + rfbErr("httpd: filename didn't begin with '/'\n"); + rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); + httpCloseSock(rfbScreen); + return; + } + + if (strchr(fname+1, '/') != NULL) { + rfbErr("httpd: asking for file in other directory\n"); + rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); + httpCloseSock(rfbScreen); + return; + } + + getpeername(rfbScreen->httpSock, (struct sockaddr *)&addr, &addrlen); + rfbLog("httpd: get '%s' for %s\n", fname+1, + inet_ntoa(addr.sin_addr)); + + /* Extract parameters from the URL string if necessary */ + + params[0] = '\0'; + ptr = strchr(fname, '?'); + if (ptr != NULL) { + *ptr = '\0'; + if (!parseParams(&ptr[1], params, 1024)) { + params[0] = '\0'; + rfbErr("httpd: bad parameters in the URL\n"); + } + } + + + /* If we were asked for '/', actually read the file index.vnc */ + + if (strcmp(fname, "/") == 0) { +// strcpy(fname, "/index.vnc"); + strcpy(fname, "/novnc.html"); + rfbLog("httpd: defaulting to '%s'\n", fname+1); + } + + /* Substitutions are performed on files ending .vnc */ + + if (strlen(fname) >= 4 && strcmp(&fname[strlen(fname)-4], ".vnc") == 0) { + performSubstitutions = TRUE; + } + + /* Open the file */ + + if ((fd = fopen(fullFname, "r")) == 0) { + rfbLogPerror("httpProcessInput: open"); + rfbLogPerror(fname); + + rfbWriteExact(&cl, NOT_FOUND_STR, strlen(NOT_FOUND_STR)); + + httpCloseSock(rfbScreen); + return; + } + + + + + + +if (strstr(fullFname,".js")!=NULL) +{ + char *ok="HTTP/1.0 200 OK\r\nContent-Type: application/x-javascript\r\n\r\n"; + rfbWriteExact(&cl, ok, strlen(ok)); +}else if (strstr(fullFname,".css")!=NULL) +{ + char *ok="HTTP/1.0 200 OK\r\nContent-Type: text/css\r\n\r\n"; + rfbWriteExact(&cl, ok, strlen(ok)); +}else + rfbWriteExact(&cl, OK_STR, strlen(OK_STR)); + + + while (1) { + int n = fread(buf, 1, BUF_SIZE-1, fd); + if (n < 0) { + rfbLogPerror("httpProcessInput: read"); + fclose(fd); + httpCloseSock(rfbScreen); + return; + } + + if (n == 0) + break; + + if (performSubstitutions) { + + /* Substitute $WIDTH, $HEIGHT, etc with the appropriate values. + This won't quite work properly if the .vnc file is longer than + BUF_SIZE, but it's reasonable to assume that .vnc files will + always be short. */ + + char *ptr = buf; + char *dollar; + buf[n] = 0; /* make sure it's null-terminated */ + + while ((dollar = strchr(ptr, '$'))!=NULL) { + rfbWriteExact(&cl, ptr, (dollar - ptr)); + + ptr = dollar; + + if (compareAndSkip(&ptr, "$WIDTH")) { + + sprintf(str, "%d", rfbScreen->width); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$HEIGHT")) { + + sprintf(str, "%d", rfbScreen->height); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$APPLETWIDTH")) { + + sprintf(str, "%d", rfbScreen->width); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$APPLETHEIGHT")) { + + sprintf(str, "%d", rfbScreen->height + 32); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$PORT")) { + + sprintf(str, "%d", rfbScreen->port); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$DESKTOP")) { + + rfbWriteExact(&cl, rfbScreen->desktopName, strlen(rfbScreen->desktopName)); + + } else if (compareAndSkip(&ptr, "$DISPLAY")) { + + sprintf(str, "%s:%d", rfbScreen->thisHost, rfbScreen->port-5900); + rfbWriteExact(&cl, str, strlen(str)); + + } else if (compareAndSkip(&ptr, "$USER")) { +#ifndef WIN32 + if (user) { + rfbWriteExact(&cl, user, + strlen(user)); + } else +#endif + rfbWriteExact(&cl, "?", 1); + } else if (compareAndSkip(&ptr, "$PARAMS")) { + if (params[0] != '\0') + rfbWriteExact(&cl, params, strlen(params)); + } else { + if (!compareAndSkip(&ptr, "$$")) + ptr++; + + if (rfbWriteExact(&cl, "$", 1) < 0) { + fclose(fd); + httpCloseSock(rfbScreen); + return; + } + } + } + if (rfbWriteExact(&cl, ptr, (&buf[n] - ptr)) < 0) + break; + + } else { + + /* For files not ending .vnc, just write out the buffer */ + + if (rfbWriteExact(&cl, buf, n) < 0) + break; + } + } + + fclose(fd); + httpCloseSock(rfbScreen); +} + + +static rfbBool +compareAndSkip(char **ptr, const char *str) +{ + if (strncmp(*ptr, str, strlen(str)) == 0) { + *ptr += strlen(str); + return TRUE; + } + + return FALSE; +} + +/* + * Parse the request tail after the '?' character, and format a sequence + * of tags for inclusion into an HTML page with embedded applet. + */ + +static rfbBool +parseParams(const char *request, char *result, int max_bytes) +{ + char param_request[128]; + char param_formatted[196]; + const char *tail; + char *delim_ptr; + char *value_str; + int cur_bytes, len; + + result[0] = '\0'; + cur_bytes = 0; + + tail = request; + for (;;) { + /* Copy individual "name=value" string into a buffer */ + delim_ptr = strchr((char *)tail, '&'); + if (delim_ptr == NULL) { + if (strlen(tail) >= sizeof(param_request)) { + return FALSE; + } + strcpy(param_request, tail); + } else { + len = delim_ptr - tail; + if (len >= sizeof(param_request)) { + return FALSE; + } + memcpy(param_request, tail, len); + param_request[len] = '\0'; + } + + /* Split the request into parameter name and value */ + value_str = strchr(¶m_request[1], '='); + if (value_str == NULL) { + return FALSE; + } + *value_str++ = '\0'; + if (strlen(value_str) == 0) { + return FALSE; + } + + /* Validate both parameter name and value */ + if (!validateString(param_request) || !validateString(value_str)) { + return FALSE; + } + + /* Prepare HTML-formatted representation of the name=value pair */ + len = sprintf(param_formatted, + "\n", + param_request, value_str); + if (cur_bytes + len + 1 > max_bytes) { + return FALSE; + } + strcat(result, param_formatted); + cur_bytes += len; + + /* Go to the next parameter */ + if (delim_ptr == NULL) { + break; + } + tail = delim_ptr + 1; + } + return TRUE; +} + +/* + * Check if the string consists only of alphanumeric characters, '+' + * signs, underscores, and dots. Replace all '+' signs with spaces. + */ + +static rfbBool +validateString(char *str) +{ + char *ptr; + + for (ptr = str; *ptr != '\0'; ptr++) { + if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') { + if (*ptr == '+') { + *ptr = ' '; + } else { + return FALSE; + } + } + } + return TRUE; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h new file mode 100755 index 0000000..96db180 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/lzoconf.h @@ -0,0 +1,451 @@ +/* lzoconf.h -- configuration for the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H +#define __LZOCONF_H + +#define LZO_VERSION 0x1080 +#define LZO_VERSION_STRING "1.08" +#define LZO_VERSION_DATE "Jul 12 2002" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* workaround a cpp bug under hpux 10.20 */ +#define LZO_0xffffffffL 4294967295ul + +#if !defined(LZO_UINT32_C) +# if (UINT_MAX < LZO_0xffffffffL) +# define LZO_UINT32_C(c) c ## UL +# else +# define LZO_UINT32_C(c) c ## U +# endif +#endif + + +/*********************************************************************** +// architecture defines +************************************************************************/ + +#if !defined(__LZO_WIN) && !defined(__LZO_DOS) && !defined(__LZO_OS2) +# if defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# define __LZO_WIN +# elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) +# define __LZO_WIN +# elif defined(__NT__) || defined(__NT_DLL__) || defined(__WINDOWS_386__) +# define __LZO_WIN +# elif defined(__DOS__) || defined(__MSDOS__) || defined(MSDOS) +# define __LZO_DOS +# elif defined(__OS2__) || defined(__OS2V2__) || defined(OS2) +# define __LZO_OS2 +# elif defined(__palmos__) +# define __LZO_PALMOS +# elif defined(__TOS__) || defined(__atarist__) +# define __LZO_TOS +# endif +#endif + +#if (UINT_MAX < LZO_0xffffffffL) +# if defined(__LZO_WIN) +# define __LZO_WIN16 +# elif defined(__LZO_DOS) +# define __LZO_DOS16 +# elif defined(__LZO_PALMOS) +# define __LZO_PALMOS16 +# elif defined(__LZO_TOS) +# define __LZO_TOS16 +# elif defined(__C166__) +# else + /* porting hint: for pure 16-bit architectures try compiling + * everything with -D__LZO_STRICT_16BIT */ +# error "16-bit target not supported - contact me for porting hints" +# endif +#endif + +#if !defined(__LZO_i386) +# if defined(__LZO_DOS) || defined(__LZO_WIN16) +# define __LZO_i386 +# elif defined(__i386__) || defined(__386__) || defined(_M_IX86) +# define __LZO_i386 +# endif +#endif + +#if defined(__LZO_STRICT_16BIT) +# if (UINT_MAX < LZO_0xffffffffL) +# include +# endif +#endif + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER +# elif defined(__CHECKER__) +# define __LZO_CHECKER +# elif defined(__INSURE__) +# define __LZO_CHECKER +# elif defined(__PURIFY__) +# define __LZO_CHECKER +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* Integral types with 32 bits or more */ +#if !defined(LZO_UINT32_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint32; + typedef int lzo_int32; +# define LZO_UINT32_MAX UINT_MAX +# define LZO_INT32_MAX INT_MAX +# define LZO_INT32_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint32; + typedef long lzo_int32; +# define LZO_UINT32_MAX ULONG_MAX +# define LZO_INT32_MAX LONG_MAX +# define LZO_INT32_MIN LONG_MIN +# else +# error "lzo_uint32" +# endif +#endif + +/* lzo_uint is used like size_t */ +#if !defined(LZO_UINT_MAX) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +typedef int lzo_bool; + + +/*********************************************************************** +// memory models +************************************************************************/ + +/* Memory model for the public code segment. */ +#if !defined(__LZO_CMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CMODEL __near +# else +# define __LZO_CMODEL +# endif +#endif + +/* Memory model for the public data segment. */ +#if !defined(__LZO_DMODEL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_DMODEL __far +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_DMODEL __near +# else +# define __LZO_DMODEL +# endif +#endif + +/* Memory model that allows to access memory at offsets of lzo_uint. */ +#if !defined(__LZO_MMODEL) +# if (LZO_UINT_MAX <= UINT_MAX) +# define __LZO_MMODEL +# elif defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_MMODEL __huge +# define LZO_999_UNSUPPORTED +# elif defined(__LZO_PALMOS16) || defined(__LZO_TOS16) +# define __LZO_MMODEL +# else +# error "__LZO_MMODEL" +# endif +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_byte unsigned char __LZO_MMODEL +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_uint32p lzo_uint32 __LZO_MMODEL * +#define lzo_int32p lzo_int32 __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t sizeof(lzo_bytep) +#endif + + +/*********************************************************************** +// calling conventions and function types +************************************************************************/ + +/* linkage */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(_MSC_VER) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# elif defined(__LZO_i386) && defined(__WATCOMC__) +# define __LZO_CDECL __LZO_CMODEL __cdecl +# else +# define __LZO_CDECL __LZO_CMODEL +# endif +#endif +#if !defined(__LZO_ENTRY) +# define __LZO_ENTRY __LZO_CDECL +#endif + +/* C++ exception specification for extern "C" function types */ +#if !defined(__cplusplus) +# undef LZO_NOTHROW +# define LZO_NOTHROW +#elif !defined(LZO_NOTHROW) +# define LZO_NOTHROW +#endif + + +typedef int +(__LZO_ENTRY *lzo_compress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_decompress_t) ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_optimize_t) ( lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_ENTRY *lzo_compress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + +typedef int +(__LZO_ENTRY *lzo_decompress_dict_t)(const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_byte *dict, lzo_uint dict_len ); + + +/* assembler versions always use __cdecl */ +typedef int +(__LZO_CDECL *lzo_compress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_asm_t)( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + + +/* a progress indicator callback function */ +typedef void (__LZO_ENTRY *lzo_progress_callback_t) (lzo_uint, lzo_uint); + + +/*********************************************************************** +// export information +************************************************************************/ + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 +#endif + +/* exported calling convention for C functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_ENTRY +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(_rettype) __LZO_EXTERN_C LZO_PUBLIC(_rettype) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(_rettype) static _rettype __LZO_ENTRY +#endif + +/* exported __cdecl calling convention for assembler functions */ +#if !defined(LZO_PUBLIC_CDECL) +# define LZO_PUBLIC_CDECL(_rettype) \ + __LZO_EXPORT1 _rettype __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN_CDECL) +# define LZO_EXTERN_CDECL(_rettype) __LZO_EXTERN_C LZO_PUBLIC_CDECL(_rettype) +#endif + +/* exported global variables (LZO currently uses no static variables and + * is fully thread safe) */ +#if !defined(LZO_PUBLIC_VAR) +# define LZO_PUBLIC_VAR(_type) \ + __LZO_EXPORT1 _type __LZO_EXPORT2 __LZO_DMODEL +#endif +#if !defined(LZO_EXTERN_VAR) +# define LZO_EXTERN_VAR(_type) extern LZO_PUBLIC_VAR(_type) +#endif + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) + + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_compress_t)) +LZO_EXTERN(int) __lzo_init2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) +lzo_memcmp(const lzo_voidp _s1, const lzo_voidp _s2, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memcpy(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memmove(lzo_voidp _dest, const lzo_voidp _src, lzo_uint _len); +LZO_EXTERN(lzo_voidp) +lzo_memset(lzo_voidp _s, int _c, lzo_uint _len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32) +lzo_adler32(lzo_uint32 _adler, const lzo_byte *_buf, lzo_uint _len); +LZO_EXTERN(lzo_uint32) +lzo_crc32(lzo_uint32 _c, const lzo_byte *_buf, lzo_uint _len); + +/* misc. */ +LZO_EXTERN(lzo_bool) lzo_assert(int _expr); +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { lzo_bytep p; lzo_uint u; } __lzo_pu_u; +typedef union { lzo_bytep p; lzo_uint32 u32; } __lzo_pu32_u; +typedef union { void *vp; lzo_bytep bp; lzo_uint32 u32; long l; } lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of `size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp _ptr, lzo_uint _size); +#define LZO_PTR_ALIGN_UP(_ptr,_size) \ + ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size))) + +/* deprecated - only for backward compatibility */ +#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c new file mode 100755 index 0000000..288fda0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/main.c @@ -0,0 +1,1182 @@ +/* + * This file is called main.c, because it contains most of the new functions + * for use with LibVNCServer. + * + * LibVNCServer (C) 2001 Johannes E. Schindelin + * Original OSXvnc (C) 2001 Dan McGuirk . + * Original Xvnc (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * see GPL (latest version) for full details + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include "private.h" + +#include +#include + +#ifndef false +#define false 0 +#define true -1 +#endif + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifndef WIN32 +#include +#include +#include +#endif + +#include +#include + +static int extMutex_initialized = 0; +static int logMutex_initialized = 0; +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +static MUTEX(logMutex); +static MUTEX(extMutex); +#endif + +static int rfbEnableLogging=1; + +#ifdef LIBVNCSERVER_WORDS_BIGENDIAN +char rfbEndianTest = (1==0); +#else +char rfbEndianTest = (1==1); +#endif + +/* + * Protocol extensions + */ + +static rfbProtocolExtension* rfbExtensionHead = NULL; + +/* + * This method registers a list of new extensions. + * It avoids same extension getting registered multiple times. + * The order is not preserved if multiple extensions are + * registered at one-go. + */ +void +rfbRegisterProtocolExtension(rfbProtocolExtension* extension) +{ + rfbProtocolExtension *head = rfbExtensionHead, *next = NULL; + + if(extension == NULL) + return; + + next = extension->next; + + if (! extMutex_initialized) { + INIT_MUTEX(extMutex); + extMutex_initialized = 1; + } + + LOCK(extMutex); + + while(head != NULL) { + if(head == extension) { + UNLOCK(extMutex); + rfbRegisterProtocolExtension(next); + return; + } + + head = head->next; + } + + extension->next = rfbExtensionHead; + rfbExtensionHead = extension; + + UNLOCK(extMutex); + rfbRegisterProtocolExtension(next); +} + +/* + * This method unregisters a list of extensions. + * These extensions won't be available for any new + * client connection. + */ +void +rfbUnregisterProtocolExtension(rfbProtocolExtension* extension) +{ + + rfbProtocolExtension *cur = NULL, *pre = NULL; + + if(extension == NULL) + return; + + if (! extMutex_initialized) { + INIT_MUTEX(extMutex); + extMutex_initialized = 1; + } + + LOCK(extMutex); + + if(rfbExtensionHead == extension) { + rfbExtensionHead = rfbExtensionHead->next; + UNLOCK(extMutex); + rfbUnregisterProtocolExtension(extension->next); + return; + } + + cur = pre = rfbExtensionHead; + + while(cur) { + if(cur == extension) { + pre->next = cur->next; + break; + } + pre = cur; + cur = cur->next; + } + + UNLOCK(extMutex); + + rfbUnregisterProtocolExtension(extension->next); +} + +rfbProtocolExtension* rfbGetExtensionIterator() +{ + LOCK(extMutex); + return rfbExtensionHead; +} + +void rfbReleaseExtensionIterator() +{ + UNLOCK(extMutex); +} + +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension, + void* data) +{ + rfbExtensionData* extData; + + /* make sure extension is not yet enabled. */ + for(extData = cl->extensions; extData; extData = extData->next) + if(extData->extension == extension) + return FALSE; + + extData = calloc(sizeof(rfbExtensionData),1); + extData->extension = extension; + extData->data = data; + extData->next = cl->extensions; + cl->extensions = extData; + + return TRUE; +} + +rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension) +{ + rfbExtensionData* extData; + rfbExtensionData* prevData = NULL; + + for(extData = cl->extensions; extData; extData = extData->next) { + if(extData->extension == extension) { + if(extData->data) + free(extData->data); + if(prevData == NULL) + cl->extensions = extData->next; + else + prevData->next = extData->next; + return TRUE; + } + prevData = extData; + } + + return FALSE; +} + +void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension) +{ + rfbExtensionData* data = cl->extensions; + + while(data && data->extension != extension) + data = data->next; + + if(data == NULL) { + rfbLog("Extension is not enabled !\n"); + /* rfbCloseClient(cl); */ + return NULL; + } + + return data->data; +} + +/* + * Logging + */ + +void rfbLogEnable(int enabled) { + rfbEnableLogging=enabled; +} + +/* + * rfbLog prints a time-stamped message to the log file (stderr). + */ + +static void +rfbDefaultLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableLogging) + return; + + if (! logMutex_initialized) { + INIT_MUTEX(logMutex); + logMutex_initialized = 1; + } + + LOCK(logMutex); + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock)); + fprintf(stderr, "%s", buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); + UNLOCK(logMutex); +} + +rfbLogProc rfbLog=rfbDefaultLog; +rfbLogProc rfbErr=rfbDefaultLog; + +void rfbLogPerror(const char *str) +{ + rfbErr("%s: %s\n", str, strerror(errno)); +} + +void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + iterator=rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(iterator))) { + LOCK(cl->updateMutex); + if(cl->useCopyRect) { + sraRegionPtr modifiedRegionBackup; + if(!sraRgnEmpty(cl->copyRegion)) { + if(cl->copyDX!=dx || cl->copyDY!=dy) { + /* if a copyRegion was not yet executed, treat it as a + * modifiedRegion. The idea: in this case it could be + * source of the new copyRect or modified anyway. */ + sraRgnOr(cl->modifiedRegion,cl->copyRegion); + sraRgnMakeEmpty(cl->copyRegion); + } else { + /* we have to set the intersection of the source of the copy + * and the old copy to modified. */ + modifiedRegionBackup=sraRgnCreateRgn(copyRegion); + sraRgnOffset(modifiedRegionBackup,-dx,-dy); + sraRgnAnd(modifiedRegionBackup,cl->copyRegion); + sraRgnOr(cl->modifiedRegion,modifiedRegionBackup); + sraRgnDestroy(modifiedRegionBackup); + } + } + + sraRgnOr(cl->copyRegion,copyRegion); + cl->copyDX = dx; + cl->copyDY = dy; + + /* if there were modified regions, which are now copied, + * mark them as modified, because the source of these can be overlapped + * either by new modified or now copied regions. */ + modifiedRegionBackup=sraRgnCreateRgn(cl->modifiedRegion); + sraRgnOffset(modifiedRegionBackup,dx,dy); + sraRgnAnd(modifiedRegionBackup,cl->copyRegion); + sraRgnOr(cl->modifiedRegion,modifiedRegionBackup); + sraRgnDestroy(modifiedRegionBackup); + + if(!cl->enableCursorShapeUpdates) { + /* + * n.b. (dx, dy) is the vector pointing in the direction the + * copyrect displacement will take place. copyRegion is the + * destination rectangle (say), not the source rectangle. + */ + sraRegionPtr cursorRegion; + int x = cl->cursorX - cl->screen->cursor->xhot; + int y = cl->cursorY - cl->screen->cursor->yhot; + int w = cl->screen->cursor->width; + int h = cl->screen->cursor->height; + + cursorRegion = sraRgnCreateRect(x, y, x + w, y + h); + sraRgnAnd(cursorRegion, cl->copyRegion); + if(!sraRgnEmpty(cursorRegion)) { + /* + * current cursor rect overlaps with the copy region *dest*, + * mark it as modified since we won't copy-rect stuff to it. + */ + sraRgnOr(cl->modifiedRegion, cursorRegion); + } + sraRgnDestroy(cursorRegion); + + cursorRegion = sraRgnCreateRect(x, y, x + w, y + h); + /* displace it to check for overlap with copy region source: */ + sraRgnOffset(cursorRegion, dx, dy); + sraRgnAnd(cursorRegion, cl->copyRegion); + if(!sraRgnEmpty(cursorRegion)) { + /* + * current cursor rect overlaps with the copy region *source*, + * mark the *displaced* cursorRegion as modified since we + * won't copyrect stuff to it. + */ + sraRgnOr(cl->modifiedRegion, cursorRegion); + } + sraRgnDestroy(cursorRegion); + } + + } else { + sraRgnOr(cl->modifiedRegion,copyRegion); + } + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + } + + rfbReleaseClientIterator(iterator); +} + +void rfbDoCopyRegion(rfbScreenInfoPtr screen,sraRegionPtr copyRegion,int dx,int dy) +{ + sraRectangleIterator* i; + sraRect rect; + int j,widthInBytes,bpp=screen->serverFormat.bitsPerPixel/8, + rowstride=screen->paddedWidthInBytes; + char *in,*out; + + /* copy it, really */ + i = sraRgnGetReverseIterator(copyRegion,dx<0,dy<0); + while(sraRgnIteratorNext(i,&rect)) { + widthInBytes = (rect.x2-rect.x1)*bpp; + out = screen->frameBuffer+rect.x1*bpp+rect.y1*rowstride; + in = screen->frameBuffer+(rect.x1-dx)*bpp+(rect.y1-dy)*rowstride; + if(dy<0) + for(j=rect.y1;j=rect.y1;j--,out-=rowstride,in-=rowstride) + memmove(out,in,widthInBytes); + } + } + sraRgnReleaseIterator(i); + + rfbScheduleCopyRegion(screen,copyRegion,dx,dy); +} + +void rfbDoCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy) +{ + sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2); + rfbDoCopyRegion(screen,region,dx,dy); + sraRgnDestroy(region); +} + +void rfbScheduleCopyRect(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2,int dx,int dy) +{ + sraRegionPtr region = sraRgnCreateRect(x1,y1,x2,y2); + rfbScheduleCopyRegion(screen,region,dx,dy); + sraRgnDestroy(region); +} + +void rfbMarkRegionAsModified(rfbScreenInfoPtr screen,sraRegionPtr modRegion) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + iterator=rfbGetClientIterator(screen); + while((cl=rfbClientIteratorNext(iterator))) { + LOCK(cl->updateMutex); + sraRgnOr(cl->modifiedRegion,modRegion); + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + } + + rfbReleaseClientIterator(iterator); +} + +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2); +void rfbMarkRectAsModified(rfbScreenInfoPtr screen,int x1,int y1,int x2,int y2) +{ + sraRegionPtr region; + int i; + + if(x1>x2) { i=x1; x1=x2; x2=i; } + if(x1<0) x1=0; + if(x2>screen->width) x2=screen->width; + if(x1==x2) return; + + if(y1>y2) { i=y1; y1=y2; y2=i; } + if(y1<0) y1=0; + if(y2>screen->height) y2=screen->height; + if(y1==y2) return; + + /* update scaled copies for this rectangle */ + rfbScaledScreenUpdate(screen,x1,y1,x2,y2); + + region = sraRgnCreateRect(x1,y1,x2,y2); + rfbMarkRegionAsModified(screen,region); + sraRgnDestroy(region); +} + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#include + +static void * +clientOutput(void *data) +{ + rfbClientPtr cl = (rfbClientPtr)data; + rfbBool haveUpdate; + sraRegion* updateRegion; + + while (1) { + haveUpdate = false; + while (!haveUpdate) { + if (cl->sock == -1) { + /* Client has disconnected. */ + return NULL; + } + if (cl->state != RFB_NORMAL || cl->onHold) { + /* just sleep until things get normal */ + usleep(cl->screen->deferUpdateTime * 1000); + continue; + } + + LOCK(cl->updateMutex); + + if (sraRgnEmpty(cl->requestedRegion)) { + ; /* always require a FB Update Request (otherwise can crash.) */ + } else { + haveUpdate = FB_UPDATE_PENDING(cl); + if(!haveUpdate) { + updateRegion = sraRgnCreateRgn(cl->modifiedRegion); + haveUpdate = sraRgnAnd(updateRegion,cl->requestedRegion); + sraRgnDestroy(updateRegion); + } + } + + if (!haveUpdate) { + WAIT(cl->updateCond, cl->updateMutex); + } + + UNLOCK(cl->updateMutex); + } + + /* OK, now, to save bandwidth, wait a little while for more + updates to come along. */ + usleep(cl->screen->deferUpdateTime * 1000); + + /* Now, get the region we're going to update, and remove + it from cl->modifiedRegion _before_ we send the update. + That way, if anything that overlaps the region we're sending + is updated, we'll be sure to do another update later. */ + LOCK(cl->updateMutex); + updateRegion = sraRgnCreateRgn(cl->modifiedRegion); + UNLOCK(cl->updateMutex); + + /* Now actually send the update. */ + rfbIncrClientRef(cl); + LOCK(cl->sendMutex); + rfbSendFramebufferUpdate(cl, updateRegion); + UNLOCK(cl->sendMutex); + rfbDecrClientRef(cl); + + sraRgnDestroy(updateRegion); + } + + /* Not reached. */ + return NULL; +} + +static void * +clientInput(void *data) +{ + rfbClientPtr cl = (rfbClientPtr)data; + pthread_t output_thread; + pthread_create(&output_thread, NULL, clientOutput, (void *)cl); + + while (1) { + fd_set rfds, wfds, efds; + struct timeval tv; + int n; + + FD_ZERO(&rfds); + FD_SET(cl->sock, &rfds); + FD_ZERO(&efds); + FD_SET(cl->sock, &efds); + + /* Are we transferring a file in the background? */ + FD_ZERO(&wfds); + if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1)) + FD_SET(cl->sock, &wfds); + + tv.tv_sec = 60; /* 1 minute */ + tv.tv_usec = 0; + n = select(cl->sock + 1, &rfds, &wfds, &efds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); + break; + } + if (n == 0) /* timeout */ + { + rfbSendFileTransferChunk(cl); + continue; + } + + /* We have some space on the transmit queue, send some data */ + if (FD_ISSET(cl->sock, &wfds)) + rfbSendFileTransferChunk(cl); + + if (FD_ISSET(cl->sock, &rfds) || FD_ISSET(cl->sock, &efds)) + rfbProcessClientMessage(cl); + + if (cl->sock == -1) { + /* Client has disconnected. */ + break; + } + } + + /* Get rid of the output thread. */ + LOCK(cl->updateMutex); + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + IF_PTHREADS(pthread_join(output_thread, NULL)); + + rfbClientConnectionGone(cl); + + return NULL; +} + +static void* +listenerRun(void *data) +{ + rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data; + int client_fd; + struct sockaddr_in peer; + rfbClientPtr cl; + socklen_t len; + + len = sizeof(peer); + + /* TODO: this thread wont die by restarting the server */ + /* TODO: HTTP is not handled */ + while ((client_fd = accept(screen->listenSock, + (struct sockaddr*)&peer, &len)) >= 0) { + cl = rfbNewClient(screen,client_fd); + len = sizeof(peer); + + if (cl && !cl->onHold ) + rfbStartOnHoldClient(cl); + } + return(NULL); +} + + +void +rfbStartOnHoldClient(rfbClientPtr cl) +{ + pthread_create(&cl->client_thread, NULL, clientInput, (void *)cl); +} + +#else + +void +rfbStartOnHoldClient(rfbClientPtr cl) +{ + cl->onHold = FALSE; +} + +#endif + +void +rfbRefuseOnHoldClient(rfbClientPtr cl) +{ + rfbCloseClient(cl); + rfbClientConnectionGone(cl); +} + +static void +rfbDefaultKbdAddEvent(rfbBool down, rfbKeySym keySym, rfbClientPtr cl) +{ +} + +void +rfbDefaultPtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl) +{ + rfbClientIteratorPtr iterator; + rfbClientPtr other_client; + rfbScreenInfoPtr s = cl->screen; + + if (x != s->cursorX || y != s->cursorY) { + LOCK(s->cursorMutex); + s->cursorX = x; + s->cursorY = y; + UNLOCK(s->cursorMutex); + + /* The cursor was moved by this client, so don't send CursorPos. */ + if (cl->enableCursorPosUpdates) + cl->cursorWasMoved = FALSE; + + /* But inform all remaining clients about this cursor movement. */ + iterator = rfbGetClientIterator(s); + while ((other_client = rfbClientIteratorNext(iterator)) != NULL) { + if (other_client != cl && other_client->enableCursorPosUpdates) { + other_client->cursorWasMoved = TRUE; + } + } + rfbReleaseClientIterator(iterator); + } +} + +static void rfbDefaultSetXCutText(char* text, int len, rfbClientPtr cl) +{ +} + +/* TODO: add a nice VNC or RFB cursor */ + +#if defined(WIN32) || defined(sparc) || !defined(NO_STRICT_ANSI) +static rfbCursor myCursor = +{ + FALSE, FALSE, FALSE, FALSE, + (unsigned char*)"\000\102\044\030\044\102\000", + (unsigned char*)"\347\347\176\074\176\347\347", + 8, 7, 3, 3, + 0, 0, 0, + 0xffff, 0xffff, 0xffff, + NULL +}; +#else +static rfbCursor myCursor = +{ + cleanup: FALSE, + cleanupSource: FALSE, + cleanupMask: FALSE, + cleanupRichSource: FALSE, + source: "\000\102\044\030\044\102\000", + mask: "\347\347\176\074\176\347\347", + width: 8, height: 7, xhot: 3, yhot: 3, + foreRed: 0, foreGreen: 0, foreBlue: 0, + backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff, + richSource: NULL +}; +#endif + +static rfbCursorPtr rfbDefaultGetCursorPtr(rfbClientPtr cl) +{ + return(cl->screen->cursor); +} + +/* response is cl->authChallenge vncEncrypted with passwd */ +static rfbBool rfbDefaultPasswordCheck(rfbClientPtr cl,const char* response,int len) +{ + int i; + char *passwd=rfbDecryptPasswdFromFile(cl->screen->authPasswdData); + + if(!passwd) { + rfbErr("Couldn't read password file: %s\n",cl->screen->authPasswdData); + return(FALSE); + } + + rfbEncryptBytes(cl->authChallenge, passwd); + + /* Lose the password from memory */ + for (i = strlen(passwd); i >= 0; i--) { + passwd[i] = '\0'; + } + + free(passwd); + + if (memcmp(cl->authChallenge, response, len) != 0) { + rfbErr("authProcessClientMessage: authentication failed from %s\n", + cl->host); + return(FALSE); + } + + return(TRUE); +} + +/* for this method, authPasswdData is really a pointer to an array + of char*'s, where the last pointer is 0. */ +rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len) +{ + char **passwds; + int i=0; + + for(passwds=(char**)cl->screen->authPasswdData;*passwds;passwds++,i++) { + uint8_t auth_tmp[CHALLENGESIZE]; + memcpy((char *)auth_tmp, (char *)cl->authChallenge, CHALLENGESIZE); + rfbEncryptBytes(auth_tmp, *passwds); + + if (memcmp(auth_tmp, response, len) == 0) { + if(i>=cl->screen->authPasswdFirstViewOnly) + cl->viewOnly=TRUE; + return(TRUE); + } + } + + rfbErr("authProcessClientMessage: authentication failed from %s\n", + cl->host); + return(FALSE); +} + +void rfbDoNothingWithClient(rfbClientPtr cl) +{ +} + +static enum rfbNewClientAction rfbDefaultNewClientHook(rfbClientPtr cl) +{ + return RFB_CLIENT_ACCEPT; +} + +/* + * Update server's pixel format in screenInfo structure. This + * function is called from rfbGetScreen() and rfbNewFramebuffer(). + */ + +static void rfbInitServerFormat(rfbScreenInfoPtr screen, int bitsPerSample) +{ + rfbPixelFormat* format=&screen->serverFormat; + + format->bitsPerPixel = screen->bitsPerPixel; + format->depth = screen->depth; + format->bigEndian = rfbEndianTest?FALSE:TRUE; + format->trueColour = TRUE; + screen->colourMap.count = 0; + screen->colourMap.is16 = 0; + screen->colourMap.data.bytes = NULL; + + if (format->bitsPerPixel == 8) { + format->redMax = 7; + format->greenMax = 7; + format->blueMax = 3; + format->redShift = 0; + format->greenShift = 3; + format->blueShift = 6; + } else { + format->redMax = (1 << bitsPerSample) - 1; + format->greenMax = (1 << bitsPerSample) - 1; + format->blueMax = (1 << bitsPerSample) - 1; + if(rfbEndianTest) { + format->redShift = 0; + format->greenShift = bitsPerSample; + format->blueShift = bitsPerSample * 2; + } else { + if(format->bitsPerPixel==8*3) { + format->redShift = bitsPerSample*2; + format->greenShift = bitsPerSample*1; + format->blueShift = 0; + } else { + format->redShift = bitsPerSample*3; + format->greenShift = bitsPerSample*2; + format->blueShift = bitsPerSample; + } + } + } +} + +rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, + int width,int height,int bitsPerSample,int samplesPerPixel, + int bytesPerPixel) +{ + rfbScreenInfoPtr screen=calloc(sizeof(rfbScreenInfo),1); + + if (! logMutex_initialized) { + INIT_MUTEX(logMutex); + logMutex_initialized = 1; + } + + + if(width&3) + rfbErr("WARNING: Width (%d) is not a multiple of 4. VncViewer has problems with that.\n",width); + + screen->autoPort=FALSE; + screen->clientHead=NULL; + screen->pointerClient=NULL; + screen->port=5900; + screen->socketState=RFB_SOCKET_INIT; + + screen->inetdInitDone = FALSE; + screen->inetdSock=-1; + + screen->udpSock=-1; + screen->udpSockConnected=FALSE; + screen->udpPort=0; + screen->udpClient=NULL; + + screen->maxFd=0; + screen->listenSock=-1; + + screen->httpInitDone=FALSE; + screen->httpEnableProxyConnect=FALSE; + screen->httpPort=0; + screen->httpDir=NULL; + screen->httpListenSock=-1; + screen->httpSock=-1; + + screen->desktopName = "LibVNCServer"; + screen->alwaysShared = FALSE; + screen->neverShared = FALSE; + screen->dontDisconnect = FALSE; + screen->authPasswdData = NULL; + screen->authPasswdFirstViewOnly = 1; + + screen->width = width; + screen->height = height; + screen->bitsPerPixel = screen->depth = 8*bytesPerPixel; + + screen->passwordCheck = rfbDefaultPasswordCheck; + + screen->ignoreSIGPIPE = TRUE; + + /* disable progressive updating per default */ + screen->progressiveSliceHeight = 0; + + screen->listenInterface = htonl(INADDR_ANY); + + screen->deferUpdateTime=5; + screen->maxRectsPerUpdate=50; + + screen->handleEventsEagerly = FALSE; + + screen->protocolMajorVersion = rfbProtocolMajorVersion; + screen->protocolMinorVersion = rfbProtocolMinorVersion; + + screen->permitFileTransfer = FALSE; + + if(!rfbProcessArguments(screen,argc,argv)) { + free(screen); + return NULL; + } + +#ifdef WIN32 + { + DWORD dummy=255; + GetComputerName(screen->thisHost,&dummy); + } +#else + gethostname(screen->thisHost, 255); +#endif + + screen->paddedWidthInBytes = width*bytesPerPixel; + + /* format */ + + rfbInitServerFormat(screen, bitsPerSample); + + /* cursor */ + + screen->cursorX=screen->cursorY=screen->underCursorBufferLen=0; + screen->underCursorBuffer=NULL; + screen->dontConvertRichCursorToXCursor = FALSE; + screen->cursor = &myCursor; + INIT_MUTEX(screen->cursorMutex); + + IF_PTHREADS(screen->backgroundLoop = FALSE); + + /* proc's and hook's */ + + screen->kbdAddEvent = rfbDefaultKbdAddEvent; + screen->kbdReleaseAllKeys = rfbDoNothingWithClient; + screen->ptrAddEvent = rfbDefaultPtrAddEvent; + screen->setXCutText = rfbDefaultSetXCutText; + screen->getCursorPtr = rfbDefaultGetCursorPtr; + screen->setTranslateFunction = rfbSetTranslateFunction; + screen->newClientHook = rfbDefaultNewClientHook; + screen->displayHook = NULL; + screen->displayFinishedHook = NULL; + screen->getKeyboardLedStateHook = NULL; + + /* initialize client list and iterator mutex */ + rfbClientListInit(screen); + + return(screen); +} + +/* + * Switch to another framebuffer (maybe of different size and color + * format). Clients supporting NewFBSize pseudo-encoding will change + * their local framebuffer dimensions if necessary. + * NOTE: Rich cursor data should be converted to new pixel format by + * the caller. + */ + +void rfbNewFramebuffer(rfbScreenInfoPtr screen, char *framebuffer, + int width, int height, + int bitsPerSample, int samplesPerPixel, + int bytesPerPixel) +{ + rfbPixelFormat old_format; + rfbBool format_changed = FALSE; + rfbClientIteratorPtr iterator; + rfbClientPtr cl; + + /* Update information in the screenInfo structure */ + + old_format = screen->serverFormat; + + if (width & 3) + rfbErr("WARNING: New width (%d) is not a multiple of 4.\n", width); + + screen->width = width; + screen->height = height; + screen->bitsPerPixel = screen->depth = 8*bytesPerPixel; + screen->paddedWidthInBytes = width*bytesPerPixel; + + rfbInitServerFormat(screen, bitsPerSample); + + if (memcmp(&screen->serverFormat, &old_format, + sizeof(rfbPixelFormat)) != 0) { + format_changed = TRUE; + } + + screen->frameBuffer = framebuffer; + + /* Adjust pointer position if necessary */ + + if (screen->cursorX >= width) + screen->cursorX = width - 1; + if (screen->cursorY >= height) + screen->cursorY = height - 1; + + /* For each client: */ + iterator = rfbGetClientIterator(screen); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) { + + /* Re-install color translation tables if necessary */ + + if (format_changed) + screen->setTranslateFunction(cl); + + /* Mark the screen contents as changed, and schedule sending + NewFBSize message if supported by this client. */ + + LOCK(cl->updateMutex); + sraRgnDestroy(cl->modifiedRegion); + cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height); + sraRgnMakeEmpty(cl->copyRegion); + cl->copyDX = 0; + cl->copyDY = 0; + + if (cl->useNewFBSize) + cl->newFBSizePending = TRUE; + + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + } + rfbReleaseClientIterator(iterator); +} + +/* hang up on all clients and free all reserved memory */ + +void rfbScreenCleanup(rfbScreenInfoPtr screen) +{ + rfbClientIteratorPtr i=rfbGetClientIterator(screen); + rfbClientPtr cl,cl1=rfbClientIteratorNext(i); + while(cl1) { + cl=rfbClientIteratorNext(i); + rfbClientConnectionGone(cl1); + cl1=cl; + } + rfbReleaseClientIterator(i); + +#define FREE_IF(x) if(screen->x) free(screen->x) + FREE_IF(colourMap.data.bytes); + FREE_IF(underCursorBuffer); + TINI_MUTEX(screen->cursorMutex); + if(screen->cursor && screen->cursor->cleanup) + rfbFreeCursor(screen->cursor); + + rfbRRECleanup(screen); + rfbCoRRECleanup(screen); + rfbUltraCleanup(screen); +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbZlibCleanup(screen); +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + rfbTightCleanup(screen); +#endif + + /* free all 'scaled' versions of this screen */ + while (screen->scaledScreenNext!=NULL) + { + rfbScreenInfoPtr ptr; + ptr = screen->scaledScreenNext; + screen->scaledScreenNext = ptr->scaledScreenNext; + free(ptr->frameBuffer); + free(ptr); + } + +#endif + free(screen); +} + +void rfbInitServer(rfbScreenInfoPtr screen) +{ +#ifdef WIN32 + WSADATA trash; + WSAStartup(MAKEWORD(2,2),&trash); +#endif + rfbInitSockets(screen); + rfbHttpInitSockets(screen); +#ifndef __MINGW32__ + if(screen->ignoreSIGPIPE) + signal(SIGPIPE,SIG_IGN); +#endif +} + +void rfbShutdownServer(rfbScreenInfoPtr screen,rfbBool disconnectClients) { + if(disconnectClients) { + rfbClientPtr cl; + rfbClientIteratorPtr iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) + if (cl->sock > -1) + /* we don't care about maxfd here, because the server goes away */ + rfbCloseClient(cl); + rfbReleaseClientIterator(iter); + } + + rfbShutdownSockets(screen); + rfbHttpShutdownSockets(screen); +} + +#include + +// #ifndef LIBVNCSERVER_HAVE_GETTIMEOFDAY +// #include +// #include +// #include +// +// void gettimeofday(struct timeval* tv,char* dummy) +// { +// SYSTEMTIME t; +// GetSystemTime(&t); +// tv->tv_sec=t.wHour*3600+t.wMinute*60+t.wSecond; +// tv->tv_usec=t.wMilliseconds*1000; +// } +// #endif + +rfbBool +rfbProcessEvents(rfbScreenInfoPtr screen,long usec) +{ + rfbClientIteratorPtr i; + rfbClientPtr cl,clPrev; + struct timeval tv; + rfbBool result=FALSE; + extern rfbClientIteratorPtr + rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen); + + if(usec<0) + usec=screen->deferUpdateTime*1000; + + rfbCheckFds(screen,usec); + rfbHttpCheckFds(screen); +#ifdef CORBA + corbaCheckFds(screen); +#endif + + i = rfbGetClientIteratorWithClosed(screen); + cl=rfbClientIteratorHead(i); + while(cl) { + if (cl->sock >= 0 && !cl->onHold && FB_UPDATE_PENDING(cl) && + !sraRgnEmpty(cl->requestedRegion)) { + result=TRUE; + if(screen->deferUpdateTime == 0) { + rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + } else if(cl->startDeferring.tv_usec == 0) { + gettimeofday(&cl->startDeferring,NULL); + if(cl->startDeferring.tv_usec == 0) + cl->startDeferring.tv_usec++; + } else { + gettimeofday(&tv,NULL); + if(tv.tv_sec < cl->startDeferring.tv_sec /* at midnight */ + || ((tv.tv_sec-cl->startDeferring.tv_sec)*1000 + +(tv.tv_usec-cl->startDeferring.tv_usec)/1000) + > screen->deferUpdateTime) { + cl->startDeferring.tv_usec = 0; + rfbSendFramebufferUpdate(cl,cl->modifiedRegion); + } + } + } + + if (!cl->viewOnly && cl->lastPtrX >= 0) { + if(cl->startPtrDeferring.tv_usec == 0) { + gettimeofday(&cl->startPtrDeferring,NULL); + if(cl->startPtrDeferring.tv_usec == 0) + cl->startPtrDeferring.tv_usec++; + } else { + struct timeval tv; + gettimeofday(&tv,NULL); + if(tv.tv_sec < cl->startPtrDeferring.tv_sec /* at midnight */ + || ((tv.tv_sec-cl->startPtrDeferring.tv_sec)*1000 + +(tv.tv_usec-cl->startPtrDeferring.tv_usec)/1000) + > cl->screen->deferPtrUpdateTime) { + cl->startPtrDeferring.tv_usec = 0; + cl->screen->ptrAddEvent(cl->lastPtrButtons, + cl->lastPtrX, + cl->lastPtrY, cl); + cl->lastPtrX = -1; + } + } + } + clPrev=cl; + cl=rfbClientIteratorNext(i); + if(clPrev->sock==-1) { + rfbClientConnectionGone(clPrev); + result=TRUE; + } + } + rfbReleaseClientIterator(i); + + return result; +} + +rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo) { + return screenInfo->socketState!=RFB_SOCKET_SHUTDOWN || screenInfo->clientHead!=NULL; +} + +static void *httpListen(void *data) +{ + rfbScreenInfoPtr screen=(rfbScreenInfoPtr)data; + while (1) + { + rfbHttpCheckFds(screen);//backgrounded event loop doesnt listen for connections from browser + usleep(100000); + } + return NULL; +} + +void rfbRunEventLoop(rfbScreenInfoPtr screen, long usec, rfbBool runInBackground) +{ + if(runInBackground) { +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t listener_thread; + + screen->backgroundLoop = TRUE; + + pthread_create(&listener_thread, NULL, listenerRun, screen); + pthread_create(&listener_thread, NULL, httpListen, screen); + return; +#else + rfbErr("Can't run in background, because I don't have PThreads!\n"); + return; +#endif + } + + if(usec<0) + usec=screen->deferUpdateTime*1000; + + while(rfbIsActive(screen)) + rfbProcessEvents(screen,usec); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c new file mode 100755 index 0000000..a12c146 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.c @@ -0,0 +1,448 @@ +/* Functions to compute MD5 message digest of files or memory blocks. + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995,1996,1997,1999,2000,2001,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Written by Ulrich Drepper , 1995. */ + +#include + +# include +# include + +#include "md5.h" + +#ifdef _LIBC +# include +# if __BYTE_ORDER == __BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# endif +/* We need to keep the namespace clean so define the MD5 function + protected using leading __ . */ +# define md5_init_ctx __md5_init_ctx +# define md5_process_block __md5_process_block +# define md5_process_bytes __md5_process_bytes +# define md5_finish_ctx __md5_finish_ctx +# define md5_read_ctx __md5_read_ctx +# define md5_stream __md5_stream +# define md5_buffer __md5_buffer +#endif + +#ifdef WORDS_BIGENDIAN +# define SWAP(n) \ + (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) +#else +# define SWAP(n) (n) +#endif + + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (ctx) + struct md5_ctx *ctx; +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (ctx, resbuf) + const struct md5_ctx *ctx; + void *resbuf; +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +int +md5_stream (stream, resblock) + FILE *stream; + void *resblock; +{ + /* Important: BLOCKSIZE must be a multiple of 64. */ +#define BLOCKSIZE 4096 + struct md5_ctx ctx; + char buffer[BLOCKSIZE + 72]; + size_t sum; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Iterate over full file contents. */ + while (1) + { + /* We read the file in blocks of BLOCKSIZE bytes. One call of the + computation function processes the whole buffer so that with the + next round of the loop another block can be read. */ + size_t n; + sum = 0; + + /* Read block. Take care for partial reads. */ + do + { + n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); + + sum += n; + } + while (sum < BLOCKSIZE && n != 0); + if (n == 0 && ferror (stream)) + return 1; + + /* If end of file is reached, end the loop. */ + if (n == 0) + break; + + /* Process buffer with BLOCKSIZE bytes. Note that + BLOCKSIZE % 64 == 0 + */ + md5_process_block (buffer, BLOCKSIZE, &ctx); + } + + /* Add the last bytes if necessary. */ + if (sum > 0) + md5_process_bytes (buffer, sum, &ctx); + + /* Construct result in desired memory. */ + md5_finish_ctx (&ctx, resblock); + return 0; +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (buffer, len, resblock) + const char *buffer; + size_t len; + void *resblock; +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#if !_STRING_ARCH_unaligned +/* To check alignment gcc has an appropriate operator. Other + compilers don't. */ +# if __GNUC__ >= 2 +# define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) +# else +# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0) +# endif + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else +#endif + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* It is unfortunate that C does not provide an operator for + cyclic rotation. Hope the C compiler is smart enough. */ +#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + CYCLIC (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h new file mode 100755 index 0000000..2709660 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/md5.h @@ -0,0 +1,148 @@ +/* Declaration of functions and data types used for MD5 sum computing + library functions. + Copyright (C) 1995-1997,1999,2000,2001,2004,2005 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include + +#if defined HAVE_LIMITS_H || _LIBC +# include +#endif + +#define MD5_DIGEST_SIZE 16 +#define MD5_BLOCK_SIZE 64 + +/* The following contortions are an attempt to use the C preprocessor + to determine an unsigned integral type that is 32 bits wide. An + alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but + doing that would require that the configure script compile and *run* + the resulting executable. Locally running cross-compiled executables + is usually not possible. */ + +#ifdef _LIBC +# include +typedef uint32_t md5_uint32; +typedef uintptr_t md5_uintptr; +#else +# if defined __STDC__ && __STDC__ +# define UINT_MAX_32_BITS 4294967295U +# else +# define UINT_MAX_32_BITS 0xFFFFFFFF +# endif + +/* If UINT_MAX isn't defined, assume it's a 32-bit type. + This should be valid for all systems GNU cares about because + that doesn't include 16-bit systems, and only modern systems + (that certainly have ) have 64+-bit integral types. */ + +# ifndef UINT_MAX +# define UINT_MAX UINT_MAX_32_BITS +# endif + +# if UINT_MAX == UINT_MAX_32_BITS + typedef unsigned int md5_uint32; +# else +# if USHRT_MAX == UINT_MAX_32_BITS + typedef unsigned short md5_uint32; +# else +# if ULONG_MAX == UINT_MAX_32_BITS + typedef unsigned long md5_uint32; +# else + /* The following line is intended to evoke an error. + Using #error is not portable enough. */ + "Cannot determine unsigned 32-bit data type." +# endif +# endif +# endif +/* We have to make a guess about the integer type equivalent in size + to pointers which should always be correct. */ +typedef unsigned long int md5_uintptr; +#endif + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32)))); +}; + +/* + * The following three functions are build up the low level used in + * the functions `md5_stream' and `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void __md5_init_ctx (struct md5_ctx *ctx) ;//__THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void __md5_process_block (const void *buffer, size_t len, + struct md5_ctx *ctx) ;//__THROW; + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void __md5_process_bytes (const void *buffer, size_t len, + struct md5_ctx *ctx) ;//__THROW; + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) ;//__THROW; + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) ;//__THROW; + + +/* Compute MD5 message digest for bytes read from STREAM. The + resulting message digest number will be written into the 16 bytes + beginning at RESBLOCK. */ +extern int __md5_stream (FILE *stream, void *resblock) ;//__THROW; + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *__md5_buffer (const char *buffer, size_t len, + void *resblock) ;//__THROW; + +#endif /* md5.h */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c new file mode 100755 index 0000000..85771eb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.c @@ -0,0 +1,2935 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO +#define LZO_BUILD + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x1080) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H +#endif + +#if !defined(LZO_NO_SYS_TYPES_H) +# include +#endif +#include + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H + +#if !defined(__LZO_IN_MINILZO) +# ifndef __LZOCONF_H +# include +# endif +#endif + +#if defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if !defined(LZO_HAVE_CONFIG_H) +# include +# include +# if !defined(NO_STDLIB_H) +# include +# endif +# define HAVE_MEMCMP +# define HAVE_MEMCPY +# define HAVE_MEMMOVE +# define HAVE_MEMSET +#else +# include +# if defined(HAVE_STDDEF_H) +# include +# endif +# if defined(STDC_HEADERS) +# include +# include +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# define HAVE_MALLOC_H +# define HAVE_HALLOC +#endif + +#undef NDEBUG +#if !defined(LZO_DEBUG) +# define NDEBUG +#endif +#if defined(LZO_DEBUG) || !defined(NDEBUG) +# if !defined(NO_STDIO_H) +# include +# endif +#endif +#include + +#if !defined(LZO_COMPILE_TIME_ASSERT) +# define LZO_COMPILE_TIME_ASSERT(expr) \ + { typedef int __lzo_compile_time_assert_fail[1 - 2 * !(expr)]; } +#endif + +#if !defined(LZO_UNUSED) +# if 1 +# define LZO_UNUSED(var) ((void)&var) +# elif 0 +# define LZO_UNUSED(var) { typedef int __lzo_unused[sizeof(var) ? 2 : 1]; } +# else +# define LZO_UNUSED(parm) (parm = parm) +# endif +#endif + +#if !defined(__inline__) && !defined(__GNUC__) +# if defined(__cplusplus) +# define __inline__ inline +# else +# define __inline__ +# endif +#endif + +#if defined(NO_MEMCMP) +# undef HAVE_MEMCMP +#endif + +#if !defined(HAVE_MEMCMP) +# undef memcmp +# define memcmp lzo_memcmp +#endif +#if !defined(HAVE_MEMCPY) +# undef memcpy +# define memcpy lzo_memcpy +#endif +#if !defined(HAVE_MEMMOVE) +# undef memmove +# define memmove lzo_memmove +#endif +#if !defined(HAVE_MEMSET) +# undef memset +# define memset lzo_memset +#endif + +#if 0 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_LSIZE(bits) (1ul << (bits)) +#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2))) +#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1))) + +#if !defined(SIZEOF_UNSIGNED) +# if (UINT_MAX == 0xffff) +# define SIZEOF_UNSIGNED 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 4 +# elif (UINT_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED 8 +# else +# error "SIZEOF_UNSIGNED" +# endif +#endif + +#if !defined(SIZEOF_UNSIGNED_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 4 +# elif (ULONG_MAX >= LZO_0xffffffffL) +# define SIZEOF_UNSIGNED_LONG 8 +# else +# error "SIZEOF_UNSIGNED_LONG" +# endif +#endif + +#if !defined(SIZEOF_SIZE_T) +# define SIZEOF_SIZE_T SIZEOF_UNSIGNED +#endif +#if !defined(SIZE_T_MAX) +# define SIZE_T_MAX LZO_UTYPE_MAX(SIZEOF_SIZE_T) +#endif + +#if 1 && defined(__LZO_i386) && (UINT_MAX == LZO_0xffffffffL) +# if !defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX == 0xffff) +# define LZO_UNALIGNED_OK_2 +# endif +# if !defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX == LZO_0xffffffffL) +# define LZO_UNALIGNED_OK_4 +# endif +#endif + +#if defined(LZO_UNALIGNED_OK_2) || defined(LZO_UNALIGNED_OK_4) +# if !defined(LZO_UNALIGNED_OK) +# define LZO_UNALIGNED_OK +# endif +#endif + +#if defined(__LZO_NO_UNALIGNED) +# undef LZO_UNALIGNED_OK +# undef LZO_UNALIGNED_OK_2 +# undef LZO_UNALIGNED_OK_4 +#endif + +#if defined(LZO_UNALIGNED_OK_2) && (USHRT_MAX != 0xffff) +# error "LZO_UNALIGNED_OK_2 must not be defined on this system" +#endif +#if defined(LZO_UNALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_UNALIGNED_OK_4 must not be defined on this system" +#endif + +#if defined(__LZO_NO_ALIGNED) +# undef LZO_ALIGNED_OK_4 +#endif + +#if defined(LZO_ALIGNED_OK_4) && (LZO_UINT32_MAX != LZO_0xffffffffL) +# error "LZO_ALIGNED_OK_4 must not be defined on this system" +#endif + +#define LZO_LITTLE_ENDIAN 1234 +#define LZO_BIG_ENDIAN 4321 +#define LZO_PDP_ENDIAN 3412 + +#if !defined(LZO_BYTE_ORDER) +# if defined(MFX_BYTE_ORDER) +# define LZO_BYTE_ORDER MFX_BYTE_ORDER +# elif defined(__LZO_i386) +# define LZO_BYTE_ORDER LZO_LITTLE_ENDIAN +# elif defined(BYTE_ORDER) +# define LZO_BYTE_ORDER BYTE_ORDER +# elif defined(__BYTE_ORDER) +# define LZO_BYTE_ORDER __BYTE_ORDER +# endif +#endif + +#if defined(LZO_BYTE_ORDER) +# if (LZO_BYTE_ORDER != LZO_LITTLE_ENDIAN) && \ + (LZO_BYTE_ORDER != LZO_BIG_ENDIAN) +# error "invalid LZO_BYTE_ORDER" +# endif +#endif + +#if defined(LZO_UNALIGNED_OK) && !defined(LZO_BYTE_ORDER) +# error "LZO_BYTE_ORDER is not defined" +#endif + +#define LZO_OPTIMIZE_GNUC_i386_IS_BUGGY + +#if defined(NDEBUG) && !defined(LZO_DEBUG) && !defined(__LZO_CHECKER) +# if defined(__GNUC__) && defined(__i386__) +# if !defined(LZO_OPTIMIZE_GNUC_i386_IS_BUGGY) +# define LZO_OPTIMIZE_GNUC_i386 +# endif +# endif +#endif + +__LZO_EXTERN_C int __lzo_init_done; +__LZO_EXTERN_C const lzo_byte __lzo_copyright[]; +LZO_EXTERN(const lzo_byte *) lzo_copyright(void); +__LZO_EXTERN_C const lzo_uint32 _lzo_crc32_table[256]; + +#define _LZO_STRINGIZE(x) #x +#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x) + +#define _LZO_CONCAT2(a,b) a ## b +#define _LZO_CONCAT3(a,b,c) a ## b ## c +#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d +#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e + +#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b) +#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c) +#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d) +#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e) + +#if 0 + +#define __LZO_IS_COMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_COMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_DECOMPRESS_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_DECOMPRESS(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#define __LZO_IS_OPTIMIZE_QUERY(i,il,o,ol,w) ((lzo_voidp)(o) == (w)) +#define __LZO_QUERY_OPTIMIZE(i,il,o,ol,w,n,s) \ + (*ol = (n)*(s), LZO_E_OK) + +#endif + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +# include +# if 1 && defined(__WATCOMC__) +# include + __LZO_EXTERN_C unsigned char _HShift; +# define __LZO_HShift _HShift +# elif 1 && defined(_MSC_VER) + __LZO_EXTERN_C unsigned short __near _AHSHIFT; +# define __LZO_HShift ((unsigned) &_AHSHIFT) +# elif defined(__LZO_WIN16) +# define __LZO_HShift 3 +# else +# define __LZO_HShift 12 +# endif +# if !defined(_FP_SEG) && defined(FP_SEG) +# define _FP_SEG FP_SEG +# endif +# if !defined(_FP_OFF) && defined(FP_OFF) +# define _FP_OFF FP_OFF +# endif +#endif + +#if !defined(lzo_ptrdiff_t) +# if (UINT_MAX >= LZO_0xffffffffL) + typedef ptrdiff_t lzo_ptrdiff_t; +# else + typedef long lzo_ptrdiff_t; +# endif +#endif + +#if !defined(__LZO_HAVE_PTR_T) +# if defined(lzo_ptr_t) +# define __LZO_HAVE_PTR_T +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_LONG) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_LONG) + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED) + typedef unsigned int lzo_ptr_t; + typedef int lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(SIZEOF_CHAR_P) && defined(SIZEOF_UNSIGNED_SHORT) +# if (SIZEOF_CHAR_P == SIZEOF_UNSIGNED_SHORT) + typedef unsigned short lzo_ptr_t; + typedef short lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +# endif +#endif +#if !defined(__LZO_HAVE_PTR_T) +# if defined(LZO_HAVE_CONFIG_H) || defined(SIZEOF_CHAR_P) +# error "no suitable type for lzo_ptr_t" +# else + typedef unsigned long lzo_ptr_t; + typedef long lzo_sptr_t; +# define __LZO_HAVE_PTR_T +# endif +#endif + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) +#define PTR(a) ((lzo_bytep) (a)) +#define PTR_ALIGNED_4(a) ((_FP_OFF(a) & 3) == 0) +#define PTR_ALIGNED2_4(a,b) (((_FP_OFF(a) | _FP_OFF(b)) & 3) == 0) +#else +#define PTR(a) ((lzo_ptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b))) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_int32 a_lzo_int32; + lzo_uint32 a_lzo_uint32; + ptrdiff_t a_ptrdiff_t; + lzo_ptrdiff_t a_lzo_ptrdiff_t; + lzo_ptr_t a_lzo_ptr_t; + lzo_voidp a_lzo_voidp; + void * a_void_p; + lzo_bytep a_lzo_bytep; + lzo_bytepp a_lzo_bytepp; + lzo_uintp a_lzo_uintp; + lzo_uint * a_lzo_uint_p; + lzo_uint32p a_lzo_uint32p; + lzo_uint32 * a_lzo_uint32_p; + unsigned char * a_uchar_p; + char * a_char_p; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#define LZO_DETERMINISTIC + +#define LZO_DICT_USE_PTR +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) || defined(__LZO_STRICT_16BIT) +# undef LZO_DICT_USE_PTR +#endif + +#if defined(LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t __LZO_MMODEL * +#endif + +#if !defined(lzo_moff_t) +#define lzo_moff_t lzo_uint +#endif + +#endif + +LZO_PUBLIC(lzo_ptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_ptr_t p; + +#if defined(__LZO_DOS16) || defined(__LZO_WIN16) + p = (((lzo_ptr_t)(_FP_SEG(ptr))) << (16 - __LZO_HShift)) + (_FP_OFF(ptr)); +#else + p = PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ + lzo_ptr_t p, s, n; + + assert(size > 0); + + p = __lzo_ptr_linear(ptr); + s = (lzo_ptr_t) (size - 1); +#if 0 + assert((size & (size - 1)) == 0); + n = ((p + s) & ~s) - p; +#else + n = (((p + s) / size) * size) - p; +#endif + + assert((long)n >= 0); + assert(n <= s); + + return (unsigned)n; +} + +#ifndef __LZO_UTIL_H +#define __LZO_UTIL_H + +#ifndef __LZO_CONF_H +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if 1 && defined(HAVE_MEMCPY) +#if !defined(__LZO_DOS16) && !defined(__LZO_WIN16) + +#define MEMCPY8_DS(dest,src,len) \ + memcpy(dest,src,len); \ + dest += len; \ + src += len + +#endif +#endif + +#if 0 && !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + len -= 8; \ + } while (len > 0); } + +#endif + +#if !defined(MEMCPY8_DS) + +#define MEMCPY8_DS(dest,src,len) \ + { register lzo_uint __l = (len) / 8; \ + do { \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + *dest++ = *src++; \ + } while (--__l > 0); } + +#endif + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#define MEMMOVE_DS(dest,src,len) \ + do *dest++ = *src++; \ + while (--len > 0) + +#if 0 && defined(LZO_OPTIMIZE_GNUC_i386) + +#define BZERO8_PTR(s,l,n) \ +__asm__ __volatile__( \ + "movl %0,%%eax \n" \ + "movl %1,%%edi \n" \ + "movl %2,%%ecx \n" \ + "cld \n" \ + "rep \n" \ + "stosl %%eax,(%%edi) \n" \ + : \ + :"g" (0),"g" (s),"g" (n) \ + :"eax","edi","ecx", "memory", "cc" \ +) + +#elif (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + +#if 1 +#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n)) +#else +#define BZERO8_PTR(s,l,n) memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) +#endif + +#else + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#endif + +#if 0 +#if defined(__GNUC__) && defined(__i386__) + +unsigned char lzo_rotr8(unsigned char value, int shift); +extern __inline__ unsigned char lzo_rotr8(unsigned char value, int shift) +{ + unsigned char result; + + __asm__ __volatile__ ("movb %b1, %b0; rorb %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +unsigned short lzo_rotr16(unsigned short value, int shift); +extern __inline__ unsigned short lzo_rotr16(unsigned short value, int shift) +{ + unsigned short result; + + __asm__ __volatile__ ("movw %b1, %b0; rorw %b2, %b0" + : "=a"(result) : "g"(value), "c"(shift)); + return result; +} + +#endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +LZO_PUBLIC(lzo_bool) +lzo_assert(int expr) +{ + return (expr) ? 1 : 0; +} + +/* If you use the LZO library in a product, you *must* keep this + * copyright string in the executable of your product. + */ + +const lzo_byte __lzo_copyright[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\n\n\n" + "LZO real-time data compression library.\n" + "Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com/opensource/lzo/\n" + "\n" + "LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE "\n" + "LZO build date: " __DATE__ " " __TIME__ "\n\n" + "LZO special compilation options:\n" +#ifdef __cplusplus + " __cplusplus\n" +#endif +#if defined(__PIC__) + " __PIC__\n" +#elif defined(__pic__) + " __pic__\n" +#endif +#if (UINT_MAX < LZO_0xffffffffL) + " 16BIT\n" +#endif +#if defined(__LZO_STRICT_16BIT) + " __LZO_STRICT_16BIT\n" +#endif +#if (UINT_MAX > LZO_0xffffffffL) + " UINT_MAX=" _LZO_MEXPAND(UINT_MAX) "\n" +#endif +#if (ULONG_MAX > LZO_0xffffffffL) + " ULONG_MAX=" _LZO_MEXPAND(ULONG_MAX) "\n" +#endif +#if defined(LZO_BYTE_ORDER) + " LZO_BYTE_ORDER=" _LZO_MEXPAND(LZO_BYTE_ORDER) "\n" +#endif +#if defined(LZO_UNALIGNED_OK_2) + " LZO_UNALIGNED_OK_2\n" +#endif +#if defined(LZO_UNALIGNED_OK_4) + " LZO_UNALIGNED_OK_4\n" +#endif +#if defined(LZO_ALIGNED_OK_4) + " LZO_ALIGNED_OK_4\n" +#endif +#if defined(LZO_DICT_USE_PTR) + " LZO_DICT_USE_PTR\n" +#endif +#if defined(__LZO_QUERY_COMPRESS) + " __LZO_QUERY_COMPRESS\n" +#endif +#if defined(__LZO_QUERY_DECOMPRESS) + " __LZO_QUERY_DECOMPRESS\n" +#endif +#if defined(__LZO_IN_MINILZO) + " __LZO_IN_MINILZO\n" +#endif + "\n\n" + "$Id: LZO " LZO_VERSION_STRING " built " __DATE__ " " __TIME__ +#if defined(__GNUC__) && defined(__VERSION__) + " by gcc " __VERSION__ +#elif defined(__BORLANDC__) + " by Borland C " _LZO_MEXPAND(__BORLANDC__) +#elif defined(_MSC_VER) + " by Microsoft C " _LZO_MEXPAND(_MSC_VER) +#elif defined(__PUREC__) + " by Pure C " _LZO_MEXPAND(__PUREC__) +#elif defined(__SC__) + " by Symantec C " _LZO_MEXPAND(__SC__) +#elif defined(__TURBOC__) + " by Turbo C " _LZO_MEXPAND(__TURBOC__) +#elif defined(__WATCOMC__) + " by Watcom C " _LZO_MEXPAND(__WATCOMC__) +#endif + " $\n" + "$Copyright: LZO (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002 Markus Franz Xaver Johannes Oberhumer $\n"; +#endif + +LZO_PUBLIC(const lzo_byte *) +lzo_copyright(void) +{ + return __lzo_copyright; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return LZO_VERSION_STRING; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return LZO_VERSION_DATE; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1); +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2); +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4); +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8); + +LZO_PUBLIC(lzo_uint32) +lzo_adler32(lzo_uint32 adler, const lzo_byte *buf, lzo_uint len) +{ + lzo_uint32 s1 = adler & 0xffff; + lzo_uint32 s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (int) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +LZO_PUBLIC(int) +lzo_memcmp(const lzo_voidp s1, const lzo_voidp s2, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCMP) + return memcmp(s1,s2,len); +#else + const lzo_byte *p1 = (const lzo_byte *) s1; + const lzo_byte *p2 = (const lzo_byte *) s2; + int d; + + if (len > 0) do + { + d = *p1 - *p2; + if (d != 0) + return d; + p1++; + p2++; + } + while (--len > 0); + return 0; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memcpy(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMCPY) + return memcpy(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + do + *p1++ = *p2++; + while (--len > 0); + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memmove(lzo_voidp dest, const lzo_voidp src, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMMOVE) + return memmove(dest,src,len); +#else + lzo_byte *p1 = (lzo_byte *) dest; + const lzo_byte *p2 = (const lzo_byte *) src; + + if (len <= 0 || p1 == p2) + return dest; + + if (p1 < p2) + { + do + *p1++ = *p2++; + while (--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while (--len > 0); + } + return dest; +#endif +} + +LZO_PUBLIC(lzo_voidp) +lzo_memset(lzo_voidp s, int c, lzo_uint len) +{ +#if (LZO_UINT_MAX <= SIZE_T_MAX) && defined(HAVE_MEMSET) + return memset(s,c,len); +#else + lzo_byte *p = (lzo_byte *) s; + + if (len > 0) do + *p++ = LZO_BYTE(c); + while (--len > 0); + return s; +#endif +} + +#if 0 +# define IS_SIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) < 0) +# define IS_UNSIGNED(type) (((type) (1ul << (8 * sizeof(type) - 1))) > 0) +#else +# define IS_SIGNED(type) (((type) (-1)) < ((type) 0)) +# define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0)) +#endif + +#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +static lzo_bool schedule_insns_bug(void); +static lzo_bool strength_reduce_bug(int *); + +#if 0 || defined(LZO_DEBUG) +#include +static lzo_bool __lzo_assert_fail(const char *s, unsigned line) +{ +#if defined(__palmos__) + printf("LZO assertion failed in line %u: '%s'\n",line,s); +#else + fprintf(stderr,"LZO assertion failed in line %u: '%s'\n",line,s); +#endif + return 0; +} +# define __lzo_assert(x) ((x) ? 1 : __lzo_assert_fail(#x,__LINE__)) +#else +# define __lzo_assert(x) ((x) ? 1 : 0) +#endif + +#undef COMPILE_TIME_ASSERT +#if 0 +# define COMPILE_TIME_ASSERT(expr) r &= __lzo_assert(expr) +#else +# define COMPILE_TIME_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif + +static lzo_bool basic_integral_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(CHAR_BIT == 8); + COMPILE_TIME_ASSERT(sizeof(char) == 1); + COMPILE_TIME_ASSERT(sizeof(short) >= 2); + COMPILE_TIME_ASSERT(sizeof(long) >= 4); + COMPILE_TIME_ASSERT(sizeof(int) >= sizeof(short)); + COMPILE_TIME_ASSERT(sizeof(long) >= sizeof(int)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == sizeof(lzo_int)); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == sizeof(lzo_int32)); + + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) >= sizeof(unsigned)); +#if defined(__LZO_STRICT_16BIT) + COMPILE_TIME_ASSERT(sizeof(lzo_uint) == 2); +#else + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_uint) >= sizeof(unsigned)); +#endif + +#if (USHRT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(short) == 2); +#elif (USHRT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) == 4); +#elif (USHRT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(short) > 4); +#endif +#if (UINT_MAX == 65535u) + COMPILE_TIME_ASSERT(sizeof(int) == 2); +#elif (UINT_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) == 4); +#elif (UINT_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(int) > 4); +#endif +#if (ULONG_MAX == 65535ul) + COMPILE_TIME_ASSERT(sizeof(long) == 2); +#elif (ULONG_MAX == LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) == 4); +#elif (ULONG_MAX >= LZO_0xffffffffL) + COMPILE_TIME_ASSERT(sizeof(long) > 4); +#endif + +#if defined(SIZEOF_UNSIGNED) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED == sizeof(unsigned)); +#endif +#if defined(SIZEOF_UNSIGNED_LONG) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_LONG == sizeof(unsigned long)); +#endif +#if defined(SIZEOF_UNSIGNED_SHORT) + COMPILE_TIME_ASSERT(SIZEOF_UNSIGNED_SHORT == sizeof(unsigned short)); +#endif +#if !defined(__LZO_IN_MINILZO) +#if defined(SIZEOF_SIZE_T) + COMPILE_TIME_ASSERT(SIZEOF_SIZE_T == sizeof(size_t)); +#endif +#endif + + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned char)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned short)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(unsigned long)); + COMPILE_TIME_ASSERT(IS_SIGNED(short)); + COMPILE_TIME_ASSERT(IS_SIGNED(int)); + COMPILE_TIME_ASSERT(IS_SIGNED(long)); + + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint32)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_uint)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int32)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_int)); + + COMPILE_TIME_ASSERT(INT_MAX == LZO_STYPE_MAX(sizeof(int))); + COMPILE_TIME_ASSERT(UINT_MAX == LZO_UTYPE_MAX(sizeof(unsigned))); + COMPILE_TIME_ASSERT(LONG_MAX == LZO_STYPE_MAX(sizeof(long))); + COMPILE_TIME_ASSERT(ULONG_MAX == LZO_UTYPE_MAX(sizeof(unsigned long))); + COMPILE_TIME_ASSERT(SHRT_MAX == LZO_STYPE_MAX(sizeof(short))); + COMPILE_TIME_ASSERT(USHRT_MAX == LZO_UTYPE_MAX(sizeof(unsigned short))); + COMPILE_TIME_ASSERT(LZO_UINT32_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint32))); + COMPILE_TIME_ASSERT(LZO_UINT_MAX == LZO_UTYPE_MAX(sizeof(lzo_uint))); +#if !defined(__LZO_IN_MINILZO) + COMPILE_TIME_ASSERT(SIZE_T_MAX == LZO_UTYPE_MAX(sizeof(size_t))); +#endif + + r &= __lzo_assert(LZO_BYTE(257) == 1); + + return r; +} + +static lzo_bool basic_ptr_check(void) +{ + lzo_bool r = 1; + + COMPILE_TIME_ASSERT(sizeof(char *) >= sizeof(int)); + COMPILE_TIME_ASSERT(sizeof(lzo_byte *) >= sizeof(char *)); + + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_byte *)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_voidpp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) == sizeof(lzo_bytepp)); + COMPILE_TIME_ASSERT(sizeof(lzo_voidp) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_voidp)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) == sizeof(lzo_sptr_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptr_t) >= sizeof(lzo_uint)); + + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= 4); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(ptrdiff_t)); + + COMPILE_TIME_ASSERT(sizeof(ptrdiff_t) >= sizeof(size_t)); + COMPILE_TIME_ASSERT(sizeof(lzo_ptrdiff_t) >= sizeof(lzo_uint)); + +#if defined(SIZEOF_CHAR_P) + COMPILE_TIME_ASSERT(SIZEOF_CHAR_P == sizeof(char *)); +#endif +#if defined(SIZEOF_PTRDIFF_T) + COMPILE_TIME_ASSERT(SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)); +#endif + + COMPILE_TIME_ASSERT(IS_SIGNED(ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(size_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_ptrdiff_t)); + COMPILE_TIME_ASSERT(IS_SIGNED(lzo_sptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_ptr_t)); + COMPILE_TIME_ASSERT(IS_UNSIGNED(lzo_moff_t)); + + return r; +} + +static lzo_bool ptr_check(void) +{ + lzo_bool r = 1; + int i; + char _wrkmem[10 * sizeof(lzo_byte *) + sizeof(lzo_full_align_t)]; + lzo_bytep wrkmem; + lzo_bytepp dict; + unsigned char x[4 * sizeof(lzo_full_align_t)]; + long d; + lzo_full_align_t a; + lzo_full_align_t u; + + for (i = 0; i < (int) sizeof(x); i++) + x[i] = LZO_BYTE(i); + + wrkmem = LZO_PTR_ALIGN_UP((lzo_byte *)_wrkmem,sizeof(lzo_full_align_t)); + +#if 0 + dict = (lzo_bytepp) wrkmem; +#else + + u.a_lzo_bytep = wrkmem; dict = u.a_lzo_bytepp; +#endif + + d = (long) ((const lzo_bytep) dict - (const lzo_bytep) _wrkmem); + r &= __lzo_assert(d >= 0); + r &= __lzo_assert(d < (long) sizeof(lzo_full_align_t)); + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_lzo_voidp == NULL); + + memset(&a,0xff,sizeof(a)); + r &= __lzo_assert(a.a_ushort == USHRT_MAX); + r &= __lzo_assert(a.a_uint == UINT_MAX); + r &= __lzo_assert(a.a_ulong == ULONG_MAX); + r &= __lzo_assert(a.a_lzo_uint == LZO_UINT_MAX); + r &= __lzo_assert(a.a_lzo_uint32 == LZO_UINT32_MAX); + + if (r == 1) + { + for (i = 0; i < 8; i++) + r &= __lzo_assert((const lzo_voidp) (&dict[i]) == (const lzo_voidp) (&wrkmem[i * sizeof(lzo_byte *)])); + } + + memset(&a,0,sizeof(a)); + r &= __lzo_assert(a.a_char_p == NULL); + r &= __lzo_assert(a.a_lzo_bytep == NULL); + r &= __lzo_assert(NULL == (void *)0); + if (r == 1) + { + for (i = 0; i < 10; i++) + dict[i] = wrkmem; + BZERO8_PTR(dict+1,sizeof(dict[0]),8); + r &= __lzo_assert(dict[0] == wrkmem); + for (i = 1; i < 9; i++) + r &= __lzo_assert(dict[i] == NULL); + r &= __lzo_assert(dict[9] == wrkmem); + } + + if (r == 1) + { + unsigned k = 1; + const unsigned n = (unsigned) sizeof(lzo_uint32); + lzo_byte *p0; + lzo_byte *p1; + + k += __lzo_align_gap(&x[k],n); + p0 = (lzo_bytep) &x[k]; +#if defined(PTR_LINEAR) + r &= __lzo_assert((PTR_LINEAR(p0) & (n-1)) == 0); +#else + r &= __lzo_assert(n == 4); + r &= __lzo_assert(PTR_ALIGNED_4(p0)); +#endif + + r &= __lzo_assert(k >= 1); + p1 = (lzo_bytep) &x[1]; + r &= __lzo_assert(PTR_GE(p0,p1)); + + r &= __lzo_assert(k < 1+n); + p1 = (lzo_bytep) &x[1+n]; + r &= __lzo_assert(PTR_LT(p0,p1)); + + if (r == 1) + { + lzo_uint32 v0, v1; +#if 0 + v0 = * (lzo_uint32 *) &x[k]; + v1 = * (lzo_uint32 *) &x[k+n]; +#else + + u.a_uchar_p = &x[k]; + v0 = *u.a_lzo_uint32_p; + u.a_uchar_p = &x[k+n]; + v1 = *u.a_lzo_uint32_p; +#endif + r &= __lzo_assert(v0 > 0); + r &= __lzo_assert(v1 > 0); + } + } + + return r; +} + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ + lzo_bool r = 1; + int i; + union { + lzo_uint32 a; + unsigned short b; + lzo_uint32 aa[4]; + unsigned char x[4*sizeof(lzo_full_align_t)]; + } u; + + COMPILE_TIME_ASSERT( (int) ((unsigned char) ((signed char) -1)) == 255); + COMPILE_TIME_ASSERT( (((unsigned char)128) << (int)(8*sizeof(int)-8)) < 0); + +#if 0 + r &= __lzo_assert((const void *)&u == (const void *)&u.a); + r &= __lzo_assert((const void *)&u == (const void *)&u.b); + r &= __lzo_assert((const void *)&u == (const void *)&u.x[0]); + r &= __lzo_assert((const void *)&u == (const void *)&u.aa[0]); +#endif + + r &= basic_integral_check(); + r &= basic_ptr_check(); + if (r != 1) + return LZO_E_ERROR; + + u.a = 0; u.b = 0; + for (i = 0; i < (int) sizeof(u.x); i++) + u.x[i] = LZO_BYTE(i); + +#if defined(LZO_BYTE_ORDER) + if (r == 1) + { +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + lzo_uint32 a = (lzo_uint32) (u.a & LZO_0xffffffffL); + unsigned short b = (unsigned short) (u.b & 0xffff); + r &= __lzo_assert(a == 0x03020100L); + r &= __lzo_assert(b == 0x0100); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + lzo_uint32 a = u.a >> (8 * sizeof(u.a) - 32); + unsigned short b = u.b >> (8 * sizeof(u.b) - 16); + r &= __lzo_assert(a == 0x00010203L); + r &= __lzo_assert(b == 0x0001); +# else +# error "invalid LZO_BYTE_ORDER" +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_2) + COMPILE_TIME_ASSERT(sizeof(short) == 2); + if (r == 1) + { + unsigned short b[4]; + + for (i = 0; i < 4; i++) + b[i] = * (const unsigned short *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(b[0] == 0x0100); + r &= __lzo_assert(b[1] == 0x0201); + r &= __lzo_assert(b[2] == 0x0302); + r &= __lzo_assert(b[3] == 0x0403); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(b[0] == 0x0001); + r &= __lzo_assert(b[1] == 0x0102); + r &= __lzo_assert(b[2] == 0x0203); + r &= __lzo_assert(b[3] == 0x0304); +# endif + } +#endif + +#if defined(LZO_UNALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); + if (r == 1) + { + lzo_uint32 a[4]; + + for (i = 0; i < 4; i++) + a[i] = * (const lzo_uint32 *) &u.x[i]; + +# if (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + r &= __lzo_assert(a[0] == 0x03020100L); + r &= __lzo_assert(a[1] == 0x04030201L); + r &= __lzo_assert(a[2] == 0x05040302L); + r &= __lzo_assert(a[3] == 0x06050403L); +# elif (LZO_BYTE_ORDER == LZO_BIG_ENDIAN) + r &= __lzo_assert(a[0] == 0x00010203L); + r &= __lzo_assert(a[1] == 0x01020304L); + r &= __lzo_assert(a[2] == 0x02030405L); + r &= __lzo_assert(a[3] == 0x03040506L); +# endif + } +#endif + +#if defined(LZO_ALIGNED_OK_4) + COMPILE_TIME_ASSERT(sizeof(lzo_uint32) == 4); +#endif + + COMPILE_TIME_ASSERT(lzo_sizeof_dict_t == sizeof(lzo_dict_t)); + +#if defined(__LZO_IN_MINLZO) + if (r == 1) + { + lzo_uint32 adler; + adler = lzo_adler32(0, NULL, 0); + adler = lzo_adler32(adler, lzo_copyright(), 200); + r &= __lzo_assert(adler == 0xc76f1751L); + } +#endif + + if (r == 1) + { + r &= __lzo_assert(!schedule_insns_bug()); + } + + if (r == 1) + { + static int x[3]; + static unsigned xn = 3; + register unsigned j; + + for (j = 0; j < xn; j++) + x[j] = (int)j - 3; + r &= __lzo_assert(!strength_reduce_bug(x)); + } + + if (r == 1) + { + r &= ptr_check(); + } + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +static lzo_bool schedule_insns_bug(void) +{ +#if defined(__LZO_CHECKER) + return 0; +#else + const int clone[] = {1, 2, 0}; + const int *q; + q = clone; + return (*q) ? 0 : 1; +#endif +} + +static lzo_bool strength_reduce_bug(int *x) +{ + return x[0] != -3 || x[1] != -2 || x[2] != -1; +} + +#undef COMPILE_TIME_ASSERT + +int __lzo_init_done = 0; + +LZO_PUBLIC(int) +__lzo_init2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + + __lzo_init_done = 1; + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_compress_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +LZO_EXTERN(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7); + +LZO_PUBLIC(int) +__lzo_init(unsigned v,int s1,int s2,int s3,int s4,int s5,int s6,int s7) +{ + if (v == 0 || v > 0x1010) + return LZO_E_ERROR; + return __lzo_init2(v,s1,s2,s3,s4,s5,-1,-1,s6,s7); +} + +#endif + +#define do_compress _lzo1x_1_do_compress + +#define LZO_NEED_DICT_H +#define D_BITS 14 +#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#define LZO_EOF_CODE +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 8 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 8 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_uint32)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_uint32)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_uint32)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_uint32)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_uint32)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((0x9f5f * (dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +static void DVAL_ASSERT(lzo_uint32 dv, const lzo_byte *p) +{ + lzo_uint32 df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if defined(LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_uint) ((p)-(in))) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if defined(LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR( \ + (PTR_LT(m_pos,in) || \ + (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \ + m_off > max_offset) )) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + ((lzo_moff_t) ((ip)-(in)) <= m_off || \ + ((m_off = (lzo_moff_t) ((ip)-(in)) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if defined(LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define DO_COMPRESS lzo1x_1_compress + +static +lzo_uint do_compress ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *ip __asm__("%esi"); +#else + register const lzo_byte *ip; +#endif + lzo_byte *op; + const lzo_byte * const in_end = in + in_len; + const lzo_byte * const ip_end = in + in_len - M2_MAX_LEN - 5; + const lzo_byte *ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += 4; + for (;;) + { +#if 0 && defined(__GNUC__) && defined(__i386__) + register const lzo_byte *m_pos __asm__("%edi"); +#else + register const lzo_byte *m_pos; +#endif + lzo_moff_t m_off; + lzo_uint m_len; + lzo_uint dindex; + + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if 1 && defined(LZO_UNALIGNED_OK_2) + if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1]) +#endif + { + } + else + { + if (m_pos[2] == ip[2]) + { +#if 0 + if (m_off <= M2_MAX_OFFSET) + goto match; + if (lit <= 3) + goto match; + if (lit == 3) + { + assert(op - 2 > out); op[-2] |= LZO_BYTE(3); + *op++ = *ii++; *op++ = *ii++; *op++ = *ii++; + goto code_match; + } + if (m_pos[3] == ip[3]) +#endif + goto match; + } + else + { +#if 0 +#if 0 + if (m_off <= M1_MAX_OFFSET && lit > 0 && lit <= 3) +#else + if (m_off <= M1_MAX_OFFSET && lit == 3) +#endif + { + register lzo_uint t; + + t = lit; + assert(op - 2 > out); op[-2] |= LZO_BYTE(t); + do *op++ = *ii++; while (--t > 0); + assert(ii == ip); + m_off -= 1; + *op++ = LZO_BYTE(M1_MARKER | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); + ip += 2; + goto match_done; + } +#endif + } + } + +literal: + UPDATE_I(dict,0,dindex,ip,in); + ++ip; + if (ip >= ip_end) + break; + continue; + +match: + UPDATE_I(dict,0,dindex,ip,in); + if (pd(ip,ii) > 0) + { + register lzo_uint t = pd(ip,ii); + + if (t <= 3) + { + assert(op - 2 > out); + op[-2] |= LZO_BYTE(t); + } + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + register lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + assert(ii == ip); + ip += 3; + if (m_pos[3] != *ip++ || m_pos[4] != *ip++ || m_pos[5] != *ip++ || + m_pos[6] != *ip++ || m_pos[7] != *ip++ || m_pos[8] != *ip++ +#ifdef LZO1Y + || m_pos[ 9] != *ip++ || m_pos[10] != *ip++ || m_pos[11] != *ip++ + || m_pos[12] != *ip++ || m_pos[13] != *ip++ || m_pos[14] != *ip++ +#endif + ) + { + --ip; + m_len = ip - ii; + assert(m_len >= 3); assert(m_len <= M2_MAX_LEN); + + if (m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + goto m3_m4_offset; + } + else +#if defined(LZO1X) + { + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + goto m3_m4_offset; + } +#elif defined(LZO1Y) + goto m4_match; +#endif + } + else + { + { + const lzo_byte *end = in_end; + const lzo_byte *m = m_pos + M2_MAX_LEN + 1; + while (ip < end && *m == *ip) + m++, ip++; + m_len = (ip - ii); + } + assert(m_len > M2_MAX_LEN); + + if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= 33) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= 33; + *op++ = M3_MARKER | 0; + goto m3_m4_len; + } + } + else + { +#if defined(LZO1Y) +m4_match: +#endif + m_off -= 0x4000; + assert(m_off > 0); assert(m_off <= 0x7fff); + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | + ((m_off & 0x4000) >> 11) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off & 0x4000) >> 11)); +m3_m4_len: + while (m_len > 255) + { + m_len -= 255; + *op++ = 0; + } + assert(m_len > 0); + *op++ = LZO_BYTE(m_len); + } + } + +m3_m4_offset: + *op++ = LZO_BYTE((m_off & 63) << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + +#if 0 +match_done: +#endif + ii = ip; + if (ip >= ip_end) + break; + } + + *out_len = op - out; + return pd(in_end,ii); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + lzo_byte *op = out; + lzo_uint t; + +#if defined(__LZO_QUERY_COMPRESS) + if (__LZO_IS_COMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_COMPRESS(in,in_len,out,out_len,wrkmem,D_SIZE,lzo_sizeof(lzo_dict_t)); +#endif + + if (in_len <= M2_MAX_LEN + 5) + t = in_len; + else + { + t = do_compress(in,in_len,op,out_len,wrkmem); + op += *out_len; + } + + if (t > 0) + { + const lzo_byte *ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] |= LZO_BYTE(t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + *op++ = 0; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + do *op++ = *ii++; while (--t > 0); + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = op - out; + return LZO_E_OK; +} + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_DECOMPRESS_OVERRUN +#undef LZO_TEST_DECOMPRESS_OVERRUN_INPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT +#undef LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#define LZO_TEST_DECOMPRESS_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN) +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# define LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_LOOKBEHIND +#undef NEED_IP +#undef NEED_OP +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_INPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT) +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_DECOMPRESS_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +# define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun +#else +# define TEST_LOOKBEHIND(m_pos,op) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP +#else +# define TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP +#else +# define NEED_IP(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP +#else +# define NEED_OP(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP +#endif + +#undef __COPY4 +#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src) + +#undef COPY4 +#if defined(LZO_UNALIGNED_OK_4) +# define COPY4(dst,src) __COPY4(dst,src) +#elif defined(LZO_ALIGNED_OK_4) +# define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src)) +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_byte *in , lzo_uint in_len, + lzo_byte *out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + register lzo_byte *op; + register const lzo_byte *ip; + register lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_byte *dict_end; +#else + register const lzo_byte *m_pos; +#endif + + const lzo_byte * const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_byte * const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(__LZO_QUERY_DECOMPRESS) + if (__LZO_IS_DECOMPRESS_QUERY(in,in_len,out,out_len,wrkmem)) + return __LZO_QUERY_DECOMPRESS(in,in_len,out,out_len,wrkmem,0,0); +#endif + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (TEST_IP && TEST_OP) + { + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+4); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !defined(LZO_UNALIGNED_OK_4) + } + else +#endif +#endif +#if !defined(LZO_UNALIGNED_OK_4) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + while (TEST_IP && TEST_OP) + { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 31 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + NEED_IP(1); + while (*ip == 0) + { + t += 255; + ip++; + NEED_IP(1); + } + t += 7 + *ip++; + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif defined(LZO_UNALIGNED_OK_2) && (LZO_BYTE_ORDER == LZO_LITTLE_ENDIAN) + m_pos -= (* (const lzo_ushortp) ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = op - m_pos; +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LOOKBEHIND(m_pos,out); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LOOKBEHIND(m_pos,out); assert(t > 0); NEED_OP(t+3-1); +#if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4) +#if !defined(LZO_UNALIGNED_OK_4) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); NEED_OP(t); NEED_IP(t+1); + do *op++ = *ip++; while (--t > 0); + t = *ip++; + } + } + +#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) + *out_len = op - out; + return LZO_E_EOF_NOT_FOUND; +#endif + +eof_found: + assert(t == 1); + *out_len = op - out; + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = op - out; + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = op - out; + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_DECOMPRESS_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +/***** End of minilzo.c *****/ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h new file mode 100755 index 0000000..e3270f9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/minilzo.h @@ -0,0 +1,100 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer + Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library 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. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H +#define __MINILZO_H + +#define MINILZO_VERSION 0x1080 + +#ifdef __LZOCONF_H +# error "you cannot use both LZO and miniLZO" +#endif + +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_byte *src, lzo_uint src_len, + lzo_byte *dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h new file mode 100755 index 0000000..71370b5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/private.h @@ -0,0 +1,44 @@ +#ifndef RFB_PRIVATE_H +#define RFB_PRIVATE_H + +/* from cursor.c */ + +void rfbShowCursor(rfbClientPtr cl); +void rfbHideCursor(rfbClientPtr cl); +void rfbRedrawAfterHideCursor(rfbClientPtr cl,sraRegionPtr updateRegion); + +/* from main.c */ + +rfbClientPtr rfbClientIteratorHead(rfbClientIteratorPtr i); + +/* from tight.c */ + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG +extern void rfbTightCleanup(rfbScreenInfoPtr screen); +#endif + +/* from zlib.c */ +extern void rfbZlibCleanup(rfbScreenInfoPtr screen); + +/* from zrle.c */ +void rfbFreeZrleData(rfbClientPtr cl); + +#endif + + +/* from ultra.c */ + +extern void rfbUltraCleanup(rfbScreenInfoPtr screen); +extern void rfbFreeUltraData(rfbClientPtr cl); + +/* from rre.c */ + +extern void rfbRRECleanup(rfbScreenInfoPtr screen); + +/* from corre.c */ + +extern void rfbCoRRECleanup(rfbScreenInfoPtr screen); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c new file mode 100755 index 0000000..0ab8a12 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbregion.c @@ -0,0 +1,886 @@ +/* -=- sraRegion.c + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + * + * A general purpose region clipping library + * Only deals with rectangular regions, though. + */ + +#include +#include + +/* -=- Internal Span structure */ + +struct sraRegion; + +typedef struct sraSpan { + struct sraSpan *_next; + struct sraSpan *_prev; + int start; + int end; + struct sraRegion *subspan; +} sraSpan; + +typedef struct sraRegion { + sraSpan front; + sraSpan back; +} sraSpanList; + +/* -=- Span routines */ + +sraSpanList *sraSpanListDup(const sraSpanList *src); +void sraSpanListDestroy(sraSpanList *list); + +static sraSpan * +sraSpanCreate(int start, int end, const sraSpanList *subspan) { + sraSpan *item = (sraSpan*)malloc(sizeof(sraSpan)); + item->_next = item->_prev = NULL; + item->start = start; + item->end = end; + item->subspan = sraSpanListDup(subspan); + return item; +} + +static sraSpan * +sraSpanDup(const sraSpan *src) { + sraSpan *span; + if (!src) return NULL; + span = sraSpanCreate(src->start, src->end, src->subspan); + return span; +} + +static void +sraSpanInsertAfter(sraSpan *newspan, sraSpan *after) { + newspan->_next = after->_next; + newspan->_prev = after; + after->_next->_prev = newspan; + after->_next = newspan; +} + +static void +sraSpanInsertBefore(sraSpan *newspan, sraSpan *before) { + newspan->_next = before; + newspan->_prev = before->_prev; + before->_prev->_next = newspan; + before->_prev = newspan; +} + +static void +sraSpanRemove(sraSpan *span) { + span->_prev->_next = span->_next; + span->_next->_prev = span->_prev; +} + +static void +sraSpanDestroy(sraSpan *span) { + if (span->subspan) sraSpanListDestroy(span->subspan); + free(span); +} + +#ifdef DEBUG +static void +sraSpanCheck(const sraSpan *span, const char *text) { + /* Check the span is valid! */ + if (span->start == span->end) { + printf(text); + printf(":%d-%d\n", span->start, span->end); + } +} +#endif + +/* -=- SpanList routines */ + +static void sraSpanPrint(const sraSpan *s); + +static void +sraSpanListPrint(const sraSpanList *l) { + sraSpan *curr; + if (!l) { + printf("NULL"); + return; + } + curr = l->front._next; + printf("["); + while (curr != &(l->back)) { + sraSpanPrint(curr); + curr = curr->_next; + } + printf("]"); +} + +void +sraSpanPrint(const sraSpan *s) { + printf("(%d-%d)", (s->start), (s->end)); + if (s->subspan) + sraSpanListPrint(s->subspan); +} + +static sraSpanList * +sraSpanListCreate(void) { + sraSpanList *item = (sraSpanList*)malloc(sizeof(sraSpanList)); + item->front._next = &(item->back); + item->front._prev = NULL; + item->back._prev = &(item->front); + item->back._next = NULL; + return item; +} + +sraSpanList * +sraSpanListDup(const sraSpanList *src) { + sraSpanList *newlist; + sraSpan *newspan, *curr; + + if (!src) return NULL; + newlist = sraSpanListCreate(); + curr = src->front._next; + while (curr != &(src->back)) { + newspan = sraSpanDup(curr); + sraSpanInsertBefore(newspan, &(newlist->back)); + curr = curr->_next; + } + + return newlist; +} + +void +sraSpanListDestroy(sraSpanList *list) { + sraSpan *curr, *next; + while (list->front._next != &(list->back)) { + curr = list->front._next; + next = curr->_next; + sraSpanRemove(curr); + sraSpanDestroy(curr); + curr = next; + } + free(list); +} + +static void +sraSpanListMakeEmpty(sraSpanList *list) { + sraSpan *curr, *next; + while (list->front._next != &(list->back)) { + curr = list->front._next; + next = curr->_next; + sraSpanRemove(curr); + sraSpanDestroy(curr); + curr = next; + } + list->front._next = &(list->back); + list->front._prev = NULL; + list->back._prev = &(list->front); + list->back._next = NULL; +} + +static rfbBool +sraSpanListEqual(const sraSpanList *s1, const sraSpanList *s2) { + sraSpan *sp1, *sp2; + + if (!s1) { + if (!s2) { + return 1; + } else { + rfbErr("sraSpanListEqual:incompatible spans (only one NULL!)\n"); + return FALSE; + } + } + + sp1 = s1->front._next; + sp2 = s2->front._next; + while ((sp1 != &(s1->back)) && + (sp2 != &(s2->back))) { + if ((sp1->start != sp2->start) || + (sp1->end != sp2->end) || + (!sraSpanListEqual(sp1->subspan, sp2->subspan))) { + return 0; + } + sp1 = sp1->_next; + sp2 = sp2->_next; + } + + if ((sp1 == &(s1->back)) && (sp2 == &(s2->back))) { + return 1; + } else { + return 0; + } +} + +static rfbBool +sraSpanListEmpty(const sraSpanList *list) { + return (list->front._next == &(list->back)); +} + +static unsigned long +sraSpanListCount(const sraSpanList *list) { + sraSpan *curr = list->front._next; + unsigned long count = 0; + while (curr != &(list->back)) { + if (curr->subspan) { + count += sraSpanListCount(curr->subspan); + } else { + count += 1; + } + curr = curr->_next; + } + return count; +} + +static void +sraSpanMergePrevious(sraSpan *dest) { + sraSpan *prev = dest->_prev; + + while ((prev->_prev) && + (prev->end == dest->start) && + (sraSpanListEqual(prev->subspan, dest->subspan))) { + /* + printf("merge_prev:"); + sraSpanPrint(prev); + printf(" & "); + sraSpanPrint(dest); + printf("\n"); + */ + dest->start = prev->start; + sraSpanRemove(prev); + sraSpanDestroy(prev); + prev = dest->_prev; + } +} + +static void +sraSpanMergeNext(sraSpan *dest) { + sraSpan *next = dest->_next; + while ((next->_next) && + (next->start == dest->end) && + (sraSpanListEqual(next->subspan, dest->subspan))) { +/* + printf("merge_next:"); + sraSpanPrint(dest); + printf(" & "); + sraSpanPrint(next); + printf("\n"); + */ + dest->end = next->end; + sraSpanRemove(next); + sraSpanDestroy(next); + next = dest->_next; + } +} + +static void +sraSpanListOr(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr; + int s_start, s_end; + + if (!dest) { + if (!src) { + return; + } else { + rfbErr("sraSpanListOr:incompatible spans (only one NULL!)\n"); + return; + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + s_start = s_curr->start; + s_end = s_curr->end; + while (s_curr != &(src->back)) { + + /* - If we are at end of destination list OR + If the new span comes before the next destination one */ + if ((d_curr == &(dest->back)) || + (d_curr->start >= s_end)) { + /* - Add the span */ + sraSpanInsertBefore(sraSpanCreate(s_start, s_end, + s_curr->subspan), + d_curr); + if (d_curr != &(dest->back)) + sraSpanMergePrevious(d_curr); + s_curr = s_curr->_next; + s_start = s_curr->start; + s_end = s_curr->end; + } else { + + /* - If the new span overlaps the existing one */ + if ((s_start < d_curr->end) && + (s_end > d_curr->start)) { + + /* - Insert new span before the existing destination one? */ + if (s_start < d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(s_start, + d_curr->start, + s_curr->subspan), + d_curr); + sraSpanMergePrevious(d_curr); + } + + /* Split the existing span if necessary */ + if (s_end < d_curr->end) { + sraSpanInsertAfter(sraSpanCreate(s_end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_end; + } + if (s_start > d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(d_curr->start, + s_start, + d_curr->subspan), + d_curr); + d_curr->start = s_start; + } + + /* Recursively OR subspans */ + sraSpanListOr(d_curr->subspan, s_curr->subspan); + + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + if (d_curr->_next != &(dest->back)) + sraSpanMergeNext(d_curr); + + /* Move onto the next pair to compare */ + if (s_end > d_curr->end) { + s_start = d_curr->end; + d_curr = d_curr->_next; + } else { + s_curr = s_curr->_next; + s_start = s_curr->start; + s_end = s_curr->end; + } + } else { + /* - No overlap. Move to the next destination span */ + d_curr = d_curr->_next; + } + } + } +} + +static rfbBool +sraSpanListAnd(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr, *d_next; + + if (!dest) { + if (!src) { + return 1; + } else { + rfbErr("sraSpanListAnd:incompatible spans (only one NULL!)\n"); + return FALSE; + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { + + /* - If we haven't reached a destination span yet then move on */ + if (d_curr->start >= s_curr->end) { + s_curr = s_curr->_next; + continue; + } + + /* - If we are beyond the current destination span then remove it */ + if (d_curr->end <= s_curr->start) { + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + continue; + } + + /* - If we partially overlap a span then split it up or remove bits */ + if (s_curr->start > d_curr->start) { + /* - The top bit of the span does not match */ + d_curr->start = s_curr->start; + } + if (s_curr->end < d_curr->end) { + /* - The end of the span does not match */ + sraSpanInsertAfter(sraSpanCreate(s_curr->end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_curr->end; + } + + /* - Now recursively process the affected span */ + if (!sraSpanListAnd(d_curr->subspan, s_curr->subspan)) { + /* - The destination subspan is now empty, so we should remove it */ + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + } else { + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + + /* - Move on to the next span */ + d_next = d_curr; + if (s_curr->end >= d_curr->end) { + d_next = d_curr->_next; + } + if (s_curr->end <= d_curr->end) { + s_curr = s_curr->_next; + } + d_curr = d_next; + } + } + + while (d_curr != &(dest->back)) { + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr=next; + } + + return !sraSpanListEmpty(dest); +} + +static rfbBool +sraSpanListSubtract(sraSpanList *dest, const sraSpanList *src) { + sraSpan *d_curr, *s_curr; + + if (!dest) { + if (!src) { + return 1; + } else { + rfbErr("sraSpanListSubtract:incompatible spans (only one NULL!)\n"); + return FALSE; + } + } + + d_curr = dest->front._next; + s_curr = src->front._next; + while ((s_curr != &(src->back)) && (d_curr != &(dest->back))) { + + /* - If we haven't reached a destination span yet then move on */ + if (d_curr->start >= s_curr->end) { + s_curr = s_curr->_next; + continue; + } + + /* - If we are beyond the current destination span then skip it */ + if (d_curr->end <= s_curr->start) { + d_curr = d_curr->_next; + continue; + } + + /* - If we partially overlap the current span then split it up */ + if (s_curr->start > d_curr->start) { + sraSpanInsertBefore(sraSpanCreate(d_curr->start, + s_curr->start, + d_curr->subspan), + d_curr); + d_curr->start = s_curr->start; + } + if (s_curr->end < d_curr->end) { + sraSpanInsertAfter(sraSpanCreate(s_curr->end, + d_curr->end, + d_curr->subspan), + d_curr); + d_curr->end = s_curr->end; + } + + /* - Now recursively process the affected span */ + if ((!d_curr->subspan) || !sraSpanListSubtract(d_curr->subspan, s_curr->subspan)) { + /* - The destination subspan is now empty, so we should remove it */ + sraSpan *next = d_curr->_next; + sraSpanRemove(d_curr); + sraSpanDestroy(d_curr); + d_curr = next; + } else { + /* Merge this span with previous or next? */ + if (d_curr->_prev != &(dest->front)) + sraSpanMergePrevious(d_curr); + if (d_curr->_next != &(dest->back)) + sraSpanMergeNext(d_curr); + + /* - Move on to the next span */ + if (s_curr->end > d_curr->end) { + d_curr = d_curr->_next; + } else { + s_curr = s_curr->_next; + } + } + } + + return !sraSpanListEmpty(dest); +} + +/* -=- Region routines */ + +sraRegion * +sraRgnCreate(void) { + return (sraRegion*)sraSpanListCreate(); +} + +sraRegion * +sraRgnCreateRect(int x1, int y1, int x2, int y2) { + sraSpanList *vlist, *hlist; + sraSpan *vspan, *hspan; + + /* - Build the horizontal portion of the span */ + hlist = sraSpanListCreate(); + hspan = sraSpanCreate(x1, x2, NULL); + sraSpanInsertAfter(hspan, &(hlist->front)); + + /* - Build the vertical portion of the span */ + vlist = sraSpanListCreate(); + vspan = sraSpanCreate(y1, y2, hlist); + sraSpanInsertAfter(vspan, &(vlist->front)); + + sraSpanListDestroy(hlist); + + return (sraRegion*)vlist; +} + +sraRegion * +sraRgnCreateRgn(const sraRegion *src) { + return (sraRegion*)sraSpanListDup((sraSpanList*)src); +} + +void +sraRgnDestroy(sraRegion *rgn) { + sraSpanListDestroy((sraSpanList*)rgn); +} + +void +sraRgnMakeEmpty(sraRegion *rgn) { + sraSpanListMakeEmpty((sraSpanList*)rgn); +} + +/* -=- Boolean Region ops */ + +rfbBool +sraRgnAnd(sraRegion *dst, const sraRegion *src) { + return sraSpanListAnd((sraSpanList*)dst, (sraSpanList*)src); +} + +void +sraRgnOr(sraRegion *dst, const sraRegion *src) { + sraSpanListOr((sraSpanList*)dst, (sraSpanList*)src); +} + +rfbBool +sraRgnSubtract(sraRegion *dst, const sraRegion *src) { + return sraSpanListSubtract((sraSpanList*)dst, (sraSpanList*)src); +} + +void +sraRgnOffset(sraRegion *dst, int dx, int dy) { + sraSpan *vcurr, *hcurr; + + vcurr = ((sraSpanList*)dst)->front._next; + while (vcurr != &(((sraSpanList*)dst)->back)) { + vcurr->start += dy; + vcurr->end += dy; + + hcurr = vcurr->subspan->front._next; + while (hcurr != &(vcurr->subspan->back)) { + hcurr->start += dx; + hcurr->end += dx; + hcurr = hcurr->_next; + } + + vcurr = vcurr->_next; + } +} + +sraRegion *sraRgnBBox(const sraRegion *src) { + int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax; + sraSpan *vcurr, *hcurr; + + if(!src) + return sraRgnCreate(); + + vcurr = ((sraSpanList*)src)->front._next; + while (vcurr != &(((sraSpanList*)src)->back)) { + if(vcurr->startstart; + if(vcurr->end>ymax) + ymax=vcurr->end; + + hcurr = vcurr->subspan->front._next; + while (hcurr != &(vcurr->subspan->back)) { + if(hcurr->startstart; + if(hcurr->end>xmax) + xmax=hcurr->end; + hcurr = hcurr->_next; + } + + vcurr = vcurr->_next; + } + + if(xmaxback._prev; + vend = &(((sraSpanList*)rgn)->front); + } else { + vcurr = ((sraSpanList*)rgn)->front._next; + vend = &(((sraSpanList*)rgn)->back); + } + + if (vcurr != vend) { + rect->y1 = vcurr->start; + rect->y2 = vcurr->end; + + /* - Pick correct order */ + if (right2left) { + hcurr = vcurr->subspan->back._prev; + hend = &(vcurr->subspan->front); + } else { + hcurr = vcurr->subspan->front._next; + hend = &(vcurr->subspan->back); + } + + if (hcurr != hend) { + rect->x1 = hcurr->start; + rect->x2 = hcurr->end; + + sraSpanRemove(hcurr); + sraSpanDestroy(hcurr); + + if (sraSpanListEmpty(vcurr->subspan)) { + sraSpanRemove(vcurr); + sraSpanDestroy(vcurr); + } + +#if 0 + printf("poprect:(%dx%d)-(%dx%d)\n", + rect->x1, rect->y1, rect->x2, rect->y2); +#endif + return 1; + } + } + + return 0; +} + +unsigned long +sraRgnCountRects(const sraRegion *rgn) { + unsigned long count = sraSpanListCount((sraSpanList*)rgn); + return count; +} + +rfbBool +sraRgnEmpty(const sraRegion *rgn) { + return sraSpanListEmpty((sraSpanList*)rgn); +} + +/* iterator stuff */ +sraRectangleIterator *sraRgnGetIterator(sraRegion *s) +{ + /* these values have to be multiples of 4 */ +#define DEFSIZE 4 +#define DEFSTEP 8 + sraRectangleIterator *i = + (sraRectangleIterator*)malloc(sizeof(sraRectangleIterator)); + if(!i) + return NULL; + + /* we have to recurse eventually. So, the first sPtr is the pointer to + the sraSpan in the first level. the second sPtr is the pointer to + the sraRegion.back. The third and fourth sPtr are for the second + recursion level and so on. */ + i->sPtrs = (sraSpan**)malloc(sizeof(sraSpan*)*DEFSIZE); + if(!i->sPtrs) { + free(i); + return NULL; + } + i->ptrSize = DEFSIZE; + i->sPtrs[0] = &(s->front); + i->sPtrs[1] = &(s->back); + i->ptrPos = 0; + i->reverseX = 0; + i->reverseY = 0; + return i; +} + +sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY) +{ + sraRectangleIterator *i = sraRgnGetIterator(s); + if(reverseY) { + i->sPtrs[1] = &(s->front); + i->sPtrs[0] = &(s->back); + } + i->reverseX = reverseX; + i->reverseY = reverseY; + return(i); +} + +static rfbBool sraReverse(sraRectangleIterator *i) +{ + return( ((i->ptrPos&2) && i->reverseX) || + (!(i->ptrPos&2) && i->reverseY)); +} + +static sraSpan* sraNextSpan(sraRectangleIterator *i) +{ + if(sraReverse(i)) + return(i->sPtrs[i->ptrPos]->_prev); + else + return(i->sPtrs[i->ptrPos]->_next); +} + +rfbBool sraRgnIteratorNext(sraRectangleIterator* i,sraRect* r) +{ + /* is the subspan finished? */ + while(sraNextSpan(i) == i->sPtrs[i->ptrPos+1]) { + i->ptrPos -= 2; + if(i->ptrPos < 0) /* the end */ + return(0); + } + + i->sPtrs[i->ptrPos] = sraNextSpan(i); + + /* is this a new subspan? */ + while(i->sPtrs[i->ptrPos]->subspan) { + if(i->ptrPos+2 > i->ptrSize) { /* array is too small */ + i->ptrSize += DEFSTEP; + i->sPtrs = (sraSpan**)realloc(i->sPtrs, sizeof(sraSpan*)*i->ptrSize); + } + i->ptrPos =+ 2; + if(sraReverse(i)) { + i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->back._prev; + i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->front); + } else { + i->sPtrs[i->ptrPos] = i->sPtrs[i->ptrPos-2]->subspan->front._next; + i->sPtrs[i->ptrPos+1] = &(i->sPtrs[i->ptrPos-2]->subspan->back); + } + } + + if((i->ptrPos%4)!=2) { + rfbErr("sraRgnIteratorNext: offset is wrong (%d%%4!=2)\n",i->ptrPos); + return FALSE; + } + + r->y1 = i->sPtrs[i->ptrPos-2]->start; + r->y2 = i->sPtrs[i->ptrPos-2]->end; + r->x1 = i->sPtrs[i->ptrPos]->start; + r->x2 = i->sPtrs[i->ptrPos]->end; + + return(-1); +} + +void sraRgnReleaseIterator(sraRectangleIterator* i) +{ + free(i->sPtrs); + free(i); +} + +void +sraRgnPrint(const sraRegion *rgn) { + sraSpanListPrint((sraSpanList*)rgn); +} + +rfbBool +sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch) { + if (*x < cx) { + *w -= (cx-*x); + *x = cx; + } + if (*y < cy) { + *h -= (cy-*y); + *y = cy; + } + if (*x+*w > cx+cw) { + *w = (cx+cw)-*x; + } + if (*y+*h > cy+ch) { + *h = (cy+ch)-*y; + } + return (*w>0) && (*h>0); +} + +rfbBool +sraClipRect2(int *x, int *y, int *x2, int *y2, + int cx, int cy, int cx2, int cy2) { + if (*x < cx) + *x = cx; + if (*y < cy) + *y = cy; + if (*x >= cx2) + *x = cx2-1; + if (*y >= cy2) + *y = cy2-1; + if (*x2 <= cx) + *x2 = cx+1; + if (*y2 <= cy) + *y2 = cy+1; + if (*x2 > cx2) + *x2 = cx2; + if (*y2 > cy2) + *y2 = cy2; + return (*x2>*x) && (*y2>*y); +} + +/* test */ + +#ifdef SRA_TEST +/* pipe the output to sort|uniq -u and you'll get the errors. */ +int main(int argc, char** argv) +{ + sraRegionPtr region, region1, region2; + sraRectangleIterator* i; + sraRect rect; + rfbBool b; + + region = sraRgnCreateRect(10, 10, 600, 300); + region1 = sraRgnCreateRect(40, 50, 350, 200); + region2 = sraRgnCreateRect(0, 0, 20, 40); + + sraRgnPrint(region); + printf("\n[(10-300)[(10-600)]]\n\n"); + + b = sraRgnSubtract(region, region1); + printf("%s ",b?"true":"false"); + sraRgnPrint(region); + printf("\ntrue [(10-50)[(10-600)](50-200)[(10-40)(350-600)](200-300)[(10-600)]]\n\n"); + + sraRgnOr(region, region2); + printf("%ld\n6\n\n", sraRgnCountRects(region)); + + i = sraRgnGetIterator(region); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n20x10+0+0 600x30+0+10 590x10+10+40 30x150+10+50 250x150+350+50 590x100+10+200 \n\n"); + + i = sraRgnGetReverseIterator(region,1,0); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n20x10+0+0 600x30+0+10 590x10+10+40 250x150+350+50 30x150+10+50 590x100+10+200 \n\n"); + + i = sraRgnGetReverseIterator(region,1,1); + while(sraRgnIteratorNext(i, &rect)) + printf("%dx%d+%d+%d ", + rect.x2-rect.x1,rect.y2-rect.y1, + rect.x1,rect.y1); + sraRgnReleaseIterator(i); + printf("\n590x100+10+200 250x150+350+50 30x150+10+50 590x10+10+40 600x30+0+10 20x10+0+0 \n\n"); + + sraRgnDestroy(region); + sraRgnDestroy(region1); + sraRgnDestroy(region2); + + return(0); +} +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c new file mode 100755 index 0000000..9c8bb9d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rfbserver.c @@ -0,0 +1,3383 @@ +/* + * rfbserver.c - deal with server-side of the RFB protocol. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include "private.h" + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#ifdef WIN32 +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#endif +#endif + +#ifdef CORBA +#include +#endif + +#ifdef DEBUGPROTO +#undef DEBUGPROTO +#define DEBUGPROTO(x) x +#else +#define DEBUGPROTO(x) +#endif +#include +#include +/* stst() */ +#include +#include +#include +/* readdir() */ +#include +/* errno */ +#include +/* strftime() */ +#include + +#ifdef __MINGW32__ +static int compat_mkdir(const char *path, int mode) +{ + return mkdir(path); +} +#define mkdir compat_mkdir +#endif + +static void rfbProcessClientProtocolVersion(rfbClientPtr cl); +static void rfbProcessClientNormalMessage(rfbClientPtr cl); +static void rfbProcessClientInitMessage(rfbClientPtr cl); + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +void rfbIncrClientRef(rfbClientPtr cl) +{ + LOCK(cl->refCountMutex); + cl->refCount++; + UNLOCK(cl->refCountMutex); +} + +void rfbDecrClientRef(rfbClientPtr cl) +{ + LOCK(cl->refCountMutex); + cl->refCount--; + if(cl->refCount<=0) /* just to be sure also < 0 */ + TSIGNAL(cl->deleteCond); + UNLOCK(cl->refCountMutex); +} +#else +void rfbIncrClientRef(rfbClientPtr cl) {} +void rfbDecrClientRef(rfbClientPtr cl) {} +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +static MUTEX(rfbClientListMutex); +#endif + +struct rfbClientIterator { + rfbClientPtr next; + rfbScreenInfoPtr screen; + rfbBool closedToo; +}; + +void +rfbClientListInit(rfbScreenInfoPtr rfbScreen) +{ + if(sizeof(rfbBool)!=1) { + /* a sanity check */ + fprintf(stderr,"rfbBool's size is not 1 (%d)!\n",(int)sizeof(rfbBool)); + /* we cannot continue, because rfbBool is supposed to be char everywhere */ + exit(1); + } + rfbScreen->clientHead = NULL; + INIT_MUTEX(rfbClientListMutex); +} + +rfbClientIteratorPtr +rfbGetClientIterator(rfbScreenInfoPtr rfbScreen) +{ + rfbClientIteratorPtr i = + (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator)); + i->next = NULL; + i->screen = rfbScreen; + i->closedToo = FALSE; + return i; +} + +rfbClientIteratorPtr +rfbGetClientIteratorWithClosed(rfbScreenInfoPtr rfbScreen) +{ + rfbClientIteratorPtr i = + (rfbClientIteratorPtr)malloc(sizeof(struct rfbClientIterator)); + i->next = NULL; + i->screen = rfbScreen; + i->closedToo = TRUE; + return i; +} + +rfbClientPtr +rfbClientIteratorHead(rfbClientIteratorPtr i) +{ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(i->next != 0) { + rfbDecrClientRef(i->next); + rfbIncrClientRef(i->screen->clientHead); + } +#endif + LOCK(rfbClientListMutex); + i->next = i->screen->clientHead; + UNLOCK(rfbClientListMutex); + return i->next; +} + +rfbClientPtr +rfbClientIteratorNext(rfbClientIteratorPtr i) +{ + if(i->next == 0) { + LOCK(rfbClientListMutex); + i->next = i->screen->clientHead; + UNLOCK(rfbClientListMutex); + } else { + IF_PTHREADS(rfbClientPtr cl = i->next); + i->next = i->next->next; + IF_PTHREADS(rfbDecrClientRef(cl)); + } + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(!i->closedToo) + while(i->next && i->next->sock<0) + i->next = i->next->next; + if(i->next) + rfbIncrClientRef(i->next); +#endif + + return i->next; +} + +void +rfbReleaseClientIterator(rfbClientIteratorPtr iterator) +{ + IF_PTHREADS(if(iterator->next) rfbDecrClientRef(iterator->next)); + free(iterator); +} + + +/* + * rfbNewClientConnection is called from sockets.c when a new connection + * comes in. + */ + +void +rfbNewClientConnection(rfbScreenInfoPtr rfbScreen, + int sock) +{ + rfbClientPtr cl; + + cl = rfbNewClient(rfbScreen,sock); +#ifdef CORBA + if(cl!=NULL) + newConnection(cl, (KEYBOARD_DEVICE|POINTER_DEVICE),1,1,1); +#endif +} + + +/* + * rfbReverseConnection is called by the CORBA stuff to make an outward + * connection to a "listening" RFB client. + */ + +rfbClientPtr +rfbReverseConnection(rfbScreenInfoPtr rfbScreen, + char *host, + int port) +{ + int sock; + rfbClientPtr cl; + + if ((sock = rfbConnect(rfbScreen, host, port)) < 0) + return (rfbClientPtr)NULL; + + cl = rfbNewClient(rfbScreen, sock); + + if (cl) { + cl->reverseConnection = TRUE; + } + + return cl; +} + + +void +rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_) +{ + /* Permit the server to set the version to report */ + /* TODO: sanity checking */ + if ((major_==3) && (minor_ > 2 && minor_ < 9)) + { + rfbScreen->protocolMajorVersion = major_; + rfbScreen->protocolMinorVersion = minor_; + } + else + rfbLog("rfbSetProtocolVersion(%d,%d) set to invalid values\n", major_, minor_); +} + +/* + * rfbNewClient is called when a new connection has been made by whatever + * means. + */ + +static rfbClientPtr +rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen, + int sock, + rfbBool isUDP) +{ + rfbProtocolVersionMsg pv; + rfbClientIteratorPtr iterator; + rfbClientPtr cl,cl_; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(struct sockaddr_in); + rfbProtocolExtension* extension; + + cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1); + + cl->screen = rfbScreen; + cl->sock = sock; + cl->viewOnly = FALSE; + /* setup pseudo scaling */ + cl->scaledScreen = rfbScreen; + cl->scaledScreen->scaledScreenRefCount++; + + rfbResetStats(cl); + + cl->clientData = NULL; + cl->clientGoneHook = rfbDoNothingWithClient; + + if(isUDP) { + rfbLog(" accepted UDP client\n"); + } else { + int one=1; + + getpeername(sock, (struct sockaddr *)&addr, &addrlen); + cl->host = strdup(inet_ntoa(addr.sin_addr)); + + rfbLog(" other clients:\n"); + iterator = rfbGetClientIterator(rfbScreen); + while ((cl_ = rfbClientIteratorNext(iterator)) != NULL) { + rfbLog(" %s\n",cl_->host); + } + rfbReleaseClientIterator(iterator); + +#ifndef WIN32 + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl failed"); + close(sock); + return NULL; + } +#endif + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt failed"); + close(sock); + return NULL; + } + + FD_SET(sock,&(rfbScreen->allFds)); + rfbScreen->maxFd = max(sock,rfbScreen->maxFd); + + INIT_MUTEX(cl->outputMutex); + INIT_MUTEX(cl->refCountMutex); + INIT_MUTEX(cl->sendMutex); + INIT_COND(cl->deleteCond); + + cl->state = RFB_PROTOCOL_VERSION; + + cl->reverseConnection = FALSE; + cl->readyForSetColourMapEntries = FALSE; + cl->useCopyRect = FALSE; + cl->preferredEncoding = -1; + cl->correMaxWidth = 48; + cl->correMaxHeight = 48; +#ifdef LIBVNCSERVER_HAVE_LIBZ + cl->zrleData = NULL; +#endif + + cl->copyRegion = sraRgnCreate(); + cl->copyDX = 0; + cl->copyDY = 0; + + cl->modifiedRegion = + sraRgnCreateRect(0,0,rfbScreen->width,rfbScreen->height); + + INIT_MUTEX(cl->updateMutex); + INIT_COND(cl->updateCond); + + cl->requestedRegion = sraRgnCreate(); + + cl->format = cl->screen->serverFormat; + cl->translateFn = rfbTranslateNone; + cl->translateLookupTable = NULL; + + LOCK(rfbClientListMutex); + + IF_PTHREADS(cl->refCount = 0); + cl->next = rfbScreen->clientHead; + cl->prev = NULL; + if (rfbScreen->clientHead) + rfbScreen->clientHead->prev = cl; + + rfbScreen->clientHead = cl; + UNLOCK(rfbClientListMutex); + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + cl->webSockets = FALSE; + cl->webSocketsSSL = FALSE; + cl->webSocketsBase64 = FALSE; + cl->dblen= 0; + cl->carrylen = 0; +#endif + +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + cl->tightQualityLevel = -1; +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) + cl->tightCompressLevel = TIGHT_DEFAULT_COMPRESSION; +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + { + int i; + for (i = 0; i < 4; i++) + cl->zsActive[i] = FALSE; + } +#endif +#endif + + cl->fileTransfer.fd = -1; + + cl->enableCursorShapeUpdates = FALSE; + cl->enableCursorPosUpdates = FALSE; + cl->useRichCursorEncoding = FALSE; + cl->enableLastRectEncoding = FALSE; + cl->enableKeyboardLedState = FALSE; + cl->enableSupportedMessages = FALSE; + cl->enableSupportedEncodings = FALSE; + cl->enableServerIdentity = FALSE; + cl->lastKeyboardLedState = -1; + cl->cursorX = rfbScreen->cursorX; + cl->cursorY = rfbScreen->cursorY; + cl->useNewFBSize = FALSE; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + cl->compStreamInited = FALSE; + cl->compStream.total_in = 0; + cl->compStream.total_out = 0; + cl->compStream.zalloc = Z_NULL; + cl->compStream.zfree = Z_NULL; + cl->compStream.opaque = Z_NULL; + + cl->zlibCompressLevel = 5; +#endif + + cl->progressiveSliceY = 0; + + cl->extensions = NULL; + + cl->lastPtrX = -1; + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + /* + * Wait a few ms for the client to send one of: + * - Flash policy request + * - WebSockets connection (TLS/SSL or plain) + */ + + if (!webSocketsCheck(cl)) { + // Error reporting handled in webSocketsHandshake + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return NULL; + } + +#endif + + sprintf(pv,rfbProtocolVersionFormat,rfbScreen->protocolMajorVersion, + rfbScreen->protocolMinorVersion); + + if (rfbWriteExact(cl, pv, sz_rfbProtocolVersionMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return NULL; + } + } + + for(extension = rfbGetExtensionIterator(); extension; + extension=extension->next) { + void* data = NULL; + /* if the extension does not have a newClient method, it wants + * to be initialized later. */ + if(extension->newClient && extension->newClient(cl, &data)) + rfbEnableExtension(cl, extension, data); + } + rfbReleaseExtensionIterator(); + + printf("--------\n"); + switch (cl->screen->newClientHook(cl)) { + case RFB_CLIENT_ON_HOLD: + cl->onHold = TRUE; + break; + case RFB_CLIENT_ACCEPT: + cl->onHold = FALSE; + break; + case RFB_CLIENT_REFUSE: + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + cl = NULL; + break; + } + + return cl; +} + +rfbClientPtr +rfbNewClient(rfbScreenInfoPtr rfbScreen, + int sock) +{ + return(rfbNewTCPOrUDPClient(rfbScreen,sock,FALSE)); +} + +rfbClientPtr +rfbNewUDPClient(rfbScreenInfoPtr rfbScreen) +{ + return((rfbScreen->udpClient= + rfbNewTCPOrUDPClient(rfbScreen,rfbScreen->udpSock,TRUE))); +} + +/* + * rfbClientConnectionGone is called from sockets.c just after a connection + * has gone away. + */ + +void +rfbClientConnectionGone(rfbClientPtr cl) +{ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + int i; +#endif + + LOCK(rfbClientListMutex); + + if (cl->prev) + cl->prev->next = cl->next; + else + cl->screen->clientHead = cl->next; + if (cl->next) + cl->next->prev = cl->prev; + + if(cl->sock>=0) + close(cl->sock); + + if (cl->scaledScreen!=NULL) + cl->scaledScreen->scaledScreenRefCount--; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbFreeZrleData(cl); +#endif + + rfbFreeUltraData(cl); + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if(cl->screen->backgroundLoop != FALSE) { + int i; + do { + LOCK(cl->refCountMutex); + i=cl->refCount; + if(i>0) + WAIT(cl->deleteCond,cl->refCountMutex); + UNLOCK(cl->refCountMutex); + } while(i>0); + } +#endif + + UNLOCK(rfbClientListMutex); + + if(cl->sock>=0) + FD_CLR(cl->sock,&(cl->screen->allFds)); + + cl->clientGoneHook(cl); + + rfbLog("Client %s gone\n",cl->host); + free(cl->host); + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* Release the compression state structures if any. */ + if ( cl->compStreamInited ) { + deflateEnd( &(cl->compStream) ); + } + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + for (i = 0; i < 4; i++) { + if (cl->zsActive[i]) + deflateEnd(&cl->zsStruct[i]); + } +#endif +#endif + + if (cl->screen->pointerClient == cl) + cl->screen->pointerClient = NULL; + + sraRgnDestroy(cl->modifiedRegion); + sraRgnDestroy(cl->requestedRegion); + sraRgnDestroy(cl->copyRegion); + + if (cl->translateLookupTable) free(cl->translateLookupTable); + + TINI_COND(cl->updateCond); + TINI_MUTEX(cl->updateMutex); + + /* make sure outputMutex is unlocked before destroying */ + LOCK(cl->outputMutex); + UNLOCK(cl->outputMutex); + TINI_MUTEX(cl->outputMutex); + + LOCK(cl->sendMutex); + UNLOCK(cl->sendMutex); + TINI_MUTEX(cl->sendMutex); + +#ifdef CORBA + destroyConnection(cl); +#endif + + rfbPrintStats(cl); + + free(cl); +} + + +/* + * rfbProcessClientMessage is called when there is data to read from a client. + */ + +void +rfbProcessClientMessage(rfbClientPtr cl) +{ + switch (cl->state) { + case RFB_PROTOCOL_VERSION: + rfbProcessClientProtocolVersion(cl); + return; + case RFB_SECURITY_TYPE: + rfbProcessClientSecurityType(cl); + return; + case RFB_AUTHENTICATION: + rfbAuthProcessClientMessage(cl); + return; + case RFB_INITIALISATION: + rfbProcessClientInitMessage(cl); + return; + default: + rfbProcessClientNormalMessage(cl); + return; + } +} + + +/* + * rfbProcessClientProtocolVersion is called when the client sends its + * protocol version. + */ + +static void +rfbProcessClientProtocolVersion(rfbClientPtr cl) +{ + rfbProtocolVersionMsg pv; + int n, major_, minor_; + + if ((n = rfbReadExact(cl, pv, sz_rfbProtocolVersionMsg)) <= 0) { + if (n == 0) + rfbLog("rfbProcessClientProtocolVersion: client gone\n"); + else + rfbLogPerror("rfbProcessClientProtocolVersion: read"); + rfbCloseClient(cl); + return; + } + + pv[sz_rfbProtocolVersionMsg] = 0; + if (sscanf(pv,rfbProtocolVersionFormat,&major_,&minor_) != 2) { + char name[1024]; + if(sscanf(pv,"RFB %03d.%03d %1023s\n",&major_,&minor_,name) != 3) { + rfbErr("rfbProcessClientProtocolVersion: not a valid RFB client: %s\n", pv); + rfbCloseClient(cl); + return; + } + free(cl->host); + cl->host=strdup(name); + } + rfbLog("Client Protocol Version %d.%d\n", major_, minor_); + + if (major_ != rfbProtocolMajorVersion) { + rfbErr("RFB protocol version mismatch - server %d.%d, client %d.%d", + cl->screen->protocolMajorVersion, cl->screen->protocolMinorVersion, + major_,minor_); + rfbCloseClient(cl); + return; + } + + /* Check for the minor version use either of the two standard version of RFB */ + /* + * UltraVNC Viewer detects FileTransfer compatible servers via rfb versions + * 3.4, 3.6, 3.14, 3.16 + * It's a bad method, but it is what they use to enable features... + * maintaining RFB version compatibility across multiple servers is a pain + * Should use something like ServerIdentity encoding + */ + cl->protocolMajorVersion = major_; + cl->protocolMinorVersion = minor_; + + rfbLog("Protocol version sent %d.%d, using %d.%d\n", + major_, minor_, rfbProtocolMajorVersion, cl->protocolMinorVersion); + + rfbAuthNewClient(cl); +} + + +void +rfbClientSendString(rfbClientPtr cl, char *reason) +{ + char *buf; + int len = strlen(reason); + + rfbLog("rfbClientSendString(\"%s\")\n", reason); + + buf = (char *)malloc(4 + len); + ((uint32_t *)buf)[0] = Swap32IfLE(len); + memcpy(buf + 4, reason, len); + + if (rfbWriteExact(cl, buf, 4 + len) < 0) + rfbLogPerror("rfbClientSendString: write"); + free(buf); + + rfbCloseClient(cl); +} + +/* + * rfbClientConnFailed is called when a client connection has failed either + * because it talks the wrong protocol or it has failed authentication. + */ + +void +rfbClientConnFailed(rfbClientPtr cl, + char *reason) +{ + char *buf; + int len = strlen(reason); + + rfbLog("rfbClientConnFailed(\"%s\")\n", reason); + + buf = (char *)malloc(8 + len); + ((uint32_t *)buf)[0] = Swap32IfLE(rfbConnFailed); + ((uint32_t *)buf)[1] = Swap32IfLE(len); + memcpy(buf + 8, reason, len); + + if (rfbWriteExact(cl, buf, 8 + len) < 0) + rfbLogPerror("rfbClientConnFailed: write"); + free(buf); + + rfbCloseClient(cl); +} + + +/* + * rfbProcessClientInitMessage is called when the client sends its + * initialisation message. + */ + +static void +rfbProcessClientInitMessage(rfbClientPtr cl) +{ + rfbClientInitMsg ci; + union { + char buf[256]; + rfbServerInitMsg si; + } u; + int len, n; + rfbClientIteratorPtr iterator; + rfbClientPtr otherCl; + rfbExtensionData* extension; + + if ((n = rfbReadExact(cl, (char *)&ci,sz_rfbClientInitMsg)) <= 0) { + if (n == 0) + rfbLog("rfbProcessClientInitMessage: client gone\n"); + else + rfbLogPerror("rfbProcessClientInitMessage: read"); + rfbCloseClient(cl); + return; + } + + memset(u.buf,0,sizeof(u.buf)); + + u.si.framebufferWidth = Swap16IfLE(cl->screen->width); + u.si.framebufferHeight = Swap16IfLE(cl->screen->height); + u.si.format = cl->screen->serverFormat; + u.si.format.redMax = Swap16IfLE(u.si.format.redMax); + u.si.format.greenMax = Swap16IfLE(u.si.format.greenMax); + u.si.format.blueMax = Swap16IfLE(u.si.format.blueMax); + + strncpy(u.buf + sz_rfbServerInitMsg, cl->screen->desktopName, 127); + len = strlen(u.buf + sz_rfbServerInitMsg); + u.si.nameLength = Swap32IfLE(len); + + if (rfbWriteExact(cl, u.buf, sz_rfbServerInitMsg + len) < 0) { + rfbLogPerror("rfbProcessClientInitMessage: write"); + rfbCloseClient(cl); + return; + } + + for(extension = cl->extensions; extension;) { + rfbExtensionData* next = extension->next; + if(extension->extension->init && + !extension->extension->init(cl, extension->data)) + /* extension requested that it be removed */ + rfbDisableExtension(cl, extension->extension); + extension = next; + } + + cl->state = RFB_NORMAL; + + if (!cl->reverseConnection && + (cl->screen->neverShared || (!cl->screen->alwaysShared && !ci.shared))) { + + if (cl->screen->dontDisconnect) { + iterator = rfbGetClientIterator(cl->screen); + while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) { + if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { + rfbLog("-dontdisconnect: Not shared & existing client\n"); + rfbLog(" refusing new client %s\n", cl->host); + rfbCloseClient(cl); + rfbReleaseClientIterator(iterator); + return; + } + } + rfbReleaseClientIterator(iterator); + } else { + iterator = rfbGetClientIterator(cl->screen); + while ((otherCl = rfbClientIteratorNext(iterator)) != NULL) { + if ((otherCl != cl) && (otherCl->state == RFB_NORMAL)) { + rfbLog("Not shared - closing connection to client %s\n", + otherCl->host); + rfbCloseClient(otherCl); + } + } + rfbReleaseClientIterator(iterator); + } + } +} + +/* The values come in based on the scaled screen, we need to convert them to + * values based on the man screen's coordinate system + */ +static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t* h, + rfbClientPtr cl) +{ + int x1=Swap16IfLE(*x); + int y1=Swap16IfLE(*y); + int w1=Swap16IfLE(*w); + int h1=Swap16IfLE(*h); + + rfbScaledCorrection(cl->scaledScreen, cl->screen, &x1, &y1, &w1, &h1, "rectSwapIfLEAndClip"); + *x = x1; + *y = y1; + *w = w1; + *h = h1; + + if(*w>cl->screen->width-*x) + *w=cl->screen->width-*x; + /* possible underflow */ + if(*w>cl->screen->width-*x) + return FALSE; + if(*h>cl->screen->height-*y) + *h=cl->screen->height-*y; + if(*h>cl->screen->height-*y) + return FALSE; + + return TRUE; +} + +/* + * Send keyboard state (PointerPos pseudo-encoding). + */ + +rfbBool +rfbSendKeyboardLedState(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState); + rect.r.x = Swap16IfLE(cl->lastKeyboardLedState); + rect.r.y = 0; + rect.r.w = 0; + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingKeyboardLedState, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + + +#define rfbSetBit(buffer, position) (buffer[(position & 255) / 8] |= (1 << (position % 8))) + +/* + * Send rfbEncodingSupportedMessages. + */ + +rfbBool +rfbSendSupportedMessages(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + rfbSupportedMessages msgs; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + + sz_rfbSupportedMessages > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingSupportedMessages); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(sz_rfbSupportedMessages); + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + memset((char *)&msgs, 0, sz_rfbSupportedMessages); + rfbSetBit(msgs.client2server, rfbSetPixelFormat); + rfbSetBit(msgs.client2server, rfbFixColourMapEntries); + rfbSetBit(msgs.client2server, rfbSetEncodings); + rfbSetBit(msgs.client2server, rfbFramebufferUpdateRequest); + rfbSetBit(msgs.client2server, rfbKeyEvent); + rfbSetBit(msgs.client2server, rfbPointerEvent); + rfbSetBit(msgs.client2server, rfbClientCutText); + rfbSetBit(msgs.client2server, rfbFileTransfer); + rfbSetBit(msgs.client2server, rfbSetScale); + /*rfbSetBit(msgs.client2server, rfbSetServerInput); */ + /*rfbSetBit(msgs.client2server, rfbSetSW); */ + /*rfbSetBit(msgs.client2server, rfbTextChat); */ + /*rfbSetBit(msgs.client2server, rfbKeyFrameRequest); */ + rfbSetBit(msgs.client2server, rfbPalmVNCSetScaleFactor); + + rfbSetBit(msgs.server2client, rfbFramebufferUpdate); + rfbSetBit(msgs.server2client, rfbSetColourMapEntries); + rfbSetBit(msgs.server2client, rfbBell); + rfbSetBit(msgs.server2client, rfbServerCutText); + rfbSetBit(msgs.server2client, rfbResizeFrameBuffer); + /*rfbSetBit(msgs.server2client, rfbKeyFrameUpdate); */ + rfbSetBit(msgs.server2client, rfbPalmVNCReSizeFrameBuffer); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&msgs, sz_rfbSupportedMessages); + cl->ublen += sz_rfbSupportedMessages; + + rfbStatRecordEncodingSent(cl, rfbEncodingSupportedMessages, + sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages, + sz_rfbFramebufferUpdateRectHeader+sz_rfbSupportedMessages); + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + + + +/* + * Send rfbEncodingSupportedEncodings. + */ + +rfbBool +rfbSendSupportedEncodings(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + static uint32_t supported[] = { + rfbEncodingRaw, + rfbEncodingCopyRect, + rfbEncodingRRE, + rfbEncodingCoRRE, + rfbEncodingHextile, +#ifdef LIBVNCSERVER_HAVE_LIBZ + rfbEncodingZlib, + rfbEncodingZRLE, + rfbEncodingZYWRLE, +#endif +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + rfbEncodingTight, +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + rfbEncodingTightPng, +#endif + rfbEncodingUltra, + rfbEncodingUltraZip, + rfbEncodingXCursor, + rfbEncodingRichCursor, + rfbEncodingPointerPos, + rfbEncodingLastRect, + rfbEncodingNewFBSize, + rfbEncodingKeyboardLedState, + rfbEncodingSupportedMessages, + rfbEncodingSupportedEncodings, + rfbEncodingServerIdentity, + }; + uint32_t nEncodings = sizeof(supported) / sizeof(supported[0]), i; + + /* think rfbSetEncodingsMsg */ + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + + (nEncodings * sizeof(uint32_t)) > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingSupportedEncodings); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(nEncodings * sizeof(uint32_t)); + rect.r.h = Swap16IfLE(nEncodings); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + for (i = 0; i < nEncodings; i++) { + uint32_t encoding = Swap32IfLE(supported[i]); + memcpy(&cl->updateBuf[cl->ublen], (char *)&encoding, sizeof(encoding)); + cl->ublen += sizeof(encoding); + } + + rfbStatRecordEncodingSent(cl, rfbEncodingSupportedEncodings, + sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t)), + sz_rfbFramebufferUpdateRectHeader+(nEncodings * sizeof(uint32_t))); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + + +void +rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...) +{ + char buffer[256]; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buffer, sizeof(buffer)-1, fmt, ap); + va_end(ap); + + if (screen->versionString!=NULL) free(screen->versionString); + screen->versionString = strdup(buffer); +} + +/* + * Send rfbEncodingServerIdentity. + */ + +rfbBool +rfbSendServerIdentity(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + char buffer[512]; + + /* tack on our library version */ + snprintf(buffer,sizeof(buffer)-1, "%s (%s)", + (cl->screen->versionString==NULL ? "unknown" : cl->screen->versionString), + LIBVNCSERVER_PACKAGE_STRING); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + + (strlen(buffer)+1) > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingServerIdentity); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(strlen(buffer)+1); + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + memcpy(&cl->updateBuf[cl->ublen], buffer, strlen(buffer)+1); + cl->ublen += strlen(buffer)+1; + + rfbStatRecordEncodingSent(cl, rfbEncodingServerIdentity, + sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1, + sz_rfbFramebufferUpdateRectHeader+strlen(buffer)+1); + + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + +rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer) +{ + rfbTextChatMsg tc; + int bytesToSend=0; + + memset((char *)&tc, 0, sizeof(tc)); + tc.type = rfbTextChat; + tc.length = Swap32IfLE(length); + + switch(length) { + case rfbTextChatOpen: + case rfbTextChatClose: + case rfbTextChatFinished: + bytesToSend=0; + break; + default: + bytesToSend=length; + if (bytesToSend>rfbTextMaxSize) + bytesToSend=rfbTextMaxSize; + } + + if (cl->ublen + sz_rfbTextChatMsg + bytesToSend > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + memcpy(&cl->updateBuf[cl->ublen], (char *)&tc, sz_rfbTextChatMsg); + cl->ublen += sz_rfbTextChatMsg; + if (bytesToSend>0) { + memcpy(&cl->updateBuf[cl->ublen], buffer, bytesToSend); + cl->ublen += bytesToSend; + } + rfbStatRecordMessageSent(cl, rfbTextChat, sz_rfbTextChatMsg+bytesToSend, sz_rfbTextChatMsg+bytesToSend); + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + return TRUE; +} + +#define FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN(msg, cl, ret) \ + if ((cl->screen->getFileTransferPermission != NULL \ + && cl->screen->getFileTransferPermission(cl) != TRUE) \ + || cl->screen->permitFileTransfer != TRUE) { \ + rfbLog("%sUltra File Transfer is disabled, dropping client: %s\n", msg, cl->host); \ + rfbCloseClient(cl); \ + return ret; \ + } + +int DB = 1; + +rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer) +{ + rfbFileTransferMsg ft; + ft.type = rfbFileTransfer; + ft.contentType = contentType; + ft.contentParam = contentParam; + ft.pad = 0; /* UltraVNC did not Swap16LE(ft.contentParam) (Looks like it might be BigEndian) */ + ft.size = Swap32IfLE(size); + ft.length = Swap32IfLE(length); + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE); + /* + rfbLog("rfbSendFileTransferMessage( %dtype, %dparam, %dsize, %dlen, %p)\n", contentType, contentParam, size, length, buffer); + */ + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&ft, sz_rfbFileTransferMsg) < 0) { + rfbLogPerror("rfbSendFileTransferMessage: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + return FALSE; + } + + if (length>0) + { + if (rfbWriteExact(cl, buffer, length) < 0) { + rfbLogPerror("rfbSendFileTransferMessage: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + return FALSE; + } + } + UNLOCK(cl->sendMutex); + + rfbStatRecordMessageSent(cl, rfbFileTransfer, sz_rfbFileTransferMsg+length, sz_rfbFileTransferMsg+length); + + return TRUE; +} + + +/* + * UltraVNC uses Windows Structures + */ +#define MAX_PATH 260 + +typedef struct { + uint32_t dwLowDateTime; + uint32_t dwHighDateTime; +} RFB_FILETIME; + +typedef struct { + uint32_t dwFileAttributes; + RFB_FILETIME ftCreationTime; + RFB_FILETIME ftLastAccessTime; + RFB_FILETIME ftLastWriteTime; + uint32_t nFileSizeHigh; + uint32_t nFileSizeLow; + uint32_t dwReserved0; + uint32_t dwReserved1; + uint8_t cFileName[ MAX_PATH ]; + uint8_t cAlternateFileName[ 14 ]; +} RFB_FIND_DATA; + +#define RFB_FILE_ATTRIBUTE_READONLY 0x1 +#define RFB_FILE_ATTRIBUTE_HIDDEN 0x2 +#define RFB_FILE_ATTRIBUTE_SYSTEM 0x4 +#define RFB_FILE_ATTRIBUTE_DIRECTORY 0x10 +#define RFB_FILE_ATTRIBUTE_ARCHIVE 0x20 +#define RFB_FILE_ATTRIBUTE_NORMAL 0x80 +#define RFB_FILE_ATTRIBUTE_TEMPORARY 0x100 +#define RFB_FILE_ATTRIBUTE_COMPRESSED 0x800 + +rfbBool rfbFilenameTranslate2UNIX(rfbClientPtr cl, char *path, char *unixPath) +{ + int x; + char *home=NULL; + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, FALSE); + + /* C: */ + if (path[0]=='C' && path[1]==':') + strcpy(unixPath, &path[2]); + else + { + home = getenv("HOME"); + if (home!=NULL) + { + strcpy(unixPath, home); + strcat(unixPath,"/"); + strcat(unixPath, path); + } + else + strcpy(unixPath, path); + } + for (x=0;x\"%s\"\n",buffer, path); + + dirp=opendir(path); + if (dirp==NULL) + return rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, 0, NULL); + /* send back the path name (necessary for links) */ + if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, length, buffer)==FALSE) return FALSE; + for (direntp=readdir(dirp); direntp!=NULL; direntp=readdir(dirp)) + { + /* get stats */ + snprintf(retfilename,sizeof(retfilename),"%s/%s", path, direntp->d_name); + retval = stat(retfilename, &statbuf); + + if (retval==0) + { + memset((char *)&win32filename, 0, sizeof(win32filename)); + win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_NORMAL); + if (S_ISDIR(statbuf.st_mode)) + win32filename.dwFileAttributes = Swap32IfBE(RFB_FILE_ATTRIBUTE_DIRECTORY); + win32filename.ftCreationTime.dwLowDateTime = Swap32IfBE(statbuf.st_ctime); /* Intel Order */ + win32filename.ftCreationTime.dwHighDateTime = 0; + win32filename.ftLastAccessTime.dwLowDateTime = Swap32IfBE(statbuf.st_atime); /* Intel Order */ + win32filename.ftLastAccessTime.dwHighDateTime = 0; + win32filename.ftLastWriteTime.dwLowDateTime = Swap32IfBE(statbuf.st_mtime); /* Intel Order */ + win32filename.ftLastWriteTime.dwHighDateTime = 0; + win32filename.nFileSizeLow = Swap32IfBE(statbuf.st_size); /* Intel Order */ + win32filename.nFileSizeHigh = 0; + win32filename.dwReserved0 = 0; + win32filename.dwReserved1 = 0; + + /* If this had the full path, we would need to translate to DOS format ("C:\") */ + /* rfbFilenameTranslate2DOS(cl, retfilename, win32filename.cFileName); */ + strcpy((char *)win32filename.cFileName, direntp->d_name); + + /* Do not show hidden files (but show how to move up the tree) */ + if ((strcmp(direntp->d_name, "..")==0) || (direntp->d_name[0]!='.')) + { + nOptLen = sizeof(RFB_FIND_DATA) - MAX_PATH - 14 + strlen((char *)win32filename.cFileName); + /* + rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent: Sending \"%s\"\n", (char *)win32filename.cFileName); + */ + if (rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADirectory, 0, nOptLen, (char *)&win32filename)==FALSE) return FALSE; + } + } + } + closedir(dirp); + /* End of the transfer */ + return rfbSendFileTransferMessage(cl, rfbDirPacket, 0, 0, 0, NULL); +} + + +char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length) +{ + char *buffer=NULL; + int n=0; + + FILEXFER_ALLOWED_OR_CLOSE_AND_RETURN("", cl, NULL); + /* + rfbLog("rfbProcessFileTransferReadBuffer(%dlen)\n", length); + */ + if (length>0) { + buffer=malloc(length+1); + if (buffer!=NULL) { + if ((n = rfbReadExact(cl, (char *)buffer, length)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessFileTransferReadBuffer: read"); + rfbCloseClient(cl); + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return NULL; + } + /* Null Terminate */ + buffer[length]=0; + } + } + return buffer; +} + + +rfbBool rfbSendFileTransferChunk(rfbClientPtr cl) +{ + /* Allocate buffer for compression */ + unsigned char readBuf[sz_rfbBlockSize]; + int bytesRead=0; + int retval=0; + fd_set wfds; + struct timeval tv; + int n; +#ifdef LIBVNCSERVER_HAVE_LIBZ + unsigned char compBuf[sz_rfbBlockSize + 1024]; + unsigned long nMaxCompSize = sizeof(compBuf); + int nRetC = 0; +#endif + + /* + * Don't close the client if we get into this one because + * it is called from many places to service file transfers. + * Note that permitFileTransfer is checked first. + */ + if (cl->screen->permitFileTransfer != TRUE || + (cl->screen->getFileTransferPermission != NULL + && cl->screen->getFileTransferPermission(cl) != TRUE)) { + return TRUE; + } + + /* If not sending, or no file open... Return as if we sent something! */ + if ((cl->fileTransfer.fd!=-1) && (cl->fileTransfer.sending==1)) + { + FD_ZERO(&wfds); + FD_SET(cl->sock, &wfds); + + /* return immediately */ + tv.tv_sec = 0; + tv.tv_usec = 0; + n = select(cl->sock + 1, NULL, &wfds, NULL, &tv); + + if (n<0) { + rfbLog("rfbSendFileTransferChunk() select failed: %s\n", strerror(errno)); + } + /* We have space on the transmit queue */ + if (n > 0) + { + bytesRead = read(cl->fileTransfer.fd, readBuf, sz_rfbBlockSize); + switch (bytesRead) { + case 0: + /* + rfbLog("rfbSendFileTransferChunk(): End-Of-File Encountered\n"); + */ + retval = rfbSendFileTransferMessage(cl, rfbEndOfFile, 0, 0, 0, NULL); + close(cl->fileTransfer.fd); + cl->fileTransfer.fd = -1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + return retval; + case -1: + /* TODO : send an error msg to the client... */ + rfbLog("rfbSendFileTransferChunk(): %s\n",strerror(errno)); + retval = rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, 0, 0, NULL); + close(cl->fileTransfer.fd); + cl->fileTransfer.fd = -1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + return retval; + default: + /* + rfbLog("rfbSendFileTransferChunk(): Read %d bytes\n", bytesRead); + */ + if (!cl->fileTransfer.compressionEnabled) + return rfbSendFileTransferMessage(cl, rfbFilePacket, 0, 0, bytesRead, (char *)readBuf); + else + { +#ifdef LIBVNCSERVER_HAVE_LIBZ + nRetC = compress(compBuf, &nMaxCompSize, readBuf, bytesRead); + /* + rfbLog("Compressed the packet from %d -> %d bytes\n", nMaxCompSize, bytesRead); + */ + + if ((nRetC==0) && (nMaxCompSizeD:\....Z:\ + * + * We replace the "\" char following the drive letter and ":" + * with a char corresponding to the type of drive + * We obtain something like "C:lD:c....Z:n\" + * Isn't it ugly ? + * DRIVE_FIXED = 'l' (local?) + * DRIVE_REMOVABLE = 'f' (floppy?) + * DRIVE_CDROM = 'c' + * DRIVE_REMOTE = 'n' + */ + + /* in unix, there are no 'drives' (We could list mount points though) + * We fake the root as a "C:" for the Winblows users + */ + filename2[0]='C'; + filename2[1]=':'; + filename2[2]='l'; + filename2[3]=0; + filename2[4]=0; + retval = rfbSendFileTransferMessage(cl, rfbDirPacket, rfbADrivesList, 0, 5, filename2); + if (buffer!=NULL) free(buffer); + return retval; + break; + case rfbRDirContent: /* Client requests the content of a directory */ + /* + rfbLog("rfbProcessFileTransfer() rfbDirContentRequest: rfbRDirContent\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + retval = rfbSendDirContent(cl, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + } + break; + + case rfbDirPacket: + rfbLog("rfbProcessFileTransfer() rfbDirPacket\n"); + break; + case rfbFileAcceptHeader: + rfbLog("rfbProcessFileTransfer() rfbFileAcceptHeader\n"); + break; + case rfbCommandReturn: + rfbLog("rfbProcessFileTransfer() rfbCommandReturn\n"); + break; + case rfbFileChecksums: + /* Destination file already exists - the viewer sends the checksums */ + rfbLog("rfbProcessFileTransfer() rfbFileChecksums\n"); + break; + case rfbFileTransferAccess: + rfbLog("rfbProcessFileTransfer() rfbFileTransferAccess\n"); + break; + + /* + * sending from the server to the viewer + */ + + case rfbFileTransferRequest: + /* + rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest:\n"); + */ + /* add some space to the end of the buffer as we will be adding a timespec to it */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + /* The client requests a File */ + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + cl->fileTransfer.fd=open(filename1, O_RDONLY, 0744); + + /* + */ + if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\") Open: %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), cl->fileTransfer.fd); + + if (cl->fileTransfer.fd!=-1) { + if (fstat(cl->fileTransfer.fd, &statbuf)!=0) { + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + } + else + { + /* Add the File Time Stamp to the filename */ + strftime(timespec, sizeof(timespec), "%m/%d/%Y %H:%M",gmtime(&statbuf.st_ctime)); + buffer=realloc(buffer, length + strlen(timespec) + 2); /* comma, and Null term */ + if (buffer==NULL) { + rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest: Failed to malloc %d bytes\n", length + strlen(timespec) + 2); + return FALSE; + } + strcat(buffer,","); + strcat(buffer, timespec); + length = strlen(buffer); + if (DB) rfbLog("rfbProcessFileTransfer() buffer is now: \"%s\"\n", buffer); + } + } + + /* The viewer supports compression if size==1 */ + cl->fileTransfer.compressionEnabled = (size==1); + + /* + rfbLog("rfbProcessFileTransfer() rfbFileTransferRequest(\"%s\"->\"%s\")%s\n", buffer, filename1, (size==1?" ":"")); + */ + + /* File Size in bytes, 0xFFFFFFFF (-1) means error */ + retval = rfbSendFileTransferMessage(cl, rfbFileHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : statbuf.st_size), length, buffer); + + if (cl->fileTransfer.fd==-1) + { + if (buffer!=NULL) free(buffer); + return retval; + } + /* setup filetransfer stuff */ + cl->fileTransfer.fileSize = statbuf.st_size; + cl->fileTransfer.numPackets = statbuf.st_size / sz_rfbBlockSize; + cl->fileTransfer.receiving = 0; + cl->fileTransfer.sending = 0; /* set when we receive a rfbFileHeader: */ + + /* TODO: finish 64-bit file size support */ + sizeHtmp = 0; + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&sizeHtmp, 4) < 0) { + rfbLogPerror("rfbProcessFileTransfer: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + if (buffer!=NULL) free(buffer); + return FALSE; + } + UNLOCK(cl->sendMutex); + break; + + case rfbFileHeader: + /* Destination file (viewer side) is ready for reception (size > 0) or not (size = -1) */ + if (size==-1) { + rfbLog("rfbProcessFileTransfer() rfbFileHeader (error, aborting)\n"); + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + return TRUE; + } + + /* + rfbLog("rfbProcessFileTransfer() rfbFileHeader (%d bytes of a file)\n", size); + */ + + /* Starts the transfer! */ + cl->fileTransfer.sending=1; + return rfbSendFileTransferChunk(cl); + break; + + + /* + * sending from the viewer to the server + */ + + case rfbFileTransferOffer: + /* client is sending a file to us */ + /* buffer contains full path name (plus FileTime) */ + /* size contains size of the file */ + /* + rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer:\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + + /* Parse the FileTime */ + p = strrchr(buffer, ','); + if (p!=NULL) { + *p = '\0'; + strcpy(szFileTime, p+1); + } else + szFileTime[0]=0; + + + + /* Need to read in sizeHtmp */ + if ((n = rfbReadExact(cl, (char *)&sizeHtmp, 4)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessFileTransfer: read sizeHtmp"); + rfbCloseClient(cl); + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return FALSE; + } + sizeHtmp = Swap32IfLE(sizeHtmp); + + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + + /* If the file exists... We can send a rfbFileChecksums back to the client before we send an rfbFileAcceptHeader */ + /* TODO: Delta Transfer */ + + cl->fileTransfer.fd=open(filename1, O_CREAT|O_WRONLY|O_TRUNC, 0744); + if (DB) rfbLog("rfbProcessFileTransfer() rfbFileTransferOffer(\"%s\"->\"%s\") %s %s fd=%d\n", buffer, filename1, (cl->fileTransfer.fd==-1?"Failed":"Success"), (cl->fileTransfer.fd==-1?strerror(errno):""), cl->fileTransfer.fd); + /* + */ + + /* File Size in bytes, 0xFFFFFFFF (-1) means error */ + retval = rfbSendFileTransferMessage(cl, rfbFileAcceptHeader, 0, (cl->fileTransfer.fd==-1 ? -1 : 0), length, buffer); + if (cl->fileTransfer.fd==-1) { + free(buffer); + return retval; + } + + /* setup filetransfer stuff */ + cl->fileTransfer.fileSize = size; + cl->fileTransfer.numPackets = size / sz_rfbBlockSize; + cl->fileTransfer.receiving = 1; + cl->fileTransfer.sending = 0; + break; + + case rfbFilePacket: + /* + rfbLog("rfbProcessFileTransfer() rfbFilePacket:\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + if (cl->fileTransfer.fd!=-1) { + /* buffer contains the contents of the file */ + if (size==0) + retval=write(cl->fileTransfer.fd, buffer, length); + else + { +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* compressed packet */ + nRet = uncompress(compBuff,&nRawBytes,(const unsigned char*)buffer, length); + retval=write(cl->fileTransfer.fd, compBuff, nRawBytes); +#else + /* Write the file out as received... */ + retval=write(cl->fileTransfer.fd, buffer, length); +#endif + } + if (retval==-1) + { + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + } + } + break; + + case rfbEndOfFile: + if (DB) rfbLog("rfbProcessFileTransfer() rfbEndOfFile\n"); + /* + */ + if (cl->fileTransfer.fd!=-1) + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + break; + + case rfbAbortFileTransfer: + if (DB) rfbLog("rfbProcessFileTransfer() rfbAbortFileTransfer\n"); + /* + */ + if (cl->fileTransfer.fd!=-1) + { + close(cl->fileTransfer.fd); + cl->fileTransfer.fd=-1; + cl->fileTransfer.sending = 0; + cl->fileTransfer.receiving = 0; + } + else + { + /* We use this message for FileTransfer rights (<=RC18 versions) + * The client asks for FileTransfer permission + */ + if (contentParam == 0) + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED! (Client Version <=RC18)\n"); + /* Old method for FileTransfer handshake perimssion (<=RC18) (Deny it)*/ + return rfbSendFileTransferMessage(cl, rfbAbortFileTransfer, 0, -1, 0, ""); + } + /* New method is allowed */ + if (cl->screen->getFileTransferPermission!=NULL) + { + if (cl->screen->getFileTransferPermission(cl)==TRUE) + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */ + } + else + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* Deny */ + } + } + else + { + if (cl->screen->permitFileTransfer) + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission Granted!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, 1 , 0, ""); /* Permit */ + } + else + { + rfbLog("rfbProcessFileTransfer() File Transfer Permission DENIED by default!\n"); + return rfbSendFileTransferMessage(cl, rfbFileTransferAccess, 0, -1 , 0, ""); /* DEFAULT: DENY (for security) */ + } + + } + } + break; + + + case rfbCommand: + /* + rfbLog("rfbProcessFileTransfer() rfbCommand:\n"); + */ + if ((buffer = rfbProcessFileTransferReadBuffer(cl, length))==NULL) return FALSE; + switch (contentParam) { + case rfbCDirCreate: /* Client requests the creation of a directory */ + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + retval = mkdir(filename1, 0755); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCDirCreate(\"%s\"->\"%s\") %s\n", buffer, filename1, (retval==-1?"Failed":"Success")); + /* + */ + retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbADirCreate, retval, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + case rfbCFileDelete: /* Client requests the deletion of a file */ + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + if (stat(filename1,&statbuf)==0) + { + if (S_ISDIR(statbuf.st_mode)) + retval = rmdir(filename1); + else + retval = unlink(filename1); + } + else retval=-1; + retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileDelete, retval, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + case rfbCFileRename: /* Client requests the Renaming of a file/directory */ + p = strrchr(buffer, '*'); + if (p != NULL) + { + /* Split into 2 filenames ('*' is a seperator) */ + *p = '\0'; + rfbFilenameTranslate2UNIX(cl, buffer, filename1); + rfbFilenameTranslate2UNIX(cl, p+1, filename2); + retval = rename(filename1,filename2); + if (DB) rfbLog("rfbProcessFileTransfer() rfbCommand: rfbCFileRename(\"%s\"->\"%s\" -->> \"%s\"->\"%s\") %s\n", buffer, filename1, p+1, filename2, (retval==-1?"Failed":"Success")); + /* + */ + /* Restore the buffer so the reply is good */ + *p = '*'; + retval = rfbSendFileTransferMessage(cl, rfbCommandReturn, rfbAFileRename, retval, length, buffer); + if (buffer!=NULL) free(buffer); + return retval; + } + break; + } + + break; + } + + /* NOTE: don't forget to free(buffer) if you return early! */ + if (buffer!=NULL) free(buffer); + return TRUE; +} + +/* + * rfbProcessClientNormalMessage is called when the client has sent a normal + * protocol message. + */ + +static void +rfbProcessClientNormalMessage(rfbClientPtr cl) +{ + + int n=0; + rfbClientToServerMsg msg; + char *str; + int i; + uint32_t enc=0; + uint32_t lastPreferredEncoding = -1; + char encBuf[64]; + char encBuf2[64]; + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->webSockets) { + + if (cl->ssl) + n = SSL_peek(cl->ssl, encBuf, 4); + else + n = recv(cl->sock, encBuf, 4, MSG_PEEK); + + if (cl->webSocketsBase64) { + /* With Base64 encoding we need at least 4 bytes */ + if ((n > 0) && (n < 4)) { + if (encBuf[0] == '\xff') { + /* Make sure we don't miss a client disconnect on an end frame + * marker */ + if (cl->ssl) + n = SSL_read(cl->ssl, encBuf, 1); + else + n = read(cl->sock, encBuf, 1); + } + return; + } + } else { + /* With UTF-8 encoding we need at least 3 bytes (framing + 1) */ + if ((n == 1) || (n == 2)) { + if (encBuf[0] == '\xff') { + /* Make sure we don't miss a client disconnect on an end frame + * marker */ + if (cl->ssl) + n = SSL_read(cl->ssl, encBuf, 1); + else + n = read(cl->sock, encBuf, 1); + } + return; + } + } + } +#endif + + if ((n = rfbReadExact(cl, (char *)&msg, 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + switch (msg.type) { + + case rfbSetPixelFormat: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetPixelFormatMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + cl->format.bitsPerPixel = msg.spf.format.bitsPerPixel; + cl->format.depth = msg.spf.format.depth; + cl->format.bigEndian = (msg.spf.format.bigEndian ? TRUE : FALSE); + cl->format.trueColour = (msg.spf.format.trueColour ? TRUE : FALSE); + cl->format.redMax = Swap16IfLE(msg.spf.format.redMax); + cl->format.greenMax = Swap16IfLE(msg.spf.format.greenMax); + cl->format.blueMax = Swap16IfLE(msg.spf.format.blueMax); + cl->format.redShift = msg.spf.format.redShift; + cl->format.greenShift = msg.spf.format.greenShift; + cl->format.blueShift = msg.spf.format.blueShift; + + cl->readyForSetColourMapEntries = TRUE; + cl->screen->setTranslateFunction(cl); + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg); + + return; + + + case rfbFixColourMapEntries: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbFixColourMapEntriesMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetPixelFormatMsg, sz_rfbSetPixelFormatMsg); + rfbLog("rfbProcessClientNormalMessage: %s", + "FixColourMapEntries unsupported\n"); + rfbCloseClient(cl); + return; + + + /* NOTE: Some clients send us a set of encodings (ie: PointerPos) designed to enable/disable features... + * We may want to look into this... + * Example: + * case rfbEncodingXCursor: + * cl->enableCursorShapeUpdates = TRUE; + * + * Currently: cl->enableCursorShapeUpdates can *never* be turned off... + */ + case rfbSetEncodings: + { + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetEncodingsMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + msg.se.nEncodings = Swap16IfLE(msg.se.nEncodings); + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4),sz_rfbSetEncodingsMsg+(msg.se.nEncodings*4)); + + /* + * UltraVNC Client has the ability to adapt to changing network environments + * So, let's give it a change to tell us what it wants now! + */ + if (cl->preferredEncoding!=-1) + lastPreferredEncoding = cl->preferredEncoding; + + /* Reset all flags to defaults (allows us to switch between PointerPos and Server Drawn Cursors) */ + cl->preferredEncoding=-1; + cl->useCopyRect = FALSE; + cl->useNewFBSize = FALSE; + cl->cursorWasChanged = FALSE; + cl->useRichCursorEncoding = FALSE; + cl->enableCursorPosUpdates = FALSE; + cl->enableCursorShapeUpdates = FALSE; + cl->enableCursorShapeUpdates = FALSE; + cl->enableLastRectEncoding = FALSE; + cl->enableKeyboardLedState = FALSE; + cl->enableSupportedMessages = FALSE; + cl->enableSupportedEncodings = FALSE; + cl->enableServerIdentity = FALSE; + + +int j; + for (j = 0; j < msg.se.nEncodings; j++) { + + if ((n = rfbReadExact(cl, (char *)&enc, 4)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + printf("close\n"); + rfbCloseClient(cl); + return; + } + enc = Swap32IfLE(enc); + + + switch (enc) { + + case rfbEncodingCopyRect: + cl->useCopyRect = TRUE; + break; + case rfbEncodingRaw: + case rfbEncodingRRE: + case rfbEncodingCoRRE: + case rfbEncodingHextile: + case rfbEncodingUltra: +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + case rfbEncodingZRLE: + case rfbEncodingZYWRLE: +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + case rfbEncodingTightPng: +#endif + + /* The first supported encoding is the 'preferred' encoding */ + if (cl->preferredEncoding == -1) + cl->preferredEncoding = enc; + + + break; + case rfbEncodingXCursor: + if(!cl->screen->dontConvertRichCursorToXCursor) { + rfbLog("Enabling X-style cursor updates for client %s\n", + cl->host); + /* if cursor was drawn, hide the cursor */ + if(!cl->enableCursorShapeUpdates) + rfbRedrawAfterHideCursor(cl,NULL); + + cl->enableCursorShapeUpdates = TRUE; + cl->cursorWasChanged = TRUE; + } + break; + case rfbEncodingRichCursor: + rfbLog("Enabling full-color cursor updates for client %s\n", + cl->host); + /* if cursor was drawn, hide the cursor */ + if(!cl->enableCursorShapeUpdates) + rfbRedrawAfterHideCursor(cl,NULL); + + cl->enableCursorShapeUpdates = TRUE; + cl->useRichCursorEncoding = TRUE; + cl->cursorWasChanged = TRUE; + break; + case rfbEncodingPointerPos: + if (!cl->enableCursorPosUpdates) { + rfbLog("Enabling cursor position updates for client %s\n", + cl->host); + cl->enableCursorPosUpdates = TRUE; + cl->cursorWasMoved = TRUE; + } + break; + case rfbEncodingLastRect: + if (!cl->enableLastRectEncoding) { + rfbLog("Enabling LastRect protocol extension for client " + "%s\n", cl->host); + cl->enableLastRectEncoding = TRUE; + } + break; + case rfbEncodingNewFBSize: + if (!cl->useNewFBSize) { + rfbLog("Enabling NewFBSize protocol extension for client " + "%s\n", cl->host); + cl->useNewFBSize = TRUE; + } + break; + case rfbEncodingKeyboardLedState: + if (!cl->enableKeyboardLedState) { + rfbLog("Enabling KeyboardLedState protocol extension for client " + "%s\n", cl->host); + cl->enableKeyboardLedState = TRUE; + } + break; + case rfbEncodingSupportedMessages: + if (!cl->enableSupportedMessages) { + rfbLog("Enabling SupportedMessages protocol extension for client " + "%s\n", cl->host); + cl->enableSupportedMessages = TRUE; + } + break; + case rfbEncodingSupportedEncodings: + if (!cl->enableSupportedEncodings) { + rfbLog("Enabling SupportedEncodings protocol extension for client " + "%s\n", cl->host); + cl->enableSupportedEncodings = TRUE; + } + break; + case rfbEncodingServerIdentity: + if (!cl->enableServerIdentity) { + rfbLog("Enabling ServerIdentity protocol extension for client " + "%s\n", cl->host); + cl->enableServerIdentity = TRUE; + } + break; + default: +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + if ( enc >= (uint32_t)rfbEncodingCompressLevel0 && + enc <= (uint32_t)rfbEncodingCompressLevel9 ) { + cl->zlibCompressLevel = enc & 0x0F; +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) + cl->tightCompressLevel = enc & 0x0F; + rfbLog("Using compression level %d for client %s\n", + cl->tightCompressLevel, cl->host); +#endif + } else if ( enc >= (uint32_t)rfbEncodingQualityLevel0 && + enc <= (uint32_t)rfbEncodingQualityLevel9 ) { + cl->tightQualityLevel = enc & 0x0F; + rfbLog("Using image quality level %d for client %s\n", + cl->tightQualityLevel, cl->host); + } else +#endif + { + rfbExtensionData* e; + for(e = cl->extensions; e;) { + rfbExtensionData* next = e->next; + if(e->extension->enablePseudoEncoding && + e->extension->enablePseudoEncoding(cl, + &e->data, (int)enc)) + /* ext handles this encoding */ + break; + e = next; + } + if(e == NULL) { + rfbBool handled = FALSE; + /* if the pseudo encoding is not handled by the + enabled extensions, search through all + extensions. */ + rfbProtocolExtension* e; + + for(e = rfbGetExtensionIterator(); e;) { + int* encs = e->pseudoEncodings; + while(encs && *encs!=0) { + if(*encs==(int)enc) { + void* data = NULL; + if(!e->enablePseudoEncoding(cl, &data, (int)enc)) { + rfbLog("Installed extension pretends to handle pseudo encoding 0x%x, but does not!\n",(int)enc); + } else { + rfbEnableExtension(cl, e, data); + handled = TRUE; + e = NULL; + break; + } + } + encs++; + } + + if(e) + e = e->next; + } + rfbReleaseExtensionIterator(); + + if(!handled) + rfbLog("rfbProcessClientNormalMessage: " + "ignoring unsupported encoding type %s\n", + encodingName(enc,encBuf,sizeof(encBuf))); + } + } + } + } + + + if (cl->preferredEncoding == -1) { + if (lastPreferredEncoding==-1) { + cl->preferredEncoding = rfbEncodingRaw; + rfbLog("Defaulting to %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host); + } + else { + cl->preferredEncoding = lastPreferredEncoding; + rfbLog("Sticking with %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host); + } + } + else + { + if (lastPreferredEncoding==-1) { + rfbLog("Using %s encoding for client %s\n", encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)),cl->host); + } else { + rfbLog("Switching from %s to %s Encoding for client %s\n", + encodingName(lastPreferredEncoding,encBuf2,sizeof(encBuf2)), + encodingName(cl->preferredEncoding,encBuf,sizeof(encBuf)), cl->host); + } + } + + if (cl->enableCursorPosUpdates && !cl->enableCursorShapeUpdates) { + rfbLog("Disabling cursor position updates for client %s\n", + cl->host); + cl->enableCursorPosUpdates = FALSE; + } + + return; + } + + + case rfbFramebufferUpdateRequest: + { + sraRegionPtr tmpRegion; + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbFramebufferUpdateRequestMsg-1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbFramebufferUpdateRequestMsg,sz_rfbFramebufferUpdateRequestMsg); + + /* The values come in based on the scaled screen, we need to convert them to + * values based on the main screen's coordinate system + */ + if(!rectSwapIfLEAndClip(&msg.fur.x,&msg.fur.y,&msg.fur.w,&msg.fur.h,cl)) + { + rfbLog("Warning, ignoring rfbFramebufferUpdateRequest: %dXx%dY-%dWx%dH\n",msg.fur.x, msg.fur.y, msg.fur.w, msg.fur.h); + return; + } + + + tmpRegion = + sraRgnCreateRect(msg.fur.x, + msg.fur.y, + msg.fur.x+msg.fur.w, + msg.fur.y+msg.fur.h); + + LOCK(cl->updateMutex); + sraRgnOr(cl->requestedRegion,tmpRegion); + + if (!cl->readyForSetColourMapEntries) { + /* client hasn't sent a SetPixelFormat so is using server's */ + cl->readyForSetColourMapEntries = TRUE; + if (!cl->format.trueColour) { + if (!rfbSetClientColourMap(cl, 0, 0)) { + sraRgnDestroy(tmpRegion); + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + return; + } + } + } + + if (!msg.fur.incremental) { + sraRgnOr(cl->modifiedRegion,tmpRegion); + sraRgnSubtract(cl->copyRegion,tmpRegion); + } + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); + + sraRgnDestroy(tmpRegion); + + return; + } + + case rfbKeyEvent: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbKeyEventMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbKeyEventMsg, sz_rfbKeyEventMsg); + + if(!cl->viewOnly) { + cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl); + } + + return; + + + case rfbPointerEvent: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbPointerEventMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbPointerEventMsg, sz_rfbPointerEventMsg); + + if (cl->screen->pointerClient && cl->screen->pointerClient != cl) + return; + + if (msg.pe.buttonMask == 0) + cl->screen->pointerClient = NULL; + else + cl->screen->pointerClient = cl; + + if(!cl->viewOnly) { + if (msg.pe.buttonMask != cl->lastPtrButtons || + cl->screen->deferPtrUpdateTime == 0) { + cl->screen->ptrAddEvent(msg.pe.buttonMask, + ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)), + ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)), + cl); + cl->lastPtrButtons = msg.pe.buttonMask; + } else { + cl->lastPtrX = ScaleX(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.x)); + cl->lastPtrY = ScaleY(cl->scaledScreen, cl->screen, Swap16IfLE(msg.pe.y)); + cl->lastPtrButtons = msg.pe.buttonMask; + } + } + return; + + + case rfbFileTransfer: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbFileTransferMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + msg.ft.size = Swap32IfLE(msg.ft.size); + msg.ft.length = Swap32IfLE(msg.ft.length); + /* record statistics in rfbProcessFileTransfer as length is filled with garbage when it is not valid */ + rfbProcessFileTransfer(cl, msg.ft.contentType, msg.ft.contentParam, msg.ft.size, msg.ft.length); + return; + + case rfbSetSW: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetSWMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + msg.sw.x = Swap16IfLE(msg.sw.x); + msg.sw.y = Swap16IfLE(msg.sw.y); + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetSWMsg, sz_rfbSetSWMsg); + /* msg.sw.status is not initialized in the ultraVNC viewer and contains random numbers (why???) */ + + rfbLog("Received a rfbSetSingleWindow(%d x, %d y)\n", msg.sw.x, msg.sw.y); + if (cl->screen->setSingleWindow!=NULL) + cl->screen->setSingleWindow(cl, msg.sw.x, msg.sw.y); + return; + + case rfbSetServerInput: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetServerInputMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetServerInputMsg, sz_rfbSetServerInputMsg); + + /* msg.sim.pad is not initialized in the ultraVNC viewer and contains random numbers (why???) */ + /* msg.sim.pad = Swap16IfLE(msg.sim.pad); */ + + rfbLog("Received a rfbSetServerInput(%d status)\n", msg.sim.status); + if (cl->screen->setServerInput!=NULL) + cl->screen->setServerInput(cl, msg.sim.status); + return; + + case rfbTextChat: + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbTextChatMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + msg.tc.pad2 = Swap16IfLE(msg.tc.pad2); + msg.tc.length = Swap32IfLE(msg.tc.length); + + switch (msg.tc.length) { + case rfbTextChatOpen: + case rfbTextChatClose: + case rfbTextChatFinished: + /* commands do not have text following */ + /* Why couldn't they have used the pad byte??? */ + str=NULL; + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbTextChatMsg, sz_rfbTextChatMsg); + break; + default: + if ((msg.tc.length>0) && (msg.tc.length%d\n", msg.tc.length, rfbTextMaxSize); + rfbCloseClient(cl); + return; + } + } + + /* Note: length can be commands: rfbTextChatOpen, rfbTextChatClose, and rfbTextChatFinished + * at which point, the str is NULL (as it is not sent) + */ + if (cl->screen->setTextChat!=NULL) + cl->screen->setTextChat(cl, msg.tc.length, str); + + free(str); + return; + + + case rfbClientCutText: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbClientCutTextMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + + msg.cct.length = Swap32IfLE(msg.cct.length); + + str = (char *)malloc(msg.cct.length); + + if ((n = rfbReadExact(cl, str, msg.cct.length)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + free(str); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbClientCutTextMsg+msg.cct.length, sz_rfbClientCutTextMsg+msg.cct.length); + if(!cl->viewOnly) { + cl->screen->setXCutText(str, msg.cct.length, cl); + } + free(str); + + return; + + case rfbPalmVNCSetScaleFactor: + cl->PalmVNC = TRUE; + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetScaleMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg); + rfbLog("rfbSetScale(%d)\n", msg.ssc.scale); + rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale); + + rfbSendNewScaleSize(cl); + return; + + case rfbSetScale: + + if ((n = rfbReadExact(cl, ((char *)&msg) + 1, + sz_rfbSetScaleMsg - 1)) <= 0) { + if (n != 0) + rfbLogPerror("rfbProcessClientNormalMessage: read"); + rfbCloseClient(cl); + return; + } + rfbStatRecordMessageRcvd(cl, msg.type, sz_rfbSetScaleMsg, sz_rfbSetScaleMsg); + rfbLog("rfbSetScale(%d)\n", msg.ssc.scale); + rfbScalingSetup(cl,cl->screen->width/msg.ssc.scale, cl->screen->height/msg.ssc.scale); + + rfbSendNewScaleSize(cl); + return; + + default: + { + rfbExtensionData *e,*next; + + for(e=cl->extensions; e;) { + next = e->next; + if(e->extension->handleMessage && + e->extension->handleMessage(cl, e->data, &msg)) + { + rfbStatRecordMessageRcvd(cl, msg.type, 0, 0); /* Extension should handle this */ + return; + } + e = next; + } + + rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", + msg.type); + rfbLog(" ... closing connection\n"); + rfbCloseClient(cl); + return; + } + } +} + + + +/* + * rfbSendFramebufferUpdate - send the currently pending framebuffer update to + * the RFB client. + * givenUpdateRegion is not changed. + */ + +rfbBool +rfbSendFramebufferUpdate(rfbClientPtr cl, + sraRegionPtr givenUpdateRegion) +{ + sraRectangleIterator* i=NULL; + sraRect rect; + int nUpdateRegionRects; + rfbFramebufferUpdateMsg *fu = (rfbFramebufferUpdateMsg *)cl->updateBuf; + sraRegionPtr updateRegion,updateCopyRegion,tmpRegion; + int dx, dy; + rfbBool sendCursorShape = FALSE; + rfbBool sendCursorPos = FALSE; + rfbBool sendKeyboardLedState = FALSE; + rfbBool sendSupportedMessages = FALSE; + rfbBool sendSupportedEncodings = FALSE; + rfbBool sendServerIdentity = FALSE; + rfbBool result = TRUE; + + + if(cl->screen->displayHook) + cl->screen->displayHook(cl); + + /* + * If framebuffer size was changed and the client supports NewFBSize + * encoding, just send NewFBSize marker and return. + */ + + if (cl->useNewFBSize && cl->newFBSizePending) { + LOCK(cl->updateMutex); + cl->newFBSizePending = FALSE; + UNLOCK(cl->updateMutex); + fu->type = rfbFramebufferUpdate; + fu->nRects = Swap16IfLE(1); + cl->ublen = sz_rfbFramebufferUpdateMsg; + if (!rfbSendNewFBSize(cl, cl->scaledScreen->width, cl->scaledScreen->height)) { + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, FALSE); + return FALSE; + } + result = rfbSendUpdateBuf(cl); + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, result); + return result; + } + + /* + * If this client understands cursor shape updates, cursor should be + * removed from the framebuffer. Otherwise, make sure it's put up. + */ + + if (cl->enableCursorShapeUpdates) { + if (cl->cursorWasChanged && cl->readyForSetColourMapEntries) + sendCursorShape = TRUE; + } + + /* + * Do we plan to send cursor position update? + */ + + if (cl->enableCursorPosUpdates && cl->cursorWasMoved) + sendCursorPos = TRUE; + + /* + * Do we plan to send a keyboard state update? + */ + if ((cl->enableKeyboardLedState) && + (cl->screen->getKeyboardLedStateHook!=NULL)) + { + int x; + x=cl->screen->getKeyboardLedStateHook(cl->screen); + if (x!=cl->lastKeyboardLedState) + { + sendKeyboardLedState = TRUE; + cl->lastKeyboardLedState=x; + } + } + + /* + * Do we plan to send a rfbEncodingSupportedMessages? + */ + if (cl->enableSupportedMessages) + { + sendSupportedMessages = TRUE; + /* We only send this message ONCE + * (We disable it here) + */ + cl->enableSupportedMessages = FALSE; + } + /* + * Do we plan to send a rfbEncodingSupportedEncodings? + */ + if (cl->enableSupportedEncodings) + { + sendSupportedEncodings = TRUE; + /* We only send this message ONCE + * (We disable it here) + */ + cl->enableSupportedEncodings = FALSE; + } + /* + * Do we plan to send a rfbEncodingServerIdentity? + */ + if (cl->enableServerIdentity) + { + sendServerIdentity = TRUE; + /* We only send this message ONCE + * (We disable it here) + */ + cl->enableServerIdentity = FALSE; + } + + LOCK(cl->updateMutex); + + /* + * The modifiedRegion may overlap the destination copyRegion. We remove + * any overlapping bits from the copyRegion (since they'd only be + * overwritten anyway). + */ + + sraRgnSubtract(cl->copyRegion,cl->modifiedRegion); + + /* + * The client is interested in the region requestedRegion. The region + * which should be updated now is the intersection of requestedRegion + * and the union of modifiedRegion and copyRegion. If it's empty then + * no update is needed. + */ + + updateRegion = sraRgnCreateRgn(givenUpdateRegion); + if(cl->screen->progressiveSliceHeight>0) { + int height=cl->screen->progressiveSliceHeight, + y=cl->progressiveSliceY; + sraRegionPtr bbox=sraRgnBBox(updateRegion); + sraRect rect; + if(sraRgnPopRect(bbox,&rect,0)) { + sraRegionPtr slice; + if(y=rect.y2) + y=rect.y1; + slice=sraRgnCreateRect(0,y,cl->screen->width,y+height); + sraRgnAnd(updateRegion,slice); + sraRgnDestroy(slice); + } + sraRgnDestroy(bbox); + y+=height; + if(y>=cl->screen->height) + y=0; + cl->progressiveSliceY=y; + } + + sraRgnOr(updateRegion,cl->copyRegion); + if(!sraRgnAnd(updateRegion,cl->requestedRegion) && + sraRgnEmpty(updateRegion) && + (cl->enableCursorShapeUpdates || + (cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) && + !sendCursorShape && !sendCursorPos && !sendKeyboardLedState && + !sendSupportedMessages && !sendSupportedEncodings && !sendServerIdentity) { + sraRgnDestroy(updateRegion); + UNLOCK(cl->updateMutex); + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, TRUE); + return TRUE; + } + + /* + * We assume that the client doesn't have any pixel data outside the + * requestedRegion. In other words, both the source and destination of a + * copy must lie within requestedRegion. So the region we can send as a + * copy is the intersection of the copyRegion with both the requestedRegion + * and the requestedRegion translated by the amount of the copy. We set + * updateCopyRegion to this. + */ + + updateCopyRegion = sraRgnCreateRgn(cl->copyRegion); + sraRgnAnd(updateCopyRegion,cl->requestedRegion); + tmpRegion = sraRgnCreateRgn(cl->requestedRegion); + sraRgnOffset(tmpRegion,cl->copyDX,cl->copyDY); + sraRgnAnd(updateCopyRegion,tmpRegion); + sraRgnDestroy(tmpRegion); + dx = cl->copyDX; + dy = cl->copyDY; + + /* + * Next we remove updateCopyRegion from updateRegion so that updateRegion + * is the part of this update which is sent as ordinary pixel data (i.e not + * a copy). + */ + + sraRgnSubtract(updateRegion,updateCopyRegion); + + /* + * Finally we leave modifiedRegion to be the remainder (if any) of parts of + * the screen which are modified but outside the requestedRegion. We also + * empty both the requestedRegion and the copyRegion - note that we never + * carry over a copyRegion for a future update. + */ + + sraRgnOr(cl->modifiedRegion,cl->copyRegion); + sraRgnSubtract(cl->modifiedRegion,updateRegion); + sraRgnSubtract(cl->modifiedRegion,updateCopyRegion); + + sraRgnMakeEmpty(cl->requestedRegion); + sraRgnMakeEmpty(cl->copyRegion); + cl->copyDX = 0; + cl->copyDY = 0; + + UNLOCK(cl->updateMutex); + + if (!cl->enableCursorShapeUpdates) { + if(cl->cursorX != cl->screen->cursorX || cl->cursorY != cl->screen->cursorY) { + rfbRedrawAfterHideCursor(cl,updateRegion); + LOCK(cl->screen->cursorMutex); + cl->cursorX = cl->screen->cursorX; + cl->cursorY = cl->screen->cursorY; + UNLOCK(cl->screen->cursorMutex); + rfbRedrawAfterHideCursor(cl,updateRegion); + } + rfbShowCursor(cl); + } + + /* + * Now send the update. + */ + + rfbStatRecordMessageSent(cl, rfbFramebufferUpdate, 0, 0); + if (cl->preferredEncoding == rfbEncodingCoRRE) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int rectsPerRow, rows; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + rectsPerRow = (w-1)/cl->correMaxWidth+1; + rows = (h-1)/cl->correMaxHeight+1; + nUpdateRegionRects += rectsPerRow*rows; + } + sraRgnReleaseIterator(i); i=NULL; + } else if (cl->preferredEncoding == rfbEncodingUltra) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + nUpdateRegionRects += (((h-1) / (ULTRA_MAX_SIZE( w ) / w)) + 1); + } + sraRgnReleaseIterator(i); i=NULL; +#ifdef LIBVNCSERVER_HAVE_LIBZ + } else if (cl->preferredEncoding == rfbEncodingZlib) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + nUpdateRegionRects += (((h-1) / (ZLIB_MAX_SIZE( w ) / w)) + 1); + } + sraRgnReleaseIterator(i); i=NULL; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + } else if (cl->preferredEncoding == rfbEncodingTight) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int n; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + n = rfbNumCodedRectsTight(cl, x, y, w, h); + if (n == 0) { + nUpdateRegionRects = 0xFFFF; + break; + } + nUpdateRegionRects += n; + } + sraRgnReleaseIterator(i); i=NULL; +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + } else if (cl->preferredEncoding == rfbEncodingTightPng) { + nUpdateRegionRects = 0; + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + int n; + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + n = rfbNumCodedRectsTight(cl, x, y, w, h); + if (n == 0) { + nUpdateRegionRects = 0xFFFF; + break; + } + nUpdateRegionRects += n; + } + sraRgnReleaseIterator(i); i=NULL; +#endif + } else { + nUpdateRegionRects = sraRgnCountRects(updateRegion); + } + + fu->type = rfbFramebufferUpdate; + if (nUpdateRegionRects != 0xFFFF) { + if(cl->screen->maxRectsPerUpdate>0 + /* CoRRE splits the screen into smaller squares */ + && cl->preferredEncoding != rfbEncodingCoRRE + /* Ultra encoding splits rectangles up into smaller chunks */ + && cl->preferredEncoding != rfbEncodingUltra +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* Zlib encoding splits rectangles up into smaller chunks */ + && cl->preferredEncoding != rfbEncodingZlib +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* Tight encoding counts the rectangles differently */ + && cl->preferredEncoding != rfbEncodingTight +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + /* Tight encoding counts the rectangles differently */ + && cl->preferredEncoding != rfbEncodingTightPng +#endif + && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) { + sraRegion* newUpdateRegion = sraRgnBBox(updateRegion); + sraRgnDestroy(updateRegion); + updateRegion = newUpdateRegion; + nUpdateRegionRects = sraRgnCountRects(updateRegion); + } + fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) + + nUpdateRegionRects + + !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState + + !!sendSupportedMessages + !!sendSupportedEncodings + !!sendServerIdentity)); + } else { + fu->nRects = 0xFFFF; + } + cl->ublen = sz_rfbFramebufferUpdateMsg; + + if (sendCursorShape) { + cl->cursorWasChanged = FALSE; + if (!rfbSendCursorShape(cl)) + goto updateFailed; + } + + if (sendCursorPos) { + cl->cursorWasMoved = FALSE; + if (!rfbSendCursorPos(cl)) + goto updateFailed; + } + + if (sendKeyboardLedState) { + if (!rfbSendKeyboardLedState(cl)) + goto updateFailed; + } + + if (sendSupportedMessages) { + if (!rfbSendSupportedMessages(cl)) + goto updateFailed; + } + if (sendSupportedEncodings) { + if (!rfbSendSupportedEncodings(cl)) + goto updateFailed; + } + if (sendServerIdentity) { + if (!rfbSendServerIdentity(cl)) + goto updateFailed; + } + + if (!sraRgnEmpty(updateCopyRegion)) { + if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy)) + goto updateFailed; + } + + for(i = sraRgnGetIterator(updateRegion); sraRgnIteratorNext(i,&rect);){ + int x = rect.x1; + int y = rect.y1; + int w = rect.x2 - x; + int h = rect.y2 - y; + + /* We need to count the number of rects in the scaled screen */ + if (cl->screen!=cl->scaledScreen) + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "rfbSendFramebufferUpdate"); + + switch (cl->preferredEncoding) { + case -1: + case rfbEncodingRaw: + if (!rfbSendRectEncodingRaw(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingRRE: + if (!rfbSendRectEncodingRRE(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingCoRRE: + if (!rfbSendRectEncodingCoRRE(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingHextile: + if (!rfbSendRectEncodingHextile(cl, x, y, w, h)) + goto updateFailed; + break; + case rfbEncodingUltra: + if (!rfbSendRectEncodingUltra(cl, x, y, w, h)) + goto updateFailed; + break; +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZlib: + if (!rfbSendRectEncodingZlib(cl, x, y, w, h)) + goto updateFailed; + break; +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + case rfbEncodingTight: + if (!rfbSendRectEncodingTight(cl, x, y, w, h)) + goto updateFailed; + break; +#endif +#endif +#ifdef LIBVNCSERVER_HAVE_LIBPNG + case rfbEncodingTightPng: + if (!rfbSendRectEncodingTightPng(cl, x, y, w, h)) + goto updateFailed; + break; +#endif +#ifdef LIBVNCSERVER_HAVE_LIBZ + case rfbEncodingZRLE: + case rfbEncodingZYWRLE: + if (!rfbSendRectEncodingZRLE(cl, x, y, w, h)) + goto updateFailed; + break; +#endif + } + } + if (i) { + sraRgnReleaseIterator(i); + i = NULL; + } + + if ( nUpdateRegionRects == 0xFFFF && + !rfbSendLastRectMarker(cl) ) + goto updateFailed; + + if (!rfbSendUpdateBuf(cl)) { +updateFailed: + result = FALSE; + } + + if (!cl->enableCursorShapeUpdates) { + rfbHideCursor(cl); + } + + if(i) + sraRgnReleaseIterator(i); + sraRgnDestroy(updateRegion); + sraRgnDestroy(updateCopyRegion); + + if(cl->screen->displayFinishedHook) + cl->screen->displayFinishedHook(cl, result); + return result; +} + + +/* + * Send the copy region as a string of CopyRect encoded rectangles. + * The only slightly tricky thing is that we should send the messages in + * the correct order so that an earlier CopyRect will not corrupt the source + * of a later one. + */ + +rfbBool +rfbSendCopyRegion(rfbClientPtr cl, + sraRegionPtr reg, + int dx, + int dy) +{ + int x, y, w, h; + rfbFramebufferUpdateRectHeader rect; + rfbCopyRect cr; + sraRectangleIterator* i; + sraRect rect1; + + /* printf("copyrect: "); sraRgnPrint(reg); putchar('\n');fflush(stdout); */ + i = sraRgnGetReverseIterator(reg,dx>0,dy>0); + + /* correct for the scale of the screen */ + dx = ScaleX(cl->screen, cl->scaledScreen, dx); + dy = ScaleX(cl->screen, cl->scaledScreen, dy); + + while(sraRgnIteratorNext(i,&rect1)) { + x = rect1.x1; + y = rect1.y1; + w = rect1.x2 - x; + h = rect1.y2 - y; + + /* correct for scaling (if necessary) */ + rfbScaledCorrection(cl->screen, cl->scaledScreen, &x, &y, &w, &h, "copyrect"); + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingCopyRect); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + cr.srcX = Swap16IfLE(x - dx); + cr.srcY = Swap16IfLE(y - dy); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&cr, sz_rfbCopyRect); + cl->ublen += sz_rfbCopyRect; + + rfbStatRecordEncodingSent(cl, rfbEncodingCopyRect, sz_rfbFramebufferUpdateRectHeader + sz_rfbCopyRect, + w * h * (cl->scaledScreen->bitsPerPixel / 8)); + } + sraRgnReleaseIterator(i); + + return TRUE; +} + +/* + * Send a given rectangle in raw encoding (rfbEncodingRaw). + */ + +rfbBool +rfbSendRectEncodingRaw(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + int nlines; + int bytesPerLine = w * (cl->format.bitsPerPixel / 8); + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + /* Flush the buffer to guarantee correct alignment for translateFn(). */ + if (cl->ublen > 0) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingRaw); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + + rfbStatRecordEncodingSent(cl, rfbEncodingRaw, sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h, + sz_rfbFramebufferUpdateRectHeader + bytesPerLine * h); + + nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine; + + while (TRUE) { + if (nlines > h) + nlines = h; + + (*cl->translateFn)(cl->translateLookupTable, + &(cl->screen->serverFormat), + &cl->format, fbptr, &cl->updateBuf[cl->ublen], + cl->scaledScreen->paddedWidthInBytes, w, nlines); + + cl->ublen += nlines * bytesPerLine; + h -= nlines; + + if (h == 0) /* rect fitted in buffer, do next one */ + return TRUE; + + /* buffer full - flush partial rect and do another nlines */ + + if (!rfbSendUpdateBuf(cl)) + return FALSE; + + fbptr += (cl->scaledScreen->paddedWidthInBytes * nlines); + + nlines = (UPDATE_BUF_SIZE - cl->ublen) / bytesPerLine; + if (nlines == 0) { + rfbErr("rfbSendRectEncodingRaw: send buffer too small for %d " + "bytes per line\n", bytesPerLine); + rfbCloseClient(cl); + return FALSE; + } + } +} + + + +/* + * Send an empty rectangle with encoding field set to value of + * rfbEncodingLastRect to notify client that this is the last + * rectangle in framebuffer update ("LastRect" extension of RFB + * protocol). + */ + +rfbBool +rfbSendLastRectMarker(rfbClientPtr cl) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.encoding = Swap32IfLE(rfbEncodingLastRect); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = 0; + rect.r.h = 0; + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + + rfbStatRecordEncodingSent(cl, rfbEncodingLastRect, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + return TRUE; +} + + +/* + * Send NewFBSize pseudo-rectangle. This tells the client to change + * its framebuffer size. + */ + +rfbBool +rfbSendNewFBSize(rfbClientPtr cl, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if (cl->PalmVNC==TRUE) + rfbLog("Sending rfbEncodingNewFBSize in response to a PalmVNC style framebuffer resize (%dx%d)\n", w, h); + else + rfbLog("Sending rfbEncodingNewFBSize for resize to (%dx%d)\n", w, h); + + rect.encoding = Swap32IfLE(rfbEncodingNewFBSize); + rect.r.x = 0; + rect.r.y = 0; + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, rfbEncodingNewFBSize, sz_rfbFramebufferUpdateRectHeader, sz_rfbFramebufferUpdateRectHeader); + + return TRUE; +} + + +/* + * Send the contents of cl->updateBuf. Returns 1 if successful, -1 if + * not (errno should be set). + */ + +rfbBool +rfbSendUpdateBuf(rfbClientPtr cl) +{ + if(cl->sock<0) + return FALSE; + + if (rfbWriteExact(cl, cl->updateBuf, cl->ublen) < 0) { + rfbLogPerror("rfbSendUpdateBuf: write"); + rfbCloseClient(cl); + return FALSE; + } + + cl->ublen = 0; + return TRUE; +} + +/* + * rfbSendSetColourMapEntries sends a SetColourMapEntries message to the + * client, using values from the currently installed colormap. + */ + +rfbBool +rfbSendSetColourMapEntries(rfbClientPtr cl, + int firstColour, + int nColours) +{ + char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; + char *wbuf = buf; + rfbSetColourMapEntriesMsg *scme; + uint16_t *rgb; + rfbColourMap* cm = &cl->screen->colourMap; + int i, len; + + if (nColours > 256) { + /* some rare hardware has, e.g., 4096 colors cells: PseudoColor:12 */ + wbuf = (char *) malloc(sz_rfbSetColourMapEntriesMsg + nColours * 3 * 2); + } + + scme = (rfbSetColourMapEntriesMsg *)wbuf; + rgb = (uint16_t *)(&wbuf[sz_rfbSetColourMapEntriesMsg]); + + scme->type = rfbSetColourMapEntries; + + scme->firstColour = Swap16IfLE(firstColour); + scme->nColours = Swap16IfLE(nColours); + + len = sz_rfbSetColourMapEntriesMsg; + + for (i = 0; i < nColours; i++) { + if(i<(int)cm->count) { + if(cm->is16) { + rgb[i*3] = Swap16IfLE(cm->data.shorts[i*3]); + rgb[i*3+1] = Swap16IfLE(cm->data.shorts[i*3+1]); + rgb[i*3+2] = Swap16IfLE(cm->data.shorts[i*3+2]); + } else { + rgb[i*3] = Swap16IfLE((unsigned short)cm->data.bytes[i*3]); + rgb[i*3+1] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+1]); + rgb[i*3+2] = Swap16IfLE((unsigned short)cm->data.bytes[i*3+2]); + } + } + } + + len += nColours * 3 * 2; + + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, wbuf, len) < 0) { + rfbLogPerror("rfbSendSetColourMapEntries: write"); + rfbCloseClient(cl); + if (wbuf != buf) free(wbuf); + UNLOCK(cl->sendMutex); + return FALSE; + } + UNLOCK(cl->sendMutex); + + rfbStatRecordMessageSent(cl, rfbSetColourMapEntries, len, len); + if (wbuf != buf) free(wbuf); + return TRUE; +} + +/* + * rfbSendBell sends a Bell message to all the clients. + */ + +void +rfbSendBell(rfbScreenInfoPtr rfbScreen) +{ + rfbClientIteratorPtr i; + rfbClientPtr cl; + rfbBellMsg b; + + i = rfbGetClientIterator(rfbScreen); + while((cl=rfbClientIteratorNext(i))) { + b.type = rfbBell; + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&b, sz_rfbBellMsg) < 0) { + rfbLogPerror("rfbSendBell: write"); + rfbCloseClient(cl); + } + UNLOCK(cl->sendMutex); + } + rfbStatRecordMessageSent(cl, rfbBell, sz_rfbBellMsg, sz_rfbBellMsg); + rfbReleaseClientIterator(i); +} + + +/* + * rfbSendServerCutText sends a ServerCutText message to all the clients. + */ + +void +rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len) +{ + rfbClientPtr cl; + rfbServerCutTextMsg sct; + rfbClientIteratorPtr iterator; + + iterator = rfbGetClientIterator(rfbScreen); + while ((cl = rfbClientIteratorNext(iterator)) != NULL) { + sct.type = rfbServerCutText; + sct.length = Swap32IfLE(len); + LOCK(cl->sendMutex); + if (rfbWriteExact(cl, (char *)&sct, + sz_rfbServerCutTextMsg) < 0) { + rfbLogPerror("rfbSendServerCutText: write"); + rfbCloseClient(cl); + UNLOCK(cl->sendMutex); + continue; + } + if (rfbWriteExact(cl, str, len) < 0) { + rfbLogPerror("rfbSendServerCutText: write"); + rfbCloseClient(cl); + } + UNLOCK(cl->sendMutex); + rfbStatRecordMessageSent(cl, rfbServerCutText, sz_rfbServerCutTextMsg+len, sz_rfbServerCutTextMsg+len); + } + rfbReleaseClientIterator(iterator); +} + +/***************************************************************************** + * + * UDP can be used for keyboard and pointer events when the underlying + * network is highly reliable. This is really here to support ORL's + * videotile, whose TCP implementation doesn't like sending lots of small + * packets (such as 100s of pen readings per second!). + */ + +static unsigned char ptrAcceleration = 50; + +void +rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen, + int sock) +{ + if (write(sock, &ptrAcceleration, 1) < 0) { + rfbLogPerror("rfbNewUDPConnection: write"); + } +} + +/* + * Because UDP is a message based service, we can't read the first byte and + * then the rest of the packet separately like we do with TCP. We will always + * get a whole packet delivered in one go, so we ask read() for the maximum + * number of bytes we can possibly get. + */ + +void +rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen) +{ + int n; + rfbClientPtr cl=rfbScreen->udpClient; + rfbClientToServerMsg msg; + + if((!cl) || cl->onHold) + return; + + if ((n = read(rfbScreen->udpSock, (char *)&msg, sizeof(msg))) <= 0) { + if (n < 0) { + rfbLogPerror("rfbProcessUDPInput: read"); + } + rfbDisconnectUDPSock(rfbScreen); + return; + } + + switch (msg.type) { + + case rfbKeyEvent: + if (n != sz_rfbKeyEventMsg) { + rfbErr("rfbProcessUDPInput: key event incorrect length\n"); + rfbDisconnectUDPSock(rfbScreen); + return; + } + cl->screen->kbdAddEvent(msg.ke.down, (rfbKeySym)Swap32IfLE(msg.ke.key), cl); + break; + + case rfbPointerEvent: + if (n != sz_rfbPointerEventMsg) { + rfbErr("rfbProcessUDPInput: ptr event incorrect length\n"); + rfbDisconnectUDPSock(rfbScreen); + return; + } + cl->screen->ptrAddEvent(msg.pe.buttonMask, + Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl); + break; + + default: + rfbErr("rfbProcessUDPInput: unknown message type %d\n", + msg.type); + rfbDisconnectUDPSock(rfbScreen); + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c new file mode 100755 index 0000000..b43561a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/rre.c @@ -0,0 +1,329 @@ +/* + * rre.c + * + * Routines to implement Rise-and-Run-length Encoding (RRE). This + * code is based on krw's original javatel rfbserver. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +/* + * rreBeforeBuf contains pixel data in the client's format. + * rreAfterBuf contains the RRE encoded version. If the RRE encoded version is + * larger than the raw data or if it exceeds rreAfterBufSize then + * raw encoding is used instead. + */ + +static int rreBeforeBufSize = 0; +static char *rreBeforeBuf = NULL; + +static int rreAfterBufSize = 0; +static char *rreAfterBuf = NULL; +static int rreAfterBufLen=0; + +static int subrectEncode8(uint8_t *data, int w, int h); +static int subrectEncode16(uint16_t *data, int w, int h); +static int subrectEncode32(uint32_t *data, int w, int h); +static uint32_t getBgColour(char *data, int size, int bpp); + + +void rfbRRECleanup(rfbScreenInfoPtr screen) +{ + if (rreBeforeBufSize) { + free(rreBeforeBuf); + rreBeforeBufSize=0; + } + if (rreAfterBufSize) { + free(rreAfterBuf); + rreAfterBufSize=0; + } +} + + +/* + * rfbSendRectEncodingRRE - send a given rectangle using RRE encoding. + */ + +rfbBool +rfbSendRectEncodingRRE(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + rfbRREHeader hdr; + int nSubrects; + int i; + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + int maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height + * (cl->format.bitsPerPixel / 8)); + + if (rreBeforeBufSize < maxRawSize) { + rreBeforeBufSize = maxRawSize; + if (rreBeforeBuf == NULL) + rreBeforeBuf = (char *)malloc(rreBeforeBufSize); + else + rreBeforeBuf = (char *)realloc(rreBeforeBuf, rreBeforeBufSize); + } + + if (rreAfterBufSize < maxRawSize) { + rreAfterBufSize = maxRawSize; + if (rreAfterBuf == NULL) + rreAfterBuf = (char *)malloc(rreAfterBufSize); + else + rreAfterBuf = (char *)realloc(rreAfterBuf, rreAfterBufSize); + } + + (*cl->translateFn)(cl->translateLookupTable, + &(cl->screen->serverFormat), + &cl->format, fbptr, rreBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + switch (cl->format.bitsPerPixel) { + case 8: + nSubrects = subrectEncode8((uint8_t *)rreBeforeBuf, w, h); + break; + case 16: + nSubrects = subrectEncode16((uint16_t *)rreBeforeBuf, w, h); + break; + case 32: + nSubrects = subrectEncode32((uint32_t *)rreBeforeBuf, w, h); + break; + default: + rfbLog("getBgColour: bpp %d?\n",cl->format.bitsPerPixel); + return FALSE; + } + + if (nSubrects < 0) { + + /* RRE encoding was too large, use raw */ + + return rfbSendRectEncodingRaw(cl, x, y, w, h); + } + + rfbStatRecordEncodingSent(cl, rfbEncodingRRE, + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + rreAfterBufLen, + sz_rfbFramebufferUpdateRectHeader + w * h * (cl->format.bitsPerPixel / 8)); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbRREHeader + > UPDATE_BUF_SIZE) + { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingRRE); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.nSubrects = Swap32IfLE(nSubrects); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbRREHeader); + cl->ublen += sz_rfbRREHeader; + + for (i = 0; i < rreAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > rreAfterBufLen) { + bytesToCopy = rreAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &rreAfterBuf[i], bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; +} + + + +/* + * subrectEncode() encodes the given multicoloured rectangle as a background + * colour overwritten by single-coloured rectangles. It returns the number + * of subrectangles in the encoded buffer, or -1 if subrect encoding won't + * fit in the buffer. It puts the encoded rectangles in rreAfterBuf. The + * single-colour rectangle partition is not optimal, but does find the biggest + * horizontal or vertical rectangle top-left anchored to each consecutive + * coordinate position. + * + * The coding scheme is simply [...] where each + * is []. + */ + +#define DEFINE_SUBRECT_ENCODE(bpp) \ +static int \ +subrectEncode##bpp(uint##bpp##_t *data, int w, int h) { \ + uint##bpp##_t cl; \ + rfbRectangle subrect; \ + int x,y; \ + int i,j; \ + int hx=0,hy,vx=0,vy; \ + int hyflag; \ + uint##bpp##_t *seg; \ + uint##bpp##_t *line; \ + int hw,hh,vw,vh; \ + int thex,they,thew,theh; \ + int numsubs = 0; \ + int newLen; \ + uint##bpp##_t bg = (uint##bpp##_t)getBgColour((char*)data,w*h,bpp); \ + \ + *((uint##bpp##_t*)rreAfterBuf) = bg; \ + \ + rreAfterBufLen = (bpp/8); \ + \ + for (y=0; y 0) && (i >= hx)) {hy += 1;} else {hyflag = 0;} \ + } \ + vy = j-1; \ + \ + /* We now have two possible subrects: (x,y,hx,hy) and (x,y,vx,vy) \ + * We'll choose the bigger of the two. \ + */ \ + hw = hx-x+1; \ + hh = hy-y+1; \ + vw = vx-x+1; \ + vh = vy-y+1; \ + \ + thex = x; \ + they = y; \ + \ + if ((hw*hh) > (vw*vh)) { \ + thew = hw; \ + theh = hh; \ + } else { \ + thew = vw; \ + theh = vh; \ + } \ + \ + subrect.x = Swap16IfLE(thex); \ + subrect.y = Swap16IfLE(they); \ + subrect.w = Swap16IfLE(thew); \ + subrect.h = Swap16IfLE(theh); \ + \ + newLen = rreAfterBufLen + (bpp/8) + sz_rfbRectangle; \ + if ((newLen > (w * h * (bpp/8))) || (newLen > rreAfterBufSize)) \ + return -1; \ + \ + numsubs += 1; \ + *((uint##bpp##_t*)(rreAfterBuf + rreAfterBufLen)) = cl; \ + rreAfterBufLen += (bpp/8); \ + memcpy(&rreAfterBuf[rreAfterBufLen],&subrect,sz_rfbRectangle); \ + rreAfterBufLen += sz_rfbRectangle; \ + \ + /* \ + * Now mark the subrect as done. \ + */ \ + for (j=they; j < (they+theh); j++) { \ + for (i=thex; i < (thex+thew); i++) { \ + data[j*w+i] = bg; \ + } \ + } \ + } \ + } \ + } \ + \ + return numsubs; \ +} + +DEFINE_SUBRECT_ENCODE(8) +DEFINE_SUBRECT_ENCODE(16) +DEFINE_SUBRECT_ENCODE(32) + + +/* + * getBgColour() gets the most prevalent colour in a byte array. + */ +static uint32_t +getBgColour(char *data, int size, int bpp) +{ + +#define NUMCLRS 256 + + static int counts[NUMCLRS]; + int i,j,k; + + int maxcount = 0; + uint8_t maxclr = 0; + + if (bpp != 8) { + if (bpp == 16) { + return ((uint16_t *)data)[0]; + } else if (bpp == 32) { + return ((uint32_t *)data)[0]; + } else { + rfbLog("getBgColour: bpp %d?\n",bpp); + return 0; + } + } + + for (i=0; i= NUMCLRS) { + rfbErr("getBgColour: unusual colour = %d\n", k); + return 0; + } + counts[k] += 1; + if (counts[k] > maxcount) { + maxcount = counts[k]; + maxclr = ((uint8_t *)data)[j]; + } + } + + return maxclr; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c new file mode 100755 index 0000000..55598fa --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.c @@ -0,0 +1,420 @@ +/* + * scale.c - deal with server-side scaling. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include "private.h" + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#ifdef WIN32 +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#include +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#endif +#endif + +#ifdef CORBA +#include +#endif + +#ifdef DEBUGPROTO +#undef DEBUGPROTO +#define DEBUGPROTO(x) x +#else +#define DEBUGPROTO(x) +#endif + +/****************************/ +#define CEIL(x) ( (double) ((int) (x)) == (x) ? \ + (double) ((int) (x)) : (double) ((int) (x) + 1) ) +#define FLOOR(x) ( (double) ((int) (x)) ) + + +int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x) +{ + if ((from==to) || (from==NULL) || (to==NULL)) return x; + return ((int)(((double) x / (double)from->width) * (double)to->width )); +} + +int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y) +{ + if ((from==to) || (from==NULL) || (to==NULL)) return y; + return ((int)(((double) y / (double)from->height) * (double)to->height )); +} + +/* So, all of the encodings point to the ->screen->frameBuffer, + * We need to change this! + */ +void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, char *function) +{ + double x1,y1,w1,h1, x2, y2, w2, h2; + double scaleW = ((double) to->width) / ((double) from->width); + double scaleH = ((double) to->height) / ((double) from->height); + + + /* + * rfbLog("rfbScaledCorrection(%p -> %p, %dx%d->%dx%d (%dXx%dY-%dWx%dH)\n", + * from, to, from->width, from->height, to->width, to->height, *x, *y, *w, *h); + */ + + /* If it's the original framebuffer... */ + if (from==to) return; + + x1 = ((double) *x) * scaleW; + y1 = ((double) *y) * scaleH; + w1 = ((double) *w) * scaleW; + h1 = ((double) *h) * scaleH; + + + /*cast from double to int is same as "*x = floor(x1);" */ + x2 = FLOOR(x1); + y2 = FLOOR(y1); + + /* include into W and H the jitter of scaling X and Y */ + w2 = CEIL(w1 + ( x1 - x2 )); + h2 = CEIL(h1 + ( y1 - y2 )); + + /* + * rfbLog("%s (%dXx%dY-%dWx%dH -> %fXx%fY-%fWx%fH) {%dWx%dH -> %dWx%dH}\n", + * function, *x, *y, *w, *h, x2, y2, w2, h2, + * from->width, from->height, to->width, to->height); + */ + + /* simulate ceil() without math library */ + *x = (int)x2; + *y = (int)y2; + *w = (int)w2; + *h = (int)h2; + + /* Small changes for a thumbnail may be scaled to zero */ + if (*w==0) (*w)++; + if (*h==0) (*h)++; + /* scaling from small to big may overstep the size a bit */ + if (*x+*w > to->width) *w=to->width - *x; + if (*y+*h > to->height) *h=to->height - *y; +} + +void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0) +{ + int x,y,w,v,z; + int x1, y1, w1, h1; + int bitsPerPixel, bytesPerPixel, bytesPerLine, areaX, areaY, area2; + unsigned char *srcptr, *dstptr; + + /* Nothing to do!!! */ + if (screen==ptr) return; + + x1 = x0; + y1 = y0; + w1 = w0; + h1 = h0; + + rfbScaledCorrection(screen, ptr, &x1, &y1, &w1, &h1, "rfbScaledScreenUpdateRect"); + x0 = ScaleX(ptr, screen, x1); + y0 = ScaleY(ptr, screen, y1); + w0 = ScaleX(ptr, screen, w1); + h0 = ScaleY(ptr, screen, h1); + + bitsPerPixel = screen->bitsPerPixel; + bytesPerPixel = bitsPerPixel / 8; + bytesPerLine = w1 * bytesPerPixel; + srcptr = (unsigned char *)(screen->frameBuffer + + (y0 * screen->paddedWidthInBytes + x0 * bytesPerPixel)); + dstptr = (unsigned char *)(ptr->frameBuffer + + ( y1 * ptr->paddedWidthInBytes + x1 * bytesPerPixel)); + /* The area of the source framebuffer for each destination pixel */ + areaX = ScaleX(ptr,screen,1); + areaY = ScaleY(ptr,screen,1); + area2 = areaX*areaY; + + + /* Ensure that we do not go out of bounds */ + if ((x1+w1) > (ptr->width)) + { + if (x1==0) w1=ptr->width; else x1 = ptr->width - w1; + } + if ((y1+h1) > (ptr->height)) + { + if (y1==0) h1=ptr->height; else y1 = ptr->height - h1; + } + /* + * rfbLog("rfbScaledScreenUpdateRect(%dXx%dY-%dWx%dH -> %dXx%dY-%dWx%dH <%dx%d>) {%dWx%dH -> %dWx%dH} 0x%p\n", + * x0, y0, w0, h0, x1, y1, w1, h1, areaX, areaY, + * screen->width, screen->height, ptr->width, ptr->height, ptr->frameBuffer); + */ + + if (screen->serverFormat.trueColour) { /* Blend neighbouring pixels together */ + unsigned char *srcptr2; + unsigned long pixel_value, red, green, blue; + unsigned int redShift = screen->serverFormat.redShift; + unsigned int greenShift = screen->serverFormat.greenShift; + unsigned int blueShift = screen->serverFormat.blueShift; + unsigned long redMax = screen->serverFormat.redMax; + unsigned long greenMax = screen->serverFormat.greenMax; + unsigned long blueMax = screen->serverFormat.blueMax; + + /* for each *destination* pixel... */ + for (y = 0; y < h1; y++) { + for (x = 0; x < w1; x++) { + red = green = blue = 0; + /* Get the totals for rgb from the source grid... */ + for (w = 0; w < areaX; w++) { + for (v = 0; v < areaY; v++) { + srcptr2 = &srcptr[(((x * areaX) + w) * bytesPerPixel) + + (v * screen->paddedWidthInBytes)]; + pixel_value = 0; + + + switch (bytesPerPixel) { + case 4: pixel_value = *((unsigned int *)srcptr2); break; + case 2: pixel_value = *((unsigned short *)srcptr2); break; + case 1: pixel_value = *((unsigned char *)srcptr2); break; + default: + /* fixme: endianess problem? */ + for (z = 0; z < bytesPerPixel; z++) + pixel_value += (srcptr2[z] << (8 * z)); + break; + } + /* + srcptr2 += bytesPerPixel; + */ + + red += ((pixel_value >> redShift) & redMax); + green += ((pixel_value >> greenShift) & greenMax); + blue += ((pixel_value >> blueShift) & blueMax); + + } + } + /* We now have a total for all of the colors, find the average! */ + red /= area2; + green /= area2; + blue /= area2; + /* Stuff the new value back into memory */ + pixel_value = ((red & redMax) << redShift) | ((green & greenMax) << greenShift) | ((blue & blueMax) << blueShift); + + switch (bytesPerPixel) { + case 4: *((unsigned int *)dstptr) = (unsigned int) pixel_value; break; + case 2: *((unsigned short *)dstptr) = (unsigned short) pixel_value; break; + case 1: *((unsigned char *)dstptr) = (unsigned char) pixel_value; break; + default: + /* fixme: endianess problem? */ + for (z = 0; z < bytesPerPixel; z++) + dstptr[z]=(pixel_value >> (8 * z)) & 0xff; + break; + } + dstptr += bytesPerPixel; + } + srcptr += (screen->paddedWidthInBytes * areaY); + dstptr += (ptr->paddedWidthInBytes - bytesPerLine); + } + } else + { /* Not truecolour, so we can't blend. Just use the top-left pixel instead */ + for (y = y1; y < (y1+h1); y++) { + for (x = x1; x < (x1+w1); x++) + memcpy (&ptr->frameBuffer[(y *ptr->paddedWidthInBytes) + (x * bytesPerPixel)], + &screen->frameBuffer[(y * areaY * screen->paddedWidthInBytes) + (x *areaX * bytesPerPixel)], bytesPerPixel); + } + } +} + +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2) +{ + /* ok, now the task is to update each and every scaled version of the framebuffer + * and we only have to do this for this specific changed rectangle! + */ + rfbScreenInfoPtr ptr; + int count=0; + + /* We don't point to cl->screen as it is the original */ + for (ptr=screen->scaledScreenNext;ptr!=NULL;ptr=ptr->scaledScreenNext) + { + /* Only update if it has active clients... */ + if (ptr->scaledScreenRefCount>0) + { + rfbScaledScreenUpdateRect(screen, ptr, x1, y1, x2-x1, y2-y1); + count++; + } + } +} + +/* Create a new scaled version of the framebuffer */ +rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + ptr = malloc(sizeof(rfbScreenInfo)); + if (ptr!=NULL) + { + /* copy *everything* (we don't use most of it, but just in case) */ + memcpy(ptr, cl->screen, sizeof(rfbScreenInfo)); + ptr->width = width; + ptr->height = height; + ptr->paddedWidthInBytes = (ptr->bitsPerPixel/8)*ptr->width; + + /* Need to by multiples of 4 for Sparc systems */ + ptr->paddedWidthInBytes += (ptr->paddedWidthInBytes % 4); + + /* Reset the reference count to 0! */ + ptr->scaledScreenRefCount = 0; + + ptr->sizeInBytes = ptr->paddedWidthInBytes * ptr->height; + ptr->serverFormat = cl->screen->serverFormat; + + ptr->frameBuffer = malloc(ptr->sizeInBytes); + if (ptr->frameBuffer!=NULL) + { + /* Reset to a known condition: scale the entire framebuffer */ + rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); + /* Now, insert into the chain */ + LOCK(cl->updateMutex); + ptr->scaledScreenNext = cl->screen->scaledScreenNext; + cl->screen->scaledScreenNext = ptr; + UNLOCK(cl->updateMutex); + } + else + { + /* Failed to malloc the new frameBuffer, cleanup */ + free(ptr); + ptr=NULL; + } + } + return ptr; +} + +/* Find an active scaled version of the framebuffer + * TODO: implement a refcount per scaled screen to prevent + * unreferenced scaled screens from hanging around + */ +rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + /* include the original in the search (ie: fine 1:1 scaled version of the frameBuffer) */ + for (ptr=cl->screen; ptr!=NULL; ptr=ptr->scaledScreenNext) + { + if ((ptr->width==width) && (ptr->height==height)) + return ptr; + } + return NULL; +} + +/* Future needs "scale to 320x240, as that's the client's screen size */ +void rfbScalingSetup(rfbClientPtr cl, int width, int height) +{ + rfbScreenInfoPtr ptr; + + ptr = rfbScalingFind(cl,width,height); + if (ptr==NULL) + ptr = rfbScaledScreenAllocate(cl,width,height); + /* Now, there is a new screen available (if ptr is not NULL) */ + if (ptr!=NULL) + { + /* Update it! */ + if (ptr->scaledScreenRefCount<1) + rfbScaledScreenUpdateRect(cl->screen, ptr, 0, 0, cl->screen->width, cl->screen->height); + /* + * rfbLog("Taking one from %dx%d-%d and adding it to %dx%d-%d\n", + * cl->scaledScreen->width, cl->scaledScreen->height, + * cl->scaledScreen->scaledScreenRefCount, + * ptr->width, ptr->height, ptr->scaledScreenRefCount); + */ + + LOCK(cl->updateMutex); + cl->scaledScreen->scaledScreenRefCount--; + ptr->scaledScreenRefCount++; + cl->scaledScreen=ptr; + cl->newFBSizePending = TRUE; + UNLOCK(cl->updateMutex); + + rfbLog("Scaling to %dx%d (refcount=%d)\n",width,height,ptr->scaledScreenRefCount); + } + else + rfbLog("Scaling to %dx%d failed, leaving things alone\n",width,height); +} + +int rfbSendNewScaleSize(rfbClientPtr cl) +{ + /* if the client supports newFBsize Encoding, use it */ + if (cl->useNewFBSize && cl->newFBSizePending) + return FALSE; + + LOCK(cl->updateMutex); + cl->newFBSizePending = FALSE; + UNLOCK(cl->updateMutex); + + if (cl->PalmVNC==TRUE) + { + rfbPalmVNCReSizeFrameBufferMsg pmsg; + pmsg.type = rfbPalmVNCReSizeFrameBuffer; + pmsg.pad1 = 0; + pmsg.desktop_w = Swap16IfLE(cl->screen->width); + pmsg.desktop_h = Swap16IfLE(cl->screen->height); + pmsg.buffer_w = Swap16IfLE(cl->scaledScreen->width); + pmsg.buffer_h = Swap16IfLE(cl->scaledScreen->height); + pmsg.pad2 = 0; + + rfbLog("Sending a response to a PalmVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); + if (rfbWriteExact(cl, (char *)&pmsg, sz_rfbPalmVNCReSizeFrameBufferMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return FALSE; + } + } + else + { + rfbResizeFrameBufferMsg rmsg; + rmsg.type = rfbResizeFrameBuffer; + rmsg.pad1=0; + rmsg.framebufferWidth = Swap16IfLE(cl->scaledScreen->width); + rmsg.framebufferHeigth = Swap16IfLE(cl->scaledScreen->height); + rfbLog("Sending a response to a UltraVNC style frameuffer resize event (%dx%d)\n", cl->scaledScreen->width, cl->scaledScreen->height); + if (rfbWriteExact(cl, (char *)&rmsg, sz_rfbResizeFrameBufferMsg) < 0) { + rfbLogPerror("rfbNewClient: write"); + rfbCloseClient(cl); + rfbClientConnectionGone(cl); + return FALSE; + } + } + return TRUE; +} +/****************************/ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h new file mode 100755 index 0000000..13dd942 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/scale.h @@ -0,0 +1,10 @@ + +int ScaleX(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int x); +int ScaleY(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int y); +void rfbScaledCorrection(rfbScreenInfoPtr from, rfbScreenInfoPtr to, int *x, int *y, int *w, int *h, char *function); +void rfbScaledScreenUpdateRect(rfbScreenInfoPtr screen, rfbScreenInfoPtr ptr, int x0, int y0, int w0, int h0); +void rfbScaledScreenUpdate(rfbScreenInfoPtr screen, int x1, int y1, int x2, int y2); +rfbScreenInfoPtr rfbScaledScreenAllocate(rfbClientPtr cl, int width, int height); +rfbScreenInfoPtr rfbScalingFind(rfbClientPtr cl, int width, int height); +void rfbScalingSetup(rfbClientPtr cl, int width, int height); +int rfbSendNewScaleSize(rfbClientPtr cl); diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c new file mode 100755 index 0000000..bbc6d52 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/selbox.c @@ -0,0 +1,300 @@ +#include +#include +#include + +typedef struct { + rfbScreenInfoPtr screen; + rfbFontDataPtr font; + char** list; + int listSize; + int selected; + int displayStart; + int x1,y1,x2,y2,textH,pageH; + int xhot,yhot; + int buttonWidth,okBX,cancelBX,okX,cancelX,okY; + rfbBool okInverted,cancelInverted; + int lastButtons; + rfbPixel colour,backColour; + SelectionChangedHookPtr selChangedHook; + enum { SELECTING, OK, CANCEL } state; +} rfbSelectData; + +static const char* okStr="OK"; +static const char* cancelStr="Cancel"; + +static void selPaintButtons(rfbSelectData* m,rfbBool invertOk,rfbBool invertCancel) +{ + rfbScreenInfoPtr s = m->screen; + rfbPixel bcolour = m->backColour; + rfbPixel colour = m->colour; + + rfbFillRect(s,m->x1,m->okY-m->textH,m->x2,m->okY,bcolour); + + if(invertOk) { + rfbFillRect(s,m->okBX,m->okY-m->textH,m->okBX+m->buttonWidth,m->okY,colour); + rfbDrawStringWithClip(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr, + m->x1,m->okY-m->textH,m->x2,m->okY, + bcolour,colour); + } else + rfbDrawString(s,m->font,m->okX+m->xhot,m->okY-1+m->yhot,okStr,colour); + + if(invertCancel) { + rfbFillRect(s,m->cancelBX,m->okY-m->textH, + m->cancelBX+m->buttonWidth,m->okY,colour); + rfbDrawStringWithClip(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot, + cancelStr,m->x1,m->okY-m->textH,m->x2,m->okY, + bcolour,colour); + } else + rfbDrawString(s,m->font,m->cancelX+m->xhot,m->okY-1+m->yhot,cancelStr,colour); + + m->okInverted = invertOk; + m->cancelInverted = invertCancel; +} + +/* line is relative to displayStart */ +static void selPaintLine(rfbSelectData* m,int line,rfbBool invert) +{ + int y1 = m->y1+line*m->textH, y2 = y1+m->textH; + if(y2>m->y2) + y2=m->y2; + rfbFillRect(m->screen,m->x1,y1,m->x2,y2,invert?m->colour:m->backColour); + if(m->displayStart+linelistSize) + rfbDrawStringWithClip(m->screen,m->font,m->x1+m->xhot,y2-1+m->yhot, + m->list[m->displayStart+line], + m->x1,y1,m->x2,y2, + invert?m->backColour:m->colour, + invert?m->backColour:m->colour); +} + +static void selSelect(rfbSelectData* m,int _index) +{ + int delta; + + if(_index==m->selected || _index<0 || _index>=m->listSize) + return; + + if(m->selected>=0) + selPaintLine(m,m->selected-m->displayStart,FALSE); + + if(_indexdisplayStart || _index>=m->displayStart+m->pageH) { + /* targetLine is the screen line in which the selected line will + be displayed. + targetLine = m->pageH/2 doesn't look so nice */ + int targetLine = m->selected-m->displayStart; + int lineStart,lineEnd; + + /* scroll */ + if(_indexpageH-targetLine>=m->listSize) + targetLine = _index+m->pageH-m->listSize; + delta = _index-(m->displayStart+targetLine); + + if(delta>-m->pageH && deltapageH) { + if(delta>0) { + lineStart = m->pageH-delta; + lineEnd = m->pageH; + rfbDoCopyRect(m->screen,m->x1,m->y1,m->x2,m->y1+lineStart*m->textH, + 0,-delta*m->textH); + } else { + lineStart = 0; + lineEnd = -delta; + rfbDoCopyRect(m->screen, + m->x1,m->y1+lineEnd*m->textH,m->x2,m->y2, + 0,-delta*m->textH); + } + } else { + lineStart = 0; + lineEnd = m->pageH; + } + m->displayStart += delta; + for(delta=lineStart;deltaselected = _index; + selPaintLine(m,m->selected-m->displayStart,TRUE); + + if(m->selChangedHook) + m->selChangedHook(_index); + + /* todo: scrollbars */ +} + +static void selKbdAddEvent(rfbBool down,rfbKeySym keySym,rfbClientPtr cl) +{ + if(down) { + if(keySym>' ' && keySym<0xff) { + int i; + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + char c = tolower(keySym); + + for(i=m->selected+1;m->list[i] && tolower(m->list[i][0])!=c;i++); + if(!m->list[i]) + for(i=0;iselected && tolower(m->list[i][0])!=c;i++); + selSelect(m,i); + } else if(keySym==XK_Escape) { + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + m->state = CANCEL; + } else if(keySym==XK_Return) { + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + m->state = OK; + } else { + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + int curSel=m->selected; + if(keySym==XK_Up) { + if(curSel>0) + selSelect(m,curSel-1); + } else if(keySym==XK_Down) { + if(curSel+1listSize) + selSelect(m,curSel+1); + } else { + if(keySym==XK_Page_Down) { + if(curSel+m->pageHlistSize) + selSelect(m,curSel+m->pageH); + else + selSelect(m,m->listSize-1); + } else if(keySym==XK_Page_Up) { + if(curSel-m->pageH>=0) + selSelect(m,curSel-m->pageH); + else + selSelect(m,0); + } + } + } + } +} + +static void selPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl) +{ + rfbSelectData* m = (rfbSelectData*)cl->screen->screenData; + if(yokY && y>=m->okY-m->textH) { + if(x>=m->okBX && xokBX+m->buttonWidth) { + if(!m->okInverted) + selPaintButtons(m,TRUE,FALSE); + if(buttonMask) + m->state = OK; + } else if(x>=m->cancelBX && xcancelBX+m->buttonWidth) { + if(!m->cancelInverted) + selPaintButtons(m,FALSE,TRUE); + if(buttonMask) + m->state = CANCEL; + } else if(m->okInverted || m->cancelInverted) + selPaintButtons(m,FALSE,FALSE); + } else { + if(m->okInverted || m->cancelInverted) + selPaintButtons(m,FALSE,FALSE); + if(!m->lastButtons && buttonMask) { + if(x>=m->x1 && xx2 && y>=m->y1 && yy2) + selSelect(m,m->displayStart+(y-m->y1)/m->textH); + } + } + m->lastButtons = buttonMask; + + /* todo: scrollbars */ +} + +static rfbCursorPtr selGetCursorPtr(rfbClientPtr cl) +{ + return NULL; +} + +int rfbSelectBox(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font, + char** list, + int x1,int y1,int x2,int y2, + rfbPixel colour,rfbPixel backColour, + int border,SelectionChangedHookPtr selChangedHook) +{ + int bpp = rfbScreen->bitsPerPixel/8; + char* frameBufferBackup; + void* screenDataBackup = rfbScreen->screenData; + rfbKbdAddEventProcPtr kbdAddEventBackup = rfbScreen->kbdAddEvent; + rfbPtrAddEventProcPtr ptrAddEventBackup = rfbScreen->ptrAddEvent; + rfbGetCursorProcPtr getCursorPtrBackup = rfbScreen->getCursorPtr; + rfbDisplayHookPtr displayHookBackup = rfbScreen->displayHook; + rfbSelectData selData; + int i,j,k; + int fx1,fy1,fx2,fy2; /* for font bbox */ + + if(list==0 || *list==0) + return(-1); + + rfbWholeFontBBox(font, &fx1, &fy1, &fx2, &fy2); + selData.textH = fy2-fy1; + /* I need at least one line for the choice and one for the buttons */ + if(y2-y1screenData = &selData; + rfbScreen->kbdAddEvent = selKbdAddEvent; + rfbScreen->ptrAddEvent = selPtrAddEvent; + rfbScreen->getCursorPtr = selGetCursorPtr; + rfbScreen->displayHook = NULL; + + /* backup screen */ + for(j=0;jframeBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp, + (x2-x1)*bpp); + + /* paint list and buttons */ + rfbFillRect(rfbScreen,x1,y1,x2,y2,colour); + selPaintButtons(&selData,FALSE,FALSE); + selSelect(&selData,0); + + /* modal loop */ + while(selData.state == SELECTING) + rfbProcessEvents(rfbScreen,20000); + + /* copy back screen data */ + for(j=0;jframeBuffer+j*rfbScreen->paddedWidthInBytes+x1*bpp, + frameBufferBackup+j*(x2-x1)*bpp, + (x2-x1)*bpp); + free(frameBufferBackup); + rfbMarkRectAsModified(rfbScreen,x1,y1,x2,y2); + rfbScreen->screenData = screenDataBackup; + rfbScreen->kbdAddEvent = kbdAddEventBackup; + rfbScreen->ptrAddEvent = ptrAddEventBackup; + rfbScreen->getCursorPtr = getCursorPtrBackup; + rfbScreen->displayHook = displayHookBackup; + + if(selData.state==CANCEL) + selData.selected=-1; + return(selData.selected); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c new file mode 100755 index 0000000..c95225f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/sockets.c @@ -0,0 +1,822 @@ +/* + * sockets.c - deal with TCP & UDP sockets. + * + * This code should be independent of any changes in the RFB protocol. It just + * deals with the X server scheduling stuff, calling rfbNewClientConnection and + * rfbProcessClientMessage to actually deal with the protocol. If a socket + * needs to be closed for any reason then rfbCloseClient should be called, and + * this in turn will call rfbClientConnectionGone. To make an active + * connection out, call rfbConnect - note that this does _not_ call + * rfbNewClientConnection. + * + * This file is divided into two types of function. Those beginning with + * "rfb" are specific to sockets using the RFB protocol. Those without the + * "rfb" prefix are more general socket routines (which are used by the http + * code). + * + * Thanks to Karl Hakimian for pointing out that some platforms return EAGAIN + * not EWOULDBLOCK. + */ + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_SOCKET_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#include +#include +#include +#endif +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif + +#if defined(__linux__) && defined(NEED_TIMEVAL) +struct timeval +{ + long int tv_sec,tv_usec; +} +; +#endif + +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif + +#include + +#ifdef USE_LIBWRAP +#include +#include +int allow_severity=LOG_INFO; +int deny_severity=LOG_WARNING; +#endif + +#if defined(WIN32) +#ifndef __MINGW32__ +#pragma warning (disable: 4018 4761) +#endif +#define read(sock,buf,len) recv(sock,buf,len,0) +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ETIMEDOUT WSAETIMEDOUT +#define write(sock,buf,len) send(sock,buf,len,0) +#else +#define closesocket close +#endif + +int rfbMaxClientWait = 20000; /* time (ms) after which we decide client has + gone away - needed to stop us hanging */ + +/* + * rfbInitSockets sets up the TCP and UDP sockets to listen for RFB + * connections. It does nothing if called again. + */ + +void +rfbInitSockets(rfbScreenInfoPtr rfbScreen) +{ + in_addr_t iface = rfbScreen->listenInterface; + + if (rfbScreen->socketState!=RFB_SOCKET_INIT) + return; + + rfbScreen->socketState = RFB_SOCKET_READY; + + if (rfbScreen->inetdSock != -1) { + const int one = 1; + +#ifndef WIN32 + if (fcntl(rfbScreen->inetdSock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl"); + return; + } +#endif + + if (setsockopt(rfbScreen->inetdSock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt"); + return; + } + + FD_ZERO(&(rfbScreen->allFds)); + FD_SET(rfbScreen->inetdSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->inetdSock; + return; + } + + if(rfbScreen->autoPort) { + int i; + rfbLog("Autoprobing TCP port \n"); + for (i = 5900; i < 6000; i++) { + if ((rfbScreen->listenSock = rfbListenOnTCPPort(i, iface)) >= 0) { + rfbScreen->port = i; + break; + } + } + + if (i >= 6000) { + rfbLogPerror("Failure autoprobing"); + return; + } + + rfbLog("Autoprobing selected port %d\n", rfbScreen->port); + FD_ZERO(&(rfbScreen->allFds)); + FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->listenSock; + } + else if(rfbScreen->port>0) { + rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->port); + + if ((rfbScreen->listenSock = rfbListenOnTCPPort(rfbScreen->port, iface)) < 0) { + rfbLogPerror("ListenOnTCPPort"); + return; + } + + FD_ZERO(&(rfbScreen->allFds)); + FD_SET(rfbScreen->listenSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = rfbScreen->listenSock; + } + + if (rfbScreen->udpPort != 0) { + rfbLog("rfbInitSockets: listening for input on UDP port %d\n",rfbScreen->udpPort); + + if ((rfbScreen->udpSock = rfbListenOnUDPPort(rfbScreen->udpPort, iface)) < 0) { + rfbLogPerror("ListenOnUDPPort"); + return; + } + FD_SET(rfbScreen->udpSock, &(rfbScreen->allFds)); + rfbScreen->maxFd = max((int)rfbScreen->udpSock,rfbScreen->maxFd); + } +} + +void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen) +{ + if (rfbScreen->socketState!=RFB_SOCKET_READY) + return; + + rfbScreen->socketState = RFB_SOCKET_SHUTDOWN; + + if(rfbScreen->inetdSock>-1) { + closesocket(rfbScreen->inetdSock); + FD_CLR(rfbScreen->inetdSock,&rfbScreen->allFds); + rfbScreen->inetdSock=-1; + } + + if(rfbScreen->listenSock>-1) { + closesocket(rfbScreen->listenSock); + FD_CLR(rfbScreen->listenSock,&rfbScreen->allFds); + rfbScreen->listenSock=-1; + } + + if(rfbScreen->udpSock>-1) { + closesocket(rfbScreen->udpSock); + FD_CLR(rfbScreen->udpSock,&rfbScreen->allFds); + rfbScreen->udpSock=-1; + } +} + +/* + * rfbCheckFds is called from ProcessInputEvents to check for input on the RFB + * socket(s). If there is input to process, the appropriate function in the + * RFB server code will be called (rfbNewClientConnection, + * rfbProcessClientMessage, etc). + */ + +int +rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec) +{ + int nfds; + fd_set fds; + struct timeval tv; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(addr); + char buf[6]; + const int one = 1; + int sock; + rfbClientIteratorPtr i; + rfbClientPtr cl; + int result = 0; + + if (!rfbScreen->inetdInitDone && rfbScreen->inetdSock != -1) { + rfbNewClientConnection(rfbScreen,rfbScreen->inetdSock); + rfbScreen->inetdInitDone = TRUE; + } + + do { + memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set)); + tv.tv_sec = 0; + tv.tv_usec = usec; + nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv); + if (nfds == 0) { + /* timed out, check for async events */ + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) { + if (cl->onHold) + continue; + if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) + rfbSendFileTransferChunk(cl); + } + rfbReleaseClientIterator(i); + return result; + } + + if (nfds < 0) { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno != EINTR) + rfbLogPerror("rfbCheckFds: select"); + return -1; + } + + result += nfds; + + if (rfbScreen->listenSock != -1 && FD_ISSET(rfbScreen->listenSock, &fds)) { + + if ((sock = accept(rfbScreen->listenSock, + (struct sockaddr *)&addr, &addrlen)) < 0) { + rfbLogPerror("rfbCheckFds: accept"); + return -1; + } + +#ifndef WIN32 + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("rfbCheckFds: fcntl"); + closesocket(sock); + return -1; + } +#endif + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("rfbCheckFds: setsockopt"); + closesocket(sock); + return -1; + } + +#ifdef USE_LIBWRAP + if(!hosts_ctl("vnc",STRING_UNKNOWN,inet_ntoa(addr.sin_addr), + STRING_UNKNOWN)) { + rfbLog("Rejected connection from client %s\n", + inet_ntoa(addr.sin_addr)); + closesocket(sock); + return -1; + } +#endif + + rfbLog("Got connection from client %s\n", inet_ntoa(addr.sin_addr)); + + rfbNewClient(rfbScreen,sock); + + FD_CLR(rfbScreen->listenSock, &fds); + if (--nfds == 0) + return result; + } + + if ((rfbScreen->udpSock != -1) && FD_ISSET(rfbScreen->udpSock, &fds)) { + if(!rfbScreen->udpClient) + rfbNewUDPClient(rfbScreen); + if (recvfrom(rfbScreen->udpSock, buf, 1, MSG_PEEK, + (struct sockaddr *)&addr, &addrlen) < 0) { + rfbLogPerror("rfbCheckFds: UDP: recvfrom"); + rfbDisconnectUDPSock(rfbScreen); + rfbScreen->udpSockConnected = FALSE; + } else { + if (!rfbScreen->udpSockConnected || + (memcmp(&addr, &rfbScreen->udpRemoteAddr, addrlen) != 0)) + { + /* new remote end */ + rfbLog("rfbCheckFds: UDP: got connection\n"); + + memcpy(&rfbScreen->udpRemoteAddr, &addr, addrlen); + rfbScreen->udpSockConnected = TRUE; + + if (connect(rfbScreen->udpSock, + (struct sockaddr *)&addr, addrlen) < 0) { + rfbLogPerror("rfbCheckFds: UDP: connect"); + rfbDisconnectUDPSock(rfbScreen); + return -1; + } + + rfbNewUDPConnection(rfbScreen,rfbScreen->udpSock); + } + + rfbProcessUDPInput(rfbScreen); + } + + FD_CLR(rfbScreen->udpSock, &fds); + if (--nfds == 0) + return result; + } + + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) { + + if (cl->onHold) + continue; + + if (FD_ISSET(cl->sock, &(rfbScreen->allFds))) + { + if (FD_ISSET(cl->sock, &fds)) + rfbProcessClientMessage(cl); + else + rfbSendFileTransferChunk(cl); + } + } + rfbReleaseClientIterator(i); + } while(rfbScreen->handleEventsEagerly); + return result; +} + + +void +rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen) +{ + rfbScreen->udpSockConnected = FALSE; +} + + + +void +rfbCloseClient(rfbClientPtr cl) +{ + rfbExtensionData* extension; + + for(extension=cl->extensions; extension; extension=extension->next) + if(extension->extension->close) + extension->extension->close(cl, extension->data); + + LOCK(cl->updateMutex); +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + if (cl->sock != -1) +#endif + { + FD_CLR(cl->sock,&(cl->screen->allFds)); + if(cl->sock==cl->screen->maxFd) + while(cl->screen->maxFd>0 + && !FD_ISSET(cl->screen->maxFd,&(cl->screen->allFds))) + cl->screen->maxFd--; +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) { + SSL_free(cl->ssl); + } + if (cl->ssl_ctx) { + SSL_CTX_free(cl->ssl_ctx); + } +#endif +#ifndef __MINGW32__ + shutdown(cl->sock,SHUT_RDWR); +#endif + closesocket(cl->sock); + cl->sock = -1; + } + TSIGNAL(cl->updateCond); + UNLOCK(cl->updateMutex); +} + + +/* + * rfbConnect is called to make a connection out to a given TCP address. + */ + +int +rfbConnect(rfbScreenInfoPtr rfbScreen, + char *host, + int port) +{ + int sock; + int one = 1; + + rfbLog("Making connection to client on host %s port %d\n", + host,port); + + if ((sock = rfbConnectToTcpAddr(host, port)) < 0) { + rfbLogPerror("connection failed"); + return -1; + } + +#ifndef WIN32 + if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) { + rfbLogPerror("fcntl failed"); + closesocket(sock); + return -1; + } +#endif + + if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + (char *)&one, sizeof(one)) < 0) { + rfbLogPerror("setsockopt failed"); + closesocket(sock); + return -1; + } + + /* AddEnabledDevice(sock); */ + FD_SET(sock, &rfbScreen->allFds); + rfbScreen->maxFd = max(sock,rfbScreen->maxFd); + + return sock; +} + +/* + * ReadExact reads an exact number of bytes from a client. Returns 1 if + * those bytes have been read, 0 if the other end has closed, or -1 if an error + * occurred (errno is set to ETIMEDOUT if it timed out). + */ + +int +rfbReadExactTimeout(rfbClientPtr cl, char* buf, int len, int timeout) +{ +// rfbLog(">> rfbReadExactTimeout, len: %d\n", len); + int sock = cl->sock; + int n; + char *end; + fd_set fds; + struct timeval tv; + + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->webSockets) { + n = webSocketsDecode(cl, buf, len); + } else if (cl->ssl) { + n = SSL_read(cl->ssl, buf, len); + } else { + n = read(sock, buf, len); + } +#else + n = read(sock, buf, len); +#endif + + if (n > 0) { + + buf += n; + len -= n; + + } else if (n == 0) { + + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + if (errno != ENOENT) +#endif + if (errno != EWOULDBLOCK && errno != EAGAIN) { + return n; + } + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) { + if (SSL_pending(cl->ssl)) + continue; + } +#endif + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + n = select(sock+1, &fds, NULL, &fds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); + return n; + } + if (n == 0) { + errno = ETIMEDOUT; + return -1; + } + } + } + +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + rfbLog("ReadExact %d bytes\n",len); + for(n=0;nsock; + int n; + fd_set fds; + struct timeval tv; + + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) + n = SSL_peek(cl->ssl, buf, len); + else + n = recv(sock, buf, len, MSG_PEEK); +#endif + if (n == len) { + + break; + + } else if (n == 0) { + + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + +#ifdef LIBVNCSERVER_ENOENT_WORKAROUND + if (errno != ENOENT) +#endif + if (errno != EWOULDBLOCK && errno != EAGAIN) { + return n; + } + + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + n = select(sock+1, &fds, NULL, &fds, &tv); + if (n < 0) { + rfbLogPerror("ReadExact: select"); + return n; + } + if (n == 0) { + errno = ETIMEDOUT; + return -1; + } + } + } +#undef DEBUG_READ_EXACT +#ifdef DEBUG_READ_EXACT + rfbLog("ReadExact %d bytes\n",len); + for(n=0;n> rfbWriteExact, len: %d\n", len); + int sock = cl->sock; + int n; + fd_set fds; + struct timeval tv; + int totalTimeWaited = 0; + +#undef DEBUG_WRITE_EXACT +#ifdef DEBUG_WRITE_EXACT + rfbLog("WriteExact %d bytes\n",len); + for(n=0;nwebSockets) { + if ((len = webSocketsEncode(cl, buf, len)) < 0) { + rfbErr("WriteExact: WebSockets encode error\n"); + return -1; + } + buf = cl->encodeBuf; + } +#endif + + LOCK(cl->outputMutex); + while (len > 0) { +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + if (cl->ssl) { + n = SSL_write(cl->ssl, buf, len); + } else { + n = write(sock, buf, len); + } +#endif + + if (n > 0) { + + buf += n; + len -= n; + + } else if (n == 0) { + + rfbErr("WriteExact: write returned 0?\n"); + return 0; + + } else { +#ifdef WIN32 + errno = WSAGetLastError(); +#endif + if (errno == EINTR) + continue; + + if (errno != EWOULDBLOCK && errno != EAGAIN) { + UNLOCK(cl->outputMutex); + return n; + } + + /* Retry every 5 seconds until we exceed rfbMaxClientWait. We + need to do this because select doesn't necessarily return + immediately when the other end has gone away */ + + FD_ZERO(&fds); + FD_SET(sock, &fds); + tv.tv_sec = 5; + tv.tv_usec = 0; + n = select(sock+1, NULL, &fds, NULL /* &fds */, &tv); + if (n < 0) { + if(errno==EINTR) + continue; + rfbLogPerror("WriteExact: select"); + UNLOCK(cl->outputMutex); + return n; + } + if (n == 0) { + totalTimeWaited += 5000; + if (totalTimeWaited >= rfbMaxClientWait) { + errno = ETIMEDOUT; + UNLOCK(cl->outputMutex); + return -1; + } + } else { + totalTimeWaited = 0; + } + } + } + UNLOCK(cl->outputMutex); +// rfbLog("<< rfbWriteExact, len: %d\n", len); + return 1; +} + +/* currently private, called by rfbProcessArguments() */ +int +rfbStringToAddr(char *str, in_addr_t *addr) { + if (str == NULL || *str == '\0' || strcmp(str, "any") == 0) { + *addr = htonl(INADDR_ANY); + } else if (strcmp(str, "localhost") == 0) { + *addr = htonl(INADDR_LOOPBACK); + } else { + struct hostent *hp; + if ((*addr = inet_addr(str)) == htonl(INADDR_NONE)) { + if (!(hp = gethostbyname(str))) { + return 0; + } + *addr = *(unsigned long *)hp->h_addr; + } + } + return 1; +} + +int +rfbListenOnTCPPort(int port, + in_addr_t iface) +{ + struct sockaddr_in addr; + int sock; + int one = 1; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = iface; + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return -1; + } + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&one, sizeof(one)) < 0) { + closesocket(sock); + return -1; + } + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + closesocket(sock); + return -1; + } + if (listen(sock, 32) < 0) { + closesocket(sock); + return -1; + } + + return sock; +} + +int +rfbConnectToTcpAddr(char *host, + int port) +{ + struct hostent *hp; + int sock; + struct sockaddr_in addr; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + + if ((addr.sin_addr.s_addr = inet_addr(host)) == htonl(INADDR_NONE)) + { + if (!(hp = gethostbyname(host))) { + errno = EINVAL; + return -1; + } + addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr; + } + + if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return -1; + } + + if (connect(sock, (struct sockaddr *)&addr, (sizeof(addr))) < 0) { + closesocket(sock); + return -1; + } + + return sock; +} + +int +rfbListenOnUDPPort(int port, + in_addr_t iface) +{ + struct sockaddr_in addr; + int sock; + int one = 1; + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + addr.sin_addr.s_addr = iface; + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + return -1; + } + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&one, sizeof(one)) < 0) { + return -1; + } + if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + return -1; + } + + return sock; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c new file mode 100755 index 0000000..9763ce4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/stats.c @@ -0,0 +1,479 @@ +/* + * stats.c + */ + +/* + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +char *messageNameServer2Client(uint32_t type, char *buf, int len); +char *messageNameClient2Server(uint32_t type, char *buf, int len); +char *encodingName(uint32_t enc, char *buf, int len); + +rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); +rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); + +void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +void rfbResetStats(rfbClientPtr cl); +void rfbPrintStats(rfbClientPtr cl); + + + + +char *messageNameServer2Client(uint32_t type, char *buf, int len) { + if (buf==NULL) return "error"; + switch (type) { + case rfbFramebufferUpdate: snprintf(buf, len, "FramebufferUpdate"); break; + case rfbSetColourMapEntries: snprintf(buf, len, "SetColourMapEntries"); break; + case rfbBell: snprintf(buf, len, "Bell"); break; + case rfbServerCutText: snprintf(buf, len, "ServerCutText"); break; + case rfbResizeFrameBuffer: snprintf(buf, len, "ResizeFrameBuffer"); break; + case rfbKeyFrameUpdate: snprintf(buf, len, "KeyFrameUpdate"); break; + case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; + case rfbTextChat: snprintf(buf, len, "TextChat"); break; + case rfbPalmVNCReSizeFrameBuffer: snprintf(buf, len, "PalmVNCReSize"); break; + default: + snprintf(buf, len, "svr2cli-0x%08X", 0xFF); + } + return buf; +} + +char *messageNameClient2Server(uint32_t type, char *buf, int len) { + if (buf==NULL) return "error"; + switch (type) { + case rfbSetPixelFormat: snprintf(buf, len, "SetPixelFormat"); break; + case rfbFixColourMapEntries: snprintf(buf, len, "FixColourMapEntries"); break; + case rfbSetEncodings: snprintf(buf, len, "SetEncodings"); break; + case rfbFramebufferUpdateRequest: snprintf(buf, len, "FramebufferUpdate"); break; + case rfbKeyEvent: snprintf(buf, len, "KeyEvent"); break; + case rfbPointerEvent: snprintf(buf, len, "PointerEvent"); break; + case rfbClientCutText: snprintf(buf, len, "ClientCutText"); break; + case rfbFileTransfer: snprintf(buf, len, "FileTransfer"); break; + case rfbSetScale: snprintf(buf, len, "SetScale"); break; + case rfbSetServerInput: snprintf(buf, len, "SetServerInput"); break; + case rfbSetSW: snprintf(buf, len, "SetSingleWindow"); break; + case rfbTextChat: snprintf(buf, len, "TextChat"); break; + case rfbKeyFrameRequest: snprintf(buf, len, "KeyFrameRequest"); break; + case rfbPalmVNCSetScaleFactor: snprintf(buf, len, "PalmVNCSetScale"); break; + default: + snprintf(buf, len, "cli2svr-0x%08X", type); + + + } + return buf; +} + +/* Encoding name must be <=16 characters to fit nicely on the status output in + * an 80 column terminal window + */ +char *encodingName(uint32_t type, char *buf, int len) { + if (buf==NULL) return "error"; + + switch (type) { + case rfbEncodingRaw: snprintf(buf, len, "raw"); break; + case rfbEncodingCopyRect: snprintf(buf, len, "copyRect"); break; + case rfbEncodingRRE: snprintf(buf, len, "RRE"); break; + case rfbEncodingCoRRE: snprintf(buf, len, "CoRRE"); break; + case rfbEncodingHextile: snprintf(buf, len, "hextile"); break; + case rfbEncodingZlib: snprintf(buf, len, "zlib"); break; + case rfbEncodingTight: snprintf(buf, len, "tight"); break; + case rfbEncodingTightPng: snprintf(buf, len, "tightPng"); break; + case rfbEncodingZlibHex: snprintf(buf, len, "zlibhex"); break; + case rfbEncodingUltra: snprintf(buf, len, "ultra"); break; + case rfbEncodingZRLE: snprintf(buf, len, "ZRLE"); break; + case rfbEncodingZYWRLE: snprintf(buf, len, "ZYWRLE"); break; + case rfbEncodingCache: snprintf(buf, len, "cache"); break; + case rfbEncodingCacheEnable: snprintf(buf, len, "cacheEnable"); break; + case rfbEncodingXOR_Zlib: snprintf(buf, len, "xorZlib"); break; + case rfbEncodingXORMonoColor_Zlib: snprintf(buf, len, "xorMonoZlib"); break; + case rfbEncodingXORMultiColor_Zlib: snprintf(buf, len, "xorColorZlib"); break; + case rfbEncodingSolidColor: snprintf(buf, len, "solidColor"); break; + case rfbEncodingXOREnable: snprintf(buf, len, "xorEnable"); break; + case rfbEncodingCacheZip: snprintf(buf, len, "cacheZip"); break; + case rfbEncodingSolMonoZip: snprintf(buf, len, "monoZip"); break; + case rfbEncodingUltraZip: snprintf(buf, len, "ultraZip"); break; + + case rfbEncodingXCursor: snprintf(buf, len, "Xcursor"); break; + case rfbEncodingRichCursor: snprintf(buf, len, "RichCursor"); break; + case rfbEncodingPointerPos: snprintf(buf, len, "PointerPos"); break; + + case rfbEncodingLastRect: snprintf(buf, len, "LastRect"); break; + case rfbEncodingNewFBSize: snprintf(buf, len, "NewFBSize"); break; + case rfbEncodingKeyboardLedState: snprintf(buf, len, "LedState"); break; + case rfbEncodingSupportedMessages: snprintf(buf, len, "SupportedMessage"); break; + case rfbEncodingSupportedEncodings: snprintf(buf, len, "SupportedEncoding"); break; + case rfbEncodingServerIdentity: snprintf(buf, len, "ServerIdentify"); break; + + /* The following lookups do not report in stats */ + case rfbEncodingCompressLevel0: snprintf(buf, len, "CompressLevel0"); break; + case rfbEncodingCompressLevel1: snprintf(buf, len, "CompressLevel1"); break; + case rfbEncodingCompressLevel2: snprintf(buf, len, "CompressLevel2"); break; + case rfbEncodingCompressLevel3: snprintf(buf, len, "CompressLevel3"); break; + case rfbEncodingCompressLevel4: snprintf(buf, len, "CompressLevel4"); break; + case rfbEncodingCompressLevel5: snprintf(buf, len, "CompressLevel5"); break; + case rfbEncodingCompressLevel6: snprintf(buf, len, "CompressLevel6"); break; + case rfbEncodingCompressLevel7: snprintf(buf, len, "CompressLevel7"); break; + case rfbEncodingCompressLevel8: snprintf(buf, len, "CompressLevel8"); break; + case rfbEncodingCompressLevel9: snprintf(buf, len, "CompressLevel9"); break; + + case rfbEncodingQualityLevel0: snprintf(buf, len, "QualityLevel0"); break; + case rfbEncodingQualityLevel1: snprintf(buf, len, "QualityLevel1"); break; + case rfbEncodingQualityLevel2: snprintf(buf, len, "QualityLevel2"); break; + case rfbEncodingQualityLevel3: snprintf(buf, len, "QualityLevel3"); break; + case rfbEncodingQualityLevel4: snprintf(buf, len, "QualityLevel4"); break; + case rfbEncodingQualityLevel5: snprintf(buf, len, "QualityLevel5"); break; + case rfbEncodingQualityLevel6: snprintf(buf, len, "QualityLevel6"); break; + case rfbEncodingQualityLevel7: snprintf(buf, len, "QualityLevel7"); break; + case rfbEncodingQualityLevel8: snprintf(buf, len, "QualityLevel8"); break; + case rfbEncodingQualityLevel9: snprintf(buf, len, "QualityLevel9"); break; + + + default: + snprintf(buf, len, "Enc(0x%08X)", type); + } + + return buf; +} + + + + + +rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr; + if (cl==NULL) return NULL; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + { + if (ptr->type==type) return ptr; + } + /* Well, we are here... need to *CREATE* an entry */ + ptr = (rfbStatList *)malloc(sizeof(rfbStatList)); + if (ptr!=NULL) + { + memset((char *)ptr, 0, sizeof(rfbStatList)); + ptr->type = type; + /* add to the top of the list */ + ptr->Next = cl->statEncList; + cl->statEncList = ptr; + } + return ptr; +} + + +rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr; + if (cl==NULL) return NULL; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + { + if (ptr->type==type) return ptr; + } + /* Well, we are here... need to *CREATE* an entry */ + ptr = (rfbStatList *)malloc(sizeof(rfbStatList)); + if (ptr!=NULL) + { + memset((char *)ptr, 0, sizeof(rfbStatList)); + ptr->type = type; + /* add to the top of the list */ + ptr->Next = cl->statMsgList; + cl->statMsgList = ptr; + } + return ptr; +} + +void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount) /* Specifically for tight encoding */ +{ + rfbStatList *ptr; + + ptr = rfbStatLookupEncoding(cl, type); + if (ptr!=NULL) + ptr->bytesSent += byteCount; +} + + +void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupEncoding(cl, type); + if (ptr!=NULL) + { + ptr->sentCount++; + ptr->bytesSent += byteCount; + ptr->bytesSentIfRaw += byteIfRaw; + } +} + +void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupEncoding(cl, type); + if (ptr!=NULL) + { + ptr->rcvdCount++; + ptr->bytesRcvd += byteCount; + ptr->bytesRcvdIfRaw += byteIfRaw; + } +} + +void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupMessage(cl, type); + if (ptr!=NULL) + { + ptr->sentCount++; + ptr->bytesSent += byteCount; + ptr->bytesSentIfRaw += byteIfRaw; + } +} + +void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw) +{ + rfbStatList *ptr; + + ptr = rfbStatLookupMessage(cl, type); + if (ptr!=NULL) + { + ptr->rcvdCount++; + ptr->bytesRcvd += byteCount; + ptr->bytesRcvdIfRaw += byteIfRaw; + } +} + + +int rfbStatGetSentBytes(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSent; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSent; + return bytes; +} + +int rfbStatGetSentBytesIfRaw(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSentIfRaw; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesSentIfRaw; + return bytes; +} + +int rfbStatGetRcvdBytes(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvd; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvd; + return bytes; +} + +int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + int bytes=0; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvdIfRaw; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + bytes += ptr->bytesRcvdIfRaw; + return bytes; +} + +int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->sentCount; + return 0; +} +int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->rcvdCount; + return 0; +} + +int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->sentCount; + return 0; +} +int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type) +{ + rfbStatList *ptr=NULL; + if (cl==NULL) return 0; + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + if (ptr->type==type) return ptr->rcvdCount; + return 0; +} + + + + +void rfbResetStats(rfbClientPtr cl) +{ + rfbStatList *ptr; + if (cl==NULL) return; + while (cl->statEncList!=NULL) + { + ptr = cl->statEncList; + cl->statEncList = ptr->Next; + free(ptr); + } + while (cl->statMsgList!=NULL) + { + ptr = cl->statMsgList; + cl->statMsgList = ptr->Next; + free(ptr); + } +} + + +void rfbPrintStats(rfbClientPtr cl) +{ + rfbStatList *ptr=NULL; + char encBuf[64]; + double savings=0.0; + int totalRects=0; + double totalBytes=0.0; + double totalBytesIfRaw=0.0; + + char *name=NULL; + int bytes=0; + int bytesIfRaw=0; + int count=0; + + if (cl==NULL) return; + + rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Transmit","RawEquiv","saved"); + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + { + name = messageNameServer2Client(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->sentCount; + bytes = ptr->bytesSent; + bytesIfRaw = ptr->bytesSentIfRaw; + + savings = 0.0; + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + { + name = encodingName(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->sentCount; + bytes = ptr->bytesSent; + bytesIfRaw = ptr->bytesSentIfRaw; + savings = 0.0; + + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + savings=0.0; + if (totalBytesIfRaw>0.0) + savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); + rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", + "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); + + totalRects=0.0; + totalBytes=0.0; + totalBytesIfRaw=0.0; + + rfbLog("%-21.21s %-6.6s %9.9s/%9.9s (%6.6s)\n", "Statistics", "events", "Received","RawEquiv","saved"); + for (ptr = cl->statMsgList; ptr!=NULL; ptr=ptr->Next) + { + name = messageNameClient2Server(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->rcvdCount; + bytes = ptr->bytesRcvd; + bytesIfRaw = ptr->bytesRcvdIfRaw; + savings = 0.0; + + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + for (ptr = cl->statEncList; ptr!=NULL; ptr=ptr->Next) + { + name = encodingName(ptr->type, encBuf, sizeof(encBuf)); + count = ptr->rcvdCount; + bytes = ptr->bytesRcvd; + bytesIfRaw = ptr->bytesRcvdIfRaw; + savings = 0.0; + + if (bytesIfRaw>0.0) + savings = 100.0 - (((double)bytes / (double)bytesIfRaw) * 100.0); + if ((bytes>0) || (count>0) || (bytesIfRaw>0)) + rfbLog(" %-20.20s: %6d | %9d/%9d (%5.1f%%)\n", + name, count, bytes, bytesIfRaw, savings); + totalRects += count; + totalBytes += bytes; + totalBytesIfRaw += bytesIfRaw; + } + savings=0.0; + if (totalBytesIfRaw>0.0) + savings = 100.0 - ((totalBytes/totalBytesIfRaw)*100.0); + rfbLog(" %-20.20s: %6d | %9.0f/%9.0f (%5.1f%%)\n", + "TOTALS", totalRects, totalBytes,totalBytesIfRaw, savings); + +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c new file mode 100755 index 0000000..39e9920 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinit24.c @@ -0,0 +1,157 @@ +/* + 24 bit + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +static void +rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift,int swap); + + +static void +rfbInitColourMapSingleTable24(char **table, rfbPixelFormat *in, + rfbPixelFormat *out,rfbColourMap* colourMap) +{ + uint32_t i, r, g, b, outValue; + uint8_t *t; + uint8_t c; + unsigned int nEntries = 1 << in->bitsPerPixel; + int shift = colourMap->is16?16:8; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * 3 + 1); + t = (uint8_t *)*table; + + for (i = 0; i < nEntries; i++) { + r = g = b = 0; + if(i < colourMap->count) { + if(colourMap->is16) { + r = colourMap->data.shorts[3*i+0]; + g = colourMap->data.shorts[3*i+1]; + b = colourMap->data.shorts[3*i+2]; + } else { + r = colourMap->data.bytes[3*i+0]; + g = colourMap->data.bytes[3*i+1]; + b = colourMap->data.bytes[3*i+2]; + } + } + outValue = ((((r * (1 + out->redMax)) >> shift) << out->redShift) | + (((g * (1 + out->greenMax)) >> shift) << out->greenShift) | + (((b * (1 + out->blueMax)) >> shift) << out->blueShift)); + *(uint32_t*)&t[3*i] = outValue; + if(!rfbEndianTest) + memmove(t+3*i,t+3*i+1,3); + if (out->bigEndian != in->bigEndian) { + c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c; + } + } +} + +/* + * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour + * translation. + */ + +static void +rfbInitTrueColourSingleTable24 (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + int i,outValue; + int inRed, inGreen, inBlue, outRed, outGreen, outBlue; + uint8_t *t; + uint8_t c; + int nEntries = 1 << in->bitsPerPixel; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * 3 + 1); + t = (uint8_t *)*table; + + for (i = 0; i < nEntries; i++) { + inRed = (i >> in->redShift) & in->redMax; + inGreen = (i >> in->greenShift) & in->greenMax; + inBlue = (i >> in->blueShift) & in->blueMax; + + outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; + outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; + outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; + + outValue = ((outRed << out->redShift) | + (outGreen << out->greenShift) | + (outBlue << out->blueShift)); + *(uint32_t*)&t[3*i] = outValue; + if(!rfbEndianTest) + memmove(t+3*i,t+3*i+1,3); + if (out->bigEndian != in->bigEndian) { + c = t[3*i]; t[3*i] = t[3*i+2]; t[3*i+2] = c; + } + } +} + + +/* + * rfbInitTrueColourRGBTables sets up three separate lookup tables for the + * red, green and blue values. + */ + +static void +rfbInitTrueColourRGBTables24 (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + uint8_t *redTable; + uint8_t *greenTable; + uint8_t *blueTable; + + if (*table) free(*table); + *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) + * 3 + 1); + redTable = (uint8_t *)*table; + greenTable = redTable + 3*(in->redMax + 1); + blueTable = greenTable + 3*(in->greenMax + 1); + + rfbInitOneRGBTable24 (redTable, in->redMax, out->redMax, + out->redShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTable24 (greenTable, in->greenMax, out->greenMax, + out->greenShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTable24 (blueTable, in->blueMax, out->blueMax, + out->blueShift, (out->bigEndian != in->bigEndian)); +} + +static void +rfbInitOneRGBTable24 (uint8_t *table, int inMax, int outMax, int outShift, + int swap) +{ + int i; + int nEntries = inMax + 1; + uint32_t outValue; + uint8_t c; + + for (i = 0; i < nEntries; i++) { + outValue = ((i * outMax + inMax / 2) / inMax) << outShift; + *(uint32_t *)&table[3*i] = outValue; + if(!rfbEndianTest) + memmove(table+3*i,table+3*i+1,3); + if (swap) { + c = table[3*i]; table[3*i] = table[3*i+2]; + table[3*i+2] = c; + } + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c new file mode 100755 index 0000000..df01b23 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinitcmtemplate.c @@ -0,0 +1,84 @@ +/* + * tableinitcmtemplate.c - template for initialising lookup tables for + * translation from a colour map to true colour. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with a different definition of the macro OUT. + * For each value of OUT, this file defines a function which allocates an + * appropriately sized lookup table and initialises it. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if !defined(OUT) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#define OUT_T CONCAT3E(uint,OUT,_t) +#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) +#define rfbInitColourMapSingleTableOUT \ + CONCAT2E(rfbInitColourMapSingleTable,OUT) + +static void +rfbInitColourMapSingleTableOUT(char **table, rfbPixelFormat *in, + rfbPixelFormat *out,rfbColourMap* colourMap) +{ + uint32_t i, r, g, b; + OUT_T *t; + uint32_t nEntries = 1 << in->bitsPerPixel; + int shift = colourMap->is16?16:8; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * sizeof(OUT_T)); + t = (OUT_T *)*table; + + for (i = 0; i < nEntries; i++) { + r = g = b = 0; + if(i < colourMap->count) { + if(colourMap->is16) { + r = colourMap->data.shorts[3*i+0]; + g = colourMap->data.shorts[3*i+1]; + b = colourMap->data.shorts[3*i+2]; + } else { + r = colourMap->data.bytes[3*i+0]; + g = colourMap->data.bytes[3*i+1]; + b = colourMap->data.bytes[3*i+2]; + } + } + t[i] = ((((r * (1 + out->redMax)) >> shift) << out->redShift) | + (((g * (1 + out->greenMax)) >> shift) << out->greenShift) | + (((b * (1 + out->blueMax)) >> shift) << out->blueShift)); +#if (OUT != 8) + if (out->bigEndian != in->bigEndian) { + t[i] = SwapOUT(t[i]); + } +#endif + } +} + +#undef OUT_T +#undef SwapOUT +#undef rfbInitColourMapSingleTableOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c new file mode 100755 index 0000000..8d4f742 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tableinittctemplate.c @@ -0,0 +1,142 @@ +/* + * tableinittctemplate.c - template for initialising lookup tables for + * truecolour to truecolour translation. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with a different definition of the macro OUT. + * For each value of OUT, this file defines two functions for initialising + * lookup tables. One is for truecolour translation using a single lookup + * table, the other is for truecolour translation using three separate + * lookup tables for the red, green and blue values. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if !defined(OUT) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#define OUT_T CONCAT3E(uint,OUT,_t) +#define SwapOUT(x) CONCAT2E(Swap,OUT(x)) +#define rfbInitTrueColourSingleTableOUT \ + CONCAT2E(rfbInitTrueColourSingleTable,OUT) +#define rfbInitTrueColourRGBTablesOUT CONCAT2E(rfbInitTrueColourRGBTables,OUT) +#define rfbInitOneRGBTableOUT CONCAT2E(rfbInitOneRGBTable,OUT) + +static void +rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, + int swap); + + +/* + * rfbInitTrueColourSingleTable sets up a single lookup table for truecolour + * translation. + */ + +static void +rfbInitTrueColourSingleTableOUT (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + int i; + int inRed, inGreen, inBlue, outRed, outGreen, outBlue; + OUT_T *t; + int nEntries = 1 << in->bitsPerPixel; + + if (*table) free(*table); + *table = (char *)malloc(nEntries * sizeof(OUT_T)); + t = (OUT_T *)*table; + + for (i = 0; i < nEntries; i++) { + inRed = (i >> in->redShift) & in->redMax; + inGreen = (i >> in->greenShift) & in->greenMax; + inBlue = (i >> in->blueShift) & in->blueMax; + + outRed = (inRed * out->redMax + in->redMax / 2) / in->redMax; + outGreen = (inGreen * out->greenMax + in->greenMax / 2) / in->greenMax; + outBlue = (inBlue * out->blueMax + in->blueMax / 2) / in->blueMax; + + t[i] = ((outRed << out->redShift) | + (outGreen << out->greenShift) | + (outBlue << out->blueShift)); +#if (OUT != 8) + if (out->bigEndian != in->bigEndian) { + t[i] = SwapOUT(t[i]); + } +#endif + } +} + + +/* + * rfbInitTrueColourRGBTables sets up three separate lookup tables for the + * red, green and blue values. + */ + +static void +rfbInitTrueColourRGBTablesOUT (char **table, rfbPixelFormat *in, + rfbPixelFormat *out) +{ + OUT_T *redTable; + OUT_T *greenTable; + OUT_T *blueTable; + + if (*table) free(*table); + *table = (char *)malloc((in->redMax + in->greenMax + in->blueMax + 3) + * sizeof(OUT_T)); + redTable = (OUT_T *)*table; + greenTable = redTable + in->redMax + 1; + blueTable = greenTable + in->greenMax + 1; + + rfbInitOneRGBTableOUT (redTable, in->redMax, out->redMax, + out->redShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTableOUT (greenTable, in->greenMax, out->greenMax, + out->greenShift, (out->bigEndian != in->bigEndian)); + rfbInitOneRGBTableOUT (blueTable, in->blueMax, out->blueMax, + out->blueShift, (out->bigEndian != in->bigEndian)); +} + +static void +rfbInitOneRGBTableOUT (OUT_T *table, int inMax, int outMax, int outShift, + int swap) +{ + int i; + int nEntries = inMax + 1; + + for (i = 0; i < nEntries; i++) { + table[i] = ((i * outMax + inMax / 2) / inMax) << outShift; +#if (OUT != 8) + if (swap) { + table[i] = SwapOUT(table[i]); + } +#endif + } +} + +#undef OUT_T +#undef SwapOUT +#undef rfbInitTrueColourSingleTableOUT +#undef rfbInitTrueColourRGBTablesOUT +#undef rfbInitOneRGBTableOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c new file mode 100755 index 0000000..4b3a0a0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletrans24template.c @@ -0,0 +1,281 @@ +/* + * tabletranstemplate.c - template for translation using lookup tables. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with different definitions of the macros IN and OUT. + * + * For each pair of values IN and OUT, this file defines two functions for + * translating a given rectangle of pixel data. One uses a single lookup + * table, and the other uses three separate lookup tables for the red, green + * and blue values. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if !defined(BPP) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#if BPP == 24 + +/* + * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTable24to24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines - width * 3; + uint8_t *opLineEnd; + uint8_t *t = (uint8_t *)table; + int shift = rfbEndianTest?0:8; + uint8_t c; + + while (height > 0) { + opLineEnd = op + width*3; + + while (op < opLineEnd) { + *(uint32_t*)op = t[((*(uint32_t *)ip)>>shift)&0x00ffffff]; + if(!rfbEndianTest) + memmove(op,op+1,3); + if (out->bigEndian != in->bigEndian) { + c = op[0]; op[0] = op[2]; op[2] = c; + } + op += 3; + ip += 3; + } + + ip += ipextra; + height--; + } +} + +/* + * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTables24to24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines - width*3; + uint8_t *opLineEnd; + uint8_t *redTable = (uint8_t *)table; + uint8_t *greenTable = redTable + 3*(in->redMax + 1); + uint8_t *blueTable = greenTable + 3*(in->greenMax + 1); + uint32_t outValue,inValue; + int shift = rfbEndianTest?0:8; + + while (height > 0) { + opLineEnd = op+3*width; + + while (op < opLineEnd) { + inValue = ((*(uint32_t *)ip)>>shift)&0x00ffffff; + outValue = (redTable[(inValue >> in->redShift) & in->redMax] | + greenTable[(inValue >> in->greenShift) & in->greenMax] | + blueTable[(inValue >> in->blueShift) & in->blueMax]); + memcpy(op,&outValue,3); + op += 3; + ip+=3; + } + ip += ipextra; + height--; + } +} + +#else + +#define IN_T CONCAT3E(uint,BPP,_t) +#define OUT_T CONCAT3E(uint,BPP,_t) +#define rfbTranslateWithSingleTable24toOUT \ + CONCAT4E(rfbTranslateWithSingleTable,24,to,BPP) +#define rfbTranslateWithSingleTableINto24 \ + CONCAT4E(rfbTranslateWithSingleTable,BPP,to,24) +#define rfbTranslateWithRGBTables24toOUT \ + CONCAT4E(rfbTranslateWithRGBTables,24,to,BPP) +#define rfbTranslateWithRGBTablesINto24 \ + CONCAT4E(rfbTranslateWithRGBTables,BPP,to,24) + +/* + * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTable24toOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines - width*3; + OUT_T *opLineEnd; + OUT_T *t = (OUT_T *)table; + int shift = rfbEndianTest?0:8; + + while (height > 0) { + opLineEnd = op + width; + + while (op < opLineEnd) { + *(op++) = t[((*(uint32_t *)ip)>>shift)&0x00ffffff]; + ip+=3; + } + + ip += ipextra; + height--; + } +} + + +/* + * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTables24toOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + uint8_t *ip = (uint8_t *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines - width*3; + OUT_T *opLineEnd; + OUT_T *redTable = (OUT_T *)table; + OUT_T *greenTable = redTable + in->redMax + 1; + OUT_T *blueTable = greenTable + in->greenMax + 1; + uint32_t inValue; + int shift = rfbEndianTest?0:8; + + while (height > 0) { + opLineEnd = &op[width]; + + while (op < opLineEnd) { + inValue = ((*(uint32_t *)ip)>>shift)&0x00ffffff; + *(op++) = (redTable[(inValue >> in->redShift) & in->redMax] | + greenTable[(inValue >> in->greenShift) & in->greenMax] | + blueTable[(inValue >> in->blueShift) & in->blueMax]); + ip+=3; + } + ip += ipextra; + height--; + } +} + +/* + * rfbTranslateWithSingleTableINto24 translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTableINto24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + uint8_t *opLineEnd; + uint8_t *t = (uint8_t *)table; + + while (height > 0) { + opLineEnd = op + width * 3; + + while (op < opLineEnd) { + memcpy(op,&t[3*(*(ip++))],3); + op += 3; + } + + ip += ipextra; + height--; + } +} + + +/* + * rfbTranslateWithRGBTablesINto24 translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTablesINto24 (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + uint8_t *op = (uint8_t *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + uint8_t *opLineEnd; + uint8_t *redTable = (uint8_t *)table; + uint8_t *greenTable = redTable + 3*(in->redMax + 1); + uint8_t *blueTable = greenTable + 3*(in->greenMax + 1); + uint32_t outValue; + + while (height > 0) { + opLineEnd = op+3*width; + + while (op < opLineEnd) { + outValue = (redTable[(*ip >> in->redShift) & in->redMax] | + greenTable[(*ip >> in->greenShift) & in->greenMax] | + blueTable[(*ip >> in->blueShift) & in->blueMax]); + memcpy(op,&outValue,3); + op += 3; + ip++; + } + ip += ipextra; + height--; + } +} + +#undef IN_T +#undef OUT_T +#undef rfbTranslateWithSingleTable24toOUT +#undef rfbTranslateWithRGBTables24toOUT +#undef rfbTranslateWithSingleTableINto24 +#undef rfbTranslateWithRGBTablesINto24 + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c new file mode 100755 index 0000000..e83c623 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tabletranstemplate.c @@ -0,0 +1,117 @@ +/* + * tabletranstemplate.c - template for translation using lookup tables. + * + * This file shouldn't be compiled. It is included multiple times by + * translate.c, each time with different definitions of the macros IN and OUT. + * + * For each pair of values IN and OUT, this file defines two functions for + * translating a given rectangle of pixel data. One uses a single lookup + * table, and the other uses three separate lookup tables for the red, green + * and blue values. + * + * I know this code isn't nice to read because of all the macros, but + * efficiency is important here. + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if !defined(IN) || !defined(OUT) +#error "This file shouldn't be compiled." +#error "It is included as part of translate.c" +#endif + +#define IN_T CONCAT3E(uint,IN,_t) +#define OUT_T CONCAT3E(uint,OUT,_t) +#define rfbTranslateWithSingleTableINtoOUT \ + CONCAT4E(rfbTranslateWithSingleTable,IN,to,OUT) +#define rfbTranslateWithRGBTablesINtoOUT \ + CONCAT4E(rfbTranslateWithRGBTables,IN,to,OUT) + +/* + * rfbTranslateWithSingleTableINtoOUT translates a rectangle of pixel data + * using a single lookup table. + */ + +static void +rfbTranslateWithSingleTableINtoOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + OUT_T *opLineEnd; + OUT_T *t = (OUT_T *)table; + + while (height > 0) { + opLineEnd = op + width; + + while (op < opLineEnd) { + *(op++) = t[*(ip++)]; + } + + ip += ipextra; + height--; + } +} + + +/* + * rfbTranslateWithRGBTablesINtoOUT translates a rectangle of pixel data + * using three separate lookup tables for the red, green and blue values. + */ + +static void +rfbTranslateWithRGBTablesINtoOUT (char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height) +{ + IN_T *ip = (IN_T *)iptr; + OUT_T *op = (OUT_T *)optr; + int ipextra = bytesBetweenInputLines / sizeof(IN_T) - width; + OUT_T *opLineEnd; + OUT_T *redTable = (OUT_T *)table; + OUT_T *greenTable = redTable + in->redMax + 1; + OUT_T *blueTable = greenTable + in->greenMax + 1; + + while (height > 0) { + opLineEnd = &op[width]; + + while (op < opLineEnd) { + *(op++) = (redTable[(*ip >> in->redShift) & in->redMax] | + greenTable[(*ip >> in->greenShift) & in->greenMax] | + blueTable[(*ip >> in->blueShift) & in->blueMax]); + ip++; + } + ip += ipextra; + height--; + } +} + +#undef IN_T +#undef OUT_T +#undef rfbTranslateWithSingleTableINtoOUT +#undef rfbTranslateWithRGBTablesINtoOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c new file mode 100755 index 0000000..9423ba5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tight.c @@ -0,0 +1,2053 @@ +/* + * tight.c + * + * Routines to implement Tight Encoding + */ + +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/*#include */ +#include +#include "private.h" + +#ifdef WIN32 +#define XMD_H +#undef FAR +#define NEEDFAR_POINTERS +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPNG +#include +#endif +#include + +/* Note: The following constant should not be changed. */ +#define TIGHT_MIN_TO_COMPRESS 12 + +/* The parameters below may be adjusted. */ +#define MIN_SPLIT_RECT_SIZE 4096 +#define MIN_SOLID_SUBRECT_SIZE 2048 +#define MAX_SPLIT_TILE_SIZE 16 + +/* May be set to TRUE with "-lazytight" Xvnc option. */ +rfbBool rfbTightDisableGradient = FALSE; + +/* + * There is so much access of the Tight encoding static data buffers + * that we resort to using thread local storage instead of having + * per-client data. + */ +#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__) +#define TLS __thread +#endif +#ifndef TLS +#define TLS +#endif + +/* This variable is set on every rfbSendRectEncodingTight() call. */ +static TLS rfbBool usePixelFormat24 = FALSE; + +/* Compression level stuff. The following array contains various + encoder parameters for each of 10 compression levels (0..9). + Last three parameters correspond to JPEG quality levels (0..9). */ + +typedef struct TIGHT_CONF_s { + int maxRectSize, maxRectWidth; + int monoMinRectSize, gradientMinRectSize; + int idxZlibLevel, monoZlibLevel, rawZlibLevel, gradientZlibLevel; + int gradientThreshold, gradientThreshold24; + int idxMaxColorsDivisor; + int jpegQuality, jpegThreshold, jpegThreshold24; +} TIGHT_CONF; + +static TIGHT_CONF tightConf[10] = { + { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 }, + { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 }, + { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 }, + { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 }, + { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 }, + { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 }, + { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 }, + { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 }, + { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 }, + { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 } +}; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG +typedef struct TIGHT_PNG_CONF_s { + int png_zlib_level, png_filters; +} TIGHT_PNG_CONF; + +static TIGHT_PNG_CONF tightPngConf[10] = { + { 0, PNG_NO_FILTERS }, + { 1, PNG_NO_FILTERS }, + { 2, PNG_NO_FILTERS }, + { 3, PNG_NO_FILTERS }, + { 4, PNG_NO_FILTERS }, + { 5, PNG_ALL_FILTERS }, + { 6, PNG_ALL_FILTERS }, + { 7, PNG_ALL_FILTERS }, + { 8, PNG_ALL_FILTERS }, + { 9, PNG_ALL_FILTERS }, +}; +#endif + +static TLS int compressLevel = 0; +static TLS int qualityLevel = 0; + +/* Stuff dealing with palettes. */ + +typedef struct COLOR_LIST_s { + struct COLOR_LIST_s *next; + int idx; + uint32_t rgb; +} COLOR_LIST; + +typedef struct PALETTE_ENTRY_s { + COLOR_LIST *listNode; + int numPixels; +} PALETTE_ENTRY; + +typedef struct PALETTE_s { + PALETTE_ENTRY entry[256]; + COLOR_LIST *hash[256]; + COLOR_LIST list[256]; +} PALETTE; + +/* TODO: move into rfbScreen struct */ +static TLS int paletteNumColors = 0; +static TLS int paletteMaxColors = 0; +static TLS uint32_t monoBackground = 0; +static TLS uint32_t monoForeground = 0; +static TLS PALETTE palette; + +/* Pointers to dynamically-allocated buffers. */ + +static TLS int tightBeforeBufSize = 0; +static TLS char *tightBeforeBuf = NULL; + +static TLS int tightAfterBufSize = 0; +static TLS char *tightAfterBuf = NULL; + +static TLS int *prevRowBuf = NULL; + +void rfbTightCleanup(rfbScreenInfoPtr screen) +{ + if(tightBeforeBufSize) { + free(tightBeforeBuf); + tightBeforeBufSize=0; + tightBeforeBuf = NULL; + } + if(tightAfterBufSize) { + free(tightAfterBuf); + tightAfterBufSize=0; + tightAfterBuf = NULL; + } +} + +/* Prototypes for static functions. */ + +static rfbBool SendRectEncodingTight(rfbClientPtr cl, int x, int y, + int w, int h); +static void FindBestSolidArea (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t colorValue, int *w_ptr, int *h_ptr); +static void ExtendSolidArea (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t colorValue, + int *x_ptr, int *y_ptr, int *w_ptr, int *h_ptr); +static rfbBool CheckSolidTile (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); +static rfbBool CheckSolidTile8 (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); +static rfbBool CheckSolidTile16 (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); +static rfbBool CheckSolidTile32 (rfbClientPtr cl, int x, int y, int w, int h, + uint32_t *colorPtr, rfbBool needSameColor); + +static rfbBool SendRectSimple (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendSubrect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendTightHeader (rfbClientPtr cl, int x, int y, int w, int h); + +static rfbBool SendSolidRect (rfbClientPtr cl); +static rfbBool SendMonoRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendIndexedRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendFullColorRect (rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool SendGradientRect (rfbClientPtr cl, int x, int y, int w, int h); + +static rfbBool CompressData(rfbClientPtr cl, int streamId, int dataLen, + int zlibLevel, int zlibStrategy); +static rfbBool SendCompressedData(rfbClientPtr cl, int compressedLen); + +static void FillPalette8(int count); +static void FillPalette16(int count); +static void FillPalette32(int count); + +static void PaletteReset(void); +static int PaletteInsert(uint32_t rgb, int numPixels, int bpp); + +static void Pack24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int count); + +static void EncodeIndexedRect16(uint8_t *buf, int count); +static void EncodeIndexedRect32(uint8_t *buf, int count); + +static void EncodeMonoRect8(uint8_t *buf, int w, int h); +static void EncodeMonoRect16(uint8_t *buf, int w, int h); +static void EncodeMonoRect32(uint8_t *buf, int w, int h); + +static void FilterGradient24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int w, int h); +static void FilterGradient16(rfbClientPtr cl, uint16_t *buf, rfbPixelFormat *fmt, int w, int h); +static void FilterGradient32(rfbClientPtr cl, uint32_t *buf, rfbPixelFormat *fmt, int w, int h); + +static int DetectSmoothImage(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); +static unsigned long DetectSmoothImage24(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); +static unsigned long DetectSmoothImage16(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); +static unsigned long DetectSmoothImage32(rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h); + +static rfbBool SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, + int quality); +static void PrepareRowForImg(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg24(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg16(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); +static void PrepareRowForImg32(rfbClientPtr cl, uint8_t *dst, int x, int y, int count); + +static void JpegInitDestination(j_compress_ptr cinfo); +static boolean JpegEmptyOutputBuffer(j_compress_ptr cinfo); +static void JpegTermDestination(j_compress_ptr cinfo); +static void JpegSetDstManager(j_compress_ptr cinfo); + +#ifdef LIBVNCSERVER_HAVE_LIBPNG +static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h); +static rfbBool CanSendPngRect(rfbClientPtr cl, int w, int h); +#endif + +/* + * Tight encoding implementation. + */ + +int +rfbNumCodedRectsTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int maxRectSize, maxRectWidth; + int subrectMaxWidth, subrectMaxHeight; + + /* No matter how many rectangles we will send if LastRect markers + are used to terminate rectangle stream. */ + if (cl->enableLastRectEncoding && w * h >= MIN_SPLIT_RECT_SIZE) + return 0; + + maxRectSize = tightConf[cl->tightCompressLevel].maxRectSize; + maxRectWidth = tightConf[cl->tightCompressLevel].maxRectWidth; + + if (w > maxRectWidth || w * h > maxRectSize) { + subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + subrectMaxHeight = maxRectSize / subrectMaxWidth; + return (((w - 1) / maxRectWidth + 1) * + ((h - 1) / subrectMaxHeight + 1)); + } else { + return 1; + } +} + +rfbBool +rfbSendRectEncodingTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + cl->tightEncoding = rfbEncodingTight; + return SendRectEncodingTight(cl, x, y, w, h); +} + +rfbBool +rfbSendRectEncodingTightPng(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + cl->tightEncoding = rfbEncodingTightPng; + return SendRectEncodingTight(cl, x, y, w, h); +} + + +rfbBool +SendRectEncodingTight(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int nMaxRows; + uint32_t colorValue; + int dx, dy, dw, dh; + int x_best, y_best, w_best, h_best; + char *fbptr; + + rfbSendUpdateBuf(cl); + + compressLevel = cl->tightCompressLevel; + qualityLevel = cl->tightQualityLevel; + + if ( cl->format.depth == 24 && cl->format.redMax == 0xFF && + cl->format.greenMax == 0xFF && cl->format.blueMax == 0xFF ) { + usePixelFormat24 = TRUE; + } else { + usePixelFormat24 = FALSE; + } + + if (!cl->enableLastRectEncoding || w * h < MIN_SPLIT_RECT_SIZE) + return SendRectSimple(cl, x, y, w, h); + + /* Make sure we can write at least one pixel into tightBeforeBuf. */ + + if (tightBeforeBufSize < 4) { + tightBeforeBufSize = 4; + if (tightBeforeBuf == NULL) + tightBeforeBuf = (char *)malloc(tightBeforeBufSize); + else + tightBeforeBuf = (char *)realloc(tightBeforeBuf, + tightBeforeBufSize); + } + + /* Calculate maximum number of rows in one non-solid rectangle. */ + + { + int maxRectSize, maxRectWidth, nMaxWidth; + + maxRectSize = tightConf[compressLevel].maxRectSize; + maxRectWidth = tightConf[compressLevel].maxRectWidth; + nMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + nMaxRows = maxRectSize / nMaxWidth; + } + + /* Try to find large solid-color areas and send them separately. */ + + for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { + + /* If a rectangle becomes too large, send its upper part now. */ + + if (dy - y >= nMaxRows) { + if (!SendRectSimple(cl, x, y, w, nMaxRows)) + return 0; + y += nMaxRows; + h -= nMaxRows; + } + + dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? + MAX_SPLIT_TILE_SIZE : (y + h - dy); + + for (dx = x; dx < x + w; dx += MAX_SPLIT_TILE_SIZE) { + + dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w) ? + MAX_SPLIT_TILE_SIZE : (x + w - dx); + + if (CheckSolidTile(cl, dx, dy, dw, dh, &colorValue, FALSE)) { + + /* Get dimensions of solid-color area. */ + + FindBestSolidArea(cl, dx, dy, w - (dx - x), h - (dy - y), + colorValue, &w_best, &h_best); + + /* Make sure a solid rectangle is large enough + (or the whole rectangle is of the same color). */ + + if ( w_best * h_best != w * h && + w_best * h_best < MIN_SOLID_SUBRECT_SIZE ) + continue; + + /* Try to extend solid rectangle to maximum size. */ + + x_best = dx; y_best = dy; + ExtendSolidArea(cl, x, y, w, h, colorValue, + &x_best, &y_best, &w_best, &h_best); + + /* Send rectangles at top and left to solid-color area. */ + + if ( y_best != y && + !SendRectSimple(cl, x, y, w, y_best-y) ) + return FALSE; + if ( x_best != x && + !SendRectEncodingTight(cl, x, y_best, + x_best-x, h_best) ) + return FALSE; + + /* Send solid-color rectangle. */ + + if (!SendTightHeader(cl, x_best, y_best, w_best, h_best)) + return FALSE; + + fbptr = (cl->scaledScreen->frameBuffer + + (cl->scaledScreen->paddedWidthInBytes * y_best) + + (x_best * (cl->scaledScreen->bitsPerPixel / 8))); + + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, tightBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, 1, 1); + + if (!SendSolidRect(cl)) + return FALSE; + + /* Send remaining rectangles (at right and bottom). */ + + if ( x_best + w_best != x + w && + !SendRectEncodingTight(cl, x_best+w_best, y_best, + w-(x_best-x)-w_best, h_best) ) + return FALSE; + if ( y_best + h_best != y + h && + !SendRectEncodingTight(cl, x, y_best+h_best, + w, h-(y_best-y)-h_best) ) + return FALSE; + + /* Return after all recursive calls are done. */ + + return TRUE; + } + + } + + } + + /* No suitable solid-color rectangles found. */ + + return SendRectSimple(cl, x, y, w, h); +} + +static void +FindBestSolidArea(rfbClientPtr cl, + int x, + int y, + int w, + int h, + uint32_t colorValue, + int *w_ptr, + int *h_ptr) +{ + int dx, dy, dw, dh; + int w_prev; + int w_best = 0, h_best = 0; + + w_prev = w; + + for (dy = y; dy < y + h; dy += MAX_SPLIT_TILE_SIZE) { + + dh = (dy + MAX_SPLIT_TILE_SIZE <= y + h) ? + MAX_SPLIT_TILE_SIZE : (y + h - dy); + dw = (w_prev > MAX_SPLIT_TILE_SIZE) ? + MAX_SPLIT_TILE_SIZE : w_prev; + + if (!CheckSolidTile(cl, x, dy, dw, dh, &colorValue, TRUE)) + break; + + for (dx = x + dw; dx < x + w_prev;) { + dw = (dx + MAX_SPLIT_TILE_SIZE <= x + w_prev) ? + MAX_SPLIT_TILE_SIZE : (x + w_prev - dx); + if (!CheckSolidTile(cl, dx, dy, dw, dh, &colorValue, TRUE)) + break; + dx += dw; + } + + w_prev = dx - x; + if (w_prev * (dy + dh - y) > w_best * h_best) { + w_best = w_prev; + h_best = dy + dh - y; + } + } + + *w_ptr = w_best; + *h_ptr = h_best; +} + +static void +ExtendSolidArea(rfbClientPtr cl, + int x, + int y, + int w, + int h, + uint32_t colorValue, + int *x_ptr, + int *y_ptr, + int *w_ptr, + int *h_ptr) +{ + int cx, cy; + + /* Try to extend the area upwards. */ + for ( cy = *y_ptr - 1; + cy >= y && CheckSolidTile(cl, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); + cy-- ); + *h_ptr += *y_ptr - (cy + 1); + *y_ptr = cy + 1; + + /* ... downwards. */ + for ( cy = *y_ptr + *h_ptr; + cy < y + h && + CheckSolidTile(cl, *x_ptr, cy, *w_ptr, 1, &colorValue, TRUE); + cy++ ); + *h_ptr += cy - (*y_ptr + *h_ptr); + + /* ... to the left. */ + for ( cx = *x_ptr - 1; + cx >= x && CheckSolidTile(cl, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); + cx-- ); + *w_ptr += *x_ptr - (cx + 1); + *x_ptr = cx + 1; + + /* ... to the right. */ + for ( cx = *x_ptr + *w_ptr; + cx < x + w && + CheckSolidTile(cl, cx, *y_ptr, 1, *h_ptr, &colorValue, TRUE); + cx++ ); + *w_ptr += cx - (*x_ptr + *w_ptr); +} + +/* + * Check if a rectangle is all of the same color. If needSameColor is + * set to non-zero, then also check that its color equals to the + * *colorPtr value. The result is 1 if the test is successfull, and in + * that case new color will be stored in *colorPtr. + */ + +static rfbBool CheckSolidTile(rfbClientPtr cl, int x, int y, int w, int h, uint32_t* colorPtr, rfbBool needSameColor) +{ + switch(cl->screen->serverFormat.bitsPerPixel) { + case 32: + return CheckSolidTile32(cl, x, y, w, h, colorPtr, needSameColor); + case 16: + return CheckSolidTile16(cl, x, y, w, h, colorPtr, needSameColor); + default: + return CheckSolidTile8(cl, x, y, w, h, colorPtr, needSameColor); + } +} + +#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \ + \ +static rfbBool \ +CheckSolidTile##bpp(rfbClientPtr cl, int x, int y, int w, int h, \ + uint32_t* colorPtr, rfbBool needSameColor) \ +{ \ + uint##bpp##_t *fbptr; \ + uint##bpp##_t colorValue; \ + int dx, dy; \ + \ + fbptr = (uint##bpp##_t *) \ + &cl->scaledScreen->frameBuffer[y * cl->scaledScreen->paddedWidthInBytes + x * (bpp/8)]; \ + \ + colorValue = *fbptr; \ + if (needSameColor && (uint32_t)colorValue != *colorPtr) \ + return FALSE; \ + \ + for (dy = 0; dy < h; dy++) { \ + for (dx = 0; dx < w; dx++) { \ + if (colorValue != fbptr[dx]) \ + return FALSE; \ + } \ + fbptr = (uint##bpp##_t *)((uint8_t *)fbptr + cl->scaledScreen->paddedWidthInBytes); \ + } \ + \ + *colorPtr = (uint32_t)colorValue; \ + return TRUE; \ +} + +DEFINE_CHECK_SOLID_FUNCTION(8) +DEFINE_CHECK_SOLID_FUNCTION(16) +DEFINE_CHECK_SOLID_FUNCTION(32) + +static rfbBool +SendRectSimple(rfbClientPtr cl, int x, int y, int w, int h) +{ + int maxBeforeSize, maxAfterSize; + int maxRectSize, maxRectWidth; + int subrectMaxWidth, subrectMaxHeight; + int dx, dy; + int rw, rh; + + maxRectSize = tightConf[compressLevel].maxRectSize; + maxRectWidth = tightConf[compressLevel].maxRectWidth; + + maxBeforeSize = maxRectSize * (cl->format.bitsPerPixel / 8); + maxAfterSize = maxBeforeSize + (maxBeforeSize + 99) / 100 + 12; + + if (tightBeforeBufSize < maxBeforeSize) { + tightBeforeBufSize = maxBeforeSize; + if (tightBeforeBuf == NULL) + tightBeforeBuf = (char *)malloc(tightBeforeBufSize); + else + tightBeforeBuf = (char *)realloc(tightBeforeBuf, + tightBeforeBufSize); + } + + if (tightAfterBufSize < maxAfterSize) { + tightAfterBufSize = maxAfterSize; + if (tightAfterBuf == NULL) + tightAfterBuf = (char *)malloc(tightAfterBufSize); + else + tightAfterBuf = (char *)realloc(tightAfterBuf, + tightAfterBufSize); + } + + if (w > maxRectWidth || w * h > maxRectSize) { + subrectMaxWidth = (w > maxRectWidth) ? maxRectWidth : w; + subrectMaxHeight = maxRectSize / subrectMaxWidth; + + for (dy = 0; dy < h; dy += subrectMaxHeight) { + for (dx = 0; dx < w; dx += maxRectWidth) { + rw = (dx + maxRectWidth < w) ? maxRectWidth : w - dx; + rh = (dy + subrectMaxHeight < h) ? subrectMaxHeight : h - dy; + if (!SendSubrect(cl, x+dx, y+dy, rw, rh)) + return FALSE; + } + } + } else { + if (!SendSubrect(cl, x, y, w, h)) + return FALSE; + } + + return TRUE; +} + +static rfbBool +SendSubrect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + char *fbptr; + rfbBool success = FALSE; + + /* Send pending data if there is more than 128 bytes. */ + if (cl->ublen > 128) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if (!SendTightHeader(cl, x, y, w, h)) + return FALSE; + + fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, tightBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + paletteMaxColors = w * h / tightConf[compressLevel].idxMaxColorsDivisor; + if ( paletteMaxColors < 2 && + w * h >= tightConf[compressLevel].monoMinRectSize ) { + paletteMaxColors = 2; + } + switch (cl->format.bitsPerPixel) { + case 8: + FillPalette8(w * h); + break; + case 16: + FillPalette16(w * h); + break; + default: + FillPalette32(w * h); + } + + switch (paletteNumColors) { + case 0: + /* Truecolor image */ + if (DetectSmoothImage(cl, &cl->format, w, h)) { + if (qualityLevel != -1) { + success = SendJpegRect(cl, x, y, w, h, + tightConf[qualityLevel].jpegQuality); + } else { + success = SendGradientRect(cl, x, y, w, h); + } + } else { + success = SendFullColorRect(cl, x, y, w, h); + } + break; + case 1: + /* Solid rectangle */ + success = SendSolidRect(cl); + break; + case 2: + /* Two-color rectangle */ + success = SendMonoRect(cl, x, y, w, h); + break; + default: + /* Up to 256 different colors */ + if ( paletteNumColors > 96 && + qualityLevel != -1 && qualityLevel <= 3 && + DetectSmoothImage(cl, &cl->format, w, h) ) { + success = SendJpegRect(cl, x, y, w, h, + tightConf[qualityLevel].jpegQuality); + } else { + success = SendIndexedRect(cl, x, y, w, h); + } + } + return success; +} + +static rfbBool +SendTightHeader(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(cl->tightEncoding); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + rfbStatRecordEncodingSent(cl, cl->tightEncoding, sz_rfbFramebufferUpdateRectHeader, + sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h); + + return TRUE; +} + +/* + * Subencoding implementations. + */ + +static rfbBool +SendSolidRect(rfbClientPtr cl) +{ + int len; + + if (usePixelFormat24) { + Pack24(cl, tightBeforeBuf, &cl->format, 1); + len = 3; + } else + len = cl->format.bitsPerPixel / 8; + + if (cl->ublen + 1 + len > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightFill << 4); + memcpy (&cl->updateBuf[cl->ublen], tightBeforeBuf, len); + cl->ublen += len; + + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, len+1); + + return TRUE; +} + +static rfbBool +SendMonoRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 1; + int paletteLen, dataLen; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + // TODO: setup palette maybe + return SendPngRect(cl, x, y, w, h); + // TODO: destroy palette maybe + } +#endif + + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + + 2 * cl->format.bitsPerPixel / 8 > UPDATE_BUF_SIZE ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + /* Prepare tight encoding header. */ + dataLen = (w + 7) / 8; + dataLen *= h; + + cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; + cl->updateBuf[cl->ublen++] = rfbTightFilterPalette; + cl->updateBuf[cl->ublen++] = 1; + + /* Prepare palette, convert image. */ + switch (cl->format.bitsPerPixel) { + + case 32: + EncodeMonoRect32((uint8_t *)tightBeforeBuf, w, h); + + ((uint32_t *)tightAfterBuf)[0] = monoBackground; + ((uint32_t *)tightAfterBuf)[1] = monoForeground; + if (usePixelFormat24) { + Pack24(cl, tightAfterBuf, &cl->format, 2); + paletteLen = 6; + } else + paletteLen = 8; + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteLen); + cl->ublen += paletteLen; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteLen); + break; + + case 16: + EncodeMonoRect16((uint8_t *)tightBeforeBuf, w, h); + + ((uint16_t *)tightAfterBuf)[0] = (uint16_t)monoBackground; + ((uint16_t *)tightAfterBuf)[1] = (uint16_t)monoForeground; + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, 4); + cl->ublen += 4; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 7); + break; + + default: + EncodeMonoRect8((uint8_t *)tightBeforeBuf, w, h); + + cl->updateBuf[cl->ublen++] = (char)monoBackground; + cl->updateBuf[cl->ublen++] = (char)monoForeground; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 5); + } + + return CompressData(cl, streamId, dataLen, + tightConf[compressLevel].monoZlibLevel, + Z_DEFAULT_STRATEGY); +} + +static rfbBool +SendIndexedRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 2; + int i, entryLen; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + + if ( cl->ublen + TIGHT_MIN_TO_COMPRESS + 6 + + paletteNumColors * cl->format.bitsPerPixel / 8 > + UPDATE_BUF_SIZE ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + /* Prepare tight encoding header. */ + cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; + cl->updateBuf[cl->ublen++] = rfbTightFilterPalette; + cl->updateBuf[cl->ublen++] = (char)(paletteNumColors - 1); + + /* Prepare palette, convert image. */ + switch (cl->format.bitsPerPixel) { + + case 32: + EncodeIndexedRect32((uint8_t *)tightBeforeBuf, w * h); + + for (i = 0; i < paletteNumColors; i++) { + ((uint32_t *)tightAfterBuf)[i] = + palette.entry[i].listNode->rgb; + } + if (usePixelFormat24) { + Pack24(cl, tightAfterBuf, &cl->format, paletteNumColors); + entryLen = 3; + } else + entryLen = 4; + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * entryLen); + cl->ublen += paletteNumColors * entryLen; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * entryLen); + break; + + case 16: + EncodeIndexedRect16((uint8_t *)tightBeforeBuf, w * h); + + for (i = 0; i < paletteNumColors; i++) { + ((uint16_t *)tightAfterBuf)[i] = + (uint16_t)palette.entry[i].listNode->rgb; + } + + memcpy(&cl->updateBuf[cl->ublen], tightAfterBuf, paletteNumColors * 2); + cl->ublen += paletteNumColors * 2; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 3 + paletteNumColors * 2); + break; + + default: + return FALSE; /* Should never happen. */ + } + + return CompressData(cl, streamId, w * h, + tightConf[compressLevel].idxZlibLevel, + Z_DEFAULT_STRATEGY); +} + +static rfbBool +SendFullColorRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 0; + int len; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = 0x00; /* stream id = 0, no flushing, no filter */ + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + if (usePixelFormat24) { + Pack24(cl, tightBeforeBuf, &cl->format, w * h); + len = 3; + } else + len = cl->format.bitsPerPixel / 8; + + return CompressData(cl, streamId, w * h * len, + tightConf[compressLevel].rawZlibLevel, + Z_DEFAULT_STRATEGY); +} + +static rfbBool +SendGradientRect(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int streamId = 3; + int len; + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + if (CanSendPngRect(cl, w, h)) { + return SendPngRect(cl, x, y, w, h); + } +#endif + + if (cl->format.bitsPerPixel == 8) + return SendFullColorRect(cl, x, y, w, h); + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 2 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + if (prevRowBuf == NULL) + prevRowBuf = (int *)malloc(2048 * 3 * sizeof(int)); + + cl->updateBuf[cl->ublen++] = (streamId | rfbTightExplicitFilter) << 4; + cl->updateBuf[cl->ublen++] = rfbTightFilterGradient; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 2); + + if (usePixelFormat24) { + FilterGradient24(cl, tightBeforeBuf, &cl->format, w, h); + len = 3; + } else if (cl->format.bitsPerPixel == 32) { + FilterGradient32(cl, (uint32_t *)tightBeforeBuf, &cl->format, w, h); + len = 4; + } else { + FilterGradient16(cl, (uint16_t *)tightBeforeBuf, &cl->format, w, h); + len = 2; + } + + return CompressData(cl, streamId, w * h * len, + tightConf[compressLevel].gradientZlibLevel, + Z_FILTERED); +} + +static rfbBool +CompressData(rfbClientPtr cl, + int streamId, + int dataLen, + int zlibLevel, + int zlibStrategy) +{ + z_streamp pz; + int err; + + if (dataLen < TIGHT_MIN_TO_COMPRESS) { + memcpy(&cl->updateBuf[cl->ublen], tightBeforeBuf, dataLen); + cl->ublen += dataLen; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, dataLen); + return TRUE; + } + + pz = &cl->zsStruct[streamId]; + + /* Initialize compression stream if needed. */ + if (!cl->zsActive[streamId]) { + pz->zalloc = Z_NULL; + pz->zfree = Z_NULL; + pz->opaque = Z_NULL; + + err = deflateInit2 (pz, zlibLevel, Z_DEFLATED, MAX_WBITS, + MAX_MEM_LEVEL, zlibStrategy); + if (err != Z_OK) + return FALSE; + + cl->zsActive[streamId] = TRUE; + cl->zsLevel[streamId] = zlibLevel; + } + + /* Prepare buffer pointers. */ + pz->next_in = (Bytef *)tightBeforeBuf; + pz->avail_in = dataLen; + pz->next_out = (Bytef *)tightAfterBuf; + pz->avail_out = tightAfterBufSize; + + /* Change compression parameters if needed. */ + if (zlibLevel != cl->zsLevel[streamId]) { + if (deflateParams (pz, zlibLevel, zlibStrategy) != Z_OK) { + return FALSE; + } + cl->zsLevel[streamId] = zlibLevel; + } + + /* Actual compression. */ + if ( deflate (pz, Z_SYNC_FLUSH) != Z_OK || + pz->avail_in != 0 || pz->avail_out == 0 ) { + return FALSE; + } + + return SendCompressedData(cl, tightAfterBufSize - pz->avail_out); +} + +static rfbBool SendCompressedData(rfbClientPtr cl, + int compressedLen) +{ + int i, portionLen; + + cl->updateBuf[cl->ublen++] = compressedLen & 0x7F; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + if (compressedLen > 0x7F) { + cl->updateBuf[cl->ublen-1] |= 0x80; + cl->updateBuf[cl->ublen++] = compressedLen >> 7 & 0x7F; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + if (compressedLen > 0x3FFF) { + cl->updateBuf[cl->ublen-1] |= 0x80; + cl->updateBuf[cl->ublen++] = compressedLen >> 14 & 0xFF; + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + } + } + + portionLen = UPDATE_BUF_SIZE; + for (i = 0; i < compressedLen; i += portionLen) { + if (i + portionLen > compressedLen) { + portionLen = compressedLen - i; + } + if (cl->ublen + portionLen > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + memcpy(&cl->updateBuf[cl->ublen], &tightAfterBuf[i], portionLen); + cl->ublen += portionLen; + } + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, compressedLen); + + return TRUE; +} + +/* + * Code to determine how many different colors used in rectangle. + */ + +static void +FillPalette8(int count) +{ + uint8_t *data = (uint8_t *)tightBeforeBuf; + uint8_t c0, c1; + int i, n0, n1; + + paletteNumColors = 0; + + c0 = data[0]; + for (i = 1; i < count && data[i] == c0; i++); + if (i == count) { + paletteNumColors = 1; + return; /* Solid rectangle */ + } + + if (paletteMaxColors < 2) + return; + + n0 = i; + c1 = data[i]; + n1 = 0; + for (i++; i < count; i++) { + if (data[i] == c0) { + n0++; + } else if (data[i] == c1) { + n1++; + } else + break; + } + if (i == count) { + if (n0 > n1) { + monoBackground = (uint32_t)c0; + monoForeground = (uint32_t)c1; + } else { + monoBackground = (uint32_t)c1; + monoForeground = (uint32_t)c0; + } + paletteNumColors = 2; /* Two colors */ + } +} + +#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \ + \ +static void \ +FillPalette##bpp(int count) { \ + uint##bpp##_t *data = (uint##bpp##_t *)tightBeforeBuf; \ + uint##bpp##_t c0, c1, ci; \ + int i, n0, n1, ni; \ + \ + c0 = data[0]; \ + for (i = 1; i < count && data[i] == c0; i++); \ + if (i >= count) { \ + paletteNumColors = 1; /* Solid rectangle */ \ + return; \ + } \ + \ + if (paletteMaxColors < 2) { \ + paletteNumColors = 0; /* Full-color encoding preferred */ \ + return; \ + } \ + \ + n0 = i; \ + c1 = data[i]; \ + n1 = 0; \ + for (i++; i < count; i++) { \ + ci = data[i]; \ + if (ci == c0) { \ + n0++; \ + } else if (ci == c1) { \ + n1++; \ + } else \ + break; \ + } \ + if (i >= count) { \ + if (n0 > n1) { \ + monoBackground = (uint32_t)c0; \ + monoForeground = (uint32_t)c1; \ + } else { \ + monoBackground = (uint32_t)c1; \ + monoForeground = (uint32_t)c0; \ + } \ + paletteNumColors = 2; /* Two colors */ \ + return; \ + } \ + \ + PaletteReset(); \ + PaletteInsert (c0, (uint32_t)n0, bpp); \ + PaletteInsert (c1, (uint32_t)n1, bpp); \ + \ + ni = 1; \ + for (i++; i < count; i++) { \ + if (data[i] == ci) { \ + ni++; \ + } else { \ + if (!PaletteInsert (ci, (uint32_t)ni, bpp)) \ + return; \ + ci = data[i]; \ + ni = 1; \ + } \ + } \ + PaletteInsert (ci, (uint32_t)ni, bpp); \ +} + +DEFINE_FILL_PALETTE_FUNCTION(16) +DEFINE_FILL_PALETTE_FUNCTION(32) + + +/* + * Functions to operate with palette structures. + */ + +#define HASH_FUNC16(rgb) ((int)(((rgb >> 8) + rgb) & 0xFF)) +#define HASH_FUNC32(rgb) ((int)(((rgb >> 16) + (rgb >> 8)) & 0xFF)) + +static void +PaletteReset(void) +{ + paletteNumColors = 0; + memset(palette.hash, 0, 256 * sizeof(COLOR_LIST *)); +} + +static int +PaletteInsert(uint32_t rgb, + int numPixels, + int bpp) +{ + COLOR_LIST *pnode; + COLOR_LIST *prev_pnode = NULL; + int hash_key, idx, new_idx, count; + + hash_key = (bpp == 16) ? HASH_FUNC16(rgb) : HASH_FUNC32(rgb); + + pnode = palette.hash[hash_key]; + + while (pnode != NULL) { + if (pnode->rgb == rgb) { + /* Such palette entry already exists. */ + new_idx = idx = pnode->idx; + count = palette.entry[idx].numPixels + numPixels; + if (new_idx && palette.entry[new_idx-1].numPixels < count) { + do { + palette.entry[new_idx] = palette.entry[new_idx-1]; + palette.entry[new_idx].listNode->idx = new_idx; + new_idx--; + } + while (new_idx && palette.entry[new_idx-1].numPixels < count); + palette.entry[new_idx].listNode = pnode; + pnode->idx = new_idx; + } + palette.entry[new_idx].numPixels = count; + return paletteNumColors; + } + prev_pnode = pnode; + pnode = pnode->next; + } + + /* Check if palette is full. */ + if (paletteNumColors == 256 || paletteNumColors == paletteMaxColors) { + paletteNumColors = 0; + return 0; + } + + /* Move palette entries with lesser pixel counts. */ + for ( idx = paletteNumColors; + idx > 0 && palette.entry[idx-1].numPixels < numPixels; + idx-- ) { + palette.entry[idx] = palette.entry[idx-1]; + palette.entry[idx].listNode->idx = idx; + } + + /* Add new palette entry into the freed slot. */ + pnode = &palette.list[paletteNumColors]; + if (prev_pnode != NULL) { + prev_pnode->next = pnode; + } else { + palette.hash[hash_key] = pnode; + } + pnode->next = NULL; + pnode->idx = idx; + pnode->rgb = rgb; + palette.entry[idx].listNode = pnode; + palette.entry[idx].numPixels = numPixels; + + return (++paletteNumColors); +} + + +/* + * Converting 32-bit color samples into 24-bit colors. + * Should be called only when redMax, greenMax and blueMax are 255. + * Color components assumed to be byte-aligned. + */ + +static void Pack24(rfbClientPtr cl, + char *buf, + rfbPixelFormat *fmt, + int count) +{ + uint32_t *buf32; + uint32_t pix; + int r_shift, g_shift, b_shift; + + buf32 = (uint32_t *)buf; + + if (!cl->screen->serverFormat.bigEndian == !fmt->bigEndian) { + r_shift = fmt->redShift; + g_shift = fmt->greenShift; + b_shift = fmt->blueShift; + } else { + r_shift = 24 - fmt->redShift; + g_shift = 24 - fmt->greenShift; + b_shift = 24 - fmt->blueShift; + } + + while (count--) { + pix = *buf32++; + *buf++ = (char)(pix >> r_shift); + *buf++ = (char)(pix >> g_shift); + *buf++ = (char)(pix >> b_shift); + } +} + + +/* + * Converting truecolor samples into palette indices. + */ + +#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \ + \ +static void \ +EncodeIndexedRect##bpp(uint8_t *buf, int count) { \ + COLOR_LIST *pnode; \ + uint##bpp##_t *src; \ + uint##bpp##_t rgb; \ + int rep = 0; \ + \ + src = (uint##bpp##_t *) buf; \ + \ + while (count--) { \ + rgb = *src++; \ + while (count && *src == rgb) { \ + rep++, src++, count--; \ + } \ + pnode = palette.hash[HASH_FUNC##bpp(rgb)]; \ + while (pnode != NULL) { \ + if ((uint##bpp##_t)pnode->rgb == rgb) { \ + *buf++ = (uint8_t)pnode->idx; \ + while (rep) { \ + *buf++ = (uint8_t)pnode->idx; \ + rep--; \ + } \ + break; \ + } \ + pnode = pnode->next; \ + } \ + } \ +} + +DEFINE_IDX_ENCODE_FUNCTION(16) +DEFINE_IDX_ENCODE_FUNCTION(32) + +#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \ + \ +static void \ +EncodeMonoRect##bpp(uint8_t *buf, int w, int h) { \ + uint##bpp##_t *ptr; \ + uint##bpp##_t bg; \ + unsigned int value, mask; \ + int aligned_width; \ + int x, y, bg_bits; \ + \ + ptr = (uint##bpp##_t *) buf; \ + bg = (uint##bpp##_t) monoBackground; \ + aligned_width = w - w % 8; \ + \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < aligned_width; x += 8) { \ + for (bg_bits = 0; bg_bits < 8; bg_bits++) { \ + if (*ptr++ != bg) \ + break; \ + } \ + if (bg_bits == 8) { \ + *buf++ = 0; \ + continue; \ + } \ + mask = 0x80 >> bg_bits; \ + value = mask; \ + for (bg_bits++; bg_bits < 8; bg_bits++) { \ + mask >>= 1; \ + if (*ptr++ != bg) { \ + value |= mask; \ + } \ + } \ + *buf++ = (uint8_t)value; \ + } \ + \ + mask = 0x80; \ + value = 0; \ + if (x >= w) \ + continue; \ + \ + for (; x < w; x++) { \ + if (*ptr++ != bg) { \ + value |= mask; \ + } \ + mask >>= 1; \ + } \ + *buf++ = (uint8_t)value; \ + } \ +} + +DEFINE_MONO_ENCODE_FUNCTION(8) +DEFINE_MONO_ENCODE_FUNCTION(16) +DEFINE_MONO_ENCODE_FUNCTION(32) + + +/* + * ``Gradient'' filter for 24-bit color samples. + * Should be called only when redMax, greenMax and blueMax are 255. + * Color components assumed to be byte-aligned. + */ + +static void +FilterGradient24(rfbClientPtr cl, char *buf, rfbPixelFormat *fmt, int w, int h) +{ + uint32_t *buf32; + uint32_t pix32; + int *prevRowPtr; + int shiftBits[3]; + int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; + int prediction; + int x, y, c; + + buf32 = (uint32_t *)buf; + memset (prevRowBuf, 0, w * 3 * sizeof(int)); + + if (!cl->screen->serverFormat.bigEndian == !fmt->bigEndian) { + shiftBits[0] = fmt->redShift; + shiftBits[1] = fmt->greenShift; + shiftBits[2] = fmt->blueShift; + } else { + shiftBits[0] = 24 - fmt->redShift; + shiftBits[1] = 24 - fmt->greenShift; + shiftBits[2] = 24 - fmt->blueShift; + } + + for (y = 0; y < h; y++) { + for (c = 0; c < 3; c++) { + pixUpper[c] = 0; + pixHere[c] = 0; + } + prevRowPtr = prevRowBuf; + for (x = 0; x < w; x++) { + pix32 = *buf32++; + for (c = 0; c < 3; c++) { + pixUpperLeft[c] = pixUpper[c]; + pixLeft[c] = pixHere[c]; + pixUpper[c] = *prevRowPtr; + pixHere[c] = (int)(pix32 >> shiftBits[c] & 0xFF); + *prevRowPtr++ = pixHere[c]; + + prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; + if (prediction < 0) { + prediction = 0; + } else if (prediction > 0xFF) { + prediction = 0xFF; + } + *buf++ = (char)(pixHere[c] - prediction); + } + } + } +} + + +/* + * ``Gradient'' filter for other color depths. + */ + +#define DEFINE_GRADIENT_FILTER_FUNCTION(bpp) \ + \ +static void \ +FilterGradient##bpp(rfbClientPtr cl, uint##bpp##_t *buf, \ + rfbPixelFormat *fmt, int w, int h) { \ + uint##bpp##_t pix, diff; \ + rfbBool endianMismatch; \ + int *prevRowPtr; \ + int maxColor[3], shiftBits[3]; \ + int pixHere[3], pixUpper[3], pixLeft[3], pixUpperLeft[3]; \ + int prediction; \ + int x, y, c; \ + \ + memset (prevRowBuf, 0, w * 3 * sizeof(int)); \ + \ + endianMismatch = (!cl->screen->serverFormat.bigEndian != !fmt->bigEndian); \ + \ + maxColor[0] = fmt->redMax; \ + maxColor[1] = fmt->greenMax; \ + maxColor[2] = fmt->blueMax; \ + shiftBits[0] = fmt->redShift; \ + shiftBits[1] = fmt->greenShift; \ + shiftBits[2] = fmt->blueShift; \ + \ + for (y = 0; y < h; y++) { \ + for (c = 0; c < 3; c++) { \ + pixUpper[c] = 0; \ + pixHere[c] = 0; \ + } \ + prevRowPtr = prevRowBuf; \ + for (x = 0; x < w; x++) { \ + pix = *buf; \ + if (endianMismatch) { \ + pix = Swap##bpp(pix); \ + } \ + diff = 0; \ + for (c = 0; c < 3; c++) { \ + pixUpperLeft[c] = pixUpper[c]; \ + pixLeft[c] = pixHere[c]; \ + pixUpper[c] = *prevRowPtr; \ + pixHere[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ + *prevRowPtr++ = pixHere[c]; \ + \ + prediction = pixLeft[c] + pixUpper[c] - pixUpperLeft[c]; \ + if (prediction < 0) { \ + prediction = 0; \ + } else if (prediction > maxColor[c]) { \ + prediction = maxColor[c]; \ + } \ + diff |= ((pixHere[c] - prediction) & maxColor[c]) \ + << shiftBits[c]; \ + } \ + if (endianMismatch) { \ + diff = Swap##bpp(diff); \ + } \ + *buf++ = diff; \ + } \ + } \ +} + +DEFINE_GRADIENT_FILTER_FUNCTION(16) +DEFINE_GRADIENT_FILTER_FUNCTION(32) + + +/* + * Code to guess if given rectangle is suitable for smooth image + * compression (by applying "gradient" filter or JPEG coder). + */ + +#define JPEG_MIN_RECT_SIZE 4096 + +#define DETECT_SUBROW_WIDTH 7 +#define DETECT_MIN_WIDTH 8 +#define DETECT_MIN_HEIGHT 8 + +static int +DetectSmoothImage (rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h) +{ + long avgError; + + if ( cl->screen->serverFormat.bitsPerPixel == 8 || fmt->bitsPerPixel == 8 || + w < DETECT_MIN_WIDTH || h < DETECT_MIN_HEIGHT ) { + return 0; + } + + if (qualityLevel != -1) { + if (w * h < JPEG_MIN_RECT_SIZE) { + return 0; + } + } else { + if ( rfbTightDisableGradient || + w * h < tightConf[compressLevel].gradientMinRectSize ) { + return 0; + } + } + + if (fmt->bitsPerPixel == 32) { + if (usePixelFormat24) { + avgError = DetectSmoothImage24(cl, fmt, w, h); + if (qualityLevel != -1) { + return (avgError < tightConf[qualityLevel].jpegThreshold24); + } + return (avgError < tightConf[compressLevel].gradientThreshold24); + } else { + avgError = DetectSmoothImage32(cl, fmt, w, h); + } + } else { + avgError = DetectSmoothImage16(cl, fmt, w, h); + } + if (qualityLevel != -1) { + return (avgError < tightConf[qualityLevel].jpegThreshold); + } + return (avgError < tightConf[compressLevel].gradientThreshold); +} + +static unsigned long +DetectSmoothImage24 (rfbClientPtr cl, + rfbPixelFormat *fmt, + int w, + int h) +{ + int off; + int x, y, d, dx, c; + int diffStat[256]; + int pixelCount = 0; + int pix, left[3]; + unsigned long avgError; + + /* If client is big-endian, color samples begin from the second + byte (offset 1) of a 32-bit pixel value. */ + off = (fmt->bigEndian != 0); + + memset(diffStat, 0, 256*sizeof(int)); + + y = 0, x = 0; + while (y < h && x < w) { + for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { + for (c = 0; c < 3; c++) { + left[c] = (int)tightBeforeBuf[((y+d)*w+x+d)*4+off+c] & 0xFF; + } + for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { + for (c = 0; c < 3; c++) { + pix = (int)tightBeforeBuf[((y+d)*w+x+d+dx)*4+off+c] & 0xFF; + diffStat[abs(pix - left[c])]++; + left[c] = pix; + } + pixelCount++; + } + } + if (w > h) { + x += h; + y = 0; + } else { + x = 0; + y += w; + } + } + + if (diffStat[0] * 33 / pixelCount >= 95) + return 0; + + avgError = 0; + for (c = 1; c < 8; c++) { + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); + if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) + return 0; + } + for (; c < 256; c++) { + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); + } + avgError /= (pixelCount * 3 - diffStat[0]); + + return avgError; +} + +#define DEFINE_DETECT_FUNCTION(bpp) \ + \ +static unsigned long \ +DetectSmoothImage##bpp (rfbClientPtr cl, rfbPixelFormat *fmt, int w, int h) {\ + rfbBool endianMismatch; \ + uint##bpp##_t pix; \ + int maxColor[3], shiftBits[3]; \ + int x, y, d, dx, c; \ + int diffStat[256]; \ + int pixelCount = 0; \ + int sample, sum, left[3]; \ + unsigned long avgError; \ + \ + endianMismatch = (!cl->screen->serverFormat.bigEndian != !fmt->bigEndian); \ + \ + maxColor[0] = fmt->redMax; \ + maxColor[1] = fmt->greenMax; \ + maxColor[2] = fmt->blueMax; \ + shiftBits[0] = fmt->redShift; \ + shiftBits[1] = fmt->greenShift; \ + shiftBits[2] = fmt->blueShift; \ + \ + memset(diffStat, 0, 256*sizeof(int)); \ + \ + y = 0, x = 0; \ + while (y < h && x < w) { \ + for (d = 0; d < h - y && d < w - x - DETECT_SUBROW_WIDTH; d++) { \ + pix = ((uint##bpp##_t *)tightBeforeBuf)[(y+d)*w+x+d]; \ + if (endianMismatch) { \ + pix = Swap##bpp(pix); \ + } \ + for (c = 0; c < 3; c++) { \ + left[c] = (int)(pix >> shiftBits[c] & maxColor[c]); \ + } \ + for (dx = 1; dx <= DETECT_SUBROW_WIDTH; dx++) { \ + pix = ((uint##bpp##_t *)tightBeforeBuf)[(y+d)*w+x+d+dx]; \ + if (endianMismatch) { \ + pix = Swap##bpp(pix); \ + } \ + sum = 0; \ + for (c = 0; c < 3; c++) { \ + sample = (int)(pix >> shiftBits[c] & maxColor[c]); \ + sum += abs(sample - left[c]); \ + left[c] = sample; \ + } \ + if (sum > 255) \ + sum = 255; \ + diffStat[sum]++; \ + pixelCount++; \ + } \ + } \ + if (w > h) { \ + x += h; \ + y = 0; \ + } else { \ + x = 0; \ + y += w; \ + } \ + } \ + \ + if ((diffStat[0] + diffStat[1]) * 100 / pixelCount >= 90) \ + return 0; \ + \ + avgError = 0; \ + for (c = 1; c < 8; c++) { \ + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ + if (diffStat[c] == 0 || diffStat[c] > diffStat[c-1] * 2) \ + return 0; \ + } \ + for (; c < 256; c++) { \ + avgError += (unsigned long)diffStat[c] * (unsigned long)(c * c); \ + } \ + avgError /= (pixelCount - diffStat[0]); \ + \ + return avgError; \ +} + +DEFINE_DETECT_FUNCTION(16) +DEFINE_DETECT_FUNCTION(32) + + +/* + * JPEG compression stuff. + */ + +static TLS struct jpeg_destination_mgr jpegDstManager; +static TLS rfbBool jpegError = FALSE; +static TLS int jpegDstDataLen = 0; + +static rfbBool +SendJpegRect(rfbClientPtr cl, int x, int y, int w, int h, int quality) +{ + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + uint8_t *srcBuf; + JSAMPROW rowPointer[1]; + int dy; + + if (cl->screen->serverFormat.bitsPerPixel == 8) + return SendFullColorRect(cl, x, y, w, h); + + srcBuf = (uint8_t *)malloc(w * 3); + if (srcBuf == NULL) { + return SendFullColorRect(cl, x, y, w, h); + } + rowPointer[0] = srcBuf; + + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + cinfo.image_width = w; + cinfo.image_height = h; + cinfo.input_components = 3; + cinfo.in_color_space = JCS_RGB; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, TRUE); + + JpegSetDstManager (&cinfo); + + jpeg_start_compress(&cinfo, TRUE); + + for (dy = 0; dy < h; dy++) { + PrepareRowForImg(cl, srcBuf, x, y + dy, w); + jpeg_write_scanlines(&cinfo, rowPointer, 1); + if (jpegError) + break; + } + + if (!jpegError) + jpeg_finish_compress(&cinfo); + + jpeg_destroy_compress(&cinfo); + free(srcBuf); + + if (jpegError) + return SendFullColorRect(cl, x, y, w, h); + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightJpeg << 4); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + return SendCompressedData(cl, jpegDstDataLen); +} + +static void +PrepareRowForImg(rfbClientPtr cl, + uint8_t *dst, + int x, + int y, + int count) +{ + if (cl->screen->serverFormat.bitsPerPixel == 32) { + if ( cl->screen->serverFormat.redMax == 0xFF && + cl->screen->serverFormat.greenMax == 0xFF && + cl->screen->serverFormat.blueMax == 0xFF ) { + PrepareRowForImg24(cl, dst, x, y, count); + } else { + PrepareRowForImg32(cl, dst, x, y, count); + } + } else { + /* 16 bpp assumed. */ + PrepareRowForImg16(cl, dst, x, y, count); + } +} + +static void +PrepareRowForImg24(rfbClientPtr cl, + uint8_t *dst, + int x, + int y, + int count) +{ + uint32_t *fbptr; + uint32_t pix; + + fbptr = (uint32_t *) + &cl->scaledScreen->frameBuffer[y * cl->scaledScreen->paddedWidthInBytes + x * 4]; + + while (count--) { + pix = *fbptr++; + *dst++ = (uint8_t)(pix >> cl->screen->serverFormat.redShift); + *dst++ = (uint8_t)(pix >> cl->screen->serverFormat.greenShift); + *dst++ = (uint8_t)(pix >> cl->screen->serverFormat.blueShift); + } +} + +#define DEFINE_JPEG_GET_ROW_FUNCTION(bpp) \ + \ +static void \ +PrepareRowForImg##bpp(rfbClientPtr cl, uint8_t *dst, int x, int y, int count) { \ + uint##bpp##_t *fbptr; \ + uint##bpp##_t pix; \ + int inRed, inGreen, inBlue; \ + \ + fbptr = (uint##bpp##_t *) \ + &cl->scaledScreen->frameBuffer[y * cl->scaledScreen->paddedWidthInBytes + \ + x * (bpp / 8)]; \ + \ + while (count--) { \ + pix = *fbptr++; \ + \ + inRed = (int) \ + (pix >> cl->screen->serverFormat.redShift & cl->screen->serverFormat.redMax); \ + inGreen = (int) \ + (pix >> cl->screen->serverFormat.greenShift & cl->screen->serverFormat.greenMax); \ + inBlue = (int) \ + (pix >> cl->screen->serverFormat.blueShift & cl->screen->serverFormat.blueMax); \ + \ + *dst++ = (uint8_t)((inRed * 255 + cl->screen->serverFormat.redMax / 2) / \ + cl->screen->serverFormat.redMax); \ + *dst++ = (uint8_t)((inGreen * 255 + cl->screen->serverFormat.greenMax / 2) / \ + cl->screen->serverFormat.greenMax); \ + *dst++ = (uint8_t)((inBlue * 255 + cl->screen->serverFormat.blueMax / 2) / \ + cl->screen->serverFormat.blueMax); \ + } \ +} + +DEFINE_JPEG_GET_ROW_FUNCTION(16) +DEFINE_JPEG_GET_ROW_FUNCTION(32) + +/* + * Destination manager implementation for JPEG library. + */ + +static void +JpegInitDestination(j_compress_ptr cinfo) +{ + jpegError = FALSE; + jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; + jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; +} + +static boolean +JpegEmptyOutputBuffer(j_compress_ptr cinfo) +{ + jpegError = TRUE; + jpegDstManager.next_output_byte = (JOCTET *)tightAfterBuf; + jpegDstManager.free_in_buffer = (size_t)tightAfterBufSize; + + return TRUE; +} + +static void +JpegTermDestination(j_compress_ptr cinfo) +{ + jpegDstDataLen = tightAfterBufSize - jpegDstManager.free_in_buffer; +} + +static void +JpegSetDstManager(j_compress_ptr cinfo) +{ + jpegDstManager.init_destination = JpegInitDestination; + jpegDstManager.empty_output_buffer = JpegEmptyOutputBuffer; + jpegDstManager.term_destination = JpegTermDestination; + cinfo->dest = &jpegDstManager; +} + +/* + * PNG compression stuff. + */ + +#ifdef LIBVNCSERVER_HAVE_LIBPNG + +static TLS int pngDstDataLen = 0; + +static rfbBool CanSendPngRect(rfbClientPtr cl, int w, int h) { + if (cl->tightEncoding != rfbEncodingTightPng) { + return FALSE; + } + + if ( cl->screen->serverFormat.bitsPerPixel == 8 || + cl->format.bitsPerPixel == 8) { + return FALSE; + } + + return TRUE; +} + +static void pngWriteData(png_structp png_ptr, png_bytep data, + png_size_t length) +{ + //rfbClientPtr cl = png_get_io_ptr(png_ptr); + + //buffer_reserve(&vs->tight.png, vs->tight.png.offset + length); + //memcpy(vs->tight.png.buffer + vs->tight.png.offset, data, length); + memcpy(tightAfterBuf + pngDstDataLen, data, length); + + pngDstDataLen += length; +} + +static void pngFlushData(png_structp png_ptr) +{ +} + + +static void *pngMalloc(png_structp png_ptr, png_size_t size) +{ + return malloc(size); +} + +static void pngFree(png_structp png_ptr, png_voidp ptr) +{ + free(ptr); +} + +static rfbBool SendPngRect(rfbClientPtr cl, int x, int y, int w, int h) { + //rfbLog(">> SendPngRect x:%d, y:%d, w:%d, h:%d\n", x, y, w, h); + + png_byte color_type; + png_structp png_ptr; + png_infop info_ptr; + png_colorp png_palette = NULL; + int level = tightPngConf[cl->tightCompressLevel].png_zlib_level; + int filters = tightPngConf[cl->tightCompressLevel].png_filters; + uint8_t *buf; + int dy; + + pngDstDataLen = 0; + + png_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL, + NULL, pngMalloc, pngFree); + + if (png_ptr == NULL) + return FALSE; + + info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr == NULL) { + png_destroy_write_struct(&png_ptr, NULL); + return FALSE; + } + + png_set_write_fn(png_ptr, (void *) cl, pngWriteData, pngFlushData); + png_set_compression_level(png_ptr, level); + png_set_filter(png_ptr, PNG_FILTER_TYPE_DEFAULT, filters); + +// TODO: +// if (palette) { +// color_type = PNG_COLOR_TYPE_PALETTE; +// } else { + color_type = PNG_COLOR_TYPE_RGB; +// } + + png_set_IHDR(png_ptr, info_ptr, w, h, + 8, color_type, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + +// if (color_type == PNG_COLOR_TYPE_PALETTE) { +// struct palette_cb_priv priv; +// +// png_palette = pngMalloc(png_ptr, sizeof(*png_palette) * +// palette_size(palette)); +// +// priv.vs = vs; +// priv.png_palette = png_palette; +// palette_iter(palette, write_png_palette, &priv); +// +// png_set_PLTE(png_ptr, info_ptr, png_palette, palette_size(palette)); +// +// offset = vs->tight.tight.offset; +// if (vs->clientds.pf.bytes_per_pixel == 4) { +// tight_encode_indexed_rect32(vs->tight.tight.buffer, w * h, palette); +// } else { +// tight_encode_indexed_rect16(vs->tight.tight.buffer, w * h, palette); +// } +// } + + png_write_info(png_ptr, info_ptr); + + ////buffer_reserve(&vs->tight.png, 2048); + buf = malloc(w * 3); + for (dy = 0; dy < h; dy++) + { +// if (color_type == PNG_COLOR_TYPE_PALETTE) { +// memcpy(buf, vs->tight.tight.buffer + (dy * w), w); +// } else { + PrepareRowForImg(cl, buf, x, y + dy, w); +// } + png_write_row(png_ptr, buf); + } + free(buf); + + png_write_end(png_ptr, NULL); + + if (color_type == PNG_COLOR_TYPE_PALETTE) { + pngFree(png_ptr, png_palette); + } + + png_destroy_write_struct(&png_ptr, &info_ptr); + + // done v + + if (cl->ublen + TIGHT_MIN_TO_COMPRESS + 1 > UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + cl->updateBuf[cl->ublen++] = (char)(rfbTightPng << 4); + rfbStatRecordEncodingSentAdd(cl, cl->tightEncoding, 1); + + //rfbLog("<< SendPngRect\n"); + return SendCompressedData(cl, pngDstDataLen); +} +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore new file mode 100755 index 0000000..22a4e72 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/.cvsignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c new file mode 100755 index 0000000..c08e506 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#include +#include "rfb/rfb.h" +#include "filelistinfo.h" + + +/* This method is used for debugging purpose */ +void +DisplayFileList(FileListInfo fli) +{ + int i = 0; + if((fli.pEntries == NULL) || (fli.numEntries == 0)) return; + + rfbLog("DISPLAYING FILE NAMES IN THE LIST ...START\n\n"); + rfbLog("Numer of entries:: %d\n", fli.numEntries); + for(i = 0; i < fli.numEntries; i++) + rfbLog("file[%d]\t<%s>\n", i, fli.pEntries[i].name); + rfbLog("DISPLAYING FILE NAMES IN THE LIST ...END\n\n"); +} + +#ifndef __GNUC__ +#define __FUNCTION__ "unknown" +#endif + +int +AddFileListItemInfo(FileListInfoPtr fileListInfoPtr, char* name, + unsigned int size, unsigned int data) +{ + FileListItemInfoPtr fileListItemInfoPtr = (FileListItemInfoPtr) + calloc((fileListInfoPtr->numEntries + 1), + sizeof(FileListItemInfo)); + if(fileListItemInfoPtr == NULL) { + rfbLog("File [%s]: Method [%s]: fileListItemInfoPtr is NULL\n", + __FILE__, __FUNCTION__); + return FAILURE; + } + + if(fileListInfoPtr->numEntries != 0) { + memcpy(fileListItemInfoPtr, fileListInfoPtr->pEntries, + fileListInfoPtr->numEntries * sizeof(FileListItemInfo)); + } + + strcpy(fileListItemInfoPtr[fileListInfoPtr->numEntries].name, name); + fileListItemInfoPtr[fileListInfoPtr->numEntries].size = size; + fileListItemInfoPtr[fileListInfoPtr->numEntries].data = data; + + if(fileListInfoPtr->pEntries != NULL) { + free(fileListInfoPtr->pEntries); + fileListInfoPtr->pEntries = NULL; + } + + fileListInfoPtr->pEntries = fileListItemInfoPtr; + fileListItemInfoPtr = NULL; + fileListInfoPtr->numEntries++; + + return SUCCESS; +} + + +char* +GetFileNameAt(FileListInfo fileListInfo, int number) +{ + char* name = NULL; + if(number >= 0 && number < fileListInfo.numEntries) + name = fileListInfo.pEntries[number].name; + return name; +} + + +unsigned int +GetFileSizeAt(FileListInfo fileListInfo, int number) +{ + unsigned int size = 0; + if(number >= 0 && number < fileListInfo.numEntries) + size = fileListInfo.pEntries[number].size; + return size; +} + + +unsigned int +GetFileDataAt(FileListInfo fileListInfo, int number) +{ + unsigned int data = 0; + if(number >= 0 && number < fileListInfo.numEntries) + data = fileListInfo.pEntries[number].data; + return data; +} + + +unsigned int +GetSumOfFileNamesLength(FileListInfo fileListInfo) +{ + int i = 0, sumLen = 0; + for(i = 0; i < fileListInfo.numEntries; i++) + sumLen += strlen(fileListInfo.pEntries[i].name); + return sumLen; +} + + +void +FreeFileListInfo(FileListInfo fileListInfo) +{ + if(fileListInfo.pEntries != NULL) { + free(fileListInfo.pEntries); + fileListInfo.pEntries = NULL; + } + fileListInfo.numEntries = 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h new file mode 100755 index 0000000..a53964c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filelistinfo.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#ifndef FILE_LIST_INFO_H +#define FILE_LIST_INFO_H + +#include + +#if !defined(NAME_MAX) +#define NAME_MAX 255 +#endif + + +#define SUCCESS 1 +#define FAILURE 0 + +typedef struct _FileListItemInfo { + char name[NAME_MAX]; + unsigned int size; + unsigned int data; +} FileListItemInfo, *FileListItemInfoPtr; + +typedef struct _FileListItemSize { + unsigned int size; + unsigned int data; +} FileListItemSize, *FileListItemSizePtr; + +typedef struct _FileListInfo { + FileListItemInfoPtr pEntries; + int numEntries; +} FileListInfo, *FileListInfoPtr; + +int AddFileListItemInfo(FileListInfoPtr fileListInfoPtr, char* name, unsigned int size, unsigned int data); +char* GetFileNameAt(FileListInfo fileListInfo, int number); +unsigned int GetFileSizeAt(FileListInfo fileListInfo, int number); +unsigned int GetFileDataAt(FileListInfo fileListInfo, int number); +unsigned int GetSumOfFileNamesLength(FileListInfo fileListInfo); +void FreeFileListInfo(FileListInfo fileListInfo); + +void DisplayFileList(FileListInfo fli); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c new file mode 100755 index 0000000..7dae2cd --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.c @@ -0,0 +1,636 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rfbtightproto.h" +#include "filelistinfo.h" +#include "filetransfermsg.h" +#include "handlefiletransferrequest.h" + +#define SZ_RFBBLOCKSIZE 8192 + + +void +FreeFileTransferMsg(FileTransferMsg ftm) +{ + + if(ftm.data != NULL) { + free(ftm.data); + ftm.data = NULL; + } + + ftm.length = 0; + +} + + +/****************************************************************************** + * Methods to handle file list request. + ******************************************************************************/ + +int CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag); +FileTransferMsg CreateFileListErrMsg(char flags); +FileTransferMsg CreateFileListMsg(FileListInfo fileListInfo, char flags); + + +/* + * This is the method called by HandleFileListRequest to get the file list + */ + +FileTransferMsg +GetFileListResponseMsg(char* path, char flags) +{ + FileTransferMsg fileListMsg; + FileListInfo fileListInfo; + int status = -1; + + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + memset(&fileListInfo, 0, sizeof(FileListInfo)); + + + /* fileListInfo can have null data if the folder is Empty + or if some error condition has occured. + The return value is 'failure' only if some error condition has occured. + */ + status = CreateFileListInfo(&fileListInfo, path, !(flags & 0x10)); + + if(status == FAILURE) { + fileListMsg = CreateFileListErrMsg(flags); + } + else { + /* DisplayFileList(fileListInfo); For Debugging */ + + fileListMsg = CreateFileListMsg(fileListInfo, flags); + FreeFileListInfo(fileListInfo); + } + + return fileListMsg; +} + +#ifndef __GNUC__ +#define __FUNCTION__ "unknown" +#endif + +int +CreateFileListInfo(FileListInfoPtr pFileListInfo, char* path, int flag) +{ + DIR* pDir = NULL; + struct dirent* pDirent = NULL; + + if((path == NULL) || (strlen(path) == 0)) { + /* In this case we will send the list of entries in ftp root*/ + sprintf(path, "%s%s", GetFtpRoot(), "/"); + } + + if((pDir = opendir(path)) == NULL) { + rfbLog("File [%s]: Method [%s]: not able to open the dir\n", + __FILE__, __FUNCTION__); + return FAILURE; + } + + while((pDirent = readdir(pDir))) { + if(strcmp(pDirent->d_name, ".") && strcmp(pDirent->d_name, "..")) { + struct stat stat_buf; + /* + int fpLen = sizeof(char)*(strlen(pDirent->d_name)+strlen(path)+2); + */ + char fullpath[PATH_MAX]; + + memset(fullpath, 0, PATH_MAX); + + strcpy(fullpath, path); + if(path[strlen(path)-1] != '/') + strcat(fullpath, "/"); + strcat(fullpath, pDirent->d_name); + + if(stat(fullpath, &stat_buf) < 0) { + rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n", + __FILE__, __FUNCTION__, fullpath); + continue; + } + + if(S_ISDIR(stat_buf.st_mode)) { + if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, -1, 0) == 0) { + rfbLog("File [%s]: Method [%s]: Add directory %s in the" + " list failed\n", __FILE__, __FUNCTION__, fullpath); + continue; + } + } + else { + if(flag) { + if(AddFileListItemInfo(pFileListInfo, pDirent->d_name, + stat_buf.st_size, + stat_buf.st_mtime) == 0) { + rfbLog("File [%s]: Method [%s]: Add file %s in the " + "list failed\n", __FILE__, __FUNCTION__, fullpath); + continue; + } + } + } + } + } + if(closedir(pDir) < 0) { + rfbLog("File [%s]: Method [%s]: ERROR Couldn't close dir\n", + __FILE__, __FUNCTION__); + } + + return SUCCESS; +} + + +FileTransferMsg +CreateFileListErrMsg(char flags) +{ + FileTransferMsg fileListMsg; + rfbFileListDataMsg* pFLD = NULL; + char* data = NULL; + unsigned int length = 0; + + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + + data = (char*) calloc(sizeof(rfbFileListDataMsg), sizeof(char)); + if(data == NULL) { + return fileListMsg; + } + length = sizeof(rfbFileListDataMsg) * sizeof(char); + pFLD = (rfbFileListDataMsg*) data; + + pFLD->type = rfbFileListData; + pFLD->numFiles = Swap16IfLE(0); + pFLD->dataSize = Swap16IfLE(0); + pFLD->compressedSize = Swap16IfLE(0); + pFLD->flags = flags | 0x80; + + fileListMsg.data = data; + fileListMsg.length = length; + + return fileListMsg; +} + + +FileTransferMsg +CreateFileListMsg(FileListInfo fileListInfo, char flags) +{ + FileTransferMsg fileListMsg; + rfbFileListDataMsg* pFLD = NULL; + char *data = NULL, *pFileNames = NULL; + unsigned int length = 0, dsSize = 0, i = 0; + FileListItemSizePtr pFileListItemSize = NULL; + + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + dsSize = fileListInfo.numEntries * 8; + length = sz_rfbFileListDataMsg + dsSize + + GetSumOfFileNamesLength(fileListInfo) + + fileListInfo.numEntries; + + data = (char*) calloc(length, sizeof(char)); + if(data == NULL) { + return fileListMsg; + } + pFLD = (rfbFileListDataMsg*) data; + pFileListItemSize = (FileListItemSizePtr) &data[sz_rfbFileListDataMsg]; + pFileNames = &data[sz_rfbFileListDataMsg + dsSize]; + + pFLD->type = rfbFileListData; + pFLD->flags = flags & 0xF0; + pFLD->numFiles = Swap16IfLE(fileListInfo.numEntries); + pFLD->dataSize = Swap16IfLE(GetSumOfFileNamesLength(fileListInfo) + + fileListInfo.numEntries); + pFLD->compressedSize = pFLD->dataSize; + + for(i =0; i rcft.rcfd.fName; + + memset(pBuf, 0, SZ_RFBBLOCKSIZE); + + if((rtcp->rcft.rcfd.downloadInProgress == FALSE) && (rtcp->rcft.rcfd.downloadFD == -1)) { + if((rtcp->rcft.rcfd.downloadFD = open(path, O_RDONLY)) == -1) { + rfbLog("File [%s]: Method [%s]: Error: Couldn't open file\n", + __FILE__, __FUNCTION__); + return GetFileDownloadReadDataErrMsg(); + } + rtcp->rcft.rcfd.downloadInProgress = TRUE; + } + if((rtcp->rcft.rcfd.downloadInProgress == TRUE) && (rtcp->rcft.rcfd.downloadFD != -1)) { + if( (numOfBytesRead = read(rtcp->rcft.rcfd.downloadFD, pBuf, SZ_RFBBLOCKSIZE)) <= 0) { + close(rtcp->rcft.rcfd.downloadFD); + rtcp->rcft.rcfd.downloadFD = -1; + rtcp->rcft.rcfd.downloadInProgress = FALSE; + if(numOfBytesRead == 0) { + return CreateFileDownloadZeroSizeDataMsg(rtcp->rcft.rcfd.mTime); + } + return GetFileDownloadReadDataErrMsg(); + } + return CreateFileDownloadBlockSizeDataMsg(numOfBytesRead, pBuf); + } + return GetFileDownLoadErrMsg(); +} + + +FileTransferMsg +ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + FileTransferMsg fileDownloadMsg; + struct stat stat_buf; + int sz_rfbFileSize = 0; + char* path = rtcp->rcft.rcfd.fName; + + memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); + + if( (path == NULL) || (strlen(path) == 0) || + (stat(path, &stat_buf) < 0) || (!(S_ISREG(stat_buf.st_mode))) ) { + + char reason[] = "Cannot open file, perhaps it is absent or is not a regular file"; + int reasonLen = strlen(reason); + + rfbLog("File [%s]: Method [%s]: Reading stat for path %s failed\n", + __FILE__, __FUNCTION__, path); + + fileDownloadMsg = CreateFileDownloadErrMsg(reason, reasonLen); + } + else { + rtcp->rcft.rcfd.mTime = stat_buf.st_mtime; + sz_rfbFileSize = stat_buf.st_size; + if(sz_rfbFileSize <= 0) { + fileDownloadMsg = CreateFileDownloadZeroSizeDataMsg(stat_buf.st_mtime); + } + + } + return fileDownloadMsg; +} + + +FileTransferMsg +CreateFileDownloadErrMsg(char* reason, unsigned int reasonLen) +{ + FileTransferMsg fileDownloadErrMsg; + int length = sz_rfbFileDownloadFailedMsg + reasonLen + 1; + rfbFileDownloadFailedMsg *pFDF = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileDownloadErrMsg, 0, sizeof(FileTransferMsg)); + if(pData == NULL) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileDownloadErrMsg; + } + + pFDF = (rfbFileDownloadFailedMsg *) pData; + pFollow = &pData[sz_rfbFileDownloadFailedMsg]; + + pFDF->type = rfbFileDownloadFailed; + pFDF->reasonLen = Swap16IfLE(reasonLen); + memcpy(pFollow, reason, reasonLen); + + fileDownloadErrMsg.data = pData; + fileDownloadErrMsg.length = length; + + return fileDownloadErrMsg; +} + + +FileTransferMsg +CreateFileDownloadZeroSizeDataMsg(unsigned long mTime) +{ + FileTransferMsg fileDownloadZeroSizeDataMsg; + int length = sz_rfbFileDownloadDataMsg + sizeof(int); + rfbFileDownloadDataMsg *pFDD = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileDownloadZeroSizeDataMsg, 0, sizeof(FileTransferMsg)); + if(pData == NULL) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileDownloadZeroSizeDataMsg; + } + + pFDD = (rfbFileDownloadDataMsg *) pData; + pFollow = &pData[sz_rfbFileDownloadDataMsg]; + + pFDD->type = rfbFileDownloadData; + pFDD->compressLevel = 0; + pFDD->compressedSize = Swap16IfLE(0); + pFDD->realSize = Swap16IfLE(0); + + memcpy(pFollow, &mTime, sizeof(unsigned long)); + + fileDownloadZeroSizeDataMsg.data = pData; + fileDownloadZeroSizeDataMsg.length = length; + + return fileDownloadZeroSizeDataMsg; + +} + + +FileTransferMsg +CreateFileDownloadBlockSizeDataMsg(unsigned short sizeFile, char *pFile) +{ + FileTransferMsg fileDownloadBlockSizeDataMsg; + int length = sz_rfbFileDownloadDataMsg + sizeFile; + rfbFileDownloadDataMsg *pFDD = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileDownloadBlockSizeDataMsg, 0, sizeof(FileTransferMsg)); + if(NULL == pData) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileDownloadBlockSizeDataMsg; + } + + pFDD = (rfbFileDownloadDataMsg *) pData; + pFollow = &pData[sz_rfbFileDownloadDataMsg]; + + pFDD->type = rfbFileDownloadData; + pFDD->compressLevel = 0; + pFDD->compressedSize = Swap16IfLE(sizeFile); + pFDD->realSize = Swap16IfLE(sizeFile); + + memcpy(pFollow, pFile, sizeFile); + + fileDownloadBlockSizeDataMsg.data = pData; + fileDownloadBlockSizeDataMsg.length = length; + + return fileDownloadBlockSizeDataMsg; + +} + + +/****************************************************************************** + * Methods to handle file upload request + ******************************************************************************/ + +FileTransferMsg CreateFileUploadErrMsg(char* reason, unsigned int reasonLen); + +FileTransferMsg +GetFileUploadLengthErrResponseMsg() +{ + char reason [] = "Path length exceeds PATH_MAX (4096) bytes"; + int reasonLen = strlen(reason); + + return CreateFileUploadErrMsg(reason, reasonLen); +} + + +FileTransferMsg +ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + FileTransferMsg fileUploadErrMsg; + + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + if( (rtcp->rcft.rcfu.fName == NULL) || + (strlen(rtcp->rcft.rcfu.fName) == 0) || + ((rtcp->rcft.rcfu.uploadFD = creat(rtcp->rcft.rcfu.fName, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) == -1)) { + + char reason[] = "Could not create file"; + int reasonLen = strlen(reason); + fileUploadErrMsg = CreateFileUploadErrMsg(reason, reasonLen); + } + else + rtcp->rcft.rcfu.uploadInProgress = TRUE; + + return fileUploadErrMsg; +} + + +FileTransferMsg +GetFileUploadCompressedLevelErrMsg() +{ + char reason[] = "Server does not support data compression on upload"; + int reasonLen = strlen(reason); + + return CreateFileUploadErrMsg(reason, reasonLen); +} + + +FileTransferMsg +ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf) +{ + FileTransferMsg ftm; + unsigned long numOfBytesWritten = 0; + + memset(&ftm, 0, sizeof(FileTransferMsg)); + + numOfBytesWritten = write(rtcp->rcft.rcfu.uploadFD, pBuf, rtcp->rcft.rcfu.fSize); + + if(numOfBytesWritten != rtcp->rcft.rcfu.fSize) { + char reason[] = "Error writing file data"; + int reasonLen = strlen(reason); + ftm = CreateFileUploadErrMsg(reason, reasonLen); + CloseUndoneFileTransfer(cl, rtcp); + } + return ftm; +} + + +void +FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + /* Here we are settimg the modification and access time of the file */ + /* Windows code stes mod/access/creation time of the file */ + struct utimbuf utb; + + utb.actime = utb.modtime = rtcp->rcft.rcfu.mTime; + if(utime(rtcp->rcft.rcfu.fName, &utb) == -1) { + rfbLog("File [%s]: Method [%s]: Setting the modification/access" + " time for the file <%s> failed\n", __FILE__, + __FUNCTION__, rtcp->rcft.rcfu.fName); + } + + if(rtcp->rcft.rcfu.uploadFD != -1) { + close(rtcp->rcft.rcfu.uploadFD); + rtcp->rcft.rcfu.uploadFD = -1; + rtcp->rcft.rcfu.uploadInProgress = FALSE; + } +} + + +FileTransferMsg +CreateFileUploadErrMsg(char* reason, unsigned int reasonLen) +{ + FileTransferMsg fileUploadErrMsg; + int length = sz_rfbFileUploadCancelMsg + reasonLen; + rfbFileUploadCancelMsg *pFDF = NULL; + char *pFollow = NULL; + + char *pData = (char*) calloc(length, sizeof(char)); + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + if(pData == NULL) { + rfbLog("File [%s]: Method [%s]: pData is NULL\n", + __FILE__, __FUNCTION__); + return fileUploadErrMsg; + } + + pFDF = (rfbFileUploadCancelMsg *) pData; + pFollow = &pData[sz_rfbFileUploadCancelMsg]; + + pFDF->type = rfbFileUploadCancel; + pFDF->reasonLen = Swap16IfLE(reasonLen); + memcpy(pFollow, reason, reasonLen); + + fileUploadErrMsg.data = pData; + fileUploadErrMsg.length = length; + + return fileUploadErrMsg; +} + + +/****************************************************************************** + * Method to cancel File Transfer operation. + ******************************************************************************/ + +void +CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + /* TODO :: File Upload case is not handled currently */ + /* TODO :: In case of concurrency we need to use Critical Section */ + + if(cl == NULL) + return; + + + if(rtcp->rcft.rcfu.uploadInProgress == TRUE) { + rtcp->rcft.rcfu.uploadInProgress = FALSE; + + if(rtcp->rcft.rcfu.uploadFD != -1) { + close(rtcp->rcft.rcfu.uploadFD); + rtcp->rcft.rcfu.uploadFD = -1; + } + + if(unlink(rtcp->rcft.rcfu.fName) == -1) { + rfbLog("File [%s]: Method [%s]: Delete operation on file <%s> failed\n", + __FILE__, __FUNCTION__, rtcp->rcft.rcfu.fName); + } + + memset(rtcp->rcft.rcfu.fName, 0 , PATH_MAX); + } + + if(rtcp->rcft.rcfd.downloadInProgress == TRUE) { + rtcp->rcft.rcfd.downloadInProgress = FALSE; + + if(rtcp->rcft.rcfd.downloadFD != -1) { + close(rtcp->rcft.rcfd.downloadFD); + rtcp->rcft.rcfd.downloadFD = -1; + } + memset(rtcp->rcft.rcfd.fName, 0 , PATH_MAX); + } +} + + +/****************************************************************************** + * Method to handle create directory request. + ******************************************************************************/ + +void +CreateDirectory(char* dirName) +{ + if(dirName == NULL) return; + + if(mkdir(dirName, 0700) == -1) { + rfbLog("File [%s]: Method [%s]: Create operation for directory <%s> failed\n", + __FILE__, __FUNCTION__, dirName); + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h new file mode 100755 index 0000000..30e58df --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/filetransfermsg.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + + +#ifndef FILE_TRANSFER_MSG_H +#define FILE_TRANSFER_MSG_H + +typedef struct _FileTransferMsg { + char* data; + unsigned int length; +} FileTransferMsg; + +FileTransferMsg GetFileListResponseMsg(char* path, char flag); + +FileTransferMsg GetFileDownloadResponseMsg(char* path); +FileTransferMsg GetFileDownloadLengthErrResponseMsg(); +FileTransferMsg GetFileDownLoadErrMsg(); +FileTransferMsg GetFileDownloadResponseMsgInBlocks(rfbClientPtr cl, rfbTightClientPtr data); +FileTransferMsg ChkFileDownloadErr(rfbClientPtr cl, rfbTightClientPtr data); + +FileTransferMsg GetFileUploadLengthErrResponseMsg(); +FileTransferMsg GetFileUploadCompressedLevelErrMsg(); +FileTransferMsg ChkFileUploadErr(rfbClientPtr cl, rfbTightClientPtr data); +FileTransferMsg ChkFileUploadWriteErr(rfbClientPtr cl, rfbTightClientPtr data, char* pBuf); + +void CreateDirectory(char* dirName); +void FileUpdateComplete(rfbClientPtr cl, rfbTightClientPtr data); +void CloseUndoneFileTransfer(rfbClientPtr cl, rfbTightClientPtr data); + +void FreeFileTransferMsg(FileTransferMsg ftm); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c new file mode 100755 index 0000000..2bd5ba1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.c @@ -0,0 +1,993 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "rfbtightproto.h" +#include "filetransfermsg.h" +#include "handlefiletransferrequest.h" + + +pthread_mutex_t fileDownloadMutex = PTHREAD_MUTEX_INITIALIZER; + +rfbBool fileTransferEnabled = TRUE; +rfbBool fileTransferInitted = FALSE; +char ftproot[PATH_MAX]; + + +/****************************************************************************** + * File Transfer Init methods. These methods are called for initializating + * File Transfer and setting ftproot. + ******************************************************************************/ + +void InitFileTransfer(); +int SetFtpRoot(char* path); +char* GetHomeDir(uid_t uid); +void FreeHomeDir(char *homedir); + +/* + * InitFileTransfer method is called before parsing the command-line options + * for Xvnc. This sets the ftproot to the Home dir of the user running the Xvnc + * server. In case of error ftproot is set to '\0' char. + */ + +void +InitFileTransfer() +{ + char* userHome = NULL; + uid_t uid = geteuid(); + + if(fileTransferInitted) + return; + + rfbLog("tightvnc-filetransfer/InitFileTransfer\n"); + + memset(ftproot, 0, sizeof(ftproot)); + + userHome = GetHomeDir(uid); + + if((userHome != NULL) && (strlen(userHome) != 0)) { + SetFtpRoot(userHome); + FreeHomeDir(userHome); + } + + fileTransferEnabled = TRUE; + fileTransferInitted = TRUE; +} + +#ifndef __GNUC__ +#define __FUNCTION__ "unknown" +#endif + +/* + * This method is called from InitFileTransfer method and + * if the command line option for ftproot is provided. + */ +int +SetFtpRoot(char* path) +{ + struct stat stat_buf; + DIR* dir = NULL; + + rfbLog("tightvnc-filetransfer/SetFtpRoot\n"); + + if((path == NULL) || (strlen(path) == 0) || (strlen(path) > (PATH_MAX - 1))) { + rfbLog("File [%s]: Method [%s]: parameter passed is improper, ftproot" + " not changed\n", __FILE__, __FUNCTION__); + return FALSE; + } + + if(stat(path, &stat_buf) < 0) { + rfbLog("File [%s]: Method [%s]: Reading stat for file %s failed\n", + __FILE__, __FUNCTION__, path); + return FALSE; + } + + if(S_ISDIR(stat_buf.st_mode) == 0) { + rfbLog("File [%s]: Method [%s]: path specified is not a directory\n", + __FILE__, __FUNCTION__); + return FALSE; + } + + if((dir = opendir(path)) == NULL) { + rfbLog("File [%s]: Method [%s]: Not able to open the directory\n", + __FILE__, __FUNCTION__); + return FALSE; + } + else { + closedir(dir); + dir = NULL; + } + + + memset(ftproot, 0, PATH_MAX); + if(path[strlen(path)-1] == '/') { + memcpy(ftproot, path, strlen(path)-1); + } + else + memcpy(ftproot, path, strlen(path)); + + + return TRUE; +} + + +/* + * Get the home directory for the user name + * param: username - name of the user for whom the home directory is required. + * returns: returns the home directory for the user, or null in case the entry + * is not found or any error. The returned string must be freed by calling the + * freehomedir function. +*/ +char* +GetHomeDir(uid_t uid) +{ + struct passwd *pwEnt = NULL; + char *homedir = NULL; + + pwEnt = getpwuid (uid); + if (pwEnt == NULL) + return NULL; + + if(pwEnt->pw_dir != NULL) { + homedir = strdup (pwEnt->pw_dir); + } + + return homedir; +} + + +/* + * Free the home directory allocated by a previous call to retrieve the home + * directory. param: homedir - the string returned by a previous call to + * retrieve home directory for a user. + */ +void +FreeHomeDir(char *homedir) +{ + free (homedir); +} + + +/****************************************************************************** + * General methods. + ******************************************************************************/ + +/* + * When the console sends the File Transfer Request, it sends the file path with + * ftproot as "/". So on Agent, to get the absolute file path we need to prepend + * the ftproot to it. + */ +char* +ConvertPath(char* path) +{ + char p[PATH_MAX]; + memset(p, 0, PATH_MAX); + + if( (path == NULL) || + (strlen(path) == 0) || + (strlen(path)+strlen(ftproot) > PATH_MAX - 1) ) { + + rfbLog("File [%s]: Method [%s]: cannot create path for file transfer\n", + __FILE__, __FUNCTION__); + return NULL; + } + + memcpy(p, path, strlen(path)); + memset(path, 0, PATH_MAX); + sprintf(path, "%s%s", ftproot, p); + + return path; +} + + +void +EnableFileTransfer(rfbBool enable) +{ + fileTransferEnabled = enable; +} + + +rfbBool +IsFileTransferEnabled() +{ + return fileTransferEnabled; +} + + +char* +GetFtpRoot() +{ + return ftproot; +} + + +/****************************************************************************** + * Methods to Handle File List Request. + ******************************************************************************/ + +/* + * HandleFileListRequest method is called when the server receives + * FileListRequest. In case of success a file list is sent to the client. + * For File List Request there is no failure reason sent.So here in case of any + * "unexpected" error no information will be sent. As these conditions should + * never come. Lets hope it never arrives :) + * In case of dir open failure an empty list will be sent, just the header of + * the message filled up. So on console you will get an Empty listing. + */ +void +HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data) +{ + rfbClientToServerTightMsg msg; + int n = 0; + char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */ + FileTransferMsg fileListMsg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + memset(path, 0, PATH_MAX); + memset(&fileListMsg, 0, sizeof(FileTransferMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileListRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Socket error while reading dir name" + " length\n", __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.flr.dirNameSize = Swap16IfLE(msg.flr.dirNameSize); + if ((msg.flr.dirNameSize == 0) || + (msg.flr.dirNameSize > (PATH_MAX - 1))) { + + rfbLog("File [%s]: Method [%s]: Unexpected error:: path length is " + "greater that PATH_MAX\n", __FILE__, __FUNCTION__); + + return; + } + + if((n = rfbReadExact(cl, path, msg.flr.dirNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Socket error while reading dir name\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + if(ConvertPath(path) == NULL) { + + /* The execution should never reach here */ + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL", + __FILE__, __FUNCTION__); + return; + } + + fileListMsg = GetFileListResponseMsg(path, (char) (msg.flr.flags)); + + if((fileListMsg.data == NULL) || (fileListMsg.length == 0)) { + + rfbLog("File [%s]: Method [%s]: Unexpected error:: Data to be sent is " + "of Zero length\n", __FILE__, __FUNCTION__); + return; + } + + rfbWriteExact(cl, fileListMsg.data, fileListMsg.length); + + FreeFileTransferMsg(fileListMsg); +} + + +/****************************************************************************** + * Methods to Handle File Download Request. + ******************************************************************************/ + +void HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize); +void SendFileDownloadLengthErrMsg(rfbClientPtr cl); +void HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr data); +#ifdef TODO +void HandleFileDownloadRequest(rfbClientPtr cl); +void SendFileDownloadErrMsg(rfbClientPtr cl); +void* RunFileDownloadThread(void* client); +#endif + +/* + * HandleFileDownloadRequest method is called when the server receives + * rfbFileDownload request message. + */ +void +HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */ + rfbClientToServerTightMsg msg; + + memset(path, 0, sizeof(path)); + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + + rfbLog("File [%s]: Method [%s]: Unexpected error:: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fdr.fNameSize = Swap16IfLE(msg.fdr.fNameSize); + msg.fdr.position = Swap16IfLE(msg.fdr.position); + + if ((msg.fdr.fNameSize == 0) || + (msg.fdr.fNameSize > (PATH_MAX - 1))) { + + rfbLog("File [%s]: Method [%s]: Error: path length is greater than" + " PATH_MAX\n", __FILE__, __FUNCTION__); + + HandleFileDownloadLengthError(cl, msg.fdr.fNameSize); + return; + } + + if((n = rfbReadExact(cl, rtcp->rcft.rcfd.fName, msg.fdr.fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name length\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + rtcp->rcft.rcfd.fName[msg.fdr.fNameSize] = '\0'; + + if(ConvertPath(rtcp->rcft.rcfd.fName) == NULL) { + + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL", + __FILE__, __FUNCTION__); + + + /* This condition can come only if the file path is greater than + PATH_MAX. So sending file path length error msg back to client. + */ + + SendFileDownloadLengthErrMsg(cl); + return; + } + + HandleFileDownload(cl, rtcp); + +} + + +void +HandleFileDownloadLengthError(rfbClientPtr cl, short fNameSize) +{ + char *path = NULL; + int n = 0; + + if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) { + rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n", + __FILE__, __FUNCTION__); + return; + } + if((n = rfbReadExact(cl, path, fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(path != NULL) { + free(path); + path = NULL; + } + + return; + } + + if(path != NULL) { + free(path); + path = NULL; + } + + SendFileDownloadLengthErrMsg(cl); +} + + +void +SendFileDownloadLengthErrMsg(rfbClientPtr cl) +{ + FileTransferMsg fileDownloadErrMsg; + + memset(&fileDownloadErrMsg, 0 , sizeof(FileTransferMsg)); + + fileDownloadErrMsg = GetFileDownloadLengthErrResponseMsg(); + + if((fileDownloadErrMsg.data == NULL) || (fileDownloadErrMsg.length == 0)) { + rfbLog("File [%s]: Method [%s]: Unexpected error: fileDownloadErrMsg " + "is null\n", __FILE__, __FUNCTION__); + return; + } + + rfbWriteExact(cl, fileDownloadErrMsg.data, fileDownloadErrMsg.length); + + FreeFileTransferMsg(fileDownloadErrMsg); +} + +extern rfbTightClientPtr rfbGetTightClientData(rfbClientPtr cl); + +void* +RunFileDownloadThread(void* client) +{ + rfbClientPtr cl = (rfbClientPtr) client; + rfbTightClientPtr rtcp = rfbGetTightClientData(cl); + FileTransferMsg fileDownloadMsg; + + if(rtcp == NULL) + return NULL; + + memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); + do { + pthread_mutex_lock(&fileDownloadMutex); + fileDownloadMsg = GetFileDownloadResponseMsgInBlocks(cl, rtcp); + pthread_mutex_unlock(&fileDownloadMutex); + + if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) { + if(rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length) < 0) { + rfbLog("File [%s]: Method [%s]: Error while writing to socket \n" + , __FILE__, __FUNCTION__); + + if(cl != NULL) { + rfbCloseClient(cl); + CloseUndoneFileTransfer(cl, rtcp); + } + + FreeFileTransferMsg(fileDownloadMsg); + return NULL; + } + FreeFileTransferMsg(fileDownloadMsg); + } + } while(rtcp->rcft.rcfd.downloadInProgress == TRUE); + return NULL; +} + + +void +HandleFileDownload(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + pthread_t fileDownloadThread; + FileTransferMsg fileDownloadMsg; + + memset(&fileDownloadMsg, 0, sizeof(FileTransferMsg)); + fileDownloadMsg = ChkFileDownloadErr(cl, rtcp); + if((fileDownloadMsg.data != NULL) && (fileDownloadMsg.length != 0)) { + rfbWriteExact(cl, fileDownloadMsg.data, fileDownloadMsg.length); + FreeFileTransferMsg(fileDownloadMsg); + return; + } + rtcp->rcft.rcfd.downloadInProgress = FALSE; + rtcp->rcft.rcfd.downloadFD = -1; + + if(pthread_create(&fileDownloadThread, NULL, RunFileDownloadThread, (void*) + cl) != 0) { + FileTransferMsg ftm = GetFileDownLoadErrMsg(); + + rfbLog("File [%s]: Method [%s]: Download thread creation failed\n", + __FILE__, __FUNCTION__); + + if((ftm.data != NULL) && (ftm.length != 0)) { + rfbWriteExact(cl, ftm.data, ftm.length); + FreeFileTransferMsg(ftm); + return; + } + + } + +} + + +/****************************************************************************** + * Methods to Handle File Download Cancel Request. + ******************************************************************************/ + + +void +HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char *reason = NULL; + rfbClientToServerTightMsg msg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileDownloadCancelMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading " + "FileDownloadCancelMsg\n", __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fdc.reasonLen = Swap16IfLE(msg.fdc.reasonLen); + + if(msg.fdc.reasonLen == 0) { + rfbLog("File [%s]: Method [%s]: reason length received is Zero\n", + __FILE__, __FUNCTION__); + return; + } + + reason = (char*) calloc(msg.fdc.reasonLen + 1, sizeof(char)); + if(reason == NULL) { + rfbLog("File [%s]: Method [%s]: Fatal Error: Memory alloc failed\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, reason, msg.fdc.reasonLen)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading " + "FileDownloadCancelMsg\n", __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + } + + rfbLog("File [%s]: Method [%s]: File Download Cancel Request received:" + " reason <%s>\n", __FILE__, __FUNCTION__, reason); + + pthread_mutex_lock(&fileDownloadMutex); + CloseUndoneFileTransfer(cl, rtcp); + pthread_mutex_unlock(&fileDownloadMutex); + + if(reason != NULL) { + free(reason); + reason = NULL; + } + +} + + +/****************************************************************************** + * Methods to Handle File upload request + ******************************************************************************/ + +#ifdef TODO +void HandleFileUploadRequest(rfbClientPtr cl); +#endif +void HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr data); +void HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize); +void SendFileUploadLengthErrMsg(rfbClientPtr cl); + + +void +HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char path[PATH_MAX]; /* PATH_MAX has the value 4096 and is defined in limits.h */ + rfbClientToServerTightMsg msg; + + memset(path, 0, PATH_MAX); + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fupr.fNameSize = Swap16IfLE(msg.fupr.fNameSize); + msg.fupr.position = Swap16IfLE(msg.fupr.position); + + if ((msg.fupr.fNameSize == 0) || + (msg.fupr.fNameSize > (PATH_MAX - 1))) { + + rfbLog("File [%s]: Method [%s]: error: path length is greater than PATH_MAX\n", + __FILE__, __FUNCTION__); + HandleFileUploadLengthError(cl, msg.fupr.fNameSize); + return; + } + + if((n = rfbReadExact(cl, rtcp->rcft.rcfu.fName, msg.fupr.fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n" + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + rtcp->rcft.rcfu.fName[msg.fupr.fNameSize] = '\0'; + + if(ConvertPath(rtcp->rcft.rcfu.fName) == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n", + __FILE__, __FUNCTION__); + + /* This may come if the path length exceeds PATH_MAX. + So sending path length error to client + */ + SendFileUploadLengthErrMsg(cl); + return; + } + + HandleFileUpload(cl, rtcp); +} + + +void +HandleFileUploadLengthError(rfbClientPtr cl, short fNameSize) +{ + char *path = NULL; + int n = 0; + + if((path = (char*) calloc(fNameSize, sizeof(char))) == NULL) { + rfbLog("File [%s]: Method [%s]: Fatal Error: Alloc failed\n", + __FILE__, __FUNCTION__); + return; + } + if((n = rfbReadExact(cl, path, fNameSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading dir name\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(path != NULL) { + free(path); + path = NULL; + } + + return; + } + + rfbLog("File [%s]: Method [%s]: File Upload Length Error occured" + "file path requested is <%s>\n", __FILE__, __FUNCTION__, path); + + if(path != NULL) { + free(path); + path = NULL; + } + + SendFileUploadLengthErrMsg(cl); +} + +void +SendFileUploadLengthErrMsg(rfbClientPtr cl) +{ + + FileTransferMsg fileUploadErrMsg; + + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + fileUploadErrMsg = GetFileUploadLengthErrResponseMsg(); + + if((fileUploadErrMsg.data == NULL) || (fileUploadErrMsg.length == 0)) { + rfbLog("File [%s]: Method [%s]: Unexpected error: fileUploadErrMsg is null\n", + __FILE__, __FUNCTION__); + return; + } + + rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length); + FreeFileTransferMsg(fileUploadErrMsg); +} + +void +HandleFileUpload(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + FileTransferMsg fileUploadErrMsg; + + memset(&fileUploadErrMsg, 0, sizeof(FileTransferMsg)); + + rtcp->rcft.rcfu.uploadInProgress = FALSE; + rtcp->rcft.rcfu.uploadFD = -1; + + fileUploadErrMsg = ChkFileUploadErr(cl, rtcp); + if((fileUploadErrMsg.data != NULL) && (fileUploadErrMsg.length != 0)) { + rfbWriteExact(cl, fileUploadErrMsg.data, fileUploadErrMsg.length); + FreeFileTransferMsg(fileUploadErrMsg); + } +} + + +/****************************************************************************** + * Methods to Handle File Upload Data Request + *****************************************************************************/ + +void HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf); + + +void +HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char* pBuf = NULL; + rfbClientToServerTightMsg msg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadDataMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fud.realSize = Swap16IfLE(msg.fud.realSize); + msg.fud.compressedSize = Swap16IfLE(msg.fud.compressedSize); + if((msg.fud.realSize == 0) && (msg.fud.compressedSize == 0)) { + if((n = rfbReadExact(cl, (char*)&(rtcp->rcft.rcfu.mTime), sizeof(unsigned + long))) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + FileUpdateComplete(cl, rtcp); + return; + } + + pBuf = (char*) calloc(msg.fud.compressedSize, sizeof(char)); + if(pBuf == NULL) { + rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__); + return; + } + if((n = rfbReadExact(cl, pBuf, msg.fud.compressedSize)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(pBuf != NULL) { + free(pBuf); + pBuf = NULL; + } + + return; + } + if(msg.fud.compressedLevel != 0) { + FileTransferMsg ftm; + memset(&ftm, 0, sizeof(FileTransferMsg)); + + ftm = GetFileUploadCompressedLevelErrMsg(); + + if((ftm.data != NULL) && (ftm.length != 0)) { + rfbWriteExact(cl, ftm.data, ftm.length); + FreeFileTransferMsg(ftm); + } + + CloseUndoneFileTransfer(cl, rtcp); + + if(pBuf != NULL) { + free(pBuf); + pBuf = NULL; + } + + return; + } + + rtcp->rcft.rcfu.fSize = msg.fud.compressedSize; + + HandleFileUploadWrite(cl, rtcp, pBuf); + + if(pBuf != NULL) { + free(pBuf); + pBuf = NULL; + } + +} + + +void +HandleFileUploadWrite(rfbClientPtr cl, rfbTightClientPtr rtcp, char* pBuf) +{ + FileTransferMsg ftm; + memset(&ftm, 0, sizeof(FileTransferMsg)); + + ftm = ChkFileUploadWriteErr(cl, rtcp, pBuf); + + if((ftm.data != NULL) && (ftm.length != 0)) { + rfbWriteExact(cl, ftm.data, ftm.length); + FreeFileTransferMsg(ftm); + } +} + + +/****************************************************************************** + * Methods to Handle File Upload Failed Request. + ******************************************************************************/ + + +void +HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char* reason = NULL; + rfbClientToServerTightMsg msg; + + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileUploadFailedMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fuf.reasonLen = Swap16IfLE(msg.fuf.reasonLen); + if(msg.fuf.reasonLen == 0) { + rfbLog("File [%s]: Method [%s]: reason length received is Zero\n", + __FILE__, __FUNCTION__); + return; + } + + + reason = (char*) calloc(msg.fuf.reasonLen + 1, sizeof(char)); + if(reason == NULL) { + rfbLog("File [%s]: Method [%s]: Memory alloc failed\n", __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, reason, msg.fuf.reasonLen)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + + if(reason != NULL) { + free(reason); + reason = NULL; + } + + return; + } + + rfbLog("File [%s]: Method [%s]: File Upload Failed Request received:" + " reason <%s>\n", __FILE__, __FUNCTION__, reason); + + CloseUndoneFileTransfer(cl, rtcp); + + if(reason != NULL) { + free(reason); + reason = NULL; + } + +} + + +/****************************************************************************** + * Methods to Handle File Create Request. + ******************************************************************************/ + + +void +HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientPtr rtcp) +{ + int n = 0; + char dirName[PATH_MAX]; + rfbClientToServerTightMsg msg; + + memset(dirName, 0, PATH_MAX); + memset(&msg, 0, sizeof(rfbClientToServerTightMsg)); + + if(cl == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: rfbClientPtr is null\n", + __FILE__, __FUNCTION__); + return; + } + + if((n = rfbReadExact(cl, ((char *)&msg)+1, sz_rfbFileCreateDirRequestMsg-1)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileCreateDirRequestMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + msg.fcdr.dNameLen = Swap16IfLE(msg.fcdr.dNameLen); + + /* TODO :: chk if the dNameLen is greater than PATH_MAX */ + + if((n = rfbReadExact(cl, dirName, msg.fcdr.dNameLen)) <= 0) { + + if (n < 0) + rfbLog("File [%s]: Method [%s]: Error while reading FileUploadFailedMsg\n", + __FILE__, __FUNCTION__); + + rfbCloseClient(cl); + return; + } + + if(ConvertPath(dirName) == NULL) { + rfbLog("File [%s]: Method [%s]: Unexpected error: path is NULL\n", + __FILE__, __FUNCTION__); + + return; + } + + CreateDirectory(dirName); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h new file mode 100755 index 0000000..74c0e8a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/handlefiletransferrequest.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 14th July 2005 + */ + +#ifndef HANDLE_FILE_TRANSFER_REQUEST_H +#define HANDLE_FILE_TRANSFER_REQUEST_H + + +#include + + +void InitFileTransfer(); +int SetFtpRoot(char* path); +void EnableFileTransfer(rfbBool enable); +rfbBool IsFileTransferEnabled(); +char* GetFtpRoot(); + +void HandleFileListRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileDownloadRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileDownloadCancelRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileUploadRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileUploadDataRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileUploadFailedRequest(rfbClientPtr cl, rfbTightClientRec* data); +void HandleFileCreateDirRequest(rfbClientPtr cl, rfbTightClientRec* data); + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h new file mode 100755 index 0000000..ef683ae --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightproto.h @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 25th August 2005 + */ + +#ifndef RFBTIGHTPROTO_H +#define RFBTIGHTPROTO_H + +#include +#include + +/* PATH_MAX is not defined in limits.h on some platforms */ +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + + +#define rfbSecTypeTight 16 + +void rfbTightUsage(void); +int rfbTightProcessArgs(int argc, char *argv[]); + +/*----------------------------------------------------------------------------- + * Negotiation of Tunneling Capabilities (protocol version 3.7t) + * + * If the chosen security type is rfbSecTypeTight, the server sends a list of + * supported tunneling methods ("tunneling" refers to any additional layer of + * data transformation, such as encryption or external compression.) + * + * nTunnelTypes specifies the number of following rfbCapabilityInfo structures + * that list all supported tunneling methods in the order of preference. + * + * NOTE: If nTunnelTypes is 0, that tells the client that no tunneling can be + * used, and the client should not send a response requesting a tunneling + * method. + */ + +typedef struct _rfbTunnelingCapsMsg { + uint32_t nTunnelTypes; + /* followed by nTunnelTypes * rfbCapabilityInfo structures */ +} rfbTunnelingCapsMsg; + +#define sz_rfbTunnelingCapsMsg 4 + +/*----------------------------------------------------------------------------- + * Tunneling Method Request (protocol version 3.7t) + * + * If the list of tunneling capabilities sent by the server was not empty, the + * client should reply with a 32-bit code specifying a particular tunneling + * method. The following code should be used for no tunneling. + */ + +#define rfbNoTunneling 0 +#define sig_rfbNoTunneling "NOTUNNEL" + + +/*----------------------------------------------------------------------------- + * Negotiation of Authentication Capabilities (protocol version 3.7t) + * + * After setting up tunneling, the server sends a list of supported + * authentication schemes. + * + * nAuthTypes specifies the number of following rfbCapabilityInfo structures + * that list all supported authentication schemes in the order of preference. + * + * NOTE: If nAuthTypes is 0, that tells the client that no authentication is + * necessary, and the client should not send a response requesting an + * authentication scheme. + */ + +typedef struct _rfbAuthenticationCapsMsg { + uint32_t nAuthTypes; + /* followed by nAuthTypes * rfbCapabilityInfo structures */ +} rfbAuthenticationCapsMsg; + +#define sz_rfbAuthenticationCapsMsg 4 + +/*----------------------------------------------------------------------------- + * Authentication Scheme Request (protocol version 3.7t) + * + * If the list of authentication capabilities sent by the server was not empty, + * the client should reply with a 32-bit code specifying a particular + * authentication scheme. The following codes are supported. + */ + +#define rfbAuthNone 1 +#define rfbAuthVNC 2 +#define rfbAuthUnixLogin 129 +#define rfbAuthExternal 130 + +#define sig_rfbAuthNone "NOAUTH__" +#define sig_rfbAuthVNC "VNCAUTH_" +#define sig_rfbAuthUnixLogin "ULGNAUTH" +#define sig_rfbAuthExternal "XTRNAUTH" + +/*----------------------------------------------------------------------------- + * Structure used to describe protocol options such as tunneling methods, + * authentication schemes and message types (protocol version 3.7t). + */ + +typedef struct _rfbCapabilityInfo { + + uint32_t code; /* numeric identifier */ + uint8_t vendorSignature[4]; /* vendor identification */ + uint8_t nameSignature[8]; /* abbreviated option name */ + +} rfbCapabilityInfo; + +#define sz_rfbCapabilityInfoVendor 4 +#define sz_rfbCapabilityInfoName 8 +#define sz_rfbCapabilityInfo 16 + +/* + * Vendors known by TightVNC: standard VNC/RealVNC, TridiaVNC, and TightVNC. + */ + +#define rfbStandardVendor "STDV" +#define rfbTridiaVncVendor "TRDV" +#define rfbTightVncVendor "TGHT" + + +/* It's a good idea to keep these values a bit greater than required. */ +#define MAX_TIGHT_ENCODINGS 10 +#define MAX_TUNNELING_CAPS 16 +#define MAX_AUTH_CAPS 16 + +typedef struct _rfbClientFileDownload { + char fName[PATH_MAX]; + int downloadInProgress; + unsigned long mTime; + int downloadFD; +} rfbClientFileDownload ; + +typedef struct _rfbClientFileUpload { + char fName[PATH_MAX]; + int uploadInProgress; + unsigned long mTime; + unsigned long fSize; + int uploadFD; +} rfbClientFileUpload ; + +typedef struct _rfbClientFileTransfer { + rfbClientFileDownload rcfd; + rfbClientFileUpload rcfu; +} rfbClientFileTransfer; + + +typedef struct _rfbTightClientRec { + + /* Lists of capability codes sent to clients. We remember these + lists to restrict clients from choosing those tunneling and + authentication types that were not advertised. */ + + int nAuthCaps; + uint32_t authCaps[MAX_AUTH_CAPS]; + + /* This is not useful while we don't support tunneling: + int nTunnelingCaps; + uint32_t tunnelingCaps[MAX_TUNNELING_CAPS]; */ + + rfbClientFileTransfer rcft; + +} rfbTightClientRec, *rfbTightClientPtr; + +/* + * Macro to fill in an rfbCapabilityInfo structure (protocol 3.7t). + * Normally, using macros is no good, but this macro saves us from + * writing constants twice -- it constructs signature names from codes. + * Note that "code_sym" argument should be a single symbol, not an expression. + */ + +#define SetCapInfo(cap_ptr, code_sym, vendor) \ +{ \ + rfbCapabilityInfo *pcap; \ + pcap = (cap_ptr); \ + pcap->code = Swap32IfLE(code_sym); \ + memcpy(pcap->vendorSignature, (vendor), \ + sz_rfbCapabilityInfoVendor); \ + memcpy(pcap->nameSignature, sig_##code_sym, \ + sz_rfbCapabilityInfoName); \ +} + +void rfbHandleSecTypeTight(rfbClientPtr cl); + + +/*----------------------------------------------------------------------------- + * Server Interaction Capabilities Message (protocol version 3.7t) + * + * In the protocol version 3.7t, the server informs the client what message + * types it supports in addition to ones defined in the protocol version 3.7. + * Also, the server sends the list of all supported encodings (note that it's + * not necessary to advertise the "raw" encoding sinse it MUST be supported in + * RFB 3.x protocols). + * + * This data immediately follows the server initialisation message. + */ + +typedef struct _rfbInteractionCapsMsg { + uint16_t nServerMessageTypes; + uint16_t nClientMessageTypes; + uint16_t nEncodingTypes; + uint16_t pad; /* reserved, must be 0 */ + /* followed by nServerMessageTypes * rfbCapabilityInfo structures */ + /* followed by nClientMessageTypes * rfbCapabilityInfo structures */ +} rfbInteractionCapsMsg; + +#define sz_rfbInteractionCapsMsg 8 + +#define rfbFileListData 130 +#define rfbFileDownloadData 131 +#define rfbFileUploadCancel 132 +#define rfbFileDownloadFailed 133 + +/* signatures for non-standard messages */ +#define sig_rfbFileListData "FTS_LSDT" +#define sig_rfbFileDownloadData "FTS_DNDT" +#define sig_rfbFileUploadCancel "FTS_UPCN" +#define sig_rfbFileDownloadFailed "FTS_DNFL" + + + +#define rfbFileListRequest 130 +#define rfbFileDownloadRequest 131 +#define rfbFileUploadRequest 132 +#define rfbFileUploadData 133 +#define rfbFileDownloadCancel 134 +#define rfbFileUploadFailed 135 +#define rfbFileCreateDirRequest 136 + +/* signatures for non-standard messages */ +#define sig_rfbFileListRequest "FTC_LSRQ" +#define sig_rfbFileDownloadRequest "FTC_DNRQ" +#define sig_rfbFileUploadRequest "FTC_UPRQ" +#define sig_rfbFileUploadData "FTC_UPDT" +#define sig_rfbFileDownloadCancel "FTC_DNCN" +#define sig_rfbFileUploadFailed "FTC_UPFL" +#define sig_rfbFileCreateDirRequest "FTC_FCDR" + + +/* signatures for basic encoding types */ +#define sig_rfbEncodingRaw "RAW_____" +#define sig_rfbEncodingCopyRect "COPYRECT" +#define sig_rfbEncodingRRE "RRE_____" +#define sig_rfbEncodingCoRRE "CORRE___" +#define sig_rfbEncodingHextile "HEXTILE_" +#define sig_rfbEncodingZlib "ZLIB____" +#define sig_rfbEncodingTight "TIGHT___" +#define sig_rfbEncodingZlibHex "ZLIBHEX_" + + +/* signatures for "fake" encoding types */ +#define sig_rfbEncodingCompressLevel0 "COMPRLVL" +#define sig_rfbEncodingXCursor "X11CURSR" +#define sig_rfbEncodingRichCursor "RCHCURSR" +#define sig_rfbEncodingPointerPos "POINTPOS" +#define sig_rfbEncodingLastRect "LASTRECT" +#define sig_rfbEncodingNewFBSize "NEWFBSIZ" +#define sig_rfbEncodingQualityLevel0 "JPEGQLVL" + + +/*----------------------------------------------------------------------------- + * FileListRequest + */ + +typedef struct _rfbFileListRequestMsg { + uint8_t type; + uint8_t flags; + uint16_t dirNameSize; + /* Followed by char Dirname[dirNameSize] */ +} rfbFileListRequestMsg; + +#define sz_rfbFileListRequestMsg 4 + +/*----------------------------------------------------------------------------- + * FileDownloadRequest + */ + +typedef struct _rfbFileDownloadRequestMsg { + uint8_t type; + uint8_t compressedLevel; + uint16_t fNameSize; + uint32_t position; + /* Followed by char Filename[fNameSize] */ +} rfbFileDownloadRequestMsg; + +#define sz_rfbFileDownloadRequestMsg 8 + +/*----------------------------------------------------------------------------- + * FileUploadRequest + */ + +typedef struct _rfbFileUploadRequestMsg { + uint8_t type; + uint8_t compressedLevel; + uint16_t fNameSize; + uint32_t position; + /* Followed by char Filename[fNameSize] */ +} rfbFileUploadRequestMsg; + +#define sz_rfbFileUploadRequestMsg 8 + + +/*----------------------------------------------------------------------------- + * FileUploadData + */ + +typedef struct _rfbFileUploadDataMsg { + uint8_t type; + uint8_t compressedLevel; + uint16_t realSize; + uint16_t compressedSize; + /* Followed by File[compressedSize], + but if (realSize = compressedSize = 0) followed by uint32_t modTime */ +} rfbFileUploadDataMsg; + +#define sz_rfbFileUploadDataMsg 6 + +/*----------------------------------------------------------------------------- + * FileDownloadCancel + */ + +typedef struct _rfbFileDownloadCancelMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileDownloadCancelMsg; + +#define sz_rfbFileDownloadCancelMsg 4 + +/*----------------------------------------------------------------------------- + * FileUploadFailed + */ + +typedef struct _rfbFileUploadFailedMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileUploadFailedMsg; + +#define sz_rfbFileUploadFailedMsg 4 + +/*----------------------------------------------------------------------------- + * FileCreateDirRequest + */ + +typedef struct _rfbFileCreateDirRequestMsg { + uint8_t type; + uint8_t unused; + uint16_t dNameLen; + /* Followed by dName[dNameLen] */ +} rfbFileCreateDirRequestMsg; + +#define sz_rfbFileCreateDirRequestMsg 4 + + +/*----------------------------------------------------------------------------- + * Union of all client->server messages. + */ + +typedef union _rfbClientToServerTightMsg { + rfbFileListRequestMsg flr; + rfbFileDownloadRequestMsg fdr; + rfbFileUploadRequestMsg fupr; + rfbFileUploadDataMsg fud; + rfbFileDownloadCancelMsg fdc; + rfbFileUploadFailedMsg fuf; + rfbFileCreateDirRequestMsg fcdr; +} rfbClientToServerTightMsg; + + + +/*----------------------------------------------------------------------------- + * FileListData + */ + +typedef struct _rfbFileListDataMsg { + uint8_t type; + uint8_t flags; + uint16_t numFiles; + uint16_t dataSize; + uint16_t compressedSize; + /* Followed by SizeData[numFiles] */ + /* Followed by Filenames[compressedSize] */ +} rfbFileListDataMsg; + +#define sz_rfbFileListDataMsg 8 + +/*----------------------------------------------------------------------------- + * FileDownloadData + */ + +typedef struct _rfbFileDownloadDataMsg { + uint8_t type; + uint8_t compressLevel; + uint16_t realSize; + uint16_t compressedSize; + /* Followed by File[copressedSize], + but if (realSize = compressedSize = 0) followed by uint32_t modTime */ +} rfbFileDownloadDataMsg; + +#define sz_rfbFileDownloadDataMsg 6 + + +/*----------------------------------------------------------------------------- + * FileUploadCancel + */ + +typedef struct _rfbFileUploadCancelMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileUploadCancelMsg; + +#define sz_rfbFileUploadCancelMsg 4 + +/*----------------------------------------------------------------------------- + * FileDownloadFailed + */ + +typedef struct _rfbFileDownloadFailedMsg { + uint8_t type; + uint8_t unused; + uint16_t reasonLen; + /* Followed by reason[reasonLen] */ +} rfbFileDownloadFailedMsg; + +#define sz_rfbFileDownloadFailedMsg 4 + + + + +#endif + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c new file mode 100755 index 0000000..d43d3f3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/tightvnc-filetransfer/rfbtightserver.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 2005 Novell, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program 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 program; if not, contact Novell, Inc. + * + * To contact Novell about this file by physical or electronic mail, + * you may find current contact information at www.novell.com + * + * Author : Rohit Kumar + * Email ID : rokumar@novell.com + * Date : 25th August 2005 + */ + + +#include +#include "rfbtightproto.h" +#include "handlefiletransferrequest.h" + +/* + * Get my data! + * + * This gets the extension specific data from the client structure. If + * the data is not found, the client connection is closed, a complaint + * is logged, and NULL is returned. + */ + +extern rfbProtocolExtension tightVncFileTransferExtension; + +rfbTightClientPtr +rfbGetTightClientData(rfbClientPtr cl) +{ + rfbTightClientPtr rtcp = (rfbTightClientPtr) + rfbGetExtensionClientData(cl, + &tightVncFileTransferExtension); + if(rtcp == NULL) { + rfbLog("Extension client data is null, closing the connection !\n"); + rfbCloseClient(cl); + } + + return rtcp; +} + +/* + * Send the authentication challenge. + */ + +static void +rfbVncAuthSendChallenge(rfbClientPtr cl) +{ + + rfbLog("tightvnc-filetransfer/rfbVncAuthSendChallenge\n"); + /* 4 byte header is alreay sent. Which is rfbSecTypeVncAuth (same as rfbVncAuth). Just send the challenge. */ + rfbRandomBytes(cl->authChallenge); + if (rfbWriteExact(cl, (char *)cl->authChallenge, CHALLENGESIZE) < 0) { + rfbLogPerror("rfbAuthNewClient: write"); + rfbCloseClient(cl); + return; + } + + /* Dispatch client input to rfbVncAuthProcessResponse. */ + /* This methos is defined in auth.c file */ + rfbAuthProcessClientMessage(cl); + +} + +/* + * LibVNCServer has a bug WRT Tight SecurityType and RFB 3.8 + * It should send auth result even for rfbAuthNone. + * See http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=517422 + * For testing set USE_SECTYPE_TIGHT_FOR_RFB_3_8 when compiling + * or set it here. + */ +#define SECTYPE_TIGHT_FOR_RFB_3_8 \ + if (cl->protocolMajorVersion==3 && cl->protocolMinorVersion > 7) { \ + uint32_t authResult; \ + rfbLog("rfbProcessClientSecurityType: returning securityResult for client rfb version >= 3.8\n"); \ + authResult = Swap32IfLE(rfbVncAuthOK); \ + if (rfbWriteExact(cl, (char *)&authResult, 4) < 0) { \ + rfbLogPerror("rfbAuthProcessClientMessage: write"); \ + rfbCloseClient(cl); \ + return; \ + } \ + } + +/* + Enabled by runge on 2010/01/02 + */ +#define USE_SECTYPE_TIGHT_FOR_RFB_3_8 + +/* + * Read client's preferred authentication type (protocol 3.7t). + */ + +void +rfbProcessClientAuthType(rfbClientPtr cl) +{ + uint32_t auth_type; + int n, i; + rfbTightClientPtr rtcp = rfbGetTightClientData(cl); + + rfbLog("tightvnc-filetransfer/rfbProcessClientAuthType\n"); + + if(rtcp == NULL) + return; + + /* Read authentication type selected by the client. */ + n = rfbReadExact(cl, (char *)&auth_type, sizeof(auth_type)); + if (n <= 0) { + if (n == 0) + rfbLog("rfbProcessClientAuthType: client gone\n"); + else + rfbLogPerror("rfbProcessClientAuthType: read"); + rfbCloseClient(cl); + return; + } + auth_type = Swap32IfLE(auth_type); + + /* Make sure it was present in the list sent by the server. */ + for (i = 0; i < rtcp->nAuthCaps; i++) { + if (auth_type == rtcp->authCaps[i]) + break; + } + if (i >= rtcp->nAuthCaps) { + rfbLog("rfbProcessClientAuthType: " + "wrong authentication type requested\n"); + rfbCloseClient(cl); + return; + } + + switch (auth_type) { + case rfbAuthNone: + /* Dispatch client input to rfbProcessClientInitMessage. */ +#ifdef USE_SECTYPE_TIGHT_FOR_RFB_3_8 + SECTYPE_TIGHT_FOR_RFB_3_8 +#endif + cl->state = RFB_INITIALISATION; + break; + case rfbAuthVNC: + rfbVncAuthSendChallenge(cl); + break; + default: + rfbLog("rfbProcessClientAuthType: unknown authentication scheme\n"); + rfbCloseClient(cl); + } +} + + +/* + * Read tunneling type requested by the client (protocol 3.7t). + * NOTE: Currently, we don't support tunneling, and this function + * can never be called. + */ + +void +rfbProcessClientTunnelingType(rfbClientPtr cl) +{ + /* If we were called, then something's really wrong. */ + rfbLog("rfbProcessClientTunnelingType: not implemented\n"); + rfbCloseClient(cl); + return; +} + + +/* + * Send the list of our authentication capabilities to the client + * (protocol 3.7t). + */ + +static void +rfbSendAuthCaps(rfbClientPtr cl) +{ + rfbAuthenticationCapsMsg caps; + rfbCapabilityInfo caplist[MAX_AUTH_CAPS]; + int count = 0; + rfbTightClientPtr rtcp = rfbGetTightClientData(cl); + + rfbLog("tightvnc-filetransfer/rfbSendAuthCaps\n"); + + if(rtcp == NULL) + return; + + if (cl->screen->authPasswdData && !cl->reverseConnection) { + /* chk if this condition is valid or not. */ + SetCapInfo(&caplist[count], rfbAuthVNC, rfbStandardVendor); + rtcp->authCaps[count++] = rfbAuthVNC; + } + + rtcp->nAuthCaps = count; + caps.nAuthTypes = Swap32IfLE((uint32_t)count); + if (rfbWriteExact(cl, (char *)&caps, sz_rfbAuthenticationCapsMsg) < 0) { + rfbLogPerror("rfbSendAuthCaps: write"); + rfbCloseClient(cl); + return; + } + + if (count) { + if (rfbWriteExact(cl, (char *)&caplist[0], + count * sz_rfbCapabilityInfo) < 0) { + rfbLogPerror("rfbSendAuthCaps: write"); + rfbCloseClient(cl); + return; + } + /* Dispatch client input to rfbProcessClientAuthType. */ + /* Call the function for authentication from here */ + rfbProcessClientAuthType(cl); + } else { +#ifdef USE_SECTYPE_TIGHT_FOR_RFB_3_8 + SECTYPE_TIGHT_FOR_RFB_3_8 +#endif + /* Dispatch client input to rfbProcessClientInitMessage. */ + cl->state = RFB_INITIALISATION; + } +} + + +/* + * Send the list of our tunneling capabilities (protocol 3.7t). + */ + +static void +rfbSendTunnelingCaps(rfbClientPtr cl) +{ + rfbTunnelingCapsMsg caps; + uint32_t nTypes = 0; /* we don't support tunneling yet */ + + rfbLog("tightvnc-filetransfer/rfbSendTunnelingCaps\n"); + + caps.nTunnelTypes = Swap32IfLE(nTypes); + if (rfbWriteExact(cl, (char *)&caps, sz_rfbTunnelingCapsMsg) < 0) { + rfbLogPerror("rfbSendTunnelingCaps: write"); + rfbCloseClient(cl); + return; + } + + if (nTypes) { + /* Dispatch client input to rfbProcessClientTunnelingType(). */ + /* The flow should not reach here as tunneling is not implemented. */ + rfbProcessClientTunnelingType(cl); + } else { + rfbSendAuthCaps(cl); + } +} + + + +/* + * rfbSendInteractionCaps is called after sending the server + * initialisation message, only if TightVNC protocol extensions were + * enabled (protocol 3.7t). In this function, we send the lists of + * supported protocol messages and encodings. + */ + +/* Update these constants on changing capability lists below! */ +/* Values updated for FTP */ +#define N_SMSG_CAPS 4 +#define N_CMSG_CAPS 6 +#define N_ENC_CAPS 12 + +void +rfbSendInteractionCaps(rfbClientPtr cl) +{ + rfbInteractionCapsMsg intr_caps; + rfbCapabilityInfo smsg_list[N_SMSG_CAPS]; + rfbCapabilityInfo cmsg_list[N_CMSG_CAPS]; + rfbCapabilityInfo enc_list[N_ENC_CAPS]; + int i, n_enc_caps = N_ENC_CAPS; + + /* Fill in the header structure sent prior to capability lists. */ + intr_caps.nServerMessageTypes = Swap16IfLE(N_SMSG_CAPS); + intr_caps.nClientMessageTypes = Swap16IfLE(N_CMSG_CAPS); + intr_caps.nEncodingTypes = Swap16IfLE(N_ENC_CAPS); + intr_caps.pad = 0; + + rfbLog("tightvnc-filetransfer/rfbSendInteractionCaps\n"); + + /* Supported server->client message types. */ + /* For file transfer support: */ + i = 0; + if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) { + SetCapInfo(&smsg_list[i++], rfbFileListData, rfbTightVncVendor); + SetCapInfo(&smsg_list[i++], rfbFileDownloadData, rfbTightVncVendor); + SetCapInfo(&smsg_list[i++], rfbFileUploadCancel, rfbTightVncVendor); + SetCapInfo(&smsg_list[i++], rfbFileDownloadFailed, rfbTightVncVendor); + if (i != N_SMSG_CAPS) { + rfbLog("rfbSendInteractionCaps: assertion failed, i != N_SMSG_CAPS\n"); + rfbCloseClient(cl); + return; + } + } + + /* Supported client->server message types. */ + /* For file transfer support: */ + i = 0; + if((IsFileTransferEnabled() == TRUE) && ( cl->viewOnly == FALSE)) { + SetCapInfo(&cmsg_list[i++], rfbFileListRequest, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileDownloadRequest, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileUploadRequest, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileUploadData, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileDownloadCancel, rfbTightVncVendor); + SetCapInfo(&cmsg_list[i++], rfbFileUploadFailed, rfbTightVncVendor); + if (i != N_CMSG_CAPS) { + rfbLog("rfbSendInteractionCaps: assertion failed, i != N_CMSG_CAPS\n"); + rfbCloseClient(cl); + return; + } + } + + /* Encoding types. */ + i = 0; + SetCapInfo(&enc_list[i++], rfbEncodingCopyRect, rfbStandardVendor); + SetCapInfo(&enc_list[i++], rfbEncodingRRE, rfbStandardVendor); + SetCapInfo(&enc_list[i++], rfbEncodingCoRRE, rfbStandardVendor); + SetCapInfo(&enc_list[i++], rfbEncodingHextile, rfbStandardVendor); +#ifdef LIBVNCSERVER_HAVE_LIBZ + SetCapInfo(&enc_list[i++], rfbEncodingZlib, rfbTridiaVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingTight, rfbTightVncVendor); +#else + n_enc_caps -= 2; +#endif + SetCapInfo(&enc_list[i++], rfbEncodingCompressLevel0, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingQualityLevel0, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingXCursor, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingRichCursor, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingPointerPos, rfbTightVncVendor); + SetCapInfo(&enc_list[i++], rfbEncodingLastRect, rfbTightVncVendor); + if (i != n_enc_caps) { + rfbLog("rfbSendInteractionCaps: assertion failed, i != N_ENC_CAPS\n"); + rfbCloseClient(cl); + return; + } + + /* Send header and capability lists */ + if (rfbWriteExact(cl, (char *)&intr_caps, + sz_rfbInteractionCapsMsg) < 0 || + rfbWriteExact(cl, (char *)&smsg_list[0], + sz_rfbCapabilityInfo * N_SMSG_CAPS) < 0 || + rfbWriteExact(cl, (char *)&cmsg_list[0], + sz_rfbCapabilityInfo * N_CMSG_CAPS) < 0 || + rfbWriteExact(cl, (char *)&enc_list[0], + sz_rfbCapabilityInfo * N_ENC_CAPS) < 0) { + rfbLogPerror("rfbSendInteractionCaps: write"); + rfbCloseClient(cl); + return; + } + + /* Dispatch client input to rfbProcessClientNormalMessage(). */ + cl->state = RFB_NORMAL; +} + + + +rfbBool +rfbTightExtensionInit(rfbClientPtr cl, void* data) +{ + + rfbSendInteractionCaps(cl); + + return TRUE; +} + +static rfbBool +handleMessage(rfbClientPtr cl, + const char* messageName, + void (*handler)(rfbClientPtr cl, rfbTightClientPtr data)) +{ + rfbTightClientPtr data; + + rfbLog("tightvnc-filetransfer: %s message received\n", messageName); + + if((IsFileTransferEnabled() == FALSE) || ( cl->viewOnly == TRUE)) { + rfbCloseClient(cl); + return FALSE; + } + + data = rfbGetTightClientData(cl); + if(data == NULL) + return FALSE; + + handler(cl, data); + return TRUE; +} + +rfbBool +rfbTightExtensionMsgHandler(struct _rfbClientRec* cl, void* data, + const rfbClientToServerMsg* msg) +{ + switch (msg->type) { + + case rfbFileListRequest: + + return handleMessage(cl, "rfbFileListRequest", HandleFileListRequest); + + case rfbFileDownloadRequest: + + return handleMessage(cl, "rfbFileDownloadRequest", HandleFileDownloadRequest); + + case rfbFileUploadRequest: + + return handleMessage(cl, "rfbFileUploadRequest", HandleFileUploadRequest); + + case rfbFileUploadData: + + return handleMessage(cl, "rfbFileUploadDataRequest", HandleFileUploadDataRequest); + + case rfbFileDownloadCancel: + + return handleMessage(cl, "rfbFileDownloadCancelRequest", HandleFileDownloadCancelRequest); + + case rfbFileUploadFailed: + + return handleMessage(cl, "rfbFileUploadFailedRequest", HandleFileUploadFailedRequest); + + case rfbFileCreateDirRequest: + + return handleMessage(cl, "rfbFileCreateDirRequest", HandleFileCreateDirRequest); + + default: + + rfbLog("rfbProcessClientNormalMessage: unknown message type %d\n", + msg->type); + + /* + + We shouldn't close the connection here for unhandled msg, + it should be left to libvncserver. + rfbLog(" ... closing connection\n"); + rfbCloseClient(cl); + + */ + + return FALSE; + + } +} + + +void +rfbTightExtensionClientClose(rfbClientPtr cl, void* data) { + + if(data != NULL) + free(data); + +} + +void +rfbTightUsage(void) { + fprintf(stderr, "\nlibvncserver-tight-extension options:\n"); + fprintf(stderr, "-disablefiletransfer disable file transfer\n"); + fprintf(stderr, "-ftproot string set ftp root\n"); + fprintf(stderr,"\n"); +} + +int +rfbTightProcessArg(int argc, char *argv[]) { + + rfbLog("tightvnc-filetransfer/rfbTightProcessArg\n"); + + InitFileTransfer(); + + if(argc<1) + return 0; + + if (strcmp(argv[0], "-ftproot") == 0) { /* -ftproot string */ + if (2 > argc) { + return 0; + } + rfbLog("ftproot is set to <%s>\n", argv[1]); + if(SetFtpRoot(argv[1]) == FALSE) { + rfbLog("ERROR:: Path specified for ftproot in invalid\n"); + return 0; + } + return 2; + } else if (strcmp(argv[0], "-disablefiletransfer") == 0) { + EnableFileTransfer(FALSE); + return 1; + } + return 0; +} + +/* + * This method should be registered to libvncserver to handle rfbSecTypeTight security type. + */ +void +rfbHandleSecTypeTight(rfbClientPtr cl) { + + rfbTightClientPtr rtcp = (rfbTightClientPtr) malloc(sizeof(rfbTightClientRec)); + + rfbLog("tightvnc-filetransfer/rfbHandleSecTypeTight\n"); + + if(rtcp == NULL) { + /* Error condition close socket */ + rfbLog("Memory error has occured while handling " + "Tight security type... closing connection.\n"); + rfbCloseClient(cl); + return; + } + + memset(rtcp, 0, sizeof(rfbTightClientRec)); + rtcp->rcft.rcfd.downloadFD = -1; + rtcp->rcft.rcfu.uploadFD = -1; + rfbEnableExtension(cl, &tightVncFileTransferExtension, rtcp); + + rfbSendTunnelingCaps(cl); + +} + +rfbProtocolExtension tightVncFileTransferExtension = { + NULL, + rfbTightExtensionInit, + NULL, + NULL, + rfbTightExtensionMsgHandler, + rfbTightExtensionClientClose, + rfbTightUsage, + rfbTightProcessArg, + NULL +}; + +static rfbSecurityHandler tightVncSecurityHandler = { + rfbSecTypeTight, + rfbHandleSecTypeTight, + NULL +}; + +void rfbRegisterTightVNCFileTransferExtension() { + rfbRegisterProtocolExtension(&tightVncFileTransferExtension); + rfbRegisterSecurityHandler(&tightVncSecurityHandler); +} + +void +rfbUnregisterTightVNCFileTransferExtension() { + rfbUnregisterProtocolExtension(&tightVncFileTransferExtension); + rfbUnregisterSecurityHandler(&tightVncSecurityHandler); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c new file mode 100755 index 0000000..7c341c2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/translate.c @@ -0,0 +1,477 @@ +/* + * translate.c - translate between different pixel formats + */ + +/* + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include +#include + +static void PrintPixelFormat(rfbPixelFormat *pf); +static rfbBool rfbSetClientColourMapBGR233(rfbClientPtr cl); + +rfbBool rfbEconomicTranslate = FALSE; + +/* + * Some standard pixel formats. + */ + +static const rfbPixelFormat BGR233Format = { + 8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0 +}; + + +/* + * Macro to compare pixel formats. + */ + +#define PF_EQ(x,y) \ + ((x.bitsPerPixel == y.bitsPerPixel) && \ + (x.depth == y.depth) && \ + ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \ + (x.trueColour == y.trueColour) && \ + (!x.trueColour || ((x.redMax == y.redMax) && \ + (x.greenMax == y.greenMax) && \ + (x.blueMax == y.blueMax) && \ + (x.redShift == y.redShift) && \ + (x.greenShift == y.greenShift) && \ + (x.blueShift == y.blueShift)))) + +#define CONCAT2(a,b) a##b +#define CONCAT2E(a,b) CONCAT2(a,b) +#define CONCAT3(a,b,c) a##b##c +#define CONCAT3E(a,b,c) CONCAT3(a,b,c) +#define CONCAT4(a,b,c,d) a##b##c##d +#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d) + +#undef OUT +#undef IN + +#define OUT 8 +#include "tableinitcmtemplate.c" +#include "tableinittctemplate.c" +#define IN 8 +#include "tabletranstemplate.c" +#undef IN +#define IN 16 +#include "tabletranstemplate.c" +#undef IN +#define IN 32 +#include "tabletranstemplate.c" +#undef IN +#undef OUT + +#define OUT 16 +#include "tableinitcmtemplate.c" +#include "tableinittctemplate.c" +#define IN 8 +#include "tabletranstemplate.c" +#undef IN +#define IN 16 +#include "tabletranstemplate.c" +#undef IN +#define IN 32 +#include "tabletranstemplate.c" +#undef IN +#undef OUT + +#define OUT 32 +#include "tableinitcmtemplate.c" +#include "tableinittctemplate.c" +#define IN 8 +#include "tabletranstemplate.c" +#undef IN +#define IN 16 +#include "tabletranstemplate.c" +#undef IN +#define IN 32 +#include "tabletranstemplate.c" +#undef IN +#undef OUT + +#ifdef LIBVNCSERVER_ALLOW24BPP +#define COUNT_OFFSETS 4 +#define BPP2OFFSET(bpp) ((bpp)/8-1) +#include "tableinit24.c" +#define BPP 8 +#include "tabletrans24template.c" +#undef BPP +#define BPP 16 +#include "tabletrans24template.c" +#undef BPP +#define BPP 24 +#include "tabletrans24template.c" +#undef BPP +#define BPP 32 +#include "tabletrans24template.c" +#undef BPP +#else +#define COUNT_OFFSETS 3 +#define BPP2OFFSET(bpp) ((int)(bpp)/16) +#endif + +typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in, + rfbPixelFormat *out,rfbColourMap* cm); +typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in, + rfbPixelFormat *out); + +static rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = { + rfbInitColourMapSingleTable8, + rfbInitColourMapSingleTable16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbInitColourMapSingleTable24, +#endif + rfbInitColourMapSingleTable32 +}; + +static rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = { + rfbInitTrueColourSingleTable8, + rfbInitTrueColourSingleTable16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbInitTrueColourSingleTable24, +#endif + rfbInitTrueColourSingleTable32 +}; + +static rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = { + rfbInitTrueColourRGBTables8, + rfbInitTrueColourRGBTables16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbInitTrueColourRGBTables24, +#endif + rfbInitTrueColourRGBTables32 +}; + +static rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = { + { rfbTranslateWithSingleTable8to8, + rfbTranslateWithSingleTable8to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithSingleTable8to24, +#endif + rfbTranslateWithSingleTable8to32 }, + { rfbTranslateWithSingleTable16to8, + rfbTranslateWithSingleTable16to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithSingleTable16to24, +#endif + rfbTranslateWithSingleTable16to32 }, +#ifdef LIBVNCSERVER_ALLOW24BPP + { rfbTranslateWithSingleTable24to8, + rfbTranslateWithSingleTable24to16, + rfbTranslateWithSingleTable24to24, + rfbTranslateWithSingleTable24to32 }, +#endif + { rfbTranslateWithSingleTable32to8, + rfbTranslateWithSingleTable32to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithSingleTable32to24, +#endif + rfbTranslateWithSingleTable32to32 } +}; + +static rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = { + { rfbTranslateWithRGBTables8to8, + rfbTranslateWithRGBTables8to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithRGBTables8to24, +#endif + rfbTranslateWithRGBTables8to32 }, + { rfbTranslateWithRGBTables16to8, + rfbTranslateWithRGBTables16to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithRGBTables16to24, +#endif + rfbTranslateWithRGBTables16to32 }, +#ifdef LIBVNCSERVER_ALLOW24BPP + { rfbTranslateWithRGBTables24to8, + rfbTranslateWithRGBTables24to16, + rfbTranslateWithRGBTables24to24, + rfbTranslateWithRGBTables24to32 }, +#endif + { rfbTranslateWithRGBTables32to8, + rfbTranslateWithRGBTables32to16, +#ifdef LIBVNCSERVER_ALLOW24BPP + rfbTranslateWithRGBTables32to24, +#endif + rfbTranslateWithRGBTables32to32 } +}; + + + +/* + * rfbTranslateNone is used when no translation is required. + */ + +void +rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out, + char *iptr, char *optr, int bytesBetweenInputLines, + int width, int height) +{ + int bytesPerOutputLine = width * (out->bitsPerPixel / 8); + + while (height > 0) { + memcpy(optr, iptr, bytesPerOutputLine); + iptr += bytesBetweenInputLines; + optr += bytesPerOutputLine; + height--; + } +} + + +/* + * rfbSetTranslateFunction sets the translation function. + */ + +rfbBool +rfbSetTranslateFunction(rfbClientPtr cl) +{ + rfbLog("Pixel format for client %s:\n",cl->host); + PrintPixelFormat(&cl->format); + + /* + * Check that bits per pixel values are valid + */ + + if ((cl->screen->serverFormat.bitsPerPixel != 8) && + (cl->screen->serverFormat.bitsPerPixel != 16) && +#ifdef LIBVNCSERVER_ALLOW24BPP + (cl->screen->serverFormat.bitsPerPixel != 24) && +#endif + (cl->screen->serverFormat.bitsPerPixel != 32)) + { + rfbErr("%s: server bits per pixel not 8, 16 or 32 (is %d)\n", + "rfbSetTranslateFunction", + cl->screen->serverFormat.bitsPerPixel); + rfbCloseClient(cl); + return FALSE; + } + + if ((cl->format.bitsPerPixel != 8) && + (cl->format.bitsPerPixel != 16) && +#ifdef LIBVNCSERVER_ALLOW24BPP + (cl->format.bitsPerPixel != 24) && +#endif + (cl->format.bitsPerPixel != 32)) + { + rfbErr("%s: client bits per pixel not 8, 16 or 32\n", + "rfbSetTranslateFunction"); + rfbCloseClient(cl); + return FALSE; + } + + if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) { + rfbErr("rfbSetTranslateFunction: client has colour map " + "but %d-bit - can only cope with 8-bit colour maps\n", + cl->format.bitsPerPixel); + rfbCloseClient(cl); + return FALSE; + } + + /* + * bpp is valid, now work out how to translate + */ + + if (!cl->format.trueColour) { + /* + * truecolour -> colour map + * + * Set client's colour map to BGR233, then effectively it's + * truecolour as well + */ + + if (!rfbSetClientColourMapBGR233(cl)) + return FALSE; + + cl->format = BGR233Format; + } + + /* truecolour -> truecolour */ + + if (PF_EQ(cl->format,cl->screen->serverFormat)) { + + /* client & server the same */ + + rfbLog("no translation needed\n"); + cl->translateFn = rfbTranslateNone; + return TRUE; + } + + if ((cl->screen->serverFormat.bitsPerPixel < 16) || + ((!cl->screen->serverFormat.trueColour || !rfbEconomicTranslate) && + (cl->screen->serverFormat.bitsPerPixel == 16))) { + + /* we can use a single lookup table for <= 16 bpp */ + + cl->translateFn = rfbTranslateWithSingleTableFns + [BPP2OFFSET(cl->screen->serverFormat.bitsPerPixel)] + [BPP2OFFSET(cl->format.bitsPerPixel)]; + + if(cl->screen->serverFormat.trueColour) + (*rfbInitTrueColourSingleTableFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &(cl->screen->serverFormat), &cl->format); + else + (*rfbInitColourMapSingleTableFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &(cl->screen->serverFormat), &cl->format,&cl->screen->colourMap); + + } else { + + /* otherwise we use three separate tables for red, green and blue */ + + cl->translateFn = rfbTranslateWithRGBTablesFns + [BPP2OFFSET(cl->screen->serverFormat.bitsPerPixel)] + [BPP2OFFSET(cl->format.bitsPerPixel)]; + + (*rfbInitTrueColourRGBTablesFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &(cl->screen->serverFormat), &cl->format); + } + + return TRUE; +} + + + +/* + * rfbSetClientColourMapBGR233 sets the client's colour map so that it's + * just like an 8-bit BGR233 true colour client. + */ + +static rfbBool +rfbSetClientColourMapBGR233(rfbClientPtr cl) +{ + char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2]; + rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf; + uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]); + int i, len; + int r, g, b; + + if (cl->format.bitsPerPixel != 8 ) { + rfbErr("%s: client not 8 bits per pixel\n", + "rfbSetClientColourMapBGR233"); + rfbCloseClient(cl); + return FALSE; + } + + scme->type = rfbSetColourMapEntries; + + scme->firstColour = Swap16IfLE(0); + scme->nColours = Swap16IfLE(256); + + len = sz_rfbSetColourMapEntriesMsg; + + i = 0; + + for (b = 0; b < 4; b++) { + for (g = 0; g < 8; g++) { + for (r = 0; r < 8; r++) { + rgb[i++] = Swap16IfLE(r * 65535 / 7); + rgb[i++] = Swap16IfLE(g * 65535 / 7); + rgb[i++] = Swap16IfLE(b * 65535 / 3); + } + } + } + + len += 256 * 3 * 2; + + if (rfbWriteExact(cl, buf, len) < 0) { + rfbLogPerror("rfbSetClientColourMapBGR233: write"); + rfbCloseClient(cl); + return FALSE; + } + return TRUE; +} + +/* this function is not called very often, so it needn't be + efficient. */ + +/* + * rfbSetClientColourMap is called to set the client's colour map. If the + * client is a true colour client, we simply update our own translation table + * and mark the whole screen as having been modified. + */ + +rfbBool +rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours) +{ + if (cl->screen->serverFormat.trueColour || !cl->readyForSetColourMapEntries) { + return TRUE; + } + + if (nColours == 0) { + nColours = cl->screen->colourMap.count; + } + + if (cl->format.trueColour) { + LOCK(cl->updateMutex); + (*rfbInitColourMapSingleTableFns + [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable, + &cl->screen->serverFormat, &cl->format,&cl->screen->colourMap); + + sraRgnDestroy(cl->modifiedRegion); + cl->modifiedRegion = + sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height); + UNLOCK(cl->updateMutex); + + return TRUE; + } + + return rfbSendSetColourMapEntries(cl, firstColour, nColours); +} + + +/* + * rfbSetClientColourMaps sets the colour map for each RFB client. + */ + +void +rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours) +{ + rfbClientIteratorPtr i; + rfbClientPtr cl; + + i = rfbGetClientIterator(rfbScreen); + while((cl = rfbClientIteratorNext(i))) + rfbSetClientColourMap(cl, firstColour, nColours); + rfbReleaseClientIterator(i); +} + +static void +PrintPixelFormat(rfbPixelFormat *pf) +{ + if (pf->bitsPerPixel == 1) { + rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n", + (pf->bigEndian ? "most" : "least")); + } else { + rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth, + ((pf->bitsPerPixel == 8) ? "" + : (pf->bigEndian ? ", big endian" : ", little endian"))); + if (pf->trueColour) { + rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n", + pf->redMax, pf->greenMax, pf->blueMax, + pf->redShift, pf->greenShift, pf->blueShift); + } else { + rfbLog(" uses a colour map (not true colour).\n"); + } + } +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c new file mode 100755 index 0000000..a802026 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/ultra.c @@ -0,0 +1,248 @@ +/* + * ultra.c + * + * Routines to implement ultra based encoding (minilzo). + * ultrazip supports packed rectangles if the rects are tiny... + * This improves performance as lzo has more data to work with at once + * This is 'UltraZip' and is currently not implemented. + */ + +#include +#include "minilzo.h" + +/* + * lzoBeforeBuf contains pixel data in the client's format. + * lzoAfterBuf contains the lzo (deflated) encoding version. + * If the lzo compressed/encoded version is + * larger than the raw data or if it exceeds lzoAfterBufSize then + * raw encoding is used instead. + */ + +static int lzoBeforeBufSize = 0; +static char *lzoBeforeBuf = NULL; + +static int lzoAfterBufSize = 0; +static char *lzoAfterBuf = NULL; +static int lzoAfterBufLen = 0; + +/* + * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib + * rectangle encoding. + */ + +#define MAX_WRKMEM ((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) + +void rfbUltraCleanup(rfbScreenInfoPtr screen) +{ + if (lzoBeforeBufSize) { + free(lzoBeforeBuf); + lzoBeforeBufSize=0; + } + if (lzoAfterBufSize) { + free(lzoAfterBuf); + lzoAfterBufSize=0; + } +} + +void rfbFreeUltraData(rfbClientPtr cl) { + if (cl->compStreamInitedLZO) { + free(cl->lzoWrkMem); + cl->compStreamInitedLZO=FALSE; + } +} + + +static rfbBool +rfbSendOneRectEncodingUltra(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + rfbZlibHeader hdr; + int deflateResult; + int i; + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + int maxRawSize; + int maxCompSize; + + maxRawSize = (w * h * (cl->format.bitsPerPixel / 8)); + + if (lzoBeforeBufSize < maxRawSize) { + lzoBeforeBufSize = maxRawSize; + if (lzoBeforeBuf == NULL) + lzoBeforeBuf = (char *)malloc(lzoBeforeBufSize); + else + lzoBeforeBuf = (char *)realloc(lzoBeforeBuf, lzoBeforeBufSize); + } + + /* + * lzo requires output buffer to be slightly larger than the input + * buffer, in the worst case. + */ + maxCompSize = (maxRawSize + maxRawSize / 16 + 64 + 3); + + if (lzoAfterBufSize < maxCompSize) { + lzoAfterBufSize = maxCompSize; + if (lzoAfterBuf == NULL) + lzoAfterBuf = (char *)malloc(lzoAfterBufSize); + else + lzoAfterBuf = (char *)realloc(lzoAfterBuf, lzoAfterBufSize); + } + + /* + * Convert pixel data to client format. + */ + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, lzoBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + if ( cl->compStreamInitedLZO == FALSE ) { + cl->compStreamInitedLZO = TRUE; + /* Work-memory needed for compression. Allocate memory in units + * of `lzo_align_t' (instead of `char') to make sure it is properly aligned. + */ + cl->lzoWrkMem = malloc(sizeof(lzo_align_t) * (((LZO1X_1_MEM_COMPRESS) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t))); + } + + /* Perform the compression here. */ + deflateResult = lzo1x_1_compress((unsigned char *)lzoBeforeBuf, (lzo_uint)(w * h * (cl->format.bitsPerPixel / 8)), (unsigned char *)lzoAfterBuf, (lzo_uint *)&maxCompSize, cl->lzoWrkMem); + /* maxCompSize now contains the compressed size */ + + /* Find the total size of the resulting compressed data. */ + lzoAfterBufLen = maxCompSize; + + if ( deflateResult != LZO_E_OK ) { + rfbErr("lzo deflation error: %d\n", deflateResult); + return FALSE; + } + + /* Update statics */ + rfbStatRecordEncodingSent(cl, rfbEncodingUltra, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + lzoAfterBufLen, maxRawSize); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + > UPDATE_BUF_SIZE) + { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingUltra); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.nBytes = Swap32IfLE(lzoAfterBufLen); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader); + cl->ublen += sz_rfbZlibHeader; + + /* We might want to try sending the data directly... */ + for (i = 0; i < lzoAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > lzoAfterBufLen) { + bytesToCopy = lzoAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &lzoAfterBuf[i], bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; + +} + +/* + * rfbSendRectEncodingUltra - send a given rectangle using one or more + * LZO encoding rectangles. + */ + +rfbBool +rfbSendRectEncodingUltra(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int maxLines; + int linesRemaining; + rfbRectangle partialRect; + + partialRect.x = x; + partialRect.y = y; + partialRect.w = w; + partialRect.h = h; + + /* Determine maximum pixel/scan lines allowed per rectangle. */ + maxLines = ( ULTRA_MAX_SIZE(w) / w ); + + /* Initialize number of scan lines left to do. */ + linesRemaining = h; + + /* Loop until all work is done. */ + while ( linesRemaining > 0 ) { + + int linesToComp; + + if ( maxLines < linesRemaining ) + linesToComp = maxLines; + else + linesToComp = linesRemaining; + + partialRect.h = linesToComp; + + /* Encode (compress) and send the next rectangle. */ + if ( ! rfbSendOneRectEncodingUltra( cl, + partialRect.x, + partialRect.y, + partialRect.w, + partialRect.h )) { + + return FALSE; + } + + /* Technically, flushing the buffer here is not extrememly + * efficient. However, this improves the overall throughput + * of the system over very slow networks. By flushing + * the buffer with every maximum size lzo rectangle, we + * improve the pipelining usage of the server CPU, network, + * and viewer CPU components. Insuring that these components + * are working in parallel actually improves the performance + * seen by the user. + * Since, lzo is most useful for slow networks, this flush + * is appropriate for the desired behavior of the lzo encoding. + */ + if (( cl->ublen > 0 ) && + ( linesToComp == maxLines )) { + if (!rfbSendUpdateBuf(cl)) { + + return FALSE; + } + } + + /* Update remaining and incremental rectangle location. */ + linesRemaining -= linesToComp; + partialRect.y += linesToComp; + + } + + return TRUE; + +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c new file mode 100755 index 0000000..0b73531 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/vncauth.c @@ -0,0 +1,208 @@ +/* + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncauth.c - Functions for VNC password management and authentication. + */ + +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif +#include +#include +#include +#include +#include "d3des.h" + +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_STAT_H +#include +#endif + +#include + +#ifdef WIN32 +#define srandom srand +#define random rand +#else +#include +#endif + + +/* libvncclient does not need this */ +#ifndef rfbEncryptBytes + +/* + * We use a fixed key to store passwords, since we assume that our local + * file system is secure but nonetheless don't want to store passwords + * as plaintext. + */ + +static unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7}; + + +/* + * Encrypt a password and store it in a file. Returns 0 if successful, + * 1 if the file could not be written. + */ + +int +rfbEncryptAndStorePasswd(char *passwd, char *fname) +{ + FILE *fp; + unsigned int i; + unsigned char encryptedPasswd[8]; + + if ((fp = fopen(fname,"w")) == NULL) return 1; + + /* windows security sux */ +#ifndef WIN32 + fchmod(fileno(fp), S_IRUSR|S_IWUSR); +#endif + + /* pad password with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + encryptedPasswd[i] = passwd[i]; + } else { + encryptedPasswd[i] = 0; + } + } + + /* Do encryption in-place - this way we overwrite our copy of the plaintext + password */ + + rfbDesKey(fixedkey, EN0); + rfbDes(encryptedPasswd, encryptedPasswd); + + for (i = 0; i < 8; i++) { + putc(encryptedPasswd[i], fp); + } + + fclose(fp); + return 0; +} + + +/* + * Decrypt a password from a file. Returns a pointer to a newly allocated + * string containing the password or a null pointer if the password could + * not be retrieved for some reason. + */ + +char * +rfbDecryptPasswdFromFile(char *fname) +{ + FILE *fp; + int i, ch; + unsigned char *passwd = (unsigned char *)malloc(9); + + if ((fp = fopen(fname,"r")) == NULL) return NULL; + + for (i = 0; i < 8; i++) { + ch = getc(fp); + if (ch == EOF) { + fclose(fp); + return NULL; + } + passwd[i] = ch; + } + + fclose(fp); + + rfbDesKey(fixedkey, DE1); + rfbDes(passwd, passwd); + + passwd[8] = 0; + + return (char *)passwd; +} + + +/* + * Generate CHALLENGESIZE random bytes for use in challenge-response + * authentication. + */ + +void +rfbRandomBytes(unsigned char *bytes) +{ + int i; + static rfbBool s_srandom_called = FALSE; + + if (!s_srandom_called) { + srandom((unsigned int)time(NULL) ^ (unsigned int)getpid()); + s_srandom_called = TRUE; + } + + for (i = 0; i < CHALLENGESIZE; i++) { + bytes[i] = (unsigned char)(random() & 255); + } +} + +#endif + +/* + * Encrypt CHALLENGESIZE bytes in memory using a password. + */ + +void +rfbEncryptBytes(unsigned char *bytes, char *passwd) +{ + unsigned char key[8]; + unsigned int i; + + /* key is simply password padded with nulls */ + + for (i = 0; i < 8; i++) { + if (i < strlen(passwd)) { + key[i] = passwd[i]; + } else { + key[i] = 0; + } + } + + rfbDesKey(key, EN0); + + for (i = 0; i < CHALLENGESIZE; i += 8) { + rfbDes(bytes+i, bytes+i); + } +} + +void +rfbEncryptBytes2(unsigned char *where, const int length, unsigned char *key) { + int i, j; + rfbDesKey(key, EN0); + for (i = 0; i< 8; i++) + where[i] ^= key[i]; + rfbDes(where, where); + for (i = 8; i < length; i += 8) { + for (j = 0; j < 8; j++) + where[i + j] ^= where[i + j - 8]; + rfbDes(where + i, where + i); + } +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c new file mode 100755 index 0000000..46cc46f --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/websockets.c @@ -0,0 +1,568 @@ +/* + * websockets.c - deal with WebSockets clients. + * + * This code should be independent of any changes in the RFB protocol. It is + * an additional handshake and framing of normal sockets: + * http://www.whatwg.org/specs/web-socket-protocol/ + * + */ + +/* + * Copyright (C) 2010 Joel Martin + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +/* errno */ +#include + +#include +#include +#include + +#define FLASH_POLICY_RESPONSE "\n" +#define SZ_FLASH_POLICY_RESPONSE 93 + +#define WEBSOCKETS_HANDSHAKE_RESPONSE "HTTP/1.1 101 Web Socket Protocol Handshake\r\n\ +Upgrade: WebSocket\r\n\ +Connection: Upgrade\r\n\ +%sWebSocket-Origin: %s\r\n\ +%sWebSocket-Location: %s://%s%s\r\n\ +%sWebSocket-Protocol: %s\r\n\ +\r\n%s" + +#define WEBSOCKETS_CLIENT_CONNECT_WAIT_MS 100 +#define WEBSOCKETS_CLIENT_SEND_WAIT_MS 100 +#define WEBSOCKETS_MAX_HANDSHAKE_LEN 4096 + +#if defined(__linux__) && defined(NEED_TIMEVAL) +struct timeval +{ + long int tv_sec,tv_usec; +} +; +#endif + +static rfbBool webSocketsHandshake(rfbClientPtr cl, char *scheme); +void webSocketsGenMd5(char * target, char *key1, char *key2, char *key3); + +static int +min (int a, int b) { + return a < b ? a : b; +} + +int +webSocketsSSLInit(rfbClientPtr cl) +{ + char *keyfile; + int r, ret = -1; + + SSL_library_init(); + OpenSSL_add_all_algorithms(); + SSL_load_error_strings(); + + if (cl->screen->sslkeyfile && *cl->screen->sslkeyfile) { + keyfile = cl->screen->sslkeyfile; + } else { + keyfile = cl->screen->sslcertfile; + } + + if (!cl->screen->sslcertfile || !cl->screen->sslcertfile[0]) { + rfbErr("SSL connection but no cert specified\n"); + } else if (NULL == (cl->ssl_ctx = SSL_CTX_new(TLSv1_server_method()))) { + ERR_print_errors_fp(stderr); + } else if (SSL_CTX_use_PrivateKey_file(cl->ssl_ctx, keyfile, SSL_FILETYPE_PEM) <= 0) { + rfbErr("Unable to load private key file %s\n", keyfile); + } else if (SSL_CTX_use_certificate_file(cl->ssl_ctx, cl->screen->sslcertfile, SSL_FILETYPE_PEM) <= 0) { + rfbErr("Unable to load certificate file %s\n", cl->screen->sslcertfile); + } else if (NULL == (cl->ssl = SSL_new(cl->ssl_ctx))) { + rfbErr("SSL_new failed\n"); + ERR_print_errors_fp(stderr); + } else if (!(SSL_set_fd(cl->ssl, cl->sock))) { + rfbErr("SSL_set_fd failed\n"); + ERR_print_errors_fp(stderr); + } else { + while ((r = SSL_accept(cl->ssl)) < 0) { + if (SSL_get_error(cl->ssl, r) != SSL_ERROR_WANT_READ) + break; + } + if (r < 0) { + rfbErr("SSL_accept failed %d\n", SSL_get_error(cl->ssl, r)); + } else { + ret = 0; + } + } + return ret; +} + + +/* + * rfbWebSocketsHandshake is called to handle new WebSockets connections + */ + +rfbBool +webSocketsCheck (rfbClientPtr cl) +{ + char bbuf[4], *scheme; + int ret; + + ret = rfbPeekExactTimeout(cl, bbuf, 4, + WEBSOCKETS_CLIENT_CONNECT_WAIT_MS); + if ((ret < 0) && (errno == ETIMEDOUT)) { + rfbLog("Normal socket connection\n"); + return TRUE; + } else if (ret <= 0) { + rfbErr("webSocketsHandshake: unknown connection error\n"); + return FALSE; + } + + if (strncmp(bbuf, "<", 1) == 0) { + rfbLog("Got Flash policy request, sending response\n"); + if (rfbWriteExact(cl, FLASH_POLICY_RESPONSE, + SZ_FLASH_POLICY_RESPONSE) < 0) { + rfbErr("webSocketsHandshake: failed sending Flash policy response"); + } + return FALSE; + } else if (strncmp(bbuf, "\x16", 1) == 0 || strncmp(bbuf, "\x80", 1) == 0) { + rfbLog("Got TLS/SSL WebSockets connection\n"); + if (-1 == webSocketsSSLInit(cl)) { + rfbErr("webSocketsHandshake: webSocketsSSLInit failed\n"); + return FALSE; + } + ret = rfbPeekExactTimeout(cl, bbuf, 4, WEBSOCKETS_CLIENT_CONNECT_WAIT_MS); + cl->webSocketsSSL = TRUE; + scheme = "wss"; + } else { + cl->webSocketsSSL = FALSE; + scheme = "ws"; + } + + if (strncmp(bbuf, "GET ", 4) != 0) { + rfbErr("webSocketsHandshake: invalid client header\n"); + return FALSE; + } + + rfbLog("Got '%s' WebSockets handshake\n", scheme); + + if (!webSocketsHandshake(cl, scheme)) { + return FALSE; + } + cl->webSockets = TRUE; // Start WebSockets framing + return TRUE; +} + +static rfbBool +webSocketsHandshake(rfbClientPtr cl, char *scheme) +{ + char *buf, *response, *line; + int n, linestart = 0, len = 0, llen; + char prefix[5], trailer[17]; + char *path, *host, *origin, *protocol; + char *key1 = NULL, *key2 = NULL, *key3 = NULL; + + buf = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN); + if (!buf) { + rfbLogPerror("webSocketsHandshake: malloc"); + return FALSE; + } + response = (char *) malloc(WEBSOCKETS_MAX_HANDSHAKE_LEN); + if (!response) { + free(buf); + rfbLogPerror("webSocketsHandshake: malloc"); + return FALSE; + } + + while (len < WEBSOCKETS_MAX_HANDSHAKE_LEN-1) { + if ((n = rfbReadExactTimeout(cl, buf+len, 1, + WEBSOCKETS_CLIENT_SEND_WAIT_MS)) <= 0) { + if ((n < 0) && (errno == ETIMEDOUT)) { + break; + } + if (n == 0) + rfbLog("webSocketsHandshake: client gone\n"); + else + rfbLogPerror("webSocketsHandshake: read"); + return FALSE; + } + + len += 1; + llen = len - linestart; + if (((llen >= 2)) && (buf[len-1] == '\n')) { + line = buf+linestart; + if ((llen == 2) && (strncmp("\r\n", line, 2) == 0)) { + if (key1 && key2) { + if ((n = rfbReadExact(cl, buf+len, 8)) <= 0) { + if ((n < 0) && (errno == ETIMEDOUT)) { + break; + } + if (n == 0) + rfbLog("webSocketsHandshake: client gone\n"); + else + rfbLogPerror("webSocketsHandshake: read"); + return FALSE; + } + rfbLog("Got key3\n"); + key3 = buf+len; + len += 8; + } else { + buf[len] = '\0'; + } + break; + } else if ((llen >= 16) && ((strncmp("GET ", line, min(llen,4))) == 0)) { + // 16 = 4 ("GET ") + 1 ("/.*") + 11 (" HTTP/1.1\r\n") + path = line+4; + buf[len-11] = '\0'; // Trim trailing " HTTP/1.1\r\n" + cl->webSocketsBase64 = TRUE; + //rfbLog("Got path: %s\n", path); + } else if ((strncasecmp("host: ", line, min(llen,6))) == 0) { + host = line+6; + buf[len-2] = '\0'; + //rfbLog("Got host: %s\n", host); + } else if ((strncasecmp("origin: ", line, min(llen,8))) == 0) { + origin = line+8; + buf[len-2] = '\0'; + //rfbLog("Got origin: %s\n", origin); + } else if ((strncasecmp("sec-websocket-key1: ", line, min(llen,20))) == 0) { + key1 = line+20; + buf[len-2] = '\0'; + //rfbLog("Got key1: %s\n", key1); + } else if ((strncasecmp("sec-websocket-key2: ", line, min(llen,20))) == 0) { + key2 = line+20; + buf[len-2] = '\0'; + //rfbLog("Got key2: %s\n", key2); + } else if ((strncasecmp("sec-websocket-protocol: ", line, min(llen,24))) == 0) { + protocol = line+24; + buf[len-2] = '\0'; + //rfbLog("Got protocol: %s\n", protocol); + } + linestart = len; + } + } + + if (!(path && host && origin)) { + rfbErr("webSocketsHandshake: incomplete client handshake\n"); + free(response); + free(buf); + return FALSE; + } + + /* + if ((!protocol) || (!strcasestr(protocol, "base64"))) { + rfbErr("webSocketsHandshake: base64 subprotocol not supported by client\n"); + free(response); + free(buf); + return FALSE; + } + */ + + /* + * Generate the WebSockets server response based on the the headers sent + * by the client. + */ + + if (!(key1 && key2 && key3)) { + rfbLog(" - WebSockets client version 75\n"); + prefix[0] = '\0'; + trailer[0] = '\0'; + } else { + rfbLog(" - WebSockets client version 76\n"); + snprintf(prefix, 5, "Sec-"); + webSocketsGenMd5(trailer, key1, key2, key3); + } + + snprintf(response, WEBSOCKETS_MAX_HANDSHAKE_LEN, + WEBSOCKETS_HANDSHAKE_RESPONSE, prefix, origin, prefix, scheme, + host, path, prefix, protocol, trailer); + + if (rfbWriteExact(cl, response, strlen(response)) < 0) { + rfbErr("webSocketsHandshake: failed sending WebSockets response\n"); + free(response); + free(buf); + return FALSE; + } + //rfbLog("webSocketsHandshake: handshake complete\n"); + return TRUE; +} + +void +webSocketsGenMd5(char * target, char *key1, char *key2, char *key3) +{ + unsigned int i, spaces1 = 0, spaces2 = 0; + unsigned long num1 = 0, num2 = 0; + unsigned char buf[17]; + for (i=0; i < strlen(key1); i++) { + if (key1[i] == ' ') { + spaces1 += 1; + } + if ((key1[i] >= 48) && (key1[i] <= 57)) { + num1 = num1 * 10 + (key1[i] - 48); + } + } + num1 = num1 / spaces1; + + for (i=0; i < strlen(key2); i++) { + if (key2[i] == ' ') { + spaces2 += 1; + } + if ((key2[i] >= 48) && (key2[i] <= 57)) { + num2 = num2 * 10 + (key2[i] - 48); + } + } + num2 = num2 / spaces2; + + /* Pack it big-endian */ + buf[0] = (num1 & 0xff000000) >> 24; + buf[1] = (num1 & 0xff0000) >> 16; + buf[2] = (num1 & 0xff00) >> 8; + buf[3] = num1 & 0xff; + + buf[4] = (num2 & 0xff000000) >> 24; + buf[5] = (num2 & 0xff0000) >> 16; + buf[6] = (num2 & 0xff00) >> 8; + buf[7] = num2 & 0xff; + + strncpy((char *)buf+8, key3, 8); + buf[16] = '\0'; + + md5_buffer((char *)buf, 16, target); + target[16] = '\0'; + + return; +} + +int +webSocketsEncode(rfbClientPtr cl, const char *src, int len) +{ + int i, sz = 0; + unsigned char chr; + cl->encodeBuf[sz++] = '\x00'; + if (cl->webSocketsBase64) { + len = __b64_ntop(src, len, cl->encodeBuf+sz, UPDATE_BUF_SIZE*2); + if (len < 0) { + return len; + } + sz += len; + } else { + for (i=0; i < len; i++) { + chr = src[i]; + if (chr < 128) { + if (chr == 0x00) { + cl->encodeBuf[sz++] = '\xc4'; + cl->encodeBuf[sz++] = '\x80'; + } else { + cl->encodeBuf[sz++] = chr; + } + } else { + if (chr < 192) { + cl->encodeBuf[sz++] = '\xc2'; + cl->encodeBuf[sz++] = chr; + } else { + cl->encodeBuf[sz++] = '\xc3'; + cl->encodeBuf[sz++] = chr - 64; + } + } + } + } + cl->encodeBuf[sz++] = '\xff'; + //rfbLog("<< webSocketsEncode: %d\n", len); + return sz; +} + +static int +ws_read(rfbClientPtr cl, char *buf, int len) +{ + int n; + if (cl->ssl) { + while ((n = SSL_read(cl->ssl, buf, len)) <= 0) { + if (SSL_get_error(cl->ssl, n) != SSL_ERROR_WANT_READ) + return -1; + } + } else { + n = read(cl->sock, buf, len); + } + return n; +} + +static int +ws_peek(rfbClientPtr cl, char *buf, int len) +{ + int total = 0, n; + if (cl->ssl) { + while ((n = SSL_peek(cl->ssl, buf, len)) <= 0) { + if (SSL_get_error(cl->ssl, n) != SSL_ERROR_WANT_READ) + return -1; + } + } else { + n = recv(cl->sock, buf, len, MSG_PEEK); + } + return n; +} + +int +webSocketsDecode(rfbClientPtr cl, char *dst, int len) +{ + int retlen = 0, n, i, avail, modlen, needlen, actual; + char *buf, *end = NULL; + unsigned char chr, chr2; + + char debug[1024]; + + buf = cl->decodeBuf; + + n = ws_peek(cl, buf, len*2+2); + + if (n <= 0) { + rfbLog("recv of %d\n", n); + return n; + } + + + if (cl->webSocketsBase64) { + /* Base64 encoded WebSockets stream */ + + if (buf[0] == '\xff') { + i = ws_read(cl, buf, 1); // Consume marker + buf++; + n--; + } + if (n == 0) { + errno = EAGAIN; + return -1; + } + if (buf[0] == '\x00') { + i = ws_read(cl, buf, 1); // Consume marker + buf++; + n--; + } + if (n == 0) { + errno = EAGAIN; + return -1; + } + + //end = memchr(buf, '\xff', len*2+2); + end = memchr(buf, '\xff', n); + if (!end) { + end = buf + n; + } + avail = end - buf; + + len -= cl->carrylen; + + /* Determine how much base64 data we need */ + modlen = len + (len+2)/3; + needlen = modlen; + if (needlen % 4) { + needlen += 4 - (needlen % 4); + } + + if (needlen > avail) { + //rfbLog("Waiting for more base64 data\n"); + errno = EAGAIN; + return -1; + } + + /* Any carryover from previous decode */ + for (i=0; i < cl->carrylen; i++) { +// rfbLog("Adding carryover %d\n", cl->carryBuf[i]); + dst[i] = cl->carryBuf[i]; + retlen += 1; + } + + /* Decode the rest of what we need */ + buf[needlen] = '\x00'; // Replace end marker with end of string +// rfbLog("buf: %s\n", buf); + n = __b64_pton(buf, dst+retlen, 2+len); + if (n < len) { + rfbErr("Base64 decode error\n"); + errno = EIO; + return -1; + } + retlen += n; + + /* Consume the data from socket */ + i = ws_read(cl, buf, needlen); + + cl->carrylen = n - len; + retlen -= cl->carrylen; + for (i=0; i < cl->carrylen; i++) { +// rfbLog("Saving carryover %d\n", dst[retlen + i]); + cl->carryBuf[i] = dst[retlen + i]; + } + } else { + /* UTF-8 encoded WebSockets stream */ + + actual = 0; + for (needlen = 0; needlen < n && actual < len; needlen++) { + chr = buf[needlen]; + if ((chr > 0) && (chr < 128)) { + actual++; + } else if ((chr > 127) && (chr < 255)) { + if (needlen + 1 >= n) { + break; + } + needlen++; + actual++; + } + } + + if (actual < len) { + errno = EAGAIN; + return -1; + } + + /* Consume what we need */ + if ((n = ws_read(cl, buf, needlen)) < needlen) { + return n; + } + + while (retlen < len) { + chr = buf[0]; + buf += 1; + + if (chr == 0) { + /* Begin frame marker, just skip it */ + } else if (chr == 255) { + /* Begin frame marker, just skip it */ + } else if (chr < 128) { + dst[retlen++] = chr; + } else { + chr2 = buf[0]; + buf += 1; + + switch (chr) { + case (unsigned char) '\xc2': + dst[retlen++] = chr2; + break; + case (unsigned char) '\xc3': + dst[retlen++] = chr2 + 64; + break; + case (unsigned char) '\xc4': + dst[retlen++] = 0; + break; + default: + rfbErr("Invalid UTF-8 encoding\n"); + errno = EIO; + return -1; + } + } + } + } + +// rfbLog("<< webSocketsDecode, retlen: %d\n", retlen); + return retlen; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c new file mode 100755 index 0000000..ac20c9c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zlib.c @@ -0,0 +1,331 @@ +/* + * zlib.c + * + * Routines to implement zlib based encoding (deflate). + */ + +/* + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * For the latest source code, please check: + * + * http://www.developVNC.org/ + * + * or send email to feedback@developvnc.org. + */ + +#include + +/* + * zlibBeforeBuf contains pixel data in the client's format. + * zlibAfterBuf contains the zlib (deflated) encoding version. + * If the zlib compressed/encoded version is + * larger than the raw data or if it exceeds zlibAfterBufSize then + * raw encoding is used instead. + */ + +/* + * Out of lazyiness, we use thread local storage for zlib as we did for + * tight. N.B. ZRLE does it the traditional way with per-client storage + * (and so at least ZRLE will work threaded on older systems.) + */ +#if LIBVNCSERVER_HAVE_LIBPTHREAD && LIBVNCSERVER_HAVE_TLS && !defined(TLS) && defined(__linux__) +#define TLS __thread +#endif +#ifndef TLS +#define TLS +#endif + +static TLS int zlibBeforeBufSize = 0; +static TLS char *zlibBeforeBuf = NULL; + +static TLS int zlibAfterBufSize = 0; +static TLS char *zlibAfterBuf = NULL; +static TLS int zlibAfterBufLen = 0; + +void rfbZlibCleanup(rfbScreenInfoPtr screen) +{ + if (zlibBeforeBufSize) { + free(zlibBeforeBuf); + zlibBeforeBufSize=0; + } + if (zlibAfterBufSize) { + zlibAfterBufSize=0; + free(zlibAfterBuf); + } +} + + +/* + * rfbSendOneRectEncodingZlib - send a given rectangle using one Zlib + * rectangle encoding. + */ + +static rfbBool +rfbSendOneRectEncodingZlib(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + rfbFramebufferUpdateRectHeader rect; + rfbZlibHeader hdr; + int deflateResult; + int previousOut; + int i; + char *fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) + + (x * (cl->scaledScreen->bitsPerPixel / 8))); + + int maxRawSize; + int maxCompSize; + + maxRawSize = (cl->scaledScreen->width * cl->scaledScreen->height + * (cl->format.bitsPerPixel / 8)); + + if (zlibBeforeBufSize < maxRawSize) { + zlibBeforeBufSize = maxRawSize; + if (zlibBeforeBuf == NULL) + zlibBeforeBuf = (char *)malloc(zlibBeforeBufSize); + else + zlibBeforeBuf = (char *)realloc(zlibBeforeBuf, zlibBeforeBufSize); + } + + /* zlib compression is not useful for very small data sets. + * So, we just send these raw without any compression. + */ + if (( w * h * (cl->scaledScreen->bitsPerPixel / 8)) < + VNC_ENCODE_ZLIB_MIN_COMP_SIZE ) { + + int result; + + /* The translation function (used also by the in raw encoding) + * requires 4/2/1 byte alignment in the output buffer (which is + * updateBuf for the raw encoding) based on the bitsPerPixel of + * the viewer/client. This prevents SIGBUS errors on some + * architectures like SPARC, PARISC... + */ + if (( cl->format.bitsPerPixel > 8 ) && + ( cl->ublen % ( cl->format.bitsPerPixel / 8 )) != 0 ) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + result = rfbSendRectEncodingRaw(cl, x, y, w, h); + + return result; + + } + + /* + * zlib requires output buffer to be slightly larger than the input + * buffer, in the worst case. + */ + maxCompSize = maxRawSize + (( maxRawSize + 99 ) / 100 ) + 12; + + if (zlibAfterBufSize < maxCompSize) { + zlibAfterBufSize = maxCompSize; + if (zlibAfterBuf == NULL) + zlibAfterBuf = (char *)malloc(zlibAfterBufSize); + else + zlibAfterBuf = (char *)realloc(zlibAfterBuf, zlibAfterBufSize); + } + + + /* + * Convert pixel data to client format. + */ + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat, + &cl->format, fbptr, zlibBeforeBuf, + cl->scaledScreen->paddedWidthInBytes, w, h); + + cl->compStream.next_in = ( Bytef * )zlibBeforeBuf; + cl->compStream.avail_in = w * h * (cl->format.bitsPerPixel / 8); + cl->compStream.next_out = ( Bytef * )zlibAfterBuf; + cl->compStream.avail_out = maxCompSize; + cl->compStream.data_type = Z_BINARY; + + /* Initialize the deflation state. */ + if ( cl->compStreamInited == FALSE ) { + + cl->compStream.total_in = 0; + cl->compStream.total_out = 0; + cl->compStream.zalloc = Z_NULL; + cl->compStream.zfree = Z_NULL; + cl->compStream.opaque = Z_NULL; + + deflateInit2( &(cl->compStream), + cl->zlibCompressLevel, + Z_DEFLATED, + MAX_WBITS, + MAX_MEM_LEVEL, + Z_DEFAULT_STRATEGY ); + /* deflateInit( &(cl->compStream), Z_BEST_COMPRESSION ); */ + /* deflateInit( &(cl->compStream), Z_BEST_SPEED ); */ + cl->compStreamInited = TRUE; + + } + + previousOut = cl->compStream.total_out; + + /* Perform the compression here. */ + deflateResult = deflate( &(cl->compStream), Z_SYNC_FLUSH ); + + /* Find the total size of the resulting compressed data. */ + zlibAfterBufLen = cl->compStream.total_out - previousOut; + + if ( deflateResult != Z_OK ) { + rfbErr("zlib deflation error: %s\n", cl->compStream.msg); + return FALSE; + } + + /* Note that it is not possible to switch zlib parameters based on + * the results of the compression pass. The reason is + * that we rely on the compressor and decompressor states being + * in sync. Compressing and then discarding the results would + * cause lose of synchronization. + */ + + /* Update statics */ + rfbStatRecordEncodingSent(cl, rfbEncodingZlib, sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + zlibAfterBufLen, + + w * (cl->format.bitsPerPixel / 8) * h); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZlibHeader + > UPDATE_BUF_SIZE) + { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(rfbEncodingZlib); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.nBytes = Swap32IfLE(zlibAfterBufLen); + + memcpy(&cl->updateBuf[cl->ublen], (char *)&hdr, sz_rfbZlibHeader); + cl->ublen += sz_rfbZlibHeader; + + for (i = 0; i < zlibAfterBufLen;) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > zlibAfterBufLen) { + bytesToCopy = zlibAfterBufLen - i; + } + + memcpy(&cl->updateBuf[cl->ublen], &zlibAfterBuf[i], bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; + +} + + +/* + * rfbSendRectEncodingZlib - send a given rectangle using one or more + * Zlib encoding rectangles. + */ + +rfbBool +rfbSendRectEncodingZlib(rfbClientPtr cl, + int x, + int y, + int w, + int h) +{ + int maxLines; + int linesRemaining; + rfbRectangle partialRect; + + partialRect.x = x; + partialRect.y = y; + partialRect.w = w; + partialRect.h = h; + + /* Determine maximum pixel/scan lines allowed per rectangle. */ + maxLines = ( ZLIB_MAX_SIZE(w) / w ); + + /* Initialize number of scan lines left to do. */ + linesRemaining = h; + + /* Loop until all work is done. */ + while ( linesRemaining > 0 ) { + + int linesToComp; + + if ( maxLines < linesRemaining ) + linesToComp = maxLines; + else + linesToComp = linesRemaining; + + partialRect.h = linesToComp; + + /* Encode (compress) and send the next rectangle. */ + if ( ! rfbSendOneRectEncodingZlib( cl, + partialRect.x, + partialRect.y, + partialRect.w, + partialRect.h )) { + + return FALSE; + } + + /* Technically, flushing the buffer here is not extrememly + * efficient. However, this improves the overall throughput + * of the system over very slow networks. By flushing + * the buffer with every maximum size zlib rectangle, we + * improve the pipelining usage of the server CPU, network, + * and viewer CPU components. Insuring that these components + * are working in parallel actually improves the performance + * seen by the user. + * Since, zlib is most useful for slow networks, this flush + * is appropriate for the desired behavior of the zlib encoding. + */ + if (( cl->ublen > 0 ) && + ( linesToComp == maxLines )) { + if (!rfbSendUpdateBuf(cl)) { + + return FALSE; + } + } + + /* Update remaining and incremental rectangle location. */ + linesRemaining -= linesToComp; + partialRect.y += linesToComp; + + } + + return TRUE; + +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c new file mode 100755 index 0000000..e1f1447 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrle.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * zrle.c + * + * Routines to implement Zlib Run-length Encoding (ZRLE). + */ + +#include "rfb/rfb.h" +#include "private.h" +#include "zrleoutstream.h" + + +#define GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf) \ +{ char *fbptr = (cl->scaledScreen->frameBuffer \ + + (cl->scaledScreen->paddedWidthInBytes * ty) \ + + (tx * (cl->scaledScreen->bitsPerPixel / 8))); \ + \ + (*cl->translateFn)(cl->translateLookupTable, &cl->screen->serverFormat,\ + &cl->format, fbptr, (char*)buf, \ + cl->scaledScreen->paddedWidthInBytes, tw, th); } + +#define EXTRA_ARGS , rfbClientPtr cl + +#define ENDIAN_LITTLE 0 +#define ENDIAN_BIG 1 +#define ENDIAN_NO 2 +#define BPP 8 +#define ZYWRLE_ENDIAN ENDIAN_NO +#include +#undef BPP +#define BPP 15 +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef BPP +#define BPP 16 +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef BPP +#define BPP 32 +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#define CPIXEL 24A +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef CPIXEL +#define CPIXEL 24B +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_LITTLE +#include +#undef ZYWRLE_ENDIAN +#define ZYWRLE_ENDIAN ENDIAN_BIG +#include +#undef CPIXEL +#undef BPP + + +/* + * zrleBeforeBuf contains pixel data in the client's format. It must be at + * least one pixel bigger than the largest tile of pixel data, since the + * ZRLE encoding algorithm writes to the position one past the end of the pixel + * data. + */ + +/* TODO: put into rfbClient struct */ + +static char zrleBeforeBuf[rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4]; + +/* + * rfbSendRectEncodingZRLE - send a given rectangle using ZRLE encoding. + */ + +rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w, int h) +{ + zrleOutStream* zos; + rfbFramebufferUpdateRectHeader rect; + rfbZRLEHeader hdr; + int i; + char *zrleBeforeBuf; + + if (cl->zrleBeforeBuf == NULL) { + cl->zrleBeforeBuf = (char *) malloc(rfbZRLETileWidth * rfbZRLETileHeight * 4 + 4); + } + zrleBeforeBuf = cl->zrleBeforeBuf; + + if (cl->preferredEncoding == rfbEncodingZYWRLE) { + if (cl->tightQualityLevel < 0) { + cl->zywrleLevel = 1; + } else if (cl->tightQualityLevel < 3) { + cl->zywrleLevel = 3; + } else if (cl->tightQualityLevel < 6) { + cl->zywrleLevel = 2; + } else { + cl->zywrleLevel = 1; + } + } else + cl->zywrleLevel = 0; + + if (!cl->zrleData) + cl->zrleData = zrleOutStreamNew(); + zos = cl->zrleData; + zos->in.ptr = zos->in.start; + zos->out.ptr = zos->out.start; + + switch (cl->format.bitsPerPixel) { + + case 8: + zrleEncode8NE(x, y, w, h, zos, zrleBeforeBuf, cl); + break; + + case 16: + if (cl->format.greenMax > 0x1F) { + if (cl->format.bigEndian) + zrleEncode16BE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode16LE(x, y, w, h, zos, zrleBeforeBuf, cl); + } else { + if (cl->format.bigEndian) + zrleEncode15BE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode15LE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + break; + + case 32: { + rfbBool fitsInLS3Bytes + = ((cl->format.redMax << cl->format.redShift) < (1<<24) && + (cl->format.greenMax << cl->format.greenShift) < (1<<24) && + (cl->format.blueMax << cl->format.blueShift) < (1<<24)); + + rfbBool fitsInMS3Bytes = (cl->format.redShift > 7 && + cl->format.greenShift > 7 && + cl->format.blueShift > 7); + + if ((fitsInLS3Bytes && !cl->format.bigEndian) || + (fitsInMS3Bytes && cl->format.bigEndian)) { + if (cl->format.bigEndian) + zrleEncode24ABE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode24ALE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + else if ((fitsInLS3Bytes && cl->format.bigEndian) || + (fitsInMS3Bytes && !cl->format.bigEndian)) { + if (cl->format.bigEndian) + zrleEncode24BBE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode24BLE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + else { + if (cl->format.bigEndian) + zrleEncode32BE(x, y, w, h, zos, zrleBeforeBuf, cl); + else + zrleEncode32LE(x, y, w, h, zos, zrleBeforeBuf, cl); + } + } + break; + } + + rfbStatRecordEncodingSent(cl, rfbEncodingZRLE, sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + ZRLE_BUFFER_LENGTH(&zos->out), + + w * (cl->format.bitsPerPixel / 8) * h); + + if (cl->ublen + sz_rfbFramebufferUpdateRectHeader + sz_rfbZRLEHeader + > UPDATE_BUF_SIZE) + { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + + rect.r.x = Swap16IfLE(x); + rect.r.y = Swap16IfLE(y); + rect.r.w = Swap16IfLE(w); + rect.r.h = Swap16IfLE(h); + rect.encoding = Swap32IfLE(cl->preferredEncoding); + + memcpy(cl->updateBuf+cl->ublen, (char *)&rect, + sz_rfbFramebufferUpdateRectHeader); + cl->ublen += sz_rfbFramebufferUpdateRectHeader; + + hdr.length = Swap32IfLE(ZRLE_BUFFER_LENGTH(&zos->out)); + + memcpy(cl->updateBuf+cl->ublen, (char *)&hdr, sz_rfbZRLEHeader); + cl->ublen += sz_rfbZRLEHeader; + + /* copy into updateBuf and send from there. Maybe should send directly? */ + + for (i = 0; i < ZRLE_BUFFER_LENGTH(&zos->out);) { + + int bytesToCopy = UPDATE_BUF_SIZE - cl->ublen; + + if (i + bytesToCopy > ZRLE_BUFFER_LENGTH(&zos->out)) { + bytesToCopy = ZRLE_BUFFER_LENGTH(&zos->out) - i; + } + + memcpy(cl->updateBuf+cl->ublen, (uint8_t*)zos->out.start + i, bytesToCopy); + + cl->ublen += bytesToCopy; + i += bytesToCopy; + + if (cl->ublen == UPDATE_BUF_SIZE) { + if (!rfbSendUpdateBuf(cl)) + return FALSE; + } + } + + return TRUE; +} + + +void rfbFreeZrleData(rfbClientPtr cl) +{ + if (cl->zrleData) { + zrleOutStreamFree(cl->zrleData); + } + cl->zrleData = NULL; + + if (cl->zrleBeforeBuf) { + free(cl->zrleBeforeBuf); + } + cl->zrleBeforeBuf = NULL; + + if (cl->paletteHelper) { + free(cl->paletteHelper); + } + cl->paletteHelper = NULL; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c new file mode 100755 index 0000000..3a6f117 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleencodetemplate.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * Before including this file, you must define a number of CPP macros. + * + * BPP should be 8, 16 or 32 depending on the bits per pixel. + * GET_IMAGE_INTO_BUF should be some code which gets a rectangle of pixel data + * into the given buffer. EXTRA_ARGS can be defined to pass any other + * arguments needed by GET_IMAGE_INTO_BUF. + * + * Note that the buf argument to ZRLE_ENCODE needs to be at least one pixel + * bigger than the largest tile of pixel data, since the ZRLE encoding + * algorithm writes to the position one past the end of the pixel data. + */ + +#include "zrleoutstream.h" +#include "zrlepalettehelper.h" +#include + +/* __RFB_CONCAT2 concatenates its two arguments. __RFB_CONCAT2E does the same + but also expands its arguments if they are macros */ + +#ifndef __RFB_CONCAT2E +#define __RFB_CONCAT2(a,b) a##b +#define __RFB_CONCAT2E(a,b) __RFB_CONCAT2(a,b) +#endif + +#ifndef __RFB_CONCAT3E +#define __RFB_CONCAT3(a,b,c) a##b##c +#define __RFB_CONCAT3E(a,b,c) __RFB_CONCAT3(a,b,c) +#endif + +#undef END_FIX +#if ZYWRLE_ENDIAN == ENDIAN_LITTLE +# define END_FIX LE +#elif ZYWRLE_ENDIAN == ENDIAN_BIG +# define END_FIX BE +#else +# define END_FIX NE +#endif + +#ifdef CPIXEL +#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,CPIXEL) +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,CPIXEL,END_FIX) +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,CPIXEL,END_FIX) +#define BPPOUT 24 +#elif BPP==15 +#define PIXEL_T __RFB_CONCAT2E(zrle_U,16) +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,16) +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) +#define BPPOUT 16 +#else +#define PIXEL_T __RFB_CONCAT2E(zrle_U,BPP) +#define zrleOutStreamWRITE_PIXEL __RFB_CONCAT2E(zrleOutStreamWriteOpaque,BPP) +#define ZRLE_ENCODE __RFB_CONCAT3E(zrleEncode,BPP,END_FIX) +#define ZRLE_ENCODE_TILE __RFB_CONCAT3E(zrleEncodeTile,BPP,END_FIX) +#define BPPOUT BPP +#endif + +#ifndef ZRLE_ONCE +#define ZRLE_ONCE + +static const int bitsPerPackedPixel[] = { + 0, 1, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 +}; + +static zrlePaletteHelper paletteHelper; + +#endif /* ZRLE_ONCE */ + +void ZRLE_ENCODE_TILE (PIXEL_T* data, int w, int h, zrleOutStream* os, + int zywrle_level, int *zywrleBuf, void *paletteHelper); + +#if BPP!=8 +#define ZYWRLE_ENCODE +#include "zywrletemplate.c" +#endif + +static void ZRLE_ENCODE (int x, int y, int w, int h, + zrleOutStream* os, void* buf + EXTRA_ARGS + ) +{ + int ty; + for (ty = y; ty < y+h; ty += rfbZRLETileHeight) { + int tx, th = rfbZRLETileHeight; + if (th > y+h-ty) th = y+h-ty; + for (tx = x; tx < x+w; tx += rfbZRLETileWidth) { + int tw = rfbZRLETileWidth; + if (tw > x+w-tx) tw = x+w-tx; + + GET_IMAGE_INTO_BUF(tx,ty,tw,th,buf); + + if (cl->paletteHelper == NULL) { + cl->paletteHelper = (void *) calloc(sizeof(zrlePaletteHelper), 1); + } + + ZRLE_ENCODE_TILE((PIXEL_T*)buf, tw, th, os, + cl->zywrleLevel, cl->zywrleBuf, cl->paletteHelper); + } + } + zrleOutStreamFlush(os); +} + + +void ZRLE_ENCODE_TILE(PIXEL_T* data, int w, int h, zrleOutStream* os, + int zywrle_level, int *zywrleBuf, void *paletteHelper) +{ + /* First find the palette and the number of runs */ + + zrlePaletteHelper *ph; + + int runs = 0; + int singlePixels = 0; + + rfbBool useRle; + rfbBool usePalette; + + int estimatedBytes; + int plainRleBytes; + int i; + + PIXEL_T* ptr = data; + PIXEL_T* end = ptr + h * w; + *end = ~*(end-1); /* one past the end is different so the while loop ends */ + +#if 0 + ph = &paletteHelper; +#else + ph = (zrlePaletteHelper *) paletteHelper; +#endif + zrlePaletteHelperInit(ph); + + while (ptr < end) { + PIXEL_T pix = *ptr; + if (*++ptr != pix) { + singlePixels++; + } else { + while (*++ptr == pix) ; + runs++; + } + zrlePaletteHelperInsert(ph, pix); + } + + /* Solid tile is a special case */ + + if (ph->size == 1) { + zrleOutStreamWriteU8(os, 1); + zrleOutStreamWRITE_PIXEL(os, ph->palette[0]); + return; + } + + /* Try to work out whether to use RLE and/or a palette. We do this by + estimating the number of bytes which will be generated and picking the + method which results in the fewest bytes. Of course this may not result + in the fewest bytes after compression... */ + + useRle = FALSE; + usePalette = FALSE; + + estimatedBytes = w * h * (BPPOUT/8); /* start assuming raw */ + +#if BPP!=8 + if (zywrle_level > 0 && !(zywrle_level & 0x80)) + estimatedBytes >>= zywrle_level; +#endif + + plainRleBytes = ((BPPOUT/8)+1) * (runs + singlePixels); + + if (plainRleBytes < estimatedBytes) { + useRle = TRUE; + estimatedBytes = plainRleBytes; + } + + if (ph->size < 128) { + int paletteRleBytes = (BPPOUT/8) * ph->size + 2 * runs + singlePixels; + + if (paletteRleBytes < estimatedBytes) { + useRle = TRUE; + usePalette = TRUE; + estimatedBytes = paletteRleBytes; + } + + if (ph->size < 17) { + int packedBytes = ((BPPOUT/8) * ph->size + + w * h * bitsPerPackedPixel[ph->size-1] / 8); + + if (packedBytes < estimatedBytes) { + useRle = FALSE; + usePalette = TRUE; + estimatedBytes = packedBytes; + } + } + } + + if (!usePalette) ph->size = 0; + + zrleOutStreamWriteU8(os, (useRle ? 128 : 0) | ph->size); + + for (i = 0; i < ph->size; i++) { + zrleOutStreamWRITE_PIXEL(os, ph->palette[i]); + } + + if (useRle) { + + PIXEL_T* ptr = data; + PIXEL_T* end = ptr + w * h; + PIXEL_T* runStart; + PIXEL_T pix; + while (ptr < end) { + int len; + runStart = ptr; + pix = *ptr++; + while (*ptr == pix && ptr < end) + ptr++; + len = ptr - runStart; + if (len <= 2 && usePalette) { + int index = zrlePaletteHelperLookup(ph, pix); + if (len == 2) + zrleOutStreamWriteU8(os, index); + zrleOutStreamWriteU8(os, index); + continue; + } + if (usePalette) { + int index = zrlePaletteHelperLookup(ph, pix); + zrleOutStreamWriteU8(os, index | 128); + } else { + zrleOutStreamWRITE_PIXEL(os, pix); + } + len -= 1; + while (len >= 255) { + zrleOutStreamWriteU8(os, 255); + len -= 255; + } + zrleOutStreamWriteU8(os, len); + } + + } else { + + /* no RLE */ + + if (usePalette) { + int bppp; + PIXEL_T* ptr = data; + + /* packed pixels */ + + assert (ph->size < 17); + + bppp = bitsPerPackedPixel[ph->size-1]; + + for (i = 0; i < h; i++) { + zrle_U8 nbits = 0; + zrle_U8 byte = 0; + + PIXEL_T* eol = ptr + w; + + while (ptr < eol) { + PIXEL_T pix = *ptr++; + zrle_U8 index = zrlePaletteHelperLookup(ph, pix); + byte = (byte << bppp) | index; + nbits += bppp; + if (nbits >= 8) { + zrleOutStreamWriteU8(os, byte); + nbits = 0; + } + } + if (nbits > 0) { + byte <<= 8 - nbits; + zrleOutStreamWriteU8(os, byte); + } + } + } else { + + /* raw */ + +#if BPP!=8 + if (zywrle_level > 0 && !(zywrle_level & 0x80)) { + ZYWRLE_ANALYZE(data, data, w, h, w, zywrle_level, zywrleBuf); + ZRLE_ENCODE_TILE(data, w, h, os, zywrle_level | 0x80, zywrleBuf, paletteHelper); + } + else +#endif + { +#ifdef CPIXEL + PIXEL_T *ptr; + for (ptr = data; ptr < data+w*h; ptr++) + zrleOutStreamWRITE_PIXEL(os, *ptr); +#else + zrleOutStreamWriteBytes(os, (zrle_U8 *)data, w*h*(BPP/8)); +#endif + } + } + } +} + +#undef PIXEL_T +#undef zrleOutStreamWRITE_PIXEL +#undef ZRLE_ENCODE +#undef ZRLE_ENCODE_TILE +#undef ZYWRLE_ENCODE_TILE +#undef BPPOUT diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c new file mode 100755 index 0000000..4efe609 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.c @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "zrleoutstream.h" +#include + +#define ZRLE_IN_BUFFER_SIZE 16384 +#define ZRLE_OUT_BUFFER_SIZE 1024 +#undef ZRLE_DEBUG + +static rfbBool zrleBufferAlloc(zrleBuffer *buffer, int size) +{ + buffer->ptr = buffer->start = malloc(size); + if (buffer->start == NULL) { + buffer->end = NULL; + return FALSE; + } + + buffer->end = buffer->start + size; + + return TRUE; +} + +static void zrleBufferFree(zrleBuffer *buffer) +{ + if (buffer->start) + free(buffer->start); + buffer->start = buffer->ptr = buffer->end = NULL; +} + +static rfbBool zrleBufferGrow(zrleBuffer *buffer, int size) +{ + int offset; + + size += buffer->end - buffer->start; + offset = ZRLE_BUFFER_LENGTH (buffer); + + buffer->start = realloc(buffer->start, size); + if (!buffer->start) { + return FALSE; + } + + buffer->end = buffer->start + size; + buffer->ptr = buffer->start + offset; + + return TRUE; +} + +zrleOutStream *zrleOutStreamNew(void) +{ + zrleOutStream *os; + + os = malloc(sizeof(zrleOutStream)); + if (os == NULL) + return NULL; + + if (!zrleBufferAlloc(&os->in, ZRLE_IN_BUFFER_SIZE)) { + free(os); + return NULL; + } + + if (!zrleBufferAlloc(&os->out, ZRLE_OUT_BUFFER_SIZE)) { + zrleBufferFree(&os->in); + free(os); + return NULL; + } + + os->zs.zalloc = Z_NULL; + os->zs.zfree = Z_NULL; + os->zs.opaque = Z_NULL; + if (deflateInit(&os->zs, Z_DEFAULT_COMPRESSION) != Z_OK) { + zrleBufferFree(&os->in); + free(os); + return NULL; + } + + return os; +} + +void zrleOutStreamFree (zrleOutStream *os) +{ + deflateEnd(&os->zs); + zrleBufferFree(&os->in); + zrleBufferFree(&os->out); + free(os); +} + +rfbBool zrleOutStreamFlush(zrleOutStream *os) +{ + os->zs.next_in = os->in.start; + os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamFlush: avail_in %d\n", os->zs.avail_in); +#endif + + while (os->zs.avail_in != 0) { + do { + int ret; + + if (os->out.ptr >= os->out.end && + !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { + rfbLog("zrleOutStreamFlush: failed to grow output buffer\n"); + return FALSE; + } + + os->zs.next_out = os->out.ptr; + os->zs.avail_out = os->out.end - os->out.ptr; + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamFlush: calling deflate, avail_in %d, avail_out %d\n", + os->zs.avail_in, os->zs.avail_out); +#endif + + if ((ret = deflate(&os->zs, Z_SYNC_FLUSH)) != Z_OK) { + rfbLog("zrleOutStreamFlush: deflate failed with error code %d\n", ret); + return FALSE; + } + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamFlush: after deflate: %d bytes\n", + os->zs.next_out - os->out.ptr); +#endif + + os->out.ptr = os->zs.next_out; + } while (os->zs.avail_out == 0); + } + + os->in.ptr = os->in.start; + + return TRUE; +} + +static int zrleOutStreamOverrun(zrleOutStream *os, + int size) +{ +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamOverrun\n"); +#endif + + while (os->in.end - os->in.ptr < size && os->in.ptr > os->in.start) { + os->zs.next_in = os->in.start; + os->zs.avail_in = ZRLE_BUFFER_LENGTH (&os->in); + + do { + int ret; + + if (os->out.ptr >= os->out.end && + !zrleBufferGrow(&os->out, os->out.end - os->out.start)) { + rfbLog("zrleOutStreamOverrun: failed to grow output buffer\n"); + return FALSE; + } + + os->zs.next_out = os->out.ptr; + os->zs.avail_out = os->out.end - os->out.ptr; + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamOverrun: calling deflate, avail_in %d, avail_out %d\n", + os->zs.avail_in, os->zs.avail_out); +#endif + + if ((ret = deflate(&os->zs, 0)) != Z_OK) { + rfbLog("zrleOutStreamOverrun: deflate failed with error code %d\n", ret); + return 0; + } + +#ifdef ZRLE_DEBUG + rfbLog("zrleOutStreamOverrun: after deflate: %d bytes\n", + os->zs.next_out - os->out.ptr); +#endif + + os->out.ptr = os->zs.next_out; + } while (os->zs.avail_out == 0); + + /* output buffer not full */ + + if (os->zs.avail_in == 0) { + os->in.ptr = os->in.start; + } else { + /* but didn't consume all the data? try shifting what's left to the + * start of the buffer. + */ + rfbLog("zrleOutStreamOverrun: out buf not full, but in data not consumed\n"); + memmove(os->in.start, os->zs.next_in, os->in.ptr - os->zs.next_in); + os->in.ptr -= os->zs.next_in - os->in.start; + } + } + + if (size > os->in.end - os->in.ptr) + size = os->in.end - os->in.ptr; + + return size; +} + +static int zrleOutStreamCheck(zrleOutStream *os, int size) +{ + if (os->in.ptr + size > os->in.end) { + return zrleOutStreamOverrun(os, size); + } + return size; +} + +void zrleOutStreamWriteBytes(zrleOutStream *os, + const zrle_U8 *data, + int length) +{ + const zrle_U8* dataEnd = data + length; + while (data < dataEnd) { + int n = zrleOutStreamCheck(os, dataEnd - data); + memcpy(os->in.ptr, data, n); + os->in.ptr += n; + data += n; + } +} + +void zrleOutStreamWriteU8(zrleOutStream *os, zrle_U8 u) +{ + zrleOutStreamCheck(os, 1); + *os->in.ptr++ = u; +} + +void zrleOutStreamWriteOpaque8(zrleOutStream *os, zrle_U8 u) +{ + zrleOutStreamCheck(os, 1); + *os->in.ptr++ = u; +} + +void zrleOutStreamWriteOpaque16 (zrleOutStream *os, zrle_U16 u) +{ + zrleOutStreamCheck(os, 2); + *os->in.ptr++ = ((zrle_U8*)&u)[0]; + *os->in.ptr++ = ((zrle_U8*)&u)[1]; +} + +void zrleOutStreamWriteOpaque32 (zrleOutStream *os, zrle_U32 u) +{ + zrleOutStreamCheck(os, 4); + *os->in.ptr++ = ((zrle_U8*)&u)[0]; + *os->in.ptr++ = ((zrle_U8*)&u)[1]; + *os->in.ptr++ = ((zrle_U8*)&u)[2]; + *os->in.ptr++ = ((zrle_U8*)&u)[3]; +} + +void zrleOutStreamWriteOpaque24A(zrleOutStream *os, zrle_U32 u) +{ + zrleOutStreamCheck(os, 3); + *os->in.ptr++ = ((zrle_U8*)&u)[0]; + *os->in.ptr++ = ((zrle_U8*)&u)[1]; + *os->in.ptr++ = ((zrle_U8*)&u)[2]; +} + +void zrleOutStreamWriteOpaque24B(zrleOutStream *os, zrle_U32 u) +{ + zrleOutStreamCheck(os, 3); + *os->in.ptr++ = ((zrle_U8*)&u)[1]; + *os->in.ptr++ = ((zrle_U8*)&u)[2]; + *os->in.ptr++ = ((zrle_U8*)&u)[3]; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h new file mode 100755 index 0000000..9e4fe51 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrleoutstream.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __ZRLE_OUT_STREAM_H__ +#define __ZRLE_OUT_STREAM_H__ + +#include +#include "zrletypes.h" +#include "rfb/rfb.h" + +typedef struct { + zrle_U8 *start; + zrle_U8 *ptr; + zrle_U8 *end; +} zrleBuffer; + +typedef struct { + zrleBuffer in; + zrleBuffer out; + + z_stream zs; +} zrleOutStream; + +#define ZRLE_BUFFER_LENGTH(b) ((b)->ptr - (b)->start) + +zrleOutStream *zrleOutStreamNew (void); +void zrleOutStreamFree (zrleOutStream *os); +rfbBool zrleOutStreamFlush (zrleOutStream *os); +void zrleOutStreamWriteBytes (zrleOutStream *os, + const zrle_U8 *data, + int length); +void zrleOutStreamWriteU8 (zrleOutStream *os, + zrle_U8 u); +void zrleOutStreamWriteOpaque8 (zrleOutStream *os, + zrle_U8 u); +void zrleOutStreamWriteOpaque16 (zrleOutStream *os, + zrle_U16 u); +void zrleOutStreamWriteOpaque32 (zrleOutStream *os, + zrle_U32 u); +void zrleOutStreamWriteOpaque24A(zrleOutStream *os, + zrle_U32 u); +void zrleOutStreamWriteOpaque24B(zrleOutStream *os, + zrle_U32 u); + +#endif /* __ZRLE_OUT_STREAM_H__ */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c new file mode 100755 index 0000000..d758a26 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.c @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include "zrlepalettehelper.h" +#include +#include + +#define ZRLE_HASH(pix) (((pix) ^ ((pix) >> 17)) & 4095) + +void zrlePaletteHelperInit(zrlePaletteHelper *helper) +{ + memset(helper->palette, 0, sizeof(helper->palette)); + memset(helper->index, 255, sizeof(helper->index)); + memset(helper->key, 0, sizeof(helper->key)); + helper->size = 0; +} + +void zrlePaletteHelperInsert(zrlePaletteHelper *helper, zrle_U32 pix) +{ + if (helper->size < ZRLE_PALETTE_MAX_SIZE) { + int i = ZRLE_HASH(pix); + + while (helper->index[i] != 255 && helper->key[i] != pix) + i++; + if (helper->index[i] != 255) return; + + helper->index[i] = helper->size; + helper->key[i] = pix; + helper->palette[helper->size] = pix; + } + helper->size++; +} + +int zrlePaletteHelperLookup(zrlePaletteHelper *helper, zrle_U32 pix) +{ + int i = ZRLE_HASH(pix); + + assert(helper->size <= ZRLE_PALETTE_MAX_SIZE); + + while (helper->index[i] != 255 && helper->key[i] != pix) + i++; + if (helper->index[i] != 255) return helper->index[i]; + + return -1; +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h new file mode 100755 index 0000000..e1213d1 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrlepalettehelper.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * Copyright (C) 2003 Sun Microsystems, Inc. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * The PaletteHelper class helps us build up the palette from pixel data by + * storing a reverse index using a simple hash-table + */ + +#ifndef __ZRLE_PALETTE_HELPER_H__ +#define __ZRLE_PALETTE_HELPER_H__ + +#include "zrletypes.h" + +#define ZRLE_PALETTE_MAX_SIZE 127 + +typedef struct { + zrle_U32 palette[ZRLE_PALETTE_MAX_SIZE]; + zrle_U8 index[ZRLE_PALETTE_MAX_SIZE + 4096]; + zrle_U32 key[ZRLE_PALETTE_MAX_SIZE + 4096]; + int size; +} zrlePaletteHelper; + +void zrlePaletteHelperInit (zrlePaletteHelper *helper); +void zrlePaletteHelperInsert(zrlePaletteHelper *helper, + zrle_U32 pix); +int zrlePaletteHelperLookup(zrlePaletteHelper *helper, + zrle_U32 pix); + +#endif /* __ZRLE_PALETTE_HELPER_H__ */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h new file mode 100755 index 0000000..0df42c9 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zrletypes.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2002 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __ZRLE_TYPES_H__ +#define __ZRLE_TYPES_H__ + +typedef unsigned char zrle_U8; +typedef unsigned short zrle_U16; +typedef unsigned int zrle_U32; +typedef signed char zrle_S8; +typedef signed short zrle_S16; +typedef signed int zrle_S32; + +#endif /* __ZRLE_TYPES_H__ */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c new file mode 100755 index 0000000..52b2b0b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/libvncserver/zywrletemplate.c @@ -0,0 +1,824 @@ + +/******************************************************************** + * * + * THIS FILE IS PART OF THE 'ZYWRLE' VNC CODEC SOURCE CODE. * + * * + * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * + * GOVERNED BY A FOLLOWING BSD-STYLE SOURCE LICENSE. * + * PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * + * * + * THE 'ZYWRLE' VNC CODEC SOURCE CODE IS (C) COPYRIGHT 2006 * + * BY Hitachi Systems & Services, Ltd. * + * (Noriaki Yamazaki, Research & Developement Center) * * + * * + ******************************************************************** +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +- Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +- 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. + +- Neither the name of the Hitachi Systems & Services, Ltd. nor +the names of its contributors may be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 FOUNDATION +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. + ********************************************************************/ + +/* Change Log: + V0.02 : 2008/02/04 : Fix mis encode/decode when width != scanline + (Thanks Johannes Schindelin, author of LibVNC + Server/Client) + V0.01 : 2007/02/06 : Initial release +*/ + +/* #define ZYWRLE_ENCODE */ +/* #define ZYWRLE_DECODE */ +#define ZYWRLE_QUANTIZE + +/* +[References] + PLHarr: + Senecal, J. G., P. Lindstrom, M. A. Duchaineau, and K. I. Joy, "An Improved N-Bit to N-Bit Reversible Haar-Like Transform," Pacific Graphics 2004, October 2004, pp. 371-380. + EZW: + Shapiro, JM: Embedded Image Coding Using Zerotrees of Wavelet Coefficients, IEEE Trans. Signal. Process., Vol.41, pp.3445-3462 (1993). +*/ + + +/* Template Macro stuffs. */ +#undef ZYWRLE_ANALYZE +#undef ZYWRLE_SYNTHESIZE +#define ZYWRLE_ANALYZE __RFB_CONCAT3E(zywrleAnalyze,BPP,END_FIX) +#define ZYWRLE_SYNTHESIZE __RFB_CONCAT3E(zywrleSynthesize,BPP,END_FIX) + +#define ZYWRLE_RGBYUV __RFB_CONCAT3E(zywrleRGBYUV,BPP,END_FIX) +#define ZYWRLE_YUVRGB __RFB_CONCAT3E(zywrleYUVRGB,BPP,END_FIX) +#define ZYWRLE_YMASK __RFB_CONCAT2E(ZYWRLE_YMASK,BPP) +#define ZYWRLE_UVMASK __RFB_CONCAT2E(ZYWRLE_UVMASK,BPP) +#define ZYWRLE_LOAD_PIXEL __RFB_CONCAT2E(ZYWRLE_LOAD_PIXEL,BPP) +#define ZYWRLE_SAVE_PIXEL __RFB_CONCAT2E(ZYWRLE_SAVE_PIXEL,BPP) + +/* Packing/Unpacking pixel stuffs. + Endian conversion stuffs. */ +#undef S_0 +#undef S_1 +#undef L_0 +#undef L_1 +#undef L_2 +#if ZYWRLE_ENDIAN == ENDIAN_BIG +# define S_0 1 +# define S_1 0 +# define L_0 3 +# define L_1 2 +# define L_2 1 +#else +# define S_0 0 +# define S_1 1 +# define L_0 0 +# define L_1 1 +# define L_2 2 +#endif + +/* Load/Save pixel stuffs. */ +#define ZYWRLE_YMASK15 0xFFFFFFF8 +#define ZYWRLE_UVMASK15 0xFFFFFFF8 +#define ZYWRLE_LOAD_PIXEL15(pSrc,R,G,B) { \ + R = (((unsigned char*)pSrc)[S_1]<< 1)& 0xF8; \ + G = ((((unsigned char*)pSrc)[S_1]<< 6)|(((unsigned char*)pSrc)[S_0]>> 2))& 0xF8; \ + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ +} +#define ZYWRLE_SAVE_PIXEL15(pDst,R,G,B) { \ + R &= 0xF8; \ + G &= 0xF8; \ + B &= 0xF8; \ + ((unsigned char*)pDst)[S_1] = (unsigned char)( (R>>1)|(G>>6) ); \ + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<2))& 0xFF); \ +} +#define ZYWRLE_YMASK16 0xFFFFFFFC +#define ZYWRLE_UVMASK16 0xFFFFFFF8 +#define ZYWRLE_LOAD_PIXEL16(pSrc,R,G,B) { \ + R = ((unsigned char*)pSrc)[S_1] & 0xF8; \ + G = ((((unsigned char*)pSrc)[S_1]<< 5)|(((unsigned char*)pSrc)[S_0]>> 3))& 0xFC; \ + B = (((unsigned char*)pSrc)[S_0]<< 3)& 0xF8; \ +} +#define ZYWRLE_SAVE_PIXEL16(pDst,R,G,B) { \ + R &= 0xF8; \ + G &= 0xFC; \ + B &= 0xF8; \ + ((unsigned char*)pDst)[S_1] = (unsigned char)( R |(G>>5) ); \ + ((unsigned char*)pDst)[S_0] = (unsigned char)(((B>>3)|(G<<3))& 0xFF); \ +} +#define ZYWRLE_YMASK32 0xFFFFFFFF +#define ZYWRLE_UVMASK32 0xFFFFFFFF +#define ZYWRLE_LOAD_PIXEL32(pSrc,R,G,B) { \ + R = ((unsigned char*)pSrc)[L_2]; \ + G = ((unsigned char*)pSrc)[L_1]; \ + B = ((unsigned char*)pSrc)[L_0]; \ +} +#define ZYWRLE_SAVE_PIXEL32(pDst,R,G,B) { \ + ((unsigned char*)pDst)[L_2] = (unsigned char)R; \ + ((unsigned char*)pDst)[L_1] = (unsigned char)G; \ + ((unsigned char*)pDst)[L_0] = (unsigned char)B; \ +} + +#ifndef ZYWRLE_ONCE +#define ZYWRLE_ONCE + +#ifdef WIN32 +#define InlineX __inline +#else +#define InlineX inline +#endif + +#ifdef ZYWRLE_ENCODE +/* Tables for Coefficients filtering. */ +# ifndef ZYWRLE_QUANTIZE +/* Type A:lower bit omitting of EZW style. */ +const static unsigned int zywrleParam[3][3]={ + {0x0000F000,0x00000000,0x00000000}, + {0x0000C000,0x00F0F0F0,0x00000000}, + {0x0000C000,0x00C0C0C0,0x00F0F0F0}, +/* {0x0000FF00,0x00000000,0x00000000}, + {0x0000FF00,0x00FFFFFF,0x00000000}, + {0x0000FF00,0x00FFFFFF,0x00FFFFFF}, */ +}; +# else +/* Type B:Non liner quantization filter. */ +static const signed char zywrleConv[4][256]={ +{ /* bi=5, bo=5 r=0.0:PSNR=24.849 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=5 r=2.0:PSNR=74.031 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 64, 64, 64, 64, + 64, 64, 64, 64, 72, 72, 72, 72, + 72, 72, 72, 72, 80, 80, 80, 80, + 80, 80, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 96, 96, + 96, 96, 96, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 0, -120, -120, -120, -120, -120, -120, -120, + -120, -120, -120, -112, -112, -112, -112, -112, + -112, -112, -112, -112, -104, -104, -104, -104, + -104, -104, -104, -104, -104, -104, -96, -96, + -96, -96, -96, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -80, + -80, -80, -80, -80, -80, -72, -72, -72, + -72, -72, -72, -72, -72, -64, -64, -64, + -64, -64, -64, -64, -64, -56, -56, -56, + -56, -56, -56, -56, -56, -56, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, -32, -32, -32, -32, -32, -32, -32, + -32, -32, -32, -32, -32, -32, -32, -32, + -32, -32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=4 r=2.0:PSNR=64.441 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 48, 48, 48, 48, 48, 48, 48, 48, + 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, + 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 120, 120, 120, 120, + 120, 120, 120, 120, 120, 120, 120, 120, + 0, -120, -120, -120, -120, -120, -120, -120, + -120, -120, -120, -120, -120, -112, -112, -112, + -112, -112, -112, -112, -112, -112, -104, -104, + -104, -104, -104, -104, -104, -104, -104, -104, + -104, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, + -80, -64, -64, -64, -64, -64, -64, -64, + -64, -64, -64, -64, -64, -64, -64, -64, + -64, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, -48, -48, -48, -48, -48, -48, -48, + -48, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +}, +{ /* bi=5, bo=2 r=2.0:PSNR=43.175 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, + 0, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, -88, -88, -88, -88, -88, -88, -88, + -88, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, +} +}; +const static signed char* zywrleParam[3][3][3]={ + {{zywrleConv[0],zywrleConv[2],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]},{zywrleConv[0],zywrleConv[0],zywrleConv[0]}}, + {{zywrleConv[0],zywrleConv[3],zywrleConv[0]},{zywrleConv[2],zywrleConv[2],zywrleConv[2]},{zywrleConv[1],zywrleConv[1],zywrleConv[1]}}, +}; +# endif +#endif + +static InlineX void Harr(signed char* pX0, signed char* pX1) +{ + /* Piecewise-Linear Harr(PLHarr) */ + int X0 = (int)*pX0, X1 = (int)*pX1; + int orgX0 = X0, orgX1 = X1; + if ((X0 ^ X1) & 0x80) { + /* differ sign */ + X1 += X0; + if (((X1^orgX1)&0x80)==0) { + /* |X1| > |X0| */ + X0 -= X1; /* H = -B */ + } + } else { + /* same sign */ + X0 -= X1; + if (((X0 ^ orgX0) & 0x80) == 0) { + /* |X0| > |X1| */ + X1 += X0; /* L = A */ + } + } + *pX0 = (signed char)X1; + *pX1 = (signed char)X0; +} +/* + 1D-Wavelet transform. + + In coefficients array, the famous 'pyramid' decomposition is well used. + + 1D Model: + |L0L0L0L0|L0L0L0L0|H0H0H0H0|H0H0H0H0| : level 0 + |L1L1L1L1|H1H1H1H1|H0H0H0H0|H0H0H0H0| : level 1 + + But this method needs line buffer because H/L is different position from X0/X1. + So, I used 'interleave' decomposition instead of it. + + 1D Model: + |L0H0L0H0|L0H0L0H0|L0H0L0H0|L0H0L0H0| : level 0 + |L1H0H1H0|L1H0H1H0|L1H0H1H0|L1H0H1H0| : level 1 + + In this method, H/L and X0/X1 is always same position. + This lead us to more speed and less memory. + Of cause, the result of both method is quite same + because it's only difference that coefficient position. +*/ +static InlineX void WaveletLevel(int* data, int size, int l, int SkipPixel) +{ + int s, ofs; + signed char* pX0; + signed char* end; + + pX0 = (signed char*)data; + s = (8<>(l+1))*s; + s -= 2; + ofs = (4<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + /* + these are same following code. + pH[x] = pH[x] / (~pM[x]+1) * (~pM[x]+1); + ( round pH[x] with pM[x] bit ) + '&' operator isn't 'round' but is 'floor'. + So, we must offset when pH[x] is negative. + */ + if (((signed char*)pH)[0] & 0x80) + ((signed char*)pH)[0] += ~((signed char*)pM)[0]; + if (((signed char*)pH)[1] & 0x80) + ((signed char*)pH)[1] += ~((signed char*)pM)[1]; + if (((signed char*)pH)[2] & 0x80) + ((signed char*)pH)[2] += ~((signed char*)pM)[2]; + *pH &= *pM; + pH += s; + } + pH += (s-1)*width; + } + } +} +# else +/* + Type B:Non liner quantization filter. + + Coefficients have Gaussian curve and smaller value which is + large part of coefficients isn't more important than larger value. + So, I use filter of Non liner quantize/dequantize table. + In general, Non liner quantize formula is explained as following. + + y=f(x) = sign(x)*round( ((abs(x)/(2^7))^ r )* 2^(bo-1) )*2^(8-bo) + x=f-1(y) = sign(y)*round( ((abs(y)/(2^7))^(1/r))* 2^(bi-1) )*2^(8-bi) + ( r:power coefficient bi:effective MSB in input bo:effective MSB in output ) + + r < 1.0 : Smaller value is more important than larger value. + r > 1.0 : Larger value is more important than smaller value. + r = 1.0 : Liner quantization which is same with EZW style. + + r = 0.75 is famous non liner quantization used in MP3 audio codec. + In contrast to audio data, larger value is important in wavelet coefficients. + So, I select r = 2.0 table( quantize is x^2, dequantize sqrt(x) ). + + As compared with EZW style liner quantization, this filter tended to be + more sharp edge and be more compression rate but be more blocking noise and be less quality. + Especially, the surface of graphic objects has distinguishable noise in middle quality mode. + + We need only quantized-dequantized(filtered) value rather than quantized value itself + because all values are packed or palette-lized in later ZRLE section. + This lead us not to need to modify client decoder when we change + the filtering procedure in future. + Client only decodes coefficients given by encoder. +*/ +static InlineX void FilterWaveletSquare(int* pBuf, int width, int height, int level, int l) +{ + int r, s; + int x, y; + int* pH; + const signed char** pM; + + pM = zywrleParam[level-1][l]; + s = 2<>1; + if (r & 0x02) + pH += (s>>1)*width; + for (y = 0; y < height / s; y++) { + for (x = 0; x < width / s; x++) { + ((signed char*)pH)[0] = pM[0][((unsigned char*)pH)[0]]; + ((signed char*)pH)[1] = pM[1][((unsigned char*)pH)[1]]; + ((signed char*)pH)[2] = pM[2][((unsigned char*)pH)[2]]; + pH += s; + } + pH += (s-1)*width; + } + } +} +# endif + +static InlineX void Wavelet(int* pBuf, int width, int height, int level) +{ + int l, s; + int* pTop; + int* pEnd; + + for (l = 0; l < level; l++) { + pTop = pBuf; + pEnd = pBuf+height*width; + s = width<= 0; l--) { + pTop = pBuf; + pEnd = pBuf+width; + s = 1< YUV conversion stuffs. + YUV coversion is explained as following formula in strict meaning: + Y = 0.299R + 0.587G + 0.114B ( 0<=Y<=255) + U = -0.169R - 0.331G + 0.500B (-128<=U<=127) + V = 0.500R - 0.419G - 0.081B (-128<=V<=127) + + I use simple conversion RCT(reversible color transform) which is described + in JPEG-2000 specification. + Y = (R + 2G + B)/4 ( 0<=Y<=255) + U = B-G (-256<=U<=255) + V = R-G (-256<=V<=255) +*/ +#define ROUND(x) (((x)<0)?0:(((x)>255)?255:(x))) + /* RCT is N-bit RGB to N-bit Y and N+1-bit UV. + For make Same N-bit, UV is lossy. + More exact PLHarr, we reduce to odd range(-127<=x<=127). */ +#define ZYWRLE_RGBYUV1(R,G,B,Y,U,V,ymask,uvmask) { \ + Y = (R+(G<<1)+B)>>2; \ + U = B-G; \ + V = R-G; \ + Y -= 128; \ + U >>= 1; \ + V >>= 1; \ + Y &= ymask; \ + U &= uvmask; \ + V &= uvmask; \ + if (Y == -128) \ + Y += (0xFFFFFFFF-ymask+1); \ + if (U == -128) \ + U += (0xFFFFFFFF-uvmask+1); \ + if (V == -128) \ + V += (0xFFFFFFFF-uvmask+1); \ +} +#define ZYWRLE_YUVRGB1(R,G,B,Y,U,V) { \ + Y += 128; \ + U <<= 1; \ + V <<= 1; \ + G = Y-((U+V)>>2); \ + B = U+G; \ + R = V+G; \ + G = ROUND(G); \ + B = ROUND(B); \ + R = ROUND(R); \ +} + +/* + coefficient packing/unpacking stuffs. + Wavelet transform makes 4 sub coefficient image from 1 original image. + + model with pyramid decomposition: + +------+------+ + | | | + | L | Hx | + | | | + +------+------+ + | | | + | H | Hxy | + | | | + +------+------+ + + So, we must transfer each sub images individually in strict meaning. + But at least ZRLE meaning, following one decompositon image is same as + avobe individual sub image. I use this format. + (Strictly saying, transfer order is reverse(Hxy->Hy->Hx->L) + for simplified procedure for any wavelet level.) + + +------+------+ + | L | + +------+------+ + | Hx | + +------+------+ + | Hy | + +------+------+ + | Hxy | + +------+------+ +*/ +#define INC_PTR(data) \ + data++; \ + if( data-pData >= (w+uw) ){ \ + data += scanline-(w+uw); \ + pData = data; \ + } + +#define ZYWRLE_TRANSFER_COEFF(pBuf,data,r,w,h,scanline,level,TRANS) \ + pH = pBuf; \ + s = 2<>1; \ + if (r & 0x02) \ + pH += (s>>1)*w; \ + pEnd = pH+h*w; \ + while (pH < pEnd) { \ + pLine = pH+w; \ + while (pH < pLine) { \ + TRANS \ + INC_PTR(data) \ + pH += s; \ + } \ + pH += (s-1)*w; \ + } + +#define ZYWRLE_PACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_COEFF(pH,R,G,B);ZYWRLE_SAVE_PIXEL(data,R,G,B);) + +#define ZYWRLE_UNPACK_COEFF(pBuf,data,r,width,height,scanline,level) \ + ZYWRLE_TRANSFER_COEFF(pBuf,data,r,width,height,scanline,level,ZYWRLE_LOAD_PIXEL(data,R,G,B);ZYWRLE_SAVE_COEFF(pH,R,G,B);) + +#define ZYWRLE_SAVE_UNALIGN(data,TRANS) \ + pTop = pBuf+w*h; \ + pEnd = pBuf + (w+uw)*(h+uh); \ + while (pTop < pEnd) { \ + TRANS \ + INC_PTR(data) \ + pTop++; \ + } + +#define ZYWRLE_LOAD_UNALIGN(data,TRANS) \ + pTop = pBuf+w*h; \ + if (uw) { \ + pData= data + w; \ + pEnd = (int*)(pData+ h*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + uw); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-uw; \ + } \ + } \ + if (uh) { \ + pData= data + h*scanline; \ + pEnd = (int*)(pData+ uh*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + w); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-w; \ + } \ + } \ + if (uw && uh) { \ + pData= data + w+ h*scanline; \ + pEnd = (int*)(pData+ uh*scanline); \ + while (pData < (PIXEL_T*)pEnd) { \ + pLine = (int*)(pData + uw); \ + while (pData < (PIXEL_T*)pLine) { \ + TRANS \ + pData++; \ + pTop++; \ + } \ + pData += scanline-uw; \ + } \ + } + +static InlineX void zywrleCalcSize(int* pW, int* pH, int level) +{ + *pW &= ~((1<, 1996 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program 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 program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +basename="s,^.*/,,g" + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + +# The name of this program: +progname=`echo "$progpath" | $SED $basename` +modename="$progname" + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 + +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.5.22 +TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)" + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes. +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$progpath" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +duplicate_deps=no +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +##################################### +# Shell function definitions: +# This seems to be the best place for them + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $mkdir "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || { + $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2 + exit $EXIT_FAILURE + } + fi + + $echo "X$my_tmpdir" | $Xsed +} + + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +func_win32_libid () +{ + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \ + $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + win32_nmres=`eval $NM -f posix -A $1 | \ + $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $echo $win32_libid_type +} + + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + CC_quoted="$CC_quoted $arg" + done + case "$@ " in + " $CC "* | "$CC "* | " `$echo $CC` "* | "`$echo $CC` "* | " $CC_quoted"* | "$CC_quoted "* | " `$echo $CC_quoted` "* | "`$echo $CC_quoted` "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + $echo "$modename: unable to infer tagged configuration" + $echo "$modename: specify a tag with \`--tag'" 1>&2 + exit $EXIT_FAILURE +# else +# $echo "$modename: using $tagname tagged configuration" + fi + ;; + esac + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + + $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)" + $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $? + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2 + exit $EXIT_FAILURE + fi +} + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + my_status="" + + $show "${rm}r $my_gentop" + $run ${rm}r "$my_gentop" + $show "$mkdir $my_gentop" + $run $mkdir "$my_gentop" + my_status=$? + if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then + exit $my_status + fi + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'` + my_xdir="$my_gentop/$my_xlib" + + $show "${rm}r $my_xdir" + $run ${rm}r "$my_xdir" + $show "$mkdir $my_xdir" + $run $mkdir "$my_xdir" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then + exit $exit_status + fi + case $host in + *-darwin*) + $show "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + if test -z "$run"; then + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'` + darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null` + if test -n "$darwin_arches"; then + darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + $show "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we have a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + lipo -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + ${rm}r unfat-$$ + cd "$darwin_orig_dir" + else + cd "$darwin_orig_dir" + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + fi # $run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + done + func_extract_archives_result="$my_oldobjs" +} +# End of Shell function definitions +##################################### + +# Darwin sucks +eval std_shrext=\"$shrext_cmds\" + +disable_libs=no + +# Parse our command line options once, thoroughly. +while test "$#" -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + tag) + tagname="$arg" + preserve_args="${preserve_args}=$arg" + + # Check whether tagname contains only valid characters + case $tagname in + *[!-_A-Za-z0-9,/]*) + $echo "$progname: invalid tag name: $tagname" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $tagname in + CC) + # Don't test for the "default" C tag, as we know, it's there, but + # not specially marked. + ;; + *) + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "$progpath" > /dev/null; then + taglist="$taglist $tagname" + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$tagname'$/,/^# ### END LIBTOOL TAG CONFIG: '$tagname'$/p' < $progpath`" + else + $echo "$progname: ignoring unknown tag $tagname" 1>&2 + fi + ;; + esac + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + $echo + $echo "Copyright (C) 2005 Free Software Foundation, Inc." + $echo "This is free software; see the source for copying conditions. There is NO" + $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + exit $? + ;; + + --config) + ${SED} -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $progpath + # Now print the configurations for the tags. + for tagname in $taglist; do + ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath" + done + exit $? + ;; + + --debug) + $echo "$progname: enabling shell trace mode" + set -x + preserve_args="$preserve_args $arg" + ;; + + --dry-run | -n) + run=: + ;; + + --features) + $echo "host: $host" + if test "$build_libtool_libs" = yes; then + $echo "enable shared libraries" + else + $echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + $echo "enable static libraries" + else + $echo "disable static libraries" + fi + exit $? + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + preserve_args="$preserve_args $arg" + ;; + + --tag) + prevopt="--tag" + prev=tag + preserve_args="$preserve_args --tag" + ;; + --tag=*) + set tag "$optarg" ${1+"$@"} + shift + prev=tag + preserve_args="$preserve_args --tag" + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE +fi + +case $disable_libs in +no) + ;; +shared) + build_libtool_libs=no + build_old_libs=yes + ;; +static) + build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` + ;; +esac + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2 + $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2 + case $nonopt in + *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + if test -n "$libobj" ; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit $EXIT_FAILURE + fi + arg_mode=target + continue + ;; + + -static | -prefer-pic | -prefer-non-pic) + later="$later $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + base_compile="$base_compile $lastarg" + continue + ;; + + * ) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + case $lastarg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, and some SunOS ksh mistreat backslash-escaping + # in scan sets (worked around with variable expansion), + # and furthermore cannot handle '|' '&' '(' ')' in scan sets + # at all, so we specify them separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + base_compile="$base_compile $lastarg" + done # for arg + + case $arg_mode in + arg) + $echo "$modename: you must specify an argument for -Xcompile" + exit $EXIT_FAILURE + ;; + target) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit $EXIT_FAILURE + ;; + *) + # Get the name of the library object. + [ -z "$libobj" ] && libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSifmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.ii) xform=ii ;; + *.class) xform=class ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + *.java) xform=java ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"` + case $qlibobj in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qlibobj="\"$qlibobj\"" ;; + esac + test "X$libobj" != "X$qlibobj" \ + && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && $echo "$modename: libobj name \`$libobj' may not contain shell special characters." + objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir= + else + xdir=$xdir/ + fi + lobj=${xdir}$objdir/$objname + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit $EXIT_FAILURE" 1 2 15 + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$progpath" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + $echo "$srcfile" > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"` + case $qsrcfile in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qsrcfile="\"$qsrcfile\"" ;; + esac + + $run $rm "$libobj" "${libobj}T" + + # Create a libtool object file (analogous to a ".la" file), + # but don't create it if we're doing a dry run. + test -z "$run" && cat > ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + $show "$mv $output_obj $lobj" + if $run $mv $output_obj $lobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the PIC object to the libtool object file. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T </dev/null`" != "X$srcfile"; then + $echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Append the name of the non-PIC object the libtool object file. + # Only append if the libtool object file exists. + test -z "$run" && cat >> ${libobj}T <> ${libobj}T <&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + fi + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit $EXIT_FAILURE + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat $save_arg` + do +# moreargs="$moreargs $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + done + else + $echo "$modename: link input file \`$save_arg' does not exist" + exit $EXIT_FAILURE + fi + arg=$save_arg + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + xcclinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + darwin_framework|darwin_framework_skip) + test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + prev= + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit $EXIT_FAILURE + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework|-arch|-isysroot) + case " $CC " in + *" ${arg} ${1} "* | *" ${arg} ${1} "*) + prev=darwin_framework_skip ;; + *) compiler_flags="$compiler_flags $arg" + prev=darwin_framework ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + notinst_path="$notinst_path $dir" + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + deplibs="$deplibs -framework System" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + -model) + compile_command="$compile_command $arg" + compiler_flags="$compiler_flags $arg" + finalize_command="$finalize_command $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + compiler_flags="$compiler_flags $arg" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # -64, -mips[0-9] enable 64-bit mode on the SGI compiler + # -r[0-9][0-9]* specifies the processor on the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler + # +DA*, +DD* enable 64-bit mode on the HP compiler + # -q* pass through compiler args for the IBM compiler + # -m* pass through architecture-specific compiler args for GCC + # -m*, -t[45]*, -txscale* pass through architecture-specific + # compiler args for GCC + # -pg pass through profiling flag for GCC + # @file GCC response files + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \ + -t[45]*|-txscale*|@*) + + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + compiler_flags="$compiler_flags $arg" + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit $EXIT_FAILURE + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.$objext) + # A standard object. + objs="$objs $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if (${SED} -e '2q' $arg | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + pic_object= + non_pic_object= + + # Read the .lo file + # If there is no directory component, then add one. + case $arg in + */* | *\\*) . $arg ;; + *) . ./$arg ;; + esac + + if test -z "$pic_object" || \ + test -z "$non_pic_object" || + test "$pic_object" = none && \ + test "$non_pic_object" = none; then + $echo "$modename: cannot find name of object for \`$arg'" 1>&2 + exit $EXIT_FAILURE + fi + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles $pic_object" + prev= + fi + + # A PIC object. + libobjs="$libobjs $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + non_pic_objects="$non_pic_objects $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if test -z "$run"; then + $echo "$modename: \`$arg' is not a valid libtool object" 1>&2 + exit $EXIT_FAILURE + else + # Dry-run case. + + # Extract subdirectory from the argument. + xdir=`$echo "X$arg" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$arg"; then + xdir= + else + xdir="$xdir/" + fi + + pic_object=`$echo "X${xdir}${objdir}/${arg}" | $Xsed -e "$lo2o"` + non_pic_object=`$echo "X${xdir}${arg}" | $Xsed -e "$lo2o"` + libobjs="$libobjs $pic_object" + non_pic_objects="$non_pic_objects $non_pic_object" + fi + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then + exit $exit_status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + case $host in + *cygwin* | *mingw* | *pw32*) + # don't eliminate duplications in $postdeps and $predeps + duplicate_compiler_generated_deps=yes + ;; + *) + duplicate_compiler_generated_deps=$duplicate_deps + ;; + esac + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_compiler_generated_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + compiler_flags="$compiler_flags $deplib" + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2 + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if (${SED} -e '2q' $lib | + grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + library_names= + old_library= + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + if eval $echo \"$deplib\" 2>/dev/null \ + | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + $echo + $echo "*** Warning: Trying to link with static lib archive $deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because the file extensions .$libext of this argument makes me believe" + $echo "*** that it is just a static archive that I should not used here." + else + $echo + $echo "*** Warning: Linking the shared library $output against the" + $echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2 + exit $EXIT_FAILURE + fi + + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $lib | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit $EXIT_FAILURE + fi + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + dlprefiles="$dlprefiles $lib $dependency_libs" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit $EXIT_FAILURE + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $absdir" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes ; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + # This is a shared library + + # Warn about portability, can't link against -module's on + # some systems (darwin) + if test "$shouldnotlink" = yes && test "$pass" = link ; then + $echo + if test "$linkmode" = prog; then + $echo "*** Warning: Linking the executable $output against the loadable module" + else + $echo "*** Warning: Linking the shared library $output against the loadable module" + fi + $echo "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`$echo $soroot | ${SED} -e 's/^.*\///'` + newlib="libimp-`$echo $soname | ${SED} 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$extract_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + cmds=$old_archive_from_expsyms_cmds + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a module then we can not link against + # it, someone is ignoring the new warnings I added + if /usr/bin/file -L $add 2> /dev/null | + $EGREP ": [^:]* bundle" >/dev/null ; then + $echo "** Warning, lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + $echo + $echo "** And there doesn't seem to be a static archive available" + $echo "** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit $EXIT_FAILURE + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + add_dir="$add_dir -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + $echo + $echo "*** Warning: This system can not link to static lib archive $lib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + $echo "*** But as you try to build a module library, libtool will still create " + $echo "*** a static module, that should work as long as the dlopening application" + $echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="$absdir/$objdir" + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="$absdir" + fi + depdepl= + case $host in + *-*-darwin*) + # we do not want to link against static libs, + # but need to link against shared + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$path/$depdepl" ; then + depdepl="$path/$depdepl" + fi + # do not add paths which are already there + case " $newlib_search_path " in + *" $path "*) ;; + *) newlib_search_path="$newlib_search_path $path";; + esac + fi + path="" + ;; + *) + path="-L$path" + ;; + esac + ;; + -l*) + case $host in + *-*-darwin*) + # Again, we only want to link against shared libraries + eval tmp_libs=`$echo "X$deplib" | $Xsed -e "s,^\-l,,"` + for tmp in $newlib_search_path ; do + if test -f "$tmp/lib$tmp_libs.dylib" ; then + eval depdepl="$tmp/lib$tmp_libs.dylib" + break + fi + done + path="" + ;; + *) continue ;; + esac + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + case " $deplibs " in + *" $depdepl "*) ;; + *) deplibs="$depdepl $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + tmp_libs="$tmp_libs $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for archives" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit $EXIT_FAILURE + else + $echo + $echo "*** Warning: Linking the shared library $output against the non-libtool" + $echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info/-version-number' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$2" + number_minor="$3" + number_revision="$4" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows) + current=`expr $number_major + $number_minor` + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + current=`expr $number_major + $number_minor - 1` + age="$number_minor" + revision="$number_minor" + ;; + esac + ;; + no) + current="$2" + revision="$3" + age="$4" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit $EXIT_FAILURE + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix | nonstopux) + major=`expr $current - $age + 1` + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=.`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + $echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$echo "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if echo $p | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + removelist="$removelist $p" + ;; + *) ;; + esac + done + if test -n "$removelist"; then + $show "${rm}r $removelist" + $run ${rm}r $removelist + fi + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"` + deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"` + dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c </dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for file magic test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a file magic. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name=`expr $a_deplib : '-l\(.*\)'` + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval $echo \"$potent_lib\" 2>/dev/null \ + | ${SED} 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + $echo + $echo "*** Warning: linker path does not have real file for library $a_deplib." + $echo "*** I have the capability to make that library automatically link in when" + $echo "*** you link to this library. But I can only do this if you have a" + $echo "*** shared version of the library, which you do not appear to have" + $echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $echo "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $echo "*** with $libname and none of the candidates passed a file format test" + $echo "*** using a regex pattern. Last file checked: $potlib" + fi + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$echo "X $tmp_deplibs" | ${SED} -e "1s,^X,," -e "s,$i,,"` + done + fi + if $echo "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' \ + | grep . >/dev/null; then + $echo + if test "X$deplibs_check_method" = "Xnone"; then + $echo "*** Warning: inter-library dependencies are not supported in this platform." + else + $echo "*** Warning: inter-library dependencies are not known to be supported." + fi + $echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + $echo + $echo "*** Warning: libtool could not satisfy all declared inter-library" + $echo "*** dependencies of module $libname. Therefore, libtool will create" + $echo "*** a static module, that should work as long as the dlopening" + $echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + $echo + $echo "*** However, this would only work if libtool was able to extract symbol" + $echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + $echo "*** not find such a program. So, this module is probably useless." + $echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + $echo "*** The inter-library dependencies that have been dropped here will be" + $echo "*** automatically added whenever a program is linked with this library" + $echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + $echo + $echo "*** Since this library must not contain undefined symbols," + $echo "*** because either the platform does not support them or" + $echo "*** it was explicitly requested with -no-undefined," + $echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + deplibs="$new_libs" + + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + linknames="$linknames $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + if len=`expr "X$cmd" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + $show "$cmd" + $run eval "$cmd" || exit $? + skipped_export=false + else + # The command line is too long to execute in one step. + $show "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "$EGREP -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + tmp_deplibs="$tmp_deplibs $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + libobjs="$libobjs $func_extract_archives_result" + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise. + $echo "creating reloadable object files..." + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + output_la=`$echo "X$output" | $Xsed -e "$basename"` + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + delfiles= + last_robj= + k=1 + output=$output_objdir/$output_la-${k}.$objext + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + eval test_cmds=\"$reload_cmds $objlist $last_robj\" + if test "X$objlist" = X || + { len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; }; then + objlist="$objlist $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + else + # All subsequent reloadable object files will link in + # the last one created. + eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + k=`expr $k + 1` + output=$output_objdir/$output_la-${k}.$objext + objlist=$obj + len=1 + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + + if ${skipped_export-false}; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + libobjs=$output + # Append the command to create the export file. + eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\" + fi + + # Set up a command to remove the reloadable object files + # after they are used. + i=0 + while test "$i" -lt "$k" + do + i=`expr $i + 1` + delfiles="$delfiles $output_objdir/$output_la-${i}.$objext" + done + + $echo "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + + # Append the command to remove the reloadable object files + # to the just-reset $cmds. + eval cmds=\"\$cmds~\$rm $delfiles\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit $EXIT_FAILURE + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + generated="$generated $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $run eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + cmds=$reload_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) output=`$echo $output | ${SED} -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + case $host in + *darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + if test "$tagname" = CXX ; then + compile_command="$compile_command ${wl}-bind_at_load" + finalize_command="$finalize_command ${wl}-bind_at_load" + fi + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + new_libs="$new_libs -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$new_libs $deplib" ;; + esac + ;; + *) new_libs="$new_libs $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + *) dllsearchpath="$dllsearchpath:$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $run $rm $export_symbols + $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + else + $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* ) + $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`$echo "$arg" | ${SED} -e 's%^.*/%%'` + $run eval '$echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + $echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +" + + case $host in + *cygwin* | *mingw* ) + $echo >> "$output_objdir/$dlsyms" "\ +/* DATA imports from DLLs on WIN32 can't be const, because + runtime relocations are performed -- see ld's documentation + on pseudo-relocs */ +struct { +" + ;; + * ) + $echo >> "$output_objdir/$dlsyms" "\ +const struct { +" + ;; + esac + + + $echo >> "$output_objdir/$dlsyms" "\ + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $LTCC $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + case $host in + *cygwin* | *mingw* ) + if test -f "$output_objdir/${outputname}.def" ; then + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%"` + else + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + fi + ;; + * ) + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + esac + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit $EXIT_FAILURE + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + exit_status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $exit_status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $progpath --fallback-echo"; then + case $progpath in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; + *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`$echo $output|${SED} 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + outputname=`$echo $outputname|${SED} 's,.exe$,,'` ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + output_name=`basename $output` + output_path=`dirname $output` + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $rm $cwrappersource $cwrapper + trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + cat > $cwrappersource <> $cwrappersource<<"EOF" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +/* -DDEBUG is fairly common in CFLAGS. */ +#undef DEBUG +#if defined DEBUGWRAPPER +# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__) +#else +# define DEBUG(format, ...) +#endif + +const char *program_name = NULL; + +void * xmalloc (size_t num); +char * xstrdup (const char *string); +const char * base_name (const char *name); +char * find_executable(const char *wrapper); +int check_executable(const char *path); +char * strendzap(char *str, const char *pat); +void lt_fatal (const char *message, ...); + +int +main (int argc, char *argv[]) +{ + char **newargz; + int i; + + program_name = (char *) xstrdup (base_name (argv[0])); + DEBUG("(main) argv[0] : %s\n",argv[0]); + DEBUG("(main) program_name : %s\n",program_name); + newargz = XMALLOC(char *, argc+2); +EOF + + cat >> $cwrappersource <> $cwrappersource <<"EOF" + newargz[1] = find_executable(argv[0]); + if (newargz[1] == NULL) + lt_fatal("Couldn't find %s", argv[0]); + DEBUG("(main) found exe at : %s\n",newargz[1]); + /* we know the script has the same name, without the .exe */ + /* so make sure newargz[1] doesn't end in .exe */ + strendzap(newargz[1],".exe"); + for (i = 1; i < argc; i++) + newargz[i+1] = xstrdup(argv[i]); + newargz[argc+1] = NULL; + + for (i=0; i> $cwrappersource <> $cwrappersource <> $cwrappersource <<"EOF" + return 127; +} + +void * +xmalloc (size_t num) +{ + void * p = (void *) malloc (num); + if (!p) + lt_fatal ("Memory exhausted"); + + return p; +} + +char * +xstrdup (const char *string) +{ + return string ? strcpy ((char *) xmalloc (strlen (string) + 1), string) : NULL +; +} + +const char * +base_name (const char *name) +{ + const char *base; + +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + /* Skip over the disk name in MSDOS pathnames. */ + if (isalpha ((unsigned char)name[0]) && name[1] == ':') + name += 2; +#endif + + for (base = name; *name; name++) + if (IS_DIR_SEPARATOR (*name)) + base = name + 1; + return base; +} + +int +check_executable(const char * path) +{ + struct stat st; + + DEBUG("(check_executable) : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!"); + if ((!path) || (!*path)) + return 0; + + if ((stat (path, &st) >= 0) && + ( + /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */ +#if defined (S_IXOTH) + ((st.st_mode & S_IXOTH) == S_IXOTH) || +#endif +#if defined (S_IXGRP) + ((st.st_mode & S_IXGRP) == S_IXGRP) || +#endif + ((st.st_mode & S_IXUSR) == S_IXUSR)) + ) + return 1; + else + return 0; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise */ +char * +find_executable (const char* wrapper) +{ + int has_slash = 0; + const char* p; + const char* p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char* concat_name; + + DEBUG("(find_executable) : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!"); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char* path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char* q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR(*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal ("getcwd failed"); + tmp_len = strlen(tmp); + concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable(concat_name)) + return concat_name; + XFREE(concat_name); + return NULL; +} + +char * +strendzap(char *str, const char *pat) +{ + size_t len, patlen; + + assert(str != NULL); + assert(pat != NULL); + + len = strlen(str); + patlen = strlen(pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp(str, pat) == 0) + *str = '\0'; + } + return str; +} + +static void +lt_error_core (int exit_status, const char * mode, + const char * message, va_list ap) +{ + fprintf (stderr, "%s: %s: ", program_name, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + va_end (ap); +} +EOF + # we should really use a build-platform specific compiler + # here, but OTOH, the wrappers (shell script and this C one) + # are only useful if you want to execute the "real" binary. + # Since the "real" binary is built for $host, then this + # wrapper might as well be built for $host, too. + $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource + ;; + esac + $rm $output + trap "$rm $output; exit $EXIT_FAILURE" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='${SED} -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + $echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit $EXIT_FAILURE + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + $echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit $EXIT_FAILURE + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + $echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit $EXIT_FAILURE + fi +fi\ +" + chmod +x $output + fi + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + func_extract_archives $gentop $addlibs + oldobjs="$oldobjs $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + $echo "X$obj" | $Xsed -e 's%^.*/%%' + done | sort | sort -uc >/dev/null 2>&1); then + : + else + $echo "copying selected object files to avoid basename conflicts..." + + if test -z "$gentop"; then + gentop="$output_objdir/${outputname}x" + generated="$generated $gentop" + + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "$mkdir $gentop" + $run $mkdir "$gentop" + exit_status=$? + if test "$exit_status" -ne 0 && test ! -d "$gentop"; then + exit $exit_status + fi + fi + + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + counter=`expr $counter + 1` + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + $run ln "$obj" "$gentop/$newobj" || + $run cp "$obj" "$gentop/$newobj" + oldobjs="$oldobjs $gentop/$newobj" + ;; + *) oldobjs="$oldobjs $obj" ;; + esac + done + fi + + eval cmds=\"$old_archive_cmds\" + + if len=`expr "X$cmds" : ".*"` && + test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + $echo "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + for obj in $save_oldobjs + do + oldobjs="$objlist $obj" + objlist="$objlist $obj" + eval test_cmds=\"$old_archive_cmds\" + if len=`expr "X$test_cmds" : ".*" 2>/dev/null` && + test "$len" -le "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + eval cmd=\"$cmd\" + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit $EXIT_FAILURE + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlfiles="$newdlfiles $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + newdlprefiles="$newdlprefiles $abs" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit $EXIT_SUCCESS + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + case " $install_prog " in + *[\\\ /]cp\ *) ;; + *) prev=$arg ;; + esac + ;; + -g | -m | -o) prev=$arg ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | $SED "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit $EXIT_FAILURE + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit $EXIT_FAILURE + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + cmds=$postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)' + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + file=`$echo $file|${SED} 's,.exe$,,'` + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin*|*mingw*) + wrapper=`$echo $file | ${SED} -e 's,.exe$,,'` + ;; + *) + wrapper=$file + ;; + esac + if (${SED} -e '4q' $wrapper | grep "^# Generated by .*$PACKAGE")>/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$wrapper'" 1>&2 + exit $EXIT_FAILURE + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # Note that it is not necessary on cygwin/mingw to append a dot to + # foo even if both foo and FILE.exe exist: automatic-append-.exe + # behavior happens only for exec(3), not for open(2)! Also, sourcing + # `FILE.' does not work on cygwin managed mounts. + # + # If there is no directory component, then add one. + case $wrapper in + */* | *\\*) . ${wrapper} ;; + *) . ./${wrapper} ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir=`func_mktempdir` + file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`$echo $destfile | ${SED} -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$old_striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + cmds=$old_postinstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + cmds=$finish_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit $EXIT_SUCCESS + + $echo "X----------------------------------------------------------------------" | $Xsed + $echo "Libraries have been installed in:" + for libdir in $libdirs; do + $echo " $libdir" + done + $echo + $echo "If you ever happen to want to link against installed libraries" + $echo "in a given directory, LIBDIR, you must either use libtool, and" + $echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + $echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + $echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + $echo " during execution" + fi + if test -n "$runpath_var"; then + $echo " - add LIBDIR to the \`$runpath_var' environment variable" + $echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + $echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + $echo + $echo "See any operating system documentation about shared libraries for" + $echo "more information, such as the ld(1) and ld.so(8) manual pages." + $echo "X----------------------------------------------------------------------" | $Xsed + exit $EXIT_SUCCESS + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit $EXIT_FAILURE + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit $EXIT_FAILURE + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit $EXIT_SUCCESS + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + fi + + rmdirs= + + origobjdir="$objdir" + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$origobjdir" + else + objdir="$dir/$origobjdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + + case "$mode" in + clean) + case " $library_names " in + # " " in the beginning catches empty $dlname + *" $dlname "*) ;; + *) rmfiles="$rmfiles $objdir/$dlname" ;; + esac + test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + cmds=$postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + cmds=$old_postuninstall_cmds + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if (${SED} -e '2q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + + # Read the .lo file + . $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" \ + && test "$pic_object" != none; then + rmfiles="$rmfiles $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" \ + && test "$non_pic_object" != none; then + rmfiles="$rmfiles $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$mode" = clean ; then + noexename=$name + case $file in + *.exe) + file=`$echo $file|${SED} 's,.exe$,,'` + noexename=`$echo $name|${SED} 's,.exe$,,'` + # $file with .exe has already been added to rmfiles, + # add $file without .exe + rmfiles="$rmfiles $file" + ;; + esac + # Do a test to see if this is a libtool program. + if (${SED} -e '4q' $file | grep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$noexename + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + rmfiles="$rmfiles $objdir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + objdir="$origobjdir" + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit $EXIT_FAILURE + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit $EXIT_FAILURE +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --tag=TAG use configuration variables from tag TAG + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE. + +Report bugs to ." + exit $EXIT_SUCCESS + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit $EXIT_FAILURE + ;; +esac + +$echo +$echo "Try \`$modename --help' for more information about other modes." + +exit $? + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +disable_libs=shared +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +disable_libs=static +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh b/droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh new file mode 100755 index 0000000..e28ea6d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/prepare_x11vnc_dist.sh @@ -0,0 +1,136 @@ +#!/bin/bash + +VERSION="0.9.11" + +cd "$(dirname "$0")" + +mv configure.ac configure.ac.LibVNCServer + +cat configure.ac.LibVNCServer | \ +egrep -v '(AC_CONFIG_COMMANDS|chmod).*libvncserver-config' | \ +egrep -v '^[ ]*libvncserver-config$' | \ +sed -e "s/LibVNCServer, [^,)]*\([(,]\)*/x11vnc, $VERSION\1/g" \ + -e "s/\(contrib\|examples\|vncterm\|test\|client_examples\)\/Makefile//g" \ + -e "s/LibVNCServer.spec/x11vnc.spec/g" \ + -e "s/AC_PROG_LIBTOOL/AC_PROG_RANLIB/" \ + -e "s/PKG_CHECK/#PKG_CHECK/" \ + -e 's/if test "x$with_gnutls/with_gnutls=no; if test "x$with_gnutls/' \ +> configure.ac + +mv Makefile.am Makefile.am.LibVNCServer + +echo "EXTRA_DIST=tightvnc-1.3dev5-vncviewer-alpha-cursor.patch README.LibVNCServer" > Makefile.am +echo "" >> Makefile.am +echo "if HAVE_SYSTEM_LIBVNCSERVER" >> Makefile.am +echo "SUBDIRS=x11vnc classes" >> Makefile.am +echo "DIST_SUBDIRS=x11vnc classes" >> Makefile.am +echo "else" >> Makefile.am +echo "SUBDIRS=libvncserver libvncclient x11vnc classes" >> Makefile.am +echo "DIST_SUBDIRS=libvncserver libvncclient x11vnc classes" >> Makefile.am +echo "endif" >> Makefile.am +echo "" >> Makefile.am + +cat Makefile.am.LibVNCServer | \ +sed -e "s/^SUBDIRS.*$/#SUBDIRS=libvncserver libvncclient x11vnc classes/" \ + -e "s/^DIST_SUBDIRS.*$/#DIST_SUBDIRS=libvncserver libvncclient x11vnc classes/" \ + -e "/all: make_config_executable/,\$d" \ + -e "/^.*bin_SCRIPTS.*$/d" \ + -e "s/include_/noinst_/" \ +>> Makefile.am + +mv README README.LibVNCServer +cp x11vnc/README ./README + +cat LibVNCServer.spec.in | \ +sed -e "s/Johannes.Schindelin@gmx.de/runge@karlrunge.com/gi" \ + -e "s/Johannes.Schindelin/Karl Runge/g" \ + -e "s/a library to make writing a vnc server easy/a VNC server for the current X11 session/" \ + -e "/^%description$/,/%description devel$/d" \ + -e 's/^Static libraries.*$/%description\ +x11vnc is to X Window System what WinVNC is to Windows, i.e. a server\ +which serves the current Xwindows desktop via RFB (VNC) protocol\ +to the user.\ +\ +Based on the ideas of x0rfbserver and on LibVNCServer, it has evolved\ +into a versatile and performant while still easy to use program.\ +\ +x11vnc was put together and is (actively ;-) maintained by\ +Karl Runge \ +\ +/i' \ +> x11vnc.spec.in.tmp + +perl -e ' + $s = 0; + while (<>) { + if ($s) { + if (/^\s*$/) { + $s = 0; + } + } else { + if (/^%files\s*$/ || /^%files devel/) { + $s = 1; + } + } + next if $s; + if (/^%files x11vnc/) { + print "\%files\n"; + print "\%doc README x11vnc/ChangeLog\n"; + next; + } + print; + }' < x11vnc.spec.in.tmp > x11vnc.spec.in + +rm -f x11vnc.spec.in.tmp + +mv libvncserver/Makefile.am libvncserver/Makefile.am.LibVNCServer + +cat libvncserver/Makefile.am.LibVNCServer | \ +sed -e "s/\(include\|LIB\|lib\)_/noinst_/g" \ + -e "s/_la_/_a_/" \ + -e "s/\.la/.a/" \ + -e "s/_LTLIBRARIES/_LIBRARIES/" \ +> libvncserver/Makefile.am + +mv libvncclient/Makefile.am libvncclient/Makefile.am.LibVNCServer + +cat libvncclient/Makefile.am.LibVNCServer | \ +sed -e "s/\(include\|LIB\|lib\)_/noinst_/g" \ + -e "s/_la_/_a_/" \ + -e "s/\.la/.a/" \ + -e "s/_LTLIBRARIES/_LIBRARIES/" \ +> libvncclient/Makefile.am + +mv x11vnc/Makefile.am x11vnc/Makefile.am.LibVNCServer + +cat x11vnc/Makefile.am.LibVNCServer | \ +sed -e "s/_la_/_a_/" \ + -e "s/\.la/.a/g" \ + -e "s/_LTLIBRARIES/_LIBRARIES/" \ +> x11vnc/Makefile.am + + +cp classes/Makefile.am classes/Makefile.am.LibVNCServer +echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes' >> classes/Makefile.am +echo 'pkgdata_DATA=VncViewer.jar index.vnc' >> classes/Makefile.am + +cp classes/ssl/Makefile.am classes/ssl/Makefile.am.LibVNCServer +sed -e 's/EXTRA_DIST=/EXTRA_DIST=tightvnc-1.3dev7_javasrc-vncviewer-ssl.patch tightvnc-1.3dev7_javasrc-vncviewer-cursor-colors+no-tab-traversal.patch /' \ + classes/ssl/Makefile.am.LibVNCServer > classes/ssl/Makefile.am +echo 'pkgdatadir = $(datadir)/@PACKAGE@/classes/ssl' >> classes/ssl/Makefile.am +echo 'pkgdata_DATA=VncViewer.jar index.vnc SignedVncViewer.jar proxy.vnc README UltraViewerSSL.jar SignedUltraViewerSSL.jar ultra.vnc ultrasigned.vnc' >> classes/ssl/Makefile.am +echo 'pkgdata_SCRIPTS=ss_vncviewer' >> classes/ssl/Makefile.am + +chmod 755 classes/ssl/ss_vncviewer + +mv acinclude.m4 acinclude.m4.LibVNCServer + +cat acinclude.m4.LibVNCServer | \ +sed -e "s/^\(_PKG.*\)\$PACKAGE\(.*\)$/\1LibVNCServer\2/" \ +> acinclude.m4 + +make x11vnc-${VERSION}.tar.gz +for f in configure.ac Makefile.am x11vnc/Makefile.am libvncserver/Makefile.am libvncclient/Makefile.am classes/Makefile.am classes/ssl/Makefile.am acinclude.m4 README; do + mv -f $f.LibVNCServer $f +done + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore new file mode 100755 index 0000000..cec07e0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/.cvsignore @@ -0,0 +1,5 @@ +rfbconfig.h +rfbconfig.h.in +stamp-h* +rfbint.h + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h new file mode 100755 index 0000000..252f411 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/default8x16.h @@ -0,0 +1,261 @@ +static unsigned char default8x16FontData[4096+1]={ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0x81,0xa5,0x81,0x81,0xbd,0x99,0x81,0x81,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7e,0xff,0xdb,0xff,0xff,0xc3,0xe7,0xff,0xff,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0x00,0x00,0x00,0x00, +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x1e,0x0e,0x1a,0x32,0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b,0x00,0x00,0x00,0x00, +0x00,0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xfe,0xfe,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x7e,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0xfe,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xfe,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0xc0,0xc0,0xfe,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x3c,0x3c,0x3c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18,0x00,0x00, +0x00,0x00,0x00,0x00,0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0c,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x18,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xce,0xde,0xf6,0xe6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x06,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x06,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x60,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x60,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78,0x00,0x00,0x00,0x00, +0x00,0x00,0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xe7,0xff,0xff,0xdb,0xc3,0xc3,0xc3,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e,0x00,0x00, +0x00,0x00,0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xdb,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x3c,0x66,0xc3,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0xff,0xc3,0x86,0x0c,0x18,0x30,0x60,0xc1,0xc3,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00,0x00,0x00,0x00, +0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00, +0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78,0x00, +0x00,0x00,0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x06,0x06,0x00,0x0e,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3c,0x00, +0x00,0x00,0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xe6,0xff,0xdb,0xdb,0xdb,0xdb,0xdb,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e,0x00, +0x00,0x00,0x00,0x00,0x00,0xdc,0x76,0x66,0x60,0x60,0x60,0xf0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xc3,0x66,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0xc3,0xc3,0xdb,0xdb,0xff,0x66,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc3,0x66,0x3c,0x18,0x3c,0x66,0xc3,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8,0x00, +0x00,0x00,0x00,0x00,0x00,0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0e,0x00,0x00,0x00,0x00, +0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x70,0x18,0x18,0x18,0x0e,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x3c,0x66,0x60,0x60,0x66,0x3c,0x0c,0x06,0x3c,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x3c,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x6e,0x3b,0x1b,0x7e,0xd8,0xdc,0x77,0x00,0x00,0x00,0x00, +0x00,0x00,0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce,0x00,0x00,0x00,0x00, +0x00,0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78,0x00, +0x00,0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x18,0x7e,0xc3,0xc0,0xc0,0xc0,0xc3,0x7e,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc,0x00,0x00,0x00,0x00, +0x00,0x00,0xc3,0x66,0x3c,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0xfc,0x66,0x66,0x7c,0x62,0x66,0x6f,0x66,0x66,0x66,0xf3,0x00,0x00,0x00,0x00, +0x00,0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x0c,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00, +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x3c,0x6c,0x6c,0x3e,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x7c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xce,0x9b,0x06,0x0c,0x1f,0x00,0x00, +0x00,0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x96,0x3e,0x06,0x06,0x00,0x00, +0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3c,0x3c,0x3c,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x36,0x6c,0xd8,0x6c,0x36,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xd8,0x6c,0x36,0x6c,0xd8,0x00,0x00,0x00,0x00,0x00,0x00, +0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44, +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, +0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f, +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76,0x00,0x00,0x00,0x00, +0x00,0x00,0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc,0x00,0x00,0x00,0x00, +0x00,0x00,0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7e,0x18,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38,0x00,0x00,0x00,0x00, +0x00,0x00,0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee,0x00,0x00,0x00,0x00, +0x00,0x00,0x1e,0x30,0x18,0x0c,0x3e,0x66,0x66,0x66,0x66,0x3c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x7e,0xdb,0xdb,0xdb,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0,0x00,0x00,0x00,0x00, +0x00,0x00,0x1c,0x30,0x60,0x60,0x7c,0x60,0x60,0x60,0x30,0x1c,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x30,0x18,0x0c,0x06,0x0c,0x18,0x30,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x0c,0x18,0x30,0x60,0x30,0x18,0x0c,0x00,0x7e,0x00,0x00,0x00,0x00, +0x00,0x00,0x0e,0x1b,0x1b,0x1b,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7e,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x76,0xdc,0x00,0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x38,0x6c,0x6c,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c,0x00,0x00,0x00,0x00, +0x00,0xd8,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x70,0xd8,0x30,0x60,0xc8,0xf8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +}; +static int default8x16FontMetaData[256*5+1]={ +0,8,16,0,0,16,8,16,0,0,32,8,16,0,0,48,8,16,0,0,64,8,16,0,0,80,8,16,0,0,96,8,16,0,0,112,8,16,0,0,128,8,16,0,0,144,8,16,0,0,160,8,16,0,0,176,8,16,0,0,192,8,16,0,0,208,8,16,0,0,224,8,16,0,0,240,8,16,0,0,256,8,16,0,0,272,8,16,0,0,288,8,16,0,0,304,8,16,0,0,320,8,16,0,0,336,8,16,0,0,352,8,16,0,0,368,8,16,0,0,384,8,16,0,0,400,8,16,0,0,416,8,16,0,0,432,8,16,0,0,448,8,16,0,0,464,8,16,0,0,480,8,16,0,0,496,8,16,0,0,512,8,16,0,0,528,8,16,0,0,544,8,16,0,0,560,8,16,0,0,576,8,16,0,0,592,8,16,0,0,608,8,16,0,0,624,8,16,0,0,640,8,16,0,0,656,8,16,0,0,672,8,16,0,0,688,8,16,0,0,704,8,16,0,0,720,8,16,0,0,736,8,16,0,0,752,8,16,0,0,768,8,16,0,0,784,8,16,0,0,800,8,16,0,0,816,8,16,0,0,832,8,16,0,0,848,8,16,0,0,864,8,16,0,0,880,8,16,0,0,896,8,16,0,0,912,8,16,0,0,928,8,16,0,0,944,8,16,0,0,960,8,16,0,0,976,8,16,0,0,992,8,16,0,0,1008,8,16,0,0,1024,8,16,0,0,1040,8,16,0,0,1056,8,16,0,0,1072,8,16,0,0,1088,8,16,0,0,1104,8,16,0,0,1120,8,16,0,0,1136,8,16,0,0,1152,8,16,0,0,1168,8,16,0,0,1184,8,16,0,0,1200,8,16,0,0,1216,8,16,0,0,1232,8,16,0,0,1248,8,16,0,0,1264,8,16,0,0,1280,8,16,0,0,1296,8,16,0,0,1312,8,16,0,0,1328,8,16,0,0,1344,8,16,0,0,1360,8,16,0,0,1376,8,16,0,0,1392,8,16,0,0,1408,8,16,0,0,1424,8,16,0,0,1440,8,16,0,0,1456,8,16,0,0,1472,8,16,0,0,1488,8,16,0,0,1504,8,16,0,0,1520,8,16,0,0,1536,8,16,0,0,1552,8,16,0,0,1568,8,16,0,0,1584,8,16,0,0,1600,8,16,0,0,1616,8,16,0,0,1632,8,16,0,0,1648,8,16,0,0,1664,8,16,0,0,1680,8,16,0,0,1696,8,16,0,0,1712,8,16,0,0,1728,8,16,0,0,1744,8,16,0,0,1760,8,16,0,0,1776,8,16,0,0,1792,8,16,0,0,1808,8,16,0,0,1824,8,16,0,0,1840,8,16,0,0,1856,8,16,0,0,1872,8,16,0,0,1888,8,16,0,0,1904,8,16,0,0,1920,8,16,0,0,1936,8,16,0,0,1952,8,16,0,0,1968,8,16,0,0,1984,8,16,0,0,2000,8,16,0,0,2016,8,16,0,0,2032,8,16,0,0,2048,8,16,0,0,2064,8,16,0,0,2080,8,16,0,0,2096,8,16,0,0,2112,8,16,0,0,2128,8,16,0,0,2144,8,16,0,0,2160,8,16,0,0,2176,8,16,0,0,2192,8,16,0,0,2208,8,16,0,0,2224,8,16,0,0,2240,8,16,0,0,2256,8,16,0,0,2272,8,16,0,0,2288,8,16,0,0,2304,8,16,0,0,2320,8,16,0,0,2336,8,16,0,0,2352,8,16,0,0,2368,8,16,0,0,2384,8,16,0,0,2400,8,16,0,0,2416,8,16,0,0,2432,8,16,0,0,2448,8,16,0,0,2464,8,16,0,0,2480,8,16,0,0,2496,8,16,0,0,2512,8,16,0,0,2528,8,16,0,0,2544,8,16,0,0,2560,8,16,0,0,2576,8,16,0,0,2592,8,16,0,0,2608,8,16,0,0,2624,8,16,0,0,2640,8,16,0,0,2656,8,16,0,0,2672,8,16,0,0,2688,8,16,0,0,2704,8,16,0,0,2720,8,16,0,0,2736,8,16,0,0,2752,8,16,0,0,2768,8,16,0,0,2784,8,16,0,0,2800,8,16,0,0,2816,8,16,0,0,2832,8,16,0,0,2848,8,16,0,0,2864,8,16,0,0,2880,8,16,0,0,2896,8,16,0,0,2912,8,16,0,0,2928,8,16,0,0,2944,8,16,0,0,2960,8,16,0,0,2976,8,16,0,0,2992,8,16,0,0,3008,8,16,0,0,3024,8,16,0,0,3040,8,16,0,0,3056,8,16,0,0,3072,8,16,0,0,3088,8,16,0,0,3104,8,16,0,0,3120,8,16,0,0,3136,8,16,0,0,3152,8,16,0,0,3168,8,16,0,0,3184,8,16,0,0,3200,8,16,0,0,3216,8,16,0,0,3232,8,16,0,0,3248,8,16,0,0,3264,8,16,0,0,3280,8,16,0,0,3296,8,16,0,0,3312,8,16,0,0,3328,8,16,0,0,3344,8,16,0,0,3360,8,16,0,0,3376,8,16,0,0,3392,8,16,0,0,3408,8,16,0,0,3424,8,16,0,0,3440,8,16,0,0,3456,8,16,0,0,3472,8,16,0,0,3488,8,16,0,0,3504,8,16,0,0,3520,8,16,0,0,3536,8,16,0,0,3552,8,16,0,0,3568,8,16,0,0,3584,8,16,0,0,3600,8,16,0,0,3616,8,16,0,0,3632,8,16,0,0,3648,8,16,0,0,3664,8,16,0,0,3680,8,16,0,0,3696,8,16,0,0,3712,8,16,0,0,3728,8,16,0,0,3744,8,16,0,0,3760,8,16,0,0,3776,8,16,0,0,3792,8,16,0,0,3808,8,16,0,0,3824,8,16,0,0,3840,8,16,0,0,3856,8,16,0,0,3872,8,16,0,0,3888,8,16,0,0,3904,8,16,0,0,3920,8,16,0,0,3936,8,16,0,0,3952,8,16,0,0,3968,8,16,0,0,3984,8,16,0,0,4000,8,16,0,0,4016,8,16,0,0,4032,8,16,0,0,4048,8,16,0,0,4064,8,16,0,0,4080,8,16,0,0,}; +static rfbFontData default8x16Font = { default8x16FontData, default8x16FontMetaData }; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h new file mode 100755 index 0000000..219f95b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/keysym.h @@ -0,0 +1,1638 @@ +#ifndef XK_0 + +/* $XConsortium: keysym.h,v 1.15 94/04/17 20:10:55 rws Exp $ */ + +/*********************************************************** + +Copyright (c) 1987 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +/* default keysyms */ +#define XK_MISCELLANY +#define XK_XKB_KEYS +#define XK_LATIN1 +#define XK_LATIN2 +#define XK_LATIN3 +#define XK_LATIN4 +#define XK_GREEK + +/* $TOG: keysymdef.h /main/25 1997/06/21 10:54:51 kaleb $ */ + +/*********************************************************** +Copyright (c) 1987, 1994 X Consortium + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from the X Consortium. + + +Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of Digital not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +******************************************************************/ + +#define XK_VoidSymbol 0xFFFFFF /* void symbol */ + +#ifdef XK_MISCELLANY +/* + * TTY Functions, cleverly chosen to map to ascii, for convenience of + * programming, but could have been arbitrary (at the cost of lookup + * tables in client code. + */ + +#define XK_BackSpace 0xFF08 /* back space, back char */ +#define XK_Tab 0xFF09 +#define XK_Linefeed 0xFF0A /* Linefeed, LF */ +#define XK_Clear 0xFF0B +#define XK_Return 0xFF0D /* Return, enter */ +#define XK_Pause 0xFF13 /* Pause, hold */ +#define XK_Scroll_Lock 0xFF14 +#define XK_Sys_Req 0xFF15 +#define XK_Escape 0xFF1B +#define XK_Delete 0xFFFF /* Delete, rubout */ + + + +/* International & multi-key character composition */ + +#define XK_Multi_key 0xFF20 /* Multi-key character compose */ +#define XK_SingleCandidate 0xFF3C +#define XK_MultipleCandidate 0xFF3D +#define XK_PreviousCandidate 0xFF3E + +/* Japanese keyboard support */ + +#define XK_Kanji 0xFF21 /* Kanji, Kanji convert */ +#define XK_Muhenkan 0xFF22 /* Cancel Conversion */ +#define XK_Henkan_Mode 0xFF23 /* Start/Stop Conversion */ +#define XK_Henkan 0xFF23 /* Alias for Henkan_Mode */ +#define XK_Romaji 0xFF24 /* to Romaji */ +#define XK_Hiragana 0xFF25 /* to Hiragana */ +#define XK_Katakana 0xFF26 /* to Katakana */ +#define XK_Hiragana_Katakana 0xFF27 /* Hiragana/Katakana toggle */ +#define XK_Zenkaku 0xFF28 /* to Zenkaku */ +#define XK_Hankaku 0xFF29 /* to Hankaku */ +#define XK_Zenkaku_Hankaku 0xFF2A /* Zenkaku/Hankaku toggle */ +#define XK_Touroku 0xFF2B /* Add to Dictionary */ +#define XK_Massyo 0xFF2C /* Delete from Dictionary */ +#define XK_Kana_Lock 0xFF2D /* Kana Lock */ +#define XK_Kana_Shift 0xFF2E /* Kana Shift */ +#define XK_Eisu_Shift 0xFF2F /* Alphanumeric Shift */ +#define XK_Eisu_toggle 0xFF30 /* Alphanumeric toggle */ +#define XK_Zen_Koho 0xFF3D /* Multiple/All Candidate(s) */ +#define XK_Mae_Koho 0xFF3E /* Previous Candidate */ + +/* 0xFF31 thru 0xFF3F are under XK_KOREAN */ + +/* Cursor control & motion */ + +#define XK_Home 0xFF50 +#define XK_Left 0xFF51 /* Move left, left arrow */ +#define XK_Up 0xFF52 /* Move up, up arrow */ +#define XK_Right 0xFF53 /* Move right, right arrow */ +#define XK_Down 0xFF54 /* Move down, down arrow */ +#define XK_Prior 0xFF55 /* Prior, previous */ +#define XK_Page_Up 0xFF55 +#define XK_Next 0xFF56 /* Next */ +#define XK_Page_Down 0xFF56 +#define XK_End 0xFF57 /* EOL */ +#define XK_Begin 0xFF58 /* BOL */ + + +/* Misc Functions */ + +#define XK_Select 0xFF60 /* Select, mark */ +#define XK_Print 0xFF61 +#define XK_Execute 0xFF62 /* Execute, run, do */ +#define XK_Insert 0xFF63 /* Insert, insert here */ +#define XK_Undo 0xFF65 /* Undo, oops */ +#define XK_Redo 0xFF66 /* redo, again */ +#define XK_Menu 0xFF67 +#define XK_Find 0xFF68 /* Find, search */ +#define XK_Cancel 0xFF69 /* Cancel, stop, abort, exit */ +#define XK_Help 0xFF6A /* Help */ +#define XK_Break 0xFF6B +#define XK_Mode_switch 0xFF7E /* Character set switch */ +#define XK_script_switch 0xFF7E /* Alias for mode_switch */ +#define XK_Num_Lock 0xFF7F + +/* Keypad Functions, keypad numbers cleverly chosen to map to ascii */ + +#define XK_KP_Space 0xFF80 /* space */ +#define XK_KP_Tab 0xFF89 +#define XK_KP_Enter 0xFF8D /* enter */ +#define XK_KP_F1 0xFF91 /* PF1, KP_A, ... */ +#define XK_KP_F2 0xFF92 +#define XK_KP_F3 0xFF93 +#define XK_KP_F4 0xFF94 +#define XK_KP_Home 0xFF95 +#define XK_KP_Left 0xFF96 +#define XK_KP_Up 0xFF97 +#define XK_KP_Right 0xFF98 +#define XK_KP_Down 0xFF99 +#define XK_KP_Prior 0xFF9A +#define XK_KP_Page_Up 0xFF9A +#define XK_KP_Next 0xFF9B +#define XK_KP_Page_Down 0xFF9B +#define XK_KP_End 0xFF9C +#define XK_KP_Begin 0xFF9D +#define XK_KP_Insert 0xFF9E +#define XK_KP_Delete 0xFF9F +#define XK_KP_Equal 0xFFBD /* equals */ +#define XK_KP_Multiply 0xFFAA +#define XK_KP_Add 0xFFAB +#define XK_KP_Separator 0xFFAC /* separator, often comma */ +#define XK_KP_Subtract 0xFFAD +#define XK_KP_Decimal 0xFFAE +#define XK_KP_Divide 0xFFAF + +#define XK_KP_0 0xFFB0 +#define XK_KP_1 0xFFB1 +#define XK_KP_2 0xFFB2 +#define XK_KP_3 0xFFB3 +#define XK_KP_4 0xFFB4 +#define XK_KP_5 0xFFB5 +#define XK_KP_6 0xFFB6 +#define XK_KP_7 0xFFB7 +#define XK_KP_8 0xFFB8 +#define XK_KP_9 0xFFB9 + + + +/* + * Auxilliary Functions; note the duplicate definitions for left and right + * function keys; Sun keyboards and a few other manufactures have such + * function key groups on the left and/or right sides of the keyboard. + * We've not found a keyboard with more than 35 function keys total. + */ + +#define XK_F1 0xFFBE +#define XK_F2 0xFFBF +#define XK_F3 0xFFC0 +#define XK_F4 0xFFC1 +#define XK_F5 0xFFC2 +#define XK_F6 0xFFC3 +#define XK_F7 0xFFC4 +#define XK_F8 0xFFC5 +#define XK_F9 0xFFC6 +#define XK_F10 0xFFC7 +#define XK_F11 0xFFC8 +#define XK_L1 0xFFC8 +#define XK_F12 0xFFC9 +#define XK_L2 0xFFC9 +#define XK_F13 0xFFCA +#define XK_L3 0xFFCA +#define XK_F14 0xFFCB +#define XK_L4 0xFFCB +#define XK_F15 0xFFCC +#define XK_L5 0xFFCC +#define XK_F16 0xFFCD +#define XK_L6 0xFFCD +#define XK_F17 0xFFCE +#define XK_L7 0xFFCE +#define XK_F18 0xFFCF +#define XK_L8 0xFFCF +#define XK_F19 0xFFD0 +#define XK_L9 0xFFD0 +#define XK_F20 0xFFD1 +#define XK_L10 0xFFD1 +#define XK_F21 0xFFD2 +#define XK_R1 0xFFD2 +#define XK_F22 0xFFD3 +#define XK_R2 0xFFD3 +#define XK_F23 0xFFD4 +#define XK_R3 0xFFD4 +#define XK_F24 0xFFD5 +#define XK_R4 0xFFD5 +#define XK_F25 0xFFD6 +#define XK_R5 0xFFD6 +#define XK_F26 0xFFD7 +#define XK_R6 0xFFD7 +#define XK_F27 0xFFD8 +#define XK_R7 0xFFD8 +#define XK_F28 0xFFD9 +#define XK_R8 0xFFD9 +#define XK_F29 0xFFDA +#define XK_R9 0xFFDA +#define XK_F30 0xFFDB +#define XK_R10 0xFFDB +#define XK_F31 0xFFDC +#define XK_R11 0xFFDC +#define XK_F32 0xFFDD +#define XK_R12 0xFFDD +#define XK_F33 0xFFDE +#define XK_R13 0xFFDE +#define XK_F34 0xFFDF +#define XK_R14 0xFFDF +#define XK_F35 0xFFE0 +#define XK_R15 0xFFE0 + +/* Modifiers */ + +#define XK_Shift_L 0xFFE1 /* Left shift */ +#define XK_Shift_R 0xFFE2 /* Right shift */ +#define XK_Control_L 0xFFE3 /* Left control */ +#define XK_Control_R 0xFFE4 /* Right control */ +#define XK_Caps_Lock 0xFFE5 /* Caps lock */ +#define XK_Shift_Lock 0xFFE6 /* Shift lock */ + +#define XK_Meta_L 0xFFE7 /* Left meta */ +#define XK_Meta_R 0xFFE8 /* Right meta */ +#define XK_Alt_L 0xFFE9 /* Left alt */ +#define XK_Alt_R 0xFFEA /* Right alt */ +#define XK_Super_L 0xFFEB /* Left super */ +#define XK_Super_R 0xFFEC /* Right super */ +#define XK_Hyper_L 0xFFED /* Left hyper */ +#define XK_Hyper_R 0xFFEE /* Right hyper */ +#endif /* XK_MISCELLANY */ + +/* + * ISO 9995 Function and Modifier Keys + * Byte 3 = 0xFE + */ + +#ifdef XK_XKB_KEYS +#define XK_ISO_Lock 0xFE01 +#define XK_ISO_Level2_Latch 0xFE02 +#define XK_ISO_Level3_Shift 0xFE03 +#define XK_ISO_Level3_Latch 0xFE04 +#define XK_ISO_Level3_Lock 0xFE05 +#define XK_ISO_Group_Shift 0xFF7E /* Alias for mode_switch */ +#define XK_ISO_Group_Latch 0xFE06 +#define XK_ISO_Group_Lock 0xFE07 +#define XK_ISO_Next_Group 0xFE08 +#define XK_ISO_Next_Group_Lock 0xFE09 +#define XK_ISO_Prev_Group 0xFE0A +#define XK_ISO_Prev_Group_Lock 0xFE0B +#define XK_ISO_First_Group 0xFE0C +#define XK_ISO_First_Group_Lock 0xFE0D +#define XK_ISO_Last_Group 0xFE0E +#define XK_ISO_Last_Group_Lock 0xFE0F + +#define XK_ISO_Left_Tab 0xFE20 +#define XK_ISO_Move_Line_Up 0xFE21 +#define XK_ISO_Move_Line_Down 0xFE22 +#define XK_ISO_Partial_Line_Up 0xFE23 +#define XK_ISO_Partial_Line_Down 0xFE24 +#define XK_ISO_Partial_Space_Left 0xFE25 +#define XK_ISO_Partial_Space_Right 0xFE26 +#define XK_ISO_Set_Margin_Left 0xFE27 +#define XK_ISO_Set_Margin_Right 0xFE28 +#define XK_ISO_Release_Margin_Left 0xFE29 +#define XK_ISO_Release_Margin_Right 0xFE2A +#define XK_ISO_Release_Both_Margins 0xFE2B +#define XK_ISO_Fast_Cursor_Left 0xFE2C +#define XK_ISO_Fast_Cursor_Right 0xFE2D +#define XK_ISO_Fast_Cursor_Up 0xFE2E +#define XK_ISO_Fast_Cursor_Down 0xFE2F +#define XK_ISO_Continuous_Underline 0xFE30 +#define XK_ISO_Discontinuous_Underline 0xFE31 +#define XK_ISO_Emphasize 0xFE32 +#define XK_ISO_Center_Object 0xFE33 +#define XK_ISO_Enter 0xFE34 + +#define XK_dead_grave 0xFE50 +#define XK_dead_acute 0xFE51 +#define XK_dead_circumflex 0xFE52 +#define XK_dead_tilde 0xFE53 +#define XK_dead_macron 0xFE54 +#define XK_dead_breve 0xFE55 +#define XK_dead_abovedot 0xFE56 +#define XK_dead_diaeresis 0xFE57 +#define XK_dead_abovering 0xFE58 +#define XK_dead_doubleacute 0xFE59 +#define XK_dead_caron 0xFE5A +#define XK_dead_cedilla 0xFE5B +#define XK_dead_ogonek 0xFE5C +#define XK_dead_iota 0xFE5D +#define XK_dead_voiced_sound 0xFE5E +#define XK_dead_semivoiced_sound 0xFE5F +#define XK_dead_belowdot 0xFE60 + +#define XK_First_Virtual_Screen 0xFED0 +#define XK_Prev_Virtual_Screen 0xFED1 +#define XK_Next_Virtual_Screen 0xFED2 +#define XK_Last_Virtual_Screen 0xFED4 +#define XK_Terminate_Server 0xFED5 + +#define XK_AccessX_Enable 0xFE70 +#define XK_AccessX_Feedback_Enable 0xFE71 +#define XK_RepeatKeys_Enable 0xFE72 +#define XK_SlowKeys_Enable 0xFE73 +#define XK_BounceKeys_Enable 0xFE74 +#define XK_StickyKeys_Enable 0xFE75 +#define XK_MouseKeys_Enable 0xFE76 +#define XK_MouseKeys_Accel_Enable 0xFE77 +#define XK_Overlay1_Enable 0xFE78 +#define XK_Overlay2_Enable 0xFE79 +#define XK_AudibleBell_Enable 0xFE7A + +#define XK_Pointer_Left 0xFEE0 +#define XK_Pointer_Right 0xFEE1 +#define XK_Pointer_Up 0xFEE2 +#define XK_Pointer_Down 0xFEE3 +#define XK_Pointer_UpLeft 0xFEE4 +#define XK_Pointer_UpRight 0xFEE5 +#define XK_Pointer_DownLeft 0xFEE6 +#define XK_Pointer_DownRight 0xFEE7 +#define XK_Pointer_Button_Dflt 0xFEE8 +#define XK_Pointer_Button1 0xFEE9 +#define XK_Pointer_Button2 0xFEEA +#define XK_Pointer_Button3 0xFEEB +#define XK_Pointer_Button4 0xFEEC +#define XK_Pointer_Button5 0xFEED +#define XK_Pointer_DblClick_Dflt 0xFEEE +#define XK_Pointer_DblClick1 0xFEEF +#define XK_Pointer_DblClick2 0xFEF0 +#define XK_Pointer_DblClick3 0xFEF1 +#define XK_Pointer_DblClick4 0xFEF2 +#define XK_Pointer_DblClick5 0xFEF3 +#define XK_Pointer_Drag_Dflt 0xFEF4 +#define XK_Pointer_Drag1 0xFEF5 +#define XK_Pointer_Drag2 0xFEF6 +#define XK_Pointer_Drag3 0xFEF7 +#define XK_Pointer_Drag4 0xFEF8 +#define XK_Pointer_Drag5 0xFEFD + +#define XK_Pointer_EnableKeys 0xFEF9 +#define XK_Pointer_Accelerate 0xFEFA +#define XK_Pointer_DfltBtnNext 0xFEFB +#define XK_Pointer_DfltBtnPrev 0xFEFC + +#endif + +/* + * 3270 Terminal Keys + * Byte 3 = 0xFD + */ + +#ifdef XK_3270 +#define XK_3270_Duplicate 0xFD01 +#define XK_3270_FieldMark 0xFD02 +#define XK_3270_Right2 0xFD03 +#define XK_3270_Left2 0xFD04 +#define XK_3270_BackTab 0xFD05 +#define XK_3270_EraseEOF 0xFD06 +#define XK_3270_EraseInput 0xFD07 +#define XK_3270_Reset 0xFD08 +#define XK_3270_Quit 0xFD09 +#define XK_3270_PA1 0xFD0A +#define XK_3270_PA2 0xFD0B +#define XK_3270_PA3 0xFD0C +#define XK_3270_Test 0xFD0D +#define XK_3270_Attn 0xFD0E +#define XK_3270_CursorBlink 0xFD0F +#define XK_3270_AltCursor 0xFD10 +#define XK_3270_KeyClick 0xFD11 +#define XK_3270_Jump 0xFD12 +#define XK_3270_Ident 0xFD13 +#define XK_3270_Rule 0xFD14 +#define XK_3270_Copy 0xFD15 +#define XK_3270_Play 0xFD16 +#define XK_3270_Setup 0xFD17 +#define XK_3270_Record 0xFD18 +#define XK_3270_ChangeScreen 0xFD19 +#define XK_3270_DeleteWord 0xFD1A +#define XK_3270_ExSelect 0xFD1B +#define XK_3270_CursorSelect 0xFD1C +#define XK_3270_PrintScreen 0xFD1D +#define XK_3270_Enter 0xFD1E +#endif + +/* + * Latin 1 + * Byte 3 = 0 + */ +#ifdef XK_LATIN1 +#define XK_space 0x020 +#define XK_exclam 0x021 +#define XK_quotedbl 0x022 +#define XK_numbersign 0x023 +#define XK_dollar 0x024 +#define XK_percent 0x025 +#define XK_ampersand 0x026 +#define XK_apostrophe 0x027 +#define XK_quoteright 0x027 /* deprecated */ +#define XK_parenleft 0x028 +#define XK_parenright 0x029 +#define XK_asterisk 0x02a +#define XK_plus 0x02b +#define XK_comma 0x02c +#define XK_minus 0x02d +#define XK_period 0x02e +#define XK_slash 0x02f +#define XK_0 0x030 +#define XK_1 0x031 +#define XK_2 0x032 +#define XK_3 0x033 +#define XK_4 0x034 +#define XK_5 0x035 +#define XK_6 0x036 +#define XK_7 0x037 +#define XK_8 0x038 +#define XK_9 0x039 +#define XK_colon 0x03a +#define XK_semicolon 0x03b +#define XK_less 0x03c +#define XK_equal 0x03d +#define XK_greater 0x03e +#define XK_question 0x03f +#define XK_at 0x040 +#define XK_A 0x041 +#define XK_B 0x042 +#define XK_C 0x043 +#define XK_D 0x044 +#define XK_E 0x045 +#define XK_F 0x046 +#define XK_G 0x047 +#define XK_H 0x048 +#define XK_I 0x049 +#define XK_J 0x04a +#define XK_K 0x04b +#define XK_L 0x04c +#define XK_M 0x04d +#define XK_N 0x04e +#define XK_O 0x04f +#define XK_P 0x050 +#define XK_Q 0x051 +#define XK_R 0x052 +#define XK_S 0x053 +#define XK_T 0x054 +#define XK_U 0x055 +#define XK_V 0x056 +#define XK_W 0x057 +#define XK_X 0x058 +#define XK_Y 0x059 +#define XK_Z 0x05a +#define XK_bracketleft 0x05b +#define XK_backslash 0x05c +#define XK_bracketright 0x05d +#define XK_asciicircum 0x05e +#define XK_underscore 0x05f +#define XK_grave 0x060 +#define XK_quoteleft 0x060 /* deprecated */ +#define XK_a 0x061 +#define XK_b 0x062 +#define XK_c 0x063 +#define XK_d 0x064 +#define XK_e 0x065 +#define XK_f 0x066 +#define XK_g 0x067 +#define XK_h 0x068 +#define XK_i 0x069 +#define XK_j 0x06a +#define XK_k 0x06b +#define XK_l 0x06c +#define XK_m 0x06d +#define XK_n 0x06e +#define XK_o 0x06f +#define XK_p 0x070 +#define XK_q 0x071 +#define XK_r 0x072 +#define XK_s 0x073 +#define XK_t 0x074 +#define XK_u 0x075 +#define XK_v 0x076 +#define XK_w 0x077 +#define XK_x 0x078 +#define XK_y 0x079 +#define XK_z 0x07a +#define XK_braceleft 0x07b +#define XK_bar 0x07c +#define XK_braceright 0x07d +#define XK_asciitilde 0x07e + +#define XK_nobreakspace 0x0a0 +#define XK_exclamdown 0x0a1 +#define XK_cent 0x0a2 +#define XK_sterling 0x0a3 +#define XK_currency 0x0a4 +#define XK_yen 0x0a5 +#define XK_brokenbar 0x0a6 +#define XK_section 0x0a7 +#define XK_diaeresis 0x0a8 +#define XK_copyright 0x0a9 +#define XK_ordfeminine 0x0aa +#define XK_guillemotleft 0x0ab /* left angle quotation mark */ +#define XK_notsign 0x0ac +#define XK_hyphen 0x0ad +#define XK_registered 0x0ae +#define XK_macron 0x0af +#define XK_degree 0x0b0 +#define XK_plusminus 0x0b1 +#define XK_twosuperior 0x0b2 +#define XK_threesuperior 0x0b3 +#define XK_acute 0x0b4 +#define XK_mu 0x0b5 +#define XK_paragraph 0x0b6 +#define XK_periodcentered 0x0b7 +#define XK_cedilla 0x0b8 +#define XK_onesuperior 0x0b9 +#define XK_masculine 0x0ba +#define XK_guillemotright 0x0bb /* right angle quotation mark */ +#define XK_onequarter 0x0bc +#define XK_onehalf 0x0bd +#define XK_threequarters 0x0be +#define XK_questiondown 0x0bf +#define XK_Agrave 0x0c0 +#define XK_Aacute 0x0c1 +#define XK_Acircumflex 0x0c2 +#define XK_Atilde 0x0c3 +#define XK_Adiaeresis 0x0c4 +#define XK_Aring 0x0c5 +#define XK_AE 0x0c6 +#define XK_Ccedilla 0x0c7 +#define XK_Egrave 0x0c8 +#define XK_Eacute 0x0c9 +#define XK_Ecircumflex 0x0ca +#define XK_Ediaeresis 0x0cb +#define XK_Igrave 0x0cc +#define XK_Iacute 0x0cd +#define XK_Icircumflex 0x0ce +#define XK_Idiaeresis 0x0cf +#define XK_ETH 0x0d0 +#define XK_Eth 0x0d0 /* deprecated */ +#define XK_Ntilde 0x0d1 +#define XK_Ograve 0x0d2 +#define XK_Oacute 0x0d3 +#define XK_Ocircumflex 0x0d4 +#define XK_Otilde 0x0d5 +#define XK_Odiaeresis 0x0d6 +#define XK_multiply 0x0d7 +#define XK_Ooblique 0x0d8 +#define XK_Ugrave 0x0d9 +#define XK_Uacute 0x0da +#define XK_Ucircumflex 0x0db +#define XK_Udiaeresis 0x0dc +#define XK_Yacute 0x0dd +#define XK_THORN 0x0de +#define XK_Thorn 0x0de /* deprecated */ +#define XK_ssharp 0x0df +#define XK_agrave 0x0e0 +#define XK_aacute 0x0e1 +#define XK_acircumflex 0x0e2 +#define XK_atilde 0x0e3 +#define XK_adiaeresis 0x0e4 +#define XK_aring 0x0e5 +#define XK_ae 0x0e6 +#define XK_ccedilla 0x0e7 +#define XK_egrave 0x0e8 +#define XK_eacute 0x0e9 +#define XK_ecircumflex 0x0ea +#define XK_ediaeresis 0x0eb +#define XK_igrave 0x0ec +#define XK_iacute 0x0ed +#define XK_icircumflex 0x0ee +#define XK_idiaeresis 0x0ef +#define XK_eth 0x0f0 +#define XK_ntilde 0x0f1 +#define XK_ograve 0x0f2 +#define XK_oacute 0x0f3 +#define XK_ocircumflex 0x0f4 +#define XK_otilde 0x0f5 +#define XK_odiaeresis 0x0f6 +#define XK_division 0x0f7 +#define XK_oslash 0x0f8 +#define XK_ugrave 0x0f9 +#define XK_uacute 0x0fa +#define XK_ucircumflex 0x0fb +#define XK_udiaeresis 0x0fc +#define XK_yacute 0x0fd +#define XK_thorn 0x0fe +#define XK_ydiaeresis 0x0ff +#endif /* XK_LATIN1 */ + +/* + * Latin 2 + * Byte 3 = 1 + */ + +#ifdef XK_LATIN2 +#define XK_Aogonek 0x1a1 +#define XK_breve 0x1a2 +#define XK_Lstroke 0x1a3 +#define XK_Lcaron 0x1a5 +#define XK_Sacute 0x1a6 +#define XK_Scaron 0x1a9 +#define XK_Scedilla 0x1aa +#define XK_Tcaron 0x1ab +#define XK_Zacute 0x1ac +#define XK_Zcaron 0x1ae +#define XK_Zabovedot 0x1af +#define XK_aogonek 0x1b1 +#define XK_ogonek 0x1b2 +#define XK_lstroke 0x1b3 +#define XK_lcaron 0x1b5 +#define XK_sacute 0x1b6 +#define XK_caron 0x1b7 +#define XK_scaron 0x1b9 +#define XK_scedilla 0x1ba +#define XK_tcaron 0x1bb +#define XK_zacute 0x1bc +#define XK_doubleacute 0x1bd +#define XK_zcaron 0x1be +#define XK_zabovedot 0x1bf +#define XK_Racute 0x1c0 +#define XK_Abreve 0x1c3 +#define XK_Lacute 0x1c5 +#define XK_Cacute 0x1c6 +#define XK_Ccaron 0x1c8 +#define XK_Eogonek 0x1ca +#define XK_Ecaron 0x1cc +#define XK_Dcaron 0x1cf +#define XK_Dstroke 0x1d0 +#define XK_Nacute 0x1d1 +#define XK_Ncaron 0x1d2 +#define XK_Odoubleacute 0x1d5 +#define XK_Rcaron 0x1d8 +#define XK_Uring 0x1d9 +#define XK_Udoubleacute 0x1db +#define XK_Tcedilla 0x1de +#define XK_racute 0x1e0 +#define XK_abreve 0x1e3 +#define XK_lacute 0x1e5 +#define XK_cacute 0x1e6 +#define XK_ccaron 0x1e8 +#define XK_eogonek 0x1ea +#define XK_ecaron 0x1ec +#define XK_dcaron 0x1ef +#define XK_dstroke 0x1f0 +#define XK_nacute 0x1f1 +#define XK_ncaron 0x1f2 +#define XK_odoubleacute 0x1f5 +#define XK_udoubleacute 0x1fb +#define XK_rcaron 0x1f8 +#define XK_uring 0x1f9 +#define XK_tcedilla 0x1fe +#define XK_abovedot 0x1ff +#endif /* XK_LATIN2 */ + +/* + * Latin 3 + * Byte 3 = 2 + */ + +#ifdef XK_LATIN3 +#define XK_Hstroke 0x2a1 +#define XK_Hcircumflex 0x2a6 +#define XK_Iabovedot 0x2a9 +#define XK_Gbreve 0x2ab +#define XK_Jcircumflex 0x2ac +#define XK_hstroke 0x2b1 +#define XK_hcircumflex 0x2b6 +#define XK_idotless 0x2b9 +#define XK_gbreve 0x2bb +#define XK_jcircumflex 0x2bc +#define XK_Cabovedot 0x2c5 +#define XK_Ccircumflex 0x2c6 +#define XK_Gabovedot 0x2d5 +#define XK_Gcircumflex 0x2d8 +#define XK_Ubreve 0x2dd +#define XK_Scircumflex 0x2de +#define XK_cabovedot 0x2e5 +#define XK_ccircumflex 0x2e6 +#define XK_gabovedot 0x2f5 +#define XK_gcircumflex 0x2f8 +#define XK_ubreve 0x2fd +#define XK_scircumflex 0x2fe +#endif /* XK_LATIN3 */ + + +/* + * Latin 4 + * Byte 3 = 3 + */ + +#ifdef XK_LATIN4 +#define XK_kra 0x3a2 +#define XK_kappa 0x3a2 /* deprecated */ +#define XK_Rcedilla 0x3a3 +#define XK_Itilde 0x3a5 +#define XK_Lcedilla 0x3a6 +#define XK_Emacron 0x3aa +#define XK_Gcedilla 0x3ab +#define XK_Tslash 0x3ac +#define XK_rcedilla 0x3b3 +#define XK_itilde 0x3b5 +#define XK_lcedilla 0x3b6 +#define XK_emacron 0x3ba +#define XK_gcedilla 0x3bb +#define XK_tslash 0x3bc +#define XK_ENG 0x3bd +#define XK_eng 0x3bf +#define XK_Amacron 0x3c0 +#define XK_Iogonek 0x3c7 +#define XK_Eabovedot 0x3cc +#define XK_Imacron 0x3cf +#define XK_Ncedilla 0x3d1 +#define XK_Omacron 0x3d2 +#define XK_Kcedilla 0x3d3 +#define XK_Uogonek 0x3d9 +#define XK_Utilde 0x3dd +#define XK_Umacron 0x3de +#define XK_amacron 0x3e0 +#define XK_iogonek 0x3e7 +#define XK_eabovedot 0x3ec +#define XK_imacron 0x3ef +#define XK_ncedilla 0x3f1 +#define XK_omacron 0x3f2 +#define XK_kcedilla 0x3f3 +#define XK_uogonek 0x3f9 +#define XK_utilde 0x3fd +#define XK_umacron 0x3fe +#endif /* XK_LATIN4 */ + +/* + * Katakana + * Byte 3 = 4 + */ + +#ifdef XK_KATAKANA +#define XK_overline 0x47e +#define XK_kana_fullstop 0x4a1 +#define XK_kana_openingbracket 0x4a2 +#define XK_kana_closingbracket 0x4a3 +#define XK_kana_comma 0x4a4 +#define XK_kana_conjunctive 0x4a5 +#define XK_kana_middledot 0x4a5 /* deprecated */ +#define XK_kana_WO 0x4a6 +#define XK_kana_a 0x4a7 +#define XK_kana_i 0x4a8 +#define XK_kana_u 0x4a9 +#define XK_kana_e 0x4aa +#define XK_kana_o 0x4ab +#define XK_kana_ya 0x4ac +#define XK_kana_yu 0x4ad +#define XK_kana_yo 0x4ae +#define XK_kana_tsu 0x4af +#define XK_kana_tu 0x4af /* deprecated */ +#define XK_prolongedsound 0x4b0 +#define XK_kana_A 0x4b1 +#define XK_kana_I 0x4b2 +#define XK_kana_U 0x4b3 +#define XK_kana_E 0x4b4 +#define XK_kana_O 0x4b5 +#define XK_kana_KA 0x4b6 +#define XK_kana_KI 0x4b7 +#define XK_kana_KU 0x4b8 +#define XK_kana_KE 0x4b9 +#define XK_kana_KO 0x4ba +#define XK_kana_SA 0x4bb +#define XK_kana_SHI 0x4bc +#define XK_kana_SU 0x4bd +#define XK_kana_SE 0x4be +#define XK_kana_SO 0x4bf +#define XK_kana_TA 0x4c0 +#define XK_kana_CHI 0x4c1 +#define XK_kana_TI 0x4c1 /* deprecated */ +#define XK_kana_TSU 0x4c2 +#define XK_kana_TU 0x4c2 /* deprecated */ +#define XK_kana_TE 0x4c3 +#define XK_kana_TO 0x4c4 +#define XK_kana_NA 0x4c5 +#define XK_kana_NI 0x4c6 +#define XK_kana_NU 0x4c7 +#define XK_kana_NE 0x4c8 +#define XK_kana_NO 0x4c9 +#define XK_kana_HA 0x4ca +#define XK_kana_HI 0x4cb +#define XK_kana_FU 0x4cc +#define XK_kana_HU 0x4cc /* deprecated */ +#define XK_kana_HE 0x4cd +#define XK_kana_HO 0x4ce +#define XK_kana_MA 0x4cf +#define XK_kana_MI 0x4d0 +#define XK_kana_MU 0x4d1 +#define XK_kana_ME 0x4d2 +#define XK_kana_MO 0x4d3 +#define XK_kana_YA 0x4d4 +#define XK_kana_YU 0x4d5 +#define XK_kana_YO 0x4d6 +#define XK_kana_RA 0x4d7 +#define XK_kana_RI 0x4d8 +#define XK_kana_RU 0x4d9 +#define XK_kana_RE 0x4da +#define XK_kana_RO 0x4db +#define XK_kana_WA 0x4dc +#define XK_kana_N 0x4dd +#define XK_voicedsound 0x4de +#define XK_semivoicedsound 0x4df +#define XK_kana_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_KATAKANA */ + +/* + * Arabic + * Byte 3 = 5 + */ + +#ifdef XK_ARABIC +#define XK_Arabic_comma 0x5ac +#define XK_Arabic_semicolon 0x5bb +#define XK_Arabic_question_mark 0x5bf +#define XK_Arabic_hamza 0x5c1 +#define XK_Arabic_maddaonalef 0x5c2 +#define XK_Arabic_hamzaonalef 0x5c3 +#define XK_Arabic_hamzaonwaw 0x5c4 +#define XK_Arabic_hamzaunderalef 0x5c5 +#define XK_Arabic_hamzaonyeh 0x5c6 +#define XK_Arabic_alef 0x5c7 +#define XK_Arabic_beh 0x5c8 +#define XK_Arabic_tehmarbuta 0x5c9 +#define XK_Arabic_teh 0x5ca +#define XK_Arabic_theh 0x5cb +#define XK_Arabic_jeem 0x5cc +#define XK_Arabic_hah 0x5cd +#define XK_Arabic_khah 0x5ce +#define XK_Arabic_dal 0x5cf +#define XK_Arabic_thal 0x5d0 +#define XK_Arabic_ra 0x5d1 +#define XK_Arabic_zain 0x5d2 +#define XK_Arabic_seen 0x5d3 +#define XK_Arabic_sheen 0x5d4 +#define XK_Arabic_sad 0x5d5 +#define XK_Arabic_dad 0x5d6 +#define XK_Arabic_tah 0x5d7 +#define XK_Arabic_zah 0x5d8 +#define XK_Arabic_ain 0x5d9 +#define XK_Arabic_ghain 0x5da +#define XK_Arabic_tatweel 0x5e0 +#define XK_Arabic_feh 0x5e1 +#define XK_Arabic_qaf 0x5e2 +#define XK_Arabic_kaf 0x5e3 +#define XK_Arabic_lam 0x5e4 +#define XK_Arabic_meem 0x5e5 +#define XK_Arabic_noon 0x5e6 +#define XK_Arabic_ha 0x5e7 +#define XK_Arabic_heh 0x5e7 /* deprecated */ +#define XK_Arabic_waw 0x5e8 +#define XK_Arabic_alefmaksura 0x5e9 +#define XK_Arabic_yeh 0x5ea +#define XK_Arabic_fathatan 0x5eb +#define XK_Arabic_dammatan 0x5ec +#define XK_Arabic_kasratan 0x5ed +#define XK_Arabic_fatha 0x5ee +#define XK_Arabic_damma 0x5ef +#define XK_Arabic_kasra 0x5f0 +#define XK_Arabic_shadda 0x5f1 +#define XK_Arabic_sukun 0x5f2 +#define XK_Arabic_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_ARABIC */ + +/* + * Cyrillic + * Byte 3 = 6 + */ +#ifdef XK_CYRILLIC +#define XK_Serbian_dje 0x6a1 +#define XK_Macedonia_gje 0x6a2 +#define XK_Cyrillic_io 0x6a3 +#define XK_Ukrainian_ie 0x6a4 +#define XK_Ukranian_je 0x6a4 /* deprecated */ +#define XK_Macedonia_dse 0x6a5 +#define XK_Ukrainian_i 0x6a6 +#define XK_Ukranian_i 0x6a6 /* deprecated */ +#define XK_Ukrainian_yi 0x6a7 +#define XK_Ukranian_yi 0x6a7 /* deprecated */ +#define XK_Cyrillic_je 0x6a8 +#define XK_Serbian_je 0x6a8 /* deprecated */ +#define XK_Cyrillic_lje 0x6a9 +#define XK_Serbian_lje 0x6a9 /* deprecated */ +#define XK_Cyrillic_nje 0x6aa +#define XK_Serbian_nje 0x6aa /* deprecated */ +#define XK_Serbian_tshe 0x6ab +#define XK_Macedonia_kje 0x6ac +#define XK_Byelorussian_shortu 0x6ae +#define XK_Cyrillic_dzhe 0x6af +#define XK_Serbian_dze 0x6af /* deprecated */ +#define XK_numerosign 0x6b0 +#define XK_Serbian_DJE 0x6b1 +#define XK_Macedonia_GJE 0x6b2 +#define XK_Cyrillic_IO 0x6b3 +#define XK_Ukrainian_IE 0x6b4 +#define XK_Ukranian_JE 0x6b4 /* deprecated */ +#define XK_Macedonia_DSE 0x6b5 +#define XK_Ukrainian_I 0x6b6 +#define XK_Ukranian_I 0x6b6 /* deprecated */ +#define XK_Ukrainian_YI 0x6b7 +#define XK_Ukranian_YI 0x6b7 /* deprecated */ +#define XK_Cyrillic_JE 0x6b8 +#define XK_Serbian_JE 0x6b8 /* deprecated */ +#define XK_Cyrillic_LJE 0x6b9 +#define XK_Serbian_LJE 0x6b9 /* deprecated */ +#define XK_Cyrillic_NJE 0x6ba +#define XK_Serbian_NJE 0x6ba /* deprecated */ +#define XK_Serbian_TSHE 0x6bb +#define XK_Macedonia_KJE 0x6bc +#define XK_Byelorussian_SHORTU 0x6be +#define XK_Cyrillic_DZHE 0x6bf +#define XK_Serbian_DZE 0x6bf /* deprecated */ +#define XK_Cyrillic_yu 0x6c0 +#define XK_Cyrillic_a 0x6c1 +#define XK_Cyrillic_be 0x6c2 +#define XK_Cyrillic_tse 0x6c3 +#define XK_Cyrillic_de 0x6c4 +#define XK_Cyrillic_ie 0x6c5 +#define XK_Cyrillic_ef 0x6c6 +#define XK_Cyrillic_ghe 0x6c7 +#define XK_Cyrillic_ha 0x6c8 +#define XK_Cyrillic_i 0x6c9 +#define XK_Cyrillic_shorti 0x6ca +#define XK_Cyrillic_ka 0x6cb +#define XK_Cyrillic_el 0x6cc +#define XK_Cyrillic_em 0x6cd +#define XK_Cyrillic_en 0x6ce +#define XK_Cyrillic_o 0x6cf +#define XK_Cyrillic_pe 0x6d0 +#define XK_Cyrillic_ya 0x6d1 +#define XK_Cyrillic_er 0x6d2 +#define XK_Cyrillic_es 0x6d3 +#define XK_Cyrillic_te 0x6d4 +#define XK_Cyrillic_u 0x6d5 +#define XK_Cyrillic_zhe 0x6d6 +#define XK_Cyrillic_ve 0x6d7 +#define XK_Cyrillic_softsign 0x6d8 +#define XK_Cyrillic_yeru 0x6d9 +#define XK_Cyrillic_ze 0x6da +#define XK_Cyrillic_sha 0x6db +#define XK_Cyrillic_e 0x6dc +#define XK_Cyrillic_shcha 0x6dd +#define XK_Cyrillic_che 0x6de +#define XK_Cyrillic_hardsign 0x6df +#define XK_Cyrillic_YU 0x6e0 +#define XK_Cyrillic_A 0x6e1 +#define XK_Cyrillic_BE 0x6e2 +#define XK_Cyrillic_TSE 0x6e3 +#define XK_Cyrillic_DE 0x6e4 +#define XK_Cyrillic_IE 0x6e5 +#define XK_Cyrillic_EF 0x6e6 +#define XK_Cyrillic_GHE 0x6e7 +#define XK_Cyrillic_HA 0x6e8 +#define XK_Cyrillic_I 0x6e9 +#define XK_Cyrillic_SHORTI 0x6ea +#define XK_Cyrillic_KA 0x6eb +#define XK_Cyrillic_EL 0x6ec +#define XK_Cyrillic_EM 0x6ed +#define XK_Cyrillic_EN 0x6ee +#define XK_Cyrillic_O 0x6ef +#define XK_Cyrillic_PE 0x6f0 +#define XK_Cyrillic_YA 0x6f1 +#define XK_Cyrillic_ER 0x6f2 +#define XK_Cyrillic_ES 0x6f3 +#define XK_Cyrillic_TE 0x6f4 +#define XK_Cyrillic_U 0x6f5 +#define XK_Cyrillic_ZHE 0x6f6 +#define XK_Cyrillic_VE 0x6f7 +#define XK_Cyrillic_SOFTSIGN 0x6f8 +#define XK_Cyrillic_YERU 0x6f9 +#define XK_Cyrillic_ZE 0x6fa +#define XK_Cyrillic_SHA 0x6fb +#define XK_Cyrillic_E 0x6fc +#define XK_Cyrillic_SHCHA 0x6fd +#define XK_Cyrillic_CHE 0x6fe +#define XK_Cyrillic_HARDSIGN 0x6ff +#endif /* XK_CYRILLIC */ + +/* + * Greek + * Byte 3 = 7 + */ + +#ifdef XK_GREEK +#define XK_Greek_ALPHAaccent 0x7a1 +#define XK_Greek_EPSILONaccent 0x7a2 +#define XK_Greek_ETAaccent 0x7a3 +#define XK_Greek_IOTAaccent 0x7a4 +#define XK_Greek_IOTAdieresis 0x7a5 +#define XK_Greek_OMICRONaccent 0x7a7 +#define XK_Greek_UPSILONaccent 0x7a8 +#define XK_Greek_UPSILONdieresis 0x7a9 +#define XK_Greek_OMEGAaccent 0x7ab +#define XK_Greek_accentdieresis 0x7ae +#define XK_Greek_horizbar 0x7af +#define XK_Greek_alphaaccent 0x7b1 +#define XK_Greek_epsilonaccent 0x7b2 +#define XK_Greek_etaaccent 0x7b3 +#define XK_Greek_iotaaccent 0x7b4 +#define XK_Greek_iotadieresis 0x7b5 +#define XK_Greek_iotaaccentdieresis 0x7b6 +#define XK_Greek_omicronaccent 0x7b7 +#define XK_Greek_upsilonaccent 0x7b8 +#define XK_Greek_upsilondieresis 0x7b9 +#define XK_Greek_upsilonaccentdieresis 0x7ba +#define XK_Greek_omegaaccent 0x7bb +#define XK_Greek_ALPHA 0x7c1 +#define XK_Greek_BETA 0x7c2 +#define XK_Greek_GAMMA 0x7c3 +#define XK_Greek_DELTA 0x7c4 +#define XK_Greek_EPSILON 0x7c5 +#define XK_Greek_ZETA 0x7c6 +#define XK_Greek_ETA 0x7c7 +#define XK_Greek_THETA 0x7c8 +#define XK_Greek_IOTA 0x7c9 +#define XK_Greek_KAPPA 0x7ca +#define XK_Greek_LAMDA 0x7cb +#define XK_Greek_LAMBDA 0x7cb +#define XK_Greek_MU 0x7cc +#define XK_Greek_NU 0x7cd +#define XK_Greek_XI 0x7ce +#define XK_Greek_OMICRON 0x7cf +#define XK_Greek_PI 0x7d0 +#define XK_Greek_RHO 0x7d1 +#define XK_Greek_SIGMA 0x7d2 +#define XK_Greek_TAU 0x7d4 +#define XK_Greek_UPSILON 0x7d5 +#define XK_Greek_PHI 0x7d6 +#define XK_Greek_CHI 0x7d7 +#define XK_Greek_PSI 0x7d8 +#define XK_Greek_OMEGA 0x7d9 +#define XK_Greek_alpha 0x7e1 +#define XK_Greek_beta 0x7e2 +#define XK_Greek_gamma 0x7e3 +#define XK_Greek_delta 0x7e4 +#define XK_Greek_epsilon 0x7e5 +#define XK_Greek_zeta 0x7e6 +#define XK_Greek_eta 0x7e7 +#define XK_Greek_theta 0x7e8 +#define XK_Greek_iota 0x7e9 +#define XK_Greek_kappa 0x7ea +#define XK_Greek_lamda 0x7eb +#define XK_Greek_lambda 0x7eb +#define XK_Greek_mu 0x7ec +#define XK_Greek_nu 0x7ed +#define XK_Greek_xi 0x7ee +#define XK_Greek_omicron 0x7ef +#define XK_Greek_pi 0x7f0 +#define XK_Greek_rho 0x7f1 +#define XK_Greek_sigma 0x7f2 +#define XK_Greek_finalsmallsigma 0x7f3 +#define XK_Greek_tau 0x7f4 +#define XK_Greek_upsilon 0x7f5 +#define XK_Greek_phi 0x7f6 +#define XK_Greek_chi 0x7f7 +#define XK_Greek_psi 0x7f8 +#define XK_Greek_omega 0x7f9 +#define XK_Greek_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_GREEK */ + +/* + * Technical + * Byte 3 = 8 + */ + +#ifdef XK_TECHNICAL +#define XK_leftradical 0x8a1 +#define XK_topleftradical 0x8a2 +#define XK_horizconnector 0x8a3 +#define XK_topintegral 0x8a4 +#define XK_botintegral 0x8a5 +#define XK_vertconnector 0x8a6 +#define XK_topleftsqbracket 0x8a7 +#define XK_botleftsqbracket 0x8a8 +#define XK_toprightsqbracket 0x8a9 +#define XK_botrightsqbracket 0x8aa +#define XK_topleftparens 0x8ab +#define XK_botleftparens 0x8ac +#define XK_toprightparens 0x8ad +#define XK_botrightparens 0x8ae +#define XK_leftmiddlecurlybrace 0x8af +#define XK_rightmiddlecurlybrace 0x8b0 +#define XK_topleftsummation 0x8b1 +#define XK_botleftsummation 0x8b2 +#define XK_topvertsummationconnector 0x8b3 +#define XK_botvertsummationconnector 0x8b4 +#define XK_toprightsummation 0x8b5 +#define XK_botrightsummation 0x8b6 +#define XK_rightmiddlesummation 0x8b7 +#define XK_lessthanequal 0x8bc +#define XK_notequal 0x8bd +#define XK_greaterthanequal 0x8be +#define XK_integral 0x8bf +#define XK_therefore 0x8c0 +#define XK_variation 0x8c1 +#define XK_infinity 0x8c2 +#define XK_nabla 0x8c5 +#define XK_approximate 0x8c8 +#define XK_similarequal 0x8c9 +#define XK_ifonlyif 0x8cd +#define XK_implies 0x8ce +#define XK_identical 0x8cf +#define XK_radical 0x8d6 +#define XK_includedin 0x8da +#define XK_includes 0x8db +#define XK_intersection 0x8dc +#define XK_union 0x8dd +#define XK_logicaland 0x8de +#define XK_logicalor 0x8df +#define XK_partialderivative 0x8ef +#define XK_function 0x8f6 +#define XK_leftarrow 0x8fb +#define XK_uparrow 0x8fc +#define XK_rightarrow 0x8fd +#define XK_downarrow 0x8fe +#endif /* XK_TECHNICAL */ + +/* + * Special + * Byte 3 = 9 + */ + +#ifdef XK_SPECIAL +#define XK_blank 0x9df +#define XK_soliddiamond 0x9e0 +#define XK_checkerboard 0x9e1 +#define XK_ht 0x9e2 +#define XK_ff 0x9e3 +#define XK_cr 0x9e4 +#define XK_lf 0x9e5 +#define XK_nl 0x9e8 +#define XK_vt 0x9e9 +#define XK_lowrightcorner 0x9ea +#define XK_uprightcorner 0x9eb +#define XK_upleftcorner 0x9ec +#define XK_lowleftcorner 0x9ed +#define XK_crossinglines 0x9ee +#define XK_horizlinescan1 0x9ef +#define XK_horizlinescan3 0x9f0 +#define XK_horizlinescan5 0x9f1 +#define XK_horizlinescan7 0x9f2 +#define XK_horizlinescan9 0x9f3 +#define XK_leftt 0x9f4 +#define XK_rightt 0x9f5 +#define XK_bott 0x9f6 +#define XK_topt 0x9f7 +#define XK_vertbar 0x9f8 +#endif /* XK_SPECIAL */ + +/* + * Publishing + * Byte 3 = a + */ + +#ifdef XK_PUBLISHING +#define XK_emspace 0xaa1 +#define XK_enspace 0xaa2 +#define XK_em3space 0xaa3 +#define XK_em4space 0xaa4 +#define XK_digitspace 0xaa5 +#define XK_punctspace 0xaa6 +#define XK_thinspace 0xaa7 +#define XK_hairspace 0xaa8 +#define XK_emdash 0xaa9 +#define XK_endash 0xaaa +#define XK_signifblank 0xaac +#define XK_ellipsis 0xaae +#define XK_doubbaselinedot 0xaaf +#define XK_onethird 0xab0 +#define XK_twothirds 0xab1 +#define XK_onefifth 0xab2 +#define XK_twofifths 0xab3 +#define XK_threefifths 0xab4 +#define XK_fourfifths 0xab5 +#define XK_onesixth 0xab6 +#define XK_fivesixths 0xab7 +#define XK_careof 0xab8 +#define XK_figdash 0xabb +#define XK_leftanglebracket 0xabc +#define XK_decimalpoint 0xabd +#define XK_rightanglebracket 0xabe +#define XK_marker 0xabf +#define XK_oneeighth 0xac3 +#define XK_threeeighths 0xac4 +#define XK_fiveeighths 0xac5 +#define XK_seveneighths 0xac6 +#define XK_trademark 0xac9 +#define XK_signaturemark 0xaca +#define XK_trademarkincircle 0xacb +#define XK_leftopentriangle 0xacc +#define XK_rightopentriangle 0xacd +#define XK_emopencircle 0xace +#define XK_emopenrectangle 0xacf +#define XK_leftsinglequotemark 0xad0 +#define XK_rightsinglequotemark 0xad1 +#define XK_leftdoublequotemark 0xad2 +#define XK_rightdoublequotemark 0xad3 +#define XK_prescription 0xad4 +#define XK_minutes 0xad6 +#define XK_seconds 0xad7 +#define XK_latincross 0xad9 +#define XK_hexagram 0xada +#define XK_filledrectbullet 0xadb +#define XK_filledlefttribullet 0xadc +#define XK_filledrighttribullet 0xadd +#define XK_emfilledcircle 0xade +#define XK_emfilledrect 0xadf +#define XK_enopencircbullet 0xae0 +#define XK_enopensquarebullet 0xae1 +#define XK_openrectbullet 0xae2 +#define XK_opentribulletup 0xae3 +#define XK_opentribulletdown 0xae4 +#define XK_openstar 0xae5 +#define XK_enfilledcircbullet 0xae6 +#define XK_enfilledsqbullet 0xae7 +#define XK_filledtribulletup 0xae8 +#define XK_filledtribulletdown 0xae9 +#define XK_leftpointer 0xaea +#define XK_rightpointer 0xaeb +#define XK_club 0xaec +#define XK_diamond 0xaed +#define XK_heart 0xaee +#define XK_maltesecross 0xaf0 +#define XK_dagger 0xaf1 +#define XK_doubledagger 0xaf2 +#define XK_checkmark 0xaf3 +#define XK_ballotcross 0xaf4 +#define XK_musicalsharp 0xaf5 +#define XK_musicalflat 0xaf6 +#define XK_malesymbol 0xaf7 +#define XK_femalesymbol 0xaf8 +#define XK_telephone 0xaf9 +#define XK_telephonerecorder 0xafa +#define XK_phonographcopyright 0xafb +#define XK_caret 0xafc +#define XK_singlelowquotemark 0xafd +#define XK_doublelowquotemark 0xafe +#define XK_cursor 0xaff +#endif /* XK_PUBLISHING */ + +/* + * APL + * Byte 3 = b + */ + +#ifdef XK_APL +#define XK_leftcaret 0xba3 +#define XK_rightcaret 0xba6 +#define XK_downcaret 0xba8 +#define XK_upcaret 0xba9 +#define XK_overbar 0xbc0 +#define XK_downtack 0xbc2 +#define XK_upshoe 0xbc3 +#define XK_downstile 0xbc4 +#define XK_underbar 0xbc6 +#define XK_jot 0xbca +#define XK_quad 0xbcc +#define XK_uptack 0xbce +#define XK_circle 0xbcf +#define XK_upstile 0xbd3 +#define XK_downshoe 0xbd6 +#define XK_rightshoe 0xbd8 +#define XK_leftshoe 0xbda +#define XK_lefttack 0xbdc +#define XK_righttack 0xbfc +#endif /* XK_APL */ + +/* + * Hebrew + * Byte 3 = c + */ + +#ifdef XK_HEBREW +#define XK_hebrew_doublelowline 0xcdf +#define XK_hebrew_aleph 0xce0 +#define XK_hebrew_bet 0xce1 +#define XK_hebrew_beth 0xce1 /* deprecated */ +#define XK_hebrew_gimel 0xce2 +#define XK_hebrew_gimmel 0xce2 /* deprecated */ +#define XK_hebrew_dalet 0xce3 +#define XK_hebrew_daleth 0xce3 /* deprecated */ +#define XK_hebrew_he 0xce4 +#define XK_hebrew_waw 0xce5 +#define XK_hebrew_zain 0xce6 +#define XK_hebrew_zayin 0xce6 /* deprecated */ +#define XK_hebrew_chet 0xce7 +#define XK_hebrew_het 0xce7 /* deprecated */ +#define XK_hebrew_tet 0xce8 +#define XK_hebrew_teth 0xce8 /* deprecated */ +#define XK_hebrew_yod 0xce9 +#define XK_hebrew_finalkaph 0xcea +#define XK_hebrew_kaph 0xceb +#define XK_hebrew_lamed 0xcec +#define XK_hebrew_finalmem 0xced +#define XK_hebrew_mem 0xcee +#define XK_hebrew_finalnun 0xcef +#define XK_hebrew_nun 0xcf0 +#define XK_hebrew_samech 0xcf1 +#define XK_hebrew_samekh 0xcf1 /* deprecated */ +#define XK_hebrew_ayin 0xcf2 +#define XK_hebrew_finalpe 0xcf3 +#define XK_hebrew_pe 0xcf4 +#define XK_hebrew_finalzade 0xcf5 +#define XK_hebrew_finalzadi 0xcf5 /* deprecated */ +#define XK_hebrew_zade 0xcf6 +#define XK_hebrew_zadi 0xcf6 /* deprecated */ +#define XK_hebrew_qoph 0xcf7 +#define XK_hebrew_kuf 0xcf7 /* deprecated */ +#define XK_hebrew_resh 0xcf8 +#define XK_hebrew_shin 0xcf9 +#define XK_hebrew_taw 0xcfa +#define XK_hebrew_taf 0xcfa /* deprecated */ +#define XK_Hebrew_switch 0xFF7E /* Alias for mode_switch */ +#endif /* XK_HEBREW */ + +/* + * Thai + * Byte 3 = d + */ + +#ifdef XK_THAI +#define XK_Thai_kokai 0xda1 +#define XK_Thai_khokhai 0xda2 +#define XK_Thai_khokhuat 0xda3 +#define XK_Thai_khokhwai 0xda4 +#define XK_Thai_khokhon 0xda5 +#define XK_Thai_khorakhang 0xda6 +#define XK_Thai_ngongu 0xda7 +#define XK_Thai_chochan 0xda8 +#define XK_Thai_choching 0xda9 +#define XK_Thai_chochang 0xdaa +#define XK_Thai_soso 0xdab +#define XK_Thai_chochoe 0xdac +#define XK_Thai_yoying 0xdad +#define XK_Thai_dochada 0xdae +#define XK_Thai_topatak 0xdaf +#define XK_Thai_thothan 0xdb0 +#define XK_Thai_thonangmontho 0xdb1 +#define XK_Thai_thophuthao 0xdb2 +#define XK_Thai_nonen 0xdb3 +#define XK_Thai_dodek 0xdb4 +#define XK_Thai_totao 0xdb5 +#define XK_Thai_thothung 0xdb6 +#define XK_Thai_thothahan 0xdb7 +#define XK_Thai_thothong 0xdb8 +#define XK_Thai_nonu 0xdb9 +#define XK_Thai_bobaimai 0xdba +#define XK_Thai_popla 0xdbb +#define XK_Thai_phophung 0xdbc +#define XK_Thai_fofa 0xdbd +#define XK_Thai_phophan 0xdbe +#define XK_Thai_fofan 0xdbf +#define XK_Thai_phosamphao 0xdc0 +#define XK_Thai_moma 0xdc1 +#define XK_Thai_yoyak 0xdc2 +#define XK_Thai_rorua 0xdc3 +#define XK_Thai_ru 0xdc4 +#define XK_Thai_loling 0xdc5 +#define XK_Thai_lu 0xdc6 +#define XK_Thai_wowaen 0xdc7 +#define XK_Thai_sosala 0xdc8 +#define XK_Thai_sorusi 0xdc9 +#define XK_Thai_sosua 0xdca +#define XK_Thai_hohip 0xdcb +#define XK_Thai_lochula 0xdcc +#define XK_Thai_oang 0xdcd +#define XK_Thai_honokhuk 0xdce +#define XK_Thai_paiyannoi 0xdcf +#define XK_Thai_saraa 0xdd0 +#define XK_Thai_maihanakat 0xdd1 +#define XK_Thai_saraaa 0xdd2 +#define XK_Thai_saraam 0xdd3 +#define XK_Thai_sarai 0xdd4 +#define XK_Thai_saraii 0xdd5 +#define XK_Thai_saraue 0xdd6 +#define XK_Thai_sarauee 0xdd7 +#define XK_Thai_sarau 0xdd8 +#define XK_Thai_sarauu 0xdd9 +#define XK_Thai_phinthu 0xdda +#define XK_Thai_maihanakat_maitho 0xdde +#define XK_Thai_baht 0xddf +#define XK_Thai_sarae 0xde0 +#define XK_Thai_saraae 0xde1 +#define XK_Thai_sarao 0xde2 +#define XK_Thai_saraaimaimuan 0xde3 +#define XK_Thai_saraaimaimalai 0xde4 +#define XK_Thai_lakkhangyao 0xde5 +#define XK_Thai_maiyamok 0xde6 +#define XK_Thai_maitaikhu 0xde7 +#define XK_Thai_maiek 0xde8 +#define XK_Thai_maitho 0xde9 +#define XK_Thai_maitri 0xdea +#define XK_Thai_maichattawa 0xdeb +#define XK_Thai_thanthakhat 0xdec +#define XK_Thai_nikhahit 0xded +#define XK_Thai_leksun 0xdf0 +#define XK_Thai_leknung 0xdf1 +#define XK_Thai_leksong 0xdf2 +#define XK_Thai_leksam 0xdf3 +#define XK_Thai_leksi 0xdf4 +#define XK_Thai_lekha 0xdf5 +#define XK_Thai_lekhok 0xdf6 +#define XK_Thai_lekchet 0xdf7 +#define XK_Thai_lekpaet 0xdf8 +#define XK_Thai_lekkao 0xdf9 +#endif /* XK_THAI */ + +/* + * Korean + * Byte 3 = e + */ + +#ifdef XK_KOREAN + +#define XK_Hangul 0xff31 /* Hangul start/stop(toggle) */ +#define XK_Hangul_Start 0xff32 /* Hangul start */ +#define XK_Hangul_End 0xff33 /* Hangul end, English start */ +#define XK_Hangul_Hanja 0xff34 /* Start Hangul->Hanja Conversion */ +#define XK_Hangul_Jamo 0xff35 /* Hangul Jamo mode */ +#define XK_Hangul_Romaja 0xff36 /* Hangul Romaja mode */ +#define XK_Hangul_Codeinput 0xff37 /* Hangul code input mode */ +#define XK_Hangul_Jeonja 0xff38 /* Jeonja mode */ +#define XK_Hangul_Banja 0xff39 /* Banja mode */ +#define XK_Hangul_PreHanja 0xff3a /* Pre Hanja conversion */ +#define XK_Hangul_PostHanja 0xff3b /* Post Hanja conversion */ +#define XK_Hangul_SingleCandidate 0xff3c /* Single candidate */ +#define XK_Hangul_MultipleCandidate 0xff3d /* Multiple candidate */ +#define XK_Hangul_PreviousCandidate 0xff3e /* Previous candidate */ +#define XK_Hangul_Special 0xff3f /* Special symbols */ +#define XK_Hangul_switch 0xFF7E /* Alias for mode_switch */ + +/* Hangul Consonant Characters */ +#define XK_Hangul_Kiyeog 0xea1 +#define XK_Hangul_SsangKiyeog 0xea2 +#define XK_Hangul_KiyeogSios 0xea3 +#define XK_Hangul_Nieun 0xea4 +#define XK_Hangul_NieunJieuj 0xea5 +#define XK_Hangul_NieunHieuh 0xea6 +#define XK_Hangul_Dikeud 0xea7 +#define XK_Hangul_SsangDikeud 0xea8 +#define XK_Hangul_Rieul 0xea9 +#define XK_Hangul_RieulKiyeog 0xeaa +#define XK_Hangul_RieulMieum 0xeab +#define XK_Hangul_RieulPieub 0xeac +#define XK_Hangul_RieulSios 0xead +#define XK_Hangul_RieulTieut 0xeae +#define XK_Hangul_RieulPhieuf 0xeaf +#define XK_Hangul_RieulHieuh 0xeb0 +#define XK_Hangul_Mieum 0xeb1 +#define XK_Hangul_Pieub 0xeb2 +#define XK_Hangul_SsangPieub 0xeb3 +#define XK_Hangul_PieubSios 0xeb4 +#define XK_Hangul_Sios 0xeb5 +#define XK_Hangul_SsangSios 0xeb6 +#define XK_Hangul_Ieung 0xeb7 +#define XK_Hangul_Jieuj 0xeb8 +#define XK_Hangul_SsangJieuj 0xeb9 +#define XK_Hangul_Cieuc 0xeba +#define XK_Hangul_Khieuq 0xebb +#define XK_Hangul_Tieut 0xebc +#define XK_Hangul_Phieuf 0xebd +#define XK_Hangul_Hieuh 0xebe + +/* Hangul Vowel Characters */ +#define XK_Hangul_A 0xebf +#define XK_Hangul_AE 0xec0 +#define XK_Hangul_YA 0xec1 +#define XK_Hangul_YAE 0xec2 +#define XK_Hangul_EO 0xec3 +#define XK_Hangul_E 0xec4 +#define XK_Hangul_YEO 0xec5 +#define XK_Hangul_YE 0xec6 +#define XK_Hangul_O 0xec7 +#define XK_Hangul_WA 0xec8 +#define XK_Hangul_WAE 0xec9 +#define XK_Hangul_OE 0xeca +#define XK_Hangul_YO 0xecb +#define XK_Hangul_U 0xecc +#define XK_Hangul_WEO 0xecd +#define XK_Hangul_WE 0xece +#define XK_Hangul_WI 0xecf +#define XK_Hangul_YU 0xed0 +#define XK_Hangul_EU 0xed1 +#define XK_Hangul_YI 0xed2 +#define XK_Hangul_I 0xed3 + +/* Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_Kiyeog 0xed4 +#define XK_Hangul_J_SsangKiyeog 0xed5 +#define XK_Hangul_J_KiyeogSios 0xed6 +#define XK_Hangul_J_Nieun 0xed7 +#define XK_Hangul_J_NieunJieuj 0xed8 +#define XK_Hangul_J_NieunHieuh 0xed9 +#define XK_Hangul_J_Dikeud 0xeda +#define XK_Hangul_J_Rieul 0xedb +#define XK_Hangul_J_RieulKiyeog 0xedc +#define XK_Hangul_J_RieulMieum 0xedd +#define XK_Hangul_J_RieulPieub 0xede +#define XK_Hangul_J_RieulSios 0xedf +#define XK_Hangul_J_RieulTieut 0xee0 +#define XK_Hangul_J_RieulPhieuf 0xee1 +#define XK_Hangul_J_RieulHieuh 0xee2 +#define XK_Hangul_J_Mieum 0xee3 +#define XK_Hangul_J_Pieub 0xee4 +#define XK_Hangul_J_PieubSios 0xee5 +#define XK_Hangul_J_Sios 0xee6 +#define XK_Hangul_J_SsangSios 0xee7 +#define XK_Hangul_J_Ieung 0xee8 +#define XK_Hangul_J_Jieuj 0xee9 +#define XK_Hangul_J_Cieuc 0xeea +#define XK_Hangul_J_Khieuq 0xeeb +#define XK_Hangul_J_Tieut 0xeec +#define XK_Hangul_J_Phieuf 0xeed +#define XK_Hangul_J_Hieuh 0xeee + +/* Ancient Hangul Consonant Characters */ +#define XK_Hangul_RieulYeorinHieuh 0xeef +#define XK_Hangul_SunkyeongeumMieum 0xef0 +#define XK_Hangul_SunkyeongeumPieub 0xef1 +#define XK_Hangul_PanSios 0xef2 +#define XK_Hangul_KkogjiDalrinIeung 0xef3 +#define XK_Hangul_SunkyeongeumPhieuf 0xef4 +#define XK_Hangul_YeorinHieuh 0xef5 + +/* Ancient Hangul Vowel Characters */ +#define XK_Hangul_AraeA 0xef6 +#define XK_Hangul_AraeAE 0xef7 + +/* Ancient Hangul syllable-final (JongSeong) Characters */ +#define XK_Hangul_J_PanSios 0xef8 +#define XK_Hangul_J_KkogjiDalrinIeung 0xef9 +#define XK_Hangul_J_YeorinHieuh 0xefa + +/* Korean currency symbol */ +#define XK_Korean_Won 0xeff + +#endif /* XK_KOREAN */ + +/* Euro currency symbol */ +#define XK_EuroSign 0x20ac + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h new file mode 100755 index 0000000..797416a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfb.h @@ -0,0 +1,1044 @@ +#ifndef RFB_H +#define RFB_H + +/* + * rfb.h - header file for RFB DDX implementation. + */ + +/* + * Copyright (C) 2005 Rohit Kumar , + * Johannes E. Schindelin + * Copyright (C) 2002 RealVNC Ltd. + * OSXvnc Copyright (C) 2001 Dan McGuirk . + * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge. + * All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#if(defined __cplusplus) +extern "C" +{ +#endif + +#include +#include +#include +#include + +#ifdef LIBVNCSERVER_HAVE_SYS_TYPES_H +#include +#endif + +#ifdef ANDROID +#include +#include +#endif + +#ifdef __MINGW32__ +#undef SOCKET +#include +#endif + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS +#include +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#include +#if 0 /* debugging */ +#define LOCK(mutex) (rfbLog("%s:%d LOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_lock(&(mutex))) +#define UNLOCK(mutex) (rfbLog("%s:%d UNLOCK(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_unlock(&(mutex))) +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) (rfbLog("%s:%d INIT_MUTEX(%s,0x%x)\n",__FILE__,__LINE__,#mutex,&(mutex)), pthread_mutex_init(&(mutex),NULL)) +#define TINI_MUTEX(mutex) (rfbLog("%s:%d TINI_MUTEX(%s)\n",__FILE__,__LINE__,#mutex), pthread_mutex_destroy(&(mutex))) +#define TSIGNAL(cond) (rfbLog("%s:%d TSIGNAL(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_signal(&(cond))) +#define WAIT(cond,mutex) (rfbLog("%s:%d WAIT(%s,%s)\n",__FILE__,__LINE__,#cond,#mutex), pthread_cond_wait(&(cond),&(mutex))) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) (rfbLog("%s:%d INIT_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_init(&(cond),NULL)) +#define TINI_COND(cond) (rfbLog("%s:%d TINI_COND(%s)\n",__FILE__,__LINE__,#cond), pthread_cond_destroy(&(cond))) +#define IF_PTHREADS(x) x +#else +#if !NONETWORK +#define LOCK(mutex) pthread_mutex_lock(&(mutex)); +#define UNLOCK(mutex) pthread_mutex_unlock(&(mutex)); +#endif +#define MUTEX(mutex) pthread_mutex_t (mutex) +#define INIT_MUTEX(mutex) pthread_mutex_init(&(mutex),NULL) +#define TINI_MUTEX(mutex) pthread_mutex_destroy(&(mutex)) +#define TSIGNAL(cond) pthread_cond_signal(&(cond)) +#define WAIT(cond,mutex) pthread_cond_wait(&(cond),&(mutex)) +#define COND(cond) pthread_cond_t (cond) +#define INIT_COND(cond) pthread_cond_init(&(cond),NULL) +#define TINI_COND(cond) pthread_cond_destroy(&(cond)) +#define IF_PTHREADS(x) x +#endif +#else +#define LOCK(mutex) +#define UNLOCK(mutex) +#define MUTEX(mutex) +#define INIT_MUTEX(mutex) +#define TINI_MUTEX(mutex) +#define TSIGNAL(cond) +#define WAIT(cond,mutex) this_is_unsupported +#define COND(cond) +#define INIT_COND(cond) +#define TINI_COND(cond) +#define IF_PTHREADS(x) +#endif + +/* end of stuff for autoconf */ + +/* if you use pthreads, but don't define LIBVNCSERVER_HAVE_LIBPTHREAD, the structs + get all mixed up. So this gives a linker error reminding you to compile + the library and your application (at least the parts including rfb.h) + with the same support for pthreads. */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithPthreadsAndZRLE +#else +#define rfbInitServer rfbInitServerWithPthreadsButWithoutZRLE +#endif +#else +#ifdef LIBVNCSERVER_HAVE_LIBZ +#define rfbInitServer rfbInitServerWithoutPthreadsButWithZRLE +#else +#define rfbInitServer rfbInitServerWithoutPthreadsAndZRLE +#endif +#endif + +struct _rfbClientRec; +struct _rfbScreenInfo; +struct rfbCursor; + +enum rfbNewClientAction { + RFB_CLIENT_ACCEPT, + RFB_CLIENT_ON_HOLD, + RFB_CLIENT_REFUSE +}; + +enum rfbSocketState { + RFB_SOCKET_INIT, + RFB_SOCKET_READY, + RFB_SOCKET_SHUTDOWN +}; + +typedef void (*rfbKbdAddEventProcPtr) (rfbBool down, rfbKeySym keySym, struct _rfbClientRec* cl); +typedef void (*rfbKbdReleaseAllKeysProcPtr) (struct _rfbClientRec* cl); +typedef void (*rfbPtrAddEventProcPtr) (int buttonMask, int x, int y, struct _rfbClientRec* cl); +typedef void (*rfbSetXCutTextProcPtr) (char* str,int len, struct _rfbClientRec* cl); +typedef struct rfbCursor* (*rfbGetCursorProcPtr) (struct _rfbClientRec* pScreen); +typedef rfbBool (*rfbSetTranslateFunctionProcPtr)(struct _rfbClientRec* cl); +typedef rfbBool (*rfbPasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len); +typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl); +typedef void (*rfbDisplayFinishedHookPtr)(struct _rfbClientRec* cl, int result); +/* support the capability to view the caps/num/scroll states of the X server */ +typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen); +/* If x==1 and y==1 then set the whole display + * else find the window underneath x and y and set the framebuffer to the dimensions + * of that window + */ +typedef void (*rfbSetSingleWindowProcPtr) (struct _rfbClientRec* cl, int x, int y); +/* Status determines if the X11 server permits input from the local user + * status==0 or 1 + */ +typedef void (*rfbSetServerInputProcPtr) (struct _rfbClientRec* cl, int status); +/* Permit the server to allow or deny filetransfers. This is defaulted to deny + * It is called when a client initiates a connection to determine if it is permitted. + */ +typedef int (*rfbFileTransferPermitted) (struct _rfbClientRec* cl); +/* Handle the textchat messages */ +typedef void (*rfbSetTextChat) (struct _rfbClientRec* cl, int length, char *string); + +typedef struct { + uint32_t count; + rfbBool is16; /* is the data format short? */ + union { + uint8_t* bytes; + uint16_t* shorts; + } data; /* there have to be count*3 entries */ +} rfbColourMap; + +/* + * Security handling (RFB protocol version 3.7) + */ + +typedef struct _rfbSecurity { + uint8_t type; + void (*handler)(struct _rfbClientRec* cl); + struct _rfbSecurity* next; +} rfbSecurityHandler; + +/* + * Protocol extension handling. + */ + +typedef struct _rfbProtocolExtension { + /* returns FALSE if extension should be deactivated for client. + if newClient == NULL, it is always deactivated. */ + rfbBool (*newClient)(struct _rfbClientRec* client, void** data); + /* returns FALSE if extension should be deactivated for client. + if init == NULL, it stays activated. */ + rfbBool (*init)(struct _rfbClientRec* client, void* data); + /* if pseudoEncodings is not NULL, it contains a 0 terminated + list of the pseudo encodings handled by this extension. */ + int *pseudoEncodings; + /* returns TRUE if that pseudo encoding is handled by the extension. + encodingNumber==0 means "reset encodings". */ + rfbBool (*enablePseudoEncoding)(struct _rfbClientRec* client, + void** data, int encodingNumber); + /* returns TRUE if message was handled */ + rfbBool (*handleMessage)(struct _rfbClientRec* client, + void* data, + const rfbClientToServerMsg* message); + void (*close)(struct _rfbClientRec* client, void* data); + void (*usage)(void); + /* processArguments returns the number of handled arguments */ + int (*processArgument)(int argc, char *argv[]); + struct _rfbProtocolExtension* next; +} rfbProtocolExtension; + +typedef struct _rfbExtensionData { + rfbProtocolExtension* extension; + void* data; + struct _rfbExtensionData* next; +} rfbExtensionData; + +/* + * Per-screen (framebuffer) structure. There can be as many as you wish, + * each serving different clients. However, you have to call + * rfbProcessEvents for each of these. + */ + +typedef struct _rfbScreenInfo +{ + /* this structure has children that are scaled versions of this screen */ + struct _rfbScreenInfo *scaledScreenNext; + int scaledScreenRefCount; + + int width; + int paddedWidthInBytes; + int height; + int depth; + int bitsPerPixel; + int sizeInBytes; + + rfbPixel blackPixel; + rfbPixel whitePixel; + + /* some screen specific data can be put into a struct where screenData + * points to. You need this if you have more than one screen at the + * same time while using the same functions. + */ + void* screenData; + + /* additions by libvncserver */ + + rfbPixelFormat serverFormat; + rfbColourMap colourMap; /* set this if rfbServerFormat.trueColour==FALSE */ + const char* desktopName; + char thisHost[255]; + + rfbBool autoPort; + int port; + SOCKET listenSock; + int maxSock; + int maxFd; +#ifdef __MINGW32__ + struct fd_set allFds; +#else + fd_set allFds; +#endif + + enum rfbSocketState socketState; + SOCKET inetdSock; + rfbBool inetdInitDone; + + int udpPort; + SOCKET udpSock; + struct _rfbClientRec* udpClient; + rfbBool udpSockConnected; + struct sockaddr_in udpRemoteAddr; + + int maxClientWait; + + /* http stuff */ + rfbBool httpInitDone; + rfbBool httpEnableProxyConnect; + int httpPort; + char* httpDir; + SOCKET httpListenSock; + SOCKET httpSock; + + rfbPasswordCheckProcPtr passwordCheck; + void* authPasswdData; + /* If rfbAuthPasswdData is given a list, this is the first + view only password. */ + int authPasswdFirstViewOnly; + + /* send only this many rectangles in one update */ + int maxRectsPerUpdate; + /* this is the amount of milliseconds to wait at least before sending + * an update. */ + int deferUpdateTime; +#ifdef TODELETE + char* screen; +#endif + rfbBool alwaysShared; + rfbBool neverShared; + rfbBool dontDisconnect; + struct _rfbClientRec* clientHead; + struct _rfbClientRec* pointerClient; /* "Mutex" for pointer events */ + + + /* cursor */ + int cursorX, cursorY,underCursorBufferLen; + char* underCursorBuffer; + rfbBool dontConvertRichCursorToXCursor; + struct rfbCursor* cursor; + + /* the frameBufferhas to be supplied by the serving process. + * The buffer will not be freed by + */ + char* frameBuffer; + rfbKbdAddEventProcPtr kbdAddEvent; + rfbKbdReleaseAllKeysProcPtr kbdReleaseAllKeys; + rfbPtrAddEventProcPtr ptrAddEvent; + rfbSetXCutTextProcPtr setXCutText; + rfbGetCursorProcPtr getCursorPtr; + rfbSetTranslateFunctionProcPtr setTranslateFunction; + rfbSetSingleWindowProcPtr setSingleWindow; + rfbSetServerInputProcPtr setServerInput; + rfbFileTransferPermitted getFileTransferPermission; + rfbSetTextChat setTextChat; + + /* newClientHook is called just after a new client is created */ + rfbNewClientHookPtr newClientHook; + /* displayHook is called just before a frame buffer update */ + rfbDisplayHookPtr displayHook; + + /* These hooks are called to pass keyboard state back to the client */ + rfbGetKeyboardLedStateHookPtr getKeyboardLedStateHook; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + MUTEX(cursorMutex); + rfbBool backgroundLoop; +#endif + + /* if TRUE, an ignoring signal handler is installed for SIGPIPE */ + rfbBool ignoreSIGPIPE; + + /* if not zero, only a slice of this height is processed every time + * an update should be sent. This should make working on a slow + * link more interactive. */ + int progressiveSliceHeight; + + in_addr_t listenInterface; + int deferPtrUpdateTime; + + /* handle as many input events as possible (default off) */ + rfbBool handleEventsEagerly; + + /* rfbEncodingServerIdentity */ + char *versionString; + + /* What does the server tell the new clients which version it supports */ + int protocolMajorVersion; + int protocolMinorVersion; + + /* command line authorization of file transfers */ + rfbBool permitFileTransfer; + + /* displayFinishedHook is called just after a frame buffer update */ + rfbDisplayFinishedHookPtr displayFinishedHook; +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + char *sslkeyfile; + char *sslcertfile; +#endif +} rfbScreenInfo, *rfbScreenInfoPtr; + + +/* + * rfbTranslateFnType is the type of translation functions. + */ + +typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); + + +/* region stuff */ + +struct sraRegion; +typedef struct sraRegion* sraRegionPtr; + +/* + * Per-client structure. + */ + +typedef void (*ClientGoneHookPtr)(struct _rfbClientRec* cl); + +typedef struct _rfbFileTransferData { + int fd; + int compressionEnabled; + int fileSize; + int numPackets; + int receiving; + int sending; +} rfbFileTransferData; + + +typedef struct _rfbStatList { + uint32_t type; + uint32_t sentCount; + uint32_t bytesSent; + uint32_t bytesSentIfRaw; + uint32_t rcvdCount; + uint32_t bytesRcvd; + uint32_t bytesRcvdIfRaw; + struct _rfbStatList *Next; +} rfbStatList; + +typedef struct _rfbClientRec { + + /* back pointer to the screen */ + rfbScreenInfoPtr screen; + + /* points to a scaled version of the screen buffer in cl->scaledScreenList */ + rfbScreenInfoPtr scaledScreen; + /* how did the client tell us it wanted the screen changed? Ultra style or palm style? */ + rfbBool PalmVNC; + + + /* private data. You should put any application client specific data + * into a struct and let clientData point to it. Don't forget to + * free the struct via clientGoneHook! + * + * This is useful if the IO functions have to behave client specific. + */ + void* clientData; + ClientGoneHookPtr clientGoneHook; + + SOCKET sock; + char *host; + + /* RFB protocol minor version number */ + int protocolMajorVersion; + int protocolMinorVersion; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + pthread_t client_thread; +#endif + /* Possible client states: */ + enum { + RFB_PROTOCOL_VERSION, /* establishing protocol version */ + RFB_SECURITY_TYPE, /* negotiating security (RFB v.3.7) */ + RFB_AUTHENTICATION, /* authenticating */ + RFB_INITIALISATION, /* sending initialisation messages */ + RFB_NORMAL /* normal protocol messages */ + } state; + + rfbBool reverseConnection; + rfbBool onHold; + rfbBool readyForSetColourMapEntries; + rfbBool useCopyRect; + int preferredEncoding; + int correMaxWidth, correMaxHeight; + + rfbBool viewOnly; + + /* The following member is only used during VNC authentication */ + uint8_t authChallenge[CHALLENGESIZE]; + + /* The following members represent the update needed to get the client's + framebuffer from its present state to the current state of our + framebuffer. + + If the client does not accept CopyRect encoding then the update is + simply represented as the region of the screen which has been modified + (modifiedRegion). + + If the client does accept CopyRect encoding, then the update consists of + two parts. First we have a single copy from one region of the screen to + another (the destination of the copy is copyRegion), and second we have + the region of the screen which has been modified in some other way + (modifiedRegion). + + Although the copy is of a single region, this region may have many + rectangles. When sending an update, the copyRegion is always sent + before the modifiedRegion. This is because the modifiedRegion may + overlap parts of the screen which are in the source of the copy. + + In fact during normal processing, the modifiedRegion may even overlap + the destination copyRegion. Just before an update is sent we remove + from the copyRegion anything in the modifiedRegion. */ + + sraRegionPtr copyRegion; /* the destination region of the copy */ + int copyDX, copyDY; /* the translation by which the copy happens */ + + sraRegionPtr modifiedRegion; + + /* As part of the FramebufferUpdateRequest, a client can express interest + in a subrectangle of the whole framebuffer. This is stored in the + requestedRegion member. In the normal case this is the whole + framebuffer if the client is ready, empty if it's not. */ + + sraRegionPtr requestedRegion; + + /* The following member represents the state of the "deferred update" timer + - when the framebuffer is modified and the client is ready, in most + cases it is more efficient to defer sending the update by a few + milliseconds so that several changes to the framebuffer can be combined + into a single update. */ + + struct timeval startDeferring; + struct timeval startPtrDeferring; + int lastPtrX; + int lastPtrY; + int lastPtrButtons; + + /* translateFn points to the translation function which is used to copy + and translate a rectangle from the framebuffer to an output buffer. */ + + rfbTranslateFnType translateFn; + char *translateLookupTable; + rfbPixelFormat format; + + /* + * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the + * framebuffer. So for a max screen width of say 2K with 32-bit pixels this + * means 8K minimum. + */ + +#define UPDATE_BUF_SIZE 30000 + + char updateBuf[UPDATE_BUF_SIZE]; + int ublen; + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS + rfbBool webSockets; + rfbBool webSocketsSSL; + rfbBool webSocketsBase64; + + SSL_CTX *ssl_ctx; + SSL *ssl; + + char *keyfile; + char *certfile; + char encodeBuf[UPDATE_BUF_SIZE*2 + 2]; // UTF-8 could double it + framing + char decodeBuf[8192]; // TODO: what makes sense? + int dblen; + char carryBuf[3]; // For base64 carry-over + int carrylen; +#endif + + + /* statistics */ + struct _rfbStatList *statEncList; + struct _rfbStatList *statMsgList; + int rawBytesEquivalent; + int bytesSent; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* zlib encoding -- necessary compression state info per client */ + + struct z_stream_s compStream; + rfbBool compStreamInited; + uint32_t zlibCompressLevel; +#endif +#if defined(LIBVNCSERVER_HAVE_LIBZ) || defined(LIBVNCSERVER_HAVE_LIBPNG) + uint32_t tightEncoding; /* rfbEncodingTight or rfbEncodingTightPng */ + /* the quality level is also used by ZYWRLE and TightPng */ + int tightQualityLevel; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* tight encoding -- preserve zlib streams' state for each client */ + z_stream zsStruct[4]; + rfbBool zsActive[4]; + int zsLevel[4]; +#endif +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) + int tightCompressLevel; +#endif +#endif + + /* Ultra Encoding support */ + rfbBool compStreamInitedLZO; + char *lzoWrkMem; + + rfbFileTransferData fileTransfer; + + int lastKeyboardLedState; /* keep track of last value so we can send *change* events */ + rfbBool enableSupportedMessages; /* client supports SupportedMessages encoding */ + rfbBool enableSupportedEncodings; /* client supports SupportedEncodings encoding */ + rfbBool enableServerIdentity; /* client supports ServerIdentity encoding */ + rfbBool enableKeyboardLedState; /* client supports KeyboardState encoding */ + rfbBool enableLastRectEncoding; /* client supports LastRect encoding */ + rfbBool enableCursorShapeUpdates; /* client supports cursor shape updates */ + rfbBool enableCursorPosUpdates; /* client supports cursor position updates */ + rfbBool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */ + rfbBool cursorWasChanged; /* cursor shape update should be sent */ + rfbBool cursorWasMoved; /* cursor position update should be sent */ + int cursorX,cursorY; /* the coordinates of the cursor, + if enableCursorShapeUpdates = FALSE */ + + rfbBool useNewFBSize; /* client supports NewFBSize encoding */ + rfbBool newFBSizePending; /* framebuffer size was changed */ + + struct _rfbClientRec *prev; + struct _rfbClientRec *next; + +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD + /* whenever a client is referenced, the refCount has to be incremented + and afterwards decremented, so that the client is not cleaned up + while being referenced. + Use the functions rfbIncrClientRef(cl) and rfbDecrClientRef(cl); + */ + int refCount; + MUTEX(refCountMutex); + COND(deleteCond); + + MUTEX(outputMutex); + MUTEX(updateMutex); + COND(updateCond); +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ + void* zrleData; + int zywrleLevel; + int zywrleBuf[rfbZRLETileWidth * rfbZRLETileHeight]; +#endif + + /* if progressive updating is on, this variable holds the current + * y coordinate of the progressive slice. */ + int progressiveSliceY; + + rfbExtensionData* extensions; + + /* for threaded zrle */ + char *zrleBeforeBuf; + void *paletteHelper; + + /* for thread safety for rfbSendFBUpdate() */ +#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD +#define LIBVNCSERVER_SEND_MUTEX + MUTEX(sendMutex); +#endif + +} rfbClientRec, *rfbClientPtr; + +/* + * This macro is used to test whether there is a framebuffer update needing to + * be sent to the client. + */ + +#define FB_UPDATE_PENDING(cl) \ + (((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \ + (((cl)->enableCursorShapeUpdates == FALSE && \ + ((cl)->cursorX != (cl)->screen->cursorX || \ + (cl)->cursorY != (cl)->screen->cursorY))) || \ + ((cl)->useNewFBSize && (cl)->newFBSizePending) || \ + ((cl)->enableCursorPosUpdates && (cl)->cursorWasMoved) || \ + !sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion)) + +/* + * Macros for endian swapping. + */ + +#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) + +#define Swap24(l) ((((l) & 0xff) << 16) | (((l) >> 16) & 0xff) | \ + (((l) & 0x00ff00))) + +#define Swap32(l) (((l) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + ((l) << 24)) + + +extern char rfbEndianTest; + +#define Swap16IfLE(s) (rfbEndianTest ? Swap16(s) : (s)) +#define Swap24IfLE(l) (rfbEndianTest ? Swap24(l) : (l)) +#define Swap32IfLE(l) (rfbEndianTest ? Swap32(l) : (l)) + +/* UltraVNC uses some windows structures unmodified, so the viewer expects LittleEndian Data */ +#define Swap16IfBE(s) (rfbEndianTest ? (s) : Swap16(s)) +#define Swap24IfBE(l) (rfbEndianTest ? (l) : Swap24(l)) +#define Swap32IfBE(l) (rfbEndianTest ? (l) : Swap32(l)) + +/* sockets.c */ + +extern int rfbMaxClientWait; + +extern void rfbInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbDisconnectUDPSock(rfbScreenInfoPtr rfbScreen); +extern void rfbCloseClient(rfbClientPtr cl); +extern int rfbReadExact(rfbClientPtr cl, char *buf, int len); +extern int rfbReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbPeekExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout); +extern int rfbWriteExact(rfbClientPtr cl, const char *buf, int len); +extern int rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec); +extern int rfbConnect(rfbScreenInfoPtr rfbScreen, char* host, int port); +extern int rfbConnectToTcpAddr(char* host, int port); +extern int rfbListenOnTCPPort(int port, in_addr_t iface); +extern int rfbListenOnUDPPort(int port, in_addr_t iface); +extern int rfbStringToAddr(char* string,in_addr_t* addr); + +#ifdef LIBVNCSERVER_WITH_WEBSOCKETS +/* websockets.c */ + +extern rfbBool webSocketsCheck(rfbClientPtr cl); +extern int webSocketsEncode(rfbClientPtr cl, const char *src, int len); +extern int webSocketsDecode(rfbClientPtr cl, char *dst, int len); +#endif + +/* rfbserver.c */ + +/* Routines to iterate over the client list in a thread-safe way. + Only a single iterator can be in use at a time process-wide. */ +typedef struct rfbClientIterator *rfbClientIteratorPtr; + +extern void rfbClientListInit(rfbScreenInfoPtr rfbScreen); +extern rfbClientIteratorPtr rfbGetClientIterator(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbClientIteratorNext(rfbClientIteratorPtr iterator); +extern void rfbReleaseClientIterator(rfbClientIteratorPtr iterator); +extern void rfbIncrClientRef(rfbClientPtr cl); +extern void rfbDecrClientRef(rfbClientPtr cl); + +extern void rfbNewClientConnection(rfbScreenInfoPtr rfbScreen,int sock); +extern rfbClientPtr rfbNewClient(rfbScreenInfoPtr rfbScreen,int sock); +extern rfbClientPtr rfbNewUDPClient(rfbScreenInfoPtr rfbScreen); +extern rfbClientPtr rfbReverseConnection(rfbScreenInfoPtr rfbScreen,char *host, int port); +extern void rfbClientConnectionGone(rfbClientPtr cl); +extern void rfbProcessClientMessage(rfbClientPtr cl); +extern void rfbClientConnFailed(rfbClientPtr cl, char *reason); +extern void rfbNewUDPConnection(rfbScreenInfoPtr rfbScreen,int sock); +extern void rfbProcessUDPInput(rfbScreenInfoPtr rfbScreen); +extern rfbBool rfbSendFramebufferUpdate(rfbClientPtr cl, sraRegionPtr updateRegion); +extern rfbBool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h); +extern rfbBool rfbSendUpdateBuf(rfbClientPtr cl); +extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len); +extern rfbBool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy); +extern rfbBool rfbSendLastRectMarker(rfbClientPtr cl); +extern rfbBool rfbSendNewFBSize(rfbClientPtr cl, int w, int h); +extern rfbBool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSendBell(rfbScreenInfoPtr rfbScreen); + +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbSendFileTransferChunk(rfbClientPtr cl); +extern rfbBool rfbSendDirContent(rfbClientPtr cl, int length, char *buffer); +extern rfbBool rfbSendFileTransferMessage(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length, char *buffer); +extern char *rfbProcessFileTransferReadBuffer(rfbClientPtr cl, uint32_t length); +extern rfbBool rfbProcessFileTransfer(rfbClientPtr cl, uint8_t contentType, uint8_t contentParam, uint32_t size, uint32_t length); + +void rfbGotXCutText(rfbScreenInfoPtr rfbScreen, char *str, int len); + +/* translate.c */ + +extern rfbBool rfbEconomicTranslate; + +extern void rfbTranslateNone(char *table, rfbPixelFormat *in, + rfbPixelFormat *out, + char *iptr, char *optr, + int bytesBetweenInputLines, + int width, int height); +extern rfbBool rfbSetTranslateFunction(rfbClientPtr cl); +extern rfbBool rfbSetClientColourMap(rfbClientPtr cl, int firstColour, int nColours); +extern void rfbSetClientColourMaps(rfbScreenInfoPtr rfbScreen, int firstColour, int nColours); + +/* httpd.c */ + +extern void rfbHttpInitSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpShutdownSockets(rfbScreenInfoPtr rfbScreen); +extern void rfbHttpCheckFds(rfbScreenInfoPtr rfbScreen); + + + +/* auth.c */ + +extern void rfbAuthNewClient(rfbClientPtr cl); +extern void rfbProcessClientSecurityType(rfbClientPtr cl); +extern void rfbAuthProcessClientMessage(rfbClientPtr cl); +extern void rfbRegisterSecurityHandler(rfbSecurityHandler* handler); +extern void rfbUnregisterSecurityHandler(rfbSecurityHandler* handler); + +/* rre.c */ + +extern rfbBool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* corre.c */ + +extern rfbBool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h); + + +/* hextile.c */ + +extern rfbBool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w, + int h); + +/* ultra.c */ + +/* Set maximum ultra rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ULTRA_MAX_RECT_SIZE (128*256) +#define ULTRA_MAX_SIZE(min) ((( min * 2 ) > ULTRA_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ULTRA_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingUltra(rfbClientPtr cl, int x,int y,int w,int h); + + +#ifdef LIBVNCSERVER_HAVE_LIBZ +/* zlib.c */ + +/* Minimum zlib rectangle size in bytes. Anything smaller will + * not compress well due to overhead. + */ +#define VNC_ENCODE_ZLIB_MIN_COMP_SIZE (17) + +/* Set maximum zlib rectangle size in pixels. Always allow at least + * two scan lines. + */ +#define ZLIB_MAX_RECT_SIZE (128*256) +#define ZLIB_MAX_SIZE(min) ((( min * 2 ) > ZLIB_MAX_RECT_SIZE ) ? \ + ( min * 2 ) : ZLIB_MAX_RECT_SIZE ) + +extern rfbBool rfbSendRectEncodingZlib(rfbClientPtr cl, int x, int y, int w, + int h); + +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) || defined(LIBVNCSERVER_HAVE_LIBPNG) +/* tight.c */ + +#define TIGHT_DEFAULT_COMPRESSION 6 + +extern rfbBool rfbTightDisableGradient; + +extern int rfbNumCodedRectsTight(rfbClientPtr cl, int x,int y,int w,int h); + +#if defined(LIBVNCSERVER_HAVE_LIBJPEG) +extern rfbBool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h); +#endif +#if defined(LIBVNCSERVER_HAVE_LIBPNG) +extern rfbBool rfbSendRectEncodingTightPng(rfbClientPtr cl, int x,int y,int w,int h); +#endif + +#endif +#endif + + +/* cursor.c */ + +typedef struct rfbCursor { + /* set this to true if LibVNCServer has to free this cursor */ + rfbBool cleanup, cleanupSource, cleanupMask, cleanupRichSource; + unsigned char *source; /* points to bits */ + unsigned char *mask; /* points to bits */ + unsigned short width, height, xhot, yhot; /* metrics */ + unsigned short foreRed, foreGreen, foreBlue; /* device-independent colour */ + unsigned short backRed, backGreen, backBlue; /* device-independent colour */ + unsigned char *richSource; /* source bytes for a rich cursor */ + unsigned char *alphaSource; /* source for alpha blending info */ + rfbBool alphaPreMultiplied; /* if richSource already has alpha applied */ +} rfbCursor, *rfbCursorPtr; +extern unsigned char rfbReverseByte[0x100]; + +extern rfbBool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/); +extern rfbBool rfbSendCursorPos(rfbClientPtr cl); +extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap); +extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString); +extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString); +extern char* rfbMakeMaskFromAlphaSource(int width,int height,unsigned char* alphaSource); +extern void rfbMakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbMakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor); +extern void rfbFreeCursor(rfbCursorPtr cursor); +extern void rfbSetCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr c); + +/* cursor handling for the pointer */ +extern void rfbDefaultPtrAddEvent(int buttonMask,int x,int y,rfbClientPtr cl); + +/* zrle.c */ +#ifdef LIBVNCSERVER_HAVE_LIBZ +extern rfbBool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w,int h); +#endif + +/* stats.c */ + +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +/* font.c */ + +typedef struct rfbFontData { + unsigned char* data; + /* + metaData is a 256*5 array: + for each character + (offset,width,height,x,y) + */ + int* metaData; +} rfbFontData,* rfbFontDataPtr; + +int rfbDrawChar(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,rfbPixel colour); +void rfbDrawString(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,rfbPixel colour); +/* if colour==backColour, background is transparent */ +int rfbDrawCharWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,unsigned char c,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +void rfbDrawStringWithClip(rfbScreenInfoPtr rfbScreen,rfbFontDataPtr font,int x,int y,const char* string,int x1,int y1,int x2,int y2,rfbPixel colour,rfbPixel backColour); +int rfbWidthOfString(rfbFontDataPtr font,const char* string); +int rfbWidthOfChar(rfbFontDataPtr font,unsigned char c); +void rfbFontBBox(rfbFontDataPtr font,unsigned char c,int* x1,int* y1,int* x2,int* y2); +/* this returns the smallest box enclosing any character of font. */ +void rfbWholeFontBBox(rfbFontDataPtr font,int *x1, int *y1, int *x2, int *y2); + +/* dynamically load a linux console font (4096 bytes, 256 glyphs a 8x16 */ +rfbFontDataPtr rfbLoadConsoleFont(char *filename); +/* free a dynamically loaded font */ +void rfbFreeFont(rfbFontDataPtr font); + +/* draw.c */ + +void rfbFillRect(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); +void rfbDrawPixel(rfbScreenInfoPtr s,int x,int y,rfbPixel col); +void rfbDrawLine(rfbScreenInfoPtr s,int x1,int y1,int x2,int y2,rfbPixel col); + +/* selbox.c */ + +/* this opens a modal select box. list is an array of strings, the end marked + with a NULL. + It returns the index in the list or -1 if cancelled or something else + wasn't kosher. */ +typedef void (*SelectionChangedHookPtr)(int _index); +extern int rfbSelectBox(rfbScreenInfoPtr rfbScreen, + rfbFontDataPtr font, char** list, + int x1, int y1, int x2, int y2, + rfbPixel foreColour, rfbPixel backColour, + int border,SelectionChangedHookPtr selChangedHook); + +/* cargs.c */ + +extern void rfbUsage(void); +extern void rfbPurgeArguments(int* argc,int* position,int count,char *argv[]); +extern rfbBool rfbProcessArguments(rfbScreenInfoPtr rfbScreen,int* argc, char *argv[]); +extern rfbBool rfbProcessSizeArguments(int* width,int* height,int* bpp,int* argc, char *argv[]); + +/* main.c */ + +extern void rfbLogEnable(int enabled); +typedef void (*rfbLogProc)(const char *format, ...); +extern rfbLogProc rfbLog, rfbErr; +extern void rfbLogPerror(const char *str); + +void rfbScheduleCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbScheduleCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbDoCopyRect(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2,int dx,int dy); +void rfbDoCopyRegion(rfbScreenInfoPtr rfbScreen,sraRegionPtr copyRegion,int dx,int dy); + +void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y2); +void rfbMarkRegionAsModified(rfbScreenInfoPtr rfbScreen,sraRegionPtr modRegion); +void rfbDoNothingWithClient(rfbClientPtr cl); +enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl); +void rfbRegisterProtocolExtension(rfbProtocolExtension* extension); +void rfbUnregisterProtocolExtension(rfbProtocolExtension* extension); +struct _rfbProtocolExtension* rfbGetExtensionIterator(); +void rfbReleaseExtensionIterator(); +rfbBool rfbEnableExtension(rfbClientPtr cl, rfbProtocolExtension* extension, + void* data); +rfbBool rfbDisableExtension(rfbClientPtr cl, rfbProtocolExtension* extension); +void* rfbGetExtensionClientData(rfbClientPtr cl, rfbProtocolExtension* extension); + +/* to check against plain passwords */ +rfbBool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len); + +/* functions to make a vnc server */ +extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv, + int width,int height,int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); +extern void rfbInitServer(rfbScreenInfoPtr rfbScreen); +extern void rfbShutdownServer(rfbScreenInfoPtr rfbScreen,rfbBool disconnectClients); +extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer, + int width,int height, int bitsPerSample,int samplesPerPixel, + int bytesPerPixel); + +extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo); +extern void rfbSetServerVersionIdentity(rfbScreenInfoPtr screen, char *fmt, ...); + +/* functions to accept/refuse a client that has been put on hold + by a NewClientHookPtr function. Must not be called in other + situations. */ +extern void rfbStartOnHoldClient(rfbClientPtr cl); +extern void rfbRefuseOnHoldClient(rfbClientPtr cl); + +/* call one of these two functions to service the vnc clients. + usec are the microseconds the select on the fds waits. + if you are using the event loop, set this to some value > 0, so the + server doesn't get a high load just by listening. + rfbProcessEvents() returns TRUE if an update was pending. */ + +extern void rfbRunEventLoop(rfbScreenInfoPtr screenInfo, long usec, rfbBool runInBackground); +extern rfbBool rfbProcessEvents(rfbScreenInfoPtr screenInfo,long usec); +extern rfbBool rfbIsActive(rfbScreenInfoPtr screenInfo); + +/* TightVNC file transfer extension */ +void rfbRegisterTightVNCFileTransferExtension(); +void rfbUnregisterTightVNCFileTransferExtension(); + +/* Statistics */ +extern char *messageNameServer2Client(uint32_t type, char *buf, int len); +extern char *messageNameClient2Server(uint32_t type, char *buf, int len); +extern char *encodingName(uint32_t enc, char *buf, int len); + +extern rfbStatList *rfbStatLookupEncoding(rfbClientPtr cl, uint32_t type); +extern rfbStatList *rfbStatLookupMessage(rfbClientPtr cl, uint32_t type); + +/* Each call to rfbStatRecord* adds one to the rect count for that type */ +extern void rfbStatRecordEncodingSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordEncodingSentAdd(rfbClientPtr cl, uint32_t type, int byteCount); /* Specifically for tight encoding */ +extern void rfbStatRecordEncodingRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageSent(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbStatRecordMessageRcvd(rfbClientPtr cl, uint32_t type, int byteCount, int byteIfRaw); +extern void rfbResetStats(rfbClientPtr cl); +extern void rfbPrintStats(rfbClientPtr cl); + +extern int rfbStatGetSentBytes(rfbClientPtr cl); +extern int rfbStatGetSentBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetRcvdBytes(rfbClientPtr cl); +extern int rfbStatGetRcvdBytesIfRaw(rfbClientPtr cl); +extern int rfbStatGetMessageCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetMessageCountRcvd(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountSent(rfbClientPtr cl, uint32_t type); +extern int rfbStatGetEncodingCountRcvd(rfbClientPtr cl, uint32_t type); + +/* Set which version you want to advertise 3.3, 3.6, 3.7 and 3.8 are currently supported*/ +extern void rfbSetProtocolVersion(rfbScreenInfoPtr rfbScreen, int major_, int minor_); + +/* send a TextChat message to a client */ +extern rfbBool rfbSendTextChatMessage(rfbClientPtr cl, uint32_t length, char *buffer); + + + + +#if(defined __cplusplus) +} +#endif + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h new file mode 100755 index 0000000..bc4ec14 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbclient.h @@ -0,0 +1,406 @@ +#ifndef RFBCLIENT_H +#define RFBCLIENT_H + +/* + * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * vncviewer.h + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS +#include +#endif + +#define rfbClientSwap16IfLE(s) \ + (*(char *)&client->endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s)) + +#define rfbClientSwap32IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) & 0xff000000) >> 24) | \ + (((l) & 0x00ff0000) >> 8) | \ + (((l) & 0x0000ff00) << 8) | \ + (((l) & 0x000000ff) << 24)) : (l)) + +#define rfbClientSwap64IfLE(l) \ + (*(char *)&client->endianTest ? ((((l) & 0xff00000000000000ULL) >> 56) | \ + (((l) & 0x00ff000000000000ULL) >> 40) | \ + (((l) & 0x0000ff0000000000ULL) >> 24) | \ + (((l) & 0x000000ff00000000ULL) >> 8) | \ + (((l) & 0x00000000ff000000ULL) << 8) | \ + (((l) & 0x0000000000ff0000ULL) << 24) | \ + (((l) & 0x000000000000ff00ULL) << 40) | \ + (((l) & 0x00000000000000ffULL) << 56)) : (l)) + +#define FLASH_PORT_OFFSET 5400 +#define LISTEN_PORT_OFFSET 5500 +#define TUNNEL_PORT_OFFSET 5500 +#define SERVER_PORT_OFFSET 5900 + +#define DEFAULT_SSH_CMD "/usr/bin/ssh" +#define DEFAULT_TUNNEL_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20") +#define DEFAULT_VIA_CMD \ + (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") + +#if(defined __cplusplus) +extern "C" +{ +#endif + +/* vncrec */ + +typedef struct { + FILE* file; + struct timeval tv; + rfbBool readTimestamp; + rfbBool doNotSleep; +} rfbVNCRec; + +/* client data */ + +typedef struct rfbClientData { + void* tag; + void* data; + struct rfbClientData* next; +} rfbClientData; + +/* app data (belongs into rfbClient?) */ + +typedef struct { + rfbBool shareDesktop; + rfbBool viewOnly; + + const char* encodingsString; + + rfbBool useBGR233; + int nColours; + rfbBool forceOwnCmap; + rfbBool forceTrueColour; + int requestedDepth; + + int compressLevel; + int qualityLevel; + rfbBool enableJPEG; + rfbBool useRemoteCursor; + rfbBool palmVNC; /* use palmvnc specific SetScale (vs ultravnc) */ + int scaleSetting; /* 0 means no scale set, else 1/scaleSetting */ +} AppData; + +/* For GetCredentialProc callback function to return */ +typedef union _rfbCredential +{ + /* X509 (VeNCrypt) */ + struct + { + char *x509CACertFile; + char *x509CACrlFile; + char *x509ClientCertFile; + char *x509ClientKeyFile; + } x509Credential; + /* Plain (VeNCrypt), MSLogon (UltraVNC) */ + struct + { + char *username; + char *password; + } userCredential; +} rfbCredential; + +#define rfbCredentialTypeX509 1 +#define rfbCredentialTypeUser 2 + +struct _rfbClient; + +typedef void (*HandleTextChatProc)(struct _rfbClient* client, int value, char *text); +typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad); +typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y); +typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client); +typedef void (*GotFrameBufferUpdateProc)(struct _rfbClient* client, int x, int y, int w, int h); +typedef void (*FinishedFrameBufferUpdateProc)(struct _rfbClient* client); +typedef char* (*GetPasswordProc)(struct _rfbClient* client); +typedef rfbCredential* (*GetCredentialProc)(struct _rfbClient* client, int credentialType); +typedef rfbBool (*MallocFrameBufferProc)(struct _rfbClient* client); +typedef void (*GotXCutTextProc)(struct _rfbClient* client, const char *text, int textlen); +typedef void (*BellProc)(struct _rfbClient* client); + +typedef void (*GotCursorShapeProc)(struct _rfbClient* client, int xhot, int yhot, int width, int height, int bytesPerPixel); +typedef void (*GotCopyRectProc)(struct _rfbClient* client, int src_x, int src_y, int w, int h, int dest_x, int dest_y); + +typedef struct _rfbClient { + uint8_t* frameBuffer; + int width, height; + + int endianTest; + + AppData appData; + + const char* programName; + char* serverHost; + int serverPort; /* if -1, then use file recorded by vncrec */ + rfbBool listenSpecified; + int listenPort, flashPort; + + struct { + int x, y, w, h; + } updateRect; + + /* Note that the CoRRE encoding uses this buffer and assumes it is big enough + to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes. + Hextile also assumes it is big enough to hold 16 * 16 * 32 bits. + Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */ + +#define RFB_BUFFER_SIZE (640*480) + char buffer[RFB_BUFFER_SIZE]; + + /* rfbproto.c */ + + int sock; + rfbBool canUseCoRRE; + rfbBool canUseHextile; + char *desktopName; + rfbPixelFormat format; + rfbServerInitMsg si; + + /* listen.c */ + int listenSock; + + /* sockets.c */ +#define RFB_BUF_SIZE 8192 + char buf[RFB_BUF_SIZE]; + char *bufoutptr; + int buffered; + + /* The zlib encoding requires expansion/decompression/deflation of the + compressed data in the "buffer" above into another, result buffer. + However, the size of the result buffer can be determined precisely + based on the bitsPerPixel, height and width of the rectangle. We + allocate this buffer one time to be the full size of the buffer. */ + + /* Ultra Encoding uses this buffer too */ + + int ultra_buffer_size; + char *ultra_buffer; + + int raw_buffer_size; + char *raw_buffer; + +#ifdef LIBVNCSERVER_HAVE_LIBZ + z_stream decompStream; + rfbBool decompStreamInited; +#endif + + +#ifdef LIBVNCSERVER_HAVE_LIBZ + /* + * Variables for the ``tight'' encoding implementation. + */ + + /* Separate buffer for compressed data. */ +#define ZLIB_BUFFER_SIZE 30000 + char zlib_buffer[ZLIB_BUFFER_SIZE]; + + /* Four independent compression streams for zlib library. */ + z_stream zlibStream[4]; + rfbBool zlibStreamActive[4]; + + /* Filter stuff. Should be initialized by filter initialization code. */ + rfbBool cutZeros; + int rectWidth, rectColors; + char tightPalette[256*4]; + uint8_t tightPrevRow[2048*3*sizeof(uint16_t)]; + +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + /* JPEG decoder state. */ + rfbBool jpegError; + + struct jpeg_source_mgr* jpegSrcManager; + void* jpegBufferPtr; + size_t jpegBufferLen; + +#endif +#endif + + + /* cursor.c */ + uint8_t *rcSource, *rcMask; + + /* private data pointer */ + rfbClientData* clientData; + + rfbVNCRec* vncRec; + + /* Keyboard State support (is 'Caps Lock' set on the remote display???) */ + int KeyboardLedStateEnabled; + int CurrentKeyboardLedState; + + int canHandleNewFBSize; + + /* hooks */ + HandleTextChatProc HandleTextChat; + HandleKeyboardLedStateProc HandleKeyboardLedState; + HandleCursorPosProc HandleCursorPos; + SoftCursorLockAreaProc SoftCursorLockArea; + SoftCursorUnlockScreenProc SoftCursorUnlockScreen; + GotFrameBufferUpdateProc GotFrameBufferUpdate; + FinishedFrameBufferUpdateProc FinishedFrameBufferUpdate; + /* the pointer returned by GetPassword will be freed after use! */ + GetPasswordProc GetPassword; + MallocFrameBufferProc MallocFrameBuffer; + GotXCutTextProc GotXCutText; + BellProc Bell; + + GotCursorShapeProc GotCursorShape; + GotCopyRectProc GotCopyRect; + + /* Which messages are supported by the server + * This is a *guess* for most servers. + * (If we can even detect the type of server) + * + * If the server supports the "rfbEncodingSupportedMessages" + * then this will be updated when the encoding is received to + * accurately reflect the servers capabilities. + */ + rfbSupportedMessages supportedMessages; + + /* negotiated protocol version */ + int major, minor; + + /* The selected security types */ + uint32_t authScheme, subAuthScheme; + +#ifdef LIBVNCSERVER_WITH_CLIENT_TLS + /* The TLS session for Anonymous TLS and VeNCrypt */ + gnutls_session_t tlsSession; +#endif + + /* To support security types that requires user input (except VNC password + * authentication), for example VeNCrypt and MSLogon, this callback function + * must be set before the authentication. Otherwise, it implicates that the + * caller application does not support it and related security types should + * be bypassed. + */ + GetCredentialProc GetCredential; + + /* The 0-terminated security types supported by the client. + * Set by function SetClientAuthSchemes() */ + uint32_t *clientAuthSchemes; + + /* When the server is a repeater, this specifies the final destination */ + char *destHost; + int destPort; +} rfbClient; + +/* cursor.c */ + +extern rfbBool HandleCursorShape(rfbClient* client,int xhot, int yhot, int width, int height, uint32_t enc); + +/* listen.c */ + +extern void listenForIncomingConnections(rfbClient* viewer); +extern int listenForIncomingConnectionsNoFork(rfbClient* viewer, int usec_timeout); + +/* rfbproto.c */ + +extern rfbBool rfbEnableClientLogging; +typedef void (*rfbClientLogProc)(const char *format, ...); +extern rfbClientLogProc rfbClientLog,rfbClientErr; +extern rfbBool ConnectToRFBServer(rfbClient* client,const char *hostname, int port); +extern rfbBool ConnectToRFBRepeater(rfbClient* client,const char *repeaterHost, int repeaterPort, const char *destHost, int destPort); +extern void SetClientAuthSchemes(rfbClient* client,const uint32_t *authSchemes, int size); +extern rfbBool InitialiseRFBConnection(rfbClient* client); +extern rfbBool SetFormatAndEncodings(rfbClient* client); +extern rfbBool SendIncrementalFramebufferUpdateRequest(rfbClient* client); +extern rfbBool SendFramebufferUpdateRequest(rfbClient* client, + int x, int y, int w, int h, + rfbBool incremental); +extern rfbBool SendScaleSetting(rfbClient* client,int scaleSetting); +extern rfbBool SendPointerEvent(rfbClient* client,int x, int y, int buttonMask); +extern rfbBool SendKeyEvent(rfbClient* client,uint32_t key, rfbBool down); +extern rfbBool SendClientCutText(rfbClient* client,char *str, int len); +extern rfbBool HandleRFBServerMessage(rfbClient* client); + +extern rfbBool TextChatSend(rfbClient* client, char *text); +extern rfbBool TextChatOpen(rfbClient* client); +extern rfbBool TextChatClose(rfbClient* client); +extern rfbBool TextChatFinish(rfbClient* client); +extern rfbBool PermitServerInput(rfbClient* client, int enabled); + +extern void PrintPixelFormat(rfbPixelFormat *format); + +extern rfbBool SupportsClient2Server(rfbClient* client, int messageType); +extern rfbBool SupportsServer2Client(rfbClient* client, int messageType); + +/* client data */ + +void rfbClientSetClientData(rfbClient* client, void* tag, void* data); +void* rfbClientGetClientData(rfbClient* client, void* tag); + +/* protocol extensions */ + +typedef struct _rfbClientProtocolExtension { + int* encodings; + /* returns TRUE if the encoding was handled */ + rfbBool (*handleEncoding)(rfbClient* cl, + rfbFramebufferUpdateRectHeader* rect); + /* returns TRUE if it handled the message */ + rfbBool (*handleMessage)(rfbClient* cl, + rfbServerToClientMsg* message); + struct _rfbClientProtocolExtension* next; +} rfbClientProtocolExtension; + +void rfbClientRegisterExtension(rfbClientProtocolExtension* e); + +/* sockets.c */ + +extern rfbBool errorMessageOnReadFailure; + +extern rfbBool ReadFromRFBServer(rfbClient* client, char *out, unsigned int n); +extern rfbBool WriteToRFBServer(rfbClient* client, char *buf, int n); +extern int FindFreeTcpPort(void); +extern int ListenAtTcpPort(int port); +extern int ConnectClientToTcpAddr(unsigned int host, int port); +extern int ConnectClientToUnixSock(const char *sockFile); +extern int AcceptTcpConnection(int listenSock); +extern rfbBool SetNonBlocking(int sock); + +extern rfbBool StringToIPAddr(const char *str, unsigned int *addr); +extern rfbBool SameMachine(int sock); +extern int WaitForMessage(rfbClient* client,unsigned int usecs); + +/* vncviewer.c */ +rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,int bytesPerPixel); +rfbBool rfbInitClient(rfbClient* client,int* argc,char** argv); +/* rfbClientCleanup() does not touch client->frameBuffer */ +void rfbClientCleanup(rfbClient* client); + +#if(defined __cplusplus) +} +#endif + +#endif + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake new file mode 100755 index 0000000..f9f9ba3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbconfig.h.cmake @@ -0,0 +1,92 @@ +#ifndef _RFB_RFBCONFIG_H +#cmakedefine _RFB_RFBCONFIG_H 1 + +/* rfb/rfbconfig.h. Generated automatically by cmake. */ + +/* Enable 24 bit per pixel in native framebuffer */ +#cmakedefine LIBVNCSERVER_ALLOW24BPP 1 + +/* work around when write() returns ENOENT but does not mean it */ +#cmakedefine LIBVNCSERVER_ENOENT_WORKAROUND 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +#cmakedefine LIBVNCSERVER_HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the `jpeg' library (-ljpeg). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBJPEG 1 + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBPTHREAD 1 + +/* Define to 1 if you have the `z' library (-lz). */ +#cmakedefine LIBVNCSERVER_HAVE_LIBZ 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have that is POSIX.1 compatible. */ +#cmakedefine LIBVNCSERVER_HAVE_SYS_WAIT_H 1 + +/* Define to 1 if you have the header file. */ +#cmakedefine LIBVNCSERVER_HAVE_UNISTD_H 1 + +/* Need a typedef for in_addr_t */ +#cmakedefine LIBVNCSERVER_NEED_INADDR_T 1 + +/* Define to the full name and version of this package. */ +#define LIBVNCSERVER_PACKAGE_STRING "@FULL_PACKAGE_NAME@ @PACKAGE_VERSION@" + +/* Define to the version of this package. */ +#define LIBVNCSERVER_PACKAGE_VERSION "@PACKAGE_VERSION@" + +/* Define to 1 if GnuTLS is present */ +#cmakedefine LIBVNCSERVER_WITH_CLIENT_TLS 1 + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#cmakedefine LIBVNCSERVER_WORDS_BIGENDIAN 1 + +/* Define to empty if `const' does not conform to ANSI C. */ +//#cmakedefine const @CMAKE_CONST@ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +//#ifndef __cplusplus +//#cmakedefine inline @CMAKE_INLINE@ +//#endif + +/* Define to `int' if does not define. */ +#cmakedefine HAVE_LIBVNCSERVER_PID_T 1 +#ifndef HAVE_LIBVNCSERVER_PID_T +typedef int pid_t; +#endif + +/* The type for size_t */ +#cmakedefine HAVE_LIBVNCSERVER_SIZE_T 1 +#ifndef HAVE_LIBVNCSERVER_SIZE_T +typedef int size_t; +#endif + +/* The type for socklen */ +#cmakedefine HAVE_LIBVNCSERVER_SOCKLEN_T 1 +#ifndef HAVE_LIBVNCSERVER_SOCKLEN_T +typedef int socklen_t; +#endif + +/* once: _RFB_RFBCONFIG_H */ +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake new file mode 100755 index 0000000..17de6cd --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbint.h.cmake @@ -0,0 +1,4 @@ +#ifndef _RFB_RFBINT_H +#define _RFB_RFBINT_H 1 +/* empty ... */ +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h new file mode 100755 index 0000000..944c1d2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbproto.h @@ -0,0 +1,1383 @@ +#ifndef RFBPROTO_H +#define RFBPROTO_H + +/* + * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin + * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved. + * Copyright (C) 2000 Tridia Corporation. All Rights Reserved. + * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +/* + * rfbproto.h - header file for the RFB protocol version 3.3 + * + * Uses types CARD for an n-bit unsigned integer, INT for an n-bit signed + * integer (for n = 8, 16 and 32). + * + * All multiple byte integers are in big endian (network) order (most + * significant byte first). Unless noted otherwise there is no special + * alignment of protocol structures. + * + * + * Once the initial handshaking is done, all messages start with a type byte, + * (usually) followed by message-specific data. The order of definitions in + * this file is as follows: + * + * (1) Structures used in several types of message. + * (2) Structures used in the initial handshaking. + * (3) Message types. + * (4) Encoding types. + * (5) For each message type, the form of the data following the type byte. + * Sometimes this is defined by a single structure but the more complex + * messages have to be explained by comments. + */ + + +#if defined(WIN32) && !defined(__MINGW32__) +#define LIBVNCSERVER_WORDS_BIGENDIAN +#define rfbBool int +#include +#include +#undef SOCKET +#define SOCKET int +#else +#include + +#endif + +#ifdef LIBVNCSERVER_HAVE_LIBZ +#include +#ifdef __CHECKER__ +#undef Z_NULL +#define Z_NULL NULL +#endif +#endif + + +#if !defined(WIN32) || defined(__MINGW32__) +#define max(a,b) (((a)>(b))?(a):(b)) +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_NETINET_IN_H +#include +#endif +#define SOCKET int +typedef int8_t rfbBool; +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE -1 +#endif + +typedef uint32_t rfbKeySym; +typedef uint32_t rfbPixel; + +#ifdef LIBVNCSERVER_NEED_INADDR_T +typedef uint32_t in_addr_t; +#endif +/* +#ifndef INADDR_NONE +#define INADDR_NONE ((in_addr_t) 0xffffffff) +#endif*/ + +#define MAX_ENCODINGS 20 + +/***************************************************************************** + * + * Structures used in several messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Structure used to specify a rectangle. This structure is a multiple of 4 + * bytes so that it can be interspersed with 32-bit pixel data without + * affecting alignment. + */ + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbRectangle; + +#define sz_rfbRectangle 8 + + +/*----------------------------------------------------------------------------- + * Structure used to specify pixel format. + */ + +typedef struct { + + uint8_t bitsPerPixel; /* 8,16,32 only */ + + uint8_t depth; /* 8 to 32 */ + + uint8_t bigEndian; /* True if multi-byte pixels are interpreted + as big endian, or if single-bit-per-pixel + has most significant bit of the byte + corresponding to first (leftmost) pixel. Of + course this is meaningless for 8 bits/pix */ + + uint8_t trueColour; /* If false then we need a "colour map" to + convert pixels to RGB. If true, xxxMax and + xxxShift specify bits used for red, green + and blue */ + + /* the following fields are only meaningful if trueColour is true */ + + uint16_t redMax; /* maximum red value (= 2^n - 1 where n is the + number of bits used for red). Note this + value is always in big endian order. */ + + uint16_t greenMax; /* similar for green */ + + uint16_t blueMax; /* and blue */ + + uint8_t redShift; /* number of shifts needed to get the red + value in a pixel to the least significant + bit. To find the red value from a given + pixel, do the following: + 1) Swap pixel value according to bigEndian + (e.g. if bigEndian is false and host byte + order is big endian, then swap). + 2) Shift right by redShift. + 3) AND with redMax (in host byte order). + 4) You now have the red value between 0 and + redMax. */ + + uint8_t greenShift; /* similar for green */ + + uint8_t blueShift; /* and blue */ + + uint8_t pad1; + uint16_t pad2; + +} rfbPixelFormat; + +#define sz_rfbPixelFormat 16 + +/* UltraVNC: Color settings values */ +#define rfbPFFullColors 0 +#define rfbPF256Colors 1 +#define rfbPF64Colors 2 +#define rfbPF8Colors 3 +#define rfbPF8GreyColors 4 +#define rfbPF4GreyColors 5 +#define rfbPF2GreyColors 6 + + +/***************************************************************************** + * + * Initial handshaking messages + * + *****************************************************************************/ + +/*----------------------------------------------------------------------------- + * Protocol Version + * + * The server always sends 12 bytes to start which identifies the latest RFB + * protocol version number which it supports. These bytes are interpreted + * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where + * xxx and yyy are the major and minor version numbers (for version 3.3 + * this is "RFB 003.003\n"). + * + * The client then replies with a similar 12-byte message giving the version + * number of the protocol which should actually be used (which may be different + * to that quoted by the server). + * + * It is intended that both clients and servers may provide some level of + * backwards compatibility by this mechanism. Servers in particular should + * attempt to provide backwards compatibility, and even forwards compatibility + * to some extent. For example if a client demands version 3.1 of the + * protocol, a 3.0 server can probably assume that by ignoring requests for + * encoding types it doesn't understand, everything will still work OK. This + * will probably not be the case for changes in the major version number. + * + * The format string below can be used in sprintf or sscanf to generate or + * decode the version string respectively. + */ + +#define rfbProtocolVersionFormat "RFB %03d.%03d\n" +#define rfbProtocolMajorVersion 3 +#define rfbProtocolMinorVersion 8 +/* UltraVNC Viewer examines rfbProtocolMinorVersion number (4, and 6) + * to identify if the server supports File Transfer + */ + +typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */ + +#define sz_rfbProtocolVersionMsg 12 + +/* + * Negotiation of the security type (protocol version 3.7) + * + * Once the protocol version has been decided, the server either sends a list + * of supported security types, or informs the client about an error (when the + * number of security types is 0). Security type rfbSecTypeTight is used to + * enable TightVNC-specific protocol extensions. The value rfbSecTypeVncAuth + * stands for classic VNC authentication. + * + * The client selects a particular security type from the list provided by the + * server. + */ + +#define rfbSecTypeInvalid 0 +#define rfbSecTypeNone 1 +#define rfbSecTypeVncAuth 2 + + +/*----------------------------------------------------------------------------- + * Authentication + * + * Once the protocol version has been decided, the server then sends a 32-bit + * word indicating whether any authentication is needed on the connection. + * The value of this word determines the authentication scheme in use. For + * version 3.0 of the protocol this may have one of the following values: + */ + +#define rfbConnFailed 0 +#define rfbNoAuth 1 +#define rfbVncAuth 2 + +#define rfbRA2 5 +#define rfbRA2ne 6 +#define rfbSSPI 7 +#define rfbSSPIne 8 +#define rfbTight 16 +#define rfbUltra 17 +#define rfbTLS 18 +#define rfbVeNCrypt 19 +#define rfbMSLogon 0xfffffffa + +#define rfbVeNCryptPlain 256 +#define rfbVeNCryptTLSNone 257 +#define rfbVeNCryptTLSVNC 258 +#define rfbVeNCryptTLSPlain 259 +#define rfbVeNCryptX509None 260 +#define rfbVeNCryptX509VNC 261 +#define rfbVeNCryptX509Plain 262 +#define rfbVeNCryptX509SASL 263 +#define rfbVeNCryptTLSSASL 264 + +/* + * rfbConnFailed: For some reason the connection failed (e.g. the server + * cannot support the desired protocol version). This is + * followed by a string describing the reason (where a + * string is specified as a 32-bit length followed by that + * many ASCII characters). + * + * rfbNoAuth: No authentication is needed. + * + * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte + * challenge follows, which the client encrypts as + * appropriate using the password and sends the resulting + * 16-byte response. If the response is correct, the + * server sends the 32-bit word rfbVncAuthOK. If a simple + * failure happens, the server sends rfbVncAuthFailed and + * closes the connection. If the server decides that too + * many failures have occurred, it sends rfbVncAuthTooMany + * and closes the connection. In the latter case, the + * server should not allow an immediate reconnection by + * the client. + */ + +#define rfbVncAuthOK 0 +#define rfbVncAuthFailed 1 +#define rfbVncAuthTooMany 2 + + +/*----------------------------------------------------------------------------- + * Client Initialisation Message + * + * Once the client and server are sure that they're happy to talk to one + * another, the client sends an initialisation message. At present this + * message only consists of a boolean indicating whether the server should try + * to share the desktop by leaving other clients connected, or give exclusive + * access to this client by disconnecting all other clients. + */ + +typedef struct { + uint8_t shared; +} rfbClientInitMsg; + +#define sz_rfbClientInitMsg 1 + + +/*----------------------------------------------------------------------------- + * Server Initialisation Message + * + * After the client initialisation message, the server sends one of its own. + * This tells the client the width and height of the server's framebuffer, + * its pixel format and the name associated with the desktop. + */ + +typedef struct { + uint16_t framebufferWidth; + uint16_t framebufferHeight; + rfbPixelFormat format; /* the server's preferred pixel format */ + uint32_t nameLength; + /* followed by char name[nameLength] */ +} rfbServerInitMsg; + +#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat) + + +/* + * Following the server initialisation message it's up to the client to send + * whichever protocol messages it wants. Typically it will send a + * SetPixelFormat message and a SetEncodings message, followed by a + * FramebufferUpdateRequest. From then on the server will send + * FramebufferUpdate messages in response to the client's + * FramebufferUpdateRequest messages. The client should send + * FramebufferUpdateRequest messages with incremental set to true when it has + * finished processing one FramebufferUpdate and is ready to process another. + * With a fast client, the rate at which FramebufferUpdateRequests are sent + * should be regulated to avoid hogging the network. + */ + + + +/***************************************************************************** + * + * Message types + * + *****************************************************************************/ + +/* server -> client */ + +#define rfbFramebufferUpdate 0 +#define rfbSetColourMapEntries 1 +#define rfbBell 2 +#define rfbServerCutText 3 +/* Modif sf@2002 */ +#define rfbResizeFrameBuffer 4 +#define rfbKeyFrameUpdate 5 +#define rfbPalmVNCReSizeFrameBuffer 0xF + +/* client -> server */ + +#define rfbSetPixelFormat 0 +#define rfbFixColourMapEntries 1 /* not currently supported */ +#define rfbSetEncodings 2 +#define rfbFramebufferUpdateRequest 3 +#define rfbKeyEvent 4 +#define rfbPointerEvent 5 +#define rfbClientCutText 6 +/* Modif sf@2002 - actually bidirectionnal */ +#define rfbFileTransfer 7 +/* Modif sf@2002 */ +#define rfbSetScale 8 +/* Modif rdv@2002 */ +#define rfbSetServerInput 9 +/* Modif rdv@2002 */ +#define rfbSetSW 10 +/* Modif sf@2002 - TextChat - Bidirectionnal */ +#define rfbTextChat 11 +/* Modif cs@2005 */ +#define rfbKeyFrameRequest 12 +/* PalmVNC 1.4 & 2.0 SetScale Factor message */ +#define rfbPalmVNCSetScaleFactor 0xF + + + + +/***************************************************************************** + * + * Encoding types + * + *****************************************************************************/ + +#define rfbEncodingRaw 0 +#define rfbEncodingCopyRect 1 +#define rfbEncodingRRE 2 +#define rfbEncodingCoRRE 4 +#define rfbEncodingHextile 5 +#define rfbEncodingZlib 6 +#define rfbEncodingTight 7 +#define rfbEncodingTightPng 0xFFFFFEFC /* -260 */ +#define rfbEncodingZlibHex 8 +#define rfbEncodingUltra 9 +#define rfbEncodingZRLE 16 +#define rfbEncodingZYWRLE 17 + +/* Cache & XOR-Zlib - rdv@2002 */ +#define rfbEncodingCache 0xFFFF0000 +#define rfbEncodingCacheEnable 0xFFFF0001 +#define rfbEncodingXOR_Zlib 0xFFFF0002 +#define rfbEncodingXORMonoColor_Zlib 0xFFFF0003 +#define rfbEncodingXORMultiColor_Zlib 0xFFFF0004 +#define rfbEncodingSolidColor 0xFFFF0005 +#define rfbEncodingXOREnable 0xFFFF0006 +#define rfbEncodingCacheZip 0xFFFF0007 +#define rfbEncodingSolMonoZip 0xFFFF0008 +#define rfbEncodingUltraZip 0xFFFF0009 + +/* + * Special encoding numbers: + * 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels; + * 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data; + * 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions; + * 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet; + * 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor; + * 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels. + */ + +#define rfbEncodingCompressLevel0 0xFFFFFF00 +#define rfbEncodingCompressLevel1 0xFFFFFF01 +#define rfbEncodingCompressLevel2 0xFFFFFF02 +#define rfbEncodingCompressLevel3 0xFFFFFF03 +#define rfbEncodingCompressLevel4 0xFFFFFF04 +#define rfbEncodingCompressLevel5 0xFFFFFF05 +#define rfbEncodingCompressLevel6 0xFFFFFF06 +#define rfbEncodingCompressLevel7 0xFFFFFF07 +#define rfbEncodingCompressLevel8 0xFFFFFF08 +#define rfbEncodingCompressLevel9 0xFFFFFF09 + +#define rfbEncodingXCursor 0xFFFFFF10 +#define rfbEncodingRichCursor 0xFFFFFF11 +#define rfbEncodingPointerPos 0xFFFFFF18 + +#define rfbEncodingLastRect 0xFFFFFF20 +#define rfbEncodingNewFBSize 0xFFFFFF21 + +#define rfbEncodingQualityLevel0 0xFFFFFFE0 +#define rfbEncodingQualityLevel1 0xFFFFFFE1 +#define rfbEncodingQualityLevel2 0xFFFFFFE2 +#define rfbEncodingQualityLevel3 0xFFFFFFE3 +#define rfbEncodingQualityLevel4 0xFFFFFFE4 +#define rfbEncodingQualityLevel5 0xFFFFFFE5 +#define rfbEncodingQualityLevel6 0xFFFFFFE6 +#define rfbEncodingQualityLevel7 0xFFFFFFE7 +#define rfbEncodingQualityLevel8 0xFFFFFFE8 +#define rfbEncodingQualityLevel9 0xFFFFFFE9 + + +/* LibVNCServer additions. We claim 0xFFFE0000 - 0xFFFE00FF */ +#define rfbEncodingKeyboardLedState 0xFFFE0000 +#define rfbEncodingSupportedMessages 0xFFFE0001 +#define rfbEncodingSupportedEncodings 0xFFFE0002 +#define rfbEncodingServerIdentity 0xFFFE0003 + + +/***************************************************************************** + * + * Server -> client message definitions + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * FramebufferUpdate - a block of rectangles to be copied to the framebuffer. + * + * This message consists of a header giving the number of rectangles of pixel + * data followed by the rectangles themselves. The header is padded so that + * together with the type byte it is an exact multiple of 4 bytes (to help + * with alignment of 32-bit pixels): + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdate */ + uint8_t pad; + uint16_t nRects; + /* followed by nRects rectangles */ +} rfbFramebufferUpdateMsg; + +#define sz_rfbFramebufferUpdateMsg 4 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyFrameUpdate - Acknowledgment of a key frame request, it tells the client + * that the next update received will be a key frame. + */ + +typedef struct { + uint8_t type; +} rfbKeyFrameUpdateMsg; + +#define sz_rfbKeyFrameUpdateMsg 1 + + +/* + * Each rectangle of pixel data consists of a header describing the position + * and size of the rectangle and a type word describing the encoding of the + * pixel data, followed finally by the pixel data. Note that if the client has + * not sent a SetEncodings message then it will only receive raw pixel data. + * Also note again that this structure is a multiple of 4 bytes. + */ + +typedef struct { + rfbRectangle r; + uint32_t encoding; /* one of the encoding types rfbEncoding... */ +} rfbFramebufferUpdateRectHeader; + +#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Messages Encoding. This encoding does not contain any pixel data. + * Instead, it contains 2 sets of bitflags. These bitflags indicate what messages + * are supported by the server. + * rect->w contains byte count + */ + +typedef struct { + uint8_t client2server[32]; /* maximum of 256 message types (256/8)=32 */ + uint8_t server2client[32]; /* maximum of 256 message types (256/8)=32 */ +} rfbSupportedMessages; + +#define sz_rfbSupportedMessages 64 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Supported Encodings Encoding. This encoding does not contain any pixel data. + * Instead, it contains a list of (uint32_t) Encodings supported by this server. + * rect->w contains byte count + * rect->h contains encoding count + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Server Identity Encoding. This encoding does not contain any pixel data. + * Instead, it contains a text string containing information about the server. + * ie: "x11vnc: 0.8.1 lastmod: 2006-04-25 (libvncserver 0.9pre)\0" + * rect->w contains byte count + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Raw Encoding. Pixels are sent in top-to-bottom scanline order, + * left-to-right within a scanline with no padding in between. + */ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * KeyboardLedState Encoding. The X coordinate contains the Locked Modifiers + * so that a remote troubleshooter can identify that the users 'Caps Lock' + * is set... (It helps a *lot* when the users are untrained) + */ +#define rfbKeyboardMaskShift 1 +#define rfbKeyboardMaskCapsLock 2 +#define rfbKeyboardMaskControl 4 +#define rfbKeyboardMaskAlt 8 +#define rfbKeyboardMaskMeta 16 +#define rfbKeyboardMaskSuper 32 +#define rfbKeyboardMaskHyper 64 +#define rfbKeyboardMaskNumLock 128 +#define rfbKeyboardMaskScrollLock 256 +#define rfbKeyboardMaskAltGraph 512 + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CopyRect Encoding. The pixels are specified simply by the x and y position + * of the source rectangle. + */ + +typedef struct { + uint16_t srcX; + uint16_t srcY; +} rfbCopyRect; + +#define sz_rfbCopyRect 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure + * giving the number of subrectangles following. Finally the data follows in + * the form [...] where each is + * []. + */ + +typedef struct { + uint32_t nSubrects; +} rfbRREHeader; + +#define sz_rfbRREHeader 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving + * the number of subrectangles following. Finally the data follows in the form + * [...] where each is + * []. This means that + * the whole rectangle must be at most 255x255 pixels. + */ + +typedef struct { + uint8_t x; + uint8_t y; + uint8_t w; + uint8_t h; +} rfbCoRRERectangle; + +#define sz_rfbCoRRERectangle 4 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels, + * starting at the top left going in left-to-right, top-to-bottom order. If + * the width of the rectangle is not an exact multiple of 16 then the width of + * the last tile in each row will be correspondingly smaller. Similarly if the + * height is not an exact multiple of 16 then the height of each tile in the + * final row will also be smaller. Each tile begins with a "subencoding" type + * byte, which is a mask made up of a number of bits. If the Raw bit is set + * then the other bits are irrelevant; w*h pixel values follow (where w and h + * are the width and height of the tile). Otherwise the tile is encoded in a + * similar way to RRE, except that the position and size of each subrectangle + * can be specified in just two bytes. The other bits in the mask are as + * follows: + * + * BackgroundSpecified - if set, a pixel value follows which specifies + * the background colour for this tile. The first non-raw tile in a + * rectangle must have this bit set. If this bit isn't set then the + * background is the same as the last tile. + * + * ForegroundSpecified - if set, a pixel value follows which specifies + * the foreground colour to be used for all subrectangles in this tile. + * If this bit is set then the SubrectsColoured bit must be zero. + * + * AnySubrects - if set, a single byte follows giving the number of + * subrectangles following. If not set, there are no subrectangles (i.e. + * the whole tile is just solid background colour). + * + * SubrectsColoured - if set then each subrectangle is preceded by a pixel + * value giving the colour of that subrectangle. If not set, all + * subrectangles are the same colour, the foreground colour; if the + * ForegroundSpecified bit wasn't set then the foreground is the same as + * the last tile. + * + * The position and size of each subrectangle is specified in two bytes. The + * Pack macros below can be used to generate the two bytes from x, y, w, h, + * and the Extract macros can be used to extract the x, y, w, h values from + * the two bytes. + */ + +#define rfbHextileRaw (1 << 0) +#define rfbHextileBackgroundSpecified (1 << 1) +#define rfbHextileForegroundSpecified (1 << 2) +#define rfbHextileAnySubrects (1 << 3) +#define rfbHextileSubrectsColoured (1 << 4) + +#define rfbHextilePackXY(x,y) (((x) << 4) | (y)) +#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1)) +#define rfbHextileExtractX(byte) ((byte) >> 4) +#define rfbHextileExtractY(byte) ((byte) & 0xf) +#define rfbHextileExtractW(byte) (((byte) >> 4) + 1) +#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1) + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * zlib - zlib compressed Encoding. We have an rfbZlibHeader structure + * giving the number of bytes following. Finally the data follows is + * zlib compressed version of the raw pixel data as negotiated. + * (NOTE: also used by Ultra Encoding) + */ + +typedef struct { + uint32_t nBytes; +} rfbZlibHeader; + +#define sz_rfbZlibHeader 4 + +#ifdef LIBVNCSERVER_HAVE_LIBZ + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * Tight and TightPng Encoding. + * + *-- TightPng is like Tight but basic compression is not used, instead PNG + * data is sent. + * + *-- The first byte of each Tight-encoded rectangle is a "compression control + * byte". Its format is as follows (bit 0 is the least significant one): + * + * bit 0: if 1, then compression stream 0 should be reset; + * bit 1: if 1, then compression stream 1 should be reset; + * bit 2: if 1, then compression stream 2 should be reset; + * bit 3: if 1, then compression stream 3 should be reset; + * bits 7-4: if 1000 (0x08), then the compression type is "fill", + * if 1001 (0x09), then the compression type is "jpeg", + * if 1001 (0x0A), then the compression type is "png", + * if 0xxx, then the compression type is "basic", + * values greater than 1010 are not valid. + * + * If the compression type is "basic", then bits 6..4 of the + * compression control byte (those xxx in 0xxx) specify the following: + * + * bits 5-4: decimal representation is the index of a particular zlib + * stream which should be used for decompressing the data; + * bit 6: if 1, then a "filter id" byte is following this byte. + * + *-- The data that follows after the compression control byte described + * above depends on the compression type ("fill", "jpeg", "png" or "basic"). + * + *-- If the compression type is "fill", then the only pixel value follows, in + * client pixel format (see NOTE 1). This value applies to all pixels of the + * rectangle. + * + *-- If the compression type is "jpeg" or "png", the following data stream + * looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: JPEG or PNG image. + * + * Data size is compactly represented in one, two or three bytes, according + * to the following scheme: + * + * 0xxxxxxx (for values 0..127) + * 1xxxxxxx 0yyyyyyy (for values 128..16383) + * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303) + * + * Here each character denotes one bit, xxxxxxx are the least significant 7 + * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the + * most significant 8 bits (bits 14-21). For example, decimal value 10000 + * should be represented as two bytes: binary 10010000 01001110, or + * hexadecimal 90 4E. + * + *-- If the compression type is "basic" and bit 6 of the compression control + * byte was set to 1, then the next (second) byte specifies "filter id" which + * tells the decoder what filter type was used by the encoder to pre-process + * pixel data before the compression. The "filter id" byte can be one of the + * following: + * + * 0: no filter ("copy" filter); + * 1: "palette" filter; + * 2: "gradient" filter. + * + *-- If bit 6 of the compression control byte is set to 0 (no "filter id" + * byte), or if the filter id is 0, then raw pixel values in the client + * format (see NOTE 1) will be compressed. See below details on the + * compression. + * + *-- The "gradient" filter pre-processes pixel data with a simple algorithm + * which converts each color component to a difference between a "predicted" + * intensity and the actual intensity. Such a technique does not affect + * uncompressed data size, but helps to compress photo-like images better. + * Pseudo-code for converting intensities to differences is the following: + * + * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1]; + * if (P[i,j] < 0) then P[i,j] := 0; + * if (P[i,j] > MAX) then P[i,j] := MAX; + * D[i,j] := V[i,j] - P[i,j]; + * + * Here V[i,j] is the intensity of a color component for a pixel at + * coordinates (i,j). MAX is the maximum value of intensity for a color + * component. + * + *-- The "palette" filter converts true-color pixel data to indexed colors + * and a palette which can consist of 2..256 colors. If the number of colors + * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to + * encode one pixel. 1-bit encoding is performed such way that the most + * significant bits correspond to the leftmost pixels, and each raw of pixels + * is aligned to the byte boundary. When "palette" filter is used, the + * palette is sent before the pixel data. The palette begins with an unsigned + * byte which value is the number of colors in the palette minus 1 (i.e. 1 + * means 2 colors, 255 means 256 colors in the palette). Then follows the + * palette itself which consist of pixel values in client pixel format (see + * NOTE 1). + * + *-- The pixel data is compressed using the zlib library. But if the data + * size after applying the filter but before the compression is less then 12, + * then the data is sent as is, uncompressed. Four separate zlib streams + * (0..3) can be used and the decoder should read the actual stream id from + * the compression control byte (see NOTE 2). + * + * If the compression is not used, then the pixel data is sent as is, + * otherwise the data stream looks like this: + * + * 1..3 bytes: data size (N) in compact representation; + * N bytes: zlib-compressed data. + * + * Data size is compactly represented in one, two or three bytes, just like + * in the "jpeg" compression method (see above). + * + *-- NOTE 1. If the color depth is 24, and all three color components are + * 8-bit wide, then one pixel in Tight encoding is always represented by + * three bytes, where the first byte is red component, the second byte is + * green component, and the third byte is blue component of the pixel color + * value. This applies to colors in palettes as well. + * + *-- NOTE 2. The decoder must reset compression streams' states before + * decoding the rectangle, if some of bits 0,1,2,3 in the compression control + * byte are set to 1. Note that the decoder must reset zlib streams even if + * the compression type is "fill", "jpeg" or "png". + * + *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only + * when bits-per-pixel value is either 16 or 32, not 8. + * + *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048 + * pixels. If a rectangle is wider, it must be split into several rectangles + * and each one should be encoded separately. + * + */ + +#define rfbTightExplicitFilter 0x04 +#define rfbTightFill 0x08 +#define rfbTightJpeg 0x09 +#define rfbTightPng 0x0A +#define rfbTightMaxSubencoding 0x0A + +/* Filters to improve compression efficiency */ +#define rfbTightFilterCopy 0x00 +#define rfbTightFilterPalette 0x01 +#define rfbTightFilterGradient 0x02 + +#endif + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * XCursor encoding. This is a special encoding used to transmit X-style + * cursor shapes from server to clients. Note that for this encoding, + * coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot + * position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB + * samples are sent after header in the rfbXCursorColors structure. They + * denote foreground and background colors of the cursor. If a client + * supports only black-and-white cursors, it should ignore these colors and + * assume that foreground is black and background is white. Next, two bitmaps + * (1 bits per pixel) follow: first one with actual data (value 0 denotes + * background color, value 1 denotes foreground color), second one with + * transparency data (bits with zero value mean that these pixels are + * transparent). Both bitmaps represent cursor data in a byte stream, from + * left to right, from top to bottom, and each row is byte-aligned. Most + * significant bits correspond to leftmost pixels. The number of bytes in + * each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor + * should be hidden (or default local cursor should be set by the client). + */ + +typedef struct { + uint8_t foreRed; + uint8_t foreGreen; + uint8_t foreBlue; + uint8_t backRed; + uint8_t backGreen; + uint8_t backBlue; +} rfbXCursorColors; + +#define sz_rfbXCursorColors 6 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RichCursor encoding. This is a special encoding used to transmit cursor + * shapes from server to clients. It is similar to the XCursor encoding but + * uses client pixel format instead of two RGB colors to represent cursor + * image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader + * structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h). + * After header, two pixmaps follow: first one with cursor image in current + * client pixel format (like in raw encoding), second with transparency data + * (1 bit per pixel, exactly the same format as used for transparency bitmap + * in the XCursor encoding). If (w * h == 0), cursor should be hidden (or + * default local cursor should be set by the client). + */ + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZRLE - encoding combining Zlib compression, tiling, palettisation and + * run-length encoding. + */ + +typedef struct { + uint32_t length; +} rfbZRLEHeader; + +#define sz_rfbZRLEHeader 4 + +#define rfbZRLETileWidth 64 +#define rfbZRLETileHeight 64 + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * ZLIBHEX - zlib compressed Hextile Encoding. Essentially, this is the + * hextile encoding with zlib compression on the tiles that can not be + * efficiently encoded with one of the other hextile subencodings. The + * new zlib subencoding uses two bytes to specify the length of the + * compressed tile and then the compressed data follows. As with the + * raw sub-encoding, the zlib subencoding invalidates the other + * values, if they are also set. + */ + +#define rfbHextileZlibRaw (1 << 5) +#define rfbHextileZlibHex (1 << 6) +#define rfbHextileZlibMono (1 << 7) + + +/*----------------------------------------------------------------------------- + * SetColourMapEntries - these messages are only sent if the pixel + * format uses a "colour map" (i.e. trueColour false) and the client has not + * fixed the entire colour map using FixColourMapEntries. In addition they + * will only start being sent after the client has sent its first + * FramebufferUpdateRequest. So if the client always tells the server to use + * trueColour then it never needs to process this type of message. + */ + +typedef struct { + uint8_t type; /* always rfbSetColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbSetColourMapEntriesMsg; + +#define sz_rfbSetColourMapEntriesMsg 6 + + + +/*----------------------------------------------------------------------------- + * Bell - ring a bell on the client if it has one. + */ + +typedef struct { + uint8_t type; /* always rfbBell */ +} rfbBellMsg; + +#define sz_rfbBellMsg 1 + + + +/*----------------------------------------------------------------------------- + * ServerCutText - the server has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbServerCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbServerCutTextMsg; + +#define sz_rfbServerCutTextMsg 8 + + +/*----------------------------------------------------------------------------- + * // Modif sf@2002 + * FileTransferMsg - The client sends FileTransfer message. + * Bidirectional message - Files can be sent from client to server & vice versa + */ + +typedef struct _rfbFileTransferMsg { + uint8_t type; /* always rfbFileTransfer */ + uint8_t contentType; /* See defines below */ + uint8_t contentParam;/* Other possible content classification (Dir or File name, etc..) */ + uint8_t pad; /* It appears that UltraVNC *forgot* to Swap16IfLE(contentParam) */ + uint32_t size; /* FileSize or packet index or error or other */ +/* uint32_t sizeH; Additional 32Bits params to handle big values. Only for V2 (we want backward compatibility between all V1 versions) */ + uint32_t length; + /* followed by data char text[length] */ +} rfbFileTransferMsg; + +#define sz_rfbFileTransferMsg 12 + +#define rfbFileTransferVersion 2 /* v1 is the old FT version ( <= 1.0.0 RC18 versions) */ + +/* FileTransfer Content types and Params defines */ +#define rfbDirContentRequest 1 /* Client asks for the content of a given Server directory */ +#define rfbDirPacket 2 /* Full directory name or full file name. */ + /* Null content means end of Directory */ +#define rfbFileTransferRequest 3 /* Client asks the server for the transfer of a given file */ +#define rfbFileHeader 4 /* First packet of a file transfer, containing file's features */ +#define rfbFilePacket 5 /* One chunk of the file */ +#define rfbEndOfFile 6 /* End of file transfer (the file has been received or error) */ +#define rfbAbortFileTransfer 7 /* The file transfer must be aborted, whatever the state */ +#define rfbFileTransferOffer 8 /* The client offers to send a file to the server */ +#define rfbFileAcceptHeader 9 /* The server accepts or rejects the file */ +#define rfbCommand 10 /* The Client sends a simple command (File Delete, Dir create etc...) */ +#define rfbCommandReturn 11 /* The Client receives the server's answer about a simple command */ +#define rfbFileChecksums 12 /* The zipped checksums of the destination file (Delta Transfer) */ +#define rfbFileTransferAccess 14 /* Request FileTransfer authorization */ + + /* rfbDirContentRequest client Request - content params */ +#define rfbRDirContent 1 /* Request a Server Directory contents */ +#define rfbRDrivesList 2 /* Request the server's drives list */ +#define rfbRDirRecursiveList 3 /* Request a server directory content recursive sorted list */ +#define rfbRDirRecursiveSize 4 /* Request a server directory content recursive size */ + + /* rfbDirPacket & rfbCommandReturn server Answer - content params */ +#define rfbADirectory 1 /* Reception of a directory name */ +#define rfbAFile 2 /* Reception of a file name */ +#define rfbADrivesList 3 /* Reception of a list of drives */ +#define rfbADirCreate 4 /* Response to a create dir command */ +#define rfbADirDelete 5 /* Response to a delete dir command */ +#define rfbAFileCreate 6 /* Response to a create file command */ +#define rfbAFileDelete 7 /* Response to a delete file command */ +#define rfbAFileRename 8 /* Response to a rename file command */ +#define rfbADirRename 9 /* Response to a rename dir command */ +#define rfbADirRecursiveListItem 10 +#define rfbADirRecursiveSize 11 + + /* rfbCommand Command - content params */ +#define rfbCDirCreate 1 /* Request the server to create the given directory */ +#define rfbCDirDelete 2 /* Request the server to delete the given directory */ +#define rfbCFileCreate 3 /* Request the server to create the given file */ +#define rfbCFileDelete 4 /* Request the server to delete the given file */ +#define rfbCFileRename 5 /* Request the server to rename the given file */ +#define rfbCDirRename 6 /* Request the server to rename the given directory */ + + /* Errors - content params or "size" field */ +#define rfbRErrorUnknownCmd 1 /* Unknown FileTransfer command. */ +#define rfbRErrorCmd 0xFFFFFFFF/* Error when a command fails on remote side (ret in "size" field) */ + +#define sz_rfbBlockSize 8192 /* Size of a File Transfer packet (before compression) */ +#define rfbZipDirectoryPrefix "!UVNCDIR-\0" /* Transfered directory are zipped in a file with this prefix. Must end with "-" */ +#define sz_rfbZipDirectoryPrefix 9 +#define rfbDirPrefix "[ " +#define rfbDirSuffix " ]" + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * TextChatMsg - Utilized to order the TextChat mode on server or client + * Bidirectional message + */ + +typedef struct _rfbTextChatMsg { + uint8_t type; /* always rfbTextChat */ + uint8_t pad1; /* Could be used later as an additionnal param */ + uint16_t pad2; /* Could be used later as text offset, for instance */ + uint32_t length; /* Specific values for Open, close, finished (-1, -2, -3) */ + /* followed by char text[length] */ +} rfbTextChatMsg; + +#define sz_rfbTextChatMsg 8 + +#define rfbTextMaxSize 4096 +#define rfbTextChatOpen 0xFFFFFFFF +#define rfbTextChatClose 0xFFFFFFFE +#define rfbTextChatFinished 0xFFFFFFFD + + + +/*----------------------------------------------------------------------------- + * Modif sf@2002 + * ResizeFrameBuffer - The Client must change the size of its framebuffer + */ + +typedef struct _rfbResizeFrameBufferMsg { + uint8_t type; /* always rfbResizeFrameBuffer */ + uint8_t pad1; + uint16_t framebufferWidth; /* FrameBuffer width */ + uint16_t framebufferHeigth; /* FrameBuffer height */ +} rfbResizeFrameBufferMsg; + +#define sz_rfbResizeFrameBufferMsg 6 + + +/*----------------------------------------------------------------------------- + * Copyright (C) 2001 Harakan Software + * PalmVNC 1.4 & 2.? ResizeFrameBuffer message + * ReSizeFrameBuffer - tell the RFB client to alter its framebuffer, either + * due to a resize of the server desktop or a client-requested scaling factor. + * The pixel format remains unchanged. + */ + +typedef struct { + uint8_t type; /* always rfbReSizeFrameBuffer */ + uint8_t pad1; + uint16_t desktop_w; /* Desktop width */ + uint16_t desktop_h; /* Desktop height */ + uint16_t buffer_w; /* FrameBuffer width */ + uint16_t buffer_h; /* Framebuffer height */ + uint16_t pad2; + +} rfbPalmVNCReSizeFrameBufferMsg; + +#define sz_rfbPalmVNCReSizeFrameBufferMsg (12) + + + + +/*----------------------------------------------------------------------------- + * Union of all server->client messages. + */ + +typedef union { + uint8_t type; + rfbFramebufferUpdateMsg fu; + rfbSetColourMapEntriesMsg scme; + rfbBellMsg b; + rfbServerCutTextMsg sct; + rfbResizeFrameBufferMsg rsfb; + rfbPalmVNCReSizeFrameBufferMsg prsfb; + rfbFileTransferMsg ft; + rfbTextChatMsg tc; +} rfbServerToClientMsg; + + + +/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + * RDV Cache Encoding. + * special is not used at this point, can be used to reset cache or other specials + * just put it to make sure we don't have to change the encoding again. + */ + +typedef struct { + uint16_t special; +} rfbCacheRect; + +#define sz_rfbCacheRect 2 + + + + +/***************************************************************************** + * + * Message definitions (client -> server) + * + *****************************************************************************/ + + +/*----------------------------------------------------------------------------- + * SetPixelFormat - tell the RFB server the format in which the client wants + * pixels sent. + */ + +typedef struct { + uint8_t type; /* always rfbSetPixelFormat */ + uint8_t pad1; + uint16_t pad2; + rfbPixelFormat format; +} rfbSetPixelFormatMsg; + +#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4) + + +/*----------------------------------------------------------------------------- + * FixColourMapEntries - when the pixel format uses a "colour map", fix + * read-only colour map entries. + * + * ***************** NOT CURRENTLY SUPPORTED ***************** + */ + +typedef struct { + uint8_t type; /* always rfbFixColourMapEntries */ + uint8_t pad; + uint16_t firstColour; + uint16_t nColours; + + /* Followed by nColours * 3 * uint16_t + r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */ + +} rfbFixColourMapEntriesMsg; + +#define sz_rfbFixColourMapEntriesMsg 6 + + +/*----------------------------------------------------------------------------- + * SetEncodings - tell the RFB server which encoding types we accept. Put them + * in order of preference, if we have any. We may always receive raw + * encoding, even if we don't specify it here. + */ + +typedef struct { + uint8_t type; /* always rfbSetEncodings */ + uint8_t pad; + uint16_t nEncodings; + /* followed by nEncodings * uint32_t encoding types */ +} rfbSetEncodingsMsg; + +#define sz_rfbSetEncodingsMsg 4 + + +/*----------------------------------------------------------------------------- + * FramebufferUpdateRequest - request for a framebuffer update. If incremental + * is true then the client just wants the changes since the last update. If + * false then it wants the whole of the specified rectangle. + */ + +typedef struct { + uint8_t type; /* always rfbFramebufferUpdateRequest */ + uint8_t incremental; + uint16_t x; + uint16_t y; + uint16_t w; + uint16_t h; +} rfbFramebufferUpdateRequestMsg; + +#define sz_rfbFramebufferUpdateRequestMsg 10 + + +/*----------------------------------------------------------------------------- + * KeyEvent - key press or release + * + * Keys are specified using the "keysym" values defined by the X Window System. + * For most ordinary keys, the keysym is the same as the corresponding ASCII + * value. Other common keys are: + * + * BackSpace 0xff08 + * Tab 0xff09 + * Return or Enter 0xff0d + * Escape 0xff1b + * Insert 0xff63 + * Delete 0xffff + * Home 0xff50 + * End 0xff57 + * Page Up 0xff55 + * Page Down 0xff56 + * Left 0xff51 + * Up 0xff52 + * Right 0xff53 + * Down 0xff54 + * F1 0xffbe + * F2 0xffbf + * ... ... + * F12 0xffc9 + * Shift 0xffe1 + * Control 0xffe3 + * Meta 0xffe7 + * Alt 0xffe9 + */ + +typedef struct { + uint8_t type; /* always rfbKeyEvent */ + uint8_t down; /* true if down (press), false if up */ + uint16_t pad; + uint32_t key; /* key is specified as an X keysym */ +} rfbKeyEventMsg; + +#define sz_rfbKeyEventMsg 8 + + +/*----------------------------------------------------------------------------- + * PointerEvent - mouse/pen move and/or button press. + */ + +typedef struct { + uint8_t type; /* always rfbPointerEvent */ + uint8_t buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */ + uint16_t x; + uint16_t y; +} rfbPointerEventMsg; + +#define rfbButton1Mask 1 +#define rfbButton2Mask 2 +#define rfbButton3Mask 4 +#define rfbButton4Mask 8 +#define rfbButton5Mask 16 +/* RealVNC 335 method */ +#define rfbWheelUpMask rfbButton4Mask +#define rfbWheelDownMask rfbButton5Mask + +#define sz_rfbPointerEventMsg 6 + + + +/*----------------------------------------------------------------------------- + * ClientCutText - the client has new text in its cut buffer. + */ + +typedef struct { + uint8_t type; /* always rfbClientCutText */ + uint8_t pad1; + uint16_t pad2; + uint32_t length; + /* followed by char text[length] */ +} rfbClientCutTextMsg; + +#define sz_rfbClientCutTextMsg 8 + + + +/*----------------------------------------------------------------------------- + * sf@2002 - Set Server Scale + * SetServerScale - Server must change the scale of the client buffer. + */ + +typedef struct _rfbSetScaleMsg { + uint8_t type; /* always rfbSetScale */ + uint8_t scale; /* Scale value 1server messages. + */ + +typedef union { + uint8_t type; + rfbSetPixelFormatMsg spf; + rfbFixColourMapEntriesMsg fcme; + rfbSetEncodingsMsg se; + rfbFramebufferUpdateRequestMsg fur; + rfbKeyEventMsg ke; + rfbPointerEventMsg pe; + rfbClientCutTextMsg cct; + rfbSetScaleMsg ssc; + rfbPalmVNCSetScaleFactorMsg pssf; + rfbSetServerInputMsg sim; + rfbFileTransferMsg ft; + rfbSetSWMsg sw; + rfbTextChatMsg tc; +} rfbClientToServerMsg; + +/* + * vncauth.h - describes the functions provided by the vncauth library. + */ + +#define MAXPWLEN 8 +#define CHALLENGESIZE 16 + +extern int rfbEncryptAndStorePasswd(char *passwd, char *fname); +extern char *rfbDecryptPasswdFromFile(char *fname); +extern void rfbRandomBytes(unsigned char *bytes); +extern void rfbEncryptBytes(unsigned char *bytes, char *passwd); + + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h new file mode 100755 index 0000000..53da667 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/rfb/rfbregion.h @@ -0,0 +1,65 @@ +#ifndef SRAREGION_H +#define SRAREGION_H + +/* -=- SRA - Simple Region Algorithm + * A simple rectangular region implementation. + * Copyright (c) 2001 James "Wez" Weatherall, Johannes E. Schindelin + */ + +/* -=- sraRect */ + +typedef struct _rect { + int x1; + int y1; + int x2; + int y2; +} sraRect; + +typedef struct sraRegion sraRegion; + +/* -=- Region manipulation functions */ + +extern sraRegion *sraRgnCreate(); +extern sraRegion *sraRgnCreateRect(int x1, int y1, int x2, int y2); +extern sraRegion *sraRgnCreateRgn(const sraRegion *src); + +extern void sraRgnDestroy(sraRegion *rgn); +extern void sraRgnMakeEmpty(sraRegion *rgn); +extern rfbBool sraRgnAnd(sraRegion *dst, const sraRegion *src); +extern void sraRgnOr(sraRegion *dst, const sraRegion *src); +extern rfbBool sraRgnSubtract(sraRegion *dst, const sraRegion *src); + +extern void sraRgnOffset(sraRegion *dst, int dx, int dy); + +extern rfbBool sraRgnPopRect(sraRegion *region, sraRect *rect, + unsigned long flags); + +extern unsigned long sraRgnCountRects(const sraRegion *rgn); +extern rfbBool sraRgnEmpty(const sraRegion *rgn); + +extern sraRegion *sraRgnBBox(const sraRegion *src); + +/* -=- rectangle iterator */ + +typedef struct sraRectangleIterator { + rfbBool reverseX,reverseY; + int ptrSize,ptrPos; + struct sraSpan** sPtrs; +} sraRectangleIterator; + +extern sraRectangleIterator *sraRgnGetIterator(sraRegion *s); +extern sraRectangleIterator *sraRgnGetReverseIterator(sraRegion *s,rfbBool reverseX,rfbBool reverseY); +extern rfbBool sraRgnIteratorNext(sraRectangleIterator *i,sraRect *r); +extern void sraRgnReleaseIterator(sraRectangleIterator *i); + +void sraRgnPrint(const sraRegion *s); + +/* -=- Rectangle clipper (for speed) */ + +extern rfbBool sraClipRect(int *x, int *y, int *w, int *h, + int cx, int cy, int cw, int ch); + +extern rfbBool sraClipRect2(int *x, int *y, int *x2, int *y2, + int cx, int cy, int cx2, int cy2); + +#endif diff --git a/droidvncgrab/vnc/libvncserver-kanaka/success.html b/droidvncgrab/vnc/libvncserver-kanaka/success.html new file mode 100755 index 0000000..45caf18 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/success.html @@ -0,0 +1,45 @@ + + +Success stories + + +
    +
  • +Karl Runge took my first version of +x11vnc, which was just a proof-of-concept that the library actually is +usable, and turned it into a +fully fledged application. +
  • +Tim Jansen created KRFB, which is +x11vnc integrated into KDE. +
  • +Jeff Mock of the world's largest radio telescope +in Arecibo sent me a nice +screenshot, +describing his use of LibVNCServer: + +

    + +I've been using it for about 4 months +on a project to build a new spectrometer for the radio telescope at +Arecibo. Arecibo is the largest radio telescope in the world (305m!) in +Puerto Rico. It has 10-times the collecting area of the second largest +telescope in Effelsburg (maybe near you?). + +

    + +The project is an embedded linux box that boots from a compact flash +card. The root filesystem is only about 5MB. X wasn't reasonable +for such a small embedded system, but libvncserver was perfect. On +the console we run graphical diagnostics that write directly to the +frame buffer. It was a simple matter to hook this direct-framebuffer +application to libvncserver. This way we can easily view the +diagnostics for the spectrometer from the control room (or anyplace +else for that matter). + +

  • +michu let me know that +LCD4Linux has a VNC backend using LibVNCServer. + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore new file mode 100755 index 0000000..0c7b7d7 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/.cvsignore @@ -0,0 +1,9 @@ +.deps +Makefile +Makefile.in +encodingstest +blooptest +cargstest +copyrecttest +cursortest + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am new file mode 100755 index 0000000..30498c2 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = -I$(top_srcdir) +LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLIB@ + +if HAVE_LIBPTHREAD +BACKGROUND_TEST=blooptest +ENCODINGS_TEST=encodingstest +endif + +copyrecttest_LDADD=$(LDADD) -lm + +check_PROGRAMS=$(ENCODINGS_TEST) cargstest copyrecttest $(BACKGROUND_TEST) \ + cursortest + +test: encodingstest$(EXEEXT) cargstest$(EXEEXT) copyrecttest$(EXEEXT) + ./encodingstest && ./cargstest + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c new file mode 100755 index 0000000..a2661e8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/blooptest.c @@ -0,0 +1,2 @@ +#define BACKGROUND_LOOP_TEST +#include "../examples/example.c" diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c new file mode 100755 index 0000000..263982d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/cargstest.c @@ -0,0 +1,29 @@ +#include + +int main(int argc,char** argv) +{ + int fake_argc=6; + char* fake_argv[6]={ + "dummy_program","-alwaysshared","-httpport","3002","-nothing","-dontdisconnect" + }; + rfbScreenInfoPtr screen; + rfbBool ret=0; + + screen = rfbGetScreen(&fake_argc,fake_argv,1024,768,8,3,1); +#define CHECK(a,b) if(screen->a!=b) { fprintf(stderr,#a " is %d (should be " #b ")\n",screen->a); ret=1; } + CHECK(width,1024); + CHECK(height,768); + CHECK(alwaysShared,TRUE); + CHECK(httpPort,3002); + CHECK(dontDisconnect,TRUE); + if(fake_argc!=2) { + fprintf(stderr,"fake_argc is %d (should be 2)\n",fake_argc); + ret=1; + } + if(strcmp(fake_argv[1],"-nothing")) { + fprintf(stderr,"fake_argv[1] is %s (should be -nothing)\n",fake_argv[1]); + ret=1; + } + return ret; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c new file mode 100755 index 0000000..5521595 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/copyrecttest.c @@ -0,0 +1,53 @@ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include + +static void initBackground(rfbScreenInfoPtr server) +{ + unsigned int i,j; + + for(i=0;iwidth;i++) + for(j=0;jheight;j++) { + server->frameBuffer[(j*server->width+i)*4+0]=i&0xff; + server->frameBuffer[(j*server->width+i)*4+1]=j&0xff; + server->frameBuffer[(j*server->width+i)*4+2]=(i*j)&0xff; + } +} + +int main(int argc,char** argv) +{ + int width=400,height=300,w=20,x,y; + double r,phi=0; + + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,width,height,8,3,4); + server->frameBuffer=(char*)malloc(width*height*4); + initBackground(server); + server->deferUpdateTime=0; + rfbInitServer(server); + + r=0; + while(1) { + if(r<=0) { + initBackground(server); + rfbMarkRectAsModified(server,0,0,width,height); + r=0.43; + phi=0; + } else { + r-=0.0001; + phi+=0.02; + if(phi>2*M_PI) + phi-=2*M_PI; + } + x=width*(0.5+cos(phi)*r); + y=height*(0.5+sin(phi)*r); + if(x>=0 && y>=0 && x+w<=width && y+w<=height) { + unsigned int dx=width*0.5*(1-cos(phi)*r)-x, + dy=height*0.5*(1-sin(phi)*r)-y; + rfbDoCopyRect(server,x,y,x+w,y+w,-dx,-dy); + } + rfbProcessEvents(server,50000); + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c new file mode 100755 index 0000000..7a4efd3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/cursortest.c @@ -0,0 +1,351 @@ +/* + * + * This is an example of how to use libvncserver. + * + * libvncserver example + * Copyright (C) 2005 Johannes E. Schindelin , + * Karl Runge + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#include + +static const int bpp=4; +static int maxx=800, maxy=600; + +/* This initializes a nice (?) background */ + +static void initBuffer(unsigned char* buffer) +{ + int i,j; + for(j=0;jxhot=width/2;c->yhot=height/2; + + rfbSetCursor(rfbScreen, c); +} + +static void SetXCursor2(rfbScreenInfoPtr rfbScreen) +{ + int width=13,height=22; + char cursor[]= + " xx " + " x x " + " x x " + " x x " + " x x " + " x x " + " x x " + " x x " + " x xx x " + " x x x xxx " + " x xx x x " + " xx x x " + " xx x x " + " x x x " + " x x x " + " x x " + " x x " + " x x " + " xx " + " " + " ", + mask[]= + "xxx " + "xxxx " + "xxxxx " + "xxxxxx " + "xxxxxxx " + "xxxxxxxx " + "xxxxxxxxx " + "xxxxxxxxxx " + "xxxxxxxxxxx " + "xxxxxxxxxxxx " + "xxxxxxxxxxxxx" + "xxxxxxxxxxxxx" + "xxxxxxxxxx x" + "xxxxxxxxxx " + "xxx xxxxxx " + "xxx xxxxxx " + "xx xxxxxx " + " xxxxx " + " xxxxxx" + " xxxxx" + " xxx " + " "; + rfbCursorPtr c; + + c=rfbMakeXCursor(width,height,cursor,mask); + c->xhot=0;c->yhot=0; + + rfbSetCursor(rfbScreen, c); +} + +/* Example for a rich cursor (full-colour) */ + +static void SetRichCursor(rfbScreenInfoPtr rfbScreen) +{ + int i,j,w=32,h=32; + /* runge */ + /* rfbCursorPtr c = rfbScreen->cursor; */ + rfbCursorPtr c; + char bitmap[]= + " " + " xxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxx xxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxx xxxxxxxxx xxxxxx " + " xxxxx xxxxxxxxxxx xxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxx xxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxx xxxxxxxxxxxxxx " + " xxxxxxxxxx xxxxxxxxxxxx " + " xxxxxxxxx xxxxxxxxx " + " xxxxxxxxxx xxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxx " + " xxxx xxxxxxxxxxxxx " + " xx x xxxxxxxxxxx " + " xxx xxxxxxxxxxx " + " xxxx xxxxxxxxxxx " + " xxxxxx xxxxxxxxxxxx " + " xxxxxxxxxxxxxxxxxxxxxx " + " xxxxxxxxxxxxxxxx " + " "; + + c=rfbMakeXCursor(w,h,bitmap,bitmap); + c->xhot = 16; c->yhot = 24; + + c->richSource = (char*)malloc(w*h*bpp); + for(j=0;jrichSource[j*w*bpp+i*bpp+0]=i*0xff/w; + c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h); + c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h; + c->richSource[j*w*bpp+i*bpp+3]=0; + } + } + rfbSetCursor(rfbScreen, c); +} + +/* runge */ +static void SetRichCursor2(rfbScreenInfoPtr rfbScreen) +{ + int i,j,w=17,h=16; + /* rfbCursorPtr c = rfbScreen->cursor; */ + rfbCursorPtr c; + char bitmap[]= + " " + "xxxx " + "xxxxxxxx " + "xxxxxxxxxxxx x" + "xxx xxxxxxxx x" + "xxxxxxxxxxxxxx x" + "xxxxxxxxxxxxxxx x" + "xxxxx xxxxxxx x" + "xxxx xxxxxx x" + "xxxxx xxxxxxx x" + "xxxxxxxxxxxxxxx x" + "xxxxxxxxxxxxxxx x" + "xxxxxxxxxxxxxx x" + "xxxxxxxxxxxxx x" + "xxxxxxxxxxxxx x" + "xxxxxxxxxxxxx x"; + /* c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); */ + c=rfbMakeXCursor(w,h,bitmap,bitmap); + c->xhot = 5; c->yhot = 7; + + c->richSource = (char*)malloc(w*h*bpp); + for(j=0;jrichSource[j*w*bpp+i*bpp+0]=0xff; + c->richSource[j*w*bpp+i*bpp+1]=0x00; + c->richSource[j*w*bpp+i*bpp+2]=0x7f; + c->richSource[j*w*bpp+i*bpp+3]=0; + } + } + rfbSetCursor(rfbScreen, c); +} + +/* alpha channel */ + +static void SetAlphaCursor(rfbScreenInfoPtr screen,int mode) +{ + int i,j; + rfbCursorPtr c = screen->cursor; + int maskStride=(c->width+7)/8; + + if(!c) + return; + + if(c->alphaSource) { + free(c->alphaSource); + c->alphaSource=NULL; + } + + if(mode==0) + return; + + c->alphaSource = (unsigned char*)malloc(c->width*c->height); + + for(j=0;jheight;j++) + for(i=0;iwidth;i++) { + unsigned char value=0x100*i/c->width; + rfbBool masked=(c->mask[(i/8)+maskStride*j]<<(i&7))&0x80; + c->alphaSource[i+c->width*j]=(masked?(mode==1?value:0xff-value):0); + } + if(c->cleanupMask) + free(c->mask); + c->mask=rfbMakeMaskFromAlphaSource(c->width,c->height,c->alphaSource); + c->cleanupMask=TRUE; +} + +/* Here the pointer events are handled */ + +static void doptr(int buttonMask,int x,int y,rfbClientPtr cl) +{ + static int oldButtonMask=0; + static int counter=0; + + if((oldButtonMask&1)==0 && (buttonMask&1)==1) { + switch(++counter) { + case 7: + SetRichCursor(cl->screen); + SetAlphaCursor(cl->screen,2); + break; + case 6: + SetRichCursor(cl->screen); + SetAlphaCursor(cl->screen,1); + break; + case 5: + SetRichCursor2(cl->screen); + SetAlphaCursor(cl->screen,0); + break; + case 4: + SetXCursor(cl->screen); + break; + case 3: + SetRichCursor2(cl->screen); + SetAlphaCursor(cl->screen,2); + break; + case 2: + SetXCursor(cl->screen); + SetAlphaCursor(cl->screen,2); + break; + case 1: + SetXCursor2(cl->screen); + SetAlphaCursor(cl->screen,0); + break; + default: + SetRichCursor(cl->screen); + counter=0; + } + } + if(buttonMask&2) { + rfbScreenCleanup(cl->screen); + exit(0); + } + + if(buttonMask&4) + rfbCloseClient(cl); + + + oldButtonMask=buttonMask; + + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +} + +/* Initialization */ + +int main(int argc,char** argv) +{ + rfbScreenInfoPtr rfbScreen = + rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp); + rfbScreen->desktopName = "Cursor Test"; + rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp); + rfbScreen->ptrAddEvent = doptr; + + initBuffer((unsigned char*)rfbScreen->frameBuffer); + + + SetRichCursor(rfbScreen); + + /* initialize the server */ + rfbInitServer(rfbScreen); + + rfbLog("Change cursor shape with left mouse button,\n\t" + "quit with right one (middle button quits server).\n"); + + /* this is the blocking event loop, i.e. it never returns */ + /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */ + rfbRunEventLoop(rfbScreen,40000,FALSE); + + free(rfbScreen->frameBuffer); + rfbScreenCleanup(rfbScreen); + + return(0); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c b/droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c new file mode 100755 index 0000000..bef30a8 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/test/encodingstest.c @@ -0,0 +1,353 @@ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#endif +#include +#include +#include +#include + +#ifndef LIBVNCSERVER_HAVE_LIBPTHREAD +#error This test need pthread support (otherwise the client blocks the client) +#endif + +#define ALL_AT_ONCE +/*#define VERY_VERBOSE*/ + +static MUTEX(frameBufferMutex); + +typedef struct { int id; char* str; } encoding_t; +static encoding_t testEncodings[]={ + { rfbEncodingRaw, "raw" }, + { rfbEncodingRRE, "rre" }, + /* TODO: fix corre */ + /* { rfbEncodingCoRRE, "corre" }, */ + { rfbEncodingHextile, "hextile" }, +#ifdef LIBVNCSERVER_HAVE_LIBZ + { rfbEncodingZlib, "zlib" }, + { rfbEncodingZlibHex, "zlibhex" }, + { rfbEncodingZRLE, "zrle" }, +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + { rfbEncodingTight, "tight" }, +#endif +#endif + { 0, NULL } +}; + +#define NUMBER_OF_ENCODINGS_TO_TEST (sizeof(testEncodings)/sizeof(encoding_t)-1) +/*#define NUMBER_OF_ENCODINGS_TO_TEST 1*/ + +/* Here come the variables/functions to handle the test output */ + +static const int width=400,height=300; +static struct { int x1,y1,x2,y2; } lastUpdateRect; +static unsigned int statistics[2][NUMBER_OF_ENCODINGS_TO_TEST]; +static unsigned int totalFailed,totalCount; +static unsigned int countGotUpdate; +static MUTEX(statisticsMutex); + +static void initStatistics(void) { + memset(statistics[0],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); + memset(statistics[1],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); + totalFailed=totalCount=0; + lastUpdateRect.x1=0; + lastUpdateRect.y1=0; + lastUpdateRect.x2=width; + lastUpdateRect.y2=height; + INIT_MUTEX(statisticsMutex); +} + +static void updateServerStatistics(int x1,int y1,int x2,int y2) { + LOCK(statisticsMutex); + countGotUpdate=0; + lastUpdateRect.x1=x1; + lastUpdateRect.y1=y1; + lastUpdateRect.x2=x2; + lastUpdateRect.y2=y2; + UNLOCK(statisticsMutex); +} + +static void updateStatistics(int encodingIndex,rfbBool failed) { + LOCK(statisticsMutex); + if(failed) { + statistics[1][encodingIndex]++; + totalFailed++; + } + statistics[0][encodingIndex]++; + totalCount++; + countGotUpdate++; + UNLOCK(statisticsMutex); +} + +/* Here begin the functions for the client. They will be called in a + * pthread. */ + +/* maxDelta=0 means they are expected to match exactly; + * maxDelta>0 means that the average difference must be lower than maxDelta */ +static rfbBool doFramebuffersMatch(rfbScreenInfo* server,rfbClient* client, + int maxDelta) +{ + int i,j,k; + unsigned int total=0,diff=0; + if(server->width!=client->width || server->height!=client->height) + return FALSE; + LOCK(frameBufferMutex); + /* TODO: write unit test for colour transformation, use here, too */ + for(i=0;iwidth;i++) + for(j=0;jheight;j++) + for(k=0;k<3/*server->serverFormat.bitsPerPixel/8*/;k++) { + unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes]; + unsigned char cl=client->frameBuffer[k+i*4+j*client->width*4]; + + if(maxDelta==0 && s!=cl) { + UNLOCK(frameBufferMutex); + return FALSE; + } else { + total++; + diff+=(s>cl?s-cl:cl-s); + } + } + UNLOCK(frameBufferMutex); + if(maxDelta>0 && diff/total>=maxDelta) + return FALSE; + return TRUE; +} + +static rfbBool resize(rfbClient* cl) { + if(cl->frameBuffer) + free(cl->frameBuffer); + cl->frameBuffer=(char*)malloc(cl->width*cl->height*cl->format.bitsPerPixel/8); + if(!cl->frameBuffer) + return FALSE; + SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE); + return TRUE; +} + +typedef struct clientData { + int encodingIndex; + rfbScreenInfo* server; + char* display; +} clientData; + +static void update(rfbClient* client,int x,int y,int w,int h) { + clientData* cd=(clientData*)client->clientData; + int maxDelta=0; + +#ifndef VERY_VERBOSE + static const char* progress="|/-\\"; + static int counter=0; + + if(++counter>sizeof(progress)) counter=0; + fprintf(stderr,"%c\r",progress[counter]); +#else + rfbClientLog("Got update (encoding=%s): (%d,%d)-(%d,%d)\n", + testEncodings[cd->encodingIndex].str, + x,y,x+w,y+h); +#endif + + /* only check if this was the last update */ + if(x+w!=lastUpdateRect.x2 || y+h!=lastUpdateRect.y2) { +#ifdef VERY_VERBOSE + rfbClientLog("Waiting (%d!=%d or %d!=%d)\n", + x+w,lastUpdateRect.x2,y+h,lastUpdateRect.y2); +#endif + return; + } + +#ifdef LIBVNCSERVER_HAVE_LIBZ + if(testEncodings[cd->encodingIndex].id==rfbEncodingTight) + maxDelta=5; +#endif + + updateStatistics(cd->encodingIndex, + !doFramebuffersMatch(cd->server,client,maxDelta)); +} + +static void* clientLoop(void* data) { + rfbClient* client=(rfbClient*)data; + clientData* cd=(clientData*)client->clientData; + + client->appData.encodingsString=strdup(testEncodings[cd->encodingIndex].str); + + sleep(1); + rfbClientLog("Starting client (encoding %s, display %s)\n", + testEncodings[cd->encodingIndex].str, + cd->display); + if(!rfbInitClient(client,NULL,NULL)) { + rfbClientErr("Had problems starting client (encoding %s)\n", + testEncodings[cd->encodingIndex].str); + updateStatistics(cd->encodingIndex,TRUE); + return NULL; + } + while(1) { + if(WaitForMessage(client,50)>=0) + if(!HandleRFBServerMessage(client)) + break; + } + free(((clientData*)client->clientData)->display); + free(client->clientData); + if(client->frameBuffer) + free(client->frameBuffer); + rfbClientCleanup(client); + return NULL; +} + +static pthread_t all_threads[NUMBER_OF_ENCODINGS_TO_TEST]; +static int thread_counter; + +static void startClient(int encodingIndex,rfbScreenInfo* server) { + rfbClient* client=rfbGetClient(8,3,4); + clientData* cd; + + client->clientData=malloc(sizeof(clientData)); + client->MallocFrameBuffer=resize; + client->GotFrameBufferUpdate=update; + + cd=(clientData*)client->clientData; + cd->encodingIndex=encodingIndex; + cd->server=server; + cd->display=(char*)malloc(6); + sprintf(cd->display,":%d",server->port-5900); + + lastUpdateRect.x1=lastUpdateRect.y1=0; + lastUpdateRect.x2=server->width; + lastUpdateRect.y2=server->height; + + pthread_create(&all_threads[thread_counter++],NULL,clientLoop,(void*)client); +} + +/* Here begin the server functions */ + +static void idle(rfbScreenInfo* server) +{ + int c; + rfbBool goForward; + + LOCK(statisticsMutex); +#ifdef ALL_AT_ONCE + goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST); +#else + goForward=(countGotUpdate==1); +#endif + /* if(lastUpdateRect.x2==354) + rfbLog("server checked: countGotUpdate=%d\n",countGotUpdate); */ + UNLOCK(statisticsMutex); + if(!goForward) + return; + countGotUpdate=0; + + LOCK(frameBufferMutex); + { + int i,j; + int x1=(rand()%(server->width-1)),x2=(rand()%(server->width-1)), + y1=(rand()%(server->height-1)),y2=(rand()%(server->height-1)); + if(x1>x2) { i=x1; x1=x2; x2=i; } + if(y1>y2) { i=y1; y1=y2; y2=i; } + x2++; y2++; + for(c=0;c<3;c++) { + for(i=x1;iframeBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1)/(x2-x1+y2-y1); + } + rfbMarkRectAsModified(server,x1,y1,x2,y2); + + lastUpdateRect.x1=x1; + lastUpdateRect.y1=y1; + lastUpdateRect.x2=x2; + lastUpdateRect.y2=y2; +#ifdef VERY_VERBOSE + rfbLog("Sent update (%d,%d)-(%d,%d)\n",x1,y1,x2,y2); +#endif + } + UNLOCK(frameBufferMutex); +} + +/* log function (to show what messages are from the client) */ + +static void +rfbTestLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X (client) ", localtime(&log_clock)); + fprintf(stderr,buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); +} + +/* the main function */ + +int main(int argc,char** argv) +{ + int i,j; + time_t t; + rfbScreenInfoPtr server; + + rfbClientLog=rfbTestLog; + rfbClientErr=rfbTestLog; + + /* Initialize server */ + server=rfbGetScreen(&argc,argv,width,height,8,3,4); + + server->frameBuffer=malloc(400*300*4); + server->cursor=NULL; + for(j=0;j<400*300*4;j++) + server->frameBuffer[j]=j; + rfbInitServer(server); + rfbProcessEvents(server,0); + + initStatistics(); + +#ifndef ALL_AT_ONCE + for(i=0;iframeBuffer); + + rfbLog("Statistics:\n"); + for(i=0;i */ ++ static int alphablend = -1; ++ ++ if (alphablend < 0) { ++ /* you have to set NO_ALPHABLEND=1 in your environment to disable */ ++ if (getenv("NO_ALPHABLEND")) { ++ alphablend = 0; ++ } else { ++ alphablend = 1; ++ } ++ } ++ ++ bytesPerPixel = myFormat.bitsPerPixel / 8; ++ ++ if (alphablend && bytesPerPixel == 4) { ++ unsigned long pixel, put, *upos, *upix; ++ int got_alpha = 0, rsX, rsY, rsW, rsH; ++ static XImage *image = NULL; ++ static int iwidth = 128; ++ ++ if (! image) { ++ /* watch out for tiny fb (rare) */ ++ if (iwidth > si.framebufferWidth) { ++ iwidth = si.framebufferWidth; ++ } ++ if (iwidth > si.framebufferHeight) { ++ iwidth = si.framebufferHeight; ++ } ++ ++ /* initialize an XImage with a chunk of desktopWin */ ++ image = XGetImage(dpy, desktopWin, 0, 0, iwidth, iwidth, ++ AllPlanes, ZPixmap); ++ } ++ ++ /* first check if there is any non-zero alpha channel data at all: */ ++ for (y = 0; y < rcHeight; y++) { ++ for (x = 0; x < rcWidth; x++) { ++ int alpha; ++ ++ offset = y * rcWidth + x; ++ pos = (char *)&rcSource[offset * bytesPerPixel]; ++ ++ upos = (unsigned long *) pos; ++ alpha = (*upos & 0xff000000) >> 24; ++ if (alpha) { ++ got_alpha = 1; ++ break; ++ } ++ } ++ if (got_alpha) { ++ break; ++ } ++ } ++ ++ if (!got_alpha) { ++ /* no alpha channel data, fallback to the old way */ ++ goto oldway; ++ } ++ ++ /* load the saved fb patch in to image (faster way?) */ ++ XGetSubImage(dpy, rcSavedArea, 0, 0, rcWidth, rcHeight, ++ AllPlanes, ZPixmap, image, 0, 0); ++ upix = (unsigned long *)image->data; ++ ++ /* if the richcursor is clipped, the fb patch will be smaller */ ++ rsW = rcWidth; ++ rsX = 0; /* used to denote a shift from the left side */ ++ x = rcCursorX - rcHotX; ++ if (x < 0) { ++ rsW += x; ++ rsX = -x; ++ } else if (x + rsW > si.framebufferWidth) { ++ rsW = si.framebufferWidth - x; ++ } ++ rsH = rcHeight; ++ rsY = 0; /* used to denote a shift from the top side */ ++ y = rcCursorY - rcHotY; ++ if (y < 0) { ++ rsH += y; ++ rsY = -y; ++ } else if (y + rsH > si.framebufferHeight) { ++ rsH = si.framebufferHeight - y; ++ } ++ ++ /* ++ * now loop over the cursor data, blend in the fb values, ++ * and then overwrite the fb (CopyDataToScreen()) ++ */ ++ for (y = 0; y < rcHeight; y++) { ++ y0 = rcCursorY - rcHotY + y; ++ if (y0 < 0 || y0 >= si.framebufferHeight) { ++ continue; /* clipped */ ++ } ++ for (x = 0; x < rcWidth; x++) { ++ int alpha, color_curs, color_fb, i; ++ ++ x0 = rcCursorX - rcHotX + x; ++ if (x0 < 0 || x0 >= si.framebufferWidth) { ++ continue; /* clipped */ ++ } ++ ++ offset = y * rcWidth + x; ++ pos = (char *)&rcSource[offset * bytesPerPixel]; ++ ++ /* extract secret alpha byte from rich cursor: */ ++ upos = (unsigned long *) pos; ++ alpha = (*upos & 0xff000000) >> 24; /* XXX MSB? */ ++ ++ /* extract the pixel from the fb: */ ++ pixel = *(upix + (y-rsY)*iwidth + (x-rsX)); ++ ++ put = 0; ++ /* for simplicity, blend all 4 bytes */ ++ for (i = 0; i < 4; i++) { ++ int sh = i*8; ++ color_curs = ((0xff << sh) & *upos) >> sh; ++ color_fb = ((0xff << sh) & pixel) >> sh; ++ ++ /* XXX assumes pre-multipled color_curs */ ++ color_fb = color_curs ++ + ((0xff - alpha) * color_fb)/0xff; ++ put |= color_fb << sh; ++ } ++ /* place in the fb: */ ++ CopyDataToScreen((char *)&put, x0, y0, 1, 1); ++ } ++ } ++ return; ++ } ++oldway: ++#endif ++ + bytesPerPixel = myFormat.bitsPerPixel / 8; + + /* FIXME: Speed optimization is possible. */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore new file mode 100755 index 0000000..88897f0 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/.cvsignore @@ -0,0 +1,7 @@ +LinuxVNC +VNCommand +example +.deps +Makefile +Makefile.in + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog new file mode 100755 index 0000000..53a9c37 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/ChangeLog @@ -0,0 +1,15 @@ +included in LibVNCServer package, autoconf'ed it +SetXCutText implemented +fix for cargs +attributes work. +cursor in LinuxVNC is shown. +paste works +selection works (no cursor trails) +LinuxVNC gets it's dimensions via ioctl TIOCGWINSZ +First working key injection in LinuxVNC! +Added Mouse marking +added screenBuffer (so you have ASCII screen also) +fixed CopyRect for scrolling (need to propagate to libvncserver) +made VNCommand work (no prompt for bash, but else seems ok) +added flag for VNCommand to send input only after a newline + (good for interactive bash) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c new file mode 100755 index 0000000..9b58954 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/LinuxVNC.c @@ -0,0 +1,191 @@ +#include +#include "VNConsole.h" +#include "vga.h" +#include +#include + +static int tty=2; +static int tty_inject_device; + +void do_key(rfbBool down,rfbKeySym keySym,rfbClientPtr cl) +{ + static char isControl=0; + + if(down) { + /* if(keySym==XK_Escape) + rfbCloseClient(cl); + else */ if(keySym==XK_Control_L || keySym==XK_Control_R) + isControl++; + else if(tty_inject_device>=0) { + if(keySym==XK_Escape) + keySym=27; + if(isControl) { + if(keySym>='a' && keySym<='z') + keySym-='a'-1; + else if(keySym>='A' && keySym<='Z') + keySym-='A'-1; + else + keySym=0xffff; + } + + if(keySym==XK_Tab) + keySym='\t'; + else if(keySym==XK_Return) + keySym='\r'; + else if(keySym==XK_BackSpace) + keySym=8; + else if(keySym==XK_Home || keySym==XK_KP_Home) + keySym=1; + else if(keySym==XK_End || keySym==XK_KP_End) + keySym=5; + else if(keySym==XK_Up || keySym==XK_KP_Up) + keySym=16; + else if(keySym==XK_Down || keySym==XK_KP_Down) + keySym=14; + else if(keySym==XK_Right || keySym==XK_KP_Right) + keySym=6; + else if(keySym==XK_Left || keySym==XK_KP_Left) + keySym=2; + + if(keySym<0x100) { + int ret; + ret=ioctl(tty_inject_device,TIOCSTI,&keySym); + if(ret<0) { + static char device[64]; + close(tty_inject_device); + sprintf(device,"/dev/tty%d",tty); + tty_inject_device=open(device,O_WRONLY); + ret=ioctl(tty_inject_device,TIOCSTI,&keySym); + if(ret<0) + rfbErr("Couldn't reopen device %s!\n",device); + } + } + } + } else if(keySym==XK_Control_L || keySym==XK_Control_R) + if(isControl>0) + isControl--; +} + +/* these colours are from linux kernel drivers/char/console.c */ +unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7, + 8,12,10,14, 9,13,11,15 }; +/* the default colour table, for VGA+ colour systems */ +int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa, + 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff}; +int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa, + 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff}; +int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa, + 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff}; + +int main(int argc,char **argv) +{ + int width=80,height=25; + char *buffer; + vncConsolePtr console; + char tty_device[64],title[128]; + int i; + FILE* tty_file; + struct winsize dimensions; + + if(argc>1) { + if((tty=atoi(argv[1]))<1) { + rfbErr("Usage: %s [tty_number [vnc args]]\n",argv[0]); + exit(1); + } else { + argv++; + argc--; + } + } + + /* getopt goes here! */ + + sprintf(tty_device,"/dev/tty%d",tty); + if((tty_inject_device=open(tty_device,O_WRONLY))<0) { + rfbErr("Couldn't open tty device %s!\n",tty_device); + exit(1); + } + rfbLog("Using device %s.\n",tty_device); + + if(ioctl(tty_inject_device,TIOCGWINSZ,&dimensions)>=0) { + width=dimensions.ws_col; + height=dimensions.ws_row; + } + + sprintf(title,"LinuxVNC: /dev/tty%d",tty); + + /* console init */ + if(!(console=vcGetConsole(&argc,argv,width,height,&vgaFont,TRUE))) + exit(1); + + for(i=0;i<16;i++) { + console->screen->colourMap.data.bytes[i*3+0]=default_red[color_table[i]]; + console->screen->colourMap.data.bytes[i*3+1]=default_grn[color_table[i]]; + console->screen->colourMap.data.bytes[i*3+2]=default_blu[color_table[i]]; + } + console->screen->desktopName=title; + console->screen->kbdAddEvent=do_key; + console->selectTimeOut=100000; + console->wrapBottomToTop=TRUE; +#ifdef USE_OLD_VCS + buffer=malloc(width*height); + console->cursorActive=FALSE; +#else + buffer=malloc(width*height*2+4); + console->cursorActive=TRUE; +#endif + /* memcpy(buffer,console->screenBuffer,width*height); */ + +#ifdef USE_OLD_VCS + sprintf(tty_device,"/dev/vcs%d",tty); +#else + sprintf(tty_device,"/dev/vcsa%d",tty); +#endif + + while(rfbIsActive(console->screen)) { + if(!console->currentlyMarking) { + tty_file=fopen(tty_device,"rb"); + if(!tty_file) { + rfbErr("cannot open device \"%s\"\n", + tty_device); + exit(1); + } +#ifdef USE_OLD_VCS + fread(buffer,width,height,tty_file); +#else + fread(buffer,width*height*2+4,1,tty_file); + vcHideCursor(console); +#endif + fclose(tty_file); + + for(i=0;iwidth*console->height;i++) { + if +#ifdef USE_OLD_VCS + (buffer[i]!=console->screenBuffer[i]) +#else + (buffer[4+2*i]!=console->screenBuffer[i] || + buffer[5+2*i]!=console->attributeBuffer[i]) +#endif + { + console->x=(i%console->width); + console->y=(i/console->width); + /* + rfbLog("changes: %d,%d (%d!=%d || %d!=%d)\n", + console->x,console->y, + buffer[4+2*i],console->screenBuffer[i], + buffer[5+2*i],console->attributeBuffer[i]); + */ + +#ifdef USE_OLD_VCS + vcPutChar(console,buffer[i]); +#else + vcPutCharColour(console,buffer[4+i*2],buffer[5+i*2]&0x7,buffer[5+i*2]>>4); +#endif + } + } + console->x=buffer[2]; + console->y=buffer[3]; + } + vcProcessEvents(console); + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am new file mode 100755 index 0000000..3ad36a3 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/Makefile.am @@ -0,0 +1,25 @@ +INCLUDES = -I$(top_srcdir) + +CONSOLE_SRCS=VNConsole.c + +noinst_HEADERS=VNConsole.h vga.h + +LDADD=../libvncserver/libvncserver.la @WSOCKLIB@ + +if LINUX +if ! MINGW +bin_PROGRAMS=LinuxVNC +LinuxVNC_SOURCES=LinuxVNC.c $(CONSOLE_SRCS) +endif +endif + +if ! MINGW +VNCOMMAND=VNCommand +endif + +noinst_PROGRAMS=example $(VNCOMMAND) +example_SOURCES=example.c $(CONSOLE_SRCS) +VNCommand_SOURCES=VNCommand.c $(CONSOLE_SRCS) + + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/README b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/README new file mode 100755 index 0000000..b01e88a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/README @@ -0,0 +1,25 @@ + +In this stage (beta), there are two programs functional: + +LinuxVNC + monitor a virtual console (text mode) of Linux. You need + root privileges, or at least be in the "tty" group, because + it reads /dev/vcsN and writes /dev/ttyN. + It follows the same idea as WinVNC, x11vnc or OSXvnc, i.e. it + takes an existing desktop and exports it via RFB (VNC), just that + LinuxVNC exports text. + +VNCommand + executes redirecting stdin from a vncviewer and stdout & + stderr to the vnc clients. This might be renamed to vncTerm if + there are some term capabilities added (up to now, bash doesn't look + nice). Colours and other ANSI sequences need to be added. + +My original plan was to create a program named vncTerm. It was meant to +overcome incompatibilities between different TERMs, but I found "screen" to +be just such a program. Maybe once some time in the future I'll make a +patch for screen to use VNConsole to export it's contents via RFB... + +These two programs are a simple application of LibVNCServer with a small +console layer in between (VNConsole). You can use them under the terms +(not vncTerms ;-) of the GPL. They where written by Johannes E. Schindelin. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO new file mode 100755 index 0000000..5c6f189 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/TODO @@ -0,0 +1,21 @@ +VNConsole: +LinuxVNC: +VNCommand: + make Control or Alt sequences work. + Find out how to satisfy isatty(). => /dev/ptyN + Fix check if child is alive. + Add command line option for real interactive mode. + +done: + +.treat colours correctly (use /dev/vcsaN's attributes). +.introduce per cell colours (for attributes) +.fix cursor fuckup when selecting. +.default to paste for right mouse button. +.have an idea how to insert keys +.convert VNCommand to an interactive shell (vncTerm) +.bidirectional pipes (spawn a shell ...) +.mark with mouse (copy text) +.when scrolling, cursor must be hidden! + + modifiedRegion which are copied with CopyRect have to be modified also. diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c new file mode 100755 index 0000000..ecf2543 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNCommand.c @@ -0,0 +1,127 @@ +#ifdef __STRICT_ANSI__ +#define _BSD_SOURCE +#define _POSIX_SOURCE +#endif +#include "VNConsole.h" +#include "vga.h" +#ifdef LIBVNCSERVER_HAVE_FCNTL_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_UNISTD_H +#include +#endif +#ifdef LIBVNCSERVER_HAVE_SYS_WAIT_H +#include +#endif +#include + + +int main(int argc, char **argv) +{ + rfbBool interactive=FALSE,sendOnlyWholeLines=TRUE; + int serverArgc,programArg0; + for(serverArgc=1;serverArgcdoEcho = FALSE; + + if(max_fdinputCount) { + if(sendOnlyWholeLines) { + for(i=0;iinputCount;i++) + if(console->inputBuffer[i]=='\n') { + i++; + fwrite(console->inputBuffer,i,1,input_pipe); + fflush(input_pipe); + /* fwrite(console->inputBuffer,i,1,stderr); */ + if(console->inputCount>i) + memmove(console->inputBuffer,console->inputBuffer+i,console->inputCount-i); + console->inputCount-=i; + i=0; + } + } else { + fwrite(console->inputBuffer,console->inputCount,1,input_pipe); + fflush(input_pipe); + /* fwrite(console->inputBuffer,console->inputCount,1,stderr); */ + console->inputCount=0; + } + } + /* process output */ + fs1=fs; tv1=tv; + num_fds=select(max_fd+1,&fs1,NULL,NULL,&tv1); + if(num_fds>0) { + /* + if(FD_ISSET(0,&fs1)) { + ch=getchar(); + fputc(ch,f); + } + */ + if(FD_ISSET(out[0],&fs1)) { + c=read(out[0],buffer,1024); + for(i=0;i +#include +#include "VNConsole.h" + +#define DEBUG(x) + +unsigned char colourMap16[16*3]={ + /* 0 black #000000 */ 0x00,0x00,0x00, + /* 1 maroon #800000 */ 0x80,0x00,0x00, + /* 2 green #008000 */ 0x00,0x80,0x00, + /* 3 khaki #808000 */ 0x80,0x80,0x00, + /* 4 navy #000080 */ 0x00,0x00,0x80, + /* 5 purple #800080 */ 0x80,0x00,0x80, + /* 6 aqua-green #008080 */ 0x00,0x80,0x80, + /* 7 light grey #c0c0c0 */ 0xc0,0xc0,0xc0, + /* 8 dark grey #808080 */ 0x80,0x80,0x80, + /* 9 red #ff0000 */ 0xff,0x00,0x00, + /* a light green #00ff00 */ 0x00,0xff,0x00, + /* b yellow #ffff00 */ 0xff,0xff,0x00, + /* c blue #0000ff */ 0x00,0x00,0xff, + /* d pink #ff00ff */ 0xff,0x00,0xff, + /* e light blue #00ffff */ 0x00,0xff,0xff, + /* f white #ffffff */ 0xff,0xff,0xff +}; + +void MakeColourMap16(vncConsolePtr c) +{ + rfbColourMap* colourMap=&(c->screen->colourMap); + if(colourMap->count) + free(colourMap->data.bytes); + colourMap->data.bytes=malloc(16*3); + memcpy(colourMap->data.bytes,colourMap16,16*3); + colourMap->count=16; + colourMap->is16=FALSE; + c->screen->serverFormat.trueColour=FALSE; +} + +void vcDrawOrHideCursor(vncConsolePtr c) +{ + int i,j,w=c->screen->paddedWidthInBytes; + char *b=c->screen->frameBuffer+c->y*c->cHeight*w+c->x*c->cWidth; + for(j=c->cy1;jcy2;j++) + for(i=c->cx1;icx2;i++) + b[j*w+i]^=0x0f; + rfbMarkRectAsModified(c->screen, + c->x*c->cWidth+c->cx1,c->y*c->cHeight+c->cy1, + c->x*c->cWidth+c->cx2,c->y*c->cHeight+c->cy2); + c->cursorIsDrawn=c->cursorIsDrawn?FALSE:TRUE; +} + +void vcDrawCursor(vncConsolePtr c) +{ + if(c->cursorActive && c->yheight && c->xwidth) { + /* rfbLog("DrawCursor: %d,%d\n",c->x,c->y); */ + vcDrawOrHideCursor(c); + } +} + +void vcHideCursor(vncConsolePtr c) +{ + if(c->currentlyMarking) + vcUnmark(c); + vcDrawOrHideCursor(c); +} + +void vcMakeSureCursorIsDrawn(rfbClientPtr cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + if(!c->dontDrawCursor) + vcDrawCursor(c); +} + +vncConsolePtr vcGetConsole(int *argc,char **argv, + int width,int height,rfbFontDataPtr font +#ifdef USE_ATTRIBUTE_BUFFER + ,rfbBool withAttributes +#endif + ) +{ + vncConsolePtr c=(vncConsolePtr)malloc(sizeof(vncConsole)); + + c->font=font; + c->width=width; + c->height=height; + c->screenBuffer=(char*)malloc(width*height); + memset(c->screenBuffer,' ',width*height); +#ifdef USE_ATTRIBUTE_BUFFER + if(withAttributes) { + c->attributeBuffer=(char*)malloc(width*height); + memset(c->attributeBuffer,0x07,width*height); + } else + c->attributeBuffer=NULL; +#endif + c->x=0; + c->y=0; + c->wrapBottomToTop=FALSE; + c->cursorActive=TRUE; + c->cursorIsDrawn=FALSE; + c->dontDrawCursor=FALSE; + c->inputBuffer=(char*)malloc(1024); + c->inputSize=1024; + c->inputCount=0; + c->selection=0; + c->selectTimeOut=40000; /* 40 ms */ + c->doEcho=TRUE; + + c->wasRightButtonDown=FALSE; + c->currentlyMarking=FALSE; + + rfbWholeFontBBox(font,&c->xhot,&c->cHeight,&c->cWidth,&c->yhot); + c->cWidth-=c->xhot; + c->cHeight=-c->cHeight-c->yhot; + + /* text cursor */ + c->cx1=c->cWidth/8; + c->cx2=c->cWidth*7/8; + c->cy2=c->cHeight-1-c->yhot+c->cHeight/16; + if(c->cy2>=c->cHeight) + c->cy2=c->cHeight-1; + c->cy1=c->cy2-c->cHeight/8; + if(c->cy1<0) + c->cy2=0; + + if(!(c->screen = rfbGetScreen(argc,argv,c->cWidth*c->width,c->cHeight*c->height,8,1,1))) + return NULL; + c->screen->screenData=(void*)c; + c->screen->displayHook=vcMakeSureCursorIsDrawn; + c->screen->frameBuffer= + (char*)malloc(c->screen->width*c->screen->height); + memset(c->screen->frameBuffer,c->backColour, + c->screen->width*c->screen->height); + c->screen->kbdAddEvent=vcKbdAddEventProc; + c->screen->ptrAddEvent=vcPtrAddEventProc; + c->screen->setXCutText=vcSetXCutTextProc; + + MakeColourMap16(c); + c->foreColour=0x7; + c->backColour=0; + + rfbInitServer(c->screen); + + return(c); +} + +#include + +/* before using this function, hide the cursor */ +void vcScroll(vncConsolePtr c,int lineCount) +{ + int y1,y2; + rfbScreenInfoPtr s=c->screen; + + if(lineCount==0) + return; + + /* rfbLog("begin scroll\n"); */ + vcHideCursor(c); + c->dontDrawCursor=TRUE; + + if(lineCount>=c->height || lineCount<=-c->height) { + y1=0; y2=s->height; + } else if(lineCount>0) { + y1=s->height-lineCount*c->cHeight; y2=s->height; + rfbDoCopyRect(s,0,0,s->width,y1,0,-lineCount*c->cHeight); + memmove(c->screenBuffer, + c->screenBuffer+(c->height-lineCount)*c->width, + (c->height-lineCount)*c->width); +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + memmove(c->attributeBuffer, + c->attributeBuffer+(c->height-lineCount)*c->width, + (c->height-lineCount)*c->width); +#endif + } else { + y1=0; y2=-lineCount*c->cHeight; + rfbDoCopyRect(s,0,y2,s->width,s->height,0,-lineCount*c->cHeight); + memmove(c->screenBuffer-lineCount*c->width, + c->screenBuffer, + (c->height+lineCount)*c->width); +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + memmove(c->attributeBuffer-lineCount*c->width, + c->attributeBuffer, + (c->height+lineCount)*c->width); +#endif + } + + c->dontDrawCursor=FALSE; + memset(s->frameBuffer+y1*s->width,c->backColour,(y2-y1)*s->width); + rfbMarkRectAsModified(s,0,y1-c->cHeight,s->width,y2); + memset(c->screenBuffer+y1/c->cHeight*c->width,' ', + (y2-y1)/c->cHeight*c->width); +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + memset(c->attributeBuffer+y1/c->cHeight*c->width,0x07, + (y2-y1)/c->cHeight*c->width); +#endif + /* rfbLog("end scroll\n"); */ +} + +void vcCheckCoordinates(vncConsolePtr c) +{ + if(c->x>=c->width) { + c->x=0; + c->y++; + } + if(c->y>=c->height) { + if(c->wrapBottomToTop) + c->y=0; + else { + vcScroll(c,c->y+1-c->height); + c->y=c->height-1; + } + } +} + +void vcPutChar(vncConsolePtr c,unsigned char ch) +{ +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) { + unsigned char colour=c->attributeBuffer[c->x+c->y*c->width]; + vcPutCharColour(c,ch,colour&0x7,colour>>4); + } else +#endif + vcPutCharColour(c,ch,c->foreColour,c->backColour); +} + +void vcPutCharColour(vncConsolePtr c,unsigned char ch,unsigned char foreColour,unsigned char backColour) +{ + rfbScreenInfoPtr s=c->screen; + int j,x,y; + + vcHideCursor(c); + if(ch<' ') { + switch(ch) { + case 7: + case 13: + break; + case 8: /* BackSpace */ + if(c->x>0) { + c->x--; + vcPutChar(c,' '); + c->x--; + } + break; + case 10: /* return */ + c->x=0; + c->y++; + vcCheckCoordinates(c); + break; + case 9: /* tabulator */ + do { + vcPutChar(c,' '); + } while(c->x%8); + break; + default: + rfbLog("putchar of unknown character: %c(%d).\n",ch,ch); + vcPutChar(c,' '); + } + } else { +#ifdef USE_ATTRIBUTE_BUFFER + if(c->attributeBuffer) + c->attributeBuffer[c->x+c->y*c->width]=foreColour|(backColour<<4); +#endif + x=c->x*c->cWidth; + y=c->y*c->cHeight; + for(j=y+c->cHeight-1;j>=y;j--) + memset(s->frameBuffer+j*s->width+x,backColour,c->cWidth); + rfbDrawChar(s,c->font, + x-c->xhot+(c->cWidth-rfbWidthOfChar(c->font,ch))/2, + y+c->cHeight-c->yhot-1, + ch,foreColour); + c->screenBuffer[c->y*c->width+c->x]=ch; + c->x++; + rfbMarkRectAsModified(s,x,y-c->cHeight+1,x+c->cWidth,y+c->cHeight+1); + vcCheckCoordinates(c); + } +} + +void vcPrint(vncConsolePtr c,unsigned char* str) +{ + while(*str) { + vcPutChar(c,*str); + str++; + } +} + +void vcPrintColour(vncConsolePtr c,unsigned char* str,unsigned char foreColour,unsigned char backColour) +{ + while(*str) { + vcPutCharColour(c,*str,foreColour,backColour); + str++; + } +} + +void vcPrintF(vncConsolePtr c,char* format,...) +{ + va_list args; + char buf[4096]; + va_start(args, format); + vsprintf(buf, format, args); + vcPrint(c,(unsigned char*)buf); + va_end(args); +} + +void vcPrintFColour(vncConsolePtr c,unsigned char foreColour,unsigned char backColour,char* format,...) +{ + va_list args; + char buf[4096]; + va_start(args, format); + vsprintf(buf, format, args); + vcPrintColour(c,(unsigned char*)buf,foreColour,backColour); + va_end(args); +} + +char vcGetCh(vncConsolePtr c) +{ + if(c->inputCount>0) { + char ch; + ch=c->inputBuffer[0]; + c->inputCount--; + if(c->inputCount>0) + memmove(c->inputBuffer,c->inputBuffer+1,c->inputCount); + return(ch); + } else + return(0); +} + +char vcGetChar(vncConsolePtr c) +{ + while(rfbIsActive(c->screen) && c->inputCount==0) + vcProcessEvents(c); + return(vcGetCh(c)); +} + +char *vcGetString(vncConsolePtr c,char *buffer,int bufferSize) +{ + char *bufferBackup=c->inputBuffer; + int i,count=bufferSize-1; + + if(count>c->inputCount) + count=c->inputCount; + for(i=1;iinputCount-=i; + memmove(bufferBackup,bufferBackup+i+2,c->inputCount); + return(buffer); + } + memcpy(buffer,bufferBackup,c->inputCount); + count=c->inputSize; + c->inputSize=bufferSize; + c->inputBuffer=buffer; + while(rfbIsActive(c->screen) + && c->inputCountinputCount-1]!='\n') + vcProcessEvents(c); + buffer[c->inputCount]=0; + c->inputBuffer=bufferBackup; + c->inputSize=count; + c->inputCount=0; + return(buffer); +} + +void vcKbdAddEventProc(rfbBool down,rfbKeySym keySym,rfbClientPtr cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + if(down) { + if(c->inputCountinputSize) { + if(keySym<0 || keySym>0xff) { + if(keySym==XK_Return) keySym='\n'; + else if(keySym==XK_BackSpace) keySym=8; + else if(keySym==XK_Tab) keySym=9; + else keySym=0; + } + if(keySym>0) { + if(keySym==8) { + if(c->inputCount>0) + c->inputCount--; + } else + c->inputBuffer[c->inputCount++]=(char)keySym; + if(c->doEcho) + vcPutChar(c,(unsigned char)keySym); + } + } + } +} + +void vcPtrAddEventProc(int buttonMask,int x,int y,rfbClientPtr cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + + if(c->wasRightButtonDown) { + if((buttonMask&4)==0) { + if(c->selection) { + char* s; + for(s=c->selection;*s;s++) { + c->screen->kbdAddEvent(1,*s,cl); + c->screen->kbdAddEvent(0,*s,cl); + } + } + c->wasRightButtonDown=0; + } + } else if(buttonMask&4) + c->wasRightButtonDown=1; + + if(buttonMask&1) { + int cx=x/c->cWidth,cy=y/c->cHeight,pos; + if(cx<0) cx=0; else if(cx>=c->width) cx=c->width-1; + if(cy<0) cy=0; else if(cy>=c->height) cy=c->height-1; + pos=cy*c->width+cx; + + /* mark */ + if(!c->currentlyMarking) { + c->currentlyMarking=TRUE; + c->markStart=pos; + c->markEnd=pos; + vcToggleMarkCell(c,pos); + } else { + DEBUG(rfbLog("markStart: %d, markEnd: %d, pos: %d\n", + c->markStart,c->markEnd,pos)); + if(c->markEnd!=pos) { + if(c->markEndmarkEnd; cy=pos; + } else { + cx=pos; cy=c->markEnd; + } + if(cxmarkStart) { + if(cymarkStart) + cy--; + } else + cx++; + while(cx<=cy) { + vcToggleMarkCell(c,cx); + cx++; + } + c->markEnd=pos; + } + } + } else if(c->currentlyMarking) { + int i,j; + if(c->markStartmarkEnd) { + i=c->markStart; j=c->markEnd+1; + } else { + i=c->markEnd; j=c->markStart; + } + if(c->selection) free(c->selection); + c->selection=(char*)malloc(j-i+1); + memcpy(c->selection,c->screenBuffer+i,j-i); + c->selection[j-i]=0; + vcUnmark(c); + rfbGotXCutText(c->screen,c->selection,j-i); + } + rfbDefaultPtrAddEvent(buttonMask,x,y,cl); +} + +void vcSetXCutTextProc(char* str,int len, struct _rfbClientRec* cl) +{ + vncConsolePtr c=(vncConsolePtr)cl->screen->screenData; + + if(c->selection) free(c->selection); + c->selection=(char*)malloc(len+1); + memcpy(c->selection,str,len); + c->selection[len]=0; +} + +void vcToggleMarkCell(vncConsolePtr c,int pos) +{ + int x=(pos%c->width)*c->cWidth, + y=(pos/c->width)*c->cHeight; + int i,j; + rfbScreenInfoPtr s=c->screen; + char *b=s->frameBuffer+y*s->width+x; + for(j=0;jcHeight;j++) + for(i=0;icWidth;i++) + b[j*s->width+i]^=0x0f; + rfbMarkRectAsModified(c->screen,x,y,x+c->cWidth,y+c->cHeight); +} + +void vcUnmark(vncConsolePtr c) +{ + int i,j; + c->currentlyMarking=FALSE; + if(c->markStartmarkEnd) { + i=c->markStart; j=c->markEnd+1; + } else { + i=c->markEnd; j=c->markStart; + } + for(;iscreen,c->selectTimeOut); +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h new file mode 100755 index 0000000..ae6822d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/VNConsole.h @@ -0,0 +1,95 @@ +#include + +/* this is now the default */ +#define USE_ATTRIBUTE_BUFFER + +typedef struct vncConsole { + /* width and height in cells (=characters) */ + int width, height; + + /* current position */ + int x,y; + + /* characters */ + char *screenBuffer; + +#ifdef USE_ATTRIBUTE_BUFFER + /* attributes: colours. If NULL, default to gray on black, else + for each cell an unsigned char holds foreColour|(backColour<<4) */ + char *attributeBuffer; +#endif + + /* if this is set, the screen doesn't scroll. */ + rfbBool wrapBottomToTop; + + /* height and width of one character */ + int cWidth, cHeight; + /* offset of characters */ + int xhot,yhot; + + /* colour */ + unsigned char foreColour,backColour; + int8_t cx1,cy1,cx2,cy2; + + /* input buffer */ + char *inputBuffer; + int inputCount; + int inputSize; + long selectTimeOut; + rfbBool doEcho; /* if reading input, do output directly? */ + + /* selection */ + char *selection; + + /* mouse */ + rfbBool wasRightButtonDown; + rfbBool currentlyMarking; + int markStart,markEnd; + + /* should text cursor be drawn? (an underscore at current position) */ + rfbBool cursorActive; + rfbBool cursorIsDrawn; + rfbBool dontDrawCursor; /* for example, while scrolling */ + + rfbFontDataPtr font; + rfbScreenInfoPtr screen; +} vncConsole, *vncConsolePtr; + +#ifdef USE_ATTRIBUTE_BUFFER +vncConsolePtr vcGetConsole(int *argc,char **argv, + int width,int height,rfbFontDataPtr font, + rfbBool withAttributes); +#else +vncConsolePtr vcGetConsole(int argc,char **argv, + int width,int height,rfbFontDataPtr font); +#endif +void vcDrawCursor(vncConsolePtr c); +void vcHideCursor(vncConsolePtr c); +void vcCheckCoordinates(vncConsolePtr c); + +void vcPutChar(vncConsolePtr c,unsigned char ch); +void vcPrint(vncConsolePtr c,unsigned char* str); +void vcPrintF(vncConsolePtr c,char* format,...); + +void vcPutCharColour(vncConsolePtr c,unsigned char ch, + unsigned char foreColour,unsigned char backColour); +void vcPrintColour(vncConsolePtr c,unsigned char* str, + unsigned char foreColour,unsigned char backColour); +void vcPrintFColour(vncConsolePtr c,unsigned char foreColour, + unsigned char backColour,char* format,...); + +char vcGetCh(vncConsolePtr c); +char vcGetChar(vncConsolePtr c); /* blocking */ +char *vcGetString(vncConsolePtr c,char *buffer,int maxLen); + +void vcKbdAddEventProc(rfbBool down,rfbKeySym keySym,rfbClientPtr cl); +void vcPtrAddEventProc(int buttonMask,int x,int y,rfbClientPtr cl); +void vcSetXCutTextProc(char* str,int len, struct _rfbClientRec* cl); + +void vcToggleMarkCell(vncConsolePtr c,int pos); +void vcUnmark(vncConsolePtr c); + +void vcProcessEvents(vncConsolePtr c); + +/* before using this function, hide the cursor */ +void vcScroll(vncConsolePtr c,int lineCount); diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c new file mode 100755 index 0000000..54de666 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/example.c @@ -0,0 +1,31 @@ +#include "VNConsole.h" +#include "vga.h" + +int main(int argc,char **argv) +{ + vncConsolePtr c=vcGetConsole(&argc,argv,80,25,&vgaFont,FALSE); + char buffer[1024]; + int i,j,l; + for(j=32;j<256;j+=16) { + vcPrintF(c,"%02x: ",j); + for(i=j;i ",i); + vcGetString(c,buffer,1024); + l=strlen(buffer)-1; + while(l>=0 && buffer[l]=='\n') + buffer[l]=0; + if(!strcmp(buffer,"quit")) + return(0); + if(!strcmp(buffer,"s")) + vcScroll(c,2); + if(!strcmp(buffer,"S")) + vcScroll(c,-2); + i++; + } + return(0); +} diff --git a/droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h new file mode 100755 index 0000000..21e03eb --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/vncterm/vga.h @@ -0,0 +1,261 @@ +unsigned char vgaFontData[2399]={ +0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c, /* 0 */ +0x7e,0x81,0xa5,0x81,0x81,0xa5,0x99,0x81,0x81,0x7e, /* 1 */ +0x7e,0xff,0xdb,0xff,0xff,0xdb,0xe7,0xff,0xff,0x7e, /* 2 */ +0x6c,0xfe,0xfe,0xfe,0xfe,0x7c,0x38,0x10, /* 3 */ +0x10,0x38,0x7c,0xfe,0x7c,0x38,0x10, /* 4 */ +0x18,0x3c,0x3c,0xe7,0xe7,0xe7,0x18,0x18,0x3c, /* 5 */ +0x18,0x3c,0x7e,0xff,0xff,0x7e,0x18,0x18,0x3c, /* 6 */ +0x60,0xf0,0xf0,0x60, /* 7 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0xff,0xff,0xff,0xff, /* 8 */ +0x78,0xcc,0x84,0x84,0xcc,0x78, /* 9 */ +0xff,0xff,0xff,0xff,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xff,0xff,0xff,0xff, /* 10 */ +0x1e,0x06,0x0e,0x1a,0x78,0xcc,0xcc,0xcc,0xcc,0x78, /* 11 */ +0x78,0xcc,0xcc,0xcc,0xcc,0x78,0x30,0xfc,0x30,0x30, /* 12 */ +0x3f,0x33,0x3f,0x30,0x30,0x30,0x30,0x70,0xf0,0xe0, /* 13 */ +0x7f,0x63,0x7f,0x63,0x63,0x63,0x63,0x67,0xe7,0xe6,0xc0, /* 14 */ +0x18,0x18,0xdb,0x3c,0xe7,0x3c,0xdb,0x18,0x18, /* 15 */ +0x80,0xc0,0xe0,0xf0,0xf8,0xfe,0xf8,0xf0,0xe0,0xc0,0x80, /* 16 */ +0x02,0x06,0x0e,0x1e,0x3e,0xfe,0x3e,0x1e,0x0e,0x06,0x02, /* 17 */ +0x30,0x78,0xfc,0x30,0x30,0x30,0xfc,0x78,0x30, /* 18 */ +0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x00,0xcc,0xcc, /* 19 */ +0x7f,0xdb,0xdb,0xdb,0x7b,0x1b,0x1b,0x1b,0x1b,0x1b, /* 20 */ +0x7c,0xc6,0x60,0x38,0x6c,0xc6,0xc6,0x6c,0x38,0x0c,0xc6,0x7c, /* 21 */ +0xfe,0xfe,0xfe,0xfe, /* 22 */ +0x30,0x78,0xfc,0x30,0x30,0x30,0xfc,0x78,0x30,0xfc, /* 23 */ +0x30,0x78,0xfc,0x30,0x30,0x30,0x30,0x30,0x30,0x30, /* 24 */ +0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xfc,0x78,0x30, /* 25 */ +0x18,0x0c,0xfe,0x0c,0x18, /* 26 */ +0x30,0x60,0xfe,0x60,0x30, /* 27 */ +0xc0,0xc0,0xc0,0xfe, /* 28 */ +0x28,0x6c,0xfe,0x6c,0x28, /* 29 */ +0x10,0x38,0x38,0x7c,0x7c,0xfe,0xfe, /* 30 */ +0xfe,0xfe,0x7c,0x7c,0x38,0x38,0x10, /* 31 */ + /* 32 */ +0x60,0xf0,0xf0,0xf0,0x60,0x60,0x60,0x00,0x60,0x60, /* 33 */ +0xcc,0xcc,0xcc,0x48, /* 34 */ +0x6c,0x6c,0xfe,0x6c,0x6c,0x6c,0xfe,0x6c,0x6c, /* 35 */ +0x18,0x18,0x7c,0xc6,0xc2,0xc0,0x7c,0x06,0x06,0x86,0xc6,0x7c,0x18,0x18, /* 36 */ +0xc2,0xc6,0x0c,0x18,0x30,0x60,0xc6,0x86, /* 37 */ +0x38,0x6c,0x6c,0x38,0x76,0xdc,0xcc,0xcc,0xcc,0x76, /* 38 */ +0x60,0x60,0x60,0xc0, /* 39 */ +0x30,0x60,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x60,0x30, /* 40 */ +0xc0,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0xc0, /* 41 */ +0x66,0x3c,0xff,0x3c,0x66, /* 42 */ +0x30,0x30,0xfc,0x30,0x30, /* 43 */ +0x60,0x60,0x60,0xc0, /* 44 */ +0xfe, /* 45 */ +0xc0,0xc0, /* 46 */ +0x02,0x06,0x0c,0x18,0x30,0x60,0xc0,0x80, /* 47 */ +0x38,0x6c,0xc6,0xc6,0xd6,0xd6,0xc6,0xc6,0x6c,0x38, /* 48 */ +0x30,0x70,0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0xfc, /* 49 */ +0x7c,0xc6,0x06,0x0c,0x18,0x30,0x60,0xc0,0xc6,0xfe, /* 50 */ +0x7c,0xc6,0x06,0x06,0x3c,0x06,0x06,0x06,0xc6,0x7c, /* 51 */ +0x0c,0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x0c,0x0c,0x1e, /* 52 */ +0xfe,0xc0,0xc0,0xc0,0xfc,0x06,0x06,0x06,0xc6,0x7c, /* 53 */ +0x38,0x60,0xc0,0xc0,0xfc,0xc6,0xc6,0xc6,0xc6,0x7c, /* 54 */ +0xfe,0xc6,0x06,0x06,0x0c,0x18,0x30,0x30,0x30,0x30, /* 55 */ +0x7c,0xc6,0xc6,0xc6,0x7c,0xc6,0xc6,0xc6,0xc6,0x7c, /* 56 */ +0x7c,0xc6,0xc6,0xc6,0x7e,0x06,0x06,0x06,0x0c,0x78, /* 57 */ +0xc0,0xc0,0x00,0x00,0x00,0xc0,0xc0, /* 58 */ +0x60,0x60,0x00,0x00,0x00,0x60,0x60,0xc0, /* 59 */ +0x0c,0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x0c, /* 60 */ +0xfc,0x00,0x00,0xfc, /* 61 */ +0xc0,0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0xc0, /* 62 */ +0x7c,0xc6,0xc6,0x0c,0x18,0x18,0x18,0x00,0x18,0x18, /* 63 */ +0x7c,0xc6,0xc6,0xde,0xde,0xde,0xdc,0xc0,0x7c, /* 64 */ +0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6, /* 65 */ +0xfc,0x66,0x66,0x66,0x7c,0x66,0x66,0x66,0x66,0xfc, /* 66 */ +0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc0,0xc2,0x66,0x3c, /* 67 */ +0xf8,0x6c,0x66,0x66,0x66,0x66,0x66,0x66,0x6c,0xf8, /* 68 */ +0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xfe, /* 69 */ +0xfe,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xf0, /* 70 */ +0x3c,0x66,0xc2,0xc0,0xc0,0xde,0xc6,0xc6,0x66,0x3a, /* 71 */ +0xc6,0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0xc6,0xc6, /* 72 */ +0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xf0, /* 73 */ +0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0xcc,0x78, /* 74 */ +0xe6,0x66,0x66,0x6c,0x78,0x78,0x6c,0x66,0x66,0xe6, /* 75 */ +0xf0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xfe, /* 76 */ +0xc6,0xee,0xfe,0xfe,0xd6,0xc6,0xc6,0xc6,0xc6,0xc6, /* 77 */ +0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6,0xc6, /* 78 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 79 */ +0xfc,0x66,0x66,0x66,0x7c,0x60,0x60,0x60,0x60,0xf0, /* 80 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x0c,0x0e, /* 81 */ +0xfc,0x66,0x66,0x66,0x7c,0x6c,0x66,0x66,0x66,0xe6, /* 82 */ +0x7c,0xc6,0xc6,0x60,0x38,0x0c,0x06,0xc6,0xc6,0x7c, /* 83 */ +0xfc,0xfc,0xb4,0x30,0x30,0x30,0x30,0x30,0x30,0x78, /* 84 */ +0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 85 */ +0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x10, /* 86 */ +0xc6,0xc6,0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0xee,0x6c, /* 87 */ +0xc6,0xc6,0x6c,0x7c,0x38,0x38,0x7c,0x6c,0xc6,0xc6, /* 88 */ +0xcc,0xcc,0xcc,0xcc,0x78,0x30,0x30,0x30,0x30,0x78, /* 89 */ +0xfe,0xc6,0x86,0x0c,0x18,0x30,0x60,0xc2,0xc6,0xfe, /* 90 */ +0xf0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf0, /* 91 */ +0x80,0xc0,0xe0,0x70,0x38,0x1c,0x0e,0x06,0x02, /* 92 */ +0xf0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xf0, /* 93 */ +0x10,0x38,0x6c,0xc6, /* 94 */ +0xff, /* 95 */ +0xc0,0xc0,0x60, /* 96 */ +0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 97 */ +0xe0,0x60,0x60,0x78,0x6c,0x66,0x66,0x66,0x66,0x7c, /* 98 */ +0x7c,0xc6,0xc0,0xc0,0xc0,0xc6,0x7c, /* 99 */ +0x1c,0x0c,0x0c,0x3c,0x6c,0xcc,0xcc,0xcc,0xcc,0x76, /* 100 */ +0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 101 */ +0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xf0, /* 102 */ +0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0xcc,0x78, /* 103 */ +0xe0,0x60,0x60,0x6c,0x76,0x66,0x66,0x66,0x66,0xe6, /* 104 */ +0x60,0x60,0x00,0xe0,0x60,0x60,0x60,0x60,0x60,0xf0, /* 105 */ +0x0c,0x0c,0x00,0x1c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0xcc,0xcc,0x78, /* 106 */ +0xe0,0x60,0x60,0x66,0x6c,0x78,0x78,0x6c,0x66,0xe6, /* 107 */ +0xe0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0xf0, /* 108 */ +0xec,0xfe,0xd6,0xd6,0xd6,0xd6,0xc6, /* 109 */ +0xdc,0x66,0x66,0x66,0x66,0x66,0x66, /* 110 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 111 */ +0xdc,0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xf0, /* 112 */ +0x76,0xcc,0xcc,0xcc,0xcc,0xcc,0x7c,0x0c,0x0c,0x1e, /* 113 */ +0xdc,0x76,0x66,0x60,0x60,0x60,0xf0, /* 114 */ +0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c, /* 115 */ +0x10,0x30,0x30,0xfc,0x30,0x30,0x30,0x30,0x36,0x1c, /* 116 */ +0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 117 */ +0xcc,0xcc,0xcc,0xcc,0xcc,0x78,0x30, /* 118 */ +0xc6,0xc6,0xd6,0xd6,0xd6,0xfe,0x6c, /* 119 */ +0xc6,0x6c,0x38,0x38,0x38,0x6c,0xc6, /* 120 */ +0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0xf8, /* 121 */ +0xfe,0xcc,0x18,0x30,0x60,0xc6,0xfe, /* 122 */ +0x1c,0x30,0x30,0x30,0xe0,0x30,0x30,0x30,0x30,0x1c, /* 123 */ +0xc0,0xc0,0xc0,0xc0,0x00,0xc0,0xc0,0xc0,0xc0,0xc0, /* 124 */ +0xe0,0x30,0x30,0x30,0x1c,0x30,0x30,0x30,0x30,0xe0, /* 125 */ +0x76,0xdc, /* 126 */ +0x10,0x38,0x6c,0xc6,0xc6,0xc6,0xfe, /* 127 */ +0x3c,0x66,0xc2,0xc0,0xc0,0xc0,0xc2,0x66,0x3c,0x0c,0x06,0x7c, /* 128 */ +0xcc,0x00,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 129 */ +0x0c,0x18,0x30,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 130 */ +0x10,0x38,0x6c,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 131 */ +0xcc,0x00,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 132 */ +0x60,0x30,0x18,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 133 */ +0x38,0x6c,0x38,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 134 */ +0x78,0xcc,0xc0,0xc0,0xcc,0x78,0x18,0x0c,0x78, /* 135 */ +0x10,0x38,0x6c,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 136 */ +0xc6,0x00,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 137 */ +0x60,0x30,0x18,0x00,0x7c,0xc6,0xfe,0xc0,0xc0,0xc6,0x7c, /* 138 */ +0xcc,0x00,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78, /* 139 */ +0x30,0x78,0xcc,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78, /* 140 */ +0xc0,0x60,0x30,0x00,0x70,0x30,0x30,0x30,0x30,0x30,0x78, /* 141 */ +0xc6,0x00,0x10,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6, /* 142 */ +0x38,0x6c,0x38,0x00,0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6, /* 143 */ +0x18,0x30,0x60,0x00,0xfe,0x66,0x60,0x7c,0x60,0x60,0x66,0xfe, /* 144 */ +0xcc,0x76,0x36,0x7e,0xd8,0xd8,0x6e, /* 145 */ +0x3e,0x6c,0xcc,0xcc,0xfe,0xcc,0xcc,0xcc,0xcc,0xce, /* 146 */ +0x10,0x38,0x6c,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 147 */ +0xc6,0x00,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 148 */ +0x60,0x30,0x18,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 149 */ +0x30,0x78,0xcc,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 150 */ +0x60,0x30,0x18,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 151 */ +0xc6,0x00,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7e,0x06,0x0c,0x78, /* 152 */ +0xc6,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 153 */ +0xc6,0x00,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 154 */ +0x30,0x30,0x78,0xcc,0xc0,0xc0,0xc0,0xcc,0x78,0x30,0x30, /* 155 */ +0x38,0x6c,0x64,0x60,0xf0,0x60,0x60,0x60,0x60,0xe6,0xfc, /* 156 */ +0xcc,0xcc,0x78,0x30,0xfc,0x30,0xfc,0x30,0x30,0x30, /* 157 */ +0xf8,0xcc,0xcc,0xf8,0xc4,0xcc,0xde,0xcc,0xcc,0xcc,0xc6, /* 158 */ +0x0e,0x1b,0x18,0x18,0x18,0x7e,0x18,0x18,0x18,0x18,0x18,0xd8,0x70, /* 159 */ +0x18,0x30,0x60,0x00,0x78,0x0c,0x7c,0xcc,0xcc,0xcc,0x76, /* 160 */ +0x30,0x60,0xc0,0x00,0xe0,0x60,0x60,0x60,0x60,0x60,0xf0, /* 161 */ +0x18,0x30,0x60,0x00,0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c, /* 162 */ +0x18,0x30,0x60,0x00,0xcc,0xcc,0xcc,0xcc,0xcc,0xcc,0x76, /* 163 */ +0x76,0xdc,0x00,0xdc,0x66,0x66,0x66,0x66,0x66,0x66, /* 164 */ +0x76,0xdc,0x00,0xc6,0xe6,0xf6,0xfe,0xde,0xce,0xc6,0xc6,0xc6, /* 165 */ +0x78,0xd8,0xd8,0x7c,0x00,0xfc, /* 166 */ +0x70,0xd8,0xd8,0x70,0x00,0xf8, /* 167 */ +0x30,0x30,0x00,0x30,0x30,0x60,0xc0,0xc6,0xc6,0x7c, /* 168 */ +0xfe,0xc0,0xc0,0xc0,0xc0, /* 169 */ +0xfe,0x06,0x06,0x06,0x06, /* 170 */ +0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x60,0xdc,0x86,0x0c,0x18,0x3e, /* 171 */ +0xc0,0xc0,0xc2,0xc6,0xcc,0x18,0x30,0x66,0xce,0x9e,0x3e,0x06,0x06, /* 172 */ +0x60,0x60,0x00,0x60,0x60,0x60,0xf0,0xf0,0xf0,0x60, /* 173 */ +0x36,0x6c,0xd8,0x6c,0x36, /* 174 */ +0xd8,0x6c,0x36,0x6c,0xd8, /* 175 */ +0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88, /* 176 */ +0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa, /* 177 */ +0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77,0xdd,0x77, /* 178 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 179 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 180 */ +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 181 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 182 */ +0xfe,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 183 */ +0xf8,0x18,0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 184 */ +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 185 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 186 */ +0xfe,0x06,0xf6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 187 */ +0x36,0x36,0x36,0x36,0x36,0xf6,0x06,0xfe, /* 188 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xfe, /* 189 */ +0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8, /* 190 */ +0xf8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 191 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf8, /* 192 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff, /* 193 */ +0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 194 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 195 */ +0xff, /* 196 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 197 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xc0,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 198 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xdc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 199 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xdc,0xc0,0xfc, /* 200 */ +0xfc,0xc0,0xdc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 201 */ +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xff, /* 202 */ +0xff,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 203 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xdc,0xc0,0xdc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 204 */ +0xff,0x00,0xff, /* 205 */ +0x36,0x36,0x36,0x36,0x36,0xf7,0x00,0xf7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 206 */ +0x18,0x18,0x18,0x18,0x18,0xff,0x00,0xff, /* 207 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff, /* 208 */ +0xff,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 209 */ +0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 210 */ +0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xfc, /* 211 */ +0xc0,0xc0,0xc0,0xc0,0xc0,0xf8,0xc0,0xf8, /* 212 */ +0xf8,0xc0,0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 213 */ +0xfc,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8,0xd8, /* 214 */ +0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xff,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36, /* 215 */ +0x18,0x18,0x18,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, /* 216 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8, /* 217 */ +0xf8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 218 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 219 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 220 */ +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, /* 221 */ +0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0, /* 222 */ +0xff,0xff,0xff,0xff,0xff,0xff,0xff, /* 223 */ +0x76,0xdc,0xd8,0xd8,0xd8,0xdc,0x76, /* 224 */ +0x78,0xcc,0xcc,0xcc,0xd8,0xcc,0xc6,0xc6,0xc6,0xcc, /* 225 */ +0xfe,0xc6,0xc6,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 226 */ +0xfe,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c, /* 227 */ +0xfe,0xc6,0x60,0x30,0x18,0x30,0x60,0xc6,0xfe, /* 228 */ +0x7e,0xd8,0xd8,0xd8,0xd8,0xd8,0x70, /* 229 */ +0x66,0x66,0x66,0x66,0x66,0x7c,0x60,0x60,0xc0, /* 230 */ +0x76,0xdc,0x18,0x18,0x18,0x18,0x18,0x18, /* 231 */ +0xfc,0x30,0x78,0xcc,0xcc,0xcc,0x78,0x30,0xfc, /* 232 */ +0x38,0x6c,0xc6,0xc6,0xfe,0xc6,0xc6,0x6c,0x38, /* 233 */ +0x38,0x6c,0xc6,0xc6,0xc6,0x6c,0x6c,0x6c,0x6c,0xee, /* 234 */ +0x3c,0x60,0x30,0x18,0x7c,0xcc,0xcc,0xcc,0xcc,0x78, /* 235 */ +0x7e,0xdb,0xdb,0xdb,0x7e, /* 236 */ +0x03,0x06,0x7e,0xdb,0xdb,0xf3,0x7e,0x60,0xc0, /* 237 */ +0x38,0x60,0xc0,0xc0,0xf8,0xc0,0xc0,0xc0,0x60,0x38, /* 238 */ +0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0xc6, /* 239 */ +0xfe,0x00,0x00,0xfe,0x00,0x00,0xfe, /* 240 */ +0x18,0x18,0x7e,0x18,0x18,0x00,0x00,0xff, /* 241 */ +0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00,0xfc, /* 242 */ +0x18,0x30,0x60,0xc0,0x60,0x30,0x18,0x00,0xfc, /* 243 */ +0x70,0xd8,0xd8,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0, /* 244 */ +0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xd8,0xd8,0xd8,0x70, /* 245 */ +0x30,0x30,0x00,0xfc,0x00,0x30,0x30, /* 246 */ +0x76,0xdc,0x00,0x76,0xdc, /* 247 */ +0x70,0xd8,0xd8,0x70, /* 248 */ +0xc0,0xc0, /* 249 */ +0xc0, /* 250 */ +0x0f,0x0c,0x0c,0x0c,0x0c,0x0c,0xec,0x6c,0x6c,0x3c,0x1c, /* 251 */ +0xd8,0x6c,0x6c,0x6c,0x6c,0x6c, /* 252 */ +0x70,0xd8,0x30,0x60,0xc8,0xf8, /* 253 */ +0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8, /* 254 */ + /* 255 */ +}; +int vgaFontMetaData[256*5]={ +0,8,9,0,0,9,8,10,0,0,19,8,10,0,0,29,8,8,0,0,37,8,7,0,1,44,8,9,0,0,53,8,9,0,0,62,8,4,2,2,66,8,16,0,-4,82,8,6,1,1,88,8,16,0,-4,104,8,10,0,0,114,8,10,1,0,124,8,10,0,0,134,8,11,0,-1,145,8,9,0,0,154,8,11,0,0,165,8,11,0,0,176,8,9,1,1,185,8,10,1,0,195,8,10,0,0,205,8,12,0,-1,217,8,4,0,0,221,8,10,1,0,231,8,10,1,0,241,8,10,1,0,251,8,5,0,2,256,8,5,0,2,261,8,4,0,2,265,8,5,0,2,270,8,7,0,1,277,8,7,0,1,284,8,0,0,0,284,8,10,2,0,294,8,4,1,7,298,8,9,0,0,307,8,14,0,-2,321,8,8,0,0,329,8,10,0,0,339,8,4,1,7,343,8,10,2,0,353,8,10,2,0,363,8,5,0,2,368,8,5,1,2,373,8,4,2,-1,377,8,1,0,4,378,8,2,3,0,380,8,8,0,0,388,8,10,0,0,398,8,10,1,0,408,8,10,0,0,418,8,10,0,0,428,8,10,0,0,438,8,10,0,0,448,8,10,0,0,458,8,10,0,0,468,8,10,0,0,478,8,10,0,0,488,8,7,3,1,495,8,8,2,0,503,8,9,1,0,512,8,4,1,3,516,8,9,1,0,525,8,10,0,0,535,8,9,0,0,544,8,10,0,0,554,8,10,0,0,564,8,10,0,0,574,8,10,0,0,584,8,10,0,0,594,8,10,0,0,604,8,10,0,0,614,8,10,0,0,624,8,10,2,0,634,8,10,0,0,644,8,10,0,0,654,8,10,0,0,664,8,10,0,0,674,8,10,0,0,684,8,10,0,0,694,8,10,0,0,704,8,12,0,-2,716,8,10,0,0,726,8,10,0,0,736,8,10,1,0,746,8,10,0,0,756,8,10,0,0,766,8,10,0,0,776,8,10,0,0,786,8,10,1,0,796,8,10,0,0,806,8,10,2,0,816,8,9,0,0,825,8,10,2,0,835,8,4,0,8,839,8,1,0,-2,840,8,3,2,9,843,8,7,0,0,850,8,10,0,0,860,8,7,0,0,867,8,10,0,0,877,8,7,0,0,884,8,10,0,0,894,8,10,0,-3,904,8,10,0,0,914,8,10,2,0,924,8,13,1,-3,937,8,10,0,0,947,8,10,2,0,957,8,7,0,0,964,8,7,0,0,971,8,7,0,0,978,8,10,0,-3,988,8,10,0,-3,998,8,7,0,0,1005,8,7,0,0,1012,8,10,0,0,1022,8,7,0,0,1029,8,7,1,0,1036,8,7,0,0,1043,8,7,0,0,1050,8,10,0,-3,1060,8,7,0,0,1067,8,10,1,0,1077,8,10,3,0,1087,8,10,1,0,1097,8,2,0,8,1099,8,7,0,1,1106,8,12,0,-2,1118,8,10,0,0,1128,8,11,0,0,1139,8,11,0,0,1150,8,10,0,0,1160,8,11,0,0,1171,8,11,0,0,1182,8,9,1,-1,1191,8,11,0,0,1202,8,10,0,0,1212,8,11,0,0,1223,8,10,1,0,1233,8,11,1,0,1244,8,11,1,0,1255,8,11,0,0,1266,8,12,0,0,1278,8,12,0,0,1290,8,7,0,0,1297,8,10,0,0,1307,8,11,0,0,1318,8,10,0,0,1328,8,11,0,0,1339,8,11,0,0,1350,8,11,0,0,1361,8,13,0,-3,1374,8,11,0,0,1385,8,11,0,0,1396,8,11,1,0,1407,8,11,0,0,1418,8,10,1,0,1428,8,11,0,0,1439,8,13,0,-2,1452,8,11,0,0,1463,8,11,2,0,1474,8,11,0,0,1485,8,11,0,0,1496,8,10,0,0,1506,8,12,0,0,1518,8,6,1,5,1524,8,6,1,5,1530,8,10,0,0,1540,8,5,0,1,1545,8,5,0,1,1550,8,13,0,-2,1563,8,13,0,-2,1576,8,10,2,0,1586,8,5,0,2,1591,8,5,0,2,1596,8,16,1,-4,1612,8,16,0,-4,1628,8,16,0,-4,1644,8,16,3,-4,1660,8,16,0,-4,1676,8,16,0,-4,1692,8,16,0,-4,1708,8,9,0,-4,1717,8,11,0,-4,1728,8,16,0,-4,1744,8,16,2,-4,1760,8,11,0,-4,1771,8,8,0,4,1779,8,8,0,4,1787,8,8,0,4,1795,8,9,0,-4,1804,8,8,3,4,1812,8,8,0,4,1820,8,9,0,-4,1829,8,16,3,-4,1845,8,1,0,4,1846,8,16,0,-4,1862,8,16,3,-4,1878,8,16,2,-4,1894,8,8,2,4,1902,8,11,2,-4,1913,8,8,0,4,1921,8,11,0,-4,1932,8,16,2,-4,1948,8,3,0,4,1951,8,16,0,-4,1967,8,8,0,4,1975,8,8,0,4,1983,8,11,0,-4,1994,8,9,0,-4,2003,8,8,2,4,2011,8,8,3,4,2019,8,11,3,-4,2030,8,9,2,-4,2039,8,16,0,-4,2055,8,16,0,-4,2071,8,8,0,4,2079,8,9,3,-4,2088,8,16,0,-4,2104,8,9,0,-4,2113,8,16,0,-4,2129,8,16,4,-4,2145,8,7,0,5,2152,8,7,0,0,2159,8,10,0,0,2169,8,10,0,0,2179,8,8,0,0,2187,8,9,0,0,2196,8,7,0,0,2203,8,9,0,-1,2212,8,8,0,0,2220,8,9,1,0,2229,8,9,0,0,2238,8,10,0,0,2248,8,10,1,0,2258,8,5,0,2,2263,8,9,0,0,2272,8,10,1,0,2282,8,9,0,0,2291,8,7,0,1,2298,8,8,0,0,2306,8,9,1,0,2315,8,9,1,0,2324,8,14,3,-4,2338,8,12,0,0,2350,8,7,1,1,2357,8,5,0,2,2362,8,4,1,7,2366,8,2,3,3,2368,8,1,3,3,2369,8,11,0,0,2380,8,6,0,5,2386,8,6,0,5,2392,8,7,1,1,2399,8,0,0,0,}; +rfbFontData vgaFont={vgaFontData, vgaFontMetaData}; diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore new file mode 100755 index 0000000..27e9b7a --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/.cvsignore @@ -0,0 +1,5 @@ +.deps +Makefile +Makefile.in +x11vnc + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c new file mode 100755 index 0000000..4c55e02 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.c @@ -0,0 +1,2155 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- 8to24.c -- */ +#include "x11vnc.h" +#include "cleanup.h" +#include "scan.h" +#include "util.h" +#include "win_utils.h" +#include "xwrappers.h" + +int multivis_count = 0; +int multivis_24count = 0; + +void check_for_multivis(void); +void bpp8to24(int, int, int, int); +void mark_8bpp(int); + +#if SKIP_8TO24 +void check_for_multivis(void) {} +void bpp8to24(int x, int y, int z, int t) {} +void mark_8bpp(int x) {} +#else +/* lots... */ + +static void set_root_cmap(void); +static int check_pointer_in_depth24(void); +static void parse_cmap8to24(void); +static void set_poll_fb(void); +static int check_depth(Window win, Window top, int doall); +static int check_depth_win(Window win, Window top, XWindowAttributes *attr); +static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w); +static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod); +static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod); +static int poll_8bpp(sraRegionPtr, int); +static void poll_8bpp_complement(sraRegionPtr); +static void mark_rgn_rects(sraRegionPtr mod); +static int get_8bpp_regions(int validate); +static int get_cmap(int j, Colormap cmap); +static void do_8bpp_region(int n, sraRegionPtr mark); +static XImage *cmap_xi(XImage *xi, Window win, int win_depth); +static void transform_rect(sraRect rect, Window win, int win_depth, int cm); + +/* struct for keeping info about the 8bpp windows: */ +typedef struct window8 { + Window win; + Window top; + int depth; + int x, y; + int w, h; + int map_state; + Colormap cmap; + Bool map_installed; + int fetched; + double last_fetched; + sraRegionPtr clip_region; +} window8bpp_t; + +enum mark_8bpp_modes { + MARK_8BPP_ALL = 0, + MARK_8BPP_POINTER, + MARK_8BPP_TOP +}; + + +#define NCOLOR 256 + +static Colormap root_cmap = 0; +static unsigned int *root_rgb = NULL; + +static void set_root_cmap(void) { +#if NO_X11 + RAWFB_RET_VOID + return; +#else + static time_t last_set = 0; + time_t now = time(NULL); + XWindowAttributes attr; + static XColor *color = NULL; + int redo = 0; + int ncolor = 0; + + RAWFB_RET_VOID + + if (depth > 16) { + ncolor = NCOLOR; + } else if (depth > 8) { + ncolor = 1 << depth; + } else { + ncolor = NCOLOR; + } + + if (!root_rgb) { + root_rgb = (unsigned int *) malloc(ncolor * sizeof(unsigned int)); + } + if (!color) { + color = (XColor *) malloc(ncolor * sizeof(XColor)); + } + + if (now > last_set + 10) { + redo = 1; + } + if (! root_cmap || redo) { + X_LOCK; + if (! valid_window(window, &attr, 1)) { + X_UNLOCK; + return; + } + if (attr.colormap) { + int i, ncells = ncolor; + + if (depth < 8) { + ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); + } + for (i=0; i < ncells; i++) { + color[i].pixel = i; + color[i].pad = 0; + } + last_set = now; + root_cmap = attr.colormap; + XQueryColors(dpy, root_cmap, color, ncells); + for (i=0; i < ncells; i++) { + unsigned int red, green, blue; + /* strip out highest 8 bits of values: */ + red = (color[i].red & 0xff00) >> 8; + green = (color[i].green & 0xff00) >> 8; + blue = (color[i].blue & 0xff00) >> 8; + + /* + * the maxes should be at 255 already, + * but just in case... + */ + red = (main_red_max * red )/255; + green = (main_green_max * green)/255; + blue = (main_blue_max * blue )/255; + + /* shift them over and or together for value */ + red = red << main_red_shift; + green = green << main_green_shift; + blue = blue << main_blue_shift; + + /* store it in the array to be used later */ + root_rgb[i] = red | green | blue; + } + } + X_UNLOCK; + } +#endif /* NO_X11 */ +} + +/* fixed size array. Will primarily hold visible 8bpp windows */ +#define MAX_8BPP_WINDOWS 64 +static window8bpp_t windows_8bpp[MAX_8BPP_WINDOWS]; + +static int db24 = 0; +static int xgetimage_8to24 = 1; +static double poll_8to24_delay = POLL_8TO24_DELAY; +static double cache_win = 0.0; +static int level2_8to24 = 0; + +static int check_pointer_in_depth24(void) { + int tries = 0, in_24 = 0; + XWindowAttributes attr; + Window c, w; + double now = dnow(); + + c = window; + + RAWFB_RET(0) + + if (now > last_keyboard_time + 1.0 && now > last_pointer_time + 1.0) { + return 0; + } + + X_LOCK; + while (c && tries++ < 3) { + c = query_pointer(c); + if (valid_window(c, &attr, 1)) { + if (attr.depth == 24) { + in_24 = 1; + break; + } + } + } + X_UNLOCK; + if (in_24) { + int x1, y1, x2, y2; + X_LOCK; + xtranslate(c, window, 0, 0, &x1, &y1, &w, 1); + X_UNLOCK; + x2 = x1 + attr.width; + y2 = y1 + attr.height; + x1 = nfix(x1, dpy_x); + y1 = nfix(y1, dpy_y); + x2 = nfix(x2, dpy_x+1); + y2 = nfix(y2, dpy_y+1); + mark_rect_as_modified(x1, y1, x2, y2, 0); + +if (db24 > 1) fprintf(stderr, "check_pointer_in_depth24 %d %d %d %d\n", x1, y1, x2, y2); + + return 1; + } + return 0; +} + +static void parse_cmap8to24(void) { + if (cmap8to24_str) { + char *p, *str = strdup(cmap8to24_str); + p = strtok(str, ","); + /* defaults: */ + db24 = 0; + xgetimage_8to24 = 1; + poll_8to24_delay = POLL_8TO24_DELAY; + level2_8to24 = 0; + cache_win = 0.0; + while (p) { + if (strstr(p, "dbg=") == p) { + db24 = atoi(p + strlen("dbg=")); + } else if (strstr(p, "poll=") == p) { + poll_8to24_delay = atof(p + strlen("poll=")); + } else if (strstr(p, "cachewin=") == p) { + cache_win = atof(p + strlen("cachewin=")); + } else if (!strcmp(p, "nogetimage")) { + xgetimage_8to24 = 0; + } else if (!strcmp(p, "level2")) { + level2_8to24 = 1; + } + p = strtok(NULL, ","); + } + free(str); + } else { + if (getenv("DEBUG_8TO24") != NULL) { + db24 = atoi(getenv("DEBUG_8TO24")); + } + if (getenv("NOXGETIMAGE_8TO24") != NULL) { + xgetimage_8to24 = 0; + } + } +} + +static char *poll8_fb = NULL, *poll24_fb = NULL; +static int poll8_fb_w = 0, poll8_fb_h = 0; +static int poll24_fb_w = 0, poll24_fb_h = 0; + +static void pfb(int fac, char **fb, int *w, int *h) { + if (! *fb || *w != dpy_x || *h != dpy_y) { + if (*fb) { + free(*fb); + } + *fb = (char *) calloc(fac * dpy_x * dpy_y, 1); + *w = dpy_x; + *h = dpy_y; + } +} + +static void set_poll_fb(void) { + /* create polling framebuffers or recreate if too small. */ + + if (! xgetimage_8to24) { + return; /* this saves a bit of RAM */ + } + pfb(4, &poll24_fb, &poll24_fb_w, &poll24_fb_h); + if (depth > 8 && depth <= 16) { + pfb(2, &poll8_fb, &poll8_fb_w, &poll8_fb_h); /* 2X for rare 16bpp colormap case */ + } else { + pfb(1, &poll8_fb, &poll8_fb_w, &poll8_fb_h); + } +} + +int MV_glob = 0; +int MV_count; +int MV_hit; +double MV_start; + +void check_for_multivis(void) { +#if NO_X11 + RAWFB_RET_VOID + return; +#else + XWindowAttributes attr; + int doall = 0; + int k, i, cnt, diff; + static int first = 1; + static Window *stack_old = NULL; + static int stack_old_len = 0; + static double last_parse = 0.0; + static double last_update = 0.0; + static double last_clear = 0.0; + static double last_poll = 0.0; + static double last_fixup = 0.0; + static double last_call = 0.0; + static double last_query = 0.0; + double now = dnow(); + double delay; + + RAWFB_RET_VOID + + if (now > last_parse + 1.0) { + last_parse = now; + parse_cmap8to24(); + } +if (db24 > 2) fprintf(stderr, " check_for_multivis: %.4f\n", now - last_call); + last_call = now; + + if (first) { + int i; + /* initialize 8bpp window table: */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + windows_8bpp[i].win = None; + windows_8bpp[i].top = None; + windows_8bpp[i].map_state = IsUnmapped; + windows_8bpp[i].cmap = (Colormap) 0; + windows_8bpp[i].fetched = 0; + windows_8bpp[i].last_fetched = -1.0; + windows_8bpp[i].clip_region = NULL; + } + set_poll_fb(); + + first = 0; + doall = 1; /* fetch everything first time */ + } + + if (wireframe_in_progress) { + return; + } + + set_root_cmap(); + + /* + * allocate an "old stack" list of all toplevels. we compare + * this to the current stack to guess stacking order changes. + */ + if (!stack_old || stack_old_len < stack_list_len) { + int n = stack_list_len; + if (n < 256) { + n = 256; + } + if (stack_old) { + free(stack_old); + } + stack_old = (Window *) calloc(n*sizeof(Window), 1); + stack_old_len = n; + } + + /* fill the old stack with visible windows: */ + cnt = 0; + for (k=0; k < stack_list_num; k++) { + if (stack_list[k].valid && + stack_list[k].map_state == IsViewable) { + stack_old[cnt++] = stack_list[k].win; + } + } + + /* snapshot + update the current stacking order: */ + /* TUNABLE */ + if (poll_8to24_delay >= POLL_8TO24_DELAY) { + delay = 3.0 * poll_8to24_delay; + } else { + delay = 3.0 * POLL_8TO24_DELAY; /* 0.15 */ + } + if (doall || now > last_update + delay) { + snapshot_stack_list(0, 0.0); + update_stack_list(); + last_update = now; + } + + /* look for differences in the visible toplevels: */ + diff = 0; + cnt = 0; + for (k=0; k < stack_list_num; k++) { + if (stack_list[k].valid && stack_list[k].map_state == + IsViewable) { + if (stack_old[cnt] != stack_list[k].win) { + diff = 1; + break; + } + cnt++; + } + } + + multivis_count = 0; + multivis_24count = 0; + + /* + * every 10 seconds we try to clean out and also refresh the window + * info in the the 8bpp window table: + */ + if (now > last_clear + 10) { + last_clear = now; + X_LOCK; + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + Window w = windows_8bpp[i].win; + if (! valid_window(w, &attr, 1)) { + /* catch windows that went away: */ + windows_8bpp[i].win = None; + windows_8bpp[i].top = None; + windows_8bpp[i].map_state = IsUnmapped; + windows_8bpp[i].cmap = (Colormap) 0; + windows_8bpp[i].fetched = 0; + windows_8bpp[i].last_fetched = -1.0; + } + } + X_UNLOCK; + } + + MV_count = 0; + MV_hit = 0; + MV_start = dnow(); + + set_root_cmap(); + + /* loop over all toplevels, both 8 and 24 depths: */ + + X_LOCK; /* a giant lock around the whole activity */ + + for (k=0; k < stack_list_num; k++) { + Window r, parent; + Window *list0; + Status rc; + unsigned int nc0; + int i1; + XErrorHandler old_handler; + double delay; + + Window win = stack_list[k].win; + + /* TUNABLE */ + if (poll_8to24_delay >= POLL_8TO24_DELAY) { + delay = 1.5 * poll_8to24_delay; + } else { + delay = 1.5 * POLL_8TO24_DELAY; /* 0.075 */ + } + + if (now < last_query + delay) { + break; + } + + if (win == None) { + continue; + } + + if (stack_list[k].map_state != IsViewable) { + int i; + /* + * if the toplevel became unmapped, mark it + * for the children as well... + */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + if (windows_8bpp[i].top == win) { + windows_8bpp[i].map_state = + stack_list[k].map_state; + } + } + } + + if (check_depth(win, win, doall)) { + /* + * returns 1 if no need to recurse down e.g. It + * is 8bpp and we assume all lower ones are too. + */ + continue; + } + + /* we recurse up to two levels down from stack_list windows */ + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + rc = XQueryTree_wr(dpy, win, &r, &parent, &list0, &nc0); + XSetErrorHandler(old_handler); + + if (! rc || trapped_xerror) { + trapped_xerror = 0; + continue; + } + trapped_xerror = 0; + + /* loop over grandchildren of rootwin: */ + for (i1=0; i1 < (int) nc0; i1++) { + Window win1 = list0[i1]; + Window *list1; + unsigned int nc1; + int i2; + + if (check_depth(win1, win, doall)) { + continue; + } + + if (level2_8to24) { + continue; + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + rc = XQueryTree_wr(dpy, win1, &r, &parent, &list1, &nc1); + XSetErrorHandler(old_handler); + + if (! rc || trapped_xerror) { + trapped_xerror = 0; + continue; + } + trapped_xerror = 0; + + /* loop over great-grandchildren of rootwin: */ + for (i2=0; i2< (int) nc1; i2++) { + Window win2 = list1[i2]; + + if (check_depth(win2, win, doall)) { + continue; + } + /* more? Which wm does this? */ + } + if (nc1) { + XFree_wr(list1); + } + } + if (nc0) { + XFree_wr(list0); + } + } + X_UNLOCK; + + last_query = dnow(); + +MV_glob += MV_count; +if (0) fprintf(stderr, "MV_count: %d hit: %d %.4f %10.2f\n", MV_count, MV_hit, last_query - MV_start, MV_glob / (last_query - x11vnc_start)); + + if (screen_fixup_8 > 0.0 && now > last_fixup + screen_fixup_8) { + last_fixup = now; + mark_8bpp(MARK_8BPP_ALL); + last_poll = now; + + } else if (poll_8to24_delay > 0.0) { + int area = -1; + int validate = 0; + + if (diff && multivis_count) { + validate = 1; + } + if (now > last_poll + poll_8to24_delay) { + sraRegionPtr mod; + + last_poll = now; + mod = sraRgnCreate(); + area = poll_8bpp(mod, validate); + if (depth == 24) { + poll_8bpp_complement(mod); + } + mark_rgn_rects(mod); + sraRgnDestroy(mod); + } + if (0 && area < dpy_x * dpy_y / 2 && diff && multivis_count) { + mark_8bpp(MARK_8BPP_POINTER); + last_poll = now; + } + + } else if (diff && multivis_count) { + mark_8bpp(MARK_8BPP_ALL); + last_poll = now; + + } else if (depth <= 16 && multivis_24count) { + static double last_check = 0.0; + if (now > last_check + 0.4) { + last_check = now; + if (check_pointer_in_depth24()) { + last_poll = now; + } + } + } +if (0) fprintf(stderr, "done: %.4f\n", dnow() - last_query); +#endif /* NO_X11 */ +} + +#define VW_CACHE_MAX 1024 +static XWindowAttributes vw_cache_attr[VW_CACHE_MAX]; +static Window vw_cache_win[VW_CACHE_MAX]; + +static void set_attr(XWindowAttributes *attr, int j) { + memcpy((void *) (vw_cache_attr+j), (void *) attr, + sizeof(XWindowAttributes)); +} +#if 0 +static int get_attr(XWindowAttributes *attr, int j) { + memcpy((void *) attr, (void *) (vw_cache_attr+j), + sizeof(XWindowAttributes)); + return 1; +} +#endif + +static XWindowAttributes wattr; + +static XWindowAttributes *vw_lookup(Window win) { + static double last_purge = 0.0; + double now; + int i, j, k; + + if (win == None) { + return NULL; + } + + now = dnow(); + if (now > last_purge + cache_win) { + last_purge = now; + for (i=0; i= 0) { +MV_hit++; + return vw_cache_attr+j; + + } else if (k >= 0) { + XWindowAttributes attr2; + int rc = valid_window(win, &attr2, 1); + if (rc) { + vw_cache_win[k] = win; + set_attr(&attr2, k); + return vw_cache_attr+k; + } else { + return NULL; + } + } else { + /* Full */ + int rc = valid_window(win, &wattr, 1); + if (rc) { + return &wattr; + } else { + return NULL; + } + } +} + +static int check_depth(Window win, Window top, int doall) { + XWindowAttributes attr, *pattr; + + /* first see if it is (still) a valid window: */ +MV_count++; + + if (cache_win > 0.0) { + pattr = vw_lookup(win); + if (pattr == NULL) { + return 1; /* indicate done */ + } + } else { + if (! valid_window(win, &attr, 1)) { + return 1; /* indicate done */ + } + pattr = &attr; + } + + if (! doall && pattr->map_state != IsViewable) { + /* + * store results anyway... this may lead to table + * filling up, but currently this allows us to update + * state of onetime mapped windows. + */ + check_depth_win(win, top, pattr); + return 1; /* indicate done */ + } else if (check_depth_win(win, top, pattr)) { + return 1; /* indicate done */ + } else { + return 0; /* indicate not done */ + } +} + +static int check_depth_win(Window win, Window top, XWindowAttributes *attr) { + int store_it = 0; + /* + * only store windows with depth not equal to the default visual's + * depth note some windows can have depth == 0 ... (skip them). + */ + if (attr->depth > 0) { + if (depth == 24 && attr->depth != 24) { + store_it = 1; + } else if (depth <= 16 && root_cmap && attr->colormap != root_cmap) { + store_it = 1; + } + } + + if (store_it) { + int i, j = -1, none = -1, nomap = -1; + int new = 0; + if (attr->map_state == IsViewable) { + /* count the visible ones: */ + multivis_count++; + if (attr->depth == 24) { + multivis_24count++; + } +if (db24 > 1) fprintf(stderr, "multivis: 0x%lx %d\n", win, attr->depth); + } + + /* try to find a table slot for this window: */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + if (none < 0 && windows_8bpp[i].win == None) { + /* found first None */ + none = i; + } + if (windows_8bpp[i].win == win) { + /* found myself */ + j = i; + break; + } + if (nomap < 0 && windows_8bpp[i].win != None && + windows_8bpp[i].map_state != IsViewable) { + /* found first unmapped */ + nomap = i; + } + } + if (j < 0) { + if (attr->map_state != IsViewable) { + /* no slot and not visible: not worth keeping */ + return 1; + } else if (none >= 0) { + /* put it in the first None slot */ + j = none; + new = 1; + } else if (nomap >=0) { + /* put it in the first unmapped slot */ + j = nomap; + } + /* otherwise we cannot store it... */ + } + +if (db24 > 1) fprintf(stderr, "multivis: 0x%lx ms: %d j: %d no: %d nm: %d dep=%d\n", win, attr->map_state, j, none, nomap, attr->depth); + + /* store if if we found a slot j: */ + if (j >= 0) { + Window w; + int x, y; + int now_vis = 0; + + if (attr->map_state == IsViewable && + windows_8bpp[j].map_state != IsViewable) { + now_vis = 1; + } +if (db24 > 1) fprintf(stderr, "multivis: STORE 0x%lx j: %3d ms: %d dep=%d\n", win, j, attr->map_state, attr->depth); + windows_8bpp[j].win = win; + windows_8bpp[j].top = top; + windows_8bpp[j].depth = attr->depth; + windows_8bpp[j].map_state = attr->map_state; + windows_8bpp[j].cmap = attr->colormap; + windows_8bpp[j].map_installed = attr->map_installed; + windows_8bpp[j].w = attr->width; + windows_8bpp[j].h = attr->height; + windows_8bpp[j].fetched = 1; + windows_8bpp[j].last_fetched = dnow(); + + /* translate x y to be WRT the root window (not parent) */ + xtranslate(win, window, 0, 0, &x, &y, &w, 1); + windows_8bpp[j].x = x; + windows_8bpp[j].y = y; + + if (new || now_vis) { +if (db24) fprintf(stderr, "new/now_vis: 0x%lx %d/%d\n", win, new, now_vis); + /* mark it immediately if a new one: */ + X_UNLOCK; /* dont forget the giant lock */ + mark_rect_as_modified(x, y, x + attr->width, + y + attr->height, 0); + X_LOCK; + } + } else { + /* + * Error: could not find a slot. + * perhaps keep age and expire old ones?? + */ +if (db24) fprintf(stderr, "multivis: CANNOT STORE 0x%lx j=%d\n", win, j); + for (i=0; i < MAX_8BPP_WINDOWS; i++) { +if (db24 > 1) fprintf(stderr, " ------------ 0x%lx i=%d\n", windows_8bpp[i].win, i); + } + + } + return 1; + } + return 0; +} + +/* polling line XImage */ +static XImage *p_xi(XImage *xi, Visual *visual, int win_depth, int *w) { + RAWFB_RET(NULL) + +#if NO_X11 + if (!xi || !visual || !win_depth || !w) {} + return NULL; +#else + if (xi == NULL || *w < dpy_x) { + char *d; + if (xi) { + XDestroyImage(xi); + } + if (win_depth != 24) { + if (win_depth > 8) { + d = (char *) malloc(dpy_x * 2); + } else { + d = (char *) malloc(dpy_x * 1); + } + } else { + d = (char *) malloc(dpy_x * 4); + } + *w = dpy_x; + xi = XCreateImage(dpy, visual, win_depth, ZPixmap, 0, d, + dpy_x, 1, 8, 0); + } + return xi; +#endif /* NO_X11 */ +} + +static int poll_line(int x1, int x2, int y1, int n, sraRegionPtr mod) { +#if NO_X11 + RAWFB_RET(1) + if (!x1 || !x2 || !y1 || !n || !mod) {} + return 1; +#else + int fac, n_off, w, xo, yo; + char *poll_fb, *dst, *src; + int w2, xl, xh, stride = 32; + int inrun = 0, rx1 = -1, rx2 = -1; + + static XImage *xi8 = NULL, *xi24 = NULL, *xi_r; + static int xi8_w = 0, xi24_w = 0; + + XErrorHandler old_handler = NULL; + XImage *xi; + Window c, win = windows_8bpp[n].win; + + static XWindowAttributes attr; + static Window last_win = None; + static double last_time = 0.0; + double now; + + sraRegionPtr rect; + int mx1, mx2, my1, my2; + int ns = NSCAN/2; + + RAWFB_RET(1) + + if (win == None) { + return 1; + } + if (windows_8bpp[n].map_state != IsViewable) { + return 1; + } + if (! xgetimage_8to24) { + return 1; + } + + X_LOCK; + now = dnow(); + if (last_win != None && win == last_win && now < last_time + 0.5) { + ; /* use previous attr */ + } else { + if (! valid_window(win, &attr, 1)) { + X_UNLOCK; + last_win = None; + return 0; + } + last_time = now; + last_win = win; + } + + if (attr.depth > 16 && attr.depth != 24) { + X_UNLOCK; + return 1; + } else if (attr.depth <= 16) { + xi = xi8 = p_xi(xi8, attr.visual, attr.depth, &xi8_w); + + poll_fb = poll8_fb; + if (attr.depth > 8) { + fac = 2; + } else { + fac = 1; + } + n_off = poll8_fb_w * y1 + x1; + } else { + xi = xi24 = p_xi(xi24, attr.visual, 24, &xi24_w); + + poll_fb = poll24_fb; + fac = 4; + n_off = poll24_fb_w * y1 + x1; + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + + /* xtranslate() not used to save two XSetErrorHandler calls */ + XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c); + + xo = x1 - xo; + yo = y1 - yo; + w = x2 - x1; + + if (trapped_xerror || xo < 0 || yo < 0 || xo + w > attr.width) { +if (db24 > 2) fprintf(stderr, "avoid bad match...\n"); + XSetErrorHandler(old_handler); + trapped_xerror = 0; + X_UNLOCK; + return 0; + } + + trapped_xerror = 0; + xi_r = XGetSubImage(dpy, win, xo, yo, w, 1, AllPlanes, ZPixmap, xi, + 0, 0); + XSetErrorHandler(old_handler); + + X_UNLOCK; + + if (! xi_r || trapped_xerror) { + trapped_xerror = 0; + return 0; + } + trapped_xerror = 0; + + src = xi->data; + dst = poll_fb + fac * n_off; + + inrun = 0; + + xl = x1; + while (xl < x2) { + xh = xl + stride; + if (xh > x2) { + xh = x2; + } + w2 = xh - xl; + if (memcmp(dst, src, fac * w2)) { + if (inrun) { + rx2 = xh; + } else { + rx1 = xl; + rx2 = xh; + inrun = 1; + } + } else { + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + inrun = 0; + } + } + + xl += stride; + dst += fac * stride; + src += fac * stride; + } + + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + } + return 1; +#endif /* NO_X11 */ +} + +static void poll_line_complement(int x1, int x2, int y1, sraRegionPtr mod) { + int n_off, w, xl, xh, stride = 32; + char *dst, *src; + int inrun = 0, rx1 = -1, rx2 = -1; + sraRegionPtr rect; + int mx1, mx2, my1, my2; + int ns = NSCAN/2; + + if (depth != 24) { + return; + } + if (! cmap8to24_fb) { + return; + } + if (! xgetimage_8to24) { + return; + } + + n_off = main_bytes_per_line * y1 + 4 * x1; + + src = main_fb + n_off; + dst = cmap8to24_fb + n_off; + + inrun = 0; + + xl = x1; + while (xl < x2) { + xh = xl + stride; + if (xh > x2) { + xh = x2; + } + w = xh - xl; + if (memcmp(dst, src, 4 * w)) { + if (inrun) { + rx2 = xh; + } else { + rx1 = xl; + rx2 = xh; + inrun = 1; + } + } else { + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + + inrun = 0; + } + } + + xl += stride; + dst += 4 * stride; + src += 4 * stride; + } + + if (inrun) { + mx1 = rx1; + mx2 = rx2; + my1 = nfix(y1 - ns, dpy_y); + my2 = nfix(y1 + ns, dpy_y+1); + + rect = sraRgnCreateRect(mx1, my1, mx2, my2); + sraRgnOr(mod, rect); + sraRgnDestroy(rect); + + inrun = 0; + } +} + +#define CMAPMAX 64 +static Colormap cmaps[CMAPMAX]; +static int ncmaps; + +static int poll_8bpp(sraRegionPtr mod, int validate) { + int i, y, ysh, map_count; + static int ycnt = 0; + sraRegionPtr line; + sraRect rect; + sraRectangleIterator *iter; + int br = 0, area = 0; + static double last_call = 0.0; + + map_count = get_8bpp_regions(validate); + +if (db24 > 1) fprintf(stderr, "poll_8bpp mc: %d\n", map_count); + + if (! map_count) { + return 0; + } + + set_poll_fb(); + + ysh = scanlines[(ycnt++) % NSCAN]; +if (db24 > 2) fprintf(stderr, "poll_8bpp: ysh: %2d %.4f\n", ysh, dnow() - last_call); + last_call = dnow(); + + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr reg = windows_8bpp[i].clip_region; + + if (! reg || sraRgnEmpty(reg)) { + continue; + } + y = ysh; + while (y < dpy_y) { + line = sraRgnCreateRect(0, y, dpy_x, y+1); + + if (sraRgnAnd(line, reg)) { + iter = sraRgnGetIterator(line); + while (sraRgnIteratorNext(iter, &rect)) { + if (! poll_line(rect.x1, rect.x2, + rect.y1, i, mod)) { + br = 1; + break; /* exception */ + } + } + sraRgnReleaseIterator(iter); + } + + sraRgnDestroy(line); + y += NSCAN; + if (br) break; + } + if (br) break; + } + + iter = sraRgnGetIterator(mod); + while (sraRgnIteratorNext(iter, &rect)) { + area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1)); + } + sraRgnReleaseIterator(iter); + + return area; +} + +static void poll_8bpp_complement(sraRegionPtr mod) { + int i, y, ysh; + static int ycnt = 0; + sraRegionPtr disp, line; + sraRect rect; + sraRectangleIterator *iter; + + disp = sraRgnCreateRect(0, 0, dpy_x, dpy_y); + + ysh = scanlines[(ycnt++) % NSCAN]; + + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr reg = windows_8bpp[i].clip_region; + + if (! reg) { + continue; + } + if (windows_8bpp[i].map_state != IsViewable) { + continue; + } + sraRgnSubtract(disp, reg); + } + + y = ysh; + while (y < dpy_y) { + line = sraRgnCreateRect(0, y, dpy_x, y+1); + + if (sraRgnAnd(line, disp)) { + iter = sraRgnGetIterator(line); + while (sraRgnIteratorNext(iter, &rect)) { + poll_line_complement(rect.x1, rect.x2, + rect.y1, mod); + } + sraRgnReleaseIterator(iter); + } + + sraRgnDestroy(line); + + y += NSCAN; + } + + sraRgnDestroy(disp); +} + +static void mark_rgn_rects(sraRegionPtr mod) { + sraRect rect; + sraRectangleIterator *iter; + int area = 0; + + if (sraRgnEmpty(mod)) { + return; + } + + iter = sraRgnGetIterator(mod); + while (sraRgnIteratorNext(iter, &rect)) { + mark_rect_as_modified(rect.x1, rect.y1, rect.x2, rect.y2, 0); + area += nabs((rect.x2 - rect.x1)*(rect.y2 - rect.y1)); + } + sraRgnReleaseIterator(iter); + +if (db24 > 1) fprintf(stderr, " mark_rgn_rects area: %d\n", area); +} + +static int get_8bpp_regions(int validate) { + + XWindowAttributes attr; + int i, k, mapcount = 0; + + /* initialize color map list */ + ncmaps = 0; + for (i=0; i < CMAPMAX; i++) { + cmaps[i] = (Colormap) 0; + } + + /* loop over the table of 8bpp windows: */ + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr tmp_reg, tmp_reg2; + Window c, w = windows_8bpp[i].win; + int x, y; + + if (windows_8bpp[i].clip_region) { + sraRgnDestroy(windows_8bpp[i].clip_region); + } + windows_8bpp[i].clip_region = NULL; + + if (w == None) { + continue; + } + +if (db24 > 1) fprintf(stderr, "get_8bpp_regions: 0x%lx ms=%d dep=%d i=%d\n", w, windows_8bpp[i].map_state, windows_8bpp[i].depth, i); + if (validate) { + /* + * this could be slow: validating 8bpp windows each + * time... + */ + + X_LOCK; + if (! valid_window(w, &attr, 1)) { + X_UNLOCK; + windows_8bpp[i].win = None; + windows_8bpp[i].top = None; + windows_8bpp[i].map_state = IsUnmapped; + windows_8bpp[i].cmap = (Colormap) 0; + windows_8bpp[i].fetched = 0; + windows_8bpp[i].last_fetched = -1.0; + continue; + } + X_UNLOCK; + + windows_8bpp[i].depth = attr.depth; + windows_8bpp[i].map_state = attr.map_state; + windows_8bpp[i].cmap = attr.colormap; + windows_8bpp[i].map_installed = attr.map_installed; + windows_8bpp[i].w = attr.width; + windows_8bpp[i].h = attr.height; + windows_8bpp[i].fetched = 1; + windows_8bpp[i].last_fetched = dnow(); + + if (attr.map_state != IsViewable) { + continue; + } + + X_LOCK; + xtranslate(w, window, 0, 0, &x, &y, &c, 1); + X_UNLOCK; + windows_8bpp[i].x = x; + windows_8bpp[i].y = y; + + } else { + /* this will be faster: no call to X server: */ + if (windows_8bpp[i].map_state != IsViewable) { + continue; + } + attr.depth = windows_8bpp[i].depth; + attr.map_state = windows_8bpp[i].map_state; + attr.colormap = windows_8bpp[i].cmap; + attr.map_installed = windows_8bpp[i].map_installed; + attr.width = windows_8bpp[i].w; + attr.height = windows_8bpp[i].h; + + x = windows_8bpp[i].x; + y = windows_8bpp[i].y; + } + + mapcount++; + + /* tmp region for this 8bpp rectangle: */ + tmp_reg = sraRgnCreateRect(nfix(x, dpy_x), nfix(y, dpy_y), + nfix(x + attr.width, dpy_x+1), nfix(y + attr.height, dpy_y+1)); + + /* loop over all toplevels, top to bottom clipping: */ + for (k = stack_list_num - 1; k >= 0; k--) { + Window swin = stack_list[k].win; + int sx, sy, sw, sh; + +if (db24 > 1 && stack_list[k].map_state == IsViewable) fprintf(stderr, "Stack win: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state); + + if (swin == windows_8bpp[i].top) { + /* found our top level: we skip the rest. */ +if (db24 > 1) fprintf(stderr, "found top: 0x%lx %d iv=%d\n", swin, k, stack_list[k].map_state); + break; + } + if (stack_list[k].map_state != IsViewable) { + /* skip unmapped ones: */ + continue; + } + + /* make a temp rect for this toplevel: */ + sx = stack_list[k].x; + sy = stack_list[k].y; + sw = stack_list[k].width; + sh = stack_list[k].height; + +if (db24 > 1) fprintf(stderr, "subtract: 0x%lx %d -- %d %d %d %d\n", swin, k, sx, sy, sw, sh); + + tmp_reg2 = sraRgnCreateRect(nfix(sx, dpy_x), + nfix(sy, dpy_y), nfix(sx + sw, dpy_x+1), + nfix(sy + sh, dpy_y+1)); + + /* subtract it from the 8bpp window region */ + sraRgnSubtract(tmp_reg, tmp_reg2); + + sraRgnDestroy(tmp_reg2); + + if (sraRgnEmpty(tmp_reg)) { + break; + } + } + + if (sraRgnEmpty(tmp_reg)) { + /* skip this 8bpp if completely clipped away: */ + sraRgnDestroy(tmp_reg); + continue; + } + + /* otherwise, store any new colormaps: */ + if (ncmaps < CMAPMAX && attr.colormap != (Colormap) 0) { + int m, seen = 0; + for (m=0; m < ncmaps; m++) { + if (cmaps[m] == attr.colormap) { + seen = 1; + break; + } + } + if (!seen && attr.depth <= 16) { + /* store only new ones: */ + cmaps[ncmaps++] = attr.colormap; + } + } + + windows_8bpp[i].clip_region = tmp_reg; + } + + return mapcount; +} + +static XColor *color[CMAPMAX]; +static unsigned int *rgb[CMAPMAX]; +static int cmap_failed[CMAPMAX]; +static int color_init = 0; +int histo[65536]; + +static int get_cmap(int j, Colormap cmap) { +#if NO_X11 + RAWFB_RET(0) + if (!j || !cmap) {} + return 0; +#else + int i, ncells, ncolor; + XErrorHandler old_handler = NULL; + + RAWFB_RET(0) + + if (depth > 16) { + /* 24 */ + ncolor = NCOLOR; + } else if (depth > 8) { + ncolor = 1 << depth; + } else { + ncolor = NCOLOR; + } + if (!color_init) { + int cm; + for (cm = 0; cm < CMAPMAX; cm++) { + color[cm] = (XColor *) malloc(ncolor * sizeof(XColor)); + rgb[cm] = (unsigned int *) malloc(ncolor * sizeof(unsigned int)); + } + color_init = 1; + } + + if (depth <= 16) { + /* not working properly for depth 24... */ + X_LOCK; + ncells = CellsOfScreen(ScreenOfDisplay(dpy, scr)); + X_UNLOCK; + } else { + ncells = NCOLOR; + } + + if (depth > 16) { + ; + } else if (ncells > ncolor) { + ncells = ncolor; + } else if (ncells == 8 && depth != 3) { + /* XXX. see set_colormap() */ + ncells = 1 << depth; + } + + /* initialize XColor array: */ + for (i=0; i < ncells; i++) { + color[j][i].pixel = i; + color[j][i].pad = 0; + } +if (db24 > 1) fprintf(stderr, "get_cmap: %d 0x%x ncolor=%d ncells=%d\n", j, (unsigned int) cmap, ncolor, ncells); + + /* try to query the colormap, trap errors */ + X_LOCK; + trapped_xerror = 0; + old_handler = XSetErrorHandler(trap_xerror); + XQueryColors(dpy, cmap, color[j], ncells); + XSetErrorHandler(old_handler); + X_UNLOCK; + + if (trapped_xerror) { + trapped_xerror = 0; + return 0; + } + trapped_xerror = 0; + + /* now map each index to depth 24 RGB */ + for (i=0; i < ncells; i++) { + unsigned int red, green, blue; + /* strip out highest 8 bits of values: */ + red = (color[j][i].red & 0xff00) >> 8; + green = (color[j][i].green & 0xff00) >> 8; + blue = (color[j][i].blue & 0xff00) >> 8; + + /* + * the maxes should be at 255 already, + * but just in case... + */ + red = (main_red_max * red )/255; + green = (main_green_max * green)/255; + blue = (main_blue_max * blue )/255; + +if (db24 > 2) fprintf(stderr, " cmap[%02d][%03d]: %03d %03d %03d 0x%08x \n", j, i, red, green, blue, ( red << main_red_shift | green << main_green_shift | blue << main_blue_shift)); + + /* shift them over and or together for value */ + red = red << main_red_shift; + green = green << main_green_shift; + blue = blue << main_blue_shift; + + /* store it in the array to be used later */ + rgb[j][i] = red | green | blue; + } + return 1; +#endif /* NO_X11 */ +} + +static void do_8bpp_region(int n, sraRegionPtr mark) { + int k, cm = -1, failed = 0; + sraRectangleIterator *iter; + sraRegionPtr clip; + sraRect rect; + + if (! windows_8bpp[n].clip_region) { + return; + } + if (windows_8bpp[n].win == None) { + return; + } + if (windows_8bpp[n].map_state != IsViewable) { + return; + } +if (db24 > 1) fprintf(stderr, "ncmaps: %d\n", ncmaps); + + /* see if XQueryColors failed: */ + for (k=0; k rect.x2) { + int tmp = rect.x2; + rect.x2 = rect.x1; + rect.x1 = tmp; + } + if (rect.y1 > rect.y2) { + int tmp = rect.y2; + rect.y2 = rect.y1; + rect.y1 = tmp; + } + + transform_rect(rect, windows_8bpp[n].win, + windows_8bpp[n].depth, cm); + } + sraRgnReleaseIterator(iter); + sraRgnDestroy(clip); +} + +static XImage *cmap_xi(XImage *xi, Window win, int win_depth) { +#if NO_X11 + if (!xi || !win || !win_depth) {} + return NULL; +#else + XWindowAttributes attr; + char *d; + + if (xi) { + XDestroyImage(xi); + } + if (! dpy || ! valid_window(win, &attr, 1)) { + return (XImage *) NULL; + } + if (win_depth == 24) { + d = (char *) malloc(dpy_x * dpy_y * 4); + } else if (win_depth <= 16) { + if (win_depth > 8) { + d = (char *) malloc(dpy_x * dpy_y * 2); + } else { + d = (char *) malloc(dpy_x * dpy_y * 1); + } + } else { + return (XImage *) NULL; + } + return XCreateImage(dpy, attr.visual, win_depth, ZPixmap, 0, d, dpy_x, dpy_y, 8, 0); +#endif /* NO_X11 */ +} + + +static void transform_rect(sraRect rect, Window win, int win_depth, int cm) { +#if NO_X11 + RAWFB_RET_VOID + if (!rect.x1 || !win || !win_depth || !cm) {} + return; +#else + + char *src, *dst, *poll; + unsigned int *ui; + unsigned short *us; + unsigned char *uc; + int ps, pixelsize = bpp/8; + int poll_Bpl; + + int do_getimage = xgetimage_8to24; + int line, n_off, j, h, w; + unsigned int hi, idx; + XWindowAttributes attr; + XErrorHandler old_handler = NULL; + +if (db24 > 1) fprintf(stderr, "transform %4d %4d %4d %4d cm: %d\n", rect.x1, rect.y1, rect.x2, rect.y2, cm); + + RAWFB_RET_VOID + + attr.width = 0; + attr.height = 0; + + /* now transform the pixels in this rectangle: */ + n_off = main_bytes_per_line * rect.y1 + pixelsize * rect.x1; + + h = rect.y2 - rect.y1; + w = rect.x2 - rect.x1; + + if (depth != 24) { + /* need to fetch depth 24 data. */ + do_getimage = 1; + } + +#if 0 + if (do_getimage) { + X_LOCK; + vw = valid_window(win, &attr, 1); + X_UNLOCK; + } + + if (do_getimage && vw) { +#else + if (do_getimage) { +#endif + static XImage *xi_8 = NULL; + static XImage *xi_24 = NULL; + XImage *xi = NULL, *xi_r; + Window c; + unsigned int wu, hu; + int xo, yo; + + wu = (unsigned int) w; + hu = (unsigned int) h; + + X_LOCK; +#define GETSUBIMAGE +#ifdef GETSUBIMAGE + if (win_depth == 24) { + if (xi_24 == NULL || xi_24->width != dpy_x || + xi_24->height != dpy_y) { + xi_24 = cmap_xi(xi_24, win, 24); + } + xi = xi_24; + } else if (win_depth <= 16) { + if (xi_8 == NULL || xi_8->width != dpy_x || + xi_8->height != dpy_y) { + if (win_depth > 8) { + /* XXX */ + xi_8 = cmap_xi(xi_8, win, 16); + } else { + xi_8 = cmap_xi(xi_8, win, 8); + } + } + xi = xi_8; + } +#endif + + if (xi == NULL) { + rfbLog("transform_rect: xi is NULL\n"); + X_UNLOCK; + clean_up_exit(1); + } + + old_handler = XSetErrorHandler(trap_xerror); + trapped_xerror = 0; + + XTranslateCoordinates(dpy, win, window, 0, 0, &xo, &yo, &c); + + xo = rect.x1 - xo; + yo = rect.y1 - yo; + +if (db24 > 1) fprintf(stderr, "xywh: %d %d %d %d vs. %d %d\n", xo, yo, w, h, attr.width, attr.height); + + if (trapped_xerror || xo < 0 || yo < 0) { + /* w > attr.width || h > attr.height */ + XSetErrorHandler(old_handler); + X_UNLOCK; + trapped_xerror = 0; +if (db24 > 1) fprintf(stderr, "skipping due to potential bad match...\n"); + return; + } + trapped_xerror = 0; + +#ifndef GETSUBIMAGE + xi = XGetImage(dpy, win, xo, yo, wu, hu, AllPlanes, ZPixmap); + xi_r = xi; +#else + xi_r = XGetSubImage(dpy, win, xo, yo, wu, hu, AllPlanes, + ZPixmap, xi, 0, 0); +#endif + XSetErrorHandler(old_handler); + + X_UNLOCK; + + if (! xi_r || trapped_xerror) { + trapped_xerror = 0; +if (db24 > 1) fprintf(stderr, "xi-fail: 0x%p trap=%d %d %d %d %d\n", (void *)xi, trapped_xerror, xo, yo, w, h); + return; + } else { +if (db24 > 1) fprintf(stderr, "xi: 0x%p %d %d %d %d -- %d %d\n", (void *)xi, xo, yo, w, h, xi->width, xi->height); + } + trapped_xerror = 0; + + if (xi->depth > 16 && xi->depth != 24) { +#ifndef GETSUBIMAGE + X_LOCK; + XDestroyImage(xi); + X_UNLOCK; +#endif +if (db24) fprintf(stderr, "xi: wrong depth: %d\n", xi->depth); + return; + } + + set_poll_fb(); + + if (xi->depth == 24) { + /* line by line ... */ + int ps1 = 4, fac; + if (depth <= 8) { + fac = 4; + } else if (depth <= 16) { + fac = 2; + } else { + fac = 1; /* will not happen 24 on 24 */ + } + + src = xi->data; + dst = cmap8to24_fb + fac * n_off; + + poll = poll24_fb + (poll24_fb_w * rect.y1 + rect.x1) * 4; + poll_Bpl = poll24_fb_w * 4; + + for (line = 0; line < h; line++) { + memcpy(dst, src, w * ps1); + memcpy(poll, src, w * ps1); + + src += xi->bytes_per_line; + dst += main_bytes_per_line * fac; + poll += poll_Bpl; + } + } else if (xi->depth <= 16) { + int ps1, ps2, fac; + + if (depth <= 8) { + ps1 = 1; + ps2 = 4; + fac = 4; + } else if (depth <= 16) { + ps1 = 2; + ps2 = 4; + fac = 4; + } else { + /* should be 24 case */ + ps1 = 1; + ps2 = pixelsize; + fac = 1; + } + + src = xi->data; + dst = cmap8to24_fb + (fac/ps1) * n_off; + + poll = poll8_fb + poll8_fb_w * rect.y1 * ps1 + rect.x1 * ps1; + poll_Bpl = poll8_fb_w * ps1; + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + if (ps1 == 2) { + unsigned short *ptmp; + us = (unsigned short *) (src + ps1 * j); + idx = (int) (*us); + ptmp = (unsigned short *) (poll + ps1 * j); + *ptmp = *us; + } else { + uc = (unsigned char *) (src + ps1 * j); + idx = (int) (*uc); + *(poll + ps1 * j) = *uc; + } + ui = (unsigned int *) (dst + ps2 * j); + *ui = rgb[cm][idx]; + + } + src += xi->bytes_per_line; + dst += main_bytes_per_line * (fac/ps1); + poll += poll_Bpl; + } + } + +#ifndef GETSUBIMAGE + X_LOCK; + XDestroyImage(xi); + X_UNLOCK; +#endif + + } else if (! do_getimage) { + int fac; + + if (depth <= 16) { + /* cooked up depth 24 TrueColor */ + /* but currently disabled (high bits no useful?) */ + ps = 4; + fac = 4; + /* XXX not correct for depth > 8, but do we ever come here in that case? */ + src = cmap8to24_fb + 4 * n_off; + } else { + ps = pixelsize; + fac = 1; + src = cmap8to24_fb + n_off; + } + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + + /* grab 32 bit value */ + ui = (unsigned int *) (src + ps * j); + + /* extract top 8 bits (FIXME: masks?) */ + hi = (*ui) & 0xff000000; + + /* map to lookup index; rewrite pixel */ + idx = hi >> 24; + *ui = hi | rgb[cm][idx]; + } + src += main_bytes_per_line * fac; + } + } +#endif /* NO_X11 */ +} + +void bpp8to24(int x1, int y1, int x2, int y2) { + char *src, *dst; + unsigned char *uc; + unsigned short *us; + unsigned int *ui; + int idx, pixelsize = bpp/8; + int line, k, i, j, h, w; + int n_off; + sraRegionPtr rect; + int validate = 1; + static int last_map_count = 0, call_count = 0; + static double last_get_8bpp_validate = 0.0; + static double last_snapshot = 0.0; + double now; + double dt, d0 = 0.0, t2; + + RAWFB_RET_VOID + + if (! cmap8to24 || ! cmap8to24_fb) { + /* hmmm, why were we called? */ + return; + } + +if (db24 > 1) fprintf(stderr, "bpp8to24 %d %d %d %d %.4f\n", x1, y1, x2, y2, dnow() - last_get_8bpp_validate); + + call_count++; + + /* clip to display just in case: */ + if (!ncache) { + x1 = nfix(x1, dpy_x); + y1 = nfix(y1, dpy_y); + x2 = nfix(x2, dpy_x+1); + y2 = nfix(y2, dpy_y+1); + } + + if (wireframe_in_progress) { + /* + * draw_box() manages cmap8to24_fb for us so we get out as + * soon as we can. No need to cp main_fb -> cmap8to24_fb. + */ + return; + } + + /* copy from main_fb to cmap8to24_fb regardless of 8bpp windows: */ + + h = y2 - y1; + w = x2 - x1; + + if (depth == 24) { + /* pixelsize = 4 */ + n_off = main_bytes_per_line * y1 + pixelsize * x1; + + src = main_fb + n_off; + dst = cmap8to24_fb + n_off; + + /* otherwise, the pixel data as is */ + for (line = 0; line < h; line++) { + memcpy(dst, src, w * pixelsize); + src += main_bytes_per_line; + dst += main_bytes_per_line; + } + } else if (depth <= 16) { + /* need to cook up to depth 24 TrueColor */ + int ps1 = 1, ps2 = 4; + if (depth > 8) { + ps1 = 2; + } + + /* pixelsize = 1, 2 */ + n_off = main_bytes_per_line * y1 + pixelsize * x1; + + src = main_fb + n_off; + dst = cmap8to24_fb + (4/ps1) * n_off; + + set_root_cmap(); + if (root_cmap) { +#if 0 + unsigned int hi; +#endif + + /* line by line ... */ + for (line = 0; line < h; line++) { + /* pixel by pixel... */ + for (j = 0; j < w; j++) { + if (ps1 == 2) { + us = (unsigned short *) (src + ps1 * j); + idx = (int) (*us); + } else { + uc = (unsigned char *) (src + ps1 * j); + idx = (int) (*uc); + } + ui = (unsigned int *) (dst + ps2 * j); + +if (0 && line % 100 == 0 && j % 32 == 0) fprintf(stderr, "%d %d %u x1=%d y1=%d\n", line, j, root_rgb[idx], x1, y1); +#if 0 + if (do_hibits) { + hi = idx << 24; + *ui = hi | rgb[0][idx]; + } else { + } +#endif + *ui = root_rgb[idx]; +if (db24 > 2) histo[idx]++; + } + src += main_bytes_per_line; + dst += main_bytes_per_line * (4/ps1); + } + } + + } + + if (last_map_count > MAX_8BPP_WINDOWS/4) { + /* table is filling up... skip validating sometimes: */ + int skip = 3; + if (last_map_count > MAX_8BPP_WINDOWS/2) { + skip = 6; + } else if (last_map_count > 3*MAX_8BPP_WINDOWS/4) { + skip = 12; + } + if (call_count % skip != 0) { + validate = 0; + } + } + +if (db24 > 2) {for(i=0;i<256;i++){histo[i]=0;}} + + now = dnow(); + dt = now - last_get_8bpp_validate; + /* TUNABLES */ + if (dt < 0.003) { + ; /* XXX does this still give painting errors? */ + } else { + int snapit = 0; + double delay1, delay2, delay3; + if (poll_8to24_delay >= POLL_8TO24_DELAY) { + delay1 = 1.0 * poll_8to24_delay; + delay2 = 2.0 * poll_8to24_delay; + delay3 = 10. * poll_8to24_delay; + } else { + delay1 = 1.0 * POLL_8TO24_DELAY; /* 0.05 */ + delay2 = 2.0 * POLL_8TO24_DELAY; /* 0.1 */ + delay3 = 10. * POLL_8TO24_DELAY; /* 0.5 */ + } + if (cache_win > 1.0) { + delay2 *= 2; + delay3 *= 2; + } + if (dt < delay1) { + validate = 0; + } + if (last_map_count) { + if (now > last_snapshot + delay2) { + snapit = 1; + } + } else { + if (now > last_snapshot + delay3) { + snapit = 1; + } + } + + if (snapit) { + /* less problems if we update the stack frequently */ + snapshot_stack_list(0, 0.0); +if (0) fprintf(stderr, "SNAP time: %.4f\n", dnow() - now); + update_stack_list(); + last_snapshot = dnow(); +if (0) fprintf(stderr, "UPDA time: %.4f\n", last_snapshot - now); + } + +if (0) t2 = dnow(); + last_map_count = get_8bpp_regions(validate); + if (validate) { + last_get_8bpp_validate = dnow(); + } +if (0) fprintf(stderr, "get8bpp-%d: %.4f\n", validate, dnow() - t2); + } +if (db24) d0 = dnow(); + +if (db24 > 1) fprintf(stderr, "bpp8to24 w=%d h=%d m=%p c=%p r=%p ncmaps=%d\n", w, h, main_fb, cmap8to24_fb, rfb_fb, ncmaps); + + /* + * now go back and transform and 8bpp regions to TrueColor in + * cmap8to24_fb. + */ + if (last_map_count && (ncmaps || depth <= 16)) { + int i, j; + int win[MAX_8BPP_WINDOWS]; + int did[MAX_8BPP_WINDOWS]; + int count = 0; + + /* + * first, grab all of the associated colormaps from the + * X server. Hopefully just 1 or 2... + */ + for (j=0; j 2) fprintf(stderr, "cmap %d %.4f\n", (int) cmaps[j], dnow() - d0); + } + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + sraRegionPtr reg = windows_8bpp[i].clip_region; + if (reg) { + rect = sraRgnCreateRect(x1, y1, x2, y2); + if (sraRgnAnd(rect, reg)) { + win[count] = i; + did[count++] = 0; + } + sraRgnDestroy(rect); + } + } + + if (count) { + + rect = sraRgnCreateRect(x1, y1, x2, y2); + /* try to apply lower windows first */ + for (k=0; k < stack_list_num; k++) { + Window swin = stack_list[k].win; + for (j=0; j 2) {for(i=0; i<256;i++) {fprintf(stderr, " cmap histo[%03d] %d\n", i, histo[i]);}} +} + +void mark_8bpp(int mode) { + int i, cnt = 0; + Window top = None; + + RAWFB_RET_VOID + + if (! cmap8to24 || !cmap8to24_fb) { + return; + } + + if (mode == MARK_8BPP_TOP) { + int k; + for (k = stack_list_num - 1; k >= 0; k--) { + Window swin = stack_list[k].win; + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + if (windows_8bpp[i].win == None) { + continue; + } + if (windows_8bpp[i].map_state != IsViewable) { + continue; + } + if (swin == windows_8bpp[i].top) { + top = swin; + break; + } + } + if (top != None) { + break; + } + } + } + + /* for each mapped 8bpp window, mark it changed: */ + + for (i=0; i < MAX_8BPP_WINDOWS; i++) { + int x1, y1, x2, y2, w, h, f = 32; + + f = 0; /* skip fuzz, may bring in other windows... */ + + if (windows_8bpp[i].win == None) { + continue; + } + if (mode == MARK_8BPP_TOP) { + if (windows_8bpp[i].top != top) { + continue; + } + } + if (windows_8bpp[i].map_state != IsViewable) { + XWindowAttributes attr; + int vw = 0; + + X_LOCK; + vw = valid_window(windows_8bpp[i].win, &attr, 1); + X_UNLOCK; + if (vw) { + if (attr.map_state != IsViewable) { + continue; + } + } else { + continue; + } + } + + x1 = windows_8bpp[i].x; + y1 = windows_8bpp[i].y; + w = windows_8bpp[i].w; + h = windows_8bpp[i].h; + + x2 = x1 + w; + y2 = y1 + h; + + if (mode == MARK_8BPP_POINTER) { + int b = 32; /* apply some fuzz for wm border */ + if (cursor_x < x1 - b || cursor_y < y1 - b) { + continue; + } + if (cursor_x > x2 + b || cursor_y > y2 + b) { + continue; + } + } + + /* apply fuzz f around each one; constrain to screen */ + x1 = nfix(x1 - f, dpy_x); + y1 = nfix(y1 - f, dpy_y); + x2 = nfix(x2 + f, dpy_x+1); + y2 = nfix(y2 + f, dpy_y+1); + +if (db24 > 1) fprintf(stderr, "mark_8bpp: 0x%lx %d %d %d %d\n", windows_8bpp[i].win, x1, y1, x2, y2); + + mark_rect_as_modified(x1, y1, x2, y2, 0); + cnt++; + } + if (cnt) { + /* push it to viewers if possible. */ + rfbPE(-1); + } +} + +#endif /* SKIP_8TO24 */ + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h new file mode 100755 index 0000000..d83412b --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/8to24.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_8TO24_H +#define _X11VNC_8TO24_H + +/* -- 8to24.h -- */ + +extern int multivis_count; +extern int multivis_24count; + +extern void check_for_multivis(void); +extern void bpp8to24(int, int, int, int); +extern void mark_8bpp(int); + +#endif /* _X11VNC_8TO24_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog new file mode 100755 index 0000000..5e9a59c --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/ChangeLog @@ -0,0 +1,1218 @@ +2010-05-08 Karl Runge + * x11vnc: set cd->unixname in apply_opts. Print message in + vnc_reflect_resize. Some tweaks to prepare_x11vnc_dist.sh + +2010-05-01 Karl Runge + * x11vnc: X11VNC_DISABLE_SSL_CLIENT_MODE option to disable SSL + client role in reverse connections. Improvements to logging in + ultravnc_repeater, ULTRAVNC_REPEATER_NO_RFB option. Increase + SSL timeout and print message if 'repeater' mode is detected for + reverse SSL connection. Fix RECORD scroll XCopyArea detection + with recent gtk/gdk library; set X11VNC_SCROLL_MUST_EQUAL + to disable. Limit logging of RECORD error messages. + +2010-04-25 Karl Runge + * x11vnc: incorporate new ultravnc_dsm_helper.c, add pointer_mask + remote control query. Cut openssl default -ping delay. + +2010-04-18 Karl Runge + * x11vnc/misc: improvements to demo scripts + * x11vnc: Alias -coe for -connect_or_exit. more accurate + dotted_ip() and -listen6. Improvements to ipv6 mode. + http interface for X11VNC_HTTP_LISTEN_LOCALHOST. Print + warning about missing Xvfb, Xdummy, or Xvnc in -create. + Fix __LINUX_VIDEODEV2_H / HAVE_V4L2. Always print out info + about Xinerama screens. + * x11vnc/misc/enhanced_tightvnc_viewer: check for host cmd. + fix stunnel mode w/o proxy. Update to stunnel 4.33, Fix + build.unix with new stunnel on Solaris. ipv6 support for + unix ssvncviewer + +2010-04-09 Karl Runge + * classes/ssl: debugging and workarounds for java viewer + * x11vnc/misc: sync ssvnc, improve util scripts. + * x11vnc: exit(1) for -connect_or_exit failure, quiet query + mode for grab_state, etc. ipv6 support. STUNNEL_LISTEN for + particular interface. -input_eagerly in addition to -allinput. + quiet Xinerama message. + +2010-03-20 Karl Runge + * classes/ssl: Many improvements to Java SSL applet, onetimekey + serverCert param, debugging printout, user dialogs, catch + socket exceptions, autodetect x11vnc for GET=1. + * x11vnc: misc/scripts: desktop.cgi, inet6to4, panner.pl. + X11VNC_HTTPS_DOWNLOAD_WAIT_TIME, -unixpw %xxx documented, and + can run user cmd in UNIXPW_CMD. FD_XDMCP_IF for create script, + autodetect dm on udp6 only. Queries: pointer_x, pointer_y, + pointer_same, pointer_root. Switch on -xkd if keysyms per key > + 4 in all cases. daemon mode improvements for connect_switch, + inet6to4, ultravnc_repeater.pl. Dynamic change of -clip do + not create new fb if WxH is unchanged. + +2010-02-22 Karl Runge + * classes/ssl: Java SSL applet viewer now works with certificate + chains. + * x11vnc: Printout option -sslScripts. Suggest -auth guess + in error message. Set fake_screen width and height. Test + for +kb in Xvfb. + +2010-01-02 Karl Runge + * x11vnc: small tweaks to Xdummy, rx11vnc*. Apply + SMALL_FOOTPRINT to -appshare text. Copyright year change. + +2009-12-29 Karl Runge + * x11vnc: rename -create_x to -create_xsrv. Hopefully + done fixing Xdummy. + +2009-12-28 Karl Runge + * x11vnc: Fix problems in --without-x builds. Fix crash + with -QD query for dbus info. Adjust window size for + small screens in -gui. Improve F1 help for xdm, etc. + include ssvnc 1.0.25 source. + +2009-12-24 Karl Runge + * x11vnc: prepare_x11vnc_dist.sh for 0.9.10. -xdummy_xvfb, + -svc_xdummy_xvfb and -create_x shorthand. lxde session. + Xdummy improvements and root no longer required. + +2009-12-21 Karl Runge + * x11vnc: -DENC_HAVE_OPENSSL=0 to disable enc.h but still + have ssl. Tweak ps command in find_display. Try to handle + AIX su. Ignore an initial newline at login: for -unixpw. + +2009-12-18 Karl Runge + * x11vnc: fix keycode and other remote control actions under + DIRECT: with an extra XFlush and other safety measures. + fflush(stderr) much in su_verify. Make the -unixpw env. vars + UNIXPW_DISABLE_SSL and UNIXPW_DISABLE_LOCALHOST work correctly. + Make -loopbg actually imply -bg. Add tag=... to unixpw opts + to set FD_TAG. Prefer Xvfb over Xdummy. Reduce wait time + for https. Add 'Login succeeded' output to unixpw panel. + +2009-12-15 Karl Runge + * x11vnc: X11VNC_REMOTE, X11VNC_TICKER, and VNC_CONNECT properties + names can be changed via env. vars (e.g. for multiple + x11vnc instances.) The -quiet option documented better. + Add fakebuttonevent remote control action. Improve child + test for connecting to port 113. Add connect_switch and + ultravnc_repeater.pl to CVS. Report X server number of mouse + buttons. Change find_display script to check for stale pids + in /tmp/.XNN-lock. If root under find_display, try FD_XDM + if previous failed to find auth. Print error reasons for + -storepasswd failures. + +2009-12-06 Karl Runge + * x11vnc: findauth/-auth guess works with FD_XDM=1 for root + finding dm's xauthority. Work around for GDM's recent + 'xhost SI:localuser:root' usage. X11VNC_REOPEN_SLEEP_MAX + for longer lived -reopen-ing. X11VNC_EXTRA_HTTPS_PARAMS for + additional URL parameters, X11VNC_HTTP_LISTEN_LOCALHOST=1 to + force libvncserver http to listen on localhost. + +2009-12-04 Karl Runge + * classes/ssl: update binaries; new signing key; ss_vncviewer. + * x11vnc: add more wish possibilities for -gui. Declare crypt() + on all platforms (disable with -DDO_NOT_DECLARE_CRYPT.) + +2009-12-02 Karl Runge + * x11vnc: -appshare mode for sharing an application windows of the + entire desktop. map port + 5500 in reverse connect. Add id_cmd + remote control functions for id (and other) windows. Allow zero + port in SSL reverse connections. Adjust delays between multiple + reverse connections; X11VNC_REVERSE_SLEEP_MAX env var. Add some + missing mutex locks; add INPUT_LOCK and threads_drop_input. + More safety in -threads mode for new framebuffer change. Fix + some stderr leaking in -inetd mode. + +2009-11-18 Karl Runge + * x11vnc: use -timeout setting for reverse connections too. + Delay calling xfixes at the beginning of 1st connection to avoid + display manager Xorg server crash. Delay selwin creation at the + begin 1st connection to avoid being killed by display manager. + Options -findauth and '-auth guess'. Export icon_mode query. + Do not open X display in -rawfb mode unless asked. Bugfix for + -sid/-id handling window offscreen or bigger than display. + Search for windows with _DBUS_SESSION_BUS_PID to decide which + dbus_launch is ours. Fix missing displays in FIND_DISPLAY + script. Add X11VNC_SKIP_DISPLAY_NEGATE. Improvements to + 'x11vnc Properties' gui dialog and connecting with x11vnc via + socket (client list.) X11VNC_SYSTEM_GREETER1 for previous text + font size. Fix bug with unixpw and vencrypt plain login. + Have fast fb read rate keep waitms and defer the same. + More heuristics to check try if GDM is still running (window + names gdm-*) + +2009-10-17 Karl Runge + * x11vnc: support for -solid option in xfce desktop. + List -Q guess_dbus query. Implement -showrfbauth option. + Workaround for inane X_ShmAttach incompatibility in Xorg. + +2009-10-08 Karl Runge + * x11vnc: bcx_xattach/x2x desktop switching facility. + More remote control features: grab_state, ping:mystring, + grablocal, resend_cutbuffer, resend_clipboard, resend_primary, + keycode, keysym, ptr, sleep, get_xprop, set_xprop, wininfo, + pointer_pos, mouse_xy, noop, guess_dbus Add DIRECT: for + remote control w/o server. X11VNC_NO_CHECK_PM for more + quiet DIRECT: usage. Options -query_retries, -remote_prefix, + and X11VNC_SYNC_TIMEOUT for remote control. Add scripting + to remote control. ping clients during in unixpw login. + Option -unixpw_system_greeter as shortcut to XDM/GDM/etc panel. + Add clear_all, viewonly, nodisplay, to unixpw username:opts. + F1 help for options (including smaller console font). + Document FD_TAG. Eat multiple property change events in one + sitting (also PROP_DBG=1). Support more -ssl features (special + cert names, single port, client certs, etc.) in -stunnel + external SSL helper mode. Reorganize openssl code to allow + integration with stunnel features if not compiled with openssl. + X11VNC_HTTPS_VS_VNC_TIMEOUT Fix dbus session address for -solid + in gnome. Use dbus-launch in -create mode if available. + X11VNC_SKIP_DISPLAY=all in -find/-create mode. let noxauth + unset XAUTHORITY for use with su - $USER. CREATE_DISPLAY_EXEC + debugging. Add x_terminal_emulator to -create cmd search. + Option -extra_fbur to tune fb update requests tracking; make + default tracking more aggressive. RATE_VERB/CHECK_RATE env. for + fbur rate. Env. vars to set Tk gui fonts. Catch closed + socket reads/writes. Try to detect 'crazy' xdamage insertion, + e.g. from some xscreensavers (needs work.). Don't switch + on server autorepeat if any keys are pressed down to work + around Xorg server and/or gnome bug. If PATH is empty, set + it to minimal one. Fix bug with -bg and -dp/-dk printout if + logfile present. + * classes/ssl: license statement. + +2009-06-18 Karl Runge + * classes/ssl: java viewer now handles auth-basic proxy logins. + * misc/enhanced_tightvnc_viewer: update ssvnc. + +2009-06-14 Karl Runge + * x11vnc: Add X11VNC_REFLECT_PASSWORD env. var. for -reflect mode. + Message to user about compiz problems suggesting -noxdamage. + Improvements to single-port detection and logging. + +2009-05-21 Karl Runge + * x11vnc: Thread safety improvements. Add 'OpenOffice' to special + case list for scroll detection. Fix -clip mode under -rawfb. + Workaround Xorg bug that yields infinitely repeating keys + when 'xset r off' action is done with keys pressed. Env. var + X11VNC_IDLE_TIMEOUT. + +2009-03-12 Karl Runge + * x11vnc: Fix off-screen bug for -ncache_cr copyrect. + +2009-03-07 Karl Runge + * x11vnc: allow range for X11VNC_SKIP_DISPLAY, document grab + Xserver issue. Add progress_client() to proceed more quickly + thru handshake. Improvements to turbovnc hack. + +2009-02-28 Karl Runge + * x11vnc: add kludge to experiment with turbovnc. + +2009-02-25 Karl Runge + * x11vnc: fix some -QD cases for use in tkx11vnc. + +2009-02-21 Karl Runge + * x11vnc: add -noskip_lockkeys option for future use. + +2009-02-03 Karl Runge + * x11vnc: Add "sendbell" remote cmd. Fix copyrect updates under + -reflect. Workaround that checks valid window of selection + requestor. Wait on some ssl helper pids earlier. Workaround + XAUTHLOCALHOSTNAME for some new usage modes. Set fake fb to + requested bpp with correct masks. -padgeom once:... mode. + Set LIBXCB_ALLOW_SLOPPY_LOCK by default. rfbRandomBytes earlier. + * classes/ssl: Update jars. Add "TOP_" dropdown customization to + ultravnc java viewer applet FTP panel. + +2009-01-11 Karl Runge + * classes/ssl: Add configurable Ultra java applet Filexfer Drives + drop down (e.g. ftpDropDown=Home.Desktop.bin). Document all + applet parameters in classes/ssl/README. + +2009-01-10 Karl Runge + * x11vnc: fix failure of -8to24 on default depth 24 due to + nonstandard indexed color support changes. Fix small window + for failure after XSendEvent selection call; add env var. + X11VNC_SENDEVENT_SYNC=1 to take even more care. + +2009-01-03 Karl Runge + * x11vnc: add -rmflag option, -rawfb vt support, bpp < 8 support + for rawfb, find /dev/video better. Fix reverse SSL connection + for DH. Some improvements for CUPS TS helper, restart if needed. + +2008-12-10 Karl Runge + * x11vnc: 0.9.6 release. Some strtok bugfixes. rename -tlsvnc + to -anontls. Disable ssl caching. No cert creation prompting + in inetd or bg modes. waitpid a bit more carefully on ssl + helpers. Tune ssl initial timeouts. Let -create user specify + starting X display. fix -rfbport prompt gui for older tk. + -sslonly option. Error if no -ssl with related options. -rand + option. -ssl implies -ssl SAVE + +2008-11-22 Karl Runge + * x11vnc: x11vnc.desktop file. -reopen, -dhparams, -sslCRL, + -setdefer options. -rfbport PROMPT VeNCrypt and TLSVNC SSL/TLS + encryption support. Tweaks to choose_delay() algorithm. + -ssl ANON anonymouse Diffie-Hellman mode. Fix bugs in certs + management. Additions to tray=setpass naive user mode. + +2008-11-09 Karl Runge + * x11vnc: add zeroconf external helpers (avahi-publish and + dns-sd). Alias -zeroconf. Close pipeinput_fh on exit. + Kludge to make -solid work on MacOSX console. Attempt at + cpp macros to disable newer libvncserver interfaces. + +2008-10-29 Karl Runge + * x11vnc: -http_oneport for single port HTTP and VNC. + Improve find_display wrt lsof blocking with -b. + +2008-10-19 Karl Runge + * x11vnc: -chatwindow for chat window on X console using SSVNC + as a helper. Print suggestion for X_ShmAttach failure. + Allow -scale WxH for different X- and Y-scaling factors. + Workaround for missing -enc cipher EVP_aes_256_cfb. Modify + message digest and salt/IV parameters. Try to improve compile + time by breaking up large if blocks. + +2008-09-21 Karl Runge + * x11vnc: Add symmetric key encryption -enc cipher:keyfile, + works with SSVNC. Make -remap work on MacOSX console. + update to 0.9.5 strings. Add a couple menu items to tkx11vnc. + +2008-09-17 Karl Runge + * x11vnc: make -allow work in -ssl mode. + +2008-09-14 Karl Runge + * x11vnc: -sleepin m-n for random sleep. More mktemp and mkstemp + protections. SSL_INIT_TIMEOUT=n env. var. Fix macosx console + X call bug. Synchronize other projects sources. + +2008-09-06 Karl Runge + * x11vnc: kill gui_pid on exit in -connect/-connect_or_exit mode. + -grablocal n experiment (not compiled by default). -macuskbd + option for macosx for orig uskdb code. keycode=N remote contol + cmd. Find dpy look at non-NFS cookies in /tmp. Fix gui tray + insertion on recent gnome dt. Fix connect_file bug. Sync SSVNC + +2008-06-07 Karl Runge + * x11vnc: -clip xineramaN option, -DIGNORE_GETSPNAM for HP-UX. + Print info on SSH_CONNECTION override. + +2008-05-31 Karl Runge + * x11vnc: Improvements to nonstandard indexed color support, e.g. + depths 1, 4, 12, etc. instead of only 8. Only enable xinerama + xwarppointer if there is more than 1 subscreen. + +2008-05-07 Karl Runge + * x11vnc: add UltraVNC repeater proxy support. fix to setp gui + mode. -threads is now strongly discouraged. Read PORT= in url. + User can set nolisten for Xvfb in -create mode. clean up + wait_for_client() to some degree. + +2008-01-31 Karl Runge + * x11vnc: during speeds estimate, guard against client + disconnecting. ssvnc sync. + +2008-01-14 Karl Runge + * x11vnc: -ping option, fix memory corruption in copy_tiles + after xrandr resize. + +2007-12-16 Karl Runge + * x11vnc: setup remote-ctrl file by default on macosx. improve + tkx11vnc wrt attaching to existing server in icon/tray mode. + +2007-12-15 Karl Runge + * x11vnc: fix find_display and usleep() prototype on macosx. + -display console and check DISPLAY /tmp/...:0 on macosx. + implement -noxinerama. + +2007-11-12 Karl Runge + * x11vnc: add clear_locks (Caps_Lock, etc) action. Fix + ssh tunnel on Darwin. + +2007-10-27 Karl Runge + * x11vnc: fix ncache bug and others under -8to24, -ssh + option, socks and other proxies in -proxy option. + compiler warnings. fix TARGETS selection request bug + (java, konsole). + +2007-10-03 Karl Runge + * x11vnc: add xfce to createdisplay + +2007-09-26 Karl Runge + * x11vnc: COLUMNS=256 to find/create scripts. More ratecheck. + +2007-09-14 Karl Runge + * x11vnc: Add -sshxdmsvc. Fix find_display for inetd. Improve + -allinput method; env CHECK_RATE to watch for FBUR build up + (i.e. JFVNC). + +2007-09-11 Karl Runge + * x11vnc: fix wireframe crash under -clip. Add -redirect for + VNC redir. -rawfb nullbig, randbig, solid, swirl, etc. + FD_XDM mode to find_display. -listdpy. Add enlightenment. + Xvnc.redirect FINDDISPLAY-vnc_redirect. -xvnc, -xvnc_redirect, + -svc_xvnc. AUTO_PORT. + * ssvnc: sshvnc ssh-only, tsvnc Terminal Services modes. + Improvements to ss_vncviewer. Automatically find X dpy and + X login. Reorganize menus a bit. ~/.ssvncrc file. + +2007-09-04 Karl Runge + * x11vnc: Add -autoport and -finddpy utils. -xdummy creation. + tweak xkb tiebreaking again. Shut off -ncache in dev mode. + watch for xrandr events even if no -xrandr. Tips for types + of URLs for java viewers. Add check_redir_services() to + create_display and tsdo() redir helper utility (-tsd). + Improvements to Xdummy. Prevent dcop XAUTHORITY='' + +2007-08-19 Karl Runge + * x11vnc: better -xkb tie-breaking for up keystrokes. Add + Xsrv/FD_XSRV custom server to FINDCREATEDISPLAY list. + +2007-08-18 Karl Runge + * x11vnc: improve FINDCREATEDISPLAY (-create) script. Document + FD_GEOM, FD_SESS, FD_OPTS, FD_PROG env vars, add Xvnc support. + +2007-08-15 Karl Runge + * x11vnc: add reverse -connect support to -display WAIT: + i.e. -find, -create, -svc, ... mode. Document need for + -shared under -connect host1,host2,... Fix bug in -display + WAIT: mode if vnc client tries to only retrieve SSL cert. + +2007-08-03 Karl Runge + * x11vnc: add -xrefresh option, fix KDE .DCOPserver parse bug, + make sure UNIXPW_DISABLE_LOCALHOST/-unixpw_unsafe ignore + any SSH tunnel that would imply -localhost. + +2007-07-04 Karl Runge + * x11vnc: -debug_ncache, fix big fonts in tkx11vnc. + +2007-06-14 Karl Runge + * x11vnc: add detectors if ultravnc chat or file xfer took place, + if so ping clients more frequently. Fix compile bug if libssl + not available. + * ssvnc: add ultravnc ftp jar feature. Add certificate management + "Verify All Certs". + +2007-05-26 Karl Runge + * x11vnc: set to version 0.9.2, back to NCACHE -12 for testing. + in -unixpw, initial Escape means no echo username (see ssvnc). + +2007-05-21 Karl Runge + * x11vnc: set things up (NCACHE = -1) to not have -ncache + on by default; just give a blurb about it. + +2007-05-16 Karl Runge + * x11vnc: print out peer host and port for debugging SSL. + * ssvnc: rand check, SOCKS support, PORT=, Verify all Certs + and accepted certs logging. + +2007-05-06 Karl Runge + * x11vnc: lower -wait and -defer to 20ms. Change some SSL + debug output. Drop client doing ultravnc stuff in -unixpw + during login phase. + +2007-05-05 Karl Runge + * x11vnc: add groups handling for -users mode. + +2007-05-01 Karl Runge + * ssl: update to java viewer and utility scripts (add onetimekey). + * x11vnc: setsid() for -gone mode. setpgrp for -create script and + add -cc 4 to avoid DirectColor. + +2007-04-28 Karl Runge + * x11vnc: -users sslpeer= option. RFB_SSL_CLIENT_CERT var. + X11VNC_FINDDISPLAY_ALWAYS_FAILS var. -ncache default 10. + gid switch fix. + * ssvnc: Linux.i*86 fix and code sync. + +2007-04-07 Karl Runge + * x11vnc: add gnome, kde, etc. FINDCREATEDISPLAY tags. + In check_ncache periodically check for changed desktop. + +2007-03-24 Karl Runge + * x11vnc: reverse SSL connections. -sleepin option. + +2007-03-20 Karl Runge + * x11vnc: Add -httpsredir option for router port redirs. + set Xcursor bg/fg color values to zero. Env var to + force timeout: X11VNC_HTTPS_VS_VNC_TIMEOUT. Let user + supply nc=N at login prompt. Disable -ncache beta + test under -http/-httpdir. + +2007-03-13 Karl Runge + * x11vnc: fix crash for kde dcop. limit ncache beta + tester to 96MB viewers. + +2007-02-18 Karl Runge + * x11vnc: Get ultravnc textchat working with ssvnc. + +2007-02-16 Karl Runge + * x11vnc: add Files mode to user controlled input. more + ultra/tight filexfer tweaks. rfbversion remote control. + noncache/nc unixpw user opt. + +2007-02-15 Karl Runge + * x11vnc: tightvnc filetransfer off by default. avahi + fixes. FINDCREATEDISPLAY geometry. -noultraext. + +2007-02-12 Karl Runge + * x11vnc: add avahi (aka mDNS/Zeroconf/Bonjour...) + support thanks to Diego Pettenò. -avahi/-mdns. + Add -find and -create FINDISPLAY aliases. + +2007-02-11 Karl Runge + * x11vnc: add -grabalways, -forcedpms, -clientdpms, and + -noserverdpms (ultravnc viewer) for improvements in + the still approximate server locking. Add -loopbg + and -svc, -xdmsvc aliases. Bug fix create_display. + +2007-02-10 Karl Runge + * x11vnc: watch things like textchat, etc. more carefully + in unixpw state. Monitor broken XDAMAGE reports when + OpenGL apps like beryl are running. Implement simple + kbdReleaseAllKeys, setSingleWindow, setServerInput actions + (ultravnc extentions). Try to send XDM the username in + FINDCREATEDISPLAY, also try .dmrc before .xsession. + +2007-01-31 Karl Runge + * x11vnc: -reflect reflector/repeater mode with libvncclient. + -ncache tweaks: no kde animations and wm improvements, + fixes to FINDDISPLAY and FINDCREATEDISPLAY login modes, + MODTWEAK_LOWEST envvar for HP-UX keyboard workaround. + -N option for display and rfbport matching. + +2007-01-12 Karl Runge + * x11vnc: -N option, more -ncache improvements, kde/gnome. + +2007-01-03 Karl Runge + * x11vnc: more -ncache improvements. + +2007-01-01 Karl Runge + * x11vnc: more -ncache improvements. + +2006-12-28 Karl Runge + * x11vnc: more work on -ncache, add macosx support, fix X errors + and improve cache expiration algorithm. + +2006-12-17 Karl Runge + * x11vnc: first pass at client-side caching, -ncache option. + have -http guess ../classes/.. to run out of build area. + +2006-12-17 Karl Runge + * x11vnc: make -xwarppointer the default if xinerama is active. + +2006-12-09 Karl Runge + * java SSL viewer: guard against empty urlPrefix + * x11vnc: FINDCREATEDISPLAY support to create X session if + one cannot be found. close fds utility. Print VNC Viewer + is.. for find display mode. chvt(1) utility. + +2006-11-23 Karl Runge + * prepare_x11vnc_dist.sh: make ss_vncviewer installed 755. + * x11vnc: for HTTPONCE open new http port in -inetd mode. + -prog option to indicate full path to program (not know + when in -inetd and tcpd) + +2006-11-21 Karl Runge + * x11vnc: macosx: problem with padded framebuffer rows, wait for + user to switch back, CutText xfer support, ignore a few more + types of toplevels. Add local user wireframing. -dpms/-nodpms + option to work around kdesktop_lock problem. + +2006-11-13 Karl Runge + * x11vnc: Native Mac OS X support. + +2006-11-07 Karl Runge + * ssl_vncviewer: vnc:// direct connect, add -x to ssh, + SSL_VNC_LISTEN variable for direct proxy. + +2006-10-29 Karl Runge + * x11vnc: Add tip about how to reenable RECORD extension. + +2006-10-11 Karl Runge + * x11vnc: -cursor_drag for DnD, etc. + +2006-09-23 Karl Runge + * Java viewer: improvements to connection response, faster + connections. + * x11vnc: some cleanup for -unixpw login process. + +2006-09-20 Karl Runge + * x11vnc: -unixpw_cmd, -passwfile cmd:/custom:, -sslnofail, + -ultrafilexfer + +2006-09-17 Karl Runge + * x11vnc: move some info printout to -v, -verbose mode. Add + -connect_or_exit option. Have -rfbport 0 lead to no TCP + listening. Eliminate double certificates in .pem files. + Always print SSL certificate to the screen to aid pasting. + +2006-09-15 Karl Runge + * x11vnc: allow user set signals to ignore, clear DISPLAY in + -unixpw su_verify. -rawfb none same as null. + * rfbserver.c: shorten rfbEncodingNewFBSize message. + +2006-09-13 Karl Runge + * x11vnc: document 'ssh -t' improved keyboard response. add + extra rfbPE() around keystrokes. + misc/enhanced_tightvnc_viewer: incorporate scripts, documentation, + etc. for the enhanced tightvnc viewer package. + +2006-09-10 Karl Runge + * x11vnc: minor changes: REQ_ARGS for -sslGenCert, EV_SYN + SYN_REPORT check restore cursor most under -display WAIT. + +2006-08-10 Karl Runge + * x11vnc: first pass at touchscreens via uinput. + +2006-08-02 Karl Runge + * x11vnc: add -ssltimeout option; tweak ssl timeouts. + +2006-07-28 Karl Runge + * ssl_vncviewer: remove some bashisms, add features. + * x11vnc: -rotate option (e.g. handheld), fix FPE on tru64. + +2006-07-17 Karl Runge + * x11vnc: enable --without-x builds for -rawfb only (NO_X11) + +2006-07-11 Karl Runge + * x11vnc: more tweaks to UINPUT, mostly mouse motion. + +2006-07-08 Karl Runge + * x11vnc: add uinput support (-pipeinput UINPUT:...) for full + mouse and key input to linux console (e.g. for qt-embedded apps) + add -allinput for handleEventsEagerly. + +2006-07-04 Karl Runge + * x11vnc: 2nd -accept popup with WAIT, and UNIX: info for unixpw + login. Use RFB_CLIENT_ON_HOLD for -unixpw. -unixpw white arrow + -license option. Use getspnam if getpwnam is short. + abbrevs sc=, cm, ck for user:opts. + +2006-06-23 Karl Runge + * x11vnc: misc cleanup. + +2006-06-18 Karl Runge + * x11vnc: -grabkbd, -grabptr, -env options. under -unixpw + + WAIT let user add some options after his username (e.g. runge:3/4) + -allowedcmds to fine tune vs. -nocmds. general cleanup. + +2006-06-12 Karl Runge + * x11vnc: word tune SSL Java viewer; fix multi-certs bug. Add + -display WAIT:cmd=FINDDISPLAY builtin script and cmd=HTTPONCE + action. -http_ssl option for ssl subdir only. Add -rawfb RAND + test case. improve raw_xfer() for use in inetd https transfer. + fix bug SSH + -unixpw -> -localhost. fix bug setup cursors + in WAIT mode. Mac OS X pty tweak. + +2006-06-09 Karl Runge + * x11vnc: make -display WAIT + -unixpw work on Solaris. + +2006-06-08 Karl Runge + * x11vnc: XOpenDisplay wrapper for raw xauth data, -unixpw + su_verify() to run any cmd, -users unixpw= mode. -display WAIT:... + modes for delayed X display opening and dynamic choosing. + +2006-06-03 Karl Runge + * x11vnc: -capslock and -skip_lockkeys options. map some Alt keys + to Latin under linuxfb. switch to new stats API. Handle more + cases carefully when switching fb. + +2006-05-06 Karl Runge + * x11vnc: improved support for webcams and tv tuners with + video4linux /dev/video: -rawfb video, -freqtab etc. + Convenience option for linux VT's: -rawfb cons (LinuxVNC + method). -pipeinput builtins for video and console. + -24to32 option to avoid 24bpp problems. "snap:" method for + -rawfb. + +2006-04-26 Karl Runge + * x11vnc: skip exit in check_openssl() if not compiled with + libssl. set SKIP_HELP (again) in small footprint builds. + +2006-04-16 Karl Runge + * x11vnc: More web proxy work for Java SSL applet and wrapper + script ssl_vncviewer. Apache SSL gateway support for + incoming x11vnc connections. Handle "double proxy" case. + +2006-04-05 Karl Runge + * x11vnc: add FBPM support (-fbpm) for Suns. -rawfb ZERO for + testing. Basic key+cert management utilities: -sslGenCA, + -sslGenCert, -sslEncKey, -sslDelCert, -sslCertInfo, and + addln features. SSL proxy connection. -storepasswd with + no args or pw echo. + +2006-03-26 Karl Runge + * x11vnc: -xinerama now on by default. In -ssl mode accept https + applet downloads thru VNC port. -https option for 2nd https + port. Look for classes/ssl under -http. add Java URL messages + to final output lines. make -inetd work with -ssl (even for + https). fix -unixpw login prompt under -scale. guard against + clientData = NULL. + +2006-03-11 Karl Runge + * x11vnc: add -ssl mode using libssl. Include Xdummy in misc. + a few more macros for smallerfoot, etc. + +2006-03-08 Karl Runge + * x11vnc: manage CLIPBOARD in addition to PRIMARY. -debug_sel + Make reverse connections require passwords. -usepw option. + -storepasswd w/o args prompts and writes ~/.vnc/passwd. + +2006-03-06 Karl Runge + * x11vnc: switch remote control to X11VNC_REMOTE property. Put + in -unixpw constraints for reverse connections under -inetd. + -inetd won't quit when reverse conn client leaves. Allow keyboard + input for viewonly -unixpw logins. "%*" utils for testing + -unixpw. improve start time fix bugs, small screen in gui. + +2006-03-04 Karl Runge + * x11vnc: -unixpw on *bsd, hpux and tru64. Add -unixpw_nis for + non-shadow systems. check stunnel dying. check SSH_CONNECTION + in -unixpw. gui icon tweaks, unix username. + +2006-03-02 Karl Runge + * x11vnc: more tweaks to -unixpw mode. Add -gone popup mode. + Change filexfer via -R. Tune SMALL_FOOTPRINT. gui fixes. + +2006-02-24 Karl Runge + * x11vnc: -unixpw for Unix password auth, -stunnel to setup + stunnel(1) for an SSL tunnel on the server end. Add clipboard + input to per-client input controls. + +2006-02-20 Karl Runge + * x11vnc: add SIGINT SIGQUIT handling for run_user_command(), + set some signal handlers to SIG_DLF for forked children, + put a timeout on port 113 connection to viewer machine. + +2006-02-06 Karl Runge + * x11vnc: fix AIX build wrt h_errno. + +2006-02-06 Karl Runge + * x11vnc: -8to24 more speedups; tunables for very slow machines. + +2006-02-04 Karl Runge + * x11vnc: -8to24 speedups and improvements. + +2006-01-21 Karl Runge + * x11vnc: -8to24 opts, use XGetSubImage. fix -threads deadlocks and + -rawfb crash. + +2006-01-18 Karl Runge + * x11vnc: -8to24 now works on default depth 8 screens. + +2006-01-16 Karl Runge + * x11vnc: more tweaks to -8to24, add XGETIMAGE_8TO24 mode to call + XGetImage() on the 8bpp regions. + +2006-01-14 Karl Runge + * x11vnc: add -8to24 option for some multi-depth displays (but use + of -overlay is preferred if supported). + +2006-01-12 Karl Runge + * fix -DSMALL_FOOTPRINT=N builds. + +2006-01-11 Karl Runge + * x11vnc: close fd > 2 in run_user_command(), -nocmds in crash_debug, + fix 64bit bug for -solid. + +2006-01-08 Karl Runge + * x11vnc: the big split. opts: -afteraccept and -passwdfile read: + +2005-12-24 Karl Runge + * x11vnc: enhance -passwdfile features, filetransfer on by default, + call rfbRegisterTightVNCFileTransferExtension() earlier. + +2005-11-28 Karl Runge + * x11vnc: add -loop option. + +2005-11-25 Karl Runge + * x11vnc: throttle load if fb update requests not taking place. + * misc/x11vnc_pw: add utility script + +2005-10-22 Karl Runge + * add tightVNC FileTransfer (-filexfer) and -DFILEXFER=1 + * -slow_fb for special purpose infrequent polling. + * make -blackout work with copyrect clipping. + * -blackout noptr,WxH+X+Y,... to prevent pointer from going + into a blacked out region. + +2005-07-17 Karl Runge + * more improvements to gui UE. gui requests via client_sock + PASSWD_REQUIRED and PASSWD_UNLESS_NOPW build options. + +2005-07-12 Karl Runge + * gui: remove nevershared etc., parse cmd line, bug fixes. + * x11vnc: fix pointer queue buildup under -viewonly. + +2005-07-10 Karl Runge + * more improvements to gui, default values, save-settings.. + * x11vnc scary password warnings. Release settings. -QD option. + add \# to rc files and fix rcfile read bug. + +2005-07-09 Karl Runge + * add -grab_buster helper thread to break up grabs (might not be + need any longer due to gett XFlush-ing). Fix scrolls and + copyrect for -clip and -id cases. + +2005-07-06 Karl Runge + * many improvements to the gui. now embeds into system tray ok. + x11vnc -debug_grabs, -printgui, -nosync + +2005-07-01 Karl Runge + * support for simple "-gui tray" mode (small icon like the original + x0rfbserver had). Can't figure how to get a tray to swallow it.. + * passwd, viewpasswd changing in tray mode. + * allow typos like: x11vnc -R -scale 3/4 + +2005-06-26 Karl Runge + * track keycode state for heuristics, -sloppy_keys, -wmdt + * add -nodbg as option + +2005-06-21 Karl Runge + * reinstate "bad desktop" for wireframe. + * extra long info and tips of XOpenDisplay fails. + +2005-06-18 Karl Runge + * clean up some malloc/free problems (don't free the current cursor) + * set DISPLAY before calling gconf, dcop under -solid + * -inetd -q and no -o logfile implies closing stderr. + +2005-06-14 Karl Runge + * -DNOGUI and -DVIEWONLY build options + * -noskip_dups the default (windows viewer sends no ups when + repeating) + * HAVE_SOLARIS_XREADSCREEN and HAVE_IRIX_XREADDISPLAY + * Alt+Button+Motion to wireframe. tunable in WIREFRAME_PARMS + * copyrect now the default under -scale (works OK, but must + send a cleanup update) + * fix -pedantic and Sun cc warnings and errors (unsigned, etc..) + * print out fatal error messages under -quiet + * -seldir to control and debug selection transfers. + * fix crashes on 64bit wrt unsigned long in rich cursors. + * fix kde guessing errors + * more scrolling and wireframe tweaks. + +2005-06-03 Karl Runge + * make scrollcopyrect more or less usable under -scale + * add -fixscreen for periodic cleanup of painting errors. + * adjust keyrepeat scroll behavior. + +2005-05-30 Karl Runge + * alter "magic cleanup key sequences" (N*Alt_L and N*Super_L) + * dial down check_xrecord_reset() reset times. + +2005-05-24 Karl Runge + * more -scrollcopyrect: GrabServer detection, autorepeat throttling, + hack to clean screen 3,4,5 Alt_L in a row, mouse wheel detect. + * fix bug wrt switching to single_copytile, add Darwin to shm limit. + +2005-05-17 Karl Runge + * more -scrollcopyrect, -scr_term hacks for terminals. + * -wait_ui, -nowait_bog tunables. push cursor sooner. + +2005-05-14 Karl Runge + * much more work on "-scrollcopyrect" mode... getting usable. + * remove -pointer_mode 3, shift everyone back down + * -dbg "crash shell" for debugging + * -add_keysyms now the default, periodically clears if needed. + * try to autodetect if -xkb would be a good idea. + * improve keycode guessing for -xkb mode (force ISO_Level3_Shift) + * -remap DEAD, etc. for dead/mute keys remappings. + +2005-05-02 Karl Runge + * initial support for using RECORD to detect some types of window + scrolls. This is "-scrollcopyrect" mode, use -noscrollcopyrect + to disable. Much tuning and painting error repair still required. + * more build time customizations: REMOTE_DEFAULT, REMOTE_CONTROL, + EXTERNAL_COMMANDS, NOREPEAT, WIREFRAME*, SCROLL*, ... + * added bandwidth and latency measurements. + * added XListHosts to -privremote check. + * debug_* remote-control variables. + * removed OLD_TREE stuff. + +2005-04-19 Karl Runge + * somewhat safer remote-control defaults, and addnl options for + more safe operation: -privremote, -safer, -nocmds, -unsafe + * -wireframe, -wirecopyrect: instead of having user look at a + slowly moving, lurching window, guess when a window is being + moved/resized and just show a wireframe. -wirecopyrect means to + apply rfbDoCopyRegion to the detected move as well. + * debugging switches for X events and X damage: debug_xevents + debug_xdamage. + * -rawfb bugfixes. -noviewonly hack to still send UI to X. + +2005-04-11 Karl Runge + * fix -clip under -rawfb, fix offset bug under file lseeking. + * add -rawfb setup:cmd mode to initialize fb. example: misc/ranfb.pl + +2005-04-10 Karl Runge + * -rawfb non X-polling (i.e. shm, mmap, lseek). + * -pipeinput enable external user input processing command. + * -xtrap use XESimulateXEventRequest to inject user input. + * scaling blend for StaticGray, add :fb scaling option. + * default password macros. + * improve -norepeat use under -viewonly. + * -flag flagfile to aid wrapper scripts. + * add utility scripts, etc. dir ./misc + +2005-04-03 Karl Runge + * try DEC-XTRAP on X11R5 if XTestGrabControl is missing. + * -shiftcmap n, for 8bpp displays using < 256 color cells + and with pixel values shifted from zero. + * fix DAMAGE event leak after viewers disconnect. + * -http option to try to guess where the java viewer is. + +2005-03-29 Karl Runge + * build-time customizations X11VNC_SHARED, X11VNC_FOREVER, + REMOTE_CONTROL, SMALL_FOOTPRINT for CPPFLAGS + * fix event leaks for xkb BellNotify and ClientMessage and others, + esp. under -nofb. make nofb work with remote control. + * -nolookup for bad DNS setups. + * more playing with pointer_mode: check_user_input3() + +2005-03-19 Karl Runge + * scale cursors along with display. Use -scale_cursor to change + or disable cursor scaling. + * speed up scaling in some cases, :nb and integer magnification. + * provide alternative arrow cursors (1-6) via -arrow n. + * reset no autorepeat a couple times if something turns it off, + set with -norepeat N. + * do not take a nap if DAMAGE seems to be doing its job. + +2005-03-12 Karl Runge + * support for the X DAMAGE extension to receive damage + rectangle reports from the X server. On by default, disable + with -noxdamage. Currently only trusts small rects + (but see -xd_area n) and uses the rest as "hints" for the + scanline polling. + * -clip WxH+X+Y to show a clipped sub-region of the screen. + * use RFC 1413 (identd) to attach a name to a client in + friendly environments. + * fix XAUTHORITY wrt '-auth ... -gui other:0'. + +2005-03-04 Karl Runge + * add changes to couple with -listen option, in particular + the behavior of -localhost and remote control cmds. + * workarounds for old trees. + +2005-02-23 Karl Runge + * final changes for 0.7.1 release. + +2005-02-21 Karl Runge + * -nap is now the default, disable with -nonap + * set version to 0.7.1, word tune -help, etc. + +2005-02-14 Karl Runge + * cleanup -users stuff, add "lurk=" mode + * support cde in -solid + * simple gui mode for beginners, -gui ez,... + +2005-02-10 Karl Runge + * Add -input to fine tune client input (keystroke, mouse motion, + and button presses). Allow per-client setting via remote cntl. + * fix bug in get_remote_port, add ip2host for client info. + +2005-02-09 Karl Runge + * Add -users switch user mechanism and related utilities. + * fix -solid for gnome and kde. + * exit earlier on trapped XIO errors. + +2005-02-05 Karl Runge + * -solid solid color background when clients are connected. + * -opts/-? to show option names only. + +2005-01-23 Karl Runge + * sync with new draw cursor mechanism, keep old way in OLD_TREE. + * add -timeout option, change -alphablend to be default + * -R norepeat now forces the issue (Xsession may turn it back on). + * try :0 if no other info. + +2005-01-15 Karl Runge + * adjust alpha blending parameters, -alphablend, handle 24bpp. + * add -snapfb snapshot fb, not clear how useful it is.. + * more functions etc for -pointer_mode 4, still not finished. + * scan_for_updates() "count only" mode. + * increase max shm size on Linux. + * -oa -logappend, -pm, -speeds + * fix bugs in -allow, -R connect, screen == NULL + +2004-12-27 Karl Runge + * allow -DLIBVNCSERVER_HAVE_FOO=0 override everything + * get_xfixes_cursor() try to more carefully convert alpha channel + to opaque pixel. Options -alphacut, -alphafrac, -alpharemove + * more commands under remote control: rfbwait, rfbport, http, + httpport, httpdir, enablehttpproxy, desktop, alwaysshared, + dontdisconnect. Add to tkx11vnc. + +2004-12-22 Karl Runge + * final polishing for 0.7 release, tkx11vnc tweaks + * more careful rfbPE in pick_window, start check_user_input4() + +2004-12-19 Karl Runge + * cleanup putenv, snprint, other string manip. + * add -sync mode to remote control for better control + * allow -remote and -query at same time. + +2004-12-16 Karl Runge + * support for XFIXES extension to show the exact cursor shape, + working on Linux/Xorg and Solaris 10. disable with -noxfixes + * remote control mania - nearly everything can be changed dynamically! + see the -remote/-query (aka -R/-Q) options. e.g. -R scale:5/6 + * simple gui tkx11vnc based on the remote control mechanism, see -gui + * support for XRANDR extension, if the X screen changes size (see + xrandr(1)), x11vnc will resize the fb. Pays to have NewFBSize viewer + * -overlay support on IRIX with XReadDisplay (not tested). + * RFB_MODE is set to "accept" or "gone" in environment + * "-id pick" will let you pick the window (calls xwininfo(1)...) + * "-pointer_mode n" replaces -old_pointer (n=1) and -old_pointer2 (n=2) + a new mode n=3 is added (similary to nodragging, but dynamic). + * "-sb n" screen blank timeout option is now documented. + * renamed NON_CVS to OLD_TREE + +2004-08-31 Karl Runge + * new check_user_input() pointer input algorithm, it tries to avoid + extra-draws. still needs tuning, get previous one with -old_pointer2 + * add NON_CVS macro for building in older CVS trees. + +2004-08-29 Karl Runge + * remove old mouse patch code, now use rfbSetCursor (+ workarounds) + * changed cursor shape options (no more -mouse, ...) to '-cursor mode' + where 'mode' can be empty "X", "some", or "most". "some" adds + heuristics for two more cursors. + * -nocursorshape added. + * ifdef checks for XSHM and XTEST. Add *_wr wrappers as well. + * -vncconnect is now the default. + +2004-08-15 Karl Runge + * -overlay option to fix color problems on Sun machines with 8+24 + and 24+8 overlay visuals, uses Solaris XReadScreen(). + * expose -sid option (shifted -id windowid) to allow explicit + wrapping of XGetImage, etc for -overlay + * fix misc bugs: missing var types, hardwired blackouts sizes, + subwin desktop name crash. + +2004-08-03 Karl Runge + * add man page x11vnc.1 autogenerated from x11vnc -help; tweak + help output a little bit. Adjust autoconf to pick up manpage. + * add README from website docs. + * zero watch_bell and use_xkb_modtweak if no XKEYBOARD + +2004-07-31 Karl Runge + * -cursorpos now the default; make cursorpos work when scaling + * fix bug with multiple adds of the same keysym for -add_keysyms + * rewhack -help output again + * adjust version number and output. + +2004-07-28 Karl Runge + * -add_keysyms dynamically add missing keysyms to X server + +2004-07-26 Karl Runge + * first pass at doing modtweak via XKEYBOARD extension (-xkb) + * -skip_keycodes option for use with -xkb + * reset modtweak and xkb_modtweak on event MappingNotify. + * trap Xerror during XSendEvent/XChangeProperty. + * fix bug requesting PRIMARY way too often. + * more careful to check if XKeysymToString returns NULL. + * continuation lines "\" in x11vncrc. + * undoc'd expts: -isolevel3, -xkbcompat + +2004-07-19 Karl Runge + * ignore keysyms 5-8 for keycode keymapping. + * help to stdout for easy paging, add lastmod to help and -version. + +2004-07-15 Karl Runge + * make "modtweak" the default, disable with -nomodtweak. this + corrects ghost "< >" key on pc104 us in XFree86. + * fix bug wrt no got_keyboard_input under modtweak + +2004-07-10 Karl Runge + * -norepeat to turn off X server autorepeat when clients exist, + (this is workaround for the repeating keystroke bug. Note that + client side does autorepeating so not a big loss). + +2004-07-04 Karl Runge + * extend -allow to re-read a file with allowed IP addresses. + * improvements to -help text. + +2004-07-01 Karl Runge + * improve scaled grid calculation to prevent drift (which causes + drift in pixel weights and poorer tightvnc compression) + * add ":pad" scale option, detect small fraction scale = m/n. + +2004-06-28 Karl Runge + * round scaled width to multiple of 4 to make vncviewer happy. + * allow override of above ":n4" and allow 4 point interpolation + to be used even with shrinking ":in". + +2004-06-27 Karl Runge + * speed up scaling a bit for slow machines (still all floating point) + * add no blending option (-scale fraction:nb) + +2004-06-26 Karl Runge + * add -scale fract for global (not per-client) server-side scaling + working more or less OK, needs to be optimized at some point. + * remove -hints/-nohints options. + +2004-06-17 Karl Runge + * simple ~/.x11vncrc config file support, -rc, -norc + +2004-06-12 Karl Runge + * add -clear_mods -clear_keys for (rare) case where keys are + not being released (e.g. Ctrl-C x11vnc thru x11vnc). + * export RFB_SERVER_IP and RFB_SERVER_PORT to -accept program + so that the tcp 4-tuple is completely specified. + * add -storepasswd so storepasswd program not needed + +2004-06-05 Karl Runge + * rearrange file for easier maintenance, indicating file breakup. + * add RFB_CLIENT_COUNT, number of other connected clients to + -accept and -gone commands. + +2004-05-27 Karl Runge + * add view-only passwd via -viewpasswd and 2nd line of -passwdfile + +2004-05-21 Karl Runge + * -accept: add view-only decision and other improvements. + * add -gone command option for when a client leaves. + Thanks to Jesus Alvarez for these ideas. + * -passwdfile to keep passwd off of cmd line. + * -o logfile send stderr to a logfile. + +2004-05-14 Karl Runge + * improvements to -accept popup: yes/no buttons and timeout. + * less fprintf under -q so '-q -inetd' has no stderr output. + +2004-05-08 Karl Runge + * add -accept some-command/xmessage/popup to prompt local X11 user + or otherwise decide to accept an incoming client. + * clean up -Wall warnings. + +2004-05-05 Karl Runge + * enable mouse button -> keystrokes mapping in -buttonmap (mousewheel) + * enable keystroke -> mouse button mapping in -remap (touchpad paste) + (-remap incompat ':' -> '-', sorry...) + * shm OS blacklist (i.e. <= SunOS 5.8) -> -onetile + * revert to check_user_input() under -nofb + * cleanup: lastmod, remove tile_shm and update_client_pointer, + debug output, rfbPort failure. + * user friendly last line: 'The VNC desktop is hostname:0' + +2004-04-28 Karl Runge + * -auth cmdline option for xauthority. + * decrease default deferupdate under -nofb. + * update_client_pointer() from Edoardo Tirtarahardja. + * remove some assumptions about libvncserver defaults. + +2004-04-19 Karl Runge + * support for cursor positions updates -cursorpos + * option for SIGPIPE handling -sigpipe + +2004-04-13 Karl Runge + * solve problem with sending selection when client initializing + (not yet in RFB_NORMAL state). Increase delay to 15s as well. + * when threaded: limit rfbMaxClientWait to >= 20 secs and + increase it to a huge value unless -rfbwait is supplied. + +2004-04-08 Karl Runge + * added support for blacking out regions of the screen, primarily + for Xinerama usage, options: -blackout -xinerama + * Xinerama workaround mouse problem on 'embedded' system, + option -xwarppointer (XWarpPointer instead of XTEST) + * let -remap option take key remappings on cmdline as well as file. + * use cargs fix to test for invalid cmdline options. Add --option. + * remove copy_tile, use copy_tiles(..., 1) instead. + +2004-03-10 Karl Runge + * added reverse connection for vncconnect(1) and other means + -vncconnect, -connect host:port, and -connect watchfile + * added first pass at user keysym remapping feature via + -remap file. Ignores modifier state, need to generalize. + * debugging options for users -debug_pointer and -debug_keyboard + * clear -passwd from argv for privacy (if OS allows). + +2004-02-19 Karl Runge + * added handling of clipboard/selection exchange to/from clients, + even holds PRIMARY which Xvnc does not do. disable with -nosel. + use -noprimary to disable polling of PRIMARY selection. + * added -visual option to force framebuffer visual. not really + of general use, more for testing and workarounds (e.g. win2vnc + fails under 8bpp index color) + * improve cleanup and error handling WRT shm and other failures. + +2004-01-19 Karl Runge + * improvements to pointer event handling primarily during window + dragging. check_user_input() for non-threaded and pointer() + for threaded. Revert to old way via -old_pointer option. + * some memory I/O improvement by using copy_tiles() instead + of copy_tile(). New one does rows of tiles at same time. + Revert to old way via -old_copytile. + * handle case of more mouse buttons on client than on X server. + * added -buttonmap option for finer control over button differences. + +2004-01-09 Karl Runge + * options -allow / -localhost for simple IP based access screening + * option -nodragging to skip all screen updates during mouse drags + (thanks to Michal Sabala) + * option -input_skip to allow users to tune watch_loop dropthru rate + * try to avoid wasting RAM for framebuffer under -nofb + * cleanup wrt bpp vs. depth + +2003-12-08 Karl Runge + * add Xbell support using XKEYBOARD extension (disable: -nobell) + * add "-nofb" to disable framebuffer, i.e. mouse + keyboard only (!) + * add "-notruecolor" to force indexed 8bpp color (when 8bpp) + * make alias "-forever" for "-many" + +From Karl (x11vnc's father) on Apr 2, 2003: + +New option -nocursor to not display the vncviewer local cursor if user +does not want it (also caused some problems with older vncviewers) + +New option -mouse to show the position of the X server mouse (i.e. lagged +from the user's vnc cursor position). Also: -mouseX will try to show +the a different cursor (X) when on the root background. + +New option -many to wait for more connections rather than exiting when +the first client(s) disconnect. + +New option -flashcmap to try to follow installed colormaps under 8bpp +indexed color as pointer is moved. + +New option -nap to watch for low activity and throttle down the polling +rate. Useful on shared machines to keep the load down. + +Experimental option -id to show just that window and not +the whole display. Some remaining bugs and inconvenient behavior... +(e.g. new toplevels can be unseen) + +Fixed bug on multi-headed machines where the screen number was being +ignored in a number of places. + +Fixed bug wrt connect_once mode. Now just refuses new clients unless +shared rather than terminating all clients. + +Try to follow changing default colormap under 8bpp indexed color +as color cells are added. + +Needed to pick up HAVE_LIBPTHREAD from autoconf. + +defined a select() macro for usleep() since usleep is not always thread +safe. + +Catch and exit on errors in the shm setup work (XShmCreateImage, shmget,...) +and moved the creation and removal work to separate utility functions. + +Added signal and X error handlers to try to clean out the shm objects +before exiting on interrupt, etc. + +Improved performance a bit on the memcmp() in scan_display() by checking +the whole line first. + +Added a workaround when threaded where libvncserver may disconnect too +early if it does not hear from a client (a small heartbeat is sent). +This may not be needed any longer. + +If -desktop has not been prescribed, try to choose a title based on DISPLAY +and the hostname (and window name under -id). diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am new file mode 100755 index 0000000..c18f49d --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/Makefile.am @@ -0,0 +1,36 @@ +if HAVE_SYSTEM_LIBVNCSERVER +LDADD = @SYSTEM_LIBVNCSERVER_LIBS@ @WSOCKLIB@ +else +LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLIB@ +endif + +if OSX +x11vnc_LDFLAGS = -framework ApplicationServices -framework Carbon -framework IOKit -framework Cocoa +x11vnc_CFLAGS = -ObjC +endif + +SUBDIRS = misc +DIST_SUBDIRS = misc + +desktopdir = $(datadir)/applications +desktop_DATA = x11vnc.desktop + +man_MANS=x11vnc.1 +EXTRA_DIST=ChangeLog README tkx11vnc $(man_MANS) $(desktop_DATA) + +if CYGIPC +LD_CYGIPC=-lcygipc +endif + +bin_PROGRAMS=x11vnc +x11vnc_SOURCES = 8to24.c appshare.c avahi.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c macosx.c macosxCG.c macosxCGP.c macosxCGS.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h + +if HAVE_SYSTEM_LIBVNCSERVER +INCLUDES_LIBVNCSERVER = @SYSTEM_LIBVNCSERVER_CFLAGS@ +else +INCLUDES_LIBVNCSERVER = +endif +INCLUDES = -I$(top_srcdir) +INCLUDES += $(INCLUDES_LIBVNCSERVER) @X_CFLAGS@ @AVAHI_CFLAGS@ + +x11vnc_LDADD=$(LDADD) @SSL_LIBS@ @CRYPT_LIBS@ @X_LIBS@ @AVAHI_LIBS@ $(LD_CYGIPC) diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README new file mode 100755 index 0000000..d440a82 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/README @@ -0,0 +1,17770 @@ + +Copyright (C) 2002-2010 Karl J. Runge +All rights reserved. + +x11vnc README file Date: Sat May 8 19:32:50 EDT 2010 + +The following information is taken from these URLs: + + http://www.karlrunge.com/x11vnc/index.html + http://www.karlrunge.com/x11vnc/x11vnc_opts.html + ... + +they contain the most up to date info. + + +======================================================================= +http://www.karlrunge.com/x11vnc/index.html: + + + _________________________________________________________________ + +x11vnc: a VNC server for real X displays + (to FAQ) (to Downloads) (to Building) (to Beta Test) + (to Donations) [PayPal] + + x11vnc allows one to view remotely and interact with real X displays + (i.e. a display corresponding to a physical monitor, keyboard, and + mouse) with any VNC viewer. In this way it plays the role for Unix/X11 + that WinVNC plays for Windows. + + It has built-in SSL/TLS encryption and 2048 bit RSA authentication, + including VeNCrypt support; UNIX account and password login support; + server-side scaling; single port HTTPS/HTTP+VNC; Zeroconf service + advertising; and TightVNC and UltraVNC file-transfer. It has also been + extended to work with non-X devices: natively on Mac OS X Aqua/Quartz, + webcams and TV tuner capture devices, and embedded Linux systems such + as Qtopia Core. Full IPv6 support is provided. More features are + described here. + + It also provides an encrypted Terminal Services mode (-create, -svc, + or -xdmsvc options) based on Unix usernames and Unix passwords where + the user does not need to memorize his VNC display/port number. + Normally a virtual X session (Xvfb) is created for each user, but it + also works with X sessions on physical hardware. See the tsvnc + terminal services mode of the SSVNC viewer for one way to take + advantage of this mode. + + I wrote x11vnc back in 2002 because x0rfbserver was basically + impossible to build on Solaris and had poor performance. The primary + x0rfbserver build problems centered around esoteric C++ toolkits. + x11vnc is written in plain C and needs only standard libraries and so + should work on nearly all Unixes, even very old ones. I also created + enhancements to improve the interactive response, added many features, + and etc. + + This page including the FAQ contains much information [*]; solutions + to many problems; and interesting applications, but nevertheless + please feel free to contact me if you have problems or questions (and + if I save you time or expense by giving you some of my time, please + consider a PayPal Donation.) Do check the FAQ and this page first; I + realize the pages are massive, but you can often use your browser's + find-in-page search action using a keyword to find the answer to your + problem or question. + + SSVNC: An x11vnc side-project provides an Enhanced TightVNC Viewer + package (SSVNC) for Unix, Windows, and Mac OS X with automatic SSL + and/or SSH tunnelling support, SSL Certificate creation, Saved + connection profiles, Zeroconf, VeNCrypt, and built-in Proxy support. + Added features for the TightVNC Unix viewer: NewFBSize, ZRLE encoding, + Viewer-side Scaling, cursor alphablending, low color modes, and + enhanced popup menu; UltraVNC extensions support for: File Transfer, + Text Chat, Single Window, Server Input, and 1/n Scaling extensions, + and UltraVNC DSM encryption. The SSVNC bundle could be placed on, say, + a USB memory stick for SSL/SSH VNC viewing from nearly any networked + computer. + + _________________________________________________________________ + + Announcements: + + Important: If you created any permanent SSL certificates (e.g. via + "x11vnc -ssl SAVE ...") on a Debian or Ubuntu system from Sept. 2006 + through May 2008, then those keys are likely extremely weak and can be + easily cracked. The certificate files should be deleted and recreated + on a non-Debian system or an updated one. See + http://www.debian.org/security/2008/dsa-1571 for details. The same + applies to SSH keys (not used by x11vnc directly, but many people use + SSH tunnels for VNC access.) + + FAQ moved: The huge FAQ has finally been moved to its own page. If you + are trying to follow someone's link to an FAQ once on this page it is + now a broken link. Try inserting the string "faq.html", e.g.: +from: http://www.karlrunge.com/x11vnc/#faq-singleclick +to: http://www.karlrunge.com/x11vnc/faq.html#faq-singleclick + + Apologies for the inconvenience, unfortunately it is not possible to + automatically redirect to the new page since the '#' anchor is not + sent to the webserver. + + _________________________________________________________________ + + Background: + + VNC (Virtual Network Computing) is a very useful network graphics + protocol (applications running on one computer but displaying their + windows on another) in the spirit of X, however, unlike X, the + viewing-end is very simple and maintains no state. It is a remote + framebuffer (RFB) protocol. + + Some VNC links: + * http://www.realvnc.com + * http://www.tightvnc.com + * http://www.ultravnc.com/ + * http://www.testplant.com/products/vine_server/OS_X + + For Unix, the traditional VNC implementation includes a "virtual" X11 + server Xvnc (usually launched via the vncserver command) that is not + associated with a physical display, but provides a "fake" one X11 + clients (xterm, firefox, etc.) can attach to. A remote user then + connects to Xvnc via the VNC client vncviewer from anywhere on the + network to view and interact with the whole virtual X11 desktop. + + The VNC protocol is in most cases better suited for remote connections + with low bandwidth and high latency than is the X11 protocol because + it involves far fewer "roundtrips" (an exception is the cached pixmap + data on the viewing-end provided by X.) Also, with no state maintained + the viewing-end can crash, be rebooted, or relocated and the + applications and desktop continue running. Not so with X11. + + So the standard Xvnc/vncserver program is very useful, I use it for + things like: + * Desktop conferencing with other users (e.g. code reviews.) + * Long running apps/tasks I want to be able to view from many places + (e.g. from home and work.) + * Motif, GNOME, and similar applications that would yield very poor + performance over a high latency link. + + However, sometimes one wants to connect to a real X11 display (i.e. + one attached to a physical monitor, keyboard, and mouse: a Workstation + or a SunRay session) from far away. Maybe you want to close down an + application cleanly rather than using kill, or want to work a bit in + an already running application, or would like to help a distant + colleague solve a problem with their desktop, or would just like to + work out on the deck for a while. This is where x11vnc is useful. + _________________________________________________________________ + + How to use x11vnc: + + In this basic example let's assume the remote machine with the X + display you wish to view is "far-away.east:0" and the workstation you + are presently working at is "sitting-here.west". + + Step 0. Download x11vnc (see below) and have it available to run on + far-away.east (on some linux distros it is as easy as "apt-get install + x11vnc", "emerge x11vnc", etc.) Similarly, have a VNC viewer (e.g. + vncviewer) ready to run on sitting-here.west. We recommend TightVNC + Viewers (see also our SSVNC viewer.) + + Step 1. By some means log in to far-away.east and get a command shell + running there. You can use ssh, or even rlogin, telnet, or any other + method to do this. We do this because the x11vnc process needs to be + run on the same machine the X server process is running on (otherwise + things would be extremely slow.) + + Step 2. In that far-away.east shell (with command prompt "far-away>" + in this example) run x11vnc directed at the far-away.east X session + display: + + far-away> x11vnc -display :0 + + You could have also set the environment variable DISPLAY=:0 instead of + using "-display :0". This step attaches x11vnc to the far-away.east:0 + X display (i.e. no viewer clients yet.) + + Common Gotcha: To get X11 permissions right, you may also need to set + the XAUTHORITY environment variable (or use the -auth option) to point + to the correct MIT-MAGIC-COOKIE file (e.g. /home/joe/.Xauthority.) If + x11vnc does not have the authority to connect to the display it exits + immediately. More on how to fix this below. + + If you suspect an X11 permissions problem do this simple test: while + sitting at the physical X display open a terminal window + (gnome-terminal, xterm, etc.) You should be able to run x11vnc + successfully in that terminal without any need for command line + options. If that works OK then you know X11 permissions are the only + thing preventing it from working when you try to start x11vnc via a + remote shell. Then fix this with the tips below. + + Note as of Feb/2007 you can also try the -find option instead of + "-display ..." and see if that finds your display and Xauthority. Note + as of Dec/2009 the -findauth and "-auth guess" options may be helpful + as well. + (End of Common Gotcha) + + When x11vnc starts up there will then be much chatter printed out (use + "-q" to quiet it), until it finally says something like: + . + . + 13/05/2004 14:59:54 Autoprobing selected port 5900 + 13/05/2004 14:59:54 screen setup finished. + 13/05/2004 14:59:54 + 13/05/2004 14:59:54 The VNC desktop is far-away:0 + PORT=5900 + + which means all is OK, and we are ready for the final step. + + Step 3. At the place where you are sitting (sitting-here.west in this + example) you now want to run a VNC viewer program. There are VNC + viewers for Unix, Windows, MacOS, Java-enabled web browsers, and even + for PDA's like the Palm Pilot and Cell Phones! You can use any of them + to connect to x11vnc (see the above VNC links under "Background:" on + how to obtain a viewer for your platform or see this FAQ. For Solaris, + vncviewer is available in the Companion CD package SFWvnc.) + + In this example we'll use the Unix vncviewer program on sitting-here + by typing the following command in a second terminal window: + + sitting-here> vncviewer far-away.east:0 + + That should pop up a viewer window on sitting-here.west showing and + allowing interaction with the far-away.east:0 X11 desktop. Pretty + nifty! When finished, exit the viewer: the remote x11vnc process will + shutdown automatically (or you can use the -forever option to have it + wait for additional viewer connections.) + + Common Gotcha: Nowadays there will likely be a host-level firewall on + the x11vnc side that is blocking remote access to the VNC port (e.g. + 5900.) You will either have to open up that port (or a range of ports) + in your firewall administration tool, or try the SSH tunnelling method + below (even still the firewall must allow in the SSH port, 22.) + + + Shortcut: Of course if you left x11vnc running on far-away.east:0 in a + terminal window with the -forever option or as a service, you'd only + have to do Step 3 as you moved around. Be sure to use a VNC Password + or other measures if you do that. + + + Super Shortcut: Here is a potentially very easy way to get all of it + working. + * Have x11vnc (0.9.3 or later) available to run on the remote host + (i.e. in $PATH.) + * Download and unpack a SSVNC bundle (1.0.19 or later, e.g. + ssvnc_no_windows-1.0.23.tar.gz) on the Viewer-side machine. + * Start the SSVNC Terminal Services mode GUI: ./ssvnc/bin/tsvnc + * Enter your remote username@hostname (e.g. fred@far-away.east) in + the "VNC Terminal Server" entry. + * Click "Connect". + + That will do an SSH to username@hostname and start up x11vnc and then + connect a VNC Viewer through the SSH encrypted tunnel. + + There are a number of things assumed here, first that you are able to + SSH into the remote host; i.e. that you have a Unix account there and + the SSH server is running. On Unix and MacOS X it is assumed that the + ssh client command is available on the local machine (on Windows a + plink binary is included in the SSVNC bundle.) Finally, it is assumed + that you are already logged into an X session on the remote machine, + e.g. your workstation (otherwise, a virtual X server, e.g. Xvfb, will + be started for you.) + + In some cases the remote SSH server will not run commands with the + same $PATH that you normally have in your shell there. In this case + click on Options -> Advanced -> X11VNC Options, and type in the + location of the x11vnc binary under "Full Path". (End of Super + Shortcut) + + + Desktop Sharing: The above more or less assumed nobody was sitting at + the workstation display "far-away.east:0". This is often the case: a + user wants to access her workstation remotely. Another usage pattern + has the user sitting at "far-away.east:0" and invites one or more + other people to view and interact with his desktop. Perhaps the user + gives a demo or presentation this way (using the telephone for vocal + communication.) A "Remote Help Desk" mode would be similar: a + technician connects remotely to the user's desktop to interactively + solve a problem the user is having. + + For these cases it should be obvious how it is done. The above steps + will work, but more easily the user sitting at far-away.east:0 simply + starts up x11vnc from a terminal window, after which the guests would + start their VNC viewers. For this usage mode the "-connect + host1,host2" option may be of use to automatically connect to the + vncviewers in "-listen" mode on the list of hosts. + _________________________________________________________________ + + Tunnelling x11vnc via SSH: + + The above example had no security or privacy at all. When logging into + remote machines (certainly when going over the internet) it is best to + use ssh, or use a VPN (for a VPN, Virtual Private Network, the above + example should be pretty safe.) + + For x11vnc one can tunnel the VNC protocol through an encrypted ssh + channel. It would look something like running the following commands: + sitting-here> ssh -t -L 5900:localhost:5900 far-away.east 'x11vnc -localhost +-display :0' + + (you will likely have to provide passwords/passphrases to login from + sitting-here into your far-away.east Unix account; we assume you have + a login account on far-away.east and it is running the SSH server) + + And then in another terminal window on sitting-here run the command: + sitting-here> vncviewer -encodings "copyrect tight zrle hextile" localhost:0 + + Note: The -encodings option is very important: vncviewer will often + default to "raw" encoding if it thinks the connection is to the local + machine, and so vncviewer gets tricked this way by the ssh + redirection. "raw" encoding will be extremely slow over a networked + link, so you need to force the issue with -encodings "copyrect tight + ...". Nowadays, not all viewers use the -encodings option, try + "-PreferredEncoding=ZRLE" (although the newer viewers seem to + autodetect well when to use raw or not.) + + Note that "x11vnc -localhost ..." limits incoming vncviewer + connections to only those from the same machine. This is very natural + for ssh tunnelling (the redirection appears to come from the same + machine.) Use of a VNC password is also strongly recommended. + + Note also the -t we used above (force allocate pseudoterminal), it + actually seems to improve interactive typing response via VNC! + + You may want to add the -C option to ssh to enable compression. The + VNC compression is not perfect, and so this may help a bit. However, + over a fast LAN you probably don't want to enable SSH compression + because it can slow things down. Try both and see which is faster. + + If your username is different on the remote machine use something + like: "fred@far-away.east" in the above ssh command line. + + Some VNC viewers will do the ssh tunnelling for you automatically, the + TightVNC Unix vncviewer does this when the "-via far-away.east" option + is supplied to it (this requires x11vnc to be already running on + far-away.east or having it started by inetd(8).) See the 3rd script + example below for more info. + + SSVNC: You may also want to look at the Enhanced TightVNC Viewer + (ssvnc) bundles because they contain scripts and GUIs to automatically + set up SSH tunnels (e.g. the GUI, "ssvnc", does it automatically and + so does this command: "ssvnc_cmd -ssh user@far-away.east:0") and can + even start up x11vnc as well. + + The Terminal Services mode of SSVNC is perhaps the easiest way to use + x11vnc. You just need to have x11vnc available in $PATH on the remote + side (and can SSH to the host), and then on the viewer-side you type + something like: + tsvnc fred@far-away.east + + everything else is done automatically for you. Normally this will + start a virtual Terminal Services X session (RAM-only), but if you + already have a real X session up on the physical hardware it will find + that one for you. + + Gateways: If the machine you SSH into is not the same machine with + the X display you wish to view (e.g. your company provides incoming + SSH access to a gateway machine), then you need to change the above + to, e.g.: "-L 5900:OtherHost:5900": + sitting-here> ssh -t -L 5900:OtherHost:5900 gateway.east + + Where gateway.east is the internet hostname (or IP) of the gateway + machine (SSH server.) 'OtherHost' might be, e.g., freds-pc or + 192.168.2.33 (it is OK for these to be private hostnames or private IP + addresses, the host in -L is relative to the remote server side.) + + Once logged in, you'll need to do a second login (ssh, rsh, etc.) to + the workstation machine 'OtherHost' and then start up x11vnc on it (if + it isn't already running.) (The "-connect gateway:59xx" option may be + another alternative here with the viewer already in -listen mode.) For + an automatic way to use a gateway and have all the network traffic + encrypted (including inside the firewall) see Chaining SSH's. + + These gateway access modes also can be done automatically for you via + the "Proxy/Gateway" setting in SSVNC (including the Chaining SSH's + case, "Double Proxy".) + + Firewalls/Routers: + + A lot of people have inexpensive devices for home or office that act + as a Firewall and Router to the machines inside on a private LAN. One + can usually configure the Firewall/Router from inside the LAN via a + web browser. + + Often having a Firewall/Router sitting between the vncviewer and + x11vnc will make it impossible for the viewer to connect to x11vnc. + + One thing that can be done is to redirect a port on the + Firewall/Router to, say, the SSH port (22) on an inside machine (how + to do this depends on your particular Firewall/Router, often the + router config URL is http://192.168.100.1 See www.portforward.com for + more info.) This way you reach these computers from anywhere on the + Internet and use x11vnc to view X sessions running on them. + + Suppose you configured the Firewall/Router to redirect these ports to + two internal machines: + Port 12300 -> 192.168.1.3, Port 22 (SSH) + Port 12301 -> 192.168.1.4, Port 22 (SSH) + + (where 192.168.1.3 is "jills-pc" and 192.168.1.4 is "freds-pc".) Then + the ssh's would look something like: + sitting-here> ssh -t -p 12300 -L 5900:localhost:5900 jill@far-away.east 'x11v +nc -localhost -display :0' + sitting-here> ssh -t -p 12301 -L 5900:localhost:5900 fred@far-away.east 'x11v +nc -localhost -display :0' + + Where far-away.east means the hostname (or IP) that the + Router/Firewall is using (for home setups this is usually the IP + gotten from your ISP via DHCP, the site http://www.whatismyip.com/ is + a convenient way to determine what it is.) + + It is a good idea to add some obscurity to accessing your system via + SSH by using some high random port (e.g. 12300 in the above example.) + If you can't remember it, or are otherwise not worried about port + scanners detecting the presence of your SSH server and there is just + one internal PC involved you could map 22: + Port 22 -> 192.168.1.3, Port 22 (SSH) + + Again, this SSH gateway access can be done automatically for you via + the "Proxy/Gateway" setting in SSVNC. And under the "Remote SSH + Command" setting you can enter the x11vnc -localhost -display :0. + + Host-Level-Firewalls: even with the hardware Firewall/Router problem + solved via a port redirection, most PC systems have their own Host + level "firewalls" enabled to protect users from themselves. I.e. the + system itself blocks all incoming connections. So you will need to see + what is needed to configure it to allow in the port (e.g. 22) that you + desire. E.g. Yast, Firestarter, iptables(1), etc.. + + VNC Ports and Firewalls: The above discussion was for configuring the + Firewall/Router to let in port 22 (SSH), but the same thing can be + done for the default VNC port 5900: + Port 5900 -> 192.168.1.3, Port 5900 (VNC) + Port 5901 -> 192.168.1.4, Port 5900 (VNC) + + (where 192.168.1.3 is "jills-pc" and 192.168.1.4 is "freds-pc".) This + could be used for normal, unencrypted connections and also for SSL + encrypted ones. + + The VNC displays to enter in the VNC viewer would be, say, + "far-away.east:0" to reach jills-pc and "far-away.east:1" to reach + freds-pc. We assume above that x11vnc is using port 5900 (and any + Host-Level-firewalls on jills-pc has been configured to let that port + in.) Use the "-rfbport" option to tell which port x11vnc should listen + on. + + For a home system one likely does not have a hostname and would have + to use the IP address, say, "24.56.78.93:0". E.g.: + vncviewer 24.56.78.93:0 + + You may want to choose a more obscure port on the router side, e.g. + 5944, to avoid a lot of port scans finding your VNC server. For 5944 + you would tell the viewer to use: + vncviewer 24.56.78.93:44 + + The IP address would need to be communicated to the person running the + VNC Viewer. The site http://www.whatismyip.com/ can help here. + + _________________________________________________________________ + + Scripts to automate ssh tunneling: As discussed below, there may be + some problems with port 5900 being available. If that happens, the + above port and display numbers may change a bit (e.g. -> 5901 and :1). + However, if you "know" port 5900 will be free on the local and remote + machines, you can easily automate the above two steps by using the + x11vnc option -bg (forks into background after connection to the + display is set up) or using the -f option of ssh. Some example scripts + are shown below. Feel free to try the ssh -C to enable its compression + and see if that speeds things up noticeably. + _________________________________________________________________ + + #1. A simple example script, assuming no problems with port 5900 being + taken on the local or remote sides, looks like: +#!/bin/sh +# usage: x11vnc_ssh : +# e.g.: x11vnc_ssh snoopy.peanuts.com:0 +# (user@host:N also works) + +host=`echo $1 | awk -F: '{print $1}'` +disp=`echo $1 | awk -F: '{print $2}'` +if [ "x$disp" = "x" ]; then disp=0; fi + +cmd="x11vnc -display :$disp -localhost -rfbauth .vnc/passwd" +enc="copyrect tight zrle hextile zlib corre rre raw" + +ssh -f -t -L 5900:localhost:5900 $host "$cmd" + +for i in 1 2 3 +do + sleep 2 + if vncviewer -encodings "$enc" :0; then break; fi +done + + See also rx11vnc.pl below. + _________________________________________________________________ + + #2. Another method is to start the VNC viewer in listen mode + "vncviewer -listen" and have x11vnc initiate a reverse connection + using the -connect option: +#!/bin/sh +# usage: x11vnc_ssh : +# e.g.: x11vnc_ssh snoopy.peanuts.com:0 +# (user@host:N also works) + +host=`echo $1 | awk -F: '{print $1}'` +disp=`echo $1 | awk -F: '{print $2}'` +if [ "x$disp" = "x" ]; then disp=0; fi + +cmd="x11vnc -display :$disp -localhost -connect localhost" # <== note new opt +ion +enc="copyrect tight zrle hextile zlib corre rre raw" + +vncviewer -encodings "$enc" -listen & +pid=$! +ssh -t -R 5500:localhost:5500 $host "$cmd" +kill $pid + + Note the use of the ssh option "-R" instead of "-L" to set up a remote + port redirection. + _________________________________________________________________ + + #3. A third way is specific to the TightVNC vncviewer special option + -via for gateways. The only tricky part is we need to start up x11vnc + and give it some time (5 seconds in this example) to start listening + for connections (so we cannot use the TightVNC default setting for + VNC_VIA_CMD): +#!/bin/sh +# usage: x11vnc_ssh : +# e.g.: x11vnc_ssh snoopy.peanuts.com:0 + +host=`echo $1 | awk -F: '{print $1}'` +disp=`echo $1 | awk -F: '{print $2}'` +if [ "x$disp" = "x" ]; then disp=0; fi + +VNC_VIA_CMD="ssh -f -t -L %L:%H:%R %G x11vnc -localhost -rfbport 5900 -display +:$disp; sleep 5" +export VNC_VIA_CMD + +vncviewer -via $host localhost:0 # must be TightVNC vncviewer. + + Of course if you already have the x11vnc running waiting for + connections (or have it started out of inetd(8)), you can simply use + the TightVNC "vncviewer -via gateway host:port" in its default mode to + provide secure ssh tunnelling. + _________________________________________________________________ + + + + VNC password file: Also note in the #1. example script that the option + "-rfbauth .vnc/passwd" provides additional protection by requiring a + VNC password for every VNC viewer that connects. The vncpasswd or + storepasswd programs, or the x11vnc -storepasswd option can be used to + create the password file. x11vnc also has the slightly less secure + -passwdfile and "-passwd XXXXX" options to specify passwords. + + Very Important: It is up to YOU to tell x11vnc to use password + protection (-rfbauth or -passwdfile), it will NOT do it for you + automatically or force you to (use -usepw if you want to be forced + to.) The same goes for encrypting the channel between the viewer and + x11vnc: it is up to you to use ssh, stunnel, -ssl mode, a VPN, etc. + (use the Enhanced TightVNC Viewer (SSVNC) GUI if you want to be forced + to use SSL or SSH.) For additional safety, also look into the -allow + and -localhost options and building x11vnc with tcp_wrappers support + to limit host access. + + _________________________________________________________________ + + Tunnelling x11vnc via SSL/TLS: + + One can also encrypt the VNC traffic using an SSL/TLS tunnel such as + stunnel.mirt.net (also stunnel.org) or using the built-in (Mar/2006) + -ssl openssl mode. A SSL-enabled Java applet VNC Viewer is also + provided in the x11vnc package (and https can be used to download it.) + + Although not as ubiquitous as ssh, SSL tunnelling still provides a + useful alternative. See this FAQ on -ssl and -stunnel modes for + details and examples. + + The Enhanced TightVNC Viewer (SSVNC) bundles contain some convenient + utilities to automatically set up an SSL tunnel from the viewer-side + (i.e. to connect to "x11vnc -ssl ...".) And many other enhancements + too. + _________________________________________________________________ + + Downloading x11vnc: + + x11vnc is a contributed program to the LibVNCServer project at + SourceForge.net. I use libvncserver for all of the VNC aspects; I + couldn't have done without it. The full source code may be found and + downloaded (either file-release tarball or GIT tree) from the above + link. As of May 2010, the x11vnc-0.9.10.tar.gz source package is + released (recommended download). The x11vnc 0.9.10 release notes. + + The x11vnc package is the subset of the libvncserver package needed to + build the x11vnc program. Also, you can get a copy of my latest, + bleeding edge x11vnc-0.9.11-dev.tar.gz tarball to build the most up to + date one. + + Precompiled Binaries/Packages: See the FAQ below for information + about where you might obtain a precompiled x11vnc binary from 3rd + parties and some ones I create. + + VNC Viewers: To obtain VNC viewers for the viewing side (Windows, Mac + OS, or Unix) try these links: + * http://www.tightvnc.com/download.html + * http://www.realvnc.com/download-free.html + * http://sourceforge.net/projects/cotvnc/ + * http://www.ultravnc.com/ + * Our Enhanced TightVNC Viewer (SSVNC) + + [ssvnc.gif] + + + More tools: Here is a ssh/rsh wrapper script rx11vnc that attempts to + automatically do the above Steps 1-3 for you (provided you have + ssh/rsh login permission on the machine x11vnc is to be run on.) The + above example would be: "rx11vnc far-away.east:0" typed into a shell + on sitting-here.west. Also included is an experimental script + rx11vnc.pl that attempts to tunnel the vnc traffic through an ssh port + redirection (and does not assume port 5900 is free.) Have a look at + them to see what they do and customize as needed: + * rx11vnc wrapper script + * rx11vnc.pl wrapper script to tunnel traffic thru ssh + + _________________________________________________________________ + + Building x11vnc: + + Make sure you have all the needed build/compile/development packages + installed (e.g. Linux distributions foolishly don't install them by + default.) See this build FAQ for more details. + + If your OS has libjpeg.so and libz.so in standard locations you can + build as follows (example given for the 0.9.10 release of x11vnc: + replace with the version you downloaded): +(un-tar the x11vnc+libvncserver tarball) +# gzip -dc x11vnc-0.9.10.tar.gz | tar -xvf - + +(cd to the source directory) +# cd x11vnc-0.9.10 + +(run configure and then run make) +# ./configure +# make + +(if all went OK, copy x11vnc to the desired destination, e.g. $HOME/bin) +# cp ./x11vnc/x11vnc $HOME/bin + + Or do make install, it will probably install to /usr/local/bin (run + ./configure --help for information on customizing your configuration, + e.g. --prefix=/my/place.) You can now run it via typing "x11vnc", + "x11vnc -help | more", "x11vnc -forever -shared -display :0", etc. + + + Note: Currently gcc is recommended to build libvncserver. In some + cases it will build with non-gcc compilers, but the resulting binary + sometimes fails to run properly. For Solaris pre-built gcc binaries + are at http://www.sunfreeware.com/. Some Solaris pre-built x11vnc + binaries are here. + + However, one user reports it does work fine when built with Sun Studio + 10, so YMMV. In fact, here is a little build script to do this on + Solaris 10: +#!/bin/sh +PATH=/usr/ccs/bin:/opt/SUNWspro/bin:$PATH; export PATH + +CC='cc' \ +CFLAGS='-xO4' \ +LDFLAGS='-L/usr/sfw/lib -L/usr/X11/lib -R/usr/sfw/lib -R/usr/X11/lib' \ +CPPFLAGS='-I /usr/sfw/include -I/usr/X11/include' \ +./configure + +MAKE="make -e" +AM_CFLAGS="" +export MAKE AM_CFLAGS +$MAKE + + In general you can use the "make -e" trick if you don't like + libvncserver's choice of AM_CFLAGS. See the build scripts below for + more ideas. Scripts similar to the above have been shown to work with + vendor C compilers on HP-UX (ccom: HP92453-01) and Tru64 (Compaq C + V6.5-011.) + + You can find information on Misc. Build problems here. + + _________________________________________________________________ + + Building on Solaris, FreeBSD, etc: Depending on your version of + Solaris or other Unix OS the jpeg and/or zlib libraries may be in + non-standard places (e.g. /usr/local, /usr/sfw, /opt/sfw, etc.) + + Note: If configure cannot find these two libraries then TightVNC and + ZRLE encoding support will be disabled, and you don't want that!!! The + TightVNC encoding gives very good compression and performance, it even + makes a noticeable difference over a fast LAN. + + + Shortcuts: On Solaris 10 you can pick up almost everything just by + insuring that your PATH has /usr/sfw/bin (for gcc) and /usr/ccs/bin + (for other build tools), e.g.: + env PATH=/usr/sfw/bin:/usr/ccs/bin:$PATH sh -c './configure; make' + + (The only thing this misses is /usr/X11/lib/libXrandr.so.2, which is + for the little used -xrandr option, see the script below to pick it up + as well.) + + + libjpeg is included in Solaris 9 and later (/usr/sfw/include and + /usr/sfw/lib), and zlib in Solaris 8 and later (/usr/include and + /usr/lib.) So on Solaris 9 you can pick up everything with something + like this: + env PATH=/usr/local/bin:/usr/ccs/bin:$PATH sh -c './configure --with-jpeg=/us +r/sfw; make' + + assuming your gcc is in /usr/local/bin and x11vnc 0.7.1 or later. + These are getting pretty long, see those assignments split up in the + build script below. + + + If your system does not have these libraries at all you can get the + source for the libraries to build them: libjpeg is available at + ftp://ftp.uu.net/graphics/jpeg/ and zlib at http://www.gzip.org/zlib/. + See also http://www.sunfreeware.com/ for Solaris binary packages of + these libraries as well as for gcc. Normally they will install into + /usr/local but you can install them anywhere with the + --prefix=/path/to/anywhere, etc. + + + Here is a build script that indicates one way to pass the library + locations information to the libvncserver configuration via the + CPPFLAGS and LDFLAGS environment variables. +---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8 +<--- +#!/bin/sh + +# Build script for Solaris, etc, with gcc, libjpeg and libz in +# non-standard locations. + +# set to get your gcc, etc: +# +PATH=/path/to/gcc/bin:/usr/ccs/bin:/usr/sfw/bin:$PATH + +JPEG=/path/to/jpeg # set to maybe "/usr/local", "/usr/sfw", or "/opt/sfw" +ZLIB=/path/to/zlib # set to maybe "/usr/local", "/usr/sfw", or "/opt/sfw" + +# Below we assume headers in $JPEG/include and $ZLIB/include and the +# shared libraries are in $JPEG/lib and $ZLIB/lib. If your situation +# is different change the locations in the two lines below. +# +CPPFLAGS="-I $JPEG/include -I $ZLIB/include" +LDFLAGS="-L$JPEG/lib -R $JPEG/lib -L$ZLIB/lib -R $ZLIB/lib" + +# These two lines may not be needed on more recent Solaris releases: +# +CPPFLAGS="$CPPFLAGS -I /usr/openwin/include" +LDFLAGS="$LDFLAGS -L/usr/openwin/lib -R /usr/openwin/lib" + +# These are for libXrandr.so on Solaris 10: +# +CPPFLAGS="$CPPFLAGS -I /usr/X11/include" +LDFLAGS="$LDFLAGS -L/usr/X11/lib -R /usr/X11/lib" + +# Everything needs to built with _REENTRANT for thread safe errno: +# +CPPFLAGS="$CPPFLAGS -D_REENTRANT" + +export PATH CPPFLAGS LDFLAGS + +./configure +make + +ls -l ./x11vnc/x11vnc + +---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8<---8 +<--- + + Then do make install or copy the x11vnc binary to your desired + destination. + + BTW, To run a shell script, just cut-and-paste the above into a file, + say "myscript", then modify the "/path/to/..." items to correspond to + your system/environment, and then type: "sh myscript" to run it. + + Note that on Solaris make is /usr/ccs/bin/make, so that is why the + above puts /usr/ccs/bin in PATH. Other important build utilities are + there too: ld, ar, etc. Also, it is probably a bad idea to have + /usr/ucb in your PATH while building. + + Starting with the 0.7.1 x11vnc release the "configure --with-jpeg=DIR + --with-zlib=DIR" options are handy if you want to avoid making a + script. + + If you need to link OpenSSL libssl.a on Solaris see this method. + + If you need to build on Solaris 2.5.1 or earlier or other older Unix + OS's, see this workaround FAQ. + + + Building on FreeBSD, OpenBSD, ...: The jpeg libraries seem to be in + /usr/local or /usr/pkg on these OS's. You won't need the openwin stuff + in the above script (but you may need /usr/X11R6/....) Also starting + with the 0.7.1 x11vnc release, this usually works: + ./configure --with-jpeg=/usr/local + make + + + Building on HP-UX: For jpeg and zlib you will need to do the same + sort of thing as described above for Solaris. You set CPPFLAGS and + LDFLAGS to find them (see below for an example.) You do not need to do + any of the above /usr/openwin stuff. Also, HP-UX does not seem to + support -R, so get rid of the -R items in LDFLAGS. Because of this, at + runtime you may need to set LD_LIBRARY_PATH or SHLIB_PATH to indicate + the directory paths so the libraries can be found. It is a good idea + to have static archives, e.g. libz.a and libjpeg.a for the nonstandard + libraries so that they get bolted into the x11vnc binary (and so won't + get "lost".) + + Here is what we recently did to build x11vnc 0.7.2 on HP-UX 11.11 +./configure --with-jpeg=$HOME/hpux/jpeg --with-zlib=$HOME/hpux/zlib +make + + Where we had static archives (libjpeg.a, libz.a) only and header files + in the $HOME/hpux/... directories as discussed for the build script. + + On HP-UX 11.23 and 11.31 we have had problems compiling with gcc. + "/usr/include/rpc/auth.h:87: error: field 'syncaddr' has incomplete + type". As a workaround for x11vnc 0.9.4 and later set your CPPFLAGS to + include: + CPPFLAGS="-DIGNORE_GETSPNAM" + export CPPFLAGS + + This disables a very rare usage mode for -unixpw_nis by not trying + getspnam(3). + + Using HP-UX's C compiler on 11.23 and 11.31 we have some severe + compiler errors that have not been worked around yet. If you need to + do this, contact me and I will give you a drastic recipe that will + produce a working binary. + + + Building on AIX: AIX: one user had to add the "X11.adt" package to + AIX 4.3.3 and 5.2 to get build header files like XShm.h, etc. You may + also want to make sure that /usr/lpp/X11/include, etc is being picked + up by the configure and make. + + For a recent build on AIX 5.3 we needed to add these CFLAGS to be able + to build with gcc: + env CFLAGS='-maix64 -Xlinker -bbigtoc' ./configure ... + + we also built our own libjpeg and libz using -maix64. + + BTW, one way to run an Xvfb-like virtual X server for testing on AIX + is something like "/usr/bin/X11/X -force -vfb -ac :1". + + + Building on Mac OS X: There is now native Mac OS X support for + x11vnc by using the raw framebuffer feature. This mode does not use or + need X11 at all. To build you may need to disable X11: +./configure --without-x ... +make + + However, if your system has the Mac OS X build package for X11 apps + you will not need to supply the "--without-x" option (in this case the + resulting x11vnc would be able to export both the native Mac OS X + display and windows displayed in the XDarwin X server.) Be sure to + include the ./configure option to find libjpeg on your system. + + + OpenSSL: Starting with version 0.8.3 x11vnc can now be built with + SSL/TLS support. For this to be enabled the libssl.so library needs to + be available at build time. So you may need to have additional + CPPFLAGS and LDFLAGS items if your libssl.so is in a non-standard + place. As of x11vnc 0.9.4 there is also the --with-ssl=DIR configure + option. + + On Solaris using static archives libssl.a and libcrypto.a instead of + .so shared libraries (e.g. from www.sunfreeware.com), we found we + needed to also set LDFLAGS as follows to get the configure to work: +env LDFLAGS='-lsocket -ldl' ./configure --with-ssl=/path/to/openssl ... +make + + _________________________________________________________________ + + Beta Testing: + + I don't have any formal beta-testers for the releases of x11vnc, so + I'd appreciate any additional testing very much. + + Thanks to those who suggested features and helped beta test x11vnc + 0.9.10 released in May 2010! + + Please help test and debug the 0.9.11 version for release sometime in + Summer 2010. + + The version 0.9.11 beta tarball is kept here: + x11vnc-0.9.11-dev.tar.gz + + There are also some Linux, Solaris, Mac OS X, and other OS test + binaries here. Please kick the tires and report bugs, performance + regressions, undesired behavior, etc. to me. + + To aid testing of the built-in SSL/TLS support for x11vnc, a number of + VNC Viewer packages for Unix, Mac OS X, and Windows have been created + that provide SSL Support for the TightVNC Viewer (this is done by + wrapper scripts and a GUI that starts STUNNEL.) It should be pretty + convenient for automatic SSL and SSH connections. It is described in + detail at and can be downloaded from the Enhanced TightVNC Viewer + (SSVNC) page. The SSVNC Unix viewer also supports x11vnc's symmetric + key encryption ciphers (see the 'UltraVNC DSM Encryption Plugin' + settings panel.) + + + Here are some features that will appear in the 0.9.11 release: + * Coming Soon. + + + Here are some features that appeared in the 0.9.10 release: + * The included SSL enabled Java applet viewer now supports Chained + SSL Certificates. The debugCerts=yes applet parameter aids + troubleshooting certificate validation. The x11vnc -ssl mode has + always supported chained SSL certificates (simply put the + intermediate certificates, in order, after the server certificate + in the pem file.) + * A demo CGI script desktop.cgi shows how to create an SSL + encrypted, multi-user x11vnc web login desktop service. The script + requires x11vnc version 0.9.10. The user logs into a secure web + site and gets his/her own virtual desktop (Xvfb.) x11vnc's SSL + enabled Java Viewer Applet is launched by the web browser for + secure viewing (and so no software needs to be installed on the + viewer-side.) One can use the desktop.cgi script for ideas to + create their own fancier or customized web login desktop service + (e.g. user-creation, PHP, SQL, specialized desktop application, + etc.) More info here. There is also an optional 'port redirection' + mode that allows redirection to other SSL enabled VNC servers + running inside the firewall. + * Built-in support for IPv6 (128 bit internet addresses) is now + provided. See the -6 and -connect options for details. + Additionally, in case there are still problems with built-in IPv6 + support, a transitional tool is provided in inet6to4 that allows + x11vnc (or any other IPv4 application) to receive connections over + IPv6. + * The Xdummy wrapper script for Xorg's dummy driver is updated and + no longer requires being run as root. New service options are + provided to select Xdummy over Xvfb as the virtual X server to be + created. + * The "%" unix password verification tricks for the -unixpw option + are now documented. They have also been extended to run a command + as the user if one sets the environment variable UNIXPW_CMD. The + desktop.cgi demo script takes advantage of this new feature. + * A bug has been fixed that would prevent the Java applet viewer + from being downloaded successfully in single-port HTTPS/VNC inetd + mode. The env. var. X11VNC_HTTPS_DOWNLOAD_WAIT_TIME can be used to + adjust for how many seconds a -inetd or -https httpd download is + waited for (default 15 seconds.) The applet will now autodetect + x11vnc and use GET=1 for faster connecting. Many other + improvements and fixes. + * The TightVNC security type (TightVNC features enabler) now works + for RFB version 3.8. + * The X property X11VNC_TRAP_XRANDR can be set on a desktop to force + x11vnc to use the -xrandr screen size change trapping code. + * New remote control query options: pointer_x, pointer_y, + pointer_same, pointer_root, and pointer_mask. A demo script using + them misc/panner.pl is provided. + * The -sslScripts option prints out the SSL certificate management + scripts. + + + Here are some features that appeared in the 0.9.9 release (Dec/2009): + * The -unixpw_system_greeter option, when used in combined unixpw + and XDMCP FINDCREATEDISPLAY mode (for example: -xdmsvc), enables + the user to press Escape to jump directly to the XDM/GDM/KDM login + greeter screen. This way the user avoids entering his unix + password twice at X session creation time. Also, the unixpw login + panel now has a short help displayed if the user presses 'F1'. + * x11vnc now tries to be a little bit more aggressive in keeping up + with VNC client's framebuffer update requests. Some broken VNC + clients like Eggplant and JollysFastVNC continuously spray these + requests at VNC servers (regardless of whether they have received + any updates or not.) Under some circumstances this could lead to + x11vnc falling behind. The -extra_fbur option allows one to fine + tune the setting. Additionally, one may also dial down delays: + e.g. "-defer 5" and "-wait 5" (or to 1 or even 0) or -nonap or + -allinput to keep up with these VNC clients at the expense of + increased system load. + * Heuristics are applied to try to determine if the X display is + currently in a Display Manager Greeter Login panel (e.g. GDM) If + so, x11vnc's creation of any windows and use of XFIXES are + delayed. This is to try to avoid x11vnc being killed after the + user logs in if the GDM KillInitClients=true is in effect. So one + does not need to set KillInitClients=false. Note that in recent + GDM the KillInitClients option has been removed. Also delayed is + the use of the XFIXES cursor fetching functionality; this avoids + an Xorg bug that causes Xorg to crash right after the user logs + in. + * A new option -findauth runs the FINDDISPLAY script that applies + heuristics that try to determine the XAUTHORITY file. The use of + '-auth guess' will use the XAUTHORITY that -findauth reveals. This + can be handy in with the lastest GDM where the ability to store + cookies in ~/.Xauthority has been removed. If x11vnc is running as + root (e.g. inetd) and you add -env FD_XDM=1 to the above -findauth + or -auth guess command lines, it will find the correct XAUTHORITY + for the given display (this works for XDM/GDM/KDM if the login + greeter panel is up or if someone has already logged into an X + session.) + * The FINDDISPLAY and FINDCREATEDISPLAY modes (i.e. "-display + WAIT:cmd=...", -find, -create) now work correctly for the + user-supplied login program scheme "-unixpw_cmd ...", as long as + the login program supports running commands specified in the + environment variable "RFB_UNIXPW_CMD_RUN" as the logged-in user. + The mode "-unixpw_nis ..." has also been made more consistent. + * The -stunnel option (like -ssl but uses stunnel as an external + helper program) now works with the -ssl "SAVE" and "TMP" special + certificate names. The -sslverify and -sslCRL options now work + correctly in -stunnel mode. Single port HTTPS connections are also + supported for this mode. + * There is an experimental Application Sharing mode that improves + upon the -id/-sid single window sharing: -appshare (run "x11vnc + -appshare -help" for more info.) It is still very primitive and + approximate, but at least it displays multiple top-level windows. + * The remote control command -R can be used to instruct x11vnc to + resend its most recent copy of the Clipboard, Primary, or + Cutbuffer selections: "x11vnc -R resend_clipboard", "x11vnc -R + resend_primary", and "x11vnc -R resend_cutbuffer". + * The fonts in the GUI (-gui) can now by set via environment + variables, e.g. -env X11VNC_FONT_BOLD='Helvetica -16 bold' and + -env X11VNC_FONT_FIXED='Courier -14'. + * The XDAMAGE mechanism is now automatically disabled for a period + of time if a game or screensaver generates too many XDAMAGE + rectangles per second. This avoids the X11 event queue from + soaking up too much memory. + * There is an experimental workaround: "-env X11VNC_WATCH_DX_DY=1" + that tries to avoid problems with poorly constructed menu themes + that place the initial position of the mouse cursor inside a menu + item's active zone. More information can be found here. + + + Here are some features that appeared in the 0.9.8 release (Jul/2009): + * Stability improvements to -threads mode. Running x11vnc this way + is more reliable now. Threaded operation sometimes gives better + interactive response and faster updates: try it out. The threaded + mode now supports multiple VNC viewers using the same VNC + encoding. The threaded mode can also yield a performance + enhancement in the many client case (e.g. class-room broadcast.) + We have tested with 30 to 50 simultaneous clients. See also + -reflect. + For simultaneous clients: the ZRLE encoding is thread safe on all + platforms, and the Tight and Zlib encodings are currently only + thread safe on Linux where thread local storage, __thread, is + used. If your non-Linux system and compiler support __thread one + can supply -DTLS=__thread to enable it. When there is only one + connected client, all encodings are safe on all platforms. Note + that some features (e.g. scroll detection and -ncache) may be + disabled or run with reduced functionality in -threads mode. + * Automatically tries to work around an Xorg server and GNOME bug + involving infinitely repeating keys when turning off key + repeating. Use -repeat if the automatic workaround fails. + * Improved reliability of the Single Port SSL VNC and HTTPS java + viewer applet delivery mechanism. + * The -clip mode works under -rawfb. + + + Here are some features that appeared in the 0.9.7 release (Mar/2009): + * Support for polling Linux Virtual Terminals (also called virtual + consoles) directly instead of using /dev/fb. The option to use is, + for example, "-rawfb vt2" for Virtual Terminal 2, etc. In this + case the special file /dev/vcsa2 is used to retrieve vt2's current + text. Text and colors are shown, but no graphics. + * Support for less than 8 bits per pixel framebuffers (e.g. 4 or 1 + bpp) in the -rawfb mode. + * The SSL enabled UltraVNC Java viewer applet now has a [Home] entry + in the "drives" drop down menu. This menu can be configured with + the ftpDropDown applet parameter. All of the applet parameters are + documented in classes/ssl/README. + * Experimental support for VirtualGL's TurboVNC (an enhanced + TightVNC for fast LAN high framerate usage.) + * The CUPS Terminal Services helper mode has been improved. + * Improvements to the -ncache_cr that allows smooth opaque window + motions using the 'copyrect' encoding when using -ncache mode. + * The -rmflag option enables a way to indicate to other processes + x11vnc has exited. + * Reverse connections using anonymous Diffie Hellman SSL encryption + now work. + + + Here are some features that appeared in the 0.9.6 release (Dec/2008): + * Support for VeNCrypt SSL/TLS encrypted connections. It is enabled + by default in the -ssl mode. VNC Viewers like vinagre, + gvncviewer/gtk-vnc, the vencrypt package, SSVNC, and others + support this encryption mode. It can also be used with the -unixpw + option to enable Unix username and password authentication + (VeNCrypt's "*Plain" modes.) A similar but older VNC security type + "ANONTLS" (used by vino) is supported as well. See the -vencrypt + and -anontls options for additional control. The difference + between x11vnc's normal -ssl mode and VeNCrypt is that the former + wraps the entire VNC connection in SSL (like HTTPS does for HTTP, + i.e. "vncs://") while VeNCrypt switches on the SSL/TLS at a + certain point during the VNC handshake. Use -sslonly to disable + both VeNCrypt and ANONTLS (vino.) + * The "-ssl ANON" option enables Anonymous Diffie-Hellman (ADH) key + exchange for x11vnc's normal SSL/TLS operation. Note that + Anonymous Diffie-Hellman uses encryption for privacy, but provides + no authentication and so is susceptible to Man-In-The-Middle + attacks (and so we do not recommend it: we prefer you use "-ssl + SAVE", etc. and have the VNC viewer verify the cert.) The ANONTLS + mode (vino) only supports ADH. VeNCrypt mode supports both ADH and + regular X509 SSL certificates modes. For these ADH is enabled by + default. See -vencrypt and -anontls for how to disable ADH. + * For x11vnc's SSL/TLS modes, one can now specify a Certificate + Revocation List (CRL) with the -sslCRL option. This will only be + useful for wide deployments: say a company-wide x11vnc SSL access + deployment using a central Certificate Authority (CA) via + -sslGenCA and -sslGenCert. This way if a user has his laptop lost + or stolen, you only have to revoke his key instead of creating a + new Certificate Authority and redeploying new keys to all users. + * The default SSL/TLS mode, "-ssl" (no pem file parameter supplied), + is now the same as "-ssl SAVE" and will save the generated + self-signed cert in "~/.vnc/certs/server.pem". Previously "-ssl" + would create a temporary self-signed cert that was discarded when + x11vnc exited. The reason for the change is to at least give the + chance for the VNC Viewer side (e.g. SSVNC) to remember the cert + to authenticate subsequent connections to the same x11vnc server. + Use "-ssl TMP" to regain the previous behavior. Use "-ssl + SAVE_NOPROMPT" to avoid being prompted about using passphrase when + the certificate is created. + * The option -http_oneport enables single-port HTTP connections via + the Java VNC Viewer. So, for example, the web browser URL + "http://myhost.org:5900" works the same as + "http://myhost.org:5800", but with the convenience of only + involving one port instead of two. This works for both unencrypted + connections and for SSH tunnels (see -httpsredir if the tunnel + port differs.) Note that HTTPS single-port operation in -ssl SSL + encrypted mode has been available since x11vnc version 0.8.3. + * For the -avahi/-zeroconf Service Advertizing mode, if x11vnc was + not compiled with the avahi-client library, then an external + helper program, either avahi-publish(1) (on Unix) or dns-sd(1) (on + Mac OS X), is used instead. + * The "-rfbport PROMPT" option will prompt the user via the GUI to + select the VNC port (e.g. 5901) to listen on, and a few other + basic settings. This enables a handy GUI mode for naive users: + x11vnc -gui tray=setpass -rfbport PROMPT -logfile $HOME/.x11vnc.log.%VNCDISP +LAY + suitable for putting in a launcher or menu, e.g. x11vnc.desktop. + The -logfile expansion is new too. In the GUI, the tray=setpass + Properties panel has been improved. + * The -solid solid background color option now works for the Mac OS + X console. + * The -reopen option instructs x11vnc to try to reopen the X display + if it is prematurely closed by, say, the display manager (e.g. + GDM.) + + + Here are some features that appeared in the 0.9.5 release (Oct/2008): + * Symmetric key encryption ciphers. ARC4, AES-128, AES-256, + blowfish, and 3des are supported. Salt and initialization vector + seeding is provided. These compliment the more widely used SSL and + SSH encryption access methods. SSVNC also supports these + encryption modes. + * Scaling differently along the X- and Y-directions. E.g. "-scale + 1280x1024" or "-scale 0.8x0.75" Also, "-geometry WxH" is an + alias for "-scale WxH" + * By having SSVNC version 1.0.21 or later available in your $PATH, + the -chatwindow option allows a UltraVNC Text Chat window to + appear on the local X11 console/display (this way the remote + viewer can chat with the person at the physical display; e.g. + helpdesk mode.) This also works on the Mac OS X console if the + Xquartz X11 server (enabled by default on leopard) is running for + the chatwindow. + * The HTTP Java viewer applet jar, classes/VncViewer.jar, has been + updated with an improved implementation based on the code used by + the classes/ssl applets. + + + Here are some features that appeared in the 0.9.4 release (Sep/2008): + * Improvements to the -find and -create X session finding or + creating modes: new desktop types and service redirection options. + Personal cupsd daemon and SSH port redirection helper for use with + SSVNC's Terminal Services feature. + * Reverse VNC connections via -connect work in the -find, -create + and related -display WAIT:... modes. + * Reverse VNC connections (either normal or SSL) can use a Web Proxy + or a SOCKS proxy, or a SSH connection, or even a CGI URL to make + the outgoing connection. See: -proxy. Forward connections can also + use: -ssh. + * Reverse VNC connections via the UltraVNC repeater proxy (either + normal or SSL) are supported. Use either the "-connect + repeater=ID:NNNN+host:port" or "-connect + repeater://host:port+ID:NNNN" notation. The SSVNC VNC viewer also + supports the UltraVNC repeater. Also, a perl repeater implemention + is here: ultravnc_repeater.pl + * Support for indexed colormaps (PseudoColor) with depths other than + 8 (from 1 to 16 now work) for non-standard hardware. Option + "-advertise_truecolor" to handle some workaround in this mode. + * Support for the ZYWRLE encoding, this is the RealVNC ZRLE encoding + extended to do motion video and photo regions more efficiently by + way of a Wavelet based transformation. + * The -finddpy and -listdpy utilities help to debug and configure + the -find, -create, and -display WAIT:... modes. + * Some automatic detection of screen resizes are handled even if the + -xrandr option is not supplied. + * The -autoport options gives more control over the VNC port x11vnc + chooses. + * The -ping secs can be used to help keep idle connections alive. + * Pasting of the selection/clipboard into remote applications (e.g. + Java) has been improved. + * Fixed a bug if a client disconnects during the 'speed-estimation' + phase. + * To unset Caps_Lock, Num_Lock and raise all keys in the X server + use -clear_all. + * Usage with dvorak keyboards has been improved. See also: -xkb. + * The Java Viewer applet source code is now included in the + x11vnc-0.9.*.tar.gz tarball. This means you can now build the Java + viewer applet jar files from source. If you stopped shipping the + Java viewer applet jar files due to lack of source code, you can + start again. + + + Here are some features that appeared in the 0.9.3 release (Oct/2007): + * Viewer-side pixmap caching. A large area of pixels (at least 2-3 + times as big as the framebuffer itself; the bigger the better... + default is 10X) is placed below the framebuffer to act as a + buffer/cache area for pixel data. The VNC CopyRect encoding is + used to move it around, so any viewer can take advantage of it. + Until we start modifying viewers you will be able to see the cache + area if you scroll down (this makes it easier to debug!) For + testing the default is "-ncache 10". The unix Enhanced TightVNC + Viewer ssvnc has a nice -ycrop option to help hide the pixel cache + area from view. + + + Here are some features that appeared in the 0.9.2 release (Jun/2007): + * Building with no OpenSSL libssl available (or with --without-ssl) + has been fixed. + * One can configure x11vnc via "./configure + --with-system-libvncserver" to use a system installed libvncserver + library instead of the one bundled in the release tarball. + * If UltraVNC file transfer or chat is detected, then VNC clients + are "pinged" more often to prevent these side channels from + becoming serviced too infrequently. + * In -unixpw mode in the username and password dialog no text will + be echoed if the first character sent is "Escape". This enables a + convenience feature in SSVNC to send the username and password + automatically. + + + Here are some features that appeared in the 0.9.1 release (May/2007): + * The UltraVNC Java viewer has been enhanced to support SSL (as the + TightVNC viewer had been previously.) The UltraVNC Java supports + ultravnc filetransfer, and so can be used as a VNC viewer on Unix + that supports ultravnc filetransfer. It is in the + classes/ssl/UltraViewerSSL.jar file (that is pointed to by + ultra.vnc.) The signed applet SignedUltraViewerSSL.jar version + (pointed to by ultrasigned.vnc) will be needed to access the local + drive if you are using it for file transfer via a Web browser. + Some other bugs in the UltraVNC Java viewer were fixed and a few + improvements to the UI made. + * A new Unix username login mode for VNC Viewers authenticated via a + Client SSL Certificate: "-users sslpeer=". The emailAddress + subject field is inspected for username@hostname and then acts as + though "-users +username" has been supplied. This way the Unix + username is identified by (i.e. simply extracted from) the Client + SSL Certificate. This could be useful with -find, -create and -svc + modes if you are also have set up and use VNC Client SSL + Certificate authentication. + * For external display finding/creating programs (e.g. WAIT:cmd=...) + if the VNC Viewer is authenticated via a Client SSL Certificate, + then that Certificate is available in the environment variable + RFB_SSL_CLIENT_CERT. + + + Here are some features that appeared in the 0.9 release (Apr/2007): + * VNC Service advertising via mDNS / ZeroConf / BonJour with the + Avahi client library. Enable via "-avahi" or "-zeroconf". + * Implementations of UltraVNC's TextChat, SingleWindow, and + ServerInput extensions (requires ultravnc viewer or ssvnc Unix + viewer.) They toggle the selection of a single window (-id), and + disable (friendly) user input and viewing (monitor blank) at the + VNC server. + * Short aliases "-find", "-create", "-svc", and "-xdmsvc" for + commonly used FINDCREATEDISPLAY usage modes. + * Reverse VNC connections (viewer listening) now work in SSL (-ssl) + mode. + * New options to control the Monitor power state and keyboard/mouse + grabbing: -forcedpms, -clientdpms, -noserverdpms, and -grabalways. + * A simple way to emulate inetd(8) to some degree via the "-loopbg" + option. + * Monitor the accuracy of XDAMAGE and apply "-noxdamage" if it is + not working well. OpenGL applications like like beryl and MythTv + have been shown to make XDAMAGE not work properly. + * For Java SSL connections involving a router/firewall port + redirection, an option -httpsredir to spare the user from needing + to include &PORT=NNN in the browser URL. + + + Here are some features that appeared in the 0.8.4 release (Feb/2007): + * Native Mac OS X Aqua/Quartz support. (i.e. OSXvnc alternative; + some activities are faster) + * A new login mode: "-display WAIT:cmd=FINDCREATEDISPLAY -unixpw + ..." that will Create a new X session (either virtual or real and + with or without a display manager, e.g. kdm) for the user if it + cannot find the user's X session display via the FINDDISPLAY + method. See the -svc and the -xdmsvc aliases. + * x11vnc can act as a VNC reflector/repeater using the "-reflect + host:N" option. Instead of polling an X display, the remote VNC + Server host:N is connected to and re-exported via VNC. This is + intended for use in broadcasting a display to many (e.g. > 16; + classroom or large demo) VNC viewers where bandwidth and other + resources are conserved by spreading the load over a number of + repeaters. + * Wireframe copyrect detection for local user activity (e.g. someone + sitting at the physical display moving windows) Use + -nowireframelocal to disable. + * The "-N" option couples the VNC Display number to the X Display + number. E.g. if your X DISPLAY is :2 then the VNC display will be + :2 (i.e. using port 5902.) If that port is taken x11vnc will exit. + * Option -nodpms to avoid problems with programs like KDE's + kdesktop_lock that keep restarting the screen saver every few + seconds. + * To automatically fix the common mouse motion problem on XINERAMA + (multi-headed) displays, the -xwarppointer option is enabled by + default when XINERAMA is active. + + If you have a Mac please try out the native Mac OS X support, build + with "./configure --without-x", or download a binary mentioned above, + (even if you don't plan on ever using it in this mode!), and let me + know how it went. Thanks. + + + Here are some features that appeared in the 0.8.3 release (Nov/2006): + * The -ssl option provides SSL encryption and authentication + natively via the www.openssl.org library. One can use from a + simple self-signed certificate server certificate up to full CA + and client certificate authentication schemes. + * Similar to -ssl, the -stunnel option starts up a SSL tunnel server + stunnel (that must be installed separately on the system: + stunnel.mirt.net ) to allow only encrypted SSL connections from + the network. + * The -sslverify option allows for authenticating VNC clients via + their certificates in either -ssl or -stunnel modes. + * Certificate creation and management tools are provide in the + -sslGenCert, -sslGenCA, and related options. + * An SSL enabled Java applet VNC Viewer applet is provided by x11vnc + in classes/ssl/VncViewer.jar. In addition to normal HTTP, the + applet may be loaded into the web browser via HTTPS (HTTP over + SSL.) (one can use the VNC port, e.g. https://host:5900/, or also + the separate -https port option.) A wrapper shell script + ss_vncviewer is also provided that sets up a stunnel client-side + tunnel on Unix systems. See Enhanced TightVNC Viewer (SSVNC) for + other SSL/SSH viewer possibilities. + * The -unixpw option supports Unix username and password + authentication (a simpler variant is the -unixpw_nis option that + works in environments where the encrypted passwords are readable, + e.g. NIS.) The -ssl or -localhost + -stunnel options are enforced + in this mode to prevent password sniffing. As a convenience, these + requirements are lifted if a SSH tunnel can be deduced (but + -localhost still applies.) + * Coupling -unixpw with "-display WAIT:cmd=FINDDISPLAY" or "-display + WAIT:cmd=FINDCREATEDISPLAY" provides a way to allow a user to + login with their UNIX password and have their display connected to + automatically. See the -svc and the -xdmsvc aliases. + * Hooks are provided in the -unixpw_cmd and "-passwdfile + cmd:,custom:..." options to allow you to supply your own + authentication and password lookup programs. + * x11vnc can be configured and built to not depend on X11 libraries + "./configure --without-x" for -rawfb only operation (e.g. embedded + linux console devices.) + * The -rotate option enables you to rotate or reflect the screen + before exporting via VNC. This is intended for use on handhelds + and other devices where the rotation orientation is not "natural". + * The "-ultrafilexfer" alias is provided and improved UltraVNC + filetransfer rates have been achieved. + * Under the "-connect_or_exit host" option x11vnc will exit + immediately unless the reverse connection to host succeeds. The + "-rfbport 0" option disables TCP listening for connections (useful + for this mode.) + * The "-rawfb rand" and "-rawfb none" options are useful for testing + automation scripts, etc., without requiring a full desktop. + * Reduced spewing of information at startup, use "-verbose" (also + "-v") to turn it back on for debugging or if you are going to send + me a problem report. + + Here are some Previous Release Notes + _________________________________________________________________ + + Some Notes: + + Both a client and a server: It is sometimes confusing to people that + x11vnc is both a client and a server at the same time. It is an X + client because it connects to the running X server to do the screen + polls. Think of it as a rather efficient "screenshot" program running + continuously. It is a server in the sense that it is a VNC server that + VNC viewers on the network can connect to and view the screen + framebuffer it manages. + + When trying to debug problems, remember to think of both roles. E.g. + "how is x11vnc connecting to the X server?", "how is the vncviewer + connecting to x11vnc?", "what permits/restricts the connection?". Both + links may have reachability, permission, and other issues. + + Network performance: Whether you are using Xvnc or x11vnc it is + always a good idea to have a solid background color instead of a + pretty background image. Each and every re-exposure of the background + must be resent over the network: better to have that background be a + solid color that compresses very well compared to a photo image. (This + is one place where the X protocol has an advantage over the VNC + protocol.) I suggest using xsetroot, dtstyle or similar utility to set + a solid background while using x11vnc. You can turn the pretty + background image back on when you are using the display directly. + Update: As of Feb/2005 x11vnc has the -solid [color] option that works + on recent GNOME, KDE, and CDE and also on classic X (background image + is on the root window.) Update: As of Oct/2007 x11vnc has the -ncache + option that does a reasonable job caching the background (and other) + pixmap data on the viewer side. + + I also find the TightVNC encoding gives the best response for my usage + (Unix <-> Unix over cable modem.) One needs a tightvnc-aware vncviewer + to take advantage of this encoding. + + TCP port issues: Notice the lines + 18/07/2003 14:36:31 Autoprobing selected port 5900 + PORT=5900 + + in the output. 5900 is the default VNC listening port (just like 6000 + is X11's default listening port.) Had port 5900 been taken by some + other application, x11vnc would have next tried 5901. That would mean + the viewer command above should be changed to vncviewer + far-away.east:1. You can force the port with the "-rfbport NNNN" + option where NNNN is the desired port number. If that port is already + taken, x11vnc will exit immediately. The "-N" option will try to match + the VNC display number to the X display. (also see the "SunRay + Gotcha" note below) + + Options: x11vnc has (far too) many features that may be activated + via its command line options. Useful options are, e.g., -scale to do + server-side scaling, and -rfbauth passwd-file to use VNC password + protection (the vncpasswd or storepasswd programs, or the x11vnc + -storepasswd option can be used to create the password file.) + + Algorithm: How does x11vnc do it? Rather brute-forcedly: it + continuously polls the X11 framebuffer for changes using + XShmGetImage(). When changes are discovered, it instructs libvncserver + which rectangular regions of the framebuffer have changed, and + libvncserver compresses the changes and sends them off to any + connected VNC viewers. A number of applications do similar things, + such as x0rfbserver, krfb, x0vncserver, vino. x11vnc uses a 32 x 32 + pixel tile model (the desktop is decomposed into roughly 1000 such + tiles), where changed tiles are found by pseudo-randomly polling 1 + pixel tall horizontal scanlines separated vertically by 32 pixels. + This is a surprisingly effective algorithm for finding changed + regions. For keyboard and mouse user input the XTEST extension is used + to pass the input events to the X server. To detect XBell "beeps" the + XKEYBOARD extension is used. If available, the XFIXES extension is + used to retrieve the current mouse cursor shape. Also, if available + the X DAMAGE extension is used to receive hints from the X server + where modified regions on the screen are. This greatly reduces the + system load when not much is changing on the screen and also improves + how quickly the screen is updated. + + Barbershop mirrors effect: What if x11vnc is started up, and + vncviewer is then started up on the same machine and displayed on the + same display x11vnc is polling? One might "accidentally" do this when + first testing out the programs. You get an interesting + recursive/feedback effect where vncviewer images keep popping up each + one contained in the previous one and slightly shifted a bit by the + window manager decorations. There will be an even more interesting + effect if -scale is used. Also, if the XKEYBOARD is supported and the + XBell "beeps" once, you get an infinite loop of beeps going off. + Although all of this is mildly exciting it is not much use: you will + normally run and display the viewer on a different machine! + _________________________________________________________________ + + Sun Ray Notes: + + You can run x11vnc on your (connected or disconnected) SunRay session. + Here are some notes on SunRay usage with x11vnc. + + _________________________________________________________________ + + Limitations: + + * Due to the polling nature, some activities (opaque window moves, + scrolling), can be pretty choppy/ragged and others (exposures of + large areas) slow. Experiment with interacting a bit differently + than you normally do to minimize the effects (e.g. do fullpage + paging rather than line-by-line scrolling, and move windows in a + single, quick motion.) Recent work has provided the + -scrollcopyrect and -wireframe speedups using the CopyRect VNC + encoding and other things, but they only speed up some activities, + not all. + * A rate limiting factor for x11vnc performance is that graphics + hardware is optimized for writing, not reading (x11vnc reads the + video framebuffer for the screen image data.) The difference can + be a factor of 10 to 1000, and so it usually takes about 0.5-1 sec + to read in the whole video hardware framebuffer (e.g. 5MB for + 1280x1024 at depth 24 with a read rate of 5-10MB/sec.) So whenever + activity changes most of the screen (e.g. moving or iconifying a + large window) there is a delay of 0.5-1 sec while x11vnc reads the + changed regions in. + A slow framebuffer read rate will often be the performance + bottleneck on a fast LAN (whereas on slower links the reduced + network bandwidth becomes the bottleneck.) + Note: A quick way to get a 2X speedup of this for x11vnc is to + switch your X server from depth 24 (32bpp) to depth 16 (16bpp.) + You get a 4X speedup going to 8bpp, but the lack of color cells is + usually unacceptable. + To get a sense of the read and write speeds of your video card, + you can run benchmarks like: "x11perf -getimage500", "x11perf + -putimage500", "x11perf -shmput500" and for XFree86 displays with + direct graphics access the "dga" command (press "b" to run the + benchmark and then after a few seconds press "q" to quit.) Even + this "dd if=/dev/fb0 of=/dev/null" often gives a good estimate. + x11vnc also prints out its estimate: + 28/02/2009 11:11:07 Autoprobing TCP port + 28/02/2009 11:11:07 Autoprobing selected port 5900 + 28/02/2009 11:11:08 fb read rate: 10 MB/sec + 28/02/2009 11:11:08 screen setup finished. + We have seen a few cases where the hardware fb read speed is + greater than 65 MB/sec: on high end graphics workstations from SGI + and Sun, and also from a Linux user using nvidia proprietary + drivers for his nvidia video card. Update 2008: thankfully, these + sped up drivers are becoming more common on Linux and *BSD systems + and that makes x11vnc run somewhat more quickly. Sometimes they + have a read rate of over 400 MB/sec. + On XFree86/Xorg it is actually possible to increase the + framebuffer read speed considerably (10-100 times) by using the + Shadow Framebuffer (a copy of the framebuffer is kept in main + memory and this can be read much more quickly.) To do this one + puts the line Option "ShadowFB" "true" in the Device section of + the /etc/X11/XF86Config or /etc/X11/xorg.conf file. Note that this + disables 2D acceleration at the physical display and so that might + be unacceptable if one plays games, etc. on the machine's local + display. Nevertheless this could be handy in some circumstances, + e.g. if the slower speed while sitting at the physical display was + acceptable (this seems to be true for most video cards these + days.) Unfortunately it does not seem shadowfb can be turned on + and off dynamically... + Another amusing thing one can do is use Xvfb as the X server, e.g. + "xinit $HOME/.xinitrc -- /usr/X11R6/bin/Xvfb :1 -screen 0 + 1024x768x16" x11vnc can poll Xvfb efficiently via main memory. + It's not exactly clear why one would want to do this instead of + using vncserver/Xvnc, (perhaps to take advantage of an x11vnc + feature, such as framebuffer scaling or built-in SSL encryption), + but we mention it because it may be of use for special purpose + applications. You may need to use the "-cc 4" option to force Xvfb + to use a TrueColor visual instead of DirectColor. See also the + description of the -create option that does all of this + automatically for you (be sure to install the Xvfb package, e.g. + apt-get install xvfb.) + Also, a faster and more accurate way is to use the "dummy" + Xorg/XFree86 device driver (or our Xdummy wrapper script.) See + this FAQ for details. + * Somewhat surprisingly, the X11 mouse (cursor) shape is write-only + and cannot be queried from the X server. So traditionally in + x11vnc the cursor shape stays fixed at an arrow. (see the "-cursor + X" and "-cursor some" options, however, for a partial hack for the + root window, etc.) However, on Solaris using the SUN_OVL overlay + extension, x11vnc can show the correct mouse cursor when the + -overlay option is also supplied. A similar thing is done on IRIX + as well when -overlay is supplied. + More generally, as of Dec/2004 x11vnc supports the new XFIXES + extension (in Xorg and Solaris 10) to query the X server for the + exact cursor shape, this works pretty well except that cursors + with transparency (alpha channel) need to approximated to solid + RGB values (some cursors look worse than others.) + * Audio from applications is of course not redirected (separate + redirectors do exist, e.g. esd, see the FAQ on this below.) The + XBell() "beeps" will work if the X server supports the XKEYBOARD + extension. (Note that on Solaris XKEYBOARD is disabled by default. + Passing +kb to Xsun enables it.) + * The scroll detection algorithm for the -scrollcopyrect option can + give choppy or bunched up transient output and occasionally + painting errors. + * Using -threads can expose some bugs/crashes in libvncserver. + + Please feel free to contact me if you have any questions, problems, or + comments about x11vnc, etc. Please be polite, thorough, and not + demanding (sadly, the number of people contacting me that are rude and + demanding is increasing dramatically.) + Also, some people ask if they can make a donation, see this link for + that. + +======================================================================= +http://www.karlrunge.com/x11vnc/faq.html: + + + x11vnc Home Donations + _________________________________________________________________ + + x11vnc FAQ: + + + [Building and Starting] + + Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed + (null)" or "Xlib: connection to ":0.0" refused by server Xlib: No + protocol specified" and then exits. What do I need to do? + + Q-2: I can't get x11vnc and/or libvncserver to compile. + + Q-3: I just built x11vnc successfully, but when I use it my keystrokes + and mouse button clicks are ignored (I am able to move the mouse + though.) + + Q-4: Help, I need to run x11vnc on Solaris 2.5.1 (or other old + Unix/Linux) and it doesn't compile! + + Q-5: Where can I get a precompiled x11vnc binary for my Operating + System? + + Q-6: Where can I get a VNC Viewer binary (or source code) for the + Operating System I will be viewing from? + + Q-7: How can I see all of x11vnc's command line options and + documentation on how to use them? + + Q-8: I don't like typing arcane command line options every time I + start x11vnc. What can I do? Is there a config file? Or a GUI? + + Q-9: How can I get the GUI to run in the System Tray, or at least be a + smaller, simpler icon? + + Q-10: How can I get x11vnc to listen on a different port besides the + default VNC port (5900)? + + Q-11: My Firewall/Router doesn't allow VNC Viewers to connect to + x11vnc. + + Q-12: Is it possible for a VNC Viewer and a VNC Server to connect to + each other even though both are behind Firewalls that block all + incoming connections? + + Q-13: Can I make x11vnc more quiet and also go into the background + after starting up? + + Q-14: Sometimes when a VNC viewer dies abruptly, x11vnc also dies with + the error message like: "Broken pipe". I'm using the -forever mode and + I want x11vnc to keep running. + + Q-15: The Windows TightVNC 1.3.9 Viewer cannot connect to x11vnc. + + Q-16: KDE's krdc VNC viewer cannot connect to x11vnc. + + Q-17: When I start x11vnc on an Alpha Tru64 workstation the X server + crashes! + + Q-18: When running x11vnc on an IBM AIX workstation after a few + minutes the VNC connection freezes. + + Q-19: Are there any build-time customizations possible, e.g. change + defaults, create a smaller binary, etc? + + [Win2VNC Related] + + Q-20: I have two separate machine displays in front of me, one Windows + the other X11: can I use x11vnc in combination with Win2VNC in + dual-screen mode to pass the keystrokes and mouse motions to the X11 + display? + + Q-21: I am running Win2VNC on my Windows machine and "x11vnc -nofb" on + Unix to pass keyboard and mouse to the Unix monitor. Whenever I start + Win2VNC it quickly disconnects and x11vnc says: + rfbProcessClientNormalMessage: read: Connection reset by peer + + Q-22: Can I run "x11vnc -nofb" on a Mac OS X machine to redirect mouse + and keyboard input to it from Windows and X11 machines via Win2VNC and + x2vnc, respectively? + + [Color Issues] + + Q-23: The X display I run x11vnc on is only 8 bits per pixel (bpp) + PseudoColor (i.e. only 256 distinct colors.) The x11vnc colors may + start out OK, but after a while they are incorrect in certain windows. + + Q-24: Color problems: Why are the colors for some windows incorrect in + x11vnc? BTW, my X display has nice overlay/multi-depth visuals of + different color depths: e.g. there are both depth 8 and 24 visuals + available at the same time. + + Q-25: I am on a high color system (depth >= 24) but I seem to have + colormap problems. They either flash or everything is very dark. + + Q-26: How do I figure out the window id to supply to the -id windowid + option? + + Q-27: Why don't menus or other transient windows come up when I am + using the -id windowid option to view a single application window? + + Q-28: My X display is depth 24 at 24bpp (instead of the normal depth + 24 at 32bpp.) I'm having lots of color and visual problems with x11vnc + and/or vncviewer. What's up? + + [Xterminals] + + Q-29: Can I use x11vnc to view and interact with an Xterminal (e.g. + NCD) that is not running UNIX and so x11vnc cannot be run on it + directly? + + Q-30: How do I get my X permissions (MIT-MAGIC-COOKIE file) correct + for a Unix/Linux machine acting as an Xterminal? + + [Sun Rays] + + Q-31: I'm having trouble using x11vnc with my Sun Ray session. + + [Remote Control] + + Q-32: How do I stop x11vnc once it is running in the background? + + Q-33: Can I change settings in x11vnc without having to restart it? + Can I remote control it? + + [Security and Permissions] + + Q-34: How do I create a VNC password for use with x11vnc? + + Q-35: Can I make it so -storepasswd doesn't show my password on the + screen? + + Q-36: Can I have two passwords for VNC viewers, one for full access + and the other for view-only access to the display? + + Q-37: Can I have as many full-access and view-only passwords as I + like? + + Q-38: Does x11vnc support Unix usernames and passwords? Can I further + limit the set of Unix usernames who can connect to the VNC desktop? + + Q-39: Can I supply an external program to provide my own custom login + method (e.g. Dynamic/One-time passwords or non-Unix (LDAP) usernames + and passwords)? + + Q-40: Why does x11vnc exit as soon as the VNC viewer disconnects? And + why doesn't it allow more than one VNC viewer to connect at the same + time? + + Q-41: Can I limit which machines incoming VNC clients can connect + from? + + Q-42: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) + support? + + Q-43: Can I have x11vnc only listen on one network interface (e.g. + internal LAN) rather than having it listen on all network interfaces + and relying on -allow to filter unwanted connections out? + + Q-44: Now that -localhost implies listening only on the loopback + interface, how I can occasionally allow in a non-localhost via the -R + allowonce remote control command? + + Q-45: Can I fine tune what types of user input are allowed? E.g. have + some users just be able to move the mouse, but not click or type + anything? + + Q-46: Can I prompt the user at the local X display whether the + incoming VNC client should be accepted or not? Can I decide to make + some clients view-only? How about running an arbitrary program to make + the decisions? + + Q-47: I start x11vnc as root because it is launched via inetd(8) or a + display manager like gdm(1). Can I have x11vnc later switch to a + different user? + + Q-48: I use a screen-lock when I leave my workstation (e.g. + xscreensaver or xlock.) When I remotely access my workstation desktop + via x11vnc I can unlock the desktop fine, but I am worried people will + see my activities on the physical monitor. What can I do to prevent + this, or at least make it more difficult? + + Q-49: Can I have x11vnc automatically lock the screen when I + disconnect the VNC viewer? + + [Encrypted Connections] + + Q-50: How can I tunnel my connection to x11vnc via an encrypted SSH + channel between two Unix machines? + + Q-51: How can I tunnel my connection to x11vnc via an encrypted SSH + channel from Windows using an SSH client like Putty? + + Q-52: How can I tunnel my connection to x11vnc via an encrypted SSL + channel using an external tool like stunnel? + + Q-53: Does x11vnc have built-in SSL tunneling? + + Q-54: How do I use VNC Viewers with built-in SSL tunneling? + + Q-55: How do I use the Java applet VNC Viewer with built-in SSL + tunneling when going through a Web Proxy? + + Q-56: Can Apache web server act as a gateway for users to connect via + SSL from the Internet with a Web browser to x11vnc running on their + workstations behind a firewall? + + Q-57: Can I create and use my own SSL Certificate Authority (CA) with + x11vnc? + + [Display Managers and Services] + + Q-58: How can I run x11vnc as a "service" that is always available? + + Q-59: How can I use x11vnc to connect to an X login screen like xdm, + GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X + session yet.) + + Q-60: Can I run x11vnc out of inetd(8)? How about xinetd(8)? + + Q-61: Can I have x11vnc advertise its VNC service and port via mDNS / + Zeroconf (e.g. Avahi) so VNC viewers on the local network can detect + it automatically? + + Q-62: Can I have x11vnc allow a user to log in with her UNIX username + and password and then have it find her X session display on that + machine and then attach to it? How about starting an X session if one + cannot be found? + + Q-63: Can I have x11vnc restart itself after it terminates? + + Q-64: How do I make x11vnc work with the Java VNC viewer applet in a + web browser? + + Q-65: Are reverse connections (i.e. the VNC server connecting to the + VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? + + Q-66: Can reverse connections be made to go through a Web or SOCKS + proxy or SSH? + + Q-67: Can x11vnc provide a multi-user desktop web login service as an + Apache CGI or PHP script? + + Q-68: Can I use x11vnc as a replacement for Xvnc? (i.e. not for a real + display, but for a virtual one I keep around.) + + Q-69: How can I use x11vnc on "headless" machines? Why might I want + to? + + [Resource Usage and Performance] + + Q-70: I have lots of memory, but why does x11vnc fail with shmget: + No space left on device or Minor opcode of failed request: 1 + (X_ShmAttach)? + + Q-71: How can I make x11vnc use less system resources? + + Q-72: How can I make x11vnc use MORE system resources? + + Q-73: I use x11vnc over a slow link with high latency (e.g. dialup + modem or broadband), is there anything I can do to speed things up? + + Q-74: Does x11vnc support the X DAMAGE Xserver extension to find + modified regions of the screen quickly and efficiently? + + Q-75: My OpenGL application shows no screen updates unless I supply + the -noxdamage option to x11vnc. + + Q-76: When I drag windows around with the mouse or scroll up and down + things really bog down (unless I do the drag in a single, quick + motion.) Is there anything to do to improve things? + + Q-77: Why not do something like wireframe animations to avoid the + windows "lurching" when being moved or resized? + + Q-78: Can x11vnc try to apply heuristics to detect when a window is + scrolling its contents and use the CopyRect encoding for a speedup? + + Q-79: Can x11vnc do client-side caching of pixel data? I.e. so when + that pixel data is needed again it does not have to be retransmitted + over the network. + + Q-80: Does x11vnc support TurboVNC? + + [Mouse Cursor Shapes] + + Q-81: Why isn't the mouse cursor shape (the little icon shape where + the mouse pointer is) correct as I move from window to window? + + Q-82: When using XFIXES cursorshape mode, some of the cursors look + really bad with extra black borders around the cursor and other cruft. + How can I improve their appearance? + + Q-83: In XFIXES mode, are there any hacks to handle cursor + transparency ("alpha channel") exactly? + + [Mouse Pointer] + + Q-84: Why does the mouse arrow just stay in one corner in my + vncviewer, whereas my cursor (that does move) is just a dot? + + Q-85: Can I take advantage of the TightVNC extension to the VNC + protocol where Cursor Positions Updates are sent back to all connected + clients (i.e. passive viewers can see the mouse cursor being moved + around by another viewer)? + + Q-86: Is it possible to swap the mouse buttons (e.g. left-handed + operation), or arbitrarily remap them? How about mapping button clicks + to keystrokes, e.g. to partially emulate Mouse wheel scrolling? + + [Keyboard Issues] + + Q-87: How can I get my AltGr and Shift modifiers to work between + keyboards for different languages? + + Q-88: When I try to type a "<" (i.e. less than) instead I get ">" + (i.e. greater than)! Strangely, typing ">" works OK!! + + Q-89: Extra Character Inserted, E.g.: When I try to type a "<" (i.e. + less than) instead I get "<," (i.e. an extra comma.) + + Q-90: I'm using an "international" keyboard (e.g. German "de", or + Danish "dk") and the -modtweak mode works well if the VNC viewer is + run on a Unix/Linux machine with a similar keyboard. But if I run + the VNC viewer on Unix/Linux with a different keyboard (e.g. "us") or + Windows with any keyboard, I can't type some keys like: "@", "$", + "<", ">", etc. How can I fix this? + + Q-91: When typing I sometimes get double, triple, or more of my + keystrokes repeated. I'm sure I only typed them once, what can I do? + + Q-92: The x11vnc -norepeat mode is in effect, but I still get repeated + keystrokes!! + + Q-93: After using x11vnc for a while, I find that I cannot type some + (or any) characters or my mouse clicks and drags no longer have any + effect, or they lead to strange effects. What happened? + + Q-94: The machine where I run x11vnc has an AltGr key, but the local + machine where I run the VNC viewer does not. Is there a way I can map + a local unused key to send an AltGr? How about a Compose key as well? + + Q-95: I have a Sun machine I run x11vnc on. Its Sun keyboard has just + one Alt key labelled "Alt" and two Meta keys labelled with little + diamonds. The machine where I run the VNC viewer only has Alt keys. + How can I send a Meta keypress? (e.g. emacs needs this) + + Q-96: Running x11vnc on HP-UX I cannot type "#" I just get a "3" + instead. + + Q-97: Can I map a keystroke to a mouse button click on the remote + machine? + + Q-98: How can I get Caps_Lock to work between my VNC viewer and + x11vnc? + + [Screen Related Issues and Features] + + Q-99: The remote display is larger (in number of pixels) than the + local display I am running the vncviewer on. I don't like the + vncviewer scrollbars, what I can do? + + Q-100: Does x11vnc support server-side framebuffer scaling? (E.g. to + make the desktop smaller.) + + Q-101: Does x11vnc work with Xinerama? (i.e. multiple monitors joined + together to form one big, single screen.) + + Q-102: Can I use x11vnc on a multi-headed display that is not Xinerama + (i.e. separate screens :0.0, :0.1, ... for each monitor)? + + Q-103: Can x11vnc show only a portion of the display? (E.g. for a + special purpose application or a very large screen.) + + Q-104: Does x11vnc support the XRANDR (X Resize, Rotate and + Reflection) extension? Whenever I rotate or resize the screen x11vnc + just seems to crash. + + Q-105: Independent of any XRANDR, can I have x11vnc rotate and/or + reflect the screen that the VNC viewers see? (e.g. for a handheld + whose screen is rotated 90 degrees.) + + Q-106: Why is the view in my VNC viewer completely black? Or why is + everything flashing around randomly? + + Q-107: I use Linux Virtual Terminals (VT's) to implement 'Fast User + Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, + Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those + keystrokes to switch between their sessions.) How come the view in a + VNC viewer connecting to x11vnc is either completely black or + otherwise all messed up unless the X session x11vnc is attached to is + in the active VT? + + Q-108: I am using x11vnc where my local machine has "popup/hidden + taskbars" and the remote display where x11vnc runs also has + "popup/hidden taskbars" and they interfere and fight with each other. + What can I do? + + Q-109: Help! x11vnc and my KDE screensaver keep switching each other + on and off every few seconds. + + Q-110: I am running the beryl 3D window manager (or compiz, MythTv, + Google Earth, or some other OpenGL app) and I do not get screen + updates in x11vnc. + + Q-111: Can I use x11vnc to view my VMWare session remotely? + + [Exporting non-X11 devices via VNC] + + Q-112: Can non-X devices (e.g. a raw framebuffer) be viewed (and even + controlled) via VNC with x11vnc? + + Q-113: Can I export the Linux Console (Virtual Terminals) via VNC + using x11vnc? + + Q-114: Can I export via VNC a Webcam or TV tuner framebuffer using + x11vnc? + + Q-115: Can I connect via VNC to a Qt-embedded/Qtopia application + running on my handheld or PC using the Linux console framebuffer (i.e. + not X11)? + + Q-116: Now that non-X11 devices can be exported via VNC using x11vnc, + can I build it with no dependencies on X11 header files and libraries? + + Q-117: Does x11vnc support Mac OS X Aqua/Quartz displays natively + (i.e. no X11 involved)? + + Q-118: Can x11vnc be used as a VNC reflector/repeater to improve + performance for the case of a large number of simultaneous VNC viewers + (e.g. classroom broadcasting or a large demo)? + + Q-119: Can x11vnc be used during a Linux, Solaris, etc. system + Installation so the Installation can be done remotely? + + [Misc: Clipboard, File Transfer/Sharing, Printing, Sound, Beeps, + Thanks, etc.] + + Q-120: Does the Clipboard/Selection get transferred between the + vncviewer and the X display? + + Q-121: Can I use x11vnc to record a Shock Wave Flash (or other format) + video of my desktop, e.g. to record a tutorial or demo? + + Q-122: Can I transfer files back and forth with x11vnc? + + Q-123: Which UltraVNC extensions are supported? + + Q-124: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for + Unix? I.e. something very simple for a naive user to initiate a + reverse vnc connection from their Unix desktop to a helpdesk + operator's VNC Viewer. + + Q-125: Can I (temporarily) mount my local (viewer-side) Windows/Samba + File share on the machine where x11vnc is running? + + Q-126: Can I redirect CUPS print jobs from the remote desktop where + x11vnc is running to a printer on my local (viewer-side) machine? + + Q-127: How can I hear the sound (audio) from the remote applications + on the desktop I am viewing via x11vnc? + + Q-128: Why don't I hear the "Beeps" in my X session (e.g. when typing + tput bel in an xterm)? + + Q-129: Does x11vnc work with IPv6? + + Q-130: Thanks for your program or for your help! Can I make a + donation? + _________________________________________________________________ + + + [Building and Starting] + + Q-1: I can't get x11vnc to start up. It says "XOpenDisplay failed + (null)" or "Xlib: connection to ":0.0" refused by server Xlib: No + protocol specified" and then exits. What do I need to do? + + For the former error, you need to specify the X display to connect to + (it also needs to be on the same machine the x11vnc process is to run + on.) Set your DISPLAY environment variable (or use the -display + option) to specify it. Nearly always the correct value will be ":0" + (in fact, x11vnc will now assume :0 if given no other information.) + + + For the latter error, you need to set up the X11 permissions + correctly. + + To make sure X11 permissions are the problem do this simple test: + while sitting at the physical X display open a terminal window + (gnome-terminal, xterm, etc.) You should be able to run x11vnc + successfully without any need for special steps or command line + options in that terminal (i.e. just type "x11vnc".) If that works OK + then you know X11 permissions are the only thing preventing it from + working when you try to start x11vnc via, say, a remote shell. + + How to Solve: See the xauth(1), Xsecurity(7), and xhost(1) man pages + or this Howto for much info on X11 permissions. For example, you may + need to set your XAUTHORITY environment variable (or use the -auth + option) to point to the correct MIT-MAGIC-COOKIE file (e.g. + /home/joe/.Xauthority or /var/gdm/:0.Xauth or /var/lib/kdm/A:0-crWk72K + or /tmp/.gdmzndVlR, etc, etc.), or simply be sure you run x11vnc as + the correct user (i.e. the user who is logged into the X session you + wish to view.) + + Note: The MIT cookie file contains the secret key that allows x11vnc + to connect to the desired X display. + + If, say, sshd has set XAUTHORITY to point to a random file it has + created for X forwarding that will cause problems. (Under some + circumstances even su(1) and telnet(1) can set XAUTHORITY. See also + the gdm parameter NeverPlaceCookiesOnNFS that sets XAUTHORITY to a + random filename in /tmp for the whole X session.) + + Running x11vnc as root is often not enough: you need to know where the + MIT-MAGIC-COOKIE file for the desired X display is. + + Example solution: + x11vnc -display :0 -auth /var/gdm/:0.Xauth + + (this is for the display manager gdm and requires root permission to + read the gdm cookie file, see this faq for other display manager + cookie file names.) + + Note as of Feb/2007 you can also try the -find option instead of + "-display ..." and see if that finds your display and Xauthority. + + Less safe, but to avoid figuring out where the correct XAUTHORITY file + is, if the person sitting at the physical X session types "xhost + +localhost" then one should be able to attach x11vnc to the session + (from the same machine.) The person could then type "xhost -localhost" + after x11vnc has connected to go back to the default permissions. + Also, for some situations the "-users lurk=" option may soon be of use + (please read the documentation on the -users option.) + + To test out your X11 permissions from a remote shell, set DISPLAY and + possibly XAUTHORITY (see your shell's man page, bash(1), tcsh(1), on + how to set environment variables) and type xdpyinfo in the same place + you will be typing (or otherwise running) x11vnc. If information is + printed out about the X display (screen sizes, supported extensions, + color visuals info) that means the X11 permissions are set up + properly: xdpyinfo successfully connected to DISPLAY! You could also + type xclock and make sure no errors are reported (a clock should + appear on the X display, press Ctrl-C to stop it.) If these work, then + typing "x11vnc" in the same environment should also work. + + Important: if you cannot get your X11 permissions so that the xdpyinfo + or xclock tests work, x11vnc also will not work (all of these X + clients must be allowed to connect to the X server to function + properly.) + + Firewalls: Speaking of permissions, it should go without saying that + the host-level firewall will need to be configured to allow + connections in on a port. E.g. 5900 (default VNC port) or 22 (default + SSH port for tunnelling VNC.) Most systems these days have firewalls + turned on by default, so you will actively have to do something to + poke a hole in the firewall at the desired port number. See your + system administration tool for Firewall settings (Yast, Firestarter, + etc.) + + + Q-2: I can't get x11vnc and/or libvncserver to compile. + + Make sure you have gcc (or other C compiler) and all of the required + libraries and the corresponding -dev/-devel packages installed. These + include Xorg/XFree86, libX11, libjpeg, libz, libssl, ... and don't + forget the devs: libjpeg-dev, libssl-dev ... + + The most common build problem that people encounter is that the + necessary X11 libraries are installed on their system however it does + not have the corresponding -dev/-devel packages installed. These dev + packages include C header files and build-time .so symlink. It is a + shame the current trend in distros is to not install the dev package + by default when the the library runtime package is installed... (it + diminishes the power of open source) + + As of Nov/2006 here is a list of libraries that x11vnc usually likes + to use: +libc.so libX11.so libXtst.so libXext.so +libXfixes.so libXdamage.so libXinerama.so libXrandr.so +libz.so libjpeg.so libpthread.so +libssl.so libcrypto.so libcrypt.so + + although x11vnc will be pretty usable with the subset: libc.so, + libX11.so, libXtst.so, libXext.so, libz.so, and libjpeg.so. + + After running the libvncserver configure, carefully examine the output + and the messages in the config.log file looking for missing + components. For example, if the configure output looks like: + checking how to run the C preprocessor... gcc -E + checking for X... no + checking for XkbSelectEvents in -lX11... no + checking for XineramaQueryScreens in -lXinerama... no + checking for XTestFakeKeyEvent in -lXtst... no + + or even worse: + checking for C compiler default output file name... configure: error: + C compiler cannot create executables + See `config.log' for more details. + + there is quite a bit wrong with the build environment. Hopefully + simply adding -dev packages and/or gcc or make will fix it. + + For Debian the list seems to be: + gcc + make + libc6-dev + libjpeg8-dev (formerly libjpeg62-dev) + libx11-dev + x11proto-core-dev (formerly x-dev) + libxext-dev + libxtst-dev + libxdamage-dev + libxfixes-dev + libxrandr-dev + libxinerama-dev + libxss-dev (formerly xlibs-static-dev) + zlib1g-dev + libssl-dev + libavahi-client-dev + linux-libc-dev (only needed for linux console rawfb support) + + Note that depending on your OS version the above names may have been + changed and/or additional packages may be needed. + + For Redhat the list seems to be: + gcc + make + glibc-devel + libjpeg-devel + libX11-devel + xorg-x11-proto-devel + libXdamage-devel + libXfixes-devel + libXrandr-devel + zlib-devel + openssl-devel + avahi-devel + kernel-headers (only needed for linux console rawfb support) + + For other distros or OS's the package names may not be the same but + will look similar. Also, distros tend to rename packages as well so + the above list may be out of date. So only use the above lists as + hints for the package names that are needed. + + Have a look at Misc. Build Problems for additional fixes. + + Note: there is growing trend in Linux and other distros to slice up + core X11 software into more and smaller packages. So be prepared for + more headaches compiling software... + + + Q-3: I just built x11vnc successfully, but when I use it my keystrokes + and mouse button clicks are ignored (I am able to move the mouse + though.) + + This is most likely due to you not having a working build environment + for the XTEST client library libXtst.so. The library is probably + present on your system, but the package installing the build header + file is missing. + + If you were watching carefully while configure was running you would + have seen: + checking for XTestFakeKeyEvent in -lXtst... no + + The solution is to add the necessary build environment package (and + the library package if that is missing too.) On Debian the build + package is libxtst-dev. Other distros/OS's may have it in another + package. + + x11vnc will build without support for this library (e.g. perhaps one + wants a view-only x11vnc on a stripped down or embedded system...) And + at runtime it will also continue to run even if the X server it + connects to does not support XTEST. In both cases it cannot inject + keystrokes or button clicks since XTEST is needed for that (it can + still move the mouse pointer using the X API XWarpPointer().) + + You will see a warning message something like this at run time: + 20/03/2005 22:33:09 WARNING: XTEST extension not available (either missing fr +om + 20/03/2005 22:33:09 display or client library libXtst missing at build time +.) + 20/03/2005 22:33:09 MOST user input (pointer and keyboard) will be DISCARDE +D. + 20/03/2005 22:33:09 If display does have XTEST, be sure to build x11vnc wit +h + 20/03/2005 22:33:09 a working libXtst build environment (e.g. libxtst-dev, + 20/03/2005 22:33:09 or other packages.) + 20/03/2005 22:33:09 No XTEST extension, switching to -xwarppointer mode for + 20/03/2005 22:33:09 pointer motion input. + + Also, as of Nov/2006 there will be a configure build time warning as + well: + ... + checking for XFixesGetCursorImage in -lXfixes... yes + checking for XDamageQueryExtension in -lXdamage... yes + configure: WARNING: + ========================================================================== + A working build environment for the XTEST extension was not found (libXtst). + An x11vnc built this way will be only barely usable. You will be able to + move the mouse but not click or type. There can also be deadlocks if an + application grabs the X server. + + It is recommended that you install the necessary development packages + for XTEST (perhaps it is named something like libxtst-dev) and run + configure again. + ========================================================================== + + + Q-4: Help, I need to run x11vnc on Solaris 2.5.1 (or other old + Unix/Linux) and it doesn't compile! + + We apologize that x11vnc does not build cleanly on older versions of + Solaris, Linux, etc.: very few users are on these old releases. + + We have heard that since Dec/2004 a Solaris 2.6 built x11vnc will run + on Solaris Solaris 2.5 and 2.5.1 (since a workaround for XConvertCase + is provided.) + + In any event, here is a workaround for Solaris 2.5.1 (and perhaps + earlier and perhaps non-Solaris): + + First use the environment settings (CPPFLAGS, LDFLAGS, etc.) in the + above Solaris build script to run the configure command. That should + succeed without failure. Then you have to hand edit the autogenerated + rfb/rfbconfig.h file in the source tree, and just before the last + #endif at the bottom of that file insert these workaround lines: +struct timeval _tmp_usleep_tv; +#define usleep(x) \ + _tmp_usleep_tv.tv_sec = (x) / 1000000; \ + _tmp_usleep_tv.tv_usec = (x) % 1000000; \ + select(0, NULL, NULL, NULL, &_tmp_usleep_tv); +int gethostname(char *name, int namelen); +long random(); +int srandom(unsigned int seed); +#undef LIBVNCSERVER_HAVE_LIBPTHREAD +#define SHUT_RDWR 2 +typedef unsigned int in_addr_t; +#define snprintf(a, n, args...) sprintf((a), ## args) + + Then run make with the Solaris build script environment, everything + should compile without problems, and the resulting x11vnc binary + should work OK. If some non-x11vnc related programs fail (e.g. test + programs) and the x11vnc binary is not created try "make -k" to have + it keep going. Similar sorts of kludges in rfb/rfbconfig.h can be done + on other older OS (Solaris, Linux, ...) releases. + + Here are some notes for similar steps that need to be done to build on + SunOS 4.x + + Please let us know if you had to use the above workaround (and whether + it worked or not.) If there is enough demand we will try to push clean + compilations back to earlier Solaris, Linux, etc, releases. + + + Q-5: Where can I get a precompiled x11vnc binary for my Operating + System? + + Hopefully the build steps above and FAQ provide enough info for a + painless compile for most environments. Please report problems with + the x11vnc configure, make, etc. on your system (if your system is + known to compile other GNU packages successfully.) + + There are precompiled x11vnc binaries built by other groups that are + available at the following locations: + Slackware: (.tgz) http://www.linuxpackages.net/ + + SuSE: (.rpm) http:/software.opensuse.org/ Gentoo: (info) + http://gentoo-wiki.com/ and http://gentoo-portage.com/ FreeBSD: (.tbz) + http://www.freebsd.org/ http://www.freshports.org/net/x11vnc NetBSD: + (src) http://pkgsrc.se/x11/x11vnc OpenBSD: (.tgz) http://openports.se/ + Arch Linux: (.tgz) http://www.archlinux.org/ Nokia 770 (.deb) + http://mike.saunby.googlepages.com/x11vncfornokia7702 Sharp Zaurus + http://www.focv.com/ Debian: (.deb) http://packages.debian.org/x11vnc + Redhat/Fedora: (.rpm) http://packages.sw.be/x11vnc RPMforge + http://dag.wieers.com/rpm/packages/x11vnc/ (N.B.: unmaintained after + 0.9.3) Solaris: (pkg) http://www.sunfreeware.com/ + + If the above binaries don't work and building x11vnc on your OS fails + (and all else fails!) you can try one of My Collection of x11vnc + Binaries for various OS's and x11vnc releases. + + As a general note, the x11vnc program is simple enough you don't + really need to install a package: the binary will in most cases work + as is and from any location (as long as your system libraries are not + too old, etc.) So, for Linux distributions that are not one of the + above, the x11vnc binary from the above packages has a good chance of + working. You can "install" it by just copying the x11vnc binary to the + desired directory in your PATH. Tip on extracting files from a Debian + package: extract the archive via a command like: "ar x + x11vnc_0.6-2_i386.deb" and then you can find the binary in the + resulting data.tar.gz tar file. Also, rpm2cpio(1) is useful in + extracting files from rpm packages. + + If you use a standalone binary like this and also want x11vnc to serve + up the Java VNC Viewer jar file (either SSL enabled or regular one), + then you will need to extract the classes subdirectory from the source + tarball and point x11vnc to it via the -httpdir option. E.g.: + x11vnc -httpdir /path/to/x11vnc-0.9.9/classes/ssl ... + + + Q-6: Where can I get a VNC Viewer binary (or source code) for the + Operating System I will be viewing from? + + To obtain VNC viewers for the viewing side (Windows, Mac OS, or Unix) + try here: + * http://www.tightvnc.com/download.html + * http://www.realvnc.com/download-free.html + * http://sourceforge.net/projects/cotvnc/ + * http://www.ultravnc.com/ + * Our Enhanced TightVNC Viewer (SSVNC) + + [ssvnc.gif] + + + Q-7: How can I see all of x11vnc's command line options and + documentation on how to use them? + + Run: x11vnc -opts to list just the option names or run: x11vnc + -help for long descriptions about each option. The output is listed + here as well. Yes, x11vnc does have a lot of options, doesn't it... + + + Q-8: I don't like typing arcane command line options every time I + start x11vnc. What can I do? Is there a config file? Or a GUI? + + You could create a shell script that calls x11vnc with your options: +#!/bin/sh +# +# filename: X11vnc (i.e. not "x11vnc") +# It resides in a directory in $PATH. "chmod 755 X11vnc" has been run on it. +# +x11vnc -wait 50 -localhost -rfbauth $HOME/.vnc/passwd -display :0 $* + + a similar thing can be done via aliases in your shell (bash, tcsh, + csh, etc..) + + Or as of Jun/2004 you can use the simple $HOME/.x11vncrc config file + support. If that file exists, each line is taken as a command line + option. E.g. the above would be: +# this is a comment in my ~/.x11vncrc file +wait 50 # this is a comment to the end of the line. +-localhost # note: the leading "-" is optional. +rfbauth /home/fred/.vnc/passwd +display :0 + + As of Dec/2004 there is now a simple Tcl/Tk GUI based on the + remote-control functionality ("-R") that was added. The /usr/bin/wish + program is needed for operation. The gui is not particularly + user-friendly, it just provides a point and click mode to set all the + many x11vnc parameters and obtain help on them. It is also very useful + for testing. See the -gui option for more info. Examples: "x11vnc ... + -gui" and "x11vnc ... -gui other:0" in the latter case the gui is + displayed on other:0, not the X display x11vnc is polling. There is + also a "-gui tray" system tray mode. + + [tkx11vnc.gif] + + NOTE: You may need to install the "wish" or "tk" or "tk8.4" package + for the gui mode to work (the package name depends on your OS/distro.) + The tcl/tk "wish" interpreter is used. In debian (and so ubuntu too) + one would run "apt-get install tk" or perhaps "apt-get install tk8.4" + + + Q-9: How can I get the GUI to run in the System Tray, or at least be a + smaller, simpler icon? + + As of Jul/2005 the gui can run in a more friendly small icon mode + "-gui icon" or in the system tray: "-gui tray". It has balloon status, + a simple menu, and a Properities dialog. The full, complicated, gui is + only available under "Advanced". Other improvements were added as + well. Try "Misc -> simple_gui" for a gui with fewer esoteric menu + items. + + If the gui fails to embed itself in the system tray, do a retry via + "Window View -> icon" followed by "Window View -> tray" with the popup + menu. + + For inexperienced users starting up x11vnc and the GUI while sitting + at the physical X display (not remotely), using something like "x11vnc + -display :0 -gui tray=setpass" might be something for them that they + are accustomed to in a Desktop environment (it prompts for an initial + password, etc.) This is a basic "Share My Desktop" usage mode. + + As of Nov/2008 in x11vnc 0.9.6 there is a desktop menu item + (x11vnc.desktop) that runs this command: + x11vnc -gui tray=setpass -rfbport PROMPT -logfile %HOME/.x11vnc.log.%VNCDISP +LAY + + which also prompts for which VNC port to use and a couple other + parameters. + + + Q-10: How can I get x11vnc to listen on a different port besides the + default VNC port (5900)? + + Use something like, e.g., "x11vnc -rfbport 5901" to force it to use + port 5901 (this is VNC display :1.) If something else is using that + port x11vnc will exit immediately. If you do not supply the -rfbport + option, it will autoprobe starting at 5900 and work its way up to 5999 + looking for a free port to listen on. In that case, watch for the + PORT=59xx line to see which port it found, then subtract 5900 from it + for the VNC display number to enter into the VNC Viewer(s). + + The "-N" option will try to match the VNC display number to the X + display (e.g. X11 DISPLAY of :5 (port 6005) will have VNC display :5 + (port 5905).) + + Also see the "-autoport n" option to indicated at which value the auto + probing should start at. + + + Q-11: My Firewall/Router doesn't allow VNC Viewers to connect to + x11vnc. + + See the Firewalls/Routers discussion. + + + Q-12: Is it possible for a VNC Viewer and a VNC Server to connect to + each other even though both are behind Firewalls that block all + incoming connections? + + This is very difficult or impossible to do unless a third machine, + reachable by both, is used as a relay. So we assume a third machine is + somehow being used as a relay. + + (Update: It may be possible to do "NAT-2-NAT" without a relay machine + by using a UDP tunnel such as http://samy.pl/pwnat/. All that is + required is that both NAT firewalls allow in UDP packets from an IP + address to which a UDP packet has recently been sent to. If you try it + out let us know how it went.) + + In the following discussion, we will suppose port 5950 is being used + on the relay machine as the VNC port for the rendezvous. + + A way to rendezvous is to have the VNC Server start a reverse + connection to the relay machine: + x11vnc -connect third-machine.net:5950 ... + + and the VNC viewer forward connects as usual: + vncviewer third-machine.net:50 + + Or maybe two ports would be involved, e.g. the viewer goes to display + :51 (5951.) It depends on the relay software being used. + + What software to run on third-machine? A TCP relay of some sort could + be used... Try a google search on "tcp relay" or "ip relay". However, + note that this isn't a simple redirection because it hooks up two + incoming connections. You can look at our UltraVNC repeater + implementation ultravnc_repeater.pl for ideas and possibly to + customize. + + Also, if you are not the admin of third-machine you'd have to convince + the owner to allow you to install this software (and he would likely + need to open his server's firewall to allow the port through.) + + It is recommended that SSL is used for encryption (e.g. "-ssl SAVE") + when going over the internet. + + We have a prototype for performing a rendezvous via a Web Server + acting as the relay machine. Download the vncxfer CGI script and see + the instructions at the top. + + Once that CGI script is set up on the website, both users go to, say, + http://somesite.com/vncxfer (or maybe a "/cgi-bin" directory or ".cgi" + suffix must be used.) Previously, both have agreed on the same session + name (say by phone or email) , e.g. "5cows", and put that into the + entry form on the vncxfer starting page (hopefully separated by a few + seconds, so the relay helper can fully start up at the first request.) + + The page returned tells them the hostname and port number and possible + command to use for forward (VNC Viewer) and reverse (VNC Server, i.e. + x11vnc) connections as described above. + + Also since Oct/2007, x11vnc can connect directly (no web browser), + like this: + x11vnc ... -connect localhost:0 -proxy 'http://somesite.com/vncxfer?session= +5cows&' + + Unfortunately the prototype requires that the Web server's firewall + allow in the port (e.g. 5950) used for the rendezvous. Most web + servers are not configured to do this, so you would need to ask the + admin to do this for you. Nearly all free webspace sites, e.g. + www.zendurl.com, will not allow your CGI script to be an open relay + like this. (If you find one that does allow this, let me know!) + + Maybe someday a clever trick will be thought up to relax the listening + port requirement (e.g. use HTTP/CGI itself for the transfer... it is + difficult to emulate a full-duplex TCP connection with them.) + + See also the Firewalls/Routers discussion and Reverse Connection Proxy + discussion. + + + SSH method: If both users (i.e. one on Viewer-side and the other on + x11vnc server side) have SSH access to a common machine on the + internet (or otherwise mutually reachable), then SSH plumbing can be + used to solve this problem. The users create SSH tunnels going through + the SSH login machine. + + Instead of assuming port 5900 is free on the SSH machine, we will + assume both users agreed to use 5933. This will illustrate how to use + a different port for the redir. It could be any port, what matters is + that both parties refer to the same one. + + Set up the Tunnel from the VNC Server side: + ssh -t -R 5933:localhost:5900 user@third-machine.net + + Set up the Tunnel from the VNC Viewer side: + ssh -t -L 5900:localhost:5933 user@third-machine.net + + Run Server on the VNC Server side: + x11vnc -rfbport 5900 -localhost ... + + Run Viewer on the VNC Viewer side: + vncviewer -encodings "copyrect tight zrle hextile" localhost:0 + + (we assume the old-style -encodings option needs to be used. See here + for details.) + + If the SSH machine has been configured (see sshd_config(5)) with the + option GatewayPorts=yes, then the tunnel set up by the VNC Server will + be reachable directly by the VNC viewer (as long as the SSH machine's + firewall does not block the port, 5933 in this example.) So in that + case the Viewer side does not need to run any ssh command, but rather + only runs: + vncviewer third-machine.net:33 + + In this case we recommend SSL be used for encryption. + + The creation of both tunnels can be automated. As of Oct/2007 the -ssh + x11vnc option is available and so only this command needs to be run on + the VNC Server side: + x11vnc -ssh user@third-machine.net:33 ... + + (the SSH passphrase may need to be supplied.) + + To automate on the VNC Viewer side, the user can use the Enhanced + TightVNC Viewer (SSVNC) by: + * Clicking on 'Use SSH' + * Entering user@third-machine.net:33 into 'VNC Host:Display' entry + box + * Clicking on 'Connect' + + As above, if the SSH GatewayPorts=yes setting is configured the Viewer + side doesn't need to create a SSH tunnel. In SSVNC the Viewer user + could instead select 'Use SSL' and then, e.g., on the Server side + supply "-ssl SAVE" to x11vnc. Then end-to-end SSL encryption would be + used (in addition to the SSH encryption on the Server-side leg.) + + + Q-13: Can I make x11vnc more quiet and also go into the background + after starting up? + + Use the -q and -bg options, respectively. (also: -quiet is an alias + for -q) + + Note that under -bg the stderr messages will be lost unless you use + the "-o logfile" option. + + + Q-14: Sometimes when a VNC viewer dies abruptly, x11vnc also dies with + the error message like: "Broken pipe". I'm using the -forever mode and + I want x11vnc to keep running. + + As of Jan/2004 the SIGPIPE signal is ignored. So if a viewer client + terminates abruptly, libvncserver will notice on the next I/O + operation and will close the connection and continue on. + + Up until of Apr/2004 the above fix only works for BSD signal systems + (Linux, FreeBSD, ...) For SYSV systems there is a workaround in place + since about Jun/2004. + + + Q-15: The Windows TightVNC 1.3.9 Viewer cannot connect to x11vnc. + + This appears to be fixed in x11vnc version 0.9 and later. If you need + to use an earlier version of x11vnc, try using the "-rfbversion 3.7" + option. In general sometimes one can get a misbehaving viewer to work + by supplying rfb versions 3.7 or 3.3. + + + Q-16: KDE's krdc VNC viewer cannot connect to x11vnc. + + This has been fixed in x11vnc version 0.8.4. More info here, here, and + here. + + + Q-17: When I start x11vnc on an Alpha Tru64 workstation the X server + crashes! + + This is a bug in the X server obviously; an X client should never be + able to crash it. + + The problem seems to be with the RECORD X extension and so a + workaround is to use the "-noxrecord" x11vnc command line option. + + + Q-18: When running x11vnc on an IBM AIX workstation after a few + minutes the VNC connection freezes. + + One user reports when running x11vnc on AIX 5.3 in his CDE session + after a few minutes or seconds x11vnc will "freeze" (no more updates + being sent, etc.) The freezing appeared to be worse for versions later + than 0.9.2. + + The problem seems to be with the RECORD X extension on AIX and so a + workaround is to use the "-noxrecord" x11vnc command line option. The + user found no freezes occurred when using that option. + + + Q-19: Are there any build-time customizations possible, e.g. change + defaults, create a smaller binary, etc? + + There are some options. They are enabled by adding something like + -Dxxxx=1 to the CPPFLAGS environment variable before running configure + (see the build notes for general background.) +/* + * Mar/2006 + * Build-time customization via CPPFLAGS. + * + * Summary of options to include in CPPFLAGS for custom builds: + * + * -DVNCSHARED to have the vnc display shared by default. + * -DFOREVER to have -forever on by default. + * -DNOREPEAT=0 to have -repeat on by default. + * -DADDKEYSYMS=0 to have -noadd_keysyms the default. + * + * -DREMOTE_DEFAULT=0 to disable remote-control on by default (-yesremote.) + * -DREMOTE_CONTROL=0 to disable remote-control mechanism completely. + * -DEXTERNAL_COMMANDS=0 to disable the running of all external commands. + * -DFILEXFER=0 disable filexfer. + * + * -DHARDWIRE_PASSWD=... hardwired passwords, quoting necessary. + * -DHARDWIRE_VIEWPASSWD=... + * -DNOPW=1 make -nopw the default (skip warning) + * -DUSEPW=1 make -usepw the default + * -DPASSWD_REQUIRED=1 exit unless a password is supplied. + * -DPASSWD_UNLESS_NOPW=1 exit unless a password is supplied and no -nopw. + * + * -DWIREFRAME=0 to have -nowireframe as the default. + * -DWIREFRAME_COPYRECT=0 to have -nowirecopyrect as the default. + * -DWIREFRAME_PARMS=... set default -wirecopyrect parameters. + * -DSCROLL_COPYRECT=0 to have -noscrollcopyrect as the default. + * -DSCROLL_COPYRECT_PARMS=... set default -scrollcopyrect parameters. + * -DSCALING_COPYRECT=0 + * -DXDAMAGE=0 to have -noxdamage as the default. + * -DSKIPDUPS=0 to have -noskip_dups as the default or vice versa. + * + * -DPOINTER_MODE_DEFAULT={0,1,2,3,4} set default -pointer_mode. + * -DBOLDLY_CLOSE_DISPLAY=0 to not close X DISPLAY under -rawfb. + * -DSMALL_FOOTPRINT=1 for smaller binary size (no help, no gui, etc) + * use 2 or 3 for even smaller footprint. + * -DNOGUI do not include the gui tkx11vnc. + * -DPOLL_8TO24_DELAY=N + * -DDEBUG_XEVENTS=1 enable printout for X events. + * + * Set these in CPPFLAGS before running configure. E.g.: + * + * % env CPPFLAGS="-DFOREVER -DREMOTE_CONTROL=0" ./configure + * % make + */ + + If other things (e.g. "-I ...") are needed in CPPFLAGS add them as + well. + + On some systems is seems you need to set LC_ALL=C for configure to + work properly... + + Be careful the following two variables: HARDWIRE_PASSWD and + HARDWIRE_VIEWPASSWD. If set (remember to include the double quotes + around the string), they will be used as default values for the + -passwd and -viewpasswd options. Of course the strings will exist + unobscured in the x11vnc binary: it better not be readable by + unintendeds. Perhaps this is of use in remote access for an embedded + application, etc... + + Let us know if more build-time customizations would be useful. + + + [Win2VNC Related] + + Q-20: I have two separate machine displays in front of me, one Windows + the other X11: can I use x11vnc in combination with Win2VNC in + dual-screen mode to pass the keystrokes and mouse motions to the X11 + display? + + Yes, for best response start up x11vnc with the "-nofb" option + (disables framebuffer polling, and does other optimizations) on the + secondary display (X11) machine. Then start up Win2VNC on the primary + display (Windows) referring it to the secondary display. + + This will also work X11 to X11 using x2vnc, however you would probably + just want to avoid VNC and use x2x for that. + + For reference, here are some links to Win2VNC-like programs for + multiple monitor setups: + * Original Win2VNC + * Enhanced Win2VNC (broken?) and sourceforge link + * x2vnc + * x2x + * zvnc (MorphOS) + + All of them will work with x11vnc (except x2x where it is not needed.) + + + Q-21: I am running Win2VNC on my Windows machine and "x11vnc -nofb" on + Unix to pass keyboard and mouse to the Unix monitor. Whenever I start + Win2VNC it quickly disconnects and x11vnc says: + rfbProcessClientNormalMessage: read: Connection reset by peer + + Is the default visual of the X display you run x11vnc on low color + (e.g. 8 bit per pixel PseudoColor)? (you can run xdpyinfo to check, + look in the "screen" section.) There seems to be a bug in Win2VNC in + that it cannot deal correctly with colormaps (PseudoColor is the most + common example of a visual with a colormap.) + + If so, there are a couple options. 1) Can you set the default visual + on your display to be depth 24 TrueColor? Sun machines often have 8+24 + overlay/multi-depth visuals, and you can make the default visual depth + 24 TrueColor (see fbconfig(1) and Xsun(1).) 2) As of Feb/2004 x11vnc + has the -visual option to allow you to force the framebuffer visual to + whatever you want (this usually messes up the colors unless you are + very clever.) In this case, the option provides a convenient + workaround for the Win2VNC bug: + x11vnc -nofb -visual TrueColor -display :0 ... + + So the visual will be set to 8bpp TrueColor and Win2VNC can handle + this. Since Win2VNC does not use the framebuffer data there should be + no problems in doing this. + + Q-22: Can I run "x11vnc -nofb" on a Mac OS X machine to redirect mouse + and keyboard input to it from Windows and X11 machines via Win2VNC and + x2vnc, respectively? + + Yes, as of Nov/2006 you can. There may be a trick or two you'll need + to do to get the Clipboard exchange between the machines to work. + + + + [Color Issues] + + Q-23: The X display I run x11vnc on is only 8 bits per pixel (bpp) + PseudoColor (i.e. only 256 distinct colors.) The x11vnc colors may + start out OK, but after a while they are incorrect in certain windows. + + Use the -flashcmap option to have x11vnc watch for changes in the + colormap, and propagate those changes back to connected clients. This + can be slow (since the whole screen must be updated over the network + whenever the colormap changes.) This flashing colormap behavior often + happens if an application installs its own private colormap when the + mouse is in its window. "netscape -install" is a well-known historical + example of this. Consider reconfiguring the system to 16 bpp or depth + 24 TrueColor if at all possible. + + Also note the option -8to24 (Jan/2006) can often remove the need for + flashing the colormap. Everything is dynamically transformed to depth + 24 at 32 bpp using the colormaps. There may be painting errors however + (see the following FAQ for tips on reducing and correcting them.) + + In some rare cases (SCO unixware) the -notruecolor option has + corrected colors on 8bpp displays. The red, green, and blue masks were + non-zero in 8bpp PseudoColor on an obscure setup, and this option + corrected the problems. + + + Q-24: Color problems: Why are the colors for some windows incorrect in + x11vnc? BTW, my X display has nice overlay/multi-depth visuals of + different color depths: e.g. there are both depth 8 and 24 visuals + available at the same time. + + You may want to review the previous question regarding 8 bpp + PseudoColor. + + On some hardware (Sun/SPARC and SGI), the -overlay option discussed a + couple paragraphs down may solve this for you (you may want to skip to + it directly.) On other hardware the less robust -8to24 option may help + (also discussed below.) + + Run xdpyinfo(1) to see what the default visual is and what the depths + of the other visuals are. Does the default visual have a depth of 8 + but there are other visuals of depth 24? If it does, can you possibly + re-configure your X server to make a depth 24 visual the default? If + you can do it, this will save you a lot of grief WRT colors and x11vnc + (and for general usage too!) Here is how I do this on an old + Sparcstation 20 running Solaris 9 with SX graphics + xinit -- -dev /dev/fb defclass TrueColor defdepth 24 + + and it works nicely (note: to log into console from the dtlogin + window, select "Options -> Command Line Login", then login and enter + the above command.) See the -dev section of the Xsun(1) manpage for a + description of the above arguments. If you have root permission, a + more permanent and convenient thing to do is to record the arguments + in a line like: + :0 Local local_uid@console root /usr/openwin/bin/Xsun -dev /dev/fb defclass +TrueColor defdepth 24 + + in /etc/dt/config/Xservers (copy /usr/dt/config/Xservers.) Also look + at the fbconfig(1) and related manpages (e.g. ffbconfig, m64config, + pgxconfig, SUNWjfb_config, etc ...) for hardware framebuffer settings + that may achieve the same effect. + + In general for non-Sun machines, look at the "-cc class" and related + options in your X server manpage (perhaps Xserver(1)), it may allow + modifying the default visual (e.g. "-cc 4", see for the + visual class numbers.) On XFree86 some video card drivers (e.g. Matrox + mga) have settings like Option "Overlay" "24,8" to support multi-depth + overlays. For these, use the "-cc 4" X server command line option to + get a depth 24 default visual. + + + The -overlay mode: Another option is if the system with overlay + visuals is a Sun system running Solaris or SGI running IRIX you can + use the -overlay x11vnc option (Aug/2004) to have x11vnc use the + Solaris XReadScreen(3X11) function to poll the "true view" of the + whole screen at depth 24 TrueColor. XReadDisplay(3X11) is used on + IRIX. This is useful for Legacy applications (older versions of + Cadence CAD apps are mentioned by x11vnc users) that require the + default depth be 8bpp, or the app will use a 8bpp visual even if depth + 24 visuals are available, and so the default depth workaround + described in the previous paragraph is not sufficient for these apps. + + It seems that Xorg is working toward supporting XReadDisplay(3X11) as + part of the RENDER extension work. When it does support it and + provides a library API x11vnc will be modified to take advantage of + the feature to support -overlay on Linux, *BSD, etc. Until then see + the -8to24 mode below. + + Misc. notes on -overlay mode: An amusing by-product of -overlay mode + is that the mouse cursor shape is correct! (i.e. XFIXES is not + needed.) The -overlay mode may be somewhat slower than normal mode due + to the extra framebuffer manipulations that must be performed. Also, + on Solaris there is a bug in that for some popup menus, the windows + they overlap will have painting errors (flashing colors) while the + popup is up (a workaround is to disable SaveUnders by passing -su to + Xsun, e.g. in your /etc/dt/config/Xservers file.) + + + The -8to24 mode: The -8to24 x11vnc option (Jan/2006) is a kludge to + try to dynamically rewrite the pixel values so that the 8bpp part of + the screen is mapped onto depth 24 TrueColor. This is less robust than + the -overlay mode because it is done by x11vnc outside of the X + server. So only use it on OS's that do not support -overlay. The + -8to24 mode will work if the default visual is depth 24 or depth 8. It + scans for any windows within 3 levels of the root window that are 8bpp + (i.e. legacy application), or in general ones that are not using the + default visual. For the windows it finds it uses XGetSubImage() to + retrieve the pixels values and uses the correct indexed colormap to + create a depth 24 TrueColor view of the whole screen. This depth 24, + 32bpp view is exported via VNC. + + Even on pure 8bpp displays it can be used as an alternative to + -flashcmap to avoid color flashing completely. + + This scheme is approximate and can often lead to painting errors. You + can manually correct most painting errors by pressing 3 Alt_L's in a + row, or by using something like: -fixscreen V=3.0 to automatically + refresh the screen every 3 seconds. Also -fixscreen 8=3.0 has been + added to just refresh the non-default visual parts of the screen. + + In general the scheme uses many resources and may give rise to + sluggish behavior. If multiple windows are using different 8bpp + indexed colormaps all but one window may need to be iconified for the + colors to be correct. There are a number of tunable parameters to try + to adjust performance and painting accuracy. The option -8to24 + nogetimage can give a nice speedup if the default depth 24 X server + supports hiding the 8bpp bits in bits 25-32 of the framebuffer data. + On very slow machines -8to24 poll=0.2,cachewin=5.0 gives an useful + speedup. See the -8to24 help description for information on tunable + parameters, etc. + + + Colors still not working correctly? Run xwininfo on the application + with the incorrect colors to verify that the depth of its visual is + different from the default visual depth (gotten from xdpyinfo.) One + possible workaround in this case is to use the -id option to point + x11vnc at the application window itself. If the application is + complicated (lots of toplevel windows and popup menus) this may not be + acceptable, and may even crash x11vnc (but not the application.) See + also -appshare. + + It is theoretically possible to solve this problem in general (see + xwd(1) for example), but it does not seem trivial or sufficiently fast + for x11vnc to be able to do so in real time. The -8to24 method does + this approximately and is somewhat usable. Fortunately the -overlay + option works for Solaris machines with overlay visuals where most of + this problem occurs. + + + Q-25: I am on a high color system (depth >= 24) but I seem to have + colormap problems. They either flash or everything is very dark. + + This can happen if the default Visual (use xdpyinfo to list them) is + DirectColor instead of TrueColor. These are both usually used in high + color modes, but whereas TrueColor uses static ramps for the Red, + Green, and Blue components, DirectColor has arbitrary colormaps for + the Red, Green, and Blue Components. Currently x11vnc cannot decode + these colormaps and treats them just like TrueColor. + + The only workaround so far is to restart the X server with the "-cc 4" + option to force TrueColor as the default visual (DirectColor is "-cc + 5"; see /usr/include/X11/X.h.) The only place we have seen this is + with the virtual framebuffer server Xvfb on Xorg 7.2. So in that case + you probably should restart it with something like this: "Xvfb :1 -cc + 4 -screen 0 1280x1024x24". It should be possible for x11vnc to handle + DirectColor, but this hasn't been implemented due to its rare usage. + + You may also see this problem on an X display with a TrueColor default + visual where an application chooses a DirectColor visual for its + window(s). It seems the application also needs to install its own + colormap for the visual for the colors to be messed up in x11vnc. One + can make xwud do this for example. + + + Q-26: How do I figure out the window id to supply to the -id windowid + option? + + Run the xwininfo program in a terminal. It will ask you to click on + the desired application window. After clicking, it will print out much + information, including the window id (e.g. 0x6000010.) Also, the + visual and depth of the window printed out is often useful in + debugging x11vnc color problems. + + Also, as of Dec/2004 you can use "-id pick" to have x11vnc run + xwininfo(1) for you and after you click the window it extracts the + windowid. Besides "pick" there is also "id:root" to allow you to go + back to root window when doing remote-control. + + + Q-27: Why don't menus or other transient windows come up when I am + using the -id windowid option to view a single application window? + + This is related to the behavior of the XGetImage(3X11) and + XShmGetImage() interfaces regarding backingstore, saveunders, etc. The + way the image is retrieved depends on some aspects of how the X server + maintains the display image data and whether other windows are + clipping or obscuring it. See the XGetImage(3X11) man page for more + details. If you disable BackingStore and SaveUnders in the X server + you should be able to see these transient windows. + + If things are not working and you still want to do the single window + polling, try the -sid windowid option ("shifted" windowid.) + + Update: as of Nov/2009 in the 0.9.9 x11vnc development tarball, there + is an experimental Application Sharing mode that improves upon the + -id/-sid single window sharing: -appshare (run "x11vnc -appshare + -help" for more info.) It is still very primitive and approximate, but + at least it displays multiple top-level windows. + + + Q-28: My X display is depth 24 at 24bpp (instead of the normal depth + 24 at 32bpp.) I'm having lots of color and visual problems with x11vnc + and/or vncviewer. What's up? + + First off, depth 24 at 24bpp (bpp=bits-per-pixel) is fairly uncommon + and can cause problems in general. It also can be slower than depth 24 + at 32bpp. You might want to switch to 32bpp (for XFree86 see the + "-fbbpp 32", DefaultFbBpp, FbBpp and related options.) Perhaps you + have 24bpp because the video memory of the machine is low and the + screen wouldn't fit in video RAM at 32bpp. For this case depth 16 at + 16bpp might be an acceptable option. + + In any event x11vnc should handle depth 24 at 24bpp (although + performance may be slower, and you may need to use the ZRLE encoding + instead of Tight.) There are some caveats involving the viewer + however: + + The RealVNC Unix viewer cannot handle 24bpp from the server, it will + say: "main: setPF: not 8, 16 or 32 bpp?" and exit. I have not checked + the RealVNC Windows viewer. + + So you need to use the TightVNC Unix viewer. However there are some + problems with that too. It seems libvncserver does not do 24bpp + correctly with the Tight encoding. The colors and screen ultimately + get messed up. So you have to use a different encoding with the + TightVNC vncviewer, try "zlib", "hextile", or one of the other + encodings (e.g. vncviewer -encodings "zlib hextile" ....) I have not + checked the TightVNC or UltraVNC Windows viewers. + + It appears the older RealVNC Unix viewers (e.g. 3.3.3 and 3.3.7) can + handle 24bpp from the server, so you may want to use those. They + evidently request 32 bpp and libvncserver obliges. + + Update: as of Apr/2006 you can use the -24to32 option to have x11vnc + dynamically transform the 24bpp pixel data to 32bpp. This extra + transformation could slow things down further however. + + Now coming the opposite direction if you are running the vncviewer on + the 24bpp display, TightVNC will fail with "Can't cope with 24 + bits-per-pixel. Sorry." and RealVNC will fail with "main: Error: + couldn't find suitable pixmap format" so evidently you cannot use + 24bpp for the vncviewers to work on that X display. + + Note, however, that the Unix viewer in the Enhanced TightVNC Viewer + (SSVNC) project can handle 24bpp X displays. It does this by + requesting a 16bpp pixel format (or 8bpp if the -bgr233 option has + been supplied) from the VNC server, and translates that to 24bpp + locally. + [Xterminals] + + Q-29: Can I use x11vnc to view and interact with an Xterminal (e.g. + NCD) that is not running UNIX and so x11vnc cannot be run on it + directly? + + You can, but it will likely be very wasteful of network bandwidth + since you will be polling the X display over the network as opposed to + over the local hardware. To do this, run x11vnc on a UNIX machine as + close as possible network-wise (e.g. same switch) to the Xterminal + machine. Use the -display option to point the display to that of the + Xterminal (you'll of course need basic X11 permission to do that) and + finally supply the -noshm option (this enables the polling over the + network.) + + If the Xterminal's X display is open to the network for connections, + you might use something like "-display xterm123:0". If you are trying + to do this via an SSH tunnel (assuming you can actually ssh into the + Xterminal) it will be a little tricky (either use the ssh "-R" option + or consider ssh-ing in the other direction.) In all cases the X11 + permissions need to allow the connection. + + The response will likely be sluggish (maybe only one "frame" per + second.) This mode is not recommended except for "quick checks" of + hard to get to X servers. Use something like "-wait 150" to cut down + on the polling rate. You may also need -flipbyteorder if the colors + get messed up due to endian byte order differences. + + Q-30: How do I get my X permissions (MIT-MAGIC-COOKIE file) correct + for a Unix/Linux machine acting as an Xterminal? + + If the X display machine is a traditional Xterminal (where the X + server process runs on the Xterminal box, but all of the X client + applications (firefox, etc) run on a central server (aka "terminal + server")), you will need to log into the Xterminal machine (i.e. get a + shell running there) and then start the x11vnc program. If the + Xterminal Linux/Unix machine is stripped down (e.g. no users besides + root) that may be difficult. + + The next problem is the login Display Manager (e.g. gdm, kdm), and + hence the MIT-MAGIC-COOKIE auth files, are on the central server and + not on the Xterminal box where the X server and x11vnc processes are. + + So unless X permissions are completely turned off (e.g. "xhost +"), to + run the x11vnc process on the Xterminal box the MIT-MAGIC-COOKIE auth + file data (XAUTHORITY or $HOME/.Xauthority) must be accessible by or + copied to the Xterminal. If $HOME/.Xauthority is exported via NFS + (this is insecure of course, but has been going on for decades), then + x11vnc can simply pick it up via NFS (you may need to use the -auth + option to point to the correct file.) Other options include copying + the auth file using scp, or something like: + central-server> xauth nextract - xterm123:0 | ssh xterm123 xauth nmerge - + + and then, say, ssh from central-server to xterm123 to start x11vnc. + Here "xterm123" refers to the computer acting as the Xterminal and + "central-server" is the terminal server. You can use "xauth -f + /path/to/cookie-file list" to examine the contents of the cookie(s) in + a file "/path/to/cookie-file". See the xauth(1) manpage for more + details. + + If the display name in the cookie file needs to be changed between the + two hosts, see this note on the "xauth add ..." command. + + A less secure option is to run something like "xhost +127.0.0.1" while + sitting at the Xterminal box to allow cookie-free local access for + x11vnc. You can run "xhost -127.0.0.1" after x11vnc connects if you + want to go back to the original permissions. + + If the Xterminal is really stripped down and doesn't have any user + accounts, NFS, etc. you'll need to contact your system administrator + to set something up. It can be done!!! Some Xterminal projects have + actually enabled "run locally" facilities for the running of an + occasional app more efficiently locally on the Xterminal box (e.g. + realplayer.) + + Not recommended, but as a last resort, you could have x11vnc poll the + Xterminal Display over the network. For this you would run a "x11vnc + -noshm ..." process on the central-server (and hope the network admin + doesn't get angry...) + + Note: use of Display Manager (gdm, kdm, ...) auth cookie files (i.e. + from /var/..., /tmp/..., or elsewhere) may require modification via + xauth(1) to correctly include the display x11vnc refers to (e.g. + "xauth -f cookie-file add :0 . 45be51ae2ce9dfbacd882ab3ef8e96b1", + where the "45be51..." cookie value was found from an "xauth -f + /path/to/original/cookie-file list") or other reasons. See xauth(1) + manpage for full details on how to transfer an MIT-MAGIC-COOKIE + between machines and displays. + + VNCviewer performance on Xterminals: This isn't related to x11vnc on + Xterminals, but we mention it here anyway because of the similar + issues. If you are on an Xterminal and want to use vncviewer to + connect to a VNC server somewhere, then performance would be best if + you ran the viewer on the Xterminal box. Otherwise, (i.e. running the + viewer process on the central-server) all of the vncviewer screen + drawing is done more inefficiently over the network. Something to + consider, especially on a busy network. (BTW, this has all of the + above permission, etc, problems: both vncviewer and x11vnc are X + client apps desired to be run on the Xterminal box.) + + [Sun Rays] + + Q-31: I'm having trouble using x11vnc with my Sun Ray session. + + The Sun Ray technology is a bit like "VNC done in hardware" (the Sun + Ray terminal device, DTU, playing the role of the vncviewer.) + Completely independent of that, the SunRay user's session is still an + X server that speaks the X11 protocol and so x11vnc simply talks to + the X server part to export the SunRay desktop to any place in the + world (i.e. not only to a Sun Ray terminal device), creating a sort of + "Soft Ray". Please see this discussion of Sun Ray issues for solutions + to problems. + + Also see the Sun Ray Remote Control Toolkit that uses x11vnc. + + [Remote Control] + + Q-32: How do I stop x11vnc once it is running in the background? + + As of Dec/2004 there is a remote control feature. It can change a huge + number of parameters on the fly: see the -remote and -query options. + To shut down the running x11vnc server just type "x11vnc -R stop". To + disconnect all clients do "x11vnc -R disconnect:all", etc. + + If the -forever option has not been supplied, x11vnc will + automatically exit after the first client disconnects. In general if + you cannot use the remote control, then you will have to kill the + x11vnc process This can be done via: "kill NNNNN" (where NNNNN is the + x11vnc process id number found from ps(1)), or "pkill x11vnc", or + "killall x11vnc" (Linux only.) + + If you have not put x11vnc in the background via the -bg option or + shell & operator, then simply press Ctrl-C in the shell where x11vnc + is running to stop it. + + Potential Gotcha: If somehow your Keypress of Ctrl-C went through + x11vnc to the Xserver that then delivered it to x11vnc it is possible + one or both of the Ctrl or C keys will be left stuck in the pressed + down state in the Xserver. Tapping the stuck key (either via a new + x11vnc or at the physical console) will release it from the stuck + state. If the keyboard seems to be acting strangely it is often fixed + by tapping Ctrl, Shift, and Alt. Alternatively, the -clear_mods option + and -clear_keys option can be used to release pressed keys at startup + and exit. The option -clear_all will also try to unset Caps_Lock, + Num_Lock, etc. + + + Q-33: Can I change settings in x11vnc without having to restart it? + Can I remote control it? + + Look at the -remote (an alias is -R) and -query (an alias is -Q) + options added in Dec/2004. They allow nearly everything to be changed + dynamically and settings to be queried. Examples: "x11vnc -R shared", + "x11vnc -R forever", "x11vnc -R scale:3/4", "x11vnc -Q modtweak", + "x11vnc -R stop", "x11vnc -R disconnect:all", etc.. + + These commands do not start a x11vnc server, but rather communicate + with one that is already running. The X display (X11VNC_REMOTE + property) is used as the communication channel, so the X permissions + and DISPLAY must be set up correctly for communication to be possible. + + There is also a simple Tcl/Tk gui based on this remote control + mechanism. See the -gui option for more info. You will need to have + Tcl/Tk (i.e. /usr/bin/wish) installed for it to work. It can also run + in the system tray: "-gui tray" or as a standalone small icon window: + "-gui icon". Use "-gui tray=setpass" for a naive user "Share My + Desktop" mode. + + [Security and Permissions] + + Q-34: How do I create a VNC password for use with x11vnc? + + You may already have one in $HOME/.vnc/passwd if you have used, say, + the vncserver program from the regular RealVNC or TightVNC packages + (i.e. launching the Xvnc server.) Otherwise, you could use the + vncpasswd(1) program from those packages. + + As of Jun/2004 x11vnc supports the -storepasswd "pass" "file" option, + which is the same functionality of storepasswd. Be sure to quote the + "pass" if it contains shell meta characters, spaces, etc. Example: + x11vnc -storepasswd 'sword*fish' $HOME/myvncpasswd + + You then use the password via the x11vnc option: "-rfbauth + $HOME/myvncpasswd" + + As of Jan/2006 if you do not supply any arguments: + x11vnc -storepasswd + + you will be prompted for a password to save to ~/.vnc/passwd (your + keystrokes when entering the password will not be echoed to the + screen.) If you supply one argument, e.g. "x11vnc -storepasswd + ~/.mypass", the password you are prompted for will be stored in that + file. + + x11vnc also has the -passwdfile and -passwd/-viewpasswd plain text + (i.e. not obscured like the -rfbauth VNC passwords) password options. + + You can use the -usepw option to automatically use any password file + you have in ~/.vnc/passwd or ~/.vnc/passwdfile (the latter is used + with the -passwdfile option.) + + x11vnc -usepw -display :0 ... + + If neither file exists you are prompted to store a password in + ~/.vnc/passwd. If a password file cannot be found or created x11vnc + exits immediately. An admin may want to set it up this way for users + who do not know better. + + + Q-35: Can I make it so -storepasswd doesn't show my password on the + screen? + + You can use the vncpasswd program from RealVNC or TightVNC mentioned + above. As of Jan/2006 the -storepasswd option without any arguments + will not echo your password as you type it and save the file to + ~/.vnc/passwd: + # x11vnc -storepasswd + Enter VNC password: + Verify password: + Write password to /home/myname/.vnc/passwd? [y]/n + Password written to: /home/myname/.vnc/passwd + + You can also give it an alternate filename, e.g. "x11vnc -storepasswd + ~/.mypass" + + + Q-36: Can I have two passwords for VNC viewers, one for full access + and the other for view-only access to the display? + + Yes, as of May/2004 there is the -viewpasswd option to supply the + view-only password. Note the full-access password option -passwd must + be supplied at the same time. E.g.: -passwd sword -viewpasswd fish. + + To avoid specifying the passwords on the command line (where they + could be observed via the ps(1) command by any user) you can use the + -passwdfile option to specify a file containing plain text passwords. + Presumably this file is readable only by you, and ideally it is + located on the machine x11vnc is run on (to avoid being snooped on + over the network.) The first line of this file is the full-access + password. If there is a second line in the file and it is non-blank, + it is taken as the view-only password. (use "__EMPTY__" to supply an + empty one.) + + View-only passwords currently do not work for the -rfbauth password + option (standard VNC password storing mechanism.) FWIW, note that + although the output (usually placed in $HOME/.vnc/passwd) by the + vncpasswd or storepasswd programs (or from x11vnc -storepasswd) looks + encrypted they are really just obscured to avoid "casual" password + stealing. It takes almost no skill to figure out how to extract the + plain text passwords from $HOME/.vnc/passwd since it is very + straight-forward to work out what to do from the VNC source code. + + + Q-37: Can I have as many full-access and view-only passwords as I + like? + + Yes, as of Jan/2006 in the libvncserver CVS the -passwdfile option has + been extended to handle as many passwords as you like. You put the + view-only passwords after a line __BEGIN_VIEWONLY__. + + You can also easily annotate and comment out passwords in the file. + You can have x11vnc re-read the file dynamically when it is modified. + + + Q-38: Does x11vnc support Unix usernames and passwords? Can I further + limit the set of Unix usernames who can connect to the VNC desktop? + Update: as of Feb/2006 x11vnc has the -unixpw option that does this + outside of the VNC protocol and libvncserver. The standard su(1) + program is used to validate the user's password. A familiar "login:" + and "Password:" dialog is presented to the user on a black screen + inside the vncviewer. The connection is dropped if the user fails to + supply the correct password in 3 tries or does not send one before a + 25 second timeout. Existing clients are view-only during this period. + A list of allowed Unix usernames may also be supplied along with + per-user settings. + + There is also the -unixpw_nis option for non-shadow-password + (typically NIS environments, hence the name) systems where the + traditional getpwnam() and crypt() functions are used instead of + su(1). The encrypted user passwords must be accessible to the user + running x11vnc in -unixpw_nis mode, otherwise the logins will always + fail even when the correct password is supplied. See ypcat(1) and + shadow(5). + + Two settings are enforced in the -unixpw and -unixpw_nis modes to + provide extra security: the 1) -localhost and 2) -stunnel or -ssl + options. Without these one might send the Unix username and password + data in clear text over the network which is a very bad idea. They can + be relaxed if you want to provide encryption other than stunnel or + -ssl (the constraint is automatically relaxed if SSH_CONNECTION is set + and indicates you have ssh-ed in, however the -localhost requirement + is still enforced.) + + The two -unixpw modes have been tested on Linux, Solaris, Mac OS X, + HP-UX, AIX, Tru64, FreeBSD, OpenBSD, and NetBSD. Additional testing is + appreciated. For the last 4 it appears that su(1) will not prompt for + a password if su-ing to oneself. Since x11vnc requires a password + prompt from su, x11vnc forces those logins to fail even when the + correct password is supplied. On *BSD it appears this can be corrected + by removing the pam_self.so entry in /etc/pam.d/su. + + + Previous older discussion (prior to the -unixpw option): + + Until the VNC protocol and libvncserver support this things will be + approximate at best. + + One approximate method involves starting x11vnc with the -localhost + option. This basically requires the viewer user to log into the + workstation where x11vnc is running via their Unix username and + password, and then somehow set up a port redirection of his vncviewer + connection to make it appear to emanate from the local machine. As + discussed above, ssh is useful for this: "ssh -L 5900:localhost:5900 + user@hostname ..." See the ssh wrapper scripts mentioned elsewhere on + this page. stunnel does this as well. + + Of course a malicious user could allow other users to get in through + his channel, but that is a problem with every method. Another thing to + watch out for is a malicious user on the viewer side (where ssh is + running) trying to sneak in through the ssh port redirection there. + + Regarding limiting the set of Unix usernames who can connect, the + traditional way would be to further require a VNC password to supplied + (-rfbauth, -passwd, etc) and only tell the people allowed in what the + VNC password is. A scheme that avoids a second password involves using + the -accept option that runs a program to examine the connection + information to determine which user is connecting from the local + machine. That may be difficult to do, but, for example, the program + could use the ident service on the local machine (normally ident + should not be trusted over the network, but on the local machine it + should be accurate: otherwise root has been compromised and so there + are more serious problems! Unfortunately recent Linux distros seem to + provide a random string (MD5 hash?) instead of the username.) An + example script passed in via -accept scriptname that deduces the Unix + username and limits who can be accepted might look something like + this: +#!/bin/sh +if [ "$RFB_CLIENT_IP" != "127.0.0.1" -o "$RFB_SERVER_IP" != "127.0.0.1" ]; then + exit 1 # something fishy... reject it. +fi +user=`echo "$RFB_CLIENT_PORT, $RFB_SERVER_PORT" | nc -w 1 $RFB_CLIENT_IP 113 \ + | grep 'USERID.*UNIX' | head -1 | sed -e 's/[\r ]//g' | awk -F: '{print + $4}'` + +for okuser in fred barney wilma betty +do + if [ "X$user" = "X$okuser" ]; then + exit 0 # accept it + fi +done +exit 1 # reject it + + For this to work with ssh port redirection, the ssh option + UsePrivilegeSeparation must be enabled otherwise the userid will + always be "root". + + + Q-39: Can I supply an external program to provide my own custom login + method (e.g. Dynamic/One-time passwords or non-Unix (LDAP) usernames + and passwords)? + Yes, there are several possibilities. For background see the FAQ on + the -accept where an external program may be run to decide if a VNC + client should be allowed to try to connect and log in. If the program + (or local user prompted by a popup) answers "yes", then -accept + proceeds to the normal VNC and x11vnc authentication methods, + otherwise the connection is dropped. + + To provide more direct coupling to the VNC client's username and/or + supplied password the following options were added in Sep/2006: + * -unixpw_cmd command + * -passwdfile cmd:command + * -passwdfile custom:command + + In each case "command" is an external command run by x11vnc. You + supply it. For example, it may couple to your LDAP system or other + servers you set up. + + For -unixpw_cmd the normal -unixpw Login: and Password: prompts are + supplied to the VNC viewer and the strings the client returns are then + piped into "command" as the first two lines of its standard input. If + the command returns success, i.e. exit(0), the VNC client is accepted, + otherwise it is rejected. + + For "-passwdfile cmd:command" the command is run and it returns a + password list (like a password file, see the -passwdfile read:filename + mode.) Perhaps a dynamic, one-time password is retrieved from a server + this way. + + For "-passwdfile custom:command" one gets complete control over the + VNC challenge-response dialog with the VNC client. x11vnc sends out a + string of random bytes (16 by the VNC spec) and the client returns the + same number of bytes in a way the server can verify only the + authorized user could have created. The VNC protocol specifies DES + encryption with a password. If you are willing to modify the VNC + viewers, you can have it be anything you want, perhaps a less + crackable MD5 hash scheme or one-time pad. Your program will read from + its standard input the size of the challenge-response followed by a + newline, then the challenge bytes followed by the response bytes. If + your command then returns success, i.e. exit(0), the VNC client is + accepted, otherwise it is rejected. + + In all cases the "RFB_*" environment variables are set as under + -accept. These variables can provide useful information for the + externally supplied program to use. + + + Q-40: Why does x11vnc exit as soon as the VNC viewer disconnects? And + why doesn't it allow more than one VNC viewer to connect at the same + time? + + These defaults are simple safety measures to avoid someone unknowingly + leaving his X11 desktop exposed (to the internet, say) for long + periods of time. Use the -forever option (aka -many) to have x11vnc + wait for more connections after the first client disconnects. Use the + -shared option to have x11vnc allow multiple clients to connect + simultaneously. + + Recommended additional safety measures include using ssh (see above), + stunnel, -ssl, or a VPN to authenticate and encrypt the viewer + connections or to at least use the -rfbauth passwd-file option to use + VNC password protection (or -passwdfile) It is up to YOU to apply + these security measures, they will not be done for you automatically. + + + Q-41: Can I limit which machines incoming VNC clients can connect + from? + + Yes, look at the -allow and -localhost options to limit connections by + hostname or IP address. E.g. + x11vnc -allow 192.168.0.1,192.168.0.2 + + for those two hosts or + x11vnc -allow 192.168.0. + + for a subnet. For individual hosts you can use the hostname instead of + the IP number, e.g.: "-allow snoopy", and "-allow darkstar,wombat". + Note that -localhost achieves the same thing as "-allow 127.0.0.1" + + For more control, build libvncserver with libwrap support + (tcp_wrappers) and then use /etc/hosts.allow See hosts_access(5) for + complete details. + + + Q-42: How do I build x11vnc/libvncserver with libwrap (tcp_wrappers) + support? + + Here is one way to pass this information to the configure script: + env CPPFLAGS=-DUSE_LIBWRAP LDFLAGS=-lwrap ./configure + + then run make as usual. This requires libwrap and its development + package (tcpd.h) to be installed on the build machine. If additional + CPPFLAGS or LDFLAGS options are needed supply them as well using + quotes. + + The resulting x11vnc then uses libwrap/tcp_wrappers for connections. + The service name you will use in /etc/hosts.allow and /etc/hosts.deny + is "vnc", e.g.: + vnc: 192.168.100.3 .example.com + + Note that if you run x11vnc out of inetd you do not need to build + x11vnc with libwrap support because the /usr/sbin/tcpd reference in + /etc/inetd.conf handles the tcp_wrappers stuff. + + + Q-43: Can I have x11vnc only listen on one network interface (e.g. + internal LAN) rather than having it listen on all network interfaces + and relying on -allow to filter unwanted connections out? + + As of Mar/2005 there is the "-listen ipaddr" option that enables this. + For ipaddr either supply the desired network interface's IP address + (or use a hostname that resolves to it) or use the string "localhost". + For additional filtering simultaneously use the "-allow host1,..." + option to allow only specific hosts in. + + This option is useful if you want to insure that no one can even begin + a dialog with x11vnc from untrusted network interfaces (e.g. ppp0.) + The option -localhost now implies "-listen localhost" since that is + what most people expect it to do. + + + Q-44: Now that -localhost implies listening only on the loopback + interface, how I can occasionally allow in a non-localhost via the -R + allowonce remote control command? + + To do this specify "-allow localhost". Unlike -localhost this will + leave x11vnc listening on all interfaces (but of course only allowing + in local connections, e.g. ssh redirs.) Then you can later run "x11vnc + -R allowonce:somehost" or use to gui to permit a one-shot connection + from a remote host. + + + Q-45: Can I fine tune what types of user input are allowed? E.g. have + some users just be able to move the mouse, but not click or type + anything? + + As of Feb/2005, the -input option allows you to do this. "K", "M", + "B", "C", and "F" stand for Keystroke, Mouse-motion, Button-clicks, + Clipboard, and File-Transfer, respectively. The setting: "-input M" + makes attached viewers only able to move the mouse. "-input KMBC,M" + lets normal clients do everything and enables view-only clients to + move the mouse. + + These settings can also be applied on a per-viewer basis via the + remote control mechanism or the GUI. E.g. x11vnc -R input:hostname:M + + + Q-46: Can I prompt the user at the local X display whether the + incoming VNC client should be accepted or not? Can I decide to make + some clients view-only? How about running an arbitrary program to make + the decisions? + + Yes, look at the "-accept command" option, it allows you to specify an + external command that is run for each new client. (use quotes around + the command if it contains spaces, etc.) If the external command + returns 0 (success) the client is accepted, otherwise with any other + return code the client is rejected. See below how to also accept + clients view-only. + + The external command will have the RFB_CLIENT_IP environment variable + set to the client's numerical IP address, RFB_CLIENT_PORT its port + number. Similarly for RFB_SERVER_IP and RFB_SERVER_PORT to allow + identification of the tcp virtual circuit. DISPLAY will be set to that + of the X11 display being polled. Also, RFB_X11VNC_PID is set to the + x11vnc process id (e.g. in case you decided to kill it), RFB_CLIENT_ID + will be an id number, and RFB_CLIENT_COUNT the number of other clients + currently connected. RFB_MODE will be "accept". + + Built-in Popup Window: As a special case, "-accept popup" will + instruct x11vnc to create its own simple popup window. To accept the + client press "y" or click mouse on the "Yes" button. To reject the + client press "n" or click mouse on the "No" button. To accept the + client View-only, press "v" or click mouse on the "View" button. If + the -viewonly option has been supplied, the "View" action will not be + present: the whole display is view only in that case. + + The popup window times out after 120 seconds, to change this behavior + use "-accept popup:N" where N is the number of seconds (use 0 for no + timeout.) More tricks: "-accept popupmouse" will only take mouse click + responses, while "-accept popupkey" will only take keystroke responses + (popup takes both.) After any of the 3 popup keywords you can supply a + position of the window: +N+M, (the default is to center the window) + e.g. -accept popupmouse+10+10. + + Also as a special case "-accept xmessage" will run the xmessage(1) + program to prompt the user whether the client should be accepted or + not. This requires that you have xmessage installed and available via + PATH. In case it is not already on your system, the xmessage program + is available at ftp://ftp.x.org/ + (End of Built-in Popup Window:) + + To include view-only decisions for the external commands, prefix the + command something like this: "yes:0,no:*,view:3 mycommand ..." This + associates the three actions: yes(accept), no(reject), and + view(accept-view-only), with the numerical return (i.e. exit()) codes. + Use "*" instead of a number to set the default action (e.g. in case + the external command returns an unexpected return code.) + + Here is an example -accept script called accept_or_lock. It uses + xmessage and xlock (replace with your screen lock command, maybe it is + "xscreensaver-command -lock", or kdesktop_lock, or "dtaction + LockDisplay".) It will prompt the user at the X display whether to + accept, reject, or accept view-only the client, but if the prompt + times out after 60 seconds the screen is locked and the VNC client is + accepted. This allows the remote access when no one is at the display. +#!/bin/sh +# +# accept_or_lock: prompt user at X display whether to accept an incoming +# VNC connection. If timeout expires, screen is locked +# and the VNC viewer is accepted (allows remote access +# when no one is sitting at the display.) +# +# usage: x11vnc ... -forever -accept 'yes:0,no:*,view:4 accept_or_lock' +# +xmessage -buttons yes:2,no:3,view-only:4 -center \ + -timeout 60 "x11vnc: accept connection from $RFB_CLIENT_IP?" +rc=$? +if [ $rc = 0 ]; then + xlock & # or "xlock -mode blank" for no animations. + sleep 5 + exit 0 +elif [ $rc = 2 ]; then + exit 0 +elif [ $rc = 4 ]; then + exit 4 +fi +exit 1 + + Stefan Radman has written a nice dtksh script dtVncPopup for use in + CDE environments to do the same sort of thing. Information on how to + use it is found at the top of the file. He encourages you to provide + feedback to him to help improve the script. + + Note that in all cases x11vnc will block while the external command or + popup is being run, so attached clients will not receive screen + updates, etc during this period. + + To run a command when a client disconnects, use the "-gone command" + option. This is for the user's convenience only: the return code of + the command is not interpreted by x11vnc. The same environment + variables are set as in "-accept command" (except that RFB_MODE will + be "gone".) + + As of Jan/2006 the "-afteraccept command" option will run the command + only after the VNC client has been accepted and authenticated. Like + -gone the return code is not interpreted. RFB_MODE will be + "afteraccept".) + + + Q-47: I start x11vnc as root because it is launched via inetd(8) or a + display manager like gdm(1). Can I have x11vnc later switch to a + different user? + + As of Feb/2005 x11vnc has the -users option that allows things like + this. Please read the documentation on it (also in the x11vnc -help + output) carefully for features and caveats. It's use can often + decrease security unless care is taken. + + BTW, a nice use of it is "-users +nobody" that switches to the Unix + user nobody right after connections to the X display are established. + + In any event, while running x11vnc as root, remember it comes with no + warranty ;-). + + + Q-48: I use a screen-lock when I leave my workstation (e.g. + xscreensaver or xlock.) When I remotely access my workstation desktop + via x11vnc I can unlock the desktop fine, but I am worried people will + see my activities on the physical monitor. What can I do to prevent + this, or at least make it more difficult? + + Probably most work environments would respect your privacy if you + powered off the monitor. Also remember if people have physical access + to your workstation they basically can do anything they want with it + (e.g. install a backdoor for later use, etc.) + + In any event, as of Jun/2004 there is an experimental utility to make + it more difficult for nosey people to see your x11vnc activities. The + source for it is blockdpy.c The idea behind it is simple (but + obviously not bulletproof): when a VNC client attaches to x11vnc put + the display monitor in the DPMS "off" state, if the DPMS state ever + changes immediately start up the screen-lock program. The x11vnc user + will notice something is happening and think about what to do next + (while the screen is in a locked state.) + + This works (or at least has a chance of working) because if the + intruder moves the mouse or presses a key on the keyboard, the monitor + wakes up out of the DPMS off state, and this induces the screen lock + program to activate as soon as possible. Of course there are cracks in + this, the eavesdropper could detach your monitor and insert a non-DPMS + one, and there are race conditions. As mentioned above this is not + bulletproof. A really robust solution would likely require X server + and perhaps even video hardware support. + + The blockdpy utility is launched by the -accept option and told to + exit via the -gone option (the vnc client user should obviously + re-lock the screen before disconnecting!) Instructions can be found in + the source code for the utility at the above link. Roughly it is + something like this: + x11vnc ... -accept "blockdpy -bg -f $HOME/.bdpy" -gone "touch $HOME/.bdpy" + + but please read the top of the file. + + Update: As of Feb/2007 there is some builtin support for this: + -forcedpms and -clientdpms however, they are probably less robust than + the above blockdpy.c scheme, since if the person floods the physical + machine with mouse or pointer input he can usually see flashes of the + screen before the monitor is powered off again. See also the -grabkbd, + -grabptr, and -grabalways options. + + + Q-49: Can I have x11vnc automatically lock the screen when I + disconnect the VNC viewer? + + Yes, a user mentions he uses the -gone option under CDE to run a + screen lock program: + x11vnc -display :0 -forever -gone 'dtaction LockDisplay' + + Other possibilities are: + x11vnc -display :0 -forever -gone 'xscreensaver-command -lock' + x11vnc -display :0 -forever -gone 'kdesktop_lock' + x11vnc -display :0 -forever -gone 'xlock &' + x11vnc -display :0 -forever -gone 'xlock -mode blank &' + + Here is a scheme using the -afteraccept option (in version 0.8) to + unlock the screen after the first valid VNC login and to lock the + screen after the last valid VNC login disconnects: + x11vnc -display :0 -forever -shared -afteraccept ./myxlocker -gone ./myxlocke +r + + Where the script ./myxlocker is: +#!/bin/sh + +#/usr/bin/env | grep RFB_ | sort # for viewing RFB_* settings. + +if [ "X$RFB_MODE" = "Xafteraccept" ]; then + if [ "X$RFB_STATE" = "XNORMAL" ]; then # require valid login + if [ "X$RFB_CLIENT_COUNT" = "X1" ]; then + killall xlock # Linux only. + fi + fi +elif [ "X$RFB_MODE" = "Xgone" ]; then + if [ "X$RFB_STATE" = "XNORMAL" ]; then # require valid login + if [ "X$RFB_CLIENT_COUNT" = "X0" ]; then + xlock -mode blank & + fi + fi +fi + + Note the xlock option "-mode blank" to avoid animations. + + There is a problem if you have x11vnc running this way in -forever + mode and you hit Ctrl-C to stop it. The xlock (or other program) will + get killed too. To work around this make a little script called + setpgrp that looks like: +#!/usr/bin/perl +setpgrp(0, 0); +exec @ARGV; + + then use -gone "setpgrp xlock &", etc. + [Encrypted Connections] + + Q-50: How can I tunnel my connection to x11vnc via an encrypted SSH + channel between two Unix machines? + + See the description earlier on this page on how to tunnel VNC via SSH + from Unix to Unix. A number of ways are described along with some + issues you may encounter. + + Other secure encrypted methods exists, e.g. stunnel, IPSEC, various + VPNs, etc. + + See also the Enhanced TightVNC Viewer (SSVNC) page where much of this + is now automated. + + + Q-51: How can I tunnel my connection to x11vnc via an encrypted SSH + channel from Windows using an SSH client like Putty? + + Above we described how to tunnel VNC via SSH from Unix to Unix, you + may want to review it. To do this from Windows using Putty it would go + something like this: + * In the Putty dialog window under 'Session' enter the hostname or + IP number of the Unix machine with display to be viewed. + * Make sure the SSH protocol is selected and the server port is + correct. + * Under 'Connections/SSH/Tunnels' Add a Local connection with + 'Source port: 5900' and 'Destination: localhost:5900' + * Log into the remote machine by pressing 'Open' and supplying + username, password, etc. + * In that SSH shell, start up x11vnc by typing the command: x11vnc + -display :0 plus any other desired options (e.g. -localhost.) + * Finally, start up your VNC Viewer in Windows and enter + 'localhost:0' as the VNC server. + + You can keep all of the settings in a Putty 'Saved Session'. Also, + once everything is working, you can consider putting x11vnc -display + :0 (plus other cmdline options) in the 'Remote command' Putty setting + under 'Connections/SSH'. + + See also the Enhanced TightVNC Viewer (SSVNC) page where much of this + is now automated via the Putty plink utility. + + For extra protection feel free to run x11vnc with the -localhost and + -rfbauth/-passwdfile options. + + If the machine you SSH into via Putty is not the same machine with the + X display you wish to view (e.g. your company provides incoming SSH + access to a gateway machine), then you need to change the above Putty + dialog setting to: 'Destination: otherhost:5900', Once logged in, + you'll need to do a second login (ssh or rsh) to the workstation + machine 'otherhost' and then start up x11vnc on it. This can also be + automated by Chaining SSH's. + + As discussed above another option is to first start the VNC viewer in + "listen" mode, and then launch x11vnc with the "-connect localhost" + option to establish the reverse connection. In this case a Remote port + redirection (not Local) is needed for port 5500 instead of 5900 (i.e. + 'Source port: 5500' and 'Destination: localhost:5500' for a Remote + connection.) + + + Q-52: How can I tunnel my connection to x11vnc via an encrypted SSL + channel using an external tool like stunnel? + + It is possible to use a "lighter weight" encryption setup than SSH or + IPSEC. SSL tunnels such as stunnel (also stunnel.org) provide an + encrypted channel without the need for Unix users, passwords, and key + passphrases required for ssh (and at the other extreme SSL can also + provide a complete signed certificate chain of trust.) On the other + hand, since SSH is usually installed everywhere and firewalls often + let its port through, ssh is frequently the path of least resistance + (it also nicely manages public keys for you.) + + Update: As of Feb/2006 x11vnc has the options -ssl, -stunnel, and + -sslverify to provide integrated SSL schemes. They are discussed in + the Next FAQ (you probably want to skip to it now.) + + We include these non-built-in method descriptions below for historical + reference. They are handy because can be used to create SSL tunnels to + any VNC (or other type of) server. + + + Here are some basic examples using stunnel but the general idea for + any SSL tunnel utility is the same: + * Start up x11vnc and constrain it to listen on localhost. + * Then start up the SSL tunnel running on the same machine to + forward incoming connections to that x11vnc. + * Set up and run a similar SSL tunnel for the outgoing connection on + the VNC viewer machine pointing it to the SSL/x11vnc server. + * Optionally, set up server (or even client) public/private keys for + use in authenticating one side to the other. + * Finally, start the VNC Viewer and tell it to connect to the local + port (e.g. a vnc display localhost:0) where its outgoing SSL + tunnel is listening. + + We'll first use the stunnel version 3 syntax since it is the most + concise and Unixy. + + Start up x11vnc listening on port 5900: + x11vnc -display :0 -rfbport 5900 -localhost -bg -passwdfile ~/mypass + + Then start stunnel (version 3, not 4) with this command: + stunnel -d 5901 -r 5900 -p /path/to/stunnel.pem + + The above two commands are run on host "far-away.east". The + stunnel.pem is the self-signed PEM file certificate created when + stunnel is built. One can also create certificates signed by + Certificate Authorities or self-signed if desired using the x11vnc + utilities described there. + + SSL Viewers: Next, on the VNC viewer side we need an SSL tunnel to + encrypt the outgoing connection. The nice thing is any SSL tunnel can + be used because the protocol is a standard. For this example we'll + also use stunnel on the viewer side on Unix. First start up the + client-side stunnel (version 3, not 4): + stunnel -c -d localhost:5902 -r far-away.east:5901 + + Then point the viewer to the local tunnel on port 5902: + vncviewer -encodings "copyrect tight zrle hextile" localhost:2 + + That's it. Note that the ss_vncviewer script can automate this + easily, and so can the Enhanced TightVNC Viewer (SSVNC) package. + + Be sure to use a VNC password because unlike ssh by default the + encrypted SSL channel provides no authentication (only privacy.) With + some extra configuration one could also set up certificates to provide + authentication of either or both sides as well (and hence avoid + man-in-the-middle attacks.) See the stunnel and openssl documentation + and also the key management section for details. + + stunnel has also been ported to Windows, and there are likely others + to choose from for that OS. Much info for using it on Windows can be + found at the stunnel site and in this article The article also shows + the detailed steps to set up all the authentication certificates. (for + both server and clients, see also the x11vnc utilities that do this.) + The default Windows client setup (no certs) is simpler and only 4 + files are needed in a folder: stunnel.exe, stunnel.conf, libssl32.dll, + libeay32.dll. We used an stunnel.conf containing: +# stunnel.conf: +client = yes +options = ALL +[myvncssl] +accept = localhost:5902 +connect = far-away.east:5901 + + then double click on the stunnel.exe icon to launch it (followed by + pointing the VNC viewer to localhost:2). + + + stunnel inetd-like mode: + + As an aside, if you don't like the little "gap" of unencrypted TCP + traffic (and a localhost listening socket) on the local machine + between stunnel and x11vnc it can actually be closed by having stunnel + start up x11vnc in -inetd mode: + stunnel -p /path/to/stunnel.pem -P none -d 5900 -l ./x11vnc_sh + + Where the script x11vnc_sh starts up x11vnc: +#!/bin/sh +x11vnc -q -inetd -display :0 -passwdfile ~/mypass + + Note that this creates a separate x11vnc process for each incoming + connection (as any inetd x11vnc usage would), but for the case of + normally just one viewer at a time it should not be a big problem. + + + stunnel 4 syntax: + + Somewhat sadly, the stunnel version 4 syntax is not so amenable to the + command line or scripts. You need to create a config file with the + parameters. E.g.: + stunnel x11vnc.cfg + + Where the file x11vnc.cfg contains: +foreground = yes +pid = +cert = /path/to/stunnel.pem +[x11vnc_stunnel] +accept = 5901 +connect = 5900 + + One nice thing about version 4 is often the PEM file does not need to + be specified because stunnel finds it in its installed area. One other + gotcha the PEM file is usually only readable by root (it has the + private key afterall), so you'll need to relax the permissions or make + a copy that the user running x11vnc/stunnel can read. + + + SSL VNC Viewers: + + Regarding VNC viewers that "natively" do SSL unfortunately there do + not seem to be many. The SingleClick UltraVNC Java Viewer is SSL and + is compatible with x11vnc's -ssl option and stunnel.) Commercial + versions of VNC seem to have some SSL-like encryption built in, but we + haven't tried those either and they probably wouldn't work since their + (proprietary) SSL-like negotiation is likely embedded in the VNC + protocol unlike our case where it is external. + + Note: as of Mar/2006 libvncserver/x11vnc provides a SSL-enabled Java + applet that can be served up via the -httpdir or -http options when + -ssl is enabled. It will also be served via HTTPS via either the VNC + port (e.g. https://host:5900/) or a 2nd port via the -https option. + + In general current SSL VNC solutions are not particularly "seemless". + But it can be done, and with a wrapper script on the viewer side and + the -stunnel or -ssl option on the server side it works well and is + convenient. Here is a simple script ss_vncviewer that automates + running stunnel on the VNC viewer side on Unix a little more carefully + than the commands printed above. (One could probably do a similar + thing with a .BAT file on Windows in the stunnel folder.) + + Update Jul/2006: we now provide an Enhanced TightVNC Viewer (SSVNC) + package that starts up STUNNEL automatically along with some other + features. All binaries (stunnel, vncviewer, and some utilities) are + provided in the package. It works on Unix, Mac OS X, and Windows. + + + Q-53: Does x11vnc have built-in SSL tunneling? + + You can read about non-built-in methods in the Previous FAQ for + background. + + SSL tunnels provide an encrypted channel without the need for Unix + users, passwords, and key passphrases required for ssh (and at the + other extreme SSL can also provide a complete signed certificate chain + of trust.) On the other hand, since SSH is usually installed + everywhere and firewalls often let its port through, ssh is frequently + the path of least resistance. + + Built-in SSL x11vnc options: + + As of Feb/2006 the x11vnc -ssl option automates the SSL tunnel + creation on the x11vnc server side. An SSL-enabled Java Viewer applet + is also provided that can be served via HTTP or HTTPS to automate SSL + on the client side. + + The -ssl mode uses the www.openssl.org library if available at build + time. + + The mode requires an SSL certificate and key (i.e. .pem file.) These + are usually created via the openssl(1) program (in fact in for "-ssl" + (same as "-ssl SAVE") it will run openssl for you automatically.) So + the SSL is not completely "built-in" since this external tool needs to + be installed, but at least x11vnc runs it for you automatically. + + An -ssl example: + x11vnc -display :0 -ssl -passwdfile ~/mypass + + You'll get output like this: + 09/04/2006 19:27:35 Creating a self-signed PEM certificate... + 09/04/2006 19:27:35 + ... + + The SSL VNC desktop is: far-away.east:0 + PORT=5900 + SSLPORT=5900 + + In this case openssl(1) was used to create a PEM automatically. It + will prompt you if you want to protect it with with a passphrase. Use + "-ssl SAVE_NOPROMPT" to not be prompted. Use "-ssl TMP" to create a + temporary self-signed cert that will be discarded when x11vnc exits. + + Update: As of Nov/2008 x11vnc also supports the VeNCrypt SSL/TLS + tunnel extension to the VNC protocol. The older ANONTLS method (vino) + is also supported. This support is on by default when the -ssl option + is in use and can be fine-tuned using these options: -vencrypt, + -anontls, and -sslonly. + + The normal x11vnc -ssl operation is somewhat like a URL method + vncs://hostname if vnc://hostname indicates a standard unencrypted VNC + connection. Just as https://hostname is an SSL encrypted version of + http://hostname. The entire VNC session goes through the SSL tunnel. + VeNCrypt, on the other hand, switches to SSL/TLS early in the VNC + protocol handshake. x11vnc 0.9.6 supports both simultaneously when + -ssl is active. + + + SSL VNC Viewers:. Viewer-side will need to use SSL as well. See the + next FAQ and here for SSL enabled VNC Viewers, including SSVNC, to + connect to the above x11vnc via SSL. + + + As seen above, the PEM (privacy enhanced mail) file does not need to + be supplied if the openssl(1) command is available in PATH, in that + case a self-signed, certificate good the current and subsequent x11vnc + sessions is created (this may take a while on very slow machines.) + + In general, the PEM file contains both the Certificate (i.e. public + key) and the Private Key. Because of the latter, the file should be + protected from being read by untrusted users. The best way to do this + is to encrypt the key with a passphrase (note however this requires + supplying the passphrase each time x11vnc is started up.) + + See the discussion on x11vnc Key Management for some utilities + provided for creating and managing certificates and keys and even for + creating your own Certificate Authority (CA) for signing VNC server + and client certificates. This may be done by importing the certificate + into Web Browser or Java plugin keystores, or pointing stunnel to it. + The wrapper script ss_vncviewer provides an example on unix (see the + -verify option.) + + Here are some notes on the simpler default (non-CA) operation. To have + x11vnc save the generated certificate and key, use the "SAVE" keyword + like this: + x11vnc -ssl SAVE -display :0 ... + + (this is the same as the default: "-ssl".) This way it will be saved + in the default directory ~/.vnc/certs/ as server.crt (the certificate + only) and server.pem (both certificate and private key.) This opens up + the possibility of copying the server.crt to machines where the VNC + Viewer will be run to enable authenticating the x11vnc SSL VNC server + to the clients. When authentication takes place this way (or via the + more sophisticated CA signing described here), then + Man-In-The-Middle-Attacks are prevented. Otherwise, the SSL encryption + only provides protection against passive network traffic "sniffing" + (i.e. you are not protected against M-I-T-M attacks.) Nowadays, most + people seem mostly concerned mainly about passive sniffing (and the + default x11vnc SSL mode protects against it.) Note that there are + hacker tools like dsniff/webmitm and cain that implement SSL + Man-In-The-Middle attacks. They rely on the client not bothering to + check the cert. + + + One can test to some degree that SSL is working after starting x11vnc + with the -stunnel or -ssl option. From another machine one can use the + openssl command something like this: + openssl s_client -debug -msg -showcerts -connect far-away.east:5900 + + After all of the debugging output and informational messages you'll + see the string "RFB 003.008" that came from x11vnc. Pointing a web + browser connecting to: https://far-away.east:5900/ and then viewing + the SSL certificate information about the connection in the panels + will also work. + + Note: If you serve up the SSL enabled Java VNC Viewer via something + like: + x11vnc -ssl -httpdir /usr/local/share/x11vnc/classes/ssl + + (or just the -http option), you can test it out completely using that, + including using https to download it into the browser and connect to + x11vnc. + + + The older -stunnel option: Before the -ssl option there was a + convenience option -stunnel that would start an external SSL tunnel + for you using stunnel. The -ssl method is the preferred way, but for + historical reference we keep the -stunnel info here. + + The -stunnel mode requires the stunnel.mirt.net command stunnel(8) to + be installed on the system. + + Some -stunnel examples: + x11vnc -display :0 -stunnel /path/to/stunnel.pem -passwdfile ~/mypass + + x11vnc -display :0 -stunnel SAVE ... + + You'll get output like this: + The VNC desktop is: localhost:50 + The SSL VNC desktop is: far-away.east:0 + PORT=5950 + SSLPORT=5900 + + That indicates stunnel is listening on port 5900 for incoming + SSL-wrapped VNC connections from viewers. x11vnc is listening for + local connections on port 5950 in this case (remote viewers cannot + connect to it directly.) For -stunnel to work the stunnel command must + be installed on the machine and available in PATH (note stunnel is + often installed in sbin directories rather than bin.) Note that the + default "-stunnel" by itself creates a temporary cert (as in "-ssl + TMP".) + + + Q-54: How do I use VNC Viewers with built-in SSL tunneling? + + Notes on using "native" VNC Viewers with SSL: + + There aren't any native VNC Viewers that do SSL (ask your VNC viewer + developer to add the feature.) So a tunnel must be setup that you + point the VNC Viewer to. This is often STUNNEL. You can do this + manually, or use the ss_vncviewer script on Unix, or our Enhanced + TightVNC Viewer (SSVNC) package on Unix, Windows, or MacOSX. See the + next section for Java Web browser SSL VNC Viewers (you only need a + Java-enabled Web browser for it to work.) + + Notes on the SSL enabled Java VNC Viewer provided in x11vnc + classes/ssl/VncViewer.jar: + + A Java applet VNC Viewer allows you to connect to a VNC Server from a + Java-enabled Web browser. + + The SSL enabled Java VNC Viewer (VncViewer.jar) in the x11vnc package + supports only SSL based connections by default. As mentioned above the + -httpdir can be used to specify the path to .../classes/ssl. A typical + location might be /usr/local/share/x11vnc/classes/ssl. Or -http can be + used to try to have it find the directory automatically. + + Also note that the SingleClick UltraVNC Java Viewer is compatible with + x11vnc's -ssl SSL mode. (We tested it this way: "java -cp + ./VncViewer.jar VncViewer HOST far-away.east PORT 5900 USESSL 1 + TRUSTALL 1") + + The Java viewer uses SSL to communicate securely with x11vnc. Note + that the applet can optionally also be downloaded into your web + browser via HTTPS (which is HTTP over SSL.) This way the HTML page and + the Java applet itself are also delivered securely with SSL (as + opposed to only the VNC traffic being encrypted with SSL.) + + For this case the output will be something like this: + x11vnc -ssl SAVE -http + ... + The SSL VNC desktop is: far-away.east:0 + Java SSL viewer URL: https://far-away.east:5900/ + Java SSL viewer URL: http://far-away.east:5800/ + PORT=5900 + SSLPORT=5900 + + Indicating the two URLs (the first one encrypted, the second not) one + could point the web browser at to get the VNC viewer applet. E.g. put + this + http://far-away.east:5800/ + + or: + https://far-away.east:5900/ + + into your Java-enabled Web browser. + + Note that KDE's Konqueror web browser seems to have problems with + https Java applets, so you'll have to use the http/5800 with it (if + you get https/5900 working let us know how you did it.) + + If you are using a router/firewall with port-redirection, and you are + redirecting ports other than the default ones (5800, 5900) listed + above see here. + + The https service provided thru the actual VNC port (5900 in the above + example) can occasionally be slow or unreliable (it has to read some + input and try to guess if the connection is VNC or HTTP.) If it is + unreliable for you and you still want to serve the Java applet via + https, use the -https option to get an additional port dedicated to + https (its URL will also be printed in the output.) + + Another possibility is to add the GET applet parameter: + https://far-away.east:5900/?GET=1 + + This will have the VNC Viewer send a special HTTP GET string "GET + /request.https.vnc.connection HTTP/1.0" that x11vnc will notice more + quickly as a request for a VNC connection. Otherwise it must wait for + a timeout to expire before it assumes a VNC connection. + + You may also use "urlPrefix=somestring" to have /somestring prepended + to /request.https.vnc.connection". Perhaps you are using a web server + proxy scheme to enter a firewall or otherwise have rules applied to + the URL. If you need to have any slashes "/" in "somestring" use + "_2F_" (a deficiency in libvncserver prevents using the more natural + "%2F".) + + You apply multiple applet parameters in the regular URL way, e.g.: + https://far-away.east:5900/?GET=1&urlPrefix=mysubdir&... + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + + Tips on Getting the SSL Java Applet Working the First Time: + Unfortunately, it can be a little tricky getting the SSL VNC Java + Viewer working with x11vnc. Here are some tips to getting working the + first time (afterwards you can incrementally customize with more + complex settings.) + * First try it on the LAN: Do NOT try to have it work the first time + going through firewalls, Web proxies, home router port + redirections, or Apache portal. Just try a direct connection over + your LAN first (if you only have 1 machine and no LAN, just do a + direct connection to the same machine: localhost.) If the LAN + machine you run x11vnc on has its own host-level firewall (most + linux machine come with that on by default), disable it or at + least let tcp ports 5800-6000 through. + * First try HTTP to download the Java Applet: x11vnc can serve both + the Java Applet jar file and VNC out of the same port (both + tunneled through SSL, see below.) But it can lead to timing and + other problems. So first try HTTP instead of HTTPS to download the + Applet jar file (VncViewer.jar.) That is to say try + http://hostname:5800 in your web browser first before trying + https://hostname:5900. x11vnc will print out the ports and URLs it + is using, so use the HTTP one it prints out. + * Always Restart the Browser: If you are having failures and have to + repeatedly retry things ALWAYS restart the browser (i.e. + completely exit it and then start a new browser process) each + time. Otherwise as you are changing things the browser may + "remember" failed applet downloads, etc. and just add to the + confusion and irreproducibility. If you see it trying to download + VncViewer.class (instead of VncViewer.jar) you know it is really + confused and needs to be restarted. + * Step Lively: If you get Browser or Java VM or VNC Viewer applet + dialog boxes saying things like "Do you want to trust this + certificate?" or "The hostname does not match the one on the + certificate", etc. just go through them as quickly as possible. + x11vnc cannot wait forever for each SSL connection, and so if you + dawdle too long inspecting the certs, etc it can lead to problems. + Get it working first before taking your time to read the details + in the dialogs, etc. + * No inetd, Please: Even if you intend to deploy via inetd or xinetd + eventually, get that working later (and remember do not use + something like "-ssl TMP" that creates a new temporary SSL + certificate for every new socket connection.) + * Nothing Fancy: Do not try fancy stuff like -svc, -create, -unixpw, + "-users unixpw=", "-users sslpeer=", -sslverify, etc. Just get the + simplest connection working first and then incrementally add what + you need. + + So the recommended test command lines are: + x11vnc -ssl SAVE -http + x11vnc -ssl SAVE -httpdir /path/to/x11vnc/classes/ssl + + Use the latter if x11vnc cannot automatically find the classes/ssl + directory (this what the -http option instructs it to do.) Then point + your browser to the HTTP (not HTTPS) URL it prints out. + + Following the above guidelines, did it work? If so, Congratulations!! + you created an SSL encrypted connection between the SSL Java applet + running in your web browser and x11vnc. The fact that you used HTTP + instead of HTTPS to download the applet is not the end of the world + (some users do it this way), the main thing is that the VNC traffic is + encrypted with SSL. If you are having trouble even with the above + baseline test case feel free to contact me (please send the Full + x11vnc output, not just part of it; the complete x11vnc command line; + the URL(s) entered in the browser; the full Java Console output; and + anything else you can think of.) + + Next, you can add the features you want one by one testing it still + works each time. I suggest first turning on the HTTPS applet download + (https://hostname:5900) if that is what you intend to use. That one + gives the most trouble because of the ambiguity of passing two + different protocols (HTTP and VNC) through the same SSL service port. + + Next, turn on inetd if you intend to use that (this can be tricky too, + be sure to use -oa logfile and inspect it carefully if there are + problems.) If you are going to use non-standard ports (e.g. "-rfbport + 443" as root), work on that next. Then enable the firewall, router + port redirection channel (you will somehow need to be outside to do + that, maybe test that through another VNC session.) + + Then, if you plan to use them, enable "fancy stuff" like "-svc" or + "-unixpw", etc, etc. Be sure to add a password either "-rfbauth" or + "-unixpw" or both. If you need to have the web browser use a corporate + Web Proxy (i.e. it cannot connect directly) work on that last. Ditto + for the Apache portal. + + + Router/Firewall port redirs: If you are doing port redirection at + your router to an internal machine running x11vnc AND the internet + facing port is different from the internal machine's VNC port, you + will need to apply the PORT applet parameter to indicate to the applet + the Internet facing port number (otherwise by default the internal + machine's port, say 5900, is sent and that of course is rejected at + the firewall/router.) For example: + https://far-away.east:443/?GET=1&PORT=443 + + So in this example the user configures his router to redirect + connections to port 443 on his Internet side to, say, port 5900 on the + internal machine running x11vnc. See also the -httpsredir option that + will try to automate this for you. + + To configure your router to do port redirection, see its instructions. + Typically, from the inside you point a web browser to a special URL + (e.g. http://192.168.1.1) and you get a web interface to configure it. + Look for something like "Port Redirection" or "Port Forwarding", + probably under "Advanced" or something like that. If you have a Linux + or Unix system acting as your firewall/router, see its firewall + configuration. + + You can also use x11vnc options -rfbport NNNNN and -httpport NNNNN to + match the ports that your firewall will be redirecting to the machine + where x11vnc is run. + + + Tedious Dialogs: If you do serve the SSL enabled Java viewer via https + be prepared for quite a number of "are you sure you trust this site?" + dialogs: + * First from the Web browser that cannot verify the self-signed + certificate when it downloads index.vnc. + * From the Web browser again noting that the common name on the + certificate does not match the hostname of the remote machine. + * Next from the Java VM that cannot verify the self-signed + certificate when it downloads VncViewer.jar. + * And also from the Java VM again noting that the common name on the + certificate does not match the hostname of the remote machine. + * Finally from the Java VncViewer applet itself saying it cannot + verify the certificate! (or a popup asking you if you want to see + the certificate.) + + Note that sometimes if you pause too long at one of the above dialogs + then x11vnc may exceed a timeout and assume the current socket + connection is VNC instead of the HTTPS it actually is (but since you + have paused too long at the dialog the GET request comes too late.) + Often hitting Reload and going through the dialogs more quickly will + let you connect. The Java VM dialogs are the most important ones to + NOT linger at. If you see in the x11vnc output a request for + VncViewer.class instead of VncViewer.jar it is too late... you will + need to completely restart the Web browser to get it to try for the + jar again. You can use the -https option if you want a dedicated port + for HTTPS connections instead of sharing the VNC port. + + To see example x11vnc output for a successful https://host:5900/ + connection with the Java Applet see This Page. And here is a newer + example including the Java Console output. + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + + Notes on the VNC Viewer ss_vncviewer wrapper script: + + If you want to use a native VNC Viewer with the SSL enabled x11vnc you + will need to run an external SSL tunnel on the Viewer side. There do + not seem to be any native SSL VNC Viewers outside of our x11vnc and + SSVNC packages. The basic ideas of doing this were discussed for + external tunnel utilities here. + + The ss_vncviewer script provided with x11vnc and SSVNC can set up the + stunnel tunnel automatically on unix as long as the stunnel command is + installed on the Viewer machine and available in PATH (and vncviewer + too of course.) Note that on a Debian based system you will need to + install the package stunnel4 not stunnel. You can set the environment + variables STUNNEL and VNCVIEWERCMD to point to the correct programs if + you want to override the defaults. + + Here are some examples: + 1) ss_vncviewer far-away.east:0 + + 2) ss_vncviewer far-away.east:0 -encodings "copyrect tight zrle hextile" + + 3) ss_vncviewer -verify ./server.crt far-away.east:0 + + 4) ss_vncviewer -mycert ./client.pem far-away.east:0 + + 5) ss_vncviewer -proxy far-away.east:8080 myworkstation:0 + + The first one is the default mode and accepts the x11vnc certificate + without question. The second one is as the first, but adds the + -encodings options to the vncviewer command line. + + The third one requires that the x11vnc server authenticate itself to + the client against the certificate in the file ./server.crt (e.g. one + created by "x11vnc -ssl SAVE" and safely copied to the VNC viewer + machine.) + + The fourth one is for VNC Viewer authentication, it uses ./client.pem + to authenticate itself to x11vnc. One can supply both -verify and + -mycert simultaneously. + + The fifth one shows that Web proxies can be used if that is the only + way to get out of the firewall. If the "double proxy" situation arises + separate the two by commas. See this page for more information on how + Web proxies come into play. + + If one uses a Certificate Authority (CA) scheme described here, the + wrapper script would use the CA cert instead of the server cert: + 3') ss_vncviewer -verify ./cacert.crt far-away.east:0 + + Update Jul/2006: we now provide an Enhanced TightVNC Viewer (SSVNC) + package that starts up STUNNEL automatically along with some other + features. All binaries (stunnel, vncviewer, and some utilities) are + provided in the package. It works on Unix, Mac OS X, and Windows. + + + Q-55: How do I use the Java applet VNC Viewer with built-in SSL + tunneling when going through a Web Proxy? + The SSL enabled Java VNC Viewer and firewall Proxies: + + SSL and HTTPS aside, there is a general problem with Firewall Proxies + and Java Applets that open sockets. The applet is downloaded + successfully (through the browser) using HTTP and the proxy, but when + the applet tries to reconnect to the originating host (the only one + allowed by security) it does not use the proxy channel. So it cannot + reconnect to the server the applet came from! + + We have found a convenient workaround: in the directory where + VncViewer.jar resides there is a digitally signed version of the same + applet called SignedVncViewer.jar. Since the applet is digitally + signed, there will be an additional dialog from the Java VM plugin + asking you if you want to trust the applet fully. + + You should say "Yes". If you do, the applet will be run in a mode + where it can try to determine the firewall proxy host name and port + (it will ask you for them if it cannot find them.) This way it can + connect directly to the Proxy and then request the CONNECT method to + be redirected to the originating host (the x11vnc VNC Server.) SSL is + then layered over this socket. + + To do this you should use the proxy.vnc HTML file like via this URL in + your browser: + https://yourmachine.com:5900/proxy.vnc + + (instead of the unsigned one in https://yourmachine.com:5900/ that + gives the default index.vnc) + + Proxies that limit CONNECT to ports 443 and 563: + + Things become trickier if the Web proxy restricts which CONNECT ports + can be redirected to. For security, some (most?) proxies only allow + port 443 (HTTPS) and 563 (SNEWS) by default. In this case, the only + thing to do is run x11vnc on that low port, e.g. "-rfbport 443", (or + use a port redirection on, say, a firewall or router port 443 to the + internal machine.) + + If you do such a redirection to an internal machine and x11vnc is not + listening on port 443, you will probably need to edit proxy.vnc. + Suppose the SSL x11vnc server was listening on port 5901. You should + change the line in proxy.vnc from: + + + to: + + + Since otherwise $PORT will be expanded to 5901 by x11vnc and the + viewer applet will fail to connect to that port on the firewall. + + Another way to achieve the same thing is to use the applet PORT + parameter: + https://yourmachine.com/proxy.vnc?PORT=443 + + this is cleaner because it avoids editing the file, but requires more + parameters in the URL. See also the -httpsredir x11vnc option that + will try to automate this for you. To use the GET trick discussed + above, do: + https://yourmachine.com/proxy.vnc?GET=1&PORT=443 + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + Here is an example of Java Console and x11vnc output for the Web proxy + case. + + + Note that both the ss_vncviewer stunnel Unix wrapper script and + Enhanced TightVNC Viewer (SSVNC) can use Web proxies as well even + though they do not involve a Web browser. + + + Q-56: Can Apache web server act as a gateway for users to connect via + SSL from the Internet with a Web browser to x11vnc running on their + workstations behind a firewall? + Yes. You will need to configure apache to forward these connections. + It is discussed here. This SSL VNC portal provides a clean alternative + to the traditional method where the user uses SSH to log in through + the gateway to create the encrypted port redirection to x11vnc running + on her desktop. + + Also see the desktop.cgi CGI script method that achieves much of what + this Apache VNC SSL portal method does (as long as desktop.cgi's 'port + redirection' mode is enabled.) + + + Q-57: Can I create and use my own SSL Certificate Authority (CA) with + x11vnc? + Yes, see this page for how to do this and the utility commands x11vnc + provides to create and manage many types of certificates and private + keys. + + + + [Display Managers and Services] + + Q-58: How can I run x11vnc as a "service" that is always available? + + There are a number of ways to do this. The primary thing you need to + decide is whether you want x11vnc to connect to the X session on the + machine 1) regardless of who (or if anyone) has the X session, or 2) + only if a certain user has the X session. Because X sessions are + protected by X permissions (MIT-MAGIC-COOKIE files XAUTHORITY and + $HOME/.Xauthority) the automatically started x11vnc will of course + need to have sufficient permissions to connect to the X display. + + Here are some ideas: + * Use the description under "Continuously" in the FAQ on x11vnc and + Display Managers + * Use the description in the FAQ on x11vnc and inetd(8) + * Use the description in the FAQ on Unix user logins and inetd(8) + * Start x11vnc from your $HOME/.xsession (or $HOME/.xinitrc or + autostart script or ...) + * Although less reliable, see the x11vnc_loop rc.local hack below. + + The display manager scheme will not be specific to which user has the + X session unless a test is specifically put into the display startup + script (often named Xsetup.) The inetd(8) scheme may or may not be + specific to which user has the X session (and it may not be able to do + all users via the XAUTHORITY permission issues.) + + The .xsession/.xinitrc scheme is obviously is specific to a particular + user and only when they are logged into X. If you do not know what a + $HOME/.xsession script is or how to use one, perhaps your desktop has + a "session startup commands" configuration option. The command to be + run in the .xsession or .xinitrc file may look like this: +x11vnc -logfile $HOME/.x11vnc.log -rfbauth $HOME/.vnc/passwd -forever -bg + + plus any other options you desire. + + Depending on your desktop and/or OS/distribution the automatically run + X startup scripts (traditionally .xsession/.xinitrc) may have to be in + a different directory or have a different basename. One user + recommends the description under 'Running Scripts Automatically' at + this link. + + Firewalls: note all methods will require the host-level firewall to be + configured to allow connections in on a port. E.g. 5900 (default VNC + port) or 22 (default SSH port for tunnelling VNC.) Most systems these + days have firewalls turned on by default, so you will actively have to + do something to poke a hole in the firewall at the desired port + number. See your system administration tool for Firewall settings + (Yast, Firestarter, etc.) + + + Q-59: How can I use x11vnc to connect to an X login screen like xdm, + GNOME gdm, KDE kdm, or CDE dtlogin? (i.e. nobody is logged into an X + session yet.) + + We describe two scenarios here. The first is called 'One time only' + meaning you just need to do it quickly once and don't want to repeat; + and the second is called 'Continuously' meaning you want the access to + be available after every reboot and after every desktop logout. + _________________________________________________________________ + + One time only: If the X login screen is running and you just want to + connect to it once (i.e. a one-shot): + + It is usually possible to do this by just adjusting the XAUTHORITY + environment variable to point to the correct MIT-COOKIE auth file + while running x11vnc as root, e.g. for the gnome display manager, GDM: + x11vnc -auth /var/gdm/:0.Xauth -display :0 + + (the -auth option sets the XAUTHORITY variable for you.) + + There will be a similar thing to do for xdm using however a different + auth directory path (perhaps something like + /var/lib/xdm/authdir/authfiles/A:0-XQvaJk) for the xdm greeter or + /var/lib/kdm/A:0-crWk72 (or /var/run/xauth/A:0-qQPftr, etc. etc) for + the kdm greeter. Of course, the random characters in the file basename + will vary and you will need to use the actual filename on your system. + Read your system docs to find out where the display manager cookie + files are kept. + + Trick: sometimes ps(1) can reveal the X server process -auth argument + (e.g. "ps wwaux | grep auth") and hence the path to the auth file. + + x11vnc must be run as root for this because the /var/gdm/:0.Xauth, + /var/lib/kdm/A:0-crWk72, etc. auth files are only readable by root. If + you do not want to run x11vnc as root, you can copy (as root or sudo) + the auth file to some location and make it readable by your userid. + Then run x11vnc as your userid with -auth pointed to the copied file. + + Update Dec/2009: use "-auth guess" to have x11vnc try to guess the + location of the auth file for you. + + You next connect to x11vnc with a VNC viewer, give your username and + password to the X login prompt to start your session. + + Note: GDM: gdm seems to have an annoying setting that causes x11vnc + (and any other X clients) to be killed after the user logs in. Setting + KillInitClients=false in the [daemon] section of /etc/X11/gdm/gdm.conf + (or /etc/gdm/gdm.conf, etc.) avoids this. Otherwise, just restart + x11vnc and then reconnect your viewer. Other display managers (kdm, + etc) may also have a similar problem. One user reports having to alter + "gdm.conf-custom" as well. + + Note: Solaris: For dtlogin in addition to the above sort of trick + (BTW, the auth file should be in /var/dt), you'll also need to add + something like Dtlogin*grabServer:False to the Xconfig file + (/etc/dt/config/Xconfig or /usr/dt/config/Xconfig on Solaris, see the + example at the end of this FAQ.) Then restart dtlogin, e.g.: + /etc/init.d/dtlogin stop; /etc/init.d/dtlogin start or reboot. + + Update Nov/2008: Regarding GDM KillInitClients: see the -reopen option + for another possible workaround. + + Update Oct/2009: Regarding GDM KillInitClients: starting with x11vnc + 0.9.9 it will try to apply heuristics to detect if a window manager is + not running (i.e. whether the Display Manager Greeter Login panel is + still up.) If it thinks the display manager login is still up it will + delay creating windows or using XFIXES. The former is what GDM uses to + kill the initial clients, use of the latter can cause a different + problem: an Xorg server crash. So with 0.9.9 and later it should all + work without needing to set KillInitClients=false (which is a good + because recent GDM, v2.24, has removed this option) or use -noxfixes. + To disable the heuristics and delaying set X11VNC_AVOID_WINDOWS=never; + to set the delay time explicitly use, e.g., X11VNC_AVOID_WINDOWS=120 + (delays for 120 seconds after the VNC connection; you have that long + to log in.) + _________________________________________________________________ + + Continuously: Have x11vnc reattach each time the X server is + restarted (i.e. after each logout and reboot): + + To make x11vnc always attached to the X server including the login + screen you will need to add a command to a display manager startup + script. + + Please consider the security implications of this! The VNC display for + the X session always accessible (but hopefully password protected.) + Add -localhost if you only plan to access via a SSH tunnel. + + The name of the display manager startup script file depends on desktop + used and seem to be: + GDM (GNOME) /etc/X11/gdm/Init/Default + /etc/gdm/Init/Default + KDM (KDE) /etc/kde*/kdm/Xsetup + XDM /etc/X11/xdm/Xsetup (or sometimes xdm/Xsetup_0) + CDE /etc/dt/config/Xsetup + + although the exact location can be operating system, distribution, and + time dependent. See the documentation for your display manager: + gdm(1), kdm(1), xdm(1), dtlogin(1) for additional details. There may + also be display number specific scripts: e.g. Xsetup_0 vs. Xsetup, you + need to watch out for. + + Note: You should read and understand all of the Note's and Update's + in the 'One time only' section above. All of the GDM topics apply here + as well: + + Note: GDM: The above (in 'One time only') gdm setting of + KillInitClients=false in /etc/X11/gdm/gdm.conf (or /etc/gdm/gdm.conf, + etc.) for GDM is needed here as well. Other display managers (KDM, + etc) may also have a similar problem. + + Also see the Update Oct/2009 above where x11vnc 0.9.9 and later + automatically avoids being killed. + + Note: DtLogin: The above (in 'One time only') + Dtlogin*grabServer:False step for Solaris will be needed for dtlogin + here as well. + + In any event, the line you will add to the display manager script + (Xsetup, Default, or whatever) will look something like: + /usr/local/bin/x11vnc -rfbauth /path/to/the/vnc/passwd -o /var/log/x11vnc.log + -forever -bg + + where you should customize the exact command to your needs (e.g. + -localhost for SSH tunnel-only access; -ssl SAVE for SSL access; etc.) + + Happy, happy, joy, joy: Note that we do not need to specify -display + or -auth because happily they are already set for us in the DISPLAY + and XAUTHORITY environment variables for the Xsetup script!!! + + You may also want to force the VNC port with something like "-rfbport + 5900" (or -N) to avoid autoselecting one if 5900 is already taken. + _________________________________________________________________ + + Fedora/gdm: Here is an example of what we did on a vanilla install of + Fedora-C3 (seems to use gdm by default.) Add a line like this to + /etc/X11/gdm/Init/:0 + /usr/local/bin/x11vnc -rfbauth /etc/x11vnc.passwd -forever -bg -o /var/log/x1 +1vnc.log + + And then add this line to /etc/X11/gdm/gdm.conf (or /etc/gdm/gdm.conf, + etc.) in the [daemon] section: + KillInitClients=false + + Then restart: /usr/sbin/gdm-restart (or reboot.) The + KillInitClients=false setting is important: without it x11vnc will be + killed immediately after the user logs in. Here are full details on + how to configure gdm + _________________________________________________________________ + + Solaris/dtlogin: Here is an example of what we did on a vanilla + install of Solaris: + Make the directory /etc/dt/config: + mkdir -p /etc/dt/config + + Copy over the Xconfig file for customization: + cp /usr/dt/config/Xconfig /etc/dt/config/Xconfig + + Edit /etc/dt/config/Xconfig and uncomment the line: + Dtlogin*grabServer: False + + Next, copy over Xsetup for customization: + cp /usr/dt/config/Xsetup /etc/dt/config/Xsetup + + Edit /etc/dt/config/Xsetup and at the bottom put a line like: + /usr/local/bin/x11vnc -forever -o /var/log/x11vnc.log -bg + + (tweaked to your local setup and preferences, a password via -rfbauth, + etc. would be a very good idea.) + + Restart the X server and dtlogin: + /etc/init.d/dtlogin stop + /etc/init.d/dtlogin start + + (or reboot or maybe just restart the X session.) + _________________________________________________________________ + + KDM: One user running the kdm display manager reports putting this + line: + x11vnc -forever -rfbauth /home/xyz/.vnc/passwd -bg -o /var/log/x11vnc.log + + in /etc/kde/kdm/Xsetup. After rebooting the system it all seemed to + work fine. + _________________________________________________________________ + + + If you do not want to deal with any display manager startup scripts, + here is a kludgey script that can be run manually or out of a boot + file like rc.local: x11vnc_loop It will need some local customization + before running. Because the XAUTHORITY auth file must be guessed by + this script, use of the display manager script method described above + is greatly preferred. There is also the -loop option that does + something similar. + + If the machine is a traditional Xterminal you may want to read this + FAQ. + + Firewalls: note all methods will require the host-level firewall to be + configured to allow connections in on a port. E.g. 5900 (default VNC + port) or 22 (default SSH port for tunnelling VNC.) Most systems these + days have firewalls turned on by default, so you will actively have to + do something to poke a hole in the firewall at the desired port + number. See your system administration tool for Firewall settings + (Yast, Firestarter, etc.) + + + Q-60: Can I run x11vnc out of inetd(8)? How about xinetd(8)? + + Yes, perhaps a line something like this in /etc/inetd.conf will do it + for you: + + 5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_sh + + where the shell script /usr/local/bin/x11vnc_sh uses the -inetd option + and looks something like (you'll need to customize to your settings.) +#!/bin/sh +/usr/local/bin/x11vnc -inetd -display :0 -auth /home/fred/.Xauthority \ + -rfbauth /home/fred/.vnc/passwd -o /var/log/x11vnc_sh.log + + Important: Note that you must redirect the standard error output to a + log file (e.g. -o logfile) or "2>/dev/null" for proper operation via + inetd (otherwise the standard error also goes to the VNC vncviewer, + and that confuses it greatly, causing it to abort.) If you do not use + a wrapper script as above but rather call x11vnc directly in + /etc/inetd.conf and do not redirect stderr to a file, then you must + specify the -q (aka -quiet) option: "/usr/local/bin/x11vnc -q -inetd + ...". When you supply both -q and -inet and no "-o logfile" then + stderr will automatically be closed (to prevent, e.g. library stderr + messages leaking out to the viewer.) The recommended practice is to + use "-o logfile" to collect the output in a file or wrapper script + with "2>logfile" redirection because the errors and warnings printed + out are very useful in troubleshooting problems. + + Note also the need to set XAUTHORITY via -auth to point to the + MIT-COOKIE auth file to get permission to connect to the X display + (setting and exporting the XAUTHORITY variable accomplishes the same + thing.) See the x11vnc_loop file in the previous question for more + ideas on what that auth file may be, etc. The scheme described in the + FAQ on Unix user logins and inetd(8) works around the XAUTHORITY issue + nicely. + + Note: On Solaris you cannot have the bare number 5900 in + /etc/inetd.conf, you'll need to replace it with a word like x11vnc an + then put something like "x11vnc 5900/tcp" in /etc/services. + + Since the process runs as root, it might be a bad idea to have the + logfile in a world-writable area like /tmp if there are untrustworthy + users on the machine. Perhaps /var/log is a better place. + + Be sure to look at your /etc/hosts.allow and /etc/hosts.deny settings + to limit the machines that can connect to this service (your desktop!) + For the above example with /etc/hosts.allow: + x11vnc_sh : 123.45.67.89 + + A really safe way to do things is to limit the above inetd to + localhost only (via /etc/hosts.allow) and use ssh to tunnel the + incoming connection. Using inetd for this prevents there being a tiny + window of opportunity between x11vnc starting up and your vncviewer + connecting to it. Always use a VNC password to further protect against + unwanted access. + + For xinetd(8), one user reports he created the file + /etc/xinetd.d/x11vncservice containing the following: +# default: off +# description: +service x11vncservice +{ + flags = REUSE NAMEINARGS + port = 5900 + type = UNLISTED + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/sbin/tcpd + server_args = /usr/local/bin/x11vnc_sh + disable = no +} + + With the contents of /usr/local/bin/x11vnc_sh similar to the example + given above. One user reports this works with avoiding the wrapper + script: +service x11vncservice +{ + port = 5900 + type = UNLISTED + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/local/bin/x11vnc + server_args = -inetd -q -display :0 -auth /var/gdm/:0.Xauth + disable = no +} + + (or one can replace the -q with say "-o /var/log/x11vnc.log" to + capture a log) + + The above works nicely for GDM because the -auth file is a fixed name. + For KDM or XDM the filename varies. Here is one idea for a x11vnc_sh + wrapper to try to guess the name: +#!/bin/sh +COLUMNS=256 +export COLUMNS +authfile=`ps wwaux | grep '/X.*-auth' | grep -v grep | sed -e 's/^.*-auth *//' +-e 's/ .*$//' | head -n 1` + +if [ -r "$authfile" ]; then + exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -display :0 -a +uth "$authfile" +fi +exit 1 + + Starting with x11vnc 0.9.3 this can be automated by: +#!/bin/sh +exec /usr/local/bin/x11vnc -inetd -o /var/log/x11vnc.log -find -env FD_XDM=1 + + + Q-61: Can I have x11vnc advertise its VNC service and port via mDNS / + Zeroconf (e.g. Avahi) so VNC viewers on the local network can detect + it automatically? + + Yes, as of Feb/2007 x11vnc supports mDNS / Zeroconf advertising of its + service via the Avahi client library. Use the option -avahi (same as + -mdns or -zeroconf) to enable it. Depending on your setup you may need + to install Avahi (including the development/build packages), enable + the server: avahi-daemon and avahi-dnsconfd, and possibly open up UDP + port 5353 on your firewall. + + If the Avahi client library or build environment is not available at + build-time, then at run-time x11vnc will try to look for external + helper programs, avahi-browse(1) or dns-sd(1), to do the work. + + The service was tested with Chicken of the VNC ("Use Bonjour" + selected) on a Mac on the same network and the service was noted and + listed in the servers list. Clicking on it and then "Connect" + connected automatically w/o having to enter any hostnames or port + numbers. + + It appears SuSE 10.1 comes with avahi (or you can add packages, e.g. + avahi-0.6.5-27) but not the development package (you can use the + OpenSuSE avahi-devel rpm.) Unfortunately, you may need to disable + another Zeroconf daemon "/etc/init.d/mdnsd stop", before doing + "/etc/init.d/avahi-daemon start" and "/etc/init.d/avahi-dnsconfd + start". We also had to comment out the browse-domains line in + /etc/avahi/avahi-daemon.conf. Hopefully there is "LessConf" to do on + other distros/OS's... + + + Q-62: Can I have x11vnc allow a user to log in with her UNIX username + and password and then have it find her X session display on that + machine and then attach to it? How about starting an X session if one + cannot be found? + + The easiest way to do this is via inetd(8) using the -unixpw and + -display WAIT options. The reason inetd(8) makes this easier is that + it starts a new x11vnc process for each new user connection. Otherwise + a wrapper would have to listen for connections and spawn new x11vnc's + (see this example and also the -loopbg option.) inetd(8) is not + required for this, but it makes some aspects more general. + + Also with inetd(8) users always connect to a fixed VNC display, say + hostname:0, and do not need to memorize a special VNC display number + just for their personal use, etc. + + Update: Use the -find, -create, -svc, and -xdmsvc options that are + shorthand for common FINDCREATEDISPLAY usage modes (e.g. terminal + services) described below. (i.e. simply use "-svc" instead of the + cumbersome "-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb -unixpw -users + unixpw= -ssl SAVE") + + The -display WAIT option makes x11vnc wait until a VNC viewer is + connected before attaching to the X display. + + Additionally it can be used to run an external command that returns + the DISPLAY and XAUTHORITY data. We provide some useful builtin ones + (FINDDISPLAY and FINDCREATEDISPLAY below), but in principle one could + supply his own script: "-display WAIT:cmd=/path/to/find_display" where + the script find_display might look something like this. + + A default script somewhat like the above is used under "-display + WAIT:cmd=FINDDISPLAY" (same as -find) The format for any such command + is that it returns DISPLAY=:disp as the first line and any remaining + lines are either XAUTHORITY=file or raw xauth data (the above example + does the latter.) If applicable (-unixpw mode), the program is run as + the Unix user name who logged in. + + On Linux if the virtual terminal is known the program appends ",VT=n" + to the DISPLAY line; a chvt n will be attempted automatically. Or if + only the X server process ID is known it appends ",XPID=n" (a chvt + will be attempted by x11vnc.) + + Tip: Note that the -find option is an alias for "-display + WAIT:cmd=FINDDISPLAY". Use it! + + The -unixpw option allows UNIX password logins. It conveniently knows + the Unix username whose X display should be found. Here are a couple + /etc/inetd.conf examples of this usage: +5900 stream tcp nowait nobody /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd +-unixpw \ + -find -o /var/log/x11vnc.log -ssl SAVE -ssldir /usr/local/certs +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd +-unixpw \ + -find -o /var/log/x11vnc.log -ssl SAVE -users unixpw= + + Note we have used the -find alias and the very long lines have been + split. An alternative is to use a wrapper script, e.g. + /usr/local/bin/x11vnc.sh that has all of the options. (see also the + -svc alias.) + + In the first inetd line x11vnc is run as user "nobody" and stays user + nobody during the whole session. The permissions of the log files and + certs directory will need to be set up to allow "nobody" to use them. + + In the second one x11vnc is run as root and switches to the user that + logs in due to the "-users unixpw=" option. + + Note that SSL is required for this mode because otherwise the Unix + password would be passed in clear text over the network. In general + -unixpw is not required for this sort of scheme, but it is convenient + because it determines exactly who the Unix user is whose display + should be sought. Otherwise the find_display script would have to use + some method to work out DISPLAY, XAUTHORITY, etc (perhaps you use + multiple inetd ports and hardwire usernames for different ports.) + + If you really want to disable the SSL or SSH -localhost constraints + (this is not recommended unless you really know what you are doing: + Unix passwords sent in clear text is a very bad idea...) read the + -unixpw documentation. + + A inetd(8) scheme for a fixed user that doesn't use SSL or unix + passwds could be: + /usr/local/bin/x11vnc -inetd -users =fred -find -rfbauth /home/fred/.vnc/pass +wd -o /var/log/x11vnc.log + + The "-users =fred" option will cause x11vnc to switch to user fred and + then find his X display. The VNC password (-rfbauth) as opposed to + Unix password (-unixpw) is used to authenticate the VNC client. + + Similar looking commands to the above examples can be run directly and + do not use inetd (just remove the -inetd option and run from the + cmdline, etc.) + + + X Session Creation: An added (Nov/2006) extension to FINDDISPLAY is + FINDCREATEDISPLAY where if it does not find an X display via the + FINDDISPLAY method it will create an X server session for the user + (i.e. desktop/terminal server.) This is the only time x11vnc actually + tries to start up an X server (normally it just attaches to an + existing one.) + + For virtual sessions you will need to install the Xvfb program (e.g. + apt-get install xvfb) or our Xdummy program (see below.) + + By default it will only try to start up virtual (non-hardware) X + servers: first Xvfb and if that is not available then Xdummy (included + in the x11vnc source code.) Note that Xdummy only works on Linux + whereas Xvfb works just about everywhere (and in some situations + Xdummy must be run as root.) An advantage of Xdummy over Xvfb is that + Xdummy supports RANDR dynamic screen resizing, which can be handy if + the user accesses the desktop from different sized screens (e.g. + workstation and laptop.) + + So an inetd(8) example might look like: +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd \ + -o /var/log/x11vnc.log -http -prog /usr/local/bin/x11vnc \ + -ssl SAVE -unixpw -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY + + Where the very long lines have been split. See below where that long + and cumbersome last line is replaced by the -svc alias. + + The above mode will allow direct SSL (e.g. ss_vncviewer or SSVNC) + access and also Java Web browers access via: https://hostname:5900/. + + Tip: Note that the -create option is an alias for "-display + WAIT:cmd=FINDCREATEDISPLAY-Xvfb". + + Tip: Note that -svc is a short hand for the long "-ssl SAVE -unixpw + -users unixpw= -display WAIT:cmd=FINDCREATEDISPLAY" part. Unlike + -create, this alias also sets up SSL encryption and Unix password + login. + + The above inetd example then simplifies to: +5900 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc -inetd \ + -o /var/log/x11vnc.log -http -prog /usr/local/bin/x11vnc \ + -svc + + Tip: In addition to the usual unixpw parameters, inside the VNC viewer + the user can specify after his username (following a ":" see -display + WAIT for details) for FINDCREATEDISPLAY they can add "geom=WxH" or + "geom=WxHxD" to specify the width, height, and optionally the color + depth. E.g. "fred:geom=800x600" at the login: prompt. Also if the env. + var X11VNC_CREATE_GEOM is set to the desired WxH or WxHxD that will be + used by x11vnc. + + You can set the env. var X11VNC_SKIP_DISPLAY to a comma separated list + of displays to ignore in the FINDDISPLAY process (to force creation of + new displays in some cases.) The user logging in via the vncviewer can + also set this via username:nodisplay=...) + + If you do not plan on using the Java Web browser applet you can remove + the -http (and -prog) option since this will speed up logging-in by a + few seconds (x11vnc will not have to wait to see if a connection is + HTTPS or VNC.) + + For reference, xinetd format in the file, say, /etc/xinetd.d/x11vnc: +service x11vnc +{ + type = UNLISTED + port = 5900 + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/local/bin/x11vnc + server_args = -inetd -o /var/log/x11vnc.log -http -prog /usr/local/ +bin/x11vnc -svc + disable = no +} + + To print out the script in this case use "-display + WAIT:cmd=FINDCREATEDISPLAY-print". To change the preference of + Xservers and which to try list them, e.g.: "-display + WAIT:cmd=FINDCREATEDISPLAY-X,Xvfb,Xdummy" or use "-create_xsrv + X,Xvfb,Xdummy". The "X" one means to try to start up a real, hardware + X server, e.g. startx(1) (if there is already a real X server running + this may only work on Linux and the chvt program may need to be run to + switch to the correct Linux virtual terminal.) x11vnc will try to run + chvt automatically if it can determine which VT should be switched to. + + XDM/GDM/KDM Login Greeter Panel: If you want to present the user with + a xdm/gdm/kdm display manager "greeter" login you can use Xvfb.xdmcp + instead of Xvfb, etc in the above list. However, you need to configure + xdm/gdm/kdm to accept localhost XDMCP messages, this can be done by + (from -help output): + If you want the FINDCREATEDISPLAY session to contact an XDMCP login + manager (xdm/gdm/kdm) on the same machine, then use "Xvfb.xdmcp" + instead of "Xvfb", etc. The user will have to supply his username + and password one more time (but he gets to select his desktop + type so that can be useful.) For this to work, you will need to + enable localhost XDMCP (udp port 177) for the display manager. + This seems to be: + + for gdm in gdm.conf: Enable=true in section [xdmcp] + for kdm in kdmrc: Enable=true in section [Xdmcp] + for xdm in xdm-config: DisplayManager.requestPort: 177 + + Unless you are also providing XDMCP service to xterminals or other + machines, make sure that the host access list only allows local + connections (the name of this file is often Xaccess and it is usually + setup by default to do just that.) Nowadays, host level firewalling + will also typically block UDP (port 177 for XDMCP) by default + effectively limiting the UDP connections to localhost. + + Tip: Note that -xdmsvc is a short hand alias for the long "-ssl SAVE + -unixpw -users unixpw= -display + WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp". So we simply use: +service x11vnc +{ + type = UNLISTED + port = 5900 + socket_type = stream + protocol = tcp + wait = no + user = root + server = /usr/local/bin/x11vnc + server_args = -inetd -o /var/log/x11vnc.log -xdmsvc + disable = no +} + + (Note: use "-svc" instead of "-xdmsvc" for no XDMCP login greeter.) + + + Local access (VNC Server and VNC Viewer on the same machine): To + access your virtual X display session locally (i.e. while sitting at + the same machine it is running on) one can perhaps have something like + this in their $HOME/.xinitrc +#!/bin/sh +x11vnc -create -rfbport 5905 -env WAITBG=1 +vncviewer -geometry +0+0 -encodings raw -passwd $HOME/.vnc/passwd localhost:5 + + You may not need the -passwd. Recent RealVNC viewers might be this: +#!/bin/sh +x11vnc -create -rfbport 5905 -env WAITBG=1 +vncviewer -FullScreen -PreferredEncoding raw -passwd $HOME/.vnc/passwd localhos +t:5 + + This way a bare X server is run with no window manager or desktop; it + simply runs only the VNC Viewer on the real X server. The Viewer then + draws the virtual X session on to the real one. On your system it + might not be $HOME/.xinitrc, but rather .xsession, .Xclients, or + something else. You will need to figure out what it is for your system + and configuration. + + There may be a problem if the resolution (WxH) of the virtual X + display does not match that of the physical X display. + + If you do not want to or cannot figure out the X startup script name + (.xinitrc, etc) you could save the above commands to a shell script, + say "vnclocal", and the log in via the normal KDM or GDM greeter + program using the "Failsafe" option. Then in the lone xterm that comes + up type "vnclocal" to connect to your virtual X display via x11vnc and + vncviewer. + + _________________________________________________________________ + + Summary: The "-display WAIT:cmd=FINDCREATEDISPLAY" scheme can be used + to provide a "desktop service" (i.e. terminal service) on the server + machine: you always get some desktop there, either a real hardware X + server or a virtual one (depending on how you set things up.) + + So it provides simple "terminal services" based on Unix username and + password. The created X server sessions (virtual or real hardware) + will remain running after you disconnect the VNC viewer and will be + found again on reconnecting via VNC and logging in. To terminate them + use the normal way to Exit/LogOut from inside your X session. The user + does not have to memorize which VNC display number is his. They all go + the same one (e.g. hostname:0) and it switches based on username. + + + Q-63: Can I have x11vnc restart itself after it terminates? + + One could do this in a shell script, but now there is an option -loop + that makes it easier. Of course when x11vnc restarts it needs to have + permissions to connect to the (potentially new) X display. This mode + could be useful if the X server restarts often. Use e.g. "-loop5000" + to sleep 5000 ms between restarts. Also "-loop2000,5" to sleep 2000 ms + and only restart 5 times. + + One can also use the -loopbg to emulate inetd(8) to some degree, where + each connected process runs in the background. It could be combined, + say, with the -svc option to provide simple terminal services without + using inetd(8). + + + Q-64: How do I make x11vnc work with the Java VNC viewer applet in a + web browser? + + To have x11vnc serve up a Java VNC viewer applet to any web browsers + that connect to it, run x11vnc with this option: + -httpdir /path/to/the/java/classes/dir + + (this directory will contain the files index.vnc and, for example, + VncViewer.jar) Note that libvncserver contains the TightVNC Java + classes jar file for your convenience. (it is the file + classes/VncViewer.jar in the source tree.) + + You will see output something like this: + 14/05/2004 11:13:56 Autoprobing selected port 5900 + 14/05/2004 11:13:56 Listening for HTTP connections on TCP port 5800 + 14/05/2004 11:13:56 URL http://walnut:5800 + 14/05/2004 11:13:56 screen setup finished. + 14/05/2004 11:13:56 The VNC desktop is walnut:0 + PORT=5900 + + then you can connect to that URL with any Java enabled browser. Feel + free to customize the default index.vnc file in the classes directory. + + As of May/2005 the -http option will try to guess where the Java + classes jar file is by looking in expected locations and ones relative + to the x11vnc binary. + + Also note that if you wanted to, you could also start the Java viewer + entirely from the viewer-side by having the jar file there and using + either the java or appletviewer commands to run the program. + java -cp ./VncViewer.jar VncViewer HOST far-away.east PORT 5900 + + Proxies: See the discussion here if the web browser must use a web + proxy to connect to the internet. It is tricky to get Java applets to + work in this case: a signed applet must be used so it can connect to + the proxy and ask for the redirection to the VNC server. One way to do + this is to use the signed SSL one referred to in classes/ssl/proxy.vnc + and set disableSSL=yes (note that this has no encryption; please use + SSL or SSH as discuss elsewhere on this page) in the URL or the file. + + + Q-65: Are reverse connections (i.e. the VNC server connecting to the + VNC viewer) using "vncviewer -listen" and vncconnect(1) supported? + + As of Mar/2004 x11vnc supports reverse connections. On Unix one starts + the VNC viewer in listen mode: "vncviewer -listen" (see your + documentation for Windows, etc), and then starts up x11vnc with the + -connect option. To connect immediately at x11vnc startup time use the + "-connect host:port" option (use commas for a list of hosts to connect + to.) The ":port" is optional (default is VNC listening port is 5500.) + + If a file is specified instead: -connect /path/to/some/file then that + file is checked periodically (about once a second) for new hosts to + connect to. + + The -remote control option (aka -R) can also be used to do this during + an active x11vnc session, e.g.: +x11vnc -display :0 -R connect:hostname.domain + + Use the "-connect_or_exit" option to have x11vnc exit if the reverse + connection fails. Also, note the "-rfbport 0" option disables TCP + listening for connections (potentially useful for reverse connection + mode, assuming you do not want any "forward" connections.) + + Note that as of Mar/2006 x11vnc requires password authentication for + reverse connections as well as for forward ones (assuming password + auth has been enabled, e.g. via -rfbauth, -passwdfile, etc.) Many VNC + servers do not require any password for reverse connections. To regain + the old behavior supply this option "-env + X11VNC_REVERSE_CONNECTION_NO_AUTH=1" to x11vnc. + + Vncconnect command: To use the vncconnect(1) program (from the core + VNC package at www.realvnc.com) specify the -vncconnect option to + x11vnc (Note: as of Dec/2004 -vncconnect is now the default.) + vncconnect(1) must be pointed to the same X11 DISPLAY as x11vnc (since + it uses X properties to communicate with x11vnc.) If you do not have + or do not want to get the vncconnect(1) program, the following script + (named "Vncconnect") may work if your xprop(1) supports the -set + option: +#!/bin/sh +# usage: Vncconnect +# Vncconnect +# note: not all xprop(1) support -set. +# +xprop -root -f VNC_CONNECT 8s -set VNC_CONNECT "$1" + + + Q-66: Can reverse connections be made to go through a Web or SOCKS + proxy or SSH? + + Yes, as of Oct/2007 x11vnc supports reverse connections through + proxies: use the "-proxy host:port" option. The default is to assume + the proxy is a Web proxy. Note that most Web proxies only allow proxy + destination connections to ports 443 (HTTPS) and 563 (SNEWS) and so + this might not be too useful unless the proxy has been modified + (AllowCONNECT apache setting) or the VNC viewer listens on one of + those ports (or the router does a port redir.) A web proxy may also be + specified via "-proxy http://host:port" + + For SOCKS4 and SOCKS4a proxies use this format "-proxy + socks://host:port". If the reverse connection hostname is a numerical + IP or "localhost" then SOCKS4 (no host lookup) is used, otherwise + SOCKS4a will be used. For SOCKS5 (proxy will do lookup and many other + things) use "-proxy socks5://host:port". Note that the SSH builtin + SOCKS proxy "ssh -D port" only does SOCKS4 or SOCKS5, so use socks5:// + for a ssh -D proxy. + + The proxying works for both SSL encrypted and normal reverse + connections. + + An experimental mode is "-proxy http://host:port/..." where the URL + (e.g. a CGI script) is retrieved via the GET method. See -proxy for + more info. + + Another experimental mode is "-proxy ssh://user@host" in which case a + SSH tunnel is used for the proxying. See -proxy for more info. + + Up to 3 proxies may be chained together by listing them by commas + e.g.: "-proxy http://host1:port1,socks5://host2:port2" in case one + needs to ricochet off of several machines to ultimately reach the + listening viewer. + + + Q-67: Can x11vnc provide a multi-user desktop web login service as an + Apache CGI or PHP script? + Yes. See the example script desktop.cgi for ideas. It is in the source + tree in the directory x11vnc/misc. It serves x11vnc's SSL enabled Java + Applet to the web browser with the correct connection information for + the user's virtual desktop (an Xvfb session via -create; be sure to + add the Xvfb package.) HTTPS/SSL enabled Apache should be used to + serve the script to avoid unix and vnc passwords from being sent in + cleartext and sniffed. + + By default it uses a separate VNC port for each user desktop (either + by autoprobing in a range of ports or using a port based on the userid + number.) The web server's firewall must allow incoming connections to + these ports. + + It is somewhat difficult to do all of this with x11vnc listening on a + single port, however there is also a 'fixed port' scheme described in + the script based on -loopbg that works fairly well (but more + experience is needed to see what problems contention for the same port + causes; however at worst one user may need to re-login.) + + There is also an optional 'port redirection' mode for desktop.cgi that + allows redirection to other machines inside the firewall already + running SSL enabled VNC servers. This provides much of the + functionality as the SSL Portal and is easier to set up. + + + Q-68: Can I use x11vnc as a replacement for Xvnc? (i.e. not for a real + display, but for a virtual one I keep around.) + + You can, but you would not be doing this for performance reasons (for + virtual X sessions via VNC, Xvnc should give the fastest response.) + You may want to do this because Xvnc is buggy and crashes, does not + support an X server extension you desire, or you want to take + advantage of one of x11vnc's unending number of options and features. + + One way to achieve this is to have a Xvfb(1) virtual framebuffer X + server running in the background and have x11vnc attached to it. + Another method, faster and more accurate, is to use the "dummy" Device + Driver in XFree86/Xorg (see below.) + + For these virtual sessions you will need to install the Xvfb program + (e.g. apt-get install xvfb) or our Xdummy program (see below.) + + In either case, one can view this desktop both remotely and also + locally using vncviewer. Make sure vncviewer's "-encodings raw" is in + effect for local viewing (compression seems to slow things down + locally.) For local viewing you set up a "bare" window manager that + just starts up vncviewer and nothing else (See how below.) + + Here is one way to start up Xvfb: + xinit -- /usr/bin/Xvfb :1 -cc 4 -screen 0 1024x768x16 + + This starts up a 16bpp virtual display. To export it via VNC use + x11vnc -display :1 ... + + Then have the remote vncviewer attach to x11vnc's VNC display (e.g. :0 + which is port 5900.) + + The "-cc 4" Xvfb option is to force it to use a TrueColor visual + instead of DirectColor (this works around a recent bug in the Xorg + Xvfb server.) + + One good thing about Xvfb is that the virtual framebuffer exists in + main memory (rather than in the video hardware), and so x11vnc can + "screen scrape" it very efficiently (more than, say, 100X faster than + normal video hardware.) + + Update Nov/2006: See the FINDCREATEDISPLAY discussion of the "-display + WAIT:cmd=FINDDISPLAY" option where virtual (Xvfb or Xdummy, or even + real ones by changing an option) X servers are started automatically + for new users connecting. This provides a "desktop service" for the + machine. You either get your real X session or your virtual + (Xvfb/Xdummy) one whenever you connect to the machine (inetd(8) is a + nice way to provide this service.) The -find, -create, -svc, and + -xdmsvc aliases can also come in handy here. + + There are some annoyances WRT Xvfb however. The default keyboard + mapping seems to be very poor. One should run x11vnc with -add_keysyms + option to have keysyms added automatically. Also, to add the Shift_R + and Control_R modifiers something like this is needed: +#!/bin/sh +xmodmap -e "keycode any = Shift_R" +xmodmap -e "add Shift = Shift_L Shift_R" +xmodmap -e "keycode any = Control_R" +xmodmap -e "add Control = Control_L Control_R" +xmodmap -e "keycode any = Alt_L" +xmodmap -e "keycode any = Alt_R" +xmodmap -e "keycode any = Meta_L" +xmodmap -e "add Mod1 = Alt_L Alt_R Meta_L" + + (note: these are applied automatically in the FINDCREATEDISPLAY mode + of x11vnc.) Perhaps the Xvfb options -xkbdb or -xkbmap could be used + to get a better default keyboard mapping... + + Dummy Driver: A user points out a faster and more accurate method is + to use the "dummy" Device Driver of XFree86/Xorg instead of Xvfb. He + uses this to create a persistent and resizable desktop accessible from + anywhere. In the Device Section of the config file set Driver "dummy". + You may also need to set VideoRam NNN to be large enough to hold the + framebuffer. The framebuffer is kept in main memory like Xvfb except + that the server code is closely correlated with the real XFree86/Xorg + Xserver unlike Xvfb. + + The main drawback to this method (besides requiring extra + configuration and possibly root permission) is that it also does the + Linux Virtual Console/Terminal (VC/VT) switching even though it does + not need to (since it doesn't use a real framebuffer.) There are some + "dual headed" (actually multi-headed/multi-user) patches to the X + server that turn off the VT usage in the X server. Update: As of + Jul/2005 we have an LD_PRELOAD script Xdummy that allows you to use a + stock (i.e. unpatched) Xorg or XFree86 server with the "dummy" driver + and not have any VT switching problems! An advantage of Xdummy over + Xvfb is that Xdummy supports RANDR dynamic screen resizing. + + The standard way to start the "dummy" driver would be: +startx -- :1 -config /etc/X11/xorg.conf.dummy + + where the file /etc/X11/xorg.conf.dummy has its Device Section + modified as described above. To use the LD_PRELOAD wrapper script: +startx -- /path/to/Xdummy :1 + + An xdm(1) example is also provided. + + In general, one can use these sorts of schemes to use x11vnc to export + other virtual X sessions, say Xnest or even Xvnc itself (useful for + testing x11vnc.) + + Local access (VNC Server and VNC Viewer on the same machine): You use + a VNC viewer to access the display remotely; to access your virtual X + display locally (i.e. while sitting at the same machine it is running + on) one can perhaps have something like this in their $HOME/.xinitrc +#!/bin/sh +x11vnc -display :5 -rfbport 5905 -bg +vncviewer -geometry +0+0 -encodings raw -passwd $HOME/.vnc/passwd localhost:5 + + The display numbers (VNC and X) will likely be different (you could + also try -find), and you may not need the -passwd. Recent RealVNC + viewers might be this: +#!/bin/sh +x11vnc -display :5 -rfbport 5905 -bg +vncviewer -FullScreen -PreferredEncoding raw -passwd $HOME/.vnc/passwd localhos +t:5 + + This way a bare X server is run with no window manager or desktop; it + simply runs only the VNC Viewer on the real X server. The Viewer then + draws the virtual X session on to the real one. On your system it + might not be $HOME/.xinitrc, but rather .xsession, .Xclients, or + something else. You will need to figure out what it is for your system + and configuration. + + + XDM/GDM/KDM One-Shot X sessions: For the general replacement of Xvnc + by Xvfb+x11vnc, one user describes a similar setup he created where + the X sessions are one-shot's (destroyed after the vncviewer + disconnects) and it uses the XDM/GDM/KDM login greeter here. + + + Q-69: How can I use x11vnc on "headless" machines? Why might I want + to? + + An interesting application of x11vnc is to let it export displays of + "headless" machines. For example, you may have some lab or server + machines with no keyboard, mouse, or monitor, but each one still has a + video card. One can use x11vnc to provide a simple "desktop service" + from these server machines. + + An X server can be started on the headless machine (sometimes this + requires configuring the X server to not fail if it cannot detect a + keyboard or mouse, see the next paragraph.) Then you can export that X + display via x11vnc (e.g. see this FAQ) and access it from anywhere on + the network via a VNC viewer. + + Some tips on getting X servers to start on machines without keyboard + or mouse: For XFree86/Xorg the Option "AllowMouseOpenFail" "true" + "ServerFlags" config file option is useful. On Solaris Xsun the + +nkeyboard and +nmouse options are useful (put them in the server + command line args in /etc/dt/config/Xservers.) There are patches + available for Xsun at lease back to Solaris 8 that support this. See + Xserver(1) for more info. + + Although this usage may sound strange it can be quite useful for a GUI + (or other) testing or QA setups: the engineers do not need to walk to + lab machines running different hardware, OS's, versions, etc (or have + many different machines in their office.) They just connect to the + various test machines over the network via VNC. The advantage to + testing this way instead of using Xvnc or even Xvfb is that the test + is done using the real X server, fonts, video hardware, etc. that will + be used in the field. + + One can imagine a single server machine crammed with as many video + cards as it can hold to provide multiple simultaneous access or + testing on different kinds of video hardware. + + See also the FINDCREATEDISPLAY discussion of the "-display + WAIT:cmd=FINDDISPLAY" option where virtual Xvfb or Xdummy, or real X + servers are started automatically for new users connecting. The -find, + -create, -svc, and -xdmsvc aliases can also come in handy here. + + [Resource Usage and Performance] + + Q-70: I have lots of memory, but why does x11vnc fail with shmget: + No space left on device or Minor opcode of failed request: 1 + (X_ShmAttach)? + + It is not a matter of free memory, but rather free shared memory (shm) + slots, also known as shm segments. This often occurs on a public + Solaris machine using the default of only 100 slots. You (or the owner + or root) can clean them out with ipcrm(1). x11vnc tries hard to + release its slots, but it, and other programs, are not always able to + (e.g. if kill -9'd.) + + Sometimes x11vnc will notice the problem with shm segments and tries + to get by with fewer, only giving a warning like this: + 19/03/2004 10:10:58 shmat(tile_row) failed. + shmat: Too many open files + 19/03/2004 10:10:58 error creating tile-row shm for len=4 + 19/03/2004 10:10:58 reverting to single_copytile mode + + Here is a shell script shm_clear to list and prompt for removal of + your unattached shm segments (attached ones are skipped.) I use it + while debugging x11vnc (I use "shm_clear -y" to assume "yes" for each + prompt.) If x11vnc is regularly not cleaning up its shm segments, + please contact me so we can work to improve the situation. + + Longer term, on Solaris you can put something like this in + /etc/system: + set shmsys:shminfo_shmmax = 0x2000000 + set shmsys:shminfo_shmmni = 0x1000 + + to sweep the problem under the rug (4096 slots.) On Linux, examine + /proc/sys/kernel/shmmni; you can modify the value by writing to that + file. + + Things are even more tight on Solaris 8 and earlier, there is a + default maximum number of shm segments per process of 6. The error is + the X server (not x11vnc) being unable to attach to the segments, and + looks something like this: + 30/04/2004 14:04:26 Got connection from client 192.168.1.23 + 30/04/2004 14:04:26 other clients: + X Error of failed request: BadAccess (attempt to access private resource den +ied) + Major opcode of failed request: 131 (MIT-SHM) + Minor opcode of failed request: 1 (X_ShmAttach) + Serial number of failed request: 14 + Current serial number in output stream: 17 + + This tight limit on Solaris 8 can be increased via: + set shmsys:shminfo_shmseg = 100 + + in /etc/system. See the next paragraph for more workarounds. + + To minimize the number of shm segments used by x11vnc try using the + -onetile option (corresponds to only 3 shm segments used, and adding + -fs 1.0 knocks it down to 2.) If you are having much trouble with shm + segments, consider disabling shm completely via the -noshm option. + Performance will be somewhat degraded but when done over local machine + sockets it should be acceptable (see an earlier question discussing + -noshm.) + + + Q-71: How can I make x11vnc use less system resources? + + The -nap (now on by default; use -nonap to disable) and "-wait n" + (where n is the sleep between polls in milliseconds, the default is 30 + or so) option are good places to start. In addition, something like + "-sb 15" will cause x11vnc to go into a deep-sleep mode after 15 + seconds of no activity (instead of the default 60.) + + Reducing the X server bits per pixel depth (e.g. to 16bpp or even + 8bpp) will further decrease memory I/O and network I/O. The ShadowFB X + server setting will make x11vnc's screen polling less severe. Using + the -onetile option will use less memory and use fewer shared memory + slots (add -fs 1.0 for one less slot.) + + + Q-72: How can I make x11vnc use MORE system resources? + + You can try -threads (note this mode can be unstable and/or crash; and + as of May/2008 is strongly discouraged, see the option description) or + dial down the wait time (e.g. -wait 1) and possibly dial down -defer + as well. Note that if you try to increase the "frame rate" too much + you can bog down the server end with the extra work it needs to do + compressing the framebuffer data, etc. + + That said, it is possible to "stream" video via x11vnc if the video + window is small enough. E.g. a 256x192 xawtv TV capture window (using + the x11vnc -id option) can be streamed over a LAN or wireless at a + reasonable frame rate. If the graphics card's framebuffer read rate is + faster than normal then the video window size and frame rate can be + much higher. The use of TurboVNC and/or TurboJPEG can make the frame + rate somewhat higher still (but most of this hinges on the graphics + card's read rate.) + + + Q-73: I use x11vnc over a slow link with high latency (e.g. dialup + modem or broadband), is there anything I can do to speed things up? + + Some things you might want to experiment with (many of which will help + performance on faster links as well): + + X server/session parameters: + * Configure the X server bits per pixel to be 16bpp or even 8bpp. + (reduces amount of data needed to be polled, compressed, and sent) + * Use a smaller desktop size (e.g. 1024x768 instead of 1280x1024) + * Make sure the desktop background is a solid color (the background + is resent every time it is re-exposed.) Consider using the -solid + [color] option to try to do this automatically. + * Configure your window manager or desktop "theme" to not use fancy + images, shading, and gradients for the window decorations, etc. + Disable window animations, etc. Maybe your desktop has a "low + bandwidth" theme you can easily switch into and out of. Also in + Firefox disable eye-candy, e.g.: Edit -> Preferences -> Advanced + -> Use Smooth Scrolling (deselect it.) + * Avoid small scrolls of large windows using the Arrow keys or + scrollbar. Try to use PageUp/PageDown instead. (not so much of a + problem in x11vnc 0.7.2 if -scrollcopyrect is active and detecting + scrolls for the application.) + * If the -wireframe option is not available (earlier than x11vnc + 0.7.2 or you have disabled it via -nowireframe) then Disable + Opaque Moves and Resizes in the window manager/desktop. + * However if -wireframe is active (on by default in x11vnc 0.7.2) + then you should Enable Opaque Moves and Resizes in the window + manager! This seems counter-intuitive, but because x11vnc detects + the move/resize events early there is a huge speedup over a slow + link when Opaque Moves and Resizes are enabled. (e.g. CopyRect + encoding will be used.) + * Turn off Anti-aliased fonts on your system, web browser, terminal + windows, etc. AA fonts do not compress as well as traditional + fonts (sometimes 10X less.) + * On Firefox/Mozilla (and anything else) turn off "Smooth Scroll" + animations. In Firefox put in the URL "about:config" and set + general.smoothScroll to false. + * On XFree86 turn on the Shadow Framebuffer to speed up reading. + (Option "ShadowFB" "true" in the Device section of + /etc/X11/XF86Config) This disables 2D acceleration on the physical + display and so may not be worth it, but could be of use in some + situations. If the link is very slow, this speedup may not be + noticed. + + VNC viewer parameters: + * Use a TightVNC enabled viewer! (Actually, RealVNC 4.x viewer with + ZRLE encoding is not too bad either; some claim it is faster.) + * Make sure the tight (or zrle) encoding is being used (look at + vncviewer and x11vnc outputs) + * Request 8 bits per pixel using -bgr233 (up to 4X speedup over + depth 24 TrueColor (32bpp), but colors will be off) + * RealVNC 4.x viewer has some extremely low color modes (only 64 and + even 8 colors.) SSVNC does too. The colors are poor, but it is + usually noticeably faster than bgr233 (256 colors.) + * Try increasing the TightVNC -compresslevel (compresses more on + server side before sending, but uses more CPU) + * Try reducing the TightVNC -quality (increases JPEG compression, + but is lossy with painting artifacts) + * Try other VNC encodings via -encodings (tight may be the fastest, + but you should compare it to zrle and maybe some of the others) + * On the machine where vncviewer is run, make sure Backing Store is + enabled (XFree86/Xorg disables it by default causing re-exposures + of vncviewer to be very slow) Option "backingstore" in config + file. + + x11vnc parameters: + * Make sure the -wireframe option is active (it should be on by + default) and you have Opaque Moves/Resizes Enabled in the window + manager. + * Make sure the -scrollcopyrect option is active (it should be on by + default.) This detects scrolls in many (but not all) applications + an applies the CopyRect encoding for a big speedup. + * Enforce a solid background when VNC viewers are connected via + -solid + * Try x11vnc's client-side caching client-side caching scheme: + -ncache + * Specify -speeds modem to force the wireframe and scrollcopyrect + heuristic parameters (and any future ones) to those of a dialup + modem connection (or supply the rd,bw,lat numerical values that + characterize your link.) + * If wireframe and scrollcopyrect aren't working, try using the more + drastic -nodragging (no screen updates when dragging mouse, but + sometimes you miss visual feedback) + * Set -fs 1.0 (disables fullscreen updates) + * Try increasing -wait or -defer (reduces the maximum "frame rate", + but won't help much for large screen changes) + * Try the -progressive pixelheight mode with the block pixelheight + 100 or so (delays sending vertical blocks since they may change + while viewer is receiving earlier ones) + * If you just want to watch one (simple) window use -id or -appshare + (cuts down extraneous polling and updates, but can be buggy or + insufficient) + * Set -nosel (disables all clipboard selection exchange) + * Use -nocursor and -nocursorpos (repainting the remote cursor + position and shape takes resources and round trips) + * On very slow links (e.g. <= 28.8) you may need to increase the + -readtimeout n setting if it sometimes takes more than 20sec to + paint the full screen, etc. + * Do not use -fixscreen to automatically refresh the whole screen, + tap three Alt_L's then the screen has painting errors (rare + problem.) + + + Example for the KDE desktop: + + Launch the "KDE Control Center" utility. Sometimes this is called + "Personal Settings". + + Select "Desktop". + + Then Select "Window Behavior". In the "Moving" Tab set these: + * YES - Display content in moving windows + * YES - Display content in resizing windows + * NO - Display window geometry when moving or resizing + * NO - Animate minimize and restore + + In the "Translucency" Tab set: + * NO - Use translucency/shadows + + Next hit "Back" and then select "Panels". + + In the "Appearance" Tab set: + * NO - Enable icon mouseover effects + * NO - Enable transparency + + Now go all the way back up to the top and Select "Appearance & + Themes". + + Select "Background" and set: + * YES - No picture + * Colors: Single Color + + Select "Fonts" and disable anti-aliased fonts if you are bold enough. + + Select "Launch Feedback" and set: + * Busy Cursor: No Busy Cursor + * NO - Enable taskbar notification + + Select "Screen Saver" and set: + * Screen Saver: Blank Screen + + Select "Style" and in the "Effects" Tab set: + * NO - Enable GUI effects + + + Example for the GNOME desktop: + * TBD. + + + Q-74: Does x11vnc support the X DAMAGE Xserver extension to find + modified regions of the screen quickly and efficiently? + + Yes, as of Mar/2005 x11vnc will use the X DAMAGE extension by default + if it is available on the display. This requires libXdamage to be + available in the build environment as well (recent Linux distros and + Solaris 10 have it.) + + The DAMAGE extension enables the X server to report changed regions of + the screen back to x11vnc. So x11vnc doesn't have to guess where the + changes are (by polling every pixel of the entire screen every 2-4 + seconds.) The use of X DAMAGE dramatically reduces the load when the + screen is not changing very much (i.e. most of the time.) It also + noticeably improves updates, especially for very small changed areas + (e.g. clock ticking, cursor flashing, typing, etc.) + + Note that the DAMAGE extension does not speed up the actual reading of + pixels from the video card framebuffer memory, by, say, mirroring them + in main memory. So reading the fb is still painfully slow (e.g. + 5MB/sec), and so even using X DAMAGE when large changes occur on the + screen the bulk of the time is still spent retrieving them. Not ideal, + but use of the ShadowFB XFree86/Xorg option speeds up the reading + considerably (at the cost of h/w acceleration.) + + Unfortunately the current Xorg DAMAGE extension implementation can at + times be overly conservative and report very large rectangles as + "damaged" even though only a small portion of the pixels have actually + been modified. This behavior is often the fault of the window manager + (e.g. it redraws the entire, unseen, frame window underneath the + application window when it gains focus), or the application itself + (e.g. does large, unnecessary repaints.) + + To work around this deficiency, x11vnc currently only trusts small + DAMAGE rectangles to contain real damage. The larger rectangles are + only used as hints to focus the traditional scanline polling (i.e. if + a scanline doesn't intersect a recent DAMAGE rectangle, the scan is + skipped.) You can use the "-xd_area A" option to adjust the size of + the trusted DAMAGE rectangles. The default is 20000 pixels (e.g. a + 140x140 square, etc.) Use "-xd_area 0" to disable the cutoff and trust + all DAMAGE rectangles. + + The option "-xd_mem f" may also be of use in tuning the algorithm. To + disable using DAMAGE entirely use "-noxdamage". + + + Q-75: My OpenGL application shows no screen updates unless I supply + the -noxdamage option to x11vnc. + One user reports in his environment (MythTV using the NVIDIA OpenGL + drivers) he gets no updates after the initial screen is drawn unless + he uses the "-noxdamage" option. + + This seems to be a bug in the X DAMAGE implementation of that driver. + You may have to use -noxdamage as well. A way to autodetect this will + be tried, probably the best it will do is automatically stop using X + DAMAGE. + + A developer for MiniMyth reports that the 'alphapulse' tag of the + theme G.A.N.T. can also cause problems, and should be avoided when + using VNC. + + Update: see this FAQ too. + + + Q-76: When I drag windows around with the mouse or scroll up and down + things really bog down (unless I do the drag in a single, quick + motion.) Is there anything to do to improve things? + + This problem is primarily due to slow hardware read rates from video + cards: as you scroll or move a large window around the screen changes + are much too rapid for x11vnc to keep up them (it can usually only + read the video card at about 5-10 MB/sec, so it can take a good + fraction of a second to read the changes induce from moving a large + window, if this to be done a number of times in succession the window + or scroll appears to "lurch" forward.) See the description in the + -pointer_mode option for more info. The next bottleneck is compressing + all of these changes and sending them out to connected viewers, + however the VNC protocol is pretty much self-adapting with respect to + that (updates are only packaged and sent when viewers ask for them.) + + As of Jan/2004 there are some improvements to libvncserver. The + default should now be much better than before and dragging small + windows around should no longer be a huge pain. If for some reason + these changes make matters worse, you can go back to the old way via + the "-pointer_mode 1" option. + + Also added was the -nodragging option that disables all screen updates + while dragging with the mouse (i.e. mouse motion with a button held + down.) This gives the snappiest response, but might be undesired in + some circumstances when you want to see the visual feedback while + dragging (e.g. menu traversal or text selection.) + + As of Dec/2004 the -pointer_mode n option was introduced. n=1 is the + original mode, n=2 an improvement, etc.. See the -pointer_mode n help + for more info. + + Also, in some circumstances the -threads option can improve response + considerably. Be forewarned that if more than one vncviewer is + connected at the same time then libvncserver may not be thread safe + (try to get the viewers to use different VNC encodings, e.g. tight and + ZRLE.) This option can be unstable and so as of Feb/2008 it is + disabled by default. Set env. X11VNC_THREADED=1 to re-enable. + + As of Apr/2005 two new options (see the wireframe FAQ and + scrollcopyrect FAQ below) provide schemes to sweep this problem under + the rug for window moves or resizes and for some (but not all) window + scrolls. These are the preferred way of avoiding the "lurching" + problem, contact me if they are not working. Note on SuSE and some + other distros the RECORD X extension used by scrollcopyrect is not + enabled by default, turn it on in xorg.conf: +Section "Module" + ... + Load "record" + ... +EndSection + + + Q-77: Why not do something like wireframe animations to avoid the + windows "lurching" when being moved or resized? + + Nice idea for a hack! As of Apr/2005 x11vnc by default will apply + heuristics to try to guess if a window is being (opaquely) moved or + resized. If such a change is detected framebuffer polling and updates + will be suspended and only an animated "wireframe" (a rectangle + outline drawn where the moved/resized window would be) is shown. When + the window move/resize stops, it returns to normal processing: you + should only see the window appear in the new position. This spares you + from interacting with a "lurching" window between all of the + intermediate steps. BTW the lurching is due to slow video card read + rates (see here too.) A displacement, even a small one, of a large + window requires a non-negligible amount of time, a good fraction of a + second, to read in from the hardware framebuffer. + + Note that Opaque Moves/Resizes must be Enabled by your window manager + for -wireframe to do any good. + + The mode is currently on by default because most people are afflicted + with the problem. It can be disabled with the -nowireframe option (aka + -nowf.) Why might one want to turn off the wireframing? Since x11vnc + is merely guessing when windows are being moved/resized, it may guess + poorly for your window-manager or desktop, or even for the way you + move the pointer. If your window-manager or desktop already does its + own wireframing then this mode is a waste of time and could do the + wrong thing occasionally. There may be other reasons the new mode + feels unnatural. If you have very expensive video hardware (SGI, well + now even proprietary Xorg drivers are fast at reading) or are using an + in-RAM video framebuffer (SunRay, ShadowFB, Xvfb), the read rate from + that framebuffer may be very fast (100's of MB/sec) and so you don't + really see much lurching (at least over a fast LAN): opaque moves look + smooth in x11vnc. Note: ShadowFB is often turned on when you are using + the vesafb or fbdev XFree86 video driver instead of a native one so + you might be using it already and not know. + + The heuristics used to guess window motion or resizing are simple, but + are not fool proof: x11vnc is sometimes tricked and so you'll + occasionally see the lurching opaque move and rarely something even + worse. + + First it assumes that the move/resize will occur with a mouse button + pressed, held down and dragged (of course this is only mostly true.) + Next it will only consider a window for wireframing if the mouse + pointer is initially "close enough" to the edges of the window frame, + e.g. you have grabbed the title bar or a resizer edge (this + requirement can be disabled and it also not applied if a modifier key, + e.g. Alt, is pressed.) If these are true, it will wait an amount of + time to see if the window starts moving or resizing. If it does, it + starts drawing the wireframe "outline" of where the window would be. + When the mouse button is released, or a timeout occurs, it goes back + to the standard mode to allow the actual framebuffer changes to + propagate to the viewers. + + These parameters can be tweaked: + * Color/Shade of the wireframe. + * Linewidth of the outline frame. + * Cutoff size of windows to not apply wireframing to. + * Cutoffs for closeness to Top, Bottom, Left, and Right edges of + window. + * Modifier keys to enable interior window grabbing. + * Maximum time to wait for dragging pointer events. + * Maximum time to wait for the window to start moving/resizing. + * Maximum time to show a wireframe animation. + * Minimum time between sending wireframe outlines. + + See the "-wireframe tweaks" option for more details. On a slow link, + e.g. dialup modem, the parameters may be automatically adjusted for + better response. + + + CopyRect encoding: In addition to the above there is the + "-wirecopyrect mode" option. It is also on by default. This instructs + x11vnc to not only show the wireframe animation, but to also instruct + all connected VNC viewers to locally translate the window image data + from the original position to the new position on the screen when the + animation is done. This speedup is the VNC CopyRect encoding: the + framebuffer update doesn't need to send the actual new image data. + This is nice in general, and very convenient over a slow link, but + since it is based on heuristics you may need to disable it with the + -nowirecopyrect option (aka -nowcr) if it works incorrectly or + unnaturally for you. + + The -wirecopyrect modes are: "never" (same as -nowirecopyrect); "top", + only apply the CopyRect if the window is appears to be on the top of + the window stack and is not obstructed by other windows; and "always" + to always try to apply the CopyRect (obstructed regions are usually + clipped off and not translated.) + + Note that some desktops (KDE and xfce) appear to mess with the window + stacking in ways that are not yet clear. In these cases x11vnc works + around the problem by applying the CopyRect even if obscuring windows' + data is translated! Use -nowirecopyrect if this yields undesirable + effects for your desktop. + + Also, the CopyRect encoding may give incorrect results under -scale + (depending on the scale factor the CopyRect operation is often only + approximate: the correctly scaled framebuffer will be slightly + different from the translated one.) x11vnc will try to push a + "cleanup" update after the CopyRect if -scale is in effect. Use + -nowirecopyrect if this or other painting errors are unacceptable. + + + Q-78: Can x11vnc try to apply heuristics to detect when a window is + scrolling its contents and use the CopyRect encoding for a speedup? + + Another nice idea for a hack! As of May/2005 x11vnc will by default + apply heuristics to try to detect if the window that has the input + focus is scrolling its contents (but only when x11vnc is feeding user + input, keystroke or pointer, to the X server.) So, when detected, + scrolls induced by dragging on a scrollbar or by typing (e.g. Up or + Down arrows, hitting Return in a terminal window, etc), will show up + much more quickly than via the standard x11vnc screen polling update + mechanism. + + There will be a speedup for both slow and fast links to viewers. For + slow links the speedup is mostly due to the CopyRect encoding not + requiring the image data to be transmitted over the network. For fast + links the speedup is primarily due to x11vnc not having to read the + scrolled framebuffer data from the X server (recall that reading from + the hardware framebuffer is slow.) + + To do this x11vnc uses the RECORD X extension to snoop the X11 + protocol between the X client with the focus window and the X server. + This extension is usually present on most X servers (but SuSE disables + it for some reason.) On XFree86/Xorg it can be enabled via Load + "record" in the Module section of the config file if it isn't already: +Section "Module" + ... + Load "record" + ... +EndSection + + Currently the RECORD extension is used as little as possible so as to + not slow down regular use. Only simple heuristics are applied to + detect XCopyArea and XConfigureWindow calls from the application. + These catch a lot of scrolls, e.g. in mozilla/firefox and in terminal + windows like gnome-terminal and xterm. Unfortunately the toolkits KDE + applications use make scroll detection less effective (only rarely are + they detected: i.e. Konqueror and Konsole don't work.) An interesting + project, that may be the direction x11vnc takes, is to record all of + the X11 protocol from all clients and try to "tee" the stream into a + modified Xvfb watching for CopyRect and other VNC speedups. A + potential issue is the RECORD stream is delayed from actual view on + the X server display: if one falls too far behind it could become a + mess... + + The initial implementation of -scrollcopyrect option is useful in that + it detects many scrolls and thus gives a much nicer working + environment (especially when combined with the -wireframe + -wirecopyrect options, which are also on by default; and if you are + willing to enable the ShadowFB things are very fast.) The fact that + there aren't long delays or lurches during scrolling is the primary + improvement. + + But there are some drawbacks: + * Not all scrolls are detected. Some apps scroll windows in ways + that cannot currently be detected, and other times x11vnc "misses" + the scroll due to timeouts, etc. Sometimes it is more distracting + that a speedup occasionally doesn't work as opposed to being + consistently slow! + * For rapid scrolling (i.e. sequence of many scrolls over a short + period) there can be painting errors (tearing, bunching up, etc.) + during the scroll. These will repair themselves after the scroll + is over, but when they are severe it can be distracting. Try to + think of the approximate window contents as a quicker and more + useful "animation" compared to the slower polling scheme... + * Scrolling inside shells in terminal windows (gnome-terminal, + xterm), can lead to odd painting errors. This is because x11vnc + did not have time to detect a screen change just before the scroll + (most common is the terminal undraws the block cursor before + scrolling the text up: in the viewer you temporarily see multiple + block cursors.) Another issue is with things like more(1): scroll + detection for 5-6 lines happens nicely, but then it can't keep up + and so there is a long pause for the standard polling method to + deliver the remaining updates. + * More rarely sometimes painting errors are not repaired after the + scroll is over. This may be a bug in x11vnc or libvncserver, or it + may be an inescapable fact of the CopyRect encoding and the delay + between RECORD callbacks and what is actually on the X display. + One can tap the Alt_L key (Left "Alt" key) 3 times in a row to + signal x11vnc to refresh the screen to all viewers. Your + VNC-viewer may have its own screen refresh hot-key or button. See + also: -fixscreen + * Some applications, notably OpenOffice, do XCopyArea scrolls in + weird ways that assume ancestor window clipping is taking place. + See the -scr_skip option for ways to tweak this on a + per-application basis. + * Selecting text while dragging the mouse may be slower, especially + if the Button-down event happens near the window's edge. This is + because the scrollcopyrect scheme is watching for scrolls via + RECORD and has to wait for a timeout to occur before it does the + update. + * For reasons not yet understood the RECORD extension can stop + responding (and hence scrolls are missed.) As a workaround x11vnc + attempts to reset the RECORD connection every 60 seconds or so. + Another workaround is to type 4 Super_L (Left Super/Windows-Flag + key) in a row to reset RECORD. Work is in progress to try to fix + this bug. + * Sometimes you need to "retrain" x11vnc for a certain window + because it fails to detect scrolls in it. Sometimes clicking + inside the application window or selecting some text in it to + force the focus helps. + * When using the -scale option there will be a quick CopyRect + scroll, but it needs to be followed by a slower "cleanup" update. + This is because for a fixed finite screen resolution (e.g. 75 dpi) + scaling and copyrect-ing are not exactly independent. Scaling + involves a blending of nearby pixels and if you translate a pixel + the neighbor pixel weighting may be different. So you have to wait + a bit for the cleanup update to finish. On slow links x11vnc may + automatically decide to not detect scrolls when -scale is in + effect. In general it will also try to defer the cleanup update if + possible. + + If you find the -scrollcopyrect behavior too approximate or + distracting you can go back to the standard polling-only update method + with the -noscrollcopyrect (or -noscr for short.) If you find some + extremely bad and repeatable behavior for -scrollcopyrect please + report a bug. + + Alternatively, as with -wireframe, there are many tuning parameters to + try to improve the situation. You can also access these parameters + inside the gui under "Tuning". These parameters can be tweaked: + * The minimum pixel area of a rectangle to be watched for scrolls. + * A list if application names to skip scroll detection. + * Which keystrokes should trigger scroll detection. + * Which applications should have a "terminal" tweak applied to them. + * When repeating keys (e.g. Up arrow) should be discarded to + preserve a scroll. + * Cutoffs for closeness to Top, Bottom, Left, and Right edges of + window for mouse induced scrolls. + * Set timeout parameters for keystroke induced scrolls. + * Set timeout parameters for mouse pointer induced scrolls. + * Have the full screen be periodically refreshed to fix painting + errors. + + + Q-79: Can x11vnc do client-side caching of pixel data? I.e. so when + that pixel data is needed again it does not have to be retransmitted + over the network. + + As of Dec/2006 in the 0.9 development tarball there is an experimental + client-side caching implementation enabled by the "-ncache n" option. + In fact, during the test period it was on by default with n set to 10. + To disable it use "-noncache". + + It is a simple scheme where a (very large) lower portion of the + framebuffer (i.e. starting just below the user's actual desktop + display) is used for storing pixel data. CopyRect; a fast, essentially + local viewer-side VNC encoding; is used to swap the pixel data in and + out of the actual display area. It gives an excellent speedup for + iconifying/deiconifying and moving windows and re-posting of menus + (often it doesn't feel like VNC at all: there is no delay waiting for + the pixel data to fill in.) + + This scheme is nice because it does all of this within the existing + VNC protocol, and so it works with all VNC viewers. + + A challenge to doing more sophisticated (e.g. compressed and/or + shared) client-side caching is that one needs to extend the VNC + protocol, modify a viewer and then also convince users to adopt your + modified VNC Viewer (or get the new features to be folded into the + main VNC viewers, patches accepted, etc... likely takes years before + they might be deployed in the field) + + A drawback of the "-ncache n" method is that in the VNC Viewer you can + scroll down and actually see the cached pixel data. So it looks like + there is a bug: you can scroll down in your viewer and see a strange + "history" of windows on your desktop. This is working as intended. One + will need to try to adjust the size of his VNC Viewer window so the + cache area cannot be seen. SSVNC (see below) can do this + automatically. + + At some point LibVNCServer may implement a "rfbFBCrop" pseudoencoding + that viewers can use to learn which portion of the framebuffer to + actually show to the users (with the hidden part used for caching, or + perhaps something else, maybe double buffering or other offscreen + rendering...) + + The Enhanced TightVNC Viewer (SSVNC) Unix viewer has a nice -ycrop + option to help hide the pixel cache area from view. It will turn on + automatically if the framebuffer appears to be very tall (height more + than twice the width), or you can supply the actual value for the + height. If the screen is resized by scaling, etc, the ycrop value is + scaled as well. In fullscreen mode you cannot scroll past the end of + the actual screen, and in non-fullscreen mode the window manager frame + is adjusted to fit the actual display (so you don't see the pixel + cache region) and the scrollbars are very thin to avoid distraction + and trouble fitting inside your display. Use the "-sbwidth n" viewer + option to make the scrollbars thicker if you like. + + Another drawback of the scheme is that it is VERY memory intensive, + the n in "-ncache n" is the factor of increase over the base + framebuffer size to use for caching. It is an even integer and should + be fairly large, 6-12, to achieve good response. This usually requires + about 50-100MB of additional RAM on both the client and server sides. + For example with n=6 a 1280x1024 display will use a framebuffer that + is 1280x7168: everything below row 1024 is the pixel buffer cache. If + you are running on low memory machines or memory is tight because of + other running applications you should not use -ncache. + + The reason for so much memory is because the pixel data is not + compressed and so the whole window to be saved must be stored + "offscreen". E.g. for a large web browser window this can be nearly 1 + million pixels, and that is only for a single window! One typically + wants to cycle between 5-10 large active windows. Also because both + backing-store (the window's actual contents) and save-unders (the + pixels covered up by the window) are cached offscreen that introduces + an additional factor of 2 in memory use. + + However, even in the smallest usage mode with n equal 2 and + -ncache_no_rootpixmap set (this requires only 2X additional + framebuffer memory) there is still a noticable improvement for many + activities, although it is not as dramatic as with, say n equal 12 and + rootpixmap (desktop background) caching enabled. + + The large memory consumption of the current implementation can be + thought of as a tradeoff to providing caching and being compatible + with all VNC viewers and also ease of implementing. Hopefully it can + be tuned to use less, or the VNC community will extend the protocol to + allow caching and replaying of compressed blobs of data. + + Another option to experiment with is "-ncache_cr". By specifying it, + x11vnc will try to do smooth opaque window moves instead of its + wireframe. This can give a very nice effect (note: on Unix the realvnc + viewer seems to be smoother than the tightvnc viewer), but can lead to + some painting problems, and can be jerky in some circumstances. + + Surprisingly, for very slow connections, e.g. modem, the -ncache_cr + option can actually improve window drags. This is probably because no + pixel data (only CopyRect instructions) are sent when dragging a + window. Normally, the wireframe must be sent and this involves + compressing and sending the lines that give rise to the moving box + effect (note that real framebuffer data is sent to "erase" the white + lines of the box.) + + If you experience painting errors you can can tap the Alt_L key (Left + "Alt" key) 3 times in a row to signal x11vnc to refresh the screen to + all viewers. You may also need to iconify and then deiconify any + damaged windows to correct their cache data as well. Note that if you + change color viewer depth (e.g. 8bpp to full color) dynamically that + will usually lead to the entire extended framebuffer being resent + which can take a long time over very slow links: it may be better to + reconnect and reset the format right after doing so. x11vnc will try + to detect the format change and clear (make completely black) the + cache region. + + Gotcha for older Unix VNC Viewers: The older Unix VNC viewers (e.g. + current TightVNC Unix Viewer) require X server backingstore to keep + off-viewer screen data local. If the viewer-side X server has + backingstore disabled (sadly, currently the default on Linux, etc), + then to get the offscreen pixels the viewer has to ask for a refresh + over the network, thereby defeating the caching. Use something like + this in your viewer-side /etc/X11/xorg.conf file (or otherwise get + your viewer-side system to do it) +Section "Device" + ... + Option "backingstore" + ... +EndSection + + No problems like this have been observed with Windows VNC Viewers: + they all seem to keep their entire framebuffer in local memory. Gotcha + for KDE krdc VNC Viewer: One user found that KDE's krdc viewer has + some sort of hardwired limit on the maximum size of the framebuffer + (64MB?). It fails quickly saying "The connection to the host has been + interrupted." The workaround for his 1280x1024 x11vnc-side display was + to run with "-ncache 10", i.e. a smaller value to be under the krdc + threshold. + + Although this scheme is not as quick (nor as compressed) as + nx/nomachine, say, it does provide a good step in the direction of + improving VNC performance by client side caching. + + + Q-80: Does x11vnc support TurboVNC? + + As of Feb/2009 (development tarball) there is an experimental kludge + to let you build x11vnc using TurboVNC's modified TightVNC encoding. + TurboVNC is part of the VirtualGL project. It does two main things to + speed up the TightVNC encoding: + * It eliminates bottlenecks, overheads, wait-times in the TightVNC + encoding implementation and instead only worries about sending + very well (and quickly) compressed JPEG data. + * A fast proprietary JPEG implemention is used (Intel IPP on x86) + instead of the usual libjpeg implementation. TurboJPEG is an + interface library, libturbojpeg, provided by the project that + achieves this. + + TurboVNC works very well over LAN and evidently fast Broadband too. + When using it with x11vnc in such a situation you may want to dial + down the delays, e.g. "-wait 5" and "-defer 5" (or even a smaller + setting) to poll and pump things out more quickly. + + See the instructions in "x11vnc/misc/turbovnc/README" for how to build + x11vnc with TurboVNC support. You will also need to download the + TurboJPEG software. + + In brief, the steps look like this: + cd x11vnc-x.y.z/x11vnc/misc/turbovnc + ./apply_turbovnc + cd ../../.. + env LDFLAGS='-L/DIR -Xlinker --rpath=/DIR' ./configure + make AM_LDFLAGS='-lturbojpeg' + + where you replace "/DIR" with the directory containing libturbojpeg.so + you downloaded separately. If it works out well enough TurboVNC + support will be integrated into x11vnc and more of its tuning features + will be implemented. Support for TurboVNC in SSVNC viewer has been + added as an experiment as well. If you try either one, let us know how + it went. + + There also may be some Linux.i686 and Darwin.i386 x11vnc binaries with + TurboVNC support in the misc. bins directory. For other platforms you + will need to compile yourself. + + On relatively cheap and old hardware (Althon64 X2 5000+ / GeForce + 6200) x11vnc and SSVNC, both TurboVNC enabled, were able to sustain + 13.5 frames/sec (fps) and 15 Megapixels/sec using the VirtualGL + supplied OpenGL benchmark program glxspheres. VirtualGL on higher-end + hardware can sustain 20-30 fps with the glxspheres benchmark. + + Potential Slowdown: As we describe elsewhere, unless you use x11vnc + with an X server using, say, NVidia proprietary drivers (or a virtual + X server like Xvfb or Xdummy, or in ShadowFB mode), then the read rate + from the graphics card can be rather slow (e.g. 10 MB/sec) and becomes + the bottleneck when using x11vnc over fast networks. Note that all of + Xorg's drivers currently (2009) have slow read rates (only proprietary + drivers appear to have optimized reads.) + + So under these (more or less typical) conditions, the speed + improvement provided by TurboVNC may only be marginal. Look for this + output to see your read rate: + 28/02/2009 11:11:07 Autoprobing TCP port + 28/02/2009 11:11:07 Autoprobing selected port 5900 + 28/02/2009 11:11:08 fb read rate: 10 MB/sec + 28/02/2009 11:11:08 screen setup finished. + + A rate of 10 MB/sec means a 1280x1024x24 screen takes 0.5 seconds to + read in. TurboVNC compresses that to JPEG in a much shorter time. On + the other hand, an NVidia driver may have a read rate of 250 MB/sec + and so only takes 0.02 seconds to read the entire screen in. + + + + [Mouse Cursor Shapes] + + Q-81: Why isn't the mouse cursor shape (the little icon shape where + the mouse pointer is) correct as I move from window to window? + + On X servers supporting XFIXES or Solaris/IRIX Overlay extensions it + is possible for x11vnc to do this correctly. See a few paragraphs down + for the answer. + + Historically, the X11 mouse cursor shape (i.e. little picture: an + arrow, X, I-beam, resizer, etc) is one of the few WRITE-only objects + in X11. That is, an application can tell the X server what the cursor + shape should be when the pointer is in a given window, but a program + (like x11vnc) unfortunately cannot read this information. I believe + this is because the cursor shape is often downloaded to the graphics + hardware (video card), but I could be mistaken. + + A simple kludge is provided by the "-cursor X" option that changes the + cursor when the mouse is on the root background (or any window has the + same cursor as the root background.) Note that desktops like GNOME or + KDE often cover up the root background, so this won't work for those + cases. Also see the "-cursor some" option for additional kludges. + + Note that as of Aug/2004 on Solaris using the SUN_OVL overlay + extension and IRIX, x11vnc can show the correct mouse cursor when the + -overlay option is supplied. See this FAQ for more info. + + Also as of Dec/2004 XFIXES X extension support has been added to allow + exact extraction of the mouse cursor shape. XFIXES fixes the problem + of the cursor-shape being write-only: x11vnc can now query the X + server for the current shape and send it back to the connected + viewers. XFIXES is available on recent Linux Xorg based distros and + Solaris 10. + + The only XFIXES issue is the handling of alpha channel transparency in + cursors. If a cursor has any translucency then in general it must be + approximated to opaque RGB values for use in VNC. There are some + situations where the cursor transparency can also handled exactly: + when the VNC Viewer requires the cursor shape be drawn into the VNC + framebuffer or if you apply a patch to your VNC Viewer to extract + hidden alpha channel data under 32bpp. Details can be found here. + + + Q-82: When using XFIXES cursorshape mode, some of the cursors look + really bad with extra black borders around the cursor and other cruft. + How can I improve their appearance? + + This happens for cursors with transparency ("alpha channel"); regular + X cursors (bitmaps) should be correct. Unfortunately x11vnc 0.7 was + released with a very poor algorithm for approximating the + transparency, which led to the ugly black borders. + + The problem is as follows: XFIXES allows x11vnc to retrieve the + current X server cursor shape, including the alpha channel for + transparency. For traditional bitmap cursors the alpha value will be 0 + for completely transparent pixels and 255 for completely opaque + pixels; whereas for modern, eye-candy cursors an alpha value between 0 + and 255 means to blend in the background colors to that degree with + the cursor colors. The pixel color blending formula is something like + this: Red = Red_cursor * a + Red_background * (1 - a), (where here 0 + =< a =< 1), with similar for Green and Blue. The VNC protocol does not + currently support an alpha channel in cursors: it only supports + regular X bitmap cursors and Rich Cursors that have RGB (Red, Green, + Blue) color data, but no "A" = alpha data. So in general x11vnc has to + approximate a cursor with transparency to create a Rich Cursor. This + is easier said than done: some cursor themes have cursors with + complicated drop shadows and other forms of translucency. + + Anyway, for the x11vnc 0.7.1 release the algorithm for approximating + transparency is much improved and hopefully gives decent cursor shapes + for most cursor themes and you don't have to worry about it. + + In case it still looks bad for your cursor theme, there are (of + course!) some tunable parameters. The "-alphacut n" option lets you + set the threshold "n" (between 0 and 255): cursor pixels with alpha + values below n will be considered completely transparent while values + equal to or above n will be completely opaque. The default is 240. The + "-alphafrac f" option tries to correct individual cursors that did not + fare well with the default -alphacut value: if a cursor has less than + fraction f (between 0.0 and 1.0) of its pixels selected by the default + -alphacut, the threshold is lowered until f of its pixels are + selected. The default fraction is 0.33. + + Finally, there is an option -alpharemove that is useful for themes + where many cursors are light colored (e.g. "whiteglass".) XFIXES + returns the cursor data with the RGB values pre-multiplied by the + alpha value. If the white cursors look too grey, specify -alpharemove + to brighten them by having x11vnc divide out the alpha value. + + One user played with these parameters and reported back: + Of the cursor themes present on my system: + + gentoo and gentoo-blue: alphacut:192 - noalpharemove + + gentoo-silver: alphacut:127 and alpharemove + + whiteglass and redglass (presumably also handhelds, which is based + heavily on redglass) look fine with the apparent default of alphacut:255. + + + Q-83: In XFIXES mode, are there any hacks to handle cursor + transparency ("alpha channel") exactly? + + As of Jan/2005 libvncserver has been modified to allow an alpha + channel (i.e. RGBA data) for Rich Cursors. So x11vnc can now send the + alpha channel data to libvncserver. However, this data will only be + used for VNC clients that do not support the CursorShapeUpdates VNC + extension (or have disabled it.) It can be disabled for all clients + with the -nocursorshape x11vnc option. In this case the cursor is + drawn, correctly blended with the background, into the VNC framebuffer + before being sent out to the client. So the alpha blending is done on + the x11vnc side. Use the -noalphablend option to disable this behavior + (always approximate transparent cursors with opaque RGB values.) + + The CursorShapeUpdates VNC extension complicates matters because the + cursor shape is sent to the VNC viewers supporting it, and the viewers + draw the cursor locally. This improves response over slow links. Alpha + channel data for these locally drawn cursors is not supported by the + VNC protocol. + + However, in the libvncserver CVS there is a patch to the TightVNC + viewer to make this work for CursorShapeUpdates under some + circumstances. This hack is outside of the VNC protocol. It requires + the screens on both sides to be depth 24 at 32bpp (it uses the extra 8 + bits to secretly hide the cursor alpha channel data.) Not only does it + require depth 24 at 32bpp, but it also currently requires the client + and server to be of the same endianness (otherwise the hidden alpha + data gets reset to zero by a libvncserver translation function; we can + fix this at some point if there is interest.) The patch is for the + TightVNC 1.3dev5 Unix vncviewer and it enables the TightVNC viewer to + do the cursor alpha blending locally. The patch code should give an + example on how to change the Windows TightVNC viewer to achieve the + same thing (send me the patch if you get that working.) + + This patch is applied to the Enhanced TightVNC Viewer (SSVNC) package + we provide. + + [Mouse Pointer] + + Q-84: Why does the mouse arrow just stay in one corner in my + vncviewer, whereas my cursor (that does move) is just a dot? + + This default takes advantage of a tightvnc extension + (CursorShapeUpdates) that allows specifying a cursor image shape for + the local VNC viewer. You may disable it with the -nocursor option to + x11vnc if your viewer does not have this extension. + + Note: as of Aug/2004 this should be fixed: the default for + non-tightvnc viewers (or ones that do not support CursorShapeUpdates) + will be to draw the moving cursor into the x11vnc framebuffer. This + can also be disabled via -nocursor. + + + Q-85: Can I take advantage of the TightVNC extension to the VNC + protocol where Cursor Positions Updates are sent back to all connected + clients (i.e. passive viewers can see the mouse cursor being moved + around by another viewer)? + + Use the -cursorpos option when starting x11vnc. A VNC viewer must + support the Cursor Positions Updates for the user to see the mouse + motions (the TightVNC viewers support this.) As of Aug/2004 -cursorpos + is the default. See also -nocursorpos and -nocursorshape. + + + Q-86: Is it possible to swap the mouse buttons (e.g. left-handed + operation), or arbitrarily remap them? How about mapping button clicks + to keystrokes, e.g. to partially emulate Mouse wheel scrolling? + + You can remap the mouse buttons via something like: -buttonmap 13-31 + (or perhaps 12-21.) Also, note that xmodmap(1) lets you directly + adjust the X server's button mappings, but in some circumstances it + might be more desirable to have x11vnc do it. + + One user had an X server with only one mouse button(!) and was able to + map all of the VNC client mouse buttons to it via: -buttonmap 123-111. + + Note that the -debug_pointer option prints out much info for every + mouse/pointer event and is handy in solving problems. + + To map mouse button clicks to keystrokes you can use the alternate + format where the keystrokes are enclosed between colons like this + :: in place of the mouse button digit. For a sequence of + keysyms separate them with "+" signs. Look in the include file + , or use xev(1), or -debug_keyboard to find the + keysym names. Button clicks can also be included in the sequence via + the fake keysyms Button1, etc. + + As an example, suppose the VNC viewer machine has a mouse wheel (these + generate button 4 and 5 events), but the machine that x11vnc is run on + only has the 3 regular buttons. In normal operation x11vnc will + discard the button 4 and 5 events. However, either of the following + button maps could possibly be of use emulating the mouse wheel events + in this case: + -buttonmap 12345-123:Prior::Next: + -buttonmap 12345-123:Up+Up+Up::Down+Down+Down: + + Exactly what keystroke "scrolling" events they should be bound to + depends on one's taste. If this method is too approximate, one could + consider not using -buttonmap but rather configuring the X server to + think it has a mouse with 5 buttons even though the physical mouse + does not. (e.g. 'Option "ZAxisMapping" "4 5"'.) + + Note that when a keysym-mapped mouse button is clicked down this + immediately generates the key-press and key-release events (for each + keysym in turn if the mapping has a sequence of keysyms.) When the + mouse button goes back up nothing is generated. + + If you include modifier keys like Shift_L instead of key-press + immediately followed by key-release the state of the modifier key is + toggled (however the initial state of the modifier key is ignored.) So + to map the right button to type my name 'Karl Runge' I could use this: + -buttonmap 3-:Shift_L+k+Shift_L+a+r+l+space+Shift_L+r+Shift_L+u+n+g+e: + + (yes, this is getting a little silly.) + + BTW, Coming the other way around, if the machine you are sitting at + does not have a mouse wheel, but the remote machine does (or at least + has 5 buttons configured), this key remapping can be useful: + -remap Super_R-Button4,Menu-Button5 + + you just tap those two keys to get the mouse wheel scrolls (this is + more useful than the Up and Down arrow keys because a mouse wheel + "click" usually gives a multi-line scroll.) + [Keyboard Issues] + + Q-87: How can I get my AltGr and Shift modifiers to work between + keyboards for different languages? + + The option -modtweak should help here. It is a mode that monitors the + state of the Shift and AltGr Modifiers and tries to deduce the correct + keycode to send, possibly by sending fake modifier key presses and + releases in addition to the actual keystroke. + + Update: As of Jul/2004 -modtweak is now the default (use -nomodtweak + to get the old behavior.) This was done because it was noticed on + newer XFree86 setups even on bland "us" keyboards like "pc104 us" + XFree86 included a "ghost" key with both "<" and ">" it. This key does + not exist on the keyboard (see this FAQ for more info.) Without + -modtweak there was then an ambiguity in the reverse map keysym => + keycode, making it so the "<" symbol could not be typed. + + Also see the FAQ about the -xkb option for a more powerful method of + modifier tweaking for use on X servers with the XKEYBOARD extension. + + When trying to resolve keyboard mapping problems, note that the + -debug_keyboard option prints out much info for every keystroke and so + can be useful debugging things. + + Note that one user had a strange setup and none of the above helped. + His solution was to disable all of the above and use -nomodtweak. This + is the simplest form of keystroke insertion and it actually solved the + problem. Try it if the other options don't help. + + + Q-88: When I try to type a "<" (i.e. less than) instead I get ">" + (i.e. greater than)! Strangely, typing ">" works OK!! + + Does your keyboard have a single key with both "<" and ">" on it? Even + if it doesn't, your X server may think your keyboard has such a key + (e.g. pc105 in the XF86Config file when it should be something else, + say pc104.) + + Short Cut: Try the -xkb or -sloppy_keys options and see if that helps + the situation. The discussion below is a bit outdated (e.g. -modtweak + is now the default) but it is useful reference for various tricks and + so is kept. + + + The problem here is that on the Xserver where x11vnc is run there are + two keycodes that correspond to the "<" keysym. Run something like + this to see: + + xmodmap -pk | egrep -i 'KeyCode|less|greater' + There are 4 KeySyms per KeyCode; KeyCodes range from 8 to 255. + KeyCode Keysym (Keysym) ... + 59 0x002c (comma) 0x003c (less) + 60 0x002e (period) 0x003e (greater) + 94 0x003c (less) 0x003e (greater) + + That keycode 94 is the special key with both "<" and ">". When x11vnc + receives the "<" keysym over the wire from the remote VNC client, it + unfortunately maps it to keycode 94 instead of 59, and sends 94 to the + X server. Since Shift is down (i.e. you are Shifting the comma key), + the X server interprets this as Shifted-94, which is ">". + + A workaround in the X server configuration is to "deaden" that special + key: + + xmodmap -e "keycode 94 = " + + However, one user said he had to do this: + + xmodmap -e "keycode 94 = 0x002c 0x003c" + + (If the numerical values are different for your setup, substitute the + ones that correspond to your display. The above xmodmap scheme can + often be used to work around other ambiguous keysym to keycode + mappings.) + + Alternatively, here are some x11vnc options to try to work around the + problem: + -modtweak + + and + -remap less-comma + + These are convenient in that they do not modify the actual X server + settings. The former (-modtweak) is a mode that monitors the state of + the Shift and AltGr modifiers and tries to deduce the correct keycode + sequence to send. Since Jul/2004 -modtweak is now the default. The + latter (-remap less-comma) is an immediate remapping of the keysym + less to the keysym comma when it comes in from a client (so when Shift + is down the comma press will yield "<".) + + See also the FAQ about the -xkb option as a possible workaround using + the XKEYBOARD extension. + + Note that the -debug_keyboard option prints out much info for every + keystroke to aid debugging keyboard problems. + + + Q-89: Extra Character Inserted, E.g.: When I try to type a "<" (i.e. + less than) instead I get "<," (i.e. an extra comma.) + + This is likely because you press "Shift" then "<" but then released + the Shift key before releasing the "<". Because of a keymapping + ambiguity the last event "< up" is interpreted as "," because that key + unshifted is the comma. + + This extra character insertion will happen for other combinations of + characters: in general it can happen whenever the Shift key is + released early. + + This should not happen in -xkb mode, because it works hard to resolve + the ambiguities. If you do not want to use -xkb, try the option + -sloppy_keys to attempt a similar type of algorithm. + + One user had this problem for Italian and German keyboards with the + key containing ":" and "." When he typed ":" he would get an extra "." + inserted after the ":". The solution was -sloppy_keys. + + + Q-90: I'm using an "international" keyboard (e.g. German "de", or + Danish "dk") and the -modtweak mode works well if the VNC viewer is + run on a Unix/Linux machine with a similar keyboard. But if I run + the VNC viewer on Unix/Linux with a different keyboard (e.g. "us") or + Windows with any keyboard, I can't type some keys like: "@", "$", + "<", ">", etc. How can I fix this? + + The problem with Windows is it does not seem to handle AltGr well. It + seems to fake it up by sending Control_L+Alt_R to applications. The + Windows VNC viewer sends those two down keystrokes out on the wire to + the VNC server, but when the user types the next key to get, e.g., "@" + the Windows VNC viewer sends events bringing the up the + Control_L+Alt_R keys, and then sends the "@" keysym by itself. + + The Unix/Linux VNC viewer on a "us" keyboard does a similar thing + since "@" is the Shift of the "2" key. The keysyms Shift and "@" are + sent to the VNC server. + + In both cases no AltGr is sent to the VNC server, but we know AltGr is + needed on the physical international keyboard to type a "@". + + This all worked fine with x11vnc running with the -modtweak option (it + figures out how to adjust the Modifier keys (Shift or AltGr) to get + the "@".) However it fails under recent versions of XFree86 (and the + X.org fork.) These run the XKEYBOARD extension by default and make + heavy use of it to handle international keyboards. + + To make a long story short, on these newer XFree86 setups the + traditional X keymap lookup x11vnc uses is no longer accurate. x11vnc + can't find the keysym "@" anywhere in the keymapping! (even though it + is in the XKEYBOARD extended keymapping.) + + How to Solve: As of Jul/2004 x11vnc has two changes: + * -modtweak (tweak Modifier keys) is now the default (use + -nomodtweak to go back to the old way) + * there is a new option -xkb to use the XKEYBOARD extension API to + do the Modifier key tweaking. + + The -xkb option seems to fix all of the missing keys: "@", "<", ">", + etc.: it is recommended that you try it if you have this sort of + problem. Let us know if there are any remaining problems (see the next + paragraph for some known problems.) If you specify the -debug_keyboard + (aka -dk) option twice you will get a huge amount of keystroke + debugging output (send it along with any problems you report.) + + Update: as of Jun/2005 x11vnc will try to automatically enable -xkb if + it appears that would be beneficial (e.g. if it sees any of "@", "<", + ">", "[" and similar keys are mapped in a way that needs the -xkb to + access them.) To disable this automatic check use -noxkb. + + Known problems: + * One user had to disable a "ghost" Mode_switch key that was causing + problems under -xkb. His physical AltGr key was bound to + ISO_Level3_Shift (which seems to be the XKEYBOARD way of doing + things), while there was a ghost key Mode_switch (which seems to + be obsolete) in the mapping as well. Both of these keysyms were + bound to Mod5 and x11vnc was unfortunately choosing Mode_switch. + From the x11vnc -xkb -dk -dk output it was noted that Mode_switch + was attached to keycode 93 (no physical key generates this + keycode) while ISO_Level3_Shift was attached to keycode 113. The + keycode skipping option was used to disable the ghost key: + -skip_keycodes 93 + * In implementing -xkb we noticed that some characters were still + not getting through, e.g. "~" and "^". This is not really an + XKEYBOARD problem. What was happening was the VNC viewer was + sending the keysyms asciitilde and asciicircum to x11vnc, but on + the X server with the international keyboard those keysyms were + not mapped to any keys. So x11vnc had to skip them (Note: as of + May/2005 they are added by default see -add_keysyms below.) + The way these characters are typically entered on international + keyboards is by "dead" (aka "mute") keys. E.g. to enter "~" at the + physical display the keysym dead_tilde is pressed and released + (this usually involves holding AltGr down while another key is + pressed) and then space is pressed. (this can also be used get + characters with the "~" symbol on top, e.g. "ã" by typing "a" + instead of space.) + What to do? In general the VNC protocol has not really solved this + problem: what should be done if the VNC viewer sends a keysym not + recognized by the VNC server side? Workarounds can possibly be + created using the -remap x11vnc option: + -remap asciitilde-dead_tilde,asciicircum-dead_circumflex + etc. Use -remap filename if the list is long. Please send us your + workarounds for this problem on your keyboard. Perhaps we can have + x11vnc adjust automatically at some point. Also see the + -add_keysyms option in the next paragraph. + Update: for convenience "-remap DEAD" does many of these mappings + at once. + * To complement the above workaround using the -remap, an option + -add_keysyms was added. This option instructs x11vnc to bind any + unknown Keysyms coming in from VNC viewers to unused Keycodes in + the X server. This modifies the global state of the X server. When + x11vnc exits it removes the extra keymappings it created. Note + that the -remap mappings are applied first, right when the Keysym + is received from a VNC viewer, and only after that would + -add_keysyms, or anything else, come into play. + Update: -add_keysyms is now on by default. Use -noadd_keysyms to + disable. + + + Q-91: When typing I sometimes get double, triple, or more of my + keystrokes repeated. I'm sure I only typed them once, what can I do? + + This may be due to an interplay between your X server's key autorepeat + delay and the extra time delays caused by x11vnc processing. + + Short answer: disable key autorepeating by running the command "xset r + off" on the Xserver where x11vnc is run (restore via "xset r on") or + use the new (Jul/2004) -norepeat x11vnc option. You will still have + autorepeating because that is taken care of on your VNC viewer side. + + Update: as of Dec/2004 -norepeat is now the default. Use -repeat to + disable it. + + Details: + suppose you press a key DOWN and it generates changes in large regions + of the screen. The CPU and I/O work x11vnc does for the large screen + change could be longer than your X server's key autorepeat delay. + x11vnc may not get to processing the key UP event until after the + screen work is completed. The X server believes the key has been held + down all this time, and applies its autorepeat rules. + + Even without inducing changes in large regions of the screen, this + problem could arise when accessing x11vnc via a dialup modem or + otherwise high latency link (e.g. > 250 ms latency.) + + Look at the output of "xset q" for the "auto repeat delay" setting. Is + it low (e.g. < 300 ms)? If you turn off autorepeat completely: "xset r + off", does the problem go away? + + The workaround is to manually apply "xset r off" and "xset r on" as + needed, or to use the -norepeat (which has since Dec/2004 been made + the default.) Note that with X server autorepeat turned off the VNC + viewer side of the connection will (nearly always) do its own + autorepeating so there is no big loss here, unless someone is also + working at the physical display and misses his autorepeating. + + + Q-92: The x11vnc -norepeat mode is in effect, but I still get repeated + keystrokes!! + + Are you using x11vnc to log in to an X session via display manager? + (as described in this FAQ) If so, x11vnc is starting before your + session and it disables autorepeat when you connect, but then after + you log in your session startup (GNOME, KDE, ...) could be resetting + the autorepeat to be on. Or it could be something inside your desktop + trying to be helpful that decides to turn it back on. + + x11vnc in -norepeat mode will by default reset autorepeat to off 2 + times (to help get thru the session startup problem), but it will not + continue to battle with things turning autorepeat back on. It will + also turn autorepeat off whenever it goes from a state of zero clients + to one client. You can adjust the number of resets via "-norepeat N", + or use "-norepeat -1" to have it keep resetting it whenever autorepeat + gets turned back on when clients are connected. + + In general you can manually turn autorepeating off by typing "xset r + off", or a using desktop utility/menu, or "x11vnc -R norepeat". If + something in your desktop is automatically turning it back on you + should figure out how to disable that somehow. + + + Q-93: After using x11vnc for a while, I find that I cannot type some + (or any) characters or my mouse clicks and drags no longer have any + effect, or they lead to strange effects. What happened? + + Probably a modifier key, e.g. Control or Alt is "stuck" in a pressed + down state. + + This happens for VNC in general by the following mechanism. Suppose on + the Viewer side desktop there is some hot-key to switch + desktops/rooms/spaces, etc. E.g. suppose Alt+LeftArrow moves to the + left desktop/room/space. Or suppose an Alt+hotkey combination + iconifies a window. This can leave the Alt key pressed down on the + remote side. + + Consider the sequence that happens. The Alt_L key and then the + LeftArrow key go down. Since you are inside the viewer the Alt_L key + press is sent to the other side (x11vnc) and so it is pressed down in + the remote desktop as well. (by "Alt_L" we mean the Alt key on the + left-hand side of the keyboard.) Your local desktop (where the VNC + Viewer is running) then warps to the new desktop/room/space: Leaving + the Alt_L key still pressed down in the remote desktop. + + If someone is sitting at the desktop, or when you return in the viewer + it may be very confusing because the Alt_L is still pressed down but + you (or the person sitting at the desktop) do not realize this. + Depending on which remote desktop (x11vnc side) is used, it can act + very strangely. + + A quick workaround when you notice this is to press and release all of + the Alt, Shift, Control, Windows-Flag, modifier keys to free the + pressed one. You need to do this for both the left and right Shift, + Alt, Control, etc. keys to be sure. + + Note that many VNC Viewers try to guard against this when they are + notified by the window system that the viewer app has "lost focus". + When it receives the "lost focus" event, the viewer sends VNC + Key-Release events for all modifier keys that are currently pressed + down. This does not always work, however, since it depends on how the + desktop manages these "warps". If the viewer is not notified it cannot + know it needs to release the modifiers. + + You can also use the -clear_mods option to try to clear all of the + modifier keys at x11vnc startup. You will still have to be careful + that you do not leave the modifier key pressed down during your + session. It is difficult to prevent this problem from occurring (short + of using -remap to prevent sending all of the problem modifier keys, + which would make the destkop pretty unusable.) + + During a session these x11vnc remote control commands can also help: + x11vnc -R clear_mods + x11vnc -R clear_keys + x11vnc -R clear_locks + x11vnc -R clear_all + + A similar problem can occur if you accidentally press the Caps_Lock or + Num_Lock down. When these are locked on the remote side it can + sometimes lead to strange desktop behavior (e.g. cannot drag or click + on windows.) As above you may not notice this because the lock isn't + down on the local (Viewer) side. See this FAQ on lock keys problem. + These options may help avoid the problem: -skip_lockkeys and + -capslock. See also -clear_all. + + + Q-94: The machine where I run x11vnc has an AltGr key, but the local + machine where I run the VNC viewer does not. Is there a way I can map + a local unused key to send an AltGr? How about a Compose key as well? + + Something like "-remap Super_R-Mode_switch" x11vnc option may work. + Note that Super_R is the "Right Windoze(tm) Flaggie" key; you may want + to choose another. The -debug_keyboard option comes in handy in + finding keysym names (so does xev(1).) + + For Compose how about "-remap Menu-Multi_key" (note that Multi_key is + the official name for Compose.) To do both at the same time: "-remap + Super_R-Mode_switch,Menu-Multi_key" or use "-remap filename" to + specify remappings from a file. + + + Q-95: I have a Sun machine I run x11vnc on. Its Sun keyboard has just + one Alt key labelled "Alt" and two Meta keys labelled with little + diamonds. The machine where I run the VNC viewer only has Alt keys. + How can I send a Meta keypress? (e.g. emacs needs this) + + Here are a couple ideas. The first one is to simply use xmodmap(1) to + adjust the Sun X server. Perhaps xmodmap -e "keysym Alt_L = Meta_L + Alt_L" will do the trick. (there are other ways to do it, one user + used: xmodmap -e "keycode 26 = Meta_L" for his setup.) + + Since xmodmap(1) modifies the X server mappings you may not want to do + this (because it affects local work on that machine.) Something like + the -remap Alt_L-Meta_L to x11vnc may be sufficient for ones needs, + and does not modify the X server environment. Note that you cannot + send Alt_L in this case, maybe -remap Super_L-Meta_L would be a better + choice if the Super_L key is typically unused in Unix. + + + Q-96: Running x11vnc on HP-UX I cannot type "#" I just get a "3" + instead. + + One user reports this problem on HP-UX Rel_B.11.23. The problem was + traced to a strange keyboard mapping for the machine (e.g. xmodmap -pk + output) that looked like: + ... + 039 2 at at at + ... + 047 3 numbersign numbersign numbersign + + and similar triple mappings (with two in the AltGr/Mode_switch group) + of a keysum to a single keycode. + + Use the -nomodtweak option as a workaround. You can also use xmodmap + to correct these mappings in the server, e.g.: + xmodmap -e "keycode 47 = 3 numbersign" + + Also, as of Feb/2007, set the environment variable MODTWEAK_LOWEST=1 + (either in your shell or via "-env MODTWEAK_LOWEST=1" option) to + handle these mappings better. + + + Q-97: Can I map a keystroke to a mouse button click on the remote + machine? + + This can be done directly in some X servers using AccessX and + Pointer_EnableKeys, but is a bit awkward. It may be more convenient to + have x11vnc do the remapping. This can be done via the -remap option + using the fake "keysyms" Button1, Button2, etc. as the "to" keys (i.e. + the ones after the "-") + + As an example, consider a laptop where the VNC viewer is run that has + a touchpad with only two buttons. It is difficult to do a middle + button "paste" because (using XFree86/Xorg Emulate3Buttons) you have + to click both buttons on the touch pad at the same time. This + remapping: + -remap Super_R-Button2 + + maps the Super_R "flag" key press to the Button2 click, thereby making + X pasting a bit easier. + + Note that once the key goes down, the button down and button up events + are generated immediately on the x11vnc side. When the key is released + (i.e. goes up) no events are generated. + + Q-98: How can I get Caps_Lock to work between my VNC viewer and + x11vnc? + + This is a little tricky because it is possible to get the Caps_Lock + state out of sync between your viewer-side machine and the x11vnc-side + X server. For best results, we recommend not ever letting the + Caps_Lock keypresses be processed by x11vnc. That way when you press + Caps_Lock in the viewer your local machine goes into the Caps_Lock on + state and sends keysym "A" say when you press "a". x11vnc will then + fake things up so that Shift is held down to generate "A". The + -skip_lockkeys option should help to accomplish this. For finer grain + control use something like: "-remap Caps_Lock-None". + + Also try the -nomodtweak and -capslock options. + + Another useful option that turns off any Lock keys on the remote side + at startup and end is the -clear_all option. During a session you can + run these remote control commands to modify the Lock keys: + x11vnc -R clear_locks + x11vnc -R clear_all + + the former will try to unset any Lock keys, the latter will do same + and also try to make it so no key is pressed down (e.g. "stuck" Alt_L, + etc.) + [Screen Related Issues and Features] + + Q-99: The remote display is larger (in number of pixels) than the + local display I am running the vncviewer on. I don't like the + vncviewer scrollbars, what I can do? + + vncviewer has a option (usually accessible via F8 key or -fullscreen + option) for vncviewer to run in full screen, where it will + automatically scroll when the mouse is near the edge of the current + view. For quick scrolling, also make sure Backing Store is enabled on + the machine vncviewer is run on. (XFree86/Xorg disables it by default + for some reason, add Option "backingstore" to XF86Config on the + vncviewer side.) + + BTW, contact me if you are having problems with vncviewer in + fullscreen mode with your window manager (i.e. no keyboard response.) + I have a workaround for vncviewer using XGrabServer(). + + There may also be scaling viewers out there (e.g. TightVNC or UltraVNC + on Windows) that automatically shrink or expand the remote framebuffer + to fit the local display. Especially for hand-held devices. See also + the next FAQ on x11vnc scaling. + + + Q-100: Does x11vnc support server-side framebuffer scaling? (E.g. to + make the desktop smaller.) + + As of Jun/2004 x11vnc provides basic server-side scaling. It is a + global scaling of the desktop, not a per-client setting. To enable it + use the "-scale fraction" option. "fraction" can either be a floating + point number (e.g. -scale 0.75) or the alternative m/n fraction + notation (e.g. -scale 3/4.) Note that if fraction is greater than one + the display is magnified. + + Extra resources (CPU, memory I/O, and memory) are required to do the + scaling. If the machine is slow where x11vnc is run with scaling + enabled, the interactive response can be unacceptable. OTOH, if run + with scaling on a fast machine the performance degradation is usually + not a big issue or even noticeable. + + It may help to compile x11vnc with compiler option -O3 or -O4 to speed + up the scaling code. Set the CFLAGS env. var. before running + configure. + + Also, if you just want a quick, rough "thumbnail" of the display you + can append ":nb" to the fraction to turn on "no blending" mode. E.g.: + "-scale 1/3:nb" Fonts will be difficult to read, but the larger + features will be recognizable. BTW, "no blending" mode is forced on + when scaling 8bpp PseudoColor displays (because blending an indexed + colormap is a bad idea and leads to random colors, use :fb to force it + on.) + + One can also use the ":nb" with an integer scale factor (say "-scale + 2:nb") to use x11vnc as a screen magnifier for vision impaired + applications. Since with integer scale factors the framebuffers become + huge and scaling operations time consuming, be sure to use ":nb" for + the fastest response. + + In general for a scaled display if you are using a TightVNC viewer you + may want to turn off jpeg encoding (e.g. vncviewer -nojpeg host:0.) + There appears to be a noise enhancement effect, especially for regions + containing font/text: the scaling can introduce some pixel artifacts + that evidently causes the tight encoding algorithm to incorrectly + detect the regions as image data and thereby introduce additional + pixel artifacts due to the lossiness of the jpeg compression + algorithm. Experiment to see if -nojpeg vncviewer option improves the + readability of text when using -scale to shrink the display size. Also + note that scaling may actually slow down the transfer of text regions + because after being scaled they do not compress as well. (this can + often be a significant slowdown, e.g. 10X.) + + Another issue is that it appears VNC viewers require the screen width + to be a multiple of 4. When scaling x11vnc will round the width to the + nearest multiple of 4. To disable this use the ":n4" sub option (like + ":nb" in the previous paragraph; to specify both use a comma: + ":nb,n4", etc.) + + If one desires per-client scaling for something like 1:1 from a + workstation and 1:2 from a smaller device (e.g. handheld), currently + the only option is to run two (or more) x11vnc processes with + different scalings listening on separate ports (-rfbport option, etc.) + + Update: As of May/2006 x11vnc also supports the UltraVNC server-side + scaling. This is a per-client scaling by factors 1/2, 1/3, ... and so + may be useful for PDA's ("-scale 1/2", etc. will give similar results + except that it applies to all clients.) You may need to supply + "-rfbversion 3.6" for this to be recognized by UltraVNC viewers. + + BTW, whenever you run two or more x11vnc's on the same X display and + use the GUI, then to avoid all of the x11vnc's simultaneously + answering the gui you will need to use something like "-connect file1 + -gui ..." with different connect files for each x11vnc you want to + control via the gui (or remote-control.) The "-connect file1" usage + gives separate communication channels between a x11vnc process and the + gui process. Otherwise they all share the same X property channels: + VNC_CONNECT and X11VNC_REMOTE. + + Update: As of Mar/2005 x11vnc now scales the mouse cursor with the + same scale factor as the screen. If you don't want that, use the + "-scale_cursor frac" option to set the cursor scaling to a different + factor (e.g. use "-scale_cursor 1" to keep the cursor at its natural + unscaled size.) + + + Q-101: Does x11vnc work with Xinerama? (i.e. multiple monitors joined + together to form one big, single screen.) + + Yes, it should generally work because it simply polls the big + effective screen. + + If the viewing-end monitor is not as big as the remote Xinerama + display, then the vncviewer scrollbars, etc, will have to be used to + pan across the large area. However one user started two x11vnc's, one + with "-clip 1280x1024+0+0" and the other with "-clip 1280x1024+1280+0" + to split the big screen into two and used two VNC viewers to access + them. + + As of Jun/2008: Use "-clip xinerama0" to clip to the first xinerama + sub-screen (if xinerama is active.) xinerama1 for the 2nd sub-screen, + etc. This way you don't need to figure out the WxH+X+Y of the desired + xinerama sub-screen. screens are sorted in increasing distance from + the (0,0) origin (I.e. not the Xserver's order.) + + There are a couple potential issues with Xinerama however. If the + screen is not rectangular (e.g. 1280x1024 and 1024x768 monitors joined + together), then there will be "non-existent" areas on the screen. The + X server will return "garbage" image data for these areas and so they + may be distracting to the viewer. The -blackout x11vnc option allows + you to blacken-out rectangles by manually specifying their WxH+X+Y + geometries. If your system has the libXinerama library, the -xinerama + x11vnc option can be used to have it automatically determine the + rectangles to be blackened out. (Note on 8bpp PseudoColor displays the + fill color may not be black.) Update: -xinerama is now on by default. + + Some users have reported that the mouse does not behave properly for + their Xinerama display: i.e. the mouse cannot be moved to all regions + of the large display. If this happens try using the -xwarppointer + option. This instructs x11vnc to fake mouse pointer motions using the + XWarpPointer function instead of the XTestFakeMotionEvent XTEST + function. (This may be due to a bug in the X server for XTEST when + Xinerama is enabled.) Update: As of Dec/2006 -xwarppointer will be + applied automatically if Xinerama is detected. To disable use: + -noxwarppointer + + + Q-102: Can I use x11vnc on a multi-headed display that is not Xinerama + (i.e. separate screens :0.0, :0.1, ... for each monitor)? + + You can, but it is a little bit awkward: you must start separate + x11vnc processes for each screen, and on the viewing end start up + separate VNC viewer processes connecting to them. e.g. on the remote + end: + x11vnc -display :0.0 -bg -q -rfbport 5900 + x11vnc -display :0.1 -bg -q -rfbport 5901 + + (this could be automated in the display manager Xsetup for example) + and then on the local machine where you are sitting: + vncviewer somehost:0 & + vncviewer somehost:1 & + + Note: if you are running on Solaris 8 or earlier you can easily hit up + against the maximum of 6 shm segments per process (for Xsun in this + case) from running multiple x11vnc processes. You should modify + /etc/system as mentioned in another FAQ to increase the limit. It is + probably also a good idea to run with the -onetile option in this case + (to limit each x11vnc to 3 shm segments), or even -noshm to use no shm + segments. + + + Q-103: Can x11vnc show only a portion of the display? (E.g. for a + special purpose application or a very large screen.) + + As of Mar/2005 x11vnc has the "-clip WxH+X+Y" option to select a + rectangle of width W, height H and offset (X, Y). Thus the VNC screen + will be the clipped sub-region of the display and be only WxH in size. + One user used -clip to split up a large Xinerama screen into two more + managable smaller screens. + + This also works to view a sub-region of a single application window if + the -id or -sid options are used. The offset is measured from the + upper left corner of the selected window. + + + Q-104: Does x11vnc support the XRANDR (X Resize, Rotate and + Reflection) extension? Whenever I rotate or resize the screen x11vnc + just seems to crash. + + As of Dec/2004 x11vnc supports XRANDR. You enable it with the -xrandr + option to make x11vnc monitor XRANDR events and also trap X server + errors if the screen change occurred in the middle of an X call like + XGetImage. Once it traps the screen change it will create a new + framebuffer using the new screen. + + If the connected vnc viewers support the NewFBSize VNC extension + (Windows TightVNC viewer and RealVNC 4.0 windows and Unix viewers do) + then the viewer will automatically resize. Otherwise, the new + framebuffer is fit as best as possible into the original viewer size + (portions of the screen may be clipped, unused, etc.) For these + viewers you can try the -padgeom option to make the region big enough + to hold all resizes and rotations. We have fixed this problem for the + TightVNC Viewer on Unix: SSVNC + + If you specify "-xrandr newfbsize" then vnc viewers that do not + support NewFBSize will be disconnected before the resize. If you + specify "-xrandr exit" then all will be disconnected and x11vnc will + terminate. + + + Q-105: Independent of any XRANDR, can I have x11vnc rotate and/or + reflect the screen that the VNC viewers see? (e.g. for a handheld + whose screen is rotated 90 degrees.) + + As of Jul/2006 there is the -rotate option allow this. E.g's: "-rotate + +90", "-rotate -90", "-rotate x", etc. + + + Q-106: Why is the view in my VNC viewer completely black? Or why is + everything flashing around randomly? + + See the next FAQ for a possible explanation. + + + Q-107: I use Linux Virtual Terminals (VT's) to implement 'Fast User + Switching' between users' sessions (e.g. Betty is on Ctrl-Alt-F7, + Bobby is on Ctrl-Alt-F8, and Sid is on Ctrl-Alt-F1: they use those + keystrokes to switch between their sessions.) How come the view in a + VNC viewer connecting to x11vnc is either completely black or + otherwise all messed up unless the X session x11vnc is attached to is + in the active VT? + + This seems to have to do with how applications (the X server processes + in this case) must "play nicely" if they are not on the active VT + (sometimes called VC for virtual console.) That is, they should not + read from the keyboard or mouse or manage the video display unless + they have the active VT. Given that it appears the XGetImage() call + must ultimately retrieve the framebuffer data from the video hardware + itself, it would make sense x11vnc's polling wouldn't work unless the + X session had active control of the VT. + + There does not seem to be an easy way to work around this. Even xwd(1) + doesn't work in this case (try it.) Something would need to be done at + a lower level, say in the XFree86/Xorg X server. Also, using the + Shadow Framebuffer (a copy of the video framebuffer is kept in main + memory) does not appear to fix the problem. + + If no one is sitting at the workstation and you just want to remotely + switch the VT over to the one associated with your X session (so + x11vnc can poll it correctly), one can use the chvt(1) command, e.g. + "chvt 7" for VT #7. + + + Q-108: I am using x11vnc where my local machine has "popup/hidden + taskbars" and the remote display where x11vnc runs also has + "popup/hidden taskbars" and they interfere and fight with each other. + What can I do? + + When you move the mouse to the edge of the screen where the popups + happen, the taskbars interfere with each other in strange ways. This + sometimes happens where the local machine is GNOME or Mac OS X and the + remote machine is GNOME. Is there a way to temporarily disable one or + both of these magic desktop taskbars? + + One x11vnc user suggests: it should be straightforward to right mouse + click on the task bar panel, and uncheck "enable auto-hide" from the + panel properties dialog box. This will make the panel always visible. + + Q-109: Help! x11vnc and my KDE screensaver keep switching each other + on and off every few seconds. + + This is a new (Jul/2006) problem seen, say, on the version of KDE that + is shipped with SuSE 10.1. It is not yet clear what is causing this... + If you move the mouse through x11vnc the screensaver shuts off like it + should but then a second or two after you stop moving the mouse the + screensaver snaps back on. + + This may be a bug in kdesktop_lock. For now the only workaround is to + disable the screensaver. You can try using another one such as + straight xscreensaver (see the instructions here for how to disable + kdesktop_lock.) If you have more info on this or see it outside of KDE + please let us know. + + Update: It appears this is due to kdesktop_lock enabling the screen + saver when the Monitor is in DPMS low-power state (e.g. standby, + suspend, or off.) In Nov/2006 the x11vnc -nodpms option was added as a + workaround. Normally it is a good thing that the monitor powers down + (since x11vnc can still poll the framebuffer in this state), but if + you experience the kdesktop_lock problem you can specify the "-nodpms" + option to keep the Monitor out of low power state while VNC clients + are connected. This is basically the same as typing "xset dpms force + on" periodically. (if you don't want to do these things just disable + the screensaver.) Feel free to file a bug against kdesktop_lock with + KDE. + + Q-110: I am running the beryl 3D window manager (or compiz, MythTv, + Google Earth, or some other OpenGL app) and I do not get screen + updates in x11vnc. + + This appears to be because the 3D OpenGL/GLX hardware screen updates + do not get reported via the XDAMAGE mechanism. So this is a bug in + beryl/compiz or XDAMAGE/Xorg or the (possibly 3rd party) video card + driver. + + As a workaround apply the -noxdamage option. As of Feb/2007 x11vnc + will try to autodetect the problem and disable XDAMAGE if is appears + to be missing a lot of updates. But if you know you are using beryl + you might as well always supply -noxdamage. Thanks to this user who + reported the problem and discovered the workaround. + + A developer for MiniMyth reports that the 'alphapulse' tag of the + theme G.A.N.T. can also cause problems, and should be avoided when + using VNC. + + Please report a bug or complaint to Beryl/Compiz and/or Xorg about + this: running x11vnc with -noxdamage disables a nice improvement in + responsiveness (especially for typing) and also leads to unnecessary + CPU and memory I/O load due to the extra polling. + + Q-111: Can I use x11vnc to view my VMWare session remotely? + + Yes, since VMWare usually runs as an X application you can view it via + x11vnc in the normal way. + + Note that VMWare has several viewing modes: + * Normal X application window (with window manager frame) + * Quick-Switch mode (with no window manager frame) + * Fullscreen mode + + The way VMWare does Fullscreen mode on Linux is to display the Guest + desktop in a separate Virtual Terminal (e.g. VT 8) (see this FAQ on + VT's for background.) Unfortunately, this Fullscreen VT is not an X + server. So x11vnc cannot access it (however, see this discussion of + -rawfb for a possible workaround.) x11vnc works fine with "Normal X + application window" and "Quick-Switch mode" because these use X. + + Update: It appears the in VMWare 5.x the Fullscreen mode is X, so + x11vnc access does work. + + One user reports he left his machine with VMWare in the Fullscreen + mode, and even though his X session wasn't in the active VT, he could + still connect x11vnc to the X session and pass the keystrokes Ctrl-Alt + (typing "blind") to the VMWare X app. This induced VMWare to switch + out of Fullscreen into Normal X mode and he could continue working in + the Guest desktop remotely. + + + Aside: Sometimes it is convenient (for performance, etc.) to start + VMWare in its own X session using startx(1). This can be used to have + a minimal window manger (e.g. twm or even no window manager), to + improve response. One can also cut the display depth (e.g. to 16bpp) + in this 2nd X session to improve video performance. This 2nd X session + emulates Fullscreen mode to some degree and can be viewed via x11vnc + as long as the VMWare X session is in the active VT. + + Also note that with a little bit of playing with "xwininfo -all + -children" output one can extract the (non-toplevel) window-id of the + of the Guest desktop only when VMWare is running as a normal X + application. Then one can export just the guest desktop (i.e. without + the VMWare menu buttons) by use of the -id windowid option. The + caveats are the X session VMWare is in must be in the active VT and + the window must be fully visible, so this mode is not terribly + convenient, but could be useful in some circumstances (e.g. running + VMWare on a very powerful server machine in a server room that happens + to have a video card, (but need not have a monitor, Keyboard or + mouse).) + + + + [Exporting non-X11 devices via VNC] + + Q-112: Can non-X devices (e.g. a raw framebuffer) be viewed (and even + controlled) via VNC with x11vnc? + + As of Apr/2005 there is support for this. Two options were added: + "-rawfb string" (to indicate the raw frame buffer device, file, etc. + and its parameters) and "-pipeinput command" (to provide an external + program that will inject or otherwise process mouse and keystroke + input.) Some useful -pipeinput schemes, VID, CONSOLE, and UINPUT, have + since been built into x11vnc for convenience. + + This non-X mode for x11vnc is somewhat experimental because it is so + removed in scope from the intended usage of the tool. Incomplete + attempt is made to make all of the other options consistent with non-X + framebuffer polling. So all of the X-related options (e.g. + -add_keysyms, -xkb) are just ignored or may cause an error if used. Be + careful applying such an option via remote control. + + The format for the -rawfb string is: + -rawfb :@xx[-][://][+] + + There are also some useful aliases (e.g. "console".) Some examples: + -rawfb shm:210337933@800x600x32:ff/ff00/ff0000 + + -rawfb map:/dev/fb0@1024x768x16 + + -rawfb map:/tmp/Xvfb_screen0@640x480x8+3232 + + -rawfb file:/tmp/my.pnm@250x200x24+37 + + -rawfb file:/dev/urandom@128x128x8 + + -rawfb snap:/dev/video0@320x240x24 -24to32 + + -rawfb console + + -rawfb vt2 + + -rawfb video + + -rawfb setup:mycmd.sh + + So the type can be "shm" for shared memory objects, and "map" or + "file" for file objects. "map" uses mmap(2) to map the file into + memory and is preferred over "file" (that uses the slower lseek(2) + access method.) Only use file if map isn't working. BTW, "mmap" is an + alias for "map" and if you do not supply a type and the file exists, + map is assumed (see the -help output and below for some exceptions to + this.) The "snap:" setting applies the -snapfb option with "file:" + type reading (this is useful for exporting webcams or TV tuner video; + see the next FAQ for more info.) + + Also, if the string is of the form "setup:cmd" then cmd is run and the + first line of its output retrieved and used as the rawfb string. This + allows initializing the device, determining WxHxB, etc. + + The object will be the numerical shared memory id for the case of shm. + The idea here is some other program has created this shared memory + segment and periodically updates it with new framebuffer data. x11vnc + polls the area for changes. See shmat(2) and ipcs(8) for more info. + The ipcs command will list current shared memory segments on the + system. Sometimes you can snoop on a program's framebuffer it did not + expect you would be polling! + + The object will be the path to the regular or character special file + for the cases of map and file. The idea here is that in the case of a + regular file some other program is writing/updating framebuffer image + data to it. In the case of a character special (e.g. /dev/fb0) it is + the kernel that is "updating" the framebuffer data. + + In most cases x11vnc needs to be told the width, height, and number of + bits per pixel (bpp) of the framebuffer. This is the @WxHxB field. For + the case of the Linux framebuffer device, /dev/fb0, the fbset(8) may + be of use (but may not always be accurate for what is currently + viewable.) In general some guessing may be required, especially for + the bpp. Update: in "-rawfb console" mode x11vnc will use the linuxfb + API to try to guess (it is still not always accurate.) Also try + "-rawfb vtN" (on x11vnc 0.9.7 and later) for the N-th Linux text + console (aka virtual terminal.) If the number of Bytes Per Line is not + WxHxB/8 (i.e. the framebuffer lines are padded) you can specify this + information after WxHxB via "-BPL", e.g. @800x600x16-2048 + + Based on the bpp x11vnc will try to guess the red, green, and blue + masks (these indicate which bits correspond to each color.) It if gets + it wrong you can specify them manually via the optional ":R/G/B" + field. E.g. ":0xff0000/0x00ff00/0x0000ff" (this is the default for + 32bpp.) + + Finally, the framebuffer may not begin at the beginning of the memory + object, so use the optional "+offset" parameter to indicate where the + framebuffer information starts. So as an example, the Xvfb virtual + framebuffer has options -shmem and -fbdir for exporting its virtual + screen to either shm or a mapped file. The format of these is XWD and + so the initial header should be skipped. BTW, since XWD is not + strictly RGB the view will only be approximate, but usable. Of course + for the case of Xvfb x11vnc can poll it much better via the X API, but + you get the idea. + + By default in -rawfb mode x11vnc will actually close any X display it + happened to open. This is basically to shake out bugs (e.g it will + crash rather than mysteriously interacting with the X display.) If you + want x11vnc to keep the X display open while polling the raw + framebuffer prefix a "+" sign at the beginning of the string (e.g. + +file:/dev/urandom@64x64x8) This could be convenient for keeping the + remote control channel active (it uses X properties.) The "-connect + /path/to/file" mechanism could also be used for remote control to + avoid the X property channel. Rare usage, but if you also supply + -noviewonly in this "+" mode then the mouse and keyboard input are + still sent to the X display, presumably for doing something amusing + with /dev/fb... + + Interesting Devices:. Here are some aliases for interesting device + files that can be polled via -rawfb: + -rawfb console /dev/fb0 Linux Console + -rawfb vt2 /dev/vcsa2 Linux Console (e.g. virtual ter +minal #2) + -rawfb video /dev/video0 Video4Linux Capture device + -rawfb rand /dev/urandom Random Bytes + -rawfb null /dev/zero Zero Bytes (black screen) + + The Linux console, /dev/fb0, etc needs to have its driver enabled in + the kernel. Some of the drivers are video card specific and + accelerated. The console is either the Text consoles (usually + tty1-tty6), or X graphical display (usually starting at tty7.) In + addition to the text console other graphical ones may be viewed and + interacted with as well, e.g. DirectFB or SVGAlib apps, VMWare non-X + fullscreen, or Qt-embedded apps (PDAs/Handhelds.) By default the + pipeinput mechanisms UINPUT and CONSOLE (keystrokes only) are + automatically attempted in this mode under "-rawfb console". + + The Video4Linux Capture device, /dev/video0, etc is either a Webcam or + a TV capture device and needs to have its driver enabled in the + kernel. See this FAQ for details. If specified via "-rawfb Video" then + the pipeinput method "VID" is applied (it lets you change video + parameters dynamically via keystrokes.) + + The last two, /dev/urandom and /dev/zero are just for fun, but are + also useful in testing. + + + All of the above -rawfb options are just for viewing the raw + framebuffer (although some of the aliases do imply keystroke and mouse + pipeinput methods.) That may be enough for certain applications of + this feature (e.g. suppose a video camera mapped its framebuffer into + memory and you just wanted to look at it via VNC.) + To handle the pointer and keyboard input from the viewer users the + "-pipeinput cmd" option was added to indicate a helper program to + process the user input. The input is streamed to it and looks + something like this: + Pointer 1 205 257 0 None + Pointer 1 198 253 0 None + Pointer 1 198 253 1 ButtonPress-1 + Pointer 1 198 253 0 ButtonRelease-1 + Pointer 1 198 252 0 None + Keysym 1 1 119 w KeyPress + Keysym 1 0 119 w KeyRelease + Keysym 1 1 65288 BackSpace KeyPress + Keysym 1 0 65288 BackSpace KeyRelease + Keysym 1 1 112 p KeyPress + Keysym 1 0 112 p KeyRelease + + Run "-pipeinput tee:/bin/cat" to get a description of the format. Note + that the -pipeinput option is independent of -rawfb mode and so may + have some other interesting uses. The "tee:" prefix means x11vnc will + both process the user input and pipe it to the command. The default is + to just pipe it to the -pipeinput command. + + Note the -pipeinput helper program could actually control the raw + framebuffer. In the libvncserver CVS a simple example program + x11vnc/misc/slide.pl is provided that demonstrates a simple jpeg + "slideshow" application. Also the builtin "-pipeinput VID" mode does + this for webcams and TV capture devices (/dev/video0.) + + The -pipeinput program is run with these environment variables set: + X11VNC_PID, X11VNC_PROG, X11VNC_CMDLINE, X11VNC_RAWFB_STR to aid its + knowing what is up. + + Another example provided in libvncserver CVS is a script to inject + keystrokes into the Linux console (e.g. the virtual consoles: + /dev/tty1, /dev/tty2, etc) in x11vnc/misc/vcinject.pl. It is based on + the vncterm/LinuxVNC.c program also in the libvncserver CVS. So to + view and interact with VT #2 (assuming it is the active VT) one can + run something like: + x11vnc -rawfb map:/dev/fb0@1024x768x16 -pipeinput './vcinject.pl 2' + + This assumes your Linux framebuffer device (/dev/fb0) is properly + configured. See fbset(8) and other documentation. Try + "file:/dev/fb0@WxHxB" as a last resort. Starting with x11vnc 0.8.1, + the above VT injection is built in, as well as WxHxB determination. + Just use something like: + x11vnc -rawfb console + + this will try to guess the active virtual console (via /dev/tty0) and + also the /dev/fb0 WxHxB and rgb masks automatically. Use, e.g., + "-rawfb console3" to force the VT number. This input method can be + used generally via "-pipeinput CONSOLE". Also starting with x11vnc + 0.8.2 the "-pipeinput UINPUT" mode is tried first (it does both + keyboard and mouse input) and then falls back to CONSOLE mode if it is + not available. Here is the -help output for this mode: + + If the rawfb string begins with "console" the framebuffer device + /dev/fb0 is opened (this requires the appropriate kernel modules to + be installed) and so is /dev/tty0. The latter is used to inject + keystrokes (not all are supported, but the basic ones are.) You + will need to be root to inject keystrokes. /dev/tty0 refers to the + active VT, to indicate one explicitly, use "console2", etc. using + the VT number. + + If the Linux version seems to be 2.6 or later and the "uinput" + module appears to be present, then the uinput method will be used + instead of /dev/ttyN. uinput allows insertion of BOTH keystrokes + and mouse input and so it preferred when accessing graphical (e.g. + Qt-embedded) linux console apps. See -pipeinput UINPUT below for + more information on this mode (you may want to also use the + -nodragging and -cursor none options.) Use "console0", etc or + -pipeinput CONSOLE to force the /dev/ttyN method. + + Note you can change VT remotely using the chvt(1) command. + Sometimes switching out and back corrects the framebuffer state. + + To skip input injecting entirely use "consolex". + + The string "/dev/fb0" (1, etc) can be used instead of "console". + This can be used to specify a different framebuffer device, e.g. + /dev/fb1. As a shortcut the "/dev/" can be dropped. If the name is + something nonstandard, use "console:/dev/foofb" + + If you do not want x11vnc to guess the framebuffer's WxHxB and + masks automatically (sometimes the kernel gives inaccurate + information), specify them with a @WxHxB at the end of the string. + + The above is just an example of what can be done. Note that if you + really want to view and interact with the Linux Text console it is + better to use the more accurate and faster LinuxVNC program. The + advantage x11vnc -rawfb might have is that it can allow interaction + with a non-text application, e.g. one based on SVGAlib or Qt-embedded + Also, for example the VMWare Fullscreen mode is actually viewable + under -rawfb and can be interacted with if uinput is enabled. + + If the Linux uinput driver is available then full keystroke and mouse + input into the Linux console can be performed. You may be able to + enable uinput via commands like these: + modprobe uinput + mknod /dev/input/uinput c 10 223 + + The -rawfb and -pipeinput features are intended to help one creatively + "get out of a jam" (say on a legacy or embedded device) where X is + absent or doesn't work properly. Feedback and bug reports are welcome. + For more control and less overhead use libvncserver in your own C + program that passes the framebuffer to libvncserver. + + + Q-113: Can I export the Linux Console (Virtual Terminals) via VNC + using x11vnc? + + Yes, you may need to be root to access the devices that make up the + linux console. + + To access the active Linux console via the computer's framebuffer try + something like: + x11vnc -rawfb console + x11vnc -rawfb console2 + + These will try to access the framebuffer through /dev/fb (or /dev/fb0, + etc.) and if it succeeds it will show any text or graphics that is + currently displayed. Keystrokes will be injected via the device + /dev/tty0 (to force an explicit virtual terminal append a number, e.g. + "console2" to select /dev/tty2.) + + If your Linux system does not have a framebuffer device (/dev/fb) you + can get one by adding, e.g., vga=0x31B boot parameter. This enables + the VGA framebuffer device at 1280x1024x24. 0x317 gives 1024x768x16, + etc. You can also enable a Linux framebuffer device by modprobing a + framebuffer driver specific to your video card. + + Note that this "-rawfb console" mode shows the contents of the + hardware framebuffer, and so will show whatever is on the screen. It + has no concept of Virtual Terminals WRT what there is to view, it + always shows the active virtual terminal. + + Another mode is specific to the Linux text Virtual Terminals, it shows + their text and colors (but no graphics) regardless of whether it is + the active VT or not. It is available on x11vnc 0.9.7 and later. + Enable this mode like this: + x11vnc -rawfb vt + x11vnc -rawfb vt2 + + The former will select the active one, the latter the 2nd VT. x11vnc + implements this mode by opening the current console text file + "/dev/vcsa2" instead of "/dev/fb". In this way it provides the basic + functionality of the LibVNCServer LinuxVNC program. + + The vt mode can be a useful way to try to get a machine's X server + working remotely, e.g. you edit /etc/X11/xorg.conf and then type + startx (or similar, e.g. gdm) in the virtual terminal. A 2nd x11vnc + could be used to see if the X server is now working correctly. + + Q-114: Can I export via VNC a Webcam or TV tuner framebuffer using + x11vnc? + + Yes, this is possible to some degree with the -rawfb option. There is + no X11 involved: snapshots from the video capture device are used for + the screen image data. See the previous FAQ on -rawfb for background. + For best results, use x11vnc version 0.8.1 or later. + + Roughly, one would do something like this: + x11vnc -rawfb snap:/dev/video@320x240x32 + + This requires that the system allows simple read(2) access to the + video device. This is true for video4Linux on Linux kernel 2.6 and + later (it won't work for 2.4, you'll need a separate program to + snapshot to a file that you point -rawfb to; ask me if it is not clear + what to do.) + + The "snap:" enforces -snapfb mode which appears to be necessary. The + read pointer for video capture devices cannot be repositioned (which + would be needed for scanline polling), but you can read a full frame + of data from the device. + + On Linux, if the Video4Linux API is present or the v4l-info(1) program + (related to xawtv) exists in in PATH, then x11vnc can be instructed to + try it to determine the -rawfb WxHxB parameters for you automatically. + In this case one would just type: + x11vnc -rawfb video + + or "-rawfb video1" for the 2nd video device, etc. + + x11vnc has also been extended to use the Video4Linux API over v4l-info + if it is available at build time. This enables setting parameters + (e.g. size and brightness) via x11vnc. See the description below. + Without Video4Linux you will need to initialize the settings of the + video device using something like xawtv or spcaview (and then hope the + settings persist until x11vnc reopens the device.) + + Many video4linux drivers tend to set the framebuffer to be 24bpp (as + opposed to 32bpp.) Since this can cause problems with VNC viewers, + etc, the -24to32 option will be automatically imposed when in 24bpp. + + Note that by its very nature, video capture involves rapid change in + the framebuffer. This is especially true for cameras where slight + wavering in brightness is always happening. This can lead to much + network bandwidth consumption for the VNC traffic and also local CPU + and I/O resource usage. You may want to experiment with "dialing down" + the framerate via the -wait, -slow_fb, or -defer options. Decreasing + the window size and bpp also helps. + + + Setting Camera/Tuner parameters via x11vnc: + + There is also some support for setting parameters of the capture + device. This is done via "-rawfb video:". This could be + useful for unattended startup at boottime, etc. Here is the -help + description: + + A more sophisticated video device scheme allows initializing the + device's settings using: + + -rawfb video: + + The prefix could also be, as above, e.g. "video1:" to specify the + device file. The v4l API must be available for this to work. + Otherwise, you will need to try to initialize the device with an + external program, e.g. xawtv, spcaview, and hope they persist when + x11vnc re-opens the device. + + is a comma separated list of key=value pairs. The + device's brightness, color, contrast, and hue can be set to + percentages, e.g. br=80,co=50,cn=44,hu=60. + + The device filename can be set too if needed (if it does not start + with "video"), e.g. fn=/dev/qcam. + + The width, height and bpp of the framebuffer can be set via, e.g., + w=160,h=120,bpp=16. + + Related to the bpp above, the pixel format can be set via the + fmt=XXX, where XXX can be one of: GREY, HI240, RGB555, RGB565, + RGB24, and RGB32 (with bpp 8, 8, 16, 16, 24, and 32 respectively.) + See http://www.linuxtv.org for more info (V4L api.) + + For TV/rf tuner cards one can set the tuning mode via tun=XXX where + XXX can be one of PAL, NTSC, SECAM, or AUTO. + + One can switch the input channel by the inp=XXX setting, where XXX + is the name of the input channel (Television, Composite1, S-Video, + etc.) Use the name that is in the information about the device that + is printed at startup. + + For input channels with tuners (e.g. Television) one can change + which station is selected by the sta=XXX setting. XXX is the + station number. Currently only the ntsc-cable-us (US cable) + channels are built into x11vnc. See the -freqtab option below to + supply one from xawtv. If XXX is greater than 500, then it is + interpreted as a raw frequency in KHz. + + Example: + + -rawfb video:br=80,w=320,h=240,fmt=RGB32,tun=NTSC,sta=47 + + one might need to add inp=Television too for the input channel to + be TV if the card doesn't come up by default in that one. + + Note that not all video capture devices will support all of the + above settings. + + See the -pipeinput VID option below for a way to control the + settings through the VNC Viewer via keystrokes. + + As above, if you specify a "@WxHxB..." after the string + they are used verbatim: the device is not queried for the current + values. Otherwise the device will be queried. + + Also, if you supply the "-pipeinput VID" (or use "-rawfb Video") + option you can control the settings to some degree via keystroke + mappings, e.g. B to increase the brightness or Up arrow to change the + TV station: + + For "-pipeinput VID" and you are using the -rawfb for a video + capture device, then an internal list of keyboard mappings is used + to set parameters of the video. The mappings are: + + "B" and "b" adjust the brightness up and down. + "H" and "h" adjust the hue. + "C" and "c" adjust the colour. + "N" and "n" adjust the contrast. + "S" and "s" adjust the size of the capture screen. + "I" and "i" cycle through input channels. + Up and Down arrows adjust the station (if a tuner) + F1, F2, ..., F6 will switch the video capture pixel + format to HI240, RGB565, RGB24, RGB32, RGB555, and + GREY respectively. See -rawfb video for details. + + See also the -freqtab option to supply your own xawtv channel to + frequency mappings for your country (only ntsc-cable-us is built into + x11vnc.) + + + Q-115: Can I connect via VNC to a Qt-embedded/Qtopia application + running on my handheld or PC using the Linux console framebuffer (i.e. + not X11)? + + Yes, the basic method for this is the -rawfb scheme where the Linux + console framebuffer (usually /dev/fb0) is polled and the uinput driver + is used to inject keystrokes and mouse input. Often you will just have + to type: + x11vnc -rawfb console + + (you may need to enable the uinput driver on the system via "modprobe + uinput; mknod /dev/input/uinput c 10 223") If this does not find the + correct frame buffer properties figure them out or guess them and use + something like: + x11vnc -rawfb /dev/fb0@640x480x16 + + Also, to force usage of the uinput injection method use "-pipeinput + UINPUT". See the -pipeinput description for tunable parameters, etc. + + One problem with the x11vnc uinput scheme is that it cannot guess the + mouse motion "acceleration" used by the windowing application (e.g. + QWS or X11.) For X11 and Qt-embedded the acceleration is usually 2 + (i.e. a dx of 1 from the mouse yields a 2 pixel displacement of the + mouse cursor.) The default x11vnc uses is 2, since that is often used. + However for one Qt-embedded system we needed to do: + x11vnc -rawfb console -pipeinput UINPUT:accel=4.0 + + to get reasonable positioning of the mouse. + + Even with the correct acceleration setting there is still some drift + (probably because of the mouse threshold where the acceleration kicks + in) and so x11vnc needs to reposition the cursor from 0,0 about 5 + times a second. See the -pipeinput UINPUT option for tuning parameters + that can be set (there are some experimental thresh=N tuning + parameters as well) + + Currently, one can expect mouse input to be a little flakey. All in + all, the Linux framebuffer input mechanism for Qt-embedded framebuffer + apps is not perfect, but it is usable. + + If you need to create a smaller x11vnc binary for a handheld + environment be sure to run strip(1) on it and also consider + configuring with, e.g. "env CPPFLAGS='-DSMALL_FOOTPRINT=1' ./configure + ..." to remove rarely used features and large texts (use 2 or 3 + instead of 1 to remove more.) Currently (Jul/2006) this can lower the + size of the x11vnc from 1.1MB to 0.6-0.7MB. + + The x11vnc uinput method applies to nearly anything on the Linux + framebuffer console, not just Qt-embedded/Qtopia. DirectFB, SDL using + fbcon driver, SVGAlib applications can also be viewed and interacted + with. Even a Linux X session can be viewed and interacted with without + using X11 (and x11vnc does not have to terminate when the X server + restarts!) The Linux Text consoles (F1-F6) also work. + + Note that Qt-embedded supplies its own VNC graphics driver, but it + cannot do both the Linux console framebuffer and VNC at the same time, + which is often what is desired from VNC. + + Update: We are finding some setups like Qtopia on the IPAQ do not + allow mouse input via uinput. Please help us debug this problem by + trying x11vnc on your device and letting us know what does and does + not work. + + + Q-116: Now that non-X11 devices can be exported via VNC using x11vnc, + can I build it with no dependencies on X11 header files and libraries? + + Yes, as of Jul/2006 x11vnc enables building for -rawfb only support. + Just do something like when building: + ./configure --without-x (plus any other flags) + make + + You can then test via "ldd x11vnc" that the binary does not depend on + libX11.so, etc. See the previous FAQ's for non-X11 framebuffer usage. + If you use this for an interesting non-X11 application please let us + know what you did. + + + Q-117: Does x11vnc support Mac OS X Aqua/Quartz displays natively + (i.e. no X11 involved)? + + Yes, since Nov/2006 in the development tree (x11vnc-0.8.4 tarball) + there is support for native Mac OS X Aqua/Quartz displays using the + -rawfb mechanism described above. The mouse and keyboard input is + achieved via Mac OS X API's. + + So you can use x11vnc as an alternative to OSXvnc (aka Vine Server), + or Apple Remote Desktop (ARD). Perhaps there is some x11vnc feature + you'd like to use on Mac OS X, etc. For a number of activities (e.g. + window drags) it seems to be faster than OSXvnc. + + Notes: + + X11: x11vnc will also work (as it has for years) with a X11 server + (XDarwin) running on Mac OS X (people often install this software to + display remote X11 apps on their Mac OS X system, or use some old + favorites locally such as xterm.) However in this case x11vnc will + only work reasonably in single window -id windowid mode (and the + window may need to have mouse focus.) + + If you do not have the DISPLAY env. variable set, x11vnc will assume + native Aqua/Quartz on Mac OS X, however if DISPLAY is set it will + assume an X11 connection. Use "-rawfb console" to force the native + display (or unset DISPLAY.) + + Update: Leopard sets DISPLAY by default in all sessions. Since it + starts with the string "/tmp/" x11vnc will use that to know if it + should ignore it. Use "-display :0.0" to force it. + + Building: If you don't have the X11 build and runtime packages + installed you will need to build it like this: + (cd to the e.g. x11vnc-0.9, source directory) + ./configure --without-x + make + + Win2VNC/x2vnc: One handy use is to use the -nofb mode to redirect + mouse and keyboard input to a nearby Mac (i.e. one to the side of your + desk) via x2vnc or Win2VNC. See this FAQ for more info. + + Options: Here are the Mac OS X specific x11vnc options: + -macnodim For the native Mac OS X server, disable dimming. + -macnosleep For the native Mac OS X server, disable display sleep +. + -macnosaver For the native Mac OS X server, disable screensaver. + -macnowait For the native Mac OS X server, do not wait for the + user to switch back to his display. + -macwheel n For the native Mac OS X server, set the mouse wheel + speed to n (default 5.) + -macnoswap For the native Mac OS X server, do not swap mouse + buttons 2 and 3. + -macnoresize For the native Mac OS X server, do not resize or rese +t + the framebuffer even if it is detected that the scree +n + resolution or depth has changed. + -maciconanim n For the native Mac OS X server, set n to the number + of milliseconds that the window iconify/deiconify + animation takes. In -ncache mode this value will be + used to skip the animation if possible. (default 400) + -macmenu For the native Mac OS X server, in -ncache client-sid +e + caching mode, try to cache pull down menus (not perfe +ct + because they have animated fades, etc.) + + PasteBoard/Clipboard: There is a bug that the Clipboard (called + PasteBoard on Mac it appears) exchange will not take place unless + x11vnc was started from inside the Aqua display (e.g. started inside a + Terminal app window.) Otherwise it cannot connect to the PasteBoard + server. So Clipboard exchange won't work for our standard "ssh in" + startup scheme. + + Hopefully this deficiency can be removed, but until then for Clipboard + exchange to work you will need to start x11vnc inside the desktop + session (i.e. either start it running before you leave, or start up a + 2nd x11vnc inside from a 1st one started outside, or use the apple + script below) + + Here also is a osascript trick that seems to work (it opens the + Terminal app and instructs it to start x11vnc): + +#!/bin/sh +# +# start_x11vnc: start x11vnc in a Terminal window +# (this will allow Clipboard/Pasteboard exchange to work) + +tmp=/tmp/start_x11vnc.$$ + +cat > $tmp < vncviewer -listen + client2> vncviewer -listen + client3> vncviewer -listen + ... + client64> vncviewer -listen + + (e.g. client1> is the cmdline prompt on machine client1 ... etc) and + all the repeaters R are started like this: + repeater1> x11vnc -reflect listen -connect client1,client2,...client8 + repeater2> x11vnc -reflect listen -connect client9,client10,...client16 + ... + repeater8> x11vnc -reflect listen -connect client57,client58,...client64 + + and finally the main server is started to kick the whole thing into + motion: + vncserver> x11vnc -display :0 -connect repeater1,repeater2,...repeater8 + + (or instruct a non-x11vnc VNC server to reverse connect to the + repeaters.) For a classroom broadcasting setup one might have the + first two sets of commands start automatically at bootup or when + someone logs in, and then start everything up with the S server. One + may even be able to script the forward connection bootstrap case, let + us know what you did. A really nice thing would be some sort of + auto-discovery of your repeater, etc... + + Q-119: Can x11vnc be used during a Linux, Solaris, etc. system + Installation so the Installation can be done remotely? + + This can be done, but it doesn't always work because it depends on how + the OS does its install. We have to "sneak in" somehow. Note that some + OS's have a remote install (ssh etc.) built in and so you might want + to use that instead. + + Usually the OS install will have to be a network-install in order to + have networking up during the install. Otherwise, you may have a + (slim) chance to configure the networking manually (ifconfig(8) and + route(8).) + + To avoid library dependencies problems in the typical minimal (e.g. + busybox) installation OS it is a good idea to build a statically + linked x11vnc binary. A way that often works is to do a normal build + and then paste the final x11vnc link line into a shell script. Then + change the "gcc" to "gcc -static" and run the shell script. You may + need to disable features (e.g. "--without-xfixes") if there is not a + static library for the feature available. You may also need to add + extra link options (e.g. "-lXrender") to complete library dependencies + manually. + + Let's call the binary x11vnc.static. Place it on a webserver + somewhere. It may be possible to retrieve it via scp(1) too. + + During the install you need to get a shell to retreive x11vnc.static + and run it. + + If the Solaris install is an older X-based one, there will be a menu + for you to get a terminal window. From that window you might be able + to retrieve x11vnc.static via wget, scp, or ftp. Remember to do "chmod + 755 ./x11vnc.static" and then find the -auth file as in this FAQ. + + If it is a Linux install that uses an X server (e.g. SuSE and probably + Fedora), then you can often get a shell by pressing Ctrl-Alt-F2 or + similar. Then get the x11vnc binary via something like this: + cd /tmp + wget http://192.168.0.22/x11vnc.static + chmod 755 ./x11vnc.static + + Find the name of the auth file as in this FAQ. (maybe run "ps wwaux | + grep auth".) Then run it like this: + ./x11vnc.static -forever -nopw -display :0 -auth /tmp/wherever/the/authfile + + then press Alt-F7 to go back to the X install. You should now be able + to connect via a vnc viewer and continue the install. Watch out for + the display being :1, etc. + + If there is a firewall blocking incoming connections during the + install, use the "-connect hostname" option option for a reverse + connection to the hostname running the VNC viewer in listen mode. + + Debian based installs are either console-text or console-framebuffer + based. These are install (or expert) and installgui (or expertgui) + boot lines, respectively. For the console-text based installs you + probably need to add a boot cmd line option like vga=0x314 (which is + 800x600x16) to get the console-text to use the linux framebuffer + device properly. + + For a Debian console-text based install after the network is + configured press Ctrl-Alt-F2 to get a shell. Retrieve the binary via + wget as above and chmod 755 it. Then run it something like this: + sleep 10; ./x11vnc.static -forever -nopw -rawfb console + + then before the sleep is over press Alt-F1 to get back to the install + virtual console. You should be able to connect via a VNC viewer and + continue with the install. + + For a recent (2009) Debian install we booted with "expert vga=0x301" + and "expert vga=0x311" to get console text based installs at 640x480x8 + and 640x480x16, respectively (replace "expert" with "install" if you + like.) Otherwise it was giving a 16 color 640x480x4 (4 bit per pixel) + display which x11vnc could not handle. + + For Debian console-framebuffer GUI based installs (installgui or + expertgui) we have not be able to enter keystrokes or mouse motions. + This may be resolved if the install had the Linux kernel module + uinput, but it doesn't; one can wget uinput.ko and then run insmod on + it, but the module must match the installation kernel. So, failing + that, you can only do the GUI view-only, which can be handy to watch a + long network install from your desk instead of in front of the machine + being installed. For these, after the network is configured press + Ctrl-Alt-F2 to get a shell. Retrieve the binary via wget as above and + chmod 755 it. Then run it something like this: + sleep 10; ./x11vnc.static -forever -nopw -rawfb console + + then before the sleep is over press Alt-F5 to get back to the GUI + install console. You should be able to connect via a VNC viewer and + watch the install. + [Misc: Clipboard, File Transfer/Sharing, Printing, Sound, Beeps, + Thanks, etc.] + + Q-120: Does the Clipboard/Selection get transferred between the + vncviewer and the X display? + + As of Jan/2004 x11vnc supports the "CutText" part of the RFB (aka VNC) + protocol. When text is selected/copied in the X session that x11vnc is + polling it will be sent to connected VNC viewers. And when CutText is + received from a VNC viewer then x11vnc will set the X11 selections + PRIMARY, CLIPBOARD, and CUTBUFFER0 to it. x11vnc is able to hold the + PRIMARY and CLIPBOARD selections (Xvnc does not seem to do this.) + + The X11 selections can be confusing, especially to those coming from + Windows or MacOSX where there is just a single 'Clipboard'. The X11 + CLIPBOARD selection is a lot like that of Windows and MacOSX, e.g. + highlighted text is sent to the clipboard when the user activates + "Edit -> Copy" or presses "Control+C" (and pasting it via "Edit -> + Paste" or "Control+V".) The X11 PRIMARY selection has been described + as 'for power users' or 'an Easter Egg'. As soon as text is + highlighted it is set to the PRIMARY selection and so it is + immediately ready for pasting, usually via the Middle Mouse Button or + "Shift+Insert". See this jwz link for more information. + + x11vnc's default behavior is to watch both CLIPBOARD and PRIMARY and + whenever one of them changes, it sends the new text to connected + viewers. Note that since the RFB protocol only has a single "CutText" + then both selections are "merged" to some degree (and this can lead to + confusing results.) One user was confused why x11vnc was "forgetting" + his CLIPBOARD selection and the reason was he also changed PRIMARY + some time after he copied text to the clipboard. Usually an app will + set PRIMARY as soon as any text is highlighted so it easy to see how + CLIPBOARD was forgotten. Use the -noprimary described below as a + workaround. Similarly, by default when x11vnc receives CutText it sets + both CLIPBOARD and PRIMARY to it (this is probably less confusing, but + could possibly lead to some failure modes as well.) + + You may not like these defaults. Here are ways to change the behavior: + * If you don't want the Clipboard/Selection exchanged at all use the + -nosel option. + * If you want changes in PRIMARY to be ignored use the -noprimary + option. + * If you want changes in CLIPBOARD to be ignored use the + -noclipboard option. + * If you don't want x11vnc to set PRIMARY to the "CutText" received + from viewers use the -nosetprimary option. + * If you don't want x11vnc to set CLIPBOARD to the "CutText" + received from viewers use the -nosetclipboard option. + + You can also fine-tune it a bit with the -seldir dir option and also + -input. + + You may need to watch out for desktop utilities such as KDE's + "Klipper" that do odd things with the selection, clipboard, and + cutbuffers. + + + Q-121: Can I use x11vnc to record a Shock Wave Flash (or other format) + video of my desktop, e.g. to record a tutorial or demo? + + Yes, it is possible with a number of tools that record VNC and + transform it to swf format or others. One such popular tool is + pyvnc2swf. There are a number of tutorials (broken link?) on how to do + this. Another option is to use the vnc2mpg that comes in the + LibVNCServer package. + An important thing to remember when doing this is that tuning + parameters should be applied to x11vnc to speed up its polling for + this sort of application, e.g. "-wait 10 -defer 10". + + Q-122: Can I transfer files back and forth with x11vnc? + + As of Oct/2005 and May/2006 x11vnc enables, respectively, the TightVNC + and UltraVNC file transfer implementations that were added to + libvncserver. This currently works with TightVNC and UltraVNC viewers + (and Windows viewers only support filetransfer it appears... but they + do work to some degree under Wine on Linux.) + + The SSVNC Unix VNC viewer supports UltraVNC file transfer by use of a + Java helper program. + + TightVNC file transfer is off by default, if you want to enable it use + the -tightfilexfer option. + + UltraVNC file transfer is off by default, to enable it use something + like "-rfbversion 3.6 -permitfiletransfer" + options (UltraVNC incorrectly uses the RFB protocol version to + determine if its features are available, so x11vnc has to pretend to + be version 3.6.) As of Sep/2006 "-ultrafilexfer" is an alias for these + two options. Note that running as RFB version 3.6 may confuse other + VNC Viewers. + + Sadly you cannot do both -tightfilexfer and -ultrafilexfer at the same + time because the latter requires setting the version to 3.6 and + tightvnc will not do filetransfer when it sees that version number. + + Also, because of the way the LibVNCServer TightVNC file transfer is + implemented, you cannot do Tightvnc file transfer in -unixpw mode. + However, UltraVNC file transfer does work in -unixpw (but if a client + tries it do a filetransfer during the login process it will be + disconnected.) + + IMPORTANT: please understand if -ultrafilexfer or -tightfilexfer is + specified and you run x11vnc as root for, say, inetd or display + manager (gdm, kdm, ...) access and you do not have it switch users via + the -users option, then VNC Viewers that connect are able to do + filetransfer reads and writes as *root*. + + The UltraVNC and TightVNC settings can be toggled on and off inside + the gui or by -R remote control. However for TightVNC the changed + setting only applies for NEW clients, current clients retain their + TightVNC file transfer ability. For UltraVNC it works better, however + if an UltraVNC client has initiated a file transfer dialog it will + remain in effect until the dialog is closed. If you want to switch + between UltraVNC and TightVNC file transfer in the gui or by remote + control you will probably be foiled by the "-rfbversion 3.6" issue. + + + Q-123: Which UltraVNC extensions are supported? + + Some of them are supported. To get UltraVNC Viewers to attempt to use + these extensions you will need to supply this option to x11vnc: + -rfbversion 3.6 + + Or use -ultrafilexfer which is an alias for the above option and + "-permitfiletransfer". UltraVNC evidently treats any other RFB version + number as non-UltraVNC. + + Here are a list of the UltraVNC extensions supported by x11vnc: + * ServerInput: "Toggle Remote Input and Remote Blank Monitor" + * FileTransfer: "Open File Transfer..." + * SingleWindow: "Select Single Window..." + * TextChat: "Open Chat..." + * 1/n Server Scaling + * rfbEncodingUltra compression encoding + + The SSVNC Unix VNC viewer supports these UltraVNC extensions. + + To disable SingleWindow and ServerInput use -noultraext (the others + are managed by LibVNCServer.) See this option too: -noserverdpms. + + Also, the UltraVNC repeater proxy is supported for use with reverse + connections: "-connect repeater://host:port+ID:NNNN". Use it for both + plaintext and SSL connections. This mode can send any string before + switching to the VNC protocol, and so could be used with other + proxy/gateway tools. Also, a perl repeater implemention is here: + ultravnc_repeater.pl + + + Q-124: Can x11vnc emulate UltraVNC's Single Click helpdesk mode for + Unix? I.e. something very simple for a naive user to initiate a + reverse vnc connection from their Unix desktop to a helpdesk + operator's VNC Viewer. + + Yes, UltraVNC's Single Click (SC) mode can be emulated fairly well on + Unix. + + We use the term "helpdesk" below, but it could be any sort of remote + assistance you want to set up, e.g. something for Unix-using friends + or family to use. This includes Mac OS X. + + Assume you create a helpdesk directory "hd" on your website: + http://www.mysite.com/hd (any website that you can upload files to + should work, although remember the user will be running the programs + you place there.) + + In that "hd" subdirectory copy an x11vnc binary to be run on the Unix + user's machine (e.g. Linux, etc) and also create a file named "vnc" + containing the following: +#!/bin/sh + +webhost="http://www.mysite.com/hd" # Your helpdesk dir URL. + +vnchost="ip.someplace.net" # Your host running 'vncviewer -listen' + # It could also be your IP number. If it is + # a router/firewall, you will need to + # configure it to redirect port 5500 to you +r + # workstation running 'vncviewer -listen' + +dir=/tmp/vnc_helpdesk.$$ # Make a temporary working dir. +mkdir $dir || exit 1 +cd $dir || exit 1 + +trap "cd /tmp; rm -rf $dir" 0 2 15 # Cleans up on exit. + +wget $webhost/x11vnc # Fetch x11vnc binary. If multi- +chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc + # or similar. + +./x11vnc -connect_or_exit $vnchost -rfbport 0 -nopw + + with the hostnames / IP addresses customized to your case. + + On the helpdesk VNC viewer machine (ip.someplace.net in this example) + you have the helpdesk operator running VNC viewer in listen mode: + vncviewer -listen + + or if on Windows, etc. somehow have the VNC viewer be in "listen" + mode. + + Then, when the naive user needs assistance you instruct him to open up + a terminal window on his Unix desktop and paste the following into the + shell: + wget -qO - http://www.mysite.com/hd/vnc | sh - + + and then press Enter. You could have this instruction on a web page or + in an email you send him, etc. This requires that the wget is + installed on the user's Unix machine (he might only have curl or lynx, + see below for more info.) + + + So I guess this is about 3-4 clicks (start a terminal and paste) and + pressing "Enter" instead of "single click"... + + See this page for some variations on this method, e.g. how to add a + password, SSL Certificates, etc. + + + If you don't have a website (there are many free ones) or don't want + to use one you will have to email him all of the ingredients (x11vnc + binary and a launcher script) and tell him how to run it. This could + be easy or challenging depending on the skill of the naive unix + user... + + A bit of obscurity security could be put in with a -passwd, -rfbauth + options, etc. (note that x11vnc will require a password even for + reverse connections.) More info here. + + + Firewalls: If the helpdesk (you) with the vncviewer is behind a + NAT/Firewall/Router the router will have to be configured to redirect + a port (i.e. 5500 or maybe different one if you like) to the vncviewer + machine. If the vncviewer machine also has its own host-level + firewall, you will have to open up the port there as well. + + NAT-2-NAT: There is currently no way to go "NAT-2-NAT", i.e. both User + and Helpdesk workstations behind NAT'ing Firewall/Routers without + configuring a router to do a port redirection (i.e. on your side, the + HelpDesk.) To avoid modifying either firewall/router, one would need + some public (IP address reachable on the internet) redirection/proxy + service. Perhaps such a thing exists. http://sc.uvnc.com provides this + service for their UltraVNC Single Click users. + + Update: It may be possible to do "NAT-2-NAT" with a UDP tunnel such as + http://samy.pl/pwnat/. All that is required is that both NAT firewalls + allow in UDP packets from an IP address to which a UDP packet has + recently been sent to. If you try it out let us know how it went. + + + Very Naive Users: + + If it is beyond the user how to open a terminal window and paste in a + command (you have my condolences...) you would have to somehow setup + his Web browser to download the "vnc" file (or a script containing the + above wget line) and prompt the user if he wants to run it. This may + be tricky to set up (which is probably a good thing to not have the + web browser readily run arbitrary programs downloaded from the + internet...) + + One command-line free way, tested with KDE, is to name the file vnc.sh + and then instruct the user to right-click on the link and do "Save + Link As" to his Desktop. It will appear as an icon, probably one that + looks like a terminal or a command line prompt. He next should + right-click on the icon and select "Properties" and go to the + "Permissions" tab. Then in that dialog select the checkbox "Is + executable". He should then be able to click on the icon to launch it. + Another option is to right-click on the icon and select "Open With -> + Other ..." and for the name of the application type in "/bin/sh". + Unfortunately in both cases the command output is lost and so errors + cannot be debugged as easily. A similar thing appears to work in GNOME + if under "Properties -> Permissions" they click on "Execute" checkbox + for "Owner". Then when they click on the icon, they will get a dialog + where they can select "Run in Terminal". In general for such cases, if + it is feasible, it might be easier to ssh to his machine and set + things up yourself... + + + SSL Encrypted Helpdesk Connections: + + As of Apr/2007 x11vnc supports reverse connections in SSL and so we + can do this. On the Helpdesk side (Viewer) you will need STUNNEL or + better use the Enhanced TightVNC Viewer (SSVNC) package we provide + that automates all of the SSL for you. + + To do this create a file named "vncs" in the website "hd" directory + containing the following: +#!/bin/sh + +webhost="http://www.mysite.com/hd" # Your helpdesk dir URL. + +vnchost="ip.someplace.net" # Your host running 'vncviewer -listen' + # It could also be your IP number. If it is + # a router/firewall, you will need to + # configure it to redirect port 5500 to you +r + # workstation running 'vncviewer -listen' + +dir=/tmp/vnc_helpdesk.$$ # Make a temporary working dir. +mkdir $dir || exit 1 +cd $dir || exit 1 + +trap "cd /tmp; rm -rf $dir" 0 2 15 # Cleans up on exit. + +wget $webhost/x11vnc # Fetch x11vnc binary. If multi- +chmod 755 ./x11vnc # platform, use $webhost/`uname`/x11vnc + # or similar. + +./x11vnc -connect_or_exit $vnchost -rfbport 0 -nopw -ssl # Note -ssl option. + + with the hostnames or IP addresses customized to your case. + + The only change from the "vnc" above is the addition of the -ssl + option to x11vnc. This will create a temporary SSL cert: openssl(1) + will need to be installed on the user's end. A fixed SSL cert file + could be used to avoid this (and provide some authentication; more + info here.) + + The naive user will be doing this: + wget -qO - http://www.mysite.com/hd/vncs | sh - + + (or perhaps even use https:// if available.) + + But before that, the helpdesk operator needs to have "vncviewer + -listen" running as before, however he needs an SSL tunnel at his end. + The easiest way to do this is use Enhanced TightVNC Viewer (SSVNC). + Start it, and select Options -> 'Reverse VNC Connection (-listen)'. + Then UN-select 'Verify All Certs' (this can be enabled later if you + want; you'll need the x11vnc SSL certificate), and click 'Listen'. + + If you don't want to use SSVNC for the viewer, but rather set up + STUNNEL manually instead, make a file "stunnel.cfg" containing: +foreground = yes +pid = + +[vnc] +accept = 5500 +connect = localhost:5501 + + and run: + stunnel ./stunnel.cfg + + and then start the "vncviewer -listen 1" (i.e. 1 to correspond to the + 5501 port.) Note that this assumes the stunnel install created a + Server SSL cert+key, usually /etc/stunnel/stunnel.pem (not all distros + will do this.) Also, that file is by default only readable by root, so + stunnel needs to be run as root. If your system does not have a key + installed or you do not want to run stunnel as root (or change the + permissions on the file), you can use x11vnc to create one for you for + example: + x11vnc -sslGenCert server self:mystunnel + + answer the prompts with whatever you want; you can take the default + for all of them if you like. The openssl(1) package must be installed. + See this link and this one too for more info on SSL certs. This + creates $HOME/.vnc/certs/server-self:mystunnel.pem, then you would + change the "stunnel.cfg" to look something like: +foreground = yes +pid = +cert = /home/myusername/.vnc/certs/server-self:mystunnel.pem + +[vnc] +accept = 5500 +connect = localhost:5501 + + In any event, with stunnel having been setup, the naive user is + instructed to paste in and run: + wget -qO - http://www.mysite.com/hd/vncs | sh - + + to pick up the vncs script this time. + + Of course if a man-in-the-middle can alter what the user downloads + then all bets are off!. + + More SSL variations and info about certificates can be found here. + + + OpenSSL libssl.so.0.9.7 problems: + + If you build your own stunnel or x11vnc for deployment, you may want + to statically link libssl.a and libcrypto.a into it because Linux + distros are currently a bit of a mess regarding which version of + libssl is installed. + + You will find the details here. + + + Q-125: Can I (temporarily) mount my local (viewer-side) Windows/Samba + File share on the machine where x11vnc is running? + + You will have to use an external network redirection for this. + Filesystem mounting is not part of the VNC protocol. + + We show a simple Samba example here. + + First you will need a tunnel to redirect the SMB requests from the + remote machine to the one you sitting at. We use an ssh tunnel: + sitting-here> ssh -C -R 1139:localhost:139 far-away.east + + Or one could combine this with the VNC tunnel at the same time, e.g.: + sitting-here> ssh -C -R 1139:localhost:139 -t -L 5900:localhost:5900 far-away +.east 'x11vnc -localhost -display :0' + + Port 139 is the Windows Service port. For Windows systems instead of + Samba, you may need to use the actual IP address of the Window machine + instead of "localhost" in the -R option (since the Windows service + does not listen on localhost by default.) + + Note that we use 1139 instead of 139 on the remote side because 139 + would require root permission to listen on (and you may have a samba + server running on it already.) + + The ssh -C is to enable compression, which might speed up the data + transfers. + + Depending on the remote system side configuration, it may or may not + be possible to mount the SMB share as a non-root user. Try it first as + a non-root user and if that fails you will have to become root. + + We will assume the user name is "fred" and we will try to mount the + viewer-side Windows SMB share "//haystack/pub" in + /home/fred/smb-haystack-pub. + far-away> mkdir -p /home/fred/smb-haystack-pub + far-away> smbmount //haystack/pub /home/fred/smb-haystack-pub -o username=fre +d,ip=127.0.0.1,port=1139 + + (The 2nd command may need to be run as root.) Then run "df" or "ls -l + /home/fred/smb-haystack-pub" to see if it is mounted properly. Consult + the smbmount(8) and related documentation (it may require some + fiddling to get write permissions correct, etc.) To unmount: + far-away> smbumount /home/fred/smb-haystack-pub + + At some point we hope to fold some automation for SMB ssh redir setup + into the Enhanced TightVNC Viewer (SSVNC) package we provide (as of + Sep 2006 it is there for testing.) + + + Q-126: Can I redirect CUPS print jobs from the remote desktop where + x11vnc is running to a printer on my local (viewer-side) machine? + + You will have to use an external network redirection for this. + Printing is not part of the VNC protocol. + + We show a simple Unix to Unix CUPS example here. Non-CUPS port + redirections (e.g. LPD) should also be possible, but may be a bit more + tricky. If you are viewing on Windows SMB and don't have a local cups + server it may be trickier still (see below.) + + First you will need a tunnel to redirect the print requests from the + remote machine to the one you sitting at. We use an ssh tunnel: + sitting-here> ssh -C -R 6631:localhost:631 far-away.east + + Or one could combine this with the VNC tunnel at the same time, e.g.: + sitting-here> ssh -C -R 6631:localhost:631 -t -L 5900:localhost:5900 far-away +.east 'x11vnc -localhost -display :0' + + Port 631 is the default CUPS port. The above assumes you have a Cups + server running on your viewer machine (localhost:631), if not, use + something like my-cups-srv:631 (the viewer-side Cups server) in the -R + instead. + + Note that we use 6631 instead of 631 on the remote side because 631 + would require root permission to listen on (and you likely have a cups + server running on it already.) + + Now the tricky part: to get applications to notice your cups + server/printer on localhost:6631. + + If you have administrative privilege (i.e. root password) on the + x11vnc side where the desktop is running, it should be easy to add the + printer through some configuration utility (e.g. in KDE: Utilities -> + Printing -> Printing Manager, and then supply admin password, and then + Add Printer/Class, and then fill in the inquisitive wizard. Most + important is the "Remote IPP server" panel where you put in localhost + for Host and 6631 for Port.) The main setting you want to convey is + the host is localhost and the port is non-standard (e.g. 6631.) Some + configuration utilities will take an Internet Printing Protocol (IPP) + URI, e.g. http://localhost:6631/printers/, + ipp://localhost:6631/printers/printer-name, + ipp://localhost:6631/ipp/printer-name, etc. Check your CUPS + documentation and admin interfaces to find what the syntax is and what + the "printer name" is. + + If you do not have root or print admin privileges, but are running a + recent (version 1.2 or greater) of the Cups client software, then an + easy way to temporarily switch Cups servers is to create the directory + and file: $HOME/.cups/client.conf on the remote side with a line like: + ServerName localhost:6631 + + When not using x11vnc for remote access you can comment the above line + out with a '#' (or rename the client.conf file), to have normal cups + operation. + + Unfortunately, running applications may need to be restarted to notice + the new printers (libcups does not track changes in client.conf.) + Depending on circumstances, a running application may actually notice + the new printers without restarting (e.g. no print dialog has taken + place yet, or there are no CUPS printers configured on the remote + side.) + + Cups client software that is older (1.1) does not support appending + the port number, and for newer ones there is a bug preventing it from + always working (fixed in 1.2.3.) Kludges like these at the command + line will work: + far-away> env CUPS_SERVER=localhost IPP_PORT=6631 lpstat -p -d + far-away> env CUPS_SERVER=localhost IPP_PORT=6631 lpr -P myprinter file.ps + far-away> env CUPS_SERVER=localhost IPP_PORT=6631 firefox + + but are somewhat awkward since you have to retroactively set the env. + var IPP_PORT. Its value cannot be broadcast to already running apps + (like the $HOME/.cups/client.conf trick sometimes does.) A common + workaround for an already running app is to somehow get it to "Print + To File", e.g. file.ps and then use something like the lpr example + above. Also, the option "-h host:port" works with CUPS lp(1) and + lpr(1). + + You can also print to Windows shares printers in principle. You may do + this with the smbspool(8) command, or configure the remote CUPS via + lpadmin(8), etc, to use a printer URI something like + smb://machine:port/printer (this may have some name resolution + problems WRT localhost.) Also, as with SMB mounting, the port redir + (-R) to the Windows machine must use the actual IP address instead of + "localhost". + + At some point we hope to fold some automation for CUPS ssh redir setup + into the Enhanced TightVNC Viewer (SSVNC) package we provide (as of + Sep 2006 it is there for testing.) + + + Q-127: How can I hear the sound (audio) from the remote applications + on the desktop I am viewing via x11vnc? + + You will have to use an external network audio mechanism for this. + Audio is not part of the VNC protocol. + + We show a simple Unix to Unix esd example here (artsd should be + possible too, we have also verified the esd Windows port works for the + method described below.) + + First you will need a tunnel to redirect the audio from the remote + machine to the one you sitting at. We use an ssh tunnel: + sitting-here> ssh -C -R 16001:localhost:16001 far-away.east + + Or one could combine this with the VNC tunnel at the same time, e.g.: + sitting-here> ssh -C -R 16001:localhost:16001 -t -L 5900:localhost:5900 far-a +way.east 'x11vnc -localhost -display :0' + + Port 16001 is the default ESD uses. So when an application on the + remote desktop makes a sound it will connect to this tunnel and be + redirected to port 16001 on the local machine (sitting-here in this + example.) The -C option is an attempt to compress the audio a little + bit. + + So we next need a local (sitting-here) esd daemon running that will + receive those requests and play them on the local sound device: + sitting-here> esd -promiscuous -port 16001 -tcp -bind 127.0.0.1 + + See the esd(1) man page for the meaning of the options (the above are + not very secure.) (This method also works with the EsounD windows port + esd.exe) + + To test this sound tunnel, we use the esdplay program to play a simple + .wav file: + far-away> esdplay -s localhost:16001 im_so_happy.wav + + If you hear the sound (Captain Kirk in this example), that means you + are in great shape. + + To run individual audio applications you can use the esddsp(1) + command: + far-away> esddsp -s localhost:16001 xmms + + Then you could try playing some sounds inside xmms. You could also set + the environment variable ESPEAKER=localhost:16001 to not need to + supply the -s option all the time. (for reasons not clear, sometimes + esddsp can figure it out on its own.) All the script esddsp does is to + set ESPEAKER and LD_PRELOAD for you so that when the application opens + the sound device (usually /dev/dsp) its interactions with the device + will be intercepted and sent to the esd daemon running on sitting-here + (that in turn writes them to the real, local /dev/dsp.) + + Redirecting All sound: + + It does not seem to be possible to switch all of the sound of the + remote machine from its sound device to the above esd+ssh tunnel + without some preparation. But it can be done reasonably well if you + prepare (i.e. restart) the desktop with this in mind. + + Here is one way to redirect all sound. The idea is we run the entire + desktop with sound directed to localhost:16001. When we are sitting at + far-away.east we run "esd -promiscuous -port 16001 -tcp -bind + 127.0.0.1" on far-away.east (to be able to hear the sound.) However, + when we are sitting at sitting-here.west we kill that esd process and + run that same esd command on sitting-here.west and start up the above + ssh tunnel. This is a little awkward, but with some scripts one would + probably kill and restart the esd processes automatically when x11vnc + is used. + + So next we have to run the whole desktop pointing toward our esd. Here + is a simple way to test. Log in to the machine via the "FailSafe" + desktop. Then in the lone terminal type something like: + esddsp -s localhost:16001 gnome-session +or: + esddsp -s localhost:16001 startkde + + where the last part is whatever command starts your desktop (even + fvwm2.) This causes the environment variables ESPEAKER and LD_PRELOAD + to be set appropriately and every application (processes with the + desktop as an ancestor) will use them. If this scheme works well you + can make it less klunky by adding the command to your ~/.xsession, + etc. file that starts your default desktop. Or you may be able to + configure your desktop to use localhost:16001, or whatever is needed, + via a gui configuration panel. Some Notes: + * Not all audio applications are compatible with the esd and artsd + mechanisms, but many are. + * The audio is not compressed so you probably need a broadband or + faster connection. Listening to music may not be very pleasant... + (Although we found streaming music from across the US over cable + modem worked OK, but took 200 KB/sec, to use less bandwidth + consider something like "ssh far-away.east 'cat favorite.mp3' | + mpg123 -b 4000 -") + * Linux does not seem to have the concept of LD_PRELOAD_64 so if you + run on a mixed 64- and 32-bit ABI system (e.g. AMD x86_64) some of + the applications will fail to run because LD_PRELOAD will point to + libraries of the wrong wordsize. + * At some point we hope to fold some automation for esd or artsd ssh + redir setup into the Enhanced TightVNC Viewer (SSVNC) package we + provide (as of Sep/2006 it is there for testing.) + + + Q-128: Why don't I hear the "Beeps" in my X session (e.g. when typing + tput bel in an xterm)? + + As of Dec/2003 "Beep" XBell events are tracked by default. The X + server must support the XKEYBOARD extension (this is not on by default + in Solaris, see Xserver(1) for how to turn it on via +kb), and so you + won't hear them if the extension is not present. + + If you don't want to hear the beeps use the -nobell option. If you + want to hear the audio from the remote applications, consider trying a + redirector such as esd. + + + Q-129: Does x11vnc work with IPv6? + + Update: as of Apr/2010 in the 0.9.10 x11vnc development tarball, there + is now built-in support for IPv6 (128 bit internet addresses.) See the + -6 and -connect options for details. + + The remainder of this FAQ entry shows how to do with this with pre + 0.9.10 x11vnc using IPv6 helper tools. + _________________________________________________________________ + + Using an external IPv6 helper: + A way to do this is via a separate helper program such as inetd (or + for encrypted connections: ssh or stunnel.) For example, you configure + x11vnc to be run from inetd or xinetd and instruct it to listen on an + IPv6 address. For xinetd the setting "flags = IPv6" will be needed. + For inetd.conf, an example is: + 5900 stream tcp6 nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_wrapper.sh + + We also provide a transitional tool in "x11vnc/misc/inet6to4" that + acts as a relay for any IPv4 application to allow connections over + IPv6. For example: + inet6to4 5900 localhost:5900 + + where x11vnc is listening on IPv4 port 5900. + + Also note that not all VNC Viewers are IPv6 enabled, so a redirector + may also be needed for them. The tool "inet6to4 -r ..." can do this as + well. SSVNC (see below) supports IPv6 without need for the helper. + + # ./inet6to4 -help + + inet6to4: Act as an ipv6-to-ipv4 relay for tcp applications that + do not support ipv6. + + Usage: inet6to4 + inet6to4 -r + + Examples: inet6to4 5900 localhost:5900 + inet6to4 8080 web1:80 + inet6to4 -r 5900 fe80::217:f2ff:fee6:6f5a%eth0:5900 + + The -r option reverses the direction of translation (e.g. for ipv4 + clients that need to connect to ipv6 servers.) Reversing is the default + if this script is named 'inet4to6' (e.g. by a symlink.) + + Use Ctrl-C to stop this program. + + You can also set env. vars INET6TO4_LOOP=1 or INET6TO4_LOOP=BG + to have an outer loop restarting this program (BG means do that + in the background), and INET6TO4_LOGFILE for a log file. + Also set INET6TO4_VERBOSE to verbosity level and INET6TO4_WAITTIME + and INET6TO4_PIDFILE (see below.) + + The "INET6TO4_LOOP=BG" and "INET6TO4_LOGFILE=..." env. variables make + the tool run reliably as a daemon for very long periods. Read the top + part of the script for more information. + _________________________________________________________________ + + Encrypted Tunnels with IPv6 Support: + For SSH tunnelled encrypted VNC connections, one can of course use the + IPv6 support in ssh(1). + + For SSL encrypted VNC connections, one possibility is to use the IPv6 + support in stunnel(1). This includes the built-in support via the + -stunnel option. For example: + x11vnc -stunnel SAVE -env STUNNEL_LISTEN=:: -env STUNNEL_DEBUG=1 ... + _________________________________________________________________ + + SSH IPv6 Tricks: + It is interesting to note that ssh(1) can do basically the same thing + as inet6to4 above by: + ssh -g -L 5900:localhost:5901 localhost "printf 'Press Enter to Exit: '; read + x" + + (where we have x11vnc running via "-rfbport 5901" in this case.) + + Note that one can also make a home-brew SOCKS5 ipv4-to-ipv6 gateway + proxy using ssh like this: + ssh -D '*:1080' localhost "printf 'Press Enter to Exit: '; read x" + + then specify a proxy like socks://hostname:1080 where hostname is the + machine running the above ssh command (add -v to ssh for connection + logging info.) + _________________________________________________________________ + + IPv6 SSVNC Viewer: + Our SSVNC VNC Viewer is basically a wrapper for ssh(1) and stunnel(1), + and so it already has good IPv6 support because these two commands do. + On Unix, MacOSX, and Windows nearly all of the the remaining parts of + SSVNC (e.g. the built-in proxying and un-encrypted connections) have + been modified to support IPv6 in SSVNC 1.0.26. + + + + + + + Contributions: + + Q-130: Thanks for your program or for your help! Can I make a + donation? + + Please do (any amount is appreciated; very few have donated) and thank + you for your support! Click on the PayPal button below for more info. + + [x-click-but04.gif]-Submit + +======================================================================= +http://www.karlrunge.com/x11vnc/chainingssh.html: + + + _________________________________________________________________ + + Chaining ssh's: Note that for use of a ssh gateway and -L redirection + to an internal host (e.g. "-L 5900:otherhost:5900") the VNC traffic + inside the firewall is not encrypted and you have to manually log into + otherhost to start x11vnc. Kyle Amon shows a method where you chain + two ssh's together that encrypts all network traffic and also + automatically starts up x11vnc on the internal workstation: +#!/bin/sh +# +gateway="example.com" # or "user@example.com" +host="labyrinth" # or "user@hostname" +user="kyle" + +# Need to sleep long enough for all of the passwords and x11vnc to start up. +# The /dev/null) & + +# Chain the vnc connection thru 2 ssh's, and connect x11vnc to user's display: +# +exec /usr/bin/ssh -t -L 5900:localhost:5900 $gateway \ + /usr/bin/ssh -t -L 5900:localhost:5900 $host \ + sudo /usr/bin/x11vnc -localhost -auth /home/$user/.Xauthority \ + -rfbauth .vnc/passwd -display :0 + + Also note the use of sudo(1) to switch to root so that the different + user's .Xauthority file can be accessed. See the visudo(8) manpage for + details on how to set this up (remove the sudo if you do not want to + do this). One can also chain together ssh's for reverse connections + with vncviewers using the -listen option. For this case -R would + replace the -L (and 5500 the 5900, see the #2 example script above). + If the gateway machine's sshd is configured with GatewayPorts=no (the + default) then the double chaining of "ssh -R ..." will be required for + reverse connections to work. + +======================================================================= +http://www.karlrunge.com/x11vnc/miscbuild.html: + + + _________________________________________________________________ + + Misc. Build problems: We collect here rare build problems some users + have reported and the corresponding workarounds. See also the FAQ's on + building. + _________________________________________________________________ + + ENV parameter: One user had a problem where the build script below was + failing because his work environment had the ENV variable set to a + script that was resetting his PATH so that gcc could no longer be + found. Make sure you do not have any ENV or BASH_ENV in your + environment doing things like that. Typing "unset ENV", etc. before + configuring and building should clear it. + _________________________________________________________________ + + Bash xpg: One user had his bash shell compiled with + --enable-xpg-echo-default that causes some strange behavior with + things like echo "\\1 ..." the configure script executes. In + particular instead of getting "\1" the non-printable character "^A" is + produced, and causes failures at compile time like: + ../rfb/rfbconfig.h:9:22: warning: extra tokens at end of #ifndef directive + + The workaround is to configure like this: + env CONFIG_SHELL=/bin/sh /bin/sh ./configure + + i.e. avoid using the bash with the misbehavior. A bug has been filed + against autoconf to guard against this. + _________________________________________________________________ + + AIX: one user had to add the "X11.adt" package to AIX to get build + header files like XShm.h, etc. + _________________________________________________________________ + + Ubuntu Feisty Fawn 7.04: In May/2007 one user said he needed to add + these packages to compile x11vnc on that Linux distro and version: + apt-get install build-essential make bin86 libjpeg62-dev libssl-dev libxtst-d +ev + + Note that Ubuntu is based on Debian, so perhaps this is the list + needed on Debian (testing?) as well. To build in Avahi (mDNS service + advertising) support it would appear that libavahi-client-dev is + needed as well. + _________________________________________________________________ + + Exceedingly slow compilation: x11vnc has a couple of files which + contain very large "case statements" (over 100 cases) that on some + platforms can take a very long time to compile (in extreme cases over + an hour). However on 32bit Linux with intel/amd processor and gcc + these files usually take less than 10 seconds to compile. For 64bit + systems using gcc the problem appears to be much worse. + + The two files with the large number of cases, remote.c and x11vnc.c, + have no real need to be optimized (the code is used only very + infrequently). So it is fine to supply "-O0" (disables optimization) + to CFLAGS when compiling them. However, it is tricky with + autoconf/automake to do this (especially since both the compiler and + make versions have a big effect). + + So if the compile times are getting too long for you for these two + files you will need to manually change some things. First, run + configure and when it has finished, edit the generated file + x11vnc/Makefile and put these lines at the very top: +x11vnc-x11vnc.o : CFLAGS += -O0 +x11vnc-remote.o : CFLAGS += -O0 + + Those lines assume gnu make (gmake) is being used. If you are using + another make, say Solaris make, insert these instead: +x11vnc-x11vnc.o := CFLAGS += -O0 +x11vnc-remote.o := CFLAGS += -O0 + + You could write a build shell script that modified the Makefile this + way before running make. + + The "-O0" (note it is "capital Oh" followed by "zero") assumes the gcc + compiler. If you are using a different compiler you will need to find + the command line option to disable optimization, or otherwise have the + lines set CFLAGS to the empty string. + _________________________________________________________________ + +======================================================================= +http://www.karlrunge.com/x11vnc/sunray.html: + + + Sun Ray Notes: + + You can run x11vnc on your (connected or disconnected) SunRay session + (Please remember to use settings like -wait 200, -sb 15, and not + running a screensaver animation (blank instead) to avoid being a + resource hog! x11vnc does induce a lot of memory I/O from polling the + X server. It also helps to have a solid background color, e.g. + -solid). + + News: Sun Ray Remote Control Toolkit: See the nice set of tools in the + Sun Ray Remote Control Toolkit that launch x11vnc automatically for + you for certain usage modes. + + You have to know the name of the machine your SunRay session X server + is running on (so you can ssh into it and start x11vnc). You also need + to know the X11 DISPLAY number for the session: on a SunRay it could + be a large number, e.g. :137, since there are many people with X + sessions (Xsun processes) on the same machine. If you don't know it, + you can get it by running who(1) in a shell on the SunRay server and + looking for the dtlocal entry with your username (and if you don't + even know which server machine has your session, you could login to + all possible ones looking at the who output for your username...). + + I put some code in my ~/.dtprofile script that stores $DISPLAY + (including the hostname) in a ~/.sunray_current file at session + startup (and deletes it when the X session ends) to make it easy to + get at the hostname and X11 display number info for my current X + sessions when I ssh in and am about to start x11vnc. + + SunRay Gotcha #1: Note that even though your SunRay X11 DISPLAY is + something like :137, x11vnc still tries for port 5900 as its listening + port if it can get it, in which case the VNC display (i.e. the + information you supply to the VNC viewer) is something like + sunray-server:0 (note the :0 corresponding to port 5900, it is not + :137). If it cannot get 5900, it tries for 5901, and so on. You can + also try to force the port (and thereby the VNC display) using the + -rfbport NNNN option. + + Especially on a busy Sun Ray server it is often difficult to find free + ports for both VNC and the HTTP Java applet server to listen on. This + script, vnc_findports may be of use for doing this automatically. It + suggests x11vnc command line options based on netstat output that + lists the occupied ports. It is even more difficult to start + vncserver/Xvnc on a busy Sun Ray because then 3 ports (HTTP, VNC, and + X11), all separated by 100 are needed! This script, findvncports may + be helpful as well. Both scripts start at VNC display :10 and work + their way up. + + SunRay Gotcha #2: If you get an error like: + shmget(tile) failed. + shmget: No space left on device + + when starting up x11vnc that most likely means all the shared memory + (shm) slots are filled up on your machine. The Solaris default is only + 100, and that can get filled up in a week or so on a SunRay server + with lots of users. If the shm slot is orphaned (e.g. creator process + dies) the slot is not reclaimed. You can view the shm slots with the + "ipcs -mA" command. If there are about 100 then you've probably hit + this problem. They can be cleaned out (by the owner or by root) using + the ipcrm command. I wrote a script shm_clear that finds the orphans + and lists or removes them. Longer term, have your SunRay sysadmin add + something like this to /etc/system: + set shmsys:shminfo_shmmax = 0x2000000 + set shmsys:shminfo_shmmni = 0x1000 + + SunRay Gotcha #3: Some SunRay installations have implemented + suspending certain applications when a SunRay session is in a + disconnected state (e.g. Java Badge pulled out, utdetach, etc). This + is a good thing because it limits hoggy or runaway apps from wasting + the shared CPU resource. Think how much CPU and memory I/O is wasted + by a bunch of Firefox windows running worthless Flash animations while + your session is disconnected! + + So some sites have implemented scripts to suspend (e.g. kill -STOP) + certain apps when your badge is removed from the SunRay terminal. When + you reattach, it kill -CONT them. This causes problems for viewing the + detached SunRay session via x11vnc: those suspended apps will not + respond (their windows will be blank or otherwise inactive). + + What to do? Well, since you are going to be using the application you + might as well unfreeze it rather than starting up a 2nd instance. Here + is one way to do it using the kill -CONT mechanism: + kill -CONT `ps -ealf | grep ' T ' | grep $LOGNAME | awk '{print $4}'` + + If you want to be a good citizen and re-freeze them before you exit + x11vnc this script could be of use: +#!/bin/sh +# +# kill -STOP/-CONT script for x11vnc (or other) SunRay usage ("freezes" +# certain apps from hogging resources when disconnected). +# +# Put here a pattern that matches the apps that are frozen: +# +appmatch="java_vm|jre|netscape-bin|firefox-bin|realplay|acroread|mozilla-bin" + +if [ "X$1" = "Xfreeze" ]; then + pkill -STOP -U $LOGNAME "$appmatch" +elif [ "X$1" = "Xthaw" ]; then + pkill -CONT -U $LOGNAME "$appmatch" + +elif [ "$RFB_MODE" = "afteraccept" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "1" ]; then + # only one client present. + pkill -CONT -U $LOGNAME "$appmatch" + fi +elif [ "$RFB_MODE" = "gone" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "0" ]; then + # last client present has just left. + pkill -STOP -U $LOGNAME "$appmatch" + fi +fi +exit 0 + + If you called the script "goodcitizen" you could type "goodcitizen + thaw" to unfreeze them, and then "goodcitizen freeze" to refreeze + them. One could also use these x11vnc options "-afteraccept + goodcitizen -gone goodcitizen" to do it automatically. + + SunRay Gotcha #4: Recent versions of the Sun Ray Server Software + SRSS (seems to be version 3.0 or 3.1) have a "misfeature" that when + the session is disconnected (i.e. badge/smartcard out) the screen + locker (xscreensaver) will freeze the X server just when the "Enter + Password" dialog box appears. So you cannot unlock the screen remotely + via x11vnc! + + Update: please see Bob Doolittle's detailed description of the this + issue at the bottom of this section. + + Here "freeze" means "stop other X clients from inserting keyboard and + mouse input and from viewing the current contents of the screen". Or + something like that; the upshot is x11vnc can't do its normal thing. + + There are several workarounds for this. + + 1) The easiest one by far is to put these lines in your + $HOME/.dtprofile file: +SUN_SUNRAY_UTXLOCK_PREF="/usr/openwin/bin/xlock -mode blank" +export SUN_SUNRAY_UTXLOCK_PREF + + One might argue that xlock isn't particularly "pretty". (Just IMHO, + but if something like this not being pretty actually gets in the way + of your work I think some introspection may be in order. :-) + + 2) The problem has been traced to the pam_sunray.so PAM module. + Evidently xscreensaver invokes this pam module and it communicates + with utsessiond who in turn instructs the Xsun server to not process + any synthetic mouse/keyboard input or to update the screen + framebuffer. It is not clear if this is by design (security?) or + something else. + + In any event, the problem can be avoided, somewhat drastically, by + commenting out the corresponding line in /etc/pam.conf: +#xscreensaver auth sufficient /opt/SUNWut/lib/pam_sunray.so syncondisplay + + Leave the other xscreensaver pam authentication lines unchanged. The + dtsession-SunRay line may also need to be commented out to avoid the + problem for CDE sessions. N.B. it is possible the application of a + SSRS patch, etc, may re-enable that /etc/pam.conf line. It may be + difficult to convince a sysadmin to make this change. + + 3) A more forceful way is to kill the xscreensaver process from a + shell prompt whenever you connect via x11vnc and the screen is in a + locked state: +pkill -U $LOGNAME '^xscreensaver$' + + And then after you are in be sure to restart it by typing something + like: +xscreensaver & + + You may want to avoid restarting it until you are about to disconnect + your VNC viewer (since if it locks the screen while you are working + you'll be stuck again). + + 3') The above idea can be done a bit more cleanly by having x11vnc do + it. Suppose we called the following script xss_killer: +#!/bin/sh +# +# xss_killer: kill xscreensaver after a valid x11vnc client logs in. +# Restart xscreensaver and lock it when the last client +# disconnects. + +PATH=/usr/openwin/bin:/usr/bin:$PATH +export PATH + +if [ "$RFB_MODE" = "afteraccept" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "1" ]; then + # only one client present. + pkill -U $LOGNAME '^xscreensaver$' + pkill -KILL -U $LOGNAME -f xscreensaver/hacks + fi +elif [ "$RFB_MODE" = "gone" -a "$RFB_STATE" = "NORMAL" ]; then + # a valid x11vnc login. + if [ "$RFB_CLIENT_COUNT" = "0" ]; then + # last client present has just left. + xscreensaver -nosplash & + sleep 1 + xscreensaver-command -lock & + fi +fi + + Then we would run x11vnc with these options: "-afteraccept xss_killer + -gone xss_killer". The -afteraccept option (introduced in version 0.8) + is used to run a command after a vncviewer has successfully logged in + (note that this is a VNC login, not a Unix login, so you may not want + to do this if you are really paranoid...) + + Note if you use the above script and also plan to Ctrl-C (SIGINT) + x11vnc you have to run the xscreensaver in a new process group to + avoid killing it as well. One way to do this is via this kludge: +perl -e 'setpgrp(0,0); exec "xscreensaver -nosplash &"' + + in the above script. + + 4) There appears to be a bug in pam_sunray.so in that it doesn't seem + to honor the convention that, say, DISPLAY=unix:3 means to use Unix + sockets to connect to display 3 on the local machine (this is a bit + faster than TCP sockets). Rather, it thinks the display is a non-local + one to a machine named "unix" (that usually does not resolve to an IP + address). + + Amusingly, this can be used to bypass the pam_sunray.so blocking of + Xsun that prevents one from unlocking the screen remotely via x11vnc. + One could put something like this in $HOME/.dtprofile to kill any + existing xscreensavers and then start up a fresh xscreensaver using + DISPLAY=unix:N +# stop/kill any running xscreensavers (probably not running yet, but to be sure +) +xscreensaver-command -exit +pkill -U $LOGNAME '^xscreensaver$' +env DISPLAY=`echo $DISPLAY | sed -e 's/^.*:/unix:/'` xscreensaver & + + + Important: Note that all of the above workarounds side-step the + pam_sunray.so PAM module in one way or another. You'll need to see if + that is appropriate for your site's SunRay / smartcard usage. Also, + these hacks may break other things and so you may want to test various + scenarios carefully. E.g. check corner cases like XDMCP/dtremote, + NSCM, etc. + + + Update May 2008: Here is a useful description of this issue from Bob + Doolittle who is a developer for Sun Ray at Sun. I don't have the time + to digest and distill it and then adjust the above methods to provide + a clearer description, so I just include below the description he sent + me with the hope that it will help some users: + + In SRSS 4.0 and earlier, the purpose of pam_sunray.so in the "auth" + PAM stack of screensavers is to enable NSCM (and, although this is + much less commonly used, "SC", which is configured when 3rd-party + software is installed to allow smartcards to be used as part of the + authentication process) to work. It should have no effect with + smartcards. Currently, however, it does block the PAM stack for all + sessions, which causes xscreensaver, when it locks a disconnected + session, to not process any mouse or keyboard events as you + describe (unless xscreensaver does an X server grab, however, other + applications should still be able to draw in the session although + xscreensaver may be playing tricks like putting a black window on + top of everything). In both of the NSCM and SC models, + authentication occurs in a separate session before SRSS will + reconnect to the user session, in which case pam_sunray.so causes + xscreensaver to just unlock the screen without prompting the user + to enter their password again. To do this, pam_sunray.so has to + block until the session becomes reconnected, so it can query SRSS + at that time to determine whether the user has already + authenticated or not. In SRSS 4.0 and earlier releases, + pam_sunray.so could have been optimized to not block smartcard + sessions, although since the session is disconnected this typically + isn't important (except in the x11vnc case, as you've observed). + + In SRSS 4.1, however, for increased security the out-of-session + authentication model has been extended to *all* session types, so + pam_sunray.so will be required in all cases unless users are + willing to authenticate twice upon hotdesking (e.g. when their card + is inserted). In future, we may do away with pam_sunray.so, and in + fact with any traditional screen locker in the user session, since + SRSS itself will be providing better security than a screen locker + running entirely within the user's X session is capable of + providing. + + Your trick of setting DISPLAY to unix:DPY will effectively disable + pam_sunray.so (I'm not sure I'd call that a bug - you're going out + of your way to do something that wouldn't occur in the normal + course of events, and really provides no useful value other than to + tickle this behavior in pam_sunray.so). This will mean that, in + SRSS 4.0 and earlier releases, users will be prompted for their + passwords twice when reconnecting to their sessions for NSCM and SC + session types. In 4.1, disabling pam_sunray.so in this way will + cause this double-authentication to occur for *all* sessions, + including simple smartcard sessions. Users may be willing to pay + that price in order to be able to use x11vnc in disconnected + sessions. I like this hack, personally. It's a little less + convenient than some of the other approaches you describe, but it's + lighter-weight and more secure than most of the other approaches, + and provides the value of being able to use x11vnc in locked + sessions. + + Here are some other minor notes: - I wouldn't recommend storing + your display in your .dtprofile, unless you're willing to live with + a single session at a time. Personally, I often find myself using + several sessions, in several FoGs, for short periods of time so + this would certainly break. IMO it's pretty easy to use $DISPLAY to + do what you want on the fly, as needed, so I don't think the price + of breaking multiple-session functionality would be worth the + convenience, to me at least. Here's some ksh/bash syntax to extract + the hostname and display number on the fly which you may find + useful: +HOSTNAME=${DISPLAY%:*} +FULLDPY=${DISPLAY#*:} +DPYNUM=${FULLDPY%.*} + + A final note may give you some insight into other clever hacks in + this area: - Check out utaction. It's a very handy little utility + that can be run as a daemon in the user session which will invoke a + specified command upon session connects and/or disconnects. + Personally, I start one up in my .dtprofile as follows: +utaction -c $HOME/.srconnectrc -d $HOME/.srdisconnectrc & + + This then allows me to construct a .srconnectrc script containing + useful commands I'd like to have run every time I insert my + smartcard, and a .srdisconnectrc script of commands to be run every + time I remove my smartcard (or, connect/disconnect to my session + via NSCM or SC). This can be used for things like notifying a chat + client of away status, as well as some of the hacks you've + described on your page such as freeze/unfreeze, or perhaps to + terminate an xscreensaver and start up a new one with the unix:DPY + $DISPLAY specification as you describe (although it probably makes + most sense to do this at login time, as opposed to every connect or + disconnect event). + +======================================================================= +http://www.karlrunge.com/x11vnc/ssl.html: + + + _________________________________________________________________ + + Notes on x11vnc SSL Certificates and Key Management: + + The simplest scheme ("x11vnc -ssl TMP") is where x11vnc generates a + temporary, self-signed certificate each time (automatically using + openssl(1)) and the VNC viewer client accepts the certificate without + question (e.g. user clicks "Yes" in a dialog box. Perhaps the dialog + allows them to view the certificate too). Also note stunnel's default + is to quietly accept all certificates. + + The encryption this provides protects against all passive sniffing of + the VNC traffic and passwords on the network and so it is quite good, + but it does not prevent a Man-In-The-Middle active attack: e.g. an + attacker intercepts the VNC client stream and sends it his own Public + key for SSL negotiation (pretending to be the server). Then it makes a + connection to SSL x11vnc itself and forwards the data back and forth. + He can see all the traffic and modify it as well. + + Most people don't seem to worry about Man-In-The-Middle attacks these + days; they are more concerned about passive sniffing of passwords, + etc. Perhaps someday that will change if attack tools are used more + widely to perform the attack. NOTE: There are hacker tools like + dsniff/webmitm and cain that implement SSL Man-In-The-Middle attacks. + They all rely on the client not bothering to check that the cert is + valid. + + If you are not worried about Man-In-The-Middle attacks you do not have + to read the techniques described in the rest of this document. + + To prevent Man-In-The-Middle attacks, certificates must somehow be + verified. This requires the VNC client side have some piece of + information that can be used to verify the SSL x11vnc server. + Alternatively, although rarely done, x11vnc can verify VNC Clients' + certificates, see the -sslverify option that is discussed below. + + There are a number of ways to have the client authenticate the SSL + x11vnc server. The quickest way perhaps would be to copy (safely) the + certificate x11vnc prints out: +26/03/2006 21:12:00 Creating a temporary, self-signed PEM certificate... +... +-----BEGIN CERTIFICATE----- +MIIC4TCCAkqgAwIBAgIJAMnwCaOjvEKaMA0GCSqGSIb3DQEBBAUAMIGmMQswCQYD +VQQGEwJBVTEOMAwGA1UEBxMFTGludXgxITAfBgNVBAsTGGFuZ2VsYS0xMTQzNDI1 +NTIwLjQxMTE2OTEPMA0GA1UEChMGeDExdm5jMS4wLAYDVQQDEyV4MTF2bmMtU0VM +(more lines) ... +-----END CERTIFICATE----- + + to the client machine(s) and have the client's SSL machinery (e.g. + stunnel, Web Browser, or Java plugin) import the certificate. That way + when the connection to x11vnc is made the client can verify that is it + the desired server on the other side of the SSL connection. + + So, for example suppose the user is using the SSL enabled Java VNC + Viewer and has incorporated the x11vnc certificate into his Web + browser on the viewing side. If he gets a dialog that the certificate + is not verified he knows something is wrong. It may be a + Man-In-The-Middle attack, but more likely x11vnc certificate has + changed or expired or his browser was reinstalled and/or lost the + certificate, etc, etc. + + As another example, if the user was using stunnel with his VNC viewer + (this is mentioned in this FAQ), e.g. STUNNEL.EXE on Windows, then he + would have to set the "CAfile = path-to-the-cert" and "verify = 2" + options in the stunnel.conf file before starting up the tunnel. If a + x11vnc certificate cannot be verified, stunnel will drop the + connection (and print a failure message in its log file). + + A third example, using the VNC viewer on Unix with stunnel the wrapper + script can be used this way: "ss_vncviewer -verify ./x11vnc.crt + far-away.east:0" where ./x11vnc.crt is the copied certificate x11vnc + printed out. + + As fourth example, our SSVNC enhanced tightvnc viewer can also use + these certificate files for server authentication. You can load them + via the SSVNC 'Certs...' dialog and set 'ServerCert' to the + certificate file you safely copied there. + + Note that in principle the copying of the certificate to the client + machine(s) itself could be altered by a Man-In-The-Middle attack! You + can't win; it is very difficult to be completely secure. It is + unlikely the attacker could predict how you were going to send it + unless you had, say, done it many times before the same way. SSH is a + very good way to send it (but of course it too depends on public keys + being sent unaltered between the two machines!). + + If you are really paranoid, I'm sure you'll figure out a really good + way to transport the certificates. See the Certificate Authority + scheme below for a way to make this easier (you just have to do it + once). + + _________________________________________________________________ + + Saving SSL certificates and keys: + + Now, it would be very inconvenient to copy the new temporary + certificate every time x11vnc is run in SSL mode. So for convenience + there is the "SAVE" keyword to instruct x11vnc to save the certificate + it creates: + x11vnc -ssl SAVE -display :0 ... + + This behavior is now the default, you must use "TMP" for a temporary + one. It will save the certificate and private key in these files: + ~/.vnc/certs/server.crt + ~/.vnc/certs/server.pem + + The ".crt" file contains only the certificate and should be safely + copied to the VNC Viewer machine(s) that will be authenticating the + x11vnc server. The ".pem" file contains both the certificate and the + private key and should be kept secret. (If you don't like the default + location ~/.vnc/certs, e.g. it is on an NFS share and you are worried + about local network sniffing, use the -ssldir dir option to point to a + different directory.) + + So the next time you run "x11vnc -ssl SAVE ..." it will read the + server.pem file directly instead of creating a new one. + + You can manage multiple SSL x11vnc server keys in this simple way by + using: + x11vnc -ssl SAVE-key2 -display :0 ... + + etc, where you put whatever name you choose for the key after "SAVE-". + E.g. "-ssl SAVE-fred". + + Also, if you want to be prompted to possibly change the made up names, + etc. that x11vnc creates (e.g. "x11vnc-SELF-SIGNED-CERT-7762" for the + CommonName) for the certificates distinguished name (DN), then use + "x11vnc -ssl SAVE_PROMPT ...", "x11vnc -ssl SAVE_PROMPT-fred ..." etc. + when you create the key the first time. + + Tip: when prompting, if you choose the CommonName entry to be the full + internet hostname of the machine the clients will be connecting to + then that will avoid an annoying dialog box in their Web browsers that + warn that the CommonName doesn't match the hostname. + + _________________________________________________________________ + + Passphrases for server keys: + + Well, since now with the "SAVE" keyword the certificate and key will + be longer lived, one can next worry about somebody stealing the + private key and pretending to be the x11vnc server! How to guard + against this? + + The first is that the file is created with perms 600 (i.e. -rw-------) + to make it harder for an untrusted user to copy the file. A better way + is to also encrypt the private key with a passphrase. You are prompted + whether you want to do this or not when the key is first created under + "-ssl SAVE" mode ("Protect key with a passphrase? y/n"). It is + suggested that you use a passphrase. The inconvenience is every time + you run "x11vnc -ssl SAVE ..." you will need to supply the passphrase + to access the private key: + 06/04/2006 11:39:11 using PEM /home/runge/.vnc/certs/server.pem 0.000s + + A passphrase is needed to unlock an OpenSSL private key (PEM file). + Enter passphrase> + + before x11vnc can continue. + + _________________________________________________________________ + + Being your own Certificate Authority: + + A very sophisticated way that scales well if the number of users is + large is to use a Certificate Authority (CA) whose public certificate + is available to all of the VNC clients and whose private key has been + used to digitally sign the x11vnc server certificate(s). + + The idea is as follows: + * A special CA cert and key is generated. + * Its private key is always protected by a good passphrase since it + is only used for signing. + * The CA cert is (safely) distributed to all machines where VNC + clients will run. + * One or more x11vnc server certs and keys are generated. + * The x11vnc server cert is signed with the CA private key. + * x11vnc is run using the server key. (e.g. "-ssl SAVE") + * VNC clients (viewers) can now authenticate the x11vnc server + because they have the CA certificate. + + The advantage is the CA cert only needs to be distributed once to the + various machines, that can be done even before x11vnc server certs are + generated. + + As above, it is important the CA private key and the x11vnc server key + are kept secret, otherwise someone could steal them and pretend to be + the CA or the x11vnc server if they copied the key. It is recommended + that the x11vnc server keys are also protected via a passphrase (see + the previous section). + + Optionally, VNC viewer certs and keys could also be generated to + enable the x11vnc server to authenticate each client. This is not + normally done (usually a simple viewer password scheme is used), but + this can be useful in some situations. These optional steps go like + this: + * One or more VNC client certs and keys are generated. + * These VNC client certs are signed with the CA private key. + * The VNC client certs+keys are safely distributed to the + corresponding client machines. + * x11vnc is told to verify clients by using the CA cert. (e.g. + "-sslverify CA") + * When VNC clients (viewers) connect, they must authenticate + themselves to x11vnc by using their client key. + + Again, it is a good idea if the client private keys are protected with + a passphrase, otherwise if stolen they could be used to gain access to + the x11vnc server. Once distributed to the client machines, there is + no need to keep the client key on the CA machine that generated and + signed it. You can keep the client certs if you like because they are + public. + + _________________________________________________________________ + + How to do the above CA steps with x11vnc: + + Some utility commands are provided to ease the cert+key creation, + signing, and management: -sslGenCA, -sslGenCert, -sslDelCert, + -sslEncKey, -sslCertInfo. They basically run the openssl(1) command + for you to manage the certs/keys. It is required that openssl(1) is + installed on the machine and available in PATH. All commands can be + pointed to an alternate toplevel certificate directory via the -ssldir + option if you don't want to use the default ~/.vnc/certs. + + 1) To generate your Certificate Authority (CA) cert and key run this: + x11vnc -sslGenCA + + Follow the prompts, you can modify any informational strings you care + to. You will also be required to encrypt the CA private key with a + passphrase. This generates these files: + ~/.vnc/certs/CA/cacert.pem (the CA public certificate) + ~/.vnc/certs/CA/private/cakey.pem (the encrypted CA private key) + + If you want to use a different directory use -ssldir It must supplied + with all subsequent SSL utility options to point them to the correct + directory. + + 2) To generate a signed x11vnc server cert and key run this: + x11vnc -sslGenCert server + + As with the CA generation, follow the prompts and you can modify any + informational strings that you care to. This will create the files: + ~/.vnc/certs/server.crt (the server public certificate) + ~/.vnc/certs/server.pem (the server private key + public cert) + + It is recommended to protect the server private key with a passphrase + (you will be prompted whether you want to). You will need to provide + it whenever you start x11vnc using this key. + + 3) Start up x11vnc using this server key: + x11vnc -ssl SAVE -display :0 ... + + (SAVE corresponds to server.pem, see -sslGenCert server somename info + on creating additional server keys, server-somename.crt ...) + + 4) Next, safely copy the CA certificate to the VNC viewer (client) + machine(s). Perhaps: + scp ~/.vnc/CA/cacert.pem clientmachine:. + + 5) Then the tricky part, make it so the SSL VNC Viewer uses this + certificate! There are a number of ways this might be done, it depends + on what your client and/or SSL tunnel is. Some examples: + + For the SSL Java VNC viewer supplied with x11vnc in + classes/ssl/VncViewer.jar or classes/ssl/SignedVncViewer.jar: + * Import the cacert.pem cert into your Web Browser (e.g. Edit -> + Preferences -> Privacy & Security -> Manage Certificates -> + WebSites -> Import) + * Or Import the cacert.pem cert into your Java Plugin (e.g. run + ControlPanel, then Security -> Certificates -> Secure Site -> + Import) + + When importing, one would give the browser/java-plugin the path to the + copied cacert.pem file in some dialog. Note that the Web browser or + Java plugin is used for the server authentication. If the user gets a + "Site not verified" message while connecting he should investigate + further. + + For the use of stunnel (e.g. on Windows) one would add this to the + stunnel.conf: + # stunnel.conf: + client = yes + options = ALL + CAfile = /path/to/cacert.pem # or maybe C:\path\to\cacert.pem + [myvncssl] + accept = 5901 + connect = far-away.east:5900 + + (then point the VNC viewer to localhost:1). + + Here is an example for the Unix stunnel wrapper script ss_vncviewer in + our SSVNC package: + ss_vncviewer -verify ./cacert.pem far-away.east:0 + + Our SSVNC enhanced tightvnc viewer GUI can also use the certificate + file for server authentication. You can load it via the SSVNC + 'Certs...' dialog and set 'ServerCert' to the cacert.pem file you + safely copied there. + + _________________________________________________________________ + + Tricks for server keys: + + To create additional x11vnc server keys do something like this: + x11vnc -sslGenCert server myotherkey + + and use it this way: + x11vnc -ssl SAVE-myotherkey ... + + The files will be ~/.vnc/certs/server-myotherkey.{crt,pem} + + You can also create a self-signed server key: + x11vnc -sslGenCert server self:third_key + + and use it this way: + x11vnc -ssl SAVE-self:third_key ... + + This key is not signed by your CA. This can be handy to have a key set + separate from your CA when you do not want to create a 2nd CA + cert+key. + + _________________________________________________________________ + + Using external CA's: + + You don't have to use your own CA cert+key, you can use a third + party's instead. Perhaps you have a company-wide CA or you can even + have your x11vnc certificate signed by a professional CA (e.g. + www.thawte.com or www.verisign.com or perhaps the free certificate + service www.startcom.org or www.cacert.org). + + The advantage to doing this is that the VNC client machines will + already have the CA certificates installed and you don't have to + install it on each machine. + + To generate an x11vnc server cert+key this way you should generate a + "request" for a certicate signing something like this (we use the name + "external" in this example, it could be anything you want): + x11vnc -sslGenCert server req:external + + This will create the request file: + ~/.vnc/certs/server-req:external.req + + Which you should send to the external CA. When you get the signed + certificate back from them, save it in the file: + ~/.vnc/certs/server-req:external.crt + + and create the .pem this way: + mv ~/.vnc/certs/server-req:external.key ~/.vnc/certs/server-req:external. +pem + chmod 600 ~/.vnc/certs/server-req:external.pem + cat ~/.vnc/certs/server-req:external.crt >> ~/.vnc/certs/server-req:external. +pem + + You also rename the two files (.crt and .pem) to have a shorter + basename if you like. E.g.: + mv ~/.vnc/certs/server-req:external.pem ~/.vnc/certs/server-ext.pem + mv ~/.vnc/certs/server-req:external.crt ~/.vnc/certs/server-ext.crt + + and the use via "x11vnc -ssl SAVE-ext ...", etc. + + On the viewer side make sure the external CA's certificate is + installed an available for the VNC viewer software you plan to use. + + _________________________________________________________________ + + Using Client Keys for Authentication: + + You can optionally create certs+keys for your VNC client machines as + well. After distributing them to the client machines you can have + x11vnc verify the clients using SSL. Here is how to do this: + + x11vnc -sslGenCert client dilbert + x11vnc -sslGenCert client wally + x11vnc -sslGenCert client alice + ... + + As usual, follow the prompts if you want to change any of the info + field values. As always, it is a good idea (although inconvenient) to + protect the private keys with a passphrase. These files are created: + ~/.vnc/certs/clients/dilbert.crt + ~/.vnc/certs/clients/dilbert.pem + ... + + Note that these are kept in a clients subdirectory. + + Next, safely copy the .pem files to each corresponding client machine + and incorporate them into the VNC viewer / SSL software (see the ideas + mentioned above for the CA and server keys). The only difference is + these certificates might be referred to as "My Certificates" or + "Client Certificates". They are used for client authentication (which + is relatively rare for SSL). + + After copying them you can delete the clients/*.pem files for extra + safety because the private keys are not needed by the x11vnc server. + You don't really need the clients/*.crt files either (because they + have been signed by the CA). But they could come in handy for tracking + or troubleshooting, etc. + + Now start up x11vnc and instruct it to verify connecting clients via + SSL and the CA cert: + x11vnc -ssl SAVE -sslverify CA + + The "CA" special token instructs x11vnc to use its CA signed certs for + verification. + + For arbitrary self-signed client certificates (no CA) it might be + something like this: + x11vnc -ssl SAVE -sslverify path/to/client.crt + x11vnc -ssl SAVE -sslverify path/to/client-hash-dir + x11vnc -ssl SAVE -sslverify path/to/certs.txt + + Where client.crt would be an individual client certificate; + client-hash-dir a directory of file names based on md5 hashes of the + certs (see -sslverify); and certs.txt signifies a single file full of + client certificates. + + Finally, connect with your VNC viewer using the key. Here is an + example for the Unix stunnel wrapper script ss_vncviewer: using client + authentication (and the standard server authentication with the CA + cert): + ss_vncviewer -mycert ./dilbert.pem -verify ./cacert.pem far-away.east:0 + + Our SSVNC enhanced tightvnc viewer can also use these openssl .pem + files (you can load them via Certs... -> MyCert dialog). + + It is also possible to use -sslverify on a per-client key basis, and + also using self-signed client keys (x11vnc -sslGenCert client + self:dilbert) + + Now a tricky part is to get Web browsers or Java Runtime to import and + use the openssl .pem cert+key files. See the next paragraph on how to + convert them to pkcs12 format. If you find a robust way to import them + and and get them to use the cert please let us know! + + Here is how to convert our openssl crt/pem files to pkcs12 format + (contains both the client certificate and key) that can be read by Web + browsers and Java for use in client authentication: + openssl pkcs12 -export -in mycert.crt -inkey mycert.pem -out mycert.p12 + + it will ask for a passphrase to protect mycert.p12. Some software + (e.g. Java ControlPanel) may require a non-empty passphrase. Actually, + since our .pem contains both the certificate and private key, you + could just supply it for the -in and remove the -inkey option. It + appears that for certificates only importing, our .crt file is + sufficient and can be read by Mozilla/Firefox and Java... + + If you have trouble getting your Java Runtime to import and use the + cert+key, there is a workaround for the SSL-enabled Java applet. On + the Web browser URL that retrieves the VNC applet, simply add a + "/?oneTimeKey=..." applet parameter (see ssl-portal for more details + on applet parameters; you don't need to do the full portal setup + though). The value of the oneTimeKey will be the very long string that + is output of the onetimekey program found in the classes/ssl x11vnc + directory. Or you can set oneTimeKey=PROMPT in which case the applet + will ask you to paste in the long string. These scheme is pretty ugly, + but it works. A nice application of it is to make one time keys for + users that have already logged into a secure HTTPS site via password. + A cgi program then makes a one time key for the logged in user to use: + it is passed back over HTTPS as the applet parameter in the URL and so + cannot be sniffed. x11vnc is run to use that key via -sslverify. + + Update: as of Apr 2007 in the 0.9.1 x11vnc tarball there is a new + option setting "-users sslpeer=" that will do a switch user much like + -unixpw does, but this time using the emailAddress field of the + Certificate subject of the verified Client. This mode requires + -sslverify turned on to verify the clients via SSL. This mode can be + useful in situations using -create or -svc where a new X server needs + to be started up as the authenticated user (but unlike in -unixpw + mode, the unix username is not obviously known). + + _________________________________________________________________ + + Revoking Certificates: + + A large, scaled-up installation may benefit from being able to revoke + certificates (e.g. suppose a user's laptop with a vnc client or server + key is compromised.) You can use this option with x11vnc: -sslCRL. See + the info at that link for a guide on what openssl(1) commands you will + need to run to revoke a certificate. + + _________________________________________________________________ + + Additional utlities: + + You can get information about your keys via -sslCertInfo. These lists + all your keys: + x11vnc -sslCertInfo list + x11vnc -sslCertInfo ll + + (the latter is long format). + + These print long output, including the public certificate, for + individual keys: + x11vnc -sslCertInfo server + x11vnc -sslCertInfo dilbert + x11vnc -sslCertInfo all (every key, very long) + + If you want to add a protecting passphrase to a key originally created + without one: + x11vnc -sslEncKey SAVE + x11vnc -sslEncKey SAVE-fred + + To delete a cert+key: + x11vnc -sslDelCert SAVE + x11vnc -sslDelCert SAVE-fred + x11vnc -sslDelCert wally + + (but rm(1) will be just as effective). + + _________________________________________________________________ + + Chained Certificates: + + There is increasing interest in using chained CA's instead of a single + CA. The merits of using chained CA's are not described here besides to + say its use may make some things easier when a certificate needs to be + revoked. + + x11vnc supports chained CA certificates. We describe a basic use case + here. + + Background: Of course the most straight forward way to use SSL with + x11vnc is to use no CA at all (see above): a self-signed certificate + and key is used and its certificate needs to be safely copied to the + client side. This is basically the same as the SSH style of managing + keys. Next level up, one can use a single CA to sign server keys: then + only the CA's certificate needs to be safely copied to the client + side, this can happen even before any server certs are created (again, + see all of the discussion above.) + + With a certificate chain there are two or more CA's involved. Perhaps + it looks like this: + root_CA ---> intermediate_CA ---> server_cert + + Where the arrow basically means "signs". + + In this usage mode the client (viewer-side) will have root_CA's + certificate available for verifying (and nothing else.) If the viewer + only received server_cert's certificate, it would not have enough info + to verify the server. The client needs to have intermediate_CA's cert + as well. The way to do this with x11vnc (i.e. an OpenSSL using app) is + to concatenate the server_cert's pem and the intermediate_CA's + certificate together. + + For example, suppose the file intermediate_CA.crt had + intermediate_CA's certificate. And suppose the file server_cert.pem + had the server's certificate and private key pair as described above + on this page. We need to do this: + cat intermediate_CA.crt >> server_cert.pem + + (Note: the order of the items inside the file matters; intermediate_CA + must be after the server key and cert) and then we run x11vnc like + this: + x11vnc -ssl ./server_cert.pem ... + + Then, on the VNC viewer client side, the viewer authenticates the + x11vnc server by using root_CA's certificate. Suppose that is in a + file named root_CA.crt, then using the SSVNC wrapper script + ss_vncviewer (which is also included in the SSVNC package) as our + example, we have: + ss_vncviewer -verify ./root_CA.crt hostname:0 + + (where "hostname" is the machine where x11vnc is running.) One could + also use the SSVNC GUI setting Certs -> ServerCert to the root_CA.crt + file. Any other SSL enabled VNC viewer would use root_CA.crt in a + similar way. + _________________________________________________________________ + + Creating Chained Certificates: + + Here is a fun example using VeriSign's "Trial Certificate" program. + Note that VeriSign has a Root CA and also an Intermediate CA and uses + the latter to sign customers certificates. So this provides an easy + way to test out the chained certificates mechanism with x11vnc. + + First we created a test x11vnc server key: + openssl genrsa -out V1.key 1024 + + then we created a certificate signing request (CSR) for it: + openssl req -new -key V1.key -out V1.csr + + (we followed the prompts and supplied information for the various + fields.) + + Then we went to VeriSign's page http://www.verisign.com/ssl/index.html + and clicked on "FREE TRIAL" (the certificate is good for 14 days.) We + filled in the forms and got to the point where it asked for the CSR + and so we pasted in the contents of the above V1.csr file. Then, after + a few more steps, VeriSign signed and emailed us our certificate. + + The VeriSign Trial certificates were found here: + http://www.verisign.com/support/verisign-intermediate-ca/Trial_Secure_Server_ +Root/index.html + http://www.verisign.com/support/verisign-intermediate-ca/trial-secure-server- +intermediate/index.html + + The former was pasted into a file V-Root.crt and the latter was pasted + into V-Intermediate.crt + + We pasted our Trial certificate that VeriSign signed and emailed to us + into a file named V1.crt and then we typed: + cat V1.key V1.crt > V1.pem + cat V1.pem V-Intermediate.crt > V1-combined.pem + chmod 600 V1.pem V1-combined.pem + + So now the file V1-combined.pem has our private key and (VeriSign + signed) certificate and VeriSign's Trial Intermediate certificate. + + Next, we start x11vnc: + x11vnc -ssl ./V1-combined.pem ... + + and finally, on the viewer side (SSVNC wrapper script example): + ss_vncviewer -verify ./V-Root.crt hostname:0 + + One will find that only that combination of certs and keys will work, + i.e. allow the SSL connection to be established. Every other + combination we tried failed (note that ss_vncviewer uses the external + stunnel command to handle the SSL so we are really testing stunnel's + SSL implementation on the viewer side); and so the system works as + expected. + _________________________________________________________________ + + VNC Client Authentication using Certificate Chains: + + Now, going the other way around with the client authenticating himself + via this chain of SSL certificates, x11vnc is run this way: + x11vnc -ssl SAVE -sslverify ./V-Root.crt ... + + (note since the server must always supply a cert, we use its normal + self-signed, etc., one via "-ssl SAVE" and use the VeriSign root cert + for client authentication via -sslverify. The viewer must now supply + the combined certificates, e.g.: + ss_vncviewer -mycert ./V1-combined.pem hostname:0 + _________________________________________________________________ + + Using OpenSSL and x11vnc to create Certificate Chains: + + Although the x11vnc CA mechanism (-sslGenCA and -sslGenCert; see + above) was designed to only handle a single root CA (to sign server + and/or client certs) it can be coerced into creating a certificate + chain by way of an extra openssl(1) command. + + We will first create two CA's via -sslGenCA; then use one of these CA + to sign the other; create a new (non-CA) server cert; and append the + intermediate CA's cert to the server cert to have everything needed in + the one file. + + Here are the commands we ran to do what the previous paragraph + outlines. + + First we create the two CA's, called CA_root and CA_Intermediate here, + in separate directories via x11vnc: + x11vnc -ssldir ~/CA_Root -sslGenCA + (follow the prompts, we included "CA_Root", e.g. Common Name, to aid ident +ifying it) + + x11vnc -ssldir ~/CA_Intermediate -sslGenCA + (follow the prompts, we included "CA_Intermediate", e.g. Common Name, to a +id identifying it) + + Next backup CA_Intermediate's cert and then sign it with CA_Root: + mv ~/CA_Intermediate/CA/cacert.pem ~/CA_Intermediate/CA/cacert.pem.ORIG + cd ~/CA_Root + openssl ca -config ./CA/ssl.cnf -policy policy_anything -extensions v3_ca -no +text -ss_cert ~/CA_Intermediate/CA/cacert.pem.ORIG -out ~/CA_Intermediate/CA/ca +cert.pem + + Note that it is required to cd to the ~/CA_Root directory and run the + openssl command from there. + + You can print out info about the cert you just modified by: + openssl x509 -noout -text -in ~/CA_Intermediate/CA/cacert.pem + + Now we create an x11vnc server cert named "test_chain" that is signed + by CA_Intermediate: + x11vnc -ssldir ~/CA_Intermediate -sslGenCert server test_chain + (follow the prompts) + + You can print out information about this server cert just created via + this command: + x11vnc -ssldir ~/CA_Intermediate -sslCertInfo SAVE-test_chain + + This will tell you the full path to the server certificate, which is + needed because we need to manually append the CA_Intermediate cert for + the chain to work: + cat ~/CA_Intermediate/CA/cacert.pem >> ~/CA_Intermediate/server-test_chain.pe +m + + Now we are finally ready to use it. We can run x11vnc using this + server cert+key by either this command: + x11vnc -ssldir ~/CA_Intermediate -ssl SAVE-test_chain ... + + or this command: + x11vnc -ssl ~/CA_Intermediate/server-test_chain.pem ... + + since they are equivalent (both load the same pem file.) + + Finally we connect via VNC viewer that uses CA_Root to verify the + server. As before we use ss_vncviewer: + ss_vncviewer -verify ~/CA_Root/CA/cacert.pem hostname:0 + + Client Certificates (see above) work in a similar manner. + + So although it is a little awkward with the extra steps (e.g. + appending the CA_Intermediate cert) it is possible. If you want to do + this entirely with openssl(1) you will have to learn the openssl + commands corresponding to -genCA and -genCert. You may be able to find + guides on the Internet to do this. Starting with x11vnc 0.9.10, you + can have it print out the wrapper scripts it uses via: -sslScripts + (you will still need to fill in a few pieces of information; ask if it + is not clear from the source code.) + + _________________________________________________________________ + + More info: + + See also this article for some some general info and examples using + stunnel and openssl on Windows with VNC. Also + http://www.stunnel.org/faq/certs.html is a very good source of + information on SSL certificate creation and management. + +======================================================================= +http://www.karlrunge.com/x11vnc/ssl-portal.html: + + + _________________________________________________________________ + + Using Apache as an SSL Gateway to multiple x11vnc servers inside a + firewall: + + Background: + + The typical way to allow access to x11vnc (or any other VNC server) + running on multiple workstations inside a firewall is via SSH. The + user somewhere out on the Internet logs in to the SSH gateway machine + and uses port forwarding (e.g. ssh -t -L 5900:myworkstation:5900 + user@gateway) to set up the encrypted channel that VNC is then + tunneled through. Next he starts up the VNC viewer on the machine + where he is sitting directed to the local tunnel port (e.g. + localhost:0). + + The SSH scheme is nice because it is a widely used and well tested + login technique for users connecting to machines inside their company + or home firewall. For VNC access it is a bit awkward, however, because + SSH needs to be installed on the Viewer machine and the user usually + has to rig up his own port redirection plumbing (however, see our + other tool). + + Also, some users have restrictive work environments where SSH and + similar applications are prohibited (i.e. only outgoing connections to + standard WWW ports from a browser are allowed, perhaps mediated by a + proxy server). These users have successfully used the method described + here for remote access. + + With the SSL support in x11vnc and the SSL enabled Java VNC viewer + applet, a convenient and secure alternative exists that uses the + Apache webserver as a gateway. The idea is that the company or home + internet connection is already running apache as a web server (either + SSL or non-SSL) and we add to it the ability to act as a gateway for + SSL VNC connections. The only thing needed on the Viewer side is a + Java enabled Web Browser: the user simply enters a URL that starts the + entire VNC connection process. No VNC or SSH specific software needs + to be installed on the viewer side machine. + + The stunnel VNC viewer stunnel wrapper script provided (ss_vncviewer) + can also take advantage of the method described here with its -proxy + option. + + _________________________________________________________________ + + Simpler Solutions: This apache SSL VNC portal solution may be too much + for you. It is mainly intended for automatically redirecting to + MULTIPLE workstations inside the firewall. If you only have one or two + inside machines that you want to access, the method described here is + overly complicated! See below for some simpler (and still non-SSH) + encrypted setups. + + Also see the recent (Mar/2010) desktop.cgi x11vnc desktop web login + CGI script that achieves much of what the method describes here + (especially if its 'port redirection' feature is enabled.) + _________________________________________________________________ + + + + There are numerous ways to achieve this with Apache. We present one of + the simplest ones here. + + Important: these sorts of schemes allow incoming connections from + anywhere on the Internet to fixed ports on machines inside the + firewall. Care must be taken to implement and test thoroughly. If one + is paranoid one can (and should) add extra layers of protection. (e.g. + extra passwords, packet filtering, SSL certificate verification, etc). + + Also, it is easy to miss the point that unless precautions are taken + to verify SSL Certificates, then the VNC Viewer is vulnerable to + man-in-the-middle attacks (but not to the more common passive sniffing + attacks). Note that there are hacker tools like dsniff/webmitm and + cain that implement SSL Man-In-The-Middle attacks. They rely on the + client not bothering to check the cert. + _________________________________________________________________ + + The Holy Grail: a single https port (443) + + Before we discuss the self-contained apache examples here, we want to + mention that many x11vnc users who read this page and implement the + apache SSL VNC portal ask for something that (so far) seems difficult + or impossible to do entirely inside apache: + * A single port, 443 (the default https:// port), is open to the + Internet + * It is HTTPS/SSL encrypted + * It handles both VNC traffic and Java VNC Applet downloads. + * And the server can also serve normal HTTPS webpages, CGI, etc. + + It is the last item that makes it tricky (otherwise the method + described on this page will work). If you are interested in such a + solution and are willing to run a separate helper program + (connect_switch) look here. Also, see this apache patch. + _________________________________________________________________ + + Example: + + The scheme described here sets up apache on the firewall/gateway as a + regular Web proxy into the intranet and allows connections to a single + fixed port on a limited set of machines. + + The configuration described in this section does not use the mod_ssl + apache module (the optional configuration described in the section + "Downloading the Java applet to the browser via HTTPS" does take + advantage of mod_ssl) + + In this example suppose the gateway machine running apache is named + "www.gateway.east" (e.g. it may also provide normal web service). We + also choose the Internet-facing port for this VNC service to be port + 563. One could choose any port, including the default HTTP port 80. + + Detail: We choose 563 because it is the rarely used SNEWS port that is + often allowed by Web proxies for the CONNECT method. The idea is the + user may be coming out of another firewall using a proxy (not the one + we describe here, that is, the case when two proxies are involved, + e.g. one at work and another Apache (described here) at home + redirecting into our firewall; the "double proxy" or "double firewall" + problem). Using port 563 simplifies things because CONNECT's to it are + usually allowed by default. + + We also assume all of the x11vnc servers on the internal machines are + all listening on port 5915 ("-rfbport 5915") instead of the default + 5900. This is to limit any unintended proxy redirections to a lesser + used port, and also to stay out of the way of normal VNC servers on + the same machines. One could obviously implement a scheme that handles + different ports, but we just discuss this simple setup here. + + So we basically assume x11vnc has been started this way on all of the + workstations to be granted VNC access: + x11vnc -ssl SAVE -http -display :0 -forever -rfbauth ~/.vnc/passwd -rfbport 5 +915 + + i.e. we force SSL VNC connections, port 5915, serve the Java VNC + viewer applet, and require a VNC password (another option would be + -unixpw). The above command could also be run out of inetd(8). It can + also be used to autodetect the user's display and Xauthority data. + + + These sections are added to the httpd.conf apache configuration file + on www.gateway.east: + +# In the global section you need to enable these modules. +# Note that the ORDER MATTERS! mod_rewrite must be before mod_proxy +# (so that we can check the allowed host list via rewrite) +# +LoadModule rewrite_module modules/mod_rewrite.so +LoadModule proxy_module modules/mod_proxy.so +LoadModule proxy_connect_module modules/mod_proxy_connect.so +LoadModule proxy_ftp_module modules/mod_proxy_ftp.so +LoadModule proxy_http_module modules/mod_proxy_http.so + +LoadModule ssl_module modules/mod_ssl.so + + + +# Near the bottom of httpd.conf you put the port 563 virtual host: + +Listen 563 + + + + # Allow proxy CONNECT requests *only* to port 5915. + # If the machines use different ports, e.g. 5916 list them here as well: + # + ProxyRequests On + AllowCONNECT 5915 + + RewriteEngine On + + # Convenience rules to expand applet parameters. These do not have a traili +ng "/" + # + # /vnc for http jar file downloading: + # + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1 [R,NE,L] + RewriteRule /vnc/trust/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&trustAllVncCerts=yes [R,NE,L] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,NE,L] + RewriteRule /vnc/trust/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes&trustAllVncCerts=yes [R,NE,L] + + # Read in the allowed host to vnc display mapping file. It looks like: + # + # host1 15 + # host2 15 + # ... + # + # the display "15" means 5815 for http applet download, 5915 for SSL vnc. + # + RewriteMap vnchosts txt:/dist/apache/conf/vnc.hosts + + # Proxy: check for the CONNECT hostname and port being in the vnc.hosts list +. + # + RewriteCond %{THE_REQUEST} ^CONNECT [NC] + RewriteCond %{REQUEST_URI} ^(.*):(.*)$ + RewriteCond ${vnchosts:%1|NOTFOUND} NOTFOUND + RewriteRule ^.*$ /VNCFAIL [F,L] + + RewriteCond %{THE_REQUEST} ^CONNECT [NC] + RewriteCond %{REQUEST_URI} ^(.*):(.*)$ + RewriteCond 59${vnchosts:%1}=%2 !^(.*)=(\1)$ + RewriteRule ^.*$ /VNCFAIL [F,L] + + + # Remap /vnc to the proxy http download (e.g. http://host:5815) + # + # First, fail if it starts with the string /vnc0: + # + RewriteRule ^/vnc0.* /VNCFAIL [F,L] + # + # Next, map the prefix to /vnc0/host:protocol:port + # + RewriteRule ^/vnc/([^/]+)/(.*) /vnc0/$1:http:58${vnchosts:$1|NOTFOUND}/$2 +[NE] + # + # Drop any not found: + # + RewriteRule ^/vnc0.*NOTFOUND.* /VNCFAIL [F,L] + + # Construct the proxy URL and retrieve it: + # + RewriteRule ^/vnc0/([^/]+):([^/]+):([^/]+)/(.*) $2://$1:$3/$4 [P,NE,L] + + + + Then restart apache (perhaps: "apachectl stop; apachectl start"). + + Note that the listing of allowed internal workstations is done in an + external file (/dist/apache/conf/vnc.hosts in the example above), the + format is like this: +# allowed vnc hosts file: +hostname1 15 +hostname2 15 +... + + You list the hostname and the VNC display (always 15 in our example). + Only to these hosts will the external VNC viewers be able to connect + to (via the HTTP CONNECT method). + + The above setup requires mod_rewrite and mod_proxy be enabled in the + apache web server. In this example they are loaded as modules (and + note that mod_rewrite must be listed before mod_proxy); + + The user at the Java enabled Web browser would simply enter this URL + into the browser: + http://www.gateway.east:563/vnc/host2 + + to connect to internal workstation host2, etc. + + Important: do not put a trailing "/" on the URL, since that will + defeat the RewriteRules that look for the hostname at the very end. + + There will be a number of SSL certificate, etc, dialogs he will have + to respond to in addition to any passwords he is required to provide + (this depends on how you set up user authentication for x11vnc). + + If a second Web proxy is involved (i.e. the user's browser is inside + another firewall and policy requires using a Web proxy server) then + use this URL: + http://www.gateway.east:563/vnc/proxy/host2 + + This will involve downloading a signed java viewer applet jar file + that is able to interact with the internal proxy for the VNC + connection. See this FAQ for more info on how this works. Note: + sometimes with the Proxy case if you see 'Bad Gateway' error you will + have to wait 10 or so seconds and then hit reload. This seems to be + due to having to wait for a Connection Keepalive to terminate... + + For completeness, the "trust" cases that skip a VNC certificate dialog + (discussed below) would be entered as: + http://www.gateway.east:563/vnc/trust/host2 + http://www.gateway.east:563/vnc/trust/proxy/host2 + + You can of course choose shorter or more easy to remember URL formats. + Just change the Convenience RewriteRules in httpd.conf. + + _________________________________________________________________ + + Port Variations: + + Note that you can run this on the default HTTP port 80 instead of port + 563. If you do not expect to have a browser connecting from inside a + proxying firewall (where sometimes only connections to ports 443 and + 563 are allowed) this should be fine. Use "80" instead of "563" in the + httpd.conf config file (you may need to merge it with other default + port 80 things you have there). + + Then the URL's will be a bit simpler: + http://www.gateway.east/vnc/host2 + http://www.gateway.east/vnc/trust/host2 + + etc. + + Besides 80 one could use any other random port number (since there are + so many port scans on 80, a little obscurity might be useful). + + One option is to use port "443" (the default https:// port) instead of + "563". In this case Apache is not configured for mod_ssl; we just + happen to use port "443" in the way any random port would be used. + This could be handy if the Viewer side environment is restrictive in + that it only allows outgoing connections to ports 80 and 443 (and, + say, you didn't want to use port 80, or you wanted to use 80 for + something else). Another reason for using 443 would be some web proxy + environments only allow the CONNECT method to go to port 443 (and not + even the case 563 we use above). + + _________________________________________________________________ + + Details: + + Let's go through the httpd.conf additions in detail from the top. + + The LoadModules directives load the necessary apache modules. Note + that mod_rewrite must be listed first. If you are compiling from + scratch something like this worked for us: + ./configure --enable-proxy=shared --enable-proxy-connect=shared --enable-ssl= +shared --enable-rewrite=shared --prefix=/dist/apache + + Then the VirtualHost *:563 virtual host section starts. + + The "ProxyRequests On" and "AllowCONNECT 5915" enable the web server + to forward proxy requests to port 5915 (and only this port) INSIDE the + firewall. Think about the implications of this thoroughly and test it + carefully. + + The RewriteRule's are for convenience only so that the URL entered + into the Web browser does not need the various extra parameters, e.g.: + http://www.gateway.east:563/vnc/host2/index.vnc?CONNECT=host2+5915&PORT=563, +blah,blah... + + (or otherwise make direct edits to index.vnc to set these parameters). + The forceProxy=yes parameter is passed to the applet to force the use + of a outgoing proxy socket connection. Use it only if the Web browser + is inside a separate Web proxying environment (i.e. large corporation) + + The rewrites with parameter urlPrefix are described under Tricks for + Better Response. The "trust" ones (also described under Tricks) with + trustAllVncCerts tell the Java VNC applet to skip a dialog asking + about the VNC Certificate. They are a bit faster and more reliable + than the original method. In the best situation they lead to being + logged in 20 seconds or less (without them the time to login can be + much longer since a number of connections must timeout). + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + The external file /dist/apache/conf/vnc.hosts containing the allowed + VNC server hostnames is read in. Its 2nd column contains the VNC + display of the host (always 15 in our example; if you make it vary you + will need to adjust some lines in the httpd.conf accordingly, e.g. + AllowCONNECT). This list is used to constrain both the Jar file + download URL and the proxy CONNECT the VNC viewer makes to only the + intended VNC servers. + + Limiting the proxy CONNECT is done with the two sets of RewriteCond + conditions. + + Limiting the Jar file download URL is done in the remaining 4 + RewriteRule's. + + Note that these index.vnc and VncViewer.jar downloads to the browser + are not encrypted via SSL, and so in principle could be tampered with + by a really bad guy. The subsequent VNC connection, however, is + encrypted through a single SSL connection (it makes a CONNECT straight + to x11vnc). See below for how to have these initial downloads + encrypted as well (if the apache web server has SSL/mod_ssl, i.e. + https, enabled and configured). + + Unfortunately the Java VNC viewer applet currently is not able to save + its own list of Certificates (e.g. the user says trust this VNC + certificate 'always'). This is because an applet it cannot open local + files, etc. Sadly, the applet cannot even remember certificates in the + same browser session because it is completely reinitialized for each + connection (see below). + + _________________________________________________________________ + + Too Much? + + If these apache rules are a little too much for you, there is a little + bit simpler scheme where you have to list each of the individual + machines in the httpd.conf and ssl.conf files. It may be a little more + typing to maintain, but perhaps being more straight forward (less + RewriteRule's) is desirable. + + _________________________________________________________________ + + Problems? + + To see example x11vnc output for a successful https://host:5900/ + connection with the Java Applet see This Page. + + _________________________________________________________________ + + Some Ideas for adding extra authentication, etc. for the paranoid: + * VNC passwords: -rfbauth, -passwdfile, or -usepw. Even adding a + simple company-wide VNC password helps block unwanted access. + * Unix passwords: -unixpw + * SSL Client certificates: -sslverify + * Apache AuthUserFile directive: .htaccess, etc. + * Filter connections based on IP address or hostname. + * Use Port-knocking on your firewall as described in: Enhanced + TightVNC Viewer (ssvnc). + * Add proxy password authentication (requires Viewer changes?) + * Run a separate instance of Apache that provides this VNC service + so it can be brought up and down independently of the normal web + server. + * How secure is the Client side? Public machines in internet cafes, + etc, are often hacked, with backdoors and VNC servers of their + own. Prefer using your own firewalled laptop to a public machine. + + + _________________________________________________________________ + + Using non-Java viewers with this scheme: + + The ss_vncviewer stunnel wrapper script for VNC viewers has the -proxy + option that can take advantage of this method. + ss_vncviewer -proxy www.gateway.east:563 host1:15 + + For the case of the "double proxy" situation (see below) supply both + separated by a comma. + ss_vncviewer -proxy proxy1.foobar.com:8080,www.gateway.east:563 host1:15 + + For the Enhanced TightVNC Viewer (ssvnc) GUI (it uses ss_vncviewer on + Unix) put 'host1:15' into the 'VNC Server' entry box, and here are + possible Proxy/Gateway entries + Proxy/Gateway: www.gateway.east:563 + Proxy/Gateway: proxy1.foobar.com:8080,www.gateway.east:563 + + then click on the 'Connect' button. + + _________________________________________________________________ + + Downloading the Java applet to the browser via HTTPS: + + To have the Java applet downloaded to the user's Web Browser via an + encrypted (and evidently safer) SSL connection the Apache webserver + should be configured for SSL via mod_ssl. + + It is actually possible to use the x11vnc Key Management utility + "-sslGenCert" to generate your Apache/SSL .crt and .key files. (In + brief, run something like "x11vnc -sslGenCert server self:apache" then + copy the resulting self:apache.crt file to conf/ssl.crt/server.crt and + extract the private key part from self:apache.pem and paste it into + conf/ssl.key/server.key). Setting the env var REQ_ARGS='-days 1095' + before running x11vnc will bump up the expiration date (3 years in + this case). + + Or you can use the standard methods described in the Apache mod_ssl + documentation to create your keys. Then restart Apache, usually + something like "apachectl stop" followed by "apachectl startssl" + + In addition to the above sections in httpd.conf one should add the + following to ssl.conf: + SSLProxyEngine On + + RewriteEngine On + + # Convenience rules to expand applet parameters. These do not have a traili +ng "/" + # + # /vnc http jar file downloading: + # + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1 [R,NE,L] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,N +E,L] + # + # (we skipped the "trust" ones above, put them in if you like) + # + # /vncs https jar file downloading: + # + RewriteRule /vncs/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1 [R,NE,L] + RewriteRule /vncs/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes [R, +NE,l] + RewriteRule /vncs/trust/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&trustAllVncCerts=y +es [R,NE,L] + RewriteRule /vncs/trust/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes&tru +stAllVncCerts=yes [R,NE,L] + + # Convenience rules used for the connect_switch helper (requires Listen 127. +0.0.1:443 above): + # + RewriteRule /vnc443/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1 [R,NE,L] + RewriteRule /vnc443/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes [R, +NE,L] + RewriteRule /vnc443/trust/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&trustAllVncCerts=y +es [R,NE,L] + RewriteRule /vnc443/trust/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$ +1+5915&PORT=443&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes&tru +stAllVncCerts=yes [R,NE,L] + + # Read in the allowed host to vnc display mapping file. It looks like: + # + # host1 15 + # host2 15 + # ... + # + # the display "15" means 5915 for SSL VNC and 5815 for http applet download. + # + RewriteMap vnchosts txt:/dist/apache/conf/vnc.hosts + + + # Remap /vnc and /vncs to the proxy http download (e.g. https://host:5915) + # + # First, fail if it starts with the string /vnc0: + # + RewriteRule ^/vnc0.* /VNCFAIL [F,L] + # + # Next, map the prefix to /vnc0:host:protocol:port + # + RewriteRule ^/vnc/([^/]+)/(.*) /vnc0/$1:http:58${vnchosts:$1|NOTFOUND}/$2 +[NE] + RewriteRule ^/vncs/([^/]+)/(.*) /vnc0/$1:https:59${vnchosts:$1|NOTFOUND}/$2 +[NE] + # + # Drop any not found: + # + RewriteRule ^/vnc0.*NOTFOUND.* /VNCFAIL [F,L] + + # Construct the proxy URL and retrieve it: + # + RewriteRule ^/vnc0/([^/]+):([^/]+):([^/]+)/(.*) $2://$1:$3/$4 [P,NE,L] + + This is all in the "" section of ssl.conf. + + The user could then point the Web Browser to: + https://www.gateway.east/vnc/host2 + + or + https://www.gateway.east/vnc/proxy/host2 + + for the "double proxy" case. (Important: do not put a trailing "/" on + the URL, since that will defeat the RewriteRules.) + + As with the httpd.conf case, the external file + (/dist/apache/conf/vnc.hosts in the above example) contains the + hostnames of the allowed VNC servers. + + Note that inside the firewall the Java applet download traffic is not + encrypted (only over the Internet is SSL used) for these cases: + https://www.gateway.east/vnc/host2 + https://www.gateway.east/vnc/proxy/host2 + + However for the special "vncs" rules above: + https://www.gateway.east/vncs/host2 + + the Java applet download is encrypted via SSL for both legs. Note that + the two legs are two separate SSL sessions. So the data is decrypted + inside an apache process and reencrypted by the apache process for the + 2nd SSL session inside the same apache process (a very small gap one + might overlook). + + The "vncs/trust" ones are like the "trust" ones described earlier + https://www.gateway.east/vncs/trust/mach2 + + and similarly for the httpsPort ones. See Tricks for Better Response. + + In all of the above cases the VNC traffic from Viewer to x11vnc is + encrypted end-to-end in a single SSL session, even for the "double + proxy" case because the CONNECT method is used (there are actually two + CONNECT's for the "double proxy" case). This part (the VNC traffic) is + the most important part to have encrypted. + + Note that the Certificate dialogs the user has in his web browser will + be for the Apache Certificate, while for the Java applet it will be + the x11vnc certificate. + + Note also that you can have Apache serve up the Jar file VncViewer.jar + and/or index.vnc/proxy.vnc instead of each x11vnc if you want to. + + The rules in ssl.conf are similar to the ones in httpd.conf and so are + not discussed in detail. The only really new thing is the /vncs + handling to download the applet jar via HTTPS on port 5915. + + The special entries "/vnc443" are only used for the special helper + program (connect_switch) for the https port 443 only mode discussed + here. + + _________________________________________________________________ + + INETD automation: + + The "single-port" (i.e. 5915) HTTPS applet download and VNC connection + aspect shown here is convenient and also enables having x11vnc run out + of inetd. That way x11vnc is run on demand instead of being run all + the time (the user does not have to remember to start it). The first + connections to inetd download index.vnc and the Jar file (via https) + and the the last connection to inetd establishes the SSL VNC + connection. Since x11vnc is restarted for each connection, this will + be a bit slower than the normal process. + + For example, the /etc/inetd.conf line could be: + 5915 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc_ssl.sh + + where the script x11vnc_ssl.sh looks something like this: +#!/bin/sh + +/usr/local/bin/x11vnc -inetd -oa /var/log/x11vnc-15.log \ + -ssl SAVE -http -unixpw -localhost \ + -display :0 -auth /home/THE_USER/.Xauthority + + where, as usual, the inetd launching needs to know which user is + typically using the display on that machine. One could imagine giving + different users different ports, 5915, 5916, etc. to distinguish (then + the script would need to be passed the username). mod_rewrite could be + used to automatically map username in the URL to his port number. + + A better way is to use the "-display WAIT:cmd=FINDDISPLAY" feature to + autodetect the user and Xauthority data: +#!/bin/sh + +/usr/local/bin/x11vnc -inetd -oa /var/log/x11vnc-15.log \ + -ssl SAVE -http -unixpw -localhost -users unixpw= \ + -find + + (we have used the alias -find for "-display WAIT:cmd=FINDDISPLAY".) + This way the user must supply his Unix username and password and then + his display and Xauthority data on that machine will be located and + returned to x11vnc to allow it to attach. If he doesn't have a display + running on that machine or he fails to log in correctly, the + connection will be dropped. + + The variant "-display WAIT:cmd=FINDCREATEDISPLAY" (aliased by + "-create") will actually create a (virtual or real) X server session + for the user if one doesn't already exist. See here for details. + + To enable inetd operation for the non-HTTPS Java viewer download (port + 5815 in the above httpd.conf example) you will need to run x11vnc in + HTTPONCE mode on port 5815: For example, the /etc/inetd.conf line + could be: + 5815 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc \ + -inetd -prog /usr/local/bin/x11vnc -oa /var/log/x11vnc-15.log \ + -http_ssl -display WAIT:cmd=HTTPONCE + + where the long inetd.conf line has been split. Note how the -http_ssl + tries to automatically find the .../classes/ssl subdirectory. This + requires the -prog option available in x11vnc 0.8.4 (a shell script + wrapper, e.g. /usr/local/bin/x11vnc_http.sh can be used to work around + this). + + Also note the use of "-ssl SAVE" above. This way a saved server.pem is + used for each inetd invocation (rather generating a new one each time + as happens for "-ssl TMP"). Note that it cannot have a protecting + passphrase because inetd will not be able to supply it. + + Another option is: + 5815 stream tcp nowait root /usr/sbin/tcpd /usr/local/bin/x11vnc \ + -inetd -httpdir /usr/local/share/x11vnc/classes/ssl \ + -oa /var/log/x11vnc-15.log -display WAIT:cmd=HTTPONCE + + (this also requires a feature found in x11vnc 0.8.4). + _________________________________________________________________ + + Other Ideas: + + - The above schemes work, but they are a bit complicated with all of + the rigging. There should be more elegant ways to configure Apache to + do these, but we have not found them (please let us know if you + discover something nice). However, once this scheme has been set up + and is working it is easy to maintain and add/delete workstations, + etc. + + - In general Apache is not required, but it makes things convenient. + The firewall itself could do the port redirection via its firewall + rules. Evidently different Internet-facing ports would be required for + each workstation. This could be set up using iptables rules for + example. If there were just one or two machines this would be the + easiest method. For example: + iptables -t nat -A PREROUTING -p tcp -d 24.35.46.57 --dport 5901 -j DNAT --to +-destination 192.168.1.2:5915 + iptables -t nat -A PREROUTING -p tcp -d 24.35.46.57 --dport 5902 -j DNAT --to +-destination 192.168.1.3:5915 + + Where 24.35.46.57 is the internet IP address of the gateway. In this + example 24.35.46.57:5901 is redirected to the internal machine + 192.168.1.2:5915 and 24.35.46.57:5902 is redirected to another + internal machine 192.168.1.3:5915, both running x11vnc -ssl ... in SSL + mode. For this example, the user would point the web browser to, e.g.: + https://24.35.46.57:5901/?PORT=5901 + + or using the stunnel wrapper script: + ss_vncviewer 24.35.46.57:1 + + One can achieve similar things with dedicated firewall/routers (e.g. + Linksys) using the device's web or other interface to configure the + firewall. + + If the user may be coming out of a firewall using a proxy it may be + better to redirect ports 443 and 563 (instead of 5901 and 5902) to the + internal machines so that the user's proxy will allow CONNECTing to + them. + + - The redirection could also be done at the application level using a + TCP redirect program (e.g. ip_relay or fancier ones). Evidently more + careful internal hostname checking, etc., could be performed by the + special purpose application to add security. See connect_switch which + is somewhat related. + + - One might imagine the ProxyPass could be done for the VNC traffic as + well (for the ssl.conf case) to avoid the CONNECT proxying completely + (which would be nice to avoid). Unfortunately we were not able to get + this to work. Since HTTP is a request-response protocol (as opposed to + a full bidirectional link required by VNC that CONNECT provides) this + makes it difficult to do. It may be possible, but we haven't found out + how yet. + + All of the x11vnc Java Viewer applet parameters are described in the + file classes/ssl/README + + _________________________________________________________________ + + Tricks for Better Response and reliability: + + The "original scheme" using httpd.conf and ssl.conf rewrites without + urlPrefix and trustAllVncCerts above should work OK, but may lead to + slow and/or unreliable loading of the applet and final connection to + x11vnc. The following are what I do now to get better response and + reliability. YMMV. + + The problem with the "original scheme" is that there is a point where + the VNC Viewer applet can try up to 3 times to retrieve the x11vnc + certificate, since it needs to get it to show it to you and ask you if + you accept it. This can add about 45 seconds to the whole process + (which takes 1 to 1.5 minutes with all the dialogs) since a couple of + those connections must time out. The "trust" items in the config add a + parameter trustAllVncCerts=yes similar to the forceProxy=yes + parameter. This can cut the total time to the VNC password prompt down + to 15 seconds which is pretty good. (Note by ignoring the certificate + this does not protect against man-in-the-middle attacks which are + rare, but maybe the won't be so rare in the future... see + dsniff/webmitm and cain) + + First make sure the x11vnc SSL certificate+key is the same as + Apache's. (otherwise you may get one extra dialog and/or one extra + connection that has to time out). + + The following RewriteRule's are the same now advocated in the + instructions above. + + The httpsPort and urlPrefix= parameters give hints to the applet to + improve connecting: This is what goes in httpd.conf: + RewriteEngine On + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1 [R,NE] + RewriteRule /vnc/trust/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&trustAllVncCerts=yes [R,NE] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,NE] + RewriteRule /vnc/trust/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&PO +RT=563&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes&trustAllVncCerts=yes [R,NE] + + The httpsPort and urlPrefix provide useful hints to the VNC Viewer + applet when it connects to x11vnc to glean information about Proxies, + certificates, etc. + + This is what goes into ssl.conf: + RewriteEngine On + RewriteRule /vnc/([^/]+)$ /vnc/$1/index.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1 [R,NE] + RewriteRule /vnc/proxy/([^/]+)$ /vnc/$1/proxy.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vnc_2F_$1&forceProxy=yes [R,NE] + RewriteRule /vncs/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1 [R,NE] + RewriteRule /vncs/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes [R,NE] + RewriteRule /vncs/trust/([^/]+)$ /vncs/$1/index.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&trustAllVncCerts=yes [R,NE +] + RewriteRule /vncs/trust/proxy/([^/]+)$ /vncs/$1/proxy.vnc?CONNECT=$1+5915&P +ORT=563&httpsPort=443&GET=1&urlPrefix=_2F_vncs_2F_$1&forceProxy=yes&trustAllVnc +Certs=yes [R,NE] + + The rest is the same. + + The httpsPort and urlPrefix and GET provide useful hints to the VNC + Viewer applet when it connects to x11vnc to glean information about + Proxies, certificates, etc, and also for the ultimate VNC connection + (GET speeds this up by sending a special HTTP GET to cause x11vnc to + immediately switch to the VNC protocol). + + To turn these into URLs, as was done above, take the string in the + RewriteRule, e.g. /vncs and turn it into + https://gateway/vncs/machinename Similarly for non-https: + http://gateway:563/vnc/machinename + + If you use the 'trust' ones, you are performing NO checks, visual or + otherwise, on the VNC SSL certificate. It is trusted without question. + This speeds things up because it avoids a dialog about certificates, + but of course has some risk WRT Man in the Middle attacks. I don't + recommend them. It is better to use /vnc or /vncs and the first time + you connect carefully check the Certificate and then tell your Browser + and Java Virtual Machine to trust the certificate 'Always'. Then if + you later get an unexpected dialog, you know something is wrong. + Nearly always it is just a changed or expired certificate, but better + safe than sorry... + +======================================================================= +http://www.karlrunge.com/x11vnc/enhanced_tightvnc_viewer.html: + + + _________________________________________________________________ + +Enhanced TightVNC Viewer (SSVNC: SSL/SSH VNC viewer) + + (To Downloads) (To Quick Start) + + [ssvnc.gif] [ssvnc_windows.gif] [ssvnc_macosx.gif] . . + + + The Enhanced TightVNC Viewer, SSVNC, adds encryption security to VNC + connections. + + The package provides a GUI for Windows, Mac OS X, and Unix that + automatically starts up an STUNNEL SSL tunnel for SSL or ssh/plink for + SSH connections to any VNC server, such as x11vnc, and then launches + the VNC Viewer to use the encrypted tunnel. + + The x11vnc server has built-in SSL support, however SSVNC can make SSL + encrypted VNC connections to any VNC Server if they are running an SSL + tunnel, such as STUNNEL or socat, at their end. SSVNC's SSH tunnel + will work to any VNC Server host running sshd that you can log into. + + The Enhanced TightVNC Viewer package started as a project to add some + patches to the long neglected Unix TightVNC Viewer. However, now the + front-end GUI, encryption, and wrapper scripts features possibly + outweigh the Unix TightVNC Viewer improvements (see the lists below to + compare). + + The SSVNC Unix vncviewer can also be run without the SSVNC encryption + GUI as an enhanced replacement for the xvncviewer, xtightvncviewer, + etc., viewers. + + In addition to normal SSL, SSVNC also supports the VeNCrypt SSL/TLS + and Vino/ANONTLS encryption extensions to VNC on Unix, Mac OS X, and + Windows. Via the provided SSVNC VeNCrypt bridge, VeNCrypt and ANONTLS + encryption also works with any third party VNC Viewer (e.g. RealVNC, + TightVNC, UltraVNC, etc...) you select via 'Change VNC Viewer'. + + The short name for this project is "ssvnc" for SSL/SSH VNC Viewer. + This is the name of the command to start it. + + There is a simplified SSH-Only mode (sshvnc). And an even more + simplified Terminal-Services mode (tsvnc) for use with x11vnc on the + remote side. + + It is also possible (although not recommended) to disable encryption: + -noenc cmdline option; Ctrl-E toggle; or Vnc:// host prefix; see the + online Help for details. + + The tool has many additional features; see the descriptions below. + + It is a self-contained bundle, you could carry it around on, say, a + USB memory stick / flash drive for secure VNC viewing from almost any + machine, Unix, Mac OS X, and Windows (and if you create a directory + named "Home" in the toplevel ssvnc directory on the drive your VNC + profiles and certs will be kept there as well). For Unix, there is + also a conventional source tarball to build and install in the normal + way and not use a pre-built bundle. + + _________________________________________________________________ + + Announcements: + + Important: If you created any SSL certificates with SSVNC (or anything + else) on a Debian or Ubuntu system from Sept. 2006 through May 2008, + then those keys are likely extremely weak and can be easily cracked. + The certificate files should be deleted and recreated on a non-Debian + system or an updated one. See + http://www.debian.org/security/2008/dsa-1571 for details. The same + applies to SSH keys. + + Please read this information on using SSVNC on workstations with + Untrusted Local Users. + + _________________________________________________________________ + + Feature List: + + Wrapper scripts and a tcl/tk GUI were written to create these features + for Unix, Mac OS X, and Windows: + * SSL support for connections using the bundled stunnel program. + * Automatic SSH connections from the GUI (system ssh is used on Unix + and MacOS X; bundled plink is used on Windows) + * Ability to Save and Load VNC profiles for different hosts. + * You can also use your own VNC Viewer, e.g. UltraVNC or RealVNC, + with the SSVNC encryption GUI front-end if you prefer. + * Create or Import SSL Certificates and Private Keys. + * Reverse (viewer listening) VNC connections via SSL and SSH. + * VeNCrypt SSL/TLS VNC encryption support (used by VeNCrypt, QEMU, + ggi, libvirt/virt-manager/xen, vinagre/gvncviewer/gtk-vnc) + * ANONTLS SSL/TLS VNC encryption support (used by Vino) + * VeNCrypt and ANONTLS are also enabled for any 3rd party VNC Viewer + (e.g. RealVNC, TightVNC, UltraVNC ...) on Unix, MacOSX, and + Windows via the provided SSVNC VeNCrypt Viewer Bridge tool (use + 'Change VNC Viewer' to select the one you want.) + * Support for Web Proxies, SOCKS Proxies, and the UltraVNC repeater + proxy (e.g. repeater://host:port+ID:1234). Multiple proxies may be + chained together (3 max). + * Support for SSH Gateway connections and non-standard SSH ports. + * Automatic Service tunnelling via SSH for CUPS and SMB Printing, + ESD/ARTSD Audio, and SMB (Windows/Samba) filesystem mounting. + * Sets up any additional SSH port redirections that you want. + * Zeroconf (aka Bonjour) is used on Unix and Mac OS X to find VNC + servers on your local network if the avahi-browse or dns-sd + program is available and in your PATH. + * Port Knocking for "closed port" SSH/SSL connections. In addition + to a simple fixed port sequence and one-time-pad implementation, a + hook is also provided to run any port knocking client before + connecting. + * Support for native MacOS X usage with bundled Chicken of the VNC + viewer (the Unix X11 viewer is also provided for MacOS X, and is + better IMHO. It is now the default on MacOS X.) + * Dynamic VNC Server Port determination and redirection (using ssh's + builtin SOCKS proxy, ssh -D) for servers like x11vnc that print + out PORT= at startup. + * Unix Username and Password entry for use with "x11vnc -unixpw" + type login dialogs. + * Simplified mode launched by command "sshvnc" that is SSH Only. + * Simplified mode launched by command "tsvnc" that provides a VNC + "Terminal Services" mode (uses x11vnc on the remote side). + * IPv6 support for all connection modes on Unix, MacOSX, and + Windows. + + Patches to TightVNC 1.3.9 vnc_unixsrc tree were created for Unix + TightVNC Viewer improvements (these only apply to the Unix VNC viewer, + including MacOSX XQuartz): + * rfbNewFBSize VNC support (dynamic screen resizing) + * Client-side Scaling of the Desktop in the viewer. + * ZRLE VNC encoding support (RealVNC's encoding) + * Support for the ZYWRLE encoding, a wavelet based extension to ZRLE + to improve compression of motion video and photo regions. + * TurboVNC support (VirtualGL's modified TightVNC encoding; requires + TurboJPEG library) + * Pipelined Updates of the framebuffer as in TurboVNC (asks for the + next update before the current one has finished downloading; this + gives some speedup on high latency connections.) + * Cursor alphablending with x11vnc at 32bpp (-alpha option) + * Option "-unixpw ..." for use with "x11vnc -unixpw" type login + dialogs. + * Support for UltraVNC extensions: 1/n Server side scaling, Text + Chat, Single Window, Disable Server-side Input. Both UltraVNC and + x11vnc servers support these extensions. + * UltraVNC File Transfer via an auxiliary Java helper program (java + must be in $PATH). Note that the x11vnc server also supports + UltraVNC file transfer. + * Connection support for the UltraVNC repeater proxy (-repeater + option). + * Support for UltraVNC Single Click operation. (both unencrypted: SC + I, and SSL encrypted: SC III) + * Support for UltraVNC DSM Encryption Plugin symmetric encryption + mode. (ARC4, AESV2, MSRC4, and SecureVNC) + * Support for UltraVNC MS-Logon authentication (NOTE: the UltraVNC + MS-Logon key exchange implementation is very weak; an eavesdropper + on the network can recover your Windows password easily in a few + seconds; you need to use an additional encrypted tunnel with + MS-Logon.) + * Support for symmetric encryption (including blowfish and 3des + ciphers) to Non-UltraVNC Servers. Any server using the same + encryption method will work, e.g.: x11vnc -enc blowfish:./my.key + * Instead of hostname:display one can also supply "exec=command + args..." to connect the viewer to the stdio of an external command + (e.g. stunnel or socat) rather than using a TCP/IP socket. Unix + domain sockets, e.g. /path/to/unix/socket, and a previously opened + file descriptor fd=0, work too. + * Local Port Protections for STUNNEL and SSH: avoid having for long + periods of time a listening port on the the local (VNC viewer) + side that redirects to the remote side. + * Reverse (viewer listening) VNC connections can show a Popup dialog + asking whether to accept the connection or not (-acceptpopup.) The + extra info provided by UltraVNC Single Click reverse connections + is also supported (-acceptpopupsc) + * Extremely low color modes: 64 and 8 colors in 8bpp + (-use64/-bgr222, -use8/-bgr111) + * Medium color mode: 16bpp mode on a 32bpp Viewer display + (-16bpp/-bgr565) + * For use with x11vnc's client-side caching -ncache method use the + cropping option -ycrop n. This will "hide" the large pixel buffer + cache below the actual display. Set to the actual height or use -1 + for autodetection (also, tall screens, H > 2*W, are autodetected + by default). + * Escape Keys: specify a set of modifier keys so that when they are + all pressed down you can invoke Popup menu actions via keystrokes. + I.e., a set of 'Hot Keys'. One can also pan (move) the desktop + inside the viewport via Arrow keys or a mouse drag. + * Scrollbar width setting: -sbwidth n, the default is very thin, 2 + pixels, for less distracting -ycrop usage. + * Selection text sending and receiving can be fine-tuned with the + -sendclipboard, -sendalways, and -recvtext options. + * TightVNC compression and quality levels are automatically set + based on observed network latency (n.b. not bandwidth.) + * Improvements to the Popup menu, all of these can now be changed + dynamically via the menu: ViewOnly, Toggle Bell, CursorShape + updates, X11 Cursor, Cursor Alphablending, Toggle Tight/ZRLE, + Toggle JPEG, FullColor/16bpp/8bpp (256/64/8 colors), Greyscale for + low color modes, Scaling the Viewer resolution, Escape Keys, + Pipeline Updates, and others, including UltraVNC extensions. + * Maintains its own BackingStore if the X server does not. + * The default for localhost:0 connections is not raw encoding since + same-machine connections are pretty rare. Default assumes you are + using a SSL or SSH tunnel. Use -rawlocal to revert. + * XGrabServer support for fullscreen mode, for old window managers + (-grab/-graball option). + * Fix for Popup menu positioning for old window managers (-popupfix + option). + * The VNC Viewer ssvncviewer supports IPv6 natively (no helpers + needed.) + + The list of 3rd party software bundled in the archive files: + * TightVNC Viewer (windows, unix, macosx) + * Chicken of the VNC Viewer (macosx) + * Stunnel (windows, unix, macosx) + * Putty/Plink/Pageant (windows) + * OpenSSL (windows) + * esound (windows) + + These are all self-contained in the bundle directory: they will not be + installed on your system. Just un-zip or un-tar the file you + downloaded and run the frontend ssvnc straight from its directory. + Alternatively, on Unix you can use the conventional source tarball. + + _________________________________________________________________ + + Here is the Quick Start info from the README for how to setup and use + SSVNC: +Quick Start: +----------- + +Unix and Mac OS X: + + Inside a Terminal do something like the following. + + Unpack the archive: + + % gzip -dc ssvnc-1.0.28.tar.gz | tar xvf - + + Run the GUI: + + % ./ssvnc/Unix/ssvnc (for Unix) + + % ./ssvnc/MacOSX/ssvnc (for Mac OS X) + + The smaller file "ssvnc_no_windows-1.0.28.tar.gz" + could have been used as well. + + On MacOSX you could also click on the SSVNC app icon in the Finder. + + On MacOSX if you don't like the Chicken of the VNC (e.g. no local + cursors, no screen size rescaling, and no password prompting), and you + have the XDarwin X server installed, you can set DISPLAY before starting + ssvnc (or type DISPLAY=... in Host:Disp and hit Return). Then our + enhanced TightVNC viewer will be used instead of COTVNC. + Update: there is now a 'Use X11 vncviewer on MacOSX' under Options ... + + + If you want a SSH-only tool (without the distractions of SSL) run + the command: + + sshvnc + + instead of "ssvnc". Or click "SSH-Only Mode" under Options. + Control-h will toggle between the two modes. + + + If you want a simple VNC Terminal Services only mode (requires x11vnc + on the remote server) run the command: + + tsvnc + + instead of "ssvnc". Or click "Terminal Services" under Options. + Control-t will toggle between the two modes. + + "tsvnc profile-name" and "tsvnc user@hostname" work too. + + +Unix/MacOSX Install: + + There is no standard install for the bundles, but you can make + symlinks like so: + + cd /a/directory/in/PATH + ln -s /path/to/ssvnc/bin/{s,t}* . + + Or put /path/to/ssvnc/bin, /path/to/ssvnc/Unix, or /path/to/ssvnc/MacOSX + in your PATH. + + For the conventional source tarball it will compile and install, e.g.: + + gzip -dc ssvnc-1.0.28.src.tar.gz | tar xvf - + cd ssvnc-1.0.28 + make config + make all + make PREFIX=/my/install/dir install + + then have /my/install/dir/bin in your PATH. + + + +Windows: + + Unzip, using WinZip or a similar utility, the zip file: + + ssvnc-1.0.28.zip + + Run the GUI, e.g.: + + Start -> Run -> Browse + + and then navigate to + + .../ssvnc/Windows/ssvnc.exe + + select Open, and then OK to launch it. + + The smaller file "ssvnc_windows_only-1.0.28.zip" + could have been used as well. + + You can make a Windows shortcut to this program if you want to. + + See the Windows/README.txt for more info. + + + If you want a SSH-only tool (without the distractions of SSL) run + the command: + + sshvnc.bat + + Or click "SSH-Only Mode" under Options. + + + If you want a simple VNC Terminal Services only mode (requires x11vnc + on the remote server) run the command: + + tsvnc.bat + + Or click "Terminal Services" under Options. Control-t will toggle + between the two modes. "tsvnc profile-name" and "tsvnc user@hostname" + work too. + + _________________________________________________________________ + + You can read all of the SSVNC GUI's Online Help Text here. + _________________________________________________________________ + + The bundle unpacks a directory/folder named: ssvnc. It contains these + programs to launch the GUI: + Windows/ssvnc.exe for Windows + MacOSX/ssvnc for Mac OS X + Unix/ssvnc for Unix + + (the Mac OS X and Unix launchers are simply links to the bin + directory). See the README for more information. + + The SSH-Only mode launcher program has name sshvnc. The Terminal + Services mode launcher program (assumes x11vnc 0.8.4 or later and Xvfb + installed on the server machine) has name tsvnc. + + The Viewer SSL support is done via a wrapper script (bin/ssvnc_cmd + that calls bin/util/ss_vncviewer) that starts up the STUNNEL tunnel + first and then starts the TightVNC viewer pointed at that tunnel. The + bin/ssvnc program is a GUI front-end to that script. See this FAQ for + more details on SSL tunnelling. In SSH connection mode, the wrappers + start up SSH appropriately. + + + Memory Stick Usage: If you create a directory named "Home" in that + toplevel ssvnc directory then that will be used as the base for + storing VNC profiles and certificates. Also, for convenience, if you + first run the command with "." as an argument (e.g. "ssvnc .") it will + automatically create the "Home" directory for you. This is handy if + you want to place SSVNC on a USB flash drive that you carry around for + mobile use and you want the profiles you create to stay with the drive + (otherwise you'd have to browse to the drive directory each time you + load or save). + + One user on Windows created a BAT file to launch SSVNC and needed to + do this to get the Home directory correct: +cd \ssvnc\Windows +start \ssvnc\Windows\ssvnc.exe + + (an optional profile name can be supplied to the ssvnc.exe line) + + WARNING: if you use ssvnc from an "Internet Cafe", i.e. some untrusted + computer, please be aware that someone may have set up that machine to + be capturing your keystrokes, etc. + + + SSH-Only version: The command "sshvnc" can be run instead of "ssvnc" + to get an SSH-only version of the tool: + + [sshvnc.gif] + + These also work: "sshvnc myprofile" and "sshvnc user@hostname". To + switch from the regular SSVNC mode, click "SSH-Only Mode" under + Options. This mode is less distracting if you never plan to use SSL, + manage certificates, etc. + + + Terminal Services Only: The command "tsvnc" can be run instead of + "ssvnc" to get a "Terminal Services" only version of the tool: + + [tsvnc.gif] + + These also work: "tsvnc myprofile" and "tsvnc user@hostname". To + switch from the regular SSVNC mode, click "Terminal Services" under + Options. + + This mode requires x11vnc (0.9.3 or later) installed on the remote + machine to find, create, and manage the user sessions. SSH is used to + create the encrypted and authenticated tunnel. The Xvfb (virtual + framebuffer X server) program must also be installed on the remote + system. However tsvnc will also connect to a real X session (i.e. on + the physical hardware) if you are already logged into the X session; + this is a useful access mode and does not require Xvfb on the remote + system. + + This mode should be very easy for beginner users to understand and + use. On the remote end you only need to have x11vnc and Xvfb available + in $PATH, and on the local end you just run something like: + tsvnc myname@myhost.com + + (or start up the tsvnc GUI first and then enter myname@myhost.com and + press "Connect"). + + Normally the Terminal Services sessions created are virtual (RAM-only) + ones (e.g. Xvfb, Xdummy, or Xvnc), however a nice feature is if you + have a regular X session (i.e displaying on the physical hardware) on + the remote machine that you are ALREADY logged into, then the x11vnc + run from tsvnc will find it for you as well. + + Also, there is setting "X Login" under Advanced Options that allows + you to attach to a real X server with no one logged in yet (i.e. + XDM/GDM/KDM Login Greeter screen) as long as you have sudo(1) + permission on the remote machine. + + Nice features to soon to be added to the tsvnc mode are easy CUPS + printing (working fairly well) and Sound redirection (needs much work) + of the Terminal Services Desktop session. It is easier in tsvnc mode + because the entire desktop session can be started with the correct + environment. ssvnc tries to handle the general case of an already + started desktop and that is more difficult. + + + Proxies: Web proxies, SOCKS proxies, and the UltraVNC repeater proxy + are supported to allow the SSVNC connection to go through the proxy to + the otherwise unreachable VNC Server. SSH gateway machines can be used + in the same way. Read more about SSVNC proxy support here. + + + Dynamic VNC Server Port determination: If you are running SSVNC on + Unix and are using SSH to start the remote VNC server and the VNC + server prints out the line "PORT=NNNN" to indicate which dynamic port + it is using (x11vnc does this), then if you prefix the SSH command + with "PORT=" SSVNC will watch for the PORT=NNNN line and uses ssh's + built in SOCKS proxy (ssh -D ...) to connect to the dynamic VNC server + port through the SSH tunnel. For example: + VNC Host:Display user@somehost.com + Remote SSH Command: PORT= x11vnc -find + + or "PORT= x11vnc -display :0 -localhost", etc. Or use "P= x11vnc ..." + + There is also code to detect the display of the regular Unix + vncserver(1). It extracts the display (and hence port) from the lines + "New 'X' desktop is hostname:4" and also "VNC server is already + running as :4". So you can use something like: + PORT= vncserver; sleep 15 +or: PORT= vncserver :4; sleep 15 + + the latter is preferred because when you reconnect with it will find + the already running one. The former one will keep creating new X + sessions if called repeatedly. + + If you use PORT= on Windows, a large random port is selected instead + and the -rfbport option is passed to x11vnc (it does not work with + vncserver). + + + + Patches for Unix Tightvnc viewer: + + The rfbNewFBSize support allows the enhanced TightVNC Unix viewer to + resize when the server does (e.g. "x11vnc -R scale=3/4" remote control + command). + + The cursor alphablending is described here. + + The RealVNC ZRLE encoding is supported, in addition to some low colors + modes (16bpp and 8bpp at 256, 64, and even 8 colors, for use on very + slow connections). Greyscales are also enabled for the low color + modes. + + The Popup menu (F8) is enhanced with the ability to change many things + on the fly. F9 is added as a shortcut to toggle FullScreen mode. + + Client Side Caching: The x11vnc client-side caching is handled nicely + by this viewer. The very large pixel cache below the actual display in + this caching method is distracting. Our Unix VNC viewer will + automatically try to autodetect the actual display height if the + framebuffer is very tall (more than twice as high as it is wide). One + can also set the height to the known value via -ycrop n, or use -ycrop + -1 to force autodection. In fullscreen mode one is not possible to + scroll down to the pixel cache region. In non-fullscreen mode the + window manager frame is "shrink-wrapped" around the actual screen + display. You can still scroll down to the pixel cache region. The + scrollbars are set to be very thin (2 pixels) to be less distracting. + Use the -sbwidth n to make them wider. + + Probably nobody is interested in the grabserver patch for old window + managers when the viewer is in fullscreen mode... This and some other + unfixed bugs have been fixed in our patches (fullscreen toggle works + with KDE, -x11cursor has been fixed, and the dot cursor has been made + smaller). + + From the -help output: +SSVNC Viewer (based on TightVNC viewer version 1.3.9) + +Usage: vncviewer [] [][:] + vncviewer [] [][::] + vncviewer [] exec=[CMD ARGS...] + vncviewer [] fd=n + vncviewer [] /path/to/unix/socket + vncviewer [] -listen [] + vncviewer -help + + are standard Xt options, or: + -via + -shared (set by default) + -noshared + -viewonly + -fullscreen + -noraiseonbeep + -passwd (standard VNC authentication) + -user (Unix login authentication) + -encodings (e.g. "tight,copyrect") + -bgr233 + -owncmap + -truecolour + -depth + -compresslevel (0..9: 0-fast, 9-best) + -quality (0..9: 0-low, 9-high) + -nojpeg + -nocursorshape + -x11cursor + -autopass + +Option names may be abbreviated, e.g. -bgr instead of -bgr233. +See the manual page for more information. + + +Enhanced TightVNC viewer (SSVNC) options: + + URL http://www.karlrunge.com/x11vnc/ssvnc.html + + Note: ZRLE and ZYWRLE encodings are now supported. + + Note: F9 is shortcut to Toggle FullScreen mode. + + Note: In -listen mode set the env var. SSVNC_MULTIPLE_LISTEN=1 + to allow more than one incoming VNC server at a time. + This is the same as -multilisten described below. Set + SSVNC_MULTIPLE_LISTEN=MAX:n to allow no more than "n" + simultaneous reverse connections. + + Note: If the host:port is specified as "exec=command args..." + then instead of making a TCP/IP socket connection to the + remote VNC server, "command args..." is executed and the + viewer is attached to its stdio. This enables tunnelling + established via an external command, e.g. an stunnel(8) + that does not involve a listening socket. This mode does + not work for -listen reverse connections. + + If the host:port is specified as "fd=n" then it is assumed + n is an already opened file descriptor to the socket. (i.e + the parent did fork+exec) + + If the host:port contains a '/' it is interpreted as a + unix-domain socket (AF_LOCAL insead of AF_INET) + + -multilisten As in -listen (reverse connection listening) except + allow more than one incoming VNC server to be connected + at a time. The default for -listen of only one at a + time tries to play it safe by not allowing anyone on + the network to put (many) desktops on your screen over + a long window of time. Use -multilisten for no limit. + + -acceptpopup In -listen (reverse connection listening) mode when + a reverse VNC connection comes in show a popup asking + whether to Accept or Reject the connection. The IP + address of the connecting host is shown. Same as + setting the env. var. SSVNC_ACCEPT_POPUP=1. + + -acceptpopupsc As in -acceptpopup except assume UltraVNC Single + Click (SC) server. Retrieve User and ComputerName + info from UltraVNC Server and display in the Popup. + + -use64 In -bgr233 mode, use 64 colors instead of 256. + -bgr222 Same as -use64. + + -use8 In -bgr233 mode, use 8 colors instead of 256. + -bgr111 Same as -use8. + + -16bpp If the vnc viewer X display is depth 24 at 32bpp + request a 16bpp format from the VNC server to cut + network traffic by up to 2X, then tranlate the + pixels to 32bpp locally. + -bgr565 Same as -16bpp. + + -grey Use a grey scale for the 16- and 8-bpp modes. + + -alpha Use alphablending transparency for local cursors + requires: x11vnc server, both client and server + must be 32bpp and same endianness. + + -scale str Scale the desktop locally. The string "str" can + a floating point ratio, e.g. "0.9", or a fraction, + e.g. "3/4", or WxH, e.g. 1280x1024. Use "fit" + to fit in the current screen size. Use "auto" to + fit in the window size. "str" can also be set by + the env. var. SSVNC_SCALE. + + If you observe mouse trail painting errors, enable + X11 Cursor mode (either via Popup or -x11cursor.) + + Note that scaling is done in software and so can be + slow and requires more memory. Some speedup Tips: + + ZRLE is faster than Tight in this mode. When + scaling is first detected, the encoding will + be automatically switched to ZRLE. Use the + Popup menu if you want to go back to Tight. + Set SSVNC_PRESERVE_ENCODING=1 to disable this. + + Use a solid background on the remote side. + (e.g. manually or via x11vnc -solid ...) + + If the remote server is x11vnc, try client + side caching: x11vnc -ncache 10 ... + + -ycrop n Only show the top n rows of the framebuffer. For + use with x11vnc -ncache client caching option + to help "hide" the pixel cache region. + Use a negative value (e.g. -1) for autodetection. + Autodetection will always take place if the remote + fb height is more than 2 times the width. + + -sbwidth n Scrollbar width for x11vnc -ncache mode (-ycrop), + default is very narrow: 2 pixels, it is narrow to + avoid distraction in -ycrop mode. + + -nobell Disable bell. + + -rawlocal Prefer raw encoding for localhost, default is + no, i.e. assumes you have a SSH tunnel instead. + + -notty Try to avoid using the terminal for interactive + responses: use windows for messages and prompting + instead. Messages will also be printed to terminal. + + -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C, + Ctrl+V) instead of the X PRIMARY selection (mouse + select and middle button paste.) + + -sendalways Whenever the mouse enters the VNC viewer main + window, send the selection to the VNC server even if + it has not changed. This is like the Xt resource + translation SelectionToVNC(always) + + -recvtext str When cut text is received from the VNC server, + ssvncviewer will set both the X PRIMARY and the + X CLIPBOARD local selections. To control which + is set, specify 'str' as 'primary', 'clipboard', + or 'both' (the default.) + + -graball Grab the entire X server when in fullscreen mode, + needed by some old window managers like fvwm2. + + -popupfix Warp the popup back to the pointer position, + needed by some old window managers like fvwm2. + -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C, + Ctrl+V) instead of the X PRIMARY selection (mouse + select and middle button paste.) + + -sendalways Whenever the mouse enters the VNC viewer main + window, send the selection to the VNC server even if + it has not changed. This is like the Xt resource + translation SelectionToVNC(always) + + -recvtext str When cut text is received from the VNC server, + ssvncviewer will set both the X PRIMARY and the + X CLIPBOARD local selections. To control which + is set, specify 'str' as 'primary', 'clipboard', + or 'both' (the default.) + + -graball Grab the entire X server when in fullscreen mode, + needed by some old window managers like fvwm2. + + -popupfix Warp the popup back to the pointer position, + needed by some old window managers like fvwm2. + + -grabkbd Grab the X keyboard when in fullscreen mode, + needed by some window managers. Same as -grabkeyboard. + -grabkbd is the default, use -nograbkbd to disable. + + -bs, -nobs Whether or not to use X server Backingstore for the + main viewer window. The default is to not, mainly + because most Linux, etc, systems X servers disable + *all* Backingstore by default. To re-enable it put + + Option "Backingstore" + + in the Device section of /etc/X11/xorg.conf. + In -bs mode with no X server backingstore, whenever an + area of the screen is re-exposed it must go out to the + VNC server to retrieve the pixels. This is too slow. + + In -nobs mode, memory is allocated by the viewer to + provide its own backing of the main viewer window. This + actually makes some activities faster (changes in large + regions) but can appear to "flash" too much. + + -noshm Disable use of MIT shared memory extension (not recommended +) + + -termchat Do the UltraVNC chat in the terminal vncviewer is in + instead of in an independent window. + + -unixpw str Useful for logging into x11vnc in -unixpw mode. "str" is a + string that allows many ways to enter the Unix Username + and Unix Password. These characters: username, newline, + password, newline are sent to the VNC server after any VNC + authentication has taken place. Under x11vnc they are + used for the -unixpw login. Other VNC servers could do + something similar. + + You can also indicate "str" via the environment + variable SSVNC_UNIXPW. + + Note that the Escape key is actually sent first to tell + x11vnc to not echo the Unix Username back to the VNC + viewer. Set SSVNC_UNIXPW_NOESC=1 to override this. + + If str is ".", then you are prompted at the command line + for the username and password in the normal way. If str is + "-" the stdin is read via getpass(3) for username@password. + Otherwise if str is a file, it is opened and the first line + read is taken as the Unix username and the 2nd as the + password. If str prefixed by "rm:" the file is removed + after reading. Otherwise, if str has a "@" character, + it is taken as username@password. Otherwise, the program + exits with an error. Got all that? + + -repeater str This is for use with UltraVNC repeater proxy described + here: http://www.uvnc.com/addons/repeater.html. The "str" + is the ID string to be sent to the repeater. E.g. ID:1234 + It can also be the hostname and port or display of the VNC + server, e.g. 12.34.56.78:0 or snoopy.com:1. Note that when + using -repeater, the host:dpy on the cmdline is the repeate +r + server, NOT the VNC server. The repeater will connect you. + + Example: vncviewer ... -repeater ID:3333 repeat.host:5900 + Example: vncviewer ... -repeater vhost:0 repeat.host:5900 + + Use, e.g., '-repeater SCIII=ID:3210' if the repeater is a + Single Click III (SSL) repeater (repeater_SSL.exe) and you + are passing the SSL part of the connection through stunnel, + socat, etc. This way the magic UltraVNC string 'testB' + needed to work with the repeater is sent to it. + + -rfbversion str Set the advertised RFB version. E.g.: -rfbversion 3.6 + For some servers, e.g. UltraVNC this needs to be done. + + -ultradsm UltraVNC has symmetric private key encryption DSM plugins: + http://www.uvnc.com/features/encryption.html. It is assumed + you are using a unix program (e.g. our ultravnc_dsm_helper) + to encrypt and decrypt the UltraVNC DSM stream. IN ADDITION + TO THAT supply -ultradsm to tell THIS viewer to modify the + RFB data sent so as to work with the UltraVNC Server. For + some reason, each RFB msg type must be sent twice under DSM +. + + -mslogon user Use Windows MS Logon to an UltraVNC server. Supply the + username or "1" to be prompted. The default is to + autodetect the UltraVNC MS Logon server and prompt for + the username and password. + + IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman + exchange is very weak and can be brute forced to recover + your username and password in a few seconds of CPU time. + To be safe, be sure to use an additional encrypted tunnel + (e.g. SSL or SSH) for the entire VNC session. + + -chatonly Try to be a client that only does UltraVNC text chat. This + mode is used by x11vnc to present a chat window on the + physical X11 console (i.e. chat with the person at the + display). + + -env VAR=VALUE To save writing a shell script to set environment variables +, + specify as many as you need on the command line. For + example, -env SSVNC_MULTIPLE_LISTEN=MAX:5 -env EDITOR=vi + + -noipv6 Disable all IPv6 sockets. Same as VNCVIEWER_NO_IPV6=1. + + -noipv4 Disable all IPv4 sockets. Same as VNCVIEWER_NO_IPV4=1. + + -printres Print out the Ssvnc X resources (appdefaults) and then exit + You can save them to a file and customize them (e.g. the + keybindings and Popup menu) Then point to the file via + XENVIRONMENT or XAPPLRESDIR. + + -pipeline Like TurboVNC, request the next framebuffer update as soon + as possible instead of waiting until the end of the current + framebuffer update coming in. Helps 'pipeline' the updates +. + This is currently the default, use -nopipeline to disable. + + -appshare Enable features for use with x11vnc's -appshare mode where + instead of sharing the full desktop only the application's + windows are shared. Viewer multilisten mode is used to + create the multiple windows: -multilisten is implied. + See 'x11vnc -appshare -help' more information on the mode. + + Features enabled in the viewer under -appshare are: + Minimum extra text in the title, auto -ycrop is disabled, + x11vnc -remote_prefix X11VNC_APPSHARE_CMD: message channel, + x11vnc initial window position hints. See also Escape Keys + below for additional key and mouse bindings. + + -escape str This sets the 'Escape Keys' modifier sequence and enables + escape keys mode. When the modifier keys escape sequence + is held down, the next keystroke is interpreted locally + to perform a special action instead of being sent to the + remote VNC server. + + Use '-escape default' for the default modifier sequence. + (Unix: Alt_L,Super_L and MacOSX: Control_L,Meta_L) + + Here are the 'Escape Keys: Help+Set' instructions from the Popup Menu: + + Escape Keys: Enter a comma separated list of modifier keys to be the + 'escape sequence'. When these keys are held down, the next keystroke is + interpreted locally to invoke a special action instead of being sent to + the remote VNC server. In other words, a set of 'Hot Keys'. + + To enable or disable this, click on 'Escape Keys: Toggle' in the Popup. + + Here is the list of hot-key mappings to special actions: + + r: refresh desktop b: toggle bell c: toggle full-color + f: file transfer x: x11cursor z: toggle Tight/ZRLE + l: full screen g: graball e: escape keys dialog + s: scale dialog +: scale up (=) -: scale down (_) + t: text chat a: alphablend cursor + V: toggle viewonly Q: quit viewer 1 2 3 4 5 6: UltraVNC scale 1/n + + Arrow keys: pan the viewport about 10% for each keypress. + PageUp / PageDown: pan the viewport by a screenful vertically. + Home / End: pan the viewport by a screenful horizontally. + KeyPad Arrow keys: pan the viewport by 1 pixel for each keypress. + Dragging the Mouse with Button1 pressed also pans the viewport. + Clicking Mouse Button3 brings up the Popup Menu. + + The above mappings are *always* active in ViewOnly mode, unless you set the + Escape Keys value to 'never'. + + If the Escape Keys value below is set to 'default' then a default list of + of modifier keys is used. For Unix it is: Alt_L,Super_L and for MacOSX it + is Control_L,Meta_L. Note: the Super_L key usually has a Windows(TM) Flag + on it. Also note the _L and _R mean the key is on the LEFT or RIGHT side + of the keyboard. + + On Unix the default is Alt and Windows keys on Left side of keyboard. + On MacOSX the default is Control and Command keys on Left side of keyboard. + + Example: Press and hold the Alt and Windows keys on the LEFT side of the + keyboard and then press 'c' to toggle the full-color state. Or press 't' + to toggle the ultravnc Text Chat window, etc. + + To use something besides the default, supply a comma separated list (or a + single one) from: Shift_L Shift_R Control_L Control_R Alt_L Alt_R Meta_L + Meta_R Super_L Super_R Hyper_L Hyper_R or Mode_switch. + + + New Popup actions: + + ViewOnly: ~ -viewonly + Disable Bell: ~ -nobell + Cursor Shape: ~ -nocursorshape + X11 Cursor: ~ -x11cursor + Cursor Alphablend: ~ -alpha + Toggle Tight/Hextile: ~ -encodings hextile... + Toggle Tight/ZRLE: ~ -encodings zrle... + Toggle ZRLE/ZYWRLE: ~ -encodings zywrle... + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) + Pipeline Updates ~ -pipeline + + Full Color as many colors as local screen allows. + Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. + 16 bit color (BGR565) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. + 64 colors ~ -bgr222 / -use64 + 8 colors ~ -bgr111 / -use8 + Scale Viewer ~ -scale + Escape Keys: Toggle ~ -escape + Escape Keys: Help+Set ~ -escape + Set Y Crop (y-max) ~ -ycrop + Set Scrollbar Width ~ -sbwidth + XGrabServer ~ -graball + + UltraVNC Extensions: + + Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. + Text Chat Ultravnc ext. Do Text Chat. + File Transfer Ultravnc ext. File xfer via Java helper. + Single Window Ultravnc ext. Grab and view a single window. + (select then click on the window you want). + Disable Remote Input Ultravnc ext. Try to prevent input and + viewing of monitor at physical display. + + Note: the Ultravnc extensions only apply to servers that support + them. x11vnc/libvncserver supports some of them. + + Send Clipboard not Primary ~ -sendclipboard + Send Selection Every time ~ -sendalways + + Nearly all of these can be changed dynamically in the Popup menu + (press F8 for it): + + [viewer_menu.gif] [unixviewer.jpg] + + _________________________________________________________________ + + Windows: + + For Windows, SSL Viewer support is provided by a GUI Windows/ssvnc.exe + that prompts for the VNC display and then starts up STUNNEL followed + by the Stock TightVNC Windows Viewer. Both are bundled in the package + for your convenience. The GUI has other useful features. When the + connection is finished, you will be asked if you want to terminate the + STUNNEL program. For SSH connections from Windows the GUI will use + PLINK instead of STUNNEL. + + Unix and Mac OS X: + + Run the GUI (ssvnc, see above) and let me know how it goes. + _________________________________________________________________ + + Hopefully this tool will make it convenient for people to help test + and use the built-in SSL support in x11vnc. Extra testing of this + feature is much appreciated!! Thanks. + + Please Help Test the newly added features: + * Automatic Service tunnelling via SSH for CUPS and SMB Printing + * ESD/ARTSD Audio + * SMB (Windows/Samba) filesystem mounting + + These allow you to print from the remote (VNC Server) machine to local + printers, listen to sounds (with some limitations) from the remote VNC + Server machine, and to mount your local Windows or Samba shares on the + remote VNC Server machine. Basically these new features try to + automate the tricks described here: + http://www.karlrunge.com/x11vnc/faq.html#faq-smb-shares + http://www.karlrunge.com/x11vnc/faq.html#faq-cups + http://www.karlrunge.com/x11vnc/faq.html#faq-sound + _________________________________________________________________ + + Downloading: Downloads for this project are hosted at Sourceforge.net. + + Choose the archive file bundle that best suits you (e.g. no source + code, windows only, unix only, zip, tar etc). + + A quick guide: + + On some flavor of Unix, e.g. Linux or Solaris? Use + "ssvnc_unix_only" (or "ssvnc_no_windows" to recompile). + On Mac OS X? Use "ssvnc_no_windows". + On Windows? Use "ssvnc_windows_only". + ssvnc_windows_only-1.0.27.zip Windows Binaries Only. No source included + (6.2MB) + ssvnc_no_windows-1.0.27.tar.gz Unix and Mac OS X Only. No Windows binarie +s. Source included. (10.1MB) + ssvnc_unix_only-1.0.27.tar.gz Unix Binaries Only. No source included +. (7.2MB) + ssvnc_unix_minimal-1.0.27.tar.gz Unix Minimal. You must supply your own vn +cviewer and stunnel. (0.2MB) + + ssvnc-1.0.27.tar.gz All Unix, Mac OS X, and Windows binaries a +nd source TGZ. (16.1MB) + ssvnc-1.0.27.zip All Unix, Mac OS X, and Windows binaries a +nd source ZIP. (16.4MB) + ssvnc_all-1.0.27.zip All Unix, Mac OS X, and Windows binaries a +nd source AND full archives in the zip dir. (19.2MB) + + + Here is a conventional source tarball: + ssvnc-1.0.27.src.tar.gz Conventional Source for SSVNC GUI and Unix + VNCviewer (0.5MB) + + it will be of use to those who do not want the SSVNC + "one-size-fits-all" bundles. For example, package/distro maintainers + will find this more familiar and useful to them (i.e. they run: "make + config; make all; make install"). Note that it does not include the + stunnel source, and so has a dependency that the system stunnel is + installed. + + Read the README.src file for more information on using the + conventional source tarball. + + + Note: even with the Unix bundles, e.g. "ssvnc_no_windows" or + "ssvnc_all", you may need to run the "./build.unix" script in the top + directory to recompile for your operating system. + + Here are the corresponding 1.0.28 development bundles (Please help + test them): + + ssvnc_windows_only-1.0.28.zip + ssvnc_no_windows-1.0.28.tar.gz + ssvnc_unix_only-1.0.28.tar.gz + ssvnc_unix_minimal-1.0.28.tar.gz + + ssvnc-1.0.28.tar.gz + ssvnc-1.0.28.zip + ssvnc_all-1.0.28.zip + + ssvnc-1.0.28.src.tar.gz Conventional Source for SSVNC GUI and Unix + VNCviewer (0.5MB) + + + For any Unix system, a self-extracting and running file for the + "ssvnc_unix_minimal" package is here: ssvnc. Save it as filename + "ssvnc", type "chmod 755 ./ssvnc", and then launch the GUI via typing + "./ssvnc". Note that this "ssvnc_unix_minimal" mode requires you + install the "stunnel" and "vncviewer" programs externally (for + example, install your distros' versions, e.g. on debian: "apt-get + install stunnel4 xtightvncviewer".) It will work, but many of the + SSVNC features will be missing. + + Previous releases: + Release 1.0.18 at Sourceforge.net + Release 1.0.19 at Sourceforge.net + Release 1.0.20 at Sourceforge.net + Release 1.0.21 at Sourceforge.net + Release 1.0.22 at Sourceforge.net + Release 1.0.23 at Sourceforge.net + Release 1.0.24 at Sourceforge.net + Release 1.0.25 at Sourceforge.net + Release 1.0.26 at Sourceforge.net + Release 1.0.27 at Sourceforge.net + + + Please help test the UltraVNC File Transfer support in the native Unix + VNC viewer! Let us know how it went. + + Current Unix binaries in the archives: + Linux.i686 + Linux.x86_64 + Linux.ppc64 X (removed) + Linux.alpha X (removed) + SunOS.sun4u + SunOS.sun4m + SunOS.i86pc + Darwin.Power.Macintosh + Darwin.i386 + HP-UX.9000 X (removed) + FreeBSD.i386 X (removed) + NetBSD.i386 X (removed) + OpenBSD.i386 X (removed) + + (some of these are out of date, marked with 'X' above, because I no + longer have access to machines running those OS's. Use the + "build.unix" script to recompile on your system). + + Note: some of the above binaries depend on libssl.so.0.9.7, whereas + some recent distros only provide libssl.so.0.9.8 by default (for + compatibility reasons they should install both by default but not all + do). So you may need to instruct your distro to install the 0.9.7 + library (it is fine to have both runtimes installed simultaneously + since the libraries have different names). Update: I now try to + statically link libssl.a for all of the binaries in the archive. + + You can also run the included build.unix script to try to + automatically build the binaries if your OS is not in the above list + or the included binary does not run properly on your system. Let me + know how that goes. + _________________________________________________________________ + + IMPORTANT: there may be restrictions for you to download, use, or + redistribute the above because of cryptographic software they contain + or for other reasons. Please check out your situation and information + at the following and related sites: + http://stunnel.mirt.net + http://www.stunnel.org + http://www.openssl.org + http://www.chiark.greenend.org.uk/~sgtatham/putty/ + http://www.tightvnc.com + http://www.realvnc.com + http://sourceforge.net/projects/cotvnc/ + _________________________________________________________________ + + README: Here is the toplevel README from the bundle. + +======================================================================= +http://www.karlrunge.com/x11vnc/x11vnc_opts.html: + + + _________________________________________________________________ + +x11vnc: a VNC server for real X displays + + Here are all of x11vnc command line options: +% x11vnc -opts (see below for -help long descriptions) + +x11vnc: allow VNC connections to real X11 displays. 0.9.11 lastmod: 2010-05-08 + +x11vnc options: + -display disp -auth file -N + -autoport n -rfbport str -6 + -no6 -noipv6 -noipv4 + -reopen -reflect host:N -id windowid + -sid windowid -appshare -clip WxH+X+Y + -flashcmap -shiftcmap n -notruecolor + -advertise_truecolor -visual n -overlay + -overlay_nocursor -8to24 [opts] -24to32 + -scale fraction -geometry WxH -scale_cursor frac + -viewonly -shared -once + -forever -loop -timeout n + -sleepin n -inetd -tightfilexfer + -ultrafilexfer -http -http_ssl + -avahi -mdns -zeroconf + -connect string -connect_or_exit str -proxy string + -vncconnect -novncconnect -allow host1[,host2..] + -localhost -listen6 str -nolookup + -input string -grabkbd -grabptr + -grabalways -viewpasswd string -passwdfile filename + -showrfbauth filename -unixpw [list] -unixpw_nis [list] + -unixpw_cmd cmd -find -finddpy + -listdpy -findauth [disp] -create + -xdummy -xvnc -xvnc_redirect + -xdummy_xvfb -create_xsrv str -svc + -svc_xdummy -svc_xvnc -svc_xdummy_xvfb + -xdmsvc -sshxdmsvc -unixpw_system_greeter + -redirect port -display WAIT:... -vencrypt mode + -anontls mode -sslonly -dhparams file + -nossl -ssl [pem] -ssltimeout n + -sslnofail -ssldir dir -sslverify path + -sslCRL path -sslGenCA [dir] -sslGenCert type name + -sslEncKey pem -sslCertInfo pem -sslDelCert pem + -sslScripts -stunnel [pem] -stunnel3 [pem] + -enc cipher:keyfile -https [port] -httpsredir [port] + -http_oneport -ssh user@host:disp -usepw + -storepasswd pass file -nopw -accept string + -afteraccept string -gone string -users list + -noshm -flipbyteorder -onetile + -solid [color] -blackout string -xinerama + -noxinerama -xtrap -xrandr [mode] + -rotate string -padgeom WxH -o logfile + -flag file -rmflag file -rc filename + -norc -env VAR=VALUE -prog /path/to/x11vnc + -h, -help -?, -opts -V, -version + -license -dbg -q, -quiet + -v, -verbose -bg -modtweak + -nomodtweak -xkb -noxkb + -capslock -skip_lockkeys -noskip_lockkeys + -skip_keycodes string -sloppy_keys -skip_dups + -noskip_dups -add_keysyms -noadd_keysyms + -clear_mods -clear_keys -clear_all + -remap string -norepeat -repeat + -nofb -nobell -nosel + -noprimary -nosetprimary -noclipboard + -nosetclipboard -seldir string -cursor [mode] + -nocursor -cursor_drag -arrow n + -noxfixes -alphacut n -alphafrac fraction + -alpharemove -noalphablend -nocursorshape + -cursorpos -nocursorpos -xwarppointer + -noxwarppointer -buttonmap string -nodragging + -ncache n -ncache_cr -ncache_no_moveraise + -ncache_no_dtchange -ncache_no_rootpixmap -ncache_keep_anims + -ncache_old_wm -ncache_pad n -debug_ncache + -wireframe [str] -nowireframe -nowireframelocal + -wirecopyrect mode -nowirecopyrect -debug_wireframe + -scrollcopyrect mode -noscrollcopyrect -scr_area n + -scr_skip list -scr_inc list -scr_keys list + -scr_term list -scr_keyrepeat lo-hi -scr_parms string + -fixscreen string -debug_scroll -noxrecord + -grab_buster -nograb_buster -debug_grabs + -debug_sel -pointer_mode n -input_skip n + -allinput -input_eagerly -speeds rd,bw,lat + -wmdt string -debug_pointer -debug_keyboard + -defer time -wait time -extra_fbur n + -wait_ui factor -setdefer n -nowait_bog + -slow_fb time -xrefresh time -nap + -nonap -sb time -readtimeout n + -ping n -nofbpm -fbpm + -nodpms -dpms -forcedpms + -clientdpms -noserverdpms -noultraext + -chatwindow -noxdamage -xd_area A + -xd_mem f -sigpipe string -threads + -nothreads -fs f -gaps n + -grow n -fuzz n -debug_tiles + -snapfb -rawfb string -freqtab file + -pipeinput cmd -macnodim -macnosleep + -macnosaver -macnowait -macwheel n + -macnoswap -macnoresize -maciconanim n + -macmenu -macuskbd -gui [gui-opts] + -remote command -query variable -QD variable + -sync -query_retries str -remote_prefix str + -noremote -yesremote -unsafe + -safer -privremote -nocmds + -allowedcmds list -deny_all + +LibVNCServer options: +-rfbport port TCP port for RFB protocol +-rfbwait time max time in ms to wait for RFB client +-rfbauth passwd-file use authentication on RFB protocol + (use 'storepasswd' to create a password file) +-rfbversion 3.x Set the version of the RFB we choose to advertise +-permitfiletransfer permit file transfer support +-passwd plain-password use authentication + (use plain-password as password, USE AT YOUR RISK) +-deferupdate time time in ms to defer updates (default 40) +-deferptrupdate time time in ms to defer pointer updates (default none) +-desktop name VNC desktop name (default "LibVNCServer") +-alwaysshared always treat new clients as shared +-nevershared never treat new clients as shared +-dontdisconnect don't disconnect existing clients when a new non-shared + connection comes in (refuse new connection instead) +-httpdir dir-path enable http server using dir-path home +-httpport portnum use portnum for http connection +-enablehttpproxy enable http proxy support +-progressive height enable progressive updating for slow links +-listen ipaddr listen for connections only on network interface with + addr ipaddr. '-listen localhost' and hostname work too. + +libvncserver-tight-extension options: +-disablefiletransfer disable file transfer +-ftproot string set ftp root + + + + +% x11vnc -help + +x11vnc: allow VNC connections to real X11 displays. 0.9.11 lastmod: 2010-05-08 + +(type "x11vnc -opts" to just list the options.) + +Typical usage is: + + Run this command in a shell on the remote machine "far-host" + with X session you wish to view: + + x11vnc -display :0 + + Then run this in another window on the machine you are sitting at: + + vncviewer far-host:0 + +Once x11vnc establishes connections with the X11 server and starts listening +as a VNC server it will print out a string: PORT=XXXX where XXXX is typically +5900 (the default VNC server port). One would next run something like +this on the local machine: "vncviewer hostname:N" where "hostname" is +the name of the machine running x11vnc and N is XXXX - 5900, i.e. usually +"vncviewer hostname:0". + +By default x11vnc will not allow the screen to be shared and it will exit +as soon as the client disconnects. See -shared and -forever below to override +these protections. See the FAQ for details how to tunnel the VNC connection +through an encrypted channel such as ssh(1). In brief: + + ssh -t -L 5900:localhost:5900 far-host 'x11vnc -localhost -display :0' + + vncviewer -encodings 'copyrect tight zrle hextile' localhost:0 + +Also, use of a VNC password (-rfbauth or -passwdfile) is strongly recommended. + +For additional info see: http://www.karlrunge.com/x11vnc/ + and http://www.karlrunge.com/x11vnc/faq.html + + +Config file support: if the file $HOME/.x11vncrc exists then each line in +it is treated as a single command line option. Disable with -norc. For +each option name, the leading character "-" is not required. E.g. a line +that is either "forever" or "-forever" may be used and are equivalent. +Likewise "wait 100" or "-wait 100" are acceptable and equivalent lines. +The "#" character comments out to the end of the line in the usual way +(backslash it for a literal). Leading and trailing whitespace is trimmed off. +Lines may be continued with a "\" as the last character of a line (it +becomes a space character). + +Options: + +-display disp X11 server display to connect to, usually :0. The X + server process must be running on same machine and + support MIT-SHM. Equivalent to setting the DISPLAY + environment variable to "disp". + + See the description below of the "-display WAIT:..." + extensions, where alias "-find" will find the user's + display automatically, and "-create" will create a + Xvfb session if no session is found. + +-auth file Set the X authority file to be "file", equivalent to + setting the XAUTHORITY environment variable to "file" + before startup. Same as -xauth file. See Xsecurity(7), + xauth(1) man pages for more info. + + Use '-auth guess' to have x11vnc use its -findauth + mechanism (described below) to try to guess the + XAUTHORITY filename and use it. + + XDM/GDM/KDM: if you are running x11vnc as root and want + to find the XAUTHORITY before anyone has logged into an + X session yet, use: x11vnc -env FD_XDM=1 -auth guess ... + (This will also find the XAUTHORITY if a user is already + logged into the X session.) When running as root, + FD_XDM=1 will be tried if the initial -auth guess fails. + +-N If the X display is :N, try to set the VNC display to + also be :N This just sets the -rfbport option to 5900+N + The program will exit immediately if that port is not + available. The -N option only works with normal -display + usage, e.g. :0 or :8, -N is ignored in the -display + WAIT:..., -create, -find, -svc, -redirect, etc modes. + +-autoport n Automatically probe for a free VNC port starting at n. + The default is to start probing at 5900. Use this to + stay away from other VNC servers near 5900. + +-rfbport str The VNC port to listen on (a LibVNCServer option), e.g. + 5900, 5901, etc. If specified as "-rfbport PROMPT" + then the x11vnc -gui is used to prompt the user to + enter the port number. + +-6 IPv6 listening support. In addition to IPv4, the + IPv6 address is listened on for incoming connections. + The same port number as IPv4 is used. + + NOTE: This x11vnc binary was compiled to have the + "-6" IPv6 listening mode ENABLED by default (CPPFLAGS + -DX11VNC_LISTEN6=1). So to disable IPv6 listening mode + you MUST supply the "-no6" option (see below.) + + The "-6" mode works for both normal connections and + -ssl encrypted ones. Nearly everything is supported + for the IPv6 case, but there are a few exceptions. + See -stunnel for its IPv6 support. + + Currently, for absolutely everything to work correctly + the machine may need to have some IPv4 support, at the + least for the loopback interface. However, for nearly + all usage modes no IPv4 support is required. See -nopiv4 +. + + If you have trouble compiling or running in IPv6 mode, + set -DX11VNC_IPV6=0 in CPPFLAGS when configuring to + disable IPv6 support. + +-no6 Disable IPv6 listening support (only useful if the + "-6" mode is compiled in to be the default; see the + X11VNC_LISTEN6 description above under "-6".) + +-noipv6 Do not try to use IPv6 for any listening or connecting + sockets. This includes both the listening service + port(s) and outgoing connections from -connect, + -connect_or_exit, or -proxy. Use this if you are having + problems due to IPv6. + +-noipv4 Do not try to use IPv4 for any listening or connecting + sockets. This is mainly for exploring the behavior of + x11vnc on an IPv6-only system, but may have other uses. + +-reopen If the X server connection is disconnected, try to + reopen the X display (up to one time.) This is of use + for display managers like GDM (KillInitClients option) + that kill x11vnc just after the user logs into the + X session. Note: the reopened state may be unstable. + Set X11VNC_REOPEN_DISPLAY=n to reopen n times and + set X11VNC_REOPEN_SLEEP_MAX to the number of seconds, + default 10, to keep trying to reopen the display (once + per second.) + + Update: as of 0.9.9, x11vnc tries to automatically avoid + being killed by the display manager by delaying creating + windows or using XFIXES. So you shouldn't need to use + KillInitClients=false as long as you log in quickly + enough (within 45 seconds of connecting.) You can + disable this by setting X11VNC_AVOID_WINDOWS=never. + You can also set it to the number of seconds to delay. + +-reflect host:N Instead of connecting to and polling an X display, + connect to the remote VNC server host:N and be a + reflector/repeater for it. This is useful for trying + to manage the case of many simultaneous VNC viewers + (e.g. classroom broadcasting) where, e.g. you put + a repeater on each network switch, etc, to improve + performance by distributing the load and network + traffic. Implies -shared (use -noshared as a later + option to disable). See the discussion below under + -rawfb vnc:host:N for more details. + +-id windowid Show the X window corresponding to "windowid" not + the entire display. New windows like popup menus, + transient toplevels, etc, may not be seen or may be + clipped. Disabling SaveUnders or BackingStore in the + X server may help show them. x11vnc may crash if the + window is initially partially obscured, changes size, + is iconified, etc. Some steps are taken to avoid this + and the -xrandr mechanism is used to track resizes. Use + xwininfo(1) to get the window id, or use "-id pick" + to have x11vnc run xwininfo(1) for you and extract + the id. The -id option is useful for exporting very + simple applications (e.g. the current view on a webcam). +-sid windowid As -id, but instead of using the window directly it + shifts a root view to it: this shows SaveUnders menus, + etc, although they will be clipped if they extend beyond + the window. + +-appshare Simple application sharing based on the -id/-sid + mechanism. Every new toplevel window that the + application creates induces a new viewer window via + a reverse connection. The -id/-sid and -connect + options are required. Run 'x11vnc -appshare -help' + for more info. + +-clip WxH+X+Y Only show the sub-region of the full display that + corresponds to the rectangle geometry with size WxH and + offset +X+Y. The VNC display has size WxH (i.e. smaller + than the full display). This also works for -id/-sid + mode where the offset is relative to the upper left + corner of the selected window. An example use of this + option would be to split a large (e.g. Xinerama) display + into two parts to be accessed via separate viewers by + running a separate x11vnc on each part. + + Use '-clip xinerama0' to clip to the first xinerama + sub-screen (if xinerama is active). xinerama1 for the + 2nd sub-screen, etc. This way you don't need to figure + out the WxH+X+Y of the desired xinerama sub-screen. + screens are sorted in increasing distance from the + (0,0) origin (I.e. not the Xserver's order). + +-flashcmap In 8bpp indexed color, let the installed colormap flash + as the pointer moves from window to window (slow). + Also try the -8to24 option to avoid flash altogether. +-shiftcmap n Rare problem, but some 8bpp displays use less than 256 + colorcells (e.g. 16-color grayscale, perhaps the other + bits are used for double buffering) *and* also need to + shift the pixels values away from 0, .., ncells. "n" + indicates the shift to be applied to the pixel values. + To see the pixel values set DEBUG_CMAP=1 to print out + a colormap histogram. Example: -shiftcmap 240 +-notruecolor For 8bpp displays, force indexed color (i.e. a colormap) + even if it looks like 8bpp TrueColor (rare problem). +-advertise_truecolor If the X11 display is indexed color, lie to clients + when they first connect by telling them it is truecolor. + To workaround RealVNC: inPF has colourMap but not 8bpp + Use '-advertise_truecolor reset' to reset client fb too. + +-visual n This option probably does not do what you think. + It simply *forces* the visual used for the framebuffer; + this may be a bad thing... (e.g. messes up colors or + cause a crash). It is useful for testing and for some + workarounds. n may be a decimal number, or 0x hex. + Run xdpyinfo(1) for the values. One may also use + "TrueColor", etc. see for a list. If the + string ends in ":m" then for better or for worse + the visual depth is forced to be m. You may want to + use -noshm when using this option (so XGetImage may + automatically translate the pixel data). + +-overlay Handle multiple depth visuals on one screen, e.g. 8+24 + and 24+8 overlay visuals (the 32 bits per pixel are + packed with 8 for PseudoColor and 24 for TrueColor). + + Currently -overlay only works on Solaris via + XReadScreen(3X11) and IRIX using XReadDisplay(3). + On Solaris there is a problem with image "bleeding" + around transient popup menus (but not for the menu + itself): a workaround is to disable SaveUnders + by passing the "-su" argument to Xsun (in + /etc/dt/config/Xservers). + + Use -overlay as a workaround for situations like these: + Some legacy applications require the default visual to + be 8bpp (8+24), or they will use 8bpp PseudoColor even + when the default visual is depth 24 TrueColor (24+8). + In these cases colors in some windows will be incorrect + in x11vnc unless -overlay is used. Another use of + -overlay is to enable showing the exact mouse cursor + shape (details below). + + Under -overlay, performance will be somewhat slower + due to the extra image transformations required. + For optimal performance do not use -overlay, but rather + configure the X server so that the default visual is + depth 24 TrueColor and try to have all apps use that + visual (e.g. some apps have -use24 or -visual options). +-overlay_nocursor Sets -overlay, but does not try to draw the exact mouse + cursor shape using the overlay mechanism. + +-8to24 [opts] Try this option if -overlay is not supported on your + OS, and you have a legacy 8bpp app that you want to + view on a multi-depth display with default depth 24 + (and is 32 bpp) OR have a default depth 8 display with + depth 24 overlay windows for some apps. This option + may not work on all X servers and hardware (tested + on XFree86/Xorg mga driver and Xsun). The "opts" + string is not required and is described below. + + This mode enables a hack where x11vnc monitors windows + within 3 levels from the root window. If it finds + any that are 8bpp it extracts the indexed color + pixel values using XGetImage() and then applies a + transformation using the colormap(s) to create TrueColor + RGB values that it in turn inserts into bits 1-24 of + the framebuffer. This creates a depth 24 "view" + of the display that is then exported via VNC. + + Conversely, for default depth 8 displays, the depth + 24 regions are read by XGetImage() and everything is + transformed and inserted into a depth 24 TrueColor + framebuffer. + + Note that even if there are *no* depth 24 visuals or + windows (i.e. pure 8bpp), this mode is potentially + an improvement over -flashcmap because it avoids the + flashing and shows each window in the correct color. + + This method works OK, but may still have bugs and it + does hog resources. If there are multiple 8bpp windows + using different colormaps, one may have to iconify all + but one for the colors to be correct. + + There may be painting errors for clipping and switching + between windows of depths 8 and 24. Heuristics are + applied to try to minimize the painting errors. One can + also press 3 Alt_L's in a row to refresh the screen + if the error does not repair itself. Also the option + -fixscreen 8=3.0 or -fixscreen V=3.0 may be used to + periodically refresh the screen at the cost of bandwidth + (every 3 sec for this example). + + The [opts] string can contain the following settings. + Multiple settings are separated by commas. + + For for some X servers with default depth 24 a + speedup may be achieved via the option "nogetimage". + This enables a scheme were XGetImage() is not used + to retrieve the 8bpp data. Instead, it assumes that + the 8bpp data is in bits 25-32 of the 32bit X pixels. + There is no requirement that the X server should put + the data there for our poll requests, but some do and + so the extra steps to retrieve it can be skipped. + Tested with mga driver with XFree86/Xorg. For the + default depth 8 case this option is ignored. + + To adjust how often XGetImage() is used to poll the + non-default visual regions for changes, use the option + "poll=t" where "t" is a floating point time. + (default: 0.05) + + Setting the option "level2" will limit the search + for non-default visual windows to two levels from the + root window. Do this on slow machines where you know + the window manager only imposes one extra window between + the app window and the root window. + + Also for very slow machines use "cachewin=t" + where t is a floating point amount of time to cache + XGetWindowAttributes results. E.g. cachewin=5.0. + This may lead to the windows being unnoticed for this + amount of time when deiconifying, painting errors, etc. + + While testing on a very old SS20 these options gave + tolerable response: -8to24 poll=0.2,cachewin=5.0. For + this machine -overlay is supported and gives better + response. + + Debugging for this mode can be enabled by setting + "dbg=1", "dbg=2", or "dbg=3". + +-24to32 Very rare problem: if the framebuffer (X display + or -rawfb) is 24bpp instead of the usual 32bpp, then + dynamically transform the pixels to 32bpp. This will be + slower, but can be used to work around problems where + VNC viewers cannot handle 24bpp (e.g. "main: setPF: + not 8, 16 or 32 bpp?"). See the FAQ for more info. + + In the case of -rawfb mode, the pixels are directly + modified by inserting a 0 byte to pad them out to 32bpp. + For X displays, a kludge is done that is equivalent to + "-noshm -visual TrueColor:32". (If better performance + is needed for the latter, feel free to ask). + +-scale fraction Scale the framebuffer by factor "fraction". Values + less than 1 shrink the fb, larger ones expand it. Note: + the image may not be sharp and response may be slower. + If "fraction" contains a decimal point "." it + is taken as a floating point number, alternatively + the notation "m/n" may be used to denote fractions + exactly, e.g. -scale 2/3 + + To scale asymmetrically in the horizontal and vertical + directions, specify a WxH geometry to stretch to: + e.g. '-scale 1024x768', or also '-scale 0.9x0.75' + + Scaling Options: can be added after "fraction" via + ":", to supply multiple ":" options use commas. + If you just want a quick, rough scaling without + blending, append ":nb" to "fraction" (e.g. -scale + 1/3:nb). No blending is the default for 8bpp indexed + color, to force blending for this case use ":fb". + + To disable -scrollcopyrect and -wirecopyrect under + -scale use ":nocr". If you need to to enable them use + ":cr" or specify them explicitly on the command line. + If a slow link is detected, ":nocr" may be applied + automatically. Default: :cr + + More esoteric options: for compatibility with vncviewers + the scaled width is adjusted to be a multiple of 4: + to disable this use ":n4". ":in" use interpolation + scheme even when shrinking, ":pad" pad scaled width + and height to be multiples of scaling denominator + (e.g. 3 for 2/3). + +-geometry WxH Same as -scale WxH + +-scale_cursor frac By default if -scale is supplied the cursor shape is + scaled by the same factor. Depending on your usage, + you may want to scale the cursor independently of the + screen or not at all. If you specify -scale_cursor + the cursor will be scaled by that factor. When using + -scale mode to keep the cursor at its "natural" size + use "-scale_cursor 1". Most of the ":" scaling + options apply here as well. + +-viewonly All VNC clients can only watch (default off). +-shared VNC display is shared, i.e. more than one viewer can + connect at the same time (default off). +-once Exit after the first successfully connected viewer + disconnects, opposite of -forever. This is the Default. +-forever Keep listening for more connections rather than exiting + as soon as the first client(s) disconnect. Same as -many + +-loop Create an outer loop restarting the x11vnc process + whenever it terminates. -bg and -inetd are ignored + in this mode (however see -loopbg below). + + Useful for continuing even if the X server terminates + and restarts (at that moment the process will need + permission to reconnect to the new X server of course). + + Use, e.g., -loop100 to sleep 100 millisecs between + restarts, etc. Default is 2000ms (i.e. 2 secs) Use, + e.g. -loop300,5 to sleep 300 ms and only loop 5 times. + + If -loopbg (plus any numbers) is specified instead, + the "-bg" option is implied and the mode approximates + inetd(8) usage to some degree. In this case when + it goes into the background any listening sockets + (i.e. ports 5900, 5800) are closed, so the next one + in the loop can use them. This mode will only be of + use if a VNC client (the only client for that process) + is already connected before the process goes into the + background, for example, usage of -display WAIT:.., + -svc, and -connect can make use of this "poor man's" + inetd mode. The default wait time is 500ms in this + mode. This usage could use useful: -svc -bg -loopbg + +-timeout n Exit unless a client connects within the first n seconds + after startup. + + If there have been no connection attempts after n + seconds x11vnc exits immediately. If a client is + trying to connect but has not progressed to the normal + operating state, x11vnc gives it a few more seconds + to finish and exits if it does not make it to the + normal state. + + For reverse connections via -connect or -connect_or_exit + a timeout of n seconds will be set for all reverse + connects. If the connect timeout alarm goes off, + x11vnc will exit immediately. + +-sleepin n At startup sleep n seconds before proceeding (e.g. to + allow redirs and listening clients to start up) + + If a range is given: '-sleepin min-max', a random value + between min and max is slept. E.g. '-sleepin 0-20' and + '-sleepin 10-30'. Floats are allowed too. + +-inetd Launched by inetd(8): stdio instead of listening socket. + Note: if you are not redirecting stderr to a log file + (via shell 2> or -o option) you MUST also specify the -q + option, otherwise the stderr goes to the viewer which + will cause it to abort. Specifying both -inetd and -q + and no -o will automatically close the stderr. + +-tightfilexfer Enable the TightVNC file transfer extension. Note that + that when the -viewonly option is supplied all file + transfers are disabled. Also clients that log in + viewonly cannot transfer files. However, if the remote + control mechanism is used to change the global or + per-client viewonly state the filetransfer permissions + will NOT change. + + IMPORTANT: please understand if -tightfilexfer is + specified and you run x11vnc as root for, say, inetd + or display manager (gdm, kdm, ...) access and you do + not have it switch users via the -users option, then + VNC Viewers that connect are able to do filetransfer + reads and writes as *root*. + + Also, tightfilexfer is disabled in -unixpw mode. + +-ultrafilexfer Note: to enable UltraVNC filetransfer and to get it to + work you probably need to supply these LibVNCServer + options: "-rfbversion 3.6 -permitfiletransfer" + "-ultrafilexfer" is an alias for this combination. + + IMPORTANT: please understand if -ultrafilexfer is + specified and you run x11vnc as root for, say, inetd + or display manager (gdm, kdm, ...) access and you do + not have it switch users via the -users option, then + VNC Viewers that connect are able to do filetransfer + reads and writes as *root*. + + Note that sadly you cannot do both -tightfilexfer and + -ultrafilexfer at the same time because the latter + requires setting the version to 3.6 and tightvnc will + not do filetransfer when it sees that version number. + +-http Instead of using -httpdir (see below) to specify + where the Java vncviewer applet is, have x11vnc try + to *guess* where the directory is by looking relative + to the program location and in standard locations + (/usr/local/share/x11vnc/classes, etc). Under -ssl or + -stunnel the ssl classes subdirectory is sought. +-http_ssl As -http, but force lookup for ssl classes subdir. + + Note that for HTTPS, single-port Java applet delivery + you can set X11VNC_HTTPS_DOWNLOAD_WAIT_TIME to the + max number of seconds to wait for the applet download + to finish. The default is 15. + +-avahi Use the Avahi/mDNS ZeroConf protocol to advertise + this VNC server to the local network. (Related terms: + Rendezvous, Bonjour). Depending on your setup, you + may need to start avahi-daemon and open udp port 5353 + in your firewall. + + If the avahi API cannot be found at build time, a helper + program like avahi-publish(1) or dns-sd(1) will be tried + +-mdns Same as -avahi. +-zeroconf Same as -avahi. + +-connect string For use with "vncviewer -listen" reverse connections. + If "string" has the form "host" or "host:port" + the connection is made once at startup. + + Use commas for a list of host's and host:port's. + E.g. -connect host1,host2 or host1:0,host2:5678. + Note that to reverse connect to multiple hosts at the + same time you will likely need to also supply: -shared + + Note that unlike most vnc servers, x11vnc will require a + password for reverse as well as for forward connections. + (provided password auth has been enabled, -rfbauth, etc) + If you do not want to require a password for reverse + connections set X11VNC_REVERSE_CONNECTION_NO_AUTH=1 in + your environment before starting x11vnc. + + If "string" contains "/" it is instead interpreted + as a file to periodically check for new hosts. + The first line is read and then the file is truncated. + Be careful about the location of this file if x11vnc + is running as root (e.g. via gdm(1), etc). + + + Repeater mode: Some services provide an intermediate + "vnc repeater": http://www.uvnc.com/addons/repeater.html + (and also http://koti.mbnet.fi/jtko/ for linux port) + that acts as a proxy/gateway. Modes like these require + an initial string to be sent for the reverse connection + before the VNC protocol is started. Here are the ways + to do this: + + -connect pre=some_string+host:port + -connect pre128=some_string+host:port + -connect repeater=ID:1234+host:port + -connect repeater=23.45.67.89::5501+host:port + + SSVNC notation is also supported: + + -connect repeater://host:port+ID:1234 + + As with normal -connect usage, if the repeater port is + not supplied 5500 is assumed. + + The basic idea is between the special tag, e.g. "pre=" + and "+" is the pre-string to be sent. Note that in + this case host:port is the repeater server, NOT the + vnc viewer. Somehow the pre-string tells the repeater + server how to find the vnc viewer and connect you to it. + + In the case pre=some_string+host:port, "some_string" + is simply sent. In the case preNNN=some_string+host:port + "some_string" is sent in a null padded buffer of + length NNN. repeater= is the same as pre250=, this is + the ultravnc repeater buffer size. + + Strings like "\n" and "\r", etc. are expanded to + newline and carriage return. "\c" is expanded to + "," since the connect string is comma separated. + + See also the -proxy option below for additional ways + to plumb reverse connections. + + Reverse SSL: using -connect in -ssl mode makes x11vnc + act as an SSL client (initiates SSL connection) rather + than an SSL server. The idea is x11vnc might be + connecting to stunnel on the viewer side with the + viewer in listening mode. If you do not want this + behavior, use -env X11VNC_DISABLE_SSL_CLIENT_MODE=1. + With this the viewer side can act as the SSL client + as it normally does for forward connections. + + Reverse SSL Repeater mode: This will work, but note + that if the VNC Client does any sort of a 'Fetch Cert' + action before connecting, then the Repeater will + likely drop the connection and both sides will need + to restart. Consider the use of -connect_or_exit + and -loop300,2 to have x11vnc reconnect once to the + repeater after the fetch. You will probably also want + to supply -sslonly to avoid x11vnc thinking the delay + in response means the connection is VeNCrypt. The env + var X11VNC_DISABLE_SSL_CLIENT_MODE=1 discussed above + may also be useful (i.e. the viewer can do a forward + connection as it normally does.) + + IPv6: as of x11vnc 0.9.10 the -connect option should + connect to IPv6 hosts properly. If there are problems + you can disable IPv6 by setting -DX11VNC_IPV6=0 + in CPPFLAGS when configuring. If there problems + connecting to IPv6 hosts consider a relay like the + included inet6to4 script or the -proxy option. + +-connect_or_exit str As with -connect, except if none of the reverse + connections succeed, then x11vnc shuts down immediately + + An easier to type alias for this option is '-coe' + + By the way, if you do not want x11vnc to listen on + ANY interface use -rfbport 0 which is handy for the + -connect_or_exit mode. + +-proxy string Use proxy in string (e.g. host:port) as a proxy for + making reverse connections (-connect or -connect_or_exit + options). + + Web proxies are supported, but note by default most of + them only support destination connections to ports 443 + or 563, so this might not be very useful (the viewer + would need to listen on that port or the router would + have to do a port redirection). + + A web proxy may be specified by either "host:port" + or "http://host:port" (the port is required even if + it is the common choices 80 or 8080) + + SOCKS4, SOCKS4a, and SOCKS5 are also supported. + SOCKS proxies normally do not have restrictions on the + destination port number. + + Use a format like this: socks://host:port or + socks5://host:port. Note that ssh -D does not support + SOCKS4a, so use socks5://. For socks:// SOCKS4 is used + on a numerical IP and "localhost", otherwise SOCKS4a + is used (and so the proxy tries to do the DNS lookup). + + An experimental mode is "-proxy http://host:port/..." + Note the "/" after the port that distinguishes it from + a normal web proxy. The port must be supplied even if + it is the default 80. For this mode a GET is done to + the supplied URL with the string host=H&port=P appended. + H and P will be the -connect reverse connect host + and port. Use the string "__END__" to disable the + appending. The basic idea here is that maybe some cgi + script provides the actual viewer hookup and tunnelling. + How to actually achieve this within cgi, php, etc. is + not clear... A custom web server or apache module + would be straight-forward. + + Another experimental mode is "-proxy ssh://user@host" + in which case a SSH tunnel is used for the proxying. + "user@" is not needed unless your unix username is + different on "host". For a non-standard SSH port + use ssh://user@host:port. If proxies are chained (see + next paragraph) then the ssh one must be the first one. + If ssh-agent is not active, then the ssh password needs + to be entered in the terminal where x11vnc is running. + Examples: + + -connect localhost:0 -proxy ssh://me@friends-pc:2222 + + -connect snoopy:0 -proxy ssh://ssh.company.com + + Multiple proxies may be chained together in case one + needs to ricochet off of a number of hosts to finally + reach the VNC viewer. Up to 3 may be chained, separate + them by commas in the order they are to be connected to. + E.g.: http://host1:port1,socks5://host2:port2 or three + like: first,second,third + + IPv6: as of x11vnc 0.9.10 the -proxy option should + connect to IPv6 hosts properly. If there are problems + you can disable IPv6 by setting -DX11VNC_IPV6=0 + in CPPFLAGS when configuring. If there problems + connecting to IPv6 hosts consider a relay like the + included inet6to4 script. + +-vncconnect Monitor the VNC_CONNECT X property set by the standard +-novncconnect VNC program vncconnect(1). When the property is + set to "host" or "host:port" establish a reverse + connection. Using xprop(1) instead of vncconnect may + work (see the FAQ). The -remote control mechanism uses + X11VNC_REMOTE channel, and this option disables/enables + it as well. Default: -vncconnect + + To use different names for these X11 properties (e.g. to + have separate communication channels for multiple + x11vnc's on the same display) set the VNC_CONNECT or + X11VNC_REMOTE env. vars. to the string you want, for + example: -env X11VNC_REMOTE=X11VNC_REMOTE_12345 + Both sides of the channel must use the same unique name. + The same can be done for the internal X11VNC_TICKER + property (heartbeat and timestamp) if desired. + +-allow host1[,host2..] Only allow client connections from hosts matching + the comma separated list of hostnames or IP addresses. + Can also be a numerical IP prefix, e.g. "192.168.100." + to match a simple subnet, for more control build + LibVNCServer with libwrap support (See the FAQ). If the + list contains a "/" it instead is a interpreted + as a file containing addresses or prefixes that is + re-read each time a new client connects. Lines can be + commented out with the "#" character in the usual way. + + -allow applies in -ssl mode, but not in -stunnel mode. + + IPv6: as of x11vnc 0.9.10 a host can be specified + in IPv6 numerical format, e.g. 2001:4860:b009::93. + +-localhost Basically the same as "-allow 127.0.0.1". + + Note: if you want to restrict which network interface + x11vnc listens on, see the -listen option below. + E.g. "-listen localhost" or "-listen 192.168.3.21". + As a special case, the option "-localhost" implies + "-listen localhost". + + A rare case, but for non-localhost -listen usage, if + you use the remote control mechanism (-R) to change + the -listen interface you may need to manually adjust + the -allow list (and vice versa) to avoid situations + where no connections (or too many) are allowed. + + If you do not want x11vnc to listen on ANY interface + (evidently you are using -connect or -connect_or_exit, + or plan to use remote control: -R connect:host), use + -rfbport 0 + + IPv6: if IPv6 is supported, this option automatically + implies the IPv6 loopback address '::1' as well. + +-listen6 str When in IPv6 listen mode "-6", listen only on the + network interface with address "str". It also works + for link scope addresses (fe80::219:dbff:fee5:3f92%eth0) + and IPv6 hostname strings (e.g. ipv6.google.com.) + Use LibVNCServer -listen option for the IPv4 interface. + +-nolookup Do not use gethostbyname() or gethostbyaddr() to look up + host names or IP numbers. Use this if name resolution + is incorrectly set up and leads to long pauses as name + lookups time out, etc. + +-input string Fine tuning of allowed user input. If "string" does + not contain a comma "," the tuning applies only to + normal clients. Otherwise the part before "," is + for normal clients and the part after for view-only + clients. "K" is for Keystroke input, "M" for + Mouse-motion input, "B" for Button-click input, "C" + is for Clipboard input, and "F" is for File transfer + (ultravnc only). Their presence in the string enables + that type of input. E.g. "-input M" means normal + users can only move the mouse and "-input KMBCF,M" + lets normal users do anything and enables view-only + users to move the mouse. This option is ignored when + a global -viewonly is in effect (all input is discarded + in that case). + +-grabkbd When VNC viewers are connected, attempt to the grab + the keyboard so a (non-malicious) user sitting at the + physical display is not able to enter keystrokes. + This method uses XGrabKeyboard(3X11) and so it is + not secure and does not rule out the person at the + physical display injecting keystrokes by flooding the + server with them, grabbing the keyboard himself, etc. + Some degree of cooperation from the person at the + display is assumed. This is intended for remote + help-desk or educational usage modes. +-grabptr As -grabkbd, but for the mouse pointer using + XGrabPointer(3X11). Unfortunately due to the way the X + server works, the mouse can still be moved around by the + user at the physical display, but he will not be able to + change window focus with it. Also some window managers + that call XGrabServer(3X11) for resizes, etc, will + act on the local user's input. Again, some degree of + cooperation from the person at the display is assumed. + +-grabalways Apply both -grabkbd and -grabptr even when no VNC + viewers are connected. If you only want one of them, + use the -R remote control to turn the other back on, + e.g. -R nograbptr. + +-viewpasswd string Supply a 2nd password for view-only logins. The -passwd + (full-access) password must also be supplied. + +-passwdfile filename Specify the LibVNCServer password via the first line + of the file "filename" (instead of via -passwd on + the command line where others might see it via ps(1)). + + See the descriptions below for how to supply multiple + passwords, view-only passwords, to specify external + programs for the authentication, and other features. + + If the filename is prefixed with "rm:" it will be + removed after being read. Perhaps this is useful in + limiting the readability of the file. In general, the + password file should not be readable by untrusted users + (BTW: neither should the VNC -rfbauth file: it is NOT + encrypted, only obscured with a fixed key). + + If the filename is prefixed with "read:" it will + periodically be checked for changes and reread. It is + guaranteed to be reread just when a new client connects + so that the latest passwords will be used. + + If "filename" is prefixed with "cmd:" then the + string after the ":" is run as an external command: + the output of the command will be interpreted as if it + were read from a password file (see below). If the + command does not exit with 0, then x11vnc terminates + immediately. To specify more than 1000 passwords this + way set X11VNC_MAX_PASSWDS before starting x11vnc. + The environment variables are set as in -accept. + + Note that due to the VNC protocol only the first 8 + characters of a password are used (DES key). + + If "filename" is prefixed with "custom:" then a + custom password checker is supplied as an external + command following the ":". The command will be run + when a client authenticates. If the command exits with + 0 the client is accepted, otherwise it is rejected. + The environment variables are set as in -accept. + + The standard input to the custom command will be a + decimal digit "len" followed by a newline. "len" + specifies the challenge size and is usually 16 (the + VNC spec). Then follows len bytes which is the random + challenge string that was sent to the client. This is + then followed by len more bytes holding the client's + response (i.e. the challenge string encrypted via DES + with the user password in the standard situation). + + The "custom:" scheme can be useful to implement + dynamic passwords or to implement methods where longer + passwords and/or different encryption algorithms + are used. The latter will require customizing the VNC + client as well. One could create an MD5SUM based scheme + for example. + + File format for -passwdfile: + + If multiple non-blank lines exist in the file they are + all taken as valid passwords. Blank lines are ignored. + Password lines may be "commented out" (ignored) if + they begin with the character "#" or the line contains + the string "__SKIP__". Lines may be annotated by use + of the "__COMM__" string: from it to the end of the + line is ignored. An empty password may be specified + via the "__EMPTY__" string on a line by itself (note + your viewer might not accept empty passwords). + + If the string "__BEGIN_VIEWONLY__" appears on a + line by itself, the remaining passwords are used for + viewonly access. For compatibility, as a special case + if the file contains only two password lines the 2nd + one is automatically taken as the viewonly password. + Otherwise the "__BEGIN_VIEWONLY__" token must be + used to have viewonly passwords. (tip: make the 3rd + and last line be "__BEGIN_VIEWONLY__" to have 2 + full-access passwords) + +-showrfbauth filename Print to the screen the obscured VNC password kept in + the rfbauth file "filename" and then exit. + +-unixpw [list] Use Unix username and password authentication. x11vnc + will use the su(1) program to verify the user's + password. [list] is an optional comma separated list + of allowed Unix usernames. If the [list] string begins + with the character "!" then the entire list is taken + as an exclude list. See below for per-user options + that can be applied. + + A familiar "login:" and "Password:" dialog is + presented to the user on a black screen inside the + vncviewer. The connection is dropped if the user fails + to supply the correct password in 3 tries or does not + send one before a 45 second timeout. Existing clients + are view-only during this period. + + If the first character received is "Escape" then the + unix username will not be displayed after "login:" + as it is typed. This could be of use for VNC viewers + that automatically type the username and password. + + Since the detailed behavior of su(1) can vary from + OS to OS and for local configurations, test the mode + before deployment to make sure it is working properly. + x11vnc will attempt to be conservative and reject a + login if anything abnormal occurs. + + One case to note: FreeBSD and the other BSD's by + default it is impossible for the user running x11vnc to + validate his *own* password via su(1) (commenting out + the pam_self.so entry in /etc/pam.d/su eliminates this + behavior). So the x11vnc login will always *FAIL* for + this case (even when the correct password is supplied). + + A possible workaround for this on *BSD would be to + start x11vnc as root with the "-users +nobody" option + to immediately switch to user nobody where the su'ing + will proceed normally. + + Another source of potential problems are PAM modules + that prompt for extra info, e.g. password aging modules. + These logins will fail as well even when the correct + password is supplied. + + **IMPORTANT**: to prevent the Unix password being sent + in *clear text* over the network, one of two schemes + will be enforced: 1) the -ssl builtin SSL mode, or 2) + require both -localhost and -stunnel be enabled. + + Method 1) ensures the traffic is encrypted between + viewer and server. A PEM file will be required, see the + discussion under -ssl below (under some circumstances + a temporary one can be automatically generated). + + Method 2) requires the viewer connection to appear + to come from the same machine x11vnc is running on + (e.g. from a ssh -L port redirection). And that the + -stunnel SSL mode be used for encryption over the + network. (see the description of -stunnel below). + + Note: as a convenience, if you ssh(1) in and start + x11vnc it will check if the environment variable + SSH_CONNECTION is set and appears reasonable. If it + does, then the -ssl or -stunnel requirement will be + dropped since it is assumed you are using ssh for the + encrypted tunnelling. -localhost is still enforced. + Use -ssl or -stunnel to force SSL usage even if + SSH_CONNECTION is set. + + To override the above restrictions you can set + environment variables before starting x11vnc: + + Set UNIXPW_DISABLE_SSL=1 to disable requiring either + -ssl or -stunnel (as under SSH_CONNECTION.) Evidently + you will be using a different method to encrypt the + data between the vncviewer and x11vnc: perhaps ssh(1) + or an IPSEC VPN. -localhost is still enforced (however, + see the next paragraph.) + + Set UNIXPW_DISABLE_LOCALHOST=1 to disable the -localhost + requirement in -unixpw modes. One should never do this + (i.e. allow the Unix passwords to be sniffed on the + network.) This also disables the localhost requirement + for reverse connections (see below.) + + Note that use of -localhost with ssh(1) (and no -unixpw) + is roughly the same as requiring a Unix user login + (since a Unix password or the user's public key + authentication is used by sshd on the machine where + x11vnc runs and only local connections from that machine + are accepted). + + Regarding reverse connections (e.g. -R connect:host + and -connect host), when the -localhost constraint is + in effect then reverse connections can only be used + to connect to the same machine x11vnc is running on + (default port 5500). Please use a ssh or stunnel port + redirection to the viewer machine to tunnel the reverse + connection over an encrypted channel. + + In -inetd mode the Method 1) will be enforced (not + Method 2). With -ssl in effect reverse connections + are disabled. If you override this via env. var, be + sure to also use encryption from the viewer to inetd. + Tip: you can also have your own stunnel spawn x11vnc + in -inetd mode (thereby bypassing inetd). See the FAQ + for details. + + The user names in the comma separated [list] may have + per-user options after a ":", e.g. "fred:opts" + where "opts" is a "+" separated list of + "viewonly", "fullaccess", "input=XXXX", or + "deny", e.g. "karl,wally:viewonly,boss:input=M". + For "input=" it is the K,M,B,C described under -input. + + If an item in the list is "*" that means those + options apply to all users. It ALSO implies all users + are allowed to log in after supplying a valid password. + Use "deny" to explicitly deny some users if you use + "*" to set a global option. If [list] begins with the + "!" character then "*" is ignored for checking if + the user is allowed, but the option values associated + with it do apply as normal. + + There are also some utilities for checking passwords + if [list] starts with the "%" character. See the + quick_pw() function for more details. Description: + "%-" or "%stdin" means read one line from stdin. + "%env" means it is in $UNIXPW env var. A leading + "%/" or "%." means read the first line from the + filename that follows after the % character. % by + itself means prompt for the username and password. + Otherwise: %user:pass E.g. -unixpw %fred:swordfish + For the other cases user:pass is read from the indicated + source. If the password is correct 'Y user' is printed + and the program exit code is 0. If the password is + incorrect it prints 'N user' and the exit code is 1. + If there is some other error the exit code is 2. + This feature enables x11vnc to be a general unix user + password checking tool; it could be used from scripts + or other programs. These % password checks also apply + to the -unixpw_nis and -unixpw_cmd options. + + For the % password check, if the env. var. UNIXPW_CMD + is set to a command then it is run as the user (assuming + the password is correct.) The output of the command is + not printed, the program or script must manage that by + some other means. The exit code of x11vnc will depend + on the exit code of the command that is run. + + Use -nounixpw to disable unixpw mode if it was enabled + earlier in the cmd line (e.g. -svc mode) + +-unixpw_nis [list] As -unixpw above, however do not use su(1) but rather + use the traditional getpwnam(3) + crypt(3) method to + verify passwords. All of the above -unixpw options and + constraints apply. + + This mode requires that the encrypted passwords be + readable. Encrypted passwords stored in /etc/shadow + will be inaccessible unless x11vnc is run as root. + + This is called "NIS" mode simply because in most + NIS setups user encrypted passwords are accessible + (e.g. "ypcat passwd") by an ordinary user and so that + user can authenticate ANY user. + + NIS is not required for this mode to work (only that + getpwnam(3) return the encrypted password is required), + but it is unlikely it will work (as an ordinary user) + for most modern environments unless NIS is available. + On the other hand, when x11vnc is run as root it will + be able to to access /etc/shadow even if NIS is not + available (note running as root is often done when + running x11vnc from inetd and xdm/gdm/kdm). + + Looked at another way, if you do not want to use the + su(1) method provided by -unixpw (i.e. su_verify()), you + can run x11vnc as root and use -unixpw_nis. Any users + with passwords in /etc/shadow can then be authenticated. + + In -unixpw_nis mode, under no circumstances is x11vnc's + user password verifying function based on su called + (i.e. the function su_verify() that runs /bin/su + in a pseudoterminal to verify passwords.) However, + if -unixpw_nis is used in conjunction with the -find + and -create -display WAIT:... modes then, if x11vnc is + running as root, /bin/su may be called externally to + run the find or create commands. + +-unixpw_cmd cmd As -unixpw above, however do not use su(1) but rather + run the externally supplied command "cmd". The first + line of its stdin will be the username and the second + line the received password. If the command exits + with status 0 (success) the VNC user will be accepted. + It will be rejected for any other return status. + + Dynamic passwords and non-unix passwords, e.g. LDAP, + can be implemented this way by providing your own custom + helper program. Note that the remote viewer is given 3 + tries to enter the correct password, and so the program + may be called in a row that many (or more) times. + + If a list of allowed users is needed to limit who can + log in, use -unixpw [list] in addition to this option. + + In FINDDISPLAY and FINDCREATEDISPLAY modes the "cmd" + will also be run with the RFB_UNIXPW_CMD_RUN env. var. + non-empty and set to the corresponding display + find/create command. The first two lines of input are + the username and passwd as in the normal case described + above. To support FINDDISPLAY and FINDCREATEDISPLAY, + "cmd" should run the requested command as the user + (and most likely refusing to run it if the password is + not correct.) Here is an example script (note it has + a hardwired bogus password "abc"!) + + #!/bin/sh + # Example x11vnc -unixpw_cmd script. + # Read the first two lines of stdin (user and passwd) + read user + read pass + + debug=0 + if [ $debug = 1 ]; then + echo "user: $user" 1>&2 + echo "pass: $pass" 1>&2 + env | egrep -i 'rfb|vnc' 1>&2 + fi + + # Check if the password is valid. + # (A real example would use ldap lookup, etc!) + if [ "X$pass" != "Xabc" ]; then + exit 1 # incorrect password + fi + + if [ "X$RFB_UNIXPW_CMD_RUN" = "X" ]; then + exit 0 # correct password + else + # Run the requested command (finddisplay) + if [ $debug = 1 ]; then + echo "run: $RFB_UNIXPW_CMD_RUN" 1>&2 + fi + exec /bin/su - "$user" -c "$RFB_UNIXPW_CMD_RUN" + fi + + In -unixpw_cmd mode, under no circumstances is x11vnc's + user password verifying function based on su called + (i.e. the function su_verify() that runs /bin/su in a + pseudoterminal to verify passwords.) It is up to the + supplied unixpw_cmd to do user switching if desired + and if it has the permissions to do so. + +-find Find the user's display using FINDDISPLAY. This + is an alias for "-display WAIT:cmd=FINDDISPLAY". + + Note: if a -display occurs later on the command line + it will override the -find setting. + + For this and the next few options see -display WAIT:... + below for all of the details. + +-finddpy Run the FINDDISPLAY program, print out the found + display (if any) and exit. Output is like: DISPLAY=:0.0 + DISPLAY=:0.0,XPID=12345 or DISPLAY=:0.0,VT=7. XPID is + the process ID of the found X server. VT is the Linux + virtual terminal of the X server. +-listdpy Have the FINDDISPLAY program list all of your displays + (i.e. all the X displays on the local machine that you + have access rights to). + +-findauth [disp] Apply the -find/-finddpy heuristics to try to guess + the XAUTHORITY file for DISPLAY 'disp'. If 'disp' + is not supplied, then the value in the -display on + the cmdline is used; failing that $DISPLAY is used; + and failing that ":0" is used. + + If nothing is printed out, that means no XAUTHORITY was + found for 'disp'; i.e. failure. If "XAUTHORITY=" + is printed out, that means use the default (i.e. do + not set XAUTHORITY). If "XAUTHORITY=/path/to/file" + is printed out, then use that file. + + XDM/GDM/KDM: if you are running x11vnc as root and want + to find the XAUTHORITY before anyone has logged into an + X session yet, use: x11vnc -env FD_XDM=1 -findauth ... + (This will also find the XAUTHORITY if a user is already + logged into the X session.) When running as root, + FD_XDM=1 will be tried if the initial -findauth fails. + +-create First try to find the user's display using FINDDISPLAY, + if that doesn't succeed create an X session via the + FINDCREATEDISPLAY method. This is an alias for + "-display WAIT:cmd=FINDCREATEDISPLAY-Xvfb". + + Note: if a -display occurs later on the command line + it will override the -create setting. + + SSH NOTE: for both -find and -create you can (should!) + add the "-localhost" option to force SSH tunnel access. + +-xdummy As in -create, except Xdummy instead of Xvfb. +-xvnc As in -create, except Xvnc instead of Xvfb. +-xvnc_redirect As in -create, except Xvnc.redirect instead of Xvfb. +-xdummy_xvfb Sets WAIT:cmd=FINDCREATEDISPLAY-Xdummy,Xvfb + +-create_xsrv str Sets WAIT:cmd=FINDCREATEDISPLAY- Can be on cmdline + after anything that sets WAIT:.. and other things + (e.g. -svc, -xdmsvc) to adjust the X server list. + Example: -svc ... -create_xsrv Xdummy,X + +-svc Terminal services mode based on SSL access. Alias for + -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb -unixpw -users + unixpw= -ssl SAVE Also "-service". + + Note: if a -display, -unixpw, -users, or -ssl occurs + later on the command line it will override the -svc + setting. + +-svc_xdummy As -svc except Xdummy instead of Xvfb. +-svc_xvnc As -svc except Xvnc instead of Xvfb. +-svc_xdummy_xvfb As -svc with Xdummy,Xvfb. + +-xdmsvc Display manager Terminal services mode based on SSL. + Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp + -unixpw -users unixpw= -ssl SAVE Also "-xdm_service". + + Note: if a -display, -unixpw, -users, or -ssl occurs + later on the command line it will override the -xdmsvc + setting. + + To create a session a user will have to first log in + to the -unixpw dialog and then log in again to the + XDM/GDM/KDM prompt. Subsequent re-connections will + only require the -unixpw password. See the discussion + under -display WAIT:... for more details about XDM, + etc configuration. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-sshxdmsvc Display manager Terminal services mode based on SSH. + Alias for -display WAIT:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp + -localhost. + + The -localhost option constrains connections to come + in via a SSH tunnel (which will require a login). + To create a session a user will also have to log into + the XDM GDM KDM prompt. Subsequent re-connections will + only only require the SSH login. See the discussion + under -display WAIT:... for more details about XDM, + etc configuration. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-unixpw_system_greeter Present a "Press 'Escape' for System Greeter" option + to the connecting VNC client in combined -unixpw + and xdmcp FINDCREATEDISPLAY modes (e.g. -xdmsvc). + + Normally in a -unixpw mode the VNC client must + supply a valid username and password to gain access. + However, if -unixpw_system_greeter is supplied AND + the FINDCREATEDISPLAY command matches 'xdmcp', then + the user has the option to press Escape and then get a + XDM/GDM/KDM login/greeter panel instead. They will then + supply a username and password directly to the greeter. + + Otherwise, in xdmcp FINDCREATEDISPLAY mode the user + must supply his username and password TWICE. First to + the initial unixpw login dialog, and second to the + subsequent XDM/GDM/KDM greeter. Note that if the user + re-connects and supplies his username and password in + the unixpw dialog the xdmcp greeter is skipped and + he is connected directly to his existing X session. + So the -unixpw_system_greeter option avoids the extra + password at X session creation time. + + Example: x11vnc -xdmsvc -unixpw_system_greeter + See -unixpw and -display WAIT:... for more info. + + The special options after a colon at the end of the + username (e.g. user:solid) described under -display + WAIT: are also applied in this mode if they are typed + in before the user hits Escape. The username is ignored + but the colon options are not. + + The default message is 2 lines in a small font, set + the env. var. X11VNC_SYSTEM_GREETER1=true for a 1 line + message in a larger font. + + If the user pressed Escape the FINDCREATEDISPLAY command + will be run with the env. var. X11VNC_XDM_ONLY=1. + + Remember to enable XDMCP in the xdm-config, gdm.conf, + or kdmrc configuration file. See -display WAIT: for + more info. + +-redirect port As in FINDCREATEDISPLAY-Xvnc.redirect mode except + redirect immediately (i.e. without X session finding + or creation) to a VNC server listening on port. You + can also supply host:port to redirect to a different + machine. + + If 0 <= port < 200 it is taken as a VNC display (5900 is + added to get the actual port), if port < 0 then -port + is used. + + Probably the only reason to use the -redirect option + is in conjunction with SSL support, e.g. -ssl SAVE. + This provides an easy way to add SSL encryption to a VNC + server that does not support SSL (e.g. Xvnc or vnc.so) + In fact, the protocol does not even need to be VNC, + and so "-rfbport port1 -ssl SAVE -redirect host:port2" + can act as a replacement for stunnel(1). + + This mode only allows one redirected connection. + The -forever option does not apply. Use -inetd or + -loop for persistent service. + +-display_WAIT :... A special usage mode for the normal -display option. + Useful with -unixpw, but can be used independently + of it. If the display string begins with WAIT: then + x11vnc waits until a VNC client connects before opening + the X display (or -rawfb device). + + This could be useful for delaying opening the display + for certain usage modes (say if x11vnc is started at + boot time and no X server is running or users logged + in yet). + + If the string is, e.g. WAIT:0.0 or WAIT:1, i.e. "WAIT" + in front of a normal X display, then that indicated + display is used. + + One can also insert a geometry between colons, e.g. + WAIT:1280x1024:... to set the size of the display the + VNC client first attaches to since some VNC viewers + will not automatically adjust to a new framebuffer size. + + A more interesting case is like this: + + WAIT:cmd=/usr/local/bin/find_display + + in which case the command after "cmd=" is run to + dynamically work out the DISPLAY and optionally the + XAUTHORITY data. The first line of the command output + must be of the form DISPLAY=. On Linux + if the virtual terminal is known append ",VT=n" to + this string and the chvt(1) program will also be run. + Any remaining output is taken as XAUTHORITY data. + It can be either of the form XAUTHORITY= or raw + xauthority data for the display. For example; + + xauth extract - $DISPLAY" + + In the case of -unixpw (and -unixpw_nis only if x11vnc + is running as root), then the cmd= command is run + as the user who just authenticated via the login and + password prompt. + + In the case of -unixpw_cmd, the commands will also be + run as the logged-in user, as long as the user-supplied + helper program supports RFB_UNIXPW_CMD_RUN (see the + -unixpw_cmd option.) + + Also in the case of -unixpw, the user logging in can + place a colon at the end of her username and supply + a few options: scale=, scale_cursor= (or sc=), solid + (or so), id=, clear_mods (or cm), clear_keys (or + ck), clear_all (or ca), repeat, speeds= (or sp=), + readtimeout= (or rd=), viewonly (or vo), nodisplay= + (or nd=), rotate= (or ro=), or noncache (or nc), + all separated by commas if there is more than one. + After the user logs in successfully, these options will + be applied to the VNC screen. For example, + + login: fred:scale=3/4,sc=1,repeat + Password: ... + + login: runge:sp=modem,rd=120,solid + + for convenience m/n implies scale= e.g. fred:3/4 If you + type and enter your password incorrectly, to retrieve + your long "login:" line press the Up arrow once + (before typing anything else). + + In the login panel, press F1 to get a list of the + available options that you can add after the username. + + Another option is "geom=WxH" or "geom=WxHxD" (or + ge=). This only has an effect in FINDCREATEDISPLAY + mode when a virtual X server such as Xvfb is going + to be created. It sets the width and height of + the new display, and optionally the color depth as + well. + + You can also supply "gnome", "kde", "twm", + "fvwm", "mwm", "dtwm", "wmaker", "xfce", + "lxde", "enlightenment", "Xsession", or + "failsafe" (same as "xterm") to have the created + display use that mode for the user session. + + Specify "tag=..." to set the unique FD_TAG desktop + session tag described below. Note: this option will + be ignored if the FD_TAG env. var. is already set or + if the viewer-side supplied value is not completely + composed of alphanumeric or '_' or '-' characters. + + To troubleshoot the FINDCREATEDISPLAY mechanism, + set the following env. var. to an ouput log file, + e.g -env CREATE_DISPLAY_OUTPUT=/tmp/mydebug.txt + + To disable the option setting set the environment + variable X11VNC_NO_UNIXPW_OPTS=1 before starting x11vnc. + To set any other options, the user can use the gui + (x11vnc -gui connect) or the remote control method + (x11vnc -R opt:val) during his VNC session. + + The combination of -display WAIT:cmd=... and -unixpw + allows automatic pairing of an unix authenticated VNC + user with his desktop. This could be very useful on + SunRays and also any system where multiple users share + a given machine. The user does not need to remember + special ports or passwords set up for his desktop + and VNC. + + A nice way to use WAIT:cmd=... is out of inetd(8) + (it automatically forks a new x11vnc for each user). + You can have the x11vnc inetd spawned process run as, + say, root or nobody. When run as root (for either inetd + or display manager), you can also supply the option + "-users unixpw=" to have the x11vnc process switch to + the user as well. Note: there will be a 2nd SSL helper + process that will not switch, but it is only encoding + and decoding the encrypted stream at that point. + + Automatic Finding of User X Sessions: + + As a special case, WAIT:cmd=FINDDISPLAY will run a + script that works on most Unixes to determine a user's + DISPLAY variable and xauthority data (see who(1)). + + The option "-find" is an alias for this mode. + + To have this default script printed to stdout (e.g. for + customization) run with WAIT:cmd=FINDDISPLAY-print To + have the script run to print what display it would find + use "-finddpy" or WAIT:cmd=FINDDISPLAY-run + + The standard script runs xdpyinfo(1) run on potential + displays. If your X server(s) have a login greeter + that exclusively grabs the Xserver, then xdpyinfo + blocks forever and this mode will not work. See + www.karlrunge.com/x11vnc/faq.html#faq-display-manager + for how to disable this for dtgreet on Solaris and + possibly for other greeters. + + In -find/cmd=FINDDISPLAY mode, if you set FD_XDM=1, + e.g. 'x11vnc -env FD_XDM=1 -find ...' and x11vnc is + running as root (e.g. inetd) then it will try to find + the XAUTHORITY file of a running XDM/GDM/KDM login + greeter (i.e. no user has logged into an X session yet.) + + As another special case, WAIT:cmd=HTTPONCE will allow + x11vnc to service one http request and then exit. + This is usually done in -inetd mode to run on, say, + port 5800 and allow the Java vncviewer to be downloaded + by client web browsers. For example: + + 5815 stream tcp nowait root /usr/sbin/tcpd /.../x11vnc +\ + -inetd -q -http_ssl -prog /.../x11vnc \ + -display WAIT:cmd=HTTPONCE + + Where /.../x11vnc is the full path to x11vnc. + It is used in the Apache SSL-portal example (see FAQ). + + In this mode you can set X11VNC_SKIP_DISPLAY to a + comma separated list of displays (e.g. ":0,:1") to + ignore in the finding process. The ":" is optional. + Ranges n-m e.g. 0-20 can also be supplied. This string + can also be set by the connecting user via "nd=" + using "+" instead of "," If "nd=all" or you set + X11VNC_SKIP_DISPLAY=all then all display finding fails + as if you set X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (below.) + + Automatic Creation of User X Sessions: + + An interesting option is WAIT:cmd=FINDCREATEDISPLAY + that is like FINDDISPLAY in that is uses the same method + to find an existing display. However, if it does not + find one it will try to *start* up an X server session + for the user. This is the only time x11vnc tries to + actually start up an X server. + + The option "-create" is an alias for this mode. + + It will start looking for an open display number at :20 + Override via X11VNC_CREATE_STARTING_DISPLAY_NUMBER=n + + By default FINDCREATEDISPLAY will try Xvfb and then + Xdummy: + + The Xdummy wrapper is part of the x11vnc source code + (x11vnc/misc/Xdummy) It should be available in PATH + and have run "Xdummy -install" once to create the + shared library. Xdummy only works on Linux. As of + 12/2009 it no longer needs to be run as root, and the + default is to not run as root. In some circumstances + permissions may require running it as root, in these + cases specify FD_XDUMMY_RUN_AS_ROOT=1, this is the same + as supplying -root to the Xdummy cmdline. + + Xvfb is available on most platforms and does not + require root. + + An advantage of Xdummy over Xvfb is that Xdummy supports + RANDR dynamic screen resizing. + + When x11vnc exits (i.e. user disconnects) the X + server session stays running in the background. + The FINDDISPLAY will find it directly next time. + The user must exit the X session in the usual way for + it to terminate (or kill the X server process if all + else fails). + + So this is a somewhat odd mode for x11vnc in that it + will start up and poll virtual X servers! This can + be used from, say, inetd(8) to provide a means of + definitely getting a desktop (either real or virtual) + on the machine. E.g. a desktop service: + + 5900 stream tcp nowait root /usr/sbin/tcpd /.../x11vnc + -inetd -q -http -ssl SAVE -unixpw -users unixpw=\ + -passwd secret -prog /.../x11vnc \ + -display WAIT:cmd=FINDCREATEDISPLAY + + Where /.../x11vnc is the full path to x11vnc. + + See the -svc/-service option alias above. + + If for some reason you do not want x11vnc to ever + try to find an existing display set the env. var + X11VNC_FINDDISPLAY_ALWAYS_FAILS=1 (also -env ...) + This is the same as setting X11VNC_SKIP_DISPLAY=all or + supplying "nd=all" after "username:" + + Use WAIT:cmd=FINDCREATEDISPLAY-print to print out the + script that is used for this. + + You can specify the preferred X server order via e.g., + WAIT:cmd=FINDCREATEDISPLAY-Xdummy,Xvfb,X and/or leave + out ones you do not want. The the case "X" means try + to start up a real, hardware X server using xinit(1) + or startx(1). If there is already an X server running + the X case may only work on Linux (see startx(1)). + + "Xvnc" will start up a VNC X server (real- + or tight-vnc, e.g. use if Xvfb is not available). + "Xsrv" will start up the server program in the + variable "FD_XSRV" if it is non-empty. You can make + this be a wrapper script if you like (it must handle :N, + -geometry, and -depth and other X server options). + + You can set the environment variable FD_GEOM (or + X11VNC_CREATE_GEOM) to WxH or WxHxD to set the width + and height and optionally the color depth of the + created display. You can also set FD_SESS to be the + session (short name of the windowmanager: kde, gnome, + twm, failsafe, etc.). FD_OPTS contains extra options + to pass to the X server. You can also set FD_PROG to + be the full path to the session/windowmanager program. + + More FD tricks: FD_CUPS=port or FD_CUPS=host:port + will set the cups printing environment. Similarly for + FD_ESD=port or FD_ESD=host:port for esddsp sound + redirection. Set FD_EXTRA to a command to be run a + few seconds after the X server starts up. Set FD_TAG + to be a unique name for the session, it is set as an + X property, that makes FINDDISPLAY only find sessions + with that tag value. + + Set FD_XDMCP_IF to the network interface that the + display manager is running on; default is 'localhost' + but you may need to set it to '::1' on some IPv6 only + systems or misconfigured display managers. + + If you want the FINDCREATEDISPLAY session to contact an + XDMCP login manager (xdm/gdm/kdm) on the same machine, + then use "Xvfb.xdmcp" instead of "Xvfb", etc. + The user will have to supply his username and password + one more time (but he gets to select his desktop type + so that can be useful). For this to work, you will + need to enable localhost XDMCP (udp port 177) for the + display manager. This seems to be: + + for gdm in gdm.conf: Enable=true in section [xdmcp] + for kdm in kdmrc: Enable=true in section [Xdmcp] + for xdm in xdm-config: DisplayManager.requestPort: 177 + + See the shorthand options above "-svc", "-xdmsvc" + and "-sshxdmsvc" that specify the above options for + some useful cases. + + If you set the env. var WAITBG=1 x11vnc will go into + the background once listening in wait mode. + + Another special mode is FINDCREATEDISPLAY-Xvnc.redirect, + (or FINDDISPLAY-Xvnc.redirect). In this case it will + start up Xvnc as above if needed, but instead of + polling it in its normal way, it simply does a socket + redirection of the connected VNC viewer to the Xvnc. + + So in Xvnc.redirect x11vnc does no VNC but merely + transfers the data back and forth. This should be + faster then x11vnc's polling method, but not as fast + as connecting directly to the Xvnc with the VNC Viewer. + The idea here is to take advantage of x11vnc's display + finding/creating scheme, SSL, and perhaps a few others. + Most of x11vnc's options do not apply in this mode. + + Xvnc.redirect should also work for the vnc.so X server + module for the h/w display however it will work only + for finding the display and the user must already be + logged into the X console. + +-vencrypt mode The VeNCrypt extension to the VNC protocol allows + encrypted SSL/TLS connections. If the -ssl mode is + enabled, then VeNCrypt is enabled as well BY DEFAULT + (they both use a SSL/TLS tunnel, only the protocol + handshake is a little different.) + + To control when and how VeNCrypt is used, specify the + mode string. If mode is "never", then VeNCrypt is + not used. If mode is "support" (the default) then + VeNCrypt is supported. If mode is "only", then the + similar and older ANONTLS protocol is not simultaneously + supported. x11vnc's normal SSL mode (vncs://) will be + supported under -ssl unless you set mode to "force". + + If mode is prefixed with "nodh:", then Diffie Hellman + anonymous key exchange is disabled. If mode is prefixed + with "nox509:", then X509 key exchange is disabled. + + To disable all Anonymous Diffie-Hellman access + (susceptible to Man-In-The-Middle attack) you will need + to supply "-vencrypt nodh:support -anontls never" + or "-vencrypt nodh:only" + + If mode is prefixed with "newdh:", then new Diffie + Hellman parameters are generated for each connection + (this can be time consuming: 1-60 secs; see -dhparams + below for a faster way) rather than using the + fixed values in the program. Using fixed, publicly + known values is not known to be a security problem. + This setting applies to ANONTLS as well. + + Long example: -vencrypt newdh:nox509:support + + Also, if mode is prefixed with "plain:", then + if -unixpw mode is active the VeNCrypt "*Plain" + username+passwd method is enabled for Unix logins. + Otherwise in -unixpw mode the normal login panel is + provided. + + You *MUST* supply the -ssl option for VeNCrypt to + be active. The -vencrypt option only fine-tunes its + operation. + +-anontls mode The ANONTLS extension to the VNC protocol allows + encrypted SSL/TLS connections. If the -ssl mode is + enabled, then ANONTLS is enabled as well BY DEFAULT + (they both use a SSL/TLS tunnel, only the protocol + handshake is a little different.) + + ANONTLS is an older SSL/TLS mode introduced by vino. + + It is referred to as 'TLS' for its registered VNC + security-type name, but we use the more descriptive + 'ANONTLS' here because it provides only Anonymous + Diffie-Hellman encrypted connections, and hence no + possibility for certificate authentication. + + To control when and how ANONTLS is used, specify the + mode string. If mode is "never", then ANONTLS is not + used. If mode is "support" (the default) then ANONTLS + is supported. If mode is "only", then the similar + VeNCrypt protocol is not simultaneously supported. + x11vnc's normal SSL mode (vncs://) will be supported + under -ssl unless you set mode to "force". + + If mode is prefixed with "newdh:", then new Diffie + Hellman parameters are generated for each connection + (this can be time consuming: 1-60 secs; see -dhparams + below for a faster way) rather than using the + fixed values in the program. Using fixed, publicly + known values is not known to be a security problem. + This setting applies to VeNCrypt as well. See the + description of "plain:" under -vencrypt. + + Long example: -anontls newdh:plain:support + + You *MUST* supply the -ssl option for ANONTLS to + be active. The -anontls option only fine-tunes its + operation. + +-sslonly Same as: "-vencrypt never -anontls never" i.e. it + disables the VeNCrypt and ANONTLS encryption methods + and only allows standard SSL tunneling. You must also + supply the -ssl ... option (see below.) + + +-dhparams file For some operations a set of Diffie Hellman parameters + (prime and generator) is needed. If so, use the + parameters in "file". In particular, the VeNCrypt and + ANONTLS anonymous DH mode need them. By default a + fixed set is used. If you do not want to do that you + can specify "newdh:" to the -vencrypt and -anontls + options to generate a new set each session. If that + is too slow for you, use -dhparams file to a set you + created manually via "openssl dhparam -out file 1024" + +-nossl Disable the -ssl option (see below). Since -ssl is off + by default -nossl would only be used on the commandline + to unset any *earlier* -ssl option (or -svc...) + +-ssl [pem] Use the openssl library (www.openssl.org) to provide a + built-in encrypted SSL/TLS tunnel between VNC viewers + and x11vnc. This requires libssl support to be + compiled into x11vnc at build time. If x11vnc is not + built with libssl support it will exit immediately when + -ssl is prescribed. See the -stunnel option below for + an alternative. + + The VNC Viewer-side needs to support SSL/TLS as well. + See this URL and also the discussion below for + ideas on how to enable SSL support for the viewer: + http://www.karlrunge.com/x11vnc/faq.html#faq-ssl-tun + nel-viewers . x11vnc provides an SSL enabled Java + viewer applet in the classes/ssl directory (-http or + -httpdir options.) The SSVNC viewer package supports + SSL tunnels too. + + If the VNC Viewer supports VeNCrypt or ANONTLS (vino's + encryption mode) they are also supported by the -ssl + mode (see the -vencrypt and -anontls options for more + info; use -sslonly to disable both of them.) + + Use "-ssl /path/to/mycert.pem" to specify an SSL + certificate file in PEM format to use to identify and + provide a key for this server. See openssl(1) for more + info about PEMs and the -sslGenCert and "-ssl SAVE" + options below for how to create them. + + The connecting VNC viewer SSL tunnel can (at its option) + authenticate this server if it has the public key part + of the certificate (or a common certificate authority, + CA, is a more sophisticated way to verify this server's + cert, see -sslGenCA below). This authentication is + done to prevent Man-In-The-Middle attacks. Otherwise, + if the VNC viewer simply accepts this server's key + WITHOUT verification, the traffic is protected from + passive sniffing on the network, but *NOT* from + Man-In-The-Middle attacks. There are hacker tools + like dsniff/webmitm and cain that implement SSL + Man-In-The-Middle attacks. + + If [pem] is empty or the string "SAVE" then the + openssl(1) command must be available to generate the + certificate the first time. A self-signed certificate + is generated (see -sslGenCA and -sslGenCert for use + of a Certificate Authority.) It will be saved to the + file ~/.vnc/certs/server.pem. On subsequent calls if + that file already exists it will be used directly. + + Use "SAVE_NOPROMPT" to avoid being prompted to + protect the generated key with a passphrase. However in + -inetd and -bg modes there will be no prompting for a + passphrase in either case. + + If [pem] is "SAVE_PROMPT" the server.pem certificate + will be created based on your answers to its prompts for + all info such as OrganizationalName, CommonName, etc. + + Use "SAVE-" and "SAVE_PROMPT-" + to refer to the file ~/.vnc/certs/server-.pem + instead (it will be generated if it does not already + exist). E.g. "SAVE-charlie" will store to the file + ~/.vnc/certs/server-charlie.pem + + Examples: x11vnc -ssl SAVE -display :0 ... + x11vnc -ssl SAVE-someother -display :0 ... + + If [pem] is "TMP" and the openssl(1) utility + command exists in PATH, then a temporary, self-signed + certificate will be generated for this session. If + openssl(1) cannot be used to generate a temporary + certificate x11vnc exits immediately. The temporary + cert will be discarded when x11vnc exits. + + If successful in using openssl(1) to generate a + temporary certificate in "SAVE" or "TMP" creation + modes, the public part of it will be displayed to stderr + (e.g. one could copy it to the client-side to provide + authentication of the server to VNC viewers.) + + NOTE: In "TMP" mode, unless you safely copy the + public part of the temporary Cert to the viewer for + authenticate *every time* (unlikely...), then only + passive sniffing attacks are prevented and you are + still open to Man-In-The-Middle attacks. This is + why the default "SAVE" mode is preferred (and more + sophisticated CA mode too). Only with saved keys AND + the VNC viewer authenticating them (via the public + certificate), are Man-In-The-Middle attacks prevented. + + If [pem] is "ANON" then the Diffie-Hellman anonymous + key exchange method is used. In this mode there + are *no* SSL certificates and so it is not possible + to authenticate either the VNC server or VNC client. + Thus only passive network sniffing attacks are avoided: + the "ANON" method is susceptible to Man-In-The-Middle + attacks. "ANON" is not recommended; instead use + a SSL PEM you created or the default "SAVE" method. + + See -ssldir below to use a directory besides the + default ~/.vnc/certs + + If your x11vnc binary was not compiled with OpenSSL + library support, use of the -ssl option will induce an + immediate failure and exit. For such binaries, consider + using the -stunnel option for SSL encrypted connections. + + Misc Info: In temporary cert creation mode "TMP", set + the env. var. X11VNC_SHOW_TMP_PEM=1 to have x11vnc print + out the entire certificate, including the PRIVATE KEY + part, to stderr. There are better ways to get/save this + info. See "SAVE" above and "-sslGenCert" below. + +-ssltimeout n Set SSL read timeout to n seconds. In some situations + (i.e. an iconified viewer in Windows) the viewer stops + talking and the connection is dropped after the default + timeout (25s for about the first minute, 43200s later). + Set to zero to poll forever. Set to a negative value + to use the builtin setting. + + Note that this value does NOT apply to the *initial* ssl + init connection. The default timeout for that is 20sec. + Use -env SSL_INIT_TIMEOUT=n to modify it. + +-sslnofail Exit at the first SSL connection failure. Useful when + scripting SSL connections (e.g. x11vnc is started via + ssh) and you do not want x11vnc waiting around for more + connections, tying up ports, etc. + +-ssldir dir Use "dir" as an alternate ssl certificate and key + management toplevel directory. The default is + ~/.vnc/certs + + This directory is used to store server and other + certificates and keys and also other materials. E.g. in + the simplest case, "-ssl SAVE" will store the x11vnc + server cert in dir/server.pem + + Use of alternate directories via -ssldir allows you to + manage multiple VNC Certificate Authority (CA) keys. + Another use is if ~/.vnc/cert is on an NFS share you + might want your certificates and keys to be on a local + filesystem to prevent network snooping (for example + -ssldir /var/lib/x11vnc-certs). + + -ssldir affects nearly all of the other -ssl* options, + e.g. -ssl SAVE, -sslGenCert, etc.. + +-sslverify path For either of the -ssl or -stunnel modes, use "path" + to provide certificates to authenticate incoming VNC + *Client* connections (normally only the server is + authenticated in SSL.) This can be used as a method + to replace standard password authentication of clients. + + If "path" is a directory it contains the client (or CA) + certificates in separate files. If path is a file, + it contains one or more certificates. See special tokens + below. These correspond to the "CApath = dir" and + "CAfile = file" stunnel options. See the stunnel(8) + manpage for details. + + Examples: + x11vnc -ssl -sslverify ~/my.crt + x11vnc -ssl -sslverify ~/my_pem_dir/ + + Note that if path is a directory, it must contain + the certs in separate files named like .0, where + the value of is found by running the command + "openssl x509 -hash -noout -in file.crt". Evidently + one uses .1 if there is a collision... + + The the key-management utility "-sslCertInfo HASHON" + and "-sslCertInfo HASHOFF" will create/delete these + hashes for you automatically (via symlink) in the HASH + subdirs it manages. Then you can point -sslverify to + the HASH subdir. + + Special tokens: in -ssl mode, if "path" is not a file or + a directory, it is taken as a comma separated list of + tokens that are interpreted as follows: + + If a token is "CA" that means load the CA/cacert.pem + file from the ssl directory. If a token is "clients" + then all the files clients/*.crt in the ssl directory + are loaded. Otherwise the file clients/token.crt + is attempted to be loaded. As a kludge, use a token + like ../server-foo to load a server cert if you find + that necessary. + + Use -ssldir to use a directory different from the + ~/.vnc/certs default. + + Note that if the "CA" cert is loaded you do not need + to load any of the certs that have been signed by it. + You will need to load any additional self-signed certs + however. + + Examples: + x11vnc -ssl -sslverify CA + x11vnc -ssl -sslverify self:fred,self:jim + x11vnc -ssl -sslverify CA,clients + + Usually "-sslverify CA" is the most effective. + See the -sslGenCA and -sslGenCert options below for + how to set up and manage the CA framework. + + + + NOTE: the following utilities, -sslGenCA, -sslGenCert, + -sslEncKey, -sslCertInfo, and -sslCRL are provided for + completeness, but for casual usage they are overkill. + + They provide VNC Certificate Authority (CA) key creation + and server / client key generation and signing. So they + provide a basic Public Key management framework for + VNC-ing with x11vnc. (note that they require openssl(1) + be installed on the system) + + However, the simplest usage mode, "-ssl TMP" (where + x11vnc automatically generates its own, self-signed, + temporary key and the VNC viewers always accept it, + e.g. accepting via a dialog box) is probably safe enough + for most scenarios. CA management is not needed. + + To protect against Man-In-The-Middle attacks the "TMP" + mode can be improved by using "-ssl SAVE" (same as + "-ssl", i.e. the default) to have x11vnc create a + longer term self-signed certificate, and then (safely) + copy the corresponding public key cert to the desired + client machines (care must be taken the private key part + is not stolen; you will be prompted for a passphrase). + + So keep in mind no CA key creation or management + (-sslGenCA and -sslGenCert) is needed for either of + the above two common usage modes. + + One might want to use -sslGenCA and -sslGenCert + if you had a large number of VNC client and server + workstations. That way the administrator could generate + a single CA key with -sslGenCA and distribute its + certificate part to all of the workstations. + + Next, he could create signed VNC server keys + (-sslGenCert server ...) for each workstation or user + that then x11vnc would use to authenticate itself to + any VNC client that has the CA cert. + + Optionally, the admin could also make it so the + VNC clients themselves are authenticated to x11vnc + (-sslGenCert client ...) For this -sslverify would be + pointed to the CA cert (and/or self-signed certs). + + x11vnc will be able to use all of these cert and + key files. On the VNC client side, they will need to + be "imported" somehow. Web browsers have "Manage + Certificates" actions as does the Java applet plugin + Control Panel. stunnel can also use these files (see + the ss_vncviewer example script in the FAQ and SSVNC.) + +-sslCRL path Set the Certificate Revocation Lists (CRL) to "path". + This setting applies for both -ssl and -stunnel modes. + + If path is a file, the file contains one or more CRLs + in PEM format. If path is a directory, it contains + hash named files of CRLs in the usual OpenSSL manner. + See the OpenSSL and stunnel(8) documentation for + more info. + + This option only applies if -sslverify has been + supplied: it checks for revocation along the + certificate chain used to verify the VNC client. + The -sslCRL setting will be ignored when -sslverify is + not specified. + + Note that if a CRL's expiration date has passed, all + SSL connections will fail regardless of if they are + related to the subject of the CRL or not. + + Only rarely will one's x11vnc -ssl infrastructure be so + large that this option would be useful (since normally + maintaining the contents of the -sslverify file or + directory should be enough.) However, when using + x11vnc with a Certificate Authority (see -sslGenCA) + to authenticate Clients via SSL/TLS, the -sslCRL option + can be useful to revoke users' certs whose private SSL + keys were lost or stolen (e.g. laptop.) This way a new + CA cert+key does not need to be created and new signed + client keys generated and distributed to all users. + + To create a CRL file with revoked certificates the + commands 'openssl ca -revoke ...' and 'openssl ca + -gencrl ...' are useful. (Run them in ~/.vnc/certs) + +-sslGenCA [dir] Generate your own Certificate Authority private key, + certificate, and other files in directory [dir]. + + If [dir] is not supplied, a -ssldir setting is used, + or otherwise ~/.vnc/certs is used. + + This command also creates directories where server and + client certs and keys will be stored. The openssl(1) + program must be installed on the system and available + in PATH. + + After the CA files and directories are created the + command exits; the VNC server is not run. + + You will be prompted for information to put into the CA + certificate. The info does not have to be accurate just + as long as clients accept the cert for VNC connections. + You will also need to supply a passphrase of at least + 4 characters for the CA private key. + + Once you have generated the CA you can distribute + its certificate part, [dir]/CA/cacert.pem, to other + workstations where VNC viewers will be run. One will + need to "import" this certificate in the applications, + e.g. Web browser, Java applet plugin, stunnel, etc. + Next, you can create and sign keys using the CA with + the -sslGenCert option below. + + Examples: + x11vnc -sslGenCA + x11vnc -sslGenCA ~/myCAdir + x11vnc -ssldir ~/myCAdir -sslGenCA + + (the last two lines are equivalent) + +-sslGenCert type name Generate a VNC server or client certificate and private + key pair signed by the CA created previously with + -sslGenCA. The openssl(1) program must be installed + on the system and available in PATH. + + After the Certificate is generated the command exits; + the VNC server is not run. + + The type of key to be generated is the string "type". + It is either "server" (i.e. for use by x11vnc) or + "client" (for a VNC viewer). Note that typically + only "server" is used: the VNC clients authenticate + themselves by a non-public-key method (e.g. VNC or + unix password). "type" is required. + + An arbitrary default name you want to associate with + the key is supplied by the "name" string. You can + change it at the various prompts when creating the key. + "name" is optional. + + If name is left blank for clients keys then "nobody" + is used. If left blank for server keys, then the + primary server key: "server.pem" is created (this + is the saved one referenced by "-ssl SAVE" when the + server is started) + + If "name" begins with the string "self:" then + a self-signed certificate is created instead of one + signed by your CA key. + + If "name" begins with the string "req:" then only a + key (.key) and a certificate signing *request* (.req) + are generated. You can then send the .req file to + an external CA (even a professional one, e.g. Thawte) + and then combine the .key and the received cert into + the .pem file with the same basename. + + The distinction between "server" and "client" is + simply the choice of output filenames and sub-directory. + This makes it so the -ssl SAVE-name option can easily + pick up the x11vnc PEM file this option generates. + And similarly makes it easy for the -sslverify option + to pick up your client certs. + + There is nothing special about the filename or directory + location of either the "server" and "client" certs. + You can rename the files or move them to wherever + you like. + + Precede this option with -ssldir [dir] to use a + directory other than the default ~/.vnc/certs You will + need to run -sslGenCA on that directory first before + doing any -sslGenCert key creation. + + Note you cannot recreate a cert with exactly the same + distiguished name (DN) as an existing one. To do so, + you will need to edit the [dir]/CA/index.txt file to + delete the line. + + Similar to -sslGenCA, you will be prompted to fill + in some information that will be recorded in the + certificate when it is created. + + Tip: if you know the fully-qualified hostname other + people will be connecting to, you can use that as the + CommonName "CN" to avoid some applications (e.g. web + browsers and java plugin) complaining that it does not + match the hostname. + + You will also need to supply the CA private key + passphrase to unlock the private key created from + -sslGenCA. This private key is used to sign the server + or client certificate. + + The "server" certs can be used by x11vnc directly by + pointing to them via the -ssl [pem] option. The default + file will be ~/.vnc/certs/server.pem. This one would + be used by simply typing -ssl SAVE. The pem file + contains both the certificate and the private key. + server.crt file contains the cert only. + + The "client" cert + private key file will need + to be copied and imported into the VNC viewer + side applications (Web browser, Java plugin, + stunnel, etc.) Once that is done you can delete the + "client" private key file on this machine since + it is only needed on the VNC viewer side. The, + e.g. ~/.vnc/certs/clients/.pem contains both + the cert and private key. The .crt contains the + certificate only. + + NOTE: It is very important to know one should + generate new keys with a passphrase. Otherwise if an + untrusted user steals the key file he could use it to + masquerade as the x11vnc server (or VNC viewer client). + You will be prompted whether to encrypt the key with + a passphrase or not. It is recommended that you do. + One inconvenience to a passphrase is that it must + be typed in EVERY time x11vnc or the client app is + started up. + + Examples: + + x11vnc -sslGenCert server + x11vnc -ssl SAVE -display :0 ... + + and then on viewer using ss_vncviewer stunnel wrapper + (see the FAQ): + ss_vncviewer -verify ./cacert.crt hostname:0 + + (this assumes the cacert.crt cert from -sslGenCA + was safely copied to the VNC viewer machine where + ss_vncviewer is run) + + Example using a name: + + x11vnc -sslGenCert server charlie + x11vnc -ssl SAVE-charlie -display :0 ... + + Example for a client certificate (rarely used): + + x11vnc -sslGenCert client roger + scp ~/.vnc/certs/clients/roger.pem somehost:. + rm ~/.vnc/certs/clients/roger.pem + + x11vnc is then started with the the option -sslverify + ~/.vnc/certs/clients/roger.crt (or simply -sslverify + roger), and on the viewer user on somehost could do + for example: + + ss_vncviewer -mycert ./roger.pem hostname:0 + + If you set the env. var REQ_ARGS='...' it will be + passed to openssl req(1). A common use would be + REQ_ARGS='-days 1095' to bump up the expiration date + (3 years in this case). + +-sslEncKey pem Utility to encrypt an existing PEM file with a + passphrase you supply when prompted. For that key to be + used (e.g. by x11vnc) the passphrase must be supplied + each time. + + The "SAVE" notation described under -ssl applies as + well. (precede this option with -ssldir [dir] to refer + a directory besides the default ~/.vnc/certs) + + The openssl(1) program must be installed on the system + and available in PATH. After the Key file is encrypted + the command exits; the VNC server is not run. + + Examples: + x11vnc -sslEncKey /path/to/foo.pem + x11vnc -sslEncKey SAVE + x11vnc -sslEncKey SAVE-charlie + +-sslCertInfo pem Prints out information about an existing PEM file. + In addition the public certificate is also printed. + The openssl(1) program must be in PATH. Basically the + command "openssl x509 -text" is run on the pem. + + The "SAVE" notation described under -ssl applies + as well. + + Using "LIST" will give a list of all certs being + managed (in the ~/.vnc/certs dir, use -ssldir to refer + to another dir). "ALL" will print out the info for + every managed key (this can be very long). Giving a + client or server cert shortname will also try a lookup + (e.g. -sslCertInfo charlie). Use "LISTL" or "LL" + for a long (ls -l style) listing. + + Using "HASHON" will create subdirs [dir]/HASH and + [dir]/HASH with OpenSSL hash filenames (e.g. 0d5fbbf1.0) + symlinks pointing up to the corresponding *.crt file. + ([dir] is ~/.vnc/certs or one given by -ssldir.) + This is a useful way for other OpenSSL applications + (e.g. stunnel) to access all of the certs without + having to concatenate them. x11vnc will not use them + unless you specifically reference them. "HASHOFF" + removes these HASH subdirs. + + The LIST, LISTL, LL, ALL, HASHON, HASHOFF words can + also be lowercase, e.g. "list". + +-sslDelCert pem Prompts you to delete all .crt .pem .key .req files + associated with [pem]. "SAVE" and lookups as in + -sslCertInfo apply as well. + +-sslScripts Prints out both the 'genCA' and 'genCert' x11vnc + openssl wrapper scripts for you to examine, modify, etc. + The scripts are printed to stdout and then the program + exits. + + +-stunnel [pem] Use the stunnel(8) (stunnel.mirt.net) to provide an + encrypted SSL tunnel between viewers and x11vnc. + + This external tunnel method was implemented prior to the + integrated -ssl encryption described above. It still + works well and avoids the requirement of linking with + the OpenSSL libraries. This mode requires stunnel + to be installed on the system and available via PATH + (n.b. stunnel is often installed in sbin directories). + Version 4.x of stunnel is assumed (but see -stunnel3 + below.) + + [pem] is optional, use "-stunnel /path/to/stunnel.pem" + to specify a PEM certificate file to pass to stunnel. + See the -ssl option for more info on certificate files. + + Whether or not your stunnel has its own certificate + depends on your stunnel configuration; stunnel often + generates one at install time. See your stunnel + documentation for details. In any event, if you want to + use this certificate you must supply the full path to it + as [pem]. Note: the file may only be readable by root. + + [pem] may also be the special strings "TMP", "SAVE", + and "SAVE..." as described in the -ssl option. + If [pem] is not supplied, "SAVE" is assumed. + + Note that the VeNCrypt, ANONTLS, and "ANON" modes + are not supported in -stunnel mode. + + stunnel is started up as a child process of x11vnc and + any SSL connections stunnel receives are decrypted and + sent to x11vnc over a local socket. The strings + "The SSL VNC desktop is ..." and "SSLPORT=..." + are printed out at startup to indicate this. + + The -localhost option is enforced by default to avoid + people routing around the SSL channel. Use -env + STUNNEL_DISABLE_LOCALHOST=1 to disable this security + requirement. + + Set -env STUNNEL_DEBUG=1 for more debugging printout. + + Set -env STUNNEL_PROG=xxx to the full path of stunnel + program you want to be used (e.g. /usr/bin/stunnel4). + + Set -env STUNNEL_LISTEN=xxx to the address of the + network interface to listen on (the default is to listen + on all interfaces), e.g. STUNNEL_LISTEN=192.168.1.100. + + A simple way to add IPv6 support is STUNNEL_LISTEN=:: + + Your VNC viewer will also need to be able to connect + via SSL. Unfortunately not too many do this. See the + information about SSL viewers under the -ssl option. + The x11vnc project's SSVNC is an option. + + Also, in the x11vnc distribution, patched TightVNC + and UltraVNC Java applet jar files are provided in + the classes/ssl directory that do SSL connections. + Enable serving them with the -http, -http_ssl, or + -httpdir (see the option descriptions for more info.) + + Note that for the Java viewer applet usage the + "?PORT=xxxx" in the various URLs printed at startup + will need to be supplied to the web browser to connect + properly. + + Currently the automatic "single port" HTTPS mode of + -ssl is not fully supported in -stunnel mode. However, + it can be emulated via: + + % x11vnc -stunnel -http_ssl -http_oneport ... + + In general, it is also not too difficult to set up + an stunnel or other SSL tunnel on the viewer side. + A simple example on Unix using stunnel 3.x is: + + % stunnel -c -d localhost:5901 -r remotehost:5900 + % vncviewer localhost:1 + + For Windows, stunnel has been ported to it and there + are probably other such tools available. See the FAQ + and SSVNC for more examples. + +-stunnel3 [pem] Use version 3.x stunnel command line syntax instead of + version 4.x. The -http/-httpdir Java applet serving + is currently not available in this mode. + +-enc cipher:keyfile Use symmetric encryption with cipher "cipher" + and secret key data in "keyfile". If keyfile is + pw= then "string" is used as the key data. + + NOTE: It is recommended that you use SSL via the -ssl + option instead of this option because SSL is well + understood and takes great care to establish unique + session keys and is more compatible with other software. + Use this option if you do not want to deal with SSL + certificates for authentication and do not want to + use SSH but want some encryption for your VNC session. + Or if you must interface with a symmetric key tunnel + that you do not have control over. + + Note that this mode will NOT work with the UltraVNC DSM + plugins because they alter the RFB protocol in addition + to tunnelling with the symmetric cipher (an unfortunate + choice of implementation...) + + cipher can be one of: arc4, aesv2, aes-cfb, blowfish, + aes256, or 3des. See the OpenSSL documentation for + more info. The keysize is 128 bits (except for aes256). + Here is one way to make a keyfile with that many bits: + + dd if=/dev/random of=./my.key bs=16 count=1 + + you will need to securely share this key with the other + side of the VNC connection (See SSVNC for examples). + + Example: -enc blowfish:./my.key + Example: -enc blowfish:pw=swordfish + + By default 16 bytes of random salt followed by 16 bytes + of random initialization vector are sent at the very + beginning of the stream. The other side must read these + and initialize their cipher with them. These values + make the session key unique (without them the security + is minimal). Similarly, the other side must send us + its random salt and IV with those same lengths. + + The salt and key data are combined to create a session + key using an md5 hash as described in EVP_BytesToKey(3). + + The exact call is: EVP_BytesToKey(Cipher, EVP_md5(), + salt, keydata, len, 1, keystr, NULL); where salt is + the random data as described above, and keydata is the + shared secret key data. keystr is the resulting session + key. The cipher is then seeded with keystr and uses + the random initialization vector as its first block. + + To modify the amount of random salt and initialization + vector use cipher@n,m where n is the salt length and + m the initialization vector length. E.g. + + -enc aes-cfb@8,16:./my.key + + It is not a good idea to set either one to zero, + although you may be forced to if the other side of the + tunnel is not under your control. + + To skip the salt and EVP_BytesToKey MD5 entirely (no + hashing is done: the keydata is directly inserted into + the cipher) specify "-1" for the salt, e.g. + + -enc blowfish@-1,16:./my.key + + The message digest can also be changed to something + besides the default MD5. Use cipher@md+n,m where "md" + can be one of sha, sha1, md5, or ripe. For example: + + -enc arc4@sha+8,16:./my.key + + The SSVNC vnc viewer project supplies a symmetric + encryption tool named "ultravnc_dsm_helper" that can + be used on the viewer side. For example: + + ssvncviewer exec='ultravnc_dsm_helper arc4 my.key 0 h:p' + + where h:p is the hostname and port of the x11vnc server. + ultravnc_dsm_helper may also be used standalone to + provide a symmetric encryption tunnel for any viewer + or server (VNC or otherwise.) The cipher (1st arg) + is basically the same syntax as we use above. + + Also see the 'Non-Ultra DSM' SSVNC option for the + 'UltraVNC DSM Encryption Plugin' advanced option. + + For both ways of using the viewer, you can specify the + salt,ivec sizes (in GUI or, e.g. arc4@8,16). + +-https [port] Use a special, separate HTTPS port (-ssl and + -stunnel modes only) for HTTPS Java viewer applet + downloading. I.e. not 5900 and not 5800 (the defaults.) + + BACKGROUND: In -ssl mode, it turns out you can use the + single VNC port (e.g. 5900) for both VNC and HTTPS + connections. (HTTPS is used to retrieve a SSL-aware + VncViewer.jar applet that is provided with x11vnc). + Since both use SSL the implementation was extended to + detect if HTTP traffic (i.e. GET) is taking place and + handle it accordingly. The URL would be, e.g.: + + https://mymachine.org:5900/ + + This is convenient for firewalls, etc, because only one + port needs to be allowed in. However, this heuristic + adds a few seconds delay to each connection and can be + unreliable (especially if the user takes much time to + ponder the Certificate dialogs in his browser, Java VM, + or VNC Viewer applet. That's right 3 separate "Are + you sure you want to connect?" dialogs!) + + END OF BACKGROUND. + + USAGE: So use the -https option to provide a separate, + more reliable HTTPS port that x11vnc will listen on. If + [port] is not provided (or is 0), one is autoselected. + The URL to use is printed out at startup. + + The SSL Java applet directory is specified via the + -httpdir option. If not supplied, -https will try + to guess the directory as though the -http option + was supplied. + +-httpsredir [port] In -ssl mode with the Java applet retrieved via HTTPS, + when the HTML file containing applet parameters + ('index.vnc' or 'proxy.vnc') is sent do NOT set the + applet PORT parameter to the actual VNC port but set it + to "port" instead. If "port" is not supplied, then + the port number is guessed from the Host: HTTP header. + + This is useful when an incoming TCP connection + redirection is performed by a router/gateway/firewall + from one port to an internal machine where x11vnc is + listening on a different port. The Java applet needs to + connect to the firewall/router port, not the VNC port + on the internal workstation. For example, one could + redir from mygateway.com:443 to workstation:5900. + + This spares the user from having to type in + https://mygateway.com/?PORT=443 into their web + browser. Note that port 443 is the default https port; + other ports must be explicitly indicated, for example: + https://mygateway.com:8000/?PORT=8000. To avoid having + to include the PORT= in the browser URL, simply supply + "-httpsredir" to x11vnc. + + This option does not work in -stunnel mode. + + More tricks: set the env var X11VNC_EXTRA_HTTPS_PARAMS + to be extra URL parameters to use. This way you do + not need to specify extra PARAMS in the index.vnc file. + E.g. x11vnc -env X11VNC_EXTRA_HTTPS_PARAMS='?GET=1' ... + + If you do not want to expose the non-SSL HTTP port to + the network (i.e. you just want the single VNC/HTTPS + port, e.g. 5900, open for connections) then specify the + option -env X11VNC_HTTP_LISTEN_LOCALHOST=1 This way + the connection to the LibVNCServer httpd server will + only be available on localhost (note that in -ssl mode, + HTTPS requests are redirected from SSL to the non-SSL + LibVNCServer HTTP server.) + +-http_oneport For UN-encrypted connections mode (i.e. no -ssl, + -stunnel, or -enc options), allow the Java VNC Viewer + applet to be downloaded thru the VNC port via HTTP. + + That is to say, you can use a single port for Java + applet viewer connections by using a URL in your web + browser like this, for example: + + http://hostname:5900 + + The regular, two-port mode, URL http://hostname:5800 + will continue to work as well. + + As mentioned above, this mode will NOT work with + the -ssl, -stunnel, or -enc encryption options. + Note that is it equivalent to '-enc none' (i.e. it + uses the same detection mechanism as for HTTPS, but + with no encryption.) + + HTTPS single-port is on by default in -ssl encrypted + mode (and -enc too), so you only need -http_oneport + when doing non-SSL encrypted connections. + + This mode could also be useful for SSH tunnels since + it means only one port needs to be redirected. + + The -httpsredir option may also be useful for this + mode when using an SSH tunnel as well as for router + port redirections. + + Note that the -env X11VNC_HTTP_LISTEN_LOCALHOST=1 + option described above under -httpsredir applies for + the LibVNCServer httpd server in all cases (ssl or not.) + +-ssh user@host:disp Create a remote listening port on machine "host" + via a SSH tunnel using the -R rport:localhost:lport + method. lport will be the local x11vnc listening port, + so a connection to rport (5900+disp) on "host" + will reach x11vnc. E.g. fred@snoopy.com:0 + + This could be useful if a firewall/router prevents + incoming connections to the x11vnc machine, but + the ssh machine "host" can be reached by the VNC + viewer. "user@" is not needed unless the remote unix + username differs from the current one. + + By default the remote sshd is usually configured to + listen only on localhost for rport, so the viewer may + need to ssh -L redir to "host" as well (See SSVNC to + automate this). The sshd setting GatewayPorts enables + listening on all interfaces for rport; viewers can + reach it more easily. + + "disp" is the VNC display for the remote SSH side, + e.g. 0 corresponds to port 5900, etc. If disp is + greater than 200 the value is used as the port. Use a + negative value to force a low port, e.g. host:-80 will + use port 80. + + If ssh-agent is not active, then the ssh password needs + to be entered in the terminal where x11vnc is running. + + By default the remote ssh will issue a 'sleep 300' to + wait for the incoming connection for 5 mins. To modify + this use user@host:disp+secs. + + If the remote SSH server is on a non-standard port + (i.e. not 22) use user@host:port:disp+secs. + + Note that the ssh process MAY NOT be killed when + x11vnc exits. It tries by looking at ps(1) output. + +-usepw If no other password method was supplied on the command + line, first look for ~/.vnc/passwd and if found use it + with -rfbauth; next, look for ~/.vnc/passwdfile and + use it with -passwdfile; otherwise, prompt the user + for a password to create ~/.vnc/passwd and use it with + the -rfbauth option. If none of these succeed x11vnc + exits immediately. + +-storepasswd pass file Store password "pass" as the VNC password in the + file "file". Once the password is stored the + program exits. Use the password via "-rfbauth file" + + If called with no arguments, "x11vnc -storepasswd", + the user is prompted for a password and it is stored + in the file ~/.vnc/passwd. Called with one argument, + that will be the file to store the prompted password in. + +-nopw Disable the big warning message when you use x11vnc + without some sort of password. + +-accept string Run a command (possibly to prompt the user at the + X11 display) to decide whether an incoming client + should be allowed to connect or not. "string" is + an external command run via system(3) or some special + cases described below. Be sure to quote "string" + if it contains spaces, shell characters, etc. If the + external command returns 0 the client is accepted, + otherwise the client is rejected. See below for an + extension to accept a client view-only. + + If x11vnc is running as root (say from inetd(8) or from + display managers xdm(1), gdm(1), etc), think about the + security implications carefully before supplying this + option (likewise for the -gone option). + + Environment: The RFB_CLIENT_IP environment variable will + be set to the incoming client IP number and the port + in RFB_CLIENT_PORT (or -1 if unavailable). Similarly, + RFB_SERVER_IP and RFB_SERVER_PORT (the x11vnc side + of the connection), are set to allow identification + of the tcp virtual circuit. The x11vnc process + id will be in RFB_X11VNC_PID, a client id number in + RFB_CLIENT_ID, and the number of other connected clients + in RFB_CLIENT_COUNT. RFB_MODE will be "accept". + RFB_STATE will be PROTOCOL_VERSION, SECURITY_TYPE, + AUTHENTICATION, INITIALISATION, NORMAL, or UNKNOWN + indicating up to which state the client has achieved. + RFB_LOGIN_VIEWONLY will be 0, 1, or -1 (unknown). + RFB_USERNAME, RFB_LOGIN_TIME, and RFB_CURRENT_TIME may + also be set. + + If "string" is "popup" then a builtin popup window + is used. The popup will time out after 120 seconds, + use "popup:N" to modify the timeout to N seconds + (use 0 for no timeout). + + In the case of "popup" and when the -unixpw option + is specified, then a *second* window will be popped + up after the user successfully logs in via his UNIX + password. This time the user will be identified as + UNIX:username@hostname, the "UNIX:" prefix indicates + which user the viewer logged as via -unixpw. The first + popup is only for whether to allow him to even *try* + to login via unix password. + + If "string" is "xmessage" then an xmessage(1) + invocation is used for the command. xmessage must be + installed on the machine for this to work. + + Both "popup" and "xmessage" will present an option + for accepting the client "View-Only" (the client + can only watch). This option will not be presented if + -viewonly has been specified, in which case the entire + display is view only. + + If the user supplied command is prefixed with something + like "yes:0,no:*,view:3 mycommand ..." then this + associates the numerical command return code with + the actions: accept, reject, and accept-view-only, + respectively. Use "*" instead of a number to indicate + the default action (in case the command returns an + unexpected value). E.g. "no:*" is a good choice. + + Note that x11vnc blocks while the external command + or popup is running (other clients may see no updates + during this period). So a person sitting a the physical + display is needed to respond to an popup prompt. (use + a 2nd x11vnc if you lock yourself out). + + More -accept tricks: use "popupmouse" to only allow + mouse clicks in the builtin popup to be recognized. + Similarly use "popupkey" to only recognize + keystroke responses. These are to help avoid the + user accidentally accepting a client by typing or + clicking. All 3 of the popup keywords can be followed + by +N+M to supply a position for the popup window. + The default is to center the popup window. +-afteraccept string As -accept, except to run a user supplied command after + a client has been accepted and authenticated. RFB_MODE + will be set to "afteraccept" and the other RFB_* + variables are as in -accept. Unlike -accept, the + command return code is not interpreted by x11vnc. + Example: -afteraccept 'killall xlock &' +-gone string As -accept, except to run a user supplied command when + a client goes away (disconnects). RFB_MODE will be + set to "gone" and the other RFB_* variables are as + in -accept. The "popup" actions apply as well. + Unlike -accept, the command return code is not + interpreted by x11vnc. Example: -gone 'xlock &' + +-users list If x11vnc is started as root (say from inetd(8) or from + display managers xdm(1), gdm(1), etc), then as soon + as possible after connections to the X display are + established try to switch to one of the users in the + comma separated "list". If x11vnc is not running as + root this option is ignored. + + Why use this option? In general it is not needed since + x11vnc is already connected to the X display and can + perform its primary functions. The option was added + to make some of the *external* utility commands x11vnc + occasionally runs work properly. In particular under + GNOME and KDE to implement the "-solid color" feature + external commands (gconftool-2 and dcop) unfortunately + must be run as the user owning the desktop session. + Since this option switches userid it also affects the + userid used to run the processes for the -accept and + -gone options. It also affects the ability to read + files for options such as -connect, -allow, and -remap + and also the ultra and tight filetransfer feature if + enabled. Note that the -connect file is also sometimes + written to. + + So be careful with this option since in some situations + its use can decrease security. + + In general the switch to a user will only take place + if the display can still be successfully opened as that + user (this is primarily to try to guess the actual owner + of the session). Example: "-users fred,wilma,betty". + Note that a malicious local user "barney" by + quickly using "xhost +" when logging in may possibly + get the x11vnc process to switch to user "fred". + What happens next? + + Under display managers it may be a long time before + the switch succeeds (i.e. a user logs in). To instead + make it switch immediately regardless if the display + can be reopened prefix the username with the "+" + character. E.g. "-users +bob" or "-users +nobody". + + The latter (i.e. switching immediately to user + "nobody") is the only obvious use of the -users option + that increases security. + + Use the following notation to associate a group with + a user: user1.group1,user2.group2,... Note that + initgroups(2) will still be called first to try to + switch to ALL of a user's groups (primary and additional + groups). Only if that fails or it is not available + then the single group specified as above (or the user's + primary group if not specified) is switched to with + setgid(2). Use -env X11VNC_SINGLE_GROUP=1 to prevent + trying initgroups(2) and only switch to the single + group. This sort of setting is only really needed to + make the ultra or tight filetransfer permissions work + properly. This format applies to any comma separated lis +t + of users, even the special "=" modes described below. + + In -unixpw mode, if "-users unixpw=" is supplied + then after a user authenticates himself via the + -unixpw mechanism, x11vnc will try to switch to that + user as though "-users +username" had been supplied. + If you want to limit which users this will be done for, + provide them as a comma separated list after "unixpw=" + Groups can also be specified as described above. + + Similarly, in -ssl mode, if "-users sslpeer=" is + supplied then after an SSL client authenticates with his + cert (the -sslverify option is required for this) x11vnc + will extract a UNIX username from the "emailAddress" + field (username@hostname.com) of the "Subject" of the + x509 SSL cert and then try to switch to that user as + though "-users +username" had been supplied. If you + want to limit which users this will be done for, provide + them as a comma separated list after "sslpeer=". + Set the env. var X11VNC_SSLPEER_CN to use the Common + Name (normally a hostname) instead of the Email field. + + NOTE: for sslpeer= mode the x11vnc administrator must + take care that any client certs he adds to -sslverify + have the intended UNIX username in the "emailAddress" + field of the cert. Otherwise a user may be able to + log in as another. This command can be of use in + checking: "openssl x509 -text -in file.crt", see the + "Subject:" line. Also, along with the normal RFB_* + env. vars. (see -accept) passed to external cmd= + commands, RFB_SSL_CLIENT_CERT will be set to the + client's x509 certificate string. + + The sslpeer= mode can aid finding X sessions via the + FINDDISPLAY and FINDCREATEDISPLAY mechanisms. + + To immediately switch to a user *before* connections + to the X display are made or any files opened use the + "=" character: "-users =bob". That user needs to + be able to open the X display and any files of course. + + The special user "guess=" means to examine the utmpx + database (see who(1)) looking for a user attached to + the display number (from DISPLAY or -display option) + and try him/her. To limit the list of guesses, use: + "-users guess=bob,betty". + + Even more sinister is the special user "lurk=" + that means to try to guess the DISPLAY from the utmpx + login database as well. So it "lurks" waiting for + anyone to log into an X session and then connects to it. + Specify a list of users after the = to limit which users + will be tried. To enable a different searching mode, if + the first user in the list is something like ":0" or + ":0-2" that indicates a range of DISPLAY numbers that + will be tried (regardless of whether they are in the + utmpx database) for all users that are logged in. Also + see the "-display WAIT:..." functionality. Examples: + "-users lurk=" and also "-users lurk=:0-1,bob,mary" + + Be especially careful using the "guess=" and "lurk=" + modes. They are not recommended for use on machines + with untrustworthy local users. + +-noshm Do not use the MIT-SHM extension for the polling. + Remote displays can be polled this way: be careful this + can use large amounts of network bandwidth. This is + also of use if the local machine has a limited number + of shm segments and -onetile is not sufficient. +-flipbyteorder Sometimes needed if remotely polled host has different + endianness. Ignored unless -noshm is set. +-onetile Do not use the new copy_tiles() framebuffer mechanism, + just use 1 shm tile for polling. Limits shm segments + used to 3. + +-solid [color] To improve performance, when VNC clients are connected + try to change the desktop background to a solid color. + The [color] is optional: the default color is "cyan4". + For a different one specify the X color (rgb.txt name, + e.g. "darkblue" or numerical "#RRGGBB"). + + Currently this option only works on GNOME, KDE, CDE, + XFCE, and classic X (i.e. with the background image + on the root window). The "gconftool-2", "dcop" + and "xfconf-query" external commands are run for + GNOME, KDE, and XFCE respectively. This also works + on native MacOSX. (There is no color selection for + MacOSX or XFCE.) Other desktops won't work, (send + us the corresponding commands if you find them). + If x11vnc is running as root (inetd(8) or gdm(1)), + the -users option may be needed for GNOME, KDE, XFCE. + If x11vnc guesses your desktop incorrectly, you can + force it by prefixing color with "gnome:", "kde:", + "cde:", "xfce:", or "root:". + + Update: -solid no longer works on KDE4. + + This mode works in a limited way on the Mac OS X Console + with one color ('kelp') using the screensaver writing + to the background. Look in "~/Library/Screen Savers" + for VncSolidColor.png to change the color. + +-blackout string Black out rectangles on the screen. "string" is a + comma separated list of WxH+X+Y type geometries for + each rectangle. If one of the items on the list is the + string "noptr" the mouse pointer will not be allowed + to go into a blacked out region. +-xinerama If your screen is composed of multiple monitors +-noxinerama glued together via XINERAMA, and that screen is + not a rectangle this option will try to guess the + areas to black out (if your system has libXinerama). + default: -xinerama + + In general, we have noticed on XINERAMA displays you may + need to use the "-xwarppointer" option if the mouse + pointer misbehaves and it is enabled by default. Use + "-noxwarppointer" if you do not want this. + +-xtrap Use the DEC-XTRAP extension for keystroke and mouse + input insertion. For use on legacy systems, e.g. X11R5, + running an incomplete or missing XTEST extension. + By default DEC-XTRAP will be used if XTEST server grab + control is missing, use -xtrap to do the keystroke and + mouse insertion via DEC-XTRAP as well. + +-xrandr [mode] If the display supports the XRANDR (X Resize, Rotate + and Reflection) extension, and you expect XRANDR events + to occur to the display while x11vnc is running, this + options indicates x11vnc should try to respond to + them (as opposed to simply crashing by assuming the + old screen size). See the xrandr(1) manpage and run + 'xrandr -q' for more info. [mode] is optional and + described below. + + Since watching for XRANDR events and trapping errors + increases polling overhead, only use this option if + XRANDR changes are expected. For example on a rotatable + screen PDA or laptop, or using a XRANDR-aware Desktop + where you resize often. It is best to be viewing with a + vncviewer that supports the NewFBSize encoding, since it + knows how to react to screen size changes. Otherwise, + LibVNCServer tries to do so something reasonable for + viewers that cannot do this (portions of the screen + may be clipped, unused, etc). + + Note: the default now is to check for XRANDR events, but + do not trap every X call that may fail due to resize. + If a resize event is received, the full -xrandr mode + is enabled. To disable even checking for events supply: + -noxrandr. + + "mode" defaults to "resize", which means create a + new, resized, framebuffer and hope all viewers can cope + with the change. "newfbsize" means first disconnect + all viewers that do not support the NewFBSize VNC + encoding, and then resize the framebuffer. "exit" + means disconnect all viewer clients, and then terminate + x11vnc. + +-rotate string Rotate and/or flip the framebuffer view exported by VNC. + This transformation is independent of XRANDR and is + done in software in main memory and so may be slower. + This mode could be useful on a handheld with portrait or + landscape modes that do not correspond to the scanline + order of the actual framebuffer. "string" can be: + + x flip along x-axis + y flip along y-axis + xy flip along x- and y-axes + +90 rotate 90 degrees clockwise + -90 rotate 90 degrees counter-clockwise + +90x rotate 90 degrees CW, then flip along x + +90y rotate 90 degrees CW, then flip along y + + these give all possible rotations and reflections. + + Aliases: same as xy: yx, +180, -180, 180 + same as -90: +270, 270 + same as +90: 90, (ditto for 90x, 90y) + + Like -scale, this transformation is applied at the very + end of any chain of framebuffer transformations and so + any options with geometries, e.g. -blackout, -clip, etc. + are relative to the original X (or -rawfb) framebuffer, + not the final one sent to VNC viewers. + + If you do not want the cursor shape to be rotated + prefix "string" with "nc:", e.g. "nc:+90", + "nc:xy", etc. + +-padgeom WxH Whenever a new vncviewer connects, the framebuffer is + replaced with a fake, solid black one of geometry WxH. + Shortly afterwards the framebuffer is replaced with the + real one. This is intended for use with vncviewers + that do not support NewFBSize and one wants to make + sure the initial viewer geometry will be big enough + to handle all subsequent resizes (e.g. under -xrandr, + -remote id:windowid, rescaling, etc.) + + In -unixpw mode this sets the size of the login screen. + Use "once:WxH" it ignore padgeom after the login + screen is set up. + +-o logfile Write stderr messages to file "logfile" instead of to + the terminal. Same as "-logfile file". To append + to the file use "-oa file" or "-logappend file". + If "logfile" contains the string "%VNCDISPLAY" + it is expanded to the vnc display (the name may need + to be guessed at.) "%HOME" works too. + +-flag file Write the "PORT=NNNN" (e.g. PORT=5900) string to + "file" in addition to stdout. This option could be + useful by wrapper script to detect when x11vnc is ready. + +-rmflag file Remove "file" at exit to signal when x11vnc is done. + The file is created at startup if it does not already + exist or if "file" is prefixed with "create:". + If the file is created, the x11vnc PID is placed in + the file. Otherwise the files contents is not changed. + Use prefix "nocreate:" to prevent creation. + +-rc filename Use "filename" instead of $HOME/.x11vncrc for rc file. +-norc Do not process any .x11vncrc file for options. + +-env VAR=VALUE Set the environment variable 'VAR' to value 'VALUE' + at x11vnc startup. This is a convenience utility to + avoid shell script wrappers, etc. to set the env. var. + You may specify as many of these as needed on the + command line. +-prog /path/to/x11vnc Set the full path to the x11vnc program for cases when + it cannot be determined from argv[0] (e.g. tcpd/inetd) + +-h, -help Print this help text. +-?, -opts Only list the x11vnc options. +-V, -version Print program version and last modification date. +-license Print out license information. Same as -copying and + -warranty. + +-dbg Instead of exiting after cleaning up, run a simple + "debug crash shell" when fatal errors are trapped. + +-q, -quiet Be quiet by printing less informational output to + stderr. (use -noquiet to undo an earlier -quiet.) + + The -quiet option does not eliminate all informational + output, it only reduces it. It is ignored in most + auxiliary usage modes, e.g. -storepasswd. To eliminate + all output use: 2>/dev/null 1>&2, etc. + +-v, -verbose Print out more information to stderr. + +-bg Go into the background after screen setup. Messages to + stderr are lost unless -o logfile is used. Something + like this could be useful in a script: + port=`ssh -t $host "x11vnc -display :0 -bg" | grep PORT +` + port=`echo "$port" | sed -e 's/PORT=//'` + port=`expr $port - 5900` + vncviewer $host:$port + +-modtweak Option -modtweak automatically tries to adjust the AltGr +-nomodtweak and Shift modifiers for differing language keyboards + between client and host. Otherwise, only a single key + press/release of a Keycode is simulated (i.e. ignoring + the state of the modifiers: this usually works for + identical keyboards). Also useful in resolving cases + where a Keysym is bound to multiple keys (e.g. "<" + ">" + and "," + "<" keys). Default: -modtweak + + If you are having trouble with with keys and -xkb or + -noxkb, and similar things don't help, try -nomodtweak. + + On some HP-UX systems it is been noted that they have + an odd keymapping where a single keycode will have a + keysym, e.g. "#", up to three times. You can check + via "xmodmap -pk" or the -dk option. The failure + is when you try to type "#" it yields "3". If you + see this problem try setting the environment variable + MODTWEAK_LOWEST=1 to see if it helps. + +-xkb When in modtweak mode, use the XKEYBOARD extension (if +-noxkb the X display supports it) to do the modifier tweaking. + This is powerful and should be tried if there are still + keymapping problems when using -modtweak by itself. + The default is to check whether some common keysyms, + e.g. !, @, [, are only accessible via -xkb mode and if + so then automatically enable the mode. To disable this + automatic detection use -noxkb. + + When -xkb mode is active you can set these env. vars. + They apply only when there is ambiguity as to which + key to choose (i.e the mapping is not one-to-one). + NOKEYHINTS=1: for up ascii keystrokes do not use score + hints saved when the key was pressed down. NOANYDOWN=1: + for up keystrokes do not resort to searching through + keys that are currently pressed down. KEYSDOWN=N: + remember the last N keys press down for tie-breaking + when an up keystroke comes in. + +-capslock When in -modtweak (the default) or -xkb mode, + if a keysym in the range A-Z comes in check the X + server to see if the Caps_Lock is set. If it is do + not artificially press Shift to generate the keysym. + This will enable the CapsLock key to behave correctly + in some circumstances: namely *both* the VNC viewer + machine and the x11vnc X server are in the CapsLock + on state. If one side has CapsLock on and the other + off and the keyboard is not behaving as you think it + should you should correct the CapsLock states (hint: + pressing CapsLock inside and outside of the viewer can + help toggle them both to the correct state). However, + for best results do not use this option, but rather + *only* enable CapsLock on the VNC viewer side (i.e. by + pressing CapsLock outside of the viewer window, also + -skip_lockkeys below). Also try -nomodtweak for a + possible workaround. + +-skip_lockkeys Have x11vnc ignore all Caps_Lock, Shift_Lock, Num_Lock, +-noskip_lockkeys Scroll_Lock keysyms received from viewers. The idea is + you press Caps_Lock on the VNC Viewer side but that does + not change the lock state in the x11vnc-side X server. + Nevertheless your capitalized letters come in over + the wire and are applied correctly to the x11vnc-side + X server. Note this mode probably won't do what you + want in -nomodtweak mode. Also, a kludge for KP_n + digits is always done it this mode: they are mapped to + regular digit keysyms. See also -capslock above. + The default is -noskip_lockkeys. + +-skip_keycodes string Ignore the comma separated list of decimal keycodes. + Perhaps these are keycodes not on your keyboard but + your X server thinks exist. Currently only applies + to -xkb mode. Use this option to help x11vnc in the + reverse problem it tries to solve: Keysym -> Keycode(s) + when ambiguities exist (more than one Keycode per + Keysym). Run 'xmodmap -pk' to see your keymapping. + Example: "-skip_keycodes 94,114" +-sloppy_keys Experimental option that tries to correct some + "sloppy" key behavior. E.g. if at the viewer you + press Shift+Key but then release the Shift before + Key that could give rise to extra unwanted characters + (usually only between keyboards of different languages). + Only use this option if you observe problems with + some keystrokes. +-skip_dups Some VNC viewers send impossible repeated key events, +-noskip_dups e.g. key-down, key-down, key-up, key-up all for the same + key, or 20 downs in a row for the same modifier key! + Setting -skip_dups means to skip these duplicates and + just process the first event. Note: some VNC viewers + assume they can send down's without the corresponding + up's and so you should not set this option for + these viewers (symptom: some keys do not autorepeat) + Default: -noskip_dups +-add_keysyms If a Keysym is received from a VNC viewer and that +-noadd_keysyms Keysym does not exist in the X server, then add the + Keysym to the X server's keyboard mapping on an unused + key. Added Keysyms will be removed periodically and + also when x11vnc exits. Default: -add_keysyms +-clear_mods At startup and exit clear the modifier keys by sending + KeyRelease for each one. The Lock modifiers are skipped. + Used to clear the state if the display was accidentally + left with any pressed down. +-clear_keys As -clear_mods, except try to release ANY pressed key. + Note that this option and -clear_mods can interfere + with a person typing at the physical keyboard. +-clear_all As -clear_keys, except try to release any CapsLock, + NumLock, etc. locks as well. + +-remap string Read Keysym remappings from file named "string". + Format is one pair of Keysyms per line (can be name + or hex value) separated by a space. If no file named + "string" exists, it is instead interpreted as this + form: key1-key2,key3-key4,... See + header file for a list of Keysym names, or use xev(1). + + To map a key to a button click, use the fake Keysyms + "Button1", ..., etc. E.g: "-remap Super_R-Button2" + (useful for pasting on a laptop) + + I use these if the machine I am viewing from does not + have a scrollwheel or I don't like using the one it has: + + -remap Super_R-Button4,Menu-Button5 + -remap KP_Add-Button4,KP_Enter-Button5 + + the former would be used on a PC, the latter on a + MacBook. This way those little used keys can be used + to generate bigger hops than the Up and Down arrows + provide. One can scroll through text or web pages more + quickly this way (especially if x11vnc scroll detection + is active.) + + Use Button44, Button12, etc. for multiple clicks. + + To disable a keysym (i.e. make it so it will not be + injected), remap it to "NoSymbol" or "None". + + Dead keys: "dead" (or silent, mute) keys are keys that + do not produce a character but must be followed by a 2nd + keystroke. This is often used for accenting characters, + e.g. to put "`" on top of "a" by pressing the dead + key and then "a". Note that this interpretation + is not part of core X11, it is up to the toolkit or + application to decide how to react to the sequence. + The X11 names for these keysyms are "dead_grave", + "dead_acute", etc. However some VNC viewers send the + keysyms "grave", "acute" instead thereby disabling + the accenting. To work around this -remap can be used. + For example "-remap grave-dead_grave,acute-dead_acute" + As a convenience, "-remap DEAD" applies these remaps: + + g grave-dead_grave + a acute-dead_acute + c asciicircum-dead_circumflex + t asciitilde-dead_tilde + m macron-dead_macron + b breve-dead_breve + D abovedot-dead_abovedot + d diaeresis-dead_diaeresis + o degree-dead_abovering + A doubleacute-dead_doubleacute + r caron-dead_caron + e cedilla-dead_cedilla + + If you just want a subset use the first letter + label, e.g. "-remap DEAD=ga" to get the first two. + Additional remaps may also be supplied via commas, + e.g. "-remap DEAD=ga,Super_R-Button2". Finally, + "DEAD=missing" means to apply all of the above as + long as the left hand member is not already in the + X11 keymap. + +-norepeat Option -norepeat disables X server key auto repeat when +-repeat VNC clients are connected and VNC keyboard input is + not idle for more than 5 minutes. This works around a + repeating keystrokes bug (triggered by long processing + delays between key down and key up client events: + either from large screen changes or high latency). + Default: -norepeat + + You can set the env. var. X11VNC_IDLE_TIMEOUT to the + number of idle seconds you want (5min = 300secs). + + Note: your VNC viewer side will likely do autorepeating, + so this is no loss unless someone is simultaneously at + the real X display. + + Use "-norepeat N" to set how many times norepeat will + be reset if something else (e.g. X session manager) + undoes it. The default is 2. Use a negative value + for unlimited resets. + +-nofb Ignore video framebuffer: only process keyboard and + pointer. Intended for use with Win2VNC and x2vnc + dual-monitor setups. +-nobell Do not watch for XBell events. (no beeps will be heard) + Note: XBell monitoring requires the XKEYBOARD extension. +-nosel Do not manage exchange of X selection/cutbuffer between + VNC viewers and the X server at all. +-noprimary Do not poll the PRIMARY selection for changes to send + back to clients. (PRIMARY is still set on received + changes, however). +-nosetprimary Do not set the PRIMARY selection for changes received + from VNC clients. +-noclipboard Do not poll the CLIPBOARD selection for changes to send + back to clients. (CLIPBOARD is still set on received + changes, however). +-nosetclipboard Do not set the CLIPBOARD selection for changes + received from VNC clients. +-seldir string If direction string is "send", only send the selection + to viewers, and if it is "recv" only receive it from + viewers. To work around apps setting the selection + too frequently and messing up the other end. You can + actually supply a comma separated list of directions, + including "debug" to turn on debugging output. + +-cursor [mode] Sets how the pointer cursor shape (little icon at the +-nocursor mouse pointer) should be handled. The "mode" string + is optional and is described below. The default + is to show some sort of cursor shape(s). How this + is done depends on the VNC viewer and the X server. + Use -nocursor to disable cursor shapes completely. + + Some VNC viewers support the TightVNC CursorPosUpdates + and CursorShapeUpdates extensions (cuts down on + network traffic by not having to send the cursor image + every time the pointer is moved), in which case these + extensions are used (see -nocursorshape and -nocursorpos + below to disable). For other viewers the cursor shape + is written directly to the framebuffer every time the + pointer is moved or changed and gets sent along with + the other framebuffer updates. In this case, there + will be some lag between the vnc viewer pointer and + the remote cursor position. + + If the X display supports retrieving the cursor shape + information from the X server, then the default is + to use that mode. On Solaris this can be done with + the SUN_OVL extension using -overlay (see also the + -overlay_nocursor option). A similar overlay scheme + is used on IRIX. Xorg (e.g. Linux) and recent Solaris + Xsun servers support the XFIXES extension to retrieve + the exact cursor shape from the X server. If XFIXES + is present it is preferred over Overlay and is used by + default (see -noxfixes below). This can be disabled + with -nocursor, and also some values of the "mode" + option below. + + Note that under XFIXES cursors with transparency (alpha + channel) will usually not be exactly represented and one + may find Overlay preferable. See also the -alphacut + and -alphafrac options below as fudge factors to try + to improve the situation for cursors with transparency + for a given theme. + + The "mode" string can be used to fine-tune the + displaying of cursor shapes. It can be used the + following ways: + + "-cursor arrow" - just show the standard arrow + nothing more or nothing less. + + "-cursor none" - same as "-nocursor" + + "-cursor X" - when the cursor appears to be on the + root window, draw the familiar X shape. Some desktops + such as GNOME cover up the root window completely, + and so this will not work, try "X1", etc, to try to + shift the tree depth. On high latency links or slow + machines there will be a time lag between expected and + the actual cursor shape. + + "-cursor some" - like "X" but use additional + heuristics to try to guess if the window should have + a windowmanager-like resizer cursor or a text input + I-beam cursor. This is a complete hack, but may be + useful in some situations because it provides a little + more feedback about the cursor shape. + + "-cursor most" - try to show as many cursors as + possible. Often this will only be the same as "some" + unless the display has overlay visuals or XFIXES + extensions available. On Solaris and IRIX if XFIXES + is not available, -overlay mode will be attempted. + +-cursor_drag Show cursor shape changes even when the mouse is being + dragged with a mouse button down. This is useful if you + want to be able to see Drag-and-Drop cursor icons, etc. + +-arrow n Choose an alternate "arrow" cursor from a set of + some common ones. n can be 1 to 6. Default is: 1 + Ignored when in XFIXES cursor-grabbing mode. + +-noxfixes Do not use the XFIXES extension to draw the exact cursor + shape even if it is available. + + Note: To work around a crash in Xorg 1.5 and later + some people needed to use -noxfixes. The Xorg crash + occurred right after a Display Manager (e.g. GDM) login. + Starting with x11vnc 0.9.9 it tries to automatically + avoid using XFIXES until it is sure a window manager + is running. See the -reopen option for more info and + how to use X11VNC_AVOID_WINDOWS=never to disable it. + +-alphacut n When using the XFIXES extension for the cursor shape, + cursors with transparency will not usually be displayed + exactly (but opaque ones will). This option sets n as + a cutoff for cursors that have transparency ("alpha + channel" with values ranging from 0 to 255) Any cursor + pixel with alpha value less than n becomes completely + transparent. Otherwise the pixel is completely opaque. + Default 240 + +-alphafrac fraction With the threshold in -alphacut some cursors will become + almost completely transparent because their alpha values + are not high enough. For those cursors adjust the + alpha threshold until fraction of the non-zero alpha + channel pixels become opaque. Default 0.33 +-alpharemove By default, XFIXES cursors pixels with transparency have + the alpha factor multiplied into the RGB color values + (i.e. that corresponding to blending the cursor with a + black background). Specify this option to remove the + alpha factor. (useful for light colored semi-transparent + cursors). +-noalphablend In XFIXES mode do not send cursor alpha channel data + to LibVNCServer. The default is to send it. The + alphablend effect will only be visible in -nocursorshape + mode or for clients with cursorshapeupdates turned + off. (However there is a hack for 32bpp with depth 24, + it uses the extra 8 bits to store cursor transparency + for use with a hacked vncviewer that applies the + transparency locally. See the FAQ for more info). + +-nocursorshape Do not use the TightVNC CursorShapeUpdates extension + even if clients support it. See -cursor above. +-cursorpos Option -cursorpos enables sending the X cursor position +-nocursorpos back to all vnc clients that support the TightVNC + CursorPosUpdates extension. Other clients will be able + to see the pointer motions. Default: -cursorpos +-xwarppointer Move the pointer with XWarpPointer(3X) instead of +-noxwarppointer the XTEST extension. Use this as a workaround + if the pointer motion behaves incorrectly, e.g. + on touchscreens or other non-standard setups. + + It is also sometimes needed on XINERAMA displays and is + enabled by default if XINERAMA is found to be active. + To prevent this, use -noxwarppointer. + +-buttonmap string String to remap mouse buttons. Format: IJK-LMN, this + maps buttons I -> L, etc., e.g. -buttonmap 13-31 + + Button presses can also be mapped to keystrokes: replace + a button digit on the right of the dash with :: + or :+: etc. for multiple keys. For example, + if the viewing machine has a mouse-wheel (buttons 4 5) + but the x11vnc side does not, these will do scrolls: + -buttonmap 12345-123:Prior::Next: + -buttonmap 12345-123:Up+Up+Up::Down+Down+Down: + + See header file for a list of Keysyms, + or use the xev(1) program. Note: mapping of button + clicks to Keysyms may not work if -modtweak or -xkb is + needed for the Keysym. + + If you include a modifier like "Shift_L" the + modifier's up/down state is toggled, e.g. to send + "The" use :Shift_L+t+Shift_L+h+e: (the 1st one is + shift down and the 2nd one is shift up). (note: the + initial state of the modifier is ignored and not reset) + To include button events use "Button1", ... etc. + + -buttonmap currently does not work on MacOSX console + or in -rawfb mode. + + Workaround: use -buttonmap IJ...-LM...=n to limit the + number of mouse buttons to n, e.g. 123-123=3. This will + prevent x11vnc from crashing if the X server reports + there are 5 buttons (4/5 scroll wheel), but there are + only really 3. + +-nodragging Do not update the display during mouse dragging events + (mouse button held down). Greatly improves response on + slow setups, but you lose all visual feedback for drags, + text selection, and some menu traversals. It overrides + any -pointer_mode setting. + +-ncache n Client-side caching scheme. Framebuffer memory "n" + (an integer) times that of the full display is allocated + below the actual framebuffer to cache screen contents + for rapid retrieval. So a W x H frambuffer is expanded + to a W x (n+1)*H one. Use 0 to disable. + + The "n" is actually optional, the default is 10. + + For this and the other -ncache* options below you can + abbreviate "-ncache" with "-nc". Also, "-nonc" + is the same as "-ncache 0" + + This is an experimental option, currently implemented in + an awkward way in that in the VNC Viewer you can see the + pixel cache contents if you scroll down, etc. So you + will have to set things up so you can't see that region. + If this method is successful, the changes required for + clients to do this less awkwardly will be investigated. + + The SSVNC viewer does a good job at automatically hiding + the pixel cache region. Or use SSVNC's -ycrop option + to explicitly hide the region. + + Note that this mode consumes a huge amount of memory, + both on the x11vnc server side and on the VNC Viewer + side. If n=2 then the amount of RAM used is roughly + tripled for both x11vnc and the VNC Viewer. As a rule + of thumb, note that 1280x1024 at depth 24 is about 5MB + of pixel data. + + For reasonable response when cycling through 4 to 6 + large (e.g. web browser) windows a value n of 6 to 12 + is recommended. (that's right: ~10X more memory...) + + Because of the way window backingstore and saveunders + are implemented, n must be even. It will be incremented + by 1 if it is not. + + This mode also works for native MacOS X, but may not + be as effective as the X version. This is due to a + number of things, one is the drop-shadow compositing + that leaves extra areas that need to be repaired (see + -ncache_pad). Another is the window iconification + animations need to be avoided (see -macicontime). + It appears the that the 'Scale' animation mode gives + better results than the 'Genie' one. Also, window event + detection not as accurate as the X version. + +-ncache_cr In -ncache mode, try to do copyrect opaque window + moves/drags instead of wireframes (this can induce + painting errors). The wireframe will still be used when + moving a window whose save-unders has not yet been set + or has been invalidated. + + Some VNC Viewers provide better response than others + with this option. On Unix, realvnc viewer gives + smoother drags than tightvnc viewer. Response may also + be choppy if the server side machine is too slow. + + Sometimes on very slow modem connections, this actually + gives an improvement because no pixel data at all + (not even the box animation) is sent during the drag. + +-ncache_no_moveraise In -ncache mode, do not assume that moving a window + will cause the window manager to raise it to the top + of the stack. The default is to assume it does, and + so at the beginning of any wireframe, etc, window moves + the window will be pushed to top in the VNC viewer. + +-ncache_no_dtchange In -ncache mode, do not try to guess when the desktop + (viewport) changes to another one (i.e. another + workarea). The default is to try to guess and when + detected try to make the transistion more smoothly. + +-ncache_no_rootpixmap In -ncache mode, do not try to snapshot the desktop + background to use in guessing or reconstructing window + save-unders. + +-ncache_keep_anims In -ncache mode, do not try to disable window + manager animations and other effects (that usually + degrade ncache performance or cause painting errors). + The default is to try to disable them on KDE (but not + GNOME) when VNC clients are connected. + + For other window managers or desktops that provide + animations, effects, compositing, translucency, + etc. that interfere with the -ncache method you will + have to disable them manually. + +-ncache_old_wm In -ncache mode, enable some heuristics for old style + window managers such as fvwm and twm. + +-ncache_pad n In -ncache mode, pad each window with n pixels for the + caching rectangles. This can be used to try to improve + the situation with dropshadows or other compositing + (e.g. MacOS X window manager), although it could make + things worse. The default is 0 on Unix and 24 on + MacOS X. +-debug_ncache Turn on debugging and profiling output under -ncache. + +-wireframe [str] Try to detect window moves or resizes when a mouse +-nowireframe button is held down and show a wireframe instead of + the full opaque window. This is based completely on + heuristics and may not always work: it depends on your + window manager and even how you move things around. + See -pointer_mode below for discussion of the "bogging + down" problem this tries to avoid. + Default: -wireframe + + Shorter aliases: -wf [str] and -nowf + + The value "str" is optional and, of course, is + packed with many tunable parameters for this scheme: + + Format: shade,linewidth,percent,T+B+L+R,mod,t1+t2+t3+t4 + Default: 0xff,2,0,32+8+8+8,all,0.15+0.30+5.0+0.125 + + If you leave nothing between commas: ",," the default + value is used. If you don't specify enough commas, + the trailing parameters are set to their defaults. + + "shade" indicate the "color" for the wireframe, + usually a greyscale: 0-255, however for 16 and 32bpp you + can specify an rgb.txt X color (e.g. "dodgerblue") or + a value > 255 is treated as RGB (e.g. red is 0xff0000). + "linewidth" sets the width of the wireframe in pixels. + "percent" indicates to not apply the wireframe scheme + to windows with area less than this percent of the + full screen. + + "T+B+L+R" indicates four integers for how close in + pixels the pointer has to be from the Top, Bottom, Left, + or Right edges of the window to consider wireframing. + This is a speedup to quickly exclude a window from being + wireframed: set them all to zero to not try the speedup + (scrolling and selecting text will likely be slower). + + "mod" specifies if a button down event in the + interior of the window with a modifier key (Alt, Shift, + etc.) down should indicate a wireframe opportunity. + It can be "0" or "none" to skip it, "1" or "all" + to apply it to any modifier, or "Shift", "Alt", + "Control", "Meta", "Super", or "Hyper" to only + apply for that type of modifier key. + + "t1+t2+t3+t4" specify four floating point times in + seconds: t1 is how long to wait for the pointer to move, + t2 is how long to wait for the window to start moving + or being resized (for some window managers this can be + rather long), t3 is how long to keep a wireframe moving + before repainting the window. t4 is the minimum time + between sending wireframe "animations". If a slow + link is detected, these values may be automatically + changed to something better for a slow link. + +-nowireframelocal By default, mouse motion and button presses of a + user sitting at the LOCAL display are monitored for + wireframing opportunities (so that the changes will be + sent efficiently to the VNC clients). Use this option + to disable this behavior. + +-wirecopyrect mode Since the -wireframe mechanism evidently tracks moving +-nowirecopyrect windows accurately, a speedup can be obtained by + telling the VNC viewers to locally copy the translated + window region. This is the VNC CopyRect encoding: + the framebuffer update doesn't need to send the actual + new image data. + + Shorter aliases: -wcr [mode] and -nowcr + + "mode" can be "never" (same as -nowirecopyrect) + to never try the copyrect, "top" means only do it if + the window was not covered by any other windows, and + "always" means to translate the orginally unobscured + region (this may look odd as the remaining pieces come + in, but helps on a slow link). Default: "always" + + Note: there can be painting errors or slow response + when using -scale so you may want to disable CopyRect + in this case "-wirecopyrect never" on the command + line or by remote-control. Or you can also use the + "-scale xxx:nocr" scale option. + +-debug_wireframe Turn on debugging info printout for the wireframe + heuristics. "-dwf" is an alias. Specify multiple + times for more output. + +-scrollcopyrect mode Like -wirecopyrect, but use heuristics to try to guess +-noscrollcopyrect if a window has scrolled its contents (either vertically + or horizontally). This requires the RECORD X extension + to "snoop" on X applications (currently for certain + XCopyArea and XConfigureWindow X protocol requests). + Examples: Hitting in a terminal window when the + cursor was at the bottom, the text scrolls up one line. + Hitting arrow in a web browser window, the web + page scrolls up a small amount. Or scrolling with a + scrollbar or mouse wheel. + + Shorter aliases: -scr [mode] and -noscr + + This scheme will not always detect scrolls, but when + it does there is a nice speedup from using the VNC + CopyRect encoding (see -wirecopyrect). The speedup + is both in reduced network traffic and reduced X + framebuffer polling/copying. On the other hand, it may + induce undesired transients (e.g. a terminal cursor + being scrolled up when it should not be) or other + painting errors (window tearing, bunching-up, etc). + These are automatically repaired in a short period + of time. If this is unacceptable disable the feature + with -noscrollcopyrect. + + Screen clearing kludges: for testing at least, there + are some "magic key sequences" (must be done in less + than 1 second) to aid repairing painting errors that + may be seen when using this mode: + + 3 Alt_L's in a row: resend whole screen, + 4 Alt_L's in a row: reread and resend whole screen, + 3 Super_L's in a row: mark whole screen for polling, + 4 Super_L's in a row: reset RECORD context, + 5 Super_L's in a row: try to push a black screen + + note: Alt_L is the Left "Alt" key (a single key) + Super_L is the Left "Super" key (Windows flag). + Both of these are modifier keys, and so should not + generate characters when pressed by themselves. Also, + your VNC viewer may have its own refresh hot-key + or button. + + "mode" can be "never" (same as -noscrollcopyrect) + to never try the copyrect, "keys" means to try it + in response to keystrokes only, "mouse" means to + try it in response to mouse events only, "always" + means to do both. Default: "always" + + Note: there can be painting errors or slow response + when using -scale so you may want to disable CopyRect + in this case "-scrollcopyrect never" on the command + line or by remote-control. Or you can also use the + "-scale xxx:nocr" scale option. + +-scr_area n Set the minimum area in pixels for a rectangle + to be considered for the -scrollcopyrect detection + scheme. This is to avoid wasting the effort on small + rectangles that would be quickly updated the normal way. + E.g. suppose an app updated the position of its skinny + scrollbar first and then shifted the large panel + it controlled. We want to be sure to skip the small + scrollbar and get the large panel. Default: 60000 + +-scr_skip list Skip scroll detection for applications matching + the comma separated list of strings in "list". + Some applications implement their scrolling in + strange ways where the XCopyArea, etc, also applies + to invisible portions of the window: if we CopyRect + those areas it looks awful during the scroll and + there may be painting errors left after the scroll. + Soffice.bin is the worst known offender. + + Use "##" to denote the start of the application class + (e.g. "##XTerm") and "++" to denote the start + of the application instance name (e.g. "++xterm"). + The string your list is matched against is of the form + "^^WM_NAME##Class++Instance" + The "xlsclients -la" command will provide this info. + + If a pattern is prefixed with "KEY:" it only applies + to Keystroke generated scrolls (e.g. Up arrow). If it + is prefixed with "MOUSE:" it only applies to Mouse + induced scrolls (e.g. dragging on a scrollbar). + Default: ##Soffice.bin,##StarOffice,##OpenOffice + +-scr_inc list Opposite of -scr_skip: this list is consulted first + and if there is a match the window will be monitored + via RECORD for scrolls irrespective of -scr_skip. + Use -scr_skip '*' to skip anything that does not match + your -scr_inc. Use -scr_inc '*' to include everything. + +-scr_keys list For keystroke scroll detection, only apply the RECORD + heuristics to the comma separated list of keysyms in + "list". You may find the RECORD overhead for every + one of your keystrokes disrupts typing too much, but you + don't want to turn it off completely with "-scr mouse" + and -scr_parms does not work or is too confusing. + + The listed keysyms can be numeric or the keysym + names in the header file or from the + xev(1) program. Example: "-scr_keys Up,Down,Return". + One probably wants to have application specific lists + (e.g. for terminals, etc) but that is too icky to think + about for now... + + If "list" begins with the "-" character the list + is taken as an exclude list: all keysyms except those + list will be considered. The special string "builtin" + expands to an internal list of keysyms that are likely + to cause scrolls. BTW, by default modifier keys, + Shift_L, Control_R, etc, are skipped since they almost + never induce scrolling by themselves. + +-scr_term list Yet another cosmetic kludge. Apply shell/terminal + heuristics to applications matching comma separated + list (same as for -scr_skip/-scr_inc). For example an + annoying transient under scroll detection is if you + hit Enter in a terminal shell with full text window, + the solid text cursor block will be scrolled up. + So for a short time there are two (or more) block + cursors on the screen. There are similar scenarios, + (e.g. an output line is duplicated). + + These transients are induced by the approximation of + scroll detection (e.g. it detects the scroll, but not + the fact that the block cursor was cleared just before + the scroll). In nearly all cases these transient errors + are repaired when the true X framebuffer is consulted + by the normal polling. But they are distracting, so + what this option provides is extra "padding" near the + bottom of the terminal window: a few extra lines near + the bottom will not be scrolled, but rather updated + from the actual X framebuffer. This usually reduces + the annoying artifacts. Use "none" to disable. + Default: "term" + +-scr_keyrepeat lo-hi If a key is held down (or otherwise repeats rapidly) and + this induces a rapid sequence of scrolls (e.g. holding + down an Arrow key) the "scrollcopyrect" detection + and overhead may not be able to keep up. A time per + single scroll estimate is performed and if that estimate + predicts a sustainable scrollrate of keys per second + between "lo" and "hi" then repeated keys will be + DISCARDED to maintain the scrollrate. For example your + key autorepeat may be 25 keys/sec, but for a large + window or slow link only 8 scrolls per second can be + sustained, then roughly 2 out of every 3 repeated keys + will be discarded during this period. Default: "4-20" + +-scr_parms string Set various parameters for the scrollcopyrect mode. + The format is similar to that for -wireframe and packed + with lots of parameters: + + Format: T+B+L+R,t1+t2+t3,s1+s2+s3+s4+s5 + Default: 0+64+32+32,0.02+0.10+0.9,0.03+0.06+0.5+0.1+5.0 + + If you leave nothing between commas: ",," the default + value is used. If you don't specify enough commas, + the trailing parameters are set to their defaults. + + "T+B+L+R" indicates four integers for how close in + pixels the pointer has to be from the Top, Bottom, Left, + or Right edges of the window to consider scrollcopyrect. + If -wireframe overlaps it takes precedence. This is a + speedup to quickly exclude a window from being watched + for scrollcopyrect: set them all to zero to not try + the speedup (things like selecting text will likely + be slower). + + "t1+t2+t3" specify three floating point times in + seconds that apply to scrollcopyrect detection with + *Keystroke* input: t1 is how long to wait after a key + is pressed for the first scroll, t2 is how long to keep + looking after a Keystroke scroll for more scrolls. + t3 is how frequently to try to update surrounding + scrollbars outside of the scrolling area (0.0 to + disable) + + "s1+s2+s3+s4+s5" specify five floating point times + in seconds that apply to scrollcopyrect detection with + *Mouse* input: s1 is how long to wait after a mouse + button is pressed for the first scroll, s2 is how long + to keep waiting for additional scrolls after the first + Mouse scroll was detected. s3 is how frequently to + try to update surrounding scrollbars outside of the + scrolling area (0.0 to disable). s4 is how long to + buffer pointer motion (to try to get fewer, bigger + mouse scrolls). s5 is the maximum time to spend just + updating the scroll window without updating the rest + of the screen. + +-fixscreen string Periodically "repair" the screen based on settings + in "string". Hopefully you won't need this option, + it is intended for cases when the -scrollcopyrect or + -wirecopyrect features leave too many painting errors, + but it can be used for any scenario. This option + periodically performs costly operations and so + interactive response may be reduced when it is on. + You can use 3 Alt_L's (the Left "Alt" key) taps in + a row (as described under -scrollcopyrect) instead to + manually request a screen repaint when it is needed. + + "string" is a comma separated list of one or more of + the following: "V=t", "C=t", "X=t", and "8=t". + In these "t" stands for a time in seconds (it is + a floating point even though one should usually use + values > 2 to avoid wasting resources). V sets how + frequently the entire screen should be sent to viewers + (it is like the 3 Alt_L's). C sets how long to wait + after a CopyRect to repaint the full screen. X sets + how frequently to reread the full X11 framebuffer from + the X server and push it out to connected viewers. + Use of X should be rare, please report a bug if you + find you need it. 8= applies only for -8to24 mode: it + sets how often the non-default visual regions of the + screen (e.g. 8bpp windows) are refreshed. Examples: + -fixscreen V=10 -fixscreen C=10 + +-debug_scroll Turn on debugging info printout for the scroll + heuristics. "-ds" is an alias. Specify it multiple + times for more output. + +-noxrecord Disable any use of the RECORD extension. This is + currently used by the -scrollcopyrect scheme and to + monitor X server grabs. + +-grab_buster Some of the use of the RECORD extension can leave a +-nograb_buster tiny window for XGrabServer deadlock. This is only if + the whole-server grabbing application expects mouse or + keyboard input before releasing the grab. It is usually + a window manager that does this. x11vnc takes care to + avoid the the problem, but if caught x11vnc will freeze. + Without -grab_buster, the only solution is to go the + physical display and give it some input to satisfy the + grabbing app. Or manually kill and restart the window + manager if that is feasible. With -grab_buster, x11vnc + will fork a helper thread and if x11vnc appears to be + stuck in a grab after a period of time (20-30 sec) then + it will inject some user input: button clicks, Escape, + mouse motion, etc to try to break the grab. If you + experience a lot of grab deadlock, please report a bug. + +-debug_grabs Turn on debugging info printout with respect to + XGrabServer() deadlock for -scrollcopyrect mode. + +-debug_sel Turn on debugging info printout with respect to + PRIMARY, CLIPBOARD, and CUTBUFFER0 selections. + +-pointer_mode n Various pointer motion update schemes. "-pm" is + an alias. The problem is pointer motion can cause + rapid changes on the screen: consider the rapid + changes when you drag a large window around opaquely. + Neither x11vnc's screen polling and vnc compression + routines nor the bandwidth to the vncviewers can keep + up these rapid screen changes: everything will bog down + when dragging or scrolling. So a scheme has to be used + to "eat" much of that pointer input before re-polling + the screen and sending out framebuffer updates. The + mode number "n" can be 0 to 4 and selects one of + the schemes desribed below. + + Note that the -wireframe and -scrollcopyrect modes + complement -pointer_mode by detecting (and improving) + certain periods of "rapid screen change". + + n=0: does the same as -nodragging. (all screen polling + is suspended if a mouse button is pressed.) + + n=1: was the original scheme used to about Jan 2004: + it basically just skips -input_skip keyboard or pointer + events before repolling the screen. + + n=2 is an improved scheme: by watching the current rate + of input events it tries to detect if it should try to + "eat" additional pointer events before continuing. + + n=3 is basically a dynamic -nodragging mode: it detects + when the mouse motion has paused and then refreshes + the display. + + n=4 attempts to measures network rates and latency, + the video card read rate, and how many tiles have been + changed on the screen. From this, it aggressively tries + to push screen "frames" when it decides it has enough + resources to do so. NOT FINISHED. + + The default n is 2. Note that modes 2, 3, 4 will skip + -input_skip keyboard events (but it will not count + pointer events). Also note that these modes are not + available in -threads mode which has its own pointer + event handling mechanism. + + To try out the different pointer modes to see which + one gives the best response for your usage, it is + convenient to use the remote control function, for + example "x11vnc -R pm:4" or the tcl/tk gui (Tuning -> + pointer_mode -> n). + +-input_skip n For the pointer handling when non-threaded: try to + read n user input events before scanning display. n < 0 + means to act as though there is always user input. + Default: 10 + +-allinput Have x11vnc read and process all available client input + before proceeding. + +-input_eagerly Similar to -allinput but use the handleEventsEagerly + mechanism built into LibVNCServer. + +-speeds rd,bw,lat x11vnc tries to estimate some speed parameters that + are used to optimize scheduling (e.g. -pointer_mode + 4, -wireframe, -scrollcopyrect) and other things. + Use the -speeds option to set these manually. + The triple "rd,bw,lat" corresponds to video h/w + read rate in MB/sec, network bandwidth to clients in + KB/sec, and network latency to clients in milliseconds, + respectively. If a value is left blank, e.g. "-speeds + ,100,15", then the internal scheme is used to estimate + the empty value(s). + + Typical PC video cards have read rates of 5-10 MB/sec. + If the framebuffer is in main memory instead of video + h/w (e.g. SunRay, shadowfb, dummy driver, Xvfb), the + read rate may be much faster. "x11perf -getimage500" + can be used to get a lower bound (remember to factor + in the bytes per pixel). It is up to you to estimate + the network bandwith and latency to clients. For the + latency the ping(1) command can be used. + + For convenience there are some aliases provided, + e.g. "-speeds modem". The aliases are: "modem" for + 6,4,200; "dsl" for 6,100,50; and "lan" for 6,5000,1 + +-wmdt string For some features, e.g. -wireframe and -scrollcopyrect, + x11vnc has to work around issues for certain window + managers or desktops (currently kde and xfce). + By default it tries to guess which one, but it can + guess incorrectly. Use this option to indicate which + wm/dt. "string" can be "gnome", "kde", "cde", + "xfce", or "root" (classic X wm). Anything else + is interpreted as "root". + +-debug_pointer Print debugging output for every pointer event. +-debug_keyboard Print debugging output for every keyboard event. + Same as -dp and -dk, respectively. Use multiple + times for more output. + +-defer time Time in ms to delay sending updates to connected clients + (deferUpdateTime) Default: 20 + +-wait time Time in ms to pause between screen polls. Used to cut + down on load. Default: 20 + +-extra_fbur n Perform extra FrameBufferUpdateRequests checks to + try to be in better sync with the client's requests. + What this does is perform extra polls of the client + socket at critical times (before '-defer' and '-wait' + calls.) The default is n=1. Set to a larger number to + insert more checks or set to n=0 to disable. A downside + of these extra calls is that more mouse input may be + processed than desired. + +-wait_ui factor Factor by which to cut the -wait time if there + has been recent user input (pointer or keyboard). + Improves response, but increases the load whenever you + are moving the mouse or typing. Default: 2.00 +-setdefer n When the -wait_ui mechanism cuts down the wait time ms, + set the defer time to the same ms value. n=1 to enable, + 0 to disable, and -1 to set defer to 0 (no delay). + Similarly, 2 and -2 indicate 'urgent_update' mode should + be used to push the updates even sooner. Default: 1 +-nowait_bog Do not detect if the screen polling is "bogging down" + and sleep more. Some activities with no user input can + slow things down a lot: consider a large terminal window + with a long build running in it continuously streaming + text output. By default x11vnc will try to detect this + (3 screen polls in a row each longer than 0.25 sec with + no user input), and sleep up to 1.5 secs to let things + "catch up". Use this option to disable that detection. +-slow_fb time Floating point time in seconds to delay all screen + polling. For special purpose usage where a low frame + rate is acceptable and desirable, but you want the + user input processed at the normal rate so you cannot + use -wait. +-xrefresh time Floating point time in seconds to indicate how often to + do the equivalent of xrefresh(1) to force all windows + (in the viewable area if -id, -sid, or -clip is used) + to repaint themselves. Use this only if applications + misbehave by not repainting themselves properly. + See also -noxdamage. +-nap Monitor activity and if it is low take longer naps +-nonap between screen polls to really cut down load when idle. + Default: take naps +-sb time Time in seconds after NO activity (e.g. screen blank) + to really throttle down the screen polls (i.e. sleep + for about 1.5 secs). Use 0 to disable. Default: 60 + +-readtimeout n Set LibVNCServer rfbMaxClientWait to n seconds. On + slow links that take a long time to paint the first + screen LibVNCServer may hit the timeout and drop the + connection. Default: 20 seconds. +-ping n Send a 1x1 framebuffer update to all clients every n + seconds (e.g. to try to keep a network connection alive) + +-nofbpm If the system supports the FBPM (Frame Buffer Power +-fbpm Management) extension (i.e. some Sun systems), then + prevent the video h/w from going into a reduced power + state when VNC clients are connected. + + FBPM capable video h/w save energy when the workstation + is idle by going into low power states (similar to DPMS + for monitors). This interferes with x11vnc's polling + of the framebuffer data. + + "-nofbpm" means prevent FBPM low power states whenever + VNC clients are connected, while "-fbpm" means to not + monitor the FBPM state at all. See the xset(1) manpage + for details. -nofbpm is basically the same as running + "xset fbpm force on" periodically. Default: -fbpm + +-nodpms If the system supports the DPMS (Display Power Managemen +t +-dpms Signaling) extension, then prevent the monitor from + going into a reduced power state when VNC clients + are connected. + + DPMS reduced power monitor states are a good thing + and you normally want the power down to take place + (usually x11vnc has no problem exporting the display in + this state). You probably only want to use "-nodpms" + to work around problems with Screen Savers kicking + on in DPMS low power states. There is known problem + with kdesktop_lock on KDE where the screen saver keeps + kicking in every time user input stops for a second + or two. Specifying "-nodpms" works around it. + + "-nodpms" means prevent DPMS low power states whenever + VNC clients are connected, while "-dpms" means to not + monitor the DPMS state at all. See the xset(1) manpage + for details. -nodpms is basically the same as running + "xset dpms force on" periodically. Default: -dpms + +-forcedpms If the system supports the DPMS (Display Power + Management Signaling) extension, then try to keep the + monitor in a powered off state. This is to prevent + nosey people at the physical display from viewing what + is on the screen. Be sure to lock the screen before + disconnecting. + + This method is far from bullet proof, e.g. suppose + someone attaches a non-DPMS monitor, or loads the + machine so that there is a gap of time before x11vnc + restores the powered off state? On many machines if + he floods it with keyboard and mouse input he can see + flashes of what is on the screen before the DPMS off + state is reestablished. For this to work securely + there would need to be support in the X server to do + this exactly rather than approximately with DPMS. + +-clientdpms As -forcedpms but only when VNC clients are connected. + +-noserverdpms The UltraVNC ServerInput extension is supported. + This allows the VNC viewer to click a button that will + cause the server (x11vnc) to try to disable keyboard + and mouse input at the physical display and put the + monitor in dpms powered off state. Use this option to + skip powering off the monitor. + +-noultraext Disable the following UltraVNC extensions: SingleWindow + and ServerInput. The others managed by LibVNCServer + (textchat, 1/n scaling, rfbEncodingUltra) are not. + +-chatwindow Place a local UltraVNC chat window on the X11 display + that x11vnc is polling. That way the person on the VNC + viewer-side can chat with the person at the physical + X11 console. (e.g. helpdesk w/o telephone) + + For this to work the SSVNC package (version 1.0.21 or + later) MUST BE installed on the system where x11vnc runs + and the 'ssvnc' command must be available in $PATH. + The ssvncviewer is used as a chat window helper. + See http://www.karlrunge.com/x11vnc/ssvnc.html + + This option implies '-rfbversion 3.6' so as to trick + UltraVNC viewers, otherwise they assume chat is not + available. To specify a different rfbversion, place + it after the -chatwindow option on the cmdline. + + See also the remote control 'chaton' and 'chatoff' + actions. These can also be set from the tkx11vnc GUI. + +-noxdamage Do not use the X DAMAGE extension to detect framebuffer + changes even if it is available. Use -xdamage if your + default is to have it off. + + x11vnc's use of the DAMAGE extension: 1) significantly + reduces the load when the screen is not changing much, + and 2) detects changed areas (small ones by default) + more quickly. + + Currently the DAMAGE extension is overly conservative + and often reports large areas (e.g. a whole terminal + or browser window) as damaged even though the actual + changed region is much smaller (sometimes just a few + pixels). So heuristics were introduced to skip large + areas and use the damage rectangles only as "hints" + for the traditional scanline polling. The following + tuning parameters are introduced to adjust this + behavior: + +-xd_area A Set the largest DAMAGE rectangle area "A" (in + pixels: width * height) to trust as truly damaged: + the rectangle will be copied from the framebuffer + (slow) no matter what. Set to zero to trust *all* + rectangles. Default: 20000 +-xd_mem f Set how long DAMAGE rectangles should be "remembered", + "f" is a floating point number and is in units of the + scanline repeat cycle time (32 iterations). The default + (1.0) should give no painting problems. Increase it if + there are problems or decrease it to live on the edge + (perhaps useful on a slow machine). + +-sigpipe string Broken pipe (SIGPIPE) handling. "string" can be + "ignore" or "exit". For "ignore" LibVNCServer + will handle the abrupt loss of a client and continue, + for "exit" x11vnc will cleanup and exit at the 1st + broken connection. + + This option is not really needed since LibVNCServer + is doing the correct thing now for quite some time. + However, for convenience you can use it to ignore other + signals, e.g. "-sigpipe ignore:HUP,INT,TERM" in case + that would be useful for some sort of application. + You can also put "exit:.." in the list to have x11vnc + cleanup on the listed signals. "-sig" is an alias + for this option if you don't like the 'pipe'. Example: + -sig ignore:INT,TERM,exit:USR1 + +-threads Whether or not to use the threaded LibVNCServer +-nothreads algorithm [rfbRunEventLoop] if libpthread is available. + In this mode new threads (one for input and one + for output) are created to handle each new client. + Default: -nothreads. + + Thread stability is much improved in version 0.9.8. + + Multiple clients in threaded mode should be stable + for the ZRLE encoding on all platforms. The Tight and + Zlib encodings are currently only stable on Linux for + multiple clients. Compile with -DTLS=__thread if your + OS and compiler and linker support it. + + For resizes (randr, etc.) set this env. var. to the numb +er + of milliseconds to sleep: X11VNC_THREADS_NEW_FB_SLEEP + at various places in the do_new_fb() action. This is to + let various activities settle. Default is about 500ms. + + Multiple clients in threaded mode could yield better + performance for 'class-room' broadcasting usage; also in + -appshare broadcast mode. See also the -reflect option. + +-fs f If the fraction of changed tiles in a poll is greater + than f, the whole screen is updated. Default: 0.75 +-gaps n Heuristic to fill in gaps in rows or cols of n or + less tiles. Used to improve text paging. Default: 4 +-grow n Heuristic to grow islands of changed tiles n or wider + by checking the tile near the boundary. Default: 3 +-fuzz n Tolerance in pixels to mark a tiles edges as changed. + Default: 2 +-debug_tiles Print debugging output for tiles, fb updates, etc. + +-snapfb Instead of polling the X display framebuffer (fb) + for changes, periodically copy all of X display fb + into main memory and examine that copy for changes. + (This setting also applies for non-X -rawfb modes). + Under some circumstances this will improve interactive + response, or at least make things look smoother, but in + others (most!) it will make the response worse. If the + video h/w fb is such that reading small tiles is very + slow this mode could help. To keep the "framerate" + up the screen size x bpp cannot be too large. Note that + this mode is very wasteful of memory I/O resources + (it makes full screen copies even if nothing changes). + It may be of use in video capture-like applications, + webcams, or where window tearing is a problem. + +-rawfb string Instead of polling X, poll the memory object specified + in "string". + + For file polling, to memory map mmap(2) a file use: + "map:/path/to/a/file@WxHxB", with framebuffer Width, + Height, and Bits per pixel. "mmap:..." is the + same. + + If there is trouble with mmap, use "file:/..." + for slower lseek(2) based reading. + + Use "snap:..." to imply -snapfb mode and the "file:" + access (this is for unseekable devices that only provide + the fb all at once, e.g. a video camera provides the + whole frame). + + For shared memory segments string is of the form: + "shm:N@WxHxB" which specifies a shmid N and with + WxHxB as above. See shmat(1) and ipcs(1) + + If you do not supply a type "map" is assumed if + the file exists (see the next paragraphs for some + exceptions to this.) + + If string is "setup:cmd", then the command "cmd" + is run and the first line from it is read and used + as "string". This allows initializing the device, + determining WxHxB, etc. These are often done as root + so take care. + + If the string begins with "video", see the VIDEO4LINUX + discussion below where the device may be queried for + (and possibly set) the framebuffer parameters. + + If the string begins with "console", "/dev/fb", + "fb", or "vt", see the LINUX CONSOLE discussion + below where the framebuffer device is opened and + keystrokes (and possibly mouse events) are inserted + into the console. + + If the string begins with "vnc", see the VNC HOST + discussion below where the framebuffer is taken as that + of another remote VNC server. + + Optional suffixes are ":R/G/B" and "+O" to specify + red, green, and blue masks (in hex) and an offset into + the memory object. If the masks are not provided x11vnc + guesses them based on the bpp (if the colors look wrong, + you need to provide the masks.) + + Another optional suffix is the Bytes Per Line which in + some cases is not WxB/8. Specify it as WxHxB-BPL + e.g. 800x600x16-2048. This could be a normal width + 1024 at 16bpp fb, but only width 800 shows up. + + So the full format is: mode:file@WxHxB:R/G/B+O-BPL + + Examples: + -rawfb shm:210337933@800x600x32:ff/ff00/ff0000 + -rawfb map:/dev/fb0@1024x768x32 + -rawfb map:/tmp/Xvfb_screen0@640x480x8+3232 + -rawfb file:/tmp/my.pnm@250x200x24+37 + -rawfb file:/dev/urandom@128x128x8 + -rawfb snap:/dev/video0@320x240x24 -24to32 + -rawfb video0 + -rawfb video -pipeinput VID + -rawfb console + -rawfb vt2 + -rawfb vnc:somehost:0 + + (see ipcs(1) and fbset(1) for the first two examples) + + In general all user input is discarded by default (see + the -pipeinput option for how to use a helper program + to insert). Most of the X11 (screen, keyboard, mouse) + options do not make sense and many will cause this + mode to crash, so please think twice before setting or + changing them in a running x11vnc. + + If you DO NOT want x11vnc to close the X DISPLAY in + rawfb mode, prepend a "+" e.g. +file:/dev/fb0... + Keeping the display open enables the default + remote-control channel, which could be useful. + Alternatively, if you specify -noviewonly, then the + mouse and keyboard input are STILL sent to the X + display, this usage should be very rare, i.e. doing + something strange with /dev/fb0. + + If the device is not "seekable" (e.g. webcam) try + reading it all at once in full snaps via the "snap:" + mode (note: this is a resource hog). If you are using + file: or map: AND the device needs to be reopened for + *every* snapfb snapshot, set the environment variable: + SNAPFB_RAWFB_RESET=1 as well. + + If you want x11vnc to dynamically transform a 24bpp + rawfb to 32bpp (note that this will be slower) also + supply the -24to32 option. This would be useful for, + say, a video camera that delivers the pixel data as + 24bpp packed RGB. This is the default under "video" + mode if the bpp is 24. + + Normally the bits per pixel, B, is 8, 16, or 32 (or + rarely 24), however there is also some support for + B < 8 (e.g. old graphics displays 4 bpp or 1 bpp). + In this case you certainly must supply the masks as + well: WxHxB:R/G/B. The pixels will be padded out to + 8 bpp using depth 8 truecolor. The scheme currently + does not work with snap fb (ask if interested.) B=1 + monochrome example: file:/dev/urandom@128x128x1:1/1/1 + Some other like this are 128x128x2:3/3/3 128x128x4:7/7/7 + + For B < 8 framebuffers you can also set the env. var + RAWFB_CGA=1 to try a CGA mapping for B=4 (e.g. linux + vga16fb driver.) Note with low bpp and/or resolution + VGA and VGA16 modes on the Linux console one's attempt + to export them via x11vnc can often be thwarted due to + special color palettes, pixel packings, and even video + painting buffering. OTOH, often experimenting with the + RGB masks can yield something recognizable. + + VIDEO4LINUX: on Linux some attempt is made to handle + video devices (webcams or TV tuners) automatically. + The idea is the WxHxB will be extracted from the + device itself. So if you do not supply "@WxHxB... + parameters x11vnc will try to determine them. It first + tries the v4l API if that support has been compiled in. + Otherwise it will run the v4l-info(1) external program + if it is available. + + The simplest examples are "-rawfb video" and "-rawfb + video1" which imply the device file /dev/video and + /dev/video1, respectively. You can also supply the + /dev if you like, e.g. "-rawfb /dev/video0" + + Since the video capture device framebuffer usually + changes continuously (e.g. brightness fluctuations), + you may want to use the -wait, -slow_fb, or -defer + options to lower the "framerate" to cut down on + network VNC traffic. + + A more sophisticated video device scheme allows + initializing the device's settings using: + + -rawfb video: + + The prefix could also be, as above, e.g. "video1:" to + specify the device file. The v4l API must be available + for this to work. Otherwise, you will need to try + to initialize the device with an external program, + e.g. xawtv, spcaview, and hope they persist when x11vnc + re-opens the device. + + is a comma separated list of key=value pairs. + The device's brightness, color, contrast, and hue can + be set to percentages, e.g. br=80,co=50,cn=44,hu=60. + + The device filename can be set too if needed (if it + does not start with "video"), e.g. fn=/dev/qcam. + + The width, height and bpp of the framebuffer can be + set via, e.g., w=160,h=120,bpp=16. + + Related to the bpp above, the pixel format can be set + via the fmt=XXX, where XXX can be one of: GREY, HI240, + RGB555, RGB565, RGB24, and RGB32 (with bpp 8, 8, 16, 16, + 24, and 32 respectively). See http://www.linuxtv.org + for more info (V4L api). + + For TV/rf tuner cards one can set the tuning mode + via tun=XXX where XXX can be one of PAL, NTSC, SECAM, + or AUTO. + + One can switch the input channel by the inp=XXX setting, + where XXX is the name of the input channel (Television, + Composite1, S-Video, etc). Use the name that is in the + information about the device that is printed at startup. + + For input channels with tuners (e.g. Television) one + can change which station is selected by the sta=XXX + setting. XXX is the station number. Currently only + the ntsc-cable-us (US cable) channels are built into + x11vnc. See the -freqtab option below to supply one + from xawtv. If XXX is greater than 500, then it is + interpreted as a raw frequency in KHz. + + Example: + + -rawfb video:br=80,w=320,h=240,fmt=RGB32,tun=NTSC,sta=47 + + one might need to add inp=Television too for the input + channel to be TV if the card doesn't come up by default + in that one. + + Note that not all video capture devices will support + all of the above settings. + + See the -pipeinput VID option below for a way to control + the settings through the VNC Viewer via keystrokes. + As a shortcut, if the string begins "Video.." instead + of "video.." then -pipeinput VID is implied. + + As above, if you specify a "@WxHxB..." after the + string they are used verbatim: the device + is not queried for the current values. Otherwise the + device will be queried. + + LINUX CONSOLE: The following describes some ways to + view and possibly interact with the Linux text/graphics + console (i.e. not X11 XFree86/Xorg) + + Note: If the LibVNCServer LinuxVNC program is on your + system you may want to use that instead of the following + method because it will be faster and more accurate + for the Linux text console and includes mouse support. + There is, however, the basic LinuxVNC functionality in + x11vnc if you replace "console" with "vt" in the + examples below. + + If the rawfb string begins with "console" the + framebuffer device /dev/fb0 is opened and /dev/tty0 is + opened too. The latter is used to inject keystrokes + (not all are supported, but the basic ones are). + You will need to be root to inject keystrokes, but + not necessarily to open /dev/fb0. /dev/tty0 refers to + the active VT, to indicate one explicitly, use, e.g., + "console2" for /dev/tty2, etc. by indicating the + specific VT number. + + For the Linux framebuffer device, /dev/fb0, (fb1, + etc) to be enabled the appropriate kernel drivers must + be loaded. E.g. vesafb or vga16fb and also by setting + the boot parameter vga=0x301 (or 0x314, 0x317, etc.) + (The vga=... method is the preferred way; set your + machines up that way.) Otherwise there will be a + 'No such device' error. You can also load a Linux + framebuffer driver specific to your make of video card + for more functionality. Once the machine is booted one + can often 'modprobe' the fb driver as root to obtain + a framebuffer device. + + If you cannot get /dev/fb0 working on Linux, try + using the LinuxVNC emulation mode by "-rawfb vtN" + where N = 1, ... 6 is the Linux Virtual Terminal (aka + virtual console) you wish to view, e.g. "-rawfb vt2". + Unlike /dev/fb mode, it need not be the active Virtual + Terminal. Note that this mode can only show text and + not graphics. x11vnc polls the text in /dev/vcsaN + + Set the env. var. RAWFB_VCSA_BW=1 to disable colors in + the "vtN" mode (i.e. black and white only.) If you + do not prefer the default 16bpp set RAWFB_VCSA_BPP to + 8 or 32. If you need to tweak the rawfb parameters by + using the 'console_guess' string printed at startup, + be sure to indicate the snap: method. + + uinput: If the Linux version appears to be 2.6 or + later and the "uinput" module appears to be present + (modprobe uinput), then the uinput method will be used + instead of /dev/ttyN. uinput allows insertion of BOTH + keystrokes and mouse input and so it preferred when + accessing graphical (e.g. QT-embedded) linux console + apps. See -pipeinput UINPUT below for more information + on this mode; you will have to use -pipeinput if you + want to tweak any UINPUT parameters. You may also want + to also use the -nodragging and -cursor none options. + Use "console0", etc or -pipeinput CONSOLE to force + the /dev/ttyN method. + + Note you can change the Linux VT remotely using the + chvt(1) command to make the one you want be the active + one (e.g. 'chvt 3'). Sometimes switching out and back + corrects the framebuffer's graphics state. For the + "-rawfb vtN" mode there is no need to switch the VT's. + + To skip input injecting entirely use "consolex" + or "vtx". + + The string "/dev/fb0" (1, etc.) can be used instead + of "console". This can be used to specify a different + framebuffer device, e.g. /dev/fb1. As a shortcut the + "/dev/" can be dropped. If the name is something + nonstandard, use "console:/dev/foofb" + + If you do not want x11vnc to guess the framebuffer's + WxHxB and masks automatically (sometimes the kernel + gives incorrect information), specify them with a @WxHxB + (and optional :R/G/B masks) at the end of the string. + + Examples: + -rawfb console + -rawfb /dev/fb0 (same) + -rawfb console3 (force /dev/tty3) + -rawfb consolex (no keystrokes or mouse) + -rawfb console:/dev/nonstd + -rawfb console -pipeinput UINPUT:accel=4.0 + -rawfb vt3 (/dev/tty3 w/o /dev/fb0) + + VNC HOST: if the -rawfb string is of the form + "vnc:host:N" then the VNC display "N" on the remote + VNC server "host" is connected to (i.e. x11vnc acts as + a VNC client itself) and that framebuffer is exported. + + This mode is really only of use if you are trying + to improve performance in the case of many (e.g. > + 10) simultaneous VNC viewers, and you try a divide + and conquer scheme to reduce bandwidth and improve + responsiveness. + + For example, if there will be 64 simultaneous VNC + viewers this can lead to a lot of redundant VNC traffic + to and from the server host:N, extra CPU usage, + and all viewers response can be reduced by having + to wait for writes to the slowest client to finish. + However, if you set up 8 reflectors/repeaters started + with option -rawfb vnc:host:N, then there are only + 8 connections to host:N. Each repeater then handles + 8 vnc viewer connections thereby spreading the load + around. In classroom broadcast usage, try to put the + repeaters on different switches. This mode is the same + as -reflect host:N. Replace "host:N" by "listen" + or "listen:port" for a reverse connection. + + Overall performance will not be as good as a single + direct connection because, among other things, + there is an additional level of framebuffer polling + and pointer motion can still induce many changes per + second that must be propagated. Tip: if the remote VNC + is x11vnc doing wireframing, or an X display that does + wireframing that gives much better response than opaque + window dragging. Consider the -nodragging option if + the problem is severe. + + The env. var. X11VNC_REFLECT_PASSWORD can be set to + the password needed to log into the vnc host server, or + to "file:path_to_file" to indicate a file containing + the password as its first line. + + The VNC HOST mode implies -shared. Use -noshared as + a subsequent cmdline option to disable sharing. + +-freqtab file For use with "-rawfb video" for TV tuner devices to + specify station frequencies. Instead of using the built + in ntsc-cable-us mapping of station number to frequency, + use the data in file. For stations that are not + numeric, e.g. SE20, they are placed above the highest + numbered station in the order they are found. Example: + "-freqtab /usr/X11R6/share/xawtv/europe-west.list" + You can make your own freqtab by copying the xawtv + format. + +-pipeinput cmd This option lets you supply an external command in + "cmd" that x11vnc will pipe all of the user input + events to in a simple format. In -pipeinput mode by + default x11vnc will not process any of the user input + events. If you prefix "cmd" with "tee:" it will + both send them to the pipe command and process them. + For a description of the format run "-pipeinput + tee:/bin/cat". Another prefix is "reopen" which + means to reopen pipe if it exits. Separate multiple + prefixes with commas. + + In combination with -rawfb one might be able to + do amusing things (e.g. control non-X devices). + To facilitate this, if -rawfb is in effect then the + value is stored in X11VNC_RAWFB_STR for the pipe command + to use if it wants. Do 'env | grep X11VNC' for more. + + Built-in pipeinput modes (no external program required): + + If cmd is "VID" and you are using the -rawfb for a + video capture device, then an internal list of keyboard + mappings is used to set parameters of the video. + The mappings are: + + "B" and "b" adjust the brightness up and down. + "H" and "h" adjust the hue. + "C" and "c" adjust the colour. + "N" and "n" adjust the contrast. + "S" and "s" adjust the size of the capture screen. + "I" and "i" cycle through input channels. + Up and Down arrows adjust the station (if a tuner) + F1, F2, ..., F6 will switch the video capture pixel + format to HI240, RGB565, RGB24, RGB32, RGB555, and + GREY respectively. See -rawfb video for details. + + If cmd is "CONSOLE" or "CONSOLEn" where n + is a Linux console number, then the linux console + keystroke insertion to /dev/ttyN (see -rawfb console) + is performed. + + If cmd begins with "UINPUT" then the Linux uinput + module is used to insert both keystroke and mouse events + to the Linux console (see -rawfb above). This usually + is the /dev/input/uinput device file (you may need to + create it with "mknod /dev/input/uinput c 10 223" + and insert the module with "modprobe uinput". + + The UINPUT mode currently only does US keyboards (a + scan code option may be added), and not all keysyms + are supported. + + You may want to use the options -cursor none and + -nodragging in this mode. + + Additional tuning options may be supplied via: + UINPUT:opt1,opt2,... (a comma separated list). If an + option begins with "/" it is taken as the uinput + device file. + + Which uinput is injected can be controlled by an option + string made of the characters "K", "M", and "B" + (see the -input option), e.g. "KM" allows keystroke + and motion but not button clicks. + + A UINPUT option of the form: accel=f, or accel=fx+fy + sets the mouse motion "acceleration". This is used + to correct raw mouse relative motion into how much the + application cursor moves (x11vnc has no control over, + or knowledge of how the windowing application interprets + the raw mouse motions). Typically the acceleration + for an X display is 2 (see xset "m" option). "f" + is a floating point number, e.g. 3.0. Use "fx+fy" + if you need to supply different corrections for x and y. + + Note: the default acceleration is 2.0 since it seems + both X and qt-embedded often (but not always) use + this value. + + Even with a correct accel setting the mouse position + will get out of sync (probably due to a mouse + "threshold" setting where the acceleration doe not + apply, set xset(1)). The option reset=N sets the + number of ms (default 150) after which the cursor is + attempted to be reset (by forcing the mouse to (0, + 0) via small increments and then back out to (x, y) + in 1 jump), This correction seems to be needed but can + cause jerkiness or unexpected behavior with menus, etc. + Use reset=0 to disable. + + If the uinput device has an absolute pointer (as opposed + to a normal mouse that is a relative pointer) you can + specify the option "abs". Note that a touchpad + on a laptop is an absolute device to some degree. + This (usually) avoids all the problems with mouse + acceleration. If x11vnc has trouble deducing the size + of the device, use "abs=WxH". Furthermore, if the + device is a touchscreen (assumed to have an absolute + pointer) use "touch" or "touch=WxH". + + If you set the env. var X11VNC_UINPUT_THRESHOLDS then + the thresh=n mode will be enabled. It is currently + not working well. If |dx| <= thresh and |dy| < thresh + no acceleration is applied. Use "thresh=+n" |dx| + + |dy| < thresh to be used instead (X11?) + + Example: + -pipeinput UINPUT:accel=4.0 -cursor none + + You can also set the env. var X11VNC_UINPUT_DEBUG=1 or + higher to get debugging output for UINPUT mode. + +-macnodim For the native MacOSX server, disable dimming. +-macnosleep For the native MacOSX server, disable display sleep. +-macnosaver For the native MacOSX server, disable screensaver. +-macnowait For the native MacOSX server, do not wait for the + user to switch back to his display. +-macwheel n For the native MacOSX server, set the mouse wheel + speed to n (default 5). +-macnoswap For the native MacOSX server, do not swap mouse + buttons 2 and 3. +-macnoresize For the native MacOSX server, do not resize or reset + the framebuffer even if it is detected that the screen + resolution or depth has changed. +-maciconanim n For the native MacOSX server, set n to the number + of milliseconds that the window iconify/deiconify + animation takes. In -ncache mode this value will be + used to skip the animation if possible. (default 400) +-macmenu For the native MacOSX server, in -ncache client-side + caching mode, try to cache pull down menus (not perfect + because they have animated fades, etc.) +-macuskbd For the native MacOSX server, use the original + keystroke insertion code based on a US keyboard. + +-gui [gui-opts] Start up a simple tcl/tk gui based on the the remote + control options -remote/-query described below. + Requires the "wish" program to be installed on the + machine. "gui-opts" is not required: the default + is to start up both the full gui and x11vnc with the + gui showing up on the X display in the environment + variable DISPLAY. + + "gui-opts" can be a comma separated list of items. + Currently there are these types of items: 1) a gui + mode, a 2) gui "simplicity", 3) the X display the + gui should display on, 4) a "tray" or "icon" mode, + and 5) a gui geometry. + + 1) The gui mode can be "start", "conn", or "wait" + "start" is the default mode above and is not required. + "conn" means do not automatically start up x11vnc, + but instead just try to connect to an existing x11vnc + process. "wait" means just start the gui and nothing + else (you will later instruct the gui to start x11vnc + or connect to an existing one.) + + 2) The gui simplicity is off by default (a power-user + gui with all options is presented) To start with + something less daunting supply the string "simple" + ("ez" is an alias for this). Once the gui is + started you can toggle between the two with "Misc -> + simple_gui". + + 3) Note the possible confusion regarding the potentially + two different X displays: x11vnc polls one, but you + may want the gui to appear on another. For example, if + you ssh in and x11vnc is not running yet you may want + the gui to come back to you via your ssh redirected X + display (e.g. localhost:10). + + If you do not specify a gui X display in "gui-opts" + then the DISPLAY environment variable and -display + option are tried (in that order). Regarding the x11vnc + X display the gui will try to communication with, it + first tries -display and then DISPLAY. For example, + "x11vnc -display :0 -gui otherhost:0", will remote + control an x11vnc polling :0 and display the gui on + otherhost:0 The "tray/icon" mode below reverses this + preference, preferring to display on the x11vnc display. + + 4) When "tray" or "icon" is specified, the gui + presents itself as a small icon with behavior typical + of a "system tray" or "dock applet". The color + of the icon indicates status (connected clients) and + there is also a balloon status. Clicking on the icon + gives a menu from which properties, etc, can be set and + the full gui is available under "Advanced". To be + fully functional, the gui mode should be "start" + (the default). + + Note that tray or icon mode will imply the -forever + x11vnc option (if the x11vnc server is started along + with the gui) unless -connect or -connect_or_exit has + been specified. So x11vnc (and the tray/icon gui) + will wait for more connections after the first client + disconnects. If you want only one viewer connection + include the -once option. + + For "icon" the gui just a small standalone window. + For "tray" it will attempt to embed itself in the + "system tray" if possible. If "=setpass" is appended the +n + at startup the X11 user will be prompted to set the + VNC session password. If = is appended + that icon will attempt to embed itself in the window + given by hexnumber. Use =noadvanced to disable the + full gui. (To supply more than one, use "+" sign). + E.g. -gui tray=setpass and -gui icon=0x3600028 + + Other modes: "full", the default and need not be + specified. "-gui none", do not show a gui, useful + to override a ~/.x11vncrc setting, etc. + + 5) When "geom=+X+Y" is specified, that geometry + is passed to the gui toplevel. This is the icon in + icon/tray mode, or the full gui otherwise. You can + also specify width and height, i.e. WxH+X+Y, but it + is not recommended. In "tray" mode the geometry is + ignored unless the system tray manager does not seem + to be running. One could imagine using something like + "-gui tray,geom=+4000+4000" with a display manager + to keep the gui invisible until someone logs in... + + More icon tricks, "icon=minimal" gives an icon just + with the VNC display number. You can also set the font + with "iconfont=...". The following could be useful: + "-gui icon=minimal,iconfont=5x8,geom=24x10+0-0" + + General examples of the -gui option: "x11vnc -gui", + "x11vnc -gui ez" "x11vnc -gui localhost:10", + "x11vnc -gui conn,host:0", "x11vnc -gui tray,ez" + "x11vnc -gui tray=setpass" + + If you do not intend to start x11vnc from the gui + (i.e. just remote control an existing one), then the + gui process can run on a different machine from the + x11vnc server as long as X permissions, etc. permit + communication between the two. + + FONTS: On some systems the tk fonts can be too small, + jagged, or otherwise unreadable. There are 4 env vars + you can set to be the tk font you prefer: + + X11VNC_FONT_BOLD main font for menus and buttons. + X11VNC_FONT_FIXED font for fixed width text. + + X11VNC_FONT_BOLD_SMALL tray icon font. + X11VNC_FONT_REG_SMALL tray icon menu font. + + The last two only apply for the tray icon mode. + + Here are some examples: + + -env X11VNC_FONT_BOLD='Helvetica -16 bold' + -env X11VNC_FONT_FIXED='Courier -14' + -env X11VNC_FONT_REG_SMALL='Helvetica -12' + + You can put the lines like the above (without the + quotes) in your ~/.x11vncrc file to avoid having to + specify them on the x11vnc command line. + +-remote command Remotely control some aspects of an already running + x11vnc server. "-R" and "-r" are aliases for + "-remote". After the remote control command is + sent to the running server the 'x11vnc -remote ...' + command exits. You can often use the -query command + (see below) to see if the x11vnc server processed your + -remote command. + + The default communication channel is that of X + properties (specifically X11VNC_REMOTE), and so this + command must be run with correct settings for DISPLAY + and possibly XAUTHORITY to connect to the X server + and set the property. Alternatively, use the -display + and -auth options to set them to the correct values. + The running server cannot use the -novncconnect option + because that disables the communication channel. + See below for alternate channels. + + For example: 'x11vnc -remote stop' (which is the same as + 'x11vnc -R stop') will close down the x11vnc server. + 'x11vnc -R shared' will enable shared connections, and + 'x11vnc -R scale:3/4' will rescale the desktop. + + To use a different name for the X11 property (e.g. to + have separate communication channels for multiple + x11vnc's on the same display) set the X11VNC_REMOTE + environment variable to the string you want, for + example: -env X11VNC_REMOTE=X11VNC_REMOTE_12345 + Both sides of the channel must use the same unique name. + + To run a bunch of commands in a sequence use something + like: x11vnc -R 'script:firstcmd;secondcmd;...' + + Use x11vnc -R script:file=/path/to/file to read commands + from a file (can be multi-line and use the comment '#' + character in the normal way. The ';' separator must + still be used to separate each command.) + + To not try to contact another x11vnc process and instead + just run the command (or query) directly, prefix the + command with the string "DIRECT:" + + The following -remote/-R commands are supported: + + stop terminate the server, same as "quit" + "exit" or "shutdown". + ping see if the x11vnc server responds. + return is: ans=ping: + ping:mystring as above, but use your own unique string +. + return is: ans=ping:mystring: + blacken try to push a black fb update to all + clients (due to timings a client + could miss it). Same as "zero", also + "zero:x1,y1,x2,y2" for a rectangle. + refresh send the entire fb to all clients. + reset recreate the fb, polling memory, etc. + id:windowid set -id window to "windowid". empty + or "root" to go back to root window + sid:windowid set -sid window to "windowid" + id_cmd:cmd cmds: raise, lower, map, unmap, iconify, + move:dXdY, resize:dWdH, geom:WxH+X+Y. dX + dY, dW, and dH must have a leading "+" + or "-" e.g.: move:-30+10 resize:+20+35 + also: wm_delete, wm_name:string and + icon_name:string. Also id_cmd:win=N:cmd + waitmapped wait until subwin is mapped. + nowaitmapped do not wait until subwin is mapped. + clip:WxH+X+Y set -clip mode to "WxH+X+Y" + flashcmap enable -flashcmap mode. + noflashcmap disable -flashcmap mode. + shiftcmap:n set -shiftcmap to n. + notruecolor enable -notruecolor mode. + truecolor disable -notruecolor mode. + overlay enable -overlay mode (if applicable). + nooverlay disable -overlay mode. + overlay_cursor in -overlay mode, enable cursor drawing. + overlay_nocursor disable cursor drawing. same as + nooverlay_cursor. + 8to24 enable -8to24 mode (if applicable). + no8to24 disable -8to24 mode. + 8to24_opts:str set the -8to24 opts to "str". + 24to32 enable -24to32 mode (if applicable). + no24to32 disable -24to32 mode. + visual:vis set -visual to "vis" + scale:frac set -scale to "frac" + scale_cursor:f set -scale_cursor to "f" + viewonly enable -viewonly mode. + noviewonly disable -viewonly mode. + shared enable -shared mode. + noshared disable -shared mode. + forever enable -forever mode. + noforever disable -forever mode. + timeout:n reset -timeout to n, if there are + currently no clients, exit unless one + connects in the next n secs. + tightfilexfer enable filetransfer for NEW clients. + notightfilexfer disable filetransfer for NEW clients. + ultrafilexfer enable filetransfer for clients. + noultrafilexfer disable filetransfer for clients. + rfbversion:n.m set -rfbversion for new clients. + http enable http client connections. + nohttp disable http client connections. + deny deny any new connections, same as "lock" + nodeny allow new connections, same as "unlock" + avahi enable avahi service advertising. + noavahi disable avahi service advertising. + mdns enable avahi service advertising. + nomdns disable avahi service advertising. + zeroconf enable avahi service advertising. + nozeroconf disable avahi service advertising. + connect:host do reverse connection to host, "host" + may be a comma separated list of hosts + or host:ports. See -connect. Passwords + required as with fwd connections. + See X11VNC_REVERSE_CONNECTION_NO_AUTH=1 + disconnect:host disconnect any clients from "host" + same as "close:host". Use host + "all" to close all current clients. + If you know the client internal hex ID, + e.g. 0x3 (returned by "-query clients" + and RFB_CLIENT_ID) you can use that too. + proxy:host:port set reverse connection proxy (empty to + disable). + allowonce:host For the next connection only, allow + connection from "host". In -ssl mode + two connections are allowed (i.e. Fetch + Cert) unless X11VNC_NO_SSL_ALLOW_TWICE=1 + allow:hostlist set -allow list to (comma separated) + "hostlist". See -allow and -localhost. + Do not use with -allow /path/to/file + Use "+host" to add a single host, and + use "-host" to delete a single host + localhost enable -localhost mode + nolocalhost disable -localhost mode + listen:str set -listen to str, empty to disable. + noipv6 enable -noipv6 mode. + ipv6 disable -noipv6 mode. + noipv4 enable -noipv4 mode. + ipv4 disable -noipv4 mode. + 6 enable -6 IPv6 listening mode. + no6 disable -6 IPv6 listening mode. + lookup disable -nolookup mode. + nolookup enable -nolookup mode. + lookup disable -nolookup mode. + input:str set -input to "str", empty to disable. + grabkbd enable -grabkbd mode. + nograbkbd disable -grabkbd mode. + grabptr enable -grabptr mode. + nograbptr disable -grabptr mode. + grabalways enable -grabalways mode. + nograbalways disable -grabalways mode. + grablocal:n set -grablocal to n. + client_input:str set the K, M, B -input on a per-client + basis. select which client as for + disconnect, e.g. client_input:host:MB + or client_input:0x2:K + accept:cmd set -accept "cmd" (empty to disable). + afteraccept:cmd set -afteraccept (empty to disable). + gone:cmd set -gone "cmd" (empty to disable). + noshm enable -noshm mode. + shm disable -noshm mode (i.e. use shm). + flipbyteorder enable -flipbyteorder mode, you may need + to set noshm for this to do something. + noflipbyteorder disable -flipbyteorder mode. + onetile enable -onetile mode. (you may need to + set shm for this to do something) + noonetile disable -onetile mode. + solid enable -solid mode + nosolid disable -solid mode. + solid_color:color set -solid color (and apply it). + blackout:str set -blackout "str" (empty to disable). + See -blackout for the form of "str" + (basically: WxH+X+Y,...) + Use "+WxH+X+Y" to append a single + rectangle use "-WxH+X+Y" to delete one + xinerama enable -xinerama mode. (if applicable) + noxinerama disable -xinerama mode. + xtrap enable -xtrap input mode(if applicable) + noxtrap disable -xtrap input mode. + xrandr enable -xrandr mode. (if applicable) + noxrandr disable -xrandr mode. + xrandr_mode:mode set the -xrandr mode to "mode". + rotate:mode set the -rotate mode to "mode". + padgeom:WxH set -padgeom to WxH (empty to disable) + If WxH is "force" or "do" the padded + geometry fb is immediately applied. + quiet enable -quiet mode. + noquiet disable -quiet mode. + modtweak enable -modtweak mode. + nomodtweak enable -nomodtweak mode. + xkb enable -xkb modtweak mode. + noxkb disable -xkb modtweak mode. + capslock enable -capslock mode. + nocapslock disable -capslock mode. + skip_lockkeys enable -skip_lockkeys mode. + noskip_lockkeys disable -skip_lockkeys mode. + skip_keycodes:str enable -xkb -skip_keycodes "str". + sloppy_keys enable -sloppy_keys mode. + nosloppy_keys disable -sloppy_keys mode. + skip_dups enable -skip_dups mode. + noskip_dups disable -skip_dups mode. + add_keysyms enable -add_keysyms mode. + noadd_keysyms stop adding keysyms. those added will + still be removed at exit. + clear_mods enable -clear_mods mode and clear them. + noclear_mods disable -clear_mods mode. + clear_keys enable -clear_keys mode and clear them. + noclear_keys disable -clear_keys mode. + clear_locks do the clear_locks action. + clear_all do the clear_all action. + keystate have x11vnc print current keystate. + remap:str set -remap "str" (empty to disable). + See -remap for the form of "str" + (basically: key1-key2,key3-key4,...) + Use "+key1-key2" to append a single + keymapping, use "-key1-key2" to delete. + norepeat enable -norepeat mode. + repeat disable -norepeat mode. + nofb enable -nofb mode. + fb disable -nofb mode. + bell enable bell (if supported). + nobell disable bell. + sendbell ring the bell now. + nosel enable -nosel mode. + sel disable -nosel mode. + noprimary enable -noprimary mode. + primary disable -noprimary mode. + nosetprimary enable -nosetprimary mode. + setprimary disable -nosetprimary mode. + noclipboard enable -noclipboard mode. + clipboard disable -noclipboard mode. + nosetclipboard enable -nosetclipboard mode. + setclipboard disable -nosetclipboard mode. + seldir:str set -seldir to "str" + resend_cutbuffer resend the most recent CUTBUFFER0 copy + resend_clipboard resend the most recent CLIPBOARD copy + resend_primary resend the most recent PRIMARY copy + cursor:mode enable -cursor "mode". + show_cursor enable showing a cursor. + noshow_cursor disable showing a cursor. (same as + "nocursor") + cursor_drag enable cursor changes during drag. + nocursor_drag disable cursor changes during drag. + arrow:n set -arrow to alternate n. + xfixes enable xfixes cursor shape mode. + noxfixes disable xfixes cursor shape mode. + alphacut:n set -alphacut to n. + alphafrac:f set -alphafrac to f. + alpharemove enable -alpharemove mode. + noalpharemove disable -alpharemove mode. + alphablend disable -noalphablend mode. + noalphablend enable -noalphablend mode. + cursorshape disable -nocursorshape mode. + nocursorshape enable -nocursorshape mode. + cursorpos disable -nocursorpos mode. + nocursorpos enable -nocursorpos mode. + xwarp enable -xwarppointer mode. + noxwarp disable -xwarppointer mode. + buttonmap:str set -buttonmap "str", empty to disable + dragging disable -nodragging mode. + nodragging enable -nodragging mode. + ncache reenable -ncache mode. + noncache disable -ncache mode. + ncache_size:n set -ncache size to n. + ncache_cr enable -ncache_cr mode. + noncache_cr disable -ncache_cr mode. + ncache_no_moveraise enable no_moveraise mode. + noncache_no_moveraise disable no_moveraise mode. + ncache_no_dtchange enable ncache_no_dtchange mode. + noncache_no_dtchange disable ncache_no_dtchange mode. + ncache_old_wm enable ncache_old_wm mode. + noncache_old_wm disable ncache_old_wm mode. + ncache_no_rootpixmap enable ncache_no_rootpixmap. + noncache_no_rootpixmap disable ncache_no_rootpixmap. + ncache_reset_rootpixmap recheck the root pixmap, ncrp + ncache_keep_anims enable ncache_keep_anims. + noncache_keep_anims disable ncache_keep_anims. + ncache_pad:n set -ncache_pad to n. + wireframe enable -wireframe mode. same as "wf" + nowireframe disable -wireframe mode. same as "nowf" + wireframe:str enable -wireframe mode string. + wireframe_mode:str enable -wireframe mode string. + wireframelocal enable wireframelocal. same as "wfl" + nowireframe disable wireframelocal. same as "nowfl" + wirecopyrect:str set -wirecopyrect string. same as "wcr: +" + scrollcopyrect:str set -scrollcopyrect string. same "scr +" + noscrollcopyrect disable -scrollcopyrect mode. "noscr" + scr_area:n set -scr_area to n + scr_skip:list set -scr_skip to "list" + scr_inc:list set -scr_inc to "list" + scr_keys:list set -scr_keys to "list" + scr_term:list set -scr_term to "list" + scr_keyrepeat:str set -scr_keyrepeat to "str" + scr_parms:str set -scr_parms parameters. + fixscreen:str set -fixscreen to "str". + noxrecord disable all use of RECORD extension. + xrecord enable use of RECORD extension. + reset_record reset RECORD extension (if avail.) + pointer_mode:n set -pointer_mode to n. same as "pm" + input_skip:n set -input_skip to n. + allinput enable use of -allinput mode. + noallinput disable use of -allinput mode. + input_eagerly enable use of -input_eagerly mode. + noinput_eagerly disable use of -input_eagerly mode. + ssltimeout:n set -ssltimeout to n. + speeds:str set -speeds to str. + wmdt:str set -wmdt to str. + debug_pointer enable -debug_pointer, same as "dp" + nodebug_pointer disable -debug_pointer, same as "nodp" + debug_keyboard enable -debug_keyboard, same as "dk" + nodebug_keyboard disable -debug_keyboard, same as "nodk" + keycode:n inject keystroke 'keycode' (xmodmap -pk) + keycode:n,down inject 'keycode' (down=0,1) + keysym:str inject keystroke 'keysym' (number/name) + keysym:str,down inject 'keysym' (down=0,1) + ptr:x,y,mask inject pointer event x, y, button-mask + fakebuttonevent:button,down direct XTestFakeButtonEvent. + sleep:t sleep floating point time t. + get_xprop:p get X property named 'p'. + set_xprop:p:val set X property named 'p' to 'val'. + p -> id=NNN:p for hex/dec window id. + wininfo:id get info about X window id. use 'root' + for root window, use +id for children. + grab_state get state of pointer and keyboard grab. + pointer_pos print XQueryPointer x,y cursor position. + pointer_x print XQueryPointer x cursor position. + pointer_y print XQueryPointer y cursor position. + pointer_same print XQueryPointer ptr on same screen. + pointer_root print XQueryPointer curr ptr rootwin. + pointer_mask print XQueryPointer button and mods mask + mouse_x print x11vnc's idea of cursor position. + mouse_y print x11vnc's idea of cursor position. + noop do nothing. + defer:n set -defer to n ms,same as deferupdate:n + wait:n set -wait to n ms. + extra_fbur:n set -extra_fbur to n. + wait_ui:f set -wait_ui factor to f. + setdefer:n set -setdefer to -2,-1,0,1, or 2. + wait_bog disable -nowait_bog mode. + nowait_bog enable -nowait_bog mode. + slow_fb:f set -slow_fb to f seconds. + xrefresh:f set -xrefresh to f seconds. + readtimeout:n set read timeout to n seconds. + nap enable -nap mode. + nonap disable -nap mode. + sb:n set -sb to n s, same as screen_blank:n + fbpm disable -nofbpm mode. + nofbpm enable -nofbpm mode. + dpms disable -nodpms mode. + nodpms enable -nodpms mode. + forcedpms enable -forcedpms mode. + noforcedpms disable -forcedpms mode. + clientdpms enable -clientdpms mode. + noclientdpms disable -clientdpms mode. + noserverdpms enable -noserverdpms mode. + serverdpms disable -noserverdpms mode. + noultraext enable -noultraext mode. + ultraext disable -noultraext mode. + chatwindow enable local chatwindow mode. + nochatwindow disable local chatwindow mode. + chaton begin chat using local window. + chatoff end chat using local window. + xdamage enable xdamage polling hints. + noxdamage disable xdamage polling hints. + xd_area:A set -xd_area max pixel area to "A" + xd_mem:f set -xd_mem remembrance to "f" + fs:frac set -fs fraction to "frac", e.g. 0.5 + gaps:n set -gaps to n. + grow:n set -grow to n. + fuzz:n set -fuzz to n. + snapfb enable -snapfb mode. + nosnapfb disable -snapfb mode. + rawfb:str set -rawfb mode to "str". + uinput_accel:f set uinput_accel to f. + uinput_thresh:n set uinput_thresh to n. + uinput_reset:n set uinput_reset to n ms. + uinput_always:n set uinput_always to 1/0. + progressive:n set LibVNCServer -progressive slice + height parameter to n. + desktop:str set -desktop name to str for new clients +. + rfbport:n set -rfbport to n. + macnosaver enable -macnosaver mode. + macsaver disable -macnosaver mode. + macnowait enable -macnowait mode. + macwait disable -macnowait mode. + macwheel:n set -macwheel to n. + macnoswap enable -macnoswap mouse button mode. + macswap disable -macnoswap mouse button mode. + macnoresize enable -macnoresize mode. + macresize disable -macnoresize mode. + maciconanim:n set -maciconanim to n. + macmenu enable -macmenu mode. + macnomenu disable -macmenu mode. + macuskbd enable -macuskbd mode. + macnouskbd disable -macuskbd mode. + httpport:n set -httpport to n. + httpdir:dir set -httpdir to dir (and enable http). + enablehttpproxy enable -enablehttpproxy mode. + noenablehttpproxy disable -enablehttpproxy mode. + alwaysshared enable -alwaysshared mode. + noalwaysshared disable -alwaysshared mode. + (may interfere with other options) + nevershared enable -nevershared mode. + nonevershared disable -nevershared mode. + (may interfere with other options) + dontdisconnect enable -dontdisconnect mode. + nodontdisconnect disable -dontdisconnect mode. + (may interfere with other options) + debug_xevents enable debugging X events. + nodebug_xevents disable debugging X events. + debug_xdamage enable debugging X DAMAGE mechanism. + nodebug_xdamage disable debugging X DAMAGE mechanism. + debug_wireframe enable debugging wireframe mechanism. + nodebug_wireframe disable debugging wireframe mechanism. + debug_scroll enable debugging scrollcopy mechanism. + nodebug_scroll disable debugging scrollcopy mechanism. + debug_tiles enable -debug_tiles + nodebug_tiles disable -debug_tiles + debug_grabs enable -debug_grabs + nodebug_grabs disable -debug_grabs + debug_sel enable -debug_sel + nodebug_sel disable -debug_sel + debug_ncache enable -debug_ncache + nodebug_ncache disable -debug_ncache + dbg enable -dbg crash shell + nodbg disable -dbg crash shell + + noremote disable the -remote command processing, + it cannot be turned back on. + + bcx_xattach:str This remote control command is for + use with the BARCO xattach program or the x2x program. + Both of these programs are for 'pointer and keyboard' + sharing between separate X displays. In general the + two displays are usually nearby, e.g. on the same desk, + and this allows the user to share a single pointer and + keyboard between them. The user moves the mouse to + an edge and then the mouse pointer appears to 'jump' + to the other display screen. Thus it emulates what a + single X server would do for two screens (e.g. :0.0 and + :0.1) The illusion of a single Xserver with multiple + screens is achieved by forwarding events to the 2nd + one via the XTEST extension. + + What the x11vnc bcx_xattach command does is to perform + some pointer movements to try to INDUCE xattach/x2x + to 'jump' to the other display. In what follows the + 'master' display refers to the one that when it has + 'focus' it is basically doing nothing besides watching + for the mouse to go over an edge. The 'slave' + display refers to the one to which the mouse and + keyboard is redirected to once an edge in the master + has been crossed. Note that the x11vnc executing the + bcx_xattach command MUST be the one connected to the + *master* display. + + Also note that when input is being redirected (via + XTEST) from the master display to the slave display, + the master display's pointer and keyboard are *grabbed* + by xattach/x2x. x11vnc can use this info to verify that + the master/slave mode change has taken place correctly. + If you specify the "ifneeded" option (see below) + and the initial grab state is that of the desired + final state, then no pointer movements are injected + and "DONE,GRAB_OK" is returned. + + "str" must contain one of "up", "down", "left", + or "right" to indicate the direction of the 'jump'. + "str" must also contain one of "master_to_slave" + or "slave_to_master" to indicate the type of mode + change induced by the jump. Use "M2S" and "S2M" + as shorter aliases. + + "str" may be a "+" separated list of additional + tuning options. The "shift=n" option indicates an + offset shift position away from (0,0) (default 20). + "final=x+y" specifies the final position of the cursor + at the end of the normal move sequence; default 30+30. + "extra_move=x+y" means to do one more pointer move + after "final" to x+y. "dt=n" sets the sleep time + in milliseconds between pointer moves (default: 40ms) + "retry=n" specifies the maximum number of retries if + the grab state change fails. "ifneeded" means to not + apply the pointer movements if the initial grab state is + that of the desired final state. "nograbcheck" means + to not check if the grab state changed as expected and + only apply the pointer movements (default is to check + the grab states.) + + If you do not specify "up", etc., to bcx_xattach + nothing will be attempted and the command returns + the string FAIL,NO_DIRECTION_SPECIFIED. If you do + not specify "master_to_slave" or "M2S", etc., to + bcx_xattach nothing will be attempted and the command + returns the string FAIL,NO_MODE_CHANGE_SPECIFIED. + + Otherwise, the returned string will contain "DONE". + It will be "DONE,GRAB_OK" if the grab state changed + as expected (or if "ifneeded" was supplied and + the initial grab state was already the desired + one.) If the initial grab state was incorrect, + but the final grab state was correct then it is + "DONE,GRAB_FAIL_INIT". If the initial grab state + was correct, but the final grab state was incorrect + then it is "DONE,GRAB_FAIL_FINAL". If both are + incorrect it will be "DONE,GRAB_FAIL". Under grab + failure the string will be followed by ":p1,k1-p2,k2" + where p1,k1 indicates the initial pointer and keyboard + grab states and p2,k2 the final ones. If GRAB_FAIL or + GRAB_FAIL_FINAL occurs, the action will be retried up + to 3 times; trying to reset the state and sleeping a + bit between each try. Set retry=n to adjust the number + of retries, zero to disable retries. + + Examples: + -R bcx_xattach:down+M2S + -R bcx_xattach:up+S2M + -R bcx_xattach:up+S2M+nograbcheck+dt=30 + -R bcx_xattach:down+M2S+extra_move=100+100 + + or use -Q instead of -R to retrieve the result text. + + End of the bcx_xattach:str description. + + The vncconnect(1) command from standard VNC + distributions may also be used if string is prefixed + with "cmd=" E.g. 'vncconnect cmd=stop'. Under some + circumstances xprop(1) can used if it supports -set + (see the FAQ). + + If "-connect /path/to/file" has been supplied to the + running x11vnc server then that file can be used as a + communication channel (this is the only way to remote + control one of many x11vnc's polling the same X display) + Simply run: 'x11vnc -connect /path/to/file -remote ...' + or you can directly write to the file via something + like: "echo cmd=stop > /path/to/file", etc. + +-query variable Like -remote, except just query the value of + "variable". "-Q" is an alias for "-query". + Multiple queries can be done by separating variables + by commas, e.g. -query var1,var2. The results come + back in the form ans=var1:value1,ans=var2:value2,... + to the standard output. If a variable is read-only, + it comes back with prefix "aro=" instead of "ans=". + + Some -remote commands are pure actions that do not make + sense as variables, e.g. "stop" or "disconnect", in + these cases the value returned is "N/A". To direct a + query straight to the X11VNC_REMOTE property or connect + file use "qry=..." instead of "cmd=..." + + ans= stop quit exit shutdown ping resend_cutbuffer + resend_clipboard resend_primary blacken zero refresh + reset close disconnect id_cmd id sid waitmapped + nowaitmapped clip flashcmap noflashcmap shiftcmap + truecolor notruecolor overlay nooverlay overlay_cursor + overlay_yescursor nooverlay_nocursor nooverlay_cursor + nooverlay_yescursor overlay_nocursor 8to24 no8to24 + 8to24_opts 24to32 no24to32 visual scale scale_cursor + viewonly noviewonly shared noshared forever noforever + once timeout tightfilexfer notightfilexfer ultrafilexfer + noultrafilexfer rfbversion deny lock nodeny unlock avahi + mdns zeroconf noavahi nomdns nozeroconf connect proxy + allowonce allow noipv6 ipv6 noipv4 ipv4 no6 6 localhost + nolocalhost listen lookup nolookup accept afteraccept + gone shm noshm flipbyteorder noflipbyteorder onetile + noonetile solid_color solid nosolid blackout xinerama + noxinerama xtrap noxtrap xrandr noxrandr xrandr_mode + rotate padgeom quiet q noquiet modtweak nomodtweak xkb + noxkb capslock nocapslock skip_lockkeys noskip_lockkeys + skip_keycodes sloppy_keys nosloppy_keys skip_dups + noskip_dups add_keysyms noadd_keysyms clear_mods + noclear_mods clear_keys noclear_keys clear_all + clear_locks keystate remap repeat norepeat fb nofb bell + nobell sendbell sel nosel primary noprimary setprimary + nosetprimary clipboard noclipboard setclipboard + nosetclipboard seldir cursorshape nocursorshape + cursorpos nocursorpos cursor_drag nocursor_drag cursor + show_cursor noshow_cursor nocursor arrow xfixes + noxfixes xdamage noxdamage xd_area xd_mem alphacut + alphafrac alpharemove noalpharemove alphablend + noalphablend xwarppointer xwarp noxwarppointer + noxwarp buttonmap dragging nodragging ncache_cr + noncache_cr ncache_no_moveraise noncache_no_moveraise + ncache_no_dtchange noncache_no_dtchange + ncache_no_rootpixmap noncache_no_rootpixmap + ncache_reset_rootpixmap ncrp ncache_keep_anims + noncache_keep_anims ncache_old_wm noncache_old_wm + ncache_pad ncache noncache ncache_size debug_ncache + nodebug_ncache wireframe_mode wireframe wf nowireframe + nowf wireframelocal wfl nowireframelocal nowfl + wirecopyrect wcr nowirecopyrect nowcr scr_area + scr_skip scr_inc scr_keys scr_term scr_keyrepeat + scr_parms scrollcopyrect scr noscrollcopyrect + noscr fixscreen noxrecord xrecord reset_record + pointer_mode pm input_skip allinput noallinput + input_eagerly noinput_eagerly input grabkbd nograbkbd + grabptr nograbptr grabalways nograbalways grablocal + client_input ssltimeout speeds wmdt debug_pointer dp + nodebug_pointer nodp debug_keyboard dk nodebug_keyboard + nodk keycode keysym ptr fakebuttonevent sleep get_xprop + set_xprop wininfo bcx_xattach deferupdate defer + setdefer extra_fbur wait_ui wait_bog nowait_bog + slow_fb xrefresh wait readtimeout nap nonap sb + screen_blank fbpm nofbpm dpms nodpms clientdpms + noclientdpms forcedpms noforcedpms noserverdpms + serverdpms noultraext ultraext chatwindow nochatwindow + chaton chatoff fs gaps grow fuzz snapfb nosnapfb + rawfb uinput_accel uinput_thresh uinput_reset + uinput_always progressive rfbport http nohttp httpport + httpdir enablehttpproxy noenablehttpproxy alwaysshared + noalwaysshared nevershared noalwaysshared dontdisconnect + nodontdisconnect desktop debug_xevents nodebug_xevents + debug_xevents debug_xdamage nodebug_xdamage + debug_xdamage debug_wireframe nodebug_wireframe + debug_wireframe debug_scroll nodebug_scroll debug_scroll + debug_tiles dbt nodebug_tiles nodbt debug_tiles + debug_grabs nodebug_grabs debug_sel nodebug_sel dbg + nodbg macnosaver macsaver nomacnosaver macnowait macwait + nomacnowait macwheel macnoswap macswap nomacnoswap + macnoresize macresize nomacnoresize maciconanim macmenu + macnomenu nomacmenu macuskbd nomacuskbd noremote + + aro= noop display vncdisplay icon_mode autoport + loop loopbg desktopname guess_desktop guess_dbus + http_url auth xauth users rootshift clipshift scale_str + scaled_x scaled_y scale_numer scale_denom scale_fac_x + scale_fac_y scaling_blend scaling_nomult4 scaling_pad + scaling_interpolate inetd privremote unsafe safer nocmds + passwdfile unixpw unixpw_nis unixpw_list ssl ssl_pem + sslverify stunnel stunnel_pem https httpsredir usepw + using_shm logfile o flag rmflag rc norc h help V version + lastmod bg sigpipe threads readrate netrate netlatency + pipeinput clients client_count pid ext_xtest ext_xtrap + ext_xrecord ext_xkb ext_xshm ext_xinerama ext_overlay + ext_xfixes ext_xdamage ext_xrandr rootwin num_buttons + button_mask mouse_x mouse_y grab_state pointer_pos + pointer_x pointer_y pointer_same pointer_root + pointer_mask bpp depth indexed_color dpy_x dpy_y wdpy_x + wdpy_y off_x off_y cdpy_x cdpy_y coff_x coff_y rfbauth + passwd viewpasswd + +-QD variable Just like -query variable, but returns the default + value for that parameter (no running x11vnc server + is consulted) + +-sync By default -remote commands are run asynchronously, that + is, the request is posted and the program immediately + exits. Use -sync to have the program wait for an + acknowledgement from the x11vnc server that command was + processed (somehow). On the other hand -query requests + are always processed synchronously because they have + to wait for the answer. + + Also note that if both -remote and -query requests are + supplied on the command line, the -remote is processed + first (synchronously: no need for -sync), and then + the -query request is processed in the normal way. + This allows for a reliable way to see if the -remote + command was processed by querying for any new settings. + Note however that there is timeout of a few seconds + (see the next paragraph) so if the x11vnc takes longer + than that to process the requests the requester will + think that a failure has taken place. + + The default is to wait 3.5 seconds. Or if cmd=stop + only 1.0 seconds. If cmd matches 'script:' then it + will wait up to 10.0 seconds. Set X11VNC_SYNC_TIMEOUT + to the number of seconds you want it to wait. + +-query_retries str If a query fails to get a response from an x11vnc + server, retry up to n times. "str" is specified as + n[:t][/match] Optionally the delay between tries may + be specified by "t" a floating point time (default + 0.5 seconds.) Note: the response is not checked for + validity or whether it corresponds to the query sent. + The query "ping:mystring" may be used to help uniquely + identify the query. Optionally, a matching string after + a "/" will be used to check the result text. Up to + n retries will take place until the matching string is + found in the output text. If the match string is never + found the program's exit code is 1; if the match is + found it exits with 0. Note that there may be stdout + printed for each retry (i.e. multiple lines printed + out to stdout.) + Example: -query_retries 4:1.5/grab_state + +-remote_prefix str Enable a remote-control communication channel for + connected VNC clients. str is a non-empty string. If a + VNC client sends rfbCutText having the prefix "str" + then the part after it is processed as though it were + sent via 'x11vnc -remote ...'. If it begins with + neither 'cmd=' nor 'qry=' then 'qry=' is assumed. + Any corresponding output text for that remote control + command is sent back to all client as rfbCutText. + The returned output is also prefixed with "str". + Example: -remote_prefix DO_THIS: + + Note that enabling -remote_prefix allows the remote + VNC viewers to run x11vnc -remote commands. Do not + use this option if they are not to be trusted. + +-noremote Do not process any remote control commands or queries. +-yesremote Do process remote control commands or queries. + Default: -yesremote + + A note about security wrt remote control commands. + If someone can connect to the X display and change + the property X11VNC_REMOTE, then they can remotely + control x11vnc. Normally access to the X display is + protected. Note that if they can modify X11VNC_REMOTE + on the X server, they have enough permissions to also + run their own x11vnc and thus have complete control + of the desktop. If the "-connect /path/to/file" + channel is being used, obviously anyone who can write + to /path/to/file can remotely control x11vnc. So be + sure to protect the X display and that file's write + permissions. See -privremote below. + + If you are paranoid and do not think -noremote is + enough, to disable the X11VNC_REMOTE property channel + completely use -novncconnect, or use the -safer option + that shuts many things off. + +-unsafe A few remote commands are disabled by default + (currently: id:pick, accept:, gone:, and + rawfb:setup:) because they are associated with + running external programs. If you specify -unsafe, then + these remote-control commands are allowed. Note that + you can still specify these parameters on the command + line, they just cannot be invoked via remote-control. +-safer Equivalent to: -novncconnect -noremote and prohibiting + -gui and the -connect file. Shuts off communcation + channels. +-privremote Perform some sanity checks and disable remote-control + commands if it appears that the X DISPLAY and/or + connectfile can be accessed by other users. Once + remote-control is disabled it cannot be turned back on. +-nocmds No external commands (e.g. system(3), popen(3), exec(3)) + will be run at all. +-allowedcmds list "list" contains a comma separated list of the only + external commands that can be run. The full list of + associated options is: + + stunnel, ssl, unixpw, WAIT, zeroconf, id, accept, + afteraccept, gone, pipeinput, v4l-info, rawfb-setup, + dt, gui, ssh, storepasswd, passwdfile, custom_passwd, + findauth, crash. + + See each option's help to learn the associated external + command. Note that the -nocmds option takes precedence + and disables all external commands. + +-deny_all For use with -remote nodeny: start out denying all + incoming clients until "-remote nodeny" is used to + let them in. + + + +These options are passed to LibVNCServer: + +-rfbport port TCP port for RFB protocol +-rfbwait time max time in ms to wait for RFB client +-rfbauth passwd-file use authentication on RFB protocol + (use 'storepasswd' to create a password file) +-rfbversion 3.x Set the version of the RFB we choose to advertise +-permitfiletransfer permit file transfer support +-passwd plain-password use authentication + (use plain-password as password, USE AT YOUR RISK) +-deferupdate time time in ms to defer updates (default 40) +-deferptrupdate time time in ms to defer pointer updates (default none) +-desktop name VNC desktop name (default "LibVNCServer") +-alwaysshared always treat new clients as shared +-nevershared never treat new clients as shared +-dontdisconnect don't disconnect existing clients when a new non-shared + connection comes in (refuse new connection instead) +-httpdir dir-path enable http server using dir-path home +-httpport portnum use portnum for http connection +-enablehttpproxy enable http proxy support +-progressive height enable progressive updating for slow links +-listen ipaddr listen for connections only on network interface with + addr ipaddr. '-listen localhost' and hostname work too. + +libvncserver-tight-extension options: +-disablefiletransfer disable file transfer +-ftproot string set ftp root + + Pretty wild huh? Contact me if you have any questions or problems. + + Personally, I use: +x11vnc -rfbauth $HOME/.vnc/passwd -solid diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h new file mode 100755 index 0000000..99e814e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/allowed_input_t.h @@ -0,0 +1,46 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_ALLOWED_INPUT_T_H +#define _X11VNC_ALLOWED_INPUT_T_H + +/* -- allowed_input_t.h -- */ + +typedef struct allowed_input { + int keystroke; + int motion; + int button; + int clipboard; + int files; +} allowed_input_t; + +#endif /* _X11VNC_ALLOWED_INPUT_T_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c new file mode 100755 index 0000000..fc3c29e --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/appshare.c @@ -0,0 +1,2124 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- appshare.c -- */ + +#include "x11vnc.h" + +extern int pick_windowid(unsigned long *num); +extern char *get_xprop(char *prop, Window win); +extern int set_xprop(char *prop, Window win, char *value); +extern void set_env(char *name, char *value); +extern double dnow(void); + +static char *usage = +"\n" +" x11vnc -appshare: an experiment in application sharing via x11vnc.\n" +"\n" +#if !SMALL_FOOTPRINT +" Usage: x11vnc -appshare -id windowid -connect viewer_host:0\n" +" x11vnc -appshare -id pick -connect viewer_host:0\n" +"\n" +" Both the -connect option and the -id (or -sid) option are required.\n" +" (However see the -control option below that can replace -connect.)\n" +"\n" +" The VNC viewer at viewer_host MUST be in 'listen' mode. This is because\n" +" a new VNC connection (and viewer window) is established for each new\n" +" toplevel window that the application creates. For example:\n" +"\n" +" vncviewer -listen 0\n" +"\n" +" The '-connect viewer_host:0' indicates the listening viewer to connect to.\n" +"\n" +" No password should be used, otherwise it will need to be typed for each\n" +" new window (or one could use vncviewer -passwd file if the viewer supports\n" +" that.) For security an SSH tunnel can be used:\n" +"\n" +" ssh -R 5500:localhost:5500 user@server_host\n" +"\n" +" (then use -connect localhost:0)\n" +"\n" +" The -id/-sid option is as in x11vnc(1). It is either a numerical window\n" +" id or the string 'pick' which will ask the user to click on an app window.\n" +" To track more than one application at the same time, list their window ids\n" +" separated by commas (see also the 'add_app' command below.)\n" +"\n" +" Additional options:\n" +"\n" +" -h, -help Print this help.\n" +" -debug Print debugging output (same as X11VNC_APPSHARE_DEBUG=1)\n" +" -showmenus Create a new viewer window even if a new window is\n" +" completely inside of an existing one. Default is to\n" +" try to not show them in a new viewer window.\n" +" -noexit Do not exit if the main app (windowid/pick) window\n" +" goes away. Default is to exit.\n" +" -display dpy X DISPLAY to use.\n" +" -trackdir dir Set tracking directory to 'dir'. x11vnc -appshare does\n" +" better if it can communicate with the x11vnc's via a\n" +" file channel. By default a dir in /tmp is used, -trackdir\n" +" specifies another directory, or use 'none' to disable.\n" +" -args 'string' Pass options 'string' to x11vnc (e.g. -scale 3/4,\n" +" -viewonly, -wait, -once, etc.)\n" +" -env VAR=VAL Set environment variables on cmdline as in x11vnc.\n" +"\n" +" -control file This is a file that one edits to manage the appshare\n" +" mode. It replaces -connect. Lines beginning with '#'\n" +" are ignored. Initially start off with all of the\n" +" desired clients in the file, one per line. If you add\n" +" a new client-line, that client is connected to. If you\n" +" delete (or comment out) a client-line, that client is\n" +" disconnected (for this to work, do not disable trackdir.)\n" +"\n" +" You can also put cmd= lines in the control file to perform\n" +" different actions. These are supported:\n" +"\n" +" cmd=quit Disconnect all clients and exit.\n" +" cmd=restart Restart all of the x11vnc's.\n" +" cmd=noop Do nothing (e.g. ping)\n" +" cmd=x11vnc Run ps(1) looking for x11vnc's\n" +" cmd=help Print out help text.\n" +" cmd=add_window:win Add a window to be watched.\n" +" cmd=del_window:win Delete a window.\n" +" cmd=add_app:win Add an application to be watched.\n" +" cmd=del_app:win Delete an application.\n" +" cmd=add_client:host Add client ('internal' mode only)\n" +" cmd=del_client:host Del client ('internal' mode only)\n" +" cmd=list_windows List all tracked windows.\n" +" cmd=list_apps List all tracked applications.\n" +" cmd=list_clients List all connected clients.\n" +" cmd=list_all List all three.\n" +" cmd=print_logs Print out the x11vnc logfiles.\n" +" cmd=debug:n Set -debug to n (0 or 1).\n" +" cmd=showmenus:n Set -showmenus to n (0 or 1).\n" +" cmd=noexit:n Set -noexit to n (0 or 1).\n" +"\n" +" See the '-command internal' mode described below for a way\n" +" that tracks connected clients internally (not in a file.)\n" +"\n" +" In '-shell' mode (see below) you can type in the above\n" +" without the leading 'cmd='.\n" +"\n" +" For 'add_window' and 'del_window' the 'win' can be a\n" +" numerical window id or 'pick'. Same for 'add_app'. Be\n" +" sure to remove or comment out the add/del line quickly\n" +" (e.g. before picking) or it will be re-run the next time\n" +" the file is processed.\n" +"\n" +" If a file with the same name as the control file but\n" +" ending with suffix '.cmd' is found, then commands in it\n" +" (cmd=...) are processed and then the file is truncated.\n" +" This allows 'one time' command actions to be run. Any\n" +" client hostnames in the '.cmd' file are ignored. Also\n" +" see below for the X11VNC_APPSHARE_COMMAND X property\n" +" which is similar to '.cmd'\n" +"\n" +" -control internal Manage connected clients internally, see below.\n" +" -control shell Same as: -shell -control internal\n" +"\n" +" -delay secs Maximum timeout delay before re-checking the control file.\n" +" It can be a fraction, e.g. -delay 0.25 Default 0.5\n" +"\n" +" -shell Simple command line for '-control internal' mode (see the\n" +" details of this mode below.) Enter '?' for command list.\n" +"\n" +" To stop x11vnc -appshare press Ctrl-C, or (if -noexit not supplied) delete\n" +" the initial app window or exit the application. Or cmd=quit in -control mode.\n" +"\n" +#if 0 +" If you want your setup to survive periods of time where there are no clients\n" +" connected you will need to supply -args '-forever' otherwise the x11vnc's\n" +" will exit when the last client disconnects. Howerver, _starting_ with no\n" +" clients (e.g. empty control file) will work without -args '-forever'.\n" +"\n" +#endif +" In addition to the '.cmd' file channel, for faster response you can set\n" +" X11VNC_APPSHARE_COMMAND X property on the root window to the string that\n" +" would go into the '.cmd' file. For example:\n" +"\n" +" xprop -root -f X11VNC_APPSHARE_COMMAND 8s -set X11VNC_APPSHARE_COMMAND cmd=quit\n" +"\n" +" The property value will be set to 'DONE' after the command(s) is processed.\n" +"\n" +" If -control file is specified as 'internal' then no control file is used\n" +" and client tracking is done internally. You must add and delete clients\n" +" with the cmd=add_client: and cmd=del_client: commands.\n" +" Note that '-control internal' is required for '-shell' mode. Using\n" +" '-control shell' implies internal mode and -shell.\n" +"\n" +" Limitations:\n" +"\n" +" This is a quick lash-up, many things will not work properly.\n" +"\n" +" The main idea is to provide simple application sharing for two or more\n" +" parties to collaborate without needing to share the entire desktop. It\n" +" provides an improvement over -id/-sid that only shows a single window.\n" +"\n" +" Only reverse connections can be done. (Note: one can specify multiple\n" +" viewing hosts via: -connect host1,host2,host3 or add/remove them\n" +" dynamically as described above.)\n" +"\n" +" If a new window obscures an old one, you will see some or all of the\n" +" new window in the old one. The hope is this is a popup dialog or menu\n" +" that will go away soon. Otherwise a user at the physical display will\n" +" need to move it. (See also the SSVNC viewer features described below.) \n" +"\n" +" The viewer side cannot resize or make windows move on the physical\n" +" display. Again, a user at the physical display may need to help, or\n" +" use the SSVNC viewer (see Tip below.)\n" +"\n" +" Tip: If the application has its own 'resize corner', then dragging\n" +" it may successfully resize the application window.\n" +" Tip: Some desktop environments enable moving a window via, say,\n" +" Alt+Left-Button-Drag. One may be able to move a window this way.\n" +" Also, e.g., Alt+Right-Button-Drag may resize a window.\n" +" Tip: Clicking on part of an obscured window may raise it to the top.\n" +" Also, e.g., Alt+Middle-Button may toggle Raise/Lower.\n" +"\n" +" Tip: The SSVNC 1.0.25 unix and macosx vncviewer has 'EscapeKeys' hot\n" +" keys that will move, resize, raise, and lower the window via the\n" +" x11vnc -remote_prefix X11VNC_APPSHARE_CMD: feature. So in the\n" +" viewer while holding down Shift_L+Super_L+Alt_L the arrow keys\n" +" move the window, PageUp/PageDn/Home/End resize it, and - and +\n" +" raise and lower it. Key 'M' or Button1 moves the remote window\n" +" to the +X+Y of the viewer window. Key 'D' or Button3 deletes\n" +" the remote window.\n" +"\n" +" You can run the SSVNC vncviewer with options '-escape default',\n" +" '-multilisten' and '-env VNCVIEWER_MIN_TITLE=1'; or just run\n" +" with option '-appshare' to enable these and automatic placement.\n" +"\n" +" If any part of a window goes off of the display screen, then x11vnc\n" +" may be unable to poll it (without crashing), and so the window will\n" +" stop updating until the window is completely on-screen again.\n" +"\n" +" The (stock) vnc viewer does not know where to best position each new\n" +" viewer window; it likely centers each one (including when resized.)\n" +" Note: The SSVNC viewer in '-appshare' mode places them correctly.\n" +"\n" +" Deleting a viewer window does not delete the real window.\n" +" Note: The SSVNC viewer Shift+EscapeKeys+Button3 deletes it.\n" +"\n" +" Sometimes new window detection fails.\n" +"\n" +" Sometimes menu/popup detection fails.\n" +"\n" +" Sometimes the contents of a menu/popup window have blacked-out regions.\n" +" Try -sid or -showmenus as a workaround.\n" +"\n" +" If the application starts up a new application (a different process)\n" +" that new application will not be tracked (but, unfortunately, it may\n" +" cover up existing windows that are being tracked.) See cmd=add_window\n" +" and cmd=add_app described above.\n" +"\n" +#endif +; + +#include +#include +#include + +#define WMAX 192 +#define CMAX 128 +#define AMAX 32 + +static Window root = None; +static Window watch[WMAX]; +static Window apps[WMAX]; +static int state[WMAX]; +static char *clients[CMAX]; +static XWindowAttributes attr; +static char *ticker_atom_str = "X11VNC_APPSHARE_TICKER"; +static Atom ticker_atom = None; +static char *cmd_atom_str = "X11VNC_APPSHARE_COMMAND"; +static Atom cmd_atom = None; +static char *connect_to = NULL; +static char *x11vnc_args = ""; +static char *id_opt = "-id"; +static int skip_menus = 1; +static int exit_no_app_win = 1; +static int shell = 0; +static int tree_depth = 3; +static char *prompt = "appshare> "; +static char *x11vnc = "x11vnc"; +static char *control = NULL; +static char *trackdir = "unset"; +static char *trackpre = "/tmp/x11vnc-appshare-trackdir-tmp"; +static char *tracktmp = NULL; +static char unique_tag[100]; +static int use_forever = 1; +static int last_event_type = 0; +static pid_t helper_pid = 0; +static pid_t parent_pid = 0; +static double helper_delay = 0.5; +static int appshare_debug = 0; +static double start_time = 0.0; + +static void get_wm_name(Window win, char **name); +static int win_attr(Window win); +static int get_xy(Window win, int *x, int *y); +static Window check_inside(Window win); +static int ours(Window win); +static void destroy_win(Window win); +static int same_app(Window win, Window app); + +static void ff(void) { + fflush(stdout); + fflush(stderr); +} + +static int find_win(Window win) { + int i; + for (i=0; i < WMAX; i++) { + if (watch[i] == win) { + return i; + } + } + return -1; +} + +static int find_app(Window app) { + int i; + for (i=0; i < AMAX; i++) { + if (apps[i] == app) { + return i; + } + } + return -1; +} + +static int find_client(char *cl) { + int i; + for (i=0; i < CMAX; i++) { + if (cl == NULL) { + if (clients[i] == NULL) { + return i; + } + continue; + } + if (clients[i] == NULL) { + continue; + } + if (!strcmp(clients[i], cl)) { + return i; + } + } + return -1; +} + +static int trackdir_pid(Window win) { + FILE *f; + int ln = 0, pid = 0; + char line[1024]; + + if (!trackdir) { + return 0; + } + sprintf(tracktmp, "%s/0x%lx.log", trackdir, win); + f = fopen(tracktmp, "r"); + if (!f) { + return 0; + } + while (fgets(line, sizeof(line), f) != NULL) { + if (ln++ > 30) { + break; + } + if (strstr(line, "x11vnc version:")) { + char *q = strstr(line, "pid:"); + if (q) { + int p; + if (sscanf(q, "pid: %d", &p) == 1) { + if (p > 0) { + pid = p; + break; + } + } + } + } + } + fclose(f); + return pid; +} + +static void trackdir_cleanup(Window win) { + char *suffix[] = {"log", "connect", NULL}; + int i=0; + if (!trackdir) { + return; + } + while (suffix[i] != NULL) { + sprintf(tracktmp, "%s/0x%lx.%s", trackdir, win, suffix[i]); + if (appshare_debug && !strcmp(suffix[i], "log")) { + fprintf(stderr, "keeping: %s\n", tracktmp); + ff(); + } else { + if (appshare_debug) { + fprintf(stderr, "removing: %s\n", tracktmp); + ff(); + } + unlink(tracktmp); + } + i++; + } +} + +static void launch(Window win) { + char *cmd, *tmp, *connto, *name; + int len, timeo = 30, uf = use_forever; + int w = 0, h = 0, x = 0, y = 0; + + if (win_attr(win)) { + /* maybe switch to debug only. */ + w = attr.width; + h = attr.height; + get_xy(win, &x, &y); + } + + get_wm_name(win, &name); + + if (strstr(x11vnc_args, "-once")) { + uf = 0; + } + + if (control) { + int i = 0; + len = 0; + for (i=0; i < CMAX; i++) { + if (clients[i] != NULL) { + len += strlen(clients[i]) + 2; + } + } + connto = (char *) calloc(len, 1); + for (i=0; i < CMAX; i++) { + if (clients[i] != NULL) { + if (connto[0] != '\0') { + strcat(connto, ","); + } + strcat(connto, clients[i]); + } + } + } else { + connto = strdup(connect_to); + } + if (!strcmp(connto, "")) { + timeo = 0; + } + if (uf) { + timeo = 0; + } + + len = 1000 + strlen(x11vnc) + strlen(connto) + strlen(x11vnc_args) + + 3 * (trackdir ? strlen(trackdir) : 100); + + cmd = (char *) calloc(len, 1); + tmp = (char *) calloc(len, 1); + + sprintf(cmd, "%s %s 0x%lx -bg -quiet %s -nopw -rfbport 0 " + "-timeout %d -noxdamage -noxinerama -norc -repeat -speeds dsl " + "-env X11VNC_AVOID_WINDOWS=never -env X11VNC_APPSHARE_ACTIVE=1 " + "-env X11VNC_NO_CHECK_PM=1 -env %s -novncconnect -shared -nonap " + "-remote_prefix X11VNC_APPSHARE_CMD:", + x11vnc, id_opt, win, use_forever ? "-forever" : "-once", timeo, unique_tag); + + if (trackdir) { + FILE *f; + sprintf(tracktmp, " -noquiet -o %s/0x%lx.log", trackdir, win); + strcat(cmd, tracktmp); + sprintf(tracktmp, "%s/0x%lx.connect", trackdir, win); + f = fopen(tracktmp, "w"); + if (f) { + fprintf(f, "%s", connto); + fclose(f); + sprintf(tmp, " -connect_or_exit '%s'", tracktmp); + strcat(cmd, tmp); + } else { + sprintf(tmp, " -connect_or_exit '%s'", connto); + strcat(cmd, tmp); + } + } else { + if (!strcmp(connto, "")) { + sprintf(tmp, " -connect '%s'", connto); + } else { + sprintf(tmp, " -connect_or_exit '%s'", connto); + } + strcat(cmd, tmp); + } + if (uf) { + char *q = strstr(cmd, "-connect_or_exit"); + if (q) q = strstr(q, "_or_exit"); + if (q) { + unsigned int i; + for (i=0; i < strlen("_or_exit"); i++) { + *q = ' '; + q++; + } + } + } + + strcat(cmd, " "); + strcat(cmd, x11vnc_args); + + fprintf(stdout, "launching: x11vnc for window 0x%08lx %dx%d+%d+%d \"%s\"\n", + win, w, h, x, y, name); + + if (appshare_debug) { + fprintf(stderr, "\nrunning: %s\n\n", cmd); + } + ff(); + + system(cmd); + + free(cmd); + free(tmp); + free(connto); + free(name); +} + +static void stop(Window win) { + char *cmd; + int pid = -1; + int f = find_win(win); + if (f < 0 || win == None) { + return; + } + if (state[f] == 0) { + return; + } + if (trackdir) { + pid = trackdir_pid(win); + if (pid > 0) { + if (appshare_debug) {fprintf(stderr, + "sending SIGTERM to: %d\n", pid); ff();} + kill((pid_t) pid, SIGTERM); + } + } + + cmd = (char *) malloc(1000 + strlen(x11vnc)); + sprintf(cmd, "pkill -TERM -f '%s %s 0x%lx -bg'", x11vnc, id_opt, win); + if (appshare_debug) { + fprintf(stdout, "stopping: 0x%08lx - %s\n", win, cmd); + } else { + fprintf(stdout, "stopping: x11vnc for window 0x%08lx " + "(pid: %d)\n", win, pid); + } + ff(); + system(cmd); + + sprintf(cmd, "(sleep 0.25 2>/dev/null || sleep 1; pkill -KILL -f '%s " + "%s 0x%lx -bg') &", x11vnc, id_opt, win); + system(cmd); + + if (trackdir) { + trackdir_cleanup(win); + } + + free(cmd); +} + +static void kill_helper_pid(void) { + int status; + if (helper_pid <= 0) { + return; + } + fprintf(stderr, "stopping: helper_pid: %d\n", (int) helper_pid); + kill(helper_pid, SIGTERM); + usleep(50 * 1000); + kill(helper_pid, SIGKILL); + usleep(25 * 1000); +#if LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_WAITPID + waitpid(helper_pid, &status, WNOHANG); +#endif +} + +static void be_helper_pid(char *dpy_str) { + int cnt = 0; + int ms = (int) (1000 * helper_delay); + double last_check = 0.0; + + if (ms < 50) ms = 50; + +#if NO_X11 + fprintf(stderr, "be_helper_pid: not compiled with X11.\n"); +#else + dpy = XOpenDisplay(dpy_str); + ticker_atom = XInternAtom(dpy, ticker_atom_str, False); + + while (1) { + char tmp[32]; + sprintf(tmp, "HELPER_CNT_%08d", cnt++); + XChangeProperty(dpy, DefaultRootWindow(dpy), ticker_atom, XA_STRING, 8, + PropModeReplace, (unsigned char *) tmp, strlen(tmp)); + XFlush(dpy); + usleep(ms*1000); + if (parent_pid > 0) { + if(dnow() > last_check + 1.0) { + last_check = dnow(); + if (kill(parent_pid, 0) != 0) { + fprintf(stderr, "be_helper_pid: parent %d is gone.\n", (int) parent_pid); + break; + } + } + } + } +#endif + exit(0); +} + +static void print_logs(void) { + if (trackdir) { + DIR *dir = opendir(trackdir); + if (dir) { + struct dirent *dp; + while ( (dp = readdir(dir)) != NULL) { + FILE *f; + char *name = dp->d_name; + if (!strcmp(name, ".") || !strcmp(name, "..")) { + continue; + } + if (strstr(name, "0x") != name) { + continue; + } + if (strstr(name, ".log") == NULL) { + continue; + } + sprintf(tracktmp, "%s/%s", trackdir, name); + f = fopen(tracktmp, "r"); + if (f) { + char line[1024]; + fprintf(stderr, "===== x11vnc log %s =====\n", tracktmp); + while (fgets(line, sizeof(line), f) != NULL) { + fprintf(stderr, "%s", line); + } + fprintf(stderr, "\n"); + ff(); + fclose(f); + } + } + closedir(dir); + } + } +} + +static void appshare_cleanup(int s) { + int i; + if (s) {} + + if (use_forever) { + /* launch this backup in case they kill -9 us before we terminate everything */ + char cmd[1000]; + sprintf(cmd, "(sleep 3; pkill -TERM -f '%s') &", unique_tag); + if (appshare_debug) fprintf(stderr, "%s\n", cmd); + system(cmd); + } + + for (i=0; i < WMAX; i++) { + if (watch[i] != None) { + stop(watch[i]); + } + } + + if (trackdir) { + DIR *dir = opendir(trackdir); + if (dir) { + struct dirent *dp; + while ( (dp = readdir(dir)) != NULL) { + char *name = dp->d_name; + if (!strcmp(name, ".") || !strcmp(name, "..")) { + continue; + } + if (strstr(name, "0x") != name) { + fprintf(stderr, "skipping: %s\n", name); + continue; + } + if (!appshare_debug) { + fprintf(stderr, "removing: %s\n", name); + sprintf(tracktmp, "%s/%s", trackdir, name); + unlink(tracktmp); + } else { + if (appshare_debug) fprintf(stderr, "keeping: %s\n", name); + } + } + closedir(dir); + } + if (!appshare_debug) { + if (strstr(trackdir, trackpre) == trackdir) { + if (appshare_debug) fprintf(stderr, "removing: %s\n", trackdir); + rmdir(trackdir); + } + } + ff(); + } + + kill_helper_pid(); + +#if !NO_X11 + XCloseDisplay(dpy); +#endif + fprintf(stdout, "done.\n"); + ff(); + exit(0); +} + +static int trap_xerror(Display *d, XErrorEvent *error) { + if (d || error) {} + return 0; +} + +#if 0 +typedef struct { + int x, y; /* location of window */ + int width, height; /* width and height of window */ + int border_width; /* border width of window */ + int depth; /* depth of window */ + Visual *visual; /* the associated visual structure */ + Window root; /* root of screen containing window */ + int class; /* InputOutput, InputOnly*/ + int bit_gravity; /* one of bit gravity values */ + int win_gravity; /* one of the window gravity values */ + int backing_store; /* NotUseful, WhenMapped, Always */ + unsigned long backing_planes;/* planes to be preserved if possible */ + unsigned long backing_pixel;/* value to be used when restoring planes */ + Bool save_under; /* boolean, should bits under be saved? */ + Colormap colormap; /* color map to be associated with window */ + Bool map_installed; /* boolean, is color map currently installed*/ + int map_state; /* IsUnmapped, IsUnviewable, IsViewable */ + long all_event_masks; /* set of events all people have interest in*/ + long your_event_mask; /* my event mask */ + long do_not_propagate_mask; /* set of events that should not propagate */ + Bool override_redirect; /* boolean value for override-redirect */ + Screen *screen; /* back pointer to correct screen */ +} XWindowAttributes; +#endif + +static void get_wm_name(Window win, char **name) { + int ok; + +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + ok = XFetchName(dpy, win, name); + XSetErrorHandler(old_handler); +#endif + + if (!ok || *name == NULL) { + *name = strdup("unknown"); + } +} + +static int win_attr(Window win) { + int ok = 0; +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + ok = XGetWindowAttributes(dpy, win, &attr); + XSetErrorHandler(old_handler); +#endif + + if (ok) { + return 1; + } else { + return 0; + } +} + +static void win_select(Window win, int ignore) { +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + if (ignore) { + XSelectInput(dpy, win, 0); + } else { + XSelectInput(dpy, win, SubstructureNotifyMask); + } + XSync(dpy, False); + XSetErrorHandler(old_handler); +#endif +} + +static Window get_parent(Window win) { + int ok; + Window r, parent = None, *list = NULL; + unsigned int nchild; + +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + ok = XQueryTree(dpy, win, &r, &parent, &list, &nchild); + XSetErrorHandler(old_handler); + + if (!ok) { + return None; + } + if (list) { + XFree(list); + } +#endif + return parent; +} + +static int get_xy(Window win, int *x, int *y) { + Window cr; + Bool rc = False; +#if !NO_X11 + XErrorHandler old_handler = XSetErrorHandler(trap_xerror); + + rc = XTranslateCoordinates(dpy, win, root, 0, 0, x, y, &cr); + XSetErrorHandler(old_handler); +#endif + + if (!rc) { + return 0; + } else { + return 1; + } +} + +static Window check_inside(Window win) { + int i, nwin = 0; + int w, h, x, y; + int Ws[WMAX], Hs[WMAX], Xs[WMAX], Ys[WMAX]; + Window wins[WMAX]; + + if (!win_attr(win)) { + return None; + } + + /* store them first to give the win app more time to settle. */ + for (i=0; i < WMAX; i++) { + int X, Y; + Window wchk = watch[i]; + if (wchk == None) { + continue; + } + if (state[i] == 0) { + continue; + } + if (!win_attr(wchk)) { + continue; + } + if (!get_xy(wchk, &X, &Y)) { + continue; + } + + Xs[nwin] = X; + Ys[nwin] = Y; + Ws[nwin] = attr.width; + Hs[nwin] = attr.height; + wins[nwin] = wchk; + nwin++; + } + + if (nwin == 0) { + return None; + } + + if (!win_attr(win)) { + return None; + } + w = attr.width; + h = attr.height; + + get_xy(win, &x, &y); + if (!get_xy(win, &x, &y)) { + return None; + } + + for (i=0; i < nwin; i++) { + int X, Y, W, H; + Window wchk = wins[i]; + X = Xs[i]; + Y = Ys[i]; + W = Ws[i]; + H = Hs[i]; + + if (appshare_debug) fprintf(stderr, "check inside: 0x%lx %dx%d+%d+%d %dx%d+%d+%d\n", wchk, w, h, x, y, W, H, X, Y); + + if (X <= x && Y <= y) { + if (x + w <= X + W && y + h < Y + H) { + return wchk; + } + } + } + + return None; +} + +static void add_win(Window win) { + int idx = find_win(win); + int free = find_win(None); + if (idx >= 0) { + if (appshare_debug) {fprintf(stderr, "already watching window: 0x%lx\n", win); ff();} + return; + } + if (free < 0) { + fprintf(stderr, "ran out of slots for window: 0x%lx\n", win); ff(); + return; + } + + if (appshare_debug) {fprintf(stderr, "watching: 0x%lx at %d\n", win, free); ff();} + + watch[free] = win; + state[free] = 0; + + win_select(win, 0); +} + +static void delete_win(Window win) { + int i; + for (i=0; i < WMAX; i++) { + if (watch[i] == win) { + watch[i] = None; + state[i] = 0; + if (appshare_debug) {fprintf(stderr, "deleting: 0x%lx at %d\n", win, i); ff();} + } + } +} + +static void recurse_search(int level, int level_max, Window top, Window app, int *nw) { + Window w, r, parent, *list = NULL; + unsigned int nchild; + int ok = 0; + + if (appshare_debug > 1) { + fprintf(stderr, "level: %d level_max: %d top: 0x%lx app: 0x%lx\n", level, level_max, top, app); + } + if (level >= level_max) { + return; + } + +#if !NO_X11 + ok = XQueryTree(dpy, top, &r, &parent, &list, &nchild); + if (ok) { + int i; + for (i=0; i < (int) nchild; i++) { + w = list[i]; + if (w == None || find_win(w) >= 0) { + continue; + } + if (ours(w) && w != app) { + if (appshare_debug) fprintf(stderr, "add level %d 0x%lx %d/%d\n", + level, w, i, nchild); + add_win(w); + (*nw)++; + } + } + for (i=0; i < (int) nchild; i++) { + w = list[i]; + if (w == None || ours(w)) { + continue; + } + recurse_search(level+1, level_max, w, app, nw); + } + } + if (list) { + XFree(list); + } +#endif +} + +static void add_app(Window app) { + int i, nw = 0, free = -1; + XErrorHandler old_handler; + +#if !NO_X11 + i = find_app(app); + if (i >= 0) { + fprintf(stderr, "already tracking app: 0x%lx\n", app); + return; + } + for (i=0; i < AMAX; i++) { + if (same_app(apps[i], app)) { + fprintf(stderr, "already tracking app: 0x%lx via 0x%lx\n", app, apps[i]); + return; + } + } + free = find_app(None); + if (free < 0) { + fprintf(stderr, "ran out of app slots.\n"); + return; + } + apps[free] = app; + + add_win(app); + + old_handler = XSetErrorHandler(trap_xerror); + recurse_search(0, tree_depth, root, app, &nw); + XSetErrorHandler(old_handler); +#endif + fprintf(stderr, "tracking %d windows related to app window 0x%lx\n", nw, app); +} + +static void del_app(Window app) { + int i; + for (i=0; i < WMAX; i++) { + Window win = watch[i]; + if (win != None) { + if (same_app(app, win)) { + destroy_win(win); + } + } + } + for (i=0; i < AMAX; i++) { + Window app2 = apps[i]; + if (app2 != None) { + if (same_app(app, app2)) { + apps[i] = None; + } + } + } +} + +static void wait_until_empty(char *file) { + double t = 0.0, dt = 0.05; + while (t < 1.0) { + struct stat sb; + if (stat(file, &sb) != 0) { + return; + } + if (sb.st_size == 0) { + return; + } + t += dt; + usleep( (int) (dt * 1000 * 1000) ); + } +} + +static void client(char *client, int add) { + DIR *dir; + struct dirent *dp; + + if (!client) { + return; + } + if (!trackdir) { + fprintf(stderr, "no trackdir, cannot %s client: %s\n", + add ? "add" : "disconnect", client); + ff(); + return; + } + fprintf(stdout, "%s client: %s\n", add ? "adding " : "deleting", client); + + dir = opendir(trackdir); + if (!dir) { + fprintf(stderr, "could not opendir trackdir: %s\n", trackdir); + return; + } + while ( (dp = readdir(dir)) != NULL) { + char *name = dp->d_name; + if (!strcmp(name, ".") || !strcmp(name, "..")) { + continue; + } + if (strstr(name, "0x") != name) { + continue; + } + if (strstr(name, ".connect")) { + FILE *f; + char *tmp; + Window twin; + + if (scan_hexdec(name, &twin)) { + int f = find_win(twin); + if (appshare_debug) { + fprintf(stderr, "twin: 0x%lx name=%s f=%d\n", twin, name, f); + ff(); + } + if (f < 0) { + continue; + } + } + + tmp = (char *) calloc(100 + strlen(client), 1); + sprintf(tracktmp, "%s/%s", trackdir, name); + if (add) { + sprintf(tmp, "%s\n", client); + } else { + sprintf(tmp, "cmd=close:%s\n", client); + } + wait_until_empty(tracktmp); + f = fopen(tracktmp, "w"); + if (f) { + if (appshare_debug) { + fprintf(stderr, "%s client: %s + %s", + add ? "add" : "disconnect", tracktmp, tmp); + ff(); + } + fprintf(f, "%s", tmp); + fclose(f); + } + free(tmp); + } + } + closedir(dir); +} + +static void mapped(Window win) { + int f; + if (win == None) { + return; + } + f = find_win(win); + if (f < 0) { + if (win_attr(win)) { + if (get_parent(win) == root) { + /* XXX more cases? */ + add_win(win); + } + } + } +} + +static void unmapped(Window win) { + int f = find_win(win); + if (f < 0 || win == None) { + return; + } + stop(win); + state[f] = 0; +} + +static void destroy_win(Window win) { + stop(win); + delete_win(win); +} + +static Window parse_win(char *str) { + Window win = None; + if (!str) { + return None; + } + if (!strcmp(str, "pick") || !strcmp(str, "p")) { + static double last_pick = 0.0; + if (dnow() < start_time + 15) { + ; + } else if (dnow() < last_pick + 2) { + return None; + } else { + last_pick = dnow(); + } + if (!pick_windowid(&win)) { + fprintf(stderr, "parse_win: bad window pick.\n"); + win = None; + } + if (win == root) { + fprintf(stderr, "parse_win: ignoring pick of rootwin 0x%lx.\n", win); + win = None; + } + ff(); + } else if (!scan_hexdec(str, &win)) { + win = None; + } + return win; +} + +static void add_or_del_app(char *str, int add) { + Window win = parse_win(str); + + if (win != None) { + if (add) { + add_app(win); + } else { + del_app(win); + } + } else if (!strcmp(str, "all")) { + if (!add) { + int i; + for (i=0; i < AMAX; i++) { + if (apps[i] != None) { + del_app(apps[i]); + } + } + } + } +} + +static void add_or_del_win(char *str, int add) { + Window win = parse_win(str); + + if (win != None) { + int f = find_win(win); + if (add) { + if (f < 0 && win_attr(win)) { + add_win(win); + } + } else { + if (f >= 0) { + destroy_win(win); + } + } + } else if (!strcmp(str, "all")) { + if (!add) { + int i; + for (i=0; i < WMAX; i++) { + if (watch[i] != None) { + destroy_win(watch[i]); + } + } + } + } +} + +static void add_or_del_client(char *str, int add) { + int i; + + if (!str) { + return; + } + if (strcmp(control, "internal")) { + return; + } + if (add) { + int idx = find_client(str); + int free = find_client(NULL); + + if (idx >=0) { + fprintf(stderr, "already tracking client: %s in slot %d\n", str, idx); + ff(); + return; + } + if (free < 0) { + static int cnt = 0; + if (cnt++ < 10) { + fprintf(stderr, "ran out of client slots.\n"); + ff(); + } + return; + } + clients[free] = strdup(str); + client(str, 1); + } else { + if (str[0] == '#' || str[0] == '%') { + if (sscanf(str+1, "%d", &i) == 1) { + i--; + if (0 <= i && i < CMAX) { + if (clients[i] != NULL) { + client(clients[i], 0); + free(clients[i]); + clients[i] = NULL; + return; + } + } + } + } else if (!strcmp(str, "all")) { + for (i=0; i < CMAX; i++) { + if (clients[i] == NULL) { + continue; + } + client(clients[i], 0); + free(clients[i]); + clients[i] = NULL; + } + return; + } + + i = find_client(str); + if (i >= 0) { + free(clients[i]); + clients[i] = NULL; + client(str, 0); + } + } +} + +static void restart_x11vnc(void) { + int i, n = 0; + Window win, active[WMAX]; + for (i=0; i < WMAX; i++) { + win = watch[i]; + if (win == None) { + continue; + } + if (state[i]) { + active[n++] = win; + stop(win); + } + } + if (n) { + usleep(1500 * 1000); + } + for (i=0; i < n; i++) { + win = active[i]; + launch(win); + } +} + +static unsigned long cmask = 0x3fc00000; /* 00111111110000000000000000000000 */ + +static void init_cmask(void) { + /* dependent on the X server implementation; XmuClientWindow better? */ + /* xc/programs/Xserver/include/resource.h */ + int didit = 0, res_cnt = 29, client_bits = 8; + + if (getenv("X11VNC_APPSHARE_CLIENT_MASK")) { + unsigned long cr; + if (sscanf(getenv("X11VNC_APPSHARE_CLIENT_MASK"), "0x%lx", &cr) == 1) { + cmask = cr; + didit = 1; + } + } else if (getenv("X11VNC_APPSHARE_CLIENT_BITS")) { + int cr = atoi(getenv("X11VNC_APPSHARE_CLIENT_BITS")); + if (cr > 0) { + client_bits = cr; + } + } + if (!didit) { + cmask = (((1 << client_bits) - 1) << (res_cnt-client_bits)); + } + fprintf(stderr, "client_mask: 0x%08lx\n", cmask); +} + +static int same_app(Window win, Window app) { + if ( (win & cmask) == (app & cmask) ) { + return 1; + } else { + return 0; + } +} + +static int ours(Window win) { + int i; + for (i=0; i < AMAX; i++) { + if (apps[i] != None) { + if (same_app(win, apps[i])) { + return 1; + } + } + } + return 0; +} + +static void list_clients(void) { + int i, n = 0; + for (i=0; i < CMAX; i++) { + if (clients[i] == NULL) { + continue; + } + fprintf(stdout, "client[%02d] %s\n", ++n, clients[i]); + } + fprintf(stdout, "total clients: %d\n", n); + ff(); +} + +static void list_windows(void) { + int i, n = 0; + for (i=0; i < WMAX; i++) { + char *name; + Window win = watch[i]; + if (win == None) { + continue; + } + get_wm_name(win, &name); + fprintf(stdout, "window[%02d] 0x%08lx state: %d slot: %03d \"%s\"\n", + ++n, win, state[i], i, name); + free(name); + } + fprintf(stdout, "total windows: %d\n", n); + ff(); +} + +static void list_apps(void) { + int i, n = 0; + for (i=0; i < AMAX; i++) { + char *name; + Window win = apps[i]; + if (win == None) { + continue; + } + get_wm_name(win, &name); + fprintf(stdout, "app[%02d] 0x%08lx state: %d slot: %03d \"%s\"\n", + ++n, win, state[i], i, name); + free(name); + } + fprintf(stdout, "total apps: %d\n", n); + ff(); +} + +static int process_control(char *file, int check_clients) { + int i, nnew = 0, seen[CMAX]; + char line[1024], *new[CMAX]; + FILE *f; + + f = fopen(file, "r"); + if (!f) { + return 1; + } + if (check_clients) { + for (i=0; i < CMAX; i++) { + seen[i] = 0; + } + } + while (fgets(line, sizeof(line), f) != NULL) { + char *q = strchr(line, '\n'); + if (q) *q = '\0'; + + if (appshare_debug) { + fprintf(stderr, "check_control: %s\n", line); + ff(); + } + + q = lblanks(line); + if (q[0] == '#') { + continue; + } + if (!strcmp(q, "")) { + continue; + } + if (strstr(q, "cmd=") == q) { + char *cmd = q + strlen("cmd="); + if (!strcmp(cmd, "quit")) { + if (strcmp(control, file) && strstr(file, ".cmd")) { + FILE *f2 = fopen(file, "w"); + if (f2) fclose(f2); + } + appshare_cleanup(0); + } else if (!strcmp(cmd, "wait")) { + return 0; + } else if (strstr(cmd, "bcast:") == cmd) { + ; + } else if (strstr(cmd, "del_window:") == cmd) { + add_or_del_win(cmd + strlen("del_window:"), 0); + } else if (strstr(cmd, "add_window:") == cmd) { + add_or_del_win(cmd + strlen("add_window:"), 1); + } else if (strstr(cmd, "del:") == cmd) { + add_or_del_win(cmd + strlen("del:"), 0); + } else if (strstr(cmd, "add:") == cmd) { + add_or_del_win(cmd + strlen("add:"), 1); + } else if (strstr(cmd, "del_client:") == cmd) { + add_or_del_client(cmd + strlen("del_client:"), 0); + } else if (strstr(cmd, "add_client:") == cmd) { + add_or_del_client(cmd + strlen("add_client:"), 1); + } else if (strstr(cmd, "-") == cmd) { + add_or_del_client(cmd + strlen("-"), 0); + } else if (strstr(cmd, "+") == cmd) { + add_or_del_client(cmd + strlen("+"), 1); + } else if (strstr(cmd, "del_app:") == cmd) { + add_or_del_app(cmd + strlen("del_app:"), 0); + } else if (strstr(cmd, "add_app:") == cmd) { + add_or_del_app(cmd + strlen("add_app:"), 1); + } else if (strstr(cmd, "debug:") == cmd) { + appshare_debug = atoi(cmd + strlen("debug:")); + } else if (strstr(cmd, "showmenus:") == cmd) { + skip_menus = atoi(cmd + strlen("showmenus:")); + skip_menus = !(skip_menus); + } else if (strstr(cmd, "noexit:") == cmd) { + exit_no_app_win = atoi(cmd + strlen("noexit:")); + exit_no_app_win = !(exit_no_app_win); + } else if (strstr(cmd, "use_forever:") == cmd) { + use_forever = atoi(cmd + strlen("use_forever:")); + } else if (strstr(cmd, "tree_depth:") == cmd) { + tree_depth = atoi(cmd + strlen("tree_depth:")); + } else if (strstr(cmd, "x11vnc_args:") == cmd) { + x11vnc_args = strdup(cmd + strlen("x11vnc_args:")); + } else if (strstr(cmd, "env:") == cmd) { + putenv(cmd + strlen("env:")); + } else if (strstr(cmd, "noop") == cmd) { + ; + } else if (!strcmp(cmd, "restart")) { + restart_x11vnc(); + } else if (!strcmp(cmd, "list_clients") || !strcmp(cmd, "lc")) { + list_clients(); + } else if (!strcmp(cmd, "list_windows") || !strcmp(cmd, "lw")) { + list_windows(); + } else if (!strcmp(cmd, "list_apps") || !strcmp(cmd, "la")) { + list_apps(); + } else if (!strcmp(cmd, "list_all") || !strcmp(cmd, "ls")) { + list_windows(); + fprintf(stderr, "\n"); + list_apps(); + fprintf(stderr, "\n"); + list_clients(); + } else if (!strcmp(cmd, "print_logs") || !strcmp(cmd, "pl")) { + print_logs(); + } else if (!strcmp(cmd, "?") || !strcmp(cmd, "h") || !strcmp(cmd, "help")) { + fprintf(stderr, "available commands:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " quit restart noop x11vnc help ? ! !!\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " add_window:win (add:win, add:pick)\n"); + fprintf(stderr, " del_window:win (del:win, del:pick, del:all)\n"); + fprintf(stderr, " add_app:win (add_app:pick)\n"); + fprintf(stderr, " del_app:win (del_app:pick, del_app:all)\n"); + fprintf(stderr, " add_client:host (+host)\n"); + fprintf(stderr, " del_client:host (-host, -all)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " list_windows (lw)\n"); + fprintf(stderr, " list_apps (la)\n"); + fprintf(stderr, " list_clients (lc)\n"); + fprintf(stderr, " list_all (ls)\n"); + fprintf(stderr, " print_logs (pl)\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " debug:n showmenus:n noexit:n\n"); + } else { + fprintf(stderr, "unrecognized %s\n", q); + } + continue; + } + if (check_clients) { + int idx = find_client(q); + if (idx >= 0) { + seen[idx] = 1; + } else { + new[nnew++] = strdup(q); + } + } + } + fclose(f); + + if (check_clients) { + for (i=0; i < CMAX; i++) { + if (clients[i] == NULL) { + continue; + } + if (!seen[i]) { + client(clients[i], 0); + free(clients[i]); + clients[i] = NULL; + } + } + for (i=0; i < nnew; i++) { + int free = find_client(NULL); + if (free < 0) { + static int cnt = 0; + if (cnt++ < 10) { + fprintf(stderr, "ran out of client slots.\n"); + ff(); + break; + } + continue; + } + clients[free] = new[i]; + client(new[i], 1); + } + } + return 1; +} + +static int check_control(void) { + static int last_size = -1; + static time_t last_mtime = 0; + struct stat sb; + char *control_cmd; + + if (!control) { + return 1; + } + + if (!strcmp(control, "internal")) { + return 1; + } + + control_cmd = (char *)malloc(strlen(control) + strlen(".cmd") + 1); + sprintf(control_cmd, "%s.cmd", control); + if (stat(control_cmd, &sb) == 0) { + FILE *f; + if (sb.st_size > 0) { + process_control(control_cmd, 0); + } + f = fopen(control_cmd, "w"); + if (f) { + fclose(f); + } + } + free(control_cmd); + + if (stat(control, &sb) != 0) { + return 1; + } + if (last_size == (int) sb.st_size && last_mtime == sb.st_mtime) { + return 1; + } + last_size = (int) sb.st_size; + last_mtime = sb.st_mtime; + + return process_control(control, 1); +} + +static void update(void) { + int i, app_ok = 0; + if (last_event_type != PropertyNotify) { + if (appshare_debug) fprintf(stderr, "\nupdate ...\n"); + } else if (appshare_debug > 1) { + fprintf(stderr, "update ... propertynotify\n"); + } + if (!check_control()) { + return; + } + for (i=0; i < WMAX; i++) { + Window win = watch[i]; + if (win == None) { + continue; + } + if (!win_attr(win)) { + destroy_win(win); + continue; + } + if (find_app(win) >= 0) { + app_ok++; + } + if (state[i] == 0) { + if (attr.map_state == IsViewable) { + if (skip_menus) { + Window inside = check_inside(win); + if (inside != None) { + if (appshare_debug) {fprintf(stderr, "skip_menus: window 0x%lx is inside of 0x%lx, not tracking it.\n", win, inside); ff();} + delete_win(win); + continue; + } + } + launch(win); + state[i] = 1; + } + } else if (state[i] == 1) { + if (attr.map_state != IsViewable) { + stop(win); + state[i] = 0; + } + } + } + if (exit_no_app_win && !app_ok) { + for (i=0; i < AMAX; i++) { + if (apps[i] != None) { + fprintf(stdout, "main application window is gone: 0x%lx\n", apps[i]); + } + } + ff(); + appshare_cleanup(0); + } + if (last_event_type != PropertyNotify) { + if (appshare_debug) {fprintf(stderr, "update done.\n"); ff();} + } +} + +static void exiter(char *msg, int rc) { + fprintf(stderr, "%s", msg); + ff(); + kill_helper_pid(); + exit(rc); +} + +static void set_trackdir(void) { + char tmp[256]; + struct stat sb; + if (!strcmp(trackdir, "none")) { + trackdir = NULL; + return; + } + if (!strcmp(trackdir, "unset")) { + int fd; + sprintf(tmp, "%s.XXXXXX", trackpre); + fd = mkstemp(tmp); + if (fd < 0) { + strcat(tmp, ": failed to create file.\n"); + exiter(tmp, 1); + } + /* XXX race */ + close(fd); + unlink(tmp); + if (mkdir(tmp, 0700) != 0) { + strcat(tmp, ": failed to create dir.\n"); + exiter(tmp, 1); + } + trackdir = strdup(tmp); + } + if (stat(trackdir, &sb) != 0) { + if (mkdir(trackdir, 0700) != 0) { + exiter("could not make trackdir.\n", 1); + } + } else if (! S_ISDIR(sb.st_mode)) { + exiter("trackdir not a directory.\n", 1); + } + tracktmp = (char *) calloc(1000 + strlen(trackdir), 1); +} + +static void process_string(char *str) { + FILE *f; + char *file; + if (trackdir) { + sprintf(tracktmp, "%s/0xprop.cmd", trackdir); + file = strdup(tracktmp); + } else { + char tmp[] = "/tmp/x11vnc-appshare.cmd.XXXXXX"; + int fd = mkstemp(tmp); + if (fd < 0) { + return; + } + file = strdup(tmp); + close(fd); + } + f = fopen(file, "w"); + if (f) { + fprintf(f, "%s", str); + fclose(f); + process_control(file, 0); + } + unlink(file); + free(file); +} + +static void handle_shell(void) { + struct timeval tv; + static char lastline[1000]; + static int first = 1; + fd_set rfds; + int fd0 = fileno(stdin); + + if (first) { + memset(lastline, 0, sizeof(lastline)); + first = 0; + } + + FD_ZERO(&rfds); + FD_SET(fd0, &rfds); + tv.tv_sec = 0; + tv.tv_usec = 0; + select(fd0+1, &rfds, NULL, NULL, &tv); + if (FD_ISSET(fd0, &rfds)) { + char line[1000], line2[1010]; + if (fgets(line, sizeof(line), stdin) != NULL) { + char *str = lblanks(line); + char *q = strrchr(str, '\n'); + if (q) *q = '\0'; + if (strcmp(str, "")) { + if (!strcmp(str, "!!")) { + sprintf(line, "%s", lastline); + fprintf(stderr, "%s\n", line); + str = line; + } + if (strstr(str, "!") == str) { + system(str+1); + } else if (!strcmp(str, "x11vnc") || !strcmp(str, "ps")) { + char *cmd = "ps -elf | egrep 'PID|x11vnc' | grep -v egrep"; + fprintf(stderr, "%s\n", cmd); + system(cmd); + } else { + sprintf(line2, "cmd=%s", str); + process_string(line2); + } + sprintf(lastline, "%s", str); + } + } + fprintf(stderr, "\n%s", prompt); ff(); + } +} + +static void handle_prop_cmd(void) { + char *value, *str, *done = "DONE"; + + if (cmd_atom == None) { + return; + } + + value = get_xprop(cmd_atom_str, root); + if (value == NULL) { + return; + } + + str = lblanks(value); + if (!strcmp(str, done)) { + free(value); + return; + } + if (strstr(str, "cmd=quit") == str || strstr(str, "\ncmd=quit")) { + set_xprop(cmd_atom_str, root, done); + appshare_cleanup(0); + } + + process_string(str); + + free(value); + set_xprop(cmd_atom_str, root, done); +} + +#define PREFIX if(appshare_debug) fprintf(stderr, " %8.2f 0x%08lx : ", dnow() - start, ev.xany.window); + +static void monitor(void) { +#if !NO_X11 + XEvent ev; + double start = dnow(); + int got_prop_cmd = 0; + + if (shell) { + update(); + fprintf(stderr, "\n\n"); + process_string("cmd=help"); + fprintf(stderr, "\n%s", prompt); ff(); + } + + while (1) { + int t; + + if (XEventsQueued(dpy, QueuedAlready) == 0) { + update(); + if (got_prop_cmd) { + handle_prop_cmd(); + } + got_prop_cmd = 0; + if (shell) { + handle_shell(); + } + } + + XNextEvent(dpy, &ev); + + last_event_type = ev.type; + + switch (ev.type) { + case Expose: + PREFIX + if(appshare_debug) fprintf(stderr, "Expose %04dx%04d+%04d+%04d\n", ev.xexpose.width, ev.xexpose.height, ev.xexpose.x, ev.xexpose.y); + break; + case ConfigureNotify: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "ConfigureNotify %04dx%04d+%04d+%04d above: 0x%lx\n", ev.xconfigure.width, ev.xconfigure.height, ev.xconfigure.x, ev.xconfigure.y, ev.xconfigure.above); +#endif + break; + case VisibilityNotify: + PREFIX + if (appshare_debug) { + fprintf(stderr, "VisibilityNotify: "); + t = ev.xvisibility.state; + if (t == VisibilityFullyObscured) fprintf(stderr, "VisibilityFullyObscured\n"); + if (t == VisibilityPartiallyObscured) fprintf(stderr, "VisibilityPartiallyObscured\n"); + if (t == VisibilityUnobscured) fprintf(stderr, "VisibilityUnobscured\n"); + } + break; + case MapNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "MapNotify win: 0x%lx\n", ev.xmap.window); + if (ours(ev.xmap.window)) { + mapped(ev.xmap.window); + } + break; + case UnmapNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "UnmapNotify win: 0x%lx\n", ev.xmap.window); + if (ours(ev.xmap.window)) { + unmapped(ev.xmap.window); + } + break; + case MapRequest: + PREFIX + if(appshare_debug) fprintf(stderr, "MapRequest\n"); + break; + case CreateNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "CreateNotify parent: 0x%lx win: 0x%lx\n", ev.xcreatewindow.parent, ev.xcreatewindow.window); + if (ev.xcreatewindow.parent == root && ours(ev.xcreatewindow.window)) { + if (find_win(ev.xcreatewindow.window) >= 0) { + destroy_win(ev.xcreatewindow.window); + } + add_win(ev.xcreatewindow.window); + } + break; + case DestroyNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "DestroyNotify win: 0x%lx\n", ev.xdestroywindow.window); + if (ours(ev.xdestroywindow.window)) { + destroy_win(ev.xdestroywindow.window); + } + break; + case ConfigureRequest: + PREFIX + if(appshare_debug) fprintf(stderr, "ConfigureRequest\n"); + break; + case CirculateRequest: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "CirculateRequest parent: 0x%lx win: 0x%lx\n", ev.xcirculaterequest.parent, ev.xcirculaterequest.window); +#endif + break; + case CirculateNotify: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "CirculateNotify\n"); +#endif + break; + case PropertyNotify: +#if 0 + PREFIX + if(appshare_debug) fprintf(stderr, "PropertyNotify\n"); +#endif + if (cmd_atom != None && ev.xproperty.atom == cmd_atom) { + got_prop_cmd++; + } + break; + case ReparentNotify: + PREFIX + if(appshare_debug) fprintf(stderr, "ReparentNotify parent: 0x%lx win: 0x%lx\n", ev.xreparent.parent, ev.xreparent.window); + if (ours(ev.xreparent.window)) { + if (ours(ev.xreparent.parent)) { + destroy_win(ev.xreparent.window); + } else if (ev.xreparent.parent == root) { + /* ??? */ + } + } + break; + default: + PREFIX + if(appshare_debug) fprintf(stderr, "Unknown: %d\n", ev.type); + break; + } + } +#endif +} + +int appshare_main(int argc, char *argv[]) { + int i; + char *app_str = NULL; + char *dpy_str = NULL; + long xselectinput = 0; +#if NO_X11 + exiter("not compiled with X11\n", 1); +#else + for (i=0; i < WMAX; i++) { + watch[i] = None; + state[i] = 0; + } + for (i=0; i < AMAX; i++) { + apps[i] = None; + } + for (i=0; i < CMAX; i++) { + clients[i] = NULL; + } + + x11vnc = strdup(argv[0]); + + for (i=1; i < argc; i++) { + int end = (i == argc-1) ? 1 : 0; + char *s = argv[i]; + if (strstr(s, "--") == s) { + s++; + } + + if (!strcmp(s, "-h") || !strcmp(s, "-help")) { + fprintf(stdout, "%s", usage); + exit(0); + } else if (!strcmp(s, "-id")) { + id_opt = "-id"; + if (end) exiter("no -id value supplied\n", 1); + app_str = strdup(argv[++i]); + } else if (!strcmp(s, "-sid")) { + id_opt = "-sid"; + if (end) exiter("no -sid value supplied\n", 1); + app_str = strdup(argv[++i]); + } else if (!strcmp(s, "-connect") || !strcmp(s, "-connect_or_exit") || !strcmp(s, "-coe")) { + if (end) exiter("no -connect value supplied\n", 1); + connect_to = strdup(argv[++i]); + } else if (!strcmp(s, "-control")) { + if (end) exiter("no -control value supplied\n", 1); + control = strdup(argv[++i]); + if (!strcmp(control, "shell")) { + free(control); + control = strdup("internal"); + shell = 1; + } + } else if (!strcmp(s, "-trackdir")) { + if (end) exiter("no -trackdir value supplied\n", 1); + trackdir = strdup(argv[++i]); + } else if (!strcmp(s, "-display")) { + if (end) exiter("no -display value supplied\n", 1); + dpy_str = strdup(argv[++i]); + set_env("DISPLAY", dpy_str); + } else if (!strcmp(s, "-delay")) { + if (end) exiter("no -delay value supplied\n", 1); + helper_delay = atof(argv[++i]); + } else if (!strcmp(s, "-args")) { + if (end) exiter("no -args value supplied\n", 1); + x11vnc_args = strdup(argv[++i]); + } else if (!strcmp(s, "-env")) { + if (end) exiter("no -env value supplied\n", 1); + putenv(argv[++i]); + } else if (!strcmp(s, "-debug")) { + appshare_debug++; + } else if (!strcmp(s, "-showmenus")) { + skip_menus = 0; + } else if (!strcmp(s, "-noexit")) { + exit_no_app_win = 0; + } else if (!strcmp(s, "-shell")) { + shell = 1; + } else if (!strcmp(s, "-nocmds") || !strcmp(s, "-safer")) { + fprintf(stderr, "ignoring %s in -appshare mode.\n", s); + } else if (!strcmp(s, "-appshare")) { + ; + } else { + fprintf(stderr, "unrecognized 'x11vnc -appshare' option: %s\n", s); + exiter("", 1); + } + } + + if (getenv("X11VNC_APPSHARE_DEBUG")) { + appshare_debug = atoi(getenv("X11VNC_APPSHARE_DEBUG")); + } + + /* let user override name for multiple instances: */ + if (getenv("X11VNC_APPSHARE_COMMAND_PROPNAME")) { + cmd_atom_str = strdup(getenv("X11VNC_APPSHARE_COMMAND_PROPNAME")); + } + if (getenv("X11VNC_APPSHARE_TICKER_PROPNAME")) { + ticker_atom_str = strdup(getenv("X11VNC_APPSHARE_TICKER_PROPNAME")); + } + + if (shell) { + if (!control || strcmp(control, "internal")) { + exiter("mode -shell requires '-control internal'\n", 1); + } + } + + if (connect_to == NULL && control != NULL) { + struct stat sb; + if (stat(control, &sb) == 0) { + int len = 100 + sb.st_size; + FILE *f = fopen(control, "r"); + + if (f) { + char *line = (char *) malloc(len); + connect_to = (char *) calloc(2 * len, 1); + while (fgets(line, len, f) != NULL) { + char *q = strchr(line, '\n'); + if (q) *q = '\0'; + q = lblanks(line); + if (q[0] == '#') { + continue; + } + if (connect_to[0] != '\0') { + strcat(connect_to, ","); + } + strcat(connect_to, q); + } + fclose(f); + } + fprintf(stderr, "set -connect to: %s\n", connect_to); + } + } + if (0 && connect_to == NULL && control == NULL) { + exiter("no -connect host or -control file specified.\n", 1); + } + + if (control) { + pid_t pid; + parent_pid = getpid(); + pid = fork(); + if (pid == (pid_t) -1) { + ; + } else if (pid == 0) { + be_helper_pid(dpy_str); + exit(0); + } else { + helper_pid = pid; + } + } + + dpy = XOpenDisplay(dpy_str); + if (!dpy) { + exiter("cannot open display\n", 1); + } + + root = DefaultRootWindow(dpy); + + xselectinput = SubstructureNotifyMask; + if (helper_pid > 0) { + ticker_atom = XInternAtom(dpy, ticker_atom_str, False); + xselectinput |= PropertyChangeMask; + } + XSelectInput(dpy, root, xselectinput); + + cmd_atom = XInternAtom(dpy, cmd_atom_str, False); + + init_cmask(); + + sprintf(unique_tag, "X11VNC_APPSHARE_TAG=%d-tag", getpid()); + + start_time = dnow(); + + if (app_str == NULL) { + exiter("no -id/-sid window specified.\n", 1); + } else { + char *p, *str = strdup(app_str); + char *alist[AMAX]; + int i, n = 0; + + p = strtok(str, ","); + while (p) { + if (n >= AMAX) { + fprintf(stderr, "ran out of app slots: %s\n", app_str); + exiter("", 1); + } + alist[n++] = strdup(p); + p = strtok(NULL, ","); + } + free(str); + + for (i=0; i < n; i++) { + Window app = None; + p = alist[i]; + app = parse_win(p); + free(p); + + if (app != None) { + if (!ours(app)) { + add_app(app); + } + } + } + } + + set_trackdir(); + + signal(SIGINT, appshare_cleanup); + signal(SIGTERM, appshare_cleanup); + + rfbLogEnable(0); + + if (connect_to) { + char *p, *str = strdup(connect_to); + int n = 0; + p = strtok(str, ","); + while (p) { + clients[n++] = strdup(p); + p = strtok(NULL, ","); + } + free(str); + } else { + connect_to = strdup(""); + } + + for (i=0; i < AMAX; i++) { + if (apps[i] == None) { + continue; + } + fprintf(stdout, "Using app win: 0x%08lx root: 0x%08lx\n", apps[i], root); + } + fprintf(stdout, "\n"); + + monitor(); + + appshare_cleanup(0); + +#endif + return 0; +} + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c new file mode 100755 index 0000000..7f38d57 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/avahi.c @@ -0,0 +1,409 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- avahi.c -- */ + +#include "x11vnc.h" +#include "connections.h" +#include "cleanup.h" + +void avahi_initialise(void); +void avahi_advertise(const char *name, const char *host, const uint16_t port); +void avahi_reset(void); +void avahi_cleanup(void); + +static pid_t avahi_pid = 0; + +static void kill_avahi_pid(void) { + if (avahi_pid != 0) { + kill(avahi_pid, SIGTERM); + avahi_pid = 0; + } +} + +static int try_avahi_helper(const char *name, const char *host, const uint16_t port) { +#if LIBVNCSERVER_HAVE_FORK + char *cmd, *p, *path = getenv("PATH"), portstr[32]; + int i; + + if (!name || !host || !port) {} + + /* avahi-publish */ + if (no_external_cmds || !cmd_ok("zeroconf")) { + return 0; + } + + if (!path) { + return 0; + } + + path = strdup(path); + cmd = (char *) malloc(strlen(path) + 100); + sprintf(portstr, "%d", (int) port); + + p = strtok(path, ":"); + while (p) { + struct stat sbuf; + + sprintf(cmd, "%s/avahi-publish", p); + if (stat(cmd, &sbuf) == 0) { + break; + } + sprintf(cmd, "%s/dns-sd", p); + if (stat(cmd, &sbuf) == 0) { + break; + } + sprintf(cmd, "%s/mDNS", p); + if (stat(cmd, &sbuf) == 0) { + break; + } + cmd[0] = '\0'; + + p = strtok(NULL, ":"); + } + free(path); + + if (!strcmp(cmd, "")) { + free(cmd); + rfbLog("Could not find an external avahi/zeroconf helper program.\n"); + return 0; + } + + avahi_pid = fork(); + + if (avahi_pid < 0) { + rfbLogPerror("fork"); + avahi_pid = 0; + free(cmd); + return 0; + } + + if (avahi_pid != 0) { + int status; + + usleep(500 * 1000); + waitpid(avahi_pid, &status, WNOHANG); + if (kill(avahi_pid, 0) != 0) { + waitpid(avahi_pid, &status, WNOHANG); + avahi_pid = 0; + free(cmd); + return 0; + } + if (! quiet) { + rfbLog("%s helper pid is: %d\n", cmd, (int) avahi_pid); + } + free(cmd); + return 1; + } + + for (i=3; i<256; i++) { + close(i); + } + + if (strstr(cmd, "/avahi-publish")) { + execlp(cmd, cmd, "-s", name, "_rfb._tcp", portstr, (char *) NULL); + } else { + execlp(cmd, cmd, "-R", name, "_rfb._tcp", ".", portstr, (char *) NULL); + } + exit(1); +#else + if (!name || !host || !port) {} + return 0; +#endif +} + +#if !defined(LIBVNCSERVER_HAVE_AVAHI) || !defined(LIBVNCSERVER_HAVE_LIBPTHREAD) +void avahi_initialise(void) { + rfbLog("avahi_initialise: no Avahi support at buildtime.\n"); +} + +void avahi_advertise(const char *name, const char *host, const uint16_t port) { + if (!try_avahi_helper(name, host, port)) { + rfbLog("avahi_advertise: no Avahi support at buildtime.\n"); + avahi = 0; + } +} + +void avahi_reset(void) { + kill_avahi_pid(); + rfbLog("avahi_reset: no Avahi support at buildtime.\n"); +} + +void avahi_cleanup(void) { + kill_avahi_pid(); + rfbLog("avahi_cleanup: no Avahi support at buildtime.\n"); +} +#else + +#include +#include +#include +#include + +#include +#include + + +static AvahiThreadedPoll *_poll = NULL; +static AvahiClient *_client = NULL; +static AvahiEntryGroup *_group = NULL; + +static int db = 0; + +typedef struct { + const char *name; + const char *host; + uint16_t port; +} avahi_service_t; + +typedef struct { + char *name; + char *host; + uint16_t port; +} avahi_reg_t; + +#define NREG 16 +static avahi_reg_t registered[NREG]; + +void avahi_initialise(void) { + int ret; + static int first = 1; + + if (getenv("AVAHI_DEBUG")) { + db = 1; + } + if (first) { + int i; + for (i=0; iname); +#if 0 /* is this the segv problem? */ + free(svc); +#endif + break; + case AVAHI_ENTRY_GROUP_COLLISION: + new_name = avahi_alternative_service_name(svc->name); + _avahi_create_services(new_name, svc->host, svc->port); + rfbLog("Avahi Entry group collision\n"); + avahi_free(new_name); + break; + case AVAHI_ENTRY_GROUP_FAILURE: + rfbLog("Avahi Entry group failure: %s\n", + avahi_strerror(avahi_client_errno( + avahi_entry_group_get_client(g)))); + break; + default: + break; + } +if (db) fprintf(stderr, "out _avahi_entry_group_callback\n"); +} + +static void _avahi_create_services(const char *name, const char *host, + const uint16_t port) { + avahi_service_t *svc = (avahi_service_t *)malloc(sizeof(avahi_service_t)); + int ret = 0; + +if (db) fprintf(stderr, "in _avahi_create_services %s %s %d\n", name, host, port); + svc->name = name; + svc->host = host; + svc->port = port; + + if (!_group) { +if (db) fprintf(stderr, " _avahi_create_services create group\n"); + _group = avahi_entry_group_new(_client, + _avahi_entry_group_callback, svc); + } + if (!_group) { + rfbLog("avahi_entry_group_new() failed: %s\n", + avahi_strerror(avahi_client_errno(_client))); + return; + } + + ret = avahi_entry_group_add_service(_group, AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, 0, name, "_rfb._tcp", NULL, NULL, port, NULL); + if (ret < 0) { + rfbLog("Failed to add _rfb._tcp service: %s\n", + avahi_strerror(ret)); + return; + } + + ret = avahi_entry_group_commit(_group); + if (ret < 0) { + rfbLog("Failed to commit entry_group:: %s\n", + avahi_strerror(ret)); + return; + } +if (db) fprintf(stderr, "out _avahi_create_services\n"); +} + +void avahi_advertise(const char *name, const char *host, const uint16_t port) { + int i; +if (db) fprintf(stderr, "in avahi_advertise: %s %s %d\n", name, host, port); + if (!_client) { +if (db) fprintf(stderr, " avahi_advertise client null\n"); + return; + } + if (_poll == NULL) { + rfbLog("Avahi poll not initialized.\n"); + return; + } + /* well, we just track it ourselves... */ + for (i=0; i= 5900 ? port : 5900+port); + avahi_threaded_poll_unlock(_poll); +if (db) fprintf(stderr, "out avahi_advertise\n"); +} + +void avahi_reset(void) { + int i; +if (db) fprintf(stderr, "in avahi_reset\n"); + for (i=0; i + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_AVAHI_H +#define _X11VNC_AVAHI_H + +/* -- avahi.h -- */ + +extern void avahi_initialise(void); +extern void avahi_advertise(const char *name, const char *host, const uint16_t port); +extern void avahi_reset(void); +extern void avahi_cleanup(void); + +#endif /* _X11VNC_AVAHI_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h new file mode 100755 index 0000000..014f5b4 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/blackout_t.h @@ -0,0 +1,49 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_BLACKOUT_T_H +#define _X11VNC_BLACKOUT_T_H + +/* -- blackout_t.h -- */ + +typedef struct bout { + int x1, y1, x2, y2; +} blackout_t; + +#define BO_MAX 32 +typedef struct tbout { + blackout_t bo[BO_MAX]; /* hardwired max rectangles. */ + int cover; + int count; +} tile_blackout_t; + +#endif /* _X11VNC_BLACKOUT_T_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c new file mode 100755 index 0000000..e9222b5 --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.c @@ -0,0 +1,755 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- cleanup.c -- */ + +#include "x11vnc.h" +#include "xwrappers.h" +#include "xdamage.h" +#include "remote.h" +#include "keyboard.h" +#include "scan.h" +#include "gui.h" +#include "solid.h" +#include "unixpw.h" +#include "sslcmds.h" +#include "sslhelper.h" +#include "connections.h" +#include "macosx.h" +#include "macosxCG.h" +#include "avahi.h" +#include "screen.h" +#include "xrecord.h" +#include "xevents.h" + +/* + * Exiting and error handling routines + */ + +int trapped_xerror = 0; +int trapped_xioerror = 0; +int trapped_getimage_xerror = 0; +int trapped_record_xerror = 0; +XErrorEvent *trapped_xerror_event; + +/* XXX CHECK BEFORE RELEASE */ +int crash_debug = 0; + +void clean_shm(int quick); +void clean_up_exit(int ret); +int trap_xerror(Display *d, XErrorEvent *error); +int trap_xioerror(Display *d); +int trap_getimage_xerror(Display *d, XErrorEvent *error); +char *xerror_string(XErrorEvent *error); +void initialize_crash_handler(void); +void initialize_signals(void); +void unset_signals(void); +void close_exec_fds(void); +int known_sigpipe_mode(char *s); + + +static int exit_flag = 0; +static int exit_sig = 0; + +static void clean_icon_mode(void); +static int Xerror(Display *d, XErrorEvent *error); +static int XIOerr(Display *d); +static void crash_shell_help(void); +static void crash_shell(void); +static void interrupted (int sig); + + +void clean_shm(int quick) { + int i, cnt = 0; + + /* + * to avoid deadlock, etc, under quick=1 we just delete the shm + * areas and leave the X stuff hanging. + */ + if (quick) { + shm_delete(&scanline_shm); + shm_delete(&fullscreen_shm); + shm_delete(&snaprect_shm); + } else { + shm_clean(&scanline_shm, scanline); + shm_clean(&fullscreen_shm, fullscreen); + shm_clean(&snaprect_shm, snaprect); + } + + /* + * Here we have to clean up quite a few shm areas for all + * the possible tile row runs (40 for 1280), not as robust + * as one might like... sometimes need to run ipcrm(1). + */ + for(i=1; i<=ntiles_x; i++) { + if (i > tile_shm_count) { + break; + } + if (quick) { + shm_delete(&tile_row_shm[i]); + } else { + shm_clean(&tile_row_shm[i], tile_row[i]); + } + cnt++; + if (single_copytile_count && i >= single_copytile_count) { + break; + } + } + if (!quiet && cnt > 0) { + rfbLog("deleted %d tile_row polling images.\n", cnt); + } +} + +static void clean_icon_mode(void) { + if (icon_mode && icon_mode_fh) { + fprintf(icon_mode_fh, "quit\n"); + fflush(icon_mode_fh); + fclose(icon_mode_fh); + icon_mode_fh = NULL; + if (icon_mode_file) { + unlink(icon_mode_file); + icon_mode_file = NULL; + } + } +} + +/* + * Normal exiting + */ +void clean_up_exit(int ret) { + static int depth = 0; + exit_flag = 1; + + if (depth++ > 2) { + exit(ret); + } + + if (icon_mode) { + clean_icon_mode(); + } + + /* remove the shm areas: */ + clean_shm(0); + + stop_stunnel(); + if (use_openssl) { + ssl_helper_pid(0, 0); /* killall */ + } + + if (avahi) { + avahi_cleanup(); + } + if (ssh_pid > 0) { + kill(ssh_pid, SIGTERM); + ssh_pid = 0; + } + +#ifdef MACOSX + if (client_connect_file) { + if (strstr(client_connect_file, "/tmp/x11vnc-macosx-remote") + == client_connect_file) { + unlink(client_connect_file); + } + } + if (macosx_console) { + macosxCG_fini(); + } +#endif + + if (pipeinput_fh != NULL) { + pclose(pipeinput_fh); + pipeinput_fh = NULL; + } + + if (! dpy) { /* raw_rb hack */ + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(ret); + } + + /* X keyboard cleanups */ + delete_added_keycodes(0); + + if (clear_mods == 1) { + clear_modifiers(0); + } else if (clear_mods == 2) { + clear_keys(); + } else if (clear_mods == 3) { + clear_keys(); + clear_locks(); + } + + if (no_autorepeat) { + autorepeat(1, 0); + } + if (use_solid_bg) { + solid_bg(1); + } + if (ncache || ncache0) { + kde_no_animate(1); + } + X_LOCK; + XTestDiscard_wr(dpy); +#if LIBVNCSERVER_HAVE_LIBXDAMAGE + if (xdamage) { + XDamageDestroy(dpy, xdamage); + } +#endif +#if LIBVNCSERVER_HAVE_LIBXTRAP + if (trap_ctx) { + XEFreeTC(trap_ctx); + } +#endif + /* XXX rdpy_ctrl, etc. cannot close w/o blocking */ + XCloseDisplay_wr(dpy); + X_UNLOCK; + + fflush(stderr); + + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + + exit(ret); +} + +/* X11 error handlers */ + +static XErrorHandler Xerror_def; +static XIOErrorHandler XIOerr_def; + +int trap_xerror(Display *d, XErrorEvent *error) { + trapped_xerror = 1; + trapped_xerror_event = error; + + if (d) {} /* unused vars warning: */ + + return 0; +} + +int trap_xioerror(Display *d) { + trapped_xioerror = 1; + + if (d) {} /* unused vars warning: */ + + return 0; +} + +int trap_getimage_xerror(Display *d, XErrorEvent *error) { + trapped_getimage_xerror = 1; + trapped_xerror_event = error; + + if (d) {} /* unused vars warning: */ + + return 0; +} + +/* Are silly Xorg people removing X_ShmAttach from XShm.h? */ +/* INDEED! What stupid, myopic morons... */ +/* Maintenance Monkeys busy typing at their keyboards... */ +#ifndef X_ShmAttach +#define X_ShmAttach 1 +#endif + +static int Xerror(Display *d, XErrorEvent *error) { + X_UNLOCK; + + if (getenv("X11VNC_PRINT_XERROR")) { + fprintf(stderr, "Xerror: major_opcode: %d minor_opcode: %d error_code: %d\n", + error->request_code, error->minor_code, error->error_code); + } + + if (xshm_opcode > 0 && error->request_code == xshm_opcode) { + if (error->minor_code == X_ShmAttach) { + char *dstr = DisplayString(dpy); + fprintf(stderr, "\nX11 MIT Shared Memory Attach failed:\n"); + fprintf(stderr, " Is your DISPLAY=%s on a remote machine?\n", dstr); + if (strstr(dstr, "localhost:")) { + fprintf(stderr, " Note: DISPLAY=localhost:N suggests a SSH X11 redir to a remote machine.\n"); + } else if (dstr[0] != ':') { + fprintf(stderr, " Note: DISPLAY=hostname:N suggests a remote display.\n"); + } + fprintf(stderr, " Suggestion, use: x11vnc -display :0 ... for local display :0\n\n"); + } + } + + interrupted(0); + + if (d) {} /* unused vars warning: */ + + return (*Xerror_def)(d, error); +} + +void watch_loop(void); + +static int XIOerr(Display *d) { + static int reopen = 0, rmax = 1; + X_UNLOCK; + + if (getenv("X11VNC_REOPEN_DISPLAY")) { + rmax = atoi(getenv("X11VNC_REOPEN_DISPLAY")); + } + +#if !NO_X11 + if (reopen < rmax && getenv("X11VNC_REOPEN_DISPLAY")) { + int db = getenv("X11VNC_REOPEN_DEBUG") ? 1 : 0; + int sleepmax = 10, i; + Display *save_dpy = dpy; + char *dstr = strdup(DisplayString(save_dpy)); + reopen++; + if (getenv("X11VNC_REOPEN_SLEEP_MAX")) { + sleepmax = atoi(getenv("X11VNC_REOPEN_SLEEP_MAX")); + } + rfbLog("*** XIO error: Trying to reopen[%d/%d] display '%s'\n", reopen, rmax, dstr); + rfbLog("*** XIO error: Note the reopened state may be unstable.\n"); + for (i=0; i < sleepmax; i++) { + usleep (1000 * 1000); + dpy = XOpenDisplay_wr(dstr); + rfbLog("dpy[%d/%d]: %p\n", i+1, sleepmax, dpy); + if (dpy) { + break; + } + } + last_open_xdisplay = time(NULL); + if (dpy) { + rfbLog("*** XIO error: Reopened display '%s' successfully.\n", dstr); + if (db) rfbLog("*** XIO error: '%s' 0x%x\n", dstr, dpy); + scr = DefaultScreen(dpy); + rootwin = RootWindow(dpy, scr); + if (db) rfbLog("*** XIO error: disable_grabserver\n"); + disable_grabserver(dpy, 0); + if (db) rfbLog("*** XIO error: xrecord\n"); + zerodisp_xrecord(); + initialize_xrecord(); + if (db) rfbLog("*** XIO error: xdamage\n"); + create_xdamage_if_needed(1); + if (db) rfbLog("*** XIO error: do_new_fb\n"); + if (using_shm) { + if (db) rfbLog("*** XIO error: clean_shm\n"); + clean_shm(1); + } + do_new_fb(1); + if (db) rfbLog("*** XIO error: check_xevents\n"); + check_xevents(1); + + /* sadly, we can never return... */ + if (db) rfbLog("*** XIO error: watch_loop\n"); + watch_loop(); + clean_up_exit(1); + } + } +#endif + + interrupted(-1); + + if (d) {} /* unused vars warning: */ + + return (*XIOerr_def)(d); +} + +static char *xerrors[] = { + "Success", + "BadRequest", + "BadValue", + "BadWindow", + "BadPixmap", + "BadAtom", + "BadCursor", + "BadFont", + "BadMatch", + "BadDrawable", + "BadAccess", + "BadAlloc", + "BadColor", + "BadGC", + "BadIDChoice", + "BadName", + "BadLength", + "BadImplementation", + "unknown" +}; +static int xerrors_max = BadImplementation; + +char *xerror_string(XErrorEvent *error) { + int index = -1; + if (error) { + index = (int) error->error_code; + } + if (0 <= index && index <= xerrors_max) { + return xerrors[index]; + } else { + return xerrors[xerrors_max+1]; + } +} + +static char *crash_stack_command1 = NULL; +static char *crash_stack_command2 = NULL; +static char *crash_debug_command = NULL; + +void initialize_crash_handler(void) { + int pid = program_pid; + crash_stack_command1 = (char *) malloc(1000); + crash_stack_command2 = (char *) malloc(1000); + crash_debug_command = (char *) malloc(1000); + + snprintf(crash_stack_command1, 500, "echo where > /tmp/gdb.%d;" + " env PATH=$PATH:/usr/local/bin:/usr/sfw/bin:/usr/bin" + " gdb -x /tmp/gdb.%d -batch -n %s %d;" + " rm -f /tmp/gdb.%d", pid, pid, program_name, pid, pid); + snprintf(crash_stack_command2, 500, "pstack %d", program_pid); + + snprintf(crash_debug_command, 500, "gdb %s %d", program_name, pid); +} + +static void crash_shell_help(void) { + int pid = program_pid; + fprintf(stderr, "\n"); + fprintf(stderr, " *** Welcome to the x11vnc crash shell! ***\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "PROGRAM: %s PID: %d\n", program_name, pid); + fprintf(stderr, "\n"); + fprintf(stderr, "POSSIBLE DEBUGGER COMMAND:\n"); + fprintf(stderr, "\n"); + fprintf(stderr, " %s\n", crash_debug_command); + fprintf(stderr, "\n"); + fprintf(stderr, "Press \"q\" to quit.\n"); + fprintf(stderr, "Press \"h\" or \"?\" for this help.\n"); + fprintf(stderr, "Press \"s\" to try to run some commands to" + " show a stack trace (gdb/pstack).\n"); + fprintf(stderr, "\n"); + fprintf(stderr, "Anything else is passed to -Q query function.\n"); + fprintf(stderr, "\n"); +} + +static void crash_shell(void) { + char qry[1000], cmd[1000], line[1000]; + char *str, *p; + + crash_shell_help(); + fprintf(stderr, "\ncrash> "); + while (fgets(line, 1000, stdin) != NULL) { + str = lblanks(line); + + p = str; + while(*p) { + if (*p == '\n') { + *p = '\0'; + } + p++; + } + + if (*str == 'q' && *(str+1) == '\0') { + fprintf(stderr, "quiting.\n"); + return; + } else if (*str == 'h' && *(str+1) == '\0') { + crash_shell_help(); + } else if (*str == '?' && *(str+1) == '\0') { + crash_shell_help(); + } else if (*str == 's' && *(str+1) == '\0') { + sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1); + /* crash */ + if (no_external_cmds || !cmd_ok("crash")) { + fprintf(stderr, "\nno_external_cmds=%d\n", + no_external_cmds); + goto crash_prompt; + } + fprintf(stderr, "\nrunning:\n\t%s\n\n", + crash_stack_command1); + system(cmd); + usleep(1000*1000); + + sprintf(cmd, "sh -c '(%s) &'", crash_stack_command2); + fprintf(stderr, "\nrunning:\n\t%s\n\n", + crash_stack_command2); + system(cmd); + usleep(1000*1000); + } else { + snprintf(qry, 1000, "qry=%s", str); + p = process_remote_cmd(qry, 1); + fprintf(stderr, "\n\nresult:\n%s\n", p); + free(p); + } + +crash_prompt: + fprintf(stderr, "crash> "); + } +} + +/* + * General problem handler + */ +static void interrupted (int sig) { + exit_sig = sig; + if (exit_flag) { + fprintf(stderr, "extra[%d] signal: %d\n", exit_flag, sig); + exit_flag++; + if (use_threads) { + usleep2(250 * 1000); + } else if (exit_flag <= 2) { + return; + } + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(4); + } + exit_flag++; + if (sig == 0) { + fprintf(stderr, "caught X11 error:\n"); + if (crash_debug) { crash_shell(); } + } else if (sig == -1) { + fprintf(stderr, "caught XIO error:\n"); + } else { + fprintf(stderr, "caught signal: %d\n", sig); + } + if (sig == SIGINT) { + shut_down = 1; + return; + } + + if (crash_debug) { + crash_shell(); + } + + X_UNLOCK; + + if (icon_mode) { + clean_icon_mode(); + } + /* remove the shm areas with quick=1: */ + clean_shm(1); + + if (sig == -1) { + /* not worth trying any more cleanup, X server probably gone */ + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(3); + } + + /* X keyboard cleanups */ + delete_added_keycodes(0); + + if (clear_mods == 1) { + clear_modifiers(0); + } else if (clear_mods == 2) { + clear_keys(); + } else if (clear_mods == 3) { + clear_keys(); + clear_locks(); + } + if (no_autorepeat) { + autorepeat(1, 0); + } + if (use_solid_bg) { + solid_bg(1); + } + if (ncache || ncache0) { + kde_no_animate(1); + } + stop_stunnel(); + + if (crash_debug) { + crash_shell(); + } + + if (sig) { + if (rm_flagfile) { + unlink(rm_flagfile); + rm_flagfile = NULL; + } + exit(2); + } +} + +static void ignore_sigs(char *list) { + char *str, *p; + int ignore = 1; + if (list == NULL || *list == '\0') { + return; + } + str = strdup(list); + p = strtok(str, ":,"); + +#define SETSIG(x, y) \ + if (strstr(p, x)) { \ + if (ignore) { \ + signal(y, SIG_IGN); \ + } else { \ + signal(y, interrupted); \ + } \ + } + +#ifdef SIG_IGN + while (p) { + if (!strcmp(p, "ignore")) { + ignore = 1; + } else if (!strcmp(p, "exit")) { + ignore = 0; + } + /* Take off every 'sig' ;-) */ +#ifdef SIGHUP + SETSIG("HUP", SIGHUP); +#endif +#ifdef SIGINT + SETSIG("INT", SIGINT); +#endif +#ifdef SIGQUIT + SETSIG("QUIT", SIGQUIT); +#endif +#ifdef SIGTRAP + SETSIG("TRAP", SIGTRAP); +#endif +#ifdef SIGABRT + SETSIG("ABRT", SIGABRT); +#endif +#ifdef SIGBUS + SETSIG("BUS", SIGBUS); +#endif +#ifdef SIGFPE + SETSIG("FPE", SIGFPE); +#endif +#ifdef SIGSEGV + SETSIG("SEGV", SIGSEGV); +#endif +#ifdef SIGPIPE + SETSIG("PIPE", SIGPIPE); +#endif +#ifdef SIGTERM + SETSIG("TERM", SIGTERM); +#endif +#ifdef SIGUSR1 + SETSIG("USR1", SIGUSR1); +#endif +#ifdef SIGUSR2 + SETSIG("USR2", SIGUSR2); +#endif +#ifdef SIGCONT + SETSIG("CONT", SIGCONT); +#endif +#ifdef SIGSTOP + SETSIG("STOP", SIGSTOP); +#endif +#ifdef SIGTSTP + SETSIG("TSTP", SIGTSTP); +#endif + p = strtok(NULL, ":,"); + } +#endif /* SIG_IGN */ + free(str); +} + +/* signal handlers */ +void initialize_signals(void) { + signal(SIGHUP, interrupted); + signal(SIGINT, interrupted); + signal(SIGQUIT, interrupted); + signal(SIGABRT, interrupted); + signal(SIGTERM, interrupted); + signal(SIGBUS, interrupted); + signal(SIGSEGV, interrupted); + signal(SIGFPE, interrupted); + + if (!sigpipe || *sigpipe == '\0' || !strcmp(sigpipe, "skip")) { + ; + } else if (strstr(sigpipe, "ignore:") == sigpipe) { + ignore_sigs(sigpipe); + } else if (strstr(sigpipe, "exit:") == sigpipe) { + ignore_sigs(sigpipe); + } else if (!strcmp(sigpipe, "ignore")) { +#ifdef SIG_IGN + signal(SIGPIPE, SIG_IGN); +#endif + } else if (!strcmp(sigpipe, "exit")) { + rfbLog("initialize_signals: will exit on SIGPIPE\n"); + signal(SIGPIPE, interrupted); + } + +#if NO_X11 + return; +#else + X_LOCK; + Xerror_def = XSetErrorHandler(Xerror); + XIOerr_def = XSetIOErrorHandler(XIOerr); + X_UNLOCK; +#endif /* NO_X11 */ +} + +void unset_signals(void) { + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGQUIT, SIG_DFL); + signal(SIGABRT, SIG_DFL); + signal(SIGTERM, SIG_DFL); + signal(SIGBUS, SIG_DFL); + signal(SIGSEGV, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGPIPE, SIG_DFL); +} + +void close_exec_fds(void) { + int fd; +#ifdef FD_CLOEXEC + for (fd = 3; fd < 64; fd++) { + int flags = fcntl(fd, F_GETFD); + if (flags != -1) { + flags |= FD_CLOEXEC; + fcntl(fd, F_SETFD, flags); + } + } +#endif +} + +int known_sigpipe_mode(char *s) { +/* + * skip, ignore, exit + */ + if (strstr(s, "ignore:") == s) { + return 1; + } + if (strstr(s, "exit:") == s) { + return 1; + } + if (strcmp(s, "skip") && strcmp(s, "ignore") && + strcmp(s, "exit")) { + return 0; + } else { + return 1; + } +} + + diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h new file mode 100755 index 0000000..0c4dcea --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/cleanup.h @@ -0,0 +1,59 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +#ifndef _X11VNC_CLEANUP_H +#define _X11VNC_CLEANUP_H + +/* -- cleanup.h -- */ + +extern int trapped_xerror; +extern int trapped_xioerror; +extern int trapped_getimage_xerror; +extern int trapped_record_xerror; +extern XErrorEvent *trapped_xerror_event; + +extern int crash_debug; + +extern void clean_shm(int quick); +extern void clean_up_exit(int ret); + +extern int trap_xerror(Display *d, XErrorEvent *error); +extern int trap_xioerror(Display *d); +extern int trap_getimage_xerror(Display *d, XErrorEvent *error); +extern char *xerror_string(XErrorEvent *error); +extern void initialize_crash_handler(void); +extern void initialize_signals(void); +extern void unset_signals(void); +extern void close_exec_fds(void); +extern int known_sigpipe_mode(char *s); + +#endif /* _X11VNC_CLEANUP_H */ diff --git a/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c new file mode 100755 index 0000000..5dd80ba --- /dev/null +++ b/droidvncgrab/vnc/libvncserver-kanaka/x11vnc/connections.c @@ -0,0 +1,4377 @@ +/* + Copyright (C) 2002-2010 Karl J. Runge + All rights reserved. + +This file is part of x11vnc. + +x11vnc 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. + +x11vnc 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 x11vnc; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA +or see . + +In addition, as a special exception, Karl J. Runge +gives permission to link the code of its release of x11vnc with the +OpenSSL project's "OpenSSL" library (or with modified versions of it +that use the same license as the "OpenSSL" library), and distribute +the linked executables. You must obey the GNU General Public License +in all respects for all of the code used other than "OpenSSL". If you +modify this file, you may extend this exception to your version of the +file, but you are not obligated to do so. If you do not wish to do +so, delete this exception statement from your version. +*/ + +/* -- connections.c -- */ + +#include "x11vnc.h" +#include "inet.h" +#include "remote.h" +#include "keyboard.h" +#include "cleanup.h" +#include "gui.h" +#include "solid.h" +#include "rates.h" +#include "screen.h" +#include "unixpw.h" +#include "user.h" +#include "scan.h" +#include "sslcmds.h" +#include "sslhelper.h" +#include "xwrappers.h" +#include "xevents.h" +#include "win_utils.h" +#include "macosx.h" +#include "macosxCG.h" +#include "userinput.h" +#include "pointer.h" +#include "xrandr.h" + +/* + * routines for handling incoming, outgoing, etc connections + */ + +/* string for the VNC_CONNECT property */ +char vnc_connect_str[VNC_CONNECT_MAX+1]; +Atom vnc_connect_prop = None; +char x11vnc_remote_str[X11VNC_REMOTE_MAX+1]; +Atom x11vnc_remote_prop = None; +rfbClientPtr inetd_client = NULL; + +int all_clients_initialized(void); +char *list_clients(void); +int new_fb_size_clients(rfbScreenInfoPtr s); +void close_all_clients(void); +void close_clients(char *str); +void set_client_input(char *str); +void set_child_info(void); +int cmd_ok(char *cmd); +void client_gone(rfbClientPtr client); +void client_gone_chat_helper(rfbClientPtr client); +void reverse_connect(char *str); +void set_vnc_connect_prop(char *str); +void read_vnc_connect_prop(int); +void set_x11vnc_remote_prop(char *str); +void read_x11vnc_remote_prop(int); +void check_connect_inputs(void); +void check_gui_inputs(void); +rfbClientPtr create_new_client(int sock, int start_thread); +enum rfbNewClientAction new_client(rfbClientPtr client); +enum rfbNewClientAction new_client_chat_helper(rfbClientPtr client); +rfbBool password_check_chat_helper(rfbClientPtr cl, const char* response, int len); +void start_client_info_sock(char *host_port_cookie); +void send_client_info(char *str); +void adjust_grabs(int grab, int quiet); +void check_new_clients(void); +int accept_client(rfbClientPtr client); +void check_ipv6_listen(long usec); +int run_user_command(char *cmd, rfbClientPtr client, char *mode, char *input, + int len, FILE *output); +int check_access(char *addr); +void client_set_net(rfbClientPtr client); +char *get_xprop(char *prop, Window win); +int set_xprop(char *prop, Window win, char *value); +char *bcx_xattach(char *str, int *pg_init, int *kg_init); +void grab_state(int *ptr_grabbed, int *kbd_grabbed); +char *wininfo(Window win, int show_children); + +static rfbClientPtr *client_match(char *str); +static void free_client_data(rfbClientPtr client); +static void ugly_geom(char *p, int *x, int *y); +static int ugly_window(char *addr, char *userhost, int X, int Y, + int timeout, char *mode, int accept); +static int action_match(char *action, int rc); +static void check_connect_file(char *file); +static void send_client_connect(void); + + +/* + * check that all clients are in RFB_NORMAL state + */ +int all_clients_initialized(void) { + rfbClientIteratorPtr iter; + rfbClientPtr cl; + int ok = 1; + + if (! screen) { + return ok; + } + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + if (cl->state != RFB_NORMAL) { + ok = 0; + } else { + client_normal_count++; + } + } + rfbReleaseClientIterator(iter); + + return ok; +} + +char *list_clients(void) { + rfbClientIteratorPtr iter; + rfbClientPtr cl; + char *list, tmp[256]; + int count = 0; + + if (!screen) { + return strdup(""); + } + + iter = rfbGetClientIterator(screen); + while( (cl = rfbClientIteratorNext(iter)) ) { + client_set_net(cl); + count++; + } + rfbReleaseClientIterator(iter); + + /* + * each client: + * ::::::::