📄 downloadwithfile.cpp
字号:
{
nLength = (QWORD)( (double)nLargestLength * nNewSpeed / ( nNewSpeed + nOldSpeed ) );
nLength = min( nLength, nLargestLength );
if ( nLargestLength > 102400 )
{
nLength = max( nLength, 51200 );
nLength = min( nLength, nLargestLength - 51200 );
}
}
if ( pExisting->m_bRecvBackwards )
{
pTransfer->m_nOffset = nLargestOffset;
pTransfer->m_nLength = nLength;
pTransfer->m_bWantBackwards = FALSE;
}
else
{
pTransfer->m_nOffset = nLargestOffset + nLargestLength - nLength;
pTransfer->m_nLength = nLength;
pTransfer->m_bWantBackwards = TRUE;
}
return TRUE;
}
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile check if a byte position is empty
BOOL CDownloadWithFile::IsPositionEmpty(QWORD nOffset)
{
if ( m_pFile == NULL || ! m_pFile->IsValid() ) return FALSE;
return m_pFile->IsPositionRemaining( nOffset );
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile check if a range would "help"
BOOL CDownloadWithFile::IsRangeUseful(QWORD nOffset, QWORD nLength)
{
if ( m_pFile == NULL || ! m_pFile->IsValid() ) return 0;
return m_pFile->DoesRangeOverlap( nOffset, nLength );
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile get a string of available ranges
CString CDownloadWithFile::GetAvailableRanges() const
{
CString strRange, strRanges;
QWORD nLast = 0;
if ( m_pFile == NULL || ! m_pFile->IsValid() ) return strRanges;
for ( CFileFragment* pFragment = m_pFile->GetFirstEmptyFragment() ; pFragment ; pFragment = pFragment->m_pNext )
{
if ( pFragment->m_nOffset > nLast )
{
if ( strRanges.IsEmpty() )
strRanges = _T("bytes ");
else
strRanges += ',';
strRange.Format( _T("%I64i-%I64i"), nLast, pFragment->m_nOffset - 1 );
strRanges += strRange;
}
nLast = pFragment->m_nOffset + pFragment->m_nLength;
}
if ( m_nSize > nLast )
{
if ( strRanges.IsEmpty() )
strRanges = _T("bytes ");
else
strRanges += ',';
strRange.Format( _T("%I64i-%I64i"), nLast, m_nSize - 1 );
strRanges += strRange;
}
return strRanges;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile clip a range to valid portions
BOOL CDownloadWithFile::ClipUploadRange(QWORD nOffset, QWORD& nLength) const
{
if ( m_pFile == NULL || ! m_pFile->IsValid() ) return FALSE;
if ( nOffset >= m_nSize ) return FALSE;
if ( m_pFile->IsPositionRemaining( nOffset ) ) return FALSE;
for ( CFileFragment* pFragment = m_pFile->GetFirstEmptyFragment() ; pFragment ; pFragment = pFragment->m_pNext )
{
if ( pFragment->m_nOffset > nOffset )
{
if ( nOffset + nLength <= pFragment->m_nOffset ) return TRUE;
nLength = pFragment->m_nOffset - nOffset;
return ( nLength > 0 );
}
}
if ( nLength > m_nSize - nOffset ) nLength = m_nSize - nOffset;
return ( nLength > 0 );
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile select a random range of available data
BOOL CDownloadWithFile::GetRandomRange(QWORD& nOffset, QWORD& nLength) const
{
if ( m_pFile == NULL || ! m_pFile->IsValid() ) return FALSE;
CFileFragment* pFilled = m_pFile->CopyFilledFragments();
if ( CFileFragment* pRandom = pFilled->GetRandom() )
{
nOffset = pRandom->m_nOffset;
nLength = pRandom->m_nLength;
pFilled->DeleteChain();
return TRUE;
}
else
{
pFilled->DeleteChain();
return FALSE;
}
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile submit data
BOOL CDownloadWithFile::SubmitData(QWORD nOffset, LPBYTE pData, QWORD nLength)
{
SetModified();
m_tReceived = GetTickCount();
if ( m_bBTH ) // Hack: Only do this for BitTorrent
{
for ( CDownloadTransfer* pTransfer = GetFirstTransfer() ; pTransfer ; pTransfer = pTransfer->m_pDlNext )
{
if ( pTransfer->m_nProtocol == PROTOCOL_BT ) pTransfer->UnrequestRange( nOffset, nLength );
}
}
return m_pFile != NULL && m_pFile->WriteRange( nOffset, pData, nLength );
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile erase a range
QWORD CDownloadWithFile::EraseRange(QWORD nOffset, QWORD nLength)
{
if ( m_pFile == NULL ) return 0;
QWORD nCount = m_pFile->InvalidateRange( nOffset, nLength );
if ( nCount > 0 ) SetModified();
return nCount;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile make the file appear complete
BOOL CDownloadWithFile::MakeComplete()
{
if ( m_sLocalName.IsEmpty() ) return FALSE;
if ( ! PrepareFile() ) return FALSE;
return m_pFile->MakeComplete();
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile run the file
BOOL CDownloadWithFile::RunFile(DWORD tNow)
{
if ( m_pFile->IsOpen() )
{
if ( m_pFile->GetRemaining() == 0 ) return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile write the metadata
BOOL CDownloadWithFile::WriteMetadata(LPCTSTR pszPath)
{
ASSERT( m_pXML != NULL );
CString strXML = m_pXML->ToString( TRUE, TRUE );
delete m_pXML;
m_pXML = NULL;
CString strMetadata;
strMetadata.Format( _T("%s\\Metadata"), pszPath );
CreateDirectory( strMetadata, NULL );
SetFileAttributes( strMetadata, FILE_ATTRIBUTE_HIDDEN );
strMetadata += m_sLocalName.Mid( m_sLocalName.ReverseFind( '\\' ) );
strMetadata += _T(".xml");
HANDLE hFile = CreateFile( strMetadata, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) return FALSE;
DWORD nWritten;
#ifdef _UNICODE
int nASCII = WideCharToMultiByte( CP_UTF8, 0, strXML, strXML.GetLength(), NULL, 0, NULL, NULL );
LPSTR pszASCII = new CHAR[ nASCII ];
WideCharToMultiByte( CP_UTF8, 0, strXML, strXML.GetLength(), pszASCII, nASCII, NULL, NULL );
WriteFile( hFile, pszASCII, nASCII, &nWritten, NULL );
delete [] pszASCII;
#else
WriteFile( hFile, (LPCSTR)strXML, strXML.GetLength(), &nWritten, NULL );
#endif
CloseHandle( hFile );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile append intrinsic metadata
BOOL CDownloadWithFile::AppendMetadata()
{
if ( ! Settings.Library.VirtualFiles ) return FALSE;
if ( m_pXML == NULL ) return FALSE;
CXMLElement* pXML = m_pXML->GetFirstElement();
if ( pXML == NULL ) return FALSE;
HANDLE hFile = CreateFile( m_sLocalName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hFile == INVALID_HANDLE_VALUE ) return FALSE;
CString strURI = m_pXML->GetAttributeValue( CXMLAttribute::schemaName );
BOOL bSuccess = FALSE;
if ( strURI == CSchema::uriAudio )
{
if ( _tcsistr( m_sLocalName, _T(".mp3") ) != NULL )
{
bSuccess |= AppendMetadataID3v1( hFile, pXML );
}
}
CloseHandle( hFile );
return bSuccess;
}
BOOL CDownloadWithFile::AppendMetadataID3v1(HANDLE hFile, CXMLElement* pXML)
{
USES_CONVERSION;
DWORD nBytes;
CString str;
ID3V1 pID3;
ZeroMemory( &pID3, sizeof(pID3) );
SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
ReadFile( hFile, &pID3, 3, &nBytes, NULL );
if ( memcmp( pID3.szTag, ID3V2_TAG, 3 ) == 0 ) return FALSE;
ZeroMemory( &pID3, sizeof(pID3) );
SetFilePointer( hFile, -(int)sizeof(pID3), NULL, FILE_END );
ReadFile( hFile, &pID3, sizeof(pID3), &nBytes, NULL );
if ( memcmp( pID3.szTag, ID3V1_TAG, 3 ) == 0 ) return FALSE;
ZeroMemory( &pID3, sizeof(pID3) );
memcpy( pID3.szTag, ID3V1_TAG, 3 );
str = pXML->GetAttributeValue( _T("title") );
if ( str.GetLength() > 0 ) strncpy( pID3.szSongname, T2CA( (LPCTSTR)str ), 30 );
str = pXML->GetAttributeValue( _T("artist") );
if ( str.GetLength() > 0 ) strncpy( pID3.szArtist, T2CA( (LPCTSTR)str ), 30 );
str = pXML->GetAttributeValue( _T("album") );
if ( str.GetLength() > 0 ) strncpy( pID3.szAlbum, T2CA( (LPCTSTR)str ), 30 );
str = pXML->GetAttributeValue( _T("year") );
if ( str.GetLength() > 0 ) strncpy( pID3.szYear, T2CA( (LPCTSTR)str ), 4 );
str = pXML->GetAttributeValue( _T("genre") );
for ( int nGenre = 0 ; nGenre < ID3_GENRES ; nGenre ++ )
{
if ( str.CompareNoCase( CLibraryBuilderInternals::pszID3Genre[ nGenre ] ) == 0 )
{
pID3.nGenre = nGenre;
break;
}
}
SetFilePointer( hFile, 0, NULL, FILE_END );
WriteFile( hFile, &pID3, sizeof(pID3), &nBytes, NULL );
return TRUE;
}
//////////////////////////////////////////////////////////////////////
// CDownloadWithFile serialize
void CDownloadWithFile::Serialize(CArchive& ar, int nVersion)
{
CDownloadWithTransfers::Serialize( ar, nVersion );
if ( ar.IsStoring() )
{
ar.WriteCount( m_pFile != NULL );
if ( m_pFile != NULL ) m_pFile->Serialize( ar, nVersion );
}
else
{
if ( nVersion < 28 )
{
CString strLocalName;
ar >> strLocalName;
if ( strLocalName.GetLength() )
{
if ( m_sLocalName.GetLength() )
MoveFile( m_sLocalName + _T(".sd"), strLocalName + _T(".sd") );
m_sLocalName = strLocalName;
}
else
{
GenerateLocalName();
}
}
if ( nVersion < 25 || ar.ReadCount() )
{
m_pFile->Serialize( ar, nVersion );
}
else
{
delete m_pFile;
m_pFile = NULL;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -