📄 remote.cpp
字号:
//
// 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 + -