⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vnchttpconnect.cpp

📁 teamviewer source code vc++
💻 CPP
字号:
//  Copyright (C) 2006 Teamviewer GmbH. All Rights Reserved.
//  Copyright (C) 2002 Ultr@VNC Team Members. All Rights Reserved.
//  Copyright (C) 2000 Const Kaplinsky. All Rights Reserved.
//  Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
//  Copyright (C) 2006 Teamviewer GmbH. All Rights Reserved.
//  Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
//  This file is part of TeamViewer.
//
//  TeamViewer 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.
//
//  If the source code for TeamViewer is not available from the place 
//  whence you received this file, check http://www.teamviewer.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 "roGateway.h"

/* Old viewer - TODO: remove
// HTTP messages/message formats
const char HTTP_MSG_OK []			="HTTP/1.0 200 OK\r\n\r\n";
const char HTTP_FMT_INDEX[]			="<HTML><TITLE>VNC desktop [%.256s]</TITLE>\n"
	"<APPLET CODE=vncviewer.class ARCHIVE=vncviewer.jar WIDTH=%d HEIGHT=%d>\n"
	"<param name=PORT value=%d></APPLET></HTML>\n";
const char HTTP_MSG_NOSOCKCONN []	="<HTML><TITLE>Ultr@VNC desktop</TITLE>\n"
	"<BODY>The requested desktop is not configured to accept incoming connections.</BODY>\n"
	"</HTML>\n";
const char HTTP_MSG_NOSUCHFILE []	="HTTP/1.0 404 Not found\r\n\r\n"
    "<HEAD><TITLE>File Not Found</TITLE></HEAD>\n"
    "<BODY><H1>The requested file could not be found</H1></BODY>\n";
*/

// HTTP messages / message formats
const char HTTP_MSG_OK[] = "HTTP/1.0 200 OK\r\n\r\n";

const char HTTP_FMT_INDEX[] =
"<HTML>\n"
"  <HEAD><TITLE>TeamViewer Desktop [%.256s] - Get TeamViewer at www.teamviewer.com!</TITLE></HEAD>\n"
"  <BODY>\n"
"  <SPAN style='position: absolute; top:0px;left:0px'>\n" // sf@2002 - Hopefully supported by all recent browsers... to be checked.

"    <APPLET CODEBASE='%s' CODE=VncViewer.class ARCHIVE=VncViewer.jar WIDTH=%d HEIGHT=%d>\r\n"
"      <PARAM NAME=PORT VALUE=%d>\r\n"
"	   <PARAM NAME=TUNNELPORT VALUE=%d>\r\n"
"    <PARAM NAME = 'Open New Window' VALUE='Yes'>\n"
"	   <PARAM NAME=DYNGATE VALUE='%s'>\r\n"
"	   <PARAM NAME=DYNGATEID VALUE='%d'>\r\n"  // This line may NOT be modified, data is analysed by DynGate!
"      <PARAM NAME=ENCODING VALUE=Tight>\r\n"
"	   <PARAM name='Show controls' value=No>\r\n"
"	   <PARAM name='View Only' value=Yes>\r\n"
"	   <param name='Cursor shape updates' value=Disable>\r\n" // Display Mouse Cursor
"    </APPLET>"
"  </SPAN>\n"
"  </BODY>\n"
"</HTML>\n";


const char HTTP_MSG_NOSOCKCONN [] =
"<HTML>\n"
"  <HEAD><TITLE>TeamViewer 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>TeamViewer 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;

/* Old viewer - TODO: remove
const FileMap filemapping []	={
	{"/vncviewer.jar", "JavaArchive", IDR_VNCVIEWER_JAR},
	{"/authenticationPanel.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},
	{"/vncviewer.class", "JavaClass", IDR_VNCVIEWER_CLASS},
	{"/animatedMemoryImageSource.class", "JavaClass", IDR_ANIMMEMIMAGESRC_CLASS}
	};
const int filemappingsize		= 9;
*/

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},
	{"/VncViewer.class", "JavaClass", IDR_VNCVIEWER_CLASS},
	{"/ButtonPanel.class", "JavaClass", IDR_BUTTONPANEL_CLASS},
	{"/RecordingFrame.class", "JavaClass", IDR_RECFRAME_CLASS},
	{"/SessionRecorder.class", "JavaClass", IDR_SESSIONREC_CLASS},
	{"/FTPFrame.class", "JavaClass", IDR_FTPFRAME_CLASS},
	{"/TunnelReader.class", "JavaClass", IDR_TUNNELREADER_CLASS},
	{"/TunnelWriter.class", "JavaClass", IDR_TUNNELWRITER_CLASS}
	};
const int filemappingsize		= 11;

#ifdef HTTP_SAMEPORT
// Added for HTTP-via-RFB. Allows us to handle an HTTP transaction
// without starting a separate thread.
class vncHTTPConnectThreadHelper {
public:
	// Routines to handle HTTP requests
	void Init(vncServer* svr) { m_server = svr; }
	void DoHTTP(VSocket *socket);
	char *ReadLine(VSocket *socket, char delimiter, int max);
protected:
	vncServer	*m_server;
};
#endif

#ifdef HTTP_SAMEPORT
class vncHTTPConnectThread : public omni_thread, public vncHTTPConnectThreadHelper
#else
// The function for the spawned thread to run
class vncHTTPConnectThread : public omni_thread
#endif
{
public:
	// Init routine
	virtual BOOL Init(VSocket *socket, vncServer *server);

	// Code to be executed by the thread
	virtual void *run_undetached(void * arg);
#ifndef HTTP_SAMEPORT
	// Routines to handle HTTP requests
	virtual void DoHTTP(VSocket *socket);
	virtual char *ReadLine(VSocket *socket, char delimiter, int max);
#endif

	// Fields used internally
	BOOL		m_shutdown;
protected:
#ifndef HTTP_SAMEPORT
	vncServer	*m_server;
#endif
	VSocket		*m_socket;
};

#ifdef HTTP_SAMEPORT
// Added for HTTP-via-RFB. This function is called when a connection is
// accepted on the RFB port. If the client sends an HTTP request we
// handle it here and return TRUE. Otherwise we return
// FALSE and the caller continues with the RFB handshake.
VBool maybeHandleHTTPRequest(VSocket* sock,vncServer* svr)
{
	if (!sock->ReadSelect(2000)) return false;

	// Client is sending data. Create a vncHTTPConnectThread to
	// handle it.
	vncHTTPConnectThreadHelper http;
	http.Init(svr);
	http.DoHTTP(sock);
	sock->Shutdown();
	sock->Close();
	delete sock;
	return true;
}
#endif

// Method implementations
BOOL vncHTTPConnectThread::Init(VSocket *socket, vncServer *server)
{
	// Save the server pointer
	m_server = server;

	// Save the socket pointer
	m_socket = socket;

	// Start the thread
	m_shutdown = FALSE;
	start_undetached();

	return TRUE;
}

// Code to be executed by the thread
void *vncHTTPConnectThread::run_undetached(void * arg)
{
	vnclog.Print(LL_INTINFO, VNCLOG("started HTTP server thread"));

	// Go into a loop, listening for connections on the given socket
	while (!m_shutdown)
	{
		// Accept an incoming connection
		VSocket *new_socket = m_socket->Accept();
		if (new_socket == NULL)
			break;
		if (m_shutdown)
		{
			delete new_socket;
			break;
		}
		vnclog.Print(LL_CLIENTS, VNCLOG("HTTP client connected"));
		Sleep(250);
		// Successful accept - perform the transaction
		new_socket->SetTimeout(15000); //ms
		DoHTTP(new_socket);
		Sleep(500);
		// And close the client
		new_socket->Shutdown();
		new_socket->Close();
		delete new_socket;
	}

	vnclog.Print(LL_INTINFO, VNCLOG("quitting HTTP server thread"));

	return NULL;
}

#ifdef HTTP_SAMEPORT
void vncHTTPConnectThreadHelper::DoHTTP(VSocket *socket)
#else
void vncHTTPConnectThread::DoHTTP(VSocket *socket)
#endif
{
	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 ", (char*)&filename);
	delete [] line;
	if ((result == 0) || (result == EOF))
		return;

	vnclog.Print(LL_CLIENTS, VNCLOG("file %s requested"), filename);

	// Read in the rest of the browser's request data and discard...
	BOOL emptyline=TRUE;

	for (;;)
	{
		char c;

		if (!socket->ReadExactHTTP(&c, 1))
			return;
		if (c=='\n')
		{
			if (emptyline)
				break;
			emptyline = TRUE;
		}
		else
			if (c >= ' ')
			{
				emptyline = FALSE;
			}
	}

	vnclog.Print(LL_INTINFO, VNCLOG("parameters read"));

    if (filename[0] != '/')
	{
		vnclog.Print(LL_CONNERR, VNCLOG("filename didn't begin with '/'"));
		socket->SendExactHTTP(HTTP_MSG_NOSUCHFILE, strlen(HTTP_MSG_NOSUCHFILE));
		return;
	}

	// Switch, dependent upon the filename:
	if (strcmp(filename, "/") == 0)
	{
		char indexpage[2048 + MAX_COMPUTERNAME_LENGTH + 1];

		vnclog.Print(LL_CLIENTS, VNCLOG("sending main page"));

		// Send the OK notification message to the client
		if (!socket->SendExactHTTP(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
			return;

		// Compose the index page
		if (m_server->SockConnected())
		{
			int width, height, depth;

			// Get the screen's dimensions
			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 (int x=0; x<strlen(desktopname); x++)
				{
					desktopname[x] = tolower(desktopname[x]);
				}
			}
			else
			{
				strcpy(desktopname, "TeamViewer");
			}

			// Is DynGate installed and active?		
			CroGateway *rgw = CroGateway::Instance();
			if (rgw->GatewayInstalled() && rgw->GatewayRunning())
			{
				char codebase[50];
				sprintf(codebase,"/tv/java/%d", rgw->NumericID());
			
				// Send the java applet page for non-DynGate use
				// Restricted to http-port
				sprintf(indexpage, HTTP_FMT_INDEX,
					desktopname, codebase, width, height+32,
					-1, 80, "Yes", rgw->NumericID()
					);
			}
			else
			{			
				// Send the java applet page for non-DynGate use
				sprintf(indexpage, HTTP_FMT_INDEX,
					desktopname, "/", width, height+32,
					m_server->GetPort(), -1, "No", 0
					);
			}

		}
		else
		{
			// Send a "sorry, not allowed" page
			sprintf(indexpage, HTTP_MSG_NOSOCKCONN);
		}

		// Send the page
		if (socket->SendExactHTTP(indexpage, strlen(indexpage)))
			vnclog.Print(LL_INTINFO, VNCLOG("sent page"));

		return;
	}

	// File requested was not the index so check the mappings
	// list for a different file.

	// 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"));

			// Find the resource here
			resource = FindResource(NULL,
					MAKEINTRESOURCE(filemapping[x].resourceID),
					filemapping[x].type
					);
			if (resource == NULL)
				return;

			// Get its size
			resourcesize = SizeofResource(NULL, resource);

			// Load the resource
			resourcehan = LoadResource(NULL, resource);
			if (resourcehan == NULL)
				return;

			// Lock the resource
			resourceptr = (char *)LockResource(resourcehan);
			if (resourceptr == NULL)
				return;

			vnclog.Print(LL_INTINFO, VNCLOG("sending file..."));

			// Send the OK message
			if (!socket->SendExactHTTP(HTTP_MSG_OK, strlen(HTTP_MSG_OK)))
				return;

			// Now send the entirety of the data to the client
			if (!socket->SendExactHTTP(resourceptr, resourcesize))
				return;

			vnclog.Print(LL_INTINFO, VNCLOG("file successfully sent"));

			return;
		}
	}

	// Send the NoSuchFile notification message to the client
	if (!socket->SendExactHTTP(HTTP_MSG_NOSUCHFILE, strlen(HTTP_MSG_NOSUCHFILE)))
		return;
}
#ifdef HTTP_SAMEPORT
char *vncHTTPConnectThreadHelper::ReadLine(VSocket *socket, char delimiter, int max)
#else
char *vncHTTPConnectThread::ReadLine(VSocket *socket, char delimiter, int max)
#endif
{
	// 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->ReadExactHTTP(&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;
		}
	}
}

// The vncSockConnect class implementation

vncHTTPConnect::vncHTTPConnect()
{
	m_thread = NULL;
}

vncHTTPConnect::~vncHTTPConnect()
{
   m_socket.Shutdown();

    // Join with our lovely thread
    if (m_thread != NULL)
    {
		// *** This is a hack to force the listen thread out of the accept call,
		// because Winsock accept semantics are broken.
		((vncHTTPConnectThread *)m_thread)->m_shutdown = TRUE;

		VSocket socket;
		socket.Create();
		//socket.Bind(0);
		socket.Connect("localhost", m_port);
		socket.Close();

		void *returnval;
		m_thread->join(&returnval);
		m_thread = NULL;

		m_socket.Close();
    }
}

BOOL vncHTTPConnect::Init(vncServer *server, UINT port)
{
	// Save the port id
	m_port = port;

	// Create the listening socket
	if (!m_socket.Create())
		return FALSE;

	// Bind it
	if (!m_socket.Bind(m_port, server->LoopbackOnly()))
		return FALSE;

	// Set it to listen
	if (!m_socket.Listen())
		return FALSE;

	// Create the new thread
	m_thread = new vncHTTPConnectThread;
	if (m_thread == NULL)
		return FALSE;

	// And start it running
	return ((vncHTTPConnectThread *)m_thread)->Init(&m_socket, server);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -