diff -r winvnc_orig/resource.h winvnc/resource.h
48a49
> #define IDR_HTML1                       157
159c160
< #define _APS_NEXT_RESOURCE_VALUE        156
---
> #define _APS_NEXT_RESOURCE_VALUE        158
diff -r winvnc_orig/stdhdrs.cpp winvnc/stdhdrs.cpp
32c32
< Log vnclog(0, 1, "WinVNC.log", false);
---
> Log vnclog(2, 20, "WinVNC.log", false);
diff -r winvnc_orig/vncDesktop.cpp winvnc/vncDesktop.cpp
2125c2125
< 		if (m_server->IncrRgnRequested())
---
> 		if (1 || m_server->IncrRgnRequested())
2210a2211,2214
>       // Save changes to region
>       m_last_changed_rgn.Clear();
>       m_last_changed_rgn.Combine(m_changed_rgn);
> 
2551a2556
>   if (bytes_in_row <= 0) return;
diff -r winvnc_orig/vncDesktop.h winvnc/vncDesktop.h
69a70
>   friend class vncHTTPConnectThread;
268a270
>   vncRegion   m_last_changed_rgn;
diff -r winvnc_orig/vncHTTPConnect.cpp winvnc/vncHTTPConnect.cpp
36a37,38
> #include <stdio.h>
> #include <string.h>
37a40,44
> extern "C" {
> #include "libjpeg/jpeglib.h"
> }
> #define XK_MISCELLANY
> #include "keysymdef.h"
40c47
< const char HTTP_MSG_OK[] = "HTTP/1.0 200 OK\n\n";
---
> const char HTTP_MSG_OK[] = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n";
185a193
>   char * str, * str2;
207a216,226
> 	static int width=0, height=0, depth=0;
>   static vncDesktop * v_desktop = NULL;
>   if (!v_desktop) {
>     v_desktop = new vncDesktop();
>     m_server->m_desktop = v_desktop;
>     v_desktop->Init(m_server);
>     v_desktop->CheckUpdates();
>   }
>   if (!width) {
> 		m_server->GetScreenInfo(width, height, depth);
>   }
217,219d235
< 		// Send the OK notification message to the client
< 		if (!socket->SendExact(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
< 			return;
224d239
< 			int width, height, depth;
227,270d241
< 			m_server->GetScreenInfo(width, height, depth);
< 
< 			// Get the name of this desktop
< 			char desktopname[MAX_COMPUTERNAME_LENGTH + 1];
< 			DWORD desktopnamelen = MAX_COMPUTERNAME_LENGTH + 1;
< 			if (GetComputerName(desktopname, &desktopnamelen))
< 			{
< 				// Make the name lowercase
< 				for (size_t x = 0; x < strlen(desktopname); x++)
< 				{
< 					desktopname[x] = tolower(desktopname[x]);
< 				}
< 			}
< 			else
< 			{
< 				strcpy(desktopname, "WinVNC");
< 			}
< 
< 			// Parse the applet parameters if specified within URL
< 			char params[1024] = "";
< 			if (filename[1] == '?') {
< 				if (!ParseParams(&filename[2], params, 1024)) {
< 					socket->SendExact(HTTP_MSG_BADPARAMS,
< 									  strlen(HTTP_MSG_BADPARAMS));
< 					return;
< 				}
< 			}
< 
< 			// Send the java applet page
< 			sprintf(indexpage, HTTP_FMT_INDEX,
< 					desktopname, width, height+32, m_server->GetPort(), params);
< 		}
< 		else
< 		{
< 			// Send a "sorry, not allowed" page
< 			sprintf(indexpage, HTTP_MSG_NOSOCKCONN);
< 		}
< 
< 		// Send the page
< 		if (socket->SendExact(indexpage, strlen(indexpage)))
< 			vnclog.Print(LL_INTINFO, VNCLOG("sent page\n"));
< 
< 		return;
< 	}
272,273c243
< 	// File requested was not the index so check the mappings
< 	// list for a different file.
---
> 			vnclog.Print(LL_INTINFO, VNCLOG("requested file recognised as index file\n"));
275,293c245,246
< 	// Now search the mappings for the desired file
< 	for (int x=0; x < filemappingsize; x++)
< 	{
< 		if (strcmp(filename, filemapping[x].filename) == 0)
< 		{
< 			HRSRC resource;
< 			HGLOBAL resourcehan;
< 			char *resourceptr;
< 			int resourcesize;
< 
< 			vnclog.Print(LL_INTINFO, VNCLOG("requested file recognised\n"));
< 
< 			// Find the resource here
< 			resource = FindResource(NULL,
< 					MAKEINTRESOURCE(filemapping[x].resourceID),
< 					filemapping[x].type
< 					);
< 			if (resource == NULL)
< 				return;
---
> 			FILE * index = fopen("res/webvnc.html", "r");
>       if (!index) return;
295,296d247
< 			// Get its size
< 			resourcesize = SizeofResource(NULL, resource);
298,301c249
< 			// Load the resource
< 			resourcehan = LoadResource(NULL, resource);
< 			if (resourcehan == NULL)
< 				return;
---
>       vnclog.Print(LL_INTINFO, VNCLOG("sending file...\n"));
303,308c251
< 			// Lock the resource
< 			resourceptr = (char *)LockResource(resourcehan);
< 			if (resourceptr == NULL)
< 				return;
< 
< 			vnclog.Print(LL_INTINFO, VNCLOG("sending file...\n"));
---
>       str = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\nConnection: close\r\n\r\n";
311,315c254
< 			if (!socket->SendExact(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
< 				return;
< 
< 			// Now send the entirety of the data to the client
< 			if (!socket->SendExact(resourceptr, resourcesize))
---
> 			if (!socket->SendExact(str, strlen(str)))
318c257,277
< 			vnclog.Print(LL_INTINFO, VNCLOG("file successfully sent\n"));
---
>       while (!feof(index)) {
>         int len;
>         len = fread(indexpage, 1, 2047, index);
>         indexpage[len] = 0;
>         if (str = strstr(indexpage, "__W__")) {
>           _snprintf(str, 5, "%05d", width);
>         }
>         socket->SendExact(indexpage, len);
>       }
>       fclose(index);
> 		}
> 		else
> 		{
> 		  // Send the OK notification message to the client
> 		  if (!socket->SendExact(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
> 			  return;
> 			// Send a "sorry, not allowed" page
> 			sprintf(indexpage, HTTP_MSG_NOSOCKCONN);
> 		  // Send the page
> 		  if (socket->SendExact(indexpage, strlen(indexpage)))
> 			  vnclog.Print(LL_INTINFO, VNCLOG("sent page\n"));
320d278
< 			return;
322d279
< 	}
324,325d280
< 	// Send the NoSuchFile notification message to the client
< 	if (!socket->SendExact(HTTP_MSG_NOSUCHFILE, strlen(HTTP_MSG_NOSUCHFILE)))
326a282,538
> 	}
>   
>   static unsigned long cookie = 0;
>   static const int tileSize = 300;
> 
>   str = "HTTP/1.1 200 OK\r\nConnection: close\r\n";
>   socket->SendExact(str, strlen(str));
>   char gbuf[1024];
>   DWORD m_flags;
>   static char * imgbuffer = NULL;
>   char * scanlinebuffer = NULL;
>   rectlist rects;
> 
>   int cookiecheck;
>   int validated = 0;
>   char * parmstart = filename + 1;
>   if (sscanf(filename, "/%x/", &cookiecheck) && cookiecheck == cookie) {
>     validated = 1;
>     parmstart = strchr(filename + 1, '/') + 1;
>   }
> 
>   switch(parmstart[0]) {
>     case 'i':
>       //Initialize - log in and give back screen parameters
>       //Grab password from URL (url like /ipassword)
>       str = parmstart + 1;
>       char passbytes[MAXPWLEN];
>       memset(passbytes, 0, MAXPWLEN);
>       if (strlen(str) > 8) str[8] = 0;
>       memcpy(passbytes, str, strlen(str));
>       vncEncryptPasswd("", passbytes);
>       char passbytes2[MAXPWLEN];
>       m_server->GetPassword(passbytes2);
>       str2 = vncDecryptPasswd(passbytes2);
>       if (!strcmp(str, str2)) {
>         str = "Content-type: text/plain\r\n\r\n";
>         socket->SendExact(str, strlen(str));
>         srand(time(NULL));
>         cookie = rand() + (rand() << 8) + (rand() << 16) + (rand() << 24);
>         _snprintf(gbuf, 1024, "%d,%d,%d,%08X", width, height, tileSize, cookie);
>         socket->SendExact(gbuf, strlen(gbuf));
>       }
>       else {
>         str = "Content-type: text/plain\r\n\r\n0,0,0,00000000";
>         socket->SendExact(str, strlen(str));
>       }
>       break;
>     case 'c':
>       if (!validated) return;
>       //Control request - delay until changed tiles show up!
>       str = "Content-type: text/plain\r\n\r\n";
>       socket->SendExact(str, strlen(str));
>       v_desktop->CheckUpdates();
>       time_t lastAMsent;
>       lastAMsent = time(NULL);
>       while (!(v_desktop->m_last_changed_rgn.Rectangles(rects))) {
>         Sleep(100);
>         v_desktop->CheckUpdates();
>         if (time(NULL) - lastAMsent > 30) {
>           socket->SendExact("_", 1);
>           lastAMsent = time(NULL);
>         }
>       }
>       bool * changedArray;
>       int tilewidth;
>       int tileheight;
>       tilewidth = (width + (tileSize - 1)) / tileSize;
>       tileheight = (height + (tileSize - 1)) / tileSize;
>       changedArray = new bool[tilewidth * tileheight];
>       memset(changedArray, 0, tilewidth * tileheight * sizeof(bool));
>       while (!rects.empty()) {
>         RECT rec = rects.front();
>         rec.left -= v_desktop->m_bmrect.left;
>         rec.top -= v_desktop->m_bmrect.top;
>         rec.right -= v_desktop->m_bmrect.left;
>         rec.bottom -= v_desktop->m_bmrect.top;
>         for (int x = rec.left / tileSize; x <= rec.right / tileSize; x++) {
>           for (int y = rec.top / tileSize; y <= rec.bottom / tileSize; y++) {
>             if (x < 0 || y < 0 || x >= tilewidth || y >= tileheight) continue;
>             changedArray[x + y*tilewidth] = true;
>           }
>         }
>         rects.pop_front();
>       }
>       for (int x = 0; x < tilewidth; x++) {
>         for (int y = 0; y < tileheight; y++) {
>           if (changedArray[x + y*tilewidth]) {
>             _snprintf(gbuf, 1024, "%d,%d;", x, y);
>             socket->SendExact(gbuf, strlen(gbuf));
>           }
>         }
>       }
>       delete changedArray;
>       break;
>     case 'm':
>       if (!validated) return;
>       //Mouse clickey
>       int mbtn, mousex, mousey;
>       sscanf(parmstart + 1, "%d,%d,%d", &mbtn, &mousex, &mousey);
>       m_flags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE;
>       mousex += v_desktop->m_bmrect.left;
>       mousey += v_desktop->m_bmrect.top;
>       mousex = mousex * 65536 / v_desktop->m_bmrect.right;
>       mousey = mousey * 65536 / v_desktop->m_bmrect.bottom;
>       if (mbtn == 0) {
>         mouse_event(m_flags, mousex, mousey, 0, NULL);
>       }
>       if (mbtn >= 1 && mbtn <= 3) {
>         if (mbtn == 1) mouse_event(m_flags | MOUSEEVENTF_LEFTDOWN, mousex, mousey, 0, NULL);
>         if (mbtn == 2) mouse_event(m_flags | MOUSEEVENTF_MIDDLEDOWN, mousex, mousey, 0, NULL);
>         if (mbtn == 3) mouse_event(m_flags | MOUSEEVENTF_RIGHTDOWN, mousex, mousey, 0, NULL);
>         Sleep(5);
>         if (mbtn == 1) mouse_event(m_flags | MOUSEEVENTF_LEFTUP, mousex, mousey, 0, NULL);
>         if (mbtn == 2) mouse_event(m_flags | MOUSEEVENTF_MIDDLEUP, mousex, mousey, 0, NULL);
>         if (mbtn == 3) mouse_event(m_flags | MOUSEEVENTF_RIGHTUP, mousex, mousey, 0, NULL);
>       }
>       if (mbtn == 4) {
>         mouse_event(m_flags | MOUSEEVENTF_WHEEL, mousex, mousey, 120, NULL);
>       }
>       if (mbtn == 5) {
>         mouse_event(m_flags | MOUSEEVENTF_WHEEL, mousex, mousey, -120, NULL);
>       }
>       if (mbtn == 6) {
>         mouse_event(m_flags | MOUSEEVENTF_LEFTDOWN, mousex, mousey, 0, NULL);
>         Sleep(5);
>         mouse_event(m_flags | MOUSEEVENTF_LEFTUP, mousex, mousey, 0, NULL);
>         Sleep(5);
>         mouse_event(m_flags | MOUSEEVENTF_LEFTDOWN, mousex, mousey, 0, NULL);
>         Sleep(5);
>         mouse_event(m_flags | MOUSEEVENTF_LEFTUP, mousex, mousey, 0, NULL);
>       }
>       if (mbtn == 7) {
>         mouse_event(m_flags | MOUSEEVENTF_LEFTDOWN, mousex, mousey, 0, NULL);
>       }
>       if (mbtn == 8) {
>         mouse_event(m_flags | MOUSEEVENTF_LEFTUP, mousex, mousey, 0, NULL);
>       }
>       str = "Content-type: text/html\r\nContent-length: 6\r\n\r\nThanks";
>       socket->SendExact(str, strlen(str));
>       break;
>     case 'f':
>       if (!validated) return;
>       //Fetch tile
>       int fetchx, fetchy;
>       FILE * outfile;
>       RECT rect;
>       jpeg_compress_struct cinfo;
>       char tmpfilename[1024];
>       int response;
>       JSAMPROW row_pointer[1];
>       jpeg_error_mgr jerr;
>       cinfo.err = jpeg_std_error(&jerr);
> 
>       sscanf(parmstart + 1, "%d,%d", &fetchx, &fetchy);
>       if (fetchx * tileSize > width
>           || fetchy * tileSize > height
>           || fetchx < 0
>           || fetchy < 0) return;
>       _snprintf(tmpfilename, 1024, "res/tmp_%02X_%02d_%02d.jpg", rand(), fetchx, fetchy);
>       outfile = fopen(tmpfilename, "wb");
>       if (!outfile) return;
>       if (!imgbuffer) imgbuffer = new char[width * height * depth / 8];
>       rect.left = fetchx * tileSize;
>       rect.top = fetchy * tileSize;
>       rect.bottom = rect.top + tileSize;
>       rect.right = rect.left + tileSize;
>       if (rect.bottom > height) rect.bottom = height;
>       if (rect.right > width) rect.right = width;
>       rect.top += v_desktop->m_bmrect.top;
>       rect.bottom += v_desktop->m_bmrect.top;
>       rect.left += v_desktop->m_bmrect.left;
>       rect.right += v_desktop->m_bmrect.left;
>       v_desktop->CopyToBuffer(rect, (BYTE *)imgbuffer);
>       jpeg_create_compress(&cinfo);
>       jpeg_stdio_dest(&cinfo, outfile);
>       cinfo.image_height = rect.bottom - rect.top;
>       cinfo.image_width = rect.right - rect.left;
>       cinfo.input_components = 3;
>       cinfo.in_color_space = JCS_RGB;
>       jpeg_set_defaults(&cinfo);
>       jpeg_set_quality(&cinfo, 20, false);
>       jpeg_start_compress(&cinfo, TRUE);
>       scanlinebuffer = new char[tileSize * 3];
>       for (int scan = 0; scan < cinfo.image_height; scan++) {
>         str = (imgbuffer + (depth/8) * (width * (fetchy * tileSize + scan) + fetchx * tileSize));
>         for (int x = 0; x < cinfo.image_width; x++) {
>           scanlinebuffer[x*3] = str[x*4+2];
>           scanlinebuffer[x*3+1] = str[x*4+1];
>           scanlinebuffer[x*3+2] = str[x*4];
>         }
>         row_pointer[0] = (JSAMPROW)scanlinebuffer;
>         jpeg_write_scanlines(&cinfo, row_pointer, 1);
>       }
>       delete scanlinebuffer;
>       jpeg_finish_compress(&cinfo);
>       jpeg_destroy_compress(&cinfo);
>       response = ftell(outfile);
>       fseek(outfile, 0, SEEK_SET);
>       _snprintf(gbuf, 1024, "Content-type: image/jpeg\r\nContent-length: %d\r\n\r\n", response);
>       socket->SendExact(gbuf, strlen(gbuf));
>       fclose(outfile);
>       if (outfile = fopen(tmpfilename, "rb")) {
>         while (!feof(outfile)) {
>           response = fread(gbuf, 1, 1024, outfile);
>           socket->SendExact(gbuf, response);
>           Sleep(10);
>         }
>         fclose(outfile);
>       }
>       unlink(tmpfilename);
> 
>       break;
>     case 'k':
>       if (!validated) return;
>       //Key events
>       str = parmstart + 1;
>       char * pc;
>       pc = strchr(str, ' ');
>       if (pc) *pc = 0;
>       for (int i = 0; i < 1024; i++) {
>         unsigned int chr = str[i];
>         if (chr == 0) break;
>         if (chr == '%') {
>           int v;
>           if (_snscanf(str + i + 1, 1023 - i, "%02x", &v)) {
>             chr = v;
>             for (int j = 0; j < 2 && str[i]; j++, i++);
>           }
>           else {
>             break;
>           }
>         }
>       switch (chr) {
>         case '\x0D': chr = XK_Return; break;
>         case '\x08': chr = XK_BackSpace; break;
>         case '\x1B': chr = XK_Escape; break;
>         }
>       vncKeymap::keyEvent(chr, 1, m_server);
>       vncKeymap::keyEvent(chr, 0, m_server);
>       }
>       str = "Content-type: text/html\r\nContent-length: 6\r\n\r\nThanks";
>       socket->SendExact(str, strlen(str));
>       break;
>     case 'h':
>       //Crosshair image
>       str = "Content-type: image/png\r\n\r\n";
>       socket->SendExact(str, strlen(str));
>       outfile = fopen("res/crosshair.png", "rb");
>       if (outfile) {
>         while (!feof(outfile)) {
>           response = fread(gbuf, 1, 1024, outfile);
>           socket->SendExact(gbuf, response);
>         }
>         fclose(outfile);
>       }
>       break;
>   }
diff -r winvnc_orig/vncServer.h winvnc/vncServer.h
67a68,69
>   friend class vncHTTPConnectThread;
> 