diff options
Diffstat (limited to 'x11vnc/misc/enhanced_tightvnc_viewer/src')
| -rw-r--r-- | x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch | 3902 |
1 files changed, 3482 insertions, 420 deletions
diff --git a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch index f0fd036..5af9ea9 100644 --- a/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch +++ b/x11vnc/misc/enhanced_tightvnc_viewer/src/patches/tight-vncviewer-full.patch @@ -664,7 +664,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/Vncviewer vnc_unixsrc/vncview + diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/vncviewer/argsresources.c --- vnc_unixsrc.orig/vncviewer/argsresources.c 2007-02-04 17:10:31.000000000 -0500 -+++ vnc_unixsrc/vncviewer/argsresources.c 2008-12-30 19:22:59.000000000 -0500 ++++ vnc_unixsrc/vncviewer/argsresources.c 2009-05-31 17:50:18.000000000 -0400 @@ -31,9 +31,9 @@ char *fallback_resources[] = { @@ -739,10 +739,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v <ButtonPress>: SendRFBEvent()\\n\ <ButtonRelease>: SendRFBEvent()\\n\ <Motion>: SendRFBEvent()\\n\ -@@ -58,23 +110,112 @@ +@@ -58,23 +110,123 @@ "*serverDialog.dialog.value.translations: #override\\n\ <Key>Return: ServerDialogDone()", ++ "*userDialog.dialog.label: Username:", ++ "*userDialog.dialog.value:", ++ "*userDialog.dialog.value.translations: #override\\n\ ++ <Key>Return: UserDialogDone()", ++ + "*scaleDialog.dialog.label: Scale: Enter 'none' (same as '1' or '1.0'),\\na geometry WxH (e.g. 1280x1024), or\\na fraction (e.g. 0.75 or 3/4).\\nUse 'fit' for full screen size.\\nUse 'auto' to match window size.\\nCurrent value:", + "*scaleDialog.dialog.value:", + "*scaleDialog.dialog.value.translations: #override\\n\ @@ -835,6 +840,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + "*scaleN.buttonForm.Command.borderWidth: 0", + "*scaleN.buttonForm.Toggle.borderWidth: 0", + ++ "*turboVNC.title: TurboVNC", ++ "*turboVNC*background: grey", ++ "*turboVNC*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", ++ "*turboVNC.buttonForm.Command.borderWidth: 0", ++ "*turboVNC.buttonForm.Toggle.borderWidth: 0", ++ + "*quality.title: quality", + "*quality*background: grey", + "*quality*font: -*-helvetica-medium-r-*-*-12-*-*-*-*-*-*-*", @@ -852,12 +863,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v <KeyPress>: SendRFBEvent() HidePopup()", - "*popupButtonCount: 8", -+ "*popupButtonCount: 38", -+ "*popupButtonBreak: 19", ++ "*popupButtonCount: 42", ++ "*popupButtonBreak: 21", "*popup*button1.label: Dismiss popup", "*popup*button1.translations: #override\\n\ -@@ -84,7 +225,7 @@ +@@ -84,7 +236,7 @@ "*popup*button2.translations: #override\\n\ <Btn1Down>,<Btn1Up>: Quit()", @@ -866,7 +877,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v "*popup*button3.type: toggle", "*popup*button3.translations: #override\\n\ <Visible>: SetFullScreenState()\\n\ -@@ -105,16 +246,332 @@ +@@ -105,16 +257,418 @@ "*popup*button7.label: Send ctrl-alt-del", "*popup*button7.translations: #override\\n\ <Btn1Down>,<Btn1Up>: SendRFBEvent(keydown,Control_L)\ @@ -945,109 +956,195 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + <Visible>: SetNOJPEGState()\\n\ + <Btn1Down>,<Btn1Up>: toggle() ToggleJPEG() HidePopup()", + -+ "*popup*button20.label: Full Color", -+ "*popup*button20.type: toggle", ++ "*popup*button20.label: TurboVNC Settings", + "*popup*button20.translations: #override\\n\ -+ <Visible>: SetFullColorState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()", ++ <Btn1Down>,<Btn1Up>: HidePopup() ShowTurboVNC()", + -+ "*popup*button21.label: Grey Scale (16 & 8-bpp)", ++ "*popup*button21.label: Pipeline Updates", + "*popup*button21.type: toggle", + "*popup*button21.translations: #override\\n\ -+ <Visible>: SetGreyScaleState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()", ++ <Visible>: SetPipelineUpdates()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() TogglePipelineUpdates() HidePopup()", + -+ "*popup*button22.label: 16 bit color (BGR565)", ++ "*popup*button22.label: Full Color", + "*popup*button22.type: toggle", + "*popup*button22.translations: #override\\n\ -+ <Visible>: Set16bppState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()", ++ <Visible>: SetFullColorState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() ToggleFullColor() HidePopup()", + -+ "*popup*button23.label: 8 bit color (BGR233)", ++ "*popup*button23.label: Grey Scale (16 & 8-bpp)", + "*popup*button23.type: toggle", + "*popup*button23.translations: #override\\n\ -+ <Visible>: Set8bppState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()", ++ <Visible>: SetGreyScaleState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() ToggleGreyScale() HidePopup()", + -+ "*popup*button24.label: - 256 colors", ++ "*popup*button24.label: 16 bit color (BGR565)", + "*popup*button24.type: toggle", + "*popup*button24.translations: #override\\n\ -+ <Visible>: Set256ColorsState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()", ++ <Visible>: Set16bppState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() Toggle16bpp() HidePopup()", + -+ "*popup*button25.label: - 64 colors", ++ "*popup*button25.label: 8 bit color (BGR233)", + "*popup*button25.type: toggle", + "*popup*button25.translations: #override\\n\ -+ <Visible>: Set64ColorsState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()", ++ <Visible>: Set8bppState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() Toggle8bpp() HidePopup()", + -+ "*popup*button26.label: - 8 colors", ++ "*popup*button26.label: - 256 colors", + "*popup*button26.type: toggle", + "*popup*button26.translations: #override\\n\ -+ <Visible>: Set8ColorsState()\\n\ -+ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()", ++ <Visible>: Set256ColorsState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() Toggle256Colors() HidePopup()", + -+ "*popup*button27.label: Scale Viewer", ++ "*popup*button27.label: - 64 colors", ++ "*popup*button27.type: toggle", + "*popup*button27.translations: #override\\n\ -+ <Btn1Down>,<Btn1Up>: HidePopup() SetScale()", ++ <Visible>: Set64ColorsState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() Toggle64Colors() HidePopup()", + -+ "*popup*button28.label: Escape Keys: Toggle", ++ "*popup*button28.label: - 8 colors", + "*popup*button28.type: toggle", + "*popup*button28.translations: #override\\n\ ++ <Visible>: Set8ColorsState()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() Toggle8Colors() HidePopup()", ++ ++ "*popup*button29.label: Scale Viewer", ++ "*popup*button29.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: HidePopup() SetScale()", ++ ++ "*popup*button30.label: Escape Keys: Toggle", ++ "*popup*button30.type: toggle", ++ "*popup*button30.translations: #override\\n\ + <Visible>: SetEscapeKeysState()\\n\ + <Btn1Down>, <Btn1Up>: toggle() ToggleEscapeActive() HidePopup()", + -+ "*popup*button29.label: Escape Keys: Help+Set", -+ "*popup*button29.translations: #override\\n\ ++ "*popup*button31.label: Escape Keys: Help+Set", ++ "*popup*button31.translations: #override\\n\ + <Btn1Down>, <Btn1Up>: HidePopup() SetEscapeKeys()", + -+ "*popup*button30.label: Set Y Crop (y-max)", -+ "*popup*button30.translations: #override\\n\ ++ "*popup*button32.label: Set Y Crop (y-max)", ++ "*popup*button32.translations: #override\\n\ + <Btn1Down>,<Btn1Up>: HidePopup() SetYCrop()", + -+ "*popup*button31.label: Set Scrollbar Width", -+ "*popup*button31.translations: #override\\n\ ++ "*popup*button33.label: Set Scrollbar Width", ++ "*popup*button33.translations: #override\\n\ + <Btn1Down>,<Btn1Up>: HidePopup() SetScbar()", + -+ "*popup*button32.label: XGrabServer", -+ "*popup*button32.type: toggle", -+ "*popup*button32.translations: #override\\n\ ++ "*popup*button34.label: XGrabServer", ++ "*popup*button34.type: toggle", ++ "*popup*button34.translations: #override\\n\ + <Visible>: SetXGrabState()\\n\ + <Btn1Down>,<Btn1Up>: toggle() ToggleXGrab() HidePopup()", + -+ "*popup*button33.label: UltraVNC Extensions:", -+ "*popup*button33.translations: #override\\n\ ++ "*popup*button35.label: UltraVNC Extensions:", ++ "*popup*button35.translations: #override\\n\ + <Btn1Down>,<Btn1Up>: HidePopup()", + -+ "*popup*button34.label: - Set 1/n Server Scale", -+ "*popup*button34.translations: #override\\n\ ++ "*popup*button36.label: - Set 1/n Server Scale", ++ "*popup*button36.translations: #override\\n\ + <Btn1Down>,<Btn1Up>: HidePopup() ShowScaleN()", + -+ "*popup*button35.label: - Text Chat", -+ "*popup*button35.type: toggle", -+ "*popup*button35.translations: #override\\n\ ++ "*popup*button37.label: - Text Chat", ++ "*popup*button37.type: toggle", ++ "*popup*button37.translations: #override\\n\ + <Visible>: SetTextChatState()\\n\ + <Btn1Down>,<Btn1Up>: toggle() ToggleTextChat() HidePopup()", + -+ "*popup*button36.label: - File Transfer", -+ "*popup*button36.type: toggle", -+ "*popup*button36.translations: #override\\n\ ++ "*popup*button38.label: - File Transfer", ++ "*popup*button38.type: toggle", ++ "*popup*button38.translations: #override\\n\ + <Visible>: SetFileXferState()\\n\ + <Btn1Down>,<Btn1Up>: toggle() ToggleFileXfer() HidePopup()", + -+ "*popup*button37.label: - Single Window", -+ "*popup*button37.type: toggle", -+ "*popup*button37.translations: #override\\n\ ++ "*popup*button39.label: - Single Window", ++ "*popup*button39.type: toggle", ++ "*popup*button39.translations: #override\\n\ + <Visible>: SetSingleWindowState()\\n\ + <Btn1Down>,<Btn1Up>: toggle() ToggleSingleWindow() HidePopup()", + -+ "*popup*button38.label: - Disable Remote Input", -+ "*popup*button38.type: toggle", -+ "*popup*button38.translations: #override\\n\ ++ "*popup*button40.label: - Disable Remote Input", ++ "*popup*button40.type: toggle", ++ "*popup*button40.translations: #override\\n\ + <Visible>: SetServerInputState()\\n\ + <Btn1Down>,<Btn1Up>: toggle() ToggleServerInput() HidePopup()", + -+// "*popup*button3x.label:", ++ "*popup*button41.label: Send Clipboard not Primary", ++ "*popup*button41.type: toggle", ++ "*popup*button41.translations: #override\\n\ ++ <Visible>: SetSendClipboard()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() ToggleSendClipboard() HidePopup()", ++ ++ "*popup*button42.label: Send Selection Every time", ++ "*popup*button42.type: toggle", ++ "*popup*button42.translations: #override\\n\ ++ <Visible>: SetSendAlways()\\n\ ++ <Btn1Down>,<Btn1Up>: toggle() ToggleSendAlways() HidePopup()", ++ ++ "*turboVNC*button0.label: Dismiss", ++ "*turboVNC*button0.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: HideTurboVNC()", ++ ++ "*turboVNC*button1.label: High Quality (LAN)", ++ "*turboVNC*button1.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(1)", ++ ++ "*turboVNC*button2.label: Medium Quality", ++ "*turboVNC*button2.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(2)", ++ ++ "*turboVNC*button3.label: Low Quality (WAN)", ++ "*turboVNC*button3.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(3)", ++ ++ "*turboVNC*button4.label: Lossless (Gigabit)", ++ "*turboVNC*button4.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(4)", ++ ++ "*turboVNC*button5.label: Lossless Zlib (WAN)", ++ "*turboVNC*button5.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(5)", ++ ++ "*turboVNC*button6.label: Subsampling:", ++ ++ "*turboVNC*button7.label: - None", ++ "*turboVNC*button7.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(6)", ++ ++ "*turboVNC*button8.label: - 2X", ++ "*turboVNC*button8.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(7)", ++ ++ "*turboVNC*button9.label: - 4X", ++ "*turboVNC*button9.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(8)", ++ ++ "*turboVNC*button10.label: - Gray", ++ "*turboVNC*button10.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(9)", ++ ++ "*turboVNC*button11.label: Lossless Refresh", ++ "*turboVNC*button11.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SetTurboVNC(10)", ++ ++ "*turboVNC*button12.label: Lossy Refresh", ++ "*turboVNC*button12.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: SendRFBEvent(fbupdate)", ++ ++ "*turboVNC*buttonNone.label: Not Compiled with\\nTurboVNC Support.", ++ "*turboVNC*buttonNone.translations: #override\\n\ ++ <Btn1Down>,<Btn1Up>: HideTurboVNC()", ++ ++ "*qualLabel.label: JPEG Image Quality:", ++ "*qualBar.length: 100", ++ "*qualBar.width: 130", ++ "*qualBar.orientation: horizontal", ++ "*qualBar.translations: #override\\n\ ++ <Btn1Down>: StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ ++ <Btn1Motion>: MoveThumb() NotifyThumb()\\n\ ++ <Btn3Down>: StartScroll(Continuous) MoveThumb() NotifyThumb()\\n\ ++ <Btn3Motion>: MoveThumb() NotifyThumb()", ++ ++ "*qualText.label: 000", + + "*scaleN*button0.label: Dismiss", + "*scaleN*button0.translations: #override\\n\ @@ -1204,7 +1301,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v NULL }; -@@ -124,7 +581,7 @@ +@@ -124,7 +678,7 @@ * from a dialog box. */ @@ -1213,7 +1310,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v int vncServerPort = 0; -@@ -135,6 +592,7 @@ +@@ -135,6 +689,7 @@ */ AppData appData; @@ -1221,13 +1318,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v static XtResource appDataResourceList[] = { {"shareDesktop", "ShareDesktop", XtRBool, sizeof(Bool), -@@ -155,14 +613,38 @@ +@@ -155,14 +710,41 @@ {"userLogin", "UserLogin", XtRString, sizeof(String), XtOffsetOf(AppData, userLogin), XtRImmediate, (XtPointer) 0}, + {"unixPW", "UnixPW", XtRString, sizeof(String), + XtOffsetOf(AppData, unixPW), XtRImmediate, (XtPointer) 0}, + ++ {"msLogon", "MSLogon", XtRString, sizeof(String), ++ XtOffsetOf(AppData, msLogon), XtRImmediate, (XtPointer) 0}, ++ + {"repeaterUltra", "RepeaterUltra", XtRString, sizeof(String), + XtOffsetOf(AppData, repeaterUltra), XtRImmediate, (XtPointer) 0}, + @@ -1262,7 +1362,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"nColours", "NColours", XtRInt, sizeof(int), XtOffsetOf(AppData, nColours), XtRImmediate, (XtPointer) 256}, -@@ -179,9 +661,12 @@ +@@ -179,9 +761,12 @@ {"requestedDepth", "RequestedDepth", XtRInt, sizeof(int), XtOffsetOf(AppData, requestedDepth), XtRImmediate, (XtPointer) 0}, @@ -1276,7 +1376,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"wmDecorationWidth", "WmDecorationWidth", XtRInt, sizeof(int), XtOffsetOf(AppData, wmDecorationWidth), XtRImmediate, (XtPointer) 4}, -@@ -191,6 +676,9 @@ +@@ -191,6 +776,9 @@ {"popupButtonCount", "PopupButtonCount", XtRInt, sizeof(int), XtOffsetOf(AppData, popupButtonCount), XtRImmediate, (XtPointer) 0}, @@ -1286,16 +1386,22 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"debug", "Debug", XtRBool, sizeof(Bool), XtOffsetOf(AppData, debug), XtRImmediate, (XtPointer) False}, -@@ -207,7 +695,7 @@ +@@ -206,11 +794,13 @@ + {"bumpScrollPixels", "BumpScrollPixels", XtRInt, sizeof(int), XtOffsetOf(AppData, bumpScrollPixels), XtRImmediate, (XtPointer) 20}, ++ /* hardwired compress -1 vs . 7 */ {"compressLevel", "CompressionLevel", XtRInt, sizeof(int), -- XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1}, -+ XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) 7}, + XtOffsetOf(AppData, compressLevel), XtRImmediate, (XtPointer) -1}, ++ /* hardwired quality was 6 */ {"qualityLevel", "QualityLevel", XtRInt, sizeof(int), - XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6}, -@@ -218,14 +706,63 @@ +- XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) 6}, ++ XtOffsetOf(AppData, qualityLevel), XtRImmediate, (XtPointer) -1}, + + {"enableJPEG", "EnableJPEG", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, enableJPEG), XtRImmediate, (XtPointer) True}, +@@ -218,14 +808,85 @@ {"useRemoteCursor", "UseRemoteCursor", XtRBool, sizeof(Bool), XtOffsetOf(AppData, useRemoteCursor), XtRImmediate, (XtPointer) True}, @@ -1352,20 +1458,43 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"scale", "Scale", XtRString, sizeof(String), + XtOffsetOf(AppData, scale), XtRImmediate, (XtPointer) 0}, + -+ {"escapeKeys", "escapeKeys", XtRString, sizeof(String), ++ {"pipelineUpdates", "PipelineUpdates", XtRBool, sizeof(Bool), ++ XtOffsetOf(AppData, pipelineUpdates), XtRImmediate, (XtPointer) ++#ifdef TURBOVNC ++ True}, ++#else ++#if 0 ++ False}, ++#else ++ True}, ++#endif ++#endif ++ ++ {"sendClipboard", "SendClipboard", XtRBool, sizeof(Bool), ++ XtOffsetOf(AppData, sendClipboard), XtRImmediate, (XtPointer) False}, ++ ++ {"sendAlways", "SendAlways", XtRBool, sizeof(Bool), ++ XtOffsetOf(AppData, sendAlways), XtRImmediate, (XtPointer) False}, ++ ++ {"recvText", "RecvText", XtRString, sizeof(String), ++ XtOffsetOf(AppData, recvText), XtRImmediate, (XtPointer) 0}, ++ ++ {"escapeKeys", "EscapeKeys", XtRString, sizeof(String), + XtOffsetOf(AppData, escapeKeys), XtRImmediate, (XtPointer) 0}, + + {"escapeActive", "EscapeActive", XtRBool, sizeof(Bool), + XtOffsetOf(AppData, escapeActive), XtRImmediate, (XtPointer) False} ++ + /* check commas */ }; -@@ -242,8 +779,25 @@ +@@ -242,8 +903,26 @@ {"-noraiseonbeep", "*raiseOnBeep", XrmoptionNoArg, "False"}, {"-passwd", "*passwordFile", XrmoptionSepArg, 0}, {"-user", "*userLogin", XrmoptionSepArg, 0}, + {"-unixpw", "*unixPW", XrmoptionSepArg, 0}, ++ {"-mslogon", "*msLogon", XrmoptionSepArg, 0}, + {"-repeater", "*repeaterUltra", XrmoptionSepArg, 0}, + {"-ultradsm", "*ultraDSM", XrmoptionNoArg, "True"}, + {"-rfbversion", "*rfbVersion", XrmoptionSepArg, 0}, @@ -1388,7 +1517,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"-owncmap", "*forceOwnCmap", XrmoptionNoArg, "True"}, {"-truecolor", "*forceTrueColour", XrmoptionNoArg, "True"}, {"-truecolour", "*forceTrueColour", XrmoptionNoArg, "True"}, -@@ -253,8 +807,22 @@ +@@ -253,8 +932,27 @@ {"-nojpeg", "*enableJPEG", XrmoptionNoArg, "False"}, {"-nocursorshape", "*useRemoteCursor", XrmoptionNoArg, "False"}, {"-x11cursor", "*useX11Cursor", XrmoptionNoArg, "True"}, @@ -1409,17 +1538,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"-termchat", "*termChat", XrmoptionNoArg, "True"}, + {"-chatonly", "*chatOnly", XrmoptionNoArg, "True"}, + {"-scale", "*scale", XrmoptionSepArg, 0}, -+ {"-escapekeys", "*escapeKeys", XrmoptionSepArg, 0} ++ {"-escape", "*escapeKeys", XrmoptionSepArg, 0}, ++ {"-sendclipboard", "*sendClipboard", XrmoptionNoArg, "True"}, ++ {"-sendalways", "*sendAlways", XrmoptionNoArg, "True"}, ++ {"-recvtext", "*recvText", XrmoptionSepArg, 0}, ++ {"-pipeline", "*pipelineUpdates", XrmoptionNoArg, "True"}, ++ {"-nopipeline", "*pipelineUpdates", XrmoptionNoArg, "False"} }; int numCmdLineOptions = XtNumber(cmdLineOptions); -@@ -267,16 +835,88 @@ +@@ -267,16 +965,98 @@ static XtActionsRec actions[] = { {"SendRFBEvent", SendRFBEvent}, {"ShowPopup", ShowPopup}, + {"Noop", Noop}, {"HidePopup", HidePopup}, + {"HideScaleN", HideScaleN}, ++ {"HideTurboVNC", HideTurboVNC}, + {"HideQuality", HideQuality}, + {"HideCompress", HideCompress}, {"ToggleFullScreen", ToggleFullScreen}, @@ -1431,6 +1566,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v {"SelectionFromVNC", SelectionFromVNC}, {"SelectionToVNC", SelectionToVNC}, {"ServerDialogDone", ServerDialogDone}, ++ {"UserDialogDone", UserDialogDone}, + {"YCropDialogDone", YCropDialogDone}, + {"ScbarDialogDone", ScbarDialogDone}, + {"ScaleNDialogDone", ScaleNDialogDone}, @@ -1457,6 +1593,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"ToggleBell", ToggleBell}, + {"ToggleRawLocal", ToggleRawLocal}, + {"ToggleServerInput", ToggleServerInput}, ++ {"TogglePipelineUpdates", TogglePipelineUpdates}, ++ {"ToggleSendClipboard", ToggleSendClipboard}, ++ {"ToggleSendAlways", ToggleSendAlways}, + {"ToggleSingleWindow", ToggleSingleWindow}, + {"ToggleTextChat", ToggleTextChat}, + {"ToggleFileXfer", ToggleFileXfer}, @@ -1466,9 +1605,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"SetYCrop", SetYCrop}, + {"SetScbar", SetScbar}, + {"ShowScaleN", ShowScaleN}, ++ {"ShowTurboVNC", ShowTurboVNC}, + {"ShowQuality", ShowQuality}, + {"ShowCompress", ShowCompress}, + {"SetScaleN", SetScaleN}, ++ {"SetTurboVNC", SetTurboVNC}, + {"SetQuality", SetQuality}, + {"SetCompress", SetCompress}, + {"Set8bppState", Set8bppState}, @@ -1491,6 +1632,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + {"SetBellState", SetBellState}, + {"SetRawLocalState", SetRawLocalState}, + {"SetServerInputState", SetServerInputState}, ++ {"SetPipelineUpdates", SetPipelineUpdates}, ++ {"SetSendClipboard", SetSendClipboard}, ++ {"SetSendAlways", SetSendAlways}, + {"SetSingleWindowState", SetSingleWindowState}, + {"SetTextChatState", SetTextChatState}, + {"SetFileXferState", SetFileXferState}, @@ -1502,7 +1646,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v }; -@@ -302,11 +942,14 @@ +@@ -302,11 +1082,14 @@ void usage(void) { @@ -1519,7 +1663,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v " %s [<OPTIONS>] -listen [<DISPLAY#>]\n" " %s -help\n" "\n" -@@ -332,10 +975,302 @@ +@@ -332,10 +1115,339 @@ " -autopass\n" "\n" "Option names may be abbreviated, e.g. -bgr instead of -bgr233.\n" @@ -1623,8 +1767,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " -rawlocal Prefer raw encoding for localhost, default is\n" + " no, i.e. assumes you have a SSH tunnel instead.\n" + "\n" ++ " -sendclipboard Send the X CLIPBOARD selection (i.e. Ctrl+C,\n" ++ " Ctrl+V) instead of the X PRIMARY selection (mouse\n" ++ " select and middle button paste.)\n" ++ "\n" ++ " -sendalways Whenever the mouse enters the VNC viewer main\n" ++ " window, send the selection to the VNC server even if\n" ++ " it has not changed. This is like the Xt resource\n" ++ " translation SelectionToVNC(always)\n" ++ "\n" ++ " -recvtext str When cut text is received from the VNC server,\n" ++ " ssvncviewer will set both the X PRIMARY and the\n" ++ " X CLIPBOARD local selections. To control which\n" ++ " is set, specify 'str' as 'primary', 'clipboard',\n" ++ " or 'both' (the default.)\n" ++ "\n" + " -graball Grab the entire X server when in fullscreen mode,\n" + " needed by some old window managers like fvwm2.\n" ++ "\n" + " -popupfix Warp the popup back to the pointer position,\n" + " needed by some old window managers like fvwm2.\n" + "\n" @@ -1707,6 +1867,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " RFB data sent so as to work with the UltraVNC Server. For\n" + " some reason, each RFB msg type must be sent twice under DSM.\n" + "\n" ++ " -mslogon user Use Windows MS Logon to an UltraVNC server. Supply the\n" ++ " username or \"1\" to be prompted. The default is to\n" ++ " autodetect the UltraVNC MS Logon server and prompt for\n" ++ " the username and password.\n" ++ "\n" ++ " IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman\n" ++ " exchange is very weak and can be brute forced to recover\n" ++ " your username and password in a few hours or seconds of CPU\n" ++ " time. To be safe, be sure to use an additional encrypted\n" ++ " tunnel (e.g. SSL or SSH) for the entire VNC session.\n" ++ "\n" + " -chatonly Try to be a client that only does UltraVNC text chat. This\n" + " mode is used by x11vnc to present a chat window on the\n" + " physical X11 console (i.e. chat with the person at the\n" @@ -1721,6 +1892,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " keybindings and Popup menu) Then point to the file via\n" + " XENVIRONMENT or XAPPLRESDIR.\n" + "\n" ++ " -pipeline Like TurboVNC, request the next framebuffer update as soon\n" ++ " as possible instead of waiting until the end of the current\n" ++ " framebuffer update coming in. Helps 'pipeline' the updates.\n" ++ " This is currently the default, use -nopipeline to disable.\n" ++ "\n" + " -escape str This sets the 'Escape Keys' modifier sequence and enables\n" + " escape keys mode. When the modifier keys escape sequence\n" + " is held down, the next keystroke is interpreted locally\n" @@ -1788,6 +1964,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " Quality Level ~ -quality (both Tight and ZYWRLE)\n" + " Compress Level ~ -compresslevel\n" + " Disable JPEG: ~ -nojpeg (Tight)\n" ++ " Pipeline Updates ~ -pipeline\n" ++ "\n" + " Full Color as many colors as local screen allows.\n" + " Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only.\n" + " 16 bit color (BGR565) ~ -16bpp / -bgr565\n" @@ -1815,6 +1993,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + " Note: the Ultravnc extensions only apply to servers that support\n" + " them. x11vnc/libvncserver supports some of them.\n" + "\n" ++ " Send Clipboard not Primary ~ -sendclipboard\n" ++ " Send Selection Every time ~ -sendalways\n" ++ "\n" + "\n", programName, programName, programName, programName, programName, programName, programName); exit(1); } @@ -1824,7 +2005,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v /* -@@ -347,73 +1282,191 @@ +@@ -347,73 +1459,214 @@ void GetArgsAndResources(int argc, char **argv) { @@ -1906,6 +2087,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + if (appData.escapeKeys != NULL) { + appData.escapeActive = True; + } ++ if (getenv("VNCVIEWER_SEND_CLIPBOARD")) { ++ appData.sendClipboard = True; ++ } ++ if (getenv("VNCVIEWER_SEND_ALWAYS")) { ++ appData.sendAlways = True; ++ } ++ if (getenv("VNCVIEWER_RECV_TEXT")) { ++ char *s = getenv("VNCVIEWER_RECV_TEXT"); ++ if (!strcasecmp(s, "clipboard")) { ++ appData.recvText = strdup("clipboard"); ++ } else if (!strcasecmp(s, "primary")) { ++ appData.recvText = strdup("primary"); ++ } else if (!strcasecmp(s, "both")) { ++ appData.recvText = strdup("both"); ++ } ++ } ++ if (getenv("VNCVIEWER_PIPELINE_UPDATES")) { ++ appData.pipelineUpdates = True; ++ } else if (getenv("VNCVIEWER_NO_PIPELINE_UPDATES")) { ++ appData.pipelineUpdates = False; ++ } + + if (appData.useBGR233 && appData.useBGR565) { + appData.useBGR233 = 0; @@ -2014,7 +2216,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/argsresources.c vnc_unixsrc/v + + if (argc == 1) { + vncServerName = DoServerDialog(); -+ appData.passwordDialog = True; ++ if (!isatty(0)) { ++ appData.passwordDialog = True; ++ } + } else if (argc != 2) { + usage(); + } else { @@ -2474,22 +2678,26 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/corre.c vnc_unixsrc/vncviewer +#undef FillRectangle diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cp_it vnc_unixsrc/vncviewer/cp_it --- vnc_unixsrc.orig/vncviewer/cp_it 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/cp_it 2007-03-24 10:05:16.000000000 -0400 -@@ -0,0 +1,14 @@ ++++ vnc_unixsrc/vncviewer/cp_it 2009-03-06 20:02:05.000000000 -0500 +@@ -0,0 +1,18 @@ +#!/bin/sh + +dest=/dist/bin/vncviewerz-1.3dev5-resize +suc "cp -p $dest $dest.back; mv $dest $dest.unlink; mv $dest.back $dest; rm $dest.unlink" +strip ./vncviewer -+cat ./vncviewer > $dest ++cat ./vncviewer > $dest +touch -r ./vncviewer $dest +yy=/dist/src/apps/VNC/etc/libvncserver_cvs/expts/etv/ssvnc/bin/Linux.i686/vncviewer +mv $yy $yy.unlink +cp -p ./vncviewer $yy ++mv $yy.turbovnc $yy.unlink.turbovnc +cp -p ./vncviewer $HOME/etv_col/Linux.i686 -+chmod 755 $yy -+rm -f $yy.unlink -+ls -l ./vncviewer $dest $yy $HOME/etv_col/Linux.i686/vncviewer ++cp -p ./vncviewer.turbovnc $yy.turbovnc ++cp -p ./vncviewer.turbovnc $HOME/etv_col/Linux.i686/vncviewer.turbovnc ++chmod 755 $yy* ++ ++rm -f $yy.unlink* ++ls -l ./vncviewer* $dest $yy* $HOME/etv_col/Linux.i686/vncviewer* diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewer/cursor.c --- vnc_unixsrc.orig/vncviewer/cursor.c 2003-01-15 04:46:52.000000000 -0500 +++ vnc_unixsrc/vncviewer/cursor.c 2008-10-18 09:35:02.000000000 -0400 @@ -3400,8 +3608,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/cursor.c vnc_unixsrc/vncviewe - diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncviewer/desktop.c --- vnc_unixsrc.orig/vncviewer/desktop.c 2004-05-28 13:29:29.000000000 -0400 -+++ vnc_unixsrc/vncviewer/desktop.c 2008-12-30 19:33:58.000000000 -0500 -@@ -28,28 +28,473 @@ ++++ vnc_unixsrc/vncviewer/desktop.c 2009-03-26 23:27:45.000000000 -0400 +@@ -28,28 +28,487 @@ #include <X11/extensions/XShm.h> #endif @@ -3500,11 +3708,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + frac_y = frac_x; + } + -+ if (fx != NULL) { -+ *fx = frac_x; -+ } -+ if (fy != NULL) { -+ *fy = frac_y; ++ if (frac_y > 0.0 && frac_x > 0.0) { ++ if (fx != NULL) { ++ *fx = frac_x; ++ } ++ if (fy != NULL) { ++ *fy = frac_y; ++ } ++ } else { ++ if (appData.scale) { ++ fprintf(stderr, "Invalid scale string: '%s'\n", appData.scale); ++ } else { ++ fprintf(stderr, "Invalid scale string.\n"); ++ } ++ appData.scale = NULL; + } +} + @@ -3581,7 +3798,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + frac_x = frac_y = 1.0; + } else { + get_scale_values(&frac_x, &frac_y); -+ if (frac_x < 0.0) { ++ if (frac_x < 0.0 || frac_y < 0.0) { + create_image(); + return; + } @@ -3778,16 +3995,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + } else { + double frac_x = -1.0, frac_y = -1.0; + ++ get_scale_values(&frac_x, &frac_y); ++ ++ if (frac_x < 0.0 || frac_y < 0.0) { ++ fprintf(stderr, "Cannot figure out scale factor!\n"); ++ goto bork; ++ } ++ + scale_factor_x = 0.0; + scale_factor_y = 0.0; + scale_x = 0; + scale_y = 0; + -+ get_scale_values(&frac_x, &frac_y); + -+ if (frac_x < 0.0) { -+ fprintf(stderr, "Cannot figure out scale factor!\n"); -+ } else { ++ if (1) { + int w, h, hyc; + + w = scale_round(si.framebufferWidth, frac_x); @@ -3828,6 +4049,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + } + } + } ++ bork: + try_create_image(); +} + @@ -3879,7 +4101,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview /* * DesktopInitBeforeRealization creates the "desktop" widget and the viewport -@@ -59,91 +504,1012 @@ +@@ -59,91 +518,1016 @@ void DesktopInitBeforeRealization() { @@ -3896,8 +4118,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + + if (appData.scale != NULL) { + get_scale_values(&frac_x, &frac_y); -+ w = scale_round(w, frac_x); -+ h = scale_round(h, frac_y); ++ if (frac_x > 0.0 && frac_y > 0.0) { ++ w = scale_round(w, frac_x); ++ h = scale_round(h, frac_y); ++ } else { ++ appData.scale = NULL; ++ } + } - form = XtVaCreateManagedWidget("form", formWidgetClass, toplevel, @@ -3974,8 +4200,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + } + + create_image(); -+} -+ + } + +static Widget scrollbar_y = NULL; + +static int xsst = 2; @@ -3995,8 +4221,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + float t = 0.0; + XtVaSetValues(w, XtNtopOfThumb, &t, NULL); + } - } - ++} ++ +static XtCallbackProc Jumped(Widget w, XtPointer closure, XtPointer call_data) { + float top = *((float *) call_data); + Position x, y; @@ -4278,7 +4504,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview +#else +#define nfix(i, n) ( i < 0 ? 0 : ( (i >= n) ? (n - 1) : i ) ) +#endif -+ + +- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); +int scale_round(int len, double fac) { + double eps = 0.000001; + @@ -4351,8 +4578,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + /* try to avoid problems with bleeding... */ + sbdy = (int) (2.0 * fmax * sbdy); + } - -- XChangeWindowAttributes(dpy, desktopWin, valuemask, &attr); ++ + //fprintf(stderr, "scale_rect: %dx%d+%d+%d\n", *pw, *ph, *px, *py); + + *px = (int) (*px * factor_x); @@ -4954,7 +5180,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview /* * HandleBasicDesktopEvent - deal with expose and leave events. -@@ -152,41 +1518,392 @@ +@@ -152,41 +1536,404 @@ static void HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) { @@ -4996,13 +5222,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + if (y + height < si.framebufferHeight) height++; + } + } -+ -+ if (x + width > si.framebufferWidth) { -+ width = si.framebufferWidth - x; -+ if (width <= 0) { -+ break; -+ } -+ } - if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) { - ev->xexpose.width = si.framebufferWidth - ev->xexpose.x; @@ -5017,6 +5236,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview - SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y, - ev->xexpose.width, ev->xexpose.height, False); - break; ++ if (x + width > si.framebufferWidth) { ++ width = si.framebufferWidth - x; ++ if (width <= 0) { ++ break; ++ } ++ } ++ + if (y + height > si.framebufferHeight) { + height = si.framebufferHeight - y; + if (height <= 0) { @@ -5088,6 +5314,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + fs_grab(1); + } + break; ++ case ClientMessage: ++ if (ev->xclient.window == XtWindow(desktop) && ev->xclient.message_type == XA_INTEGER && ++ ev->xclient.format == 8 && !strcmp(ev->xclient.data.b, "SendRFBUpdate")) { ++ SendIncrementalFramebufferUpdateRequest(); ++ } ++ break; } + check_things(); +} @@ -5212,7 +5444,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + fs = 1; + FullScreenOff(); + } -+ rescale_image(); ++ if (1) { ++ double fx, fy; ++ get_scale_values(&fx, &fy); ++ if (fx > 0.0 && fy > 0.0) { ++ rescale_image(); ++ } ++ } + if (fs) { + FullScreenOn(); + } @@ -5369,7 +5607,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview /* * SendRFBEvent is an action which sends an RFB event. It can be used in two -@@ -201,127 +1918,322 @@ +@@ -201,127 +1948,322 @@ * button2 down, 3 for both, etc). */ @@ -5800,7 +6038,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } -@@ -329,26 +2241,185 @@ +@@ -329,26 +2271,194 @@ * CreateDotCursor. */ @@ -5867,23 +6105,31 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 1, 1); + XFreePixmap(dpy, src); + XFreePixmap(dpy, msk); - -- return cursor; ++ + return cursor; +} +#endif + +int skip_maybe_sync = 0; +void maybe_sync(int width, int height) { -+ static int singles = 0; -+ if (skip_maybe_sync) { ++ static int singles = 0, always_skip = -1; ++ int singles_max = 32; ++ ++ if (always_skip < 0) { ++ if (getenv("SSVNC_NO_MAYBE_SYNC")) { ++ always_skip = 1; ++ } else { ++ always_skip = 0; ++ } ++ } ++ if (skip_maybe_sync || always_skip) { + return; + } + if (width > 1 || height > 1) { + XSync(dpy, False); + singles = 0; + } else { -+ if (++singles >= 32) { ++ if (++singles >= singles_max) { + singles = 0; + XSync(dpy, False); + } @@ -5983,7 +6229,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview + dst -= Bpl; + } + } -+ + +- return cursor; + if (image_scale && !did2) { + im = image; + Bpp = im->bits_per_pixel / 8; @@ -6002,7 +6249,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } -@@ -359,38 +2430,37 @@ +@@ -359,38 +2469,37 @@ void CopyDataToScreen(char *buf, int x, int y, int width, int height) { @@ -6070,7 +6317,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } -@@ -401,62 +2471,297 @@ +@@ -401,62 +2510,297 @@ static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height) { @@ -6424,10 +6671,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/desktop.c vnc_unixsrc/vncview } diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncviewer/dialogs.c --- vnc_unixsrc.orig/vncviewer/dialogs.c 2000-10-26 15:19:19.000000000 -0400 -+++ vnc_unixsrc/vncviewer/dialogs.c 2008-11-16 12:09:19.000000000 -0500 -@@ -26,6 +26,393 @@ ++++ vnc_unixsrc/vncviewer/dialogs.c 2009-04-15 14:12:13.000000000 -0400 +@@ -25,7 +25,395 @@ + #include <X11/Xaw/Dialog.h> static Bool serverDialogDone = False; ++static Bool userDialogDone = False; static Bool passwordDialogDone = False; +static Bool ycropDialogDone = False; +static Bool scaleDialogDone = False; @@ -6819,7 +7068,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview void ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) -@@ -44,11 +431,19 @@ +@@ -44,11 +432,19 @@ toplevel, NULL); dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); @@ -6839,7 +7088,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview serverDialogDone = False; while (!serverDialogDone) { -@@ -56,6 +451,7 @@ +@@ -56,6 +452,7 @@ } valueString = XawDialogGetValueString(dialog); @@ -6847,7 +7096,58 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview vncServerName = XtNewString(valueString); XtPopdown(pshell); -@@ -80,11 +476,19 @@ +@@ -63,6 +460,50 @@ + } + + void ++UserDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params) ++{ ++ userDialogDone = True; ++} ++ ++char * ++DoUserDialog() ++{ ++ Widget pshell, dialog; ++ char *userName; ++ char *valueString; ++ ++ pshell = XtVaCreatePopupShell("userDialog", transientShellWidgetClass, ++ toplevel, NULL); ++ dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); ++ ++ dialog_over(pshell); ++ ++ XtMoveWidget(pshell, WidthOfScreen(XtScreen(pshell))*2/5, ++ HeightOfScreen(XtScreen(pshell))*2/5); ++ XtPopup(pshell, XtGrabNonexclusive); ++ XtRealizeWidget(pshell); ++ ++ if (appData.popupFix) { ++ popupFixer(pshell); ++ } ++ //dialog_input(pshell); ++ wm_delete(pshell, "UserDialogDone()"); ++ ++ userDialogDone = False; ++ ++ while (!userDialogDone) { ++ XtAppProcessEvent(appContext, XtIMAll); ++ } ++ ++ valueString = XawDialogGetValueString(dialog); ++ rmNL(valueString); ++ userName = XtNewString(valueString); ++ ++ XtPopdown(pshell); ++ return userName; ++} ++ ++void + PasswordDialogDone(Widget w, XEvent *event, String *params, + Cardinal *num_params) + { +@@ -80,11 +521,19 @@ toplevel, NULL); dialog = XtVaCreateManagedWidget("dialog", dialogWidgetClass, pshell, NULL); @@ -6867,7 +7167,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/dialogs.c vnc_unixsrc/vncview passwordDialogDone = False; while (!passwordDialogDone) { -@@ -92,6 +496,7 @@ +@@ -92,6 +541,7 @@ } valueString = XawDialogGetValueString(dialog); @@ -8247,7 +8547,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/listen.c vnc_unixsrc/vncviewe /* diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/misc.c --- vnc_unixsrc.orig/vncviewer/misc.c 2003-01-15 02:58:32.000000000 -0500 -+++ vnc_unixsrc/vncviewer/misc.c 2008-10-14 22:32:04.000000000 -0400 ++++ vnc_unixsrc/vncviewer/misc.c 2009-03-26 23:10:56.000000000 -0400 @@ -33,12 +33,14 @@ Dimension dpyWidth, dpyHeight; @@ -8346,7 +8646,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/ + /* switched to not scaled */ + double frac_x, frac_y; + get_scale_values(&frac_x, &frac_y); -+ if (frac_x > 0.0) { ++ if (frac_x > 0.0 && frac_y > 0.0) { + w = scale_round(w, frac_x); + h = scale_round(h, frac_y); + } @@ -8642,14 +8942,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/misc.c vnc_unixsrc/vncviewer/ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer/popup.c --- vnc_unixsrc.orig/vncviewer/popup.c 2000-06-11 08:00:53.000000000 -0400 -+++ vnc_unixsrc/vncviewer/popup.c 2008-11-10 10:03:59.000000000 -0500 -@@ -25,22 +25,56 @@ ++++ vnc_unixsrc/vncviewer/popup.c 2009-04-15 15:44:22.000000000 -0400 +@@ -25,22 +25,59 @@ #include <X11/Xaw/Form.h> #include <X11/Xaw/Command.h> +#include <X11/Xaw/AsciiText.h> #include <X11/Xaw/Toggle.h> ++#include <X11/Xaw/Box.h> ++#include <X11/Xaw/Scrollbar.h> ++ Widget popup, fullScreenToggle; +void popupFixer(Widget wid) { @@ -8706,7 +9009,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer } -@@ -52,42 +86,546 @@ +@@ -52,42 +89,755 @@ }; void @@ -8823,6 +9126,131 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer + } +} + ++Widget turbovncW; ++ ++static Widget turboButtons[32]; ++ ++Widget qualtext, qualslider; ++ ++void UpdateQualSlider(void) { ++#ifdef TURBOVNC ++ char text[16]; ++ XawScrollbarSetThumb(qualslider, (float)appData.qualityLevel/100., 0.); ++ sprintf(text, "%3d", appData.qualityLevel); ++ XtVaSetValues(qualtext, XtNlabel, text, NULL); ++#endif ++} ++ ++void qualScrollProc(Widget w, XtPointer client, XtPointer p) { ++#ifdef TURBOVNC ++ float size, val; int qual, pos=(int)p; ++ XtVaGetValues(w, XtNshown, &size, XtNtopOfThumb, &val, 0); ++ if(pos<0) val-=.1; else val+=.1; ++ qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; ++ XawScrollbarSetThumb(w, val, 0.); ++ appData.qualityLevel=qual; ++ UpdateQual(); ++#endif ++} ++ ++void qualJumpProc(Widget w, XtPointer client, XtPointer p) { ++#ifdef TURBOVNC ++ float val=*(float *)p; int qual; ++ qual=(int)(val*100.); if(qual<1) qual=1; if(qual>100) qual=100; ++ appData.qualityLevel=qual; ++ UpdateQual(); ++#endif ++} ++ ++void UpdateSubsampButtons(void) { ++#ifdef TURBOVNC ++ int i; ++ for (i=7; i <= 10; i++) { ++ XtVaSetValues(turboButtons[i], XtNstate, 0, NULL); ++ } ++ if (appData.subsampLevel==TVNC_1X) { ++ i = 7; ++ } else if (appData.subsampLevel==TVNC_2X) { ++ i = 8; ++ } else if (appData.subsampLevel==TVNC_4X) { ++ i = 9; ++ } else if (appData.subsampLevel==TVNC_GRAY) { ++ i = 10; ++ } else { ++ return; ++ } ++ XtVaSetValues(turboButtons[i], XtNstate, 1, NULL); ++#endif ++} ++ ++void ++ShowTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) ++{ ++ UpdateSubsampButtons(); ++ UpdateQualSlider(); ++ if (appData.popupFix) { ++ popupFixer(turbovncW); ++ } else { ++ XtMoveWidget(turbovncW, event->xbutton.x_root, event->xbutton.y_root); ++ XtPopup(turbovncW, XtGrabNone); ++ } ++ if (appData.grabAll) { ++ XRaiseWindow(dpy, XtWindow(turbovncW)); ++ } ++ XSetWMProtocols(dpy, XtWindow(turbovncW), &wmDeleteWindow, 1); ++ XtOverrideTranslations(turbovncW, XtParseTranslationTable ("<Message>WM_PROTOCOLS: HideTurboVNC()")); ++} ++ ++void ++HideTurboVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) ++{ ++ XtPopdown(turbovncW); ++} ++ ++void ++CreateTurboVNC() { ++ Widget buttonForm, button, prevButton = NULL; ++ Widget label; ++ int i; ++ char buttonName[32]; ++ String buttonType; ++ ++ turbovncW = XtVaCreatePopupShell("turboVNC", transientShellWidgetClass, toplevel, NULL); ++ ++ buttonForm = XtVaCreateManagedWidget("buttonForm", formWidgetClass, turbovncW, NULL); ++ ++ for (i = 0; i <= 12; i++) { ++ sprintf(buttonName, "button%d", i); ++#ifndef TURBOVNC ++ if (i == 0) { ++ sprintf(buttonName, "buttonNone"); ++ } else if (i > 0) { ++ return; ++ } ++#endif ++ XtVaGetSubresources(buttonForm, (XtPointer)&buttonType, buttonName, ++ "Button", resources, 1, NULL); ++ ++ button = XtVaCreateManagedWidget(buttonName, toggleWidgetClass, ++ buttonForm, NULL); ++ turboButtons[i] = button; ++ XtVaSetValues(button, XtNfromVert, prevButton, ++ XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); ++ prevButton = button; ++ } ++ ++ label = XtCreateManagedWidget("qualLabel", toggleWidgetClass, buttonForm, NULL, 0); ++ XtVaSetValues(label, XtNfromVert, prevButton, XtNleft, XawChainLeft, XtNright, XawChainRight, NULL); ++ ++ qualslider = XtCreateManagedWidget("qualBar", scrollbarWidgetClass, buttonForm, NULL, 0); ++ XtVaSetValues(qualslider, XtNfromVert, label, XtNleft, XawChainLeft, NULL); ++ XtAddCallback(qualslider, XtNscrollProc, qualScrollProc, NULL) ; ++ XtAddCallback(qualslider, XtNjumpProc, qualJumpProc, NULL) ; ++ ++ qualtext = XtCreateManagedWidget("qualText", labelWidgetClass, buttonForm, NULL, 0); ++ XtVaSetValues(qualtext, XtNfromVert, label, XtNfromHoriz, qualslider, XtNright, XawChainRight, NULL); ++} ++ +Widget qualityW; + +void @@ -9270,6 +9698,90 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup.c vnc_unixsrc/vncviewer + + XtSetKeyboardFocus(chat, entry); +} ++ ++Widget msgwin, msgtext; ++ ++void AppendMsg(char *in) { ++ int len; ++ XawTextPosition beg, end; ++ static XawTextPosition pos = 0; ++ XawTextBlock txt; ++ ++ XawTextSetInsertionPoint(msgtext, pos); ++ beg = XawTextGetInsertionPoint(msgtext); ++ end = beg; ++ ++ txt.firstPos = 0; ++ txt.length = strlen(in); ++ txt.ptr = in; ++ txt.format = FMT8BIT; ++ ++ XawTextReplace(msgtext, beg, end, &txt); ++ XawTextSetInsertionPoint(msgtext, beg + txt.length); ++ ++ pos = XawTextGetInsertionPoint(msgtext); ++} ++ ++static msg_visible = 0; ++ ++void msg_dismiss_proc(Widget w, XtPointer client_data, XtPointer call_data) { ++ XtPopdown(msgwin); ++ msg_visible = 0; ++ XSync(dpy, False); ++ usleep(200 * 1000); ++} ++ ++void CreateMsg(char *msg, int wait) { ++ ++ Widget myform, dismiss; ++ char *p; ++ int i, n, run, wmax = 0; ++ Dimension w, h; ++ ++ n = 0; ++ run = 0; ++ p = msg; ++ while (*p != '\0') { ++ if (*p == '\n') { ++ run = 0; ++ n++; ++ } ++ run++; ++ if (run > wmax) wmax = run; ++ p++; ++ } ++ h = (Dimension) (n+2) * 14; ++ w = (Dimension) (wmax+10) * 8; ++ ++ msgwin = XtVaCreatePopupShell("Message", topLevelShellWidgetClass, toplevel, XtNmappedWhenManaged, False, NULL); ++ ++ myform = XtVaCreateManagedWidget("myform", formWidgetClass, msgwin, NULL); ++ ++ msgtext = XtVaCreateManagedWidget("msgtext", asciiTextWidgetClass, myform, ++ XtNresize, XawtextResizeBoth, XtNresizable, True, XtNwrap, XawtextWrapWord, ++ XtNscrollHorizontal, XawtextScrollNever, XtNscrollVertical, XawtextScrollAlways, ++ XtNwidth, w, XtNheight, h, XtNdisplayCaret, False, ++ XtNeditType, XawtextAppend, XtNtype, XawAsciiString, ++ XtNuseStringInPlace, False, NULL); ++ ++ dismiss = XtVaCreateManagedWidget("dismiss", commandWidgetClass, myform, XtNlabel, "OK", XtNfromVert, msgtext, NULL); ++ ++ AppendMsg(""); ++ AppendMsg(msg); ++ ++ XtAddCallback(dismiss, XtNcallback, msg_dismiss_proc, NULL); ++ ++ XtRealizeWidget(msgwin); ++ ++ XtPopup(msgwin, XtGrabNone); ++ ++ XSync(dpy, False); ++ msg_visible = 1; ++ while (wait && msg_visible) { ++ if (0) fprintf(stderr, "mv: %d\n", msg_visible); ++ XtAppProcessEvent(appContext, XtIMAll); ++ } ++} diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewer/popup_ad --- vnc_unixsrc.orig/vncviewer/popup_ad 1969-12-31 19:00:00.000000000 -0500 +++ vnc_unixsrc/vncviewer/popup_ad 2008-02-17 13:32:34.000000000 -0500 @@ -9296,7 +9808,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/popup_ad vnc_unixsrc/vncviewe +} diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncviewer/rfbproto.c --- vnc_unixsrc.orig/vncviewer/rfbproto.c 2008-09-05 19:51:24.000000000 -0400 -+++ vnc_unixsrc/vncviewer/rfbproto.c 2008-12-08 10:53:56.000000000 -0500 ++++ vnc_unixsrc/vncviewer/rfbproto.c 2009-05-31 13:29:44.000000000 -0400 @@ -23,6 +23,7 @@ * rfbproto.c - functions to deal with client side of RFB protocol. */ @@ -9360,7 +9872,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie static void ReadConnFailedReason(void); static long ReadCompactLen (void); -@@ -67,6 +109,13 @@ +@@ -67,6 +109,19 @@ static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData, int compressedLen); @@ -9368,23 +9880,62 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie +extern double scale_factor_x; +extern double scale_factor_y; + ++extern int skip_maybe_sync; ++ +int sent_FBU = 0; +int skip_XtUpdate = 0; +int skip_XtUpdateAll = 0; ++ ++static double dt_out = 0.0; ++double latency = 0.0; ++double connect_time = 0.0; int rfbsock; char *desktopName; -@@ -177,6 +226,9 @@ +@@ -75,6 +130,14 @@ + char *serverCutText = NULL; + Bool newServerCutText = False; + ++/* ultravnc mslogon */ ++#define rfbUltraVncMsLogon 0xfffffffa ++static Bool AuthUltraVncMsLogon(void); ++extern void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); ++extern void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key); ++extern void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key); ++extern unsigned int urandom(void); ++ + int endianTest = 1; + + static Bool tightVncProtocol = False; +@@ -177,8 +240,27 @@ sig_rfbEncodingPointerPos, "Pointer position update"); CapsAdd(encodingCaps, rfbEncodingLastRect, rfbTightVncVendor, sig_rfbEncodingLastRect, "LastRect protocol extension"); + + CapsAdd(encodingCaps, rfbEncodingNewFBSize, rfbTightVncVendor, + sig_rfbEncodingNewFBSize, "New FB size protocol extension"); ++ ++#ifdef TURBOVNC ++ CapsAdd(encodingCaps, rfbJpegQualityLevel1, rfbTurboVncVendor, ++ sig_rfbEncodingNewFBSize, "TurboJPEG quality level"); ++ CapsAdd(encodingCaps, rfbJpegSubsamp1X, rfbTurboVncVendor, ++ sig_rfbEncodingNewFBSize, "TurboJPEG subsampling level"); ++#endif } ++static char msgbuf[10000]; ++extern void CreateMsg(char *msg, int wait); ++ ++static void wmsg(char *msg, int wait) { ++ fprintf(stderr, "%s", msg); ++ if (!isatty(0) && !getenv("SSVNC_NO_MESSAGE_POPUP")) { ++ CreateMsg(msg, wait); ++ } ++} -@@ -187,23 +239,158 @@ + /* + * ConnectToRFBServer. +@@ -187,24 +269,167 @@ Bool ConnectToRFBServer(const char *hostname, int port) { @@ -9473,7 +10024,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + rfbsock = sfd[1]; + } + if (rfbsock < 0) { -+ fprintf(stderr,"Unable to connect to exec'd command: %s\n", cmd); ++ sprintf(msgbuf,"Unable to connect to exec'd command: %s\n", cmd); ++ wmsg(msgbuf, 1); + return False; + } + } else if (strstr(hostname, "fd=") == hostname) { @@ -9486,20 +10038,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + free(thost); + + if (rfbsock < 0) { -+ fprintf(stderr,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); ++ sprintf(msgbuf,"Unable to connect to VNC server (unix-domain socket: %s)\n", hostname); ++ wmsg(msgbuf, 1); + return False; + } + + } else { + if (!StringToIPAddr(hostname, &host)) { -+ fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname); ++ sprintf(msgbuf,"Couldn't convert '%s' to host address\n", hostname); ++ wmsg(msgbuf, 1); + return False; + } + + rfbsock = ConnectToTcpAddr(host, port); + + if (rfbsock < 0) { -+ fprintf(stderr,"Unable to connect to VNC server (%s:%d)\n", hostname, port); ++ sprintf(msgbuf,"Unable to connect to VNC server (%s:%d)\n", hostname, port); ++ wmsg(msgbuf, 1); + return False; + } + } @@ -9521,7 +10076,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + char *reason = (char *) malloc(reasonLen+1); + memset(reason, 0, reasonLen+1); + ReadFromRFBServer(reason, reasonLen); -+ fprintf(stderr, "Reason: %s\n", reason); ++ sprintf(msgbuf, "Reason: %s\n", reason); ++ wmsg(msgbuf, 1); + free(reason); + } } @@ -9538,6 +10094,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + + if (type == rfbSecTypeAnonTls) str = "rfbSecTypeAnonTls"; + if (type == rfbSecTypeVencrypt) str = "rfbSecTypeVencrypt"; ++ ++ if (type == rfbUltraVncMsLogon) str = "rfbUltraVncMsLogon"; + return str; +} + @@ -9553,9 +10111,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return str; +} ++extern void ProcessXtEvents(void); /* * InitialiseRFBConnection. -@@ -212,211 +399,493 @@ + */ +@@ -212,211 +437,559 @@ Bool InitialiseRFBConnection(void) { @@ -9570,7 +10130,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + FILE *pd; + char *hsfile = NULL; + char *hsparam[128]; ++ char *envsetsec = getenv("SSVNC_SET_SECURITY_TYPE"); + char line[128]; ++ double dt = 0.0; - /* if the connection is immediately closed, don't report anything, so - that pmw's monitor can make test connections */ @@ -9590,6 +10152,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } - errorMessageOnReadFailure = True; ++ skip_XtUpdateAll = 1; ++ ProcessXtEvents(); ++ skip_XtUpdateAll = 0; ++ + if (getenv("SSVNC_PREDIGESTED_HANDSHAKE")) { + double start = dnow(); + hsfile = getenv("SSVNC_PREDIGESTED_HANDSHAKE"); @@ -9643,9 +10209,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - fprintf(stderr,"Not a valid VNC server\n"); - return False; - } ++ dt = dnow(); + if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) { + return False; + } ++ if (getenv("PRINT_DELAY1")) fprintf(stderr, "delay1: %.3f ms\n", (dnow() - dt) * 1000); ++ dt = 0.0; - viewer_major = rfbProtocolMajorVersion; - if (server_major == 3 && server_minor >= rfbProtocolMinorVersion) { @@ -9698,12 +10267,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } + if (se == NULL) { -+ fprintf(stderr, "\n"); -+ fprintf(stderr, "***************************************************************\n"); -+ fprintf(stderr, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); -+ fprintf(stderr, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); -+ fprintf(stderr, "***************************************************************\n"); -+ fprintf(stderr, "\n"); ++ msgbuf[0] = '\0'; ++ strcat(msgbuf, "\n"); ++ strcat(msgbuf, "***************************************************************\n"); ++ strcat(msgbuf, "To work around UltraVNC SC III SSL dropping after a few minutes\n"); ++ strcat(msgbuf, "you may need to set STUNNEL_EXTRA_OPTS_USER='options = ALL'.\n"); ++ strcat(msgbuf, "***************************************************************\n"); ++ strcat(msgbuf, "\n"); ++ wmsg(msgbuf, 0); + } + if (strstr(pv, "ID:") == pv) { + goto check_ID_string; @@ -9712,7 +10283,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + goto ultra_vnc_nonsense; + } + } -+ fprintf(stderr,"Not a valid VNC server: '%s'\n", pv); ++ sprintf(msgbuf, "Not a valid VNC server: '%s'\n", pv); ++ wmsg(msgbuf, 1); + return False; + } @@ -9736,7 +10308,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return False; + } + if (sscanf(pv, rfbProtocolVersionFormat, &server_major, &server_minor) != 2) { -+ fprintf(stderr,"Not a valid VNC server: '%s'\n", pv); ++ sprintf(msgbuf,"Not a valid VNC server: '%s'\n", pv); ++ wmsg(msgbuf, 1); + return False; + } + } @@ -9812,35 +10385,56 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - (unsigned long)si.nameLength); - return False; - } -+ fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); ++ if (appData.msLogon) { ++ if (server_minor == 4) { ++ fprintf(stderr,"Setting RFB version to 3.4 for UltraVNC MS Logon.\n\n"); ++ viewer_minor = 4; ++ } ++ } - if (!ReadFromRFBServer(desktopName, si.nameLength)) return False; ++ fprintf(stderr, "Connected to RFB server, using protocol version %d.%d\n", viewer_major, viewer_minor); + +- desktopName[si.nameLength] = 0; + if (hsfile) { + int k = 0; + while (hsparam[k] != NULL) { + char *str = hsparam[k++]; ++ if (strstr(str, "latency=") == str) { ++ latency = 1000. * atof(str + strlen("latency=")); ++ } ++ } ++ k = 0; ++ while (hsparam[k] != NULL) { ++ char *str = hsparam[k++]; + int v1, v2; + if (sscanf(str, "viewer=RFB %d.%d\n", &v1, &v2) == 2) { + viewer_major = v1; + viewer_minor = v2; -+ fprintf(stderr, "\nPre-Handshake set protocol version to: %d.%d\n", viewer_major, viewer_minor); ++ fprintf(stderr, "\nPre-Handshake set protocol version to: %d.%d Latency: %.2f ms\n", viewer_major, viewer_minor, latency); + goto end_of_proto_msg; + } + } + } + sprintf(pv, rfbProtocolVersionFormat, viewer_major, viewer_minor); -- desktopName[si.nameLength] = 0; +- fprintf(stderr,"Desktop name \"%s\"\n",desktopName); ++ usleep(100*1000); ++ dt = dnow(); + if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) { + return False; + } -- fprintf(stderr,"Desktop name \"%s\"\n",desktopName); -+ end_of_proto_msg: - - fprintf(stderr,"VNC server default format:\n"); - PrintPixelFormat(&si.format); -+ if (getenv("SSVNC_SET_SECURITY_TYPE")) { ++ end_of_proto_msg: + +- if (tightVncProtocol) { +- /* Read interaction capabilities (protocol 3.7t) */ +- if (!ReadInteractionCaps()) +- return False; +- } ++ if (envsetsec) { + secType = atoi(getenv("SSVNC_SET_SECURITY_TYPE")); + goto sec_type; + } @@ -9861,23 +10455,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } -- if (tightVncProtocol) { -- /* Read interaction capabilities (protocol 3.7t) */ -- if (!ReadInteractionCaps()) -- return False; -- } +- return True; + /* Read or select the security type. */ ++ dt_out = 0.0; ++ ++ skip_XtUpdateAll = 1; + if (viewer_minor >= 7) { + secType = SelectSecurityType(); + } else { + secType = ReadSecurityType(); + } -+ fprintf(stderr, "Security-Type: %d (%s)\n", (int) secType, pr_sec_type(secType)); ++ skip_XtUpdateAll = 0; ++ ++ if (dt > 0.0 && dt_out > dt) { ++ latency = (dt_out - dt) * 1000; ++ } ++ ++ fprintf(stderr, "Security-Type: %d (%s) Latency: %.2f ms\n", (int) secType, pr_sec_type(secType), latency); + if (secType == rfbSecTypeInvalid) { + return False; + } - -- return True; ++ + sec_type: + + if (hsfile) { @@ -9916,10 +10514,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + usleep(300*1000); + } + if (subsectype == rfbVencryptTlsNone || subsectype == rfbVencryptTlsVnc || subsectype == rfbVencryptTlsPlain) { -+ fprintf(stderr, "\nWARNING: Anonymous Diffie-Hellman TLS used (%s),\n", pr_sec_subtype(subsectype)); -+ fprintf(stderr, "WARNING: there will be *NO* Authentication of the VNC Server.\n"); -+ fprintf(stderr, "WARNING: I.e. a Man-In-The-Middle attack is possible.\n"); -+ fprintf(stderr, "WARNING: Configure the server to use X509 certs and verify them.\n\n"); ++ char tmp[1000], line[100]; ++ tmp[0] = '\0'; ++ strcat(tmp, "\n"); ++ sprintf(line, "WARNING: Anonymous Diffie-Hellman TLS used (%s),\n", pr_sec_subtype(subsectype)); ++ strcat(tmp, line); ++ strcat(tmp, "WARNING: there will be *NO* Authentication of the VNC Server.\n"); ++ strcat(tmp, "WARNING: I.e. a Man-In-The-Middle attack is possible.\n"); ++ strcat(tmp, "WARNING: Configure the server to use X509 certs and verify them.\n\n"); ++ wmsg(tmp, 1); + } + if (subsectype == rfbVencryptTlsPlain || subsectype == rfbVencryptX509Plain) { + fprintf(stderr, "\nVeNCrypt Plain (username + passwd) selected.\n\n"); @@ -9949,7 +10552,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (authResult == rfbVncAuthOK) { + fprintf(stderr, "VNC authentication succeeded (%d) for rfbSecTypeNone (RFB 3.8)\n", authResult); + } else { -+ fprintf(stderr, "VNC authentication failed (%d) for rfbSecTypeNone (RFB 3.8)\n\n", authResult); ++ sprintf(msgbuf, "VNC authentication failed (%d) for rfbSecTypeNone (RFB 3.8)\n\n", authResult); ++ wmsg(msgbuf, 1); + return False; + } + } @@ -9970,11 +10574,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return False; + } + break; ++ case rfbUltraVncMsLogon: ++ if (!AuthUltraVncMsLogon()) { ++ return False; ++ } ++ break; + default: /* should never happen */ -+ fprintf(stderr, "Internal error: Invalid security type: %d\n", secType); ++ sprintf(msgbuf, "Internal error: Invalid security type: %d\n", secType); ++ wmsg(msgbuf, 1); + return False; + } + ++ connect_time = dnow(); ++ + ci.shared = (appData.shareDesktop ? 1 : 0); + + if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) { @@ -10046,6 +10658,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (!ReadFromRFBServer((char *)&secType, sizeof(secType))) { + return rfbSecTypeInvalid; + } ++ dt_out = dnow(); - secType = Swap32IfLE(secType); + secType = Swap32IfLE(secType); @@ -10064,9 +10677,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - (int)secType); - return rfbSecTypeInvalid; - } -+ if (secType != rfbSecTypeNone && secType != rfbSecTypeVncAuth) { -+ fprintf(stderr, "Unknown security type from RFB server: %d\n", -+ (int)secType); ++ if (secType == rfbSecTypeNone) { ++ ; /* OK */ ++ } else if (secType == rfbSecTypeVncAuth) { ++ ; /* OK */ ++ } else if (secType == rfbUltraVncMsLogon) { ++ ; /* OK */ ++ } else { ++ sprintf(msgbuf, "Unknown security type from RFB server: %d\n", (int)secType); ++ wmsg(msgbuf, 1); + return rfbSecTypeInvalid; + } @@ -10107,10 +10726,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + CARD8 secType = rfbSecTypeInvalid; + int i, j; + -+ /* Read the list of secutiry types. */ ++ /* Read the list of security types. */ + if (!ReadFromRFBServer((char *)&nSecTypes, sizeof(nSecTypes))) { + return rfbSecTypeInvalid; + } ++ dt_out = dnow(); - secTypes = malloc(nSecTypes); - if (!ReadFromRFBServer((char *)secTypes, nSecTypes)) @@ -10156,10 +10776,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "sec-type[%d] %d\n", j, (int) secTypes[j]); + } + } - -- free(secTypes); ++ + /* Find out if the server supports TightVNC protocol extensions */ + for (j = 0; j < (int)nSecTypes; j++) { ++ if (getenv("SSVNC_NO_SEC_TYPE_TIGHT")) { ++ break; ++ } ++#ifdef TURBOVNC ++ break; ++#endif + if (secTypes[j] == rfbSecTypeTight) { + free(secTypes); + secType = rfbSecTypeTight; @@ -10188,15 +10813,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } -- if (secType == rfbSecTypeInvalid) -- fprintf(stderr, "Server did not offer supported security type\n"); +- free(secTypes); + if (secType == rfbSecTypeInvalid) { + fprintf(stderr, "Server did not offer supported security type:\n"); + for (j = 0; j < (int)nSecTypes; j++) { + fprintf(stderr, " sectype[%d] %d\n", j, (int) secTypes[j]); + } + } -+ + +- if (secType == rfbSecTypeInvalid) +- fprintf(stderr, "Server did not offer supported security type\n"); + free(secTypes); - return (int)secType; @@ -10204,7 +10830,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -451,6 +920,9 @@ +@@ -451,6 +1024,9 @@ return True; } @@ -10214,7 +10840,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie /* * Negotiate authentication scheme (protocol version 3.7t) -@@ -459,56 +931,61 @@ +@@ -459,58 +1035,384 @@ static Bool PerformAuthenticationTight(void) { @@ -10313,12 +10939,335 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - fprintf(stderr, "No suitable authentication schemes offered by server\n"); - return False; -+ fprintf(stderr, "No suitable authentication schemes offered by server\n"); ++ sprintf(msgbuf, "No suitable authentication schemes offered by server\n"); ++ wmsg(msgbuf, 1); + return False; } ++#if 0 ++unsigned char encPasswd[8]; ++unsigned char encPasswd_MSLOGON[32]; ++char clearPasswd_MSLOGIN[256]; ++static Bool old_ultravnc_mslogon_code(void) { ++ char *passwd = NULL; ++ CARD8 challenge_mslogon[CHALLENGESIZE_MSLOGON]; ++ ++ /* code from the old uvnc way (1.0.2?) that would go into AuthenticateVNC() template */ ++ ++ if (appData.msLogon != NULL) { ++ if (!strcmp(appData.msLogon, "1")) { ++ char tmp[256]; ++ fprintf(stderr, "\nUltraVNC MS Logon Username[@Domain]: "); ++ if (fgets(tmp, 256, stdin) == NULL) { ++ exit(1); ++ } ++ appData.msLogon = strdup(tmp); ++ } ++ passwd = getpass("UltraVNC MS Logon Password: "); ++ if (! passwd) { ++ exit(1); ++ } ++ fprintf(stderr, "\n"); ++ ++ UvncEncryptPasswd_MSLOGON(encPasswd_MSLOGON, passwd); ++ } ++ if (appData.msLogon) { ++ if (!ReadFromRFBServer((char *)challenge_mslogon, CHALLENGESIZE_MSLOGON)) { ++ return False; ++ } ++ } ++ if (appData.msLogon) { ++ int i; ++ char tmp[256]; ++ char *q, *domain = "."; ++ for (i=0; i < 32; i++) { ++ challenge_mslogon[i] = encPasswd_MSLOGON[i] ^ challenge_mslogon[i]; ++ } ++ q = strchr(appData.msLogon, '@'); ++ if (q) { ++ *q = '\0'; ++ domain = strdup(q+1); ++ } ++ memset(tmp, 0, sizeof(tmp)); ++ strcat(tmp, appData.msLogon); ++ if (!WriteExact(rfbsock, tmp, 256)) { ++ return False; ++ } ++ memset(tmp, 0, sizeof(tmp)); ++ strcat(tmp, domain); ++ if (!WriteExact(rfbsock, tmp, 256)) { ++ return False; ++ } ++ memset(tmp, 0, sizeof(tmp)); ++ strcat(tmp, passwd); ++ if (!WriteExact(rfbsock, tmp, CHALLENGESIZE_MSLOGON)) { ++ return False; ++ } ++ } ++} ++#endif ++ ++static void hexprint(char *label, char *data, int len) { ++ int i; ++ fprintf(stderr, "%s: ", label); ++ for (i=0; i < len; i++) { ++ unsigned char c = (unsigned char) data[i]; ++ fprintf(stderr, "%02x ", (int) c); ++ if ((i+1) % 20 == 0) { ++ fprintf(stderr, "\n%s: ", label); ++ } ++ } ++ fprintf(stderr, "\n"); ++} ++ ++#define DH_MAX_BITS 31 ++static unsigned long long max_dh = ((unsigned long long) 1) << DH_MAX_BITS; ++ ++static unsigned long long bytes_to_uint64(char *bytes) { ++ unsigned long long result = 0; ++ int i; ++ ++ for (i=0; i < 8; i++) { ++ result <<= 8; ++ result += (unsigned char) bytes[i]; ++ } ++ return result; ++} ++ ++static void uint64_to_bytes(unsigned long long n, char *bytes) { ++ int i; ++ ++ for (i=0; i < 8; i++) { ++ bytes[i] = (unsigned char) (n >> (8 * (7 - i))); ++ } ++} ++ ++static void try_invert(char *wireuser, char *wirepass, unsigned long long actual_key) { ++ return; ++} ++ ++ ++static unsigned long long XpowYmodN(unsigned long long x, unsigned long long y, unsigned long long N) { ++ unsigned long long result = 1; ++ unsigned long long oneShift63 = ((unsigned long long) 1) << 63; ++ int i; ++ ++ for (i = 0; i < 64; y <<= 1, i++) { ++ result = result * result % N; ++ if (y & oneShift63) { ++ result = result * x % N; ++ } ++ } ++ return result; ++} ++ ++/* ++ * UltraVNC MS-Logon authentication (for v1.0.5 and later.) ++ */ ++ ++/* ++ * NOTE: The UltraVNC MS-Logon username and password exchange is ++ * VERY insecure. It can be brute forced in ~2e+9 operations. ++ * It's not clear we should support it... It is only worth using ++ * in an environment where no one is sniffing the network, in which ++ * case all of this DH exchange secrecy is unnecessary... ++ */ ++ ++static Bool AuthUltraVncMsLogon(void) { ++ CARD32 authResult; ++ char gen[8], mod[8], pub[8], rsp[8]; ++ char user[256], passwd[64], *gpw; ++ unsigned char key[8]; ++ unsigned long long ugen, umod, ursp, upub, uprv, ukey; ++ double now = dnow(); ++ int db = 0; ++ ++ if (getenv("SSVNC_DEBUG_MSLOGON")) { ++ db = atoi(getenv("SSVNC_DEBUG_MSLOGON")); ++ } ++ ++ fprintf(stderr, "\nAuthUltraVncMsLogon()\n"); ++ ++ if (!ReadFromRFBServer(gen, sizeof(gen))) { ++ return False; ++ } ++ if (db) hexprint("gen", gen, sizeof(gen)); ++ ++ if (!ReadFromRFBServer(mod, sizeof(mod))) { ++ return False; ++ } ++ if (db) hexprint("mod", mod, sizeof(mod)); ++ ++ if (!ReadFromRFBServer(rsp, sizeof(rsp))) { ++ return False; ++ } ++ if (db) hexprint("rsp", rsp, sizeof(rsp)); ++ ++ ugen = bytes_to_uint64(gen); ++ umod = bytes_to_uint64(mod); ++ ursp = bytes_to_uint64(rsp); ++ ++ if (db) { ++ fprintf(stderr, "ugen: 0x%016llx %12llu\n", ugen, ugen); ++ fprintf(stderr, "umod: 0x%016llx %12llu\n", umod, umod); ++ fprintf(stderr, "ursp: 0x%016llx %12llu\n", ursp, ursp); ++ } ++ ++ if (ugen > max_dh) { ++ fprintf(stderr, "ugen: too big: 0x%016llx\n", ugen); ++ return False; ++ } ++ ++ if (umod > max_dh) { ++ fprintf(stderr, "umod: too big: 0x%016llx\n", umod); ++ return False; ++ } ++ ++ /* make a random long long: */ ++ uprv = 0xffffffff * (now - (unsigned int) now); ++ uprv << 32; ++ uprv |= (unsigned long long) urandom(); ++ uprv = uprv % max_dh; ++ ++ if (db) fprintf(stderr, "uprv: 0x%016llx %12llu\n", uprv, uprv); ++ ++ upub = XpowYmodN(ugen, uprv, umod); ++ ++ if (db) fprintf(stderr, "upub: 0x%016llx %12llu\n", upub, upub); ++ ++ uint64_to_bytes(upub, pub); ++ ++ if (db) hexprint("pub", pub, sizeof(pub)); ++ ++ if (!WriteExact(rfbsock, (char *)pub, sizeof(pub))) { ++ return False; ++ } ++ if (db) fprintf(stderr, "wrote pub.\n"); ++ ++ if (ursp > max_dh) { ++ fprintf(stderr, "ursp: too big: 0x%016llx\n", ursp); ++ return False; ++ } ++ ++ ukey = XpowYmodN(ursp, uprv, umod); ++ ++ if (db) fprintf(stderr, "ukey: 0x%016llx %12llu\n", ukey, ukey); ++ ++ if (1) { ++ char tmp[10000]; ++ tmp[0] = '\0'; ++ strcat(tmp, "\n"); ++ strcat(tmp, "WARNING: The UltraVNC Diffie-Hellman Key is short (key < 2e+9, i.e. 31 bits)\n"); ++ strcat(tmp, "WARNING: and so an eavesdropper could recover your MS-Logon username and\n"); ++ strcat(tmp, "WARNING: password via brute force in a few hours to a few seconds of CPU time\n"); ++ strcat(tmp, "WARNING: depending on the method used. If this connection is not being\n"); ++ strcat(tmp, "WARNING: tunnelled through a separate SSL or SSH encrypted tunnel, consider\n"); ++ strcat(tmp, "WARNING: things carefully before proceeding... Do not enter an important\n"); ++ strcat(tmp, "WARNING: username+password when prompted below if there is a risk of an\n"); ++ strcat(tmp, "WARNING: eavesdropper sniffing this connection. You've been warned!\n"); ++ wmsg(tmp, 1); ++ } ++ ++ uint64_to_bytes(ukey, (char *) key); ++ ++ if (appData.msLogon == NULL || !strcmp(appData.msLogon, "1")) { ++ char tmp[256], *q, *s; ++ fprintf(stderr, "\nUltraVNC MS-Logon Username[@Domain]: "); ++ if (!isatty(0)) { ++ s = DoUserDialog(); ++ } else { ++ if (fgets(tmp, 256, stdin) == NULL) { ++ exit(1); ++ } ++ s = strdup(tmp); ++ } ++ q = strchr(s, '\n'); ++ if (q) *q = '\0'; ++ appData.msLogon = strdup(s); ++ } ++ ++ if (!isatty(0)) { ++ gpw = DoPasswordDialog(); ++ } else { ++ gpw = getpass("UltraVNC MS-Logon Password: "); ++ } ++ if (! gpw) { ++ return False; ++ } ++ fprintf(stderr, "\n"); ++ ++ memset(user, 0, sizeof(user)); ++ strncpy(user, appData.msLogon, 255); ++ ++ memset(passwd, 0, sizeof(passwd)); ++ strncpy(passwd, gpw, 63); ++ ++ if (db > 1) { ++ fprintf(stderr, "user='%s'\n", user); ++ fprintf(stderr, "pass='%s'\n", passwd); ++ } ++ ++ UvncEncryptBytes2((unsigned char *) user, sizeof(user), key); ++ UvncEncryptBytes2((unsigned char *) passwd, sizeof(passwd), key); ++ ++ if (getenv("TRY_INVERT")) { ++ try_invert(user, passwd, ukey); ++ exit(0); ++ } ++ ++ if (db) { ++ hexprint("user", user, sizeof(user)); ++ hexprint("pass", passwd, sizeof(passwd)); ++ } ++ ++ if (!WriteExact(rfbsock, user, sizeof(user))) { ++ return False; ++ } ++ if (db) fprintf(stderr, "wrote user.\n"); ++ ++ if (!WriteExact(rfbsock, passwd, sizeof(passwd))) { ++ return False; ++ } ++ if (db) fprintf(stderr, "wrote passwd.\n"); ++ ++ if (!ReadFromRFBServer((char *) &authResult, 4)) { ++ return False; ++ } ++ authResult = Swap32IfLE(authResult); ++ ++ if (db) fprintf(stderr, "authResult: %d\n", (int) authResult); ++ ++ switch (authResult) { ++ case rfbVncAuthOK: ++ fprintf(stderr, "UVNC MS-Logon authentication succeeded.\n\n"); ++ break; ++ case rfbVncAuthFailed: ++ fprintf(stderr, "UVNC MS-Logon authentication failed.\n"); ++ if (viewer_minor >= 8) { ++ printFailureReason(); ++ } else { ++ sprintf(msgbuf, "UVNC MS-Logon authentication failed.\n"); ++ wmsg(msgbuf, 1); ++ } ++ fprintf(stderr, "\n"); ++ return False; ++ case rfbVncAuthTooMany: ++ sprintf(msgbuf, "UVNC MS-Logon authentication failed - too many tries.\n\n"); ++ wmsg(msgbuf, 1); ++ return False; ++ default: ++ sprintf(msgbuf, "Unknown UVNC MS-Logon authentication result: %d\n\n", ++ (int)authResult); ++ wmsg(msgbuf, 1); ++ return False; ++ } ++ ++ return True; ++} -@@ -519,80 +996,104 @@ + /* + * Standard VNC authentication. +@@ -519,80 +1421,113 @@ static Bool AuthenticateVNC(void) { @@ -10344,30 +11293,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) { + return False; + } - -- if (appData.passwordFile) { -- passwd = vncDecryptPasswdFromFile(appData.passwordFile); -- if (!passwd) { -- fprintf(stderr, "Cannot read valid password from file \"%s\"\n", -- appData.passwordFile); -- return False; -- } -- } else if (appData.autoPass) { -- passwd = buffer; -- cstatus = fgets(buffer, sizeof buffer, stdin); -- if (cstatus == NULL) -- buffer[0] = '\0'; -- else -- { -- len = strlen(buffer); -- if (len > 0 && buffer[len - 1] == '\n') -- buffer[len - 1] = '\0'; -- } -- } else if (appData.passwordDialog) { -- passwd = DoPasswordDialog(); -- } else { -- passwd = getpass("Password: "); -- } ++ + if (restart_session_pw != NULL) { + passwd = restart_session_pw; + restart_session_pw = NULL; @@ -10375,8 +11301,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } else if (appData.passwordFile) { + passwd = vncDecryptPasswdFromFile(appData.passwordFile); + if (!passwd) { -+ fprintf(stderr, "Cannot read valid password from file \"%s\"\n", -+ appData.passwordFile); ++ sprintf(msgbuf, "Cannot read valid password from file \"%s\"\n", appData.passwordFile); ++ wmsg(msgbuf, 1); + return False; + } + } else if (appData.autoPass) { @@ -10392,13 +11318,39 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + } else if (getenv("VNCVIEWER_PASSWORD")) { + passwd = strdup(getenv("VNCVIEWER_PASSWORD")); -+ putenv("VNCVIEWER_PASSWORD=none"); + } else if (appData.passwordDialog) { + passwd = DoPasswordDialog(); + } else { + passwd = getpass("VNC Password: "); + } +- if (appData.passwordFile) { +- passwd = vncDecryptPasswdFromFile(appData.passwordFile); +- if (!passwd) { +- fprintf(stderr, "Cannot read valid password from file \"%s\"\n", +- appData.passwordFile); +- return False; +- } +- } else if (appData.autoPass) { +- passwd = buffer; +- cstatus = fgets(buffer, sizeof buffer, stdin); +- if (cstatus == NULL) +- buffer[0] = '\0'; +- else +- { +- len = strlen(buffer); +- if (len > 0 && buffer[len - 1] == '\n') +- buffer[len - 1] = '\0'; +- } +- } else if (appData.passwordDialog) { +- passwd = DoPasswordDialog(); +- } else { +- passwd = getpass("Password: "); +- } ++ if (getenv("VNCVIEWER_PASSWORD")) { ++ putenv("VNCVIEWER_PASSWORD=none"); ++ } + - if (!passwd || strlen(passwd) == 0) { - fprintf(stderr, "Reading password failed\n"); - return False; @@ -10414,38 +11366,38 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + des(passwd, passwd); + } else { + if (!passwd || strlen(passwd) == 0) { -+ fprintf(stderr, "Reading password failed\n\n"); ++ sprintf(msgbuf, "Reading password failed\n\n"); ++ wmsg(msgbuf, 1); + return False; + } + if (strlen(passwd) > 8) { + passwd[8] = '\0'; + } + } -+ vncEncryptBytes(challenge, passwd); -+ - vncEncryptBytes(challenge, passwd); ++ vncEncryptBytes(challenge, passwd); ++ - /* Lose the password from memory */ - memset(passwd, '\0', strlen(passwd)); + +- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) +- return False; +// /* Lose the password from memory */ +// memset(passwd, '\0', strlen(passwd)); -- if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) +- if (!ReadFromRFBServer((char *)&authResult, 4)) - return False; + if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) { + return False; + } -- if (!ReadFromRFBServer((char *)&authResult, 4)) -- return False; +- authResult = Swap32IfLE(authResult); + if (!ReadFromRFBServer((char *)&authResult, 4)) { + return False; + } -- authResult = Swap32IfLE(authResult); -+ authResult = Swap32IfLE(authResult); - - switch (authResult) { - case rfbVncAuthOK: - fprintf(stderr, "VNC authentication succeeded\n"); @@ -10461,6 +11413,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - (int)authResult); - return False; - } ++ authResult = Swap32IfLE(authResult); + +- return True; + switch (authResult) { + case rfbVncAuthOK: + fprintf(stderr, "VNC authentication succeeded\n\n"); @@ -10469,24 +11424,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "VNC authentication failed.\n"); + if (viewer_minor >= 8) { + printFailureReason(); ++ } else { ++ sprintf(msgbuf, "VNC authentication failed.\n"); ++ wmsg(msgbuf, 1); + } + fprintf(stderr, "\n"); + return False; + case rfbVncAuthTooMany: -+ fprintf(stderr, "VNC authentication failed - too many tries\n\n"); ++ sprintf(msgbuf, "VNC authentication failed - too many tries\n\n"); ++ wmsg(msgbuf, 1); + return False; + default: -+ fprintf(stderr, "Unknown VNC authentication result: %d\n\n", -+ (int)authResult); ++ sprintf(msgbuf, "Unknown VNC authentication result: %d\n\n", (int)authResult); ++ wmsg(msgbuf, 1); + return False; + } - -- return True; ++ + return True; } /* -@@ -602,68 +1103,71 @@ +@@ -602,68 +1537,74 @@ static Bool AuthenticateUnixLogin(void) { @@ -10594,14 +11552,17 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "Authentication succeeded\n\n"); + break; + case rfbVncAuthFailed: -+ fprintf(stderr, "Authentication failed\n\n"); ++ sprintf(msgbuf, "Authentication failed\n\n"); ++ wmsg(msgbuf, 1); + return False; + case rfbVncAuthTooMany: -+ fprintf(stderr, "Authentication failed - too many tries\n\n"); ++ sprintf(msgbuf, "Authentication failed - too many tries\n\n"); ++ wmsg(msgbuf, 1); + return False; + default: -+ fprintf(stderr, "Unknown authentication result: %d\n\n", ++ sprintf(msgbuf, "Unknown authentication result: %d\n\n", + (int)authResult); ++ wmsg(msgbuf, 1); + return False; + } @@ -10610,7 +11571,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -675,19 +1179,20 @@ +@@ -675,19 +1616,20 @@ static Bool ReadInteractionCaps(void) { @@ -10643,7 +11604,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -700,17 +1205,18 @@ +@@ -700,19 +1642,67 @@ static Bool ReadCapabilityList(CapsContainer *caps, int count) { @@ -10668,22 +11629,77 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - return True; + return True; ++} ++ ++ ++/* used to have !tunnelSpecified */ ++ ++static int guess_compresslevel(void) { ++ int n; ++ if (latency > 200.0) { ++ n = 8; ++ } else if (latency > 100.0) { ++ n = 7; ++ } else if (latency > 60.0) { ++ n = 6; ++ } else if (latency > 15.0) { ++ n = 4; ++ } else if (latency > 8.0) { ++ n = 2; ++ } else if (latency > 0.0) { ++ n = 1; ++ } else { ++ /* no latency measurement */ ++ n = 3; ++ } ++ return n; } ++static int guess_qualitylevel(void) { ++ int n; ++ if (latency > 200.0) { ++ n = 4; ++ } else if (latency > 100.0) { ++ n = 5; ++ } else if (latency > 60.0) { ++ n = 6; ++ } else if (latency > 15.0) { ++ n = 7; ++ } else if (latency > 8.0) { ++ n = 8; ++ } else if (latency > 0.0) { ++ n = 9; ++ } else { ++ /* no latency measurement */ ++ n = 6; ++ } ++#ifdef TURBOVNC ++ n *= 10; ++#endif ++ return n; ++} -@@ -729,6 +1235,11 @@ + /* + * SetFormatAndEncodings. +@@ -729,6 +1719,17 @@ Bool requestCompressLevel = False; Bool requestQualityLevel = False; Bool requestLastRectEncoding = False; + Bool requestNewFBSizeEncoding = True; + Bool requestTextChatEncoding = True; ++ Bool requestSubsampLevel = False; + int dsm = 0; ++ int tQL, tQLmax = 9; ++ static int qlmsg = 0, clmsg = 0; ++#ifdef TURBOVNC ++ tQLmax = 100; ++#endif + +// fprintf(stderr, "SetFormatAndEncodings: sent_FBU state: %2d\n", sent_FBU); spf.type = rfbSetPixelFormat; spf.format = myFormat; -@@ -736,12 +1247,18 @@ +@@ -736,12 +1737,18 @@ spf.format.greenMax = Swap16IfLE(spf.format.greenMax); spf.format.blueMax = Swap16IfLE(spf.format.blueMax); @@ -10702,7 +11718,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie if (appData.encodingsString) { char *encStr = appData.encodingsString; int encStrLen; -@@ -754,11 +1271,17 @@ +@@ -754,50 +1761,102 @@ encStrLen = strlen(encStr); } @@ -10720,17 +11736,30 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } else if (strncasecmp(encStr,"tight",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight); requestLastRectEncoding = True; - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) -@@ -767,16 +1290,33 @@ - requestQualityLevel = True; +- if (appData.compressLevel >= 0 && appData.compressLevel <= 9) +- requestCompressLevel = True; +- if (appData.enableJPEG) +- requestQualityLevel = True; ++ if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { ++ requestCompressLevel = True; ++ } ++ if (appData.enableJPEG) { ++ requestQualityLevel = True; ++ } ++#ifdef TURBOVNC ++ requestSubsampLevel = True; ++#endif } else if (strncasecmp(encStr,"hextile",encStrLen) == 0) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile); - } else if (strncasecmp(encStr,"zlib",encStrLen) == 0) { + } else if (strncasecmp(encStr,"zlib",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib); - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) - requestCompressLevel = True; +- if (appData.compressLevel >= 0 && appData.compressLevel <= 9) +- requestCompressLevel = True; - } else if (strncasecmp(encStr,"corre",encStrLen) == 0) { ++ if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { ++ requestCompressLevel = True; ++ } + } else if (strncasecmp(encStr,"corre",encStrLen) == 0 && !dsm) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE); } else if (strncasecmp(encStr,"rre",encStrLen) == 0) { @@ -10739,11 +11768,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZRLE); +#if DO_ZYWRLE + } else if (strncasecmp(encStr,"zywrle",encStrLen) == 0) { -+ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); -+ requestQualityLevel = True; -+ if (appData.qualityLevel < 3) { ++ int qlevel = appData.qualityLevel; ++ if (qlevel < 0 || qlevel > tQLmax) qlevel = guess_qualitylevel(); ++ encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZYWRLE); ++ requestQualityLevel = True; ++ if (qlevel < 3) { + zywrle_level = 3; -+ } else if (appData.qualityLevel < 6) { ++ } else if (qlevel < 6) { + zywrle_level = 2; + } else { + zywrle_level = 1; @@ -10757,7 +11788,47 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } encStr = nextEncStr; -@@ -797,7 +1337,7 @@ + } while (encStr && se->nEncodings < MAX_ENCODINGS); + + if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) { +- encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + +- rfbEncodingCompressLevel0); ++ ; ++ } else if (se->nEncodings < MAX_ENCODINGS) { ++ appData.compressLevel = guess_compresslevel(); ++ if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); + } ++ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); + + if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) { +- if (appData.qualityLevel < 0 || appData.qualityLevel > 9) +- appData.qualityLevel = 5; +- encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + +- rfbEncodingQualityLevel0); ++ if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { ++ appData.qualityLevel = guess_qualitylevel(); ++ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); ++ } ++ } else if (se->nEncodings < MAX_ENCODINGS) { ++ appData.qualityLevel = guess_qualitylevel(); ++ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); ++ } ++#ifdef TURBOVNC ++ tQL = appData.qualityLevel / 10; ++ if (tQL < 0) tQL = 1; ++ if (tQL > 9) tQL = 9; ++ encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); ++ if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { ++ if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { ++ appData.subsampLevel = TVNC_1X; ++ } ++ encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); + } ++#else ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); ++#endif + if (appData.useRemoteCursor) { if (se->nEncodings < MAX_ENCODINGS) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); @@ -10766,23 +11837,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor); if (se->nEncodings < MAX_ENCODINGS) encs[se->nEncodings++] = Swap32IfLE(rfbEncodingPointerPos); -@@ -806,10 +1346,14 @@ +@@ -806,10 +1865,16 @@ if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect); } +- } +- else { + + if (se->nEncodings < MAX_ENCODINGS && requestNewFBSizeEncoding) { + encs[se->nEncodings++] = Swap32IfLE(rfbEncodingNewFBSize); + } - } - else { ++ ++ } else { ++ /* DIFFERENT CASE */ ++ if (SameMachine(rfbsock)) { - if (!tunnelSpecified) { + if (!tunnelSpecified && appData.useRawLocal) { fprintf(stderr,"Same machine: preferring raw encoding\n"); encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw); } else { -@@ -818,13 +1362,15 @@ +@@ -818,44 +1883,84 @@ } encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect); @@ -10798,20 +11873,59 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE); - if (appData.compressLevel >= 0 && appData.compressLevel <= 9) { -+ if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { - encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + - rfbEncodingCompressLevel0); - } else if (!tunnelSpecified) { -@@ -835,7 +1381,7 @@ - encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); - } - +- encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + +- rfbEncodingCompressLevel0); +- } else if (!tunnelSpecified) { +- /* If -tunnel option was provided, we assume that server machine is +- not in the local network so we use default compression level for +- tight encoding instead of fast compression. Thus we are +- requesting level 1 compression only if tunneling is not used. */ +- encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCompressLevel1); +- } +- - if (appData.enableJPEG) { +- if (appData.qualityLevel < 0 || appData.qualityLevel > 9) +- appData.qualityLevel = 5; +- encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + +- rfbEncodingQualityLevel0); ++ if (!dsm && appData.compressLevel >= 0 && appData.compressLevel <= 9) { ++ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); ++ } else { ++ /* ++ * OUT OF DATE: If -tunnel option was provided, we assume that server machine is ++ * not in the local network so we use default compression level for ++ * tight encoding instead of fast compression. Thus we are ++ * requesting level 1 compression only if tunneling is not used. ++ */ ++ appData.compressLevel = guess_compresslevel(); ++ if (clmsg++ == 0) fprintf(stderr, "guessed: -compresslevel %d\n", appData.compressLevel); ++ encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel + rfbEncodingCompressLevel0); ++ } ++ + if (!dsm && appData.enableJPEG) { - if (appData.qualityLevel < 0 || appData.qualityLevel > 9) - appData.qualityLevel = 5; - encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + -@@ -844,18 +1390,35 @@ ++ if (appData.qualityLevel < 0 || appData.qualityLevel > tQLmax) { ++ appData.qualityLevel = guess_qualitylevel(); ++ if (qlmsg++ == 0) fprintf(stderr, "guessed: -qualitylevel %d\n", appData.qualityLevel); ++ } ++ ++#ifdef TURBOVNC ++ requestSubsampLevel = True; ++ tQL = appData.qualityLevel / 10; ++ if (tQL < 0) tQL = 1; ++ if (tQL > 9) tQL = 9; ++ encs[se->nEncodings++] = Swap32IfLE(tQL + rfbEncodingQualityLevel0); ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbJpegQualityLevel1 - 1); ++ if (se->nEncodings < MAX_ENCODINGS && requestSubsampLevel) { ++ if (appData.subsampLevel < 0 || appData.subsampLevel > TVNC_SAMPOPT - 1) { ++ appData.subsampLevel = TVNC_1X; ++ } ++ encs[se->nEncodings++] = Swap32IfLE(appData.subsampLevel + rfbJpegSubsamp1X); ++ } ++#else ++ encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel + rfbEncodingQualityLevel0); ++#endif ++ + } if (appData.useRemoteCursor) { encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor); @@ -10850,7 +11964,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie return True; } -@@ -868,31 +1431,86 @@ +@@ -868,31 +1973,86 @@ Bool SendIncrementalFramebufferUpdateRequest() { @@ -10950,7 +12064,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -903,19 +1521,36 @@ +@@ -903,19 +2063,36 @@ Bool SendPointerEvent(int x, int y, int buttonMask) { @@ -10963,19 +12077,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + return True; + } + } -+ -+ pe.type = rfbPointerEvent; -+ pe.buttonMask = buttonMask; -+ -+ if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { -+ x /= scale_factor_x; -+ } -+ if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { -+ y /= scale_factor_y; -+ } -+ -+ if (x < 0) x = 0; -+ if (y < 0) y = 0; - pe.type = rfbPointerEvent; - pe.buttonMask = buttonMask; @@ -10988,6 +12089,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - pe.x = Swap16IfLE(x); - pe.y = Swap16IfLE(y); - return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg); ++ pe.type = rfbPointerEvent; ++ pe.buttonMask = buttonMask; ++ ++ if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { ++ x /= scale_factor_x; ++ } ++ if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { ++ y /= scale_factor_y; ++ } ++ ++ if (x < 0) x = 0; ++ if (y < 0) y = 0; ++ + if (!appData.useX11Cursor) { + SoftCursorMove(x, y); + } @@ -10999,7 +12113,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -926,12 +1561,20 @@ +@@ -926,12 +2103,20 @@ Bool SendKeyEvent(CARD32 key, Bool down) { @@ -11025,7 +12139,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -942,281 +1585,943 @@ +@@ -942,281 +2127,1024 @@ Bool SendClientCutText(char *str, int len) { @@ -11036,15 +12150,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + free(serverCutText); + } + serverCutText = NULL; - -- if (serverCutText) -- free(serverCutText); -- serverCutText = NULL; -- -- cct.type = rfbClientCutText; -- cct.length = Swap32IfLE(len); -- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && -- WriteExact(rfbsock, str, len)); ++ + if (appData.fileActive) { + if (!dyn || time(NULL) < last_filexfer + delay_filexfer) { + // ultravnc java viewer lets this one through. @@ -11055,7 +12161,15 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (appData.viewOnly) { + return True; + } -+ + +- if (serverCutText) +- free(serverCutText); +- serverCutText = NULL; +- +- cct.type = rfbClientCutText; +- cct.length = Swap32IfLE(len); +- return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) && +- WriteExact(rfbsock, str, len)); + cct.type = rfbClientCutText; + cct.length = Swap32IfLE(len); + currentMsg = rfbClientCutText; @@ -11397,10 +12511,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (hdr[1] == rfbDirPacket && hdr[3] == rfbADirectory) { + + } - -- /* If RichCursor encoding is used, we should prevent collisions -- between framebuffer updates and cursor drawing operations. */ -- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); ++ + len = (hdr[8] << 24) | (hdr[9] << 16) | (hdr[10] << 8) | hdr[11]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len1 %u\n", len); + if (len > 0) { @@ -11450,7 +12561,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + len = (hdr[4] << 24) | (hdr[5] << 16) | (hdr[6] << 8) | hdr[7]; + if (db) fprintf(stderr, "Got rfbFileTransfer: len2 %u\n", len); -- switch (rect.encoding) { +- /* If RichCursor encoding is used, we should prevent collisions +- between framebuffer updates and cursor drawing operations. */ +- SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h); +#if 0 + if (hdr[1] == rfbFileHeader && len != rfbRErrorCmd) +#else @@ -11483,7 +12596,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + fprintf(stderr, "filexfer_sock closed, discarding %d bytes\n", len); + } + } -+ + +- switch (rect.encoding) { + read_no_more: + + if (filexfer_sock < 0) { @@ -11639,27 +12753,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; -- } -- break; -- } + msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour); + msg.scme.nColours = Swap16IfLE(msg.scme.nColours); - -- case rfbEncodingHextile: -- { -- switch (myFormat.bitsPerPixel) { -- case 8: -- if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 16: -- if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; -- case 32: -- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) -- return False; -- break; ++ + for (i = 0; i < msg.scme.nColours; i++) { + if (!ReadFromRFBServer((char *)rgb, 6)) { + return False; @@ -11682,19 +12778,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - } + } -- case rfbEncodingZlib: +- case rfbEncodingHextile: - { - switch (myFormat.bitsPerPixel) { - case 8: -- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 16: -- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; - case 32: -- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; + case rfbFramebufferUpdate: @@ -11710,6 +12806,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + int area_zrle = 0; + int area_raw = 0; + static int rdb = -1; ++ static int delay_sync = -1; ++ static int delay_sync_env = -1; ++ int try_delay_sync = 0; ++ int cnt_pseudo = 0; ++ int cnt_image = 0; + + if (db) fprintf(stderr, "FBU-0: %.6f\n", dnow()); + if (rdb < 0) { @@ -11720,6 +12821,46 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } } - break; +- } ++ if (delay_sync < 0) { ++ if (getenv("SSVNC_DELAY_SYNC")) { ++ delay_sync = atoi(getenv("SSVNC_DELAY_SYNC")); ++ delay_sync_env = delay_sync; ++ } else { ++ delay_sync = 0; ++ } ++ } ++ ++ int skip_incFBU = 0; ++ sent_FBU = -1; + +- case rfbEncodingZlib: +- { +- switch (myFormat.bitsPerPixel) { +- case 8: +- if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- return False; +- break; +- case 16: +- if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- return False; +- break; +- case 32: +- if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) +- return False; +- break; ++ if (appData.pipelineUpdates) { ++ /* turbovnc speed idea */ ++ XEvent ev; ++ memset(&ev, 0, sizeof(ev)); ++ ev.xclient.type = ClientMessage; ++ ev.xclient.window = XtWindow(desktop); ++ ev.xclient.message_type = XA_INTEGER; ++ ev.xclient.format = 8; ++ strcpy(ev.xclient.data.b, "SendRFBUpdate"); ++ XSendEvent(dpy, XtWindow(desktop), False, 0, &ev); + } +- break; - } - case rfbEncodingTight: @@ -11737,9 +12878,6 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h)) - return False; - break; -+ int skip_incFBU = 0; -+ sent_FBU = -1; -+ + if (!ReadFromRFBServer(((char *)&msg.fu) + 1, sz_rfbFramebufferUpdateMsg - 1)) { + return False; } @@ -11756,6 +12894,44 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie - /* Now we may discard "soft cursor locks". */ - SoftCursorUnlockScreen(); - } ++ if (rdb) fprintf(stderr, "Begin rect loop %d\n", msg.fu.nRects); ++ ++ if (delay_sync) { ++ try_delay_sync = 1; ++ } else { ++ if (delay_sync_env != -1 && delay_sync_env == 0) { ++ ; ++ } else if (appData.yCrop > 0) { ++ ; ++ } else if (scale_factor_x > 0.0 && scale_factor_x != 1.0) { ++ ; ++ } else if (scale_factor_y > 0.0 && scale_factor_y != 1.0) { ++ ; ++ } else { ++ static int msg = 0; ++ /* fullScreen? */ ++ /* useXserverBackingStore? */ ++ /* useX11Cursor & etc? */ ++ /* scrollbars? */ ++ if (!msg) { ++ fprintf(stderr, "enabling 'delay_sync' mode for faster local drawing,\ndisable via env SSVNC_DELAY_SYNC=0 if there are painting errors.\n"); ++ msg = 1; ++ } ++ try_delay_sync = 1; ++ } ++ } ++ if (try_delay_sync) { ++ skip_maybe_sync = 1; ++ } ++#define STOP_DELAY_SYNC \ ++ if (try_delay_sync) { \ ++ if (cnt_image && skip_maybe_sync) { \ ++ XSync(dpy, False); \ ++ } \ ++ try_delay_sync = 0; \ ++ skip_maybe_sync = 0; \ ++ } ++ + for (i = 0; i < msg.fu.nRects; i++) { + if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader)) { + return False; @@ -11771,8 +12947,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + rect.r.w = Swap16IfLE(rect.r.w); + rect.r.h = Swap16IfLE(rect.r.h); + ++ if (rdb > 1) fprintf(stderr, "nRects: %d i=%d enc: %d %dx%d+%d+%d\n", msg.fu.nRects, i, rect.encoding, rect.r.w, rect.r.h, rect.r.x, rect.r.y); + + if (rect.encoding == rfbEncodingXCursor || rect.encoding == rfbEncodingRichCursor) { ++ cnt_pseudo++; ++ STOP_DELAY_SYNC ++ + if (db) fprintf(stderr, "FBU-Cur1 %.6f\n", dnow()); + if (!HandleCursorShape(rect.r.x, rect.r.y, rect.r.w, rect.r.h, rect.encoding)) { + return False; @@ -11782,6 +12962,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } + + if (rect.encoding == rfbEncodingPointerPos) { ++ cnt_pseudo++; ++ STOP_DELAY_SYNC + if (db) fprintf(stderr, "FBU-Pos1 %.6f\n", dnow()); + if (0) fprintf(stderr, "CursorPos: %d %d / %d %d\n", rect.r.x, rect.r.y, rect.r.w, rect.r.h); + if (ultra_scale > 0) { @@ -11798,6 +12980,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + continue; + } + if (rect.encoding == rfbEncodingNewFBSize) { ++ cnt_pseudo++; ++ STOP_DELAY_SYNC + if (appData.chatOnly) { + continue; + } @@ -11809,6 +12993,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + continue; + } + if (rdb) fprintf(stderr,"Rect: %dx%d at (%d, %d)\n", rect.r.w, rect.r.h, rect.r.x, rect.r.y); ++ cnt_image++; + + if (appData.ultraDSM) { + /* @@ -11862,6 +13047,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + + if (db) fprintf(stderr, "FBU-SCL2 %.6f\n", dnow()); + ++ + switch (rect.encoding) { + + case rfbEncodingRaw: @@ -11892,6 +13078,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + { + rfbCopyRect cr; + ++ STOP_DELAY_SYNC ++ XSync(dpy, False); ++ + if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect)) { + return False; + } @@ -12155,7 +13344,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + if (db) fprintf(stderr, "FBU-SUL2 %.6f\n", dnow()); + } + ++ if (try_delay_sync) { ++ skip_maybe_sync = 0; ++ } ++ + if (1 || area_copyrect) { ++ /* we always do this now for some reason... */ + if (db) fprintf(stderr, "FBU-XSN1 %.6f\n", dnow()); + XSync(dpy, False); + if (db) fprintf(stderr, "FBU-XSN2 %.6f\n", dnow()); @@ -12192,7 +13386,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #ifdef MITSHM /* if using shared memory PutImage, make sure that the X server has -@@ -1224,59 +2529,165 @@ +@@ -1224,59 +3152,168 @@ mainly to avoid copyrect using invalid screen contents - not sure if we'd need it otherwise. */ @@ -12203,11 +13397,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie + } else #endif + { ++ /* we do it always now. */ + XSync(dpy, False); + } + + if (skip_XtUpdate || skip_incFBU) { + ; ++ } else if (appData.pipelineUpdates) { ++ ; + } else if (!SendIncrementalFramebufferUpdateRequest()) { + return False; + } @@ -12223,20 +13420,20 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie { - Window toplevelWin; + Window toplevelWin; - -- XBell(dpy, 0); ++ + if (appData.useBell) { + XBell(dpy, 0); + } -- if (appData.raiseOnBeep) { -- toplevelWin = XtWindow(toplevel); -- XMapRaised(dpy, toplevelWin); +- XBell(dpy, 0); + if (appData.raiseOnBeep) { + toplevelWin = XtWindow(toplevel); + XMapRaised(dpy, toplevelWin); + } -+ + +- if (appData.raiseOnBeep) { +- toplevelWin = XtWindow(toplevel); +- XMapRaised(dpy, toplevelWin); + break; } @@ -12391,7 +13588,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie } -@@ -1296,26 +2707,47 @@ +@@ -1296,26 +3333,93 @@ #define CONCAT2(a,b) a##b #define CONCAT2E(a,b) CONCAT2(a,b) @@ -12401,12 +13598,40 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie +static unsigned char* frameBuffer = NULL; +static int frameBufferLen = 0; + ++#ifdef TURBOVNC ++#include "turbovnc/turbojpeg.h" ++tjhandle tjhnd=NULL; ++static char *compressedData = NULL; ++static char *uncompressedData = NULL; ++#define CopyDataToImage CopyDataToScreen ++static void turbovnc_FillRectangle(XGCValues *gcv, int rx, int ry, int rw, int rh) { ++ if (!appData.useXserverBackingStore) { ++ FillScreen(rx, ry, rw, rh, gcv->foreground); ++ } else { ++ XChangeGC(dpy, gc, GCForeground, gcv); ++ XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh); ++ } ++} ++static void CopyImageToScreen(int x, int y, int w, int h) { ++ put_image(x, y, x, y, w, h, 0); ++} ++#endif ++ #define BPP 8 #include "rre.c" #include "corre.c" #include "hextile.c" #include "zlib.c" ++// ++#ifdef TURBOVNC ++#undef FillRectangle ++#define FillRectangle turbovnc_FillRectangle ++#include "turbovnc/tight.c" ++#undef FillRectangle ++#else #include "tight.c" ++#endif ++// +#include "zrle.c" #undef BPP + @@ -12415,7 +13640,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #include "corre.c" #include "hextile.c" #include "zlib.c" ++// ++#ifdef TURBOVNC ++#undef FillRectangle ++#define FillRectangle turbovnc_FillRectangle ++#include "turbovnc/tight.c" ++#undef FillRectangle ++#else #include "tight.c" ++#endif ++// +#include "zrle.c" +#define REALBPP 15 +#include "zrle.c" @@ -12426,7 +13660,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #include "corre.c" #include "hextile.c" #include "zlib.c" ++// ++#ifdef TURBOVNC ++#undef FillRectangle ++#define FillRectangle turbovnc_FillRectangle ++#include "turbovnc/tight.c" ++#undef FillRectangle ++#else #include "tight.c" ++#endif ++// +#include "zrle.c" +#define REALBPP 24 +#include "zrle.c" @@ -12439,7 +13682,49 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie #undef BPP /* -@@ -1358,9 +2790,9 @@ +@@ -1325,23 +3429,27 @@ + static void + ReadConnFailedReason(void) + { +- CARD32 reasonLen; +- char *reason = NULL; ++ CARD32 reasonLen; ++ char *reason = NULL; + +- if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { +- reasonLen = Swap32IfLE(reasonLen); +- if ((reason = malloc(reasonLen)) != NULL && +- ReadFromRFBServer(reason, reasonLen)) { +- fprintf(stderr,"VNC connection failed: %.*s\n", (int)reasonLen, reason); +- free(reason); +- return; +- } +- } ++ if (ReadFromRFBServer((char *)&reasonLen, sizeof(reasonLen))) { ++ reasonLen = Swap32IfLE(reasonLen); ++ if ((reason = malloc(reasonLen)) != NULL && ++ ReadFromRFBServer(reason, reasonLen)) { ++ int len = reasonLen < sizeof(msgbuf) - 10 ? (int) reasonLen : sizeof(msgbuf) - 10; ++ sprintf(msgbuf,"VNC connection failed: %.*s\n", len, reason); ++ wmsg(msgbuf, 1); ++ free(reason); ++ return; ++ } ++ } + +- fprintf(stderr, "VNC connection failed\n"); ++ sprintf(msgbuf, "VNC connection failed\n"); ++ wmsg(msgbuf, 1); + +- if (reason != NULL) +- free(reason); ++ if (reason != NULL) { ++ free(reason); ++ } + } + + /* +@@ -1358,9 +3466,9 @@ " %s significant bit in each byte is leftmost on the screen.\n", (format->bigEndian ? "Most" : "Least")); } else { @@ -12451,7 +13736,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rfbproto.c vnc_unixsrc/vncvie (format->bigEndian ? "Most" : "Least")); } if (format->trueColour) { -@@ -1462,4 +2894,3 @@ +@@ -1462,4 +3570,3 @@ cinfo->src = &jpegSrcManager; } @@ -12522,6 +13807,412 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/rre.c vnc_unixsrc/vncviewer/r } + +#undef FillRectangle +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/selection.c vnc_unixsrc/vncviewer/selection.c +--- vnc_unixsrc.orig/vncviewer/selection.c 2004-03-03 04:11:52.000000000 -0500 ++++ vnc_unixsrc/vncviewer/selection.c 2009-05-31 18:35:25.000000000 -0400 +@@ -43,13 +43,16 @@ + unsigned long* length, int* format); + static void LoseSelection(Widget w, Atom *selection); + +-static Bool iAmSelectionOwner = False; ++static Bool PrimarySelectionOwner = False; ++static Bool ClipboardSelectionOwner = False; + static Time prevSelectionTime = 0L; + static Time cutBufferTime = 0L; + + #define TIME_LATER(a, b) ((a) != 0 && ((b) == 0 || (INT32)((a) - (b)) > 0)) + + ++static Atom clipboard_atom = None; ++ + /* + * InitialiseSelection() must be called after realizing widgets (because + * otherwise XtGetSelectionValue() fails). We register events on the root +@@ -62,22 +65,28 @@ + * available. + */ + +-void +-InitialiseSelection() +-{ ++static int dbg_sel = -1; ++ ++void InitialiseSelection() { + #if XtSpecificationRelease >= 6 +- XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); ++ XtRegisterDrawable(dpy, DefaultRootWindow(dpy), toplevel); + #else +- _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); ++ _XtRegisterWindow(DefaultRootWindow(dpy), toplevel); + #endif +- XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); ++ XSelectInput(dpy, DefaultRootWindow(dpy), PropertyChangeMask); + +- XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, +- NULL); ++ XtAddRawEventHandler(toplevel, PropertyChangeMask, False, CutBufferChange, NULL); + +- XtGetSelectionValue(toplevel, XA_PRIMARY, ++ clipboard_atom = XInternAtom(dpy, "CLIPBOARD", False); ++ ++ XtGetSelectionValue(toplevel, XA_PRIMARY, + XInternAtom(dpy, "TIMESTAMP", False), + GetInitialSelectionTimeCallback, NULL, CurrentTime); ++ ++ if (dbg_sel < 0) { ++ dbg_sel = 0; ++ if (getenv("SSVNC_DEBUG_SELECTION")) dbg_sel = 1; ++ } + } + + +@@ -93,13 +102,15 @@ + Atom* selection, Atom* type, XtPointer value, + unsigned long* length, int* format) + { +- if (value && *format == 32 && *length == 1) +- prevSelectionTime = *(CARD32 *)value; +- else +- prevSelectionTime = 0L; +- +- if (value) +- XtFree(value); ++ if (value && *format == 32 && *length == 1) { ++ prevSelectionTime = *(CARD32 *)value; ++ } else { ++ prevSelectionTime = 0L; ++ } ++ ++ if (value) { ++ XtFree(value); ++ } + } + + +@@ -121,26 +132,29 @@ + void + SelectionToVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) + { +- Bool always = False; ++ Bool always = appData.sendAlways; ++ Atom sendsel = XA_PRIMARY; + +- if (*num_params != 0) { +- if (strcmp(params[0],"always") == 0) { +- always = True; +- } else if (strcmp(params[0],"new") == 0) { +- always = False; +- } else { +- fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); +- return; +- } +- } +- +- if (always) { +- XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, +- TimeFromEvent(event)); +- } else { +- XtGetSelectionValue(w, XA_PRIMARY, XInternAtom(dpy, "TIMESTAMP", False), +- GetSelectionTimeCallback, NULL, TimeFromEvent(event)); +- } ++ if (*num_params != 0) { ++ if (strcmp(params[0],"always") == 0) { ++ always = True; ++ } else if (strcmp(params[0],"new") == 0) { ++ always = False; ++ } else { ++ fprintf(stderr,"Invalid params: SelectionToVNC(always|new)\n"); ++ return; ++ } ++ } ++ if (appData.sendClipboard && clipboard_atom != None) { ++ sendsel = clipboard_atom; ++ } ++ if (dbg_sel) fprintf(stderr, "SelectionToVNC %s\n", sendsel == XA_PRIMARY ? "PRIMARY" : "CLIPBOARD"); ++ ++ if (always) { ++ XtGetSelectionValue(w, sendsel, XA_STRING, GetSelectionCallback, NULL, TimeFromEvent(event)); ++ } else { ++ XtGetSelectionValue(w, sendsel, XInternAtom(dpy, "TIMESTAMP", False), GetSelectionTimeCallback, NULL, TimeFromEvent(event)); ++ } + } + + +@@ -158,10 +172,12 @@ + int len = *length; + char *str = (char *)value; + +- if (str) +- SendClientCutText(str, len); +- else +- SendCutBuffer(); ++ if (str) { ++ if (dbg_sel) fprintf(stderr, "SendClientCutText len: %d\n", len); ++ SendClientCutText(str, len); ++ } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { ++ SendCutBuffer(); ++ } + } + + +@@ -180,26 +196,23 @@ + Atom* type, XtPointer value, unsigned long* length, + int* format) + { +- if (value && *format == 32 && *length == 1) { ++ if (value && *format == 32 && *length == 1) { ++ Time t = *(CARD32 *)value; + +- Time t = *(CARD32 *)value; +- +- if (TIME_LATER(t, prevSelectionTime)) { +- prevSelectionTime = t; +- XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, +- CurrentTime); +- } +- +- } else { +- +- if (TIME_LATER(cutBufferTime, prevSelectionTime)) { +- prevSelectionTime = cutBufferTime; +- SendCutBuffer(); +- } +- } +- +- if (value) +- XtFree(value); ++ if (TIME_LATER(t, prevSelectionTime)) { ++ prevSelectionTime = t; ++ XtGetSelectionValue(w, XA_PRIMARY, XA_STRING, GetSelectionCallback, NULL, CurrentTime); ++ } ++ } else if (!getenv("VNCVIEWER_NO_CUTBUFFER")) { ++ if (TIME_LATER(cutBufferTime, prevSelectionTime)) { ++ prevSelectionTime = cutBufferTime; ++ SendCutBuffer(); ++ } ++ } ++ ++ if (value) { ++ XtFree(value); ++ } + } + + +@@ -209,16 +222,17 @@ + */ + + static void +-SendCutBuffer() +-{ +- char *str; +- int len; ++SendCutBuffer() { ++ char *str; ++ int len; + +- str = XFetchBytes(dpy, &len); +- if (!str) return; ++ if (dbg_sel) fprintf(stderr, "SendCutBuffer len: %d\n", len); + +- SendClientCutText(str, len); +- XFree(str); ++ str = XFetchBytes(dpy, &len); ++ if (!str) return; ++ ++ SendClientCutText(str, len); ++ XFree(str); + } + + +@@ -230,10 +244,11 @@ + static void + CutBufferChange(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont) + { +- if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) +- return; ++ if (ev->type != PropertyNotify || ev->xproperty.atom != XA_CUT_BUFFER0) { ++ return; ++ } + +- cutBufferTime = ev->xproperty.time; ++ cutBufferTime = ev->xproperty.time; + } + + +@@ -249,36 +264,61 @@ + void + SelectionFromVNC(Widget w, XEvent *event, String *params, Cardinal *num_params) + { +- Bool always = False; +- Time t = TimeFromEvent(event); +- +- if (*num_params != 0) { +- if (strcmp(params[0],"always") == 0) { +- always = True; +- } else if (strcmp(params[0],"new") == 0) { +- always = False; +- } else { +- fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); +- return; +- } +- } +- +- if (t == CurrentTime) { +- fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " +- "event with time field\n"); +- return; +- } +- +- if (!serverCutText || (!always && !newServerCutText)) +- return; +- +- newServerCutText = False; +- +- XStoreBytes(dpy, serverCutText, strlen(serverCutText)); +- if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, +- NULL)) { +- iAmSelectionOwner = True; +- } ++ Bool always = False; ++ Time t = TimeFromEvent(event); ++ int hold_primary = 0; ++ int hold_clipboard = 0; ++ ++ if (dbg_sel) fprintf(stderr, "SelectionFromVNC\n"); ++ ++ if (*num_params != 0) { ++ if (strcmp(params[0],"always") == 0) { ++ always = True; ++ } else if (strcmp(params[0],"new") == 0) { ++ always = False; ++ } else { ++ fprintf(stderr,"Invalid params: SelectionFromVNC(always|new)\n"); ++ return; ++ } ++ } ++ ++ if (t == CurrentTime) { ++ fprintf(stderr,"Error in translations: SelectionFromVNC() must act on " ++ "event with time field\n"); ++ return; ++ } ++ ++ if (!serverCutText || (!always && !newServerCutText)) { ++ return; ++ } ++ ++ newServerCutText = False; ++ ++ XStoreBytes(dpy, serverCutText, strlen(serverCutText)); ++ ++ if (appData.recvText == NULL) { ++ appData.recvText = strdup("both"); ++ } ++ if (!strcasecmp(appData.recvText, "primary")) { ++ hold_primary = 1; ++ } else if (!strcasecmp(appData.recvText, "clipboard")) { ++ hold_clipboard = 1; ++ } else { ++ hold_primary = hold_clipboard = 1; ++ } ++ ++ if (!hold_primary) { ++ ; ++ } else if (XtOwnSelection(desktop, XA_PRIMARY, t, ConvertSelection, LoseSelection, NULL)) { ++ PrimarySelectionOwner = True; ++ if (dbg_sel) fprintf(stderr, "Own PRIMARY\n"); ++ } ++ if (!hold_clipboard || clipboard_atom == None) { ++ ; ++ } else if (XtOwnSelection(desktop, clipboard_atom, t, ConvertSelection, LoseSelection, NULL)) { ++ ClipboardSelectionOwner = True; ++ if (dbg_sel) fprintf(stderr, "Own CLIPBOARD\n"); ++ } + } + + +@@ -293,37 +333,36 @@ + XtPointer* value, unsigned long* length, int* format) + { + +- if (*target == XA_STRING && serverCutText != NULL) { +- *type = XA_STRING; +- *length = strlen(serverCutText); +- *value = (XtPointer)XtMalloc(*length); +- memcpy((char*)*value, serverCutText, *length); +- *format = 8; +- return True; +- } ++ if (*target == XA_STRING && serverCutText != NULL) { ++ *type = XA_STRING; ++ *length = strlen(serverCutText); ++ *value = (XtPointer)XtMalloc(*length); ++ memcpy((char*)*value, serverCutText, *length); ++ *format = 8; ++ return True; ++ } + +- if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, ++ if (XmuConvertStandardSelection(w, CurrentTime, selection, target, type, + (XPointer*)value, length, format)) { +- if (*target == XInternAtom(dpy, "TARGETS", False)) { +- /* add STRING to list of standard targets */ +- Atom* targetP; +- Atom* std_targets = (Atom*)*value; +- unsigned long std_length = *length; +- +- *length = std_length + 1; +- *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); +- targetP = *(Atom**)value; +- *targetP++ = XA_STRING; +- memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); +- XtFree((char*)std_targets); +- *type = XA_ATOM; +- *format = 32; +- return True; +- } +- +- return True; +- } +- return False; ++ if (*target == XInternAtom(dpy, "TARGETS", False)) { ++ /* add STRING to list of standard targets */ ++ Atom* targetP; ++ Atom* std_targets = (Atom*)*value; ++ unsigned long std_length = *length; ++ ++ *length = std_length + 1; ++ *value = (XtPointer)XtMalloc(sizeof(Atom)*(*length)); ++ targetP = *(Atom**)value; ++ *targetP++ = XA_STRING; ++ memmove((char*)targetP, (char*)std_targets, sizeof(Atom)*std_length); ++ XtFree((char*)std_targets); ++ *type = XA_ATOM; ++ *format = 32; ++ return True; ++ } ++ return True; ++ } ++ return False; + } + + +@@ -332,7 +371,12 @@ + */ + + static void +-LoseSelection(Widget w, Atom *selection) +-{ +- iAmSelectionOwner = False; ++LoseSelection(Widget w, Atom *selection) { ++ if (*selection == XA_PRIMARY) { ++ if (dbg_sel) fprintf(stderr, "lost PRIMARY\n"); ++ PrimarySelectionOwner = False; ++ } else if (clipboard_atom != None && *selection == clipboard_atom) { ++ if (dbg_sel) fprintf(stderr, "lost CLIPBOARD\n"); ++ ClipboardSelectionOwner = False; ++ } + } diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/shm.c vnc_unixsrc/vncviewer/shm.c --- vnc_unixsrc.orig/vncviewer/shm.c 2000-06-11 08:00:53.000000000 -0400 +++ vnc_unixsrc/vncviewer/shm.c 2008-10-10 12:26:07.000000000 -0400 @@ -12692,7 +14383,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/smake vnc_unixsrc/vncviewer/s +fi diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncviewer/sockets.c --- vnc_unixsrc.orig/vncviewer/sockets.c 2001-01-14 22:54:18.000000000 -0500 -+++ vnc_unixsrc/vncviewer/sockets.c 2008-10-15 08:30:41.000000000 -0400 ++++ vnc_unixsrc/vncviewer/sockets.c 2009-03-30 23:14:48.000000000 -0400 @@ -27,6 +27,7 @@ #include <netinet/in.h> #include <netinet/tcp.h> @@ -12701,7 +14392,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview #include <netdb.h> #include <fcntl.h> #include <assert.h> -@@ -56,22 +57,366 @@ +@@ -56,31 +57,376 @@ */ static Bool rfbsockReady = False; @@ -12722,11 +14413,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview + if (do_xfrsockId) { + XtRemoveInput(xfrsockId); + } -+} -+ -+static void + } + + static void +-ProcessXtEvents() +xfrsockReadyCallback(XtPointer clientData, int *fd, XtInputId *id) -+{ + { +- rfbsockReady = False; +- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, +- rfbsockReadyCallback, NULL); +- while (!rfbsockReady) { +- XtAppProcessEvent(appContext, XtIMAll); +- } + xfrsockReady = True; + XtRemoveInput(xfrsockId); + if (do_rfbsockId) { @@ -12927,8 +14625,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview + } +//fprintf(stderr, "Out CheckFileXfer\n"); + return; - } - ++} ++ +static void check_term_chat(void) { + fd_set fds; + struct timeval tv; @@ -12973,15 +14671,8 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview + +extern double start_time; + - static void - ProcessXtEvents() - { -- rfbsockReady = False; -- XtAppAddInput(appContext, rfbsock, (XtPointer)XtInputReadMask, -- rfbsockReadyCallback, NULL); -- while (!rfbsockReady) { -- XtAppProcessEvent(appContext, XtIMAll); -- } ++void ProcessXtEvents() ++{ + int y, db = 0; + static int dyn = -1; + static int chat_was_active = 0; @@ -13076,7 +14767,32 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview } Bool -@@ -151,6 +496,8 @@ + ReadFromRFBServer(char *out, unsigned int n) + { ++// double start = dnow(), dn = n; + if (n <= buffered) { + memcpy(out, bufoutptr, n); + bufoutptr += n; + buffered -= n; ++//fprintf(stderr, "R0: %06d\n", (int) dn); + return True; + } + +@@ -119,6 +465,7 @@ + memcpy(out, bufoutptr, n); + bufoutptr += n; + buffered -= n; ++//fprintf(stderr, "R1: %06d %06d %10.2f KB/sec\n", (int) dn, buffered+n, 1e-3 * (buffered+n)/(dnow() - start)); + return True; + + } else { +@@ -146,11 +493,14 @@ + n -= i; + } + ++//fprintf(stderr, "R2: %06d %06d %10.2f KB/sec\n", (int) dn, (int) dn, 1e-3 * (dn)/(dnow() - start)); + return True; + } } @@ -13085,7 +14801,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview /* * Write an exact number of bytes, and don't return until you've sent them. */ -@@ -158,37 +505,81 @@ +@@ -158,37 +508,81 @@ Bool WriteExact(int sock, char *buf, int n) { @@ -13196,7 +14912,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview } -@@ -203,6 +594,8 @@ +@@ -203,6 +597,8 @@ struct sockaddr_in addr; int one = 1; @@ -13205,7 +14921,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = host; -@@ -232,7 +625,22 @@ +@@ -232,7 +628,22 @@ return sock; } @@ -13228,7 +14944,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview /* * FindFreeTcpPort tries to find unused TCP port in the range -@@ -245,6 +653,8 @@ +@@ -245,6 +656,8 @@ int sock, port; struct sockaddr_in addr; @@ -13237,7 +14953,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; -@@ -272,6 +682,8 @@ +@@ -272,6 +685,8 @@ * ListenAtTcpPort starts listening at the given TCP port. */ @@ -13246,7 +14962,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/sockets.c vnc_unixsrc/vncview int ListenAtTcpPort(int port) { -@@ -279,10 +691,16 @@ +@@ -279,10 +694,16 @@ struct sockaddr_in addr; int one = 1; @@ -13292,6 +15008,23 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tight.c vnc_unixsrc/vncviewer return True; } +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tmake vnc_unixsrc/vncviewer/tmake +--- vnc_unixsrc.orig/vncviewer/tmake 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/tmake 2009-03-08 17:11:49.000000000 -0400 +@@ -0,0 +1,13 @@ ++#!/bin/sh ++TURBOVNC_DIR=/home/runge/turbojpeg ++make clean ++make CCOPTIONS=-DTURBOVNC EXTRA_LIBRARIES="-L$TURBOVNC_DIR -Xlinker --rpath=$TURBOVNC_DIR -Xlinker --rpath=/usr/local/lib -lturbojpeg" ++cp -p vncviewer vncviewer.turbovnc ++strip vncviewer.turbovnc ++ls -l vncviewer.turbovnc ++ldd vncviewer.turbovnc ++ ++echo ++make clean all ++ls -l vncviewer ++ldd vncviewer diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tunnel.c vnc_unixsrc/vncviewer/tunnel.c --- vnc_unixsrc.orig/vncviewer/tunnel.c 2003-07-31 04:03:49.000000000 -0400 +++ vnc_unixsrc/vncviewer/tunnel.c 2007-05-08 21:28:01.000000000 -0400 @@ -13318,10 +15051,860 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/tunnel.c vnc_unixsrc/vncviewe } sprintf(lastArgv, "localhost::%d", localPort); +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/tight.c vnc_unixsrc/vncviewer/turbovnc/tight.c +--- vnc_unixsrc.orig/vncviewer/turbovnc/tight.c 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/turbovnc/tight.c 2008-08-20 13:35:58.000000000 -0400 +@@ -0,0 +1,613 @@ ++/* ++ * Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. ++ * Copyright (C) 2004 Landmark Graphics Corporation. All Rights Reserved. ++ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved. ++ * ++ * This is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This software is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this software; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, ++ * USA. ++ */ ++ ++/* ++ * tight.c - handle ``tight'' encoding. ++ * ++ * This file shouldn't be compiled directly. It is included multiple ++ * times by rfbproto.c, each time with a different definition of the ++ * macro BPP. For each value of BPP, this file defines a function ++ * which handles a tight-encoded rectangle with BPP bits per pixel. ++ * ++ */ ++ ++#define TIGHT_MIN_TO_COMPRESS 12 ++ ++#define CARDBPP CONCAT2E(CARD,BPP) ++#define filterPtrBPP CONCAT2E(filterPtr,BPP) ++ ++#define HandleTightBPP CONCAT2E(HandleTight,BPP) ++#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP) ++#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP) ++#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP) ++#define FilterCopyBPP CONCAT2E(FilterCopy,BPP) ++#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP) ++#define FilterGradientBPP CONCAT2E(FilterGradient,BPP) ++ ++#if BPP != 8 ++#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP) ++#endif ++ ++#ifndef RGB_TO_PIXEL ++ ++#define RGB_TO_PIXEL(bpp,r,g,b) \ ++ (((CARD##bpp)(r) & myFormat.redMax) << myFormat.redShift | \ ++ ((CARD##bpp)(g) & myFormat.greenMax) << myFormat.greenShift | \ ++ ((CARD##bpp)(b) & myFormat.blueMax) << myFormat.blueShift) ++ ++#define RGB24_TO_PIXEL(bpp,r,g,b) \ ++ ((((CARD##bpp)(r) & 0xFF) * myFormat.redMax + 127) / 255 \ ++ << myFormat.redShift | \ ++ (((CARD##bpp)(g) & 0xFF) * myFormat.greenMax + 127) / 255 \ ++ << myFormat.greenShift | \ ++ (((CARD##bpp)(b) & 0xFF) * myFormat.blueMax + 127) / 255 \ ++ << myFormat.blueShift) ++ ++#define RGB24_TO_PIXEL32(r,g,b) \ ++ (((CARD32)(r) & 0xFF) << myFormat.redShift | \ ++ ((CARD32)(g) & 0xFF) << myFormat.greenShift | \ ++ ((CARD32)(b) & 0xFF) << myFormat.blueShift) ++ ++#endif ++ ++extern XImage *image; ++ ++/* Type declarations */ ++ ++typedef void (*filterPtrBPP)(int, int, int); ++ ++/* Prototypes */ ++ ++static int InitFilterCopyBPP (int rw, int rh); ++static int InitFilterPaletteBPP (int rw, int rh); ++static int InitFilterGradientBPP (int rw, int rh); ++static void FilterCopyBPP (int srcx, int srcy, int numRows); ++static void FilterPaletteBPP (int srcx, int srcy, int numRows); ++static void FilterGradientBPP (int srcx, int srcy, int numRows); ++ ++static Bool DecompressJpegRectBPP(int x, int y, int w, int h); ++ ++/* Definitions */ ++ ++static Bool ++HandleTightBPP (int rx, int ry, int rw, int rh) ++{ ++ CARDBPP fill_colour; ++ XGCValues gcv; ++ CARD8 comp_ctl; ++ CARD8 filter_id; ++ filterPtrBPP filterFn; ++ z_streamp zs; ++ int err, stream_id, compressedLen, bitsPixel; ++ int bufferSize, rowSize, numRows; ++ Bool readUncompressed = False; ++ CARDBPP *rawData; ++ ++ if (!ReadFromRFBServer((char *)&comp_ctl, 1)) ++ return False; ++ ++ /* Flush zlib streams if we are told by the server to do so. */ ++ for (stream_id = 0; stream_id < 4; stream_id++) { ++ if ((comp_ctl & 1) && zlibStreamActive[stream_id]) { ++ if (inflateEnd (&zlibStream[stream_id]) != Z_OK && ++ zlibStream[stream_id].msg != NULL) ++ fprintf(stderr, "inflateEnd: %s\n", zlibStream[stream_id].msg); ++ zlibStreamActive[stream_id] = False; ++ } ++ comp_ctl >>= 1; ++ } ++ ++ if ((comp_ctl & rfbTightNoZlib) == rfbTightNoZlib) { ++ comp_ctl &= ~(rfbTightNoZlib); ++ readUncompressed = True; ++ } ++ ++ /* Handle solid rectangles. */ ++ if (comp_ctl == rfbTightFill) { ++#if BPP == 32 ++ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && ++ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { ++ if (!ReadFromRFBServer(buffer, 3)) ++ return False; ++ fill_colour = RGB24_TO_PIXEL32(buffer[0], buffer[1], buffer[2]); ++ } else { ++ if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) ++ return False; ++ } ++#else ++ if (!ReadFromRFBServer((char*)&fill_colour, sizeof(fill_colour))) ++ return False; ++#endif ++ ++#if (BPP == 8) ++ gcv.foreground = (appData.useBGR233) ? ++ BGR233ToPixel[fill_colour] : fill_colour; ++#else ++ gcv.foreground = fill_colour; ++#endif ++ ++ FillRectangle(&gcv, rx, ry, rw, rh); ++ return True; ++ } ++ ++#if BPP == 8 ++ if (comp_ctl == rfbTightJpeg) { ++ fprintf(stderr, "Tight encoding: JPEG is not supported in 8 bpp mode.\n"); ++ return False; ++ } ++#else ++ if (comp_ctl == rfbTightJpeg) { ++ return DecompressJpegRectBPP(rx, ry, rw, rh); ++ } ++#endif ++ ++ /* Quit on unsupported subencoding value. */ ++ if (comp_ctl > rfbTightMaxSubencoding) { ++ fprintf(stderr, "Tight encoding: bad subencoding value received.\n"); ++ return False; ++ } ++ ++ /* ++ * Here primary compression mode handling begins. ++ * Data was processed with optional filter + zlib compression. ++ */ ++ ++ /* First, we should identify a filter to use. */ ++ if ((comp_ctl & rfbTightExplicitFilter) != 0) { ++ if (!ReadFromRFBServer((char*)&filter_id, 1)) ++ return False; ++ ++ switch (filter_id) { ++ case rfbTightFilterCopy: ++ filterFn = FilterCopyBPP; ++ bitsPixel = InitFilterCopyBPP(rw, rh); ++ break; ++ case rfbTightFilterPalette: ++ filterFn = FilterPaletteBPP; ++ bitsPixel = InitFilterPaletteBPP(rw, rh); ++ break; ++ case rfbTightFilterGradient: ++ filterFn = FilterGradientBPP; ++ bitsPixel = InitFilterGradientBPP(rw, rh); ++ break; ++ default: ++ fprintf(stderr, "Tight encoding: unknown filter code received.\n"); ++ return False; ++ } ++ } else { ++ filterFn = FilterCopyBPP; ++ bitsPixel = InitFilterCopyBPP(rw, rh); ++ } ++ if (bitsPixel == 0) { ++ fprintf(stderr, "Tight encoding: error receiving palette.\n"); ++ return False; ++ } ++ ++ /* Determine if the data should be decompressed or just copied. */ ++ rowSize = (rw * bitsPixel + 7) / 8; ++ bufferSize = -1; ++ if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) ++ bufferSize = rh * rowSize; ++ else if (readUncompressed) { ++ bufferSize = (int)ReadCompactLen(); ++ } ++ if (bufferSize != -1) { ++ uncompressedData = (char *)realloc(uncompressedData, bufferSize); ++ if (!uncompressedData) { ++ fprintf(stderr, "Memory allocation error\n"); ++ return False; ++ } ++ if (!ReadFromRFBServer(uncompressedData, bufferSize)) ++ return False; ++ filterFn(rx, ry, rh); ++ if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); ++ if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); ++ ++ return True; ++ } ++ ++ /* Read the length (1..3 bytes) of compressed data following. */ ++ compressedLen = (int)ReadCompactLen(); ++ if (compressedLen <= 0) { ++ fprintf(stderr, "Incorrect data received from the server.\n"); ++ return False; ++ } ++ ++ /* Now let's initialize compression stream if needed. */ ++ stream_id = comp_ctl & 0x03; ++ zs = &zlibStream[stream_id]; ++ if (!zlibStreamActive[stream_id]) { ++ zs->zalloc = Z_NULL; ++ zs->zfree = Z_NULL; ++ zs->opaque = Z_NULL; ++ err = inflateInit(zs); ++ if (err != Z_OK) { ++ if (zs->msg != NULL) ++ fprintf(stderr, "InflateInit error: %s.\n", zs->msg); ++ return False; ++ } ++ zlibStreamActive[stream_id] = True; ++ } ++ ++ /* Read, decode and draw actual pixel data in a loop. */ ++ ++ compressedData = (char *)realloc(compressedData, compressedLen); ++ if (!compressedData) { ++ fprintf(stderr, "Memory allocation error\n"); ++ return False; ++ } ++ uncompressedData = (char *)realloc(uncompressedData, rh * rowSize); ++ if (!uncompressedData) { ++ fprintf(stderr, "Memory allocation error\n"); ++ return False; ++ } ++ ++ if (!ReadFromRFBServer(compressedData, compressedLen)) ++ return False; ++ zs->next_in = (Bytef *)compressedData; ++ zs->avail_in = compressedLen; ++ zs->next_out = (Bytef *)uncompressedData; ++ zs->avail_out = rh * rowSize; ++ ++ err = inflate(zs, Z_SYNC_FLUSH); ++ if (err != Z_OK && err != Z_STREAM_END) { ++ if (zs->msg != NULL) { ++ fprintf(stderr, "Inflate error: %s.\n", zs->msg); ++ } else { ++ fprintf(stderr, "Inflate error: %d.\n", err); ++ } ++ return False; ++ } ++ ++ filterFn(rx, ry, rh); ++ if (appData.useBGR233) CopyDataToImage(buffer, rx, ry, rw, rh); ++ if (!appData.doubleBuffer) CopyImageToScreen(rx, ry, rw, rh); ++ ++ return True; ++} ++ ++/*---------------------------------------------------------------------------- ++ * ++ * Filter stuff. ++ * ++ */ ++ ++/* ++ The following variables are defined in rfbproto.c: ++ static Bool cutZeros; ++ static int rectWidth, rectColors; ++ static CARD8 tightPalette[256*4]; ++ static CARD8 tightPrevRow[2048*3*sizeof(CARD16)]; ++*/ ++ ++static int ++InitFilterCopyBPP (int rw, int rh) ++{ ++ rectWidth = rw; ++ ++#if BPP == 32 ++ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && ++ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { ++ cutZeros = True; ++ return 24; ++ } else { ++ cutZeros = False; ++ } ++#endif ++ ++ return BPP; ++} ++ ++static void ++FilterCopyBPP (int srcx, int srcy, int numRows) ++{ ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ int y; ++#if BPP == 32 ++ int x; ++#endif ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++#if BPP == 32 ++ if (cutZeros) { ++ for (y = 0; y < numRows; y++) { ++ for (x = 0; x < rectWidth; x++) { ++ dst[y*dstw+x] = ++ RGB24_TO_PIXEL32(uncompressedData[(y*rectWidth+x)*3], ++ uncompressedData[(y*rectWidth+x)*3+1], ++ uncompressedData[(y*rectWidth+x)*3+2]); ++ } ++ } ++ return; ++ } ++#endif ++ ++ for (y = 0; y < numRows; y++) ++ memcpy (&dst[y*dstw], &uncompressedData[y*rectWidth], rectWidth * (BPP / 8)); ++} ++ ++static int ++InitFilterGradientBPP (int rw, int rh) ++{ ++ int bits; ++ ++ bits = InitFilterCopyBPP(rw, rh); ++ if (cutZeros) ++ memset(tightPrevRow, 0, rw * 3); ++ else ++ memset(tightPrevRow, 0, rw * 3 * sizeof(CARD16)); ++ ++ return bits; ++} ++ ++#if BPP == 32 ++ ++static void ++FilterGradient24 (int srcx, int srcy, int numRows) ++{ ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ int x, y, c; ++ CARD8 thisRow[2048*3]; ++ CARD8 pix[3]; ++ int est[3]; ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++ for (y = 0; y < numRows; y++) { ++ ++ /* First pixel in a row */ ++ for (c = 0; c < 3; c++) { ++ pix[c] = tightPrevRow[c] + uncompressedData[y*rectWidth*3+c]; ++ thisRow[c] = pix[c]; ++ } ++ dst[y*dstw] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); ++ ++ /* Remaining pixels of a row */ ++ for (x = 1; x < rectWidth; x++) { ++ for (c = 0; c < 3; c++) { ++ est[c] = (int)tightPrevRow[x*3+c] + (int)pix[c] - ++ (int)tightPrevRow[(x-1)*3+c]; ++ if (est[c] > 0xFF) { ++ est[c] = 0xFF; ++ } else if (est[c] < 0x00) { ++ est[c] = 0x00; ++ } ++ pix[c] = (CARD8)est[c] + buffer[(y*rectWidth+x)*3+c]; ++ thisRow[x*3+c] = pix[c]; ++ } ++ dst[y*dstw+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]); ++ } ++ ++ memcpy(tightPrevRow, thisRow, rectWidth * 3); ++ } ++} ++ ++#endif ++ ++static void ++FilterGradientBPP (int srcx, int srcy, int numRows) ++{ ++ int x, y, c; ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ CARDBPP *src = (CARDBPP *)uncompressedData; ++ CARD16 *thatRow = (CARD16 *)tightPrevRow; ++ CARD16 thisRow[2048*3]; ++ CARD16 pix[3]; ++ CARD16 max[3]; ++ int shift[3]; ++ int est[3]; ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++#if BPP == 32 ++ if (cutZeros) { ++ FilterGradient24(srcx, srcy, numRows); ++ return; ++ } ++#endif ++ ++ max[0] = myFormat.redMax; ++ max[1] = myFormat.greenMax; ++ max[2] = myFormat.blueMax; ++ ++ shift[0] = myFormat.redShift; ++ shift[1] = myFormat.greenShift; ++ shift[2] = myFormat.blueShift; ++ ++ for (y = 0; y < numRows; y++) { ++ ++ /* First pixel in a row */ ++ for (c = 0; c < 3; c++) { ++ pix[c] = (CARD16)((src[y*rectWidth] >> shift[c]) + thatRow[c] & max[c]); ++ thisRow[c] = pix[c]; ++ } ++ dst[y*dstw] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); ++ ++ /* Remaining pixels of a row */ ++ for (x = 1; x < rectWidth; x++) { ++ for (c = 0; c < 3; c++) { ++ est[c] = (int)thatRow[x*3+c] + (int)pix[c] - (int)thatRow[(x-1)*3+c]; ++ if (est[c] > (int)max[c]) { ++ est[c] = (int)max[c]; ++ } else if (est[c] < 0) { ++ est[c] = 0; ++ } ++ pix[c] = (CARD16)((src[y*rectWidth+x] >> shift[c]) + est[c] & max[c]); ++ thisRow[x*3+c] = pix[c]; ++ } ++ dst[y*dstw+x] = RGB_TO_PIXEL(BPP, pix[0], pix[1], pix[2]); ++ } ++ memcpy(thatRow, thisRow, rectWidth * 3 * sizeof(CARD16)); ++ } ++} ++ ++static int ++InitFilterPaletteBPP (int rw, int rh) ++{ ++ int i; ++ CARD8 numColors; ++ CARDBPP *palette = (CARDBPP *)tightPalette; ++ ++ rectWidth = rw; ++ ++ if (!ReadFromRFBServer((char*)&numColors, 1)) ++ return 0; ++ ++ rectColors = (int)numColors; ++ if (++rectColors < 2) ++ return 0; ++ ++#if BPP == 32 ++ if (myFormat.depth == 24 && myFormat.redMax == 0xFF && ++ myFormat.greenMax == 0xFF && myFormat.blueMax == 0xFF) { ++ if (!ReadFromRFBServer((char*)&tightPalette, rectColors * 3)) ++ return 0; ++ for (i = rectColors - 1; i >= 0; i--) { ++ palette[i] = RGB24_TO_PIXEL32(tightPalette[i*3], ++ tightPalette[i*3+1], ++ tightPalette[i*3+2]); ++ } ++ return (rectColors == 2) ? 1 : 8; ++ } ++#endif ++ ++ if (!ReadFromRFBServer((char*)&tightPalette, rectColors * (BPP / 8))) ++ return 0; ++ ++ return (rectColors == 2) ? 1 : 8; ++} ++ ++static void ++FilterPaletteBPP (int srcx, int srcy, int numRows) ++{ ++ int x, y, b, w; ++ CARDBPP *dst = (CARDBPP *)&image->data[srcy * image->bytes_per_line ++ + srcx * image->bits_per_pixel/8]; ++ int dstw = image->bytes_per_line / (image->bits_per_pixel / 8); ++ CARD8 *src = (CARD8 *)uncompressedData; ++ CARDBPP *palette = (CARDBPP *)tightPalette; ++ ++ if (appData.useBGR233) { ++ dst = (CARDBPP *)buffer; ++ dstw = rectWidth; ++ } ++ ++ if (rectColors == 2) { ++ w = (rectWidth + 7) / 8; ++ for (y = 0; y < numRows; y++) { ++ for (x = 0; x < rectWidth / 8; x++) { ++ for (b = 7; b >= 0; b--) ++ dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; ++ } ++ for (b = 7; b >= 8 - rectWidth % 8; b--) { ++ dst[y*dstw+x*8+7-b] = palette[src[y*w+x] >> b & 1]; ++ } ++ } ++ } else { ++ for (y = 0; y < numRows; y++) ++ for (x = 0; x < rectWidth; x++) ++ dst[y*dstw+x] = palette[(int)src[y*rectWidth+x]]; ++ } ++} ++ ++#if BPP != 8 ++ ++/*---------------------------------------------------------------------------- ++ * ++ * JPEG decompression. ++ * ++ */ ++ ++/* ++ The following variables are defined in rfbproto.c: ++ static Bool jpegError; ++ static struct jpeg_source_mgr jpegSrcManager; ++ static JOCTET *jpegBufferPtr; ++ static size_t *jpegBufferLen; ++*/ ++ ++static Bool ++DecompressJpegRectBPP(int x, int y, int w, int h) ++{ ++ int compressedLen; ++ char *dstptr; ++ int ps, flags=0; ++ ++ compressedLen = (int)ReadCompactLen(); ++ if (compressedLen <= 0) { ++ fprintf(stderr, "Incorrect data received from the server.\n"); ++ return False; ++ } ++ ++ compressedData = (char *)realloc(compressedData, compressedLen); ++ if (compressedData == NULL) { ++ fprintf(stderr, "Memory allocation error.\n"); ++ return False; ++ } ++ ++ if (!ReadFromRFBServer(compressedData, compressedLen)) { ++ return False; ++ } ++ ++ if(!tjhnd) { ++ if((tjhnd=tjInitDecompress())==NULL) { ++ fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); ++ return False; ++ } ++ } ++ ++ ps=image->bits_per_pixel/8; ++ if(myFormat.bigEndian && ps==4) flags|=TJ_ALPHAFIRST; ++ if(myFormat.redShift==16 && myFormat.blueShift==0) ++ flags|=TJ_BGR; ++ if(myFormat.bigEndian) flags^=TJ_BGR; ++ ++ dstptr=&image->data[image->bytes_per_line*y+x*ps]; ++ if(tjDecompress(tjhnd, (unsigned char *)compressedData, (unsigned long)compressedLen, ++ (unsigned char *)dstptr, w, image->bytes_per_line, h, ps, flags)==-1) { ++ fprintf(stderr, "TurboJPEG error: %s\n", tjGetErrorStr()); ++ return False; ++ } ++ ++ if (!appData.doubleBuffer) ++ CopyImageToScreen(x, y, w, h); ++ ++ return True; ++} ++ ++#endif ++ +diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h +--- vnc_unixsrc.orig/vncviewer/turbovnc/turbojpeg.h 1969-12-31 19:00:00.000000000 -0500 ++++ vnc_unixsrc/vncviewer/turbovnc/turbojpeg.h 2008-04-03 04:28:56.000000000 -0400 +@@ -0,0 +1,229 @@ ++/* Copyright (C)2004 Landmark Graphics ++ * Copyright (C)2005, 2006 Sun Microsystems, Inc. ++ * ++ * This library is free software and may be redistributed and/or modified under ++ * the terms of the wxWindows Library License, Version 3.1 or (at your option) ++ * any later version. The full license is in the LICENSE.txt file included ++ * with this distribution. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * wxWindows Library License for more details. ++ */ ++ ++#if (defined(_MSC_VER) || defined(__CYGWIN__) || defined(__MINGW32__)) && defined(_WIN32) && defined(DLLDEFINE) ++#define DLLEXPORT __declspec(dllexport) ++#else ++#define DLLEXPORT ++#endif ++ ++#define DLLCALL ++ ++/* Subsampling */ ++#define NUMSUBOPT 4 ++ ++enum {TJ_444=0, TJ_422, TJ_411, TJ_GRAYSCALE}; ++ ++/* Flags */ ++#define TJ_BGR 1 ++#define TJ_BOTTOMUP 2 ++#define TJ_FORCEMMX 8 /* Force IPP to use MMX code even if SSE available */ ++#define TJ_FORCESSE 16 /* Force IPP to use SSE1 code even if SSE2 available */ ++#define TJ_FORCESSE2 32 /* Force IPP to use SSE2 code (useful if auto-detect is not working properly) */ ++#define TJ_ALPHAFIRST 64 /* BGR buffer is ABGR and RGB buffer is ARGB */ ++#define TJ_FORCESSE3 128 /* Force IPP to use SSE3 code (useful if auto-detect is not working properly) */ ++ ++typedef void* tjhandle; ++ ++#define TJPAD(p) (((p)+3)&(~3)) ++#ifndef max ++ #define max(a,b) ((a)>(b)?(a):(b)) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* API follows */ ++ ++ ++/* ++ tjhandle tjInitCompress(void) ++ ++ Creates a new JPEG compressor instance, allocates memory for the structures, ++ and returns a handle to the instance. Most applications will only ++ need to call this once at the beginning of the program or once for each ++ concurrent thread. Don't try to create a new instance every time you ++ compress an image, because this will cause performance to suffer. ++ ++ RETURNS: NULL on error ++*/ ++DLLEXPORT tjhandle DLLCALL tjInitCompress(void); ++ ++ ++/* ++ int tjCompress(tjhandle j, ++ unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, ++ unsigned char *dstbuf, unsigned long *size, ++ int jpegsubsamp, int jpegqual, int flags) ++ ++ [INPUT] j = instance handle previously returned from a call to ++ tjInitCompress() ++ [INPUT] srcbuf = pointer to user-allocated image buffer containing pixels in ++ RGB(A) or BGR(A) form ++ [INPUT] width = width (in pixels) of the source image ++ [INPUT] pitch = bytes per line of the source image (width*pixelsize if the ++ bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap ++ is padded to the nearest 32-bit boundary, such as is the case for Windows ++ bitmaps. You can also be clever and use this parameter to skip lines, etc., ++ as long as the pitch is greater than 0.) ++ [INPUT] height = height (in pixels) of the source image ++ [INPUT] pixelsize = size (in bytes) of each pixel in the source image ++ RGBA and BGRA: 4, RGB and BGR: 3 ++ [INPUT] dstbuf = pointer to user-allocated image buffer which will receive ++ the JPEG image. Use the macro TJBUFSIZE(width, height) to determine ++ the appropriate size for this buffer based on the image width and height. ++ [OUTPUT] size = pointer to unsigned long which receives the size (in bytes) ++ of the compressed image ++ [INPUT] jpegsubsamp = Specifies either 4:1:1, 4:2:2, or 4:4:4 subsampling. ++ When the image is converted from the RGB to YCbCr colorspace as part of the ++ JPEG compression process, every other Cb and Cr (chrominance) pixel can be ++ discarded to produce a smaller image with little perceptible loss of ++ image clarity (the human eye is more sensitive to small changes in ++ brightness than small changes in color.) ++ ++ TJ_411: 4:1:1 subsampling. Discards every other Cb, Cr pixel in both ++ horizontal and vertical directions. ++ TJ_422: 4:2:2 subsampling. Discards every other Cb, Cr pixel only in ++ the horizontal direction. ++ TJ_444: no subsampling. ++ TJ_GRAYSCALE: Generate grayscale JPEG image ++ ++ [INPUT] jpegqual = JPEG quality (an integer between 0 and 100 inclusive.) ++ [INPUT] flags = the bitwise OR of one or more of the following ++ ++ TJ_BGR: The components of each pixel in the source image are stored in ++ B,G,R order, not R,G,B ++ TJ_BOTTOMUP: The source image is stored in bottom-up (Windows) order, ++ not top-down ++ TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use MMX code (bypass CPU auto-detection) ++ TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE code (bypass CPU auto-detection) ++ TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) ++ TJ_FORCESSE3: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE3 code (bypass CPU auto-detection) ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjCompress(tjhandle j, ++ unsigned char *srcbuf, int width, int pitch, int height, int pixelsize, ++ unsigned char *dstbuf, unsigned long *size, ++ int jpegsubsamp, int jpegqual, int flags); ++ ++DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height); ++ ++/* ++ tjhandle tjInitDecompress(void) ++ ++ Creates a new JPEG decompressor instance, allocates memory for the ++ structures, and returns a handle to the instance. Most applications will ++ only need to call this once at the beginning of the program or once for each ++ concurrent thread. Don't try to create a new instance every time you ++ decompress an image, because this will cause performance to suffer. ++ ++ RETURNS: NULL on error ++*/ ++DLLEXPORT tjhandle DLLCALL tjInitDecompress(void); ++ ++ ++/* ++ int tjDecompressHeader(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ int *width, int *height) ++ ++ [INPUT] j = instance handle previously returned from a call to ++ tjInitDecompress() ++ [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image ++ to decompress ++ [INPUT] size = size of the JPEG image buffer (in bytes) ++ [OUTPUT] width = width (in pixels) of the JPEG image ++ [OUTPUT] height = height (in pixels) of the JPEG image ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ int *width, int *height); ++ ++ ++/* ++ int tjDecompress(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, ++ int flags) ++ ++ [INPUT] j = instance handle previously returned from a call to ++ tjInitDecompress() ++ [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image ++ to decompress ++ [INPUT] size = size of the JPEG image buffer (in bytes) ++ [INPUT] dstbuf = pointer to user-allocated image buffer which will receive ++ the bitmap image. This buffer should normally be pitch*height ++ bytes in size, although this pointer may also be used to decompress into ++ a specific region of a larger buffer. ++ [INPUT] width = width (in pixels) of the destination image ++ [INPUT] pitch = bytes per line of the destination image (width*pixelsize if the ++ bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap ++ is padded to the nearest 32-bit boundary, such as is the case for Windows ++ bitmaps. You can also be clever and use this parameter to skip lines, etc., ++ as long as the pitch is greater than 0.) ++ [INPUT] height = height (in pixels) of the destination image ++ [INPUT] pixelsize = size (in bytes) of each pixel in the destination image ++ RGBA/RGBx and BGRA/BGRx: 4, RGB and BGR: 3 ++ [INPUT] flags = the bitwise OR of one or more of the following ++ ++ TJ_BGR: The components of each pixel in the destination image should be ++ written in B,G,R order, not R,G,B ++ TJ_BOTTOMUP: The destination image should be stored in bottom-up ++ (Windows) order, not top-down ++ TJ_FORCEMMX: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use MMX code (bypass CPU auto-detection) ++ TJ_FORCESSE: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE code (bypass CPU auto-detection) ++ TJ_FORCESSE2: Valid only for the Intel Performance Primitives implementation ++ of this codec-- force IPP to use SSE2 code (bypass CPU auto-detection) ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjDecompress(tjhandle j, ++ unsigned char *srcbuf, unsigned long size, ++ unsigned char *dstbuf, int width, int pitch, int height, int pixelsize, ++ int flags); ++ ++ ++/* ++ int tjDestroy(tjhandle h) ++ ++ Frees structures associated with a compression or decompression instance ++ ++ [INPUT] h = instance handle (returned from a previous call to ++ tjInitCompress() or tjInitDecompress() ++ ++ RETURNS: 0 on success, -1 on error ++*/ ++DLLEXPORT int DLLCALL tjDestroy(tjhandle h); ++ ++ ++/* ++ char *tjGetErrorStr(void) ++ ++ Returns a descriptive error message explaining why the last command failed ++*/ ++DLLEXPORT char* DLLCALL tjGetErrorStr(void); ++ ++#ifdef __cplusplus ++} ++#endif diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vncviewer/vncviewer._man --- vnc_unixsrc.orig/vncviewer/vncviewer._man 1969-12-31 19:00:00.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer._man 2008-12-30 19:24:50.000000000 -0500 -@@ -0,0 +1,739 @@ ++++ vnc_unixsrc/vncviewer/vncviewer._man 2009-05-31 18:53:07.000000000 -0400 +@@ -0,0 +1,780 @@ +'\" t +.\" ** The above line should force tbl to be a preprocessor ** +.\" Man page for X vncviewer @@ -13329,13 +15912,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +.\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de +.\" Copyright (C) 2000,2001 Red Hat, Inc. +.\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru> -+.\" Copyright (C) 2006-2008 Karl J. Runge <runge@karlrunge.com> ++.\" Copyright (C) 2006-2009 Karl J. Runge <runge@karlrunge.com> +.\" +.\" You may distribute under the terms of the GNU General Public +.\" License as specified in the file LICENCE.TXT that comes with the +.\" TightVNC distribution. +.\" -+.TH ssvncviewer 1 "December 2008" "" "SSVNC" ++.TH ssvncviewer 1 "June 2009" "" "SSVNC" +.SH NAME +ssvncviewer \- an X viewer client for VNC +.SH SYNOPSIS @@ -13624,6 +16207,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +Prefer raw encoding for localhost, default is +no, i.e. assumes you have a SSH tunnel instead. +.TP ++\fB\-sendclipboard\fR ++Send the X CLIPBOARD selection (i.e. Ctrl+C, ++Ctrl+V) instead of the X PRIMARY selection (mouse ++select and middle button paste.) ++.TP ++\fB\-sendalways\fR ++Whenever the mouse enters the VNC viewer main ++window, send the selection to the VNC server even if ++it has not changed. This is like the Xt resource ++translation SelectionToVNC(always) ++.TP ++\fB\-recvtext\fR ++str When cut text is received from the VNC server, ++ssvncviewer will set both the X PRIMARY and the ++X CLIPBOARD local selections. To control which ++is set, specify 'str' as 'primary', 'clipboard', ++or 'both' (the default.) ++.TP +\fB\-graball\fR +Grab the entire X server when in fullscreen mode, +needed by some old window managers like fvwm2. @@ -13720,6 +16321,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +data sent so as to work with the UltraVNC Server. For some +reason, each RFB msg type must be sent twice under DSM. +.TP ++\fB\-mslogon\fR \fIuser\fR ++Use Windows MS Logon to an UltraVNC server. Supply the ++username or "1" to be prompted. The default is to ++autodetect the UltraVNC MS Logon server and prompt for ++the username and password. ++ ++IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman ++exchange is very weak and can be brute forced to recover ++your username and password in a few hours or seconds of CPU ++time. To be safe, be sure to use an additional encrypted ++tunnel (e.g. SSL or SSH) for the entire VNC session. ++.TP +\fB\-chatonly\fR +Try to be a client that only does UltraVNC text chat. This +mode is used by x11vnc to present a chat window on the physical @@ -13736,6 +16349,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +keybindings and Popup menu) Then point to the file via +XENVIRONMENT or XAPPLRESDIR. +.TP ++\fB\-pipeline\fR ++Like TurboVNC, request the next framebuffer update as soon ++as possible instead of waiting until the end of the current ++framebuffer update coming in. Helps 'pipeline' the updates. ++This is currently the default, use \fB-nopipeline\fR to disable. ++.TP +\fB\-escape \fR\fIstr\fR +This sets the 'Escape Keys' modifier sequence and enables +escape keys mode. When the modifier keys escape sequence @@ -13811,8 +16430,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) -+ Full Color ~ as many colors as local screen allows. -+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes. ++ Pipeline Updates ~ -pipeline ++ ++ Full Color as many colors as local screen allows. ++ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. + 16 bit color (BGR565) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. @@ -13827,16 +16448,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn + + UltraVNC Extensions: + -+ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. -+ Text Chat Ultravnc ext. Do Text Chat. -+ File Transfer Ultravnc ext. File xfer via Java helper. -+ Single Window Ultravnc ext. Grab a single window. -+ (click on the window you want). -+ Disable Remote Input Ultravnc ext. Try to prevent input and -+ viewing of monitor at physical display. ++ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. ++ Text Chat Ultravnc ext. Do Text Chat. ++ File Transfer Ultravnc ext. File xfer via Java helper. ++ Single Window Ultravnc ext. Grab and view a single window. ++ (select then click on the window you want). ++ Disable Remote Input Ultravnc ext. Try to prevent input and ++ viewing of monitor at physical display. ++ ++ Note: the Ultravnc extensions only apply to servers that support ++ them. x11vnc/libvncserver supports some of them. + -+ Note: the Ultravnc extensions only apply to servers that -+ support them. x11vnc/libvncserver supports some of them. ++ Send Clipboard not Primary ~ -sendclipboard ++ Send Selection Every time ~ -sendalways + +.SH ENCODINGS +The server supplies information in whatever format is desired by the @@ -14063,7 +16687,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer._man vnc_unixsrc/vn +Karl Runge <runge@karlrunge.com> diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncviewer/vncviewer.c --- vnc_unixsrc.orig/vncviewer/vncviewer.c 2004-01-13 09:22:05.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer.c 2008-12-30 19:22:19.000000000 -0500 ++++ vnc_unixsrc/vncviewer/vncviewer.c 2009-05-31 16:25:56.000000000 -0400 @@ -22,6 +22,7 @@ */ @@ -14072,7 +16696,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi char *programName; XtAppContext appContext; -@@ -29,11 +30,221 @@ +@@ -29,11 +30,234 @@ Widget toplevel; @@ -14152,10 +16776,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + if (!strcmp(str, ".")) { + char *p; + fprintf(stderr, "\nUnix Username: "); -+ if (fgets(username, N, stdin) == NULL) { -+ exit(1); ++ if (!isatty(0)) { ++ char *u = DoUserDialog(); ++ if (strlen(u) >= 100) { ++ exit(1); ++ } ++ sprintf(username, u); ++ p = DoPasswordDialog(); ++ } else { ++ if (fgets(username, N, stdin) == NULL) { ++ exit(1); ++ } ++ p = getpass("Unix Password: "); + } -+ p = getpass("Unix Password: "); + if (! p) { + exit(1); + } @@ -14164,7 +16797,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + + } else if (!strcmp(str, "-")) { + char *p, *q; -+ p = getpass("unixuser@unixpasswd: "); ++ if (!isatty(0)) { ++ p = DoPasswordDialog(); ++ } else { ++ p = getpass("unixuser@unixpasswd: "); ++ } + if (! p) { + exit(1); + } @@ -14296,7 +16933,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi /* The -listen option is used to make us a daemon process which listens for incoming connections from servers, rather than actively connecting to a -@@ -45,89 +256,1415 @@ +@@ -45,89 +269,1607 @@ listenForIncomingConnections() returns, setting the listenSpecified flag. */ @@ -14488,6 +17125,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi - CreatePopup(); + CreatePopup(); + CreateScaleN(); ++ CreateTurboVNC(); + CreateQuality(); + CreateCompress(); + CreateChat(); @@ -14692,11 +17330,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + appData.escapeActive = True; + } +} -+ + +- Cleanup(); +/* + * ToggleNColors + */ -+ + +- return 0; +static Widget w256 = NULL; +static Widget w64 = NULL; +static Widget w8 = NULL; @@ -14980,6 +17620,44 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + } +} + ++void ++TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.pipelineUpdates) { ++ appData.pipelineUpdates= False; ++ fprintf(stderr, "pipeline-update: off\n"); ++ } else { ++ appData.pipelineUpdates = True; ++ fprintf(stderr, "pipeline-update: on\n"); ++ } ++ /* XXX request one to be sure? */ ++} ++ ++void ++ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.sendClipboard) { ++ appData.sendClipboard= False; ++ fprintf(stderr, "Send CLIPBOARD Selection: off (send PRIMARY instead)\n"); ++ } else { ++ appData.sendClipboard = True; ++ fprintf(stderr, "Send CLIPBOARD Selection: on (do not send PRIMARY)\n"); ++ } ++} ++ ++void ++ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (appData.sendAlways) { ++ appData.sendAlways= False; ++ fprintf(stderr, "Send Selection Always: off\n"); ++ } else { ++ appData.sendAlways = True; ++ fprintf(stderr, "Send Selection Always: on\n"); ++ } ++} ++ ++ +Bool _sw1_ = False; /* XXX this is a weird bug... */ +Bool _sw2_ = False; +Bool _sw3_ = False; @@ -15218,10 +17896,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + if (s[0] != '\0') { + int w = si.framebufferWidth; + int h = si.framebufferHeight; ++ double fx, fy; + int fs = 0; + if (appData.scale != NULL && !strcmp(s, appData.scale)) { + return; + } ++ + if (!strcasecmp(s, "none")) { + appData.scale = NULL; + } else if (!strcmp(s, "1.0")) { @@ -15231,6 +17911,14 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + } else { + appData.scale = strdup(s); + } ++ if (appData.scale != NULL) { ++ get_scale_values(&fx, &fy); ++ if (fx <= 0.0 || fy <= 0.0) { ++ appData.scale = NULL; ++ return; ++ } ++ } ++ + if (appData.fullScreen) { + fs = 1; + FullScreenOff(); @@ -15329,6 +18017,119 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + } +} + ++void UpdateQual(void) { ++ SetFormatAndEncodings(); ++ UpdateSubsampButtons(); ++ UpdateQualSlider(); ++} ++ ++extern double latency; ++ ++static void LosslessRefresh(void) { ++ String encodings = appData.encodingsString; ++ int compressLevel = appData.compressLevel; ++ int qual = appData.qualityLevel; ++ Bool enableJPEG = appData.enableJPEG; ++ appData.qualityLevel = -1; ++ appData.enableJPEG = False; ++ appData.encodingsString = "tight copyrect"; ++ appData.compressLevel = 1; ++ SetFormatAndEncodings(); ++ SendFramebufferUpdateRequest(0, 0, si.framebufferWidth, si.framebufferHeight, False); ++ if (latency > 0.0) { ++ if (0) usleep((int) latency * 1000); ++ } ++ appData.qualityLevel = qual; ++ appData.enableJPEG = enableJPEG; ++ appData.encodingsString = encodings; ++ appData.compressLevel = compressLevel; ++ SetFormatAndEncodings(); ++} ++ ++static void QualHigh(void) { ++ appData.encodingsString = "tight copyrect"; ++ if(appData.useBGR233 || appDataNew.useBGR565) { ++ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); ++ } else { ++ appData.enableJPEG = True; ++ } ++ appData.subsampLevel = TVNC_1X; ++ appData.qualityLevel = 95; ++ UpdateQual(); ++} ++ ++static void QualMed(void) { ++ appData.encodingsString = "tight copyrect"; ++ if(appData.useBGR233 || appDataNew.useBGR565) { ++ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); ++ } else { ++ appData.enableJPEG = True; ++ } ++ appData.subsampLevel = TVNC_2X; ++ appData.qualityLevel = 80; ++ UpdateQual(); ++} ++ ++static void QualLow(void) { ++ appData.encodingsString = "tight copyrect"; ++ if(appData.useBGR233 || appDataNew.useBGR565) { ++ fprintf(stderr, "WARNING: Cannot enable JPEG because BGR233/BGR565 is enabled.\n"); ++ } else { ++ appData.enableJPEG = True; ++ } ++ appData.subsampLevel = TVNC_4X; ++ appData.qualityLevel = 30; ++ UpdateQual(); ++} ++ ++static void QualLossless(void) { ++ appData.encodingsString = "tight copyrect"; ++ appData.enableJPEG = False; ++ appData.compressLevel = 0; ++ UpdateQual(); ++} ++ ++static void QualLosslessWAN(void) { ++ appData.encodingsString = "tight copyrect"; ++ appData.enableJPEG = False; ++ appData.compressLevel = 1; ++ UpdateQual(); ++} ++ ++void ++SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (*num_params != 0) { ++ int n = atoi(params[0]); ++ if (0) fprintf(stderr, "SetTurboVNC: %d\n", n); ++ if (n == 1) { ++ QualHigh(); ++ } else if (n == 2) { ++ QualMed(); ++ } else if (n == 3) { ++ QualLow(); ++ } else if (n == 4) { ++ QualLossless(); ++ } else if (n == 5) { ++ QualLosslessWAN(); ++ } else if (n == 6) { ++ appData.subsampLevel = TVNC_1X; ++ UpdateQual(); ++ } else if (n == 7) { ++ appData.subsampLevel = TVNC_2X; ++ UpdateQual(); ++ } else if (n == 8) { ++ appData.subsampLevel = TVNC_4X; ++ UpdateQual(); ++ } else if (n == 9) { ++ appData.subsampLevel = TVNC_GRAY; ++ UpdateQual(); ++ } else if (n == 10) { ++ LosslessRefresh(); ++ } ++ } ++} ++ +void +SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ @@ -15716,8 +18517,37 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + XtVaSetValues(w, XtNstate, False, NULL); + } +} - -- Cleanup(); ++ ++void ++SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (!appData.pipelineUpdates) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ } ++} ++ ++void ++SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (!appData.sendClipboard) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ } ++} ++ ++void ++SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params) ++{ ++ if (!appData.sendAlways) { ++ XtVaSetValues(w, XtNstate, False, NULL); ++ } else { ++ XtVaSetValues(w, XtNstate, True, NULL); ++ } ++} ++ +void +SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ @@ -15727,8 +18557,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi + XtVaSetValues(w, XtNstate, False, NULL); + } +} - -- return 0; ++ +void +SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params) +{ @@ -15750,7 +18579,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.c vnc_unixsrc/vncvi } diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncviewer/vncviewer.h --- vnc_unixsrc.orig/vncviewer/vncviewer.h 2004-03-11 13:14:40.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer.h 2008-12-30 14:03:39.000000000 -0500 ++++ vnc_unixsrc/vncviewer/vncviewer.h 2009-05-31 16:26:35.000000000 -0400 @@ -28,6 +28,7 @@ #include <string.h> #include <sys/time.h> @@ -15768,9 +18597,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi #define FLASH_PORT_OFFSET 5400 #define LISTEN_PORT_OFFSET 5500 -@@ -65,59 +66,95 @@ +@@ -64,60 +65,123 @@ + #define DEFAULT_VIA_CMD \ (DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20") ++#define TVNC_SAMPOPT 4 ++enum {TVNC_1X=0, TVNC_4X, TVNC_2X, TVNC_GRAY}; -/* argsresources.c */ - @@ -15791,12 +18623,27 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi - int requestedDepth; - - Bool useShm; -- ++static const char *subsampLevel2str[TVNC_SAMPOPT] = { ++ "1X", "4X", "2X", "Gray" ++}; ++#ifdef TURBOVNC ++#define rfbTightNoZlib 0x0A ++#define rfbTurboVncVendor "TRBO" ++#define rfbJpegQualityLevel1 0xFFFFFE01 ++#define rfbJpegQualityLevel100 0xFFFFFE64 ++#define rfbJpegSubsamp1X 0xFFFFFD00 ++#define rfbJpegSubsamp4X 0xFFFFFD01 ++#define rfbJpegSubsamp2X 0xFFFFFD02 ++#define rfbJpegSubsampGray 0xFFFFFD03 ++#endif + - int wmDecorationWidth; - int wmDecorationHeight; -- ++/* for debugging width, height, etc */ ++//#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues + - char *userLogin; -- + - char *passwordFile; - Bool passwordDialog; - @@ -15804,11 +18651,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi - int copyRectDelay; - - Bool debug; -+/* for debugging width, height, etc */ -+//#define XtVaSetValues printf("%s:%d\n", __FILE__, __LINE__); XtVaSetValues - +- - int popupButtonCount; - +- - int bumpScrollTime; - int bumpScrollPixels; +/* argsresources.c */ @@ -15850,6 +18695,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi + + char *userLogin; + char *unixPW; ++ char *msLogon; + char *repeaterUltra; + Bool ultraDSM; + char *rfbVersion; @@ -15891,6 +18737,16 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi + char *scale; + char *escapeKeys; + Bool escapeActive; ++ Bool pipelineUpdates; ++ ++ Bool sendClipboard; ++ Bool sendAlways; ++ char *recvText; ++ ++ /* only for turbovnc mode */ ++ String subsampString; ++ int subsampLevel; ++ Bool doubleBuffer; } AppData; @@ -15905,7 +18761,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern int listenPort, flashPort; extern XrmOptionDescRec cmdLineOptions[]; -@@ -130,10 +167,11 @@ +@@ -130,10 +194,11 @@ /* colour.c */ extern unsigned long BGR233ToPixel[]; @@ -15918,7 +18774,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern void SetVisualAndCmap(); -@@ -157,13 +195,52 @@ +@@ -157,13 +222,52 @@ extern void DesktopInitBeforeRealization(); extern void DesktopInitAfterRealization(); @@ -15971,7 +18827,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern void ServerDialogDone(Widget w, XEvent *event, String *params, Cardinal *num_params); extern char *DoServerDialog(); -@@ -181,6 +258,13 @@ +@@ -171,6 +275,10 @@ + Cardinal *num_params); + extern char *DoPasswordDialog(); + ++extern void UserDialogDone(Widget w, XEvent *event, String *params, ++ Cardinal *num_params); ++extern char *DoUserDialog(); ++ + /* fullscreen.c */ + + extern void ToggleFullScreen(Widget w, XEvent *event, String *params, +@@ -181,6 +289,13 @@ extern void FullScreenOn(); extern void FullScreenOff(); @@ -15985,7 +18852,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* listen.c */ extern void listenForIncomingConnections(); -@@ -196,6 +280,8 @@ +@@ -196,6 +311,8 @@ Cardinal *num_params); extern void Quit(Widget w, XEvent *event, String *params, Cardinal *num_params); @@ -15994,7 +18861,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern void Cleanup(); /* popup.c */ -@@ -207,6 +293,20 @@ +@@ -207,6 +324,27 @@ Cardinal *num_params); extern void CreatePopup(); @@ -16002,6 +18869,13 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi + Cardinal *num_params); +extern void CreateScaleN(); + ++extern void HideTurboVNC(Widget w, XEvent *event, String *params, ++ Cardinal *num_params); ++extern void CreateTurboVNC(); ++extern void UpdateSubsampButtons(); ++extern void UpdateQualSlider(); ++extern void UpdateQual(); ++ +extern void HideQuality(Widget w, XEvent *event, String *params, + Cardinal *num_params); +extern void CreateQuality(); @@ -16015,7 +18889,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* rfbproto.c */ extern int rfbsock; -@@ -229,8 +329,19 @@ +@@ -229,8 +367,19 @@ extern Bool SendClientCutText(char *str, int len); extern Bool HandleRFBServerMessage(); @@ -16035,7 +18909,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* selection.c */ extern void InitialiseSelection(); -@@ -241,8 +352,9 @@ +@@ -241,8 +390,9 @@ /* shm.c */ @@ -16046,7 +18920,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi /* sockets.c */ -@@ -253,8 +365,11 @@ +@@ -253,8 +403,11 @@ extern int FindFreeTcpPort(void); extern int ListenAtTcpPort(int port); extern int ConnectToTcpAddr(unsigned int host, int port); @@ -16058,7 +18932,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi extern int StringToIPAddr(const char *str, unsigned int *addr); extern Bool SameMachine(int sock); -@@ -271,3 +386,72 @@ +@@ -271,3 +424,80 @@ extern XtAppContext appContext; extern Display* dpy; extern Widget toplevel; @@ -16083,6 +18957,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void ToggleBell(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleRawLocal(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleServerInput(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void TogglePipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void ToggleSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void ToggleSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleSingleWindow(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleXGrab(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleEscapeActive(Widget w, XEvent *ev, String *params, Cardinal *num_params); @@ -16094,9 +18971,11 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void SetYCrop(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScbar(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void ShowTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ShowCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetScaleN(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetTurboVNC(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetQuality(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetCompress(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void ToggleTextChat(Widget w, XEvent *ev, String *params, Cardinal *num_params); @@ -16125,6 +19004,9 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void SetBellState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetRawLocalState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetServerInputState(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetPipelineUpdates(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetSendClipboard(Widget w, XEvent *ev, String *params, Cardinal *num_params); ++extern void SetSendAlways(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetSingleWindowState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); +extern void SetTermTextChatState(Widget w, XEvent *ev, String *params, Cardinal *num_params); @@ -16133,19 +19015,19 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.h vnc_unixsrc/vncvi +extern void SetEscapeKeysState(Widget w, XEvent *ev, String *params, Cardinal *num_params); diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vncviewer/vncviewer.man --- vnc_unixsrc.orig/vncviewer/vncviewer.man 2004-03-11 13:14:40.000000000 -0500 -+++ vnc_unixsrc/vncviewer/vncviewer.man 2008-12-30 19:24:50.000000000 -0500 ++++ vnc_unixsrc/vncviewer/vncviewer.man 2009-05-31 18:53:07.000000000 -0400 @@ -5,38 +5,55 @@ .\" Copyright (C) 1998 Marcus.Brinkmann@ruhr-uni-bochum.de .\" Copyright (C) 2000,2001 Red Hat, Inc. .\" Copyright (C) 2001-2003 Constantin Kaplinsky <const@ce.cctpu.edu.ru> -+.\" Copyright (C) 2006-2008 Karl J. Runge <runge@karlrunge.com> ++.\" Copyright (C) 2006-2009 Karl J. Runge <runge@karlrunge.com> .\" .\" You may distribute under the terms of the GNU General Public .\" License as specified in the file LICENCE.TXT that comes with the .\" TightVNC distribution. .\" -.TH vncviewer 1 "January 2003" "" "TightVNC" -+.TH ssvncviewer 1 "December 2008" "" "SSVNC" ++.TH ssvncviewer 1 "June 2009" "" "SSVNC" .SH NAME -vncviewer \- an X viewer client for VNC +ssvncviewer \- an X viewer client for VNC @@ -16198,7 +19080,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc You can use F8 to display a pop\-up utility menu. Press F8 twice to pass single F8 to the remote side. .SH OPTIONS -@@ -168,6 +185,335 @@ +@@ -168,6 +185,376 @@ \fB\-autopass\fR Read a plain-text password from stdin. This option affects only the standard VNC authentication. @@ -16317,6 +19199,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc +Prefer raw encoding for localhost, default is +no, i.e. assumes you have a SSH tunnel instead. +.TP ++\fB\-sendclipboard\fR ++Send the X CLIPBOARD selection (i.e. Ctrl+C, ++Ctrl+V) instead of the X PRIMARY selection (mouse ++select and middle button paste.) ++.TP ++\fB\-sendalways\fR ++Whenever the mouse enters the VNC viewer main ++window, send the selection to the VNC server even if ++it has not changed. This is like the Xt resource ++translation SelectionToVNC(always) ++.TP ++\fB\-recvtext\fR ++str When cut text is received from the VNC server, ++ssvncviewer will set both the X PRIMARY and the ++X CLIPBOARD local selections. To control which ++is set, specify 'str' as 'primary', 'clipboard', ++or 'both' (the default.) ++.TP +\fB\-graball\fR +Grab the entire X server when in fullscreen mode, +needed by some old window managers like fvwm2. @@ -16413,6 +19313,18 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc +data sent so as to work with the UltraVNC Server. For some +reason, each RFB msg type must be sent twice under DSM. +.TP ++\fB\-mslogon\fR \fIuser\fR ++Use Windows MS Logon to an UltraVNC server. Supply the ++username or "1" to be prompted. The default is to ++autodetect the UltraVNC MS Logon server and prompt for ++the username and password. ++ ++IMPORTANT NOTE: The UltraVNC MS-Logon Diffie-Hellman ++exchange is very weak and can be brute forced to recover ++your username and password in a few hours or seconds of CPU ++time. To be safe, be sure to use an additional encrypted ++tunnel (e.g. SSL or SSH) for the entire VNC session. ++.TP +\fB\-chatonly\fR +Try to be a client that only does UltraVNC text chat. This +mode is used by x11vnc to present a chat window on the physical @@ -16429,6 +19341,12 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc +keybindings and Popup menu) Then point to the file via +XENVIRONMENT or XAPPLRESDIR. +.TP ++\fB\-pipeline\fR ++Like TurboVNC, request the next framebuffer update as soon ++as possible instead of waiting until the end of the current ++framebuffer update coming in. Helps 'pipeline' the updates. ++This is currently the default, use \fB-nopipeline\fR to disable. ++.TP +\fB\-escape \fR\fIstr\fR +This sets the 'Escape Keys' modifier sequence and enables +escape keys mode. When the modifier keys escape sequence @@ -16504,8 +19422,10 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc + Quality Level ~ -quality (both Tight and ZYWRLE) + Compress Level ~ -compresslevel + Disable JPEG: ~ -nojpeg (Tight) -+ Full Color ~ as many colors as local screen allows. -+ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes. ++ Pipeline Updates ~ -pipeline ++ ++ Full Color as many colors as local screen allows. ++ Grey scale (16 & 8-bpp) ~ -grey, for low colors 16/8bpp modes only. + 16 bit color (BGR565) ~ -16bpp / -bgr565 + 8 bit color (BGR233) ~ -bgr233 + 256 colors ~ -bgr233 default # of colors. @@ -16520,21 +19440,24 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc + + UltraVNC Extensions: + -+ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. -+ Text Chat Ultravnc ext. Do Text Chat. -+ File Transfer Ultravnc ext. File xfer via Java helper. -+ Single Window Ultravnc ext. Grab a single window. -+ (click on the window you want). -+ Disable Remote Input Ultravnc ext. Try to prevent input and -+ viewing of monitor at physical display. ++ Set 1/n Server Scale Ultravnc ext. Scale desktop by 1/n. ++ Text Chat Ultravnc ext. Do Text Chat. ++ File Transfer Ultravnc ext. File xfer via Java helper. ++ Single Window Ultravnc ext. Grab and view a single window. ++ (select then click on the window you want). ++ Disable Remote Input Ultravnc ext. Try to prevent input and ++ viewing of monitor at physical display. ++ ++ Note: the Ultravnc extensions only apply to servers that support ++ them. x11vnc/libvncserver supports some of them. + -+ Note: the Ultravnc extensions only apply to servers that -+ support them. x11vnc/libvncserver supports some of them. ++ Send Clipboard not Primary ~ -sendclipboard ++ Send Selection Every time ~ -sendalways + .SH ENCODINGS The server supplies information in whatever format is desired by the client, in order to make the client as easy as possible to implement. -@@ -238,6 +584,15 @@ +@@ -238,6 +625,15 @@ \-quality and \-nojpeg options above). Tight encoding is usually the best choice for low\-bandwidth network environments (e.g. slow modem connections). @@ -16550,7 +19473,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc .SH RESOURCES X resources that \fBvncviewer\fR knows about, aside from the normal Xt resources, are as follows: -@@ -364,8 +719,8 @@ +@@ -364,8 +760,8 @@ .B %R remote TCP port number. .SH SEE ALSO @@ -16561,7 +19484,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/vncviewer.man vnc_unixsrc/vnc .SH AUTHORS Original VNC was developed in AT&T Laboratories Cambridge. TightVNC additions was implemented by Constantin Kaplinsky. Many other people -@@ -380,3 +735,5 @@ +@@ -380,3 +776,5 @@ Tim Waugh <twaugh@redhat.com>, .br Constantin Kaplinsky <const@ce.cctpu.edu.ru> @@ -18833,7 +21756,7 @@ diff -Naur -X ./exclude vnc_unixsrc.orig/vncviewer/zywrletemplate.c vnc_unixsrc/ +#undef ZYWRLE_YUVRGB +#undef ZYWRLE_LOAD_PIXEL +#undef ZYWRLE_SAVE_PIXEL -diff -Naur vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h +diff -Naur -X ./exclude vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h --- vnc_unixsrc.orig/include/rfbproto.h 2004-05-27 03:02:02.000000000 -0400 +++ vnc_unixsrc/include/rfbproto.h 2008-12-07 09:35:32.000000000 -0500 @@ -205,7 +205,22 @@ @@ -19015,3 +21938,142 @@ diff -Naur vnc_unixsrc.orig/include/rfbproto.h vnc_unixsrc/include/rfbproto.h + rfbSetSWMsg sw; + rfbTextChatMsg tc; } rfbClientToServerMsg; +diff -Naur -X ./exclude vnc_unixsrc.orig/include/vncauth.h vnc_unixsrc/include/vncauth.h +--- vnc_unixsrc.orig/include/vncauth.h 2000-06-11 08:00:53.000000000 -0400 ++++ vnc_unixsrc/include/vncauth.h 2009-03-21 00:37:23.000000000 -0400 +@@ -23,8 +23,11 @@ + + #define MAXPWLEN 8 + #define CHALLENGESIZE 16 ++#define CHALLENGESIZE_MSLOGON 64 + + extern int vncEncryptAndStorePasswd(char *passwd, char *fname); + extern char *vncDecryptPasswdFromFile(char *fname); + extern void vncRandomBytes(unsigned char *bytes); + extern void vncEncryptBytes(unsigned char *bytes, char *passwd); ++ ++extern void vncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd); +diff -Naur -X ./exclude vnc_unixsrc.orig/libvncauth/vncauth.c vnc_unixsrc/libvncauth/vncauth.c +--- vnc_unixsrc.orig/libvncauth/vncauth.c 2003-03-01 11:48:06.000000000 -0500 ++++ vnc_unixsrc/libvncauth/vncauth.c 2009-04-12 22:28:08.000000000 -0400 +@@ -30,6 +30,7 @@ + #include <vncauth.h> + #include <d3des.h> + ++#include <fcntl.h> + + /* + * Make sure we call srandom() only once. +@@ -195,6 +196,44 @@ + return (i < 16) ? 1 : 2; + } + ++unsigned int urandom(void) { ++ unsigned int val = 0; ++ struct stat sb; ++ int fd = -1; ++ if (fd < 0 && stat("/dev/urandom", &sb) == 0) { ++ fd = open("/dev/urandom", O_RDONLY); ++ } ++ if (fd < 0 && stat("/dev/random", &sb) == 0) { ++ fd = open("/dev/random", O_RDONLY); ++ } ++ if (fd < 0 && stat("/proc/loadavg", &sb) == 0) { ++ fd = open("/proc/loadavg", O_RDONLY); ++ } ++ if (fd < 0 && stat("/bin/bash", &sb) == 0) { ++ fd = open("/bin/bash", O_RDONLY); ++ lseek(fd, (off_t) (unsigned int) getpid(), SEEK_SET); ++ } ++ if (fd >= 0) { ++ int i; ++ for (i=0; i < 3; i++) { ++ char buf[2]; ++ if (read(fd, buf, 1) > 0) { ++ unsigned char uc = (unsigned char) buf[0]; ++ if (i==0) { ++ val += uc; ++ } else if (i==1) { ++ val += uc * 256; ++ } else if (i==2) { ++ val += uc * 256 * 256; ++ } ++ } ++ } ++ close(fd); ++ } else { ++ val = (unsigned int) getpid(); ++ } ++ return val; ++} + + /* + * Generate CHALLENGESIZE random bytes for use in challenge-response +@@ -207,11 +246,13 @@ + int i; + unsigned int seed; + +- if (!s_srandom_called) { +- seed = (unsigned int)time(0) ^ (unsigned int)getpid(); +- srandom(seed); +- s_srandom_called = 1; +- } ++ if (!s_srandom_called) { ++ seed = (unsigned int)time(0) ^ (unsigned int)getpid(); ++ seed += urandom(); ++ ++ srandom(seed); ++ s_srandom_called = 1; ++ } + + for (i = 0; i < CHALLENGESIZE; i++) { + bytes[i] = (unsigned char)(random() & 255); +@@ -245,3 +286,48 @@ + des(bytes+i, bytes+i); + } + } ++ ++void UvncEncryptPasswd_MSLOGON(unsigned char *encryptedPasswd, char *passwd) { ++ unsigned int i; ++ for (i=0; i < 32; i++) { ++ if (i < strlen(passwd)) { ++ encryptedPasswd[i] = passwd[i]; ++ } else { ++ encryptedPasswd[i] = '\0'; ++ } ++ } ++ deskey(s_fixedkey, EN0); ++ des(encryptedPasswd, encryptedPasswd); ++} ++ ++void UvncEncryptBytes2(unsigned char *where, int length, unsigned char *key) { ++ int i, j; ++ deskey(key, EN0); ++ for (i=0; i < 8; i++) { ++ where[i] ^= key[i]; ++ } ++ des(where, where); ++ for (i=8; i < length; i += 8) { ++ for (j=0; j < 8; j++) { ++ where[i+j] ^= where[i+j-8]; ++ } ++ des(where+i, where+i); ++ } ++} ++ ++void UvncDecryptBytes2(unsigned char *where, int length, unsigned char *key) { ++ int i, j; ++ deskey(key, DE1); ++ for (i = length - 8; i > 0; i -= 8) { ++ des(where + i, where + i); ++ for (j=0; j < 8; j++) { ++ where[i+j] ^= where[i+j-8]; ++ } ++ } ++ /* i=0 */ ++ des(where, where); ++ for (i=0; i < 8; i++) { ++ where[i] ^= key[i]; ++ } ++} ++ |
