#include <set>
#include <sstream>
#include "http_request.h"
bool litebrowser::http_request::open()
{
m_canceled = false;
CURL* curl = curl_easy_init();
if(m_url[0] == '/')
{
std::set<char> chars_to_escape = {' ', ':'};
std::stringstream new_url;
new_url << "file://";
for(auto ch : m_url)
{
if( chars_to_escape.find(ch) != chars_to_escape.end())
{
new_url << '%' << std::hex << (uint32_t) ch;
} else
{
new_url << ch;
}
}
m_url = new_url.str();
}
curl_easy_setopt(curl, CURLOPT_URL, m_url.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, (long) 1);
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, (long) 10);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_request::write_function);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, (long) 0);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, (long) 512);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, (long) 30);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, http_request::progress_function);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, this);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) 0);
char errMessage[1024];
errMessage[0] = 0;
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errMessage);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, (long) 1);
if(!m_user_agent.empty())
{
curl_easy_setopt(curl, CURLOPT_USERAGENT, m_user_agent.c_str());
} else
{
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (X11; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0");
}
curl_slist* slist = nullptr;
if (!m_headers.empty())
{
for (auto& item : m_headers)
{
slist = curl_slist_append(slist, item.c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist);
}
std::string post_str;
if (!m_form_data.empty())
{
for (const auto& field : m_form_data)
{
if (!post_str.empty()) post_str += "&";
post_str += field.first;
post_str += "=";
post_str += field.second;
}
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_str.c_str());
}
m_session = curl;
CURLcode res = curl_easy_perform(curl);
long httpCode = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
m_session = nullptr;
curl_easy_cleanup(curl);
if (slist)
{
curl_slist_free_all(slist);
}
m_form_data.clear();
m_headers.clear();
if(m_on_finish)
{
m_on_finish(httpCode, res, errMessage, m_url);
}
return true;
}
size_t litebrowser::http_request::write_function(void *ptr, size_t size, size_t nmemb, void *stream)
{
auto pThis = (http_request*) stream;
pThis->m_downloaded += size * nmemb;
if(!pThis->m_total)
{
curl_off_t sz = 0;
curl_easy_getinfo((CURL*) pThis->m_session, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &sz);
pThis->m_total = (size_t) sz;
}
if(pThis->m_on_data)
{
pThis->m_on_data(ptr, size * nmemb, pThis->m_downloaded, pThis->m_total);
}
return size * nmemb;
}
int litebrowser::http_request::progress_function(void* clientp, curl_off_t , curl_off_t , curl_off_t , curl_off_t )
{
auto pThis = (http_request*) clientp;
return pThis->m_canceled ? 1 : 0;
}