Sure I am missing something obvious, but trying to make a curl get request and return the response to a variable.
size_t write_to_string(void *ptr, size_t size, size_t nmemb, std::string stream){
size_t realsize = size * nmemb;
std::string temp(static_cast<const char*>(ptr), realsize);
cout << temp << endl;
return realsize;
}
CURLcode curl_get(const std::string& url, std::ostream& os, long timeout = 30){
CURLcode code(CURLE_FAILED_INIT);
CURL* curl = curl_easy_init();
string *response;
if (curl){
if (CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_to_string))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FILE, &os))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, response))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str())))
{
code = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
}
std::string a = *response;
return code;
}
response is always either null or an out of bounds pointer from the dozen ways I have tried. The cout does show the correct response.
All I am trying to do is create a generic function for all curl get calls and have it return the get data. New to c, so sorry if I am overlooking something simple.
You declare write_to_string to accept std::string but you pass it a pointer to std::string (via CURLOPT_WRITEDATA).
You don't do anything with std::string stream in write_to_string.
You declare response as a std::string* but do not initialize it, so you have dangling pointer.
Related
I have POST request on python with a lot of settings, and I don't uderstand how their look like in curl.
data_str = '{' + '"username": "{}", "domain_id": {}, "password": {}'.format(login, domain_id, password) + '}'
try:
data = requests.post("https://example.com/v/session",
proxies=proxy,
verify=False,
data=data_str,
headers={"Content-Type": "application/json;charset=UTF-8",
"Accept": "application/json"})
if is_json(data.text):
print(data)
I find that url set parament CURLOPT_URL, headers - CURLOPT_HTTPHEADER. But how set proxy, verify, data ? How get json as in python ?
how to complete the code that it have the same result as in python:
CURL *curl = curl_easy_init();
struct curl_slist *list = NULL;
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
list = curl_slist_append(list, "Shoesize: 10");
list = curl_slist_append(list, "Accept:");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);
curl_easy_perform(curl);
curl_slist_free_all(list); /* free the list again */
}
In order to get the return data from the curl request, we need a callback function for the CURLOPT_WRITEFUNCTION option.
The proxy, data, verify parameters should be set as following :
#include <iostream>
#include <string>
#include <curl/curl.h>
size_t curlWriter(void *contents, size_t size, size_t nmemb, std::string *s)
{
size_t newLength = size*nmemb;
try
{
s->append((char*)contents, newLength);
}
catch(std::bad_alloc &e)
{
//memory problem
return 0;
}
return newLength;
}
int main()
{
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl)
{
std::string strResponse;
std::string strPostData = "my data post";
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/v/session");
curl_easy_setopt (curl, CURLOPT_VERBOSE, 1L);
//set the proxy
curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.net");
curl_easy_setopt(curl, CURLOPT_PROXYPORT, 8080L);
//verify=False. SSL checking disabled
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
//set the callback function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, curlWriter);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &strResponse);
/* size of the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strPostData.length() );
/* pass in a pointer to the data - libcurl will not copy */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strPostData.c_str() );
/* Execute the request */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
{
std::cerr << "CURL error : " << curl_easy_strerror(res) << std::endl;
}else {
std::cout << "CURL result : " << strResponse << std::endl;
}
curl_easy_cleanup(curl);
}
}
I am trying to downloading a lot of files from a website. I am recursively going from page to page and extract link from there. And after I downloaded
543 files (I've tried several times and the number is always the same),
I got a error code 2, which refers to CURLE_FAILED_INIT.
Piece of code, which downloaded a file (copy-paste from one of the tutorial):
CURLcode curl_read(const std::string& url, std::string& buffer, long timeout = 30) {
CURLcode code(CURLE_FAILED_INIT);
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if(curl) {
if(CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str()))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, string_write))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout))) {
code = curl_easy_perform(curl);
}
else {
std::cout << "Error inside setting curl" << std::endl;
}
curl_easy_cleanup(curl);
}
else {
std::cout << "Error inside curl_easy_init" << std::endl;
}
return code;
}
Before this code run, I called
curl_global_init(CURL_GLOBAL_ALL);
I have this piece of code which sends email via libcurl
#define FROM "<my#gmail.com>"
#define TO "<your#gmail.com>"
static const char *payload_text[] = {
"To: " TO "\r\n",
"From: " FROM "\r\n",
"Subject: Shift\r\n",
"text\r\n",
NULL
};
struct upload_status {
int lines_read;
};
static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct upload_status *upload_ctx = (struct upload_status *)userp;
const char *data;
if((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}
data = payload_text[upload_ctx->lines_read];
if(data) {
size_t len = strlen(data);
memcpy(ptr, data, len);
upload_ctx->lines_read++;
return len;
}
return 0;
}
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct curl_slist *recipients = NULL;
struct upload_status upload_ctx;
upload_ctx.lines_read = 0;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_USERNAME, "my#gmail.com");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "pass");
curl_easy_setopt(curl, CURLOPT_URL, "smtp://smtp.gmail.com:587");
curl_easy_setopt(curl, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL);
curl_easy_setopt(curl, CURLOPT_CAINFO, "google.pem");
curl_easy_setopt(curl, CURLOPT_MAIL_FROM, FROM);
recipients = curl_slist_append(recipients, TO);
//curl_easy_setopt(curl, CURLOPT_FILE, "edgE0DF.tmp");
curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, recipients);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(curl, CURLOPT_READDATA, &upload_ctx);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
curl_slist_free_all(recipients);
curl_easy_cleanup(curl);
}
return 0;
}
My question is: how can I make a function which takes as arguments from and to and change my global FROM and TO? Is this possible? Because, I know that global variables are initialized before other parts of code and this means that my static const char *payload_text[] that uses FROM and TO will be initialized with wrong addresses.
When i put this code in main and put it static it works fine but when i separate them to another class. This problem comes out. Does anybody know why?
#ifndef __PathToExile__ConnectHandler__
#define __PathToExile__ConnectHandler__
#include <curl/curl.h>
#include <fstream>
#include <sstream>
#include <iostream>
using namespace std;
class ConnectHandler{
public:
ConnectHandler();
size_t data_write(void* buf, size_t size, size_t nmemb, void* userp);
CURLcode curl_read(const std::string& url, std::ostream& os, long timeout = 30);
void writeWebToFile(std::string filename);
};
#endif /* defined(__PathToExile__ConnectHandler__) */
#include "ConnectHandler.h"
ConnectHandler::ConnectHandler(){
curl_global_init(CURL_GLOBAL_ALL);
}
size_t ConnectHandler::data_write(void* buf, size_t size, size_t nmemb, void* userp)
{
if(userp)
{
std::ostream& os = *static_cast<std::ostream*>(userp);
std::streamsize len = size * nmemb;
if(os.write(static_cast<char*>(buf), len)) //EROR: Thread 1: Exe_Bad_access (code = 1, address = 0x10)
return len;
}
return 0;
}
CURLcode ConnectHandler::curl_read(const std::string& url, std::ostream& os, long timeout)
{
CURLcode code(CURLE_FAILED_INIT);
CURL* curl = curl_easy_init();
if(curl)
{
if(CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &ConnectHandler::data_write))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FILE, &os))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str())))
{
code = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
}
return code;
}
void ConnectHandler::writeWebToFile(std::string filename){
std::ofstream ofs(filename);
if(CURLE_OK == ConnectHandler::curl_read("http://www.google.com", ofs))
{
std::cout << "Successfully write web to file " << filename << std::endl;
}
}
So in the main file i call it like normal:
Connecthandler c()
c.writeWebToFile("haha-masupilami.txt")
the problem occur at function size_t data_write(..) i already comment the line problem occur. Does anybody know what went wrong. 'Cause it works file when i put i static function in main file.
I'm trying to fetch website source using C++ and libcurl in Qt 4.8. I'm new to Qt and C++.
However, Im getting an error message
Error Message -
Starting C:*****.exe...
The program has unexpectedly finished.
C:*****.exe exited with code -1073741819
#include <curl/include/curl/curl.h>
#include <fstream>
#include <sstream>
#include <iostream>
static size_t data_write(void* buf, size_t size, size_t nmemb, void* userp)
{
if(userp)
{
std::ostream& os = *static_cast<std::ostream*>(userp);
std::streamsize len = size * nmemb;
if(os.write(static_cast<char*>(buf), len))
return len;
}
return 0;
}
CURLcode curl_read(const std::string& url, std::ostream& os, long timeout = 30)
{
CURLcode code(CURLE_FAILED_INIT);
CURL* curl = curl_easy_init();
if(curl)
{
if(CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &data_write))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_FILE, &os))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout))
&& CURLE_OK == (code = curl_easy_setopt(curl, CURLOPT_URL, url.c_str())))
{
code = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
}
return code;
}
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
if(CURLE_OK == curl_read("http://google.com", std::cout))
{
// Web page successfully written to standard output (console?)
}
curl_global_cleanup();
return 0;
}
Whats the problem with the code above ?
P.S - Above code is not mine.
Don't bother using external libraries use what Qt has got. And it has plenty !
Here is a simple exemple on how you can get a webpage source!
void MainWindow::on_pushButton_clicked()
{
QNetworkAccessManager * mgr = new QNetworkAccessManager(this);
connect(mgr,SIGNAL(finished(QNetworkReply*)),this,SLOT(onfinish(QNetworkReply*)));
connect(mgr,SIGNAL(finished(QNetworkReply*)),mgr,SLOT(deleteLater()));
mgr->get(QNetworkRequest(QUrl("http://www.google.com")));
}
void MainWindow::onfinish(QNetworkReply *rep)
{
QByteArray bts = rep->readAll();
QString str(bts);
QMessageBox::information(this,"sal",str,"ok");
}
And if you want to create a blocking function check out this tutorial over here.
Hope it helps!