예제 #1
0
HRESULT FAsyncDownload::FHttpDownloadTP::ProcessDownload(FAsyncDownData *pData)
{
    HRESULT hr = E_FAIL; 


    FString ReqUrl = pData->m_pUrlInfo->m_DownloadUrl;
    UrlUnescapeInPlace(ReqUrl.GetBuffer(), 0); 

    CUrl url;
    url.CrackUrl(ReqUrl);

	const tchar* pszUserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)";
    FHInternet hIn = NULL; 
	if (g_AppSettings.m_Proxy.GetLength() > 0)
	{
		hIn = InternetOpen(pszUserAgent, INTERNET_OPEN_TYPE_PROXY, g_AppSettings.m_Proxy, g_AppSettings.m_ProxyA, 0);
	}
	else
	{
		hIn = InternetOpen(pszUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	}

     
    if (NULL == hIn)
        return E_HTTP_NET_ERROR; 

    FHInternet hCon = InternetConnect(hIn, url.GetHostName(), url.GetPortNumber(), url.GetUserName(), url.GetPassword(), INTERNET_SERVICE_HTTP, 0, 0); 

    if (NULL == hCon)
    {
        _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: InternetConnect() failed: %d\n", GetLastError()); 
        return E_HTTP_NET_ERROR; 
    }

	ULONG ulRecvTimeout = 15000; 
	InternetSetOption(hCon, INTERNET_OPTION_RECEIVE_TIMEOUT, &ulRecvTimeout, sizeof(ULONG));


    FString StrRes = url.GetUrlPath();
    StrRes+= url.GetExtraInfo(); 
    
    FHInternet hReq = HttpOpenRequest(hCon, "GET", StrRes, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_DONT_CACHE, 0); 

    if (NULL == hReq)
    {
        _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: HttpOpenRequest() failed: %d\n", GetLastError()); 
        return E_HTTP_NET_ERROR; 
    }

	size_type FileSize = 0;
	
	

	if (!(pData->m_pUrlInfo->m_dwDownloadFlags & HTTP_FLAG_NO_RESUME))
		FileSize = GetFileSize(pData->m_pUrlInfo->m_DownloadFile);

    // See if file already exists on the disk.
    if (FileSize > 0)
    {
        FString StrRange; 
        StrRange.Format("Range: bytes=%I64d-", FileSize); 
        HttpAddRequestHeaders(hReq, StrRange, StrRange.GetLength(), HTTP_ADDREQ_FLAG_ADD_IF_NEW);
    }


	FString StrVersion; 
	StrVersion.Format("LTV_VERSION: %s", g_AppSettings.m_AppVersion); 
	HttpAddRequestHeaders(hReq, StrVersion, StrVersion.GetLength(), HTTP_ADDREQ_FLAG_ADD_IF_NEW);

    if (!HttpSendRequest(hReq, NULL, 0, NULL, 0))
    {
		int err = GetLastError(); 
        _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: HttpSendRequest() failed: %d (0x%x)\n", err, HRESULT_FROM_WIN32(err)); 
        InternetCloseHandle(hCon);
        InternetCloseHandle(hIn); 
        return E_HTTP_NET_ERROR; 
    }

    const DWORD dwBufferSize = 8192;
    char pBuffer[dwBufferSize];

    FHttpConnection FConn = hReq;

    DWORD dwStatusCode = FConn.GetStatusCode(); 

	FString ReqContentType = pData->m_pUrlInfo->m_ContentType; 
	pData->m_pUrlInfo->m_ContentType = FConn.GetHeader(HTTP_QUERY_CONTENT_TYPE);
	pData->m_pUrlInfo->m_dwStatusCode = dwStatusCode; 

	if (!MatchContentType(ReqContentType, pData->m_pUrlInfo->m_ContentType))
	{
		_DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Content type mismatch: %s/%s\n", ReqContentType, pData->m_pUrlInfo->m_ContentType); 
		return E_NOINTERFACE; //E_NOINTERFACE = content type mismatch
	}

	if (dwStatusCode == 416 && FileSize > 0)
	{
		_DBGAlert("FAsyncDownload::FHttpDownloadTP::ProcessDownload: Server status code: %d. Download complete\n", dwStatusCode); 
		return S_OK; 
	}

    if (dwStatusCode < 200 || dwStatusCode > 206)
    {
        _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Server status code: %d\n", dwStatusCode); 
		if (dwStatusCode == 404)
			return E_HTTP_NOTFOUND; 
		return E_HTTP_INVALID_STATUS; 
    }

    CAtlFile OutFile; 

	if (pData->m_pUrlInfo->m_dwDownloadFlags & HTTP_FLAG_NO_RESUME)
		DeleteFile(pData->m_pUrlInfo->m_DownloadFile); 

    hr = OutFile.Create(pData->m_pUrlInfo->m_DownloadFile, GENERIC_WRITE, 0, OPEN_ALWAYS);

    if (FAILED(hr))
    {
		_DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: CreateFile failed: 0x%x, %d : %s\n", hr, GetLastError(), pData->m_pUrlInfo->m_DownloadFile); 
        return E_HTTP_WRITE_FILE; 
    }

    size_type llTotalRead = 0; 
    size_type llSizeMax = 0; 

	size_type ContentLen = FConn.GetContentLength(); 

	pData->m_pUrlInfo->m_ContentLength = ContentLen; 

    if (dwStatusCode == 206)
    {
        FString FStrRange = FConn.GetHeader(HTTP_QUERY_CONTENT_RANGE);
        
        if (FStrRange)
        {
           //Content-Range: bytes 21010-47021/47022
           const char* pszBytes = strstr(FStrRange, "bytes ");
           if (pszBytes != NULL)
           {
               pszBytes+=sizeof("bytes");
               LONGLONG llOffset = _strtoi64(pszBytes, NULL, 10); 
               hr = OutFile.Seek(llOffset, FILE_BEGIN); 
               llTotalRead = (size_type)llOffset; 
               if (FAILED(hr))
               {
                   _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Seek to position %d failed: 0x%x, %d\n", hr, GetLastError()); 
               }

               const char* pszTotal = strchr(pszBytes, '/');
               if (pszTotal != NULL)
                   llSizeMax = _strtoi64(pszTotal + 1, NULL, 10); 
           }
        }
    }
	else
	{
		if (ContentLen > 0 && ContentLen == FileSize)
		{
			OutFile.Close();
			return S_OK; 
		}
	}

    if (llSizeMax == 0)
		llSizeMax = ContentLen;


    pData->pBindStatusCallback.OnProgress((ULONG)llTotalRead, (ULONG)llSizeMax, BINDSTATUS_BEGINDOWNLOADDATA, L"");

    DWORD dwBytesRead = 0; 
    for (;;)
    {
        if (!InternetReadFile(hReq, pBuffer, dwBufferSize, &dwBytesRead))
        {
            _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: InternetReadFile() failed: %d\n", GetLastError()); 
			OutFile.Close();
            return E_HTTP_NET_ERROR; 
        }

		if (dwBytesRead == 0)
		{
			hr = S_OK; 
			break; 
		}

        DWORD dwBytesWritten = 0; 
        hr = OutFile.Write(pBuffer, dwBytesRead, &dwBytesWritten); 

		if (FAILED(hr))
        {
            _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: FileWrite failed: 0x%x, %d\n", hr, GetLastError()); 
			OutFile.Close();
            return E_HTTP_WRITE_FILE; 
        }

        llTotalRead+=dwBytesRead;
		
		pData->pBindStatusCallback.OnProgress((ULONG)llTotalRead, llSizeMax > 0 ? (ULONG)llSizeMax : llTotalRead , BINDSTATUS_DOWNLOADINGDATA, L"");


        if (m_pThis->m_Stopping || pData->pBindStatusCallback.m_Abort)
        {
            _DBGAlert("**FAsyncDownload::FHttpDownloadTP::ProcessDownload: Download aborted\n", hr, GetLastError()); 
            hr = E_ABORT; 
            break; 
        }
    }

	OutFile.Close();
    return hr; 
}
예제 #2
0
void CDownloadTask::RunMergeFile(CDownload* pDownload, LPCTSTR szFilename, BOOL bMergeValidation, const Fragments::List& oMissedGaps, float fProgress)
{
//	HANDLE hSource = CreateFile( szFilename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL );

	QWORD nSourceSize = 0;		// qwSourceLength
	QWORD nSourceOffset = 0;	// qwSourceOffset

	CAtlFile oSource;
	oSource.Create( szFilename, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, OPEN_EXISTING );
	VERIFY_FILE_ACCESS( oSource, szFilename )
	if ( ! oSource )
	{
		// Source file open error
		theApp.Message( MSG_ERROR, IDS_DOWNLOAD_FILE_OPEN_ERROR, szFilename );
		return;
	}

	oSource.GetSize( nSourceSize );
	if ( ! nSourceSize )
		return;		// Empty source file

	CSingleLock pLock( &Transfers.m_pSection, TRUE );

	if ( ! Downloads.Check( pDownload ) ||
		  pDownload->IsCompleted() ||
		  pDownload->IsMoving() )
		return;		// Moot download almost completed

	if ( m_bMergeValidation &&
		! pDownload->IsTorrent() &&
		 pDownload->NeedTigerTree() &&
		 pDownload->NeedHashset() )
	{
	//	pLock.Unlock();
	//	MsgBox( IDS_DOWNLOAD_EDIT_COMPLETE_NOHASH, MB_ICONEXCLAMATION );
		DEBUG_ONLY( theApp.Message( MSG_DEBUG, IDS_DOWNLOAD_EDIT_COMPLETE_NOHASH ) );
		return;		// No hashsets
	}

	if ( ! pDownload->PrepareFile() )
		return;		// Destination file open error

	Fragments::List oList( pDownload->GetEmptyFragmentList() );
	if ( ! oMissedGaps.empty() )
	{
		Fragments::List::const_iterator pItr = oMissedGaps.begin();
		const Fragments::List::const_iterator pEnd = oMissedGaps.end();
		for ( ; pItr != pEnd ; ++pItr )
			oList.erase( *pItr );
	}

	if ( ! oList.size() )
		return;		// No available fragments

	// Determine offset if needed
	if ( pDownload->IsMultiFileTorrent() )
	{
		QWORD nOffset = 0;		// qwOffset
		BOOL bFound = FALSE;
		CBTInfo::CBTFile* pFile;
		CString strTargetName;
		const CString strSourceName = PathFindFileName( szFilename );

		if ( GetAsyncKeyState( VK_SHIFT ) & 0x8000 )	// Forced selection dialog
		{
			int nIndex = pDownload->SelectFile( &pLock );
			if ( nIndex == 0 )
			{
				bFound = TRUE;
			}
			else if ( nIndex > 0 )
			{
				CBTInfo::CBTFile* pSelectFile = pDownload->m_pTorrent.m_pFiles.GetAt( pDownload->m_pTorrent.m_pFiles.FindIndex( nIndex ) );
				for ( POSITION pos = pDownload->m_pTorrent.m_pFiles.GetHeadPosition() ; pos ; )
				{
					pFile = pDownload->m_pTorrent.m_pFiles.GetNext( pos );
					if ( pFile->m_sPath == pSelectFile->m_sPath )
					{
						DEBUG_ONLY( theApp.Message( MSG_DEBUG, _T("Merge Selected File: ") + pFile->m_sPath ) );
						nSourceOffset = nOffset;
						bFound = TRUE;	// Avoid checks below
						break;
					}

					nOffset += pFile->m_nSize;
				}
			}
		}

		if ( ! bFound )		// No forced match, try filename
		{
			for ( POSITION pos = pDownload->m_pTorrent.m_pFiles.GetHeadPosition() ; pos ; )
			{
				pFile = pDownload->m_pTorrent.m_pFiles.GetNext( pos );
				strTargetName = PathFindFileName( pFile->m_sPath );

				if ( strTargetName.CompareNoCase( strSourceName ) == 0 )
				{
					DEBUG_ONLY( theApp.Message( MSG_DEBUG, _T("Merge Filename: ") + pFile->m_sPath ) );
					nSourceOffset = nOffset;
					bFound = TRUE;	// Avoid fallback check below
					break;
				}

				nOffset += pFile->m_nSize;
			}
		}

		if ( ! bFound )		// No filename match, try exact size
		{
			nOffset = 0;
		//	const CString strExt = PathFindExtension( strSourceName );
			for ( POSITION pos = pDownload->m_pTorrent.m_pFiles.GetHeadPosition() ; pos ; )
			{
				pFile = pDownload->m_pTorrent.m_pFiles.GetNext( pos );

				if ( pFile->m_nSize == nSourceSize )	// && strExt == PathFindExtension( pFile->m_sPath )
				{
					DEBUG_ONLY( theApp.Message( MSG_DEBUG, _T("Merge Filesize Fallback") ) );
					nSourceOffset = nOffset;
				//	bFound = TRUE;
					break;
				}

				nOffset += pFile->m_nSize;
			}
		}
	}

	pLock.Unlock();

	const float fIncrement = fProgress / oList.size();

	const DWORD nBufferLength = 256 * 1024;		// Was 65536?

	// Read missing file fragments from selected file
	auto_array< BYTE > Buf( new BYTE [nBufferLength] );
	Fragments::List::const_iterator pItr = oList.begin();
	const Fragments::List::const_iterator pEnd = oList.end();
	for ( ; ! m_pEvent && pItr != pEnd ; ++pItr )
	{
		m_fProgress += fIncrement;		// Update tooltip

		QWORD qwLength = pItr->end() - pItr->begin();
		QWORD qwOffset = pItr->begin();

		// Check for overlapped fragments
		if ( qwOffset + qwLength <= nSourceOffset ||
			 nSourceOffset + nSourceSize <= qwOffset )
			 continue;	 // No overlaps

		// Calculate overlapped range end offset
		QWORD qwEnd = min( qwOffset + qwLength, nSourceOffset + nSourceSize );
		// Calculate overlapped range start offset
		qwOffset = max( qwOffset, nSourceOffset );
		// Calculate overlapped range length
		qwLength = qwEnd - qwOffset;
		// Calculate file offset if any
		QWORD qwFileOffset = ( qwOffset > nSourceOffset ) ? qwOffset - nSourceOffset : 0;
		if ( FAILED( oSource.Seek( qwFileOffset, FILE_BEGIN ) ) )
			continue;

		DWORD dwToRead;
		while ( ( dwToRead = (DWORD)min( qwLength, (QWORD)nBufferLength ) ) != 0 && ! m_pEvent )
		{
			DWORD dwReaded = 0;
			if ( SUCCEEDED( oSource.Read( Buf.get(), dwToRead, dwReaded ) ) && dwReaded )
			{
				pLock.Lock();

				if ( ! Downloads.Check( pDownload ) || pDownload->IsCompleted() || pDownload->IsMoving() )
					return;

				pDownload->SubmitData( qwOffset, Buf.get(), (QWORD)dwReaded );
				pLock.Unlock();
				qwOffset += (QWORD)dwReaded;
				qwLength -= (QWORD)dwReaded;
			}
			else
			{
				// File error or end of file. Non-Fatal
				break;
			}
		}

		pLock.Lock();

		if ( ! Downloads.Check( pDownload ) || pDownload->IsCompleted() || pDownload->IsMoving() )
			return;

		if ( bMergeValidation )
			pDownload->RunValidation();

		pDownload->SetModified();

		pLock.Unlock();
	}

//	m_bSuccess = true;
}
예제 #3
0
bool CTrueType::GetProperties(LPCTSTR pszFilePath, TTF_PROPERTIES* pProperties)
{
	CAtlFile FontFile;
	HRESULT hr = FontFile.Create(pszFilePath, GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING);
	if (FAILED(hr))
		return false;

	TTF_OFFSET_TABLE ttOffsetTable;
	FontFile.Read(&ttOffsetTable, sizeof(TTF_OFFSET_TABLE));
	ttOffsetTable.uNumOfTables = SWAPWORD(ttOffsetTable.uNumOfTables);
	ttOffsetTable.uMajorVersion = SWAPWORD(ttOffsetTable.uMajorVersion);
	ttOffsetTable.uMinorVersion = SWAPWORD(ttOffsetTable.uMinorVersion);

	// See if this is a true type font and the version is 1.0
	if (ttOffsetTable.uMajorVersion != 1 || ttOffsetTable.uMinorVersion != 0)
		return false;
	
	TTF_TABLE_DIRECTORY tblDir;
	TTF_TABLE_DIRECTORY tblName;
	TTF_TABLE_DIRECTORY tblOS2;
	bool bFoundNameTable = false;
	bool bFoundOS2Table = false;
	for (int i=0; i< ttOffsetTable.uNumOfTables; i++)
	{
		FontFile.Read(&tblDir, sizeof(TTF_TABLE_DIRECTORY));
		CString strName = CString(tblDir.szTag, 4);
		if (strName.IsEmpty())
			break;

		if (!strName.CompareNoCase("name"))
		{
			bFoundNameTable = true;
			tblName = tblDir;
			tblName.uLength = SWAPLONG(tblName.uLength);
			tblName.uOffset = SWAPLONG(tblName.uOffset);
		}
		else
		if (!strName.CompareNoCase("OS/2"))
		{
			bFoundOS2Table = true;
			tblOS2 = tblDir;
			tblOS2.uLength = SWAPLONG(tblOS2.uLength);
			tblOS2.uOffset = SWAPLONG(tblOS2.uOffset);
		}

		if (bFoundNameTable && bFoundOS2Table)
			break;
	}
	
	if (bFoundNameTable)
	{
		FontFile.Seek(tblName.uOffset, FILE_BEGIN);

		TTF_NAME_TABLE_HEADER ttNTHeader;
		FontFile.Read(&ttNTHeader, sizeof(TTF_NAME_TABLE_HEADER));
		ttNTHeader.uFSelector      = SWAPWORD(ttNTHeader.uFSelector);
		ttNTHeader.uNRCount        = SWAPWORD(ttNTHeader.uNRCount);
		ttNTHeader.uStorageOffset  = SWAPWORD(ttNTHeader.uStorageOffset);

		for (int i=0; i<ttNTHeader.uNRCount; i++)
		{
			TTF_NAME_RECORD ttRecord;
			FontFile.Read(&ttRecord, sizeof(TTF_NAME_RECORD));
			ttRecord.uPlatformID   = SWAPWORD(ttRecord.uPlatformID);
			ttRecord.uEncodingID   = SWAPWORD(ttRecord.uEncodingID);
			ttRecord.uLanguageID   = SWAPWORD(ttRecord.uLanguageID);
			ttRecord.uNameID       = SWAPWORD(ttRecord.uNameID);
			ttRecord.uStringLength = SWAPWORD(ttRecord.uStringLength);
			ttRecord.uStringOffset = SWAPWORD(ttRecord.uStringOffset);

			if (ttRecord.uPlatformID != 3) // Microsoft
				continue;

			ULONGLONG nPos = 0;
			FontFile.GetPosition(nPos);
			FontFile.Seek(tblName.uOffset + ttRecord.uStringOffset + ttNTHeader.uStorageOffset, FILE_BEGIN);

			int iUnicodeChars = (ttRecord.uStringLength + 1) / 2;
			WCHAR* pUnicodeBuffer = new WCHAR[iUnicodeChars];
			FontFile.Read(pUnicodeBuffer, ttRecord.uStringLength);
			for (int i = 0; i < iUnicodeChars; i++)
				pUnicodeBuffer[i] = SWAPWORD(pUnicodeBuffer[i]);

			CString strName = CString(pUnicodeBuffer, iUnicodeChars);
			delete [] pUnicodeBuffer;
			FontFile.Seek(nPos, FILE_BEGIN);
			
			if (strName.IsEmpty())
				continue;

			switch (ttRecord.uNameID)
			{
				case 1: // Font family
					pProperties->strFamily.IsEmpty() ? pProperties->strFamily = strName : void();
					break;
				case 0: // Copyright notice
					pProperties->strCopyright.IsEmpty() ? pProperties->strCopyright = strName : void();
					break;
				case 7: // Trademark notice
					pProperties->strTrademark.IsEmpty() ? pProperties->strTrademark = strName : void();
					break;
				case 4: // Full Name of the Font
					pProperties->strName.IsEmpty() ? pProperties->strName = strName : void();
					break;
				case 2: // Font sub family
				case 3: // Unique Family Identifier
				case 5: // Version of the name table
				case 6: // PostScript name of the font
				default:
				{
					break;
				}
			}
		}			
	}

	if (bFoundOS2Table)
	{
		FontFile.Seek(tblOS2.uOffset, FILE_BEGIN);

		TTF_OS2_TABLE ttNTHeader;
		FontFile.Read(&ttNTHeader, sizeof(TTF_OS2_TABLE));
		ttNTHeader.uVersion          = SWAPWORD(ttNTHeader.uVersion);
		ttNTHeader.uAverageCharWidth = SWAPWORD(ttNTHeader.uAverageCharWidth);
		ttNTHeader.uWeightClass      = SWAPWORD(ttNTHeader.uWeightClass);
		ttNTHeader.uWidthClass       = SWAPWORD(ttNTHeader.uWidthClass);
		ttNTHeader.uFsType           = SWAPWORD(ttNTHeader.uFsType);
	
		if (ttNTHeader.uFsType & 0x0001)	// 1: reserved - must be zero; if not, turn it off
			ttNTHeader.uFsType &= ~0x0001;

		if (ttNTHeader.uFsType == 0x0000)	// 0: embedding and permanent installation allowed
		{
			pProperties->strEmbed = "Installable";
			pProperties->enumEmbed = TTF_Embed_Installable;
		}
		else
		if (ttNTHeader.uFsType & 0x0008)	// 8: editable embedding allowed
		{
			pProperties->strEmbed = "Editable";
			pProperties->enumEmbed = TTF_Embed_Editable;
		}
		else
		if (ttNTHeader.uFsType & 0x0004)	// 4: preview and print embedding allowed
		{
			pProperties->strEmbed = "Printable";
			pProperties->enumEmbed = TTF_Embed_Printable;
		}
		else
		if (ttNTHeader.uFsType & 0x0002)
		{
			pProperties->strEmbed = "None"; // 2: no embedding allowed
			pProperties->enumEmbed = TTF_Embed_None;
		}
		else
		{
			pProperties->strEmbed.Format("%d", ttNTHeader.uFsType); // unknown
			pProperties->enumEmbed = TTF_Embed_Unknown;
		}
	}

	FontFile.Close();

	return !pProperties->strName.IsEmpty();
}