Major overhaul/rewrite of the krdc vnc client to use libvncclient

This relates to Bug 2180 among others
Please note that only minimal testing has been performed; some features may not yet work correctly
pull/1/head
Timothy Pearson pirms 9 gadiem
vecāks 8b8dfa9704
revīzija 3ddfecac5c

@ -16,6 +16,8 @@ add_subdirectory( rdp )
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../libtdevnc
${CMAKE_CURRENT_BINARY_DIR}/../libtdevnc
${CMAKE_BINARY_DIR}
${TDE_INCLUDE_DIR}
${TQT_INCLUDE_DIRS}

@ -2,6 +2,8 @@
kremoteview.h - widget that shows the remote framebuffer
-------------------
begin : Wed Dec 25 23:58:12 CET 2002
copyright : (C) 2015 by Timothy Pearson
copyright : (C) 2007 by Urs Wolfer
copyright : (C) 2002-2003 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/

@ -1,5 +1,8 @@
#################################################
#
# (C) 2015 Timothy Pearson
# kb9vqf (AT) pearsoncomputing (DOT) net
#
# (C) 2010-2011 Serghei Amelian
# serghei (DOT) amelian (AT) gmail.com
#
@ -13,6 +16,9 @@ include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
${CMAKE_CURRENT_SOURCE_DIR}/../../libtdevnc
${CMAKE_CURRENT_BINARY_DIR}/../../libtdevnc
${CMAKE_BINARY_DIR}
${TDE_INCLUDE_DIR}
${TQT_INCLUDE_DIRS}
)
@ -22,6 +28,8 @@ include_directories(
tde_add_library( vnc STATIC_PIC AUTOMOC
SOURCES
kvncview.cpp threads.cpp colour.c d3des.c desktop.c rfbproto.c sockets.c
vncauth.c vncprefs.ui vnchostpref.cpp
kvncview.cpp scaling.cpp threads.cpp
vncprefs.ui vnchostpref.cpp
LINK
tdevncclient-static
)

@ -1,415 +0,0 @@
/*
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* colour.c - functions to deal with colour - i.e. RFB pixel formats, X visuals
* and colormaps. Thanks to Grant McDorman for some of the ideas used here.
*/
#include "vncviewer.h"
#include <limits.h>
#define INVALID_PIXEL 0xffffffff
#define MAX_CMAP_SIZE 256
#define BGR233_SIZE 256
unsigned long BGR233ToPixel[BGR233_SIZE];
Colormap cmap;
Visual *vis;
unsigned int visdepth, visbpp;
Bool allocColorFailed = False;
static int nBGR233ColoursAllocated;
static int GetBPPForDepth(int depth);
static void SetupBGR233Map(void);
static void AllocateExactBGR233Colours(void);
static Bool AllocateBGR233Colour(int r, int g, int b);
/*
* SetVisualAndCmap() deals with the wonderful world of X "visuals" (which are
* equivalent to the RFB protocol's "pixel format"). Having decided on the
* best visual, it also creates a colormap if necessary, sets the appropriate
* resources on the toplevel widget, and sets up the myFormat structure to
* describe the pixel format in terms that the RFB server will be able to
* understand.
*
* The algorithm for deciding which visual to use is as follows:
*
* If forceOwnCmap is true then we try to use a PseudoColor visual - we first
* see if there's one of the same depth as the RFB server, followed by an 8-bit
* deep one.
*
* If forceTrueColour is true then we try to use a TrueColor visual - if
* requestedDepth is set then it must be of that depth, otherwise any depth
* will be used.
*
* Otherwise, we use the X server's default visual and colormap. If this is
* TrueColor then we just ask the RFB server for this format. If the default
* isn't TrueColor, or if useBGR233 is true, then we ask the RFB server for
* BGR233 pixel format and use a lookup table to translate to the nearest
* colours provided by the X server.
*/
void
SetVisualAndCmap()
{
/* just use default visual and colormap */
vis = DefaultVisual(dpy,DefaultScreen(dpy));
visdepth = DefaultDepth(dpy,DefaultScreen(dpy));
visbpp = GetBPPForDepth(visdepth);
cmap = DefaultColormap(dpy,DefaultScreen(dpy));
if (!appData.useBGR233 && (vis->class == TrueColor)) {
myFormat.bitsPerPixel = visbpp;
myFormat.depth = visdepth;
myFormat.trueColour = 1;
myFormat.bigEndian = (ImageByteOrder(dpy) == MSBFirst);
myFormat.redShift = ffs(vis->red_mask) - 1;
myFormat.greenShift = ffs(vis->green_mask) - 1;
myFormat.blueShift = ffs(vis->blue_mask) - 1;
myFormat.redMax = vis->red_mask >> myFormat.redShift;
myFormat.greenMax = vis->green_mask >> myFormat.greenShift;
myFormat.blueMax = vis->blue_mask >> myFormat.blueShift;
fprintf(stderr,
"Using default colormap which is TrueColor. Pixel format:\n");
PrintPixelFormat(&myFormat);
return;
}
appData.useBGR233 = True;
myFormat.bitsPerPixel = 8;
myFormat.depth = 8;
myFormat.trueColour = 1;
myFormat.bigEndian = 0;
myFormat.redMax = 7;
myFormat.greenMax = 7;
myFormat.blueMax = 3;
myFormat.redShift = 0;
myFormat.greenShift = 3;
myFormat.blueShift = 6;
fprintf(stderr,
"Using default colormap and translating from BGR233. Pixel format:\n");
PrintPixelFormat(&myFormat);
SetupBGR233Map();
}
/*
* GetBPPForDepth looks through the "pixmap formats" to find the bits-per-pixel
* for the given depth.
*/
static int
GetBPPForDepth(int depth)
{
XPixmapFormatValues *format;
int nformats;
int i;
int bpp;
format = XListPixmapFormats(dpy, &nformats);
for (i = 0; i < nformats; i++) {
if (format[i].depth == depth)
break;
}
if (i == nformats) {
fprintf(stderr,"no pixmap format for depth %d???\n", depth);
exit(1);
}
bpp = format[i].bits_per_pixel;
XFree(format);
if (bpp != 1 && bpp != 8 && bpp != 16 && bpp != 32) {
fprintf(stderr,"Can't cope with %d bits-per-pixel. Sorry.\n", bpp);
exit(1);
}
return bpp;
}
/*
* SetupBGR233Map() sets up the BGR233ToPixel array.
*
* It calls AllocateExactBGR233Colours to allocate some exact BGR233 colours
* (limited by space in the colormap and/or by the value of the nColours
* resource). If the number allocated is less than BGR233_SIZE then it fills
* the rest in using the "nearest" colours available. How this is done depends
* on the value of the useSharedColours resource. If it's false, we use only
* colours from the exact BGR233 colours we've just allocated. If it's true,
* then we also use other clients' "shared" colours available in the colormap.
*/
static void
SetupBGR233Map(void)
{
int r, g, b;
long i;
unsigned long nearestPixel = 0;
int cmapSize;
XColor cmapEntry[MAX_CMAP_SIZE];
Bool exactBGR233[MAX_CMAP_SIZE];
Bool shared[MAX_CMAP_SIZE];
Bool usedAsNearest[MAX_CMAP_SIZE];
int nSharedUsed = 0;
if (visdepth > 8) {
appData.nColours = 256; /* ignore nColours setting for > 8-bit deep */
}
for (i = 0; i < BGR233_SIZE; i++) {
BGR233ToPixel[i] = INVALID_PIXEL;
}
AllocateExactBGR233Colours();
fprintf(stderr,"Got %d exact BGR233 colours out of %d\n",
nBGR233ColoursAllocated, appData.nColours);
if (nBGR233ColoursAllocated < BGR233_SIZE) {
if (visdepth > 8) { /* shouldn't get here */
fprintf(stderr,"Error: couldn't allocate BGR233 colours even though "
"depth is %d\n", visdepth);
exit(1);
}
cmapSize = (1 << visdepth);
for (i = 0; i < cmapSize; i++) {
cmapEntry[i].pixel = i;
exactBGR233[i] = False;
shared[i] = False;
usedAsNearest[i] = False;
}
XQueryColors(dpy, cmap, cmapEntry, cmapSize);
/* mark all our exact BGR233 pixels */
for (i = 0; i < BGR233_SIZE; i++) {
if (BGR233ToPixel[i] != INVALID_PIXEL)
exactBGR233[BGR233ToPixel[i]] = True;
}
if (appData.useSharedColours) {
/* Try to find existing shared colours. This is harder than it sounds
because XQueryColors doesn't tell us whether colours are shared,
private or unallocated. What we do is go through the colormap and for
each pixel try to allocate exactly its RGB values. If this returns a
different pixel then it's definitely either a private or unallocated
pixel, so no use to us. If it returns us the same pixel again, then
it's likely that it's a shared colour - however, it is possible that
it was actually an unallocated pixel, which we've now allocated. We
minimise this possibility by going through the pixels in reverse order
- this helps becuse the X server allocates new pixels from the lowest
number up, so it should only be a problem for the lowest unallocated
pixel. Got that? */
for (i = cmapSize-1; i >= 0; i--) {
if (!exactBGR233[i] &&
XAllocColor(dpy, cmap, &cmapEntry[i])) {
if (cmapEntry[i].pixel == (unsigned long) i) {
shared[i] = True; /* probably shared */
} else {
/* "i" is either unallocated or private. We have now unnecessarily
allocated cmapEntry[i].pixel. Free it. */
XFreeColors(dpy, cmap, &cmapEntry[i].pixel, 1, 0);
}
}
}
}
/* Now fill in the nearest colours */
for (r = 0; r < 8; r++) {
for (g = 0; g < 8; g++) {
for (b = 0; b < 4; b++) {
if (BGR233ToPixel[(b<<6) | (g<<3) | r] == INVALID_PIXEL) {
unsigned long minDistance = ULONG_MAX;
for (i = 0; i < cmapSize; i++) {
if (exactBGR233[i] || shared[i]) {
unsigned long distance
= (abs(cmapEntry[i].red - r * 65535 / 7)
+ abs(cmapEntry[i].green - g * 65535 / 7)
+ abs(cmapEntry[i].blue - b * 65535 / 3));
if (distance < minDistance) {
minDistance = distance;
nearestPixel = i;
}
}
}
BGR233ToPixel[(b<<6) | (g<<3) | r] = nearestPixel;
if (shared[nearestPixel] && !usedAsNearest[nearestPixel])
nSharedUsed++;
usedAsNearest[nearestPixel] = True;
}
}
}
}
/* Tidy up shared colours which we allocated but aren't going to use */
for (i = 0; i < cmapSize; i++) {
if (shared[i] && !usedAsNearest[i]) {
XFreeColors(dpy, cmap, (unsigned long *)&i, 1, 0);
}
}
fprintf(stderr,"Using %d existing shared colours\n", nSharedUsed);
}
}
/*
* AllocateExactBGR233Colours() attempts to allocate each of the colours in the
* BGR233 colour cube, stopping when an allocation fails. The order it does
* this in is such that we should get a fairly well spread subset of the cube,
* however many allocations are made. There's probably a neater algorithm for
* doing this, but it's not obvious to me anyway. The way this algorithm works
* is:
*
* At each stage, we introduce a new value for one of the primaries, and
* allocate all the colours with the new value of that primary and all previous
* values of the other two primaries. We start with r=0 as the "new" value
* for r, and g=0, b=0 as the "previous" values of g and b. So we get:
*
* New primary value Previous values of other primaries Colours allocated
* ----------------- ---------------------------------- -----------------
* r=0 g=0 b=0 r0 g0 b0
* g=7 r=0 b=0 r0 g7 b0
* b=3 r=0 g=0,7 r0 g0 b3
* r0 g7 b3
* r=7 g=0,7 b=0,3 r7 g0 b0
* r7 g0 b3
* r7 g7 b0
* r7 g7 b3
* g=3 r=0,7 b=0,3 r0 g3 b0
* r0 g3 b3
* r7 g3 b0
* r7 g3 b3
* ....etc.
* */
static void
AllocateExactBGR233Colours(void)
{
int rv[] = {0,7,3,5,1,6,2,4};
int gv[] = {0,7,3,5,1,6,2,4};
int bv[] = {0,3,1,2};
int rn = 0;
int gn = 1;
int bn = 1;
int ri, gi, bi;
nBGR233ColoursAllocated = 0;
while (1) {
if (rn == 8)
break;
ri = rn;
for (gi = 0; gi < gn; gi++) {
for (bi = 0; bi < bn; bi++) {
if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
return;
}
}
rn++;
if (gn == 8)
break;
gi = gn;
for (ri = 0; ri < rn; ri++) {
for (bi = 0; bi < bn; bi++) {
if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
return;
}
}
gn++;
if (bn < 4) {
bi = bn;
for (ri = 0; ri < rn; ri++) {
for (gi = 0; gi < gn; gi++) {
if (!AllocateBGR233Colour(rv[ri], gv[gi], bv[bi]))
return;
}
}
bn++;
}
}
}
/*
* AllocateBGR233Colour() attempts to allocate the given BGR233 colour as a
* shared colormap entry, storing its pixel value in the BGR233ToPixel array.
* r is from 0 to 7, g from 0 to 7 and b from 0 to 3. It fails either when the
* allocation fails or when we would exceed the number of colours specified in
* the nColours resource.
*/
static Bool
AllocateBGR233Colour(int r, int g, int b)
{
XColor c;
if (nBGR233ColoursAllocated >= appData.nColours)
return False;
c.red = r * 65535 / 7;
c.green = g * 65535 / 7;
c.blue = b * 65535 / 3;
if (!XAllocColor(dpy, cmap, &c))
return False;
BGR233ToPixel[(b<<6) | (g<<3) | r] = c.pixel;
nBGR233ColoursAllocated++;
return True;
}

@ -1,440 +0,0 @@
/*
* This is D3DES (V5.09) by Richard Outerbridge with the double and
* triple-length support removed for use in VNC. Also the bytebit[] array
* has been reversed so that the most significant bit in each byte of the
* key is ignored, not the least significant.
*
* These changes are:
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* D3DES (V5.09) -
*
* A portable, public domain, version of the Data Encryption Standard.
*
* Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
* Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
* code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
* Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
* for humouring me on.
*
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
* (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
*/
#include "d3des.h"
static void scrunch(unsigned char *, unsigned long *);
static void unscrun(unsigned long *, unsigned char *);
static void desfunc(unsigned long *, unsigned long *);
static void cookey(unsigned long *);
static unsigned long KnL[32] = { 0L };
static unsigned long KnR[32] = { 0L };
static unsigned long Kn3[32] = { 0L };
static unsigned char Df_Key[24] = {
0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 };
static unsigned short bytebit[8] = {
01, 02, 04, 010, 020, 040, 0100, 0200 };
static unsigned long bigbyte[24] = {
0x800000L, 0x400000L, 0x200000L, 0x100000L,
0x80000L, 0x40000L, 0x20000L, 0x10000L,
0x8000L, 0x4000L, 0x2000L, 0x1000L,
0x800L, 0x400L, 0x200L, 0x100L,
0x80L, 0x40L, 0x20L, 0x10L,
0x8L, 0x4L, 0x2L, 0x1L };
/* Use the key schedule specified in the Standard (ANSI X3.92-1981). */
static unsigned char pc1[56] = {
56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 };
static unsigned char totrot[16] = {
1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 };
static unsigned char pc2[48] = {
13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 };
void deskey(key, edf) /* Thanks to James Gillogly & Phil Karn! */
unsigned char *key;
int edf;
{
register int i, j, l, m, n;
unsigned char pc1m[56], pcr[56];
unsigned long kn[32];
for ( j = 0; j < 56; j++ ) {
l = pc1[j];
m = l & 07;
pc1m[j] = (key[l >> 3] & bytebit[m]) ? 1 : 0;
}
for( i = 0; i < 16; i++ ) {
if( edf == DE1 ) m = (15 - i) << 1;
else m = i << 1;
n = m + 1;
kn[m] = kn[n] = 0L;
for( j = 0; j < 28; j++ ) {
l = j + totrot[i];
if( l < 28 ) pcr[j] = pc1m[l];
else pcr[j] = pc1m[l - 28];
}
for( j = 28; j < 56; j++ ) {
l = j + totrot[i];
if( l < 56 ) pcr[j] = pc1m[l];
else pcr[j] = pc1m[l - 28];
}
for( j = 0; j < 24; j++ ) {
if( pcr[pc2[j]] ) kn[m] |= bigbyte[j];
if( pcr[pc2[j+24]] ) kn[n] |= bigbyte[j];
}
}
cookey(kn);
return;
}
static void cookey(raw1)
register unsigned long *raw1;
{
register unsigned long *cook, *raw0;
unsigned long dough[32];
register int i;
cook = dough;
for( i = 0; i < 16; i++, raw1++ ) {
raw0 = raw1++;
*cook = (*raw0 & 0x00fc0000L) << 6;
*cook |= (*raw0 & 0x00000fc0L) << 10;
*cook |= (*raw1 & 0x00fc0000L) >> 10;
*cook++ |= (*raw1 & 0x00000fc0L) >> 6;
*cook = (*raw0 & 0x0003f000L) << 12;
*cook |= (*raw0 & 0x0000003fL) << 16;
*cook |= (*raw1 & 0x0003f000L) >> 4;
*cook++ |= (*raw1 & 0x0000003fL);
}
usekey(dough);
return;
}
void cpkey(into)
register unsigned long *into;
{
register unsigned long *from, *endp;
from = KnL, endp = &KnL[32];
while( from < endp ) *into++ = *from++;
return;
}
void usekey(from)
register unsigned long *from;
{
register unsigned long *to, *endp;
to = KnL, endp = &KnL[32];
while( to < endp ) *to++ = *from++;
return;
}
void des(inblock, outblock)
unsigned char *inblock, *outblock;
{
unsigned long work[2];
scrunch(inblock, work);
desfunc(work, KnL);
unscrun(work, outblock);
return;
}
static void scrunch(outof, into)
register unsigned char *outof;
register unsigned long *into;
{
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into++ |= (*outof++ & 0xffL);
*into = (*outof++ & 0xffL) << 24;
*into |= (*outof++ & 0xffL) << 16;
*into |= (*outof++ & 0xffL) << 8;
*into |= (*outof & 0xffL);
return;
}
static void unscrun(outof, into)
register unsigned long *outof;
register unsigned char *into;
{
*into++ = (*outof >> 24) & 0xffL;
*into++ = (*outof >> 16) & 0xffL;
*into++ = (*outof >> 8) & 0xffL;
*into++ = *outof++ & 0xffL;
*into++ = (*outof >> 24) & 0xffL;
*into++ = (*outof >> 16) & 0xffL;
*into++ = (*outof >> 8) & 0xffL;
*into = *outof & 0xffL;
return;
}
static unsigned long SP1[64] = {
0x01010400L, 0x00000000L, 0x00010000L, 0x01010404L,
0x01010004L, 0x00010404L, 0x00000004L, 0x00010000L,
0x00000400L, 0x01010400L, 0x01010404L, 0x00000400L,
0x01000404L, 0x01010004L, 0x01000000L, 0x00000004L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00010400L,
0x00010400L, 0x01010000L, 0x01010000L, 0x01000404L,
0x00010004L, 0x01000004L, 0x01000004L, 0x00010004L,
0x00000000L, 0x00000404L, 0x00010404L, 0x01000000L,
0x00010000L, 0x01010404L, 0x00000004L, 0x01010000L,
0x01010400L, 0x01000000L, 0x01000000L, 0x00000400L,
0x01010004L, 0x00010000L, 0x00010400L, 0x01000004L,
0x00000400L, 0x00000004L, 0x01000404L, 0x00010404L,
0x01010404L, 0x00010004L, 0x01010000L, 0x01000404L,
0x01000004L, 0x00000404L, 0x00010404L, 0x01010400L,
0x00000404L, 0x01000400L, 0x01000400L, 0x00000000L,
0x00010004L, 0x00010400L, 0x00000000L, 0x01010004L };
static unsigned long SP2[64] = {
0x80108020L, 0x80008000L, 0x00008000L, 0x00108020L,
0x00100000L, 0x00000020L, 0x80100020L, 0x80008020L,
0x80000020L, 0x80108020L, 0x80108000L, 0x80000000L,
0x80008000L, 0x00100000L, 0x00000020L, 0x80100020L,
0x00108000L, 0x00100020L, 0x80008020L, 0x00000000L,
0x80000000L, 0x00008000L, 0x00108020L, 0x80100000L,
0x00100020L, 0x80000020L, 0x00000000L, 0x00108000L,
0x00008020L, 0x80108000L, 0x80100000L, 0x00008020L,
0x00000000L, 0x00108020L, 0x80100020L, 0x00100000L,
0x80008020L, 0x80100000L, 0x80108000L, 0x00008000L,
0x80100000L, 0x80008000L, 0x00000020L, 0x80108020L,
0x00108020L, 0x00000020L, 0x00008000L, 0x80000000L,
0x00008020L, 0x80108000L, 0x00100000L, 0x80000020L,
0x00100020L, 0x80008020L, 0x80000020L, 0x00100020L,
0x00108000L, 0x00000000L, 0x80008000L, 0x00008020L,
0x80000000L, 0x80100020L, 0x80108020L, 0x00108000L };
static unsigned long SP3[64] = {
0x00000208L, 0x08020200L, 0x00000000L, 0x08020008L,
0x08000200L, 0x00000000L, 0x00020208L, 0x08000200L,
0x00020008L, 0x08000008L, 0x08000008L, 0x00020000L,
0x08020208L, 0x00020008L, 0x08020000L, 0x00000208L,
0x08000000L, 0x00000008L, 0x08020200L, 0x00000200L,
0x00020200L, 0x08020000L, 0x08020008L, 0x00020208L,
0x08000208L, 0x00020200L, 0x00020000L, 0x08000208L,
0x00000008L, 0x08020208L, 0x00000200L, 0x08000000L,
0x08020200L, 0x08000000L, 0x00020008L, 0x00000208L,
0x00020000L, 0x08020200L, 0x08000200L, 0x00000000L,
0x00000200L, 0x00020008L, 0x08020208L, 0x08000200L,
0x08000008L, 0x00000200L, 0x00000000L, 0x08020008L,
0x08000208L, 0x00020000L, 0x08000000L, 0x08020208L,
0x00000008L, 0x00020208L, 0x00020200L, 0x08000008L,
0x08020000L, 0x08000208L, 0x00000208L, 0x08020000L,
0x00020208L, 0x00000008L, 0x08020008L, 0x00020200L };
static unsigned long SP4[64] = {
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802080L, 0x00800081L, 0x00800001L, 0x00002001L,
0x00000000L, 0x00802000L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00800080L, 0x00800001L,
0x00000001L, 0x00002000L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002001L, 0x00002080L,
0x00800081L, 0x00000001L, 0x00002080L, 0x00800080L,
0x00002000L, 0x00802080L, 0x00802081L, 0x00000081L,
0x00800080L, 0x00800001L, 0x00802000L, 0x00802081L,
0x00000081L, 0x00000000L, 0x00000000L, 0x00802000L,
0x00002080L, 0x00800080L, 0x00800081L, 0x00000001L,
0x00802001L, 0x00002081L, 0x00002081L, 0x00000080L,
0x00802081L, 0x00000081L, 0x00000001L, 0x00002000L,
0x00800001L, 0x00002001L, 0x00802080L, 0x00800081L,
0x00002001L, 0x00002080L, 0x00800000L, 0x00802001L,
0x00000080L, 0x00800000L, 0x00002000L, 0x00802080L };
static unsigned long SP5[64] = {
0x00000100L, 0x02080100L, 0x02080000L, 0x42000100L,
0x00080000L, 0x00000100L, 0x40000000L, 0x02080000L,
0x40080100L, 0x00080000L, 0x02000100L, 0x40080100L,
0x42000100L, 0x42080000L, 0x00080100L, 0x40000000L,
0x02000000L, 0x40080000L, 0x40080000L, 0x00000000L,
0x40000100L, 0x42080100L, 0x42080100L, 0x02000100L,
0x42080000L, 0x40000100L, 0x00000000L, 0x42000000L,
0x02080100L, 0x02000000L, 0x42000000L, 0x00080100L,
0x00080000L, 0x42000100L, 0x00000100L, 0x02000000L,
0x40000000L, 0x02080000L, 0x42000100L, 0x40080100L,
0x02000100L, 0x40000000L, 0x42080000L, 0x02080100L,
0x40080100L, 0x00000100L, 0x02000000L, 0x42080000L,
0x42080100L, 0x00080100L, 0x42000000L, 0x42080100L,
0x02080000L, 0x00000000L, 0x40080000L, 0x42000000L,
0x00080100L, 0x02000100L, 0x40000100L, 0x00080000L,
0x00000000L, 0x40080000L, 0x02080100L, 0x40000100L };
static unsigned long SP6[64] = {
0x20000010L, 0x20400000L, 0x00004000L, 0x20404010L,
0x20400000L, 0x00000010L, 0x20404010L, 0x00400000L,
0x20004000L, 0x00404010L, 0x00400000L, 0x20000010L,
0x00400010L, 0x20004000L, 0x20000000L, 0x00004010L,
0x00000000L, 0x00400010L, 0x20004010L, 0x00004000L,
0x00404000L, 0x20004010L, 0x00000010L, 0x20400010L,
0x20400010L, 0x00000000L, 0x00404010L, 0x20404000L,
0x00004010L, 0x00404000L, 0x20404000L, 0x20000000L,
0x20004000L, 0x00000010L, 0x20400010L, 0x00404000L,
0x20404010L, 0x00400000L, 0x00004010L, 0x20000010L,
0x00400000L, 0x20004000L, 0x20000000L, 0x00004010L,
0x20000010L, 0x20404010L, 0x00404000L, 0x20400000L,
0x00404010L, 0x20404000L, 0x00000000L, 0x20400010L,
0x00000010L, 0x00004000L, 0x20400000L, 0x00404010L,
0x00004000L, 0x00400010L, 0x20004010L, 0x00000000L,
0x20404000L, 0x20000000L, 0x00400010L, 0x20004010L };
static unsigned long SP7[64] = {
0x00200000L, 0x04200002L, 0x04000802L, 0x00000000L,
0x00000800L, 0x04000802L, 0x00200802L, 0x04200800L,
0x04200802L, 0x00200000L, 0x00000000L, 0x04000002L,
0x00000002L, 0x04000000L, 0x04200002L, 0x00000802L,
0x04000800L, 0x00200802L, 0x00200002L, 0x04000800L,
0x04000002L, 0x04200000L, 0x04200800L, 0x00200002L,
0x04200000L, 0x00000800L, 0x00000802L, 0x04200802L,
0x00200800L, 0x00000002L, 0x04000000L, 0x00200800L,
0x04000000L, 0x00200800L, 0x00200000L, 0x04000802L,
0x04000802L, 0x04200002L, 0x04200002L, 0x00000002L,
0x00200002L, 0x04000000L, 0x04000800L, 0x00200000L,
0x04200800L, 0x00000802L, 0x00200802L, 0x04200800L,
0x00000802L, 0x04000002L, 0x04200802L, 0x04200000L,
0x00200800L, 0x00000000L, 0x00000002L, 0x04200802L,
0x00000000L, 0x00200802L, 0x04200000L, 0x00000800L,
0x04000002L, 0x04000800L, 0x00000800L, 0x00200002L };
static unsigned long SP8[64] = {
0x10001040L, 0x00001000L, 0x00040000L, 0x10041040L,
0x10000000L, 0x10001040L, 0x00000040L, 0x10000000L,
0x00040040L, 0x10040000L, 0x10041040L, 0x00041000L,
0x10041000L, 0x00041040L, 0x00001000L, 0x00000040L,
0x10040000L, 0x10000040L, 0x10001000L, 0x00001040L,
0x00041000L, 0x00040040L, 0x10040040L, 0x10041000L,
0x00001040L, 0x00000000L, 0x00000000L, 0x10040040L,
0x10000040L, 0x10001000L, 0x00041040L, 0x00040000L,
0x00041040L, 0x00040000L, 0x10041000L, 0x00001000L,
0x00000040L, 0x10040040L, 0x00001000L, 0x00041040L,
0x10001000L, 0x00000040L, 0x10000040L, 0x10040000L,
0x10040040L, 0x10000000L, 0x00040000L, 0x10001040L,
0x00000000L, 0x10041040L, 0x00040040L, 0x10000040L,
0x10040000L, 0x10001000L, 0x10001040L, 0x00000000L,
0x10041040L, 0x00041000L, 0x00041000L, 0x00001040L,
0x00001040L, 0x00040040L, 0x10000000L, 0x10041000L };
static void desfunc(block, keys)
register unsigned long *block, *keys;
{
register unsigned long fval, work, right, leftt;
register int round;
leftt = block[0];
right = block[1];
work = ((leftt >> 4) ^ right) & 0x0f0f0f0fL;
right ^= work;
leftt ^= (work << 4);
work = ((leftt >> 16) ^ right) & 0x0000ffffL;
right ^= work;
leftt ^= (work << 16);
work = ((right >> 2) ^ leftt) & 0x33333333L;
leftt ^= work;
right ^= (work << 2);
work = ((right >> 8) ^ leftt) & 0x00ff00ffL;
leftt ^= work;
right ^= (work << 8);
right = ((right << 1) | ((right >> 31) & 1L)) & 0xffffffffL;
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = ((leftt << 1) | ((leftt >> 31) & 1L)) & 0xffffffffL;
for( round = 0; round < 8; round++ ) {
work = (right << 28) | (right >> 4);
work ^= *keys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work >> 8) & 0x3fL];
fval |= SP3[(work >> 16) & 0x3fL];
fval |= SP1[(work >> 24) & 0x3fL];
work = right ^ *keys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work >> 8) & 0x3fL];
fval |= SP4[(work >> 16) & 0x3fL];
fval |= SP2[(work >> 24) & 0x3fL];
leftt ^= fval;
work = (leftt << 28) | (leftt >> 4);
work ^= *keys++;
fval = SP7[ work & 0x3fL];
fval |= SP5[(work >> 8) & 0x3fL];
fval |= SP3[(work >> 16) & 0x3fL];
fval |= SP1[(work >> 24) & 0x3fL];
work = leftt ^ *keys++;
fval |= SP8[ work & 0x3fL];
fval |= SP6[(work >> 8) & 0x3fL];
fval |= SP4[(work >> 16) & 0x3fL];
fval |= SP2[(work >> 24) & 0x3fL];
right ^= fval;
}
right = (right << 31) | (right >> 1);
work = (leftt ^ right) & 0xaaaaaaaaL;
leftt ^= work;
right ^= work;
leftt = (leftt << 31) | (leftt >> 1);
work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
right ^= work;
leftt ^= (work << 8);
work = ((leftt >> 2) ^ right) & 0x33333333L;
right ^= work;
leftt ^= (work << 2);
work = ((right >> 16) ^ leftt) & 0x0000ffffL;
leftt ^= work;
right ^= (work << 16);
work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
leftt ^= work;
right ^= (work << 4);
*block++ = right;
*block = leftt;
return;
}
/* Validation sets:
*
* Single-length key, single-length plaintext -
* Key : 0123 4567 89ab cdef
* Plain : 0123 4567 89ab cde7
* Cipher : c957 4425 6a5e d31d
*
* Double-length key, single-length plaintext -
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
* Plain : 0123 4567 89ab cde7
* Cipher : 7f1d 0a77 826b 8aff
*
* Double-length key, double-length plaintext -
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
* Cipher : 27a0 8440 406a df60 278f 47cf 42d6 15d7
*
* Triple-length key, single-length plaintext -
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
* Plain : 0123 4567 89ab cde7
* Cipher : de0b 7c06 ae5e 0ed5
*
* Triple-length key, double-length plaintext -
* Key : 0123 4567 89ab cdef fedc ba98 7654 3210 89ab cdef 0123 4567
* Plain : 0123 4567 89ab cdef 0123 4567 89ab cdff
* Cipher : ad0d 1b30 ac17 cf07 0ed1 1c63 81e4 4de5
*
* d3des V5.0a rwo 9208.07 18:44 Graven Imagery
**********************************************************************/

@ -1,51 +0,0 @@
/*
* This is D3DES (V5.09) by Richard Outerbridge with the double and
* triple-length support removed for use in VNC.
*
* These changes are:
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
/* d3des.h -
*
* Headers and defines for d3des.c
* Graven Imagery, 1992.
*
* Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge
* (GEnie : OUTER; CIS : [71755,204])
*/
#define EN0 0 /* MODE == encrypt */
#define DE1 1 /* MODE == decrypt */
extern void deskey(unsigned char *, int);
/* hexkey[8] MODE
* Sets the internal key register according to the hexadecimal
* key contained in the 8 bytes of hexkey, according to the DES,
* for encryption or decryption according to MODE.
*/
extern void usekey(unsigned long *);
/* cookedkey[32]
* Loads the internal key register with the data in cookedkey.
*/
extern void cpkey(unsigned long *);
/* cookedkey[32]
* Copies the contents of the internal key register into the storage
* located at &cookedkey[0].
*/
extern void des(unsigned char *, unsigned char *);
/* from[8] to[8]
* Encrypts/Decrypts (according to the key currently loaded in the
* internal key register) one block of eight bytes at address 'from'
* into the block at address 'to'. They can be the same.
*/
/* d3des.h V5.09 rwo 9208.04 15:06 Graven Imagery
********************************************************************/

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

@ -1,129 +0,0 @@
/*
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* hextile.c - handle hextile encoding.
*
* This file shouldn't be compiled directly. It is included multiple times by
* rfbproto.c, each time with a different definition of the macro BPP. For
* each value of BPP, this file defines a function which handles a hextile
* encoded rectangle with BPP bits per pixel.
*/
#define HandleHextileBPP CONCAT2E(HandleHextile,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
#define GET_PIXEL CONCAT2E(GET_PIXEL,BPP)
#define FillRectangleBPP CONCAT2E(FillRectangle,BPP)
static Bool
HandleHextileBPP (int rx, int ry, int rw, int rh)
{
CARDBPP bg, fg;
int i;
CARD8 *ptr;
int x, y, w, h;
int sx, sy, sw, sh;
CARD8 subencoding;
CARD8 nSubrects;
for (y = ry; y < ry+rh; y += 16) {
for (x = rx; x < rx+rw; x += 16) {
w = h = 16;
if (rx+rw - x < 16)
w = rx+rw - x;
if (ry+rh - y < 16)
h = ry+rh - y;
if (!ReadFromRFBServer((char *)&subencoding, 1))
return False;
if (subencoding & rfbHextileRaw) {
if (!ReadFromRFBServer(buffer, w * h * (BPP / 8)))
return False;
CopyDataToScreen(buffer, x, y, w, h);
continue;
}
if (subencoding & rfbHextileBackgroundSpecified)
if (!ReadFromRFBServer((char *)&bg, sizeof(bg)))
return False;
LockFramebuffer();
FillRectangleBPP(bg, x, y, w, h);
if (subencoding & rfbHextileForegroundSpecified)
if (!ReadFromRFBServer((char *)&fg, sizeof(fg))) {
UnlockFramebuffer();
return False;
}
if (!(subencoding & rfbHextileAnySubrects)) {
UnlockFramebuffer();
SyncScreenRegion(x, y, w, h);
continue;
}
if (!ReadFromRFBServer((char *)&nSubrects, 1)) {
UnlockFramebuffer();
return False;
}
ptr = (CARD8 *)buffer;
if (subencoding & rfbHextileSubrectsColoured) {
if (!ReadFromRFBServer(buffer, nSubrects * (2 + (BPP / 8)))) {
UnlockFramebuffer();
return False;
}
for (i = 0; i < nSubrects; i++) {
GET_PIXEL(fg, ptr);
sx = rfbHextileExtractX(*ptr);
sy = rfbHextileExtractY(*ptr);
ptr++;
sw = rfbHextileExtractW(*ptr);
sh = rfbHextileExtractH(*ptr);
ptr++;
FillRectangleBPP(fg, x+sx, y+sy, sw, sh);
}
} else {
if (!ReadFromRFBServer(buffer, nSubrects * 2)) {
UnlockFramebuffer();
return False;
}
for (i = 0; i < nSubrects; i++) {
sx = rfbHextileExtractX(*ptr);
sy = rfbHextileExtractY(*ptr);
ptr++;
sw = rfbHextileExtractW(*ptr);
sh = rfbHextileExtractH(*ptr);
ptr++;
FillRectangleBPP(fg, x+sx, y+sy, sw, sh);
}
}
UnlockFramebuffer();
SyncScreenRegion(x, y, w, h);
}
}
return True;
}

@ -2,7 +2,8 @@
kvncview.cpp - main widget
-------------------
begin : Thu Dec 20 15:11:42 CET 2001
copyright : (C) 2001-2003 by Tim Jansen
copyright : (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
(C) 2001-2003 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
@ -34,6 +35,8 @@
#include <tqbitmap.h>
#include <tqmutex.h>
#include <tqvbox.h>
#include <tqtimer.h>
#include <tqpainter.h>
#include <tqwaitcondition.h>
#include "vncviewer.h"
@ -47,7 +50,6 @@ bool launch_Fullscreen_vnc = false;
* application resource specs. The AppData structure is defined in the header
* file.
*/
AppData appData;
bool appDataConfigured = false;
Display* dpy;
@ -73,8 +75,7 @@ KVncView::KVncView(TQWidget *parent,
DotCursorState dotCursorState,
const TQString &encodings) :
KRemoteView(parent, name, TQt::WResizeNoErase | TQt::WRepaintNoErase | TQt::WStaticContents),
m_cthread(this, m_wthread, m_quitFlag),
m_wthread(this, m_quitFlag),
m_cthreadObject(this, m_quitFlag),
m_quitFlag(false),
m_enableFramebufferLocking(false),
m_scaling(false),
@ -147,8 +148,6 @@ int KVncView::port() {
void KVncView::startQuitting() {
m_quitFlag = true;
m_wthread.kick();
m_cthread.kick();
}
bool KVncView::isQuitting() {
@ -157,44 +156,37 @@ bool KVncView::isQuitting() {
void KVncView::configureApp(Quality q, const TQString specialEncodings) {
appDataConfigured = true;
appData.shareDesktop = 1;
appData.viewOnly = 0;
m_cthreadObject.cl->appData.shareDesktop = 1;
m_cthreadObject.cl->appData.viewOnly = 0;
if (q == QUALITY_LOW) {
appData.useBGR233 = 1;
appData.encodingsString = "background copyrect softcursor tight zlib hextile raw";
appData.compressLevel = -1;
appData.qualityLevel = 1;
appData.dotCursor = 1;
m_cthreadObject.cl->appData.useBGR233 = 1;
m_cthreadObject.cl->appData.encodingsString = "tight zrle ultra copyrect hextile zlib corre rre raw";
m_cthreadObject.cl->appData.compressLevel = 9;
m_cthreadObject.cl->appData.qualityLevel = 1;
m_cthreadObject.cl->appData.useRemoteCursor = 1;
}
else if (q == QUALITY_MEDIUM) {
appData.useBGR233 = 0;
appData.encodingsString = "background copyrect softcursor tight zlib hextile raw";
appData.compressLevel = -1;
appData.qualityLevel = 7;
appData.dotCursor = 1;
m_cthreadObject.cl->appData.useBGR233 = 0;
m_cthreadObject.cl->appData.encodingsString = "tight zrle ultra copyrect hextile zlib corre rre raw";
m_cthreadObject.cl->appData.compressLevel = 5;
m_cthreadObject.cl->appData.qualityLevel = 7;
m_cthreadObject.cl->appData.useRemoteCursor = 1;
}
else if ((q == QUALITY_HIGH) || (q == QUALITY_UNKNOWN)) {
appData.useBGR233 = 0;
appData.encodingsString = "copyrect softcursor hextile raw";
appData.compressLevel = -1;
appData.qualityLevel = 9;
appData.dotCursor = 1;
m_cthreadObject.cl->appData.useBGR233 = 0;
m_cthreadObject.cl->appData.encodingsString = "copyrect hextile raw";
m_cthreadObject.cl->appData.compressLevel = 0;
m_cthreadObject.cl->appData.qualityLevel = 9;
m_cthreadObject.cl->appData.useRemoteCursor = 1;
}
if (!specialEncodings.isNull())
appData.encodingsString = specialEncodings.latin1();
appData.nColours = 256;
appData.useSharedColours = 1;
appData.requestedDepth = 0;
appData.rawDelay = 0;
appData.copyRectDelay = 0;
if (!specialEncodings.isNull()) {
m_cthreadObject.cl->appData.encodingsString = specialEncodings.latin1();
}
if (!appData.dotCursor)
m_cursorState = DOT_CURSOR_OFF;
showDotCursorInternal();
m_cthreadObject.cl->appData.nColours = 256;
m_cthreadObject.cl->appData.requestedDepth = 0;
}
bool KVncView::checkLocalKRfb() {
@ -297,7 +289,10 @@ bool KVncView::start() {
setStatus(REMOTE_VIEW_CONNECTING);
m_cthreadObject.moveToThread(&m_cthread);
TQTimer::singleShot(0, &m_cthreadObject, SLOT(run()));
m_cthread.start();
setBackgroundMode(TQt::NoBackground);
return true;
}
@ -306,8 +301,6 @@ KVncView::~KVncView()
{
startQuitting();
m_cthread.wait();
m_wthread.wait();
freeResources();
}
bool KVncView::supportsLocalCursor() const {
@ -354,9 +347,16 @@ void KVncView::enableScaling(bool s) {
setMaximumSize(m_framebufferSize);
setMinimumSize(m_framebufferSize.width()/16,
m_framebufferSize.height()/16);
m_cthreadObject.setScaling(width(), height());
}
else
else {
setFixedSize(m_framebufferSize);
m_cthreadObject.setScaling(-1, -1);
}
// Force full redraw
drawRegion(0, 0, width(), height());
}
}
@ -367,12 +367,18 @@ void KVncView::paintEvent(TQPaintEvent *e) {
e->rect().height());
}
void KVncView::resizeEvent(TQResizeEvent *e) {
if (m_scaling) {
m_cthreadObject.setScaling(width(), height());
// Force full redraw
drawRegion(0, 0, width(), height());
}
}
void KVncView::drawRegion(int x, int y, int w, int h) {
if (m_scaling)
DrawZoomedScreenRegionX11Thread(winId(), width(), height(),
x, y, w, h);
else
DrawScreenRegionX11Thread(winId(), x, y, w, h);
TQPainter painter(this);
painter.drawImage(TQRect(x, y, w, h), m_cthreadObject.image(x, y, w, h));
}
void KVncView::customEvent(TQCustomEvent *e)
@ -387,9 +393,6 @@ void KVncView::customEvent(TQCustomEvent *e)
setFixedSize(m_framebufferSize);
emit changeSize(sre->width(), sre->height());
}
else if (e->type() == DesktopInitEventType) {
m_cthread.desktopInit();
}
else if (e->type() == StatusChangeEventType) {
StatusChangeEvent *sce = (StatusChangeEvent*) e;
setStatus(sce->status());
@ -562,10 +565,13 @@ void KVncView::mouseEvent(TQMouseEvent *e) {
x = (x * m_framebufferSize.width()) / width();
y = (y * m_framebufferSize.height()) / height();
}
m_wthread.queueMouseEvent(x, y, m_buttonMask);
m_cthreadObject.queueMouseEvent(x, y, m_buttonMask);
if (m_enableClientCursor)
DrawCursorX11Thread(x, y); // in rfbproto.c
if (m_enableClientCursor) {
// FIXME
// How to draw soft cursor?
// DrawCursorX11Thread(x, y); // in rfbproto.c
}
}
void KVncView::mousePressEvent(TQMouseEvent *e) {
@ -606,8 +612,8 @@ void KVncView::wheelEvent(TQWheelEvent *e) {
x = (x * m_framebufferSize.width()) / width();
y = (y * m_framebufferSize.height()) / height();
}
m_wthread.queueMouseEvent(x, y, eb|m_buttonMask);
m_wthread.queueMouseEvent(x, y, m_buttonMask);
m_cthreadObject.queueMouseEvent(x, y, eb|m_buttonMask);
m_cthreadObject.queueMouseEvent(x, y, m_buttonMask);
e->accept();
}
@ -620,25 +626,25 @@ void KVncView::pressKey(XEvent *xe) {
KKeyNative k(xe);
uint mod = k.mod();
if (mod & KKeyNative::modX(KKey::SHIFT))
m_wthread.queueKeyEvent(XK_Shift_L, true);
m_cthreadObject.queueKeyEvent(XK_Shift_L, true);
if (mod & KKeyNative::modX(KKey::CTRL))
m_wthread.queueKeyEvent(XK_Control_L, true);
m_cthreadObject.queueKeyEvent(XK_Control_L, true);
if (mod & KKeyNative::modX(KKey::ALT))
m_wthread.queueKeyEvent(XK_Alt_L, true);
m_cthreadObject.queueKeyEvent(XK_Alt_L, true);
if (mod & KKeyNative::modX(KKey::WIN))
m_wthread.queueKeyEvent(XK_Meta_L, true);
m_cthreadObject.queueKeyEvent(XK_Meta_L, true);
m_wthread.queueKeyEvent(k.sym(), true);
m_wthread.queueKeyEvent(k.sym(), false);
m_cthreadObject.queueKeyEvent(k.sym(), true);
m_cthreadObject.queueKeyEvent(k.sym(), false);
if (mod & KKeyNative::modX(KKey::WIN))
m_wthread.queueKeyEvent(XK_Meta_L, false);
m_cthreadObject.queueKeyEvent(XK_Meta_L, false);
if (mod & KKeyNative::modX(KKey::ALT))
m_wthread.queueKeyEvent(XK_Alt_L, false);
m_cthreadObject.queueKeyEvent(XK_Alt_L, false);
if (mod & KKeyNative::modX(KKey::CTRL))
m_wthread.queueKeyEvent(XK_Control_L, false);
m_cthreadObject.queueKeyEvent(XK_Control_L, false);
if (mod & KKeyNative::modX(KKey::SHIFT))
m_wthread.queueKeyEvent(XK_Shift_L, false);
m_cthreadObject.queueKeyEvent(XK_Shift_L, false);
m_mods.clear();
}
@ -671,7 +677,7 @@ bool KVncView::x11Event(XEvent *e) {
else
unpressModifiers();
}
m_wthread.queueKeyEvent(s, pressed);
m_cthreadObject.queueKeyEvent(s, pressed);
}
return true;
}
@ -680,7 +686,7 @@ void KVncView::unpressModifiers() {
TQValueList<unsigned int> keys = m_mods.keys();
TQValueList<unsigned int>::const_iterator it = keys.begin();
while (it != keys.end()) {
m_wthread.queueKeyEvent(*it, false);
m_cthreadObject.queueKeyEvent(*it, false);
it++;
}
m_mods.clear();
@ -713,7 +719,7 @@ void KVncView::clipboardChanged() {
if (text.length() > MAX_SELECTION_LENGTH)
return;
m_wthread.queueClientCut(text);
m_cthreadObject.queueClientCut(text);
}
void KVncView::selectionChanged() {
@ -727,7 +733,7 @@ void KVncView::selectionChanged() {
if (text.length() > MAX_SELECTION_LENGTH)
return;
m_wthread.queueClientCut(text);
m_cthreadObject.queueClientCut(text);
}
@ -759,7 +765,7 @@ void KVncView::enableClientCursor(bool enable) {
locks and signals are there to protect against deadlocks and other
horribleness. Be careful making changes here.
*/
int getPassword(char *passwd, int pwlen) {
int getPassword(char * &passwd) {
int retV = 0;
//Prepare the system
@ -786,9 +792,7 @@ int getPassword(char *passwd, int pwlen) {
//Process the password if we got it, clear it if we didn't
if (retV) {
strncpy(passwd, (const char*)password, pwlen);
} else {
passwd[0] = 0;
passwd = strdup((const char*)password);
}
//Pack up and go home

@ -2,7 +2,8 @@
kvncview.h - widget that shows the vnc client
-------------------
begin : Thu Dec 20 15:11:42 CET 2001
copyright : (C) 2001-2003 by Tim Jansen
copyright : (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
(C) 2001-2003 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
@ -24,7 +25,6 @@
#include "pointerlatencyometer.h"
#include "hostpreferences.h"
#include "vnctypes.h"
#include "threads.h"
class TQClipBoard;
@ -34,8 +34,8 @@ class KVncView : public KRemoteView
Q_OBJECT
private:
ControllerThread m_cthread;
WriterThread m_wthread;
ControllerThreadObject m_cthreadObject;
TQEventLoopThread m_cthread;
volatile bool m_quitFlag; // if set: all threads should die ASAP
TQMutex m_framebufferLock;
bool m_enableFramebufferLocking;
@ -74,6 +74,7 @@ protected:
void mouseMoveEvent(TQMouseEvent*);
void wheelEvent(TQWheelEvent *);
void focusOutEvent(TQFocusEvent *);
void resizeEvent(TQResizeEvent *);
bool x11Event(XEvent*);
public:
@ -116,6 +117,8 @@ public slots:
private slots:
// void requestPassword();
void clipboardChanged();
void selectionChanged();
};

Failā izmaiņas netiks attēlotas, jo tās ir par lielu Ielādēt izmaiņas

@ -1,963 +0,0 @@
/*
* Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved.
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* rfbproto.h - header file for the RFB protocol version 3.3
*
* Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed
* integer (for n = 8, 16 and 32).
*
* All multiple byte integers are in big endian (network) order (most
* significant byte first). Unless noted otherwise there is no special
* alignment of protocol structures.
*
*
* Once the initial handshaking is done, all messages start with a type byte,
* (usually) followed by message-specific data. The order of definitions in
* this file is as follows:
*
* (1) Structures used in several types of message.
* (2) Structures used in the initial handshaking.
* (3) Message types.
* (4) Encoding types.
* (5) For each message type, the form of the data following the type byte.
* Sometimes this is defined by a single structure but the more complex
* messages have to be explained by comments.
*/
#include "vnctypes.h"
/*****************************************************************************
*
* Structures used in several messages
*
*****************************************************************************/
/*-----------------------------------------------------------------------------
* Structure used to specify a rectangle. This structure is a multiple of 4
* bytes so that it can be interspersed with 32-bit pixel data without
* affecting alignment.
*/
typedef struct {
CARD16 x;
CARD16 y;
CARD16 w;
CARD16 h;
} rfbRectangle;
#define sz_rfbRectangle 8
/*-----------------------------------------------------------------------------
* Structure used to specify pixel format.
*/
typedef struct {
CARD8 bitsPerPixel; /* 8,16,32 only */
CARD8 depth; /* 8 to 32 */
CARD8 bigEndian; /* True if multi-byte pixels are interpreted
as big endian, or if single-bit-per-pixel
has most significant bit of the byte
corresponding to first (leftmost) pixel. Of
course this is meaningless for 8 bits/pix */
CARD8 trueColour; /* If false then we need a "colour map" to
convert pixels to RGB. If true, xxxMax and
xxxShift specify bits used for red, green
and blue */
/* the following fields are only meaningful if trueColour is true */
CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the
number of bits used for red). Note this
value is always in big endian order. */
CARD16 greenMax; /* similar for green */
CARD16 blueMax; /* and blue */
CARD8 redShift; /* number of shifts needed to get the red
value in a pixel to the least significant
bit. To find the red value from a given
pixel, do the following:
1) Swap pixel value according to bigEndian
(e.g. if bigEndian is false and host byte
order is big endian, then swap).
2) Shift right by redShift.
3) AND with redMax (in host byte order).
4) You now have the red value between 0 and
redMax. */
CARD8 greenShift; /* similar for green */
CARD8 blueShift; /* and blue */
CARD8 pad1;
CARD16 pad2;
} rfbPixelFormat;
#define sz_rfbPixelFormat 16
/*****************************************************************************
*
* Initial handshaking messages
*
*****************************************************************************/
/*-----------------------------------------------------------------------------
* Protocol Version
*
* The server always sends 12 bytes to start which identifies the latest RFB
* protocol version number which it supports. These bytes are interpreted
* as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where
* xxx and yyy are the major and minor version numbers (for version 3.3
* this is "RFB 003.003\n").
*
* The client then replies with a similar 12-byte message giving the version
* number of the protocol which should actually be used (which may be different
* to that quoted by the server).
*
* It is intended that both clients and servers may provide some level of
* backwards compatibility by this mechanism. Servers in particular should
* attempt to provide backwards compatibility, and even forwards compatibility
* to some extent. For example if a client demands version 3.1 of the
* protocol, a 3.0 server can probably assume that by ignoring requests for
* encoding types it doesn't understand, everything will still work OK. This
* will probably not be the case for changes in the major version number.
*
* The format string below can be used in sprintf or sscanf to generate or
* decode the version string respectively.
*/
#define rfbProtocolVersionFormat "RFB %03d.%03d\n"
#define rfbProtocolMajorVersion 3
#define rfbProtocolMinorVersion 3
typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
#define sz_rfbProtocolVersionMsg 12
/*-----------------------------------------------------------------------------
* Authentication
*
* Once the protocol version has been decided, the server then sends a 32-bit
* word indicating whether any authentication is needed on the connection.
* The value of this word determines the authentication scheme in use. For
* version 3.0 of the protocol this may have one of the following values:
*/
#define rfbConnFailed 0
#define rfbNoAuth 1
#define rfbVncAuth 2
/*
* rfbConnFailed: For some reason the connection failed (e.g. the server
* cannot support the desired protocol version). This is
* followed by a string describing the reason (where a
* string is specified as a 32-bit length followed by that
* many ASCII characters).
*
* rfbNoAuth: No authentication is needed.
*
* rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte
* challenge follows, which the client encrypts as
* appropriate using the password and sends the resulting
* 16-byte response. If the response is correct, the
* server sends the 32-bit word rfbVncAuthOK. If a simple
* failure happens, the server sends rfbVncAuthFailed and
* closes the connection. If the server decides that too
* many failures have occurred, it sends rfbVncAuthTooMany
* and closes the connection. In the latter case, the
* server should not allow an immediate reconnection by
* the client.
*/
#define rfbVncAuthOK 0
#define rfbVncAuthFailed 1
#define rfbVncAuthTooMany 2
/*-----------------------------------------------------------------------------
* Client Initialisation Message
*
* Once the client and server are sure that they're happy to talk to one
* another, the client sends an initialisation message. At present this
* message only consists of a boolean indicating whether the server should try
* to share the desktop by leaving other clients connected, or give exclusive
* access to this client by disconnecting all other clients.
*/
typedef struct {
CARD8 shared;
} rfbClientInitMsg;
#define sz_rfbClientInitMsg 1
/*-----------------------------------------------------------------------------
* Server Initialisation Message
*
* After the client initialisation message, the server sends one of its own.
* This tells the client the width and height of the server's framebuffer,
* its pixel format and the name associated with the desktop.
*/
typedef struct {
CARD16 framebufferWidth;
CARD16 framebufferHeight;
rfbPixelFormat format; /* the server's preferred pixel format */
CARD32 nameLength;
/* followed by char name[nameLength] */
} rfbServerInitMsg;
#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat)
/*
* Following the server initialisation message it's up to the client to send
* whichever protocol messages it wants. Typically it will send a
* SetPixelFormat message and a SetEncodings message, followed by a
* FramebufferUpdateRequest. From then on the server will send
* FramebufferUpdate messages in response to the client's
* FramebufferUpdateRequest messages. The client should send
* FramebufferUpdateRequest messages with incremental set to true when it has
* finished processing one FramebufferUpdate and is ready to process another.
* With a fast client, the rate at which FramebufferUpdateRequests are sent
* should be regulated to avoid hogging the network.
*/
/*****************************************************************************
*
* Message types
*
*****************************************************************************/
/* server -> client */
#define rfbFramebufferUpdate 0
#define rfbSetColourMapEntries 1
#define rfbBell 2
#define rfbServerCutText 3
/* client -> server */
#define rfbSetPixelFormat 0
#define rfbFixColourMapEntries 1 /* not currently supported */
#define rfbSetEncodings 2
#define rfbFramebufferUpdateRequest 3
#define rfbKeyEvent 4
#define rfbPointerEvent 5
#define rfbClientCutText 6
/*****************************************************************************
*
* Encoding types
*
*****************************************************************************/
#define rfbEncodingRaw 0
#define rfbEncodingCopyRect 1
#define rfbEncodingRRE 2
#define rfbEncodingCoRRE 4
#define rfbEncodingHextile 5
#define rfbEncodingZlib 6
#define rfbEncodingTight 7
#define rfbEncodingZlibHex 8
/*
* Special encoding numbers:
* 0xFFFFFF00 .. 0xFFFFFF0F -- encoding-specific compression levels;
* 0xFFFFFF10 .. 0xFFFFFF1F -- mouse cursor shape data;
* 0xFFFFFF20 .. 0xFFFFFF2F -- various protocol extensions;
* 0xFFFFFF30 .. 0xFFFFFFDF -- not allocated yet;
* 0xFFFFFFE0 .. 0xFFFFFFEF -- quality level for JPEG compressor;
* 0xFFFFFFF0 .. 0xFFFFFFFF -- cross-encoding compression levels.
*/
/*
* Reserved range for TDE:
* 0xFFFE0100 - 0xFFFE01FF
*/
#define rfbEncodingBackground 0xFFFE0125
#define rfbEncodingCompressLevel0 0xFFFFFF00
#define rfbEncodingCompressLevel1 0xFFFFFF01
#define rfbEncodingCompressLevel2 0xFFFFFF02
#define rfbEncodingCompressLevel3 0xFFFFFF03
#define rfbEncodingCompressLevel4 0xFFFFFF04
#define rfbEncodingCompressLevel5 0xFFFFFF05
#define rfbEncodingCompressLevel6 0xFFFFFF06
#define rfbEncodingCompressLevel7 0xFFFFFF07
#define rfbEncodingCompressLevel8 0xFFFFFF08
#define rfbEncodingCompressLevel9 0xFFFFFF09
#define rfbEncodingXCursor 0xFFFFFF10
#define rfbEncodingRichCursor 0xFFFFFF11
#define rfbEncodingSoftCursor 0xFFFFFF12
#define rfbEncodingPointerPos 0xFFFFFF18
#define rfbEncodingLastRect 0xFFFFFF20
#define rfbEncodingQualityLevel0 0xFFFFFFE0
#define rfbEncodingQualityLevel1 0xFFFFFFE1
#define rfbEncodingQualityLevel2 0xFFFFFFE2
#define rfbEncodingQualityLevel3 0xFFFFFFE3
#define rfbEncodingQualityLevel4 0xFFFFFFE4
#define rfbEncodingQualityLevel5 0xFFFFFFE5
#define rfbEncodingQualityLevel6 0xFFFFFFE6
#define rfbEncodingQualityLevel7 0xFFFFFFE7
#define rfbEncodingQualityLevel8 0xFFFFFFE8
#define rfbEncodingQualityLevel9 0xFFFFFFE9
/*****************************************************************************
*
* Server -> client message definitions
*
*****************************************************************************/
/*-----------------------------------------------------------------------------
* FramebufferUpdate - a block of rectangles to be copied to the framebuffer.
*
* This message consists of a header giving the number of rectangles of pixel
* data followed by the rectangles themselves. The header is padded so that
* together with the type byte it is an exact multiple of 4 bytes (to help
* with alignment of 32-bit pixels):
*/
typedef struct {
CARD8 type; /* always rfbFramebufferUpdate */
CARD8 pad;
CARD16 nRects;
/* followed by nRects rectangles */
} rfbFramebufferUpdateMsg;
#define sz_rfbFramebufferUpdateMsg 4
/*
* Each rectangle of pixel data consists of a header describing the position
* and size of the rectangle and a type word describing the encoding of the
* pixel data, followed finally by the pixel data. Note that if the client has
* not sent a SetEncodings message then it will only receive raw pixel data.
* Also note again that this structure is a multiple of 4 bytes.
*/
typedef struct {
rfbRectangle r;
CARD32 encoding; /* one of the encoding types rfbEncoding... */
} rfbFramebufferUpdateRectHeader;
#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Raw Encoding. Pixels are sent in top-to-bottom scanline order,
* left-to-right within a scanline with no padding in between.
*/
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* CopyRect Encoding. The pixels are specified simply by the x and y position
* of the source rectangle.
*/
typedef struct {
CARD16 srcX;
CARD16 srcY;
} rfbCopyRect;
#define sz_rfbCopyRect 4
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure
* giving the number of subrectangles following. Finally the data follows in
* the form [<bgpixel><subrect><subrect>...] where each <subrect> is
* [<pixel><rfbRectangle>].
*/
typedef struct {
CARD32 nSubrects;
} rfbRREHeader;
#define sz_rfbRREHeader 4
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving
* the number of subrectangles following. Finally the data follows in the form
* [<bgpixel><subrect><subrect>...] where each <subrect> is
* [<pixel><rfbCoRRERectangle>]. This means that
* the whole rectangle must be at most 255x255 pixels.
*/
typedef struct {
CARD8 x;
CARD8 y;
CARD8 w;
CARD8 h;
} rfbCoRRERectangle;
#define sz_rfbCoRRERectangle 4
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels,
* starting at the top left going in left-to-right, top-to-bottom order. If
* the width of the rectangle is not an exact multiple of 16 then the width of
* the last tile in each row will be correspondingly smaller. Similarly if the
* height is not an exact multiple of 16 then the height of each tile in the
* final row will also be smaller. Each tile begins with a "subencoding" type
* byte, which is a mask made up of a number of bits. If the Raw bit is set
* then the other bits are irrelevant; w*h pixel values follow (where w and h
* are the width and height of the tile). Otherwise the tile is encoded in a
* similar way to RRE, except that the position and size of each subrectangle
* can be specified in just two bytes. The other bits in the mask are as
* follows:
*
* BackgroundSpecified - if set, a pixel value follows which specifies
* the background colour for this tile. The first non-raw tile in a
* rectangle must have this bit set. If this bit isn't set then the
* background is the same as the last tile.
*
* ForegroundSpecified - if set, a pixel value follows which specifies
* the foreground colour to be used for all subrectangles in this tile.
* If this bit is set then the SubrectsColoured bit must be zero.
*
* AnySubrects - if set, a single byte follows giving the number of
* subrectangles following. If not set, there are no subrectangles (i.e.
* the whole tile is just solid background colour).
*
* SubrectsColoured - if set then each subrectangle is preceded by a pixel
* value giving the colour of that subrectangle. If not set, all
* subrectangles are the same colour, the foreground colour; if the
* ForegroundSpecified bit wasn't set then the foreground is the same as
* the last tile.
*
* The position and size of each subrectangle is specified in two bytes. The
* Pack macros below can be used to generate the two bytes from x, y, w, h,
* and the Extract macros can be used to extract the x, y, w, h values from
* the two bytes.
*/
#define rfbHextileRaw (1 << 0)
#define rfbHextileBackgroundSpecified (1 << 1)
#define rfbHextileForegroundSpecified (1 << 2)
#define rfbHextileAnySubrects (1 << 3)
#define rfbHextileSubrectsColoured (1 << 4)
#define rfbHextilePackXY(x,y) (((x) << 4) | (y))
#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1))
#define rfbHextileExtractX(byte) ((byte) >> 4)
#define rfbHextileExtractY(byte) ((byte) & 0xf)
#define rfbHextileExtractW(byte) (((byte) >> 4) + 1)
#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1)
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* zlib - zlib compressed Encoding. We have an rfbZlibHeader structure
* giving the number of bytes following. Finally the data follows is
* zlib compressed version of the raw pixel data as negotiated.
*/
typedef struct {
CARD32 nBytes;
} rfbZlibHeader;
#define sz_rfbZlibHeader 4
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Tight Encoding.
*
*-- The first byte of each Tight-encoded rectangle is a "compression control
* byte". Its format is as follows (bit 0 is the least significant one):
*
* bit 0: if 1, then compression stream 0 should be reset;
* bit 1: if 1, then compression stream 1 should be reset;
* bit 2: if 1, then compression stream 2 should be reset;
* bit 3: if 1, then compression stream 3 should be reset;
* bits 7-4: if 1000 (0x08), then the compression type is "fill",
* if 1001 (0x09), then the compression type is "jpeg",
* if 0xxx, then the compression type is "basic",
* values greater than 1001 are not valid.
*
* If the compression type is "basic", then bits 6..4 of the
* compression control byte (those xxx in 0xxx) specify the following:
*
* bits 5-4: decimal representation is the index of a particular zlib
* stream which should be used for decompressing the data;
* bit 6: if 1, then a "filter id" byte is following this byte.
*
*-- The data that follows after the compression control byte described
* above depends on the compression type ("fill", "jpeg" or "basic").
*
*-- If the compression type is "fill", then the only pixel value follows, in
* client pixel format (see NOTE 1). This value applies to all pixels of the
* rectangle.
*
*-- If the compression type is "jpeg", the following data stream looks like
* this:
*
* 1..3 bytes: data size (N) in compact representation;
* N bytes: JPEG image.
*
* Data size is compactly represented in one, two or three bytes, according
* to the following scheme:
*
* 0xxxxxxx (for values 0..127)
* 1xxxxxxx 0yyyyyyy (for values 128..16383)
* 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303)
*
* Here each character denotes one bit, xxxxxxx are the least significant 7
* bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the
* most significant 8 bits (bits 14-21). For example, decimal value 10000
* should be represented as two bytes: binary 10010000 01001110, or
* hexadecimal 90 4E.
*
*-- If the compression type is "basic" and bit 6 of the compression control
* byte was set to 1, then the next (second) byte specifies "filter id" which
* tells the decoder what filter type was used by the encoder to pre-process
* pixel data before the compression. The "filter id" byte can be one of the
* following:
*
* 0: no filter ("copy" filter);
* 1: "palette" filter;
* 2: "gradient" filter.
*
*-- If bit 6 of the compression control byte is set to 0 (no "filter id"
* byte), or if the filter id is 0, then raw pixel values in the client
* format (see NOTE 1) will be compressed. See below details on the
* compression.
*
*-- The "gradient" filter pre-processes pixel data with a simple algorithm
* which converts each color component to a difference between a "predicted"
* intensity and the actual intensity. Such a technique does not affect
* uncompressed data size, but helps to compress photo-like images better.
* Pseudo-code for converting intensities to differences is the following:
*
* P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1];
* if (P[i,j] < 0) then P[i,j] := 0;
* if (P[i,j] > MAX) then P[i,j] := MAX;
* D[i,j] := V[i,j] - P[i,j];
*
* Here V[i,j] is the intensity of a color component for a pixel at
* coordinates (i,j). MAX is the maximum value of intensity for a color
* component.
*
*-- The "palette" filter converts true-color pixel data to indexed colors
* and a palette which can consist of 2..256 colors. If the number of colors
* is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to
* encode one pixel. 1-bit encoding is performed such way that the most
* significant bits correspond to the leftmost pixels, and each raw of pixels
* is aligned to the byte boundary. When "palette" filter is used, the
* palette is sent before the pixel data. The palette begins with an unsigned
* byte which value is the number of colors in the palette minus 1 (i.e. 1
* means 2 colors, 255 means 256 colors in the palette). Then follows the
* palette itself which consist of pixel values in client pixel format (see
* NOTE 1).
*
*-- The pixel data is compressed using the zlib library. But if the data
* size after applying the filter but before the compression is less then 12,
* then the data is sent as is, uncompressed. Four separate zlib streams
* (0..3) can be used and the decoder should read the actual stream id from
* the compression control byte (see NOTE 2).
*
* If the compression is not used, then the pixel data is sent as is,
* otherwise the data stream looks like this:
*
* 1..3 bytes: data size (N) in compact representation;
* N bytes: zlib-compressed data.
*
* Data size is compactly represented in one, two or three bytes, just like
* in the "jpeg" compression method (see above).
*
*-- NOTE 1. If the color depth is 24, and all three color components are
* 8-bit wide, then one pixel in Tight encoding is always represented by
* three bytes, where the first byte is red component, the second byte is
* green component, and the third byte is blue component of the pixel color
* value. This applies to colors in palettes as well.
*
*-- NOTE 2. The decoder must reset compression streams' states before
* decoding the rectangle, if some of bits 0,1,2,3 in the compression control
* byte are set to 1. Note that the decoder must reset zlib streams even if
* the compression type is "fill" or "jpeg".
*
*-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only
* when bits-per-pixel value is either 16 or 32, not 8.
*
*-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048
* pixels. If a rectangle is wider, it must be split into several rectangles
* and each one should be encoded separately.
*
*/
#define rfbTightExplicitFilter 0x04
#define rfbTightFill 0x08
#define rfbTightJpeg 0x09
#define rfbTightMaxSubencoding 0x09
/* Filters to improve compression efficiency */
#define rfbTightFilterCopy 0x00
#define rfbTightFilterPalette 0x01
#define rfbTightFilterGradient 0x02
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* XCursor encoding. This is a special encoding used to transmit X-style
* cursor shapes from server to clients. Note that for this encoding,
* coordinates in rfbFramebufferUpdateRectHeader structure hold hotspot
* position (r.x, r.y) and cursor size (r.w, r.h). If (w * h != 0), two RGB
* samples are sent after header in the rfbXCursorColors structure. They
* denote foreground and background colors of the cursor. If a client
* supports only black-and-white cursors, it should ignore these colors and
* assume that foreground is black and background is white. Next, two bitmaps
* (1 bits per pixel) follow: first one with actual data (value 0 denotes
* background color, value 1 denotes foreground color), second one with
* transparency data (bits with zero value mean that these pixels are
* transparent). Both bitmaps represent cursor data in a byte stream, from
* left to right, from top to bottom, and each row is byte-aligned. Most
* significant bits correspond to leftmost pixels. The number of bytes in
* each row can be calculated as ((w + 7) / 8). If (w * h == 0), cursor
* should be hidden (or default local cursor should be set by the client).
*/
typedef struct {
CARD8 foreRed;
CARD8 foreGreen;
CARD8 foreBlue;
CARD8 backRed;
CARD8 backGreen;
CARD8 backBlue;
} rfbXCursorColors;
#define sz_rfbXCursorColors 6
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* RichCursor encoding. This is a special encoding used to transmit cursor
* shapes from server to clients. It is similar to the XCursor encoding but
* uses client pixel format instead of two RGB colors to represent cursor
* image. For this encoding, coordinates in rfbFramebufferUpdateRectHeader
* structure hold hotspot position (r.x, r.y) and cursor size (r.w, r.h).
* After header, two pixmaps follow: first one with cursor image in current
* client pixel format (like in raw encoding), second with transparency data
* (1 bit per pixel, exactly the same format as used for transparency bitmap
* in the XCursor encoding). If (w * h == 0), cursor should be hidden (or
* default local cursor should be set by the client).
*/
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* SoftCursor encoding. This encoding is used to transmit image and position
* of the remote cursor. It has two sub-messages: SetImage is used to upload
* one of 16 images, and Move selects the image and sets the position of the
* cursor.
* Each SoftCursor message starts with a CARD8. If it is in the 0-15 range
* it specifies the number of the cursor image and is followed by the
* rfbSoftCursorMove message. If the given cursor has not been set yet the
* message will be ignored. If the first CARD8 is in the 128-143 range it
* specifies the cursor that will be set in the following
* rfbSoftCursorSetImage message. To hide the cursor send a SetImage
* message with width and height 0 and imageLength 0.
* SetImage transmits the hotspot coordinates in the x/y fields of the
* rfbFramebufferUpdateRectHeader, width and height of the image are in the
* header's width and height fields.
* Move transmits the pointer coordinates in the w/h fields of the
* header, x/y are always 0.
*/
typedef struct {
CARD8 imageIndex;
CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
} rfbSoftCursorMove;
typedef struct {
CARD8 imageIndex;
CARD8 padding;
CARD16 imageLength;
/*
* Followed by an image of the cursor in the client's image format
* with the following RLE mask compression. It begins with CARD8 that
* specifies the number of mask'ed pixels that will be NOT transmitted.
* Then follows a CARD8 that specified by the number of unmask'd pixels
* that will be transmitted next. Then a CARD8 with the number of mask'd
* pixels and so on.
*/
} rfbSoftCursorSetImage;
typedef union {
CARD8 type;
rfbSoftCursorMove move;
rfbSoftCursorSetImage setImage;
} rfbSoftCursorMsg;
#define rfbSoftCursorMaxImages 16
#define rfbSoftCursorSetIconOffset 128
/*-----------------------------------------------------------------------------
* SetColourMapEntries - these messages are only sent if the pixel
* format uses a "colour map" (i.e. trueColour false) and the client has not
* fixed the entire colour map using FixColourMapEntries. In addition they
* will only start being sent after the client has sent its first
* FramebufferUpdateRequest. So if the client always tells the server to use
* trueColour then it never needs to process this type of message.
*/
typedef struct {
CARD8 type; /* always rfbSetColourMapEntries */
CARD8 pad;
CARD16 firstColour;
CARD16 nColours;
/* Followed by nColours * 3 * CARD16
r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
} rfbSetColourMapEntriesMsg;
#define sz_rfbSetColourMapEntriesMsg 6
/*-----------------------------------------------------------------------------
* Bell - ring a bell on the client if it has one.
*/
typedef struct {
CARD8 type; /* always rfbBell */
} rfbBellMsg;
#define sz_rfbBellMsg 1
/*-----------------------------------------------------------------------------
* ServerCutText - the server has new text in its cut buffer.
*/
typedef struct {
CARD8 type; /* always rfbServerCutText */
CARD8 pad1;
CARD16 pad2;
CARD32 length;
/* followed by char text[length] */
} rfbServerCutTextMsg;
#define sz_rfbServerCutTextMsg 8
/*-----------------------------------------------------------------------------
* Union of all server->client messages.
*/
typedef union {
CARD8 type;
rfbFramebufferUpdateMsg fu;
rfbSetColourMapEntriesMsg scme;
rfbBellMsg b;
rfbServerCutTextMsg sct;
} rfbServerToClientMsg;
/*****************************************************************************
*
* Message definitions (client -> server)
*
*****************************************************************************/
/*-----------------------------------------------------------------------------
* SetPixelFormat - tell the RFB server the format in which the client wants
* pixels sent.
*/
typedef struct {
CARD8 type; /* always rfbSetPixelFormat */
CARD8 pad1;
CARD16 pad2;
rfbPixelFormat format;
} rfbSetPixelFormatMsg;
#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4)
/*-----------------------------------------------------------------------------
* FixColourMapEntries - when the pixel format uses a "colour map", fix
* read-only colour map entries.
*
* ***************** NOT CURRENTLY SUPPORTED *****************
*/
typedef struct {
CARD8 type; /* always rfbFixColourMapEntries */
CARD8 pad;
CARD16 firstColour;
CARD16 nColours;
/* Followed by nColours * 3 * CARD16
r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
} rfbFixColourMapEntriesMsg;
#define sz_rfbFixColourMapEntriesMsg 6
/*-----------------------------------------------------------------------------
* SetEncodings - tell the RFB server which encoding types we accept. Put them
* in order of preference, if we have any. We may always receive raw
* encoding, even if we don't specify it here.
*/
typedef struct {
CARD8 type; /* always rfbSetEncodings */
CARD8 pad;
CARD16 nEncodings;
/* followed by nEncodings * CARD32 encoding types */
} rfbSetEncodingsMsg;
#define sz_rfbSetEncodingsMsg 4
/*-----------------------------------------------------------------------------
* FramebufferUpdateRequest - request for a framebuffer update. If incremental
* is true then the client just wants the changes since the last update. If
* false then it wants the whole of the specified rectangle.
*/
typedef struct {
CARD8 type; /* always rfbFramebufferUpdateRequest */
CARD8 incremental;
CARD16 x;
CARD16 y;
CARD16 w;
CARD16 h;
} rfbFramebufferUpdateRequestMsg;
#define sz_rfbFramebufferUpdateRequestMsg 10
/*-----------------------------------------------------------------------------
* KeyEvent - key press or release
*
* Keys are specified using the "keysym" values defined by the X Window System.
* For most ordinary keys, the keysym is the same as the corresponding ASCII
* value. Other common keys are:
*
* BackSpace 0xff08
* Tab 0xff09
* Return or Enter 0xff0d
* Escape 0xff1b
* Insert 0xff63
* Delete 0xffff
* Home 0xff50
* End 0xff57
* Page Up 0xff55
* Page Down 0xff56
* Left 0xff51
* Up 0xff52
* Right 0xff53
* Down 0xff54
* F1 0xffbe
* F2 0xffbf
* ... ...
* F12 0xffc9
* Shift 0xffe1
* Control 0xffe3
* Meta 0xffe7
* Alt 0xffe9
*/
typedef struct {
CARD8 type; /* always rfbKeyEvent */
CARD8 down; /* true if down (press), false if up */
CARD16 pad;
CARD32 key; /* key is specified as an X keysym */
} rfbKeyEventMsg;
#define sz_rfbKeyEventMsg 8
/*-----------------------------------------------------------------------------
* PointerEvent - mouse/pen move and/or button press.
*/
typedef struct {
CARD8 type; /* always rfbPointerEvent */
CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
CARD16 x;
CARD16 y;
} rfbPointerEventMsg;
#define rfbButton1Mask 1
#define rfbButton2Mask 2
#define rfbButton3Mask 4
#define sz_rfbPointerEventMsg 6
/*-----------------------------------------------------------------------------
* ClientCutText - the client has new text in its cut buffer.
*/
typedef struct {
CARD8 type; /* always rfbClientCutText */
CARD8 pad1;
CARD16 pad2;
CARD32 length;
/* followed by char text[length] */
} rfbClientCutTextMsg;
#define sz_rfbClientCutTextMsg 8
/*-----------------------------------------------------------------------------
* Union of all client->server messages.
*/
typedef union {
CARD8 type;
rfbSetPixelFormatMsg spf;
rfbFixColourMapEntriesMsg fcme;
rfbSetEncodingsMsg se;
rfbFramebufferUpdateRequestMsg fur;
rfbKeyEventMsg ke;
rfbPointerEventMsg pe;
rfbClientCutTextMsg cct;
} rfbClientToServerMsg;

@ -0,0 +1,331 @@
/****************************************************************************
**
** Copyright (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
**
** This file is part of TDE.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA.
**
****************************************************************************/
#include <tqimage.h>
/*!
Smooth scaling function with ability to limit scaled region
The selection rectangle is given in terms of destination coordinates
It leaves areas outside of the selection rectangle undefined...
Function code originally taken from qimage.cpp pnmscale () and modified
to only scale a section of the source
This function uses code based on pnmscale.c by Jef Poskanzer.
pnmscale.c - read a portable anymap and scale it
\legalese
Copyright (C) 1989, 1991 by Jef Poskanzer.
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that copyright notice and this permission
notice appear in supporting documentation. This software is
provided "as is" without express or implied warranty.
*/
void pnmscale_fractional(const TQImage& src, TQImage& dst, int x, int y, int w, int h)
{
TQRgb* xelrow = 0;
TQRgb* tempxelrow = 0;
register TQRgb* xP;
register TQRgb* nxP;
int rows, cols, rowsread, newrows, newcols;
register int row, col, needtoreadrow;
const uchar maxval = 255;
double xscale, yscale;
long sxscale, syscale;
register long fracrowtofill, fracrowleft;
long* as;
long* rs;
long* gs;
long* bs;
int rowswritten = 0;
int colswritten = 0;
cols = src.width();
rows = src.height();
newcols = dst.width();
newrows = dst.height();
long SCALE;
long HALFSCALE;
if (cols > 4096)
{
SCALE = 4096;
HALFSCALE = 2048;
}
else
{
int fac = 4096;
while (cols * fac > 4096)
{
fac /= 2;
}
SCALE = fac * cols;
HALFSCALE = fac * cols / 2;
}
xscale = (double) newcols / (double) cols;
yscale = (double) newrows / (double) rows;
sxscale = (long)(xscale * SCALE);
syscale = (long)(yscale * SCALE);
if ( newrows != rows ) /* shortcut Y scaling if possible */
tempxelrow = new TQRgb[cols];
if ( src.hasAlphaBuffer() ) {
dst.setAlphaBuffer(TRUE);
as = new long[cols];
for ( col = 0; col < cols; ++col )
as[col] = HALFSCALE;
} else {
as = 0;
}
rs = new long[cols];
gs = new long[cols];
bs = new long[cols];
rowsread = 0;
fracrowleft = syscale;
needtoreadrow = 1;
for ( col = 0; col < cols; ++col )
rs[col] = gs[col] = bs[col] = HALFSCALE;
fracrowtofill = SCALE;
for ( row = 0; row < newrows; ++row ) {
/* First scale Y from xelrow into tempxelrow. */
if ( newrows == rows ) {
/* shortcut Y scaling if possible */
tempxelrow = xelrow = (TQRgb*)src.scanLine(rowsread++);
} else {
while ( fracrowleft < fracrowtofill ) {
if ( needtoreadrow && rowsread < rows )
xelrow = (TQRgb*)src.scanLine(rowsread++);
for ( col = 0, xP = xelrow; col < cols; ++col, ++xP ) {
if ((rowswritten >= y) && (rowswritten <= (y + h))) {
if (as) {
as[col] += fracrowleft * tqAlpha( *xP );
rs[col] += fracrowleft * tqRed( *xP ) * tqAlpha( *xP ) / 255;
gs[col] += fracrowleft * tqGreen( *xP ) * tqAlpha( *xP ) / 255;
bs[col] += fracrowleft * tqBlue( *xP ) * tqAlpha( *xP ) / 255;
} else {
rs[col] += fracrowleft * tqRed( *xP );
gs[col] += fracrowleft * tqGreen( *xP );
bs[col] += fracrowleft * tqBlue( *xP );
}
}
}
fracrowtofill -= fracrowleft;
fracrowleft = syscale;
needtoreadrow = 1;
}
/* Now fracrowleft is >= fracrowtofill, so we can produce a row. */
if ( needtoreadrow && rowsread < rows ) {
xelrow = (TQRgb*)src.scanLine(rowsread++);
needtoreadrow = 0;
}
register long a=0;
for ( col = 0, xP = xelrow, nxP = tempxelrow, colswritten = 0;
col < cols; ++col, ++xP, ++nxP, ++colswritten )
{
if ((rowswritten >= y) && (rowswritten <= (y + h))) {
register long r, g, b;
if ( as ) {
r = rs[col] + fracrowtofill * tqRed( *xP ) * tqAlpha( *xP ) / 255;
g = gs[col] + fracrowtofill * tqGreen( *xP ) * tqAlpha( *xP ) / 255;
b = bs[col] + fracrowtofill * tqBlue( *xP ) * tqAlpha( *xP ) / 255;
a = as[col] + fracrowtofill * tqAlpha( *xP );
if ( a ) {
r = r * 255 / a * SCALE;
g = g * 255 / a * SCALE;
b = b * 255 / a * SCALE;
}
} else {
r = rs[col] + fracrowtofill * tqRed( *xP );
g = gs[col] + fracrowtofill * tqGreen( *xP );
b = bs[col] + fracrowtofill * tqBlue( *xP );
}
r /= SCALE;
if ( r > maxval ) r = maxval;
g /= SCALE;
if ( g > maxval ) g = maxval;
b /= SCALE;
if ( b > maxval ) b = maxval;
if ( as ) {
a /= SCALE;
if ( a > maxval ) a = maxval;
*nxP = tqRgba( (int)r, (int)g, (int)b, (int)a );
as[col] = HALFSCALE;
} else {
*nxP = tqRgb( (int)r, (int)g, (int)b );
}
rs[col] = gs[col] = bs[col] = HALFSCALE;
}
}
fracrowleft -= fracrowtofill;
if ( fracrowleft == 0 ) {
fracrowleft = syscale;
needtoreadrow = 1;
}
fracrowtofill = SCALE;
}
/* Now scale X from tempxelrow into dst and write it out. */
if ( newcols == cols ) {
/* shortcut X scaling if possible */
memcpy(dst.scanLine(rowswritten++), tempxelrow, newcols*4);
} else {
register long a, r, g, b;
register long fraccoltofill, fraccolleft = 0;
register int needcol;
nxP = (TQRgb*)dst.scanLine(rowswritten++);
colswritten = 0;
fraccoltofill = SCALE;
a = r = g = b = HALFSCALE;
needcol = 0;
for ( col = 0, xP = tempxelrow; col < cols; ++col, ++xP ) {
fraccolleft = sxscale;
while ( fraccolleft >= fraccoltofill ) {
if ( needcol ) {
++nxP;
++colswritten;
a = r = g = b = HALFSCALE;
}
if ((colswritten >= x) && (colswritten <= (x + w)) && (rowswritten >= y) && (rowswritten <= (y + h))) {
if ( as ) {
r += fraccoltofill * tqRed( *xP ) * tqAlpha( *xP ) / 255;
g += fraccoltofill * tqGreen( *xP ) * tqAlpha( *xP ) / 255;
b += fraccoltofill * tqBlue( *xP ) * tqAlpha( *xP ) / 255;
a += fraccoltofill * tqAlpha( *xP );
if ( a ) {
r = r * 255 / a * SCALE;
g = g * 255 / a * SCALE;
b = b * 255 / a * SCALE;
}
} else {
r += fraccoltofill * tqRed( *xP );
g += fraccoltofill * tqGreen( *xP );
b += fraccoltofill * tqBlue( *xP );
}
r /= SCALE;
if ( r > maxval ) r = maxval;
g /= SCALE;
if ( g > maxval ) g = maxval;
b /= SCALE;
if ( b > maxval ) b = maxval;
if (as) {
a /= SCALE;
if ( a > maxval ) a = maxval;
*nxP = tqRgba( (int)r, (int)g, (int)b, (int)a );
} else {
*nxP = tqRgb( (int)r, (int)g, (int)b );
}
}
fraccolleft -= fraccoltofill;
fraccoltofill = SCALE;
needcol = 1;
}
if ( fraccolleft > 0 ) {
if ( needcol ) {
++nxP;
++colswritten;
a = r = g = b = HALFSCALE;
needcol = 0;
}
if ((rowswritten >= y) && (rowswritten <= (y + h))) {
if (as) {
a += fraccolleft * tqAlpha( *xP );
r += fraccolleft * tqRed( *xP ) * tqAlpha( *xP ) / 255;
g += fraccolleft * tqGreen( *xP ) * tqAlpha( *xP ) / 255;
b += fraccolleft * tqBlue( *xP ) * tqAlpha( *xP ) / 255;
} else {
r += fraccolleft * tqRed( *xP );
g += fraccolleft * tqGreen( *xP );
b += fraccolleft * tqBlue( *xP );
}
}
fraccoltofill -= fraccolleft;
}
}
if ( fraccoltofill > 0 ) {
--xP;
if ((rowswritten >= y) && (rowswritten <= (y + h))) {
if (as) {
a += fraccolleft * tqAlpha( *xP );
r += fraccoltofill * tqRed( *xP ) * tqAlpha( *xP ) / 255;
g += fraccoltofill * tqGreen( *xP ) * tqAlpha( *xP ) / 255;
b += fraccoltofill * tqBlue( *xP ) * tqAlpha( *xP ) / 255;
if ( a ) {
r = r * 255 / a * SCALE;
g = g * 255 / a * SCALE;
b = b * 255 / a * SCALE;
}
} else {
r += fraccoltofill * tqRed( *xP );
g += fraccoltofill * tqGreen( *xP );
b += fraccoltofill * tqBlue( *xP );
}
}
}
if ( ! needcol ) {
if ((rowswritten >= y) && (rowswritten <= (y + h))) {
r /= SCALE;
if ( r > maxval ) r = maxval;
g /= SCALE;
if ( g > maxval ) g = maxval;
b /= SCALE;
if ( b > maxval ) b = maxval;
if (as) {
a /= SCALE;
if ( a > maxval ) a = maxval;
*nxP = tqRgba( (int)r, (int)g, (int)b, (int)a );
} else {
*nxP = tqRgb( (int)r, (int)g, (int)b );
}
}
}
}
}
if ( newrows != rows && tempxelrow )// Robust, tempxelrow might be 0 1 day
delete [] tempxelrow;
if ( as ) // Avoid purify complaint
delete [] as;
if ( rs ) // Robust, rs might be 0 one day
delete [] rs;
if ( gs ) // Robust, gs might be 0 one day
delete [] gs;
if ( bs ) // Robust, bs might be 0 one day
delete [] bs;
}

@ -1,325 +0,0 @@
/*
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* 03-05-2002 tim@tjansen.de: removed Xt event processing for krdc
*/
/*
* sockets.c - functions to deal with sockets.
*/
#include <unistd.h>
#include <sys/socket.h>
#include <errno.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <fcntl.h>
#include <assert.h>
#include "vncviewer.h"
void PrintInHex(char *buf, int len);
Bool errorMessageOnReadFailure = True;
#define BUF_SIZE 8192
static char buf[BUF_SIZE];
static char *bufoutptr = buf;
static unsigned int buffered = 0;
/* Wait duration of select in seconds */
#define SELECT_PERIOD 3
/*
* ReadFromRFBServer is called whenever we want to read some data from the RFB
* server.
*/
Bool
ReadFromRFBServer(char *out, unsigned int n)
{
fd_set fds;
int e;
struct timeval tx;
if (isQuitFlagSet())
return False;
if (n <= buffered) {
memcpy(out, bufoutptr, n);
bufoutptr += n;
buffered -= n;
return True;
}
memcpy(out, bufoutptr, buffered);
out += buffered;
n -= buffered;
bufoutptr = buf;
buffered = 0;
if (n <= BUF_SIZE) {
while (buffered < n) {
int i;
if (isQuitFlagSet())
return False;
i = read(rfbsock, buf + buffered, BUF_SIZE - buffered);
if (i <= 0) {
if (i < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
FD_ZERO(&fds);
FD_SET(rfbsock,&fds);
tx.tv_sec = SELECT_PERIOD;
tx.tv_usec = 0;
if ((e=select(rfbsock+1, &fds, NULL, &fds, &tx)) < 0) {
perror("krdc: select read");
return False;
}
i = 0;
} else {
perror("krdc: read");
return False;
}
} else {
fprintf(stderr,"VNC server closed connection\n");
return False;
}
}
buffered += i;
}
memcpy(out, bufoutptr, n);
bufoutptr += n;
buffered -= n;
return isQuitFlagSet() ? False : True;
} else {
while (n > 0) {
int i;
if (isQuitFlagSet())
return False;
i = read(rfbsock, out, n);
if (i <= 0) {
if (i < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
FD_ZERO(&fds);
FD_SET(rfbsock,&fds);
tx.tv_sec = SELECT_PERIOD;
tx.tv_usec = 0;
if ((e=select(rfbsock+1, &fds, NULL, &fds, &tx)) < 0) {
perror("krdc: select");
return False;
}
i = 0;
} else {
perror("krdc: read");
return False;
}
} else {
fprintf(stderr,"VNC server closed connection\n");
return False;
}
}
out += i;
n -= i;
}
return isQuitFlagSet() ? False : True;
}
}
/*
* Write an exact number of bytes, and don't return until you've sent them.
* Note: this should only be called by the WriterThread
*/
Bool
WriteExact(int sock, const char *_buf, int n)
{
fd_set fds;
int i = 0;
int j;
int e;
struct timeval tx;
while (i < n) {
if (isQuitFlagSet())
return False;
j = write(sock, _buf + i, (n - i));
if (j <= 0) {
if (j < 0) {
if (errno == EWOULDBLOCK || errno == EAGAIN) {
FD_ZERO(&fds);
FD_SET(rfbsock,&fds);
tx.tv_sec = SELECT_PERIOD;
tx.tv_usec = 0;
if ((e=select(rfbsock+1, NULL, &fds, NULL, &tx)) < 0) {
perror("krdc: select write");
return False;
}
j = 0;
} else {
perror("krdc: write");
return False;
}
} else {
fprintf(stderr,"write failed\n");
return False;
}
}
i += j;
}
return True;
}
/*
* ConnectToTcpAddr connects to the given TCP port.
*/
int
ConnectToTcpAddr(unsigned int host, int port)
{
int sock;
struct sockaddr_in addr;
int one = 1;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = host;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("krdc: ConnectToTcpAddr: socket");
return -(int)INIT_CONNECTION_FAILED;
}
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("krdc: ConnectToTcpAddr: connect");
close(sock);
return -(int)INIT_NO_SERVER;
}
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
perror("krdc: ConnectToTcpAddr: setsockopt");
close(sock);
return -(int)INIT_CONNECTION_FAILED;
}
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
perror(": AcceptTcpConnection: fcntl");
close(sock);
return -(int)INIT_CONNECTION_FAILED;
}
return sock;
}
/*
* StringToIPAddr - convert a host string to an IP address.
*/
Bool
StringToIPAddr(const char *str, unsigned int *addr)
{
struct hostent *hp;
if (strcmp(str,"") == 0) {
*addr = 0; /* local */
return True;
}
*addr = inet_addr(str);
if (*addr != -1)
return True;
hp = gethostbyname(str);
if (hp) {
*addr = *(unsigned int *)hp->h_addr;
return True;
}
return False;
}
/*
* Print out the contents of a packet for debugging.
*/
void
PrintInHex(char *_buf, int len)
{
int i, j;
char c, str[17];
str[16] = 0;
fprintf(stderr,"ReadExact: ");
for (i = 0; i < len; i++)
{
if ((i % 16 == 0) && (i != 0)) {
fprintf(stderr," ");
}
c = _buf[i];
str[i % 16] = (((c > 31) && (c < 127)) ? c : '.');
fprintf(stderr,"%02x ",(unsigned char)c);
if ((i % 4) == 3)
fprintf(stderr," ");
if ((i % 16) == 15)
{
fprintf(stderr,"%s\n",str);
}
}
if ((i % 16) != 0)
{
for (j = i % 16; j < 16; j++)
{
fprintf(stderr," ");
if ((j % 4) == 3) fprintf(stderr," ");
}
str[i % 16] = 0;
fprintf(stderr,"%s\n",str);
}
fflush(stderr);
}
void freeSocketsResources() {
close(rfbsock);
errorMessageOnReadFailure = True;
bufoutptr = buf;
buffered = 0;
}

@ -2,7 +2,8 @@
threads.cpp - threads
-------------------
begin : Thu May 09 17:01:44 CET 2002
copyright : (C) 2002 by Tim Jansen
copyright : (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
(C) 2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
@ -24,369 +25,360 @@
#include "threads.h"
#include <tqcstring.h>
#include <tqpainter.h>
// Maximum idle time for writer thread in ms. When it timeouts, it will request
// another incremental update. Must be smaller than the timeout of the server
// (krfb's is 20s).
static const int MAXIMUM_WAIT_PERIOD = 8000;
#include <math.h>
// time to postpone incremental updates that have not been requested explicitly
static const int POSTPONED_INCRRQ_WAIT_PERIOD = 110;
extern void pnmscale_fractional(const TQImage& src, TQImage& dst, int x, int y, int w, int h);
static const int MOUSEPRESS_QUEUE_SIZE = 5;
static const int MOUSEMOVE_QUEUE_SIZE = 3;
static const int KEY_QUEUE_SIZE = 8192;
int getPassword(char * &passwd);
ControllerThread::ControllerThread(KVncView *v, WriterThread &wt, volatile bool &quitFlag) :
m_view(v),
m_status(REMOTE_VIEW_CONNECTING),
m_wthread(wt),
m_quitFlag(quitFlag),
m_desktopInitialized(false)
extern rfbBool newclient(rfbClient *cl)
{
int width = cl->width, height = cl->height, depth = cl->format.bitsPerPixel;
int size = width * height * (depth / 8);
uint8_t *buf = new uint8_t[size];
memset(buf, '\0', size);
cl->frameBuffer = buf;
cl->format.bitsPerPixel = 32;
cl->format.redShift = 16;
cl->format.greenShift = 8;
cl->format.blueShift = 0;
cl->format.redMax = 0xff;
cl->format.greenMax = 0xff;
cl->format.blueMax = 0xff;
SetFormatAndEncodings(cl);
return true;
}
void ControllerThread::changeStatus(RemoteViewStatus s) {
m_status = s;
TQApplication::postEvent(m_view, new StatusChangeEvent(s));
extern void updatefb(rfbClient* cl, int x, int y, int w, int h)
{
// kdDebug(5011) << "updated client: x: " << x << ", y: " << y << ", w: " << w << ", h: " << h << endl;
int width = cl->width, height = cl->height;
TQImage img(cl->frameBuffer, width, height, 32, NULL, 256, TQImage::IgnoreEndian);
if (img.isNull())
kdDebug(5011) << "image not loaded" << endl;
ControllerThreadObject *t = (ControllerThreadObject*)rfbClientGetClientData(cl, 0);
t->setImage(img);
t->queueDrawRegion(x, y, w, h);
}
void ControllerThread::sendFatalError(ErrorCode s) {
m_quitFlag = true;
TQApplication::postEvent(m_view, new FatalErrorEvent(s));
m_wthread.kick();
extern char *passwd(rfbClient *cl)
{
Q_UNUSED(cl)
kdDebug(5011) << "password request" << endl;
char *passwd;
if (getPassword(passwd)) {
return passwd;
}
else {
return NULL;
}
}
/*
* Calls this from the X11 thread
*/
void ControllerThread::desktopInit() {
SetVisualAndCmap();
ToplevelInit();
DesktopInit(m_view->winId());
m_desktopInitialized = true;
m_waiter.wakeAll();
extern void authresults(rfbClient *cl, uint32_t authResult)
{
kdDebug(5011) << "authentication result: " << authResult << endl;
ControllerThreadObject *t = (ControllerThreadObject*)rfbClientGetClientData(cl, 0);
t->authenticationResults(authResult);
}
void ControllerThread::kick() {
m_waiter.wakeAll();
extern void networkstat(rfbClient *cl, uint32_t statuscode)
{
kdDebug(5011) << "network status: " << statuscode << endl;
ControllerThreadObject *t = (ControllerThreadObject*)rfbClientGetClientData(cl, 0);
t->networkStatus(statuscode);
}
void ControllerThread::run() {
int fd;
fd = ConnectToRFBServer(m_view->host().latin1(), m_view->port());
if (fd < 0) {
if (fd == -(int)INIT_NO_SERVER)
sendFatalError(ERROR_NO_SERVER);
else if (fd == -(int)INIT_NAME_RESOLUTION_FAILURE)
sendFatalError(ERROR_NAME);
else
sendFatalError(ERROR_CONNECTION);
return;
extern void output(const char *format, ...)
{
va_list args;
va_start(args, format);
TQString message;
message.vsprintf(format, args);
va_end(args);
kdDebug(5011) << message.local8Bit();
if (message.contains("Could not open")) {
kdDebug(5011) << "Server not found!" << endl;
}
if (m_quitFlag) {
changeStatus(REMOTE_VIEW_DISCONNECTED);
return;
if (message.contains("VNC authentication succeeded")) {
kdDebug(5011) << "Password OK" << endl;
}
}
changeStatus(REMOTE_VIEW_AUTHENTICATING);
ControllerThreadObject::ControllerThreadObject(KVncView *v, volatile bool &quitFlag) :
cl(0L),
m_view(v),
m_status(REMOTE_VIEW_CONNECTING),
m_quitFlag(quitFlag),
m_scaling(false),
m_scalingWidth(-1),
m_scalingHeight(-1),
m_resizeEntireFrame(false)
{
TQMutexLocker locker(&mutex);
enum InitStatus s = InitialiseRFBConnection();
if (s != INIT_OK) {
if (s == INIT_CONNECTION_FAILED)
sendFatalError(ERROR_IO);
else if (s == INIT_SERVER_BLOCKED)
sendFatalError(ERROR_SERVER_BLOCKED);
else if (s == INIT_PROTOCOL_FAILURE)
sendFatalError(ERROR_PROTOCOL);
else if (s == INIT_AUTHENTICATION_FAILED)
sendFatalError(ERROR_AUTHENTICATION);
else if (s == INIT_ABORTED)
changeStatus(REMOTE_VIEW_DISCONNECTED);
else
sendFatalError(ERROR_INTERNAL);
return;
}
cl = rfbGetClient(8, 3, 4);
}
TQApplication::postEvent(m_view,
new ScreenResizeEvent(si.framebufferWidth,
si.framebufferHeight));
m_wthread.queueUpdateRequest(TQRegion(TQRect(0,0,si.framebufferWidth,
si.framebufferHeight)));
ControllerThreadObject::~ControllerThreadObject() {
TQMutexLocker locker(&mutex);
TQApplication::postEvent(m_view, new DesktopInitEvent());
while ((!m_quitFlag) && (!m_desktopInitialized))
m_waiter.wait(1000);
rfbClientCleanup(cl);
}
if (m_quitFlag) {
changeStatus(REMOTE_VIEW_DISCONNECTED);
return;
}
void ControllerThreadObject::changeStatus(RemoteViewStatus s) {
m_status = s;
TQApplication::postEvent(m_view, new StatusChangeEvent(s));
}
changeStatus(REMOTE_VIEW_PREPARING);
void ControllerThreadObject::sendFatalError(ErrorCode s) {
m_quitFlag = true;
TQApplication::postEvent(m_view, new FatalErrorEvent(s));
}
if (!SetFormatAndEncodings()) {
sendFatalError(ERROR_INTERNAL);
return;
}
void ControllerThreadObject::queueDrawRegion(int x, int y, int w, int h) {
if (m_scaling) {
// Rescale desktop
changeStatus(REMOTE_VIEW_CONNECTED);
int new_x;
int new_y;
int new_w;
int new_h;
m_wthread.start();
mutex.lock();
while (!m_quitFlag) {
if ((!HandleRFBServerMessage()) && (!m_quitFlag)) {
sendFatalError(ERROR_IO);
return;
}
}
if (m_resizeEntireFrame) {
m_scaledImage.create(m_scalingWidth, m_scalingHeight, 32);
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
m_wthread.kick();
}
new_x = 0;
new_y = 0;
new_w = m_scalingWidth;
new_h = m_scalingHeight;
enum RemoteViewStatus ControllerThread::status() {
return m_status;
}
TQImage scaledBlock = m_image.smoothScale(new_w, new_h);
bitBlt(&m_scaledImage, new_x, new_y, &scaledBlock, 0, 0, new_w, new_h);
m_resizeEntireFrame = false;
}
else {
// Extend redraw boundaries to avoid pixelation artifacts due to rounding errors
x = x - round((2.0 * m_image.width()) / m_scalingWidth);
y = y - round((2.0 * m_image.height()) / m_scalingHeight);
w = w + round((4.0 * m_image.width()) / m_scalingWidth);
h = h + round((4.0 * m_image.height()) / m_scalingHeight);
if (x < 0) {
x = 0;
}
if (y < 0) {
y = 0;
}
if (w > m_image.width()) {
w = m_image.width();
}
if (h > m_image.height()) {
h = m_image.height();
}
new_x = round((x * m_scalingWidth) / m_image.width());
new_y = round((y * m_scalingHeight) / m_image.height());
new_w = round((w * m_scalingWidth) / m_image.width());
new_h = round((h * m_scalingHeight) / m_image.height());
TQImage scaledBlock(m_scalingWidth, m_scalingHeight, 32);
pnmscale_fractional(m_image, scaledBlock, new_x, new_y, new_w, new_h);
bitBlt(&m_scaledImage, new_x, new_y, &scaledBlock, new_x, new_y, new_w, new_h);
}
mutex.unlock();
static WriterThread *writerThread;
void queueIncrementalUpdateRequest() {
writerThread->queueIncrementalUpdateRequest();
DrawScreenRegion(new_x, new_y, new_w, new_h);
}
else {
DrawScreenRegion(x, y, w, h);
}
}
void announceIncrementalUpdateRequest() {
writerThread->announceIncrementalUpdateRequest();
void ControllerThreadObject::setImage(const TQImage &img) {
TQMutexLocker locker(&mutex);
m_image = img;
}
const TQImage ControllerThreadObject::image(int x, int y, int w, int h) {
TQMutexLocker locker(&mutex);
WriterThread::WriterThread(KVncView *v, volatile bool &quitFlag) :
m_quitFlag(quitFlag),
m_view(v),
m_lastIncrUpdatePostponed(false),
m_incrementalUpdateRQ(false),
m_incrementalUpdateAnnounced(false),
m_mouseEventNum(0),
m_keyEventNum(0),
m_clientCut(TQString())
{
writerThread = this;
m_lastIncrUpdate.start();
if (m_scaling) {
return m_scaledImage.copy(x, y, w, h);
}
else {
return m_image.copy(x, y, w, h);
}
}
bool WriterThread::sendIncrementalUpdateRequest() {
m_lastIncrUpdate.restart();
return SendIncrementalFramebufferUpdateRequest();
}
void ControllerThreadObject::setScaling(int w, int h) {
bool scale;
bool WriterThread::sendUpdateRequest(const TQRegion &region) {
TQMemArray<TQRect> r = region.rects();
for (unsigned int i = 0; i < r.size(); i++)
if (!SendFramebufferUpdateRequest(r[i].x(),
r[i].y(),
r[i].width(),
r[i].height(), False))
return false;
return true;
}
if (w <= 0) {
scale = false;
}
else {
scale = true;
}
bool WriterThread::sendInputEvents(const TQValueList<InputEvent> &events) {
TQValueList<InputEvent>::const_iterator it = events.begin();
while (it != events.end()) {
if ((*it).type == KeyEventType) {
if (!SendKeyEvent((*it).e.k.k, (*it).e.k.down ? True : False))
return false;
}
else
if (!SendPointerEvent((*it).e.m.x, (*it).e.m.y, (*it).e.m.buttons))
return false;
it++;
if ((m_scalingWidth != w) || (m_scalingHeight = h) || (m_scaling != scale)) {
m_resizeEntireFrame = true;
}
return true;
}
void WriterThread::queueIncrementalUpdateRequest() {
m_lock.lock();
m_incrementalUpdateRQ = true;
m_waiter.wakeAll();
m_lock.unlock();
m_scaling = scale;
m_scalingWidth = w;
m_scalingHeight = h;
}
void WriterThread::announceIncrementalUpdateRequest() {
m_lock.lock();
m_incrementalUpdateAnnounced = true;
m_lock.unlock();
}
void ControllerThreadObject::run() {
mutex.lock();
rfbClientLog = output;
rfbClientErr = output;
cl->MallocFrameBuffer = newclient;
cl->canHandleNewFBSize = true;
cl->GetPassword = passwd;
cl->AuthenticationResults = authresults;
cl->NetworkStatus = networkstat;
cl->GotFrameBufferUpdate = updatefb;
rfbClientSetClientData(cl, 0, this);
void WriterThread::queueUpdateRequest(const TQRegion &r) {
m_lock.lock();
m_updateRegionRQ += r;
m_waiter.wakeAll();
m_lock.unlock();
}
// make a copy of the host string...
char *host = (char*) malloc(m_view->host().length());
strcpy(host, m_view->host().ascii());
void WriterThread::queueMouseEvent(int x, int y, int buttonMask) {
InputEvent e;
e.type = MouseEventType;
e.e.m.x = x;
e.e.m.y = y;
e.e.m.buttons = buttonMask;
m_lock.lock();
if (m_mouseEventNum > 0) {
if ((e.e.m.x == m_lastMouseEvent.x) &&
(e.e.m.y == m_lastMouseEvent.y) &&
(e.e.m.buttons == m_lastMouseEvent.buttons)) {
m_lock.unlock();
return;
}
if (m_mouseEventNum >= MOUSEPRESS_QUEUE_SIZE) {
m_lock.unlock();
cl->serverHost = host;
int port = m_view->port();
if(port >= 0 && port < 100) // the user most likely used the short form (e.g. :1)
port += 5900;
cl->serverPort = port;
mutex.unlock();
if(!rfbInitClient(cl, 0, 0)) {
sendFatalError(ERROR_INTERNAL);
// Terminate thread
TQThread::exit();
return;
}
TQApplication::postEvent(m_view,
new ScreenResizeEvent(cl->width,
cl->height));
changeStatus(REMOTE_VIEW_CONNECTED);
while (!m_quitFlag) {
int i = WaitForMessage(cl, 500);
if (i < 0) {
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
// Terminate thread
TQThread::exit();
return;
}
if ((m_lastMouseEvent.buttons == buttonMask) &&
(m_mouseEventNum >= MOUSEMOVE_QUEUE_SIZE)) {
m_lock.unlock();
return;
if (i) {
if(!HandleRFBServerMessage(cl)) {
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
// Terminate thread
TQThread::exit();
return;
}
}
}
m_mouseEventNum++;
m_lastMouseEvent = e.e.m;
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
m_inputEvents.push_back(e);
m_waiter.wakeAll();
m_lock.unlock();
// Terminate thread
TQThread::exit();
}
void WriterThread::queueKeyEvent(unsigned int k, bool down) {
InputEvent e;
e.type = KeyEventType;
e.e.k.k = k;
e.e.k.down = down;
m_lock.lock();
if (m_keyEventNum >= KEY_QUEUE_SIZE) {
m_lock.unlock();
return;
void ControllerThreadObject::authenticationResults(int resultCode) {
if (resultCode == rfbVncAuthOK) {
changeStatus(REMOTE_VIEW_PREPARING);
}
else {
sendFatalError(ERROR_AUTHENTICATION);
m_keyEventNum++;
m_inputEvents.push_back(e);
m_waiter.wakeAll();
m_lock.unlock();
// Terminate thread
TQThread::exit();
}
}
void WriterThread::queueClientCut(const TQString &text) {
m_lock.lock();
m_clientCut = text;
void ControllerThreadObject::networkStatus(int statusCode) {
if (statusCode == rfbNetworkConnectionSuccess) {
// Stage 1 OK...
changeStatus(REMOTE_VIEW_AUTHENTICATING);
}
else if (statusCode == rfbNetworkRFBConnectionSuccess) {
// Stage 2 OK!
}
else {
if (statusCode == rfbNetworkConnectionClosed) {
sendFatalError(ERROR_CONNECTION);
}
else if (statusCode == rfbNetworkConnectionFailed) {
sendFatalError(ERROR_CONNECTION);
}
else if (statusCode == rfbNetworkNameResolutionFailed) {
sendFatalError(ERROR_NAME);
}
else if (statusCode == rfbNetworkRFBServerNotValid) {
sendFatalError(ERROR_IO);
}
else if (statusCode == rfbNetworkRFBProtocolFailure) {
sendFatalError(ERROR_PROTOCOL);
}
// Terminate thread
TQThread::exit();
}
}
m_waiter.wakeAll();
m_lock.unlock();
enum RemoteViewStatus ControllerThreadObject::status() {
return m_status;
}
void WriterThread::kick() {
m_waiter.wakeAll();
void ControllerThreadObject::queueMouseEvent(int x, int y, int buttonMask) {
SendPointerEvent(cl, x, y, buttonMask);
}
void WriterThread::run() {
bool incrementalUpdateRQ = false;
bool incrementalUpdateAnnounced = false;
TQRegion updateRegionRQ;
TQValueList<InputEvent> inputEvents;
TQString clientCut;
while (!m_quitFlag) {
m_lock.lock();
incrementalUpdateRQ = m_incrementalUpdateRQ;
incrementalUpdateAnnounced = m_incrementalUpdateAnnounced;
updateRegionRQ = m_updateRegionRQ;
inputEvents = m_inputEvents;
clientCut = m_clientCut;
if ((!incrementalUpdateRQ) &&
(updateRegionRQ.isNull()) &&
(inputEvents.size() == 0) &&
(clientCut.isNull())) {
if (!m_waiter.wait(&m_lock,
m_lastIncrUpdatePostponed ?
POSTPONED_INCRRQ_WAIT_PERIOD : MAXIMUM_WAIT_PERIOD))
m_incrementalUpdateRQ = true;
m_lock.unlock();
}
else {
m_incrementalUpdateRQ = false;
m_incrementalUpdateAnnounced = false;
m_updateRegionRQ = TQRegion();
m_inputEvents.clear();
m_keyEventNum = 0;
m_mouseEventNum = 0;
m_clientCut = TQString();
m_lock.unlock();
// always send incremental update, unless
// a) a framebuffer update is done ATM and will do the request later, or
// b) the last unrequested update has been done less than 0.1s ago
//
// if the update has not been done because of b, postpone it.
if (incrementalUpdateRQ || !incrementalUpdateAnnounced) {
bool sendUpdate;
if (incrementalUpdateRQ) {
sendUpdate = true;
m_lastIncrUpdatePostponed = false;
}
else {
if (m_lastIncrUpdate.elapsed() < 100) {
sendUpdate = false;
m_lastIncrUpdatePostponed = true;
}
else {
sendUpdate = true;
m_lastIncrUpdatePostponed = false;
}
}
if (sendUpdate)
if (!sendIncrementalUpdateRequest()) {
sendFatalError(ERROR_IO);
break;
}
}
else
m_lastIncrUpdatePostponed = false;
if (!updateRegionRQ.isNull())
if (!sendUpdateRequest(updateRegionRQ)) {
sendFatalError(ERROR_IO);
break;
}
if (inputEvents.size() != 0)
if (!sendInputEvents(inputEvents)) {
sendFatalError(ERROR_IO);
break;
}
if (!clientCut.isNull()) {
TQCString cutTextUtf8(clientCut.utf8());
if (!SendClientCutText(cutTextUtf8.data(),
(int)cutTextUtf8.length())) {
sendFatalError(ERROR_IO);
break;
}
}
}
}
m_quitFlag = true;
void ControllerThreadObject::queueKeyEvent(unsigned int k, bool down) {
SendKeyEvent(cl, k, down);
}
void WriterThread::sendFatalError(ErrorCode s) {
m_quitFlag = true;
TQApplication::postEvent(m_view, new FatalErrorEvent(s));
void ControllerThreadObject::queueClientCut(const TQString &text) {
SendClientCutText(cl, (char*)text.ascii(), text.length());
}
#include "threads.moc"

@ -2,7 +2,8 @@
threads.h - threads for kvncview
-------------------
begin : Thu May 09 16:01:42 CET 2002
copyright : (C) 2002 by Tim Jansen
copyright : (C) 2015 Timothy Pearson <kb9vqf@pearsoncomputing.net>
(C) 2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
@ -26,11 +27,15 @@
#include <tqevent.h>
#include <tqvaluelist.h>
#include <tqdatetime.h>
#include <tqimage.h>
#include <stdlib.h>
#include "events.h"
#include "vnctypes.h"
extern "C" {
#include <rfb/rfbclient.h>
}
class KVncView;
@ -57,68 +62,51 @@ struct InputEvent {
} e;
};
class ControllerThreadObject : public TQObject {
Q_OBJECT
class WriterThread : public TQThread {
private:
TQMutex m_lock;
TQWaitCondition m_waiter;
volatile bool &m_quitFlag;
KVncView *m_view;
public:
ControllerThreadObject(KVncView *v, volatile bool &quitFlag);
~ControllerThreadObject();
TQTime m_lastIncrUpdate; // start()ed when a incr update is sent
bool m_lastIncrUpdatePostponed;
enum RemoteViewStatus status();
// all things that can be send follow:
bool m_incrementalUpdateRQ; // for sending an incremental request
bool m_incrementalUpdateAnnounced; // set when a RQ will come soon
TQRegion m_updateRegionRQ; // for sending updates, null if it is done
TQValueList<InputEvent> m_inputEvents; // list of unsent input events
MouseEvent m_lastMouseEvent;
int m_mouseEventNum, m_keyEventNum;
TQString m_clientCut;
void setImage(const TQImage &img);
const TQImage image(int x = 0, int y = 0, int w = 0, int h = 0);
void authenticationResults(int resultCode);
void networkStatus(int statusCode);
void sendFatalError(ErrorCode s);
void setScaling(int w, int h);
void queueDrawRegion(int x, int y, int w, int h);
public:
WriterThread(KVncView *v, volatile bool &quitFlag);
rfbClient *cl;
void queueIncrementalUpdateRequest();
void announceIncrementalUpdateRequest();
void queueUpdateRequest(const TQRegion &r);
void queueMouseEvent(int x, int y, int buttonMask);
void queueKeyEvent(unsigned int k, bool down);
void queueClientCut(const TQString &text);
void kick();
public slots:
void run();
protected:
void run();
bool sendIncrementalUpdateRequest();
bool sendUpdateRequest(const TQRegion &r);
bool sendInputEvents(const TQValueList<InputEvent> &events);
};
class ControllerThread : public TQThread {
private:
KVncView *m_view;
enum RemoteViewStatus m_status;
WriterThread &m_wthread;
volatile bool &m_quitFlag;
volatile bool m_desktopInitialized;
TQWaitCondition m_waiter;
void changeStatus(RemoteViewStatus s);
void sendFatalError(ErrorCode s);
public:
ControllerThread(KVncView *v, WriterThread &wt, volatile bool &quitFlag);
enum RemoteViewStatus status();
void desktopInit();
void kick();
protected:
void run();
public:
void queueMouseEvent(int x, int y, int buttonMask);
void queueKeyEvent(unsigned int k, bool down);
void queueClientCut(const TQString &text);
private:
KVncView *m_view;
TQImage m_image;
TQImage m_scaledImage;
TQMutex mutex;
enum RemoteViewStatus m_status;
volatile bool &m_quitFlag;
bool m_scaling;
int m_scalingWidth;
int m_scalingHeight;
bool m_resizeEntireFrame;
// all things that can be send follow:
TQValueList<InputEvent> m_inputEvents; // list of unsent input events
void changeStatus(RemoteViewStatus s);
void sendFatalError(ErrorCode s);
};

@ -1,610 +0,0 @@
/*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* 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)
#define FillRectangleBPP CONCAT2E(FillRectangle,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
/* Type declarations */
typedef void (*filterPtrBPP)(int, CARDBPP *);
/* 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 numRows, CARDBPP *destBuffer);
static void FilterPaletteBPP (int numRows, CARDBPP *destBuffer);
static void FilterGradientBPP (int numRows, CARDBPP *destBuffer);
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;
char *buffer2;
int err, stream_id, compressedLen, bitsPixel;
int bufferSize, rowSize, numRows, portionLen, rowsProcessed, extraBytes;
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;
}
/* 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
LockFramebuffer();
FillRectangleBPP(fill_colour, rx, ry, rw, rh);
UnlockFramebuffer();
SyncScreenRegion(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;
if (rh * rowSize < TIGHT_MIN_TO_COMPRESS) {
if (!ReadFromRFBServer((char*)buffer, rh * rowSize))
return False;
buffer2 = &buffer[TIGHT_MIN_TO_COMPRESS * 4];
filterFn(rh, (CARDBPP *)buffer2);
CopyDataToScreen(buffer2, 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. */
bufferSize = BUFFER_SIZE * bitsPixel / (bitsPixel + BPP) & 0xFFFFFFFC;
buffer2 = &buffer[bufferSize];
if (rowSize > bufferSize) {
/* Should be impossible when BUFFER_SIZE >= 16384 */
fprintf(stderr, "Internal error: incorrect buffer size.\n");
return False;
}
rowsProcessed = 0;
extraBytes = 0;
while (compressedLen > 0) {
if (compressedLen > ZLIB_BUFFER_SIZE)
portionLen = ZLIB_BUFFER_SIZE;
else
portionLen = compressedLen;
if (!ReadFromRFBServer((char*)zlib_buffer, portionLen))
return False;
compressedLen -= portionLen;
zs->next_in = (Bytef *)zlib_buffer;
zs->avail_in = portionLen;
do {
zs->next_out = (Bytef *)&buffer[extraBytes];
zs->avail_out = bufferSize - extraBytes;
err = inflate(zs, Z_SYNC_FLUSH);
if (err == Z_BUF_ERROR) /* Input exhausted -- no problem. */
break;
if (err != Z_OK && err != Z_STREAM_END) {
if (zs->msg != NULL) {
fprintf(stderr, "Inflate error: %s.\n", zs->msg);
} else {
fprintf(stderr, "Inflate error: %d.\n", err);
}
return False;
}
numRows = (bufferSize - zs->avail_out) / rowSize;
filterFn(numRows, (CARDBPP *)buffer2);
extraBytes = bufferSize - zs->avail_out - numRows * rowSize;
if (extraBytes > 0)
memcpy(buffer, &buffer[numRows * rowSize], extraBytes);
CopyDataToScreen(buffer2, rx, ry + rowsProcessed, rw, numRows);
rowsProcessed += numRows;
}
while (zs->avail_out == 0);
}
if (rowsProcessed != rh) {
fprintf(stderr, "Incorrect number of scan lines after decompression.\n");
return False;
}
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 numRows, CARDBPP *dst)
{
#if BPP == 32
int x, y;
if (cutZeros) {
for (y = 0; y < numRows; y++) {
for (x = 0; x < rectWidth; x++) {
dst[y*rectWidth+x] =
RGB24_TO_PIXEL32(buffer[(y*rectWidth+x)*3],
buffer[(y*rectWidth+x)*3+1],
buffer[(y*rectWidth+x)*3+2]);
}
}
return;
}
#endif
memcpy (dst, buffer, numRows * 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 numRows, CARD32 *dst)
{
int x, y, c;
CARD8 thisRow[2048*3];
CARD8 pix[3];
int est[3];
for (y = 0; y < numRows; y++) {
/* First pixel in a row */
for (c = 0; c < 3; c++) {
pix[c] = tightPrevRow[c] + buffer[y*rectWidth*3+c];
thisRow[c] = pix[c];
}
dst[y*rectWidth] = 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*rectWidth+x] = RGB24_TO_PIXEL32(pix[0], pix[1], pix[2]);
}
memcpy(tightPrevRow, thisRow, rectWidth * 3);
}
}
#endif
static void
FilterGradientBPP (int numRows, CARDBPP *dst)
{
int x, y, c;
CARDBPP *src = (CARDBPP *)buffer;
CARD16 *thatRow = (CARD16 *)tightPrevRow;
CARD16 thisRow[2048*3];
CARD16 pix[3];
CARD16 max[3];
int shift[3];
int est[3];
#if BPP == 32
if (cutZeros) {
FilterGradient24(numRows, dst);
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*rectWidth] = 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*rectWidth+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 numRows, CARDBPP *dst)
{
int x, y, b, w;
CARD8 *src = (CARD8 *)buffer;
CARDBPP *palette = (CARDBPP *)tightPalette;
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*rectWidth+x*8+7-b] = palette[src[y*w+x] >> b & 1];
}
for (b = 7; b >= 8 - rectWidth % 8; b--) {
dst[y*rectWidth+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*rectWidth+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)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
int compressedLen;
CARD8 *compressedData;
CARDBPP *pixelPtr;
JSAMPROW rowPointer[1];
int dx, dy;
compressedLen = (int)ReadCompactLen();
if (compressedLen <= 0) {
fprintf(stderr, "Incorrect data received from the server.\n");
return False;
}
if (compressedLen > MAX_JPEG_SIZE) {
fprintf(stderr, "To large data announced by the server.\n");
return False;
}
compressedData = malloc(compressedLen);
if (compressedData == NULL) {
fprintf(stderr, "Memory allocation error.\n");
return False;
}
if (!ReadFromRFBServer((char*)compressedData, compressedLen)) {
free(compressedData);
return False;
}
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
JpegSetSrcManager(&cinfo, compressedData, compressedLen);
jpeg_read_header(&cinfo, TRUE);
cinfo.out_color_space = JCS_RGB;
jpeg_start_decompress(&cinfo);
if (cinfo.output_width != w || cinfo.output_height != h ||
cinfo.output_components != 3) {
fprintf(stderr, "Tight Encoding: Wrong JPEG data received.\n");
jpeg_destroy_decompress(&cinfo);
free(compressedData);
return False;
}
rowPointer[0] = (JSAMPROW)buffer;
dy = 0;
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, rowPointer, 1);
if (jpegError) {
break;
}
pixelPtr = (CARDBPP *)&buffer[BUFFER_SIZE / 2];
for (dx = 0; dx < w; dx++) {
*pixelPtr++ =
RGB24_TO_PIXEL(BPP, buffer[dx*3], buffer[dx*3+1], buffer[dx*3+2]);
}
CopyDataToScreen(&buffer[BUFFER_SIZE / 2], x, y + dy, w, 1);
dy++;
}
if (!jpegError)
jpeg_finish_decompress(&cinfo);
jpeg_destroy_decompress(&cinfo);
free(compressedData);
return !jpegError;
}
#endif

@ -1,161 +0,0 @@
/*
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* vncauth.c - Functions for VNC password management and authentication.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <vncauth.h>
#include <d3des.h>
/*
* We use a fixed key to store passwords, since we assume that our local
* file system is secure but nonetheless don't want to store passwords
* as plaintext.
*/
unsigned char fixedkey[8] = {23,82,107,6,35,78,88,7};
/*
* Encrypt a password and store it in a file. Returns 0 if successful,
* 1 if the file could not be written.
*/
int
vncEncryptAndStorePasswd(char *passwd, char *fname)
{
FILE *fp;
int i;
unsigned char encryptedPasswd[8];
if ((fp = fopen(fname,"w")) == NULL) return 1;
chmod(fname, S_IRUSR|S_IWUSR);
/* pad password with nulls */
for (i = 0; i < 8; i++) {
if (i < strlen(passwd)) {
encryptedPasswd[i] = passwd[i];
} else {
encryptedPasswd[i] = 0;
}
}
/* Do encryption in-place - this way we overwrite our copy of the plaintext
password */
deskey(fixedkey, EN0);
des(encryptedPasswd, encryptedPasswd);
for (i = 0; i < 8; i++) {
putc(encryptedPasswd[i], fp);
}
fclose(fp);
return 0;
}
/*
* Decrypt a password from a file. Returns a pointer to a newly allocated
* string containing the password or a null pointer if the password could
* not be retrieved for some reason.
*/
char *
vncDecryptPasswdFromFile(char *fname)
{
FILE *fp;
int i, ch;
unsigned char *passwd = (unsigned char *)malloc(9);
if ((fp = fopen(fname,"r")) == NULL) return NULL;
for (i = 0; i < 8; i++) {
ch = getc(fp);
if (ch == EOF) {
fclose(fp);
return NULL;
}
passwd[i] = ch;
}
fclose(fp);
deskey(fixedkey, DE1);
des(passwd, passwd);
passwd[8] = 0;
return (char *)passwd;
}
/*
* Generate CHALLENGESIZE random bytes for use in challenge-response
* authentication.
*/
void
vncRandomBytes(unsigned char *bytes)
{
int i;
unsigned int seed = (unsigned int) time(0);
srandom(seed);
for (i = 0; i < CHALLENGESIZE; i++) {
bytes[i] = (unsigned char)(random() & 255);
}
}
/*
* Encrypt CHALLENGESIZE bytes in memory using a password.
*/
void
vncEncryptBytes(unsigned char *bytes, char *passwd)
{
unsigned char key[8];
int i;
/* key is simply password padded with nulls */
for (i = 0; i < 8; i++) {
if (i < strlen(passwd)) {
key[i] = passwd[i];
} else {
key[i] = 0;
}
}
deskey(key, EN0);
for (i = 0; i < CHALLENGESIZE; i += 8) {
des(bytes+i, bytes+i);
}
}

@ -1,30 +0,0 @@
/*
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* vncauth.h - describes the functions provided by the vncauth library.
*/
#define MAXPWLEN 8
#define CHALLENGESIZE 16
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);

@ -1,73 +0,0 @@
/*
* Copyright (C) 2002 Tim Jansen. All Rights Reserved.
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
#ifndef VNCTYPES_H
#define VNCTYPES_H
#if(defined __cplusplus)
extern "C"
{
#endif
#include <X11/Xmd.h>
typedef struct {
int shareDesktop; /* bool */
int viewOnly; /* bool */
const char* encodingsString;
int useBGR233; /* bool */
int nColours;
int useSharedColours; /* bool */
int requestedDepth;
int rawDelay;
int copyRectDelay;
int debug; /* bool */
int compressLevel;
int qualityLevel;
int dotCursor; /* bool */
} AppData;
enum InitStatus {
INIT_OK = 0,
INIT_NAME_RESOLUTION_FAILURE = 1,
INIT_PROTOCOL_FAILURE = 2,
INIT_CONNECTION_FAILED = 3,
INIT_AUTHENTICATION_FAILED = 4,
INIT_NO_SERVER = 5,
INIT_SERVER_BLOCKED = 6,
INIT_ABORTED = 7
};
#if(defined __cplusplus)
}
#endif
#endif

@ -36,28 +36,14 @@
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xmu/StdSel.h>
#include "vnctypes.h"
#if(defined __cplusplus)
extern "C"
{
#endif
#include "rfbproto.h"
extern int endianTest;
#define Swap16IfLE(s) \
(*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
#define Swap32IfLE(l) \
(*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \
(((l) & 0x00ff0000) >> 8) | \
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
#define MAX_ENCODINGS 20
#include "rfb/rfbclient.h"
#include "rfb/rfbproto.h"
/** kvncview.cpp **/
@ -78,108 +64,6 @@ extern void beep();
extern void newServerCut(char *bytes, int len);
extern void postMouseEvent(int x, int y, int buttonMask);
/** threads.cpp **/
extern void queueIncrementalUpdateRequest();
extern void announceIncrementalUpdateRequest();
/* colour.c */
extern unsigned long BGR233ToPixel[];
extern Colormap cmap;
extern Visual *vis;
extern unsigned int visdepth, visbpp;
extern void SetVisualAndCmap(void);
/* desktop.c */
extern Widget form, viewport, desktop;
extern GC gc;
extern GC srcGC, dstGC;
extern Dimension dpyWidth, dpyHeight;
extern void DesktopInit(Window win);
extern void ToplevelInit(void);
extern void SendRFBEvent(XEvent *event, String *params, Cardinal *num_params);
extern void CopyDataToScreen(char *buf, int x, int y, int width, int height);
extern void CopyDataFromScreen(char *buf, int x, int y, int width, int height);
extern void FillRectangle8(CARD8, int x, int y, int width, int height);
extern void FillRectangle16(CARD16, int x, int y, int width, int height);
extern void FillRectangle32(CARD32, int x, int y, int width, int height);
extern void CopyArea(int srcX, int srcY, int width, int height, int x, int y);
extern void SyncScreenRegion(int x, int y, int width, int height);
extern void SyncScreenRegionX11Thread(int x, int y, int width, int height);
extern void drawCursor(void);
extern void DrawCursorX11Thread(int x, int y);
extern void undrawCursor(void);
extern void getBoundingRectCursor(int cx, int cy, int _imageIndex,
int *x, int *y, int *w, int *h);
extern int rectsIntersect(int x, int y, int w, int h,
int x2, int y2, int w2, int h2);
extern int rectContains(int outX, int outY, int outW, int outH,
int inX, int inY, int inW, int inH);
extern void rectsJoin(int *nx1, int *ny1, int *nw1, int *nh1,
int x2, int y2, int w2, int h2);
extern void DrawZoomedScreenRegionX11Thread(Window win, int zwidth,
int zheight,
int x, int y,
int width, int height);
extern void DrawScreenRegionX11Thread(Window win, int x, int y,
int width, int height);
extern void Cleanup(void);
extern XImage *CreateShmZoomImage(void);
extern XImage *CreateShmImage(void);
extern void ShmCleanup(void);
extern void freeDesktopResources(void);
/* rfbproto.c */
extern int rfbsock;
extern Bool canUseCoRRE;
extern Bool canUseHextile;
extern char *desktopName;
extern rfbPixelFormat myFormat;
extern rfbServerInitMsg si;
extern int cursorX, cursorY;
extern int imageIndex;
typedef struct {
int set;
int w, h;
int hotX, hotY;
int len;
char *image;
} PointerImage;
extern PointerImage pointerImages[];
extern int ConnectToRFBServer(const char *hostname, int port);
extern enum InitStatus InitialiseRFBConnection(void);
extern Bool SetFormatAndEncodings(void);
extern Bool SendIncrementalFramebufferUpdateRequest(void);
extern Bool SendFramebufferUpdateRequest(int x, int y, int w, int h,
Bool incremental);
extern Bool SendPointerEvent(int x, int y, int buttonMask);
extern Bool SendKeyEvent(CARD32 key, Bool down);
extern Bool SendClientCutText(const char *str, int len);
extern Bool HandleRFBServerMessage(void);
extern void PrintPixelFormat(rfbPixelFormat *format);
extern void freeRFBProtoResources(void);
extern void freeResources(void);
/* sockets.c */
extern Bool errorMessageOnReadFailure;
extern Bool ReadFromRFBServer(char *out, unsigned int n);
extern Bool WriteExact(int sock, const char *buf, int n);
extern int ConnectToTcpAddr(unsigned int host, int port);
extern int StringToIPAddr(const char *str, unsigned int *addr);
extern void freeSocketsResources(void);
#if(defined __cplusplus)
}
#endif

@ -1,157 +0,0 @@
/*
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
/*
* zlib.c - handle zlib encoding.
*
* This file shouldn't be compiled directly. It is included multiple times by
* rfbproto.c, each time with a different definition of the macro BPP. For
* each value of BPP, this file defines a function which handles an zlib
* encoded rectangle with BPP bits per pixel.
*/
#define HandleZlibBPP CONCAT2E(HandleZlib,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
static Bool
HandleZlibBPP (int rx, int ry, int rw, int rh)
{
rfbZlibHeader hdr;
int remaining;
int inflateResult;
int toRead;
/* First make sure we have a large enough raw buffer to hold the
* decompressed data. In practice, with a fixed BPP, fixed frame
* buffer size and the first update containing the entire frame
* buffer, this buffer allocation should only happen once, on the
* first update.
*/
if ( raw_buffer_size < (( rw * rh ) * ( BPP / 8 ))) {
if ( raw_buffer != NULL ) {
free( raw_buffer );
}
raw_buffer_size = (( rw * rh ) * ( BPP / 8 ));
raw_buffer = (char*) malloc( raw_buffer_size );
}
if (!ReadFromRFBServer((char *)&hdr, sz_rfbZlibHeader))
return False;
remaining = Swap32IfLE(hdr.nBytes);
/* Need to initialize the decompressor state. */
decompStream.next_in = ( Bytef * )buffer;
decompStream.avail_in = 0;
decompStream.next_out = ( Bytef * )raw_buffer;
decompStream.avail_out = raw_buffer_size;
decompStream.data_type = Z_BINARY;
/* Initialize the decompression stream structures on the first invocation. */
if ( decompStreamInited == False ) {
inflateResult = inflateInit( &decompStream );
if ( inflateResult != Z_OK ) {
fprintf(stderr,
"inflateInit returned error: %d, msg: %s\n",
inflateResult,
decompStream.msg);
return False;
}
decompStreamInited = True;
}
inflateResult = Z_OK;
/* Process buffer full of data until no more to process, or
* some type of inflater error, or Z_STREAM_END.
*/
while (( remaining > 0 ) &&
( inflateResult == Z_OK )) {
if ( remaining > BUFFER_SIZE ) {
toRead = BUFFER_SIZE;
}
else {
toRead = remaining;
}
/* Fill the buffer, obtaining data from the server. */
if (!ReadFromRFBServer(buffer,toRead))
return False;
decompStream.next_in = ( Bytef * )buffer;
decompStream.avail_in = toRead;
/* Need to uncompress buffer full. */
inflateResult = inflate( &decompStream, Z_SYNC_FLUSH );
/* We never supply a dictionary for compression. */
if ( inflateResult == Z_NEED_DICT ) {
fprintf(stderr,"zlib inflate needs a dictionary!\n");
return False;
}
if ( inflateResult < 0 ) {
fprintf(stderr,
"zlib inflate returned error: %d, msg: %s\n",
inflateResult,
decompStream.msg);
return False;
}
/* Result buffer allocated to be at least large enough. We should
* never run out of space!
*/
if (( decompStream.avail_in > 0 ) &&
( decompStream.avail_out <= 0 )) {
fprintf(stderr,"zlib inflate ran out of space!\n");
return False;
}
remaining -= toRead;
} /* while ( remaining > 0 ) */
if ( inflateResult == Z_OK ) {
/* Put the uncompressed contents of the update on the screen. */
CopyDataToScreen(raw_buffer, rx, ry, rw, rh);
}
else {
fprintf(stderr,
"zlib inflate returned error: %d, msg: %s\n",
inflateResult,
decompStream.msg);
return False;
}
return True;
}

@ -1 +1 @@
Subproject commit 366c7e7c2122cc4271a2dd65d270ac4175edd5e4
Subproject commit 1d8b3c0548782dcd7286fed6b31c17351c15bb50
Notiek ielāde…
Atcelt
Saglabāt