0

I've a code that makes a post request to a server but I'm trying to set a Cookie from the response. (Just in case, I'm doing a request to a BurningBoard Login)

Here you have my code:

HttpsWebRequestPost("example.com", "/api.php?action=UserLogin", "loginUsername=" + USERNAME + "&loginPassword=" + PASSWORD + "&url=/index.php?page=Portal");

And:

#pragma once

#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);

    LPCWSTR additionalHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
    DWORD headersLength = -1;

    // Send a request.
    if (hRequest)
        bResults = WinHttpSendRequest(hRequest,
            additionalHeaders, headersLength,
            (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;

}

Finally, this is what I get as response in WireShark:

Hypertext Transfer Protocol
    HTTP/1.1 200 OK\r\n
    Request Version: HTTP/1.1
    Status Code: 200
    Response Phrase: OK
    Date: Sat, 30 Jul 2016 11:55:02 GMT\r\n
    Server: Apache\r\n
    Set-Cookie: wcf_cookieHash=*******hash******; HttpOnly\r\n
    Set-Cookie: wcf_boardLastActivityTime=1469879702; expires=Sun, 30-Jul-2017 11:55:02 GMT; HttpOnly\r\n
    Cache-Control: max-age=0, private\r\n
    Expires: Sat, 30 Jul 2016 11:55:02 GMT\r\n
    Vary: Accept-Encoding\r\n
    Connection: close\r\n
    Transfer-Encoding: chunked\r\n
    Content-Type: text/html; charset=UTF-8\r\n
    \r\n

Can somebody help me to add cookies please? Thanks

UPDATED

Now I'm havig troubles to get data from the header, I only get the first "H".

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);

    LPCWSTR additionalHeaders = L"Content-Type: application/x-www-form-urlencoded\r\n";
    DWORD headersLength = -1;

    // Send a request.
    if (hRequest)
        bResults = WinHttpSendRequest(hRequest,
            additionalHeaders, headersLength,
            (LPVOID)data, data_len,
            data_len, 0);

    // End the request.
    if (bResults)
        bResults = WinHttpReceiveResponse(hRequest, NULL);


    // First, use WinHttpQueryHeaders to obtain the size of the buffer.
    if (bResults)
    {
        do
        {
        dwSize = 0;
        if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
            printf("Error %u in WinHttpQueryDataAvailable.\n",
                GetLastError());

        WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_RAW_HEADERS_CRLF,
            WINHTTP_HEADER_NAME_BY_INDEX, NULL,
            &dwSize, WINHTTP_NO_HEADER_INDEX);

            // 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);

                bResults = WinHttpQueryHeaders(hRequest,
                    WINHTTP_QUERY_RAW_HEADERS_CRLF,
                    WINHTTP_HEADER_NAME_BY_INDEX,
                    (LPVOID)pszOutBuffer, &dwSize,
                    WINHTTP_NO_HEADER_INDEX);
                //printf("%s", pszOutBuffer);
                response = response + string(pszOutBuffer);
                // Free the memory allocated to the buffer.
                delete[] pszOutBuffer;
            }
        } while (dwSize > 0);
    }


    // Free the allocated memory.
    //delete[] pszOutBuffer;

    // 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;

}
Community
  • 1
  • 1
Jose
  • 129
  • 2
  • 4
  • 9

1 Answers1

1

Cookies should work automatically if you make all your requests within the same session. Call WinHttpOpen once, use that session handle in all requests. It's the session that maintains the cookie jar.

See also: Cookie Handling in WinHTTP

Igor Tandetnik
  • 50,461
  • 4
  • 56
  • 85
  • Yes, But I want to make a request and then extract the cookie from it to set it in another request because I need to make multiple actions with those cookies – Jose Jul 31 '16 at 10:31
  • Well, `Cookie:` and `Set-Cookie:` are HTTP headers like any others. If you don't like the cookie jar maintained by WinHTTP, you can always maintain your own, by reading and processing `Set-Cookie:` headers from the responses (`WinHttpQueryHeaders`), and adding appropriate `Cookie:` headers to your requests (`WinHttpAddRequestHeaders`) – Igor Tandetnik Jul 31 '16 at 14:14
  • Yes, the problem is that the response that my code give starts in and don't show the header. – Jose Jul 31 '16 at 15:19
  • You are looking at response body. Response headers are, naturally, not part of the body. Which part of `WinHttpQueryHeaders` did you find unclear? – Igor Tandetnik Jul 31 '16 at 16:45
  • Yes, I updated my post with the example wich I'm working on.. I just get the first H every time, even with the "do{}" and I know why happens but I'm not capable to fix this. – Jose Jul 31 '16 at 17:21
  • The function returns the headers as a Unicode string (which, in effect, means that every other byte is zero). You interpret it as an ASCII string, stopping at the very first zero byte. The documentation for `WinHttpQueryHeaders` shows an example of using it; observe specifically how it works with a buffer of `WCHAR`s (as opposed to `char`s). – Igor Tandetnik Jul 31 '16 at 17:30