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

📄 remote.cpp

📁 著名的下载软件核心Shareaza
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Remote.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2004.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza 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.
//
// Shareaza 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 Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "Remote.h"

#include "Network.h"
#include "MatchObjects.h"
#include "QuerySearch.h"
#include "QueryHit.h"
#include "VendorCache.h"
#include "SchemaCache.h"
#include "Schema.h"
#include "Transfers.h"
#include "Downloads.h"
#include "Download.h"
#include "DownloadGroups.h"
#include "DownloadGroup.h"
#include "DownloadSource.h"
#include "DownloadTransfer.h"
#include "Uploads.h"
#include "UploadQueues.h"
#include "UploadQueue.h"
#include "UploadFile.h"
#include "UploadTransfer.h"
#include "UploadTransferBT.h"
#include "Neighbours.h"
#include "G1Neighbour.h"
#include "G2Neighbour.h"
#include "EDNeighbour.h"
#include "EDPacket.h"
#include "GProfile.h"
#include "ShareazaURL.h"

#include "WndMain.h"
#include "WndSearch.h"
#include "CtrlDownloads.h"
#include "CtrlUploads.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

CList<int> CRemote::m_pCookies;

/////////////////////////////////////////////////////////////////////////////
// CRemote construction

CRemote::CRemote(CConnection* pConnection)
{
	CTransfer::AttachTo( pConnection );
	m_mInput.pLimit = m_mOutput.pLimit = NULL;
	OnRead();
}

CRemote::~CRemote()
{
}

/////////////////////////////////////////////////////////////////////////////
// CRemote run event

BOOL CRemote::OnRun()
{
	DWORD tNow = GetTickCount();
	
	if ( tNow - m_mOutput.tLast > 180000 )
	{
		Close();
		delete this;
		return FALSE;
	}
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CRemote dropped event

void CRemote::OnDropped(BOOL bError)
{
	Close();
	delete this;
}

/////////////////////////////////////////////////////////////////////////////
// CRemote read event

BOOL CRemote::OnRead()
{
	if ( ! CTransfer::OnRead() ) return FALSE;
	
	if ( m_sHandshake.IsEmpty() )
	{
		if ( m_pInput->m_nLength > 4096 || ! Settings.Remote.Enable )
		{
			Close();
			return FALSE;
		}
		
		m_pInput->ReadLine( m_sHandshake );
	}
	
	if ( ! m_sHandshake.IsEmpty() )
	{
		return ReadHeaders();
	}
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CRemote headers complete event

BOOL CRemote::OnHeadersComplete()
{
	if ( m_sHandshake.Find( _T("GET /") ) != 0 )
	{
		Close();
		delete this;
		return FALSE;
	}
	
	m_sHandshake = m_sHandshake.Mid( 4 ).SpanExcluding( _T(" \t") );
	
	CString strPath = m_sHandshake.SpanExcluding( _T("?&") );
	strPath.MakeLower();
	
	m_sRedirect.Empty();
	m_sHeader.Empty();
	m_sResponse.Empty();
	m_pResponse.Clear();
	
	PageSwitch( strPath );
	
	if ( ! m_sRedirect.IsEmpty() )
	{
		m_pOutput->Print( "HTTP/1.1 302 Found\r\n" );
		m_pOutput->Print( "Content-Length: 0\r\n" );
		if ( ! m_sHeader.IsEmpty() ) m_pOutput->Print( m_sHeader );
		m_pOutput->Print( "Location: " );
		m_pOutput->Print( m_sRedirect );
		m_pOutput->Print( "\r\n\r\n" );
	}
	else if ( ! m_sResponse.IsEmpty() )
	{
		CString strLength;
		Prepare();
		Output( _T("commonFooter") );
		int nBytes = WideCharToMultiByte( CP_UTF8, 0, m_sResponse, m_sResponse.GetLength(), NULL, 0, NULL, NULL );
		strLength.Format( _T("Content-Length: %i\r\n"), nBytes );
		m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
		m_pOutput->Print( "Content-Type: text/html; charset=\"unicode-1-1-utf-8\"\r\n" );
		m_pOutput->Print( strLength );
		if ( ! m_sHeader.IsEmpty() ) m_pOutput->Print( m_sHeader );
		m_pOutput->Print( "\r\n" );
		m_pOutput->Print( m_sResponse, CP_UTF8 );
		m_sResponse.Empty();
	}
	else if ( m_pResponse.m_nLength > 0 )
	{
		CString strLength;
		strLength.Format( _T("Content-Length: %i\r\n"), m_pResponse.m_nLength );
		m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
		m_pOutput->Print( strLength );
		if ( ! m_sHeader.IsEmpty() ) m_pOutput->Print( m_sHeader );
		m_pOutput->Print( "\r\n" );
		m_pOutput->AddBuffer( &m_pResponse );
	}
	else
	{
		m_pOutput->Print( "HTTP/1.1 404 Not Found\r\n" );
		m_pOutput->Print( "Content-Length: 0\r\n" );
		m_pOutput->Print( "\r\n" );
	}
	
	m_sHandshake.Empty();
	ClearHeaders();
	OnWrite();
	
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CRemote get a query string key

CString CRemote::GetKey(LPCTSTR pszName)
{
	int nStart = 0;
	CString strPair = m_sHandshake.Tokenize( _T("&?"), nStart );
	
	while ( ! strPair.IsEmpty() )
	{
		CString strName = strPair.SpanExcluding( _T("=") );
		
		if ( strName.CompareNoCase( pszName ) == 0 )
		{
			strName = strPair.Mid( strName.GetLength() + 1 );
			return CConnection::URLDecode( strName );
		}
		
		strPair = m_sHandshake.Tokenize( _T("&?"), nStart );
	}
	
	strPair.Empty();
	return strPair;
}

/////////////////////////////////////////////////////////////////////////////
// CRemote check access cookie helper

BOOL CRemote::CheckCookie()
{
	for ( INT_PTR nHeader = 0 ; nHeader < m_pHeaderName.GetSize() ; nHeader ++ )
	{
		if ( m_pHeaderName.GetAt( nHeader ).CompareNoCase( _T("Cookie") ) == 0 )
		{
			CString strValue( m_pHeaderValue.GetAt( nHeader ) );
			strValue.MakeLower();
			
			int nPos = strValue.Find( _T("shareazaremote=") );
			
			if ( nPos >= 0 )
			{
				int nCookie = 0;
				_stscanf( strValue.Mid( nPos + 15 ), _T("%i"), &nCookie );
				if ( m_pCookies.Find( nCookie ) != NULL ) return FALSE;
			}
		}
	}
	
	m_sRedirect = _T("/remote/");
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CRemote prepare to output a HTML segment

void CRemote::Prepare(LPCTSTR pszPrefix)
{
	if ( pszPrefix == NULL )
	{
		m_pKeys.RemoveAll();
		if ( m_sResponse.IsEmpty() ) Output( _T("commonHeader") );
	}
	else
	{
		for ( POSITION pos = m_pKeys.GetStartPosition() ; pos != NULL ; )
		{
			CString strKey, strValue;
			m_pKeys.GetNextAssoc( pos, strKey, strValue );
			if ( strKey.Find( pszPrefix ) == 0 ) m_pKeys.RemoveKey( strKey );
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// CRemote add a substitution key for the next HTML segment

void CRemote::Add(LPCTSTR pszKey, LPCTSTR pszValue)
{
	CString strKey( pszKey );
	strKey.MakeLower();
	m_pKeys.SetAt( strKey, pszValue );
}

/////////////////////////////////////////////////////////////////////////////
// CRemote output a HTML segment

void CRemote::Output(LPCTSTR pszName)
{
	CString strBody, strValue;
	CFile hFile;
	
	if ( _tcsstr( pszName, _T("..") ) || _tcschr( pszName, '/' ) ) return;
	strValue = Settings.General.Path + _T("\\Remote\\") + pszName + _T(".htm");
	if ( ! hFile.Open( strValue, CFile::modeRead ) ) return;
	
	int nBytes		= (int)hFile.GetLength();
	CHAR* pBytes	= new CHAR[ nBytes ];
	hFile.Read( pBytes, nBytes );
	hFile.Close();
	
	int nWide = MultiByteToWideChar( CP_UTF8, 0, pBytes, nBytes, NULL, 0 );
	MultiByteToWideChar( CP_UTF8, 0, pBytes, nBytes, strBody.GetBuffer( nWide ), nWide );
	strBody.ReleaseBuffer( nWide );
	delete [] pBytes;
	
	CList<BOOL> pDisplayStack;
	
	for ( BOOL bDisplay = TRUE ; ; )
	{
		int nStart = strBody.Find( _T("<%") );
		
		if ( nStart < 0 )
		{
			if ( bDisplay ) m_sResponse += strBody;
			break;
		}
		else if ( nStart >= 0 )
		{
			if ( bDisplay && nStart > 0 ) m_sResponse += strBody.Left( nStart );
			strBody = strBody.Mid( nStart + 2 );
		}
		
		int nEnd = strBody.Find( _T("%>") );
		if ( nEnd < 0 ) break;
		
		CString strKey = strBody.Left( nEnd );
		strBody = strBody.Mid( nEnd + 2 );
		
		strKey.TrimLeft();
		strKey.TrimRight();
		strKey.MakeLower();
		
		if ( strKey.IsEmpty() )
		{
		}
		else if ( strKey.GetAt( 0 ) == '=' && bDisplay )
		{
			strKey = strKey.Mid( 1 );
			strKey.Trim();
			if ( m_pKeys.Lookup( strKey, strValue ) ) m_sResponse += strValue;
		}
		else if ( strKey.GetAt( 0 ) == '?' )
		{
			strKey = strKey.Mid( 1 );
			strKey.Trim();
			
			if ( strKey.IsEmpty() )
			{
				if ( ! pDisplayStack.IsEmpty() ) bDisplay = pDisplayStack.RemoveTail();
			}
			else
			{
				if ( strKey.GetAt( 0 ) == '!' )
				{
					strKey = strKey.Mid( 1 );
					strKey.Trim();
					if ( ! m_pKeys.Lookup( strKey, strValue ) ) strValue.Empty();
					pDisplayStack.AddTail( bDisplay );
					bDisplay = bDisplay && strValue.IsEmpty();
				}
				else
				{
					if ( ! m_pKeys.Lookup( strKey, strValue ) ) strValue.Empty();
					pDisplayStack.AddTail( bDisplay );
					bDisplay = bDisplay && ! strValue.IsEmpty();
				}
			}
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
// CRemote page switch

void CRemote::PageSwitch(CString& strPath)
{
	if ( strPath == _T("/") || strPath == _T("/remote") )
	{
		m_sRedirect = _T("/remote/");
	}
	else if ( strPath == _T("/remote/") )
	{
		PageLogin();
	}
	else if ( strPath == _T("/remote/home") )
	{
		PageHome();
	}
	else if ( strPath == _T("/remote/search") )
	{
		PageSearch();
	}
	else if ( strPath == _T("/remote/newsearch") )
	{
		PageNewSearch();
	}
	else if ( strPath == _T("/remote/downloads") )
	{
		PageDownloads();
	}
	else if ( strPath == _T("/remote/newdownload") )
	{
		PageNewDownload();
	}
	else if ( strPath == _T("/remote/uploads") )
	{
		PageUploads();
	}
	else if ( strPath == _T("/remote/network") )
	{
		PageNetwork();
	}
	else if ( strPath == _T("/remote/header_1.png") || strPath == _T("/remote/header_2.png") )
	{
		PageBanner( strPath );
	}
	else if ( strPath.Find( _T("/remote/images/") ) == 0 )
	{
		PageImage( strPath );
	}
}

/////////////////////////////////////////////////////////////////////////////
// CRemote page : login

void CRemote::PageLogin()
{
	if ( GetKey( _T("username") ) == Settings.Remote.Username &&
		 GetKey( _T("password") ) == Settings.Remote.Password &&
		 Settings.Remote.Username.GetLength() > 0 &&
		 Settings.Remote.Password.GetLength() > 0 )
	{
		int nCookie = rand();
		m_pCookies.AddTail( nCookie );
		m_sHeader.Format( _T("Set-Cookie: ShareazaRemote=%i; path=/remote\r\n"), nCookie );
		m_sRedirect.Format( _T("/remote/home?%i"), rand() );
	}
	else
	{
		Prepare();
		if ( GetKey( _T("submit") ).GetLength() > 0 ) Add( _T("failure"), _T("true") );
		Output( _T("login") );
	}
}

/////////////////////////////////////////////////////////////////////////////
// CRemote page : home

void CRemote::PageHome()
{
	if ( CheckCookie() ) return;
	
	Prepare();
	Output( _T("home") );
}

/////////////////////////////////////////////////////////////////////////////
// CRemote page : search

void CRemote::PageSearch()
{
	if ( CheckCookie() ) return;

⌨️ 快捷键说明

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