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 correctlypull/1/head
parent
8b8dfa9704
commit
3ddfecac5c
@ -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
|
||||
********************************************************************/
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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
|
@ -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
|
Loading…
Reference in New Issue