Exemple #1
0
STDMETHODIMP CBHttpRequest::Open(BSTR strMethod, BSTR strUrl, VARIANT_BOOL bAsync, VARIANT varUser, VARIANT varPassword)
{
    CUrl url;
    CStringA strObject;
    CStringA strUser;
    CStringA strPassword;

    Abort();

    s_cs.Enter();
    s_dwReqID ++;
    m_dwReqID = s_dwReqID;
    s_mapReq.SetAt(m_dwReqID, this);
    s_cs.Leave();

    url.CrackUrl(CBStringA(strUrl));
    m_bAsync = (bAsync != VARIANT_FALSE);

    strObject = url.GetUrlPath();
    strObject.Append(url.GetExtraInfo());

    if(varUser.vt != VT_ERROR)
    {
        HRESULT hr = varGetString(varUser, strUser);
        if(FAILED(hr))return hr;
    }

    if(varPassword.vt != VT_ERROR)
    {
        HRESULT hr = varGetString(varPassword, strPassword);
        if(FAILED(hr))return hr;
    }

    m_hConnection = InternetConnect(m_hSession, url.GetHostName(), url.GetPortNumber(),
                                    strUser.IsEmpty() ? NULL : (LPCSTR)strUser, strPassword.IsEmpty() ? NULL : (LPCSTR)strPassword,
                                    INTERNET_SERVICE_HTTP, 0, m_dwReqID);
    if(m_hConnection == NULL)
        return GetErrorResult();

    m_hFile = HttpOpenRequest(m_hConnection, CBStringA(strMethod), strObject, NULL, NULL, NULL, m_dwFlags, m_dwReqID);
    if(m_hFile == NULL)
        return GetErrorResult();

    m_eventComplete.Set();

    return S_OK;
}
Exemple #2
0
	HRESULT WINAPI MonitorSink::QueryIAuthenticate(void* pv, REFIID riid, LPVOID* ppv, DWORD dw)
	{
		* ppv = NULL;

		if ( pv && InlineIsEqualGUID(riid, IID_IAuthenticate) )
		{
			MonitorSink * pThis = (MonitorSink *)pv;

			if ( pThis->m_pIEHostWindow && ! pThis->m_strURL.IsEmpty() && pThis->m_spTargetProtocol )
			{
				do 
				{
					CComPtr<IWinInetHttpInfo> spWinInetHttpInfo;
					if ( FAILED(pThis->m_spTargetProtocol->QueryInterface(&spWinInetHttpInfo)) ) break;
					if ( ! spWinInetHttpInfo ) break;

					CHAR szRawHeader[8192];		// IWinInetHttpInfo::QueryInfo() 返回的 Raw Header 不是 Unicode 的
					DWORD dwBuffSize = ARRAYSIZE(szRawHeader);

					if ( FAILED(spWinInetHttpInfo->QueryInfo(HTTP_QUERY_RAW_HEADERS, szRawHeader, &dwBuffSize, 0, NULL)) ) break;

					CString strHeader;
					HttpRawHeader2CrLfHeader(szRawHeader, strHeader);

					static const WCHAR AUTH_HEAD [] = L"\r\nWWW-Authenticate:";

					LPWSTR lpAuth = NULL;
					size_t nAuthLen = 0;
					if ( ! ExtractFieldValue( strHeader, AUTH_HEAD, & lpAuth, & nAuthLen ) ) break;
					if ( ! lpAuth ) break;

					CString strAuthScheme;
					CString strAuthRealm;

					// 可能有以下几种情况:
					// WWW-Authenticate: Basic realm="Secure Area"
					// WWW-Authenticate: Digest realm="*****@*****.**", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"
					// WWW-Authenticate: NTLM
					// WWW-Authenticate: NTLM <auth token>
					LPWSTR pPos = StrStrW(lpAuth, L" ");
					if ( pPos )
					{
						* pPos = L'\0';
						strAuthScheme = lpAuth;

						do 
						{
							pPos = StrStrIW( pPos + 1, L"realm");
							if ( ! pPos ) break;
							pPos = StrChrW( pPos + 5, L'=');
							if ( ! pPos ) break;
							pPos = StrChrW( pPos + 1, L'"');
							if ( ! pPos ) break;
							LPWSTR lpRealm = pPos + 1;
							pPos = StrChrW( lpRealm, L'"');
							if ( ! pPos ) break;
							* pPos = L'\0';

							strAuthRealm = lpRealm;

						} while (false);

					}
					else
					{
						strAuthScheme = lpAuth;
					}

					VirtualFree( lpAuth, 0, MEM_RELEASE);

					// 由于 NPN_GetAuthenticationInfo 得不到 NTLM 的 domain,没办法做登录,只好不支持了
					if (strAuthRealm == _T("NTLM")) return E_NOINTERFACE;

					CUrl url;
					if ( url.CrackUrl(pThis->m_strURL) )
					{
						CW2A aScheme(url.GetSchemeName());
						CW2A aHost(url.GetHostName());
						int aPort = url.GetPortNumber();

						char* username = NULL;
						char* password = NULL;
						uint32_t ulen = 0, plen = 0;

						char* szAuthScheme = CStringToUTF8String(strAuthScheme);
						char* szAuthRealm = CStringToUTF8String(strAuthRealm);
						NPError result = NPN_GetAuthenticationInfo(pThis->m_pIEHostWindow->m_pPlugin->m_pNPInstance, aScheme, aHost, aPort, szAuthScheme, szAuthRealm, &username, &ulen, &password, &plen );
						delete[] szAuthScheme;
						delete[] szAuthRealm;
						if (result != NPERR_NO_ERROR) break;

						pThis->m_strUsername = username;
						pThis->m_strPassword = password;

						NPN_MemFree(username);
						NPN_MemFree(password);
					}

					* ppv = dynamic_cast<IAuthenticate *>(pThis);

					((IUnknown*)*ppv)->AddRef();

					return S_OK;

				} while (false);
			}
		}

		return E_NOINTERFACE;
	}
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; 
}
Exemple #4
0
int RunConverter( int argc, _TCHAR* * argv )
{
#ifdef _DEBUG
	// sleep a bit so we can have time to attach a debugger
	Tell(_T("Sleeping for %d seconds in debug mode."), startupTimeout / 1000);
	Sleep(startupTimeout);
#endif
	int ret = 0;
	wstring name;
	wstring title;
	HANDLE conversionHandle = NULL;

	po::options_description desc("Converts an MPEG-2 Program Stream to a DVR-MS, WMV, or WTV file.");
	po::positional_options_description pos;

	string input;
	string output;
	LONGLONG length;
	bool disableFileLogging;
	bool disableConsoleLogging;
	bool disableAllLogging;
	string interruptName;
	string interruptDirectory;
	string outputDirectory;
	string contentTitle;
	__int64 contentDuration = -1i64;

	desc.add_options()
		("help,?", "Display help message.")
		("input,i", po::value<string>(&input), "an MPEG2 input path. Can be a url.")
		("output,o", po::value<string>(&output), "output path.<type>. Where <type> can be one of \"dvr-ms\", \"wmv\", or \"wtv\"")
		("length,l", po::value<LONGLONG>(&length)->default_value(-1), "the length of the input content in bytes. Only required for a network path such as http." )
		("interrupt-name", po::value<string>(&interruptName), "the file name (without path or extension) of a file that will be created when conversion is to be interrupted.")
		("interrupt-directory", po::value<string>(&interruptDirectory), "the path for this app to look for an interrupt file. An interrupt file is the interrupt_file name with a .interrupt extension. The file itself can be empty.")
		("disable-file-logging", po::value<bool>(&disableFileLogging)->zero_tokens()->default_value(false), "indicates that logging to a file will be disabled.")
		("disable-console-logging", po::value<bool>(&disableConsoleLogging)->zero_tokens()->default_value(false), "indicates that logging to the console will be disabled.")
		("disable-all-logging", po::value<bool>(&disableAllLogging)->zero_tokens()->default_value(false), "indicates that all logging will be disabled.")
		("output-directory,d", po::value<string>(&outputDirectory), "the directory for this app to place conversion output. Only valid if output_path is omitted.")
		("content-title,t", po::value<string>(&contentTitle), "the Title that will be assigned to the output path.<type>.")
		("version,v", po::value<string>()->zero_tokens(), "prints the version of this app.")
		//("content-duration,d", po::value<__int64>(&contentDuration)->default_value(-1i64), "the duration of the input content in seconds." )
		;

	pos.add("input", 1);
	pos.add("output", 1);
	pos.add("length", 1);

	vector<string> args;

	for (int i = 1; i < argc; i++)
		args.push_back(WStringToString(argv[i]));

	po::variables_map variables;

	try
	{
		po::basic_parsed_options<char> oo = po::command_line_parser(args).
			options(desc).positional(pos).run();
		po::store(oo, variables);
		po::notify(variables);
	}
	catch (std::exception e)
	{
		Tell(_T("Invalid command line. Use --help to see options."));
		return -1;
	}

	if (!variables.count("input"))
	{
		bool display = false;
		wstring message;
		if (variables.count("version"))
		{
			message = _T("Version: ");
			message += MPEG2DVRMS_VERSION;
			display = true;
		}
		if (variables.count("help"))
		{
			message = _T("eh... help message not available yet. Hope you have the source!");
			display = true;
		}
		if (!display)
			message = _T("No input file was specified.");
		ret = 100;
		Tell(message);
	}
	else
	{
		try
		{
			//////////////////////////////////////////////////////////////////////////
			// command-line option handling

			LONGLONG contentLength = -1;

			if (variables.count("length"))
				contentLength = length;

			if (variables.count("interrupt-name"))
				name = StringToWString(interruptName);
			else
			{
				name = NewGuid();
				Tell(_T("Generated interrupt name is %s"), name.c_str());
			}

			if (variables.count("interrupt-directory"))
				_conversionFileStoragePath = StringToWString(interruptDirectory);

			if (variables.count("content-title"))
				title = StringToWString(contentTitle);
			else
				title = _T("");

#pragma region input output file handling
			wstring defaultExtension;

			if (IsVista())
				defaultExtension = _T(".dvr-ms");
			else
				defaultExtension = _T(".wtv");

			ATL_URL_SCHEME urlScheme;
			CUrl inputUrl;

			if (!inputUrl.CrackUrl(StringToWString(input).c_str()))
				urlScheme = ATL_URL_SCHEME_FILE;
			else
				urlScheme = inputUrl.GetScheme();

			if (urlScheme == -1)
				urlScheme = ATL_URL_SCHEME_FILE;

			wstring inputPath = StringToWString(input);
			CPath outputPath;

			if (urlScheme == ATL_URL_SCHEME_FILE)
			{
				CPath input = inputPath.c_str();

				if (input.IsFileSpec())
				{
					TCHAR szCurrentDirectory[MAX_PATH];
					if (!GetCurrentDirectory(MAX_PATH, szCurrentDirectory))
						throw CarverLab::Exception(GetLastError());
					wstring currentDirectory = (LPCTSTR)szCurrentDirectory;
					inputPath = currentDirectory + _T("\\") + inputPath.c_str();
					input = inputPath.c_str();
				}
				if (!input.FileExists())
					throw CarverLab::Exception(_T("MPEG2 input path does not exist."));

				if (!variables.count("output"))
					outputPath = inputPath.c_str();
				else
					outputPath = StringToWString(output).c_str();
			}
			else if (urlScheme == ATL_URL_SCHEME_HTTP ||
				urlScheme == ATL_URL_SCHEME_HTTPS)
			{
				if (!variables.count("output"))
				{
					wstring thefullpath;
					CString envString;
					envString.GetEnvironmentVariable(_T("PUBLIC"));
					thefullpath = envString;
					thefullpath += _T("\\Videos\\mpeg2dvrms-output");
					thefullpath += defaultExtension;
					outputPath = thefullpath.c_str();
				}
				else
					outputPath = StringToWString(output).c_str();
			}
			else
				throw CarverLab::Exception(_T("Only http or https URL schemes are supported."));

			bool isUrl = urlScheme != ATL_URL_SCHEME_FILE;

			CPath inPath = inputPath.c_str();

			if (outputPath.GetExtension().MakeLower() == inPath.GetExtension().MakeLower())
				outputPath.RenameExtension(defaultExtension.c_str());

			if (outputPath.GetExtension().MakeLower() == _T(".dvrms"))
			{
				outputPath.RemoveExtension();
				outputPath.AddExtension(_T(".dvr-ms"));
			}
#pragma endregion input output file handling

			//////////////////////////////////////////////////////////////////////////

			conversionHandle = CreateConversion(false, CComBSTR(name.c_str()));

			if (!conversionHandle)
				throw CarverLab::Exception();

			SetConsoleTitle(outputPath);

			Tell(_T("Press ENTER to interrupt and exit."));

			_done = false;
			HANDLE stdinput = GetStdHandle(STD_INPUT_HANDLE);

			std::auto_ptr<InternalThreadData> threadData(new InternalThreadData);
			threadData->activityCallback = ActivityCallback;
			threadData->contentLength = contentLength;
			threadData->conversionHandle = conversionHandle;
			threadData->inputPath = inPath;
			threadData->isUrl = isUrl;
			threadData->outputPath = outputPath;
			threadData->threadData = NULL;
			threadData->userData = NULL;
			threadData->contentTitle = StringToWString(contentTitle);
			threadData->contentDuration = contentDuration;

			_lastConvertedFilePath = outputPath;

			HANDLE thread = CreateThread(NULL, 0, BeginConversion, threadData.get(), 0, NULL);
			if (thread == NULL)
				throw CarverLab::Exception();

			bool shuttingDown = false;
			bool interruptSuccessful = false;	// will be true if the conversion is inactive after InterruptConversion is called

			while (!_done)
			{
				if (!shuttingDown && ((_kbhit() && _getch() == 13) || InterruptNow(name.c_str())))
				{
					shuttingDown = true;
					interruptSuccessful = InterruptConversion(conversionHandle, 30000);	// will wait 30 seconds for the conversion to die
				}

				Sleep(10);
			}

			if (!interruptSuccessful)
			{	// TODO: will need to kill this puppy in an unnice way... awwww
				Tell(_T("InterruptConversion was unsusccessful."));
			}
			// TODO: INFINITE? um... nope. this will need an intervention
			WaitForSingleObject(thread, INFINITE);

			CloseHandle(thread);
		}
		catch (CarverLab::Exception exception)
		{
			Tell(_T("*** Error: %s"), exception.GetErrorString());
			Tell(_T("Exiting..."));
			ret = exception.GetHRESULT();
		}
		catch (...)
		{
			DWORD errorCode = GetLastError();
			wstring error = Exception::GetLastErrorString(errorCode);
			Tell(_T("*** Unhandled Exception: %s"), error.c_str());
			Tell(_T("Exiting..."));
			ret = errorCode;
		}
		if (conversionHandle != NULL)
			CloseConversion(conversionHandle);
	}
#ifdef _DEBUG
	// sleep a bit so we can see any errors
	Tell(_T("Sleeping for %d seconds in debug mode."), sleepTimeout / 1000);
	Sleep(sleepTimeout);
#endif
	return ret;
}