problems using WinINet in MFC - c++

I'm using WinINet class in MFC to upload files to webserver.
When I run this program, httpSendRequestEx returns 12005 error which is invalid url.
If I put http:// in front of the url, httpSendRequestEx returns 12007 error which is "The server name could not be resolved".
I spent whole day to fix this problem, but I have no idea how to fix it.
Please help me
Here is my code.
CString m_strBoundary = ("abcdefg");
LPCTSTR lpszFilePath = "C:\\MFCprj\\WinINet_Example2\\WinINet_Example2\\Full.jpg";
LPCTSTR lpszFileName = "Full.jpg";;
HANDLE hFile = CreateFile("C:\\MFCprj\\WinINet_Example2\\WinINet_Example2\\Full.jpg", GENERIC_READ, 0, 0, 0, 0, 0);
HINTERNET hInternet = ::InternetOpen("WININETEXAMPLE", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(!hInternet)
{
AfxMessageBox("InternetOpen has an error");
}
HINTERNET hConnection = ::InternetConnect(hInternet, "192.168.88.4:8090/mrbs/controller?do=XML_MULTIPART_TEST_ACTION", INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);
if(!hConnection)
{
AfxMessageBox("InternetConnect has an error");
}
HINTERNET hRequest = ::HttpOpenRequest(hConnection, "POST", "/jsp/inc/head.jsp", NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
if(!hRequest)
{
AfxMessageBox("HttpOpenRequest has an error");
}
//HTTP header
_bstr_t strHeader;
strHeader = "Content-Type: multipart/form-data; boundary=";
strHeader = strHeader + m_strBoundary;
::HttpAddRequestHeaders(hRequest, (LPCTSTR)strHeader, -1, 0);
//Body header
_bstr_t strFilePartHead("--");
strFilePartHead = strFilePartHead + m_strBoundary;
strFilePartHead = strFilePartHead + "\r\nContent-Disposition: form-data; name=\"file\"; filename=\"Full.jpg\"";
strFilePartHead = strFilePartHead + "\"\r\nContent-Type: application/vnd.ms-excel\r\n\r\n";
_bstr_t strFilePartTail("\r\n");
strFilePartTail = strFilePartTail + "--";
strFilePartTail = strFilePartTail + m_strBoundary;
strFilePartTail = strFilePartTail + "--\r\n";
INTERNET_BUFFERS BufferIn;
BufferIn.dwStructSize = sizeof(INTERNET_BUFFERS);
BufferIn.Next = NULL;
BufferIn.lpcszHeader = (LPCTSTR)strHeader;
BufferIn.dwBufferLength = 0;
BufferIn.dwBufferTotal = GetFileSize(lpszFilePath) + strlen( (LPCSTR)strFilePartHead ) + strlen( (LPCSTR)strFilePartTail );
BufferIn.dwHeadersLength = lstrlen( (LPCTSTR)strHeader );
BufferIn.dwHeadersTotal = lstrlen( (LPCTSTR)strHeader );
BufferIn.lpvBuffer = NULL;
BufferIn.dwOffsetHigh = 0;
BufferIn.dwOffsetLow = 0;
if(!::HttpSendRequestEx(hRequest, &BufferIn, NULL, 0, NULL))
{
DWORD dwError = GetLastError();
::InternetCloseHandle(hRequest);
::InternetCloseHandle(hConnection);
::InternetCloseHandle(hInternet);
}

InternetConnect accepts only the server name/address, and the port.
hConnection = ::InternetConnect(hInternet, "192.168.88.4", 8090, ...);
That's because InternetConnect only makes a connection to a server (a port on a machine somewhere). The URL forms part of the request to the server, so the additional string ("/mrbs/controller?do=XML_MULTIPART_TEST_ACTION") you were passing to InternetConnect actually needs to be given to HttpOpenRequest.
hRequest = ::HttpOpenRequest(hConnection, "POST", "/mrbs/controller?do=XML_MULTIPART_TEST_ACTION", ...);
I'm not sure where the "/jsp/inc/head.jsp" that you were originally passing to HttpOpenRequest fits in, but if that really is part of the URL too then you would do this:
hRequest = ::HttpOpenRequest(hConnection, "POST", "/mrbs/controller?do=XML_MULTIPART_TEST_ACTION/jsp/inc/head.jsp", ...);

Related

C++ : the url reader function doesn't work for URL links with \ sign. pls help me

As written in the title, this is a function which returns the HTML source code string of a URL.
It works only with the main page, such as "finance.yahoo.com/". If I try a URL from one of the bookmarks in Yahoo, such as "finance.yahoo.com/quote/BTC-USD/", it doesn't work.
string getHtml() {
HINTERNET hInternet = InternetOpenA("InetURL/1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnection = InternetConnectA(hInternet, " finance.yahoo.com/quote/BTC-USD/", 80, " ", " ", INTERNET_SERVICE_HTTP, 0, 0);
HINTERNET hData = HttpOpenRequestA(hConnection, "GET", "/", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
char buf[2048];
string lol;
HttpSendRequestA(hData, NULL, 0, NULL, 0);
DWORD bytesRead = 0;
DWORD totalBytesRead = 0;
int i = 0;
string n, n2;
while (InternetReadFile(hData, buf, 2000, &bytesRead) && bytesRead != 0)
{
buf[bytesRead] = 0; // insert the null terminator.
// puts(buf); // print it to the screen.
lol = lol + buf;
n = lol;
totalBytesRead += bytesRead;
}
InternetCloseHandle(hData);
InternetCloseHandle(hConnection);
InternetCloseHandle(hInternet);
return n;
}
This is wrong:
HINTERNET hConnection = InternetConnectA(hInternet, " finance.yahoo.com/quote/BTC-USD/", 80, " ", " ", INTERNET_SERVICE_HTTP, 0, 0);
HINTERNET hData = HttpOpenRequestA(hConnection, "GET", "/", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION, 0);
You can't "connect" to a URL like that, only to a hostname.
You need to specify just the hostname in InternetConnectA(), and then specify the desired document relative to that hostname in HttpOpenRequestA().
Also, finance.yahoo.com uses HTTPS, not HTTP, so you need to connect to the HTTPS port and use secure semantics on the request.
Try this:
HINTERNET hConnection = InternetConnectA(hInternet, "finance.yahoo.com", INTERNET_DEFAULT_HTTPS_PORT, " ", " ", INTERNET_SERVICE_HTTP, 0, 0);
HINTERNET hData = HttpOpenRequestA(hConnection, "GET", "/quote/BTC-USD/", NULL, NULL, NULL, INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_SECURE, 0);

Unable to obtain POST request response using wininet

I need to make a POST request to an API to get some XML data (http://freecite.library.brown.edu/welcome/api_instructions). This works fine with curl:
curl -H "Accept: application/xml" --data "citation=Udvarhelyi, I.S., Gatsonis, C.A., Epstein, A.M., Pashos, C.L., Newhouse, J.P. and McNeil, B.J. Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes. Journal of the American Medical Association, 1992; 18:2530-2536. " http://freecite.library.brown.edu:80/citations/create
So I am trying to do a similar thingy using Win32 SDK. This is my code:
void LoadData()
{
wil::unique_hinternet hInternet(InternetOpen(L"Dummy", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0));
wil::unique_hinternet hConnect(InternetConnect(hInternet.get(), L"http://freecite.library.brown.edu", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0));
wil::unique_hinternet hRequest(HttpOpenRequest(hConnect.get(), L"POST", L"/citations/create", NULL, NULL, NULL, NULL, NULL));
wstring data = L"citation=Udvarhelyi, I.S., Gatsonis, C.A., Epstein, A.M., Pashos, C.L., Newhouse, J.P. and McNeil, B.J. Acute Myocardial Infarction in the Medicare population: process of care and clinical outcomes. Journal of the American Medical Association, 1992; 18:2530-2536.";
PCWSTR szHeaders = L"Accept: application/xml";
HttpSendRequest(hRequest.get(), szHeaders, 0, (LPVOID)data.c_str(), static_cast<int>(data.length()));
DWORD availableBytes = 0;
InternetQueryDataAvailable(hRequest.get(), &availableBytes, 0, 0);
PBYTE outputBuffer = (PBYTE)HeapAlloc(GetProcessHeap(), 0, availableBytes);
PBYTE nextBytes = outputBuffer;
DWORD bytesUsed = 0; // number of used bytes.
while (availableBytes)
{
DWORD downloadedBytes;
InternetReadFile(hRequest.get(), nextBytes, availableBytes, &downloadedBytes);
bytesUsed = bytesUsed + downloadedBytes;
InternetQueryDataAvailable(hRequest.get(), &availableBytes, 0, 0);
if (availableBytes > 0)
{
// lazy buffer growth here. Only alloc for what we need. could be optimized if we end up with huge payloads (>10MB).
// otherwise, this is good enough.
outputBuffer = (PBYTE)HeapReAlloc(GetProcessHeap(), 0, outputBuffer, bytesUsed + availableBytes);
nextBytes = outputBuffer + bytesUsed; // careful, pointer might have moved! Update cursor.
}
}
// Convert outputed XML to wide char
int size_needed = MultiByteToWideChar(CP_UTF8, 0, (PCCH)outputBuffer, bytesUsed, NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, (PCCH)outputBuffer, bytesUsed, &wstrTo[0], size_needed);
wstring res = wstrTo;
}
The problem is, before entering the for loop, even after the call to InternetQueryDataAvailable, availableBytes comes out to be 0. As a result, I finally end up getting a blank string as response, whereas I was expecting a XML response.
Can anyone point me what am I doing wrongly, and how to fix it?
InternetConnect expects server name or IP address, so don't include "http://" in the address. Change to:
InternetConnect(handle, L"freecite.library.brown.edu"...);
Use UTF-8 for data. Other parameters for WinAPI functions are correctly using UTF-16, they automatically make the necessary conversions.
Change the header:
std::wstring szHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
accept should be sent through HttpOpenRequest
const wchar_t *accept[] = { L"text/xml", NULL };
HINTERNET hrequest = HttpOpenRequest(hconnect, L"POST", L"/citations/create",
NULL, NULL, accept, 0, 0);
Note, if you don't specify accept (use NULL in its place) then the result can be in plain html.
The example below should return XML.
Note, for simplicity I put optional as ANSI string, but it should be UTF8, then you convert it to UTF16 woptional and send it. result will be UTF8 string, it should be converted to UTF16 for Windows's display.
#include <iostream>
#include <string>
#include <Windows.h>
#include <WinINet.h>
#pragma comment(lib, "wininet.lib")//include WinINet library
int main()
{
std::string result;
std::wstring server = L"freecite.library.brown.edu";
std::wstring objectname = L"/citations/create"; //file in this case!
std::wstring header = L"Content-Type: application/x-www-form-urlencoded\r\n";
std::string optional = "citation=Udvarhelyi, I.S., Gatsonis, C.A., Epstein";
HINTERNET hsession = InternetOpen(L"appname",
INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hconnect = InternetConnect(hsession, server.c_str(),
INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
const wchar_t* accept[] = { L"text/xml", NULL };
HINTERNET hrequest = HttpOpenRequest(hconnect, L"POST", objectname.c_str(),
NULL, NULL, accept, 0, 0);
if(HttpSendRequest(hrequest, header.c_str(), header.size(),
&optional[0], optional.size()))
{
DWORD blocksize = 4096;
DWORD received = 0;
std::string block(blocksize, 0);
while (InternetReadFile(hrequest, &block[0], blocksize, &received)
&& received)
{
block.resize(received);
result += block;
}
std::cout << result << std::endl;
}
if (hrequest) InternetCloseHandle(hrequest);
if (hconnect) InternetCloseHandle(hconnect);
if (hsession) InternetCloseHandle(hsession);
return 0;
}

Sending file to HTTP server (C++ Wininet)

I have code for uploading small .txt files on my HTTP-server:
#include <wininet.h>
#define BUF_SIZE 4096
void __fastcall TForm1::Button1Click(TObject *Sender)
{
TStringList * list = new TStringList();
AnsiString Path = "";
if(OpenDialog1->Execute()) {
Path = "filename=\""+OpenDialog1->FileName+"\"";
list->LoadFromFile(OpenDialog1->FileName);
}
char data[BUF_SIZE] = "";
static char hdrs[] = "Content-Type: multipart/form-data; boundary=---------------------------7d82751e2bc0858";
strcat(data,"-----------------------------7d82751e2bc0858");
strcat(data,"\n");
strcat(data,"Content-Disposition: form-data; name=\"files[]\"; ");
strcat(data,Path.c_str());
strcat(data,"\n");
strcat(data,"Content-Type: application/octet-stream");
strcat(data,"\n\n");
strcat(data,list->Text.c_str());
strcat(data,"\n");
strcat(data,"-----------------------------7d82751e2bc0858");
strcat(data,"\n");
strcat(data,"Content-Disposition: form-data; name=\"user\"");
strcat(data,"\r\n\r\n");
strcat(data,"username");
strcat(data,"\r\n");
strcat(data,"-----------------------------7d82751e2bc0858");
strcat(data,"\n");
HINTERNET hSession = InternetOpen("MyAgent",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession, "localhost",INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
HINTERNET hRequest = HttpOpenRequest(hConnect, "POST", "new_upltest.php", NULL, NULL, NULL, 0, 1);
HttpSendRequest(hRequest, hdrs, strlen(hdrs), data, strlen(data));
delete list;
}
It's working fine, but now I'm needing to upload big files (over 70-100 mb), that can be images (.jpg, .png, .bmp) and other document types (.pdf, .docx, etc).
Is it possible to solve my task with this code? I will be grateful for each advices...
P.S. My IDE is C++ Builder 6, but I think it doesn't matter.
This is working example for one file uploading:
void http_upload_file(PCHAR szServer, PCHAR szScript, PCHAR szParam, PCHAR szValue, PCHAR szFile)
{
PCHAR szHeaders = "Content-Type: multipart/form-data; boundary=----qwerty";
PCHAR szData = "------qwerty\r\n"
"Content-Disposition: form-data; name=\"%s\"\r\n\r\n%s\r\n"
"------qwerty\r\n"
"Content-Disposition: form-data; name=\"files[]\"; filename=\"%s\"\r\n"
"Content-Type: application/octet-stream\r\n"
"Content-Transfer-Encoding: binary\r\n\r\n";
PCHAR szDataEnd = "\r\n------qwerty--\r\n";
char szHeader[512];
HINTERNET hSession, hConnect, hRequest;
DWORD dwFileSize, dwBytesRead, dwContentLength,dwBytesWritten;
hSession = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hSession)
{
hConnect = InternetConnect(hSession, szServer, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP,0, 0);
if (hConnect)
{
hRequest = HttpOpenRequest(hConnect, "POST", szScript, NULL, NULL, 0, 0, 0);
if (hRequest)
{
HANDLE hFile = CreateFile(szFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
dwFileSize = GetFileSize(hFile, NULL);
wsprintf(szHeader, szData, szParam, szValue, szFile);
dwContentLength = lstrlen(szHeader) + dwFileSize + lstrlen(szDataEnd);
LPBYTE pBuf = (LPBYTE)malloc(dwContentLength);
CopyMemory(&pBuf[0], szHeader, lstrlen(szHeader));
ReadFile(hFile, &pBuf[lstrlen(szHeader)], dwFileSize, &dwBytesRead, NULL);
CopyMemory(&pBuf[lstrlen(szHeader) + dwFileSize], szDataEnd, lstrlen(szDataEnd));
HttpSendRequest(hRequest, szHeaders, lstrlen(szHeaders), pBuf, dwContentLength);
CloseHandle(hFile);
free(pBuf);
}
}
InternetCloseHandle(hRequest);
}
InternetCloseHandle(hConnect);
}
InternetCloseHandle(hSession);
}

POST Request in WinHttp c++

I'm trying to make a POST request in c++ with the WinHTTP api Click to the Microsoft Guide, the problem is that the example that is available in the microsoft webpage is a "GET" request so I came up with this code searching on the internet:
First we call the code:
HttpsWebRequestPost("example.com", "/api.php?action=UserLogin", "loginUsername=" + USERNAME + "&loginPassword=" + PASSWORD + "&url=/index.php?page=Portal");
Then:
#include <Windows.h>
#include <WinHttp.h>
#include <stdio.h>
#include <iostream> //getchar
#include <fstream>
#pragma comment(lib, "winhttp.lib")
using namespace std;
std::wstring get_utf16(const std::string &str, int codepage)
{
if (str.empty()) return std::wstring();
int sz = MultiByteToWideChar(codepage, 0, &str[0], (int)str.size(), 0, 0);
std::wstring res(sz, 0);
MultiByteToWideChar(codepage, 0, &str[0], (int)str.size(), &res[0], sz);
return res;
}
string HttpsWebRequestPost(string domain, string url, string dat)
{
//Extra
LPSTR data = const_cast<char *>(dat.c_str());;
DWORD data_len = strlen(data);
wstring sdomain = get_utf16(domain, CP_UTF8);
wstring surl = get_utf16(url, CP_UTF8);
string response;
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
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);
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession, sdomain.c_str(),
INTERNET_DEFAULT_HTTP_PORT, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"POST", surl.c_str(),
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
// Send a request.
if (hRequest)
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
(LPVOID)data, data_len,
data_len, 0);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
// Keep checking for data until there is nothing left.
if (bResults)
{
do
{
// Check for available data.
dwSize = 0;
if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
printf("Error %u in WinHttpQueryDataAvailable.\n",
GetLastError());
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize + 1];
if (!pszOutBuffer)
{
printf("Out of memory\n");
dwSize = 0;
}
else
{
// 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);
response = response + string(pszOutBuffer);
// Free the memory allocated to the buffer.
delete[] pszOutBuffer;
}
} while (dwSize > 0);
}
// Report any errors.
if (!bResults)
printf("Error %d has occurred.\n", GetLastError());
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
return response;
}
But using WireShark I only get:
Hypertext Transfer Protocol
POST ***************** HTTP/1.1\r\n
Connection: Keep-Alive\r\n
User-Agent: WinHTTP Example/1.0\r\n
Content-Length: **\r\n
Host: ******\r\n
\r\n
Anyone can help meto fix this or know an easier method?
Thanks
In order for PHP (or any other post-processing language) to recognise POST data, add this:
LPCWSTR additionalHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
DWORD headersLength = -1;
bResults = WinHttpSendRequest( hRequest,
additionalHeaders,
headersLength ,
(LPVOID)data,
data_len,
data_len,
0);
The rest of a code is functional, should work:
The following code works for me when I tried to post text in key(info) and value(this is some info) pair. The status code 200 returned at the end.
int main()
{
DWORD dwSize = 0;
LPVOID lpOutBuffer = NULL;
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen(L"A WinHTTP Example Program/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0);
std::wstring url{ L"http://app.pomdit.com:3010/uploadfile" };
URL_COMPONENTS components{};
components.dwStructSize = sizeof(components);
components.dwHostNameLength = (DWORD)-1;
components.dwUrlPathLength = (DWORD)-1;
if (!WinHttpCrackUrl(url.c_str(), static_cast<DWORD>(url.length()), 0, &components)) {
wprintf((L"WinHttpCrackUrl(): " + ErrorMessage(GetLastError())).c_str());
}
std::wstring hostName(components.lpszHostName ? std::wstring{ components.lpszHostName, components.dwHostNameLength } : L"localhost");
// Specify an HTTP server.
if (hSession)
hConnect = WinHttpConnect(hSession, hostName.c_str(),
components.nPort, 0);
// Create an HTTP request handle.
if (hConnect)
hRequest = WinHttpOpenRequest(hConnect, L"POST", components.lpszUrlPath,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
const WCHAR* ContentType =
L"Content-Type: multipart/form-data;boundary = 19024605111143684786787635207";
const char* MultipartRequestBody =
"--19024605111143684786787635207\r\n"
"Content-Disposition: form-data; name=\"info\"\r\n"
"\r\n"
"this is some info\r\n"
"--19024605111143684786787635207\r\n";
bResults = WinHttpSendRequest(hRequest, ContentType, wcslen(ContentType),
(LPVOID)MultipartRequestBody,
strlen(MultipartRequestBody),
strlen(MultipartRequestBody),
NULL);
// End the request.
if (bResults)
bResults = WinHttpReceiveResponse(hRequest, NULL);
// First, use WinHttpQueryHeaders to obtain the size of the buffer.
if (bResults)
{
DWORD status{}, len = sizeof(status);
bResults = WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &len, NULL);
if (bResults)
{
printf("Status code = %d.\n", status);
}
}
else
{
wprintf(L"WinHttpReceiveResponse(): %s\n", ErrorMessage(GetLastError()).c_str());
}
// Close any open handles.
if (hRequest) WinHttpCloseHandle(hRequest);
if (hConnect) WinHttpCloseHandle(hConnect);
if (hSession) WinHttpCloseHandle(hSession);
}

Passing Multiple params HttpPostRequest c++

I have this function to send HTTP POST requests in C++, but i am having a little problem passing multiple strings arguments to it. Here's my code so far:
#include <Windows.h>
int doHttpPost(char *szDomain, char *szPage, char *szPost)
{
int iReturn = 1;
HINTERNET hSession = NULL;
HINTERNET hConnect = NULL;
HINTERNET hRequest = NULL;
static TCHAR hdrs[] = "Content-Type: application/x-www-form-urlencoded";
const char *accept[2]={"*/*", NULL};
TCHAR *frmdata = szPost;
hSession = InternetOpen("AGENT", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession)
{
hConnect = InternetConnect(hSession, szDomain, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(hConnect)
{
hRequest = HttpOpenRequest(hConnect, "POST", szPage, NULL, NULL, accept, INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_RELOAD, 0);
if(hRequest)
{
if(HttpSendRequest(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata)))
iReturn = 0;
else
iReturn = 5;
}
else //HttpOpenRequest
iReturn = 3;
}
else //InternetConnect
iReturn = 2;
}
else //InternetOpen
iReturn = 1;
//Cleanup
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return iReturn;
}
I call the function this way:
doHttpPost((char*)"127.0.0.1",(char*)"/test/post.php",(char*)postreq);
Is there a way I can add multiple requests in the post field, such as:
value1=id&value2=password&value3=details
where id, password and details will be variables containing data.
You can build a string from parts using sprintf and friends.
The simplest code snippet, which however ignores escaping you need to do on the values, is as follows:
CHAR pszRequest[1024] = { 0 };
CHAR* pszValue1 = "id";
CHAR* pszValue2 = "password";
CHAR* pszValue3 = "details";
sprintf(pszRequest, "value1=%s&value2=%s&value3=%s",
pszValue1, pszValue2, pszValue3);
doHttpPost((char*) "127.0.0.1", (char*) "/test/post.php", pszRequest);
For a robust solution you need to read up on basic string manipulation functions, and check RFC that defines body format for "application/x-www-form-urlencoded" MIME type.