I added awxStaticBitmap on my form made by wxFormBuilder:
show_image = new wxStaticBitmap( this, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxDefaultSize, 0 );
How can I show an Internet-bases image on it using C++ and Curl? For example, an image like this one:
https://www.google.com/images/srpr/logo4w.png
#include <string>
#include <iostream>
#include <wx/string.h>
#include <wx/image.h>
#include <curl/curl.h>
struct MemoryStruct {
char *memory;
size_t read_pos;
size_t size;
};
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
register int realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory) {
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
wxImage *DownloadImage(string image_url)
{
wxImage *pImg = NULL;
struct MemoryStruct chunk;
CURL* curlCtx = curl_easy_init();
curl_easy_setopt(curlCtx, CURLOPT_URL, image_url.c_str());
curl_easy_setopt(curlCtx, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curlCtx, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curlCtx, CURLOPT_FOLLOWLOCATION, 1);
chunk.memory=NULL;
chunk.size = 0;
CURLcode rc = curl_easy_perform(curlCtx);
if (rc)
{
printf("!!! Failed to download\n");
}
wxMemoryInputStream *memin = new wxMemoryInputStream(chunk.memory, chunk.size);
if((pImg = new wxImage()) != NULL){
if(!pImg->LoadFile(*memin, wxBITMAP_TYPE_JPEG)){
delete pImg;
pImg = NULL;
}
}
curl_easy_cleanup(curlCtx);
return pImg;
}
wxImage imagewx = *DownloadImage("https://www.google.com/images/srpr/logo4w.png");
if(imagewx.IsOk()){
show_image->SetBitmap(wxBitmap(imagewx));
}
I'm not sure thats the right way,but it works for me
Related
I am trying to download/(and later upload it again) a json file from a ftp server(provider: bplaced.net) into memory using LibCurl, but im getting an error.
Please don't be to harsh im pretty new to this. Also feel free to improve my code thanks :p
Memory methods:
struct MemoryStruct {
char* memory;
size_t size;
};
static size_t
WriteMemoryCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct* mem = (struct MemoryStruct*)userp;
char* ptr = (char*)realloc(mem->memory, mem->size + realsize + 1);
if (ptr == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
Download Method:
std::string getFTPFileMem() {
CURL* curl;
CURLcode res;
std::string memory;
struct MemoryStruct chunk;
chunk.memory = (char*)malloc(1); /* will be grown as needed by the realloc above */
chunk.size = 0; /* no data at this point */
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL,
"ftp://user:pass#host/jsonLocation/Json.json");
/* send all data to this function */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
/* we pass our 'chunk' struct to the callback function */
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&chunk);
/* We activate SSL and we require it for both control and data */
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
/* Switch on full protocol/debug output */
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
memory = chunk.memory;
/* always cleanup */
curl_easy_cleanup(curl);
if (CURLE_OK != res) {
/* we failed */
fprintf(stderr, "curl told us %d\n", res);
}
}
free(chunk.memory);
/* we're done with libcurl, so clean it up */
curl_global_cleanup();
return memory;
}
int main() {
std::cout << getFTPFileMem() << "\n";
}
FTP certificate issue:
EDIT: After running a few more commands, it seems that only lines starting with * are being shown. Any way to stop that?
I'm trying to use the libcurl library with my C++ program to recieve emails using the IMAP protocol. The issue is that the response from the CURL calls are only returning one line, and cutting off the rest of what is supposed to be returned. I know that the request itself is working because when I turn on verbose mode with curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);, it has the full result within the output.
For example, when I use curl_easy_setopt(curl, "FETCH 10000 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])"); the response is:
* 10000 FETCH (FLAGS (\Seen) BODY[HEADER.FIELDS (DATE FROM SUBJECT)] {140}
When I turn on verbose mode, the console includes the full result:
< A003 OK [READ-WRITE] INBOX selected. (Success)
> A004 FETCH 10000 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])
< * 10000 FETCH (FLAGS (\Seen) BODY[HEADER.FIELDS (DATE FROM SUBJECT)] {140}
< Date: Wed, 1 Apr 2020 01:59:45 -0500
< From: [REMOVED NAME] <[REMOVED EMAIL]>
< Subject: Testing subject here
<
< )
< A004 OK Success
I have tried multiple ways of outputting the data: to stdout, an external file, and in memory (then printed). I feel like the CURL result just isn't returning more than the first line for some reason. Here is the code if it helps (I'm using wxWidgets):
App.cpp - Ignore most of this, just calls the functions
#include "App.h"
#include "Frame.h"
#include "Config.h"
#include "IMAP.h"
wxIMPLEMENT_APP(App);
bool App::OnInit() {
curl_global_init(CURL_GLOBAL_SSL);
try {
Config config("settings.conf");
for(const auto& account : config["accounts"]) {
const char* url = account["incoming_server"].asCString();
const char* username = account["username"].asCString();
const char* password = account["password"].asCString();
IMAP connection(url, IMAP_DEFAULT_PORT);
if(connection.auth(username, password) == IMAP_SUCCESS) {
connection.select("INBOX");
auto folders = connection.getFolders();
}
}
} catch(std::exception& e) {
std::cerr << e.what() << std::endl;
exit(0);
}
curl_global_cleanup();
exit(1);
Frame *frame = new Frame("MailDuck", wxDefaultPosition, wxSize(100, 100));
frame->Show(true);
frame->Centre();
return true;
}
App.cpp
#include "IMAP.h"
IMAP::IMAP(const char *url, int port) {
this->url = url;
this->port = port;
}
IMAP_CODE IMAP::auth(const char *username, const char *password) {
this->username = username;
this->password = password;
if(execute().size == -1) return IMAP_FAILED;
else return IMAP_SUCCESS;
}
std::vector<Folder> IMAP::getFolders() {
std::vector<Folder> folders;
memory mem = execute("FETCH 10000 (FLAGS BODY[HEADER.FIELDS (DATE FROM SUBJECT)])");
std::cout << mem.response << std::endl;
free(mem.response);
return folders;
}
IMAP::memory IMAP::execute(const char *command) {
CURL *curl;
CURLcode res = CURLE_OK;
struct memory chunk { (char *) malloc(1), 0 };
curl = curl_easy_init();
std::string finalURL;
finalURL.append(this->url);
finalURL.append("/");
finalURL.append(this->mailbox);
if(curl) {
curl_easy_setopt(curl, CURLOPT_USE_SSL, CURLUSESSL_ALL);
curl_easy_setopt(curl, CURLOPT_USERNAME, this->username);
curl_easy_setopt(curl, CURLOPT_PASSWORD, this->password);
curl_easy_setopt(curl, CURLOPT_URL, finalURL.c_str());
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_function);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, command);
res = curl_easy_perform(curl);
if(res != CURLE_OK) chunk.size = -1;
curl_easy_cleanup(curl);
} else chunk.size = -1;
if(chunk.size == -1) std::cerr << "ERROR >> Unable to call command: " << command << std::endl;
return chunk;
}
size_t IMAP::write_function(void *data, size_t size, size_t nmemb, void *userp) {
size_t real_size = size * nmemb;
auto *mem = (struct memory *) userp;
char *ptr = (char *) realloc(mem->response, mem->size + real_size + 1);
if(ptr == NULL) return 0;
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, real_size);
mem->size += real_size;
mem->response[mem->size] = 0;
return real_size;
}
void IMAP::select(const char *box) {
this->mailbox = box;
}
IMAP.h
#ifndef MAILDUCK_IMAP_H
#define MAILDUCK_IMAP_H
#include <map>
#include <vector>
#include <string>
#include <json/json.h>
#include <curl/curl.h>
#include <iostream>
#include <istream>
enum {
IMAP_DEFAULT_PORT = 993,
};
enum IMAP_CODE {
IMAP_SUCCESS = 1,
IMAP_FAILED = 0
};
class Folder : public std::vector<Folder> {
public:
std::string name;
};
class IMAP {
private:
const char *url, *username, *password, *mailbox = "";
int port;
struct memory { char *response; size_t size; };
memory execute(const char *command = nullptr);
static size_t write_function(void *data, size_t size, size_t nmemb, void *userp);
public:
IMAP(const char *url, int port);
IMAP_CODE auth(const char* username, const char* password);
std::vector<Folder> getFolders();
void select(const char *mailbox);
};
#endif
I've been stuck on this for a bit, so I appreciate any insight anyone could provide.
Figured it out! For all who get stuck like me:
Apparently the rest of the data is stuck in the header data, so add this:
struct memory chunk { (char *) malloc(1), 0 };
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, (void *)&chunk);
And then my write function is exactly like the other one...
size_t IMAP::header_callback(char *data, size_t size, size_t nmemb, void *userp) {
size_t real_size = size * nmemb;
auto *mem = (struct memory *) userp;
char *ptr = (char *) realloc(mem->response, mem->size + real_size + 1);
if(ptr == NULL) return 0;
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, real_size);
mem->size += real_size;
mem->response[mem->size] = 0;
return real_size;
}
Now I'm getting the full response.
I am sorry for my bad English.
I am trying to run the following code but it crashes when the progress run about one day or several hours, so this crash is come up by accident.
By the way , The SecMonitor_Curl is a single Class, so curl_global_init() run only one time global.
I can not resolve this question, so I don't know what wrong with my program . Please help me. thanks!
SecMonitor_Curl::SecMonitor_Curl()
{
curl_global_init(CURL_GLOBAL_ALL);
}
SecMonitor_Curl::~SecMonitor_Curl()
{
curl_global_cleanup();
}
static size_t write_to_string(void *ptr, size_t size, size_t nmemb, void *stream) {
((std::string*)stream)->append((char*)ptr, 0, size*nmemb);
return size * nmemb;
}
int SecMonitor_Curl::http_get(const std::string url, const std::string method, const std::map<std::string, std::string>& params, std::string post_data, std::string& response)
{
int ret = 0;
CURLcode res;
curl_ = curl_easy_init();
if (curl_ == NULL)
{
return -1;
}
if(curl_)
{
url_t = "www.google.com";
method = "POST";
post_body="{"test":"test"}";
res = curl_easy_setopt(curl_, CURLOPT_URL, url_t.c_str());
if (method == "POST" || method == "PUT" || method == "DELETE")
{
curl_easy_setopt(curl_, CURLOPT_CUSTOMREQUEST, method.c_str());
curl_easy_setopt(curl_, CURLOPT_POSTFIELDS, post_body.c_str());
curl_easy_setopt(curl_, CURLOPT_POSTFIELDSIZE, post_body.size());
}
res = curl_easy_setopt(curl_, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_setopt(curl_, CURLOPT_NOSIGNAL, 1L);
res = curl_easy_setopt(curl_, CURLOPT_ACCEPT_ENCODING, "deflate");
std::string out;
res = curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, write_to_string);
res = curl_easy_setopt(curl_, CURLOPT_WRITEDATA, &out);
//printf("curl_version : %s ",curl_version());
res = curl_easy_perform(curl_);
/* Check for errors */
if (res != CURLE_OK) {
srlog_error("SecMonitor_Curl | curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
ret = -1;
}
response = out;
}
else
{
ret = -1;
}
curl_easy_cleanup(curl_);
return ret;
}
This is the dump file :
Program terminated with signal 11, Segmentation fault.
#0 _IO_fwrite (buf=0x7f16a31dba70, size=2, count=1, fp=0x0) at iofwrite.c:43
43 iofwrite.c: No such file or directory.
in iofwrite.c
(gdb) bt
#0 _IO_fwrite (buf=0x7f16a31dba70, size=2, count=1, fp=0x0) at iofwrite.c:43
#1 0x00007f16a31aef93 in ?? () from /usr/lib64/libcurl.so.4
#2 0x00007f16a31af0c0 in Curl_debug () from /usr/lib64/libcurl.so.4
#3 0x00007f16a31afd69 in Curl_infof () from /usr/lib64/libcurl.so.4
#4 0x00007f16a31b55f4 in Curl_protocol_connect () from /usr/lib64/libcurl.so.4
#5 0x00007f16a31bbb0c in Curl_connect () from /usr/lib64/libcurl.so.4
#6 0x00007f16a31c3a90 in Curl_perform () from /usr/lib64/libcurl.so.4
#7 0x0000000000437a10 in SecMonitor_Curl::http_get (this=0x11e2db8, url=
"http://dip.alibaba-inc.com/api/v2/services/schema/mock/61919?spm=a312q.7764190.0.0.40e80cf75fUogt", method="POST", params=std::map with 5 elements = {...}, post_data="", response="")
at /home/albert.yb/secMonitorAgent/secMonitor/monitor/server/SecMonitor/SecMonitor_Curl.cpp:131
#8 0x0000000000435ab0 in SecMonitor_Cmd::run_cmd (this=0x11eeef8, cmd_name="update")
SecMonitor_Curl.cpp:131 : means curl_easy_perform().
Thanks
I collected 3 write_to_string callback function:
First :
static size_t write_to_string(void *ptr, size_t size, size_t nmemb, void *stream) {
((std::string*)stream)->append((const char*)ptr, size*nmemb);
return size * nmemb;
}
Second:
static size_t write_to_string(void *contents, size_t size, size_t nmemb, std::string *s)
{
size_t newLength = size*nmemb;
size_t oldLength = s->size();
try
{
s->resize(oldLength + newLength);
}
catch(std::bad_alloc &e)
{
//handle memory problem
return 0;
}
std::copy((char*)contents,(char*)contents+newLength,s->begin()+oldLength);
return size*nmemb;
}
Third:
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t
write_to_string(void *contents, size_t size, size_t nmemb, void *userp)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)userp;
mem->memory = realloc(mem->memory, mem->size + realsize + 1);
if(mem->memory == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
return 0;
}
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
These callback method can deal with this thing of output the curl response to String . But this problem is no in here, all crash because "crul_" which is the member variable of this class. when the function of "http_get" is quoting by multi thread , the crash must be happend.
I am having some issue getting an image into a dynamic memory buffer with cURL.
The bit of code used is the following:
struct memoryStruct {
char *memory;
size_t size;
};
static void* CURL_realloc(void *ptr, size_t size)
{
/* There might be a realloc() out there that doesn't like reallocing
NULL pointers, so we take care of it here */
if(ptr)
return realloc(ptr, size);
else
return malloc(size);
}
size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t realsize = size * nmemb;
struct memoryStruct *mem = (struct memoryStruct *)data;
mem->memory = (char *)CURL_realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory)
{
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
}
return realsize;
}
int main()
{
std::string everything = "https://upload.wikimedia.org/wikipedia/commons/1/1e/Stonehenge.jpg";
CURL *curl; // CURL objects
CURLcode res;
memoryStruct buffer; // memory buffer
curl = curl_easy_init(); // init CURL library object/structure
if(curl) {
// set up the write to memory buffer
// (buffer starts off empty)
buffer.memory = NULL;
buffer.size = 0;
// (N.B. check this URL still works in browser in case image has moved)
curl_easy_setopt(curl, CURLOPT_URL, everything);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); // tell us what is happening
// tell libcurl where to write the image (to a dynamic memory buffer)
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl,CURLOPT_WRITEDATA, (void *) &buffer);
// get the image from the specified URL
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
free(buffer.memory);
}
return 0;
}
As an error output I get the error saying the following:
I am however not sure to understand the error being displayed. My guess is that I should enable IDN support for curl? I am however not sure on how to proceed. Does that mean that I would have to recompile the library with IDN enabled? (If I find how to do it)
Thank you for your help
You're passing an std::string object to curl_easy_setopt, while you should be passing a C string. It's actually trying to resolve god-knows-what.
curl_easy_setopt(curl, CURLOPT_URL, everything.c_str());
I've created a PHP and C# app that gets the users Xbox 360 Profile ID from their gamertag.
I was just wondering how I do a web request and put the page contents of the url into a string in C++.
Thanks.
Here's a down-and-dirty C++ HTTP fetcher I wrote using libCURL some time back.
It takes a URL and returns a string with the contents of a get request. Modify and flavor to taste:
/*
* HttpFetcher.h
*/
#ifndef _http_fetcher_
#define _http_fetcher_
#include <stdlib.h>
#include <string>
class HttpFetcher {
public:
std::string simpleGetRequest(std::string url);
private:
// Private methods to handle getting
struct MemoryStruct {
char *memory;
size_t size;
};
static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);
};
#endif // ifndef _http_fetcher_
/*
* HttpFetcher.cpp
* Much of this is quite similar to examples on the libcURL site
*/
#include "HttpFetcher.h"
#include "curl.h"
#include "easy.h"
#include <iostream>
size_t HttpFetcher::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data)
{
size_t realsize = size * nmemb;
struct MemoryStruct *mem = (struct MemoryStruct *)data;
mem->memory = (char*)realloc(mem->memory, mem->size + realsize + 1);
if (mem->memory == NULL) {
/* out of memory! */
printf("not enough memory (realloc returned NULL)\n");
exit(EXIT_FAILURE);
}
memcpy(&(mem->memory[mem->size]), ptr, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}
std::string HttpFetcher::simpleGetRequest(std::string url)
{
std::string toReturn = "";
CURL *curl = NULL;
struct MemoryStruct chunk;
chunk.memory = (char*)malloc(1);
chunk.size = 0;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)&chunk);
// Some requests fail without a user agent.
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
toReturn = std::string(chunk.memory);
}
free(chunk.memory);
return toReturn;
}