Beispiel #1
0
bool WinHttpStream::enumHeaders( IEnumHeaders &enumHdr )
{
	setState(stReadResponse);

	AutoArray<char> buffer;
	buffer.resize(1000);
	DWORD size = (DWORD)buffer.length();
	while (!HttpQueryInfoA(hHTTPConn,HTTP_QUERY_RAW_HEADERS,
		buffer.data(),&size,0)) {
			DWORD res = GetLastError();
			if (res == ERROR_INSUFFICIENT_BUFFER) {
				buffer.resize(size);
			} else {
				throw ErrNoWithDescException(THISLOCATION,GetLastError(),
					"Cannot retrieve headers from the request");
			}
	}
	buffer.resize(size);

	AutoArray<char>::SplitIterator iter=buffer.split((char)0);
	TextParser<char> parser;
	while (iter.hasItems()) {
		ConstStrA line = iter.getNext();
		if (parser("%1 : %2",line)) {
			ConstStrA field = parser[1].str();
			ConstStrA value = parser[2].str();
			if(enumHdr(field, value)) return true;
		}
	}

	return false;


}
Beispiel #2
0
static HRESULT WINAPI HttpInfo_QueryInfo(IWinInetHttpInfo *iface, DWORD dwOption,
        void *pBuffer, DWORD *pcbBuffer, DWORD *pdwFlags, DWORD *pdwReserved)
{
    HttpProtocol *This = impl_from_IWinInetHttpInfo(iface);
    TRACE("(%p)->(%x %p %p %p %p)\n", This, dwOption, pBuffer, pcbBuffer, pdwFlags, pdwReserved);

    if(!This->base.request)
        return E_FAIL;

    if(!HttpQueryInfoA(This->base.request, dwOption, pBuffer, pcbBuffer, pdwFlags))
        return S_FALSE;

    return S_OK;
}
Beispiel #3
0
BOOL _InternetCloseHandle(HINTERNET hInternet) {
	BOOL ret;
	LPVOID data;
	DWORD size;

	data = malloc(10240*sizeof(BYTE));
	ZeroMemory(data, 10240*sizeof(BYTE));
	size = 0;
	HttpQueryInfoA(hInternet, HTTP_QUERY_RAW_HEADERS_CRLF, data, &size, 0);
	if(size)
		OutputDebugStringA((LPCSTR) data);
	free(data);	

	UnHookAPI("InternetCloseHandle", "wininet.dll", _Close);
	ret = InternetCloseHandle(hInternet);
	_Close = HookAPI("InternetCloseHandle", "wininet.dll", (DWORD) _InternetCloseHandle);
	return ret;

}
Beispiel #4
0
StringA WinHttpStream::getReplyHeaders()
{
	setState(stReadResponse);
	AutoArray<char> buffer;
	buffer.resize(1000);
	DWORD size = (DWORD)buffer.length();
	while (!HttpQueryInfoA(hHTTPConn,HTTP_QUERY_RAW_HEADERS_CRLF,
		buffer.data(),&size,0)) {
			DWORD res = GetLastError();
			if (res == ERROR_INSUFFICIENT_BUFFER) {
				buffer.resize(size);
			} else {
				throw ErrNoWithDescException(THISLOCATION,GetLastError(),
					"Cannot retrieve headers from the request");
			}
	}
	buffer.resize(size);
	return buffer;
}
Beispiel #5
0
//
//	This function used for full page replace. The idea is to redirect querying any infromation from the source page 
//	 HTTTP headers to the result page HTTP headers.
//
static BOOL HttpQueryInfoCommon(
	HINTERNET	hRequest, 
	DWORD		dwInfoLevel, 
	LPVOID		lpvBuffer, 
	LPDWORD		lpdwBufferLength, 
	LPDWORD		lpdwIndex,
	BOOL		bUnicode
	)
{
	BOOL Ret = FALSE;
	PHANDLE_CONTEXT Ctx;

	if (Ctx = FindHandle(hRequest))
	{
		// Checking if the page will be replaced
		if (Ctx->Flags & CF_REPLACE)
		{
			PTRANSFER_CONTEXT	tCtx = (PTRANSFER_CONTEXT)Ctx->tCtx;

			DbgPrint("ISFB_%04x: HttpQueryInfo replace, dwInfoLevel = %u\n", g_CurrentProcessId, dwInfoLevel);

			// Copmlete loading of the page to replace with
			if ((tCtx) && ((tCtx->Headers) || (TransferCompleteReceive(tCtx, TRUE) == NO_ERROR)))
				// Replacing request handle
				hRequest = tCtx->hRequest;
		}	// if (Ctx->Flags & CF_REPLACE)
		ReleaseHandle(Ctx);
	}	// if (Ctx = FindHandle(hRequest))

	if (bUnicode)
		Ret = HttpQueryInfoW(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex);
	else
		Ret = HttpQueryInfoA(hRequest, dwInfoLevel, lpvBuffer, lpdwBufferLength, lpdwIndex);

	return(Ret);
}
int HttpDownLoad_real(
                  std::string& tmp_file,
                  const std::string& url,
                  const std::string& file,
                  std::function<void(double)> callback)
{
  HINTERNET hSession  =  InternetOpen(_T("HTTPDOWNLOAD"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
  scloud::ScopeGuard session([hSession]{InternetCloseHandle(hSession);});
  if (!hSession) {
    session.cancel();
    return GetLastError();
  }

  HINTERNET hInternet  =  InternetOpenUrl(hSession, url.c_str(), NULL,  0 , INTERNET_FLAG_RAW_DATA,  0 );
  scloud::ScopeGuard internet([hInternet]{InternetCloseHandle(hInternet);});
  if (!hInternet) {
    internet.cancel();
    return GetLastError();
  }

  //get http return code.
  char szContent[32] = {0};
  DWORD dwInfoSize = 32;
  HttpQueryInfoA(hInternet, HTTP_QUERY_STATUS_CODE, szContent, &dwInfoSize, NULL);
  int ret = StrToIntA(szContent);
  if (ret >= 400)
  {
      return ret;
  }

  //get file size
  ZeroMemory(szContent, 32);
  dwInfoSize = 32;
  HttpQueryInfoA(hInternet, HTTP_QUERY_CONTENT_LENGTH, szContent, &dwInfoSize, NULL);
  __int64 size = 0;
  StrToInt64ExA(szContent, 10, &size);
  if (size <= 0)
  {
    return ERROR_CONTENT_LENGTH_LESS_THAN_ZERO;
  }

  TCHAR szTmpFile[MAX_PATH] = {0};
  if (!tmp_file.empty())
  {
    lstrcpy(szTmpFile, tmp_file.c_str());
  }
  else
  {
    TCHAR szTmpPath[MAX_PATH] = {0};
    GetTempPath(MAX_PATH, szTmpPath);
    if (0 == GetTempFileName(szTmpPath, _T("http"), 0, szTmpFile))
    {
      return GetLastError();
    }
  }
  tmp_file = szTmpFile;

  HANDLE hFile = CreateFile(szTmpFile,
                            GENERIC_WRITE,
                            FILE_SHARE_READ,
                            NULL,
                            OPEN_ALWAYS,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);
  scloud::ScopeGuard create_file([hFile]{CloseHandle(hFile);});

  if (INVALID_HANDLE_VALUE == hFile)
  {
    create_file.cancel();
    return GetLastError();
  }

  LARGE_INTEGER large_int = {0};
  GetFileSizeEx(hFile, &large_int);

  if (large_int.QuadPart > size)
  {
    return ERROR_TMP_FILE_TOO_BIG;
  }

  if (large_int.QuadPart > 0)
  {
    if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, 0, NULL, FILE_END))
    {
      return GetLastError();
    }

    if (INVALID_SET_FILE_POINTER == InternetSetFilePointer(
      hInternet, large_int.LowPart, NULL, FILE_BEGIN, 0))
    {
      return GetLastError();
    }
  }

  __int64 rsize = large_int.QuadPart;

  for(;rsize < size;)
  {
    char buf[512] = {0};
    DWORD dwRead = 0; 

    if (!InternetReadFile(hInternet, buf, 512, &dwRead))
    {
        return GetLastError();
    }

    if (dwRead == 0)
    {
      return ERROR_WTF_NO_DATA;
    }

    for(DWORD dwOnce=0; dwRead != dwOnce;)
    {
      DWORD dwWritten = 0;
      if (0 == WriteFile(hFile, buf+dwOnce, dwRead-dwOnce, &dwWritten, NULL))
        return GetLastError();
      dwOnce += dwWritten;
    }

    rsize += dwRead;

    if (rsize == size)
      break;

    if (callback)
      callback((double)rsize/size);
  }

  if (rsize == size)
  {
    create_file.cancel();
    CloseHandle(hFile);

    SetFileAttributes(file.c_str(), FILE_ATTRIBUTE_NORMAL);
    DeleteFile(file.c_str());

    if (MoveFile(szTmpFile, file.c_str()))
    {
      //succeed.
      if (callback)
        callback(1.0);

      return 0;
    }
  }

  return GetLastError();
}
Beispiel #7
0
/*
 * Background thread to check for updates
 */
static DWORD WINAPI CheckForUpdatesThread(LPVOID param)
{
	BOOL releases_only, found_new_version = FALSE;
	int status = 0;
	const char* server_url = RUFUS_URL "/";
	int i, j, k, verbose = 0, verpos[4];
	static const char* archname[] = {"win_x86", "win_x64"};
	static const char* channel[] = {"release", "beta"};		// release channel
	const char* accept_types[] = {"*/*\0", NULL};
	DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
	char* buf = NULL;
	char agent[64], hostname[64], urlpath[128], mime[32];
	OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""};
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	SYSTEMTIME ServerTime, LocalTime;
	FILETIME FileTime;
	int64_t local_time = 0, reg_time, server_time, update_interval;

	update_check_in_progress = TRUE;
	verbose = ReadRegistryKey32(REGKEY_HKCU, REGKEY_VERBOSE_UPDATES);
	// Without this the FileDialog will produce error 0x8001010E when compiled for Vista or later
	IGNORE_RETVAL(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED));
	// Unless the update was forced, wait a while before performing the update check
	if (!force_update_check) {
		// It would of course be a lot nicer to use a timer and wake the thread, but my
		// development time is limited and this is FASTER to implement.
		do {
			for (i=0; (i<30) && (!force_update_check); i++)
				Sleep(500);
		} while ((!force_update_check) && ((iso_op_in_progress || format_op_in_progress || (dialog_showing>0))));
		if (!force_update_check) {
			if ((ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL) == -1)) {
				vuprintf("Check for updates disabled, as per registry settings.\n");
				goto out;
			}
			reg_time = ReadRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE);
			update_interval = (int64_t)ReadRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL);
			if (update_interval == 0) {
				WriteRegistryKey32(REGKEY_HKCU, REGKEY_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL);
				update_interval = DEFAULT_UPDATE_INTERVAL;
			}
			GetSystemTime(&LocalTime);
			if (!SystemTimeToFileTime(&LocalTime, &FileTime))
				goto out;
			local_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
			vvuprintf("Local time: %" PRId64 "\n", local_time);
			if (local_time < reg_time + update_interval) {
				vuprintf("Next update check in %" PRId64 " seconds.\n", reg_time + update_interval - local_time);
				goto out;
			}
		}
	}

	PrintStatus(3000, TRUE, MSG_243);
	status++;	// 1

	if (!GetVersionExA(&os_version)) {
		uprintf("Could not read Windows version - Check for updates cancelled.\n");
		goto out;
	}

	if ((!InternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) || (!InternetGetConnectedState(&dwFlags, 0)))
		goto out;
	hostname[sizeof(hostname)-1] = 0;

	safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d.%d", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]);
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL)
		goto out;
	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL)
		goto out;

	status++;	// 2
	releases_only = !GetRegistryKeyBool(REGKEY_HKCU, REGKEY_INCLUDE_BETAS);

	for (k=0; (k<(releases_only?1:(int)ARRAYSIZE(channel))) && (!found_new_version); k++) {
		uprintf("Checking %s channel...\n", channel[k]);
		// At this stage we can query the server for various update version files.
		// We first try to lookup for "<appname>_<os_arch>_<os_version_major>_<os_version_minor>.ver"
		// and then remove each each of the <os_> components until we find our match. For instance, we may first
		// look for rufus_win_x64_6.2.ver (Win8 x64) but only get a match for rufus_win_x64_6.ver (Vista x64 or later)
		// This allows sunsetting OS versions (eg XP) or providing different downloads for different archs/groups.
		safe_sprintf(urlpath, sizeof(urlpath), "%s%s%s_%s_%d.%d.ver", APPLICATION_NAME, (k==0)?"":"_",
			(k==0)?"":channel[k], archname[is_x64()?1:0], os_version.dwMajorVersion, os_version.dwMinorVersion);
		vuprintf("Base update check: %s\n", urlpath);
		for (i=0, j=(int)safe_strlen(urlpath)-5; (j>0)&&(i<ARRAYSIZE(verpos)); j--) {
			if ((urlpath[j] == '.') || (urlpath[j] == '_')) {
				verpos[i++] = j;
			}
		}
		if (i != ARRAYSIZE(verpos)) {
			uprintf("Broken code in CheckForUpdatesThread()!\n");
			goto out;
		}

		UrlParts.lpszUrlPath = urlpath;
		UrlParts.dwUrlPathLength = sizeof(urlpath);
		for (i=0; i<ARRAYSIZE(verpos); i++) {
			vvuprintf("Trying %s\n", UrlParts.lpszUrlPath);
			hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types,
				INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES|
				INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL);
			if ((hRequest == NULL) || (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)))
				goto out;

			// Ensure that we get a text file
			dwSize = sizeof(dwStatus);
			dwStatus = 404;
			HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);
			if (dwStatus == 200) 
				break;
			InternetCloseHandle(hRequest);
			hRequest = NULL;
			safe_strcpy(&urlpath[verpos[i]], 5, ".ver");
		}
		if (dwStatus != 200) {
			vuprintf("Could not find a %s version file on server %s", channel[k], server_url);
			if ((releases_only) || (k+1 >= ARRAYSIZE(channel)))
				goto out;
			continue;
		}
		vuprintf("Found match for %s on server %s", urlpath, server_url);

		dwSize = sizeof(mime);
		HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_TYPE, (LPVOID)&mime, &dwSize, NULL);
		if (strcmp(mime, "text/plain") != 0)
			goto out;

		// We also get a date from Apache, which we'll use to avoid out of sync check,
		// in case some set their clock way into the future and back.
		// On the other hand, if local clock is set way back in the past, we will never check.
		dwSize = sizeof(ServerTime);
		// If we can't get a date we can trust, don't bother...
		if ( (!HttpQueryInfoA(hRequest, HTTP_QUERY_DATE|HTTP_QUERY_FLAG_SYSTEMTIME, (LPVOID)&ServerTime, &dwSize, NULL))
			|| (!SystemTimeToFileTime(&ServerTime, &FileTime)) )
			goto out;
		server_time = ((((int64_t)FileTime.dwHighDateTime)<<32) + FileTime.dwLowDateTime) / 10000000;
		vvuprintf("Server time: %" PRId64 "\n", server_time);
		// Always store the server response time - the only clock we trust!
		WriteRegistryKey64(REGKEY_HKCU, REGKEY_LAST_UPDATE, server_time);
		// Might as well let the user know
		if (!force_update_check) {
			if ((local_time > server_time + 600) || (local_time < server_time - 600)) {
				uprintf("IMPORTANT: Your local clock is more than 10 minutes in the %s. Unless you fix this, " APPLICATION_NAME " may not be able to check for updates...", 
					(local_time > server_time + 600)?"future":"past");
			}
		}

		dwSize = sizeof(dwTotalSize);
		if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL))
			goto out;

		safe_free(buf);
		// Make sure the file is NUL terminated
		buf = (char*)calloc(dwTotalSize+1, 1);
		if (buf == NULL) goto out;
		// This is a version file - we should be able to gulp it down in one go
		if (!InternetReadFile(hRequest, buf, dwTotalSize, &dwDownloaded) || (dwDownloaded != dwTotalSize))
			goto out;

		status++;
		vuprintf("Successfully downloaded version file (%d bytes)\n", dwTotalSize);

		parse_update(buf, dwTotalSize+1);

		vuprintf("UPDATE DATA:\n");
		vuprintf("  version: %d.%d.%d.%d (%s)\n", update.version[0], update.version[1], 
			update.version[2], update.version[3], channel[k]);
		vuprintf("  platform_min: %d.%d\n", update.platform_min[0], update.platform_min[1]);
		vuprintf("  url: %s\n", update.download_url);

		found_new_version = ((to_uint64_t(update.version) > to_uint64_t(rufus_version)) || (force_update))
			&& ( (os_version.dwMajorVersion > update.platform_min[0])
			  || ( (os_version.dwMajorVersion == update.platform_min[0]) && (os_version.dwMinorVersion >= update.platform_min[1])) );
		uprintf("N%sew %s version found%c\n", found_new_version?"":"o n", channel[k], found_new_version?'!':'.');
	}

out:
	safe_free(buf);
	if (hRequest) InternetCloseHandle(hRequest);
	if (hConnection) InternetCloseHandle(hConnection);
	if (hSession) InternetCloseHandle(hSession);
	switch(status) {
	case 1:
		PrintStatus(3000, TRUE, MSG_244);
		break;
	case 2:
		PrintStatus(3000, TRUE, MSG_245);
		break;
	case 3:
	case 4:
		PrintStatus(3000, FALSE, found_new_version?MSG_246:MSG_247);
	default:
		break;
	}
	// Start the new download after cleanup
	if (found_new_version) {
		// User may have started an operation while we were checking
		while ((!force_update_check) && (iso_op_in_progress || format_op_in_progress || (dialog_showing>0))) {
			Sleep(15000);
		}
		DownloadNewVersion();
	}
	force_update_check = FALSE;
	update_check_in_progress = FALSE;
	ExitThread(0);
}
Beispiel #8
0
/* 
 * Download a file from an URL
 * Mostly taken from http://support.microsoft.com/kb/234913
 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages
 * to the dialog in question, with WPARAM being set to nonzero for EXIT on success
 * and also attempt to indicate progress using an IDC_PROGRESS control
 */
DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
{
	HWND hProgressBar = NULL;
	BOOL r = FALSE;
	DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
	FILE* fd = NULL; 
	LONG progress_style;
	const char* accept_types[] = {"*/*\0", NULL};
	unsigned char buf[DOWNLOAD_BUFFER_SIZE];
	char agent[64], hostname[64], urlpath[128];
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	size_t last_slash;
	int i;

	if (hProgressDialog != NULL) {
		// Use the progress control provided, if any
		hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS);
		if (hProgressBar != NULL) {
			progress_style = GetWindowLong(hProgressBar, GWL_STYLE);
			SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
			SendMessage(hProgressBar, PBM_SETPOS, 0, 0);
		}
		SendMessage(hProgressDialog, UM_ISO_INIT, 0, 0);
	}

	for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) {
		if ((file[last_slash] == '/') || (file[last_slash] == '\\')) {
			last_slash++;
			break;
		}
	}

	PrintStatus(0, FALSE, MSG_240, &file[last_slash]);
	uprintf("Downloading '%s' from %s\n", &file[last_slash], url);

	if (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) {
		uprintf("Unable to decode URL: %s\n", WinInetErrorString());
		goto out;
	}
	hostname[sizeof(hostname)-1] = 0;

	// Open an Internet session
	for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) {
		Sleep(1000);
	}
	if (i <= 0) {
		// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong...
		SetLastError(ERROR_INTERNET_NOT_INITIALIZED);
		uprintf("Network is unavailable: %s\n", WinInetErrorString());
		goto out;
	}
	_snprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d.%d", rufus_version[0], rufus_version[1], rufus_version[2], rufus_version[3]);
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL) {
		uprintf("Could not open Internet session: %s\n", WinInetErrorString());
		goto out;
	}

	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL) {
		uprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString());
		goto out;
	}

	hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types,
		INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES|
		INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL);
	if (hRequest == NULL) {
		uprintf("Could not open URL %s: %s\n", url, WinInetErrorString());
		goto out;
	}

	if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
		uprintf("Unable to send request: %s\n", WinInetErrorString());
		goto out;
	}

	// Get the file size
	dwSize = sizeof(dwStatus);
	dwStatus = 404;
	HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);
	if (dwStatus != 200) {
		error_code = ERROR_INTERNET_ITEM_NOT_FOUND;
		uprintf("Unable to access file: Server status %d\n", dwStatus);
		goto out;
	}
	dwSize = sizeof(dwTotalSize);
	if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) {
		uprintf("Unable to retrieve file length: %s\n", WinInetErrorString());
		goto out;
	}
	uprintf("File length: %d bytes\n", dwTotalSize);

	fd = fopenU(file, "wb");
	if (fd == NULL) {
		uprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString());
		goto out;
	}

	// Keep checking for data until there is nothing left.
	dwSize = 0;
	while (1) {
		if (IS_ERROR(FormatStatus))
			goto out;

		if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0))
			break;
		dwSize += dwDownloaded;
		SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0);
		PrintStatus(0, FALSE, MSG_241, (100.0f*dwSize)/(1.0f*dwTotalSize));
		if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) {
			uprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString());
			goto out;
		}
	}

	if (dwSize != dwTotalSize) {
		uprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize);
		FormatStatus = ERROR_SEVERITY_ERROR|FAC(FACILITY_STORAGE)|ERROR_WRITE_FAULT;
		goto out;
	} else {
		r = TRUE;
		uprintf("Successfully downloaded '%s'\n", &file[last_slash]);
	}

out:
	if (hProgressDialog != NULL)
		SendMessage(hProgressDialog, UM_ISO_EXIT, (WPARAM)r, 0);
	if (fd != NULL) fclose(fd);
	if (!r) {
		_unlink(file);
		PrintStatus(0, FALSE, MSG_242);
		SetLastError(error_code);
		MessageBoxU(hMainDialog, IS_ERROR(FormatStatus)?StrError(FormatStatus, FALSE):WinInetErrorString(),
		lmprintf(MSG_044), MB_OK|MB_ICONERROR|MB_IS_RTL);
	}
	if (hRequest) InternetCloseHandle(hRequest);
	if (hConnection) InternetCloseHandle(hConnection);
	if (hSession) InternetCloseHandle(hSession);

	return r?dwSize:0;
}
Beispiel #9
0
/*
 * Download a file from an URL
 * Mostly taken from http://support.microsoft.com/kb/234913
 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages
 * to the dialog in question, with WPARAM being set to nonzero for EXIT on success
 * and also attempt to indicate progress using an IDC_PROGRESS control
 */
DWORD DownloadFile(const char* url, const char* file, HWND hProgressDialog)
{
	HWND hProgressBar = NULL;
	BOOL r = FALSE;
	LONG progress_style;
	DWORD dwFlags, dwSize, dwWritten, dwDownloaded, dwTotalSize;
	DWORD DownloadStatus;
	HANDLE hFile = INVALID_HANDLE_VALUE;
	const char* accept_types[] = {"*/*\0", NULL};
	unsigned char buf[DOWNLOAD_BUFFER_SIZE];
	char agent[64], hostname[64], urlpath[128], msg[MAX_PATH];
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	size_t last_slash;
	int i;

	DownloadStatus = 404;
	if (hProgressDialog != NULL) {
		// Use the progress control provided, if any
		hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS);
		if (hProgressBar != NULL) {
			progress_style = GetWindowLong(hProgressBar, GWL_STYLE);
			SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
			SendMessage(hProgressBar, PBM_SETPOS, 0, 0);
		}
		SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0);
	}

	if (file == NULL)
		goto out;

	for (last_slash = safe_strlen(file); last_slash != 0; last_slash--) {
		if ((file[last_slash] == '/') || (file[last_slash] == '\\')) {
			last_slash++;
			break;
		}
	}

	static_sprintf(msg, "Downloading %s: Connecting...", file);
	print_status(0, FALSE, msg);
	dprintf("Downloading %s from %s\n", file, url);

	if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts))
	  || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) {
		dprintf("Unable to decode URL: %s\n", WinInetErrorString());
		goto out;
	}
	hostname[sizeof(hostname)-1] = 0;

	// Open an Internet session
	for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) {
		Sleep(1000);
	}
	if (i <= 0) {
		// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong...
		SetLastError(ERROR_INTERNET_NOT_INITIALIZED);
		dprintf("Network is unavailable: %s\n", WinInetErrorString());
		goto out;
	}
	static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)",
		application_version[0], application_version[1], application_version[2],
		nWindowsVersion>>4, nWindowsVersion&0x0F, is_x64()?"; WOW64":"");
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL) {
		dprintf("Could not open Internet session: %s\n", WinInetErrorString());
		goto out;
	}

	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL) {
		dprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString());
		goto out;
	}

	hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types,
		INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|
		INTERNET_FLAG_NO_COOKIES|INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE|INTERNET_FLAG_HYPERLINK|
		((UrlParts.nScheme==INTERNET_SCHEME_HTTPS)?INTERNET_FLAG_SECURE:0), (DWORD_PTR)NULL);
	if (hRequest == NULL) {
		dprintf("Could not open URL %s: %s\n", url, WinInetErrorString());
		goto out;
	}

	if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
		dprintf("Unable to send request: %s\n", WinInetErrorString());
		goto out;
	}

	// Get the file size
	dwSize = sizeof(DownloadStatus);
	HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL);
	if (DownloadStatus != 200) {
		error_code = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND;
		dprintf("Unable to access file: %d\n", DownloadStatus);
		goto out;
	}
	dwSize = sizeof(dwTotalSize);
	if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) {
		dprintf("Unable to retrieve file length: %s\n", WinInetErrorString());
		goto out;
	}
	dprintf("File length: %d bytes\n", dwTotalSize);

	hFile = CreateFileU(file, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE) {
		dprintf("Unable to create file '%s': %s\n", &file[last_slash], WinInetErrorString());
		goto out;
	}

	// Keep checking for data until there is nothing left.
	dwSize = 0;
	while (1) {
		if (IS_ERROR(error_code))
			goto out;

		if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0))
			break;
		dwSize += dwDownloaded;
		SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0);
		static_sprintf(msg, "Downloading: %0.1f%%", (100.0f*dwSize)/(1.0f*dwTotalSize));
		print_status(0, FALSE, msg);
		if (!WriteFile(hFile, buf, dwDownloaded, &dwWritten, NULL)) {
			dprintf("Error writing file '%s': %s\n", &file[last_slash], WinInetErrorString());
			goto out;
		} else if (dwDownloaded != dwWritten) {
			dprintf("Error writing file '%s': Only %d/%d bytes written\n", dwWritten, dwDownloaded);
			goto out;
		}
	}

	if (dwSize != dwTotalSize) {
		dprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize);
		error_code = ERROR_SEVERITY_ERROR|ERROR_WRITE_FAULT;
		goto out;
	} else {
		r = TRUE;
		dprintf("Successfully downloaded '%s'\n", &file[last_slash]);
	}

out:
	if (hProgressDialog != NULL)
		SendMessage(hProgressDialog, UM_DOWNLOAD_EXIT, (WPARAM)r, 0);
	if (hFile != INVALID_HANDLE_VALUE) {
		// Force a flush - May help with the PKI API trying to process downloaded updates too early...
		FlushFileBuffers(hFile);
		CloseHandle(hFile);
	}
	if (!r) {
		if (file != NULL)
			_unlinkU(file);
		print_status(0, FALSE, "Failed to download file.");
		SetLastError(error_code);
		MessageBoxU(hMainDialog, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR);
	}
	if (hRequest)
		InternetCloseHandle(hRequest);
	if (hConnection)
		InternetCloseHandle(hConnection);
	if (hSession)
		InternetCloseHandle(hSession);

	return r?dwSize:0;
}
Beispiel #10
0
char* remote_data(LPWSTR verb, char* url, char* body, size_t body_size, 
				  bool bGetHeaders, bool bGetRawData = false, bool bCheckSession = false, DWORD* pdwDataSize = NULL) {
  char       *cstr = NULL;
  char		 *session = NULL;
  std::string data = "";
  //CAtlStringA data;
  char        sBuf[1024];
  DWORD       dwBytesRead  = 0;
  LPWSTR      urlw;
  HINTERNET   hInet, hConnection, hRequest;
  LPTSTR      pszFunction = NULL;

  if ( url==NULL || strlen(url)==0 ) return NULL;

  urlw = wce_mbtowc(url);  
  hInet = hConnection = hRequest = NULL;

  do {
	  // Don't make a connection attempt if there is no session
    session = get_db_session(load_source_url());
	  if ( bCheckSession && !session && !strstr(url, "clientcreate") ) {
	    break;
	  }
	  if (session) free(session);

    if( !SetupInternetConnection(urlw) ) {
      break;
    }

    hInet = InternetOpen(_T("rhodes-wm"), 
      INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, NULL );
    if ( !hInet ) {
      pszFunction = L"InternetOpen";
      break;
    }

    DWORD lpdwBufferLength = sizeof(sBuf)/sizeof(wchar_t);
    if ( !InternetCanonicalizeUrl(urlw, (LPWSTR)sBuf, &lpdwBufferLength, 0) ) {
      pszFunction = L"InternetCanonicalizeUrl";
      break;
    }

    ATLTRACE(L"Connecting to url: %s\n",(LPWSTR)sBuf);

    URL_COMPONENTS uri;
    alloc_url_components(&uri,url);
    if( !InternetCrackUrl((LPWSTR)sBuf,lpdwBufferLength,0,&uri) ) {
      pszFunction = L"InternetCrackUrl";
      free_url_components(&uri);
      break;
    }

    hConnection = InternetConnect( hInet, 
      uri.lpszHostName, uri.nPort, _T("anonymous"), NULL, 
      INTERNET_SERVICE_HTTP, 0, 0 );
    if ( !hConnection ) {
      pszFunction = L"InternetConnect";
      free_url_components(&uri);
      break;
    }

    wsprintf((LPWSTR)sBuf,L"%s%s",uri.lpszUrlPath,uri.lpszExtraInfo);
    hRequest = HttpOpenRequest( hConnection, verb, 
      (LPWSTR)sBuf, NULL, NULL, NULL, 
      INTERNET_FLAG_KEEP_CONNECTION|INTERNET_FLAG_NO_CACHE_WRITE, NULL );
    if ( !hRequest ) {
      pszFunction = L"HttpOpenRequest";
      free_url_components(&uri);
      break;
    }

    free_url_components(&uri);

    //Send data
    if ( HttpSendRequest( hRequest, NULL, 0, body, body_size) ) {
      wchar_t res[10];
      DWORD dwLen = 10;
      DWORD nIndex = 0;
      bool bOk = false;
      if( HttpQueryInfo(hRequest,HTTP_QUERY_STATUS_CODE,res,&dwLen,&nIndex) ){
        if ( wcscmp(res,L"200") == 0 )
          bOk = true;
		else {
          bOk = false;
		  // If we're unauthorized, delete any cookies that might have been
		  // stored so we don't reuse them later
		  if ( wcscmp(res,L"401") == 0 ) delete_winmo_session(load_source_url());
		}
      }

      if ( bOk ){
        if ( bGetHeaders ){
          DWORD dwSize = 0;
	        HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS, NULL, &dwSize, NULL);
	        if( dwSize != 0 )
	        {
		        cstr = new char [dwSize+1];
		        // Call HttpQueryInfo again to get the headers.
		        bOk = (bool) HttpQueryInfoA(hRequest, HTTP_QUERY_RAW_HEADERS, (LPVOID) cstr, &dwSize, NULL);
          }
        }else{
          BOOL bRead = InternetReadFile(hRequest, &sBuf, sizeof(sBuf), &dwBytesRead);
          while (bRead && (dwBytesRead > 0)) {
            data.append(sBuf, dwBytesRead);
            //data.Append(sBuf, dwBytesRead);
            bRead = InternetReadFile(hRequest, &sBuf, sizeof(sBuf), &dwBytesRead);
          }
		      if ( bGetRawData && pdwDataSize ){
			      cstr = new char [*pdwDataSize];
            memcpy (cstr, data.c_str(), *pdwDataSize);
		      }
		      else {
			      //make a copy of recieved data
			      cstr = new char [data.size()+1];
			      strcpy (cstr, data.c_str());
            //cstr = new char [data.GetLength()+1];
            //strcpy (cstr, data.GetString());
		      }
        }
      }
    } else {
      pszFunction = L"HttpOpenRequest";
    }

  } while(0);

  if (pszFunction) {
    ErrorMessage(pszFunction);
  }

  if(hRequest) InternetCloseHandle(hRequest);
  if(hConnection) InternetCloseHandle(hConnection);
  if(hInet) InternetCloseHandle(hInet);

  free(urlw);
  return cstr;
}
VOID  CALLBACK HCInternetStatusCallback(
									  __in HINTERNET hInternet,
									  __in_opt DWORD_PTR dwContext,
									  __in DWORD dwInternetStatus,
									  __in_opt LPVOID lpvStatusInformation,
									  __in DWORD dwStatusInformationLength
									  )
{



	if ( INTERNET_STATUS_REDIRECT == dwInternetStatus )
	{
		LPCSTR pszRedirectUrl = (LPCSTR)lpvStatusInformation;
		CStringA strRedirectUrl;
		strRedirectUrl = pszRedirectUrl;
		CStringA strOrgUrl;
		UrlRecorder.GetRecordData(hInternet,&strOrgUrl);
		UrlRecorder.SetRecordData(hInternet,strRedirectUrl);


		CHAR chCookieData[2000]={0};
		CommonGetCookie(strRedirectUrl,chCookieData,1999,FALSE);

		CStringA strCookieHeader;
		strCookieHeader = "Cookie: ";
		strCookieHeader += chCookieData;

		BOOL bRes = HttpAddRequestHeadersA(hInternet,strCookieHeader.GetBuffer(),strCookieHeader.GetLength(),HTTP_ADDREQ_FLAG_ADD|HTTP_ADDREQ_FLAG_REPLACE);
		
		int a=0;

	}

	if ( INTERNET_STATUS_REQUEST_COMPLETE == dwInternetStatus  )
	{
		CStringA strInternetUrl;
		UrlRecorder.GetRecordData(hInternet,&strInternetUrl);

		char chRecvCookie[2000];
		DWORD dwRecvCookieLen = 2000;
		DWORD dwCookieIndex = 0;
		while(HttpQueryInfoA(hInternet,HTTP_QUERY_SET_COOKIE,chRecvCookie,&dwRecvCookieLen,&dwCookieIndex))
		{

			CommonSetCookie(strInternetUrl,chRecvCookie);

			if ( ERROR_HTTP_HEADER_NOT_FOUND ==  dwCookieIndex)
			{
				break;
			}
			dwRecvCookieLen = 2000;
		}
	}

	INTERNET_STATUS_CALLBACK pOrgCallback = NULL;
	CallbackRecorder.GetRecordData(hInternet,&pOrgCallback);

	if (pOrgCallback)
	{
		pOrgCallback(hInternet,
			dwContext,
			dwInternetStatus,
			lpvStatusInformation,
			dwStatusInformationLength
			);
	}


}
int GTHTTP_sendRequest(const char *url,
                       const unsigned char *request, size_t request_length,
                       unsigned char **response, size_t *response_length,
                       char **error)
{
    int res = GT_UNKNOWN_ERROR;
    char *host = NULL, *query = NULL;
    URL_COMPONENTS uc = { sizeof(uc) };
    HINTERNET cnx = NULL, req = NULL;
    DWORD http_res;
    DWORD http_res_len = sizeof(http_res);
    char *http_msg = NULL;
    DWORD http_msg_len = 0;
    unsigned char *resp = NULL;
    size_t resp_len = 0;

    if (url == NULL || response == NULL || response_length == NULL) {
        res = GT_INVALID_ARGUMENT;
        goto cleanup;
    }

    // extract host, port, and query from the URL
    uc.dwHostNameLength = 1;
    uc.dwUrlPathLength = 1;
    uc.dwExtraInfoLength = 1;
    if (!InternetCrackUrlA(url, 0, 0, &uc)) {
        res = map_impl(GetLastError());
        goto cleanup;
    }
    if (uc.lpszHostName == NULL || uc.dwHostNameLength == 0) {
        res = GT_INVALID_ARGUMENT;
        goto cleanup;
    }
    host = GT_malloc(uc.dwHostNameLength + 1);
    if (host == NULL) {
        res = GT_OUT_OF_MEMORY;
        goto cleanup;
    }
    strncpy_s(host, uc.dwHostNameLength + 1, uc.lpszHostName, uc.dwHostNameLength);
    if (uc.lpszUrlPath == NULL || uc.dwUrlPathLength == 0) {
        res = GT_INVALID_ARGUMENT;
        goto cleanup;
    }
    query = GT_malloc(uc.dwUrlPathLength + uc.dwExtraInfoLength + 1);
    if (query == NULL) {
        res = GT_OUT_OF_MEMORY;
        goto cleanup;
    }
    strncpy_s(query, uc.dwUrlPathLength + 1, uc.lpszUrlPath, uc.dwUrlPathLength);
    if (!(uc.lpszExtraInfo == NULL || uc.dwExtraInfoLength == 0)) {
        strncpy_s(query + uc.dwUrlPathLength, uc.dwExtraInfoLength + 1, uc.lpszExtraInfo, uc.dwExtraInfoLength);
    }

    // open the connection and send the request
    cnx = InternetConnectA(session_handle, host, uc.nPort, NULL, NULL, uc.nScheme, 0, 0);
    if (cnx == NULL) {
        res = map_impl(GetLastError());
        goto cleanup;
    }
    req = HttpOpenRequestA(cnx,
                           (request == NULL ? "GET" : "POST"),
                           query, NULL, NULL, NULL,
                           (uc.nScheme == INTERNET_SCHEME_HTTPS ? INTERNET_FLAG_SECURE : 0),
                           0);
    if (req == NULL) {
        res = map_impl(GetLastError());
        goto cleanup;
    }
    if (connect_timeout >= 0) {
        DWORD dw = (connect_timeout == 0 ? 0xFFFFFFFF : connect_timeout * 1000);
        InternetSetOption(req, INTERNET_OPTION_CONNECT_TIMEOUT, &dw, sizeof(dw));
    }
    if (response_timeout >= 0) {
        DWORD dw = (response_timeout == 0 ? 0xFFFFFFFF : response_timeout * 1000);
        InternetSetOption(req, INTERNET_OPTION_SEND_TIMEOUT, &dw, sizeof(dw));
        InternetSetOption(req, INTERNET_OPTION_RECEIVE_TIMEOUT, &dw, sizeof(dw));
    }
again:
    if (!HttpSendRequestA(req, NULL, 0, (LPVOID) request, request_length)) {
        res = map_impl(GetLastError());
        goto cleanup;
    }

    // receive the response
    if (!HttpQueryInfo(req, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER,
                       &http_res, &http_res_len, 0)) {
        res = map_impl(GetLastError());
        goto cleanup;
    }

    // proxy server requires authentication, prompt user
    if (http_res == HTTP_STATUS_PROXY_AUTH_REQ) {
        if (InternetErrorDlg(GetDesktopWindow(), req,
                             ERROR_INTERNET_INCORRECT_PASSWORD,
                             FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
                             FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
                             FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
                             NULL) == ERROR_INTERNET_FORCE_RETRY) {
            goto again;
        }
    }

    // web server requires authentication, prompt user
    if (http_res == HTTP_STATUS_DENIED) {
        if (InternetErrorDlg(GetDesktopWindow(), req,
                             ERROR_INTERNET_INCORRECT_PASSWORD,
                             FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
                             FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
                             FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
                             NULL) == ERROR_INTERNET_FORCE_RETRY) {
            goto again;
        }
    }

    if (http_res >= 400) {
        res = map_http(http_res);
        if (error != NULL) {
            // we had some error and client code wanted the message
            if (HttpQueryInfoA(req, HTTP_QUERY_STATUS_TEXT, http_msg, &http_msg_len, 0) ||
                    GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
                // unexpected results retrieving the HTTP error message
                // just report the HTTP error code
                goto cleanup;
            }
            http_msg = GT_malloc(http_msg_len);
            if (http_msg == NULL) {
                // no memory for the HTTP error message
                // just report the HTTP error code
                goto cleanup;
            }
            if (!HttpQueryInfoA(req, HTTP_QUERY_STATUS_TEXT, http_msg, &http_msg_len, 0)) {
                // unexpected results retrieving the HTTP error message
                // just report the HTTP error code
                goto cleanup;
            }
            *error = http_msg;
            http_msg = NULL;
        }
        goto cleanup;
    }

    while (1) {
        DWORD add_len = 0x2000; // download in 8K increments
        resp = GT_realloc(resp, resp_len + add_len);
        if (resp == NULL) {
            res = GT_OUT_OF_MEMORY;
            goto cleanup;
        }
        if (!InternetReadFile(req, resp + resp_len, add_len, &add_len)) {
            res = map_impl(GetLastError());
            goto cleanup;
        }
        if (add_len == 0) {
            break;
        }
        resp_len += add_len;
    }

    *response = resp;
    resp = NULL;
    *response_length = resp_len;
    res = GT_OK;

cleanup:

    GT_free(resp);
    GT_free(http_msg);
    if (req != NULL) {
        InternetCloseHandle(req);
    }
    if (cnx != NULL) {
        InternetCloseHandle(cnx);
    }
    GT_free(query);
    GT_free(host);
    return res;
}
Beispiel #13
0
/*
 * Download a file from an URL
 * Mostly taken from http://support.microsoft.com/kb/234913
 * If hProgressDialog is not NULL, this function will send INIT and EXIT messages
 * to the dialog in question, with WPARAM being set to nonzero for EXIT on success
 * and also attempt to indicate progress using an IDC_PROGRESS control
 */
BOOL DownloadFile(const char* url, const char* file, HWND hProgressDialog)
{
	HWND hProgressBar = NULL;
	BOOL r = FALSE;
	DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus;
	FILE* fd = NULL;
	LONG progress_style;
	unsigned char buf[DOWNLOAD_BUFFER_SIZE];
	char agent[64], hostname[64], urlpath[128];
	HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL;
	URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0,
		hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1};
	int i;
	char msg[MAX_PATH];

	if (hProgressDialog != NULL) {
		// Use the progress control provided, if any
		hProgressBar = GetDlgItem(hProgressDialog, IDC_PROGRESS);
		if (hProgressBar != NULL) {
			progress_style = GetWindowLong(hProgressBar, GWL_STYLE);
			SetWindowLong(hProgressBar, GWL_STYLE, progress_style & (~PBS_MARQUEE));
			SendMessage(hProgressBar, PBM_SETPOS, 0, 0);
		}
		SendMessage(hProgressDialog, UM_DOWNLOAD_INIT, 0, 0);
	}

	safe_sprintf(msg, sizeof(msg), "Downloading %s: Connecting...", file);
	print_status(0, FALSE, msg);
	dprintf("Downloading %s from %s\n", file, url);

	if ( (!InternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts))
	  || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) {
		dprintf("Unable to decode URL: %s\n", WindowsErrorString());
		goto out;
	}
	hostname[sizeof(hostname)-1] = 0;

	// Open an Internet session
	for (i=5; (i>0) && (!InternetGetConnectedState(&dwFlags, 0)); i--) {
		Sleep(1000);
	}
	if (i <= 0) {
		// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong...
		SetLastError(ERROR_INTERNET_NOT_INITIALIZED);
		dprintf("Network is unavailable: %s\n", WinInetErrorString());
		goto out;
	}
	safe_sprintf(agent, ARRAYSIZE(agent), APPLICATION_NAME "/%d.%d.%d  (Windows NT %d.%d%s)",
		application_version[0], application_version[1], application_version[2],
		nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : "");
	hSession = InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if (hSession == NULL) {
		dprintf("Could not open internet session: %s\n", WinInetErrorString());
		goto out;
	}

	hConnection = InternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL);
	if (hConnection == NULL) {
		dprintf("Could not connect to server %s:%d: %s\n", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString());
		goto out;
	}

	hRequest = HttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, (const char**)"*/*\0",
		INTERNET_FLAG_HYPERLINK|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP|INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS|INTERNET_FLAG_NO_COOKIES|
		INTERNET_FLAG_NO_UI|INTERNET_FLAG_NO_CACHE_WRITE, (DWORD_PTR)NULL);
	if (hRequest == NULL) {
		dprintf("Could not open url %s: %s\n", url, WindowsErrorString());
		goto out;
	}

	if (!HttpSendRequestA(hRequest, NULL, 0, NULL, 0)) {
		dprintf("Unable to send request: %s\n", WinInetErrorString());
		goto out;
	}

	// Get the file size
	dwSize = sizeof(dwStatus);
	dwStatus = 404;
	HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatus, &dwSize, NULL);
	if (dwStatus != 200) {
		download_error = ERROR_SEVERITY_ERROR|ERROR_INTERNET_ITEM_NOT_FOUND;
		dprintf("Unable to access file: Server status %d\n", dwStatus);
		goto out;
	}
	dwSize = sizeof(dwTotalSize);
	if (!HttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH|HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) {
		dprintf("Unable to retrieve file length: %s\n", WinInetErrorString());
		goto out;
	}
	dprintf("File length: %d bytes\n", dwTotalSize);

	fd = fopenU(file, "wb");
	if (fd == NULL) {
		dprintf("Unable to create file '%s': %s\n", file, WinInetErrorString());
		goto out;
	}

	// Keep checking for data until there is nothing left.
	dwSize = 0;
	while (1) {
		if (download_error)
			goto out;

		if (!InternetReadFile(hRequest, buf, sizeof(buf), &dwDownloaded) || (dwDownloaded == 0))
			break;
		dwSize += dwDownloaded;
		SendMessage(hProgressBar, PBM_SETPOS, (WPARAM)(MAX_PROGRESS*((1.0f*dwSize)/(1.0f*dwTotalSize))), 0);
		safe_sprintf(msg, sizeof(msg), "Downloading: %0.1f%%", (100.0f*dwSize)/(1.0f*dwTotalSize));
		print_status(0, FALSE, msg);
		if (fwrite(buf, 1, dwDownloaded, fd) != dwDownloaded) {
			dprintf("Error writing file '%s': %s\n", file, WinInetErrorString());
			goto out;
		}
	}

	if (dwSize != dwTotalSize) {
		dprintf("Could not download complete file - read: %d bytes, expected: %d bytes\n", dwSize, dwTotalSize);
		download_error = ERROR_WRITE_FAULT;
		goto out;
	} else {
		r = TRUE;
		dprintf("Successfully downloaded '%s'\n", file);
	}

out:
	if (hProgressDialog != NULL)
		SendMessage(hProgressDialog, UM_DOWNLOAD_EXIT, (WPARAM)r, 0);
	if (fd != NULL) fclose(fd);
	if (!r) {
		_unlink(file);
		print_status(0, FALSE, "Failed to download file.");
		SetLastError(download_error);
		MessageBoxU(hMain, WinInetErrorString(), "File download", MB_OK|MB_ICONERROR);
	}
	if (hRequest) InternetCloseHandle(hRequest);
	if (hConnection) InternetCloseHandle(hConnection);
	if (hSession) InternetCloseHandle(hSession);

	return r;
}
Beispiel #14
0
BOOL CHttpSender::_Send(CString sURL, CString sFileName, AssyncNotification* an)
{ 
  BOOL bStatus = FALSE;
	TCHAR* hdrs = _T("Content-Type: application/x-www-form-urlencoded");
	LPCTSTR accept[2]={_T("*/*"), NULL};
  int uFileSize = 0;
  BYTE* uchFileData = NULL;
  HINTERNET hSession = NULL;
  HINTERNET hConnect = NULL;
  HINTERNET hRequest = NULL;
  TCHAR szProtocol[512];
  TCHAR szServer[512];
  TCHAR szURI[1024];
  DWORD dwPort;
  struct _stat st;
  int res = -1;
  FILE* f = NULL;
  BOOL bResult = FALSE;
  char* chPOSTRequest = NULL;
  CStringA sMD5Hash;
  CStringA sPOSTRequest;
  char* szPrefix="crashrpt=\"";
  char* szSuffix="\"";
  CString sErrorMsg;
  CHAR szResponce[1024];
  DWORD dwBufSize = 1024;
  MD5 md5;
  MD5_CTX md5_ctx;
  unsigned char md5_hash[16];
  int i=0;  
  CString msg;

  an->SetProgress(_T("Start sending error report over HTTP"), 0, false);

  an->SetProgress(_T("Creating Internet connection"), 3, false);

  if(an->IsCancelled()){ goto exit; }

  // Create Internet session
	hSession = InternetOpen(_T("CrashRpt"),
		INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
	if(hSession==NULL)
  {
    an->SetProgress(_T("Error creating Internet conection"), 0);
	  goto exit; // Couldn't create internet session
  }
  
  ParseURL(sURL, szProtocol, 512, szServer, 512, dwPort, szURI, 1024);

  an->SetProgress(_T("Connecting to server"), 5, false);

  // Connect to server
	hConnect = InternetConnect(
    hSession, 
    szServer,
		INTERNET_DEFAULT_HTTP_PORT, 
    NULL, 
    NULL, 
    INTERNET_SERVICE_HTTP, 
    0, 
    1);
	
	if(hConnect==NULL)
  {
    an->SetProgress(_T("Error connecting to server"), 0);
	  goto exit; // Couldn't connect
  }
	
  if(an->IsCancelled()){ goto exit; }

  an->SetProgress(_T("Preparing HTTP request data"), 7, false);

  // Load file data into memory
  res = _tstat(sFileName.GetBuffer(0), &st);
  if(res!=0)
  {
    an->SetProgress(_T("Error opening file"), 0);
    goto exit; // File not found
  }
  
  uFileSize = st.st_size;
  uchFileData = new BYTE[uFileSize];
#if _MSC_VER<1400
  f = _tfopen(sFileName.GetBuffer(0), _T("rb"));
#else
  _tfopen_s(&f, sFileName.GetBuffer(0), _T("rb"));
#endif
  if(!f || fread(uchFileData, uFileSize, 1, f)!=1)
  {
    an->SetProgress(_T("Error reading file"), 0);
    goto exit;  
  }
  fclose(f);

  md5.MD5Init(&md5_ctx);
  md5.MD5Update(&md5_ctx, uchFileData, uFileSize);
  md5.MD5Final(md5_hash, &md5_ctx);
  
  sMD5Hash = _T("&md5=");
  for(i=0; i<16; i++)
  {
    CString number;
    number.Format(_T("%02X"), md5_hash[i]);
    sMD5Hash += number;
  }
  
  sPOSTRequest = base64_encode(uchFileData, uFileSize).c_str();
  sPOSTRequest = szPrefix + sPOSTRequest + szSuffix;  
  sPOSTRequest.Replace("+", "%2B");
  sPOSTRequest.Replace("/", "%2F");  

  sPOSTRequest += sMD5Hash;
  
  an->SetProgress(_T("Opening HTTP request"), 10);

  if(an->IsCancelled()){ goto exit; }

  // Send POST request
  hRequest = HttpOpenRequest(hConnect, _T("POST"),
		                         szURI, NULL, NULL, accept, 0, 1);	
	if(hRequest==NULL)
  {
    an->SetProgress(_T("Error opening HTTP request"), 0);
	  goto exit; // Coudn't open request	
  }

  if(an->IsCancelled()){ goto exit; }

  an->SetProgress(_T("Sending HTTP request"), 50);
  bResult = HttpSendRequest(hRequest, hdrs, (int)_tcslen(hdrs), 
    (void*)sPOSTRequest.GetBuffer(), (DWORD)sPOSTRequest.GetLength());
    
  if(bResult == FALSE)
  {
    an->SetProgress(_T("Error sending HTTP request"), 100, false);
		goto exit; // Couldn't send request
  }
	  
  an->SetProgress(_T("Sending error report over HTTP completed OK"), 10, true);
    
  HttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE, szResponce, &dwBufSize, NULL); 
  if(atoi(szResponce)!=200)
  {
    CString msg;
    msg.Format(_T("Error! The server returned code %s"), CString(szResponce));
    an->SetProgress(msg, 0);
    goto exit;
  }    

  InternetReadFile(hRequest, szResponce, 1024, &dwBufSize);
  szResponce[dwBufSize] = 0;
  msg = CStringA(szResponce, dwBufSize);
  msg = _T("Server returned:")+msg;
  an->SetProgress(msg, 0);
    
  if(atoi(szResponce)!=200)
  {
    an->SetProgress(_T("Failed"), 100, false);
    goto exit;
  }

  an->SetProgress(_T("Sent OK"), 100, false);
  bStatus = TRUE;

exit:

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

	if(hConnect) 
    InternetCloseHandle(hConnect);

	if(hSession) 
    InternetCloseHandle(hSession);

  if(chPOSTRequest)
    delete [] chPOSTRequest;
    
  if(uchFileData)
    delete [] uchFileData;

  if(f)
    fclose(f);

  return bStatus;
}