BOOL CDownloadWithSources::AddSourceHit(const CQueryHit* pHit, BOOL bForce) { CQuickLock oLock( Transfers.m_pSection ); if ( ! AddSource( pHit, bForce ) ) return FALSE; if ( Settings.Downloads.Metadata && m_pXML == NULL && pHit->m_pXML && pHit->m_pSchema ) { m_pXML = pHit->m_pSchema->Instantiate( TRUE ); m_pXML->AddElement( pHit->m_pXML->Clone() ); pHit->m_pSchema->Validate( m_pXML, TRUE ); } //if ( pHit->m_nProtocol == PROTOCOL_ED2K ) // Neighbours.FindDonkeySources( pHit->m_oED2K, // (IN_ADDR*)pHit->m_oClientID.begin(), (WORD)pHit->m_oClientID.begin()[1] ); // No URL, stop now with success if ( ! pHit->m_sURL.IsEmpty() && ! AddSourceInternal( new CDownloadSource( (CDownload*)this, pHit ) ) ) return FALSE; return TRUE; }
BOOL CDownloadWithSources::AddSourceBT(const Hashes::BtGuid& oGUID, const IN_ADDR* pAddress, WORD nPort) { // Unreachable (Push) BT sources should never be added. if ( Network.IsFirewalledAddress( pAddress, Settings.Connection.IgnoreOwnIP ) ) return FALSE; return AddSourceInternal( new CDownloadSource( (CDownload*)this, oGUID, pAddress, nPort ) ); }
BOOL CDownloadWithSources::AddSourceBT(SHA1* pGUID, IN_ADDR* pAddress, WORD nPort) { // Unreachable (Push) BT sources should never be added. if ( Network.IsFirewalledAddress( pAddress, Settings.Connection.IgnoreOwnIP ) ) return FALSE; // Check for own IP, in case IgnoreLocalIP is not set if ( ( Settings.Connection.IgnoreOwnIP ) && ( pAddress->S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) ) return FALSE; return AddSourceInternal( new CDownloadSource( (CDownload*)this, pGUID, pAddress, nPort ) ); }
BOOL CDownloadWithSources::AddSourceURL(LPCTSTR pszURL, BOOL bURN, FILETIME* pLastSeen) { if ( pszURL == NULL ) return FALSE; if ( *pszURL == 0 ) return FALSE; BOOL bHashAuth = FALSE; CSourceURL pURL; if ( *pszURL == '@' ) { bHashAuth = TRUE; pszURL++; } if ( ! pURL.Parse( pszURL ) ) return FALSE; if ( bURN ) { if ( pURL.m_pAddress.S_un.S_addr == Network.m_pHost.sin_addr.S_un.S_addr ) return FALSE; if ( Network.IsFirewalledAddress( &pURL.m_pAddress, TRUE ) ) return FALSE; } if ( m_pFailedSources.Find( pszURL ) != NULL ) return FALSE; if ( pURL.m_bSHA1 && m_bSHA1 ) { if ( m_pSHA1 != pURL.m_pSHA1 ) return FALSE; } if ( m_sRemoteName.IsEmpty() && _tcslen( pszURL ) > 9 ) { m_sRemoteName = &pszURL[8]; int nPos = m_sRemoteName.ReverseFind( '/' ); if ( nPos >= 0 ) { m_sRemoteName = m_sRemoteName.Mid( nPos + 1 ).SpanExcluding( _T("?") ); m_sRemoteName = CTransfer::URLDecode( m_sRemoteName ); } else { m_sRemoteName.Empty(); } if ( m_sRemoteName.IsEmpty() ) m_sRemoteName = _T("default.htm"); } return AddSourceInternal( new CDownloadSource( (CDownload*)this, pszURL, bURN, bHashAuth, pLastSeen ) ); }
BOOL CDownloadWithSources::AddSourceED2K(DWORD nClientID, WORD nClientPort, DWORD nServerIP, WORD nServerPort, GGUID* pGUID) { return AddSourceInternal( new CDownloadSource( (CDownload*)this, nClientID, nClientPort, nServerIP, nServerPort, pGUID ) ); }
BOOL CDownloadWithSources::AddSourceHit(CQueryHit* pHit, BOOL bForce) { BOOL bHash = FALSE; if ( ! bForce ) { if ( m_bSHA1 && pHit->m_bSHA1 ) { if ( m_pSHA1 != pHit->m_pSHA1 ) return FALSE; bHash = TRUE; } else if ( m_bTiger && pHit->m_bTiger ) { if ( m_pTiger != pHit->m_pTiger ) return FALSE; bHash = TRUE; } if ( m_bED2K && pHit->m_bED2K ) { if ( m_pED2K != pHit->m_pED2K ) return FALSE; bHash = TRUE; } if ( m_bBTH && pHit->m_bBTH ) { if ( m_pBTH != pHit->m_pBTH ) return FALSE; bHash = TRUE; } } if ( ! bHash && ! bForce ) { if ( Settings.General.HashIntegrity ) return FALSE; if ( m_sRemoteName.IsEmpty() || pHit->m_sName.IsEmpty() ) return FALSE; if ( m_nSize == SIZE_UNKNOWN || ! pHit->m_bSize ) return FALSE; if ( m_nSize != pHit->m_nSize ) return FALSE; if ( m_sRemoteName.CompareNoCase( pHit->m_sName ) ) return FALSE; } if ( ! m_bSHA1 && pHit->m_bSHA1 ) { m_bSHA1 = TRUE; m_pSHA1 = pHit->m_pSHA1; } if ( ! m_bTiger && pHit->m_bTiger ) { m_bTiger = TRUE; m_pTiger = pHit->m_pTiger; } if ( ! m_bED2K && pHit->m_bED2K ) { m_bED2K = TRUE; m_pED2K = pHit->m_pED2K; } if ( m_nSize == SIZE_UNKNOWN && pHit->m_bSize ) { m_nSize = pHit->m_nSize; } if ( m_sRemoteName.IsEmpty() && pHit->m_sName.GetLength() ) { m_sRemoteName = pHit->m_sName; } if ( Settings.Downloads.Metadata && m_pXML == NULL ) { if ( pHit->m_pXML != NULL && pHit->m_sSchemaPlural.GetLength() ) { m_pXML = new CXMLElement( NULL, pHit->m_sSchemaPlural ); m_pXML->AddAttribute( _T("xmlns:xsi"), CXMLAttribute::xmlnsInstance ); m_pXML->AddAttribute( CXMLAttribute::schemaName, pHit->m_sSchemaURI ); m_pXML->AddElement( pHit->m_pXML->Clone() ); if ( CSchema* pSchema = SchemaCache.Get( pHit->m_sSchemaURI ) ) { pSchema->Validate( m_pXML, TRUE ); } } } /* if ( pHit->m_nProtocol == PROTOCOL_ED2K ) { Neighbours.FindDonkeySources( &pHit->m_pED2K, (IN_ADDR*)pHit->m_pClientID.w, (WORD)pHit->m_pClientID.w[1] ); } */ // No URL, stop now with success if ( pHit->m_sURL.IsEmpty() ) return TRUE; return AddSourceInternal( new CDownloadSource( (CDownload*)this, pHit ) ); }
BOOL CDownloadWithSources::AddSourceInternal(CDownloadSource* pSource) { if ( ! pSource ) return FALSE; // Out of memory if ( GetEffectiveSourceCount() > Settings.Downloads.SourcesWanted ) { delete pSource; return FALSE; // Too many sources } // Check/Reject if source is invalid if ( ! pSource->m_bPushOnly ) { // Reject invalid IPs (Sometimes ed2k sends invalid 0.x.x.x sources) if ( pSource->m_pAddress.S_un.S_un_b.s_b1 == 0 || pSource->m_nPort == 0 ) { delete pSource; return FALSE; } // Reject if source is the local IP/port if ( Network.IsSelfIP( pSource->m_pAddress ) ) { if ( Settings.Connection.IgnoreOwnIP || ( pSource->m_nServerPort == 0 && Settings.Connection.InPort == pSource->m_nPort ) ) { delete pSource; return FALSE; } } } else if ( pSource->m_nProtocol == PROTOCOL_ED2K ) { // Reject invalid server IPs (Sometimes ed2k sends invalid 0.x.x.x sources) if ( pSource->m_pServerAddress.S_un.S_un_b.s_b1 == 0 ) { delete pSource; return FALSE; } } CQuickLock pLock( Transfers.m_pSection ); if ( pSource->m_nRedirectionCount == 0 ) // Don't check for existing sources if source is a redirection { bool bDeleteSource = false; bool bHTTPSource = pSource->IsHTTPSource(); bool bNeedHTTPSource = ! bHTTPSource && Settings.Gnutella2.Enabled && VendorCache.IsExtended( pSource->m_sServer ); // Remove unneeded sources for ( POSITION posSource = GetIterator() ; posSource ; ) { CDownloadSource* pExisting = GetNext( posSource ); ASSERT( pSource != pExisting ); if ( pExisting->Equals( pSource ) ) // IPs and ports are equal { bool bExistingHTTPSource = pExisting->IsHTTPSource(); if ( bNeedHTTPSource && bExistingHTTPSource ) bNeedHTTPSource = false; if ( ( pExisting->m_nProtocol == pSource->m_nProtocol ) || ( bExistingHTTPSource && bHTTPSource ) ) { bDeleteSource = true; // Same protocol } else if ( ! pExisting->IsIdle() ) { // Already downloading so we can remove new non-HTTP source if ( bExistingHTTPSource && ! bHTTPSource ) bDeleteSource = true; } else // We are not downloading { // ...So we can replace non-HTTP source with a new one if ( ! bExistingHTTPSource && bHTTPSource ) { // Set connection delay the same as for the old source pSource->m_tAttempt = pExisting->m_tAttempt; pExisting->Remove( TRUE, FALSE ); } } } } if ( bDeleteSource ) { delete pSource; SetModified(); return FALSE; } // Make additional G2 source from the existing non-HTTP PeerProject source if ( bNeedHTTPSource ) { CString strURL = GetURL( pSource->m_pAddress, pSource->m_nPort ); if ( ! strURL.IsEmpty() ) { if ( CDownloadSource* pG2Source = new CDownloadSource( (CDownload*)this, strURL ) ) { pG2Source->m_sServer = pSource->m_sServer; // Copy user-agent pG2Source->m_tAttempt = pSource->m_tAttempt; // Set the same connection delay pG2Source->m_nProtocol = PROTOCOL_HTTP; AddSourceInternal( pG2Source ); } } } } InternalAdd( pSource ); SetModified(); return TRUE; }
BOOL CDownloadWithSources::AddSourceURL(LPCTSTR pszURL, BOOL bURN, FILETIME* pLastSeen, int nRedirectionCount, BOOL bFailed) { if ( pszURL == NULL || *pszURL == 0 ) return FALSE; if ( nRedirectionCount > 5 ) return FALSE; // No more than 5 redirections BOOL bHashAuth = FALSE; BOOL bValidated = FALSE; CPeerProjectURL pURL; if ( *pszURL == '@' ) { bHashAuth = TRUE; pszURL++; } if ( ! pURL.Parse( pszURL ) ) return FALSE; // Wrong URL if ( pURL.m_nAction == CPeerProjectURL::uriHost && pURL.m_nProtocol == PROTOCOL_DC ) { // Connect to specified DC++ hub for future searches Network.ConnectTo( pURL.m_sName, pURL.m_nPort, PROTOCOL_DC ); return FALSE; } if ( pURL.m_nAction != CPeerProjectURL::uriDownload && pURL.m_nAction != CPeerProjectURL::uriSource ) return FALSE; // Wrong URL type if ( bURN ) { if ( Network.IsFirewalledAddress( &pURL.m_pAddress, TRUE ) || Network.IsReserved( &pURL.m_pAddress ) ) return FALSE; } CQuickLock pLock( Transfers.m_pSection ); CFailedSource* pBadSource = LookupFailedSource( pszURL ); if ( pBadSource ) { // Add a positive vote, add to downloads if negative votes compose less than 2/3 of total. int nTotal = pBadSource->m_nPositiveVotes + pBadSource->m_nNegativeVotes + 1; if ( bFailed ) pBadSource->m_nNegativeVotes++; else pBadSource->m_nPositiveVotes++; if ( nTotal > 30 && pBadSource->m_nNegativeVotes / nTotal > 2 / 3 ) return FALSE; } else if ( bFailed ) { AddFailedSource( pszURL, false ); VoteSource( pszURL, false ); return TRUE; } // Validate SHA1 if ( pURL.m_oSHA1 && m_oSHA1 ) { if ( m_oSHA1 != pURL.m_oSHA1 ) return FALSE; bValidated = TRUE; } // Validate Tiger if ( pURL.m_oTiger && m_oTiger ) { if ( m_oTiger != pURL.m_oTiger ) return FALSE; bValidated = TRUE; } // Validate ED2K if ( pURL.m_oED2K && m_oED2K ) { if ( m_oED2K != pURL.m_oED2K ) return FALSE; bValidated = TRUE; } // Validate MD5 if ( pURL.m_oMD5 && m_oMD5 ) { if ( m_oMD5 != pURL.m_oMD5 ) return FALSE; bValidated = TRUE; } // Validate BTH if ( pURL.m_oBTH && m_oBTH && ! bValidated ) { if ( m_oBTH != pURL.m_oBTH ) return FALSE; bValidated = TRUE; } // Validate size if ( m_nSize != SIZE_UNKNOWN && pURL.m_bSize && pURL.m_nSize != SIZE_UNKNOWN ) { if ( m_nSize != pURL.m_nSize ) return FALSE; } // Get SHA1 if ( pURL.m_oSHA1 && ! m_oSHA1 ) m_oSHA1 = pURL.m_oSHA1; // Get Tiger if ( pURL.m_oTiger && ! m_oTiger ) m_oTiger = pURL.m_oTiger; // Get ED2K if ( pURL.m_oED2K && ! m_oED2K ) m_oED2K = pURL.m_oED2K; // Get MD5 if ( pURL.m_oMD5 && ! m_oMD5 ) m_oMD5 = pURL.m_oMD5; // Get BTH if ( pURL.m_oBTH && ! m_oBTH ) m_oBTH = pURL.m_oBTH; // Get size if ( m_nSize == SIZE_UNKNOWN && pURL.m_bSize && pURL.m_nSize && pURL.m_nSize != SIZE_UNKNOWN ) m_nSize = pURL.m_nSize; // Get name if ( m_sName.IsEmpty() && ! pURL.m_sName.IsEmpty() ) Rename( pURL.m_sName ); return AddSourceInternal( new CDownloadSource( static_cast< const CDownload* >( this ), pszURL, bURN, bHashAuth, pLastSeen, nRedirectionCount ) ); }
BOOL CDownloadWithSources::AddSourceED2K(DWORD nClientID, WORD nClientPort, DWORD nServerIP, WORD nServerPort, const Hashes::Guid& oGUID) { return AddSourceInternal( new CDownloadSource( (CDownload*)this, nClientID, nClientPort, nServerIP, nServerPort, oGUID ) ); }