I want to extract specific values from a string in C++ - c++

I have a program that returns a long string from a curl request, the code is as follows:
#include <iostream>
#include <string>
#include <curl/curl.h>
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 main(void)
{
std::string s;
CURL* curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "www.ecobliss.co.za/run_student_query.php?query=Select%20*%20FROM%20data%20WHERE%20ID%20%3C%2030");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
std::cout << s << std::endl;
struct curl_slist* headers = NULL;
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
res = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
//std::cout << s;
std::string arr[10000];
int i = s.find_first_of("ID");
//std::cout << i<<std::endl;
int ic = 0;
while (i>0) {
std::cout << i;
if (i > 0) {
arr[ic] = s.substr(i, i + 6);
s.erase(i,i+1);
int i = s.find_first_of("ID");
std::cout << i;
}
if (i < 0) {
break;
}
ic++;
}
for (ic = 0; ic < std::size(arr); ic++) {
std::cout << arr[ic];
}
return 0;
}
the output of the request in postman is:
<p>Results from your query:</p>
<br>{"ID":"26","datetime":"2022-03-13 03:21:07","temperature":"25.3","humidity":"80.9","pressure":"1020.2"}<br>{"ID":"27","datetime":"2022-03-13 05:12:47","temperature":"24.8","humidity":"82.1","pressure":"1020.5"}<br>{"ID":"28","datetime":"2022-03-13 05:29:05","temperature":"24.9","humidity":"83.6","pressure":"1020.5"}<br>{"ID":"29","datetime":"2022-03-13 05:29:07","temperature":"24.9","humidity":"83.8","pressure":"1020.5"}
I have tried to use string handling and extract the value the ID part holds, but it does not work at all, can someone please help.

Related

function returns empty value for std::String

Using refresh to get the output result from as Flask web server, when the function is executed it prints the result needed to the screen but when it is time to print out it does not print the out value and all you get is an empty line
Why is this happening
size_t CurlWrite_CallbackFunc_StdString(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)
{
//handle memory problem
return 0;
}
return newLength;
}
std::string refresh(std::string path) {
CURL* curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
const char* path_ = path.c_str();
std::string s;
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, path_);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "out=");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
/* 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);
}
std::cout << s << std::endl;
return s;
}
driver code
int main() {
std::string out = refresh(server_path+"/refresh");
std::cout << out << std::endl;
}

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

C++ Libcurl curl_easy_getinfo returns nothing in CURLOPT_XFERINFOFUNCTION-function

I have an application which is using LibCurl to upload files. I'm showing the upload progress with the percentage with the underneath function which works great. However, I can't get the average upload speed (CURLINFO_SPEED_UPLOAD) nor the time elapsed (CURLINFO_TOTAL_TIME) with the curl_easy_getinfo function. What am I doing wrong here? I can't see much differences with the original example from Libcurl?
static int ReceiveFileProgress(void *p, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) {
if (ultotal > 0) {
string Output;
double curtime = 0;
char ulspeed[10000];
double ulspeed_curl = 0;
double ulnow_db = (double)ulnow;
double ultotal_db = (double)ultotal;
double percentage = ceil((ulnow_db / ultotal_db) * 100);
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
if (curl) {
cout << "CURL OK" << endl;
}
else {
cout << "CURL FAILED" << endl;
}
if (percentage != 100) {
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &ulspeed_curl);
}
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &curtime);
readable_fs(ulspeed_curl, ulspeed);
stringstream OutputStream;
OutputStream << percentage;
Output = PadString(OutputStream.str(), 3, " ");
OutputStream.str("");
OutputStream << Output << "%";
if (percentage != 100) {
OutputStream << " (" << ulspeed << "/s)";
}
Output = OutputStream.str();
if (Output.length() > SendOffFileMaxProgressLength) {
Output.substr(0, SendOffFileMaxProgressLength - 3);
Output += "...";
}
else {
while (Output.length() < SendOffFileMaxProgressLength) {
Output += ' ';
}
}
cout << Output << '\r';
}
return 0;
}
The curl request:
string PerformCurlRequest(string RequestType, struct curl_httppost &formpost, struct curl_httppost &lastptr) {
CURL *curl;
CURLcode res;
bool UsedProxy;
string CurlResponse;
int LibCurlError = 0;
int ProxyRetryCount = 1;
bool TryWithProxy = true;
struct curl_slist *LibcurlHeaders = NULL;
curl = curl_easy_init();
if (curl) {
host = "url/";
host += RequestType;
host += "/";
LibcurlHeaders = curl_slist_append(LibcurlHeaders, "Expect:");
curl_easy_setopt(curl, CURLOPT_URL, (host).c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 1);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, LibcurlHeaders);
curl_easy_setopt(curl, CURLOPT_VERBOSE, CurlVerbose);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, LibcurlResponse);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &CurlResponse);
curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, GetCurlVerboseData);
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, ReceiveFileProgress);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &progress);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
res = curl_easy_perform(curl);
curl_slist_free_all(LibcurlHeaders);
curl_easy_cleanup(curl);
}
return CurlResponse;
}
Send off File:
PerformCurlRequest("SendFile", *formpostReceiveFile, *lastptrReceiveFile)
I don't know what libcurl version you're using or if you perhaps mess up your code somewhere else, but I can certainly make CURLINFO_SPEED_UPLOAD from within a libcurl progress callback in this example code doing HTTP "upload" (using a PUT here for simplicity):
#include <stdio.h>
#include <curl/curl.h>
#include <sys/stat.h>
struct myprogress {
CURL *curl;
};
static int xferinfo(void *p, curl_off_t dltotal, curl_off_t dlnow,
curl_off_t ultotal, curl_off_t ulnow)
{
struct myprogress *myp = (struct myprogress *)p;
CURL *curl = myp->curl;
double ulspeed_curl = 0;
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &ulspeed_curl);
fprintf(stderr, "UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
" DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T
" AVRUP: %.1f"
"\r\n",
ulnow, ultotal, dlnow, dltotal, ulspeed_curl);
return 0;
}
/* send off a random test file lying around */
#define FILENAME "file-to-send"
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
struct myprogress prog;
curl = curl_easy_init();
if(curl) {
FILE *strace;
struct stat file_info;
prog.curl = curl;
strace = fopen(FILENAME, "rb");
if(!strace)
return 1;
/* get the file size of the local file */
stat(FILENAME, &file_info);
curl_easy_setopt(curl, CURLOPT_URL, "http://localhost/");
curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, xferinfo);
curl_easy_setopt(curl, CURLOPT_XFERINFODATA, &prog);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)file_info.st_size);
curl_easy_setopt(curl, CURLOPT_READDATA, strace);
res = curl_easy_perform(curl);
if(res != CURLE_OK)
fprintf(stderr, "%s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return (int)res;
}

libcurl always timeout error C++

I am currently using the multi interface API of the libcurl library to send multiple HTTP requests without blocking. My current problem is that I can't send a HTTP request.
For some reason maxfd is always -1 which result in rc always being 0. So when the code get to the switch statement it always print "timeout" because rc is always 0.
I never used the mulit interface before but I used the easy interface a couple of time. Much of the code is very similar to this.
ReqestHandler.cpp
void RequestHandler::add(lua_State* lua, const std::string& url, const std::string& data) {
Request request;
CURL* curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1L);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "RoBot/ Version 1");
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &request.response);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &request.headers);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &request.code);
if (!data.empty()) {
curl_easy_setopt(curl, CURLOPT_POST, true);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, data.size());
}
request.curl = curl;
request.lua = lua;
curl_multi_add_handle(_curlm, curl);
_requests.push_back(request);
}
void RequestHandler::tick() {
if (!_requests.empty()) {
curl_multi_perform(_curlm, &_isRunning);
do {
struct timeval timeout;
int rc;
CURLMcode mc;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd = -1;
long curl_timeo = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
timeout.tv_sec = 1;
timeout.tv_usec = 0;
curl_multi_timeout(_curlm, &curl_timeo);
if (curl_timeo >= 0) {
timeout.tv_sec = curl_timeo / 1000;
if (timeout.tv_sec > 1) {
timeout.tv_sec = 1;
} else {
timeout.tv_usec = (curl_timeo % 1000) * 1000;
}
}
mc = curl_multi_fdset(_curlm, &fdread, &fdwrite, &fdexcep, &maxfd);
if (mc != CURLM_OK) {
throw new Exception("MC error code: " + mc);
break;
}
if (maxfd == -1) {
Sleep(1000);
rc = 0;
} else {
rc = select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
}
switch (rc) {
case -1:
/* select error */
std::cout << "Error" << std::endl;
break;
case 0:
/* timeout */
std::cout << "Timeout" << std::endl;
break;
default:
/* action */
std::cout << "Action" << std::endl;
curl_multi_perform(_curlm, &_isRunning);
break;
}
} while (_isRunning);
while ((_msg = curl_multi_info_read(_curlm, &_msgsLeft))) {
std::cout << "RAN";
if (_msg->msg == CURLMSG_DONE) {
for (unsigned int i = 0; i < _requests.size(); i++) {
Request request = _requests[i];
if (_msg->easy_handle == request.curl) {
std::cout << request.response << std::endl;
break;
}
}
}
}
curl_multi_cleanup(_curlm);
for (unsigned int i = 0; i < _requests.size(); i++) {
curl_easy_cleanup(_requests[i].curl);
_requests.erase(_requests.begin() + i);
}
}
}
RequestHandler.h
#pragma once
#include <string>
#include <vector>
#include "curl\curl.h"
#include "Lua\lua.hpp"
struct Request {
std::string response;
std::string headers;
int code;
CURL* curl;
lua_State* lua;
};
class RequestHandler {
public:
RequestHandler();
~RequestHandler();
static RequestHandler* getInstance();
void add(lua_State* lua, const std::string& url, const std::string& data);
void tick();
private:
static RequestHandler* INSTANCE;
std::vector<Request> _requests;
CURLM* _curlm;
CURLMsg* _msg;
int _isRunning;
int _msgsLeft;
};
Update
As suggested in the comment I used CURLOPT_STDERR and CURLOPT_VERBOSE and nothing printed to the output file.
I added this code within the RequestHandler:add(); function.
#ifdef _DEBUG
FILE* file = fopen("../Logs/Verbose.log", "wb");
curl_easy_setopt(curl, CURLOPT_VERBOSE, true);
curl_easy_setopt(curl, CURLOPT_STDERR, file);
#endif
The file does get created but nothing get written to the file.

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