Curl simple https request returns nothing C++ - c++

I'm using Visual Studio C++ 2010 and it's working just fine with cURL but the problem is that https requests returns nothing. instead of showing the output:
#include "StdAfx.h"
#include <stdio.h>
#include <curl/curl.h>
#include <conio.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.com");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
_getch();
return 0;
}
This code for example, it's just a https request to Google, but it returns nothing just because it starts with https. and if I take away the "s" of https, it works just fine: "http://www.google.com.br" shows the result normally. what am I missing here? I'm using the example from the cURL.
I tried with other websites and same thing happened. :/ like https://www.facebook.com
Btw also if you guys know how do I store the webpage content in a string, I would be glad to know.
Thanks in advance. :)

This simple example works for me:
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
/* First set the URL that is about to receive our POST. This URL can
just as well be a https:// URL if that is what should receive the
data. */
curl_easy_setopt(curl, CURLOPT_URL, "https://www.google.co.uk");
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
I got the source code and built the library long time ago but I'm sure I enabled the SSL support before compiling the sources. Make sure you have OpenSSL installed and (in case you're working under Linux) you have the PKG_CONFIG_PATH variable initialized properly. These are two options you specify when executing the configure script.
--with-ssl=PATH Where to look for OpenSSL, PATH points to the SSL
installation (default: /usr/local/ssl); when
possible, set the PKG_CONFIG_PATH environment
variable instead of using this option
--without-ssl disable OpenSSL
I hope it helps.
If you're using Windows, this post can be also useful for you:
Building libcurl with SSL support on Windows

Related

How to send a request to the WooCommerce API

I'm currently building a solution for a company as an intern, and I need to use the WooCommerce REST API features in my C++ project to send data to the website.
I've so far, after 2 long painful days, managed to install the cURL library (through vcpkg) and tested the library a bit with the many examples that you can find on the internet. But for now, what I found doesn't seem to match with what the people at WooCommerce put in their documentation.
For example, in this section, they show how to create a product on the platform using cURL, but I can't understand how to translate it in cURL language inside the C++ project. Heck, the command doesn't even work when I use it in the command prompt with my parameters.
#include <curl/curl.h>
#include <string>
// cUrl declaration
CURL* curl;
CURLcode res;
std::string readBuffer;
std::string URL = "http://www.example.com";
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, URL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
res = curl_easy_perform(curl);
// Check for errors
if (res != CURLE_OK) {
std::string error = "curl_easy_perform() failed: ";
error += curl_easy_strerror(res);
error += "\nImpossible de se connecter au site WooCommerce fourni. Veuillez verifier vos paramètres et redémarrer l'application.";
wxMessageBox(error);
}
else {
std::string success = "Connexion au domaine ";
success += URL;
success += " réussie.\nPour changer de domaine, veuillez consulter la page Paramètres.";
wxMessageBox(success);
}
}
// cleanup
curl_easy_cleanup(curl);
curl_global_cleanup();
This code works fine, I know that I have to add the company's website instead of the example, but I can't figure out where to add my client key and client secret (basically like in the example shown on the WooCommerce doc). The basic cURL commands work fine in my local command prompt, but the example doesn't event work.
I know that my request for help may be kind of basic and easy to solve but I just spent the last 2 days and a half working on this and I'm starting to lose it.
Thanks for your help, I tried to speak the best english I could, so sorry in advance for any typo, or sorry if my post doesn't live up to the presentation standards of this platform, I'm kinda new around here :D
Ok, I've figured it out, for those who pass by and may have the same problem as I had. The commands you do with cURL in the terminal and with the library are totally different :
In the command prompt, you got to enter curl -X POST https://blablablabla
In the C++ library, you have to call the curl_easy_setopt() function with parameters to specify each component of the request : CURLOPT_URL is your main domain, CURLOPT_POSTFIELDS is the data you want to POST, and there are other parameters such as CURLOPT_WRITEFUNCTION, CURLOPT_WRITE_DATA,... etc. that handles the response from the server.
For me, this example was really useful, I don't know how I could have missed it :D Thanks Jesper Juhl for the advice, it is crucial to understand how HTTP and HTTPS works to figure this out.

libcurl IMAP not working

Using the below code, I'm trying to get any of the libcurl IMAP commands to work.
Currently, regardless of the command set via CURLOPT_CUSTOMREQUEST, in my callback function the only data that is given is the oldest email (1st) in my inbox. I can even put something like "dfsafdasfasfaf" in the CURLOPT_CUSTOMREQUEST, and no error will be shown, and the oldest email will be printed from the callback.
I've tried using the sample codes on libcurl's site, to list folders, LSUB, etc and it's always the same - the only thing returned is the contents of the 1st email in my inbox.
I'm using curl 7.40 mingw32 on win32 g++ (-lcurldll).
Surely I must be doing something wrong. If you could take a moment to correct my error, I would be most appreciative. Thank you.
EDIT - Even if you don't know the answer, could you please leave a comment if you have successfully gotten libcurl IMAP to work before? Because if no one has gotten libcurl imap to work before I'll stop wasting my time with it and move on to VMime or another option..
EDIT2- My principal question is how can I list folders via libcurl?
size_t writeCallback(char* buf, size_t size, size_t nmemb, void* up)
{
printf("%s\n", buf);
return size*nmemb; //tell curl how many bytes we handled
}
int main(void)
{
CURL *curl;
CURLcode res = CURLE_OK;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_USERNAME, "gmailuser");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "password");
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com/INBOX");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "LIST");
res = curl_easy_perform(curl);
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
}
curl_easy_cleanup(curl);
}
_getch ();
return (int)res;
}
In order to get list of folders in a given GMail inbox, you should use:
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com/");
Also, I believe you don't need this line to perform LIST request:
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "LIST");
I have tested it on Linux, on libcurl version 7.35.0, though I believe the problems you are encountering are not OS-specific and are rather caused by the current state of the implementation of IMAP support in the library. You can find source code for libcurl version 7.35.0 here.
You can also find more examples of current libcurl IMAP support on the examples page (see the links on the right for more detailed examples).

libcURL and Google Docs

I'm trying to download a file needed for my application off the internet (as part of installation) so that the first time the app starts up, the needed files get downloaded. For now I'm putting them on Google Drive and making them public, then I'm going to use libcURL to download them. The problem is, I just can't get the data.
I use the following link: https://docs.google.com/uc?id=documentID&export=download and replace documentID with the id. When I try connecting to the site though, it keeps giving me a small snippet of HTML code that basically says "Moved Temporarily" and gives me a link to the new URL. When I use the new link in my program, I get no output whatsoever. However, both links work just fine in my web browser, even when I'm not signed in. So Why don't they work in my program? Am I not setting up SSL options correctly, or is Google Drive simply not meant for this kind of thing?
Here's my code:
#include <curl/curl.h>
int main()
{
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "https://docs.google.com/uc?id=documentID&export=download");
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
res = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
return 0;
}
Any help would be appreciated.
You'll need to set the CURLOPT_FOLLOWLOCATION option to tell cURL to follow redirects.
I do not know if this helps directly but I have always made the call
curl_global_init(CURL_GLOBAL_ALL);
which I see you don't use. I have seen this call made here in the threaded SSL code example http://curl.haxx.se/libcurl/c/threaded-ssl.html. This `curl_global_init() call will perform SSL initialisation amongst other things. It is discussed in this link http://curl.haxx.se/libcurl and also in the libcurl tutorial here http://curl.haxx.se/libcurl/c/libcurl-tutorial.html

Sending and receiving strings over http via curl

I have a situation where my program on a server (windows machine) outputs some strings. I need to send those strings from the server to the client via HTTP using curl. Once sent I am to receive the data on the client side as string, decode it and perform subsequent actions.
I already achieved this functionality using C Sockets using berkely API as I had familiarity with that. But for some reason I am not allowed to use a program of my own.
I poked around and seems CURL can be my solution. However I am very new to curl and cant seem to figure out how to achieve this functionality. On the Client side I found this to be useful may be:
#include <stdio.h>
#include <curl/curl.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* 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);
}
return 0;
}
I understand that you have to use the write back functions to receive data ?
Also on the client side I need to develop a program using curl that whenever the server sends over a string, it should receive it and decode it. Any pointers to tutorials related to the specific problems will be highly appreciated. Or if someone has already tried this I'll highly appreciate any help here.
Thanks.
Take a look at this example code from their site. It details how to get your response data written to a region of memory rather than a file:
http://curl.haxx.se/libcurl/c/getinmemory.html
also take a look at the generic tutorial on the curl website:
http://curl.haxx.se/libcurl/c/libcurl-tutorial.html
one final thing to consider, if using C++ you need to make sure your callbacks are not non static member functions (see here libcurl - unable to download a file)
This should get you started at least.

Downloading a file from URL to disk in C++

I have a simple question. Is it possible to write simple code to download a file from the internet (from URL to disk) without using C++ (for mac osx) libraries like curl?
I have seen some examples but all of these use the Curl library.
i use this code on my xcode projet..but i have some compilation (linking) errors
#define CURL_STATICLIB
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <string>
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {
size_t written;
written = fwrite(ptr, size, nmemb, stream);
return written;
}
int main(void) {
CURL *curl;
FILE *fp;
CURLcode res;
char *url = "http://localhost/aaa.txt";
char outfilename[FILENAME_MAX] = "bbb.txt";
curl = curl_easy_init();
if (curl) {
fp = fopen(outfilename,"wb");
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
}
return 0;
}
how can i link the curl library to my xcode project?
You can launch a console command, it is very simple :D
system("curl -o ...")
or
system("wget ...")
"Downloading a file from URL" means basically doing an GET request to some remote HTTP server. So you need to have your application know how to do that HTTP request.
But HTTP is now a quite complex protocol. Its specification alone is long and complex (more than a hundred pages). libcurl is a good library implementing it.
Why do you want to avoid using a good free library implementing a complex protocol? Of course, you could implement the complex HTTP protocol by yourself (probably that needs years of work), or make a minimal program which don't implement all the details of HTTP protocol but might work (but won't work with weird HTTP servers).
You have to learn bits of "socket programming" and implement a very basic HTTP protocol; the minimalist thing is to send string like "GET /this/path/to/file.png HTTP/1.0\r\n" to the site; then, likely it will answer with an HTTP header you have to parse to know at least the length of the binary data following (if the request succeeded, otherwise you have to handle HTTP errors, or a unexpected contet-type like a html page).
This guide should give you the basic to start with; about HTTP, it depends on your need, sometimes sending a "raw" GET could suffice, sometimes not.
EDIT
Changed to pretend that the request comes from a HTTP/1 compliant client, since HTTP/1.1 wants the Host header to be sent, as commenter has rightly pointed.
EDIT2
The OP changed the question, which became something about how to link with a library in Xcode. There's already a similar question on SO.