Example #1
0
BOOL CHttpRequestSender::InternalSend()
{ 
  BOOL bStatus = FALSE;      // Resulting status
  strconv_t strconv;         // String conversion
  HINTERNET hSession = NULL; // Internet session
  HINTERNET hConnect = NULL; // Internet connection
  HINTERNET hRequest = NULL; // Handle to HTTP request
  TCHAR szProtocol[512];     // Protocol
  TCHAR szServer[512];       // Server name
  TCHAR szURI[1024];         // URI
  DWORD dwPort=0;            // Port
  CString sHeaders = _T("Content-type: multipart/form-data, boundary=") + m_sBoundary;
	LPCTSTR szAccept[2]={_T("*/*"), NULL};
  INTERNET_BUFFERS BufferIn;
	BYTE pBuffer[2048];
	BOOL bRet = FALSE;
  DWORD dwBuffSize = 0;
  CString sMsg;
  LONGLONG lPostSize = 0;  
  std::map<CString, std::string>::iterator it;
  std::map<CString, CHttpRequestFile>::iterator it2;

  // Calculate size of data to send
  m_Assync->SetProgress(_T("Calculating size of data to send."), 0);
  bRet = CalcRequestSize(lPostSize);
  if(!bRet)
  {
    m_Assync->SetProgress(_T("Error calculating size of data to send!"), 0);
    goto cleanup;
  }

  // Create Internet session
  m_Assync->SetProgress(_T("Opening Internet connection."), 0);
  hSession = InternetOpen(_T("CrashRpt"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if(hSession==NULL)
  {
    m_Assync->SetProgress(_T("Error opening Internet session"), 0);
	  goto cleanup; 
  }
  
  // Parse application-provided URL
  ParseURL(m_Request.m_sUrl, szProtocol, 512, szServer, 512, dwPort, szURI, 1024);

  // Connect to HTTP server
  m_Assync->SetProgress(_T("Connecting to server"), 0, true);

  hConnect = InternetConnect(hSession, szServer, (WORD)dwPort, 
    NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
	if(hConnect==NULL)
  {
    m_Assync->SetProgress(_T("Error connecting to server"), 0);
	  goto cleanup; 
  }

  if(m_Assync->IsCancelled()){ goto cleanup; }

  m_Assync->SetProgress(_T("Opening HTTP request..."), 0, true);

  hRequest = HttpOpenRequest(hConnect, _T("POST"), szURI, 
			NULL, NULL, szAccept, INTERNET_FLAG_NO_CACHE_WRITE, 0);
  if (!hRequest)
  {
	  m_Assync->SetProgress(_T("HttpOpenRequest has failed."), 0, true);
    goto cleanup;
  }
  
	BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS ); // Must be set or error will occur
  BufferIn.Next = NULL; 
  BufferIn.lpcszHeader = sHeaders;
  BufferIn.dwHeadersLength = sHeaders.GetLength();
  BufferIn.dwHeadersTotal = 0;
  BufferIn.lpvBuffer = NULL;                
  BufferIn.dwBufferLength = 0;
  BufferIn.dwBufferTotal = (DWORD)lPostSize; // This is the only member used other than dwStructSize
  BufferIn.dwOffsetLow = 0;
  BufferIn.dwOffsetHigh = 0;

  m_dwPostSize = (DWORD)lPostSize;
  m_dwUploaded = 0;

  m_Assync->SetProgress(_T("Sending HTTP request..."), 0);
  if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, 0, 0))
  {
    m_Assync->SetProgress(_T("HttpSendRequestEx has failed."), 0);
    goto cleanup;
  }

  // Write text fields
  for(it=m_Request.m_aTextFields.begin(); it!=m_Request.m_aTextFields.end(); it++)
  {
    bRet = WriteTextPart(hRequest, it->first); 
    if(!bRet)
      goto cleanup;
  }
	
  // Write attachments
  for(it2=m_Request.m_aIncludedFiles.begin(); it2!=m_Request.m_aIncludedFiles.end(); it2++)
  {
    bRet = WriteAttachmentPart(hRequest, it2->first); 
    if(!bRet)
      goto cleanup;
  }
	
  bRet = WriteTrailingBoundary(hRequest);
  if(!bRet)
    goto cleanup;

  m_Assync->SetProgress(_T("Ending HTTP request..."), 0);
  if(!HttpEndRequest(hRequest, NULL, 0, 0))
  {
    m_Assync->SetProgress(_T("HttpEndRequest has failed."), 0);
    goto cleanup;
  }

  m_Assync->SetProgress(_T("Reading server responce..."), 0);
  
  InternetReadFile(hRequest, pBuffer, 2048, &dwBuffSize);
  pBuffer[dwBuffSize] = 0;
  sMsg = CString((LPCSTR)pBuffer, dwBuffSize);
  sMsg = _T("Server returned:") + sMsg;
  m_Assync->SetProgress(sMsg, 0);
    
  if(atoi((LPCSTR)pBuffer)!=200)
  {
    m_Assync->SetProgress(_T("Failed."), 100, false);
    goto cleanup;
  }

  m_Assync->SetProgress(_T("Error report was sent OK!"), 100, false);
  bStatus = TRUE;

cleanup:

  if(!bStatus)
  {
    m_Assync->SetProgress(_T("Error sending HTTP request."), 100, false);
  }

  // Clean up
	if(hRequest) 
    InternetCloseHandle(hRequest);

	if(hConnect) 
    InternetCloseHandle(hConnect);

	if(hSession) 
    InternetCloseHandle(hSession);

  m_Assync->SetCompleted(bStatus?0:1);

  return bStatus;
}
Example #2
0
// Sends HTTP request and checks response
BOOL CHttpRequestSender::InternalSend()
{ 
    BOOL bStatus = FALSE;      // Resulting status
    strconv_t strconv;         // String conversion
    HINTERNET hSession = NULL; // Internet session
    HINTERNET hConnect = NULL; // Internet connection
    HINTERNET hRequest = NULL; // Handle to HTTP request
    TCHAR szProtocol[512];     // Protocol
    TCHAR szServer[512];       // Server name
    TCHAR szURI[1024];         // URI
    DWORD dwPort=0;            // Port
    CString sHeaders = _T("Content-type: multipart/form-data; boundary=") + m_sBoundary;
    LPCTSTR szAccept[2]={_T("*/*"), NULL};
    INTERNET_BUFFERS BufferIn;
    BYTE pBuffer[4096] = {0};
    BOOL bRet = FALSE;
    DWORD dwBuffSize = 0;
    CString sMsg;
    LONGLONG lPostSize = 0;  
    std::map<CString, std::string>::iterator it;
    std::map<CString, CHttpRequestFile>::iterator it2;

    // Calculate size of data to send
    m_Assync->SetProgress(_T("Calculating size of data to send."), 0);
    bRet = CalcRequestSize(lPostSize);
    if(!bRet)
    {
        m_Assync->SetProgress(_T("Error calculating size of data to send!"), 0);
        goto cleanup;
    }

    // Create Internet session
    m_Assync->SetProgress(_T("Opening Internet connection."), 0);
    hSession = InternetOpen(_T("CrashRpt"), INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if(hSession==NULL)
    {
        m_Assync->SetProgress(_T("Error opening Internet session"), 0);
        goto cleanup; 
    }

    // Parse application-provided URL
    ParseURL(m_Request.m_sUrl, szProtocol, 512, szServer, 512, dwPort, szURI, 1024);

    // Connect to HTTP server
    m_Assync->SetProgress(_T("Connecting to server"), 0, true);

    hConnect = InternetConnect(
        hSession,     // InternetOpen handle
        szServer,     // Server  name
        (WORD)dwPort, // Default HTTPS port - 443
        NULL,         // User name
        NULL,         //  User password
        INTERNET_SERVICE_HTTP, // Service
        0,            // Flags
        0             // Context
        );
    if(hConnect==NULL)
    {
        m_Assync->SetProgress(_T("Error connecting to server"), 0);
        goto cleanup; 
    }
	
	// Set large receive timeout to avoid problems in case of 
	// slow upload => slow response from the server.
	DWORD dwReceiveTimeout = 0;
	InternetSetOption(hConnect, INTERNET_OPTION_RECEIVE_TIMEOUT, 
		&dwReceiveTimeout, sizeof(dwReceiveTimeout));

    // Check if canceled
    if(m_Assync->IsCancelled()){ goto cleanup; }

    // Add a message to log
    m_Assync->SetProgress(_T("Opening HTTP request..."), 0, true);

    // Configure flags for HttpOpenRequest
    DWORD dwFlags = INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_AUTO_REDIRECT;
    if(dwPort==INTERNET_DEFAULT_HTTPS_PORT)
	    dwFlags |= INTERNET_FLAG_SECURE; // Use SSL
	
	BOOL bRedirect = FALSE;
	int nCount = 0;
	while(nCount==0 || bRedirect)
	{
		nCount++;

		// Open HTTP request
		hRequest = HttpOpenRequest(
			hConnect, 
			_T("POST"), 
			szURI, 
			NULL, 
			NULL, 
			szAccept, 
			dwFlags, 
			0
			);
		if (!hRequest)
		{
			m_Assync->SetProgress(_T("HttpOpenRequest has failed."), 0, true);
			goto cleanup;
		}

		// This code was copied from http://support.microsoft.com/kb/182888 to address the problem
		// that MVS doesn't have a valid SSL certificate.
		DWORD extraSSLDwFlags = 0;
		DWORD dwBuffLen = sizeof(extraSSLDwFlags);
		InternetQueryOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS,
		(LPVOID)&extraSSLDwFlags, &dwBuffLen);
		// We have to specifically ignore these 2 errors for MVS	
		extraSSLDwFlags |= SECURITY_FLAG_IGNORE_REVOCATION |  // Ignores certificate revocation problems.
						   SECURITY_FLAG_IGNORE_WRONG_USAGE | // Ignores incorrect usage problems.
						   SECURITY_FLAG_IGNORE_CERT_CN_INVALID | // Ignores the ERROR_INTERNET_SEC_CERT_CN_INVALID error message.
						   SECURITY_FLAG_IGNORE_CERT_DATE_INVALID; // Ignores the ERROR_INTERNET_SEC_CERT_DATE_INVALID error message.
		InternetSetOption (hRequest, INTERNET_OPTION_SECURITY_FLAGS,
							&extraSSLDwFlags, sizeof (extraSSLDwFlags) );

		// Fill in buffer
		BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS ); // Must be set or error will occur
		BufferIn.Next = NULL; 
		BufferIn.lpcszHeader = sHeaders;
		BufferIn.dwHeadersLength = sHeaders.GetLength();
		BufferIn.dwHeadersTotal = 0;
		BufferIn.lpvBuffer = NULL;                
		BufferIn.dwBufferLength = 0;
		BufferIn.dwBufferTotal = (DWORD)lPostSize; // This is the only member used other than dwStructSize
		BufferIn.dwOffsetLow = 0;
		BufferIn.dwOffsetHigh = 0;

		m_dwPostSize = (DWORD)lPostSize;
		m_dwUploaded = 0;

		// Add a message to log
		m_Assync->SetProgress(_T("Sending HTTP request..."), 0);
		// Send request
		if(!HttpSendRequestEx( hRequest, &BufferIn, NULL, 0, 0))
		{
			m_Assync->SetProgress(_T("HttpSendRequestEx has failed."), 0);
			goto cleanup;
		}

		// Write text fields
		for(it=m_Request.m_aTextFields.begin(); it!=m_Request.m_aTextFields.end(); it++)
		{
			bRet = WriteTextPart(hRequest, it->first); 
			if(!bRet)
				goto cleanup;
		}

		// Write attachments
		for(it2=m_Request.m_aIncludedFiles.begin(); it2!=m_Request.m_aIncludedFiles.end(); it2++)
		{
			bRet = WriteAttachmentPart(hRequest, it2->first); 
			if(!bRet)
				goto cleanup;
		}

		// Write boundary
		bRet = WriteTrailingBoundary(hRequest);
		if(!bRet)
			goto cleanup;

		// Add a message to log
		m_Assync->SetProgress(_T("Ending HTTP request..."), 0);

		// End request
		if(!HttpEndRequest(hRequest, NULL, 0, 0))
		{
			m_Assync->SetProgress(_T("HttpEndRequest has failed."), 0);
			goto cleanup;
		}

		// Add a message to log
		m_Assync->SetProgress(_T("Reading server response..."), 0);
	
		// Get HTTP response code from HTTP headers
		DWORD lHttpStatus = 0;
		DWORD lHttpStatusSize = sizeof(lHttpStatus);
		BOOL bQueryInfo = HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, 
										&lHttpStatus, &lHttpStatusSize, 0);
	
		if(bQueryInfo)
		{
			sMsg.Format(_T("Server response code: %ld"), lHttpStatus);
			m_Assync->SetProgress(sMsg, 0);
		}

		// Read HTTP response
		InternetReadFile(hRequest, pBuffer, 4095, &dwBuffSize);
		pBuffer[dwBuffSize] = 0;
		sMsg = CString((LPCSTR)pBuffer, dwBuffSize);
		sMsg = _T("Server response body:")  + sMsg;
		m_Assync->SetProgress(sMsg, 0);
	
		// If the first byte of HTTP response is a digit, than assume a legacy way
		// of determining delivery status - the HTTP response starts with a delivery status code
		if(dwBuffSize>0 && pBuffer[0]>='0' && pBuffer[0]<='9')
		{
			m_Assync->SetProgress(_T("Assuming legacy method of determining delivery status (from HTTP response body)."), 0);

			// Get status code from HTTP response
			if(atoi((LPCSTR)pBuffer)!=200)
			{
				m_Assync->SetProgress(_T("Failed (HTTP response body doesn't start with code 200)."), 100, false);
				goto cleanup;
			}

			break;
		}
		else
		{
			// If the first byte of HTTP response is not a digit, assume that
			// the delivery status should be read from HTTP header
		
			// Check if we have a redirect (302 response code)
			if(bQueryInfo && lHttpStatus==302)
			{	
				// Check for multiple redirects
				if(bRedirect)
				{
					m_Assync->SetProgress(_T("Multiple redirects are not allowed."), 100, false);
					goto cleanup;
				}

				bRedirect = TRUE;

				TCHAR szBuffer[1024]=_T("");
				DWORD dwBuffSize = sizeof(szBuffer)*sizeof(TCHAR);	
				DWORD nIndex = 0;				

				BOOL bQueryInfo = HttpQueryInfo(hRequest, HTTP_QUERY_LOCATION,
						szBuffer,
						&dwBuffSize,
						&nIndex);
				if(!bQueryInfo)
				{
					m_Assync->SetProgress(_T("Failed to redirect."), 100, false);
					goto cleanup;
				}
				else
				{
					// Parse the redirect URL
					ParseURL(szBuffer, szProtocol, 512, szServer, 512, dwPort, szURI, 1024);

					CString sMsg;
					sMsg.Format(_T("Redirecting to %s"), szBuffer);
					m_Assync->SetProgress(sMsg, 0, true);
					continue;
				}
			}

			// Check for server response code - expected code 200
			if(!bQueryInfo || lHttpStatus!=200)
			{
				m_Assync->SetProgress(_T("Failed (HTTP response code is not equal to 200)."), 100, false);
				goto cleanup;
			}
			
			break;
		}
	}

	// Add a message to log
    m_Assync->SetProgress(_T("Error report has been sent OK!"), 100, false);
    bStatus = TRUE;

cleanup:

    if(!bStatus)
    {
        // Add a message to log
        m_Assync->SetProgress(_T("Error sending HTTP request."), 100, false);
    }

    // Clean up
    if(hRequest) 
        InternetCloseHandle(hRequest);

    // Clean up internet handle
    if(hConnect) 
        InternetCloseHandle(hConnect);

    // Clean up internet session
    if(hSession) 
        InternetCloseHandle(hSession);

    // Notify about completion
    m_Assync->SetCompleted(bStatus?0:1);

    return bStatus;
}