1
0
mirror of https://invent.kde.org/network/krfb synced 2024-07-05 09:28:35 +00:00

Sorry, committed my vnc client a little bit too early (and possibly at the wrong location)

svn path=/trunk/kdenetwork/krfb/; revision=156481
This commit is contained in:
Tim Jansen 2002-05-20 10:49:03 +00:00
parent d0df828c56
commit 6463941a18
29 changed files with 1 additions and 7116 deletions

View File

@ -1,4 +1,4 @@
SUBDIRS = client kinetd libvncserver krfb kcm_krfb
SUBDIRS = kinetd libvncserver krfb kcm_krfb
EXTRA_DIST = AUTHORS COPYING ChangeLog INSTALL README TODO NOTES \
ROADMAP DCOP-INTERFACE krfb.lsm

View File

@ -1,23 +0,0 @@
KDE_CXXFLAGS = $(USE_THREADS)
METASOURCES = AUTO
bin_PROGRAMS = krdc
krdc_SOURCES = main.cpp krdc.cpp kvncview.cpp threads.cpp \
colour.c cursor.c d3des.c desktop.c rfbproto.c sockets.c vncauth.c \
newconnectiondialog.ui passworddialog.ui
EXTRA_DIST = krdc.h kvncview.cpp vncviewer.h
krdc_LDADD = $(LIB_KDEUI) -ljpeg
krdc_LDFLAGS = $(all_libraries) $(KDE_RPATH)
lnkdir = $(kde_appsdir)/Internet
lnk_DATA = krdc.desktop
KDE_ICON = AUTO
INCLUDES= $(all_includes)
messages: rc.cpp
$(XGETTEXT) rc.cpp *.cpp *.cc -o $(podir)/krdc.pot

View File

@ -1,34 +0,0 @@
+ working viewing prototype
+ move logic ->kvncview widget
+ basic command line arguments
+ expose/redraw events
+ make event queues for sending events on demand
+ gentle wayto exit krdc worker thread
+ get performance comparable to xvncviewer
+ make scrollable
+ feedback from thread to widget
+ mouse input
+ keyboard input
+ create main window
+ add login gui
+ replace console password input
- advanced command line arguments
- better event-based error & disconnection handling
- fullscreen
- add fullscreen control panel (auto-hide+minimize+disable full)
- display connection status on canvas
-> release
- mouse wheel
- use pixmap only, dont paint directly on screen
-> write desktop.c function for 8,16,32 to fill rect
-> use CONCAT2E to replace func calls to xlib with desktop.c func
-> find out when to copy rect
- optional scaling if other desktop is too big
- add function to vncviewer code to de-allocate resources
- dont quit after failed connect attempt but allow re-try
- login with user's name+password?
- SSL/TLS?

View File

@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* 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, &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;
}

View File

@ -1,83 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* corre.c - handle CoRRE encoding.
*
* This file shouldn't be compiled directly. It is included multiple times by
* rfbproto.c, each time with a different definition of the macro BPP. For
* each value of BPP, this file defines a function which handles a CoRRE
* encoded rectangle with BPP bits per pixel.
*/
#define HandleCoRREBPP CONCAT2E(HandleCoRRE,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
static Bool
HandleCoRREBPP (int rx, int ry, int rw, int rh)
{
rfbRREHeader hdr;
XGCValues gcv;
int i;
CARDBPP pix;
CARD8 *ptr;
int x, y, w, h;
if (!ReadFromRFBServer((char *)&hdr, sz_rfbRREHeader))
return False;
hdr.nSubrects = Swap32IfLE(hdr.nSubrects);
if (!ReadFromRFBServer((char *)&pix, sizeof(pix)))
return False;
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
gcv.foreground = pix;
#endif
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
if (!ReadFromRFBServer(buffer, hdr.nSubrects * (4 + (BPP / 8))))
return False;
ptr = (CARD8 *)buffer;
for (i = 0; i < hdr.nSubrects; i++) {
pix = *(CARDBPP *)ptr;
ptr += BPP/8;
x = *ptr++;
y = *ptr++;
w = *ptr++;
h = *ptr++;
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
gcv.foreground = pix;
#endif
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx + x, ry + y, w, h);
}
return True;
}

View File

@ -1,431 +0,0 @@
/*
* Copyright (C) 2001 Const Kaplinsky. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* cursor.c - code to support cursor shape updates (XCursor, RichCursor).
*/
#include <vncviewer.h>
#define OPER_SAVE 0
#define OPER_RESTORE 1
/* Copied from Xvnc/lib/font/util/utilbitmap.c */
static unsigned char _reverse_byte[0x100] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
};
/* Data kept for HandleXCursor() function. */
static Bool prevXCursorSet = False;
static Cursor prevXCursor;
/* Data kept for RichCursor encoding support. */
static Bool prevRichCursorSet = False;
static Pixmap rcSavedArea;
static CARD8 *rcSource, *rcMask;
static int rcHotX, rcHotY, rcWidth, rcHeight;
static int rcCursorX = 0, rcCursorY = 0;
static int rcLockX, rcLockY, rcLockWidth, rcLockHeight;
static Bool rcCursorHidden, rcLockSet;
static Bool SoftCursorInLockedArea(void);
static void SoftCursorCopyArea(int oper);
static void SoftCursorDraw(void);
static void FreeCursors(Bool setDotCursor);
/*********************************************************************
* HandleXCursor(). XCursor encoding support code is concentrated in
* this function. XCursor shape updates are translated directly into X
* cursors and saved in the prevXCursor variable.
********************************************************************/
Bool HandleXCursor(int xhot, int yhot, int width, int height)
{
rfbXCursorColors colors;
size_t bytesPerRow, bytesData;
char *buf = NULL;
XColor bg, fg;
Drawable dr;
unsigned int wret = 0, hret = 0;
Pixmap source, mask;
Cursor cursor;
int i;
bytesPerRow = (width + 7) / 8;
bytesData = bytesPerRow * height;
dr = DefaultRootWindow(dpy);
if (width * height) {
if (!ReadFromRFBServer((char *)&colors, sz_rfbXCursorColors))
return False;
buf = malloc(bytesData * 2);
if (buf == NULL)
return False;
if (!ReadFromRFBServer(buf, bytesData * 2)) {
free(buf);
return False;
}
lockQt();
XQueryBestCursor(dpy, dr, width, height, &wret, &hret);
unlockQt();
}
if (width * height == 0 || wret < width || hret < height) {
/* Free resources, restore dot cursor. */
if (buf != NULL)
free(buf);
FreeCursors(True);
return True;
}
bg.red = (unsigned short)colors.backRed << 8 | colors.backRed;
bg.green = (unsigned short)colors.backGreen << 8 | colors.backGreen;
bg.blue = (unsigned short)colors.backBlue << 8 | colors.backBlue;
fg.red = (unsigned short)colors.foreRed << 8 | colors.foreRed;
fg.green = (unsigned short)colors.foreGreen << 8 | colors.foreGreen;
fg.blue = (unsigned short)colors.foreBlue << 8 | colors.foreBlue;
for (i = 0; i < bytesData * 2; i++)
buf[i] = (char)_reverse_byte[(int)buf[i] & 0xFF];
lockQt();
source = XCreateBitmapFromData(dpy, dr, buf, width, height);
mask = XCreateBitmapFromData(dpy, dr, &buf[bytesData], width, height);
cursor = XCreatePixmapCursor(dpy, source, mask, &fg, &bg, xhot, yhot);
XFreePixmap(dpy, source);
XFreePixmap(dpy, mask);
free(buf);
XDefineCursor(dpy, desktopWin, cursor);
FreeCursors(False);
prevXCursor = cursor;
prevXCursorSet = True;
unlockQt();
return True;
}
/*********************************************************************
* HandleRichCursor(). RichCursor shape updates support. This
* variation of cursor shape updates cannot be supported directly via
* Xlib cursors so we have to emulate cursor operating on the frame
* buffer (that is why we call it "software cursor").
********************************************************************/
Bool HandleRichCursor(int xhot, int yhot, int width, int height)
{
size_t bytesPerRow, bytesMaskData;
Drawable dr;
char *buf;
CARD8 *ptr;
int x, y, b;
bytesPerRow = (width + 7) / 8;
bytesMaskData = bytesPerRow * height;
dr = DefaultRootWindow(dpy);
FreeCursors(True);
if (width * height == 0)
return True;
/* Read cursor pixel data. */
rcSource = malloc(width * height * (myFormat.bitsPerPixel / 8));
if (rcSource == NULL)
return False;
if (!ReadFromRFBServer((char *)rcSource,
width * height * (myFormat.bitsPerPixel / 8))) {
free(rcSource);
return False;
}
/* Read and decode mask data. */
buf = malloc(bytesMaskData);
if (buf == NULL) {
free(rcSource);
return False;
}
if (!ReadFromRFBServer(buf, bytesMaskData)) {
free(rcSource);
free(buf);
return False;
}
rcMask = malloc(width * height);
if (rcMask == NULL) {
free(rcSource);
free(buf);
return False;
}
ptr = rcMask;
for (y = 0; y < height; y++) {
for (x = 0; x < width / 8; x++) {
for (b = 7; b >= 0; b--) {
*ptr++ = buf[y * bytesPerRow + x] >> b & 1;
}
}
for (b = 7; b > 7 - width % 8; b--) {
*ptr++ = buf[y * bytesPerRow + x] >> b & 1;
}
}
free(buf);
/* Set remaining data associated with cursor. */
dr = DefaultRootWindow(dpy);
lockQt();
rcSavedArea = XCreatePixmap(dpy, dr, width, height, visdepth);
unlockQt();
rcHotX = xhot;
rcHotY = yhot;
rcWidth = width;
rcHeight = height;
SoftCursorCopyArea(OPER_SAVE);
SoftCursorDraw();
rcCursorHidden = False;
rcLockSet = False;
prevRichCursorSet = True;
return True;
}
/*********************************************************************
* SoftCursorLockArea(). This function should be used to prevent
* collisions between simultaneous framebuffer update operations and
* cursor drawing operations caused by movements of pointing device.
* The parameters denote a rectangle where mouse cursor should not be
* drawn. Every next call to this function expands locked area so
* previous locks remain active.
********************************************************************/
void SoftCursorLockArea(int x, int y, int w, int h)
{
int newX, newY;
if (!prevRichCursorSet)
return;
if (!rcLockSet) {
rcLockX = x;
rcLockY = y;
rcLockWidth = w;
rcLockHeight = h;
rcLockSet = True;
} else {
newX = (x < rcLockX) ? x : rcLockX;
newY = (y < rcLockY) ? y : rcLockY;
rcLockWidth = (x + w > rcLockX + rcLockWidth) ?
(x + w - newX) : (rcLockX + rcLockWidth - newX);
rcLockHeight = (y + h > rcLockY + rcLockHeight) ?
(y + h - newY) : (rcLockY + rcLockHeight - newY);
rcLockX = newX;
rcLockY = newY;
}
if (!rcCursorHidden && SoftCursorInLockedArea()) {
SoftCursorCopyArea(OPER_RESTORE);
rcCursorHidden = True;
}
}
/*********************************************************************
* SoftCursorUnlockScreen(). This function discards all locks
* performed since previous SoftCursorUnlockScreen() call.
********************************************************************/
void SoftCursorUnlockScreen(void)
{
if (!prevRichCursorSet)
return;
if (rcCursorHidden) {
SoftCursorCopyArea(OPER_SAVE);
SoftCursorDraw();
rcCursorHidden = False;
}
rcLockSet = False;
}
/*********************************************************************
* SoftCursorMove(). Moves soft cursor in particular location. This
* function respects locking of screen areas so when the cursor is
* moved in the locked area, it becomes invisible until
* SoftCursorUnlock() functions is called.
********************************************************************/
void SoftCursorMove(int x, int y)
{
if (prevRichCursorSet && !rcCursorHidden) {
SoftCursorCopyArea(OPER_RESTORE);
rcCursorHidden = True;
}
rcCursorX = x;
rcCursorY = y;
if (prevRichCursorSet && !(rcLockSet && SoftCursorInLockedArea())) {
SoftCursorCopyArea(OPER_SAVE);
SoftCursorDraw();
rcCursorHidden = False;
}
}
/*********************************************************************
* Internal (static) low-level functions.
********************************************************************/
static Bool SoftCursorInLockedArea(void)
{
return (rcLockX < rcCursorX - rcHotX + rcWidth &&
rcLockY < rcCursorY - rcHotY + rcHeight &&
rcLockX + rcLockWidth > rcCursorX - rcHotX &&
rcLockY + rcLockHeight > rcCursorY - rcHotY);
}
static void SoftCursorCopyArea(int oper)
{
int x, y, w, h;
x = rcCursorX - rcHotX;
y = rcCursorY - rcHotY;
if (x >= si.framebufferWidth || y >= si.framebufferHeight)
return;
w = rcWidth;
h = rcHeight;
if (x < 0) {
w += x;
x = 0;
} else if (x + w > si.framebufferWidth) {
w = si.framebufferWidth - x;
}
if (y < 0) {
h += y;
y = 0;
} else if (y + h > si.framebufferHeight) {
h = si.framebufferHeight - y;
}
lockQt();
if (oper == OPER_SAVE) {
/* Save screen area in memory. */
ShmSync();
XCopyArea(dpy, desktopWin, rcSavedArea, gc, x, y, w, h, 0, 0);
} else {
/* Restore screen area. */
XCopyArea(dpy, rcSavedArea, desktopWin, gc, 0, 0, w, h, x, y);
}
unlockQt();
}
static void SoftCursorDraw(void)
{
int x, y, x0, y0;
int offset, bytesPerPixel;
char *pos;
bytesPerPixel = myFormat.bitsPerPixel / 8;
/* FIXME: Speed optimization is possible. */
for (y = 0; y < rcHeight; y++) {
y0 = rcCursorY - rcHotY + y;
if (y0 >= 0 && y0 < si.framebufferHeight) {
for (x = 0; x < rcWidth; x++) {
x0 = rcCursorX - rcHotX + x;
if (x0 >= 0 && x0 < si.framebufferWidth) {
offset = y * rcWidth + x;
if (rcMask[offset]) {
pos = (char *)&rcSource[offset * bytesPerPixel];
CopyDataToScreen(pos, x0, y0, 1, 1);
}
}
}
}
}
}
static void FreeCursors(Bool setDotCursor)
{
lockQt();
if (setDotCursor)
XDefineCursor(dpy, desktopWin, dotCursor);
if (prevXCursorSet) {
XFreeCursor(dpy, prevXCursor);
prevXCursorSet = False;
}
unlockQt();
if (prevRichCursorSet) {
SoftCursorCopyArea(OPER_RESTORE);
lockQt();
XFreePixmap(dpy, rcSavedArea);
free(rcSource);
free(rcMask);
prevRichCursorSet = False;
unlockQt();
}
}

View File

@ -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
**********************************************************************/

View File

@ -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
********************************************************************/

View File

@ -1,494 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*
* 03-05-2002 tim@tjansen.de: removed stuff for krdc, merged with shm.c
* and misc.c
*
*/
/*
* desktop.c - functions to deal with "desktop" window.
*/
#include <X11/Xlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#include "vncviewer.h"
static XShmSegmentInfo shminfo;
static Bool caughtShmError = False;
static Bool needShmCleanup = False;
GC gc;
GC srcGC, dstGC; /* used for debugging copyrect */
Window desktopWin;
Cursor dotCursor;
Dimension dpyWidth, dpyHeight;
static XImage *image = NULL;
Bool useShm = True;
static Cursor CreateDotCursor(void);
static void CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width,int height);
void
DesktopInit(Window win)
{
XGCValues gcv;
XSetWindowAttributes attr;
/* image = CreateShmImage();*/
if (!image) {
useShm = False;
image = XCreateImage(dpy, vis, visdepth, ZPixmap, 0, NULL,
si.framebufferWidth, si.framebufferHeight,
BitmapPad(dpy), 0);
image->data = malloc(image->bytes_per_line * image->height);
if (!image->data) {
fprintf(stderr,"malloc failed\n");
exit(1);
}
}
desktopWin = win;
gc = XCreateGC(dpy,desktopWin,0,NULL);
gcv.function = GXxor;
gcv.foreground = 0x0f0f0f0f;
srcGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
gcv.foreground = 0xf0f0f0f0;
dstGC = XCreateGC(dpy,desktopWin,GCFunction|GCForeground,&gcv);
dotCursor = CreateDotCursor();
attr.cursor = dotCursor;
XChangeWindowAttributes(dpy, desktopWin, CWBackingStore|CWCursor, &attr);
}
/*
* HandleBasicDesktopEvent - deal with expose and leave events.
*/
/*
static void
HandleBasicDesktopEvent(Widget w, XtPointer ptr, XEvent *ev, Boolean *cont)
{
int i;
switch (ev->type) {
case Expose:
case GraphicsExpose:
/// sometimes due to scrollbars being added/removed we get an expose outside
// the actual desktop area. Make sure we don't pass it on to the RFB
// server.
if (ev->xexpose.x + ev->xexpose.width > si.framebufferWidth) {
ev->xexpose.width = si.framebufferWidth - ev->xexpose.x;
if (ev->xexpose.width <= 0) break;
}
if (ev->xexpose.y + ev->xexpose.height > si.framebufferHeight) {
ev->xexpose.height = si.framebufferHeight - ev->xexpose.y;
if (ev->xexpose.height <= 0) break;
}
SendFramebufferUpdateRequest(ev->xexpose.x, ev->xexpose.y,
ev->xexpose.width, ev->xexpose.height, False);
break;
case LeaveNotify:
for (i = 0; i < 256; i++) {
if (modifierPressed[i]) {
SendKeyEvent(XKeycodeToKeysym(dpy, i, 0), False);
modifierPressed[i] = False;
}
}
break;
}
}
*/
/*
* SendRFBEvent is an action which sends an RFB event. It can be used in two
* ways. Without any parameters it simply sends an RFB event corresponding to
* the X event which caused it to be called. With parameters, it generates a
* "fake" RFB event based on those parameters. The first parameter is the
* event type, either "ptr", "keydown", "keyup" or "key" (down&up). For a
* "key" event the second parameter is simply a keysym string as understood by
* XStringToKeysym(). For a "ptr" event, the following three parameters are
* just X, Y and the button mask (0 for all up, 1 for button1 down, 2 for
* button2 down, 3 for both, etc).
*/
/*
void
SendRFBEvent(XEvent *ev, String *params, Cardinal *num_params)
{
KeySym ks;
char keyname[256];
int buttonMask, x, y;
if (appData.fullScreen && ev->type == MotionNotify) {
if (BumpScroll(ev))
return;
}
if (appData.viewOnly) return;
if (*num_params != 0) {
if (strncasecmp(params[0],"key",3) == 0) {
if (*num_params != 2) {
fprintf(stderr,
"Invalid params: SendRFBEvent(key|keydown|keyup,<keysym>)\n");
return;
}
ks = XStringToKeysym(params[1]);
if (ks == NoSymbol) {
fprintf(stderr,"Invalid keysym '%s' passed to SendRFBEvent\n",
params[1]);
return;
}
if (strcasecmp(params[0],"keydown") == 0) {
SendKeyEvent(ks, 1);
} else if (strcasecmp(params[0],"keyup") == 0) {
SendKeyEvent(ks, 0);
} else if (strcasecmp(params[0],"key") == 0) {
SendKeyEvent(ks, 1);
SendKeyEvent(ks, 0);
} else {
fprintf(stderr,"Invalid event '%s' passed to SendRFBEvent\n",
params[0]);
return;
}
} else if (strcasecmp(params[0],"ptr") == 0) {
if (*num_params == 4) {
x = atoi(params[1]);
y = atoi(params[2]);
buttonMask = atoi(params[3]);
SendPointerEvent(x, y, buttonMask);
} else if (*num_params == 2) {
switch (ev->type) {
case ButtonPress:
case ButtonRelease:
x = ev->xbutton.x;
y = ev->xbutton.y;
break;
case KeyPress:
case KeyRelease:
x = ev->xkey.x;
y = ev->xkey.y;
break;
default:
fprintf(stderr,
"Invalid event caused SendRFBEvent(ptr,<buttonMask>)\n");
return;
}
buttonMask = atoi(params[1]);
SendPointerEvent(x, y, buttonMask);
} else {
fprintf(stderr,
"Invalid params: SendRFBEvent(ptr,<x>,<y>,<buttonMask>)\n"
" or SendRFBEvent(ptr,<buttonMask>)\n");
return;
}
} else {
fprintf(stderr,"Invalid event '%s' passed to SendRFBEvent\n", params[0]);
}
return;
}
switch (ev->type) {
case MotionNotify:
while (XCheckTypedWindowEvent(dpy, desktopWin, MotionNotify, ev))
; // discard all queued motion notify events
SendPointerEvent(ev->xmotion.x, ev->xmotion.y,
(ev->xmotion.state & 0x1f00) >> 8);
return;
case ButtonPress:
SendPointerEvent(ev->xbutton.x, ev->xbutton.y,
(((ev->xbutton.state & 0x1f00) >> 8) |
(1 << (ev->xbutton.button - 1))));
return;
case ButtonRelease:
SendPointerEvent(ev->xbutton.x, ev->xbutton.y,
(((ev->xbutton.state & 0x1f00) >> 8) &
~(1 << (ev->xbutton.button - 1))));
return;
case KeyPress:
case KeyRelease:
XLookupString(&ev->xkey, keyname, 256, &ks, NULL);
if (IsModifierKey(ks)) {
ks = XKeycodeToKeysym(dpy, ev->xkey.keycode, 0);
modifierPressed[ev->xkey.keycode] = (ev->type == KeyPress);
}
SendKeyEvent(ks, (ev->type == KeyPress));
return;
default:
fprintf(stderr,"Invalid event passed to SendRFBEvent\n");
}
}
*/
/*
* CreateDotCursor.
*/
static Cursor
CreateDotCursor()
{
Cursor cursor;
Pixmap src, msk;
static char srcBits[] = { 0, 14,14,14, 0 };
static char mskBits[] = { 14,31,31,31,14 };
XColor fg, bg;
src = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), srcBits, 5, 5);
msk = XCreateBitmapFromData(dpy, DefaultRootWindow(dpy), mskBits, 5, 5);
XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "black",
&fg, &fg);
XAllocNamedColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), "white",
&bg, &bg);
cursor = XCreatePixmapCursor(dpy, src, msk, &fg, &bg, 2, 2);
XFreePixmap(dpy, src);
XFreePixmap(dpy, msk);
return cursor;
}
/*
* CopyDataToScreen.
*/
void
CopyDataToScreen(char *buf, int x, int y, int width, int height)
{
if (appData.rawDelay != 0) {
lockQt();
XFillRectangle(dpy, desktopWin, gc, x, y, width, height);
XSync(dpy,False);
unlockQt();
usleep(appData.rawDelay * 1000);
}
if (!appData.useBGR233) {
int h;
int widthInBytes = width * myFormat.bitsPerPixel / 8;
int scrWidthInBytes = si.framebufferWidth * myFormat.bitsPerPixel / 8;
char *scr = (image->data + y * scrWidthInBytes
+ x * myFormat.bitsPerPixel / 8);
for (h = 0; h < height; h++) {
memcpy(scr, buf, widthInBytes);
buf += widthInBytes;
scr += scrWidthInBytes;
}
} else {
CopyBGR233ToScreen((CARD8 *)buf, x, y, width, height);
}
lockQt();
if (useShm)
XShmPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height, False);
else
XPutImage(dpy, desktopWin, gc, image, x, y, x, y, width, height);
unlockQt();
}
/*
* CopyBGR233ToScreen.
*/
static void
CopyBGR233ToScreen(CARD8 *buf, int x, int y, int width, int height)
{
int p, q;
int xoff = 7 - (x & 7);
int xcur;
int fbwb = si.framebufferWidth / 8;
CARD8 *scr1 = ((CARD8 *)image->data) + y * fbwb + x / 8;
CARD8 *scrt;
CARD8 *scr8 = ((CARD8 *)image->data) + y * si.framebufferWidth + x;
CARD16 *scr16 = ((CARD16 *)image->data) + y * si.framebufferWidth + x;
CARD32 *scr32 = ((CARD32 *)image->data) + y * si.framebufferWidth + x;
switch (visbpp) {
/* thanks to Chris Hooper for single bpp support */
case 1:
for (q = 0; q < height; q++) {
xcur = xoff;
scrt = scr1;
for (p = 0; p < width; p++) {
*scrt = ((*scrt & ~(1 << xcur))
| (BGR233ToPixel[*(buf++)] << xcur));
if (xcur-- == 0) {
xcur = 7;
scrt++;
}
}
scr1 += fbwb;
}
break;
case 8:
for (q = 0; q < height; q++) {
for (p = 0; p < width; p++) {
*(scr8++) = BGR233ToPixel[*(buf++)];
}
scr8 += si.framebufferWidth - width;
}
break;
case 16:
for (q = 0; q < height; q++) {
for (p = 0; p < width; p++) {
*(scr16++) = BGR233ToPixel[*(buf++)];
}
scr16 += si.framebufferWidth - width;
}
break;
case 32:
for (q = 0; q < height; q++) {
for (p = 0; p < width; p++) {
*(scr32++) = BGR233ToPixel[*(buf++)];
}
scr32 += si.framebufferWidth - width;
}
break;
}
}
void ShmSync(void) {
if (useShm)
XSync(dpy, False);
}
/*
* ToplevelInitBeforeRealization sets the title, geometry and other resources
* on the toplevel window.
*/
void
ToplevelInit()
{
dpyWidth = WidthOfScreen(DefaultScreenOfDisplay(dpy));
dpyHeight = HeightOfScreen(DefaultScreenOfDisplay(dpy));
}
/*
* Cleanup - perform shm cleanup operations prior to exiting.
*/
void
Cleanup()
{
if (useShm)
ShmCleanup();
}
void
ShmCleanup()
{
fprintf(stderr,"ShmCleanup called\n");
if (needShmCleanup) {
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
needShmCleanup = False;
}
}
static int
ShmCreationXErrorHandler(Display* _dpy, XErrorEvent *_e)
{
caughtShmError = True;
return 0;
}
XImage *
CreateShmImage()
{
XImage *_image;
XErrorHandler oldXErrorHandler;
if (!XShmQueryExtension(dpy))
return NULL;
_image = XShmCreateImage(dpy, vis, visdepth, ZPixmap, NULL, &shminfo,
si.framebufferWidth, si.framebufferHeight);
if (!_image) return NULL;
shminfo.shmid = shmget(IPC_PRIVATE,
_image->bytes_per_line * _image->height,
IPC_CREAT|0777);
if (shminfo.shmid == -1) {
XDestroyImage(_image);
return NULL;
}
shminfo.shmaddr = _image->data = shmat(shminfo.shmid, 0, 0);
if (shminfo.shmaddr == (char *)-1) {
XDestroyImage(_image);
shmctl(shminfo.shmid, IPC_RMID, 0);
return NULL;
}
shminfo.readOnly = True;
oldXErrorHandler = XSetErrorHandler(ShmCreationXErrorHandler);
XShmAttach(dpy, &shminfo);
XSync(dpy, False);
XSetErrorHandler(oldXErrorHandler);
if (caughtShmError) {
XDestroyImage(_image);
shmdt(shminfo.shmaddr);
shmctl(shminfo.shmid, IPC_RMID, 0);
return NULL;
}
needShmCleanup = True;
fprintf(stderr,"Using shared memory PutImage\n");
return _image;
}

View File

@ -1,147 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* hextile.c - handle hextile encoding.
*
* This file shouldn't be compiled directly. It is included multiple times by
* rfbproto.c, each time with a different definition of the macro BPP. For
* each value of BPP, this file defines a function which handles a hextile
* encoded rectangle with BPP bits per pixel.
*/
#define HandleHextileBPP CONCAT2E(HandleHextile,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
#define GET_PIXEL CONCAT2E(GET_PIXEL,BPP)
static Bool
HandleHextileBPP (int rx, int ry, int rw, int rh)
{
CARDBPP bg, fg;
XGCValues gcv;
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;
#if (BPP == 8)
if (appData.useBGR233)
gcv.foreground = BGR233ToPixel[bg];
else
#endif
gcv.foreground = bg;
lockQt();
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, x, y, w, h);
unlockQt();
if (subencoding & rfbHextileForegroundSpecified)
if (!ReadFromRFBServer((char *)&fg, sizeof(fg)))
return False;
if (!(subencoding & rfbHextileAnySubrects)) {
continue;
}
if (!ReadFromRFBServer((char *)&nSubrects, 1))
return False;
ptr = (CARD8 *)buffer;
if (subencoding & rfbHextileSubrectsColoured) {
if (!ReadFromRFBServer(buffer, nSubrects * (2 + (BPP / 8))))
return False;
lockQt();
for (i = 0; i < nSubrects; i++) {
GET_PIXEL(fg, ptr);
sx = rfbHextileExtractX(*ptr);
sy = rfbHextileExtractY(*ptr);
ptr++;
sw = rfbHextileExtractW(*ptr);
sh = rfbHextileExtractH(*ptr);
ptr++;
#if (BPP == 8)
if (appData.useBGR233)
gcv.foreground = BGR233ToPixel[fg];
else
#endif
gcv.foreground = fg;
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
}
unlockQt();
} else {
if (!ReadFromRFBServer(buffer, nSubrects * 2))
return False;
#if (BPP == 8)
if (appData.useBGR233)
gcv.foreground = BGR233ToPixel[fg];
else
#endif
gcv.foreground = fg;
lockQt();
XChangeGC(dpy, gc, GCForeground, &gcv);
for (i = 0; i < nSubrects; i++) {
sx = rfbHextileExtractX(*ptr);
sy = rfbHextileExtractY(*ptr);
ptr++;
sw = rfbHextileExtractW(*ptr);
sh = rfbHextileExtractH(*ptr);
ptr++;
XFillRectangle(dpy, desktopWin, gc, x+sx, y+sy, sw, sh);
}
unlockQt();
}
}
}
return True;
}

View File

@ -1,180 +0,0 @@
/***************************************************************************
krdc.cpp - main window
-------------------
begin : Tue May 13 23:07:42 CET 2002
copyright : (C) 2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "newconnectiondialog.h"
#include "krdc.h"
#include <kdebug.h>
#include <kapplication.h>
#include <kcombobox.h>
#include <kconfig.h>
#include <qlayout.h>
KRDC::KRDC(QWidget *w, const QString &host, Quality q) :
QWidget(w, 0),
m_view(0),
m_host(host),
m_quality(q)
{
m_scrollView = new QScrollView(this, "Remote View");
QVBoxLayout *vbl = new QVBoxLayout(this);
vbl->addWidget(m_scrollView);
}
bool KRDC::start()
{
KConfig *config = KApplication::kApplication()->config();
QString vncServerHost;
int vncServerPort = 5900;
if (!m_host.isNull()) {
parseHost(m_host, vncServerHost, vncServerPort);
if (m_quality == QUALITY_UNKNOWN)
m_quality = QUALITY_HIGH;
} else {
NewConnectionDialog ncd(0, 0, true);
QStringList list = config->readListEntry("serverCompletions");
ncd.serverInput->completionObject()->setItems(list);
list = config->readListEntry("serverHistory");
ncd.serverInput->setHistoryItems(list);
if ((ncd.exec() == QDialog::Rejected) ||
(ncd.serverInput->currentText().length() == 0)) {
return false;
}
QString host = ncd.serverInput->currentText();
parseHost(host, vncServerHost, vncServerPort);
int ci = ncd.qualityCombo->currentItem();
if (ci == 0)
m_quality = QUALITY_HIGH;
else if (ci == 1)
m_quality = QUALITY_MEDIUM;
else if (ci == 2)
m_quality = QUALITY_LOW;
else {
kdDebug() << "Unknown quality";
return false;
}
ncd.serverInput->addToHistory(host);
list = ncd.serverInput->completionObject()->items();
config->writeEntry("serverCompletions", list);
list = ncd.serverInput->historyItems();
config->writeEntry("serverHistory", list);
}
configureApp(m_quality);
setFixedSize(640, 480);
m_view = new KVncView(m_scrollView, 0, vncServerHost, vncServerPort,
&m_appData);
m_scrollView->addChild(m_view);
connect(m_view, SIGNAL(changeSize(int,int)), SLOT(setSize(int,int)));
show();
m_view->start();
return true;
}
void KRDC::configureApp(Quality q) {
m_appData.shareDesktop = True;
m_appData.viewOnly = False;
if (q == QUALITY_LOW) {
m_appData.useBGR233 = True;
m_appData.encodingsString = "copyrect tight zlib hextile corre rre raw";
m_appData.compressLevel = -1;
m_appData.qualityLevel = 1;
}
else if (q == QUALITY_MEDIUM) {
m_appData.useBGR233 = False;
m_appData.encodingsString = "copyrect tight zlib hextile corre rre raw";
m_appData.compressLevel = -1;
m_appData.qualityLevel = 4;
}
else if ((q == QUALITY_HIGH) || (q == QUALITY_UNKNOWN)) {
m_appData.useBGR233 = False;
m_appData.encodingsString = "copyrect hextile corre rre raw";
m_appData.compressLevel = -1;
m_appData.qualityLevel = 9;
}
m_appData.nColours = 256;
m_appData.useSharedColours = True;
m_appData.requestedDepth = 0;
m_appData.useRemoteCursor = True;
m_appData.rawDelay = 0;
m_appData.copyRectDelay = 0;
}
void KRDC::parseHost(QString &s, QString &serverHost, int &serverPort) {
QString host = s;
int pos = s.find(':');
if (pos < 0) {
s+= ":0";
host+= ":0";
pos = s.find(':');
}
bool portOk = false;
QString portS = s.mid(pos+1);
int port = portS.toInt(&portOk);
if (portOk) {
host = s.left(pos);
if (port < 100)
serverPort = port + 5900;
else
serverPort = port;
}
serverHost = host;
}
KRDC::~KRDC()
{
}
void KRDC::setSize(int w, int h)
{
int newW, newH, dw, dh, fx, fy;
setMaximumSize(w, h);
QWidget *desktop = QApplication::desktop();
// todo: switch to fullscreen if desktop is too small
dw = desktop->width();
dh = desktop->height();
newW = (w > dw) ? dw : w;
newH = (h > dh) ? dh : h;
QRect g = geometry();
QRect f = frameGeometry();
fx = g.x() - f.x();
fy = g.y() - f.y();
g.setWidth(newW);
g.setHeight(newH);
if (g.right() > dw)
g.setX(dw - g.width());
if (g.x() < fx)
g.setX(fx);
if (g.bottom() > dh)
g.setY(dh - g.height());
if (g.y() < fy)
g.setY(fy);
setGeometry(g);
}

View File

@ -1,52 +0,0 @@
/***************************************************************************
krdc.h - main window
-------------------
begin : Tue May 13 23:10:42 CET 2002
copyright : (C) 2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef KRDC_H
#define KRDC_H
#include <qscrollview.h>
#include "kvncview.h"
class KRDC : public QWidget
{
Q_OBJECT
private:
QScrollView *m_scrollView;
KVncView *m_view;
QString m_host;
Quality m_quality;
AppData m_appData;
void configureApp(Quality q);
void parseHost(QString &s, QString &serverHost, int &serverPort);
protected:
public:
KRDC(QWidget *parent = 0,
const QString &host = QString::null,
Quality q = QUALITY_UNKNOWN);
~KRDC();
bool start();
private slots:
void setSize(int w, int h);
};
#endif

View File

@ -1 +0,0 @@

View File

@ -1,383 +0,0 @@
/***************************************************************************
kvncview.cpp - main widget
-------------------
begin : Thu Dec 20 15:11:42 CET 2001
copyright : (C) 2001-2002 by Tim Jansen
contains portions (event handling) from Keystone:
(C) 1999-2000 Richard Moore
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "passworddialog.h"
#include "kvncview.h"
#include <kdebug.h>
#include <qlineedit.h>
#include <qdialog.h>
#include <qmutex.h>
#include <qwaitcondition.h>
/*
* appData is our application-specific data which can be set by the user with
* application resource specs. The AppData structure is defined in the header
* file.
*/
AppData appData;
Display* dpy;
static KVncView *kvncview;
static QString password;
static QMutex passwordLock;
static QWaitCondition passwordWaiter;
KVncView::KVncView(QWidget *parent,
const char *name,
const QString &_host,
int _port,
AppData *data) :
QWidget(parent, name),
m_cthread(this, m_wthread, m_quitFlag),
m_wthread(m_quitFlag),
m_quitFlag(false),
m_host(_host),
m_port(_port)
{
kvncview = this;
password = QString::null;
dpy = qt_xdisplay();
if (data)
appData = *data;
else
setDefaultAppData();
setFixedSize(512, 384);
setFocusPolicy(QWidget::StrongFocus);
emit changeSize(512, 384);
}
void KVncView::setDefaultAppData() {
appData.shareDesktop = True;
appData.viewOnly = False;
appData.useBGR233 = False;
appData.encodingsString = "copyrect hextile corre rre raw";
appData.compressLevel = -1;
appData.qualityLevel = 9;
appData.nColours = 256;
appData.useSharedColours = True;
appData.requestedDepth = 0;
appData.useRemoteCursor = True;
appData.rawDelay = 0;
appData.copyRectDelay = 0;
}
QString KVncView::host() {
return m_host;
}
int KVncView::port() {
return m_port;
}
void KVncView::startQuitting() {
m_quitFlag = true;
m_wthread.kick();
}
bool KVncView::isQuitting() {
return m_quitFlag;
}
enum RemoteViewStatus KVncView::status() {
return m_status;
}
void KVncView::start() {
m_cthread.start();
}
KVncView::~KVncView()
{
m_cthread.wait();
m_wthread.wait();
}
void KVncView::paintEvent(QPaintEvent *e) {
if (status() == REMOTE_VIEW_CONNECTED)
m_wthread.queueUpdateRequest(e->region());
}
void KVncView::customEvent(QCustomEvent *e)
{
if (e->type() == ScreenResizeEventType) {
ScreenResizeEvent *sre = (ScreenResizeEvent*) e;
setFixedSize(sre->width(), sre->height());
emit changeSize(sre->width(), sre->height());
}
else if (e->type() == StatusChangeEventType) {
StatusChangeEvent *sce = (StatusChangeEvent*) e;
m_status = sce->status();
if (m_status == REMOTE_VIEW_CONNECTED) {
setFocus();
setMouseTracking(true);
}
if (m_status == REMOTE_VIEW_DISCONNECTED) {
setMouseTracking(false);
emit disconnected();
}
}
else if (e->type() == PasswordRequiredEventType) {
PasswordDialog pd(0, 0, true);
if (pd.exec() == QDialog::Accepted)
password = pd.passwordInput->text();
else
password = QString::null;
passwordLock.lock(); // to guarantee that thread is waiting
passwordWaiter.wakeAll();
passwordLock.unlock();
}
}
void KVncView::mouseEvent(QMouseEvent *e) {
if (status() != REMOTE_VIEW_CONNECTED)
return;
if ( e->type() != QEvent::MouseMove ) {
m_buttonMask = 0;
if ( e->type() == QEvent::MouseButtonPress ) {
if ( e->button() & LeftButton )
m_buttonMask |= 0x01;
if ( e->button() & MidButton )
m_buttonMask |= 0x04;
if ( e->button() & RightButton )
m_buttonMask |= 0x02;
}
else if ( e->type() == QEvent::MouseButtonRelease ) {
if ( e->button() & LeftButton )
m_buttonMask &= 0x06;
if ( e->button() & MidButton )
m_buttonMask &= 0x04;
if ( e->button() & RightButton )
m_buttonMask &= 0x02;
}
}
m_wthread.queueMouseEvent(e->x(), e->y(), m_buttonMask);
}
void KVncView::mousePressEvent(QMouseEvent *e) {
mouseEvent(e);
}
void KVncView::mouseReleaseEvent(QMouseEvent *e) {
mouseEvent(e);
}
void KVncView::mouseMoveEvent(QMouseEvent *e) {
mouseEvent(e);
}
void KVncView::keyPressEvent(QKeyEvent *e) {
m_wthread.queueKeyEvent(toKeySym(e), true);
}
void KVncView::keyReleaseEvent(QKeyEvent *e) {
m_wthread.queueKeyEvent(toKeySym(e), false);
}
int getPassword(char *passwd, int pwlen) {
int retV = 1;
passwordLock.lock();
if (password.isNull()) {
QThread::postEvent(kvncview, new PasswordRequiredEvent());
passwordWaiter.wait(&passwordLock);
}
if (!password.isNull())
strncpy(passwd, password.latin1(), pwlen);
else {
passwd[0] = 0;
retV = 0;
}
passwordLock.unlock();
if (!retV)
kvncview->startQuitting();
return retV;
}
extern int isQuitFlagSet() {
return kvncview->isQuitting() ? 1 : 0;
}
void lockQt() {
KApplication::kApplication()->lock();
}
void unlockQt() {
KApplication::kApplication()->unlock(false);
}
void unlockQtGui() {
KApplication::kApplication()->unlock(true);
}
KeySym KVncView::toKeySym(QKeyEvent *k)
{
int ke = 0;
ke = k->ascii();
// Markus: Crappy hack. I dont know why lower case letters are
// not defined in qkeydefs.h. The key() for e.g. 'l' == 'L'.
// This sucks. :-(
if ( (ke >= 'a') && (ke <= 'z') ) {
ke = k->key();
ke = ke + 0x20;
return ke;
}
// qkeydefs = xkeydefs! :-)
if ( ( k->key() >= 0x0a0 ) && k->key() <= 0x0ff )
return k->key();
if ( ( k->key() >= 0x20 ) && ( k->key() <= 0x7e ) )
return k->key();
// qkeydefs != xkeydefs! :-(
// This is gonna suck :-(
switch( k->key() ) {
case SHIFT:
return XK_Shift_L;
case CTRL:
return XK_Control_L;
case ALT:
return XK_Alt_L;
case Key_Escape:
return XK_Escape;
case Key_Tab:
return XK_Tab;
case Key_Backspace:
return XK_BackSpace;
case Key_Return:
return XK_Return;
case Key_Enter:
return XK_Return;
case Key_Insert:
return XK_Insert;
case Key_Delete:
return XK_Delete;
case Key_Pause:
return XK_Pause;
case Key_Print:
return XK_Print;
case Key_SysReq:
return XK_Sys_Req;
case Key_Home:
return XK_Home;
case Key_End:
return XK_End;
case Key_Left:
return XK_Left;
case Key_Up:
return XK_Up;
case Key_Right:
return XK_Right;
case Key_Down:
return XK_Down;
case Key_Prior:
return XK_Prior;
case Key_Next:
return XK_Next;
case Key_Shift:
return XK_Shift_L;
case Key_Control:
return XK_Control_L;
case Key_Meta:
return XK_Meta_L;
case Key_Alt:
return XK_Alt_L;
case Key_CapsLock:
return XK_Caps_Lock;
case Key_NumLock:
return XK_Num_Lock;
case Key_ScrollLock:
return XK_Scroll_Lock;
case Key_F1:
return XK_F1;
case Key_F2:
return XK_F2;
case Key_F3:
return XK_F3;
case Key_F4:
return XK_F4;
case Key_F5:
return XK_F5;
case Key_F6:
return XK_F6;
case Key_F7:
return XK_F7;
case Key_F8:
return XK_F8;
case Key_F9:
return XK_F9;
case Key_F10:
return XK_F10;
case Key_F11:
return XK_F11;
case Key_F12:
return XK_F12;
case Key_F13:
return XK_F13;
case Key_F14:
return XK_F14;
case Key_F15:
return XK_F15;
case Key_F16:
return XK_F16;
case Key_F17:
return XK_F17;
case Key_F18:
return XK_F18;
case Key_F19:
return XK_F19;
case Key_F20:
return XK_F20;
case Key_F21:
return XK_F21;
case Key_F22:
return XK_F22;
case Key_F23:
return XK_F23;
case Key_F24:
return XK_F24;
case Key_unknown:
return 0;
default:
return 0;
}
// Puhhhhh done. :-)
return 0;
}

View File

@ -1,81 +0,0 @@
/***************************************************************************
kvncview.h - widget that shows the vnc client
-------------------
begin : Thu Dec 20 15:11:42 CET 2001
copyright : (C) 2001-2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef KVNCVIEW_H
#define KVNCVIEW_H
#include <kapplication.h>
#include <qwidget.h>
#define VNCVIEWER_H
#include "threads.h"
#undef VNCVIEWER_H
#ifndef VNCVIEWER_H
#define VNCVIEWER_H
#include "vncviewer.h"
#endif
class KVncView : public QWidget
{
Q_OBJECT
private:
ControllerThread m_cthread;
WriterThread m_wthread;
volatile bool m_quitFlag;
enum RemoteViewStatus m_status;
int m_buttonMask;
QString m_host;
int m_port;
void setDefaultAppData();
void mouseEvent(QMouseEvent*);
KeySym toKeySym(QKeyEvent *k);
protected:
void paintEvent(QPaintEvent*);
void customEvent(QCustomEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void keyPressEvent(QKeyEvent*);
void keyReleaseEvent(QKeyEvent*);
public:
KVncView(QWidget* parent=0, const char *name=0,
const QString &host = QString(""), int port = 5900,
AppData *data = 0);
~KVncView();
void startQuitting();
bool isQuitting();
QString host();
int port();
void start();
enum RemoteViewStatus status();
signals:
void changeSize(int x, int y);
void disconnected();
};
#endif

View File

@ -1,73 +0,0 @@
/***************************************************************************
main.cpp - description
-------------------
begin : Thu Dec 20 15:11:42 CET 2001
copyright : (C) 2001-2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <kapplication.h>
#include <klocale.h>
#include <kdebug.h>
#include <qwindowdefs.h>
#include "kvncview.h"
#include "krdc.h"
#define VERSION "0.1"
static const char *description = I18N_NOOP("Remote Desktop Connection");
static KCmdLineOptions options[] =
{
{ "+[host]", I18N_NOOP("An optional argument 'arg1'."), 0 },
{ 0, 0, 0 }
};
int main(int argc, char *argv[])
{
KAboutData aboutData( "krdc", I18N_NOOP("Remote Desktop Connection"),
VERSION, description, KAboutData::License_GPL,
"(c) 2001, Tim Jansen", 0, 0, "tim@tjansen.de");
aboutData.addAuthor("Tim Jansen",0, "tim@tjansen.de");
KCmdLineArgs::init( argc, argv, &aboutData );
KCmdLineArgs::addCmdLineOptions( options );
KApplication a;
Quality quality = QUALITY_HIGH;
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
KRDC *krdc;
if (args->count() > 0) {
QString host = args->arg(0);
krdc = new KRDC(0, host, quality);
}
else
krdc = new KRDC();
a.setMainWidget(krdc);
if (!krdc->start())
return 0;
return a.exec();
}

View File

@ -1,273 +0,0 @@
<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
<class>NewConnectionDialog</class>
<widget class="QDialog">
<property name="name">
<cstring>NewConnectionDialog</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>412</width>
<height>170</height>
</rect>
</property>
<property name="caption">
<string>Remote Desktop Connection</string>
</property>
<property name="layoutMargin" stdset="0">
</property>
<property name="layoutSpacing" stdset="0">
</property>
<vbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>3</number>
</property>
<property name="spacing">
<number>2</number>
</property>
<widget class="QFrame">
<property name="name">
<cstring>upperFrame</cstring>
</property>
<property name="frameShape">
<enum>NoFrame</enum>
</property>
<property name="frameShadow">
<enum>Plain</enum>
</property>
<property name="layoutMargin" stdset="0">
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>11</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<widget class="QLabel" row="1" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>serverDescLabel</cstring>
</property>
<property name="font">
<font>
</font>
</property>
<property name="text">
<string>Please enter the name or address of the computer that you want to connect to.</string>
</property>
<property name="alignment">
<set>WordBreak|AlignVCenter|AlignLeft</set>
</property>
<property name="wordwrap" stdset="0">
</property>
</widget>
<widget class="QLabel" row="0" column="0">
<property name="name">
<cstring>serverLabel</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>5</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>MShape</enum>
</property>
<property name="frameShadow">
<enum>MShadow</enum>
</property>
<property name="text">
<string>Remote Desktop:</string>
</property>
</widget>
<widget class="KHistoryCombo" row="0" column="1">
<property name="name">
<cstring>serverInput</cstring>
</property>
<property name="maxCount">
<number>12</number>
</property>
<property name="duplicatesEnabled">
<bool>false</bool>
</property>
<property name="toolTip" stdset="0">
<string></string>
</property>
<property name="whatsThis" stdset="0">
<string>Enter the name of the server you want to connect to. If you have a display number enter it as well, separated from the server by a colon, e.g. 'mycomputer:2'.</string>
</property>
</widget>
</grid>
</widget>
<widget class="QFrame">
<property name="name">
<cstring>middleFrame</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>1</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>NoFrame</enum>
</property>
<property name="frameShadow">
<enum>Plain</enum>
</property>
<property name="layoutMargin" stdset="0">
</property>
<property name="layoutSpacing" stdset="0">
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
<number>5</number>
</property>
<widget class="QLabel">
<property name="name">
<cstring>connectionTypeLabel</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>0</hsizetype>
<vsizetype>1</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Connection type:</string>
</property>
</widget>
<widget class="QComboBox">
<item>
<property name="text">
<string>High Quality (LAN, direct connection)</string>
</property>
</item>
<item>
<property name="text">
<string>Medium Quality (DSL, Cable, fast Internet)</string>
</property>
</item>
<item>
<property name="text">
<string>Low Quality (Modem, ISDN, slow Internet)</string>
</property>
</item>
<property name="name">
<cstring>qualityCombo</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
<hsizetype>5</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>280</width>
<height>0</height>
</size>
</property>
<property name="whatsThis" stdset="0">
<string>Use this to specify the performance of your connection. Note that you should select the speed of the weakest link - even if you have a high speed connection this will not help you if the remote computer uses a slow modem. Choosing a too high quality on a slow link will cause slower response times. Choosing a lower quality will increase latencies in high speed connections and results in lower image quality, especially in 'Low Quality' mode.</string>
</property>
</widget>
</hbox>
</widget>
<widget class="QFrame">
<property name="name">
<cstring>bottomFrame</cstring>
</property>
<property name="frameShape">
<enum>NoFrame</enum>
</property>
<property name="frameShadow">
<enum>Plain</enum>
</property>
<property name="layoutMargin" stdset="0">
</property>
<hbox>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>5</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<spacer>
<property name="name">
<cstring>spacer</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
</spacer>
<widget class="QPushButton">
<property name="name">
<cstring>connectButton</cstring>
</property>
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>C&amp;onnect</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton">
<property name="name">
<cstring>cancelButton</cstring>
</property>
<property name="text">
<string>&amp;Cancel</string>
</property>
</widget>
</hbox>
</widget>
</vbox>
</widget>
<connections>
<connection>
<sender>connectButton</sender>
<signal>clicked()</signal>
<receiver>NewConnectionDialog</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>cancelButton</sender>
<signal>clicked()</signal>
<receiver>NewConnectionDialog</receiver>
<slot>reject()</slot>
</connection>
</connections>
<layoutdefaults spacing="6" margin="11"/>
</UI>

View File

@ -1,104 +0,0 @@
<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
<class>PasswordDialog</class>
<widget class="QDialog">
<property name="name">
<cstring>PasswordDialog</cstring>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>330</width>
<height>112</height>
</rect>
</property>
<property name="caption">
<string>Remote Desktop Connection</string>
</property>
<property name="layoutSpacing" stdset="0">
</property>
<grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
<property name="margin">
<number>11</number>
</property>
<property name="spacing">
<number>8</number>
</property>
<widget class="QLabel" row="1" column="0">
<property name="name">
<cstring>passwordLabel</cstring>
</property>
<property name="text">
<string>Password:</string>
</property>
</widget>
<widget class="QLineEdit" row="1" column="1" rowspan="1" colspan="3">
<property name="name">
<cstring>passwordInput</cstring>
</property>
<property name="echoMode">
<enum>Password</enum>
</property>
</widget>
<widget class="QLabel" row="0" column="0" rowspan="1" colspan="4">
<property name="name">
<cstring>descLabel</cstring>
</property>
<property name="text">
<string>Access to the system requires a password.</string>
</property>
</widget>
<spacer row="2" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>spacer</cstring>
</property>
<property name="orientation">
<enum>Horizontal</enum>
</property>
<property name="sizeType">
<enum>Expanding</enum>
</property>
</spacer>
<widget class="QPushButton" row="2" column="2">
<property name="name">
<cstring>okButton</cstring>
</property>
<property name="text">
<string>&amp;OK</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
<widget class="QPushButton" row="2" column="3">
<property name="name">
<cstring>cancelButton</cstring>
</property>
<property name="text">
<string>&amp;Cancel</string>
</property>
<property name="default">
<bool>false</bool>
</property>
</widget>
</grid>
</widget>
<connections>
<connection>
<sender>okButton</sender>
<signal>clicked()</signal>
<receiver>PasswordDialog</receiver>
<slot>accept()</slot>
</connection>
<connection>
<sender>cancelButton</sender>
<signal>clicked()</signal>
<receiver>PasswordDialog</receiver>
<slot>reject()</slot>
</connection>
</connections>
<layoutdefaults spacing="6" margin="11"/>
</UI>

View File

@ -1,981 +0,0 @@
/*
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* rfbproto.c - functions to deal with client side of RFB protocol.
*/
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include "vncviewer.h"
#include "vncauth.h"
#include <zlib.h>
#include <jpeglib.h>
static Bool HandleRRE8(int rx, int ry, int rw, int rh);
static Bool HandleRRE16(int rx, int ry, int rw, int rh);
static Bool HandleRRE32(int rx, int ry, int rw, int rh);
static Bool HandleCoRRE8(int rx, int ry, int rw, int rh);
static Bool HandleCoRRE16(int rx, int ry, int rw, int rh);
static Bool HandleCoRRE32(int rx, int ry, int rw, int rh);
static Bool HandleHextile8(int rx, int ry, int rw, int rh);
static Bool HandleHextile16(int rx, int ry, int rw, int rh);
static Bool HandleHextile32(int rx, int ry, int rw, int rh);
static Bool HandleZlib8(int rx, int ry, int rw, int rh);
static Bool HandleZlib16(int rx, int ry, int rw, int rh);
static Bool HandleZlib32(int rx, int ry, int rw, int rh);
static Bool HandleTight8(int rx, int ry, int rw, int rh);
static Bool HandleTight16(int rx, int ry, int rw, int rh);
static Bool HandleTight32(int rx, int ry, int rw, int rh);
static long ReadCompactLen (void);
static void JpegInitSource(j_decompress_ptr cinfo);
static boolean JpegFillInputBuffer(j_decompress_ptr cinfo);
static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
static void JpegTermSource(j_decompress_ptr cinfo);
static void JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData,
int compressedLen);
int rfbsock;
char *desktopName;
rfbPixelFormat myFormat;
rfbServerInitMsg si;
char *serverCutText = NULL;
Bool newServerCutText = False;
int endianTest = 1;
/* Note that the CoRRE encoding uses this buffer and assumes it is big enough
to hold 255 * 255 * 32 bits -> 260100 bytes. 640*480 = 307200 bytes.
Hextile also assumes it is big enough to hold 16 * 16 * 32 bits.
Tight encoding assumes BUFFER_SIZE is at least 16384 bytes. */
#define BUFFER_SIZE (640*480)
static char buffer[BUFFER_SIZE];
/* The zlib encoding requires expansion/decompression/deflation of the
compressed data in the "buffer" above into another, result buffer.
However, the size of the result buffer can be determined precisely
based on the bitsPerPixel, height and width of the rectangle. We
allocate this buffer one time to be the full size of the buffer. */
static int raw_buffer_size = -1;
static char *raw_buffer;
static z_stream decompStream;
static Bool decompStreamInited = False;
/*
* Variables for the ``tight'' encoding implementation.
*/
/* Separate buffer for compressed data. */
#define ZLIB_BUFFER_SIZE 512
static char zlib_buffer[ZLIB_BUFFER_SIZE];
/* Four independent compression streams for zlib library. */
static z_stream zlibStream[4];
static Bool zlibStreamActive[4] = {
False, False, False, False
};
/* Filter stuff. Should be initialized by filter initialization code. */
static Bool cutZeros;
static int rectWidth, rectColors;
static char tightPalette[256*4];
static CARD8 tightPrevRow[2048*3*sizeof(CARD16)];
/* JPEG decoder state. */
static Bool jpegError;
/*
* ConnectToRFBServer.
*/
Bool
ConnectToRFBServer(const char *hostname, int port)
{
unsigned int host;
if (!StringToIPAddr(hostname, &host)) {
fprintf(stderr,"Couldn't convert '%s' to host address\n", hostname);
return False;
}
rfbsock = ConnectToTcpAddr(host, port);
if (rfbsock < 0) {
fprintf(stderr,"Unable to connect to VNC server\n");
return False;
}
return SetNonBlocking(rfbsock);
}
/*
* InitialiseRFBConnection.
*/
Bool
InitialiseRFBConnection()
{
rfbProtocolVersionMsg pv;
int major,minor;
CARD32 authScheme, reasonLen, authResult;
char *reason;
CARD8 challenge[CHALLENGESIZE];
char passwd[9];
int i;
rfbClientInitMsg ci;
/* if the connection is immediately closed, don't report anything, so
that pmw's monitor can make test connections */
if (!ReadFromRFBServer(pv, sz_rfbProtocolVersionMsg)) return False;
errorMessageOnReadFailure = True;
pv[sz_rfbProtocolVersionMsg] = 0;
if (sscanf(pv,rfbProtocolVersionFormat,&major,&minor) != 2) {
fprintf(stderr,"Not a valid VNC server\n");
return False;
}
fprintf(stderr,"VNC server supports protocol version %d.%d (viewer %d.%d)\n",
major, minor, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
major = rfbProtocolMajorVersion;
minor = rfbProtocolMinorVersion;
sprintf(pv,rfbProtocolVersionFormat,major,minor);
if (!WriteExact(rfbsock, pv, sz_rfbProtocolVersionMsg)) return False;
if (!ReadFromRFBServer((char *)&authScheme, 4)) return False;
authScheme = Swap32IfLE(authScheme);
switch (authScheme) {
case rfbConnFailed:
if (!ReadFromRFBServer((char *)&reasonLen, 4)) return False;
reasonLen = Swap32IfLE(reasonLen);
reason = malloc(reasonLen);
if (!ReadFromRFBServer(reason, reasonLen)) return False;
fprintf(stderr,"VNC connection failed: %.*s\n",(int)reasonLen, reason);
free(reason);
return False;
case rfbNoAuth:
fprintf(stderr,"No authentication needed\n");
break;
case rfbVncAuth:
if (!ReadFromRFBServer((char *)challenge, CHALLENGESIZE)) return False;
if (!getPassword(passwd, 8))
return False;
passwd[8] = '\0';
vncEncryptBytes(challenge, passwd);
/* Lose the password from memory */
for (i = strlen(passwd); i >= 0; i--) {
passwd[i] = '\0';
}
if (!WriteExact(rfbsock, (char *)challenge, CHALLENGESIZE)) return False;
if (!ReadFromRFBServer((char *)&authResult, 4)) return False;
authResult = Swap32IfLE(authResult);
switch (authResult) {
case rfbVncAuthOK:
fprintf(stderr,"VNC authentication succeeded\n");
break;
case rfbVncAuthFailed:
fprintf(stderr,"VNC authentication failed\n");
return False;
case rfbVncAuthTooMany:
fprintf(stderr,"VNC authentication failed - too many tries\n");
return False;
default:
fprintf(stderr,"Unknown VNC authentication result: %d\n",
(int)authResult);
return False;
}
break;
default:
fprintf(stderr,"Unknown authentication scheme from VNC server: %d\n",
(int)authScheme);
return False;
}
ci.shared = (appData.shareDesktop ? 1 : 0);
if (!WriteExact(rfbsock, (char *)&ci, sz_rfbClientInitMsg)) return False;
if (!ReadFromRFBServer((char *)&si, sz_rfbServerInitMsg)) return False;
si.framebufferWidth = Swap16IfLE(si.framebufferWidth);
si.framebufferHeight = Swap16IfLE(si.framebufferHeight);
si.format.redMax = Swap16IfLE(si.format.redMax);
si.format.greenMax = Swap16IfLE(si.format.greenMax);
si.format.blueMax = Swap16IfLE(si.format.blueMax);
si.nameLength = Swap32IfLE(si.nameLength);
desktopName = malloc(si.nameLength + 1);
if (!desktopName) {
fprintf(stderr, "Error allocating memory for desktop name, %lu bytes\n",
(unsigned long)si.nameLength);
return False;
}
if (!ReadFromRFBServer(desktopName, si.nameLength)) return False;
desktopName[si.nameLength] = 0;
fprintf(stderr,"Desktop name \"%s\"\n",desktopName);
fprintf(stderr,"Connected to VNC server, using protocol version %d.%d\n",
rfbProtocolMajorVersion, rfbProtocolMinorVersion);
fprintf(stderr,"VNC server default format:\n");
PrintPixelFormat(&si.format);
return True;
}
/*
* SetFormatAndEncodings.
*/
Bool
SetFormatAndEncodings()
{
rfbSetPixelFormatMsg spf;
char buf[sz_rfbSetEncodingsMsg + MAX_ENCODINGS * 4];
rfbSetEncodingsMsg *se = (rfbSetEncodingsMsg *)buf;
CARD32 *encs = (CARD32 *)(&buf[sz_rfbSetEncodingsMsg]);
int len = 0;
Bool requestCompressLevel = False;
Bool requestQualityLevel = False;
Bool requestLastRectEncoding = False;
spf.type = rfbSetPixelFormat;
spf.format = myFormat;
spf.format.redMax = Swap16IfLE(spf.format.redMax);
spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
if (!WriteExact(rfbsock, (char *)&spf, sz_rfbSetPixelFormatMsg))
return False;
se->type = rfbSetEncodings;
se->nEncodings = 0;
if (appData.encodingsString) {
const char *encStr = appData.encodingsString;
int encStrLen;
do {
char *nextEncStr = strchr(encStr, ' ');
if (nextEncStr) {
encStrLen = nextEncStr - encStr;
nextEncStr++;
} else {
encStrLen = strlen(encStr);
}
if (strncasecmp(encStr,"raw",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
} else if (strncasecmp(encStr,"copyrect",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
} else if (strncasecmp(encStr,"tight",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
requestLastRectEncoding = True;
if (appData.compressLevel >= 0 && appData.compressLevel <= 9)
requestCompressLevel = True;
if (appData.qualityLevel >= 0 && appData.qualityLevel <= 9)
requestQualityLevel = True;
} else if (strncasecmp(encStr,"hextile",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
} else if (strncasecmp(encStr,"zlib",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
if (appData.compressLevel >= 0 && appData.compressLevel <= 9)
requestCompressLevel = True;
} else if (strncasecmp(encStr,"corre",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
} else if (strncasecmp(encStr,"rre",encStrLen) == 0) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
} else {
fprintf(stderr,"Unknown encoding '%.*s'\n",encStrLen,encStr);
}
encStr = nextEncStr;
} while (encStr && se->nEncodings < MAX_ENCODINGS);
if (se->nEncodings < MAX_ENCODINGS && requestCompressLevel) {
encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel +
rfbEncodingCompressLevel0);
}
if (se->nEncodings < MAX_ENCODINGS && requestQualityLevel) {
encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel +
rfbEncodingQualityLevel0);
}
if (appData.useRemoteCursor) {
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
}
if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
}
}
else {
if (SameMachine(rfbsock)) {
fprintf(stderr,"Same machine: preferring raw encoding\n");
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRaw);
}
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCopyRect);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingTight);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingHextile);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingZlib);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingCoRRE);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRRE);
if (appData.compressLevel >= 0 && appData.compressLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE(appData.compressLevel +
rfbEncodingCompressLevel0);
}
if (appData.qualityLevel >= 0 && appData.qualityLevel <= 9) {
encs[se->nEncodings++] = Swap32IfLE(appData.qualityLevel +
rfbEncodingQualityLevel0);
}
if (appData.useRemoteCursor) {
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingXCursor);
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingRichCursor);
}
encs[se->nEncodings++] = Swap32IfLE(rfbEncodingLastRect);
}
len = sz_rfbSetEncodingsMsg + se->nEncodings * 4;
se->nEncodings = Swap16IfLE(se->nEncodings);
if (!WriteExact(rfbsock, buf, len)) return False;
return True;
}
/*
* SendIncrementalFramebufferUpdateRequest.
* Note: this should only be called by the WriterThread
*/
Bool
SendIncrementalFramebufferUpdateRequest()
{
return SendFramebufferUpdateRequest(0, 0, si.framebufferWidth,
si.framebufferHeight, True);
}
/*
* SendFramebufferUpdateRequest.
* Note: this should only be called by the WriterThread
*/
Bool
SendFramebufferUpdateRequest(int x, int y, int w, int h, Bool incremental)
{
rfbFramebufferUpdateRequestMsg fur;
fur.type = rfbFramebufferUpdateRequest;
fur.incremental = incremental ? 1 : 0;
fur.x = Swap16IfLE(x);
fur.y = Swap16IfLE(y);
fur.w = Swap16IfLE(w);
fur.h = Swap16IfLE(h);
if (!WriteExact(rfbsock, (char *)&fur, sz_rfbFramebufferUpdateRequestMsg))
return False;
return True;
}
/*
* SendPointerEvent.
* Note: this should only be called by the WriterThread
*/
Bool
SendPointerEvent(int x, int y, int buttonMask)
{
rfbPointerEventMsg pe;
pe.type = rfbPointerEvent;
pe.buttonMask = buttonMask;
if (x < 0) x = 0;
if (y < 0) y = 0;
SoftCursorMove(x, y);
pe.x = Swap16IfLE(x);
pe.y = Swap16IfLE(y);
return WriteExact(rfbsock, (char *)&pe, sz_rfbPointerEventMsg);
}
/*
* SendKeyEvent.
* Note: this should only be called by the WriterThread
*/
Bool
SendKeyEvent(CARD32 key, Bool down)
{
rfbKeyEventMsg ke;
ke.type = rfbKeyEvent;
ke.down = down ? 1 : 0;
ke.key = Swap32IfLE(key);
return WriteExact(rfbsock, (char *)&ke, sz_rfbKeyEventMsg);
}
/*
* SendClientCutText.
* Note: this should only be called by the WriterThread
*/
Bool
SendClientCutText(char *str, int len)
{
rfbClientCutTextMsg cct;
if (serverCutText)
free(serverCutText);
serverCutText = NULL;
cct.type = rfbClientCutText;
cct.length = Swap32IfLE(len);
return (WriteExact(rfbsock, (char *)&cct, sz_rfbClientCutTextMsg) &&
WriteExact(rfbsock, str, len));
}
/*
* HandleRFBServerMessage.
*/
Bool
HandleRFBServerMessage()
{
rfbServerToClientMsg msg;
if (!ReadFromRFBServer((char *)&msg, 1))
return False;
switch (msg.type) {
case rfbSetColourMapEntries:
{
int i;
CARD16 rgb[3];
XColor xc;
if (!ReadFromRFBServer(((char *)&msg) + 1,
sz_rfbSetColourMapEntriesMsg - 1))
return False;
msg.scme.firstColour = Swap16IfLE(msg.scme.firstColour);
msg.scme.nColours = Swap16IfLE(msg.scme.nColours);
for (i = 0; i < msg.scme.nColours; i++) {
if (!ReadFromRFBServer((char *)rgb, 6))
return False;
xc.pixel = msg.scme.firstColour + i;
xc.red = Swap16IfLE(rgb[0]);
xc.green = Swap16IfLE(rgb[1]);
xc.blue = Swap16IfLE(rgb[2]);
xc.flags = DoRed|DoGreen|DoBlue;
lockQt();
XStoreColor(dpy, cmap, &xc);
unlockQt();
}
break;
}
case rfbFramebufferUpdate:
{
rfbFramebufferUpdateRectHeader rect;
int linesToRead;
int bytesPerLine;
int i;
if (!ReadFromRFBServer(((char *)&msg.fu) + 1,
sz_rfbFramebufferUpdateMsg - 1))
return False;
msg.fu.nRects = Swap16IfLE(msg.fu.nRects);
for (i = 0; i < msg.fu.nRects; i++) {
if (!ReadFromRFBServer((char *)&rect, sz_rfbFramebufferUpdateRectHeader))
return False;
rect.encoding = Swap32IfLE(rect.encoding);
if (rect.encoding == rfbEncodingLastRect)
break;
rect.r.x = Swap16IfLE(rect.r.x);
rect.r.y = Swap16IfLE(rect.r.y);
rect.r.w = Swap16IfLE(rect.r.w);
rect.r.h = Swap16IfLE(rect.r.h);
if (rect.encoding == rfbEncodingXCursor) {
if (!HandleXCursor(rect.r.x, rect.r.y, rect.r.w, rect.r.h)) {
return False;
}
continue;
}
if (rect.encoding == rfbEncodingRichCursor) {
if (!HandleRichCursor(rect.r.x, rect.r.y, rect.r.w, rect.r.h)) {
return False;
}
continue;
}
if ((rect.r.x + rect.r.w > si.framebufferWidth) ||
(rect.r.y + rect.r.h > si.framebufferHeight))
{
fprintf(stderr,"Rect too large: %dx%d at (%d, %d)\n",
rect.r.w, rect.r.h, rect.r.x, rect.r.y);
return False;
}
if (rect.r.h * rect.r.w == 0) {
fprintf(stderr,"Zero size rect - ignoring\n");
continue;
}
/* If RichCursor encoding is used, we should prevent collisions
between framebuffer updates and cursor drawing operations. */
SoftCursorLockArea(rect.r.x, rect.r.y, rect.r.w, rect.r.h);
switch (rect.encoding) {
case rfbEncodingRaw:
bytesPerLine = rect.r.w * myFormat.bitsPerPixel / 8;
linesToRead = BUFFER_SIZE / bytesPerLine;
while (rect.r.h > 0) {
if (linesToRead > rect.r.h)
linesToRead = rect.r.h;
if (!ReadFromRFBServer(buffer,bytesPerLine * linesToRead))
return False;
CopyDataToScreen(buffer, rect.r.x, rect.r.y, rect.r.w,
linesToRead);
rect.r.h -= linesToRead;
rect.r.y += linesToRead;
}
break;
case rfbEncodingCopyRect:
{
rfbCopyRect cr;
if (!ReadFromRFBServer((char *)&cr, sz_rfbCopyRect))
return False;
cr.srcX = Swap16IfLE(cr.srcX);
cr.srcY = Swap16IfLE(cr.srcY);
/* If RichCursor encoding is used, we should extend our
"cursor lock area" (previously set to destination
rectangle) to the source rectangle as well. */
SoftCursorLockArea(cr.srcX, cr.srcY, rect.r.w, rect.r.h);
lockQt();
if (appData.copyRectDelay != 0) {
XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
rect.r.w, rect.r.h);
XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y,
rect.r.w, rect.r.h);
XSync(dpy,False);
unlockQt();
usleep(appData.copyRectDelay * 1000);
lockQt();
XFillRectangle(dpy, desktopWin, dstGC, rect.r.x, rect.r.y,
rect.r.w, rect.r.h);
XFillRectangle(dpy, desktopWin, srcGC, cr.srcX, cr.srcY,
rect.r.w, rect.r.h);
}
XCopyArea(dpy, desktopWin, desktopWin, gc, cr.srcX, cr.srcY,
rect.r.w, rect.r.h, rect.r.x, rect.r.y);
unlockQt();
break;
}
case rfbEncodingRRE:
{
switch (myFormat.bitsPerPixel) {
case 8:
if (!HandleRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 16:
if (!HandleRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 32:
if (!HandleRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
}
break;
}
case rfbEncodingCoRRE:
{
switch (myFormat.bitsPerPixel) {
case 8:
if (!HandleCoRRE8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 16:
if (!HandleCoRRE16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 32:
if (!HandleCoRRE32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
}
break;
}
case rfbEncodingHextile:
{
switch (myFormat.bitsPerPixel) {
case 8:
if (!HandleHextile8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 16:
if (!HandleHextile16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 32:
if (!HandleHextile32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
}
break;
}
case rfbEncodingZlib:
{
switch (myFormat.bitsPerPixel) {
case 8:
if (!HandleZlib8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 16:
if (!HandleZlib16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 32:
if (!HandleZlib32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
}
break;
}
case rfbEncodingTight:
{
switch (myFormat.bitsPerPixel) {
case 8:
if (!HandleTight8(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 16:
if (!HandleTight16(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
case 32:
if (!HandleTight32(rect.r.x,rect.r.y,rect.r.w,rect.r.h))
return False;
break;
}
break;
}
default:
fprintf(stderr,"Unknown rect encoding %d\n",
(int)rect.encoding);
return False;
}
/* Now we may discard "soft cursor locks". */
SoftCursorUnlockScreen();
}
/* if using shared memory PutImage, make sure that the X server has
updated its framebuffer before we reuse the shared memory. This is
mainly to avoid copyrect using invalid screen contents - not sure
if we'd need it otherwise. */
ShmSync();
queueIncrementalUpdateRequest();
break;
}
case rfbBell:
{
Window toplevelWin;
fprintf(stderr, "tugce bell\n");
lockQt();
XBell(dpy, 0);
unlockQt();
break;
}
case rfbServerCutText:
{
fprintf(stderr, "tugce cut\n");
if (!ReadFromRFBServer(((char *)&msg) + 1,
sz_rfbServerCutTextMsg - 1))
return False;
msg.sct.length = Swap32IfLE(msg.sct.length);
if (serverCutText)
free(serverCutText);
serverCutText = malloc(msg.sct.length+1);
if (!ReadFromRFBServer(serverCutText, msg.sct.length))
return False;
serverCutText[msg.sct.length] = 0;
newServerCutText = True;
break;
}
default:
fprintf(stderr,"Unknown message type %d from VNC server\n",msg.type);
return False;
}
return True;
}
#define GET_PIXEL8(pix, ptr) ((pix) = *(ptr)++)
#define GET_PIXEL16(pix, ptr) (((CARD8*)&(pix))[0] = *(ptr)++, \
((CARD8*)&(pix))[1] = *(ptr)++)
#define GET_PIXEL32(pix, ptr) (((CARD8*)&(pix))[0] = *(ptr)++, \
((CARD8*)&(pix))[1] = *(ptr)++, \
((CARD8*)&(pix))[2] = *(ptr)++, \
((CARD8*)&(pix))[3] = *(ptr)++)
/* CONCAT2 concatenates its two arguments. CONCAT2E does the same but also
expands its arguments if they are macros */
#define CONCAT2(a,b) a##b
#define CONCAT2E(a,b) CONCAT2(a,b)
#define BPP 8
#include "rre.c"
#include "corre.c"
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
#undef BPP
#define BPP 16
#include "rre.c"
#include "corre.c"
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
#undef BPP
#define BPP 32
#include "rre.c"
#include "corre.c"
#include "hextile.c"
#include "zlib.c"
#include "tight.c"
#undef BPP
/*
* PrintPixelFormat.
*/
void
PrintPixelFormat(format)
rfbPixelFormat *format;
{
if (format->bitsPerPixel == 1) {
fprintf(stderr," Single bit per pixel.\n");
fprintf(stderr,
" %s significant bit in each byte is leftmost on the screen.\n",
(format->bigEndian ? "Most" : "Least"));
} else {
fprintf(stderr," %d bits per pixel.\n",format->bitsPerPixel);
if (format->bitsPerPixel != 8) {
fprintf(stderr," %s significant byte first in each pixel.\n",
(format->bigEndian ? "Most" : "Least"));
}
if (format->trueColour) {
fprintf(stderr," True colour: max red %d green %d blue %d",
format->redMax, format->greenMax, format->blueMax);
fprintf(stderr,", shift red %d green %d blue %d\n",
format->redShift, format->greenShift, format->blueShift);
} else {
fprintf(stderr," Colour map (not true colour).\n");
}
}
}
static long
ReadCompactLen (void)
{
long len;
CARD8 b;
if (!ReadFromRFBServer((char *)&b, 1))
return -1;
len = (int)b & 0x7F;
if (b & 0x80) {
if (!ReadFromRFBServer((char *)&b, 1))
return -1;
len |= ((int)b & 0x7F) << 7;
if (b & 0x80) {
if (!ReadFromRFBServer((char *)&b, 1))
return -1;
len |= ((int)b & 0xFF) << 14;
}
}
return len;
}
/*
* JPEG source manager functions for JPEG decompression in Tight decoder.
*/
static struct jpeg_source_mgr jpegSrcManager;
static JOCTET *jpegBufferPtr;
static size_t jpegBufferLen;
static void
JpegInitSource(j_decompress_ptr cinfo)
{
jpegError = False;
}
static boolean
JpegFillInputBuffer(j_decompress_ptr cinfo)
{
jpegError = True;
jpegSrcManager.bytes_in_buffer = jpegBufferLen;
jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr;
return TRUE;
}
static void
JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes)
{
if (num_bytes < 0 || num_bytes > jpegSrcManager.bytes_in_buffer) {
jpegError = True;
jpegSrcManager.bytes_in_buffer = jpegBufferLen;
jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr;
} else {
jpegSrcManager.next_input_byte += (size_t) num_bytes;
jpegSrcManager.bytes_in_buffer -= (size_t) num_bytes;
}
}
static void
JpegTermSource(j_decompress_ptr cinfo)
{
/* No work necessary here. */
}
static void
JpegSetSrcManager(j_decompress_ptr cinfo, CARD8 *compressedData,
int compressedLen)
{
jpegBufferPtr = (JOCTET *)compressedData;
jpegBufferLen = (size_t)compressedLen;
jpegSrcManager.init_source = JpegInitSource;
jpegSrcManager.fill_input_buffer = JpegFillInputBuffer;
jpegSrcManager.skip_input_data = JpegSkipInputData;
jpegSrcManager.resync_to_restart = jpeg_resync_to_restart;
jpegSrcManager.term_source = JpegTermSource;
jpegSrcManager.next_input_byte = jpegBufferPtr;
jpegSrcManager.bytes_in_buffer = jpegBufferLen;
cinfo->src = &jpegSrcManager;
}

View File

@ -1,785 +0,0 @@
/*
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* 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.
*/
/*****************************************************************************
*
* 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.
*/
#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 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. FIXME: Add more documentation.
*/
#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).
*/
/*-----------------------------------------------------------------------------
* 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;

View File

@ -1,86 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* rre.c - handle RRE encoding.
*
* This file shouldn't be compiled directly. It is included multiple times by
* rfbproto.c, each time with a different definition of the macro BPP. For
* each value of BPP, this file defines a function which handles an RRE
* encoded rectangle with BPP bits per pixel.
*/
#define HandleRREBPP CONCAT2E(HandleRRE,BPP)
#define CARDBPP CONCAT2E(CARD,BPP)
static Bool
HandleRREBPP (int rx, int ry, int rw, int rh)
{
rfbRREHeader hdr;
XGCValues gcv;
int i;
CARDBPP pix;
rfbRectangle subrect;
if (!ReadFromRFBServer((char *)&hdr, sz_rfbRREHeader))
return False;
hdr.nSubrects = Swap32IfLE(hdr.nSubrects);
if (!ReadFromRFBServer((char *)&pix, sizeof(pix)))
return False;
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
gcv.foreground = pix;
#endif
lockQt();
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
unlockQt();
for (i = 0; i < hdr.nSubrects; i++) {
if (!ReadFromRFBServer((char *)&pix, sizeof(pix)))
return False;
if (!ReadFromRFBServer((char *)&subrect, sz_rfbRectangle))
return False;
subrect.x = Swap16IfLE(subrect.x);
subrect.y = Swap16IfLE(subrect.y);
subrect.w = Swap16IfLE(subrect.w);
subrect.h = Swap16IfLE(subrect.h);
#if (BPP == 8)
gcv.foreground = (appData.useBGR233 ? BGR233ToPixel[pix] : pix);
#else
gcv.foreground = pix;
#endif
lockQt();
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx + subrect.x, ry + subrect.y,
subrect.w, subrect.h);
unlockQt();
}
return True;
}

View File

@ -1,446 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* 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;
tx.tv_sec = SELECT_PERIOD;
tx.tv_usec = 0;
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);
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 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);
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 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, char *_buf, int n)
{
fd_set fds;
int i = 0;
int j;
int e;
struct timeval tx;
tx.tv_sec = SELECT_PERIOD;
tx.tv_usec = 0;
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);
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 -1;
}
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("krdc: ConnectToTcpAddr: connect");
close(sock);
return -1;
}
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
perror("krdc: ConnectToTcpAddr: setsockopt");
close(sock);
return -1;
}
return sock;
}
/*
* FindFreeTcpPort tries to find unused TCP port in the range
* (TUNNEL_PORT_OFFSET, TUNNEL_PORT_OFFSET + 99]. Returns 0 on failure.
*/
int
FindFreeTcpPort(void)
{
int sock, port;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("krdc: FindFreeTcpPort: socket");
return 0;
}
for (port = TUNNEL_PORT_OFFSET + 99; port > TUNNEL_PORT_OFFSET; port--) {
addr.sin_port = htons((unsigned short)port);
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
close(sock);
return port;
}
}
close(sock);
return 0;
}
/*
* ListenAtTcpPort starts listening at the given TCP port.
*/
int
ListenAtTcpPort(int port)
{
int sock;
struct sockaddr_in addr;
int one = 1;
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = INADDR_ANY;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0) {
perror("krdc: ListenAtTcpPort: socket");
return -1;
}
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(const char *)&one, sizeof(one)) < 0) {
perror("krdc: ListenAtTcpPort: setsockopt");
close(sock);
return -1;
}
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
perror("krdc: ListenAtTcpPort: bind");
close(sock);
return -1;
}
if (listen(sock, 5) < 0) {
perror("krdc: ListenAtTcpPort: listen");
close(sock);
return -1;
}
return sock;
}
/*
* AcceptTcpConnection accepts a TCP connection.
*/
int
AcceptTcpConnection(int listenSock)
{
int sock;
struct sockaddr_in addr;
int addrlen = sizeof(addr);
int one = 1;
sock = accept(listenSock, (struct sockaddr *) &addr, &addrlen);
if (sock < 0) {
perror("krdc: AcceptTcpConnection: accept");
return -1;
}
if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
(char *)&one, sizeof(one)) < 0) {
perror("krdc: AcceptTcpConnection: setsockopt");
close(sock);
return -1;
}
return sock;
}
/*
* SetNonBlocking sets a socket into non-blocking mode.
*/
Bool
SetNonBlocking(int sock)
{
if (fcntl(sock, F_SETFL, O_NONBLOCK) < 0) {
perror("krdc: AcceptTcpConnection: fcntl");
return False;
}
return True;
}
/*
* 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;
}
/*
* Test if the other end of a socket is on the same machine.
*/
Bool
SameMachine(int sock)
{
struct sockaddr_in peeraddr, myaddr;
int addrlen = sizeof(struct sockaddr_in);
getpeername(sock, (struct sockaddr *)&peeraddr, &addrlen);
getsockname(sock, (struct sockaddr *)&myaddr, &addrlen);
return (peeraddr.sin_addr.s_addr == myaddr.sin_addr.s_addr);
}
/*
* Print out the contents of a packet for debugging.
*/
void
PrintInHex(char *_buf, int len)
{
int i, j;
char c, str[17];
str[16] = 0;
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);
}

View File

@ -1,242 +0,0 @@
/***************************************************************************
threads.cpp - threads
-------------------
begin : Thu May 09 17:01:44 CET 2002
copyright : (C) 2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#include "kvncview.h"
#include "threads.h"
#include "kdebug.h"
static const int WAIT_PERIOD = 5000;
static const unsigned int MOUSEPRESS_QUEUE_SIZE = 10;
static const unsigned int MOUSEMOVE_QUEUE_SIZE = 5;
static const unsigned int KEY_QUEUE_SIZE = 8192;
ControllerThread::ControllerThread(KVncView *v, WriterThread &wt, volatile bool &quitFlag) :
m_view(v),
m_status(REMOTE_VIEW_CONNECTING),
m_wthread(wt),
m_quitFlag(quitFlag)
{
}
void ControllerThread::changeStatus(RemoteViewStatus s) {
m_status = s;
QThread::postEvent(m_view, new StatusChangeEvent(s));
}
void ControllerThread::run() {
if (!ConnectToRFBServer(m_view->host().latin1(), m_view->port())) {
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
return;
}
changeStatus(REMOTE_VIEW_AUTHENTICATING);
if (!InitialiseRFBConnection()) {
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
return;
}
QThread::postEvent(m_view, new ScreenResizeEvent(si.framebufferWidth,
si.framebufferHeight));
changeStatus(REMOTE_VIEW_PREPARING);
lockQt();
SetVisualAndCmap();
ToplevelInit();
DesktopInit(m_view->winId());
unlockQt();
SetFormatAndEncodings();
changeStatus(REMOTE_VIEW_CONNECTED);
m_wthread.start();
while (!m_quitFlag) {
if (!HandleRFBServerMessage())
break;
}
m_quitFlag = true;
changeStatus(REMOTE_VIEW_DISCONNECTED);
}
enum RemoteViewStatus ControllerThread::status() {
return m_status;
}
static WriterThread *writerThread;
void queueIncrementalUpdateRequest() {
writerThread->queueIncrementalUpdateRequest();
}
WriterThread::WriterThread(volatile bool &quitFlag) :
m_quitFlag(quitFlag)
{
writerThread = this;
}
bool WriterThread::sendIncrementalUpdateRequest() {
return SendIncrementalFramebufferUpdateRequest();
}
bool WriterThread::sendUpdateRequest(const QRegion &region) {
QMemArray<QRect> r = region.rects();
for (unsigned int i = 0; i < r.size(); i++)
if (!SendFramebufferUpdateRequest(r[i].x(),
r[i].y(),
r[i].width(),
r[i].height(), False))
return false;
return true;
}
bool WriterThread::sendMouseEvents(const QValueList<MouseEvent> &events) {
QValueList<MouseEvent>::const_iterator it = events.begin();
while (it != events.end()) {
if (!SendPointerEvent((*it).x, (*it).y, (*it).buttons))
return false;
it++;
}
return true;
}
bool WriterThread::sendKeyEvents(const QValueList<KeyEvent> &events) {
QValueList<KeyEvent>::const_iterator it = events.begin();
while (it != events.end()) {
if (!SendKeyEvent((*it).k, (*it).down ? True : False))
return false;
it++;
}
return true;
}
void WriterThread::queueIncrementalUpdateRequest() {
m_lock.lock();
m_incrementalUpdateRQ = true;
m_waiter.wakeAll();
m_lock.unlock();
}
void WriterThread::queueUpdateRequest(const QRegion &r) {
m_lock.lock();
m_updateRegionRQ += r;
m_waiter.wakeAll();
m_lock.unlock();
}
void WriterThread::queueMouseEvent(int x, int y, int buttonMask) {
MouseEvent e;
e.x = x;
e.y = y;
e.buttons = buttonMask;
m_lock.lock();
if (m_mouseEvents.size() > 0) {
if ((e.x == m_mouseEvents.last().x) &&
(e.y == m_mouseEvents.last().y) &&
(e.buttons == m_mouseEvents.last().buttons)) {
m_lock.unlock();
return;
}
if (m_mouseEvents.size() >= MOUSEPRESS_QUEUE_SIZE) {
m_lock.unlock();
return;
}
if ((m_mouseEvents.last().buttons == buttonMask) &&
(m_mouseEvents.size() >= MOUSEMOVE_QUEUE_SIZE)) {
m_lock.unlock();
return;
}
}
m_mouseEvents.push_back(e);
m_waiter.wakeAll();
m_lock.unlock();
}
void WriterThread::queueKeyEvent(unsigned int k, bool down) {
KeyEvent e;
e.k = k;
e.down = down;
m_lock.lock();
if (m_keyEvents.size() >= KEY_QUEUE_SIZE) {
m_lock.unlock();
return;
}
m_keyEvents.push_back(e);
m_waiter.wakeAll();
m_lock.unlock();
}
void WriterThread::kick() {
m_waiter.wakeAll();
}
void WriterThread::run() {
bool incrementalUpdateRQ = false;
QRegion updateRegionRQ;
QValueList<MouseEvent> mouseEvents;
QValueList<KeyEvent> keyEvents;
while (!m_quitFlag) {
m_lock.lock();
incrementalUpdateRQ = m_incrementalUpdateRQ;
updateRegionRQ = m_updateRegionRQ;
mouseEvents = m_mouseEvents;
keyEvents = m_keyEvents;
if ((!incrementalUpdateRQ) &&
(updateRegionRQ.isNull()) &&
(mouseEvents.size() == 0) &&
(keyEvents.size() == 0)) {
m_waiter.wait(&m_lock, WAIT_PERIOD);
m_lock.unlock();
}
else {
m_incrementalUpdateRQ = false;
m_updateRegionRQ = QRegion();
m_mouseEvents.clear();
m_keyEvents.clear();
m_lock.unlock();
if (incrementalUpdateRQ)
if (!sendIncrementalUpdateRequest())
break;
if (!updateRegionRQ.isNull())
if (!sendUpdateRequest(updateRegionRQ))
break;
if (mouseEvents.size() != 0)
if (!sendMouseEvents(mouseEvents))
break;
if (keyEvents.size() != 0)
if (!sendKeyEvents(keyEvents))
break;
}
}
m_quitFlag = true;
}

View File

@ -1,146 +0,0 @@
/***************************************************************************
threads.h - threads for kvncview
-------------------
begin : Thu May 09 16:01:42 CET 2002
copyright : (C) 2002 by Tim Jansen
email : tim@tjansen.de
***************************************************************************/
/***************************************************************************
* *
* 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. *
* *
***************************************************************************/
#ifndef THREADS_H
#define THREADS_H
#ifndef VNCVIEWER_H
#define VNCVIEWER_H
#include "vncviewer.h"
#endif
#include <qthread.h>
#include <qregion.h>
#include <qrect.h>
#include <qmutex.h>
#include <qwaitcondition.h>
#include <qevent.h>
#include <qvaluelist.h>
class KVncView;
enum RemoteViewStatus {
REMOTE_VIEW_CONNECTING,
REMOTE_VIEW_AUTHENTICATING,
REMOTE_VIEW_PREPARING,
REMOTE_VIEW_CONNECTED,
REMOTE_VIEW_DISCONNECTED
};
const int ScreenResizeEventType = 781001;
class ScreenResizeEvent : public QCustomEvent
{
private:
int m_width, m_height;
public:
ScreenResizeEvent(int w, int h) :
QCustomEvent(ScreenResizeEventType),
m_width(w),
m_height(h)
{};
int width() const { return m_width; };
int height() const { return m_height; };
};
const int StatusChangeEventType = 781002;
class StatusChangeEvent : public QCustomEvent
{
private:
RemoteViewStatus m_status;
public:
StatusChangeEvent(RemoteViewStatus s) :
QCustomEvent(StatusChangeEventType),
m_status(s)
{};
RemoteViewStatus status() const { return m_status; };
};
const int PasswordRequiredEventType = 781003;
class PasswordRequiredEvent : public QCustomEvent
{
public:
PasswordRequiredEvent() :
QCustomEvent(PasswordRequiredEventType)
{};
};
struct MouseEvent {
int x, y, buttons;
};
struct KeyEvent {
unsigned int k;
bool down;
};
class WriterThread : public QThread {
private:
QMutex m_lock;
QWaitCondition m_waiter;
volatile bool &m_quitFlag;
// all things that can be send follow:
int m_incrementalUpdateRQ; // for sending an incremental request
QRegion m_updateRegionRQ; // for sending updates, null if it is done
QValueList<MouseEvent> m_mouseEvents; // list of unsent mouse events
QValueList<KeyEvent> m_keyEvents; // list of unsent key events
public:
WriterThread(volatile bool &quitFlag);
void queueIncrementalUpdateRequest();
void queueUpdateRequest(const QRegion &r);
void queueMouseEvent(int x, int y, int buttonMask);
void queueKeyEvent(unsigned int k, bool down);
void kick();
protected:
void run();
bool sendIncrementalUpdateRequest();
bool sendUpdateRequest(const QRegion &r);
bool sendMouseEvents(const QValueList<MouseEvent> &events);
bool sendKeyEvents(const QValueList<KeyEvent> &events);
};
class ControllerThread : public QThread {
private:
KVncView *m_view;
enum RemoteViewStatus m_status;
WriterThread &m_wthread;
volatile bool &m_quitFlag;
void changeStatus(RemoteViewStatus s);
public:
ControllerThread(KVncView *v, WriterThread &wt, volatile bool &quitFlag);
enum RemoteViewStatus status();
protected:
void run();
};
#endif

View File

@ -1,611 +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* tight.c - handle ``tight'' encoding.
*
* This file shouldn't be compiled directly. It is included multiple
* times by rfbproto.c, each time with a different definition of the
* macro BPP. For each value of BPP, this file defines a function
* which handles a tight-encoded rectangle with BPP bits per pixel.
*
*/
#define TIGHT_MIN_TO_COMPRESS 12
#define CARDBPP CONCAT2E(CARD,BPP)
#define filterPtrBPP CONCAT2E(filterPtr,BPP)
#define HandleTightBPP CONCAT2E(HandleTight,BPP)
#define InitFilterCopyBPP CONCAT2E(InitFilterCopy,BPP)
#define InitFilterPaletteBPP CONCAT2E(InitFilterPalette,BPP)
#define InitFilterGradientBPP CONCAT2E(InitFilterGradient,BPP)
#define FilterCopyBPP CONCAT2E(FilterCopy,BPP)
#define FilterPaletteBPP CONCAT2E(FilterPalette,BPP)
#define FilterGradientBPP CONCAT2E(FilterGradient,BPP)
#if BPP != 8
#define DecompressJpegRectBPP CONCAT2E(DecompressJpegRect,BPP)
#endif
#ifndef RGB_TO_PIXEL
#define RGB_TO_PIXEL(bpp,r,g,b) \
(((CARD##bpp)(r) & myFormat.redMax) << myFormat.redShift | \
((CARD##bpp)(g) & myFormat.greenMax) << myFormat.greenShift | \
((CARD##bpp)(b) & myFormat.blueMax) << myFormat.blueShift)
#define RGB24_TO_PIXEL(bpp,r,g,b) \
((((CARD##bpp)(r) & 0xFF) * myFormat.redMax + 127) / 255 \
<< myFormat.redShift | \
(((CARD##bpp)(g) & 0xFF) * myFormat.greenMax + 127) / 255 \
<< myFormat.greenShift | \
(((CARD##bpp)(b) & 0xFF) * myFormat.blueMax + 127) / 255 \
<< myFormat.blueShift)
#define RGB24_TO_PIXEL32(r,g,b) \
(((CARD32)(r) & 0xFF) << myFormat.redShift | \
((CARD32)(g) & 0xFF) << myFormat.greenShift | \
((CARD32)(b) & 0xFF) << myFormat.blueShift)
#endif
/* 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
#if (BPP == 8)
gcv.foreground = (appData.useBGR233) ?
BGR233ToPixel[fill_colour] : fill_colour;
#else
gcv.foreground = fill_colour;
#endif
lockQt();
XChangeGC(dpy, gc, GCForeground, &gcv);
XFillRectangle(dpy, desktopWin, gc, rx, ry, rw, rh);
unlockQt();
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;
delault:
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;
}
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

View File

@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* 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);
}
}

View File

@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* 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);

View File

@ -1,205 +0,0 @@
/*
* Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
* Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
* Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
/*
* vncviewer.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xmd.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>
#include <X11/Xmu/StdSel.h>
#if(defined __cplusplus)
extern "C"
{
#endif
#include "rfbproto.h"
extern int endianTest;
#define Swap16IfLE(s) \
(*(char *)&endianTest ? ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff)) : (s))
#define Swap32IfLE(l) \
(*(char *)&endianTest ? ((((l) & 0xff000000) >> 24) | \
(((l) & 0x00ff0000) >> 8) | \
(((l) & 0x0000ff00) << 8) | \
(((l) & 0x000000ff) << 24)) : (l))
#define MAX_ENCODINGS 20
#define FLASH_PORT_OFFSET 5400
#define LISTEN_PORT_OFFSET 5500
#define TUNNEL_PORT_OFFSET 5500
#define SERVER_PORT_OFFSET 5900
#define DEFAULT_SSH_CMD "/usr/bin/ssh"
#define DEFAULT_TUNNEL_CMD \
(DEFAULT_SSH_CMD " -f -L %L:localhost:%R %H sleep 20")
#define DEFAULT_VIA_CMD \
(DEFAULT_SSH_CMD " -f -L %L:%H:%R %G sleep 20")
/** main.cpp **/
typedef enum {
QUALITY_UNKNOWN,
QUALITY_HIGH,
QUALITY_MEDIUM,
QUALITY_LOW
} Quality;
typedef struct {
Bool shareDesktop;
Bool viewOnly;
const char* encodingsString;
Bool useBGR233;
int nColours;
Bool useSharedColours;
int requestedDepth;
int rawDelay;
int copyRectDelay;
Bool debug;
int compressLevel;
int qualityLevel;
Bool useRemoteCursor;
} AppData;
extern AppData appData;
extern Display* dpy;
extern const char *vncServerHost;
extern int vncServerPort;
extern int isQuitFlagSet();
extern void lockQt();
extern void unlockQt();
extern void unlockQtGui();
extern int getPassword(char *passwd, int pwlen);
/* threads.cpp */
extern void queueIncrementalUpdateRequest();
/* colour.c */
extern unsigned long BGR233ToPixel[];
extern Colormap cmap;
extern Visual *vis;
extern unsigned int visdepth, visbpp;
extern void SetVisualAndCmap(void);
/* cursor.c */
extern Bool HandleXCursor(int xhot, int yhot, int width, int height);
extern Bool HandleRichCursor(int xhot, int yhot, int width, int height);
extern void SoftCursorLockArea(int x, int y, int w, int h);
extern void SoftCursorUnlockScreen(void);
extern void SoftCursorMove(int x, int y);
/* desktop.c */
extern Widget form, viewport, desktop;
extern Window desktopWin;
extern Cursor dotCursor;
extern GC gc;
extern GC srcGC, dstGC;
extern Dimension dpyWidth, dpyHeight;
extern void DesktopInit(Window win);
extern void ToplevelInit(void);
extern void SendRFBEvent(XEvent *event, String *params, Cardinal *num_params);
extern void CopyDataToScreen(char *buf, int x, int y, int width, int height);
extern void ShmSync(void);
extern void Cleanup(void);
/* rfbproto.c */
extern int rfbsock;
extern Bool canUseCoRRE;
extern Bool canUseHextile;
extern char *desktopName;
extern rfbPixelFormat myFormat;
extern rfbServerInitMsg si;
extern char *serverCutText;
extern Bool newServerCutText;
extern Bool ConnectToRFBServer(const char *hostname, int port);
extern Bool InitialiseRFBConnection(void);
extern Bool SetFormatAndEncodings(void);
extern Bool SendIncrementalFramebufferUpdateRequest(void);
extern Bool SendFramebufferUpdateRequest(int x, int y, int w, int h,
Bool incremental);
extern Bool SendPointerEvent(int x, int y, int buttonMask);
extern Bool SendKeyEvent(CARD32 key, Bool down);
extern Bool SendClientCutText(char *str, int len);
extern Bool HandleRFBServerMessage(void);
extern void PrintPixelFormat(rfbPixelFormat *format);
/* selection.c */
extern void InitialiseSelection(void);
extern void SelectionToVNC(Widget w, XEvent *event, String *params,
Cardinal *num_params);
extern void SelectionFromVNC(Widget w, XEvent *event, String *params,
Cardinal *num_params);
/* shm.c */
extern XImage *CreateShmImage(void);
extern void ShmCleanup(void);
/* sockets.c */
extern Bool errorMessageOnReadFailure;
extern Bool ReadFromRFBServer(char *out, unsigned int n);
extern Bool WriteExact(int sock, char *buf, int n);
extern int FindFreeTcpPort(void);
extern int ListenAtTcpPort(int port);
extern int ConnectToTcpAddr(unsigned int host, int port);
extern int AcceptTcpConnection(int listenSock);
extern Bool SetNonBlocking(int sock);
extern int StringToIPAddr(const char *str, unsigned int *addr);
extern Bool SameMachine(int sock);
#if(defined __cplusplus)
}
#endif

View File

@ -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., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* 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;
}