Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

UploadTransferHTTP.cpp

Go to the documentation of this file.
00001 //
00002 // UploadTransferHTTP.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "Settings.h"
00025 #include "Uploads.h"
00026 #include "UploadFile.h"
00027 #include "UploadFiles.h"
00028 #include "UploadQueue.h"
00029 #include "UploadQueues.h"
00030 #include "UploadTransferHTTP.h"
00031 #include "TransferFile.h"
00032 #include "Transfers.h"
00033 #include "Remote.h"
00034 #include "ShellIcons.h"
00035 #include "Statistics.h"
00036 #include "Buffer.h"
00037 #include "Schema.h"
00038 #include "XML.h"
00039 
00040 #include "Network.h"
00041 #include "Library.h"
00042 #include "SharedFile.h"
00043 #include "Downloads.h"
00044 #include "Download.h"
00045 
00046 #include "LocalSearch.h"
00047 #include "ImageServices.h"
00048 #include "ThumbCache.h"
00049 #include "Neighbours.h"
00050 #include "Neighbour.h"
00051 #include "G2Packet.h"
00052 #include "GProfile.h"
00053 #include "Security.h"
00054 
00055 #include "SHA.h"
00056 #include "ED2K.h"
00057 #include "TigerTree.h"
00058 
00059 #ifdef _DEBUG
00060 #undef THIS_FILE
00061 static char THIS_FILE[]=__FILE__;
00062 #define new DEBUG_NEW
00063 #endif
00064 
00065 
00067 // CUploadTransferHTTP construction
00068 
00069 CUploadTransferHTTP::CUploadTransferHTTP() : CUploadTransfer( PROTOCOL_HTTP )
00070 {
00071         m_bKeepAlive            = TRUE;
00072         m_nGnutella                     = 0;
00073         m_nReaskMultiplier      = 1;
00074         m_bNotShareaza          = FALSE;
00075 }
00076 
00077 CUploadTransferHTTP::~CUploadTransferHTTP()
00078 {
00079 }
00080 
00082 // CUploadTransferHTTP attach to connection
00083 
00084 void CUploadTransferHTTP::AttachTo(CConnection* pConnection)
00085 {
00086         CUploadTransfer::AttachTo( pConnection );
00087         
00088         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_ACCEPTED, (LPCTSTR)m_sAddress );
00089         
00090         m_mInput.pLimit         = &Settings.Bandwidth.Request;
00091         m_mOutput.pLimit        = &m_nBandwidth;
00092         
00093         m_nState        = upsRequest;
00094         m_tRequest      = m_tConnected;
00095         
00096         OnRead();
00097 }
00098 
00100 // CUploadTransferHTTP read handler
00101 
00102 BOOL CUploadTransferHTTP::OnRead()
00103 {
00104         CUploadTransfer::OnRead();
00105         
00106         switch ( m_nState )
00107         {
00108         case upsRequest:
00109         case upsQueued:
00110                 if ( ! ReadRequest() ) return FALSE;
00111                 if ( m_nState != upsHeaders ) break;
00112                 
00113         case upsHeaders:
00114                 return ReadHeaders();
00115 
00116         }
00117         
00118         return TRUE;
00119 }
00120 
00122 // CUploadTransferHTTP read : request line
00123 
00124 BOOL CUploadTransferHTTP::ReadRequest()
00125 {
00126         CString strLine;
00127         
00128         if ( ! m_pInput->ReadLine( strLine ) ) return TRUE;
00129         if ( strLine.GetLength() > 512 ) strLine = _T("#LINE_TOO_LONG#");
00130         
00131         if ( m_nState == upsQueued && m_pQueue != NULL )
00132         {
00133                 DWORD tLimit = Settings.Uploads.QueuePollMin;
00134 
00135                 tLimit *= m_nReaskMultiplier;
00136                 
00137                 if ( GetTickCount() - m_tRequest < tLimit )
00138                 {
00139                         theApp.Message( MSG_ERROR, IDS_UPLOAD_BUSY_FAST, (LPCTSTR)m_sAddress );
00140                         Close();
00141                         return FALSE;
00142                 }
00143         }
00144         
00145         int nChar = strLine.Find( _T(" HTTP/") );
00146         
00147         if ( strLine.GetLength() < 14 || nChar < 5 ||
00148                  ( strLine.Left( 4 ) != _T("GET ") && strLine.Left( 5 ) != _T("HEAD ") ) )
00149         {
00150                 theApp.Message( MSG_ERROR, IDS_UPLOAD_NOHTTP, (LPCTSTR)m_sAddress );
00151                 Close();
00152                 return FALSE;
00153         }
00154         
00155         ClearRequest();
00156         
00157         m_bHead                 = ( strLine.Left( 5 ) == _T("HEAD ") );
00158         m_bConnectHdr   = FALSE;
00159         m_bKeepAlive    = TRUE;
00160         m_bHostBrowse   = FALSE;
00161         m_bDeflate              = FALSE;
00162         m_bBackwards    = FALSE;
00163         m_bRange                = FALSE;
00164         m_bQueueMe              = FALSE;
00165         m_bNotShareaza  = FALSE;
00166         
00167         m_bMetadata             = FALSE;
00168         m_bTigerTree    = FALSE;
00169         
00170         m_sLocations.Empty();
00171         m_sRanges.Empty();
00172         
00173         CString strRequest = strLine.Mid( m_bHead ? 5 : 4, nChar - ( m_bHead ? 5 : 4 ) );
00174         
00175         if ( strRequest.GetLength() > 5 && strRequest.Right( 1 ) == _T("/") )
00176         {
00177                 strRequest = strRequest.Left( strRequest.GetLength() - 1 );
00178         }
00179         
00180         strRequest = URLDecode( strRequest );
00181         
00182         if ( strRequest != m_sRequest )
00183         {
00184                 if ( m_sRequest.Find( _T("/gnutella/tigertree/") ) < 0 &&
00185                          strRequest.Find( _T("/gnutella/tigertree/") ) < 0 &&
00186                          m_sRequest.Find( _T("/gnutella/thex/") ) < 0 &&
00187                          strRequest.Find( _T("/gnutella/thex/") ) < 0 &&
00188                          m_sRequest.Find( _T("/gnutella/metadata/") ) < 0 &&
00189                          strRequest.Find( _T("/gnutella/metadata/") ) < 0 )
00190                 {
00191                         UploadQueues.Dequeue( this );
00192                 }
00193                 
00194                 m_sRequest = strRequest;
00195         }
00196         
00197         theApp.Message( MSG_DEBUG, _T("%s: UPLOAD PATH: %s"), (LPCTSTR)m_sAddress, (LPCTSTR)m_sRequest );
00198         
00199         m_nState        = upsHeaders;
00200         m_tRequest      = GetTickCount();
00201         
00202         return TRUE;
00203 }
00204 
00206 // CUploadTransferHTTP read : headers
00207 
00208 BOOL CUploadTransferHTTP::OnHeaderLine(CString& strHeader, CString& strValue)
00209 {
00210         theApp.Message( MSG_DEBUG, _T("%s: UPLOAD HEADER: %s: %s"), (LPCTSTR)m_sAddress, (LPCTSTR)strHeader, strValue );
00211         
00212         if ( strHeader.CompareNoCase( _T("Connection") ) == 0 )
00213         {
00214                 if ( strValue.CompareNoCase( _T("close") ) == 0 ) m_bKeepAlive = FALSE;
00215                 m_bConnectHdr = TRUE;
00216         }
00217         else if ( strHeader.CompareNoCase( _T("Accept") ) == 0 )
00218         {
00219                 CharLower( strValue.GetBuffer() );
00220                 strValue.ReleaseBuffer();
00221                 if ( strValue.Find( _T("application/x-gnutella-packets") ) >= 0 ) m_bHostBrowse = 1;
00222                 if ( strValue.Find( _T("application/x-gnutella2") ) >= 0 ) m_bHostBrowse = 2;
00223                 if ( strValue.Find( _T("application/x-shareaza") ) >= 0 ) m_bHostBrowse = 2;
00224         }
00225         else if ( strHeader.CompareNoCase( _T("Accept-Encoding") ) == 0 )
00226         {
00227                 if ( _tcsistr( strValue, _T("deflate") ) ) m_bDeflate = TRUE;
00228                 if ( Settings.Uploads.AllowBackwards && _tcsistr( strValue, _T("backwards") ) ) m_bBackwards = TRUE;
00229         }
00230         else if ( strHeader.CompareNoCase( _T("Range") ) == 0 )
00231         {
00232                 QWORD nFrom = 0, nTo = 0;
00233                 
00234                 if ( _stscanf( strValue, _T("bytes=%I64i-%I64i"), &nFrom, &nTo ) == 2 )
00235                 {
00236                         m_nOffset       = nFrom;
00237                         m_nLength       = nTo + 1 - nFrom;
00238                         m_bRange        = TRUE;
00239                 }
00240                 else if ( _stscanf( strValue, _T("bytes=%I64i-"), &nFrom ) == 1 )
00241                 {
00242                         m_nOffset       = nFrom;
00243                         m_nLength       = SIZE_UNKNOWN;
00244                         m_bRange        = TRUE;
00245                 }
00246         }
00247         else if (       strHeader.CompareNoCase( _T("X-Gnutella-Content-URN") ) == 0 ||
00248                                 strHeader.CompareNoCase( _T("X-Content-URN") ) == 0 ||
00249                                 strHeader.CompareNoCase( _T("Content-URN") ) == 0 )
00250         {
00251                 HashesFromURN( strValue );
00252                 m_nGnutella |= 1;
00253         }
00254         else if (       strHeader.CompareNoCase( _T("X-Gnutella-Alternate-Location") ) == 0 ||
00255                                 strHeader.CompareNoCase( _T("Alt-Location") ) == 0 ||
00256                                 strHeader.CompareNoCase( _T("X-Alt") ) == 0 )
00257         {
00258                 if ( Settings.Library.SourceMesh )
00259                 {
00260                         if ( strValue.Find( _T("Zhttp://") ) < 0 ) m_sLocations = strValue;
00261                 }
00262                 m_nGnutella |= 1;
00263         }
00264         else if ( strHeader.CompareNoCase( _T("X-NAlt") ) == 0 )
00265         {
00266                 // Dead alt-sources
00267         }
00268         else if ( strHeader.CompareNoCase( _T("X-Node") ) == 0 )
00269         {
00270                 m_bNotShareaza = TRUE; // Shareaza doesn't send this header
00271         }
00272         else if ( strHeader.CompareNoCase( _T("X-Queue") ) == 0 )
00273         {
00274                 m_bQueueMe = TRUE;
00275                 m_nGnutella |= 1;
00276                 if ( strValue == _T("1.0") ) m_bNotShareaza = TRUE;                     // Shareaza doesn't send this value
00277         }
00278         else if (       strHeader.CompareNoCase( _T("X-Nick") ) == 0 ||
00279                                 strHeader.CompareNoCase( _T("X-Name") ) == 0 ||
00280                                 strHeader.CompareNoCase( _T("X-UserName") ) == 0 )
00281         {
00282                 m_sNick = URLDecode( strValue );
00283         }
00284         else if ( strHeader.CompareNoCase( _T("X-Features") ) == 0 )
00285         {
00286                 if ( _tcsistr( strValue, _T("g2/") ) != NULL ) m_nGnutella |= 2;
00287                 if ( _tcsistr( strValue, _T("gnet2/") ) != NULL ) m_nGnutella |= 2;
00288                 if ( _tcsistr( strValue, _T("gnutella2/") ) != NULL ) m_nGnutella |= 2;
00289                 if ( m_nGnutella == 0 ) m_nGnutella = 1;
00290         }
00291 
00292         return CUploadTransfer::OnHeaderLine( strHeader, strValue );
00293 }
00294 
00296 // CUploadTransferHTTP process request
00297 
00298 BOOL CUploadTransferHTTP::OnHeadersComplete()
00299 {
00300         if ( Uploads.EnforcePerHostLimit( this, TRUE ) ) return FALSE;
00301         
00302         if ( _tcsistr( m_sUserAgent, _T("shareaza") ) != NULL )
00303         {
00304                 // Assume certain capabilitites for various Shareaza versions
00305                 m_nGnutella |= 3;
00306                 if ( m_sUserAgent == _T("Shareaza 1.4.0.0") ) m_bQueueMe = TRUE;
00307 
00308                 // Check for non-shareaza clients spoofing a Shareaza user agent
00309                 if ( m_bNotShareaza ) 
00310                 {
00311                         SendResponse( IDR_HTML_FILENOTFOUND );
00312                         theApp.Message( MSG_ERROR, _T("Client %s has a spoofed user agent, banning"), (LPCTSTR)m_sAddress );
00313                                         
00314                         Security.Ban( &m_pHost.sin_addr, banWeek, FALSE );
00315                         Remove( FALSE );
00316                         return FALSE;
00317                 }
00318         }
00319         else if ( _tcsistr( m_sUserAgent, _T("trustyfiles") ) != NULL ||
00320                           _tcsistr( m_sUserAgent, _T("gnucdna") ) != NULL ||
00321                           _tcsistr( m_sUserAgent, _T("adagio") ) != NULL )
00322         {
00323                 // Assume Gnutella2 capability for certain user-agents
00324                 m_nGnutella |= 3;
00325         }
00326         else if ( m_nGnutella & 2 )
00327         {
00328                 // Check for clients spoofing a G2 header
00329                 if ( _tcsistr( m_sUserAgent, _T("phex") ) != NULL )
00330                 {
00331                         // This is actually a G1-only client sending a fake header, so they can download 
00332                         // from (but not upload to) clients that are only connected to G2. 
00333                         m_nGnutella = 1;
00334                         
00335                         if ( ! Settings.Gnutella1.EnableToday )
00336                         {
00337                                 // Terminate the connection and do not try to download from them.
00338                                 SendResponse( IDR_HTML_FILENOTFOUND );
00339                                 theApp.Message( MSG_ERROR, _T("Client %s has a fake G2 header, banning"), (LPCTSTR)m_sAddress );
00340 
00341                                 Security.Ban( &m_pHost.sin_addr, banWeek, FALSE );
00342                                 Remove( FALSE );
00343                                 return FALSE;
00344                         }
00345                 }
00346         }
00347         
00348         if ( m_sRequest == _T("/") || StartsWith( m_sRequest, _T("/gnutella/browse/v1") ) )
00349         {
00350                 // Requests for "/" or the browse path are handled the same way
00351                 
00352                 if ( ( m_bHostBrowse == 1 && ! Settings.Community.ServeFiles ) ||
00353                          ( m_bHostBrowse == 2 && ! Settings.Community.ServeProfile && ! Settings.Community.ServeFiles ) )
00354                 {
00355                         theApp.Message( MSG_ERROR, IDS_UPLOAD_BROWSE_DENIED, (LPCTSTR)m_sAddress );
00356                         m_bHostBrowse = FALSE;
00357                 }
00358                 
00359                 if ( m_bHostBrowse )
00360                 {
00361                         RequestHostBrowse();
00362                 }
00363                 else
00364                 {
00365                         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_ABOUT, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
00366                         SendResponse( IDR_HTML_ABOUT );
00367                 }
00368                 
00369                 return TRUE;
00370         }
00371         else if ( StartsWith( m_sRequest, _T("/remote") ) || StartsWith( m_sRequest, _T("/favicon.ico") ) )
00372         {
00373                 // A web client can start requesting remote pages on the same keep-alive
00374                 // connection after previously requesting other system objects
00375                 
00376                 if ( Settings.Remote.Enable )
00377                 {
00378                         m_pInput->Prefix( "GET /remote/ HTTP/1.0\r\n\r\n" );
00379                         new CRemote( this );
00380                         Remove( FALSE );
00381                         return FALSE;
00382                 }
00383         }
00384         else if ( IsAgentBlocked() )
00385         {
00386                 if ( m_sFileName.IsEmpty() ) m_sFileName = _T("file");
00387                 SendResponse( IDR_HTML_BROWSER );
00388                 theApp.Message( MSG_ERROR, IDS_UPLOAD_BROWSER, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00389                 Security.Ban( &m_pHost.sin_addr, ban5Mins, FALSE ); // Anti-hammer protection if client doesn't understand 403 (Don't bother re-sending HTML every 5 seconds)
00390                 if ( m_sUserAgent.Find( _T("Mozilla") ) >= 0 ) return TRUE;
00391                 Remove( FALSE );
00392                 return FALSE;
00393         }
00394         else if ( IsNetworkDisabled() )
00395         {
00396                 // Network isn't active- Check if we should send 404 or 403
00397 
00398                 if ( StartsWith( m_sRequest, _T("/uri-res/N2R?urn:") ) )
00399                 {
00400                         LPCTSTR pszURN = (LPCTSTR)m_sRequest + 13;
00401                 
00402                         CSingleLock oLock( &Library.m_pSection );
00403 
00404                         if ( oLock.Lock( 50 ) )
00405                         {
00406                                 if ( CLibraryFile* pFile = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE ) )
00407                                 {
00408                                         if ( UploadQueues.CanUpload( PROTOCOL_HTTP, pFile, TRUE ) )
00409                                         {
00410                                                 // Have the file, but the network is disabled.
00411                                                 SendResponse( IDR_HTML_DISABLED );
00412                                                 theApp.Message( MSG_ERROR, IDS_UPLOAD_DISABLED, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
00413                                                 Security.Ban( &m_pHost.sin_addr, ban2Hours, FALSE ); // Anti-hammer protection if client doesn't understand 403
00414                                                 Remove( FALSE );
00415                                                 return FALSE;
00416                                         }
00417                                 }
00418                         }
00419                         // Network is disabled, but we don't have the file anyway.
00420                         SendResponse( IDR_HTML_FILENOTFOUND );
00421                 }
00422                 else
00423                 {
00424                         SendResponse( IDR_HTML_DISABLED );
00425                 }
00426                 theApp.Message( MSG_ERROR, IDS_UPLOAD_DISABLED, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
00427                 Security.Ban( &m_pHost.sin_addr, ban2Hours, FALSE ); // Anti-hammer protection if client doesn't understand 403
00428                 Remove( FALSE );
00429                 return FALSE;
00430         }
00431         else if ( StartsWith( m_sRequest, _T("/gnutella/metadata/v1?urn:") ) && Settings.Uploads.ShareMetadata )
00432         {
00433                 LPCTSTR pszURN = (LPCTSTR)m_sRequest + 22;
00434                 CXMLElement* pMetadata = NULL;
00435                 
00436                 CSingleLock oLock( &Library.m_pSection, TRUE );
00437                 if ( CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE ) )
00438                 {
00439                         if ( pShared->m_pMetadata != NULL )
00440                         {
00441                                 m_sFileName     = pShared->m_sName;
00442                                 pMetadata       = pShared->m_pSchema->Instantiate( TRUE );
00443                                 pMetadata->AddElement( pShared->m_pMetadata->Clone() );
00444                         }
00445                         oLock.Unlock();
00446                 }
00447                 else
00448                 {
00449                         oLock.Unlock();
00450                         if ( CDownload* pDownload = Downloads.FindByURN( pszURN ) )
00451                         {
00452                                 if ( pDownload->m_pXML != NULL )
00453                                 {
00454                                         m_sFileName     = pDownload->m_sRemoteName;
00455                                         pMetadata       = pDownload->m_pXML->Clone();
00456                                 }
00457                         }
00458                 }
00459                 
00460                 if ( pMetadata != NULL ) return RequestMetadata( pMetadata );
00461         }
00462         else if ( StartsWith( m_sRequest, _T("/gnutella/tigertree/v3?urn:") ) && Settings.Uploads.ShareTiger )
00463         {
00464                 LPCTSTR pszURN = (LPCTSTR)m_sRequest + 23;
00465                 
00466                 {
00467                         CQuickLock oLock( Library.m_pSection );
00468                         if ( CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE ) )
00469                         {
00470                                 CTigerTree* pTigerTree = pShared->GetTigerTree();
00471                                 m_sFileName = pShared->m_sName;
00472                                 return RequestTigerTreeRaw( pTigerTree, TRUE );
00473                         }
00474                 }
00475                 if ( CDownload* pDownload = Downloads.FindByURN( pszURN ) )
00476                 {
00477                         if ( pDownload->GetTigerTree() != NULL )
00478                         {
00479                                 m_sFileName = pDownload->m_sRemoteName;
00480                                 return RequestTigerTreeRaw( pDownload->GetTigerTree(), FALSE );
00481                         }
00482                 }
00483         }
00484         else if ( StartsWith( m_sRequest, _T("/gnutella/thex/v1?urn:") ) && Settings.Uploads.ShareTiger )
00485         {
00486                 LPCTSTR pszURN  = (LPCTSTR)m_sRequest + 18;
00487                 DWORD nDepth    = 0;
00488                 
00489                 if ( LPCTSTR pszDepth = _tcsistr( m_sRequest, _T("depth=") ) )
00490                 {
00491                         _stscanf( pszDepth + 6, _T("%i"), &nDepth );
00492                 }
00493                 
00494                 BOOL bHashset = ( _tcsistr( m_sRequest, _T("ed2k=1") ) != NULL );
00495                 
00496                 {
00497                         CQuickLock oLock( Library.m_pSection );
00498                         if ( CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE ) )
00499                         {
00500                                 CTigerTree* pTigerTree  = pShared->GetTigerTree();
00501                                 CED2K* pHashset                 = bHashset ? pShared->GetED2K() : NULL;
00502                                 m_sFileName = pShared->m_sName;
00503                                 m_nFileSize = pShared->GetSize();
00504                                 return RequestTigerTreeDIME( pTigerTree, nDepth, pHashset, TRUE );
00505                         }
00506                 }
00507                 if ( CDownload* pDownload = Downloads.FindByURN( pszURN ) )
00508                 {
00509                         if ( pDownload->GetTigerTree() != NULL )
00510                         {
00511                                 m_sFileName = pDownload->m_sRemoteName;
00512                                 m_nFileSize = pDownload->m_nSize;
00513                                 return RequestTigerTreeDIME( pDownload->GetTigerTree(), nDepth,
00514                                         bHashset ? pDownload->GetHashset() : NULL, FALSE );
00515                         }
00516                 }
00517         }
00518         else if ( StartsWith( m_sRequest, _T("/gnutella/preview/v1?urn:") ) && Settings.Uploads.SharePreviews )
00519         {
00520                 LPCTSTR pszURN = (LPCTSTR)m_sRequest + 21;
00521                 CSingleLock oLock( &Library.m_pSection, TRUE );
00522                 CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE );
00523                 if ( pShared != NULL ) return RequestPreview( pShared, oLock );
00524         }
00525         else if ( StartsWith( m_sRequest, _T("/uri-res/N2R?urn:") ) )
00526         {
00527                 LPCTSTR pszURN = (LPCTSTR)m_sRequest + 13;
00528                 
00529                 {
00530                         CSingleLock oLock( &Library.m_pSection, TRUE );
00531 
00532                         if ( CLibraryFile* pShared = LibraryMaps.LookupFileByURN( pszURN, TRUE, TRUE ) )
00533                         {
00534                                 return RequestSharedFile( pShared, oLock );
00535                         }
00536                 }
00537 
00538                 CDownload* pDownload = Downloads.FindByURN( pszURN );
00539                 
00540                 if ( pDownload != NULL && pDownload->IsShared() && pDownload->IsStarted() )
00541                 {
00542                         return RequestPartialFile( pDownload );
00543                 }
00544         }
00545         else if ( StartsWith( m_sRequest, _T("/get/") ) )
00546         {
00547                 DWORD nIndex = 0;
00548                 
00549                 CString strFile = m_sRequest.Mid( 5 );
00550                 int nChar               = strFile.Find( '/' );
00551                 
00552                 if ( _stscanf( strFile, _T("%lu/"), &nIndex ) == 1 && nChar > 0 && nChar < strFile.GetLength() - 1 )
00553                 {
00554                         strFile = strFile.Mid( nChar + 1 );
00555                         
00556                         {
00557                                 CSingleLock oLock( &Library.m_pSection, TRUE );
00558 
00559                                 CLibraryFile* pFile = Library.LookupFile( nIndex, TRUE, TRUE );
00560                         
00561                                 if ( pFile != NULL && pFile->m_sName.CompareNoCase( strFile ) )
00562                                 {
00563                                         pFile = NULL;
00564                                 }
00565                         
00566                                 if ( pFile == NULL )
00567                                 {
00568                                         pFile = LibraryMaps.LookupFileByName( strFile, TRUE, TRUE );
00569                                 }
00570                         
00571                                 if ( pFile != NULL ) return RequestSharedFile( pFile, oLock );
00572                         }
00573                 }
00574                 else
00575                 {
00576                         strFile = strFile.Mid( nChar + 1 );
00577                         CSingleLock oLock( &Library.m_pSection, TRUE );
00578                         CLibraryFile* pFile = LibraryMaps.LookupFileByName( strFile, TRUE, TRUE );
00579                         if ( pFile != NULL ) return RequestSharedFile( pFile, oLock );
00580                 }
00581         }
00582         else
00583         {
00584                 CString strFile = m_sRequest.Mid( 1 );
00585                 CSingleLock oLock( &Library.m_pSection, TRUE );
00586                 CLibraryFile* pFile = LibraryMaps.LookupFileByName( strFile, TRUE, TRUE );
00587                 if ( pFile != NULL ) return RequestSharedFile( pFile, oLock );
00588         }
00589         
00590         if ( m_sFileName.IsEmpty() )
00591         {
00592                 if ( m_bSHA1 ) m_sFileName = CSHA::HashToString( &m_pSHA1, TRUE );
00593                 else m_sFileName = m_sRequest;
00594         }
00595         
00596         SendResponse( IDR_HTML_FILENOTFOUND );
00597         theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00598         
00599         return TRUE;
00600 }
00601 
00602 BOOL CUploadTransferHTTP::IsNetworkDisabled()
00603 {
00604         if ( Settings.Connection.RequireForTransfers == FALSE ) return FALSE;
00605         
00606         if ( m_nGnutella == 2 )
00607         {
00608                 if ( ! Settings.Gnutella2.EnableToday ) return TRUE;
00609         }
00610         else if ( m_nGnutella == 1 )
00611         {
00612                 if ( ! Settings.Gnutella1.EnableToday ) return TRUE;
00613         }
00614         else
00615         {
00616                 if ( ! Settings.Gnutella1.EnableToday &&
00617                          ! Settings.Gnutella2.EnableToday ) return TRUE;
00618         }
00619         
00620         return FALSE;
00621 }
00622 
00624 // CUploadTransferHTTP request a shared file
00625 
00626 BOOL CUploadTransferHTTP::RequestSharedFile(CLibraryFile* pFile, CSingleLock& oLibraryLock)
00627 {
00628         ASSERT( pFile != NULL );
00629         
00630         if ( ! RequestComplete( pFile ) )
00631         {
00632                 oLibraryLock.Unlock();
00633                 SendResponse( IDR_HTML_HASHMISMATCH );
00634                 theApp.Message( MSG_ERROR, IDS_UPLOAD_HASH_MISMATCH, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00635                 return TRUE;
00636         }
00637 
00638         if ( ! UploadQueues.CanUpload( PROTOCOL_HTTP, pFile ) )
00639         {
00640                 // File is not uploadable. (No queue, is a ghost, etc)
00641                 if ( m_sFileName.IsEmpty() )
00642                 {
00643                         if ( m_bSHA1 ) m_sFileName = CSHA::HashToString( &m_pSHA1, TRUE );
00644                 }
00645 
00646                 oLibraryLock.Unlock();
00647                 SendResponse( IDR_HTML_FILENOTFOUND );
00648                 theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00649                 return TRUE;
00650         }
00651         
00652         m_bTigerTree    = m_bTiger;
00653         m_bMetadata             = ( pFile->m_pMetadata != NULL && ( pFile->m_bMetadataAuto == FALSE || pFile->m_nVirtualSize > 0 ) );
00654         
00655         if ( ! m_bSHA1 && ! m_bTiger && ! m_bED2K ) m_sLocations.Empty();
00656         
00657         if ( m_nLength == SIZE_UNKNOWN ) m_nLength = m_nFileSize - m_nOffset;
00658         
00659         if ( m_nOffset >= m_nFileSize || m_nOffset + m_nLength > m_nFileSize )
00660         {
00661                 oLibraryLock.Unlock();
00662                 SendResponse( IDR_HTML_BADRANGE );
00663                 theApp.Message( MSG_ERROR, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00664                 return TRUE;
00665         }
00666         
00667         CString strLocations;
00668         if ( Settings.Library.SourceMesh ) strLocations = pFile->GetAlternateSources( &m_pSourcesSent, 15, PROTOCOL_HTTP );
00669         if ( m_sLocations.GetLength() ) pFile->AddAlternateSources( m_sLocations );
00670         m_sLocations = strLocations;
00671         
00672         oLibraryLock.Unlock();
00673         
00674         return QueueRequest();
00675 }
00676 
00678 // CUploadTransferHTTP request a partial file
00679 
00680 BOOL CUploadTransferHTTP::RequestPartialFile(CDownload* pDownload)
00681 {
00682         ASSERT( pDownload != NULL );
00683         ASSERT( pDownload->IsStarted() );
00684         
00685         if ( ! RequestPartial( pDownload ) )
00686         {
00687                 SendResponse( IDR_HTML_HASHMISMATCH );
00688                 theApp.Message( MSG_ERROR, IDS_UPLOAD_HASH_MISMATCH, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00689                 return TRUE;
00690         }
00691         
00692         ASSERT( m_nFileBase == 0 );
00693         
00694         m_bTigerTree    = ( m_bTiger && pDownload->GetTigerTree() != NULL );
00695         m_bMetadata             = ( pDownload->m_pXML != NULL );
00696         
00697         if ( m_sLocations.GetLength() ) pDownload->AddSourceURLs( m_sLocations, TRUE );
00698         // if ( Settings.Library.SourceMesh ) m_sLocations = pDownload->GetSourceURLs( &m_pSourcesSent, 15, PROTOCOL_HTTP, NULL );
00699         if ( Settings.Library.SourceMesh ) 
00700         {
00701                 if ( m_nGnutella == 1 )
00702                         m_sLocations = pDownload->GetSourceURLs( &m_pSourcesSent, 15, PROTOCOL_G1, NULL );
00703                 else
00704                         m_sLocations = pDownload->GetSourceURLs( &m_pSourcesSent, 15, PROTOCOL_HTTP, NULL );
00705         }
00706         
00707         m_sRanges = pDownload->GetAvailableRanges();
00708         
00709         if ( m_bRange && m_nOffset == 0 && m_nLength == SIZE_UNKNOWN )
00710         {
00711                 pDownload->GetRandomRange( m_nOffset, m_nLength );
00712         }
00713         
00714         if ( m_nLength == SIZE_UNKNOWN ) m_nLength = m_nFileSize - m_nOffset;
00715         
00716         if ( pDownload->ClipUploadRange( m_nOffset, m_nLength ) )
00717         {
00718                 return QueueRequest();
00719         }
00720         
00721         if ( pDownload->IsMoving() )
00722         {
00723                 if ( GetTickCount() - pDownload->m_tCompleted < 30000 )
00724                 {
00725                         m_pOutput->Print( "HTTP/1.1 503 Range Temporarily Unavailable\r\n" );
00726                 }
00727                 else
00728                 {
00729                         SendResponse( IDR_HTML_FILENOTFOUND );
00730                         theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00731                         return TRUE;
00732                 }
00733         }
00734         else if ( pDownload->GetTransferCount() )
00735         {
00736                 m_pOutput->Print( "HTTP/1.1 503 Range Temporarily Unavailable\r\n" );
00737         }
00738         else
00739         {
00740                 m_pOutput->Print( "HTTP/1.1 416 Requested Range Unavailable\r\n" );
00741         }
00742         
00743         SendDefaultHeaders();
00744         SendFileHeaders();
00745         
00746         m_pOutput->Print( "Content-Length: 0\r\n" );
00747         m_pOutput->Print( "\r\n" );
00748         
00749         StartSending( upsResponse );
00750         
00751         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
00752         
00753         return TRUE;
00754 }
00755 
00757 // CUploadTransferHTTP queue the request if necessary
00758 
00759 BOOL CUploadTransferHTTP::QueueRequest()
00760 {
00761         SHA1* pSHA1 = NULL;
00762 
00763         if ( m_bHead ) return OpenFileSendHeaders();
00764         
00765         AllocateBaseFile();
00766         
00767         UINT nError             = 0;
00768         int nPosition   = 0;
00769 
00770         if ( m_bStopTransfer )
00771         {
00772 
00773                 m_tRotateTime = 0;
00774                 m_bStopTransfer = FALSE;
00775                         
00776                 CUploadQueue* pQueue = m_pQueue;
00777                 if ( pQueue ) pQueue->Dequeue( this );
00778         }
00779 
00780         if ( m_bSHA1 )
00781         {
00782                 pSHA1 = &m_pSHA1;
00783         }
00784 
00785         
00786         if ( Uploads.CanUploadFileTo( &m_pHost.sin_addr, pSHA1 ) )      //if ( Uploads.AllowMoreTo( &m_pHost.sin_addr ) )
00787         {
00788                 if ( ( nPosition = UploadQueues.GetPosition( this, TRUE ) ) >= 0 )
00789                 {
00790                         ASSERT( m_pQueue != NULL );
00791 
00792                         // If the queue can't accept this file
00793                         if( ! m_pQueue->CanAccept( m_nProtocol, m_sFileName, m_nFileSize, m_bFilePartial, m_sFileTags ) )
00794                         {       // This is probably a partial that has completed
00795                                 theApp.Message( MSG_DEBUG, _T("File queue error- Partial may have recently completed") );
00796 
00797                                 // Might as well allow the upload... so don't do anything.
00798                                 //ASSERT( FALSE );
00799                         }
00800 
00801                         
00802                         if ( nPosition == 0 )
00803                         {
00804                                 // Queued, and ready to send
00805                                 return OpenFileSendHeaders();
00806                         }
00807                         else
00808                         {
00809                                 // Queued, but must wait
00810                         }
00811                 }
00812                 else if ( UploadQueues.Enqueue( this ) )
00813                 {
00814                         ASSERT( m_pQueue != NULL );
00815                         ASSERT( m_pQueue->CanAccept( m_nProtocol, m_sFileName, m_nFileSize, m_bFilePartial, m_sFileTags ) );
00816                         
00817                         nPosition = UploadQueues.GetPosition( this, TRUE );
00818                         ASSERT( nPosition >= 0 );
00819                         
00820                         if ( nPosition == 0 )
00821                         {
00822                                 // Queued, and ready to send
00823                                 return OpenFileSendHeaders();
00824                         }
00825                         else if ( m_bQueueMe )
00826                         {
00827                                 // Queued, but must wait
00828                         }
00829                         else
00830                         {
00831                                 // Client can't queue, so dequeue and return busy
00832                                 UploadQueues.Dequeue( this );
00833                                 ASSERT( m_pQueue == NULL );
00834                         }
00835                 }
00836                 else
00837                 {
00838                         // Unable to queue anywhere
00839                 }
00840         }
00841         else
00842         {
00843                 // Too many from this host
00844                 
00845                 UploadQueues.Dequeue( this );
00846                 ASSERT( m_pQueue == NULL );
00847         
00848                 nError = IDS_UPLOAD_BUSY_HOST;
00849         }
00850         
00851         if ( m_pQueue != NULL )
00852         {
00853                 CString strHeader, strName;
00854                 
00855                 m_pOutput->Print( "HTTP/1.1 503 Busy Queued\r\n" );
00856                 
00857                 SendDefaultHeaders();
00858                 SendFileHeaders();
00859                 
00860                 m_nReaskMultiplier=( nPosition <= 9 ) ? ( (nPosition+1) / 2 ) : 5;
00861                 DWORD nTimeScale = 1000 / m_nReaskMultiplier;
00862                 
00863                 CSingleLock pLock( &UploadQueues.m_pSection, TRUE );
00864                 
00865                 if ( UploadQueues.Check( m_pQueue ) )
00866                 {
00867                         strName = m_pQueue->m_sName;
00868                         Replace( strName, _T("\""), _T("'") );
00869                         
00870                         strHeader.Format( _T("X-Queue: position=%i,length=%i,limit=%i,pollMin=%lu,pollMax=%lu,id=\"%s\"\r\n"),
00871                                 nPosition,
00872                                 m_pQueue->GetQueuedCount(),
00873                                 m_pQueue->GetTransferCount( TRUE ),
00874                                 Settings.Uploads.QueuePollMin / nTimeScale,
00875                                 Settings.Uploads.QueuePollMax / nTimeScale,
00876                                 (LPCTSTR)strName );
00877                         
00878                         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_QUEUED, (LPCTSTR)m_sFileName,
00879                                 (LPCTSTR)m_sAddress, nPosition, m_pQueue->GetQueuedCount(),
00880                                 (LPCTSTR)strName );
00881 
00882                 }
00883                 
00884                 pLock.Unlock();
00885                 
00886                 m_pOutput->Print( strHeader );
00887                 m_pOutput->Print( "Content-Length: 0\r\n" );
00888                 m_pOutput->Print( "\r\n" );
00889                 
00890                 StartSending( upsPreQueue );
00891         }
00892         else
00893         {
00894                 SendResponse( IDR_HTML_BUSY, TRUE );
00895                 
00896                 if ( ! nError ) nError = m_bQueueMe ? IDS_UPLOAD_BUSY_QUEUE : IDS_UPLOAD_BUSY_OLD;
00897                 theApp.Message( MSG_ERROR, nError, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
00898         }
00899         
00900         return TRUE;
00901 }
00902 
00904 // CUploadTransferHTTP default response headers
00905 
00906 void CUploadTransferHTTP::SendDefaultHeaders()
00907 {
00908         CString strLine = Settings.SmartAgent();
00909         
00910         if ( strLine.GetLength() )
00911         {
00912                 strLine = _T("Server: ") + strLine + _T("\r\n");
00913                 m_pOutput->Print( strLine );
00914         }
00915         
00916         if ( ! m_bInitiated )
00917         {
00918                 strLine.Format( _T("Remote-IP: %s\r\n"),
00919                         (LPCTSTR)CString( inet_ntoa( m_pHost.sin_addr ) ) );
00920                 m_pOutput->Print( strLine );
00921         }
00922         
00923         if ( m_bKeepAlive )
00924         {
00925                 m_pOutput->Print( "Connection: Keep-Alive\r\n" );
00926         }
00927         else
00928         {
00929                 m_pOutput->Print( "Connection: Close\r\n" );
00930         }
00931         
00932         m_pOutput->Print( "Accept-Ranges: bytes\r\n" );
00933         
00934         if ( m_nRequests <= 1 )
00935         {
00936                 if ( m_bInitiated ) SendMyAddress();
00937                 strLine.Format( _T("X-PerHost: %lu\r\n"), Settings.Uploads.MaxPerHost );
00938                 m_pOutput->Print( strLine );
00939                 
00940                 strLine = MyProfile.GetNick().Left( 255 );
00941                 
00942                 if ( strLine.GetLength() > 0 )
00943                 {
00944                         strLine = _T("X-Nick: ") + URLEncode( strLine ) + _T("\r\n");
00945                         m_pOutput->Print( strLine );
00946                 }
00947         }
00948 }
00949 
00951 // CUploadTransferHTTP file response headers
00952 
00953 void CUploadTransferHTTP::SendFileHeaders()
00954 {
00955         CString strHeader;
00956         
00957         if ( m_bSHA1 )
00958         {
00959                 if ( m_bTiger )
00960                 {
00961                         strHeader       = _T("X-Content-URN: urn:bitprint:")
00962                                                 + CSHA::HashToString( &m_pSHA1, FALSE ) + '.'
00963                                                 + CTigerNode::HashToString( &m_pTiger, FALSE ) + _T("\r\n");
00964                 }
00965                 else
00966                 {
00967                         strHeader = _T("X-Content-URN: ") + CSHA::HashToString( &m_pSHA1, TRUE ) + _T("\r\n");
00968                 }
00969                 
00970                 m_pOutput->Print( strHeader );
00971         }
00972         else if ( m_bTiger )
00973         {
00974                 strHeader = _T("X-Content-URN: ") + CTigerNode::HashToString( &m_pTiger, TRUE ) + _T("\r\n");
00975                 m_pOutput->Print( strHeader );
00976         }
00977         
00978         if ( m_bED2K )
00979         {
00980                 strHeader = _T("X-Content-URN: ") + CED2K::HashToString( &m_pED2K, TRUE ) + _T("\r\n");
00981                 m_pOutput->Print( strHeader );
00982         }
00983         
00984         if ( m_bTigerTree && Settings.Uploads.ShareTiger )
00985         {
00986                 strHeader       = _T("X-Thex-URI: /gnutella/thex/v1?")
00987                         + CTigerNode::HashToString( &m_pTiger, TRUE )
00988                         + _T("&depth=9&ed2k=0;") 
00989                         + CTigerNode::HashToString( &m_pTiger, FALSE )
00990                         + _T("\r\n");
00991                 m_pOutput->Print( strHeader );
00992         }
00993         
00994         if ( m_bMetadata )
00995         {
00996                 strHeader       = _T("X-Metadata-Path: /gnutella/metadata/v1?")
00997                                         + CTigerNode::HashToString( &m_pTiger, TRUE )
00998                                         + _T("\r\n");
00999                 m_pOutput->Print( strHeader );
01000         }
01001         
01002         if ( m_sRanges.GetLength() )
01003         {
01004                 strHeader = _T("X-Available-Ranges: ") + m_sRanges + _T("\r\n");
01005                 m_pOutput->Print( strHeader );
01006         }
01007         
01008         if ( m_sLocations.GetLength() )
01009         {
01010                 strHeader = _T("Alt-Location: ") + m_sLocations + _T("\r\n");
01011                 m_pOutput->Print( strHeader );
01012         }
01013 }
01014 
01016 // CUploadTransferHTTP open file and send headers
01017 
01018 BOOL CUploadTransferHTTP::OpenFileSendHeaders()
01019 {
01020         ASSERT( m_pDiskFile == NULL );
01021         
01022         m_pDiskFile = TransferFiles.Open( m_sFilePath, FALSE, FALSE );
01023         
01024         // If there's an error reading the file from disk
01025         if ( m_pDiskFile == NULL )
01026         {
01027                 SendResponse( IDR_HTML_FILENOTFOUND );
01028                 theApp.Message( MSG_ERROR, IDS_UPLOAD_CANTOPEN, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01029                 return TRUE;
01030         }
01031         
01032         CSingleLock pLock( &UploadQueues.m_pSection, TRUE );
01033         
01034         if ( m_pQueue != NULL && UploadQueues.Check( m_pQueue ) && m_pQueue->m_bRotate )
01035         {
01036                 DWORD nLimit = m_pQueue->m_nRotateChunk;
01037                 if ( nLimit == 0 ) nLimit = Settings.Uploads.RotateChunkLimit;
01038                 if ( nLimit > 0 ) m_nLength = min( m_nLength, QWORD(nLimit) );
01039         }
01040         
01041         pLock.Unlock();
01042         
01043         if ( m_nLength != m_nFileSize )
01044                 m_pOutput->Print( "HTTP/1.1 206 OK\r\n" );
01045         else
01046                 m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
01047         
01048         SendDefaultHeaders();
01049         
01050         CString strExt, strResponse;
01051         
01052         int nType = m_sFileName.ReverseFind( '.' );
01053         if ( nType > 0 ) strExt = m_sFileName.Mid( nType );
01054         ShellIcons.Lookup( strExt, NULL, NULL, NULL, &strResponse );
01055         
01056         if ( strResponse.IsEmpty() )
01057         {
01058                 m_pOutput->Print( "Content-Type: application/x-binary\r\n" );
01059         }
01060         else
01061         {
01062                 strResponse = _T("Content-Type: ") + strResponse + _T("\r\n");
01063                 m_pOutput->Print( strResponse );
01064         }
01065         
01066         strResponse.Format( _T("Content-Length: %I64i\r\n"), m_nLength );
01067         m_pOutput->Print( strResponse );
01068         
01069         if ( m_nLength != m_nFileSize )
01070         {
01071                 strResponse.Format( _T("Content-Range: bytes=%I64i-%I64i/%I64i\r\n"), m_nOffset, m_nOffset + m_nLength - 1, m_nFileSize );
01072                 m_pOutput->Print( strResponse );
01073         }
01074         
01075         if ( ! m_bHead && m_bBackwards )
01076         {
01077                 m_pOutput->Print( "Content-Encoding: backwards\r\n" );
01078         }
01079         
01080         if ( m_bSHA1 || m_bTiger || m_bED2K ) SendFileHeaders();
01081         
01082         m_pOutput->Print( "\r\n" );
01083         
01084         if ( m_bHead )
01085         {
01086                 m_pDiskFile->Release( FALSE );
01087                 m_pDiskFile = NULL;
01088                 
01089                 theApp.Message( MSG_DEFAULT, IDS_UPLOAD_HEADERS, (LPCTSTR)m_sFileName,
01090                         (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
01091                 
01092                 StartSending( upsResponse );
01093         }
01094         else
01095         {
01096                 if ( m_pBaseFile->m_nRequests++ == 0 )
01097                 {
01098                         theApp.Message( MSG_SYSTEM, IDS_UPLOAD_FILE,
01099                                 (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01100                         
01101                         CQuickLock oLock( Library.m_pSection );
01102                         if ( CLibraryFile* pFile = LibraryMaps.LookupFileByPath( m_sFilePath, TRUE, TRUE ) )
01103                         {
01104                                 pFile->m_nUploadsToday++;
01105                                 pFile->m_nUploadsTotal++;
01106                         }
01107                 }
01108                 
01109                 theApp.Message( MSG_DEFAULT,
01110                         m_sRanges.GetLength() ? IDS_UPLOAD_PARTIAL_CONTENT : IDS_UPLOAD_CONTENT,
01111                         m_nOffset, m_nOffset + m_nLength - 1, (LPCTSTR)m_sFileName,
01112                         (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
01113                 
01114                 StartSending( upsUploading );
01115         }
01116         
01117         OnWrite();
01118         
01119         return TRUE;
01120 }
01121 
01123 // CUploadTransferHTTP write handler
01124 
01125 BOOL CUploadTransferHTTP::OnWrite()
01126 {
01127         if ( m_nState == upsUploading && m_pDiskFile != NULL && m_pOutput->m_nLength == 0 )
01128         {
01129                 if ( m_nPosition >= m_nLength )
01130                 {
01131                         OnCompleted();
01132                         CUploadTransfer::OnWrite();
01133                         return TRUE;
01134                 }
01135                 
01136                 QWORD nPacket = min( m_nLength - m_nPosition, (QWORD)Transfers.m_nBuffer );
01137                 BYTE* pBuffer = Transfers.m_pBuffer;
01138                 
01139                 if ( m_bBackwards )
01140                 {
01141                         QWORD nRead = 0;
01142                         m_pDiskFile->Read( m_nFileBase + m_nOffset + m_nLength - m_nPosition - nPacket, pBuffer, nPacket, &nRead );
01143                         if ( nRead != nPacket ) return TRUE;
01144                         m_pOutput->AddReversed( pBuffer, (DWORD)nPacket );
01145                 }
01146                 else
01147                 {
01148                         m_pDiskFile->Read( m_nFileBase + m_nOffset + m_nPosition, pBuffer, nPacket, &nPacket );
01149                         if ( nPacket == 0 ) return TRUE;
01150                         m_pOutput->Add( pBuffer, (DWORD)nPacket );
01151                 }
01152                 
01153                 m_nPosition += nPacket;
01154                 m_nUploaded += nPacket;
01155                 
01156                 Statistics.Current.Uploads.Volume += ( nPacket / 1024 );
01157         }
01158         
01159         CUploadTransfer::OnWrite();
01160         
01161         if ( m_nState >= upsResponse && m_pOutput->m_nLength == 0 )
01162         {
01163                 m_nState        = ( m_nState == upsPreQueue ) ? upsQueued : upsRequest;
01164                 m_tRequest      = GetTickCount();
01165         }
01166         
01167         return TRUE;
01168 }
01169 
01170 void CUploadTransferHTTP::OnCompleted()
01171 {
01172         Uploads.SetStable( GetAverageSpeed() );
01173         
01174         m_pDiskFile->Release( FALSE );
01175         m_pDiskFile     = NULL;
01176         m_nState        = upsRequest;
01177         m_tRequest      = GetTickCount();
01178         
01179         m_pBaseFile->AddFragment( m_nOffset, m_nLength );
01180         // m_pBaseFile = NULL;
01181         
01182         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_FINISHED, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01183 }
01184 
01186 // CUploadTransferHTTP run handler
01187 
01188 BOOL CUploadTransferHTTP::OnRun()
01189 {
01190         CUploadTransfer::OnRun();
01191         
01192         DWORD tNow = GetTickCount();
01193         
01194         switch ( m_nState )
01195         {
01196         case upsRequest:
01197                 if ( ! m_bKeepAlive && m_pOutput->m_nLength == 0 )
01198                 {
01199                         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_DROPPED, (LPCTSTR)m_sAddress );
01200                         Close();
01201                         return FALSE;
01202                 }
01203 
01204         case upsHeaders:
01205                 if ( tNow - m_tRequest > Settings.Connection.TimeoutHandshake )
01206                 {
01207                         theApp.Message( MSG_ERROR, IDS_UPLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
01208                         Close();
01209                         return FALSE;
01210                 }
01211                 break;
01212 
01213         case upsQueued:
01214                 if ( tNow - m_tRequest > ( Settings.Uploads.QueuePollMax * m_nReaskMultiplier ) )
01215                 {
01216                         theApp.Message( MSG_ERROR, IDS_UPLOAD_REQUEST_TIMEOUT, (LPCTSTR)m_sAddress );
01217                         Close();
01218                         return FALSE;
01219                 }
01220                 break;
01221 
01222         case upsUploading:
01223         case upsResponse:
01224         case upsBrowse:
01225         case upsTigerTree:
01226         case upsMetadata:
01227         case upsPreview:
01228         case upsPreQueue:
01229                 if ( tNow - m_mOutput.tLast > Settings.Connection.TimeoutTraffic )
01230                 {
01231                         theApp.Message( MSG_ERROR, IDS_UPLOAD_TRAFFIC_TIMEOUT, (LPCTSTR)m_sAddress );
01232                         Close();
01233                         return FALSE;
01234                 }
01235                 break;
01236                 
01237         }
01238         
01239         return TRUE;
01240 }
01241 
01243 // CUploadTransferHTTP dropped handler
01244 
01245 void CUploadTransferHTTP::OnDropped(BOOL bError)
01246 {
01247         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_DROPPED, (LPCTSTR)m_sAddress );
01248         
01249         if ( m_nState == upsUploading && m_pBaseFile != NULL )
01250         {
01251                 if ( m_bBackwards )
01252                 {
01253                         m_pBaseFile->AddFragment( m_nOffset + m_nLength - m_nPosition, m_nPosition );
01254                 }
01255                 else
01256                 {
01257                         m_pBaseFile->AddFragment( m_nOffset, m_nPosition );
01258                 }
01259                 
01260                 m_pBaseFile = NULL;
01261         }
01262         
01263         Close();
01264 }
01265 
01267 // CUploadTransferHTTP request metadata
01268 
01269 BOOL CUploadTransferHTTP::RequestMetadata(CXMLElement* pMetadata)
01270 {
01271         ASSERT( pMetadata != NULL );
01272         CString strXML = pMetadata->ToString( TRUE, TRUE );
01273         delete pMetadata;
01274         
01275         int nXML = WideCharToMultiByte( CP_UTF8, 0, strXML, strXML.GetLength(), NULL, 0, NULL, NULL );
01276         LPSTR pszXML = new CHAR[ nXML ];
01277         WideCharToMultiByte( CP_UTF8, 0, strXML, strXML.GetLength(), pszXML, nXML, NULL, NULL );
01278         
01279         m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
01280         SendDefaultHeaders();
01281         m_pOutput->Print( "Content-Type: text/xml\r\n" );
01282         
01283         CString strHeader;
01284         strHeader.Format( _T("Content-Length: %lu\r\n"), nXML );
01285         m_pOutput->Print( strHeader );
01286         m_pOutput->Print( "\r\n" );
01287         
01288         if ( ! m_bHead ) m_pOutput->Add( pszXML, nXML );
01289         delete [] pszXML;
01290         
01291         StartSending( upsMetadata );
01292         
01293         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_METADATA_SEND,
01294                 (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01295         
01296         return TRUE;
01297 }
01298 
01300 // CUploadTransferHTTP request a tiger tree hash, raw format
01301 
01302 BOOL CUploadTransferHTTP::RequestTigerTreeRaw(CTigerTree* pTigerTree, BOOL bDelete)
01303 {
01304         if ( pTigerTree == NULL )
01305         {
01306                 ClearHashes();
01307                 m_sLocations.Empty();
01308                 
01309                 SendResponse( IDR_HTML_FILENOTFOUND, TRUE );
01310                 theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
01311                 
01312                 return TRUE;
01313         }
01314         
01315         BYTE* pSerialTree;
01316         DWORD nSerialTree;
01317         
01318         pTigerTree->ToBytes( &pSerialTree, &nSerialTree );
01319         if ( bDelete ) delete pTigerTree;
01320         
01321         if ( m_bRange )
01322         {
01323                 if ( m_nOffset >= nSerialTree ) m_nLength = SIZE_UNKNOWN;
01324                 else m_nLength = min( m_nLength, nSerialTree - m_nOffset );
01325         }
01326         else
01327         {
01328                 m_nOffset = 0;
01329                 m_nLength = nSerialTree;
01330         }
01331         
01332         if ( m_nLength <= nSerialTree )
01333         {
01334                 CString strHeader;
01335                 
01336                 if ( m_nLength != nSerialTree )
01337                         m_pOutput->Print( "HTTP/1.1 206 OK\r\n" );
01338                 else
01339                         m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
01340                 
01341                 SendDefaultHeaders();
01342                 
01343                 m_pOutput->Print( "Content-Type: application/tigertree-breadthfirst\r\n" );
01344                 strHeader.Format( _T("Content-Length: %I64i\r\n"), m_nLength );
01345                 m_pOutput->Print( strHeader );
01346                 
01347                 if ( m_nLength != nSerialTree )
01348                 {
01349                         strHeader.Format( _T("Content-Range: %I64i-%I64i\r\n"), m_nOffset, m_nOffset + m_nLength - 1 );
01350                         m_pOutput->Print( strHeader );
01351                 }
01352                 
01353                 m_pOutput->Print( "\r\n" );
01354                 
01355                 if ( ! m_bHead ) m_pOutput->Add( pSerialTree + m_nOffset, (DWORD)m_nLength );
01356                 
01357                 StartSending( upsTigerTree );
01358                 
01359                 theApp.Message( MSG_DEFAULT, IDS_UPLOAD_TIGER_SEND,
01360                         (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01361         }
01362         else
01363         {
01364                 m_sRanges.Format( _T("0-%I64i"), (QWORD)nSerialTree - 1 );
01365                 ClearHashes();
01366                 m_sLocations.Empty();
01367                 
01368                 SendResponse( IDR_HTML_BADRANGE, TRUE );
01369                 theApp.Message( MSG_ERROR, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
01370         }
01371         
01372         delete [] pSerialTree;
01373         
01374         return TRUE;
01375 }
01376 
01378 // CUploadTransferHTTP request a tiger tree hash, DIME format
01379 
01380 BOOL CUploadTransferHTTP::RequestTigerTreeDIME(CTigerTree* pTigerTree, int nDepth, CED2K* pHashset, BOOL bDelete)
01381 {
01382         if ( pTigerTree == NULL )
01383         {
01384                 ClearHashes();
01385                 m_sLocations.Empty();
01386                 
01387                 SendResponse( IDR_HTML_FILENOTFOUND, TRUE );
01388                 theApp.Message( MSG_ERROR, IDS_UPLOAD_FILENOTFOUND, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
01389                 
01390                 if ( pHashset != NULL && bDelete ) delete pHashset;
01391                 
01392                 return TRUE;
01393         }
01394         
01395         DWORD nSerialTree;
01396         BYTE* pSerialTree;
01397         CBuffer pDIME;
01398         
01399         if ( nDepth < 1 ) nDepth = pTigerTree->GetHeight();
01400         else if ( nDepth > (int)pTigerTree->GetHeight() ) nDepth = pTigerTree->GetHeight();
01401         
01402         pTigerTree->ToBytes( &pSerialTree, &nSerialTree, nDepth );
01403         if ( bDelete ) delete pTigerTree;
01404         
01405         CString strUUID, strXML;
01406         GUID pUUID;
01407         
01408         Network.CreateID( *(GGUID*)&pUUID );
01409         strUUID.Format( _T("uuid:%.8x-%.4x-%.4x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x"),
01410                 pUUID.Data1, pUUID.Data2, pUUID.Data3,
01411                 pUUID.Data4[0], pUUID.Data4[1], pUUID.Data4[2], pUUID.Data4[3],
01412                 pUUID.Data4[4], pUUID.Data4[5], pUUID.Data4[6], pUUID.Data4[7] );
01413         
01414         strXML.Format(  _T("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n")
01415                                         _T("<!DOCTYPE hashtree SYSTEM \"http://open-content.net/spec/thex/thex.dtd\">\r\n")
01416                                         _T("<hashtree>\r\n")
01417                                         _T("\t<file size=\"%I64i\" segmentsize=\"1024\"/>\r\n")
01418                                         _T("\t<digest algorithm=\"http://open-content.net/spec/digest/tiger\" outputsize=\"24\"/>\r\n")
01419                                         _T("\t<serializedtree depth=\"%i\" type=\"http://open-content.net/spec/thex/breadthfirst\" uri=\"%s\"/>\r\n")
01420                                         _T("</hashtree>"),
01421                                         m_nFileSize, nDepth, (LPCTSTR)strUUID );
01422         
01423         int nXML = WideCharToMultiByte( CP_UTF8, 0, strXML, -1, NULL, 0, NULL, NULL );
01424         LPSTR pszXML = new CHAR[ nXML ];
01425         WideCharToMultiByte( CP_UTF8, 0, strXML, -1, pszXML, nXML, NULL, NULL );
01426         int nUUID = WideCharToMultiByte( CP_ACP, 0, strUUID, -1, NULL, 0, NULL, NULL );
01427         LPSTR pszUUID = new CHAR[ nUUID ];
01428         WideCharToMultiByte( CP_ACP, 0, strUUID, -1, pszUUID, nUUID, NULL, NULL );
01429         
01430         pDIME.WriteDIME( 1, "", "text/xml", pszXML, strlen(pszXML) );
01431         pDIME.WriteDIME( pHashset ? 0 : 2, pszUUID, "http://open-content.net/spec/thex/breadthfirst", pSerialTree, nSerialTree );
01432         delete [] pSerialTree;
01433         
01434         delete [] pszUUID;
01435         delete [] pszXML;
01436         
01437         if ( pHashset != NULL )
01438         {
01439                 pHashset->ToBytes( &pSerialTree, &nSerialTree );
01440                 if ( bDelete ) delete pHashset;
01441                 
01442                 pDIME.WriteDIME( 2, "", "http://edonkey2000.com/spec/md4-hashset", pSerialTree, nSerialTree );
01443                 delete [] pSerialTree;
01444         }
01445         
01446         if ( m_bRange )
01447         {
01448                 if ( m_nOffset >= (QWORD)pDIME.m_nLength ) m_nLength = SIZE_UNKNOWN;
01449                 else m_nLength = min( m_nLength, (QWORD)pDIME.m_nLength - m_nOffset );
01450         }
01451         else
01452         {
01453                 m_nOffset = 0;
01454                 m_nLength = (QWORD)pDIME.m_nLength;
01455         }
01456         
01457         if ( m_nLength <= pDIME.m_nLength )
01458         {
01459                 CString strHeader;
01460                 
01461                 if ( m_nLength != pDIME.m_nLength )
01462                         m_pOutput->Print( "HTTP/1.1 206 OK\r\n" );
01463                 else
01464                         m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
01465                 
01466                 SendDefaultHeaders();
01467                 
01468                 m_pOutput->Print( "Content-Type: application/dime\r\n" );
01469                 strHeader.Format( _T("Content-Length: %I64i\r\n"), m_nLength );
01470                 m_pOutput->Print( strHeader );
01471                 
01472                 if ( m_nLength != pDIME.m_nLength )
01473                 {
01474                         strHeader.Format( _T("Content-Range: %I64i-%I64i\r\n"), m_nOffset, m_nOffset + m_nLength - 1 );
01475                         m_pOutput->Print( strHeader );
01476                 }
01477                 
01478                 m_pOutput->Print( "\r\n" );
01479                 
01480                 if ( ! m_bHead )
01481                 {
01482                         m_pOutput->Add( pDIME.m_pBuffer + m_nOffset, (DWORD)m_nLength );
01483                 }
01484                 
01485                 StartSending( upsTigerTree );
01486                 
01487                 theApp.Message( MSG_DEFAULT, IDS_UPLOAD_TIGER_SEND,
01488                         (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01489         }
01490         else
01491         {
01492                 m_sRanges.Format( _T("0-%I64i"), (QWORD)pDIME.m_nLength - 1 );
01493                 ClearHashes();
01494                 m_sLocations.Empty();
01495                 
01496                 SendResponse( IDR_HTML_BADRANGE, TRUE );
01497                 theApp.Message( MSG_ERROR, IDS_UPLOAD_BAD_RANGE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
01498         }
01499         
01500         return TRUE;
01501 }
01502 
01504 // CUploadTransferHTTP request preview
01505 
01506 BOOL CUploadTransferHTTP::RequestPreview(CLibraryFile* pFile, CSingleLock& oLibraryLock)
01507 {
01508         ASSERT( pFile != NULL );
01509         
01510         m_sFileName             = pFile->m_sName;
01511         m_sFilePath             = pFile->GetPath();
01512         m_bSHA1                 = pFile->m_bSHA1;
01513         m_pSHA1                 = pFile->m_pSHA1;
01514         m_bTiger                = pFile->m_bTiger;
01515         m_pTiger                = pFile->m_pTiger;
01516         m_bED2K                 = pFile->m_bED2K;
01517         m_pED2K                 = pFile->m_pED2K;
01518         DWORD nIndex    = pFile->m_nIndex;
01519         BOOL bCached    = pFile->m_bCachedPreview;
01520         
01521         oLibraryLock.Unlock();
01522         
01523         int nExisting = Uploads.GetCount( this, upsPreview );
01524         
01525         if ( nExisting >= (int)Settings.Uploads.PreviewTransfers )
01526         {
01527                 theApp.Message( MSG_ERROR, IDS_UPLOAD_PREVIEW_BUSY, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01528                 m_pOutput->Print( "HTTP/1.1 503 Busy\r\n" );
01529                 SendDefaultHeaders();
01530                 StartSending( upsResponse );
01531                 return TRUE;
01532         }
01533         
01534         CImageServices pServices;
01535         CImageFile pImage( &pServices );
01536         CThumbCache pCache;
01537         CSize szThumb( 0, 0 );
01538         
01539         if ( pCache.Load( m_sFilePath, &szThumb, nIndex, &pImage ) )
01540         {
01541                 // Got a cached copy
01542         }
01543         else if ( Settings.Uploads.DynamicPreviews && pImage.LoadFromFile( m_sFilePath, FALSE, TRUE ) && pImage.EnsureRGB() )
01544         {
01545                 theApp.Message( MSG_DEFAULT, IDS_UPLOAD_PREVIEW_DYNAMIC, (LPCTSTR)m_sFileName, (LPCTSTR)m_sAddress );
01546                 
01547                 int nSize = szThumb.cy * pImage.m_nWidth / pImage.m_nHeight;
01548                 
01549                 if ( nSize > szThumb.cx )
01550                 {
01551                         nSize = szThumb.cx * pImage.m_nHeight / pImage.m_nWidth;
01552                         pImage.Resample( szThumb.cx, nSize );
01553                 }
01554                 else
01555                 {
01556                         pImage.Resample( nSize, szThumb.cy );
01557                 }
01558                 
01559                 pCache.Store( m_sFilePath, &szThumb, nIndex, &pImage );
01560         }
01561         else
01562         {
01563                 theApp.Message( MSG_ERROR, IDS_UPLOAD_PREVIEW_EMPTY, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
01564                 SendResponse( IDR_HTML_FILENOTFOUND );
01565                 return TRUE;
01566         }
01567         
01568         if ( ! bCached )
01569         {
01570                 CQuickLock oLock( Library.m_pSection );
01571                 if ( pFile = Library.LookupFile( nIndex ) )
01572                 {
01573                         pFile->m_bCachedPreview = TRUE;
01574                         Library.Update();
01575                 }
01576         }
01577         
01578         BYTE* pBuffer = NULL;
01579         DWORD nLength = 0;
01580         
01581         int nQuality = Settings.Uploads.PreviewQuality;
01582         
01583         if ( LPCTSTR pszQuality = _tcsistr( m_sRequest, _T("&quality=") ) )
01584         {
01585                 _stscanf( pszQuality + 9, _T("%i"), &nQuality );
01586                 nQuality = max( 1, min( 100, nQuality ) );
01587         }
01588         
01589         if ( ! pImage.SaveToMemory( _T(".jpg"), nQuality, &pBuffer, &nLength ) )
01590         {
01591                 theApp.Message( MSG_ERROR, IDS_UPLOAD_PREVIEW_EMPTY, (LPCTSTR)m_sAddress, (LPCTSTR)m_sFileName );
01592                 SendResponse( IDR_HTML_FILENOTFOUND );
01593                 return TRUE;
01594         }
01595         
01596         pServices.Cleanup();
01597         
01598         m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
01599         SendDefaultHeaders();
01600         
01601         CString strHeader;
01602         
01603         if ( m_bSHA1 )
01604         {
01605                 strHeader.Format( _T("X-Previewed-URN: %s\r\n"),
01606                         (LPCTSTR)CSHA::HashToString( &m_pSHA1, TRUE ) );
01607         }
01608         else if ( m_bTiger )
01609         {
01610                 strHeader.Format( _T("X-Previewed-URN: %s\r\n"),
01611                         (LPCTSTR)CTigerNode::HashToString( &m_pTiger, TRUE ) );
01612         }
01613         else if ( m_bED2K )
01614         {
01615                 strHeader.Format( _T("X-Previewed-URN: %s\r\n"),
01616                         (LPCTSTR)CED2K::HashToString( &m_pED2K, TRUE ) );
01617         }
01618         
01619         m_pOutput->Print( strHeader );
01620         
01621         m_pOutput->Print( "Content-Type: image/jpeg\r\n" );
01622         
01623         strHeader.Format( _T("Content-Length: %lu\r\n"), nLength );
01624         m_pOutput->Print( strHeader );
01625         
01626         m_pOutput->Print( "\r\n" );
01627         
01628         if ( ! m_bHead )
01629         {
01630                 m_pOutput->Add( pBuffer, nLength );
01631         }
01632         
01633         delete [] pBuffer;
01634         
01635         StartSending( upsPreview );
01636         
01637         theApp.Message( MSG_DEFAULT, IDS_UPLOAD_PREVIEW_SEND, (LPCTSTR)m_sFileName,
01638                 (LPCTSTR)m_sAddress );
01639         
01640         return TRUE;
01641 }
01642 
01644 // CUploadTransferHTTP request host browse
01645 
01646 BOOL CUploadTransferHTTP::RequestHostBrowse()
01647 {
01648         CBuffer pBuffer;
01649         
01650         int nExisting = Uploads.GetCount( this, upsBrowse );
01651         
01652         if ( nExisting >= (int)Settings.Uploads.PreviewTransfers )
01653         {
01654                 theApp.Message( MSG_ERROR, IDS_UPLOAD_BROWSE_BUSY, (LPCTSTR)m_sAddress );
01655                 m_pOutput->Print( "HTTP/1.1 503 Busy\r\n" );
01656                 SendDefaultHeaders();
01657                 StartSending( upsResponse );
01658                 return TRUE;
01659         }
01660         
01661         if ( m_bHostBrowse < 2 )
01662         {
01663                 if ( Settings.Community.ServeFiles )
01664                 {
01665                         CLocalSearch pSearch( NULL, &pBuffer, PROTOCOL_G1 );
01666                         pSearch.Execute( 0 );
01667                 }
01668         }
01669         else
01670         {
01671                 if ( Settings.Community.ServeProfile && MyProfile.IsValid() )
01672                 {
01673                         CG2Packet* pProfile = CG2Packet::New( G2_PACKET_PROFILE_DELIVERY, TRUE );
01674                         CString strXML = MyProfile.GetXML()->ToString( TRUE );
01675                         pProfile->WritePacket( "XML", pProfile->GetStringLen( strXML ) );
01676                         pProfile->WriteString( strXML, FALSE );
01677                         pProfile->ToBuffer( &pBuffer );
01678                         pProfile->Release();
01679                 }
01680                 
01681                 if ( Settings.Community.ServeFiles )
01682                 {
01683                         CLocalSearch pSearch( NULL, &pBuffer, PROTOCOL_G2 );
01684                         pSearch.Execute( 0 );
01685                         pSearch.WriteVirtualTree();
01686                 }
01687                 
01688                 if ( Settings.Community.ServeProfile && MyProfile.IsValid() )
01689                 {
01690                         if ( CG2Packet* pAvatar = MyProfile.CreateAvatar() )
01691                         {
01692                                 pAvatar->ToBuffer( &pBuffer );
01693                                 pAvatar->Release();
01694                         }
01695                 }
01696         }
01697         
01698         m_pOutput->Print( "HTTP/1.1 200 OK\r\n" );
01699         SendDefaultHeaders();
01700         
01701         if ( m_bHostBrowse < 2 )
01702         {
01703                 m_pOutput->Print( "Content-Type: application/x-gnutella-packets\r\n" );
01704         }
01705         else
01706         {
01707                 m_pOutput->Print( "Content-Type: application/x-gnutella2\r\n" );
01708         }
01709         
01710         m_bDeflate = m_bDeflate && pBuffer.Deflate( TRUE );
01711         
01712         if ( m_bDeflate ) m_pOutput->Print( "Content-Encoding: deflate\r\n" );
01713         
01714         CString strLength;
01715         strLength.Format( _T("Content-Length: %lu\r\n\r\n"), pBuffer.m_nLength );
01716         m_pOutput->Print( strLength );
01717         
01718         if ( ! m_bHead ) m_pOutput->AddBuffer( &pBuffer );
01719         
01720         StartSending( upsBrowse );
01721         
01722         theApp.Message( MSG_SYSTEM, IDS_UPLOAD_BROWSE, (LPCTSTR)m_sAddress, (LPCTSTR)m_sUserAgent );
01723         
01724         CTransfer::OnWrite();
01725         
01726         return TRUE;
01727 }
01728 
01730 // CUploadTransferHTTP formatted response
01731 
01732 void CUploadTransferHTTP::SendResponse(UINT nResourceID, BOOL bFileHeaders)
01733 {
01734         CString strBody, strResponse;
01735         
01736         HMODULE hModule = GetModuleHandle( NULL );
01737         HRSRC hRes = FindResource( hModule, MAKEINTRESOURCE( nResourceID ), MAKEINTRESOURCE( 23 ) );
01738         
01739         if ( hRes != NULL )
01740         {
01741                 DWORD nSize                     = SizeofResource( hModule, hRes );
01742                 HGLOBAL hMemory         = LoadResource( hModule, hRes );
01743                 LPTSTR pszOutput        = strBody.GetBuffer( nSize + 1 );
01744                 LPCSTR pszInput         = (LPCSTR)LockResource( hMemory );
01745                 
01746                 while ( nSize-- ) *pszOutput++ = *pszInput++;
01747                 *pszOutput++ = 0;
01748                 
01749                 strBody.ReleaseBuffer();
01750         }
01751         
01752         int nBreak      = strBody.Find( _T("\r\n") );
01753         strResponse     = strBody.Left( nBreak + 2 );
01754         strBody         = strBody.Mid( nBreak + 2 );
01755         
01756         while ( TRUE )
01757         {
01758                 int nStart = strBody.Find( _T("<%") );
01759                 if ( nStart < 0 ) break;
01760                 
01761                 int nEnd = strBody.Find( _T("%>") );
01762                 if ( nEnd < nStart ) break;
01763 
01764                 CString strReplace = strBody.Mid( nStart + 2, nEnd - nStart - 2 );
01765 
01766                 strReplace.TrimLeft();
01767                 strReplace.TrimRight();
01768                 
01769                 if ( strReplace.CompareNoCase( _T("Name") ) == 0 )
01770                         strReplace = m_sFileName;
01771                 else if ( strReplace.CompareNoCase( _T("SHA1") ) == 0 )
01772                         strReplace = CSHA::HashToString( &m_pSHA1 );
01773                 else if ( strReplace.CompareNoCase( _T("URN") ) == 0 )
01774                         strReplace = CSHA::HashToString( &m_pSHA1, TRUE );
01775                 else if ( strReplace.CompareNoCase( _T("Version") ) == 0 )
01776                         strReplace = theApp.m_sVersion;
01777                 else if ( strReplace.CompareNoCase( _T("Neighbours") ) == 0 )
01778                         GetNeighbourList( strReplace );
01779                 else if ( strReplace.CompareNoCase( _T("ListenIP") ) == 0 )
01780                 {
01781                         if ( Network.IsListening() )
01782                         {
01783                                 strReplace.Format( _T("%s:%i"),
01784                                         (LPCTSTR)CString( inet_ntoa( Network.m_pHost.sin_addr ) ),
01785                                         htons( Network.m_pHost.sin_port ) );
01786                         }
01787                         else strReplace.Empty();
01788                 }
01789                 
01790                 strBody = strBody.Left( nStart ) + strReplace + strBody.Mid( nEnd + 2 );
01791         }
01792         
01793         m_pOutput->Print( _T("HTTP/1.1 ") + strResponse );
01794         SendDefaultHeaders();
01795         if ( bFileHeaders ) SendFileHeaders();
01796         m_pOutput->Print( "Content-Type: text/html\r\n" );
01797         
01798         int nBody = WideCharToMultiByte( CP_UTF8, 0, strBody, strBody.GetLength(), NULL, 0, NULL, NULL );
01799         LPSTR pszBody = new CHAR[ nBody ];
01800         WideCharToMultiByte( CP_UTF8, 0, strBody, strBody.GetLength(), pszBody, nBody, NULL, NULL );
01801         
01802         strResponse.Format( _T("Content-Length: %lu\r\n\r\n"), nBody );
01803         m_pOutput->Print( strResponse );
01804         
01805         if ( ! m_bHead ) m_pOutput->Add( pszBody, nBody );
01806         
01807         delete [] pszBody;
01808         
01809         StartSending( upsResponse );
01810 }
01811 
01812 void CUploadTransferHTTP::GetNeighbourList(CString& strOutput)
01813 {
01814         static LPCTSTR pszModes[4][3] =
01815         {
01816                 { _T("Handshake"), _T("Handshake"), _T("Handshake") },
01817                 { _T("G1 Peer"), _T("G1 Ultrapeer"), _T("G1 Leaf") },
01818                 { _T("G2 Peer"), _T("G2 Hub"), _T("G2 Leaf") },
01819                 { _T("eDonkey2000"), _T("eDonkey2000"), _T("eDonkey2000") }
01820         };
01821         
01822         strOutput.Empty();
01823         
01824         CSingleLock pLock( &Network.m_pSection );
01825         if ( ! pLock.Lock( 100 ) ) return;
01826                 
01827         DWORD tNow = GetTickCount();
01828                 
01829         for ( POSITION pos = Neighbours.GetIterator() ; pos ; )
01830         {
01831                 CNeighbour* pNeighbour = Neighbours.GetNext( pos );
01832                 
01833                 if ( pNeighbour->m_nState == nrsConnected )
01834                 {
01835                         CString strNode;
01836                         
01837                         DWORD nTime = ( tNow - pNeighbour->m_tConnected ) / 1000;
01838                         
01839                         strNode.Format( _T("<tr><td class=\"fi\"><a href=\"gnutella:host:%s:%lu\">%s:%lu</a></td><td class=\"fi\" align=\"center\">%i:%.2i:%.2i</td><td class=\"fi\">%s</td><td class=\"fi\">%s</td><td class=\"fi\"><a href=\"http://%s:%lu/\">Browse</a></td></tr>\r\n"),
01840                                 (LPCTSTR)pNeighbour->m_sAddress, htons( pNeighbour->m_pHost.sin_port ),
01841                                 (LPCTSTR)pNeighbour->m_sAddress, htons( pNeighbour->m_pHost.sin_port ),
01842                                 nTime / 3600, ( nTime % 3600 ) / 60, nTime % 60,
01843                                 pszModes[ pNeighbour->m_nProtocol ][ pNeighbour->m_nNodeType ],
01844                                 (LPCTSTR)pNeighbour->m_sUserAgent,
01845                                 (LPCTSTR)pNeighbour->m_sAddress, htons( pNeighbour->m_pHost.sin_port ) );
01846                         
01847                         strOutput += strNode;
01848                 }
01849         }
01850 }

Generated on Thu Dec 15 10:39:51 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2