vnchttpconnect.cpp
来自「Web VNC samples delphi」· C++ 代码 · 共 851 行 · 第 1/2 页
CPP
851 行
// Copyright (C) 2002 Constantin Kaplinsky. All Rights Reserved.
// Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
// This file is part of the VNC system.
//
// The VNC system is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// TightVNC distribution homepage on the Web: http://www.tightvnc.com/
//
// If the source code for the VNC system is not available from the place
// whence you received this file, check http://www.uk.research.att.com/vnc or contact
// the authors on vnc@uk.research.att.com for information on obtaining it.
// vncHTTPConnect.cpp
// Implementation of the HTTP server class
#include "stdhdrs.h"
#include "VSocket.h"
#include "vncHTTPConnect.h"
#include "vncServer.h"
#include <omnithread.h>
#include <stdio.h>
#include <string.h>
#include "resource.h"
extern "C" {
#include "libjpeg/jpeglib.h"
}
#define XK_MISCELLANY
#include "keysymdef.h"
// HTTP messages / message formats
const char HTTP_MSG_OK[] = "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n";
const char HTTP_FMT_INDEX[] =
"<HTML>\n"
" <HEAD><TITLE>TightVNC desktop [%.256s]</TITLE></HEAD>\n"
" <BODY>\n"
" <APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar WIDTH=%d HEIGHT=%d>\n"
" <PARAM NAME=\"PORT\" VALUE=\"%d\">\n"
"%.1024s"
" </APPLET><BR>\n"
" <A HREF=\"http://www.tightvnc.com/\">www.TightVNC.com</A>\n"
" </BODY>\n"
"</HTML>\n";
const char HTTP_MSG_NOSOCKCONN [] =
"<HTML>\n"
" <HEAD><TITLE>TightVNC desktop</TITLE></HEAD>\n"
" <BODY>\n"
" <H1>Connections Disabled</H1>\n"
" The requested desktop is not configured to accept incoming connections.\n"
" </BODY>\n"
"</HTML>\n";
const char HTTP_MSG_BADPARAMS [] =
"<HTML>\n"
" <HEAD><TITLE>TightVNC desktop</TITLE></HEAD>\n"
" <BODY>\n"
" <H1>Bad Parameters</H1>\n"
" The sequence of applet parameters specified within the URL is invalid.\n"
" </BODY>\n"
"</HTML>\n";
const char HTTP_MSG_NOSUCHFILE [] =
"HTTP/1.0 404 Not Found\n\n"
"<HTML>\n"
" <HEAD><TITLE>404 Not Found</TITLE></HEAD>\n"
" <BODY>\n"
" <H1>Not Found</H1>\n"
" The requested file could not be found.\n"
" </BODY>\n"
"</HTML>\n";
// Filename to resource ID mappings for the Java class files:
typedef struct _FileToResourceMap {
char *filename;
char *type;
int resourceID;
} FileMap;
const FileMap filemapping [] = {
{"/VncViewer.jar", "JavaArchive", IDR_VNCVIEWER_JAR},
{"/AuthPanel.class", "JavaClass", IDR_AUTHPANEL_CLASS},
{"/ClipboardFrame.class", "JavaClass", IDR_CLIPBOARDFRAME_CLASS},
{"/DesCipher.class", "JavaClass", IDR_DESCIPHER_CLASS},
{"/OptionsFrame.class", "JavaClass", IDR_OPTIONSFRAME_CLASS},
{"/RfbProto.class", "JavaClass", IDR_RFBPROTO_CLASS},
{"/VncCanvas.class", "JavaClass", IDR_VNCCANVAS_CLASS},
{"/VncCanvas2.class", "JavaClass", IDR_VNCCANVAS2_CLASS},
{"/VncViewer.class", "JavaClass", IDR_VNCVIEWER_CLASS},
{"/ButtonPanel.class", "JavaClass", IDR_BUTTONPANEL_CLASS},
{"/RecordingFrame.class", "JavaClass", IDR_RECFRAME_CLASS},
{"/SessionRecorder.class", "JavaClass", IDR_SESSIONREC_CLASS},
{"/ReloginPanel.class", "JavaClass", IDR_RELOGINPANEL_CLASS},
{"/SocketFactory.class", "JavaClass", IDR_SOCKFACTORY_CLASS},
{"/CapabilityInfo.class", "JavaClass", IDR_CAPINFO_CLASS},
{"/CapsContainer.class", "JavaClass", IDR_CAPSCONTAINER_CLASS},
{"/InStream.class", "JavaClass", IDR_INSTREAM_CLASS},
{"/MemInStream.class", "JavaClass", IDR_MEMINSTREAM_CLASS},
{"/ZlibInStream.class", "JavaClass", IDR_ZLIBINSTREAM_CLASS},
};
const int filemappingsize = 19;
#define WINDOW_LIST_MAX 1024
static HWND windowList[WINDOW_LIST_MAX];
static int windowListCount;
BOOL CALLBACK wndEnumProc(HWND hWnd, LPARAM lParam) {
if (windowListCount >= WINDOW_LIST_MAX) return FALSE;
windowList[windowListCount++] = hWnd;
return TRUE;
}
//
// Connection thread -- one per each client connection.
//
class vncHTTPConnectThread : public omni_thread
{
public:
// Init routine
virtual BOOL Init(VSocket *socket, vncServer *server, BOOL allow_params);
// Code to be executed by the thread
virtual void run(void *arg);
// Routines to handle HTTP requests
virtual void DoHTTP(VSocket *socket);
virtual BOOL ParseParams(const char *request, char *result, int max_bytes);
BOOL ValidateString(char *str);
virtual char *ReadLine(VSocket *socket, char delimiter, int max);
protected:
// Fields used internally
vncServer *m_server;
VSocket *m_socket;
BOOL m_allow_params;
};
// Method implementations
BOOL vncHTTPConnectThread::Init(VSocket *socket, vncServer *server,
BOOL allow_params)
{
m_server = server;
m_socket = socket;
m_allow_params = allow_params;
// Start the thread
start();
return TRUE;
}
// Code to be executed by the thread
void vncHTTPConnectThread::run(void *arg)
{
vnclog.Print(LL_INTINFO, VNCLOG("started HTTP client thread\n"));
// Perform the transaction
DoHTTP(m_socket);
m_socket->Close();
// And close the client
delete m_socket;
vnclog.Print(LL_INTINFO, VNCLOG("quitting HTTP client thread\n"));
}
void vncHTTPConnectThread::DoHTTP(VSocket *socket)
{
char filename[1024];
char *line;
// Read in the HTTP header
if ((line = ReadLine(socket, '\n', 1024)) == NULL)
return;
// Scan the header for the filename and free the storage
int result = sscanf(line, "GET %s HTTP/", filename);
delete [] line;
if (result != 1)
return;
vnclog.Print(LL_CLIENTS, VNCLOG("file %s requested\n"), filename);
// Read in the rest of the browser's request data and discard...
BOOL newline = TRUE;
char * str, * str2;
char c;
for (;;) {
if (!socket->ReadExact(&c, 1))
return;
if (c == '\n') {
if (newline)
break;
newline = TRUE;
} else {
if (c >= ' ')
newline = FALSE;
}
}
vnclog.Print(LL_INTINFO, VNCLOG("HTTP headers skipped\n"));
if (filename[0] != '/') {
vnclog.Print(LL_CONNERR, VNCLOG("filename didn't begin with '/'\n"));
socket->SendExact(HTTP_MSG_NOSUCHFILE, strlen(HTTP_MSG_NOSUCHFILE));
return;
}
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);
}
// Switch, dependent upon the filename:
if (filename[1] == '\0' || filename[1] == '?')
{
char indexpage[2048];
int prefwidth = 320;
if (filename[1] == '?' && (line = strstr(filename + 1, "pagewidth="))) {
line += strlen("pagewidth=");
sscanf(line, "%d", &prefwidth);
}
// Compose the index page
if (m_server->SockConnected())
{
// Get the screen's dimensions
vnclog.Print(LL_INTINFO, VNCLOG("requested file recognised as index file\n"));
FILE * index = fopen("res/webvnc.html", "r");
if (!index) 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";
// Send the OK message
if (!socket->SendExact(str, strlen(str)))
return;
while (!feof(index)) {
int len;
len = fread(indexpage, 1, 2047, index);
indexpage[len] = 0;
if (str = strstr(indexpage, "__W__")) {
_snprintf(str, 5, "%05d", prefwidth);
}
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"));
}
return;
}
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 > 10) {
_snprintf(gbuf, 1024, "0,0,%d,%d;", width, height);
return;
}
}
bool * changedArray;
int tilewidth;
int tileheight;
tilewidth = (width + (tileSize - 1)) / tileSize;
tileheight = (height + (tileSize - 1)) / tileSize;
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;
_snprintf(gbuf, 1024, "%d,%d,%d,%d;", rec.left, rec.top, rec.right, rec.bottom);
socket->SendExact(gbuf, strlen(gbuf));
rects.pop_front();
}
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, offsetx, offsety;
FILE * outfile;
RECT rect;
jpeg_compress_struct cinfo;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?