I am trying to retrieve the source code of a web page using WinHTTP. Reading from this page: http://msdn.microsoft.com/en-us/library/windows/desktop/aa384110(v=vs.85).aspx
I was able to come up with this code. The HTTP status code is 200 which means the request was completed correctly. I end up getting the source code for the login page instead of my intended web page behind it.
Should I send a httprequest to the login page and then to the file path?
Here is the code:
#include <windows.h>
#include <winhttp.h>
#include <string>
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
#pragma comment(lib, "winhttp.lib")
DWORD ChooseAuthScheme(DWORD dwSupportedSchemes)
{
// It is the server's responsibility only to accept
// authentication schemes that provide a sufficient
// level of security to protect the servers resources.
//
// The client is also obligated only to use an authentication
// scheme that adequately protects its username and password.
//
// Thus, this sample code does not use Basic authentication
// becaus Basic authentication exposes the client's username
// and password to anyone monitoring the connection.
if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NEGOTIATE)
return WINHTTP_AUTH_SCHEME_NEGOTIATE;
else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_NTLM)
return WINHTTP_AUTH_SCHEME_NTLM;
else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_PASSPORT)
return WINHTTP_AUTH_SCHEME_PASSPORT;
else if (dwSupportedSchemes & WINHTTP_AUTH_SCHEME_DIGEST)
return WINHTTP_AUTH_SCHEME_DIGEST;
else
return 0;
}
struct SWinHttpSampleGet
{
LPCWSTR szServer;
LPCWSTR szPath;
BOOL fUseSSL;
LPCWSTR szServerUsername;
LPCWSTR szServerPassword;
LPCWSTR szProxyUsername;
LPCWSTR szProxyPassword;
};
void WinHttpAuthSample(IN SWinHttpSampleGet *pGetRequest)
{
string contents;
DWORD dwStatusCode = 0;
DWORD dwSupportedSchemes;
DWORD dwFirstScheme;
DWORD dwSelectedScheme;
DWORD dwTarget;
DWORD dwLastStatus = 0;
DWORD dwSize = sizeof(DWORD);
BOOL bResults = FALSE;
BOOL bDone = FALSE;
DWORD dwProxyAuthScheme = 0;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
INTERNET_PORT nPort = (pGetRequest->fUseSSL) ?
INTERNET_DEFAULT_HTTPS_PORT :
INTERNET_DEFAULT_HTTP_PORT;
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession,
pGetRequest->szServer,
nPort, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect,
L"GET",
pGetRequest->szPath,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
(pGetRequest->fUseSSL) ?
WINHTTP_FLAG_SECURE : 0);
// Continue to send a request until status code
// is not 401 or 407.
if (hRequest == NULL)
bDone = TRUE;
while (!bDone)
{
// If a proxy authentication challenge was responded to, reset
// those credentials before each SendRequest, because the proxy
// may require re-authentication after responding to a 401 or
// to a redirect. If you don't, you can get into a
// 407-401-407-401- loop.
if (dwProxyAuthScheme != 0)
bResults = WinHttpSetCredentials(hRequest,
WINHTTP_AUTH_TARGET_PROXY,
dwProxyAuthScheme,
pGetRequest->szProxyUsername,
pGetRequest->szProxyPassword,
NULL);
// Send a request.
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,
0,
WINHTTP_NO_REQUEST_DATA,
0,
0,
0);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
// Resend the request in case of
// ERROR_WINHTTP_RESEND_REQUEST error.
if (!bResults && GetLastError() == ERROR_WINHTTP_RESEND_REQUEST)
continue;
// Check the status code.
if (bResults)
bResults = WinHttpQueryHeaders(hRequest,
WINHTTP_QUERY_STATUS_CODE |
WINHTTP_QUERY_FLAG_NUMBER,
NULL,
&dwStatusCode,
&dwSize,
NULL);
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
if (bResults)
{
switch (dwStatusCode)
{
case 200:
// The resource was successfully retrieved.
// You can use WinHttpReadData to read the
// contents of the server's response.
printf("The resource was successfully retrieved.\n");
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
{
printf("Error %u in WinHttpQueryDataAvailable.\n",
GetLastError());
break;
}
// No more available data.
if (!dwSize)
break;
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize + 1];
if (!pszOutBuffer)
{
printf("Out of memory\n");
break;
}
// Read the Data.
ZeroMemory(pszOutBuffer, dwSize + 1);
if (!WinHttpReadData(hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded))
{
printf("Error %u in WinHttpReadData.\n", GetLastError());
}
else
{
printf("%s", pszOutBuffer);
contents += pszOutBuffer;
}
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
// This condition should never be reached since WinHttpQueryDataAvailable
// reported that there are bits to read.
if (!dwDownloaded)
break;
} while (dwSize > 0);
bDone = true;
break;
case 401:
// The server requires authentication.
printf(" The server requires authentication. Sending credentials...\n");
// Obtain the supported and preferred schemes.
bResults = WinHttpQueryAuthSchemes(hRequest,
&dwSupportedSchemes,
&dwFirstScheme,
&dwTarget);
// Set the credentials before resending the request.
if (bResults)
{
dwSelectedScheme = ChooseAuthScheme(dwSupportedSchemes);
if (dwSelectedScheme == 0)
bDone = TRUE;
else
bResults = WinHttpSetCredentials(hRequest,
dwTarget,
dwSelectedScheme,
pGetRequest->szServerUsername,
pGetRequest->szServerPassword,
NULL);
}
// If the same credentials are requested twice, abort the
// request. For simplicity, this sample does not check
// for a repeated sequence of status codes.
if (dwLastStatus == 401)
bDone = TRUE;
break;
case 407:
// The proxy requires authentication.
printf("The proxy requires authentication. Sending credentials...\n");
// Obtain the supported and preferred schemes.
bResults = WinHttpQueryAuthSchemes(hRequest,
&dwSupportedSchemes,
&dwFirstScheme,
&dwTarget);
// Set the credentials before resending the request.
if (bResults)
dwProxyAuthScheme = ChooseAuthScheme(dwSupportedSchemes);
// If the same credentials are requested twice, abort the
// request. For simplicity, this sample does not check
// for a repeated sequence of status codes.
if (dwLastStatus == 407)
bDone = TRUE;
break;
default:
// The status code does not indicate success.
printf("Error. Status code %d returned.\n", dwStatusCode);
bDone = TRUE;
}
}
// Keep track of the last status code.
dwLastStatus = dwStatusCode;
// If there are any errors, break out of the loop.
if (!bResults)
bDone = TRUE;
}
// Report any errors.
if (!bResults)
{
DWORD dwLastError = GetLastError();
printf("Error %d has occurred.\n", dwLastError);
}
ofstream fout("Output.txt");
fout << contents;
fout.close();
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
}
int main()
{
wstring Server = L"moodle.redlands.edu";
wstring Path = L"/course/view.php?id=2213/";
wstring User = L"test";
wstring Pass = L"password";
wstring User_Proxy = L"test";
wstring Pass_Proxy = L"password";
SWinHttpSampleGet Lawl{
Server.c_str(),
Path.c_str(),
1,
User.c_str(),
Pass.c_str(),
User_Proxy.c_str(), Pass_Proxy.c_str()
};
WinHttpAuthSample(&Lawl);
system("PAUSE");
return 0;
}