vnchttpconnect.cpp
来自「Web VNC samples delphi」· C++ 代码 · 共 851 行 · 第 1/2 页
CPP
851 行
char tmpfilename[1024];
int response;
JSAMPROW row_pointer[1];
jpeg_error_mgr jerr;
cinfo.err = jpeg_std_error(&jerr);
offsetx = tileSize;
offsety = tileSize;
sscanf(parmstart + 1, "%d,%d,%d,%d", &fetchx, &fetchy, &offsetx, &offsety);
if (fetchx > width
|| fetchy > height
|| fetchx < 0
|| fetchy < 0
|| fetchx + offsetx > width
|| fetchy + offsety > height
|| offsetx < 0
|| offsety < 0
|| offsetx > tileSize
|| offsety > tileSize) 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;
rect.top = fetchy;
rect.bottom = rect.top + offsety;
rect.right = rect.left + offsetx;
if (rect.bottom > height) rect.bottom = height;
if (rect.right > width) rect.right = width;
RECT bufrect;
bufrect = rect;
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 * (bufrect.top + scan) + bufrect.left));
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;
case 'l':
//List windows and positions
if (!validated) return;
windowListCount = 0;
EnumWindows(&wndEnumProc, 0);
str = "Content-type: text/plain\r\n\r\n";
socket->SendExact(str, strlen(str));
_snprintf(gbuf, 1024, "Full Desktop,0,%d,%d,%d,%d;", 0, width, height, 0);
socket->SendExact(gbuf, strlen(gbuf));
for (int i; i < windowListCount; i++) {
LONG winstyle;
winstyle = GetWindowLong(windowList[i], GWL_EXSTYLE);
if (winstyle & WS_EX_TOOLWINDOW) continue;
//if (!(winstyle & WS_EX_APPWINDOW)) continue;
if (!IsWindowVisible(windowList[i])) continue;
WINDOWPLACEMENT wp;
if (GetWindowPlacement(windowList[i], &wp)) {
if (wp.showCmd == 0) continue;
}
RECT rc;
GetWindowRect(windowList[i], &rc);
if (!rc.left && !rc.right && !rc.top && !rc.bottom) continue;
if (rc.left == rc.right || rc.top == rc.bottom) continue;
while (str = strchr(gbuf, ',')) *str = '.';
while (str = strchr(gbuf, ';')) *str = ':';
if (!GetWindowText(windowList[i], gbuf, 1024)) continue;
socket->SendExact(gbuf, strlen(gbuf));
rc.left -= v_desktop->m_bmrect.left;
rc.right -= v_desktop->m_bmrect.left;
rc.top -= v_desktop->m_bmrect.top;
rc.bottom -= v_desktop->m_bmrect.top;
_snprintf(gbuf, 1024, ",%d,%d,%d,%d,%d;", windowList[i], rc.top, rc.right, rc.bottom, rc.left);
socket->SendExact(gbuf, strlen(gbuf));
}
break;
case 'w':
//Activate window and return rect
HWND wnd;
wnd = NULL;
sscanf(parmstart + 1, "%d", &wnd);
if (!wnd) {
str = "Content-type: text/plain\r\n\r\n";
socket->SendExact(str, strlen(str));
_snprintf(gbuf, 1024, "%d,%d,%d,%d", 0, width, height, 0);
socket->SendExact(gbuf, strlen(gbuf));
socket->Close();
return;
}
if (!IsWindow(wnd)) return;
DWORD oldFLTO;
SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)&oldFLTO, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)0, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
ShowWindow(wnd, SW_SHOWNORMAL);
SetForegroundWindow(wnd);
SetWindowPos(wnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
RECT rc;
GetWindowRect(wnd, &rc);
rc.left -= v_desktop->m_bmrect.left;
rc.top -= v_desktop->m_bmrect.top;
rc.right -= v_desktop->m_bmrect.left;
rc.bottom -= v_desktop->m_bmrect.top;
str = "Content-type: text/plain\r\n\r\n";
socket->SendExact(str, strlen(str));
_snprintf(gbuf, 1024, "%d,%d,%d,%d", rc.top, rc.right, rc.bottom, rc.left);
socket->SendExact(gbuf, strlen(gbuf));
socket->Close();
SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID)oldFLTO, SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);
break;
}
socket->Close();
}
//
// Parse the request tail after the '?' character, and format a sequence
// of <param> tags for the index HTML page with embedded applet.
//
BOOL vncHTTPConnectThread::ParseParams(const char *request,
char *result, int max_bytes)
{
char param_request[128];
char param_formatted[196];
result[0] = '\0';
int cur_bytes = 0;
const char *tail = request;
for (;;) {
// Copy individual "name=value" string into a buffer
char *delim_ptr = strchr((char *)tail, '&');
if (delim_ptr == NULL) {
if (strlen(tail) >= sizeof(param_request)) {
return FALSE;
}
strcpy(param_request, tail);
} else {
int len = delim_ptr - tail;
if (len >= sizeof(param_request)) {
return FALSE;
}
memcpy(param_request, tail, len);
param_request[len] = '\0';
}
// Split the request into parameter name and value
char *value_str = strchr(¶m_request[1], '=');
if (value_str == NULL) {
return FALSE;
}
*value_str++ = '\0';
if (strlen(value_str) == 0) {
return FALSE;
}
// Validate both parameter name and value
if (!ValidateString(param_request) || !ValidateString(value_str)) {
return FALSE;
}
// Prepare HTML-formatted representation of the name=value pair
int len = sprintf(param_formatted,
" <PARAM NAME=\"%s\" VALUE=\"%s\">\n",
param_request, value_str);
if (cur_bytes + len + 1 > max_bytes) {
return FALSE;
}
strcat(result, param_formatted);
cur_bytes += len;
// Go to the next parameter
if (delim_ptr == NULL) {
break;
}
tail = delim_ptr + 1;
}
return TRUE;
}
//
// Check if the string consists only of alphanumeric characters, '+' signs,
// underscores, and dots. Replace all '+' signs with spaces.
//
BOOL vncHTTPConnectThread::ValidateString(char *str)
{
for (char *ptr = str; *ptr != '\0'; ptr++) {
if (!isalnum(*ptr) && *ptr != '_' && *ptr != '.') {
if (*ptr == '+') {
*ptr = ' ';
} else {
return FALSE;
}
}
}
return TRUE;
}
char *vncHTTPConnectThread::ReadLine(VSocket *socket, char delimiter, int max)
{
// Allocate the maximum required buffer
char *buffer = new char[max+1];
int buffpos = 0;
// Read in data until a delimiter is read
for (;;)
{
char c;
if (!socket->ReadExact(&c, 1))
{
delete [] buffer;
return NULL;
}
if (c == delimiter)
{
buffer[buffpos] = 0;
return buffer;
}
buffer[buffpos] = c;
buffpos++;
if (buffpos == (max-1))
{
buffer[buffpos] = 0;
return buffer;
}
}
}
//
// Listening thread.
//
class vncHTTPListenThread : 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_undetached(void * arg);
// Fields used internally
BOOL m_shutdown;
protected:
vncServer *m_server;
VSocket *m_listen_socket;
BOOL m_allow_params;
};
BOOL vncHTTPListenThread::Init(VSocket *listen_socket, vncServer *server,
BOOL allow_params)
{
m_server = server;
m_listen_socket = listen_socket;
m_allow_params = allow_params;
// Start the thread
m_shutdown = FALSE;
start_undetached();
return TRUE;
}
// Code to be executed by the thread
void *vncHTTPListenThread::run_undetached(void * arg)
{
vnclog.Print(LL_INTINFO, VNCLOG("started HTTP server thread\n"));
// Go into a loop, listening for connections on the given socket
while (!m_shutdown) {
// Accept an incoming connection
VSocket *new_socket;
if (!m_listen_socket->TryAccept(&new_socket, 100))
break;
if (new_socket != NULL) {
// Start a client thread for this connection
vnclog.Print(LL_CLIENTS, VNCLOG("HTTP client connected\n"));
omni_thread *m_thread = new vncHTTPConnectThread;
if (m_thread == NULL)
break;
((vncHTTPConnectThread *)m_thread)->Init(new_socket, m_server,
m_allow_params);
}
}
vnclog.Print(LL_INTINFO, VNCLOG("quitting HTTP server thread\n"));
return NULL;
}
//
// The vncSockConnect class implementation
//
vncHTTPConnect::vncHTTPConnect()
{
m_listen_thread = NULL;
}
BOOL vncHTTPConnect::Init(vncServer *server, UINT listen_port, BOOL allow_params)
{
// Save the port number
m_listen_port = listen_port;
// Create the listening socket
if (!m_listen_socket.Create())
return FALSE;
// Bind it
if (!m_listen_socket.Bind(m_listen_port, server->LoopbackOnly()))
return FALSE;
// Set it to listen
if (!m_listen_socket.Listen())
return FALSE;
// Create the new thread
m_listen_thread = new vncHTTPListenThread;
if (m_listen_thread == NULL)
return FALSE;
// And start it running
return ((vncHTTPListenThread *)m_listen_thread)->Init(&m_listen_socket, server,
allow_params);
}
vncHTTPConnect::~vncHTTPConnect()
{
m_listen_socket.Shutdown();
// Join with our lovely thread
if (m_listen_thread != NULL) {
((vncHTTPListenThread *)m_listen_thread)->m_shutdown = TRUE;
void *returnval;
m_listen_thread->join(&returnval);
m_listen_thread = NULL;
m_listen_socket.Close();
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?