libcurl uninitialized variable curl error - c++

I am trying to make a HTTP Request to retrieve some JSON data; I get the error that curl variable is not initialized though I easy_init() it. Any help on how to go around this error would be very kind!!
Below is my code:
#pragma once
#include "stdafx.h"
#include "RequestJson.h"
#include <string.h>
#include <include/curl/curl.h>
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
class RequestJson
{
public:
static std::string RequestJsonString(std::string URL)
{
//set to get the JSON Response on listed loans; open a CSV file and read unemployment and other indices.
::CURL *curl;
CURLcode res;
struct curl_slist *headers = NULL;
std::ostringstream oss;
//curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
curl_slist_append(headers, "Accept: application/json");
curl_slist_append(headers, "Content-Type: application/json");
curl_easy_cleanup(curl);
if (curl)
{
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, URL.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer); //define a write-function below.
res = curl_easy_perform(curl);
if (CURLE_OK == res)
{
char *ct;
res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct);
if ((CURLE_OK == res) && ct)
{
return *DownloadedResponse;
}
}
}
}
//parse the JSON String and return the downloaded string.
static std::string *DownloadedResponse;
static int writer(char *data, size_t size, size_t nmemb, std::string *buffer_in)
{
if (buffer_in != NULL)
{
buffer_in->append(data, size * nmemb);
DownloadedResponse = buffer_in;
return size * nmemb;
}
return 0;
}
};

From the curl_easy_cleanup reference:
This function must be the last function to call for an easy session. It is the opposite of the curl_easy_init function and must be called with the same handle as input that a curl_easy_init call returned.
[Emphasis mine]
When you call curl_easy_cleanup it cleans up all resources allocated by curl_easy_init. After that you can't use the CURL pointer any more.
As the reference says: Put it last, when you're done.

Related

Store the result from curl get request for use in another function C++

Trying to store the data out of the function and use it for another function from res variable, but still to no avail.
Been able to extract the data from the website and looks like this:
Approximate: 19879888
#include <stdio.h>
#include <iostream>
using namespace std;
#define CURL_STATICLIB
#include <curl/curl.h>
int main()
{
CURLcode res;
CURL* curl = curl_easy_init();
struct curl_slist* header = NULL;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "website for c++ practice");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
return 0;
}
Been searching a lot already but cant find a direct answer. Help would be greatly appreciated!
Use the CURLOPT_WRITEFUNCTION and CURLOPT_WRITEDATA options to save the content to a variable, eg:
#include <iostream>
#include <string>
using namespace std;
#define CURL_STATICLIB
#include <curl/curl.h>
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata)
{
size_t total = size * nmemb;
static_cast<string*>(userdata)->append(ptr, total);
return total;
}
int main()
{
CURL* curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "website for c++ practice");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
string data;
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
CURLcode res = curl_easy_perform(curl);
// use res and data as needed...
curl_easy_cleanup(curl);
}
return 0;
}

Getting cURL JSON response C++

I would like to know how to get a JSON response with cURL. My current code doesn't work, it just returns an empty string. Any help would be greatly appreciated! I've included my current code below.
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
int ipCheck(std::string ip)
{
nlohmann::json j;
CURL* curl;
CURLcode res;
std::string response;
struct curl_slist* headers = NULL;
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://api.ipstack.com/" + ip + "?access_key=SECRET_KEY");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
if (response.empty()) {
std::cout << "\n\nInvalid request!";
_getch();
}
std::cout << response;
}
you have an error here :
curl_easy_setopt(curl, CURLOPT_WRITEDATA, response);
you are passing a temporary copy of std::string here instead of a pointer to the variable you expect to be passed to the callback so the original variable isn't touched ! worse : the callback is passed a dangling pointer which is the casted to std::string and operated on (undefined behavior) so expect to see strange things (usually crash)

How to rewrite POST request from python to C++ with curl

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

Libcurl Image Upload Post from memory

I am writing a program that pulls an image from a restful server that is delivered in JSON, parsed, processed and sent back to the server. I am having issues on sending the image back. Currently I have it stored in a string and am trying to use CURLFORM_BUFFER to send it back. I have confirmed that the image is in the string by writing it to file. No problems there. My current code is below. I am currently experiencing a seg fault 11 on the post. My code is below.
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "dist/jsoncpp.cpp"
#include "dist/json/json.h"
using namespace std;
static size_t write_data(void *contents, size_t size, size_t nmemb,
void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
void uploadImage(std::string readBuffer){
CURL *curl;
CURLcode res;
struct curl_httppost *formpost=NULL;
struct curl_httppost *lastptr=NULL;
struct curl_slist *headerlist=NULL;
static const char buf[] = "Expect:";
curl_global_init(CURL_GLOBAL_ALL);
printf("Image length: %d\n\n", readBuffer.length());
CURLFORMcode code = curl_formadd(&formpost,
&lastptr,
CURLFORM_COPYNAME, "processedImage",
CURLFORM_BUFFER, "image.jpg",
CURLFORM_BUFFERPTR, readBuffer,
//CURLFORM_BUFFERLENGTH, readBuffer.length(),
CURLFORM_END);
if(code != 0){
printf("Something went wrong in formadd.\n");
}
curl = curl_easy_init();
/* initialize custom header list (stating that Expect: 100-continue is not
wanted */
headerlist = curl_slist_append(headerlist, buf);
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "uploadProcessedImageURL");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, formpost);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
/* free slist */
curl_slist_free_all (headerlist);
}
}
int main(void)
{
CURL *curl;
CURLcode res;
const cv::_InputArray data;
std::string readBuffer;
char *url = "requestImageFileURL";
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
readBuffer.clear();
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
//printf("%s\n\n", readBuffer.c_str());
printf("Image retrieved.\n");
Json::Value values;
Json::Reader reader;
reader.parse(readBuffer, values);
Json::Value imageArray = values.get("userUploadedImage","default
value");
Json::Value idNumber = values.get("id","default value");
Json::FastWriter fastWriter;
std::string output = fastWriter.write(imageArray);
//cout << output << endl;
std::vector<char> vectordata(output.begin(), output.end());
//for (auto i = vectordata.begin(); i != vectordata.end(); ++i)
//std::cout << *i;
cv::Mat data_mat(vectordata,true);
cv::Mat image(cv::imdecode(data_mat, 1));
std::cout<<"Height: " << image.rows <<" Width: "<<image.cols<<endl;
//cv::namedWindow( "Display Image", CV_WINDOW_AUTOSIZE );
//cv::imshow( "Display Image",image);
//cv::waitKey(0);
uploadImage(readBuffer);
return 0;
}

Sending post request with libcurl

I am trying to login to Twitter via CURL.
This is my code:
#include <iostream>
#include <string>
#include <curl\curl.h>
#include <sstream>
using std::string;
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
std::string buf = std::string(static_cast<char *>(ptr), size * nmemb);
std::stringstream *response = static_cast<std::stringstream *>(stream);
response->write(buf.c_str(), (std::streamsize)buf.size());
return size * nmemb;
}
int main(int argc, char*argv[])
{
std::string target = "https://twitter.com/login";
CURL *curl;
CURLcode res;
std::stringstream response;
char* data = "session[username_or_email]=user&session[password]=pass";
struct curl_slist *chunk = NULL;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, target.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322)");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, false);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, true);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
curl_global_cleanup();
}
std::cout << response.str() << std::endl;
cin.ignore();
return 0;
}
And I'm getting this message:
403 Forbidden: The server understood the request, but is refusing to
fulfill it
What should I do?
I suggest your request is (correctly) being identified as coming from a program not a human, and therefore denied.
It will be a matter of capturing all the right headers and cookies from a "real" (ie browser) session... But really, I think you'd be better off working with the Twitter api, as that is what it's designed for.