From 9f0a1a3bc16d26420c703c6e6cc0f18bd4f6b81e Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Mon, 28 Jul 2003 00:57:52 +0000
Subject: synced with TightVNC and RealVNC

---
 ChangeLog       |   7 ++++
 TODO            |  21 ++++++-----
 main.c          |  10 ++++--
 rfb/rfb.h       |   7 ++++
 rfb/rfbregion.h |   2 ++
 rfbregion.c     |  33 ++++++++++++++++++
 rfbserver.c     | 106 +++++++++++++++++++++++++++++++++-----------------------
 sockets.c       |   3 ++
 tight.c         |  21 +++++++----
 vncauth.c       |   8 +++--
 10 files changed, 156 insertions(+), 62 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 469b967..ad82706 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+   checked sync with TightVNC 1.2.8:
+	viewonly/full passwords; if given a list, only the first is a full one
+	vncRandomBytes is a little more secure now
+	new weights for tight encoding
+   checked sync with RealVNC 3.3.7
+	introduced maxRectsPerUpdate
    added first alpha version of LibVNCClient
    added simple and simple15 example (really simple examples)
    finally got around to fix configure in CVS
@@ -20,6 +26,7 @@
    more portable way to determine endianness and types of a given size
 	through autoconf based methods
 0.5
+   rpm packaging through autoconf
    autoconf'ed the whole package (including optional support for zlib,
 	pthreads and libjpeg as well as zrle/c++)
    moved appropriate files to contrib/ and examples/ respectively
diff --git a/TODO b/TODO
index 8811e0c..ef09115 100644
--- a/TODO
+++ b/TODO
@@ -1,20 +1,14 @@
 immediate:
 ----------
 
-x11vnc: clipboard, cursor
+TightVNC encoding!!! Regression!!!
 extra_bytes in rfbDrawCharWithClip.
 tested mouse buttons make copy rect, but text is not marked as mod.
-cursor drawing: set optional grain to mark bigger rectangles as drawn (else
-	you end up with thousands of one-pixel-rectangles to encode).
-selectbox: scroll bars
-documentation
-	hint that to mark very tiny regions as
-	modified is possibly inefficient for the encodings.
-	(a trail of points could better be a small rectangle).
 
 later:
 ------
 
+selectbox: scroll bars
 authentification schemes (secure vnc)
 	IO function ptr exists; now explain how to tunnel and implement a
 	client address restriction scheme.
@@ -24,6 +18,17 @@ CORBA
 done:
 -----
 
+.following two items overridden by RealVNC's idea: if there are too many
+	rectangles (like >50), just use the bounding box.
+  cursor drawing: set optional grain to mark bigger rectangles as drawn (else
+	you end up with thousands of one-pixel-rectangles to encode).
+  documentation
+	hint that to mark very tiny regions as
+	modified is possibly inefficient for the encodings.
+	(a trail of points could better be a small rectangle).
+
+.viewonly/full password method
+.x11vnc: clipboard, cursor (Karl's work)
 .autoconf also CARD8,CARD16,...
 .autoconf
 .internal HTTP tunnelling feature (needs a special GET target and a few
diff --git a/main.c b/main.c
index c2d6bc3..5e8a24d 100644
--- a/main.c
+++ b/main.c
@@ -467,12 +467,16 @@ Bool defaultPasswordCheck(rfbClientPtr cl,const char* response,int len)
 Bool rfbCheckPasswordByList(rfbClientPtr cl,const char* response,int len)
 {
   char **passwds;
+  int i=0;
 
-  for(passwds=(char**)cl->screen->rfbAuthPasswdData;*passwds;passwds++) {
+  for(passwds=(char**)cl->screen->rfbAuthPasswdData;*passwds;passwds++,i++) {
     vncEncryptBytes(cl->authChallenge, *passwds);
 
-    if (memcmp(cl->authChallenge, response, len) == 0)
+    if (memcmp(cl->authChallenge, response, len) == 0) {
+      if(i>=cl->screen->rfbAuthPasswdFirstViewOnly)
+	cl->viewOnly=TRUE;
       return(TRUE);
+    }
   }
 
   rfbLog("rfbAuthProcessClientMessage: authentication failed from %s\n",
@@ -574,6 +578,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
    rfbScreen->rfbNeverShared = FALSE;
    rfbScreen->rfbDontDisconnect = FALSE;
    rfbScreen->rfbAuthPasswdData = 0;
+   rfbScreen->rfbAuthPasswdFirstViewOnly = 1;
    
    rfbScreen->width = width;
    rfbScreen->height = height;
@@ -611,6 +616,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
    IF_PTHREADS(rfbScreen->backgroundLoop = FALSE);
 
    rfbScreen->rfbDeferUpdateTime=5;
+   rfbScreen->maxRectsPerUpdate=50;
 
    /* proc's and hook's */
 
diff --git a/rfb/rfb.h b/rfb/rfb.h
index a76d955..a55f34a 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -232,7 +232,12 @@ typedef struct _rfbScreenInfo
 
     PasswordCheckProcPtr passwordCheck;
     void* rfbAuthPasswdData;
+    /* If rfbAuthPasswdData is given a list, this is the first
+       view only password. */
+    int rfbAuthPasswdFirstViewOnly;
 
+    /* send only this many rectangles in one update */
+    int maxRectsPerUpdate;
     /* this is the amount of milliseconds to wait at least before sending
      * an update. */
     int rfbDeferUpdateTime;
@@ -329,6 +334,8 @@ typedef struct _rfbClientRec {
     int preferredEncoding;
     int correMaxWidth, correMaxHeight;
 
+    Bool viewOnly;
+
     /* The following member is only used during VNC authentication */
     uint8_t authChallenge[CHALLENGESIZE];
 
diff --git a/rfb/rfbregion.h b/rfb/rfbregion.h
index 1bbedf6..95f73e2 100755
--- a/rfb/rfbregion.h
+++ b/rfb/rfbregion.h
@@ -37,6 +37,8 @@ extern Bool sraRgnPopRect(sraRegion *region, sraRect *rect,
 extern unsigned long sraRgnCountRects(const sraRegion *rgn);
 extern Bool sraRgnEmpty(const sraRegion *rgn);
 
+extern sraRegion *sraRgnBBox(const sraRegion *src);
+
 /* -=- rectangle iterator */
 
 typedef struct sraRectangleIterator {
diff --git a/rfbregion.c b/rfbregion.c
index 59b76c5..d3e241a 100755
--- a/rfbregion.c
+++ b/rfbregion.c
@@ -582,6 +582,39 @@ sraRgnOffset(sraRegion *dst, int dx, int dy) {
   }
 }
 
+sraRegion *sraRgnBBox(const sraRegion *src) {
+  int xmin=((unsigned int)(int)-1)>>1,ymin=xmin,xmax=1-xmin,ymax=xmax;
+  sraSpan *vcurr, *hcurr;
+
+  if(!src)
+    return sraRgnCreate();
+
+  vcurr = ((sraSpanList*)src)->front._next;
+  while (vcurr != &(((sraSpanList*)src)->back)) {
+    if(vcurr->start<ymin)
+      ymin=vcurr->start;
+    if(vcurr->end>ymax)
+      ymax=vcurr->end;
+    
+    hcurr = vcurr->subspan->front._next;
+    while (hcurr != &(vcurr->subspan->back)) {
+      if(hcurr->start<xmin)
+	xmin=hcurr->start;
+      if(hcurr->end>xmax)
+	xmax=hcurr->end;
+      fprintf(stderr,"%d,%d,%d,%d\n",hcurr->start,vcurr->start,hcurr->end,vcurr->end);
+      hcurr = hcurr->_next;
+    }
+
+    vcurr = vcurr->_next;
+  }
+
+  if(xmax<xmin || ymax<ymin)
+    return sraRgnCreate();
+
+  return sraRgnCreateRect(xmin,ymin,xmax,ymax);
+}
+
 Bool
 sraRgnPopRect(sraRegion *rgn, sraRect *rect, unsigned long flags) {
   sraSpan *vcurr, *hcurr;
diff --git a/rfbserver.c b/rfbserver.c
index 1403714..9ab205e 100644
--- a/rfbserver.c
+++ b/rfbserver.c
@@ -233,6 +233,8 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
 
     cl->screen = rfbScreen;
     cl->sock = sock;
+    cl->viewOnly = FALSE;
+
     rfbResetStats(cl);
 
     if(isUDP) {
@@ -932,70 +934,78 @@ rfbProcessClientNormalMessage(cl)
 
     case rfbKeyEvent:
 
-        cl->rfbKeyEventsRcvd++;
+	cl->rfbKeyEventsRcvd++;
 
-        if ((n = ReadExact(cl, ((char *)&msg) + 1,
-                           sz_rfbKeyEventMsg - 1)) <= 0) {
-            if (n != 0)
-                rfbLogPerror("rfbProcessClientNormalMessage: read");
-            rfbCloseClient(cl);
-            return;
-        }
+	if ((n = ReadExact(cl, ((char *)&msg) + 1,
+			   sz_rfbKeyEventMsg - 1)) <= 0) {
+	    if (n != 0)
+		rfbLogPerror("rfbProcessClientNormalMessage: read");
+	    rfbCloseClient(cl);
+	    return;
+	}
+
+	if(!cl->viewOnly) {
+	    cl->screen->kbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl);
+	}
 
-        cl->screen->kbdAddEvent(msg.ke.down, (KeySym)Swap32IfLE(msg.ke.key), cl);
         return;
 
 
     case rfbPointerEvent:
 
-        cl->rfbPointerEventsRcvd++;
+	cl->rfbPointerEventsRcvd++;
 
-        if ((n = ReadExact(cl, ((char *)&msg) + 1,
-                           sz_rfbPointerEventMsg - 1)) <= 0) {
-            if (n != 0)
-                rfbLogPerror("rfbProcessClientNormalMessage: read");
-            rfbCloseClient(cl);
-            return;
-        }
+	if ((n = ReadExact(cl, ((char *)&msg) + 1,
+			   sz_rfbPointerEventMsg - 1)) <= 0) {
+	    if (n != 0)
+		rfbLogPerror("rfbProcessClientNormalMessage: read");
+	    rfbCloseClient(cl);
+	    return;
+	}
 
-        if (pointerClient && (pointerClient != cl))
-            return;
+	if (pointerClient && (pointerClient != cl))
+	    return;
 
-        if (msg.pe.buttonMask == 0)
-            pointerClient = NULL;
-        else
-            pointerClient = cl;
+	if (msg.pe.buttonMask == 0)
+	    pointerClient = NULL;
+	else
+	    pointerClient = cl;
+
+	if(!cl->viewOnly) {
+	    cl->screen->ptrAddEvent(msg.pe.buttonMask,
+				    Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
+	}
 
-        cl->screen->ptrAddEvent(msg.pe.buttonMask,
-                    Swap16IfLE(msg.pe.x), Swap16IfLE(msg.pe.y), cl);
         return;
 
 
     case rfbClientCutText:
 
-        if ((n = ReadExact(cl, ((char *)&msg) + 1,
-                           sz_rfbClientCutTextMsg - 1)) <= 0) {
-            if (n != 0)
-                rfbLogPerror("rfbProcessClientNormalMessage: read");
-            rfbCloseClient(cl);
-            return;
-        }
+	if ((n = ReadExact(cl, ((char *)&msg) + 1,
+			   sz_rfbClientCutTextMsg - 1)) <= 0) {
+	    if (n != 0)
+		rfbLogPerror("rfbProcessClientNormalMessage: read");
+	    rfbCloseClient(cl);
+	    return;
+	}
 
-        msg.cct.length = Swap32IfLE(msg.cct.length);
+	if(!cl->viewOnly) {
+	    msg.cct.length = Swap32IfLE(msg.cct.length);
 
-        str = (char *)malloc(msg.cct.length);
+	    str = (char *)malloc(msg.cct.length);
 
-        if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
-            if (n != 0)
-                rfbLogPerror("rfbProcessClientNormalMessage: read");
-            free(str);
-            rfbCloseClient(cl);
-            return;
-        }
+	    if ((n = ReadExact(cl, str, msg.cct.length)) <= 0) {
+		if (n != 0)
+		    rfbLogPerror("rfbProcessClientNormalMessage: read");
+		free(str);
+		rfbCloseClient(cl);
+		return;
+	    }
 
-        cl->screen->setXCutText(str, msg.cct.length, cl);
+	    cl->screen->setXCutText(str, msg.cct.length, cl);
+	    free(str);
+	}
 
-        free(str);
         return;
 
 
@@ -1166,6 +1176,7 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
             nUpdateRegionRects += (((w-1) / cl->correMaxWidth + 1)
                                      * ((h-1) / cl->correMaxHeight + 1));
         }
+	sraRgnReleaseIterator(i);
 #ifdef HAVE_LIBZ
     } else if (cl->preferredEncoding == rfbEncodingZlib) {
 	nUpdateRegionRects = 0;
@@ -1193,6 +1204,7 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
 	    }
 	    nUpdateRegionRects += n;
 	}
+	sraRgnReleaseIterator(i);
 #endif
 #endif
     } else {
@@ -1201,6 +1213,14 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
 
     fu->type = rfbFramebufferUpdate;
     if (nUpdateRegionRects != 0xFFFF) {
+	if(cl->screen->maxRectsPerUpdate>0
+	   && nUpdateRegionRects>cl->screen->maxRectsPerUpdate) {
+	    sraRegion* newUpdateRegion = sraRgnBBox(updateRegion);
+	    sraRgnDestroy(updateRegion);
+	    updateRegion = newUpdateRegion;
+	    nUpdateRegionRects = sraRgnCountRects(updateRegion);
+	}
+
 	fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
 					 nUpdateRegionRects +
 					 !!sendCursorShape + !!sendCursorPos));
diff --git a/sockets.c b/sockets.c
index 3095ec0..c1720a5 100644
--- a/sockets.c
+++ b/sockets.c
@@ -521,6 +521,7 @@ ListenOnTCPPort(port)
     int sock;
     int one = 1;
 
+    memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
     /* addr.sin_addr.s_addr = interface.s_addr; */
@@ -555,6 +556,7 @@ ConnectToTcpAddr(host, port)
     int sock;
     struct sockaddr_in addr;
 
+    memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
 
@@ -587,6 +589,7 @@ ListenOnUDPPort(port)
     int sock;
     int one = 1;
 
+    memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
     /* addr.sin_addr.s_addr = interface.s_addr; */
diff --git a/tight.c b/tight.c
index cdc0495..7bb7c69 100644
--- a/tight.c
+++ b/tight.c
@@ -67,13 +67,13 @@ typedef struct TIGHT_CONF_s {
 } TIGHT_CONF;
 
 static TIGHT_CONF tightConf[10] = {
-    {   512,   32,   6, 65536, 0, 0, 0, 0,   0,   0,   4, 20, 10000, 23000 },
-    {  2048,  128,   6, 65536, 1, 1, 1, 0,   0,   0,   8, 30,  8000, 18000 },
-    {  6144,  256,   8, 65536, 3, 3, 2, 0,   0,   0,  24, 40,  6500, 15000 },
-    { 10240, 1024,  12, 65536, 5, 5, 3, 0,   0,   0,  32, 50,  5000, 12000 },
-    { 16384, 2048,  12, 65536, 6, 6, 4, 0,   0,   0,  32, 55,  4000, 10000 },
-    { 32768, 2048,  12,  4096, 7, 7, 5, 4, 150, 380,  32, 60,  3000,  8000 },
-    { 65536, 2048,  16,  4096, 7, 7, 6, 4, 170, 420,  48, 65,  2000,  5000 },
+    {   512,   32,   6, 65536, 0, 0, 0, 0,   0,   0,   4,  5, 10000, 23000 },
+    {  2048,  128,   6, 65536, 1, 1, 1, 0,   0,   0,   8, 10,  8000, 18000 },
+    {  6144,  256,   8, 65536, 3, 3, 2, 0,   0,   0,  24, 15,  6500, 15000 },
+    { 10240, 1024,  12, 65536, 5, 5, 3, 0,   0,   0,  32, 25,  5000, 12000 },
+    { 16384, 2048,  12, 65536, 6, 6, 4, 0,   0,   0,  32, 37,  4000, 10000 },
+    { 32768, 2048,  12,  4096, 7, 7, 5, 4, 150, 380,  32, 50,  3000,  8000 },
+    { 65536, 2048,  16,  4096, 7, 7, 6, 4, 170, 420,  48, 60,  2000,  5000 },
     { 65536, 2048,  16,  4096, 8, 8, 7, 5, 180, 450,  64, 70,  1000,  2500 },
     { 65536, 2048,  32,  8192, 9, 9, 8, 6, 190, 475,  64, 75,   500,  1200 },
     { 65536, 2048,  32,  8192, 9, 9, 9, 6, 200, 500,  96, 80,   200,   500 }
@@ -432,6 +432,13 @@ ExtendSolidArea(cl, x, y, w, h, colorValue, x_ptr, y_ptr, w_ptr, h_ptr)
     *w_ptr += cx - (*x_ptr + *w_ptr);
 }
 
+/*
+ * Check if a rectangle is all of the same color. If needSameColor is
+ * set to non-zero, then also check that its color equals to the
+ * *colorPtr value. The result is 1 if the test is successfull, and in
+ * that case new color will be stored in *colorPtr.
+ */
+
 static Bool CheckSolidTile(rfbClientPtr cl, int x, int y, int w, int h, uint32_t* colorPtr, Bool needSameColor)
 {
     switch(cl->screen->rfbServerFormat.bitsPerPixel) {
diff --git a/vncauth.c b/vncauth.c
index f701b84..39ba856 100644
--- a/vncauth.c
+++ b/vncauth.c
@@ -142,9 +142,13 @@ void
 vncRandomBytes(unsigned char *bytes)
 {
     int i;
-    unsigned int seed = (unsigned int) time(0);
+    static Bool s_srandom_called = FALSE;
+
+    if (!s_srandom_called) {
+	srandom((unsigned int)time(0) ^ (unsigned int)getpid());
+	s_srandom_called = TRUE;
+    }
 
-    srandom(seed);
     for (i = 0; i < CHALLENGESIZE; i++) {
 	bytes[i] = (unsigned char)(random() & 255);    
     }
-- 
cgit v1.2.3

