C - use libcurl to list imap sent mails - c

I use libcurl library to get all email in sent mail box from url : imaps://imap.gmail.com:993/[Gmail]/Sent Mail .But it not run and show error :
curl_easy_perform() failed: URL using bad/illegal format or missing URL
Please help me to check it . Thanks in advance. Toan Nguyen
struct string {
char *ptr;
size_t len;
};
void init_string(struct string *s) {
s->len = 0;
s->ptr = malloc(s->len+1);
if (s->ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = realloc(s->ptr, new_len+1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size*nmemb;
}
int main(int argc,char *argv[])
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
struct string s;
init_string(&s);
curl_easy_setopt(curl,CURLOPT_USERNAME,argv[1]);
curl_easy_setopt(curl,CURLOPT_PASSWORD,argv[2]);
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/%5BGmail%5D%2FSent%20Mail;UID=*");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
res = curl_easy_perform(curl);
printf("%s\n", s.ptr);
free(s.ptr);
/* 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;
}

The problem is in your IMAPS URI. According to RFC3501, mailbox names with spaces must be enclosed between double quotes " when used with SELECT or any other IMAP command.
The following should work:
curl_easy_setopt(curl, CURLOPT_URL, "imaps://imap.gmail.com:993/\"[Gmail]/All Mail\"");

Related

curl_getinfo not returning the correct values, always returning 0

I'm trying to get the content length info and the http status code in the CURLOPT_WRITEFUNCTION callback function. I'm using curl_getinfo on the curl handle to query those fields but curl_getinfo always seems to be returning the default values.
Here is the code
#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
struct url_data {
size_t size;
char* data;
CURL *curl;
};
size_t _response_header_callback(void *received_data, size_t size, size_t count, void *response_header) {
//printf("%s ", (char *)received_data);
}
size_t write_data(void *ptr, size_t size, size_t nmemb, struct url_data *data) {
size_t index = data->size;
size_t n = (size * nmemb);
char* tmp;
long responseCode = 0;
curl_easy_setopt(data->curl, CURLINFO_RESPONSE_CODE, &responseCode);
curl_off_t cl;
curl_easy_getinfo(data->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl);
printf("\n whats the response Code %d %d", responseCode, cl);
data->size += (size * nmemb);
#ifdef DEBUG
fprintf(stderr, "data at %p size=%ld nmemb=%ld\n", ptr, size, nmemb);
#endif
tmp = realloc(data->data, data->size + 1); /* +1 for '\0' */
if(tmp) {
data->data = tmp;
} else {
if(data->data) {
free(data->data);
}
fprintf(stderr, "Failed to allocate memory.\n");
return 0;
}
memcpy((data->data + index), ptr, n);
data->data[data->size] = '\0';
return size * nmemb;
}
char *handle_url(char* url) {
CURL *curl;
struct url_data data;
data.size = 0;
data.data = malloc(4096); /* reasonable size initial buffer */
if(NULL == data.data) {
fprintf(stderr, "Failed to allocate memory.\n");
return NULL;
}
data.data[0] = '\0';
CURLcode res;
curl = curl_easy_init();
if (curl) {
data.curl = curl;
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
curl_easy_setopt(curl, CURLOPT_RANGE, "0-50");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
curl_easy_setopt(curl, CURLOPT_RANGE, "51-100");
res = curl_easy_perform(curl);
if(res != CURLE_OK) {
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
// need to detect that this range isn't satisfiable
curl_easy_setopt(curl, CURLOPT_RANGE, "1551-1600");
curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
return data.data;
}
int main(int argc, char* argv[]) {
char* data;
if(argc < 2) {
fprintf(stderr, "Must provide URL to fetch.\n");
return 1;
}
data = handle_url(argv[1]);
if(data) {
printf("%s\n", data);
free(data);
}
return 0;
}
And this is the output
./fetch http://<url>/test/test_key
curl_easy_perform() failed: Couldn't resolve host name
the response Code 0 content length 0
the response Code 0 content length 0
the response Code 0 content length 0
<< download text >
I'm on centos 7 and the libcurl version 7.29.0
Appreciate if someone can let me know what I may be doing wrong. Thank you .

How can I recieve a JSON object from a CURL request in C?

I did this in PHP, and it was relatively easy. However, Its trickier in C, mostly because the cURL library is more tricky, and C isn't object oriented. Here is the snippet of code I have so far:
#include <curl/curl.h>
/* Make first curl call */
curl_global_init();
//initialize first curl instance
CURL *handle;
CURLcode response;
handle = curl_easy_init();
//craft url
char *url = "https://example.com/";
//set url
curl_easy_setopt(handle, CURLOPT_URL, url);
//get resonse
response = curl_easy_perform(handle);
//clean up
curl_easy_cleanup(handle);
The curl should be using get, and also shouldn't I specify Accept: application/json in one of the curlopts?
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
size_t len;
void* buf;
} Body;
typedef size_t (*WriteFunction)(void*, size_t, size_t, void*);
static size_t write_body(const void* ptr, size_t size, size_t nmemb, Body* body_ptr) {
size_t new_len = body_ptr->len + ( size * nmemb );
if (new_len == 0)
return 0;
char* new_buf = realloc(body_ptr->buf, new_len);
if (new_buf == NULL)
return 0;
memcpy(((char*)body_ptr) + new_len, ptr, ( size * nmemb ));
body_ptr->len = new_len;
body_ptr->buf = new_buf;
}
static int write_all(int fd, void* buf, size_t remaining) {
while (remaining > 0) {
ssize_t written = write(STDOUT, buf, remaining);
if (written == -1)
return 0;
remaning -= written;
buf = ((char*)buf) + written;
}
return 1;
}
int main(void) {
CURL* curl = NULL;
struct curl_slist* header_list = NULL;
Body body = { 0, NULL };
int error = 1;
curl = curl_easy_init();
if (curl != NULL) {
fprintf(stderr, "curl_easy_init() failed\n");
goto ERROR;
}
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
header_list = curl_slist_append(header_list, "Accept: application/json");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, (WriteFunction)write_body);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &body);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
goto ERROR;
}
long http_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);
if (http_code < 200 || http_code >= 300) {
fprintf(stderr, "Request not successful: HTTP error code %ld\n", http_code);
goto ERROR;
}
if (body.len == 0) {
printf("Empty response\n");
} else {
printf("Received %zu bytes\n", body.len);
fflush(stdout);
if (!write_all(STDOUT, body->buf, body->len)) {
perror("write");
goto ERROR;
}
}
error = 0;
ERROR:
if ( body.buf != NULL ) free(body.buf);
if ( header_list != NULL ) curl_slist_free_all(header_list);
if ( curl != NULL ) curl_easy_cleanup(curl);
return error;
}
Not tested.

using multiple curls inside for loop in C

I am a beginner in both C programming and libcurl and writing a program to fetch 1000 data values from a website. The website provides a job number and is redirected into another page for the results. Since, the code I have written is almost 500 lines, I am giving a general flow of the program and a short code which I think is the problematic area:
for(row=0;row<1000;row++)
{
------
url = "http://example.com";
curl_global_init(CURL_GLOBAL_ALL);
curlHandle = curl_easy_init();
if(curlHandle)
{
curl_easy_setopt(curlHandle, CURLOPT_TIMEOUT, 1800);
curl_easy_setopt(curlHandle, CURLOPT_ERRORBUFFER, curlErrStr);
curl_easy_setopt(curlHandle, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curlHandle, CURLOPT_URL, url);
curl_easy_setopt(curlHandle, CURLOPT_LOW_SPEED_LIMIT, dl_lowspeed_bytes);
curl_easy_setopt(curlHandle, CURLOPT_LOW_SPEED_TIME, dl_lowspeed_time);
curl_easy_setopt(curlHandle, CURLOPT_VERBOSE, 1L);
free(url);
curlErr = curl_easy_perform(curlHandle);
if(curlErr != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",curl_easy_strerror(curlErr));
}
else
{
curlErr = curl_easy_getinfo(curlHandle, CURLINFO_EFFECTIVE_URL, &url_new);
if((CURLE_OK == curlErr) && url_new)
{
sprintf(job,"%.*s\n", 18, url_new + 28);
if((ptr1 = strchr(job, '\n')) != NULL)
*ptr1 = '\0';
init_string(&s);
curl_easy_setopt(curlHandle, CURLOPT_TIMEOUT, 1800 );
curl_easy_setopt(curlHandle, CURLOPT_URL, url_new);
curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, &s);
curlErr1 = curl_easy_perform(curlHandle);
printf("###### %lu\t%s\n",strlen(s.ptr),s.ptr);
free(s.ptr);
}
curl_easy_cleanup(curlHandle);
}
}
The functions are:
struct string
{
char *ptr;
size_t len;
};
void init_string(struct string *a)
{
a->len = 0;
a->ptr = malloc(a->len+1);
if (a->ptr == NULL)
{
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
a->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *a)
{
size_t new_len = a->len + size*nmemb;
a->ptr = realloc(a->ptr, new_len+1);
if (a->ptr == NULL)
{
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(a->ptr+a->len, ptr, size*nmemb);
a->ptr[new_len] = '\0';
a->len = new_len;
return size*nmemb;
}
The program shows no error of any kind. But out of the 1000 data, almost 50% couldn't be fetched due to curl_easy_perform() failed: Timeout was reached; and 20% of them have the output of the line strlen(s.ptr),s.ptr => 0. The rest are fetched correctly.
The verbose option for the zero output gave the following:
Connection #0 to host www.example.com left intact
getaddrinfo(3) failed for :80
Couldn't resolve host ''
Closing connection #1
Couldn't resolve host name
0
Please suggest the possible errors in the program.
Here is how I would fetch data using cURL
static CURL *curl = NULL;
CURL *initCURL(void)
{
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(curl)
{
// now set all the desired options
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// etc
}
else
{ // else cURL object creation failed
// display appropriate error message
}
}
void endCurl(void)
{
// and then when all done with the cURL object,
// cleanup
curl_easy_cleanup(curl);
}
CURLcode execCurl( CURL *curl )
{
CURLcode res;
// Perform this request, for each fetch
res = curl_easy_perform(curl);
// Check for errors
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
return( res );
}
Note:
I have had this same problem with the cURL timeout occurring.
The best recovery method I found is:
when a timeout occurs, retry the communication, requesting the same data

Using HTTP authentication with libcurl in C for Twitter Streaming [duplicate]

This question already has an answer here:
Closed 11 years ago.
Possible Duplicate:
Trying to Access Twitter Streaming API with C
I am not sure what I am doing wrong in my code but it seems there's a problem on authentication. Every time I execute the code there is no output.
My goal here is I wanted to receive a stream of Tweets from Twitter API. The problem might be something else. But I am not sure. Please help.
This is the C code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
struct string {
char *ptr;
size_t len;
};
void init_string(struct string *s) {
s->len = 0;
s->ptr = malloc(s->len+1);
if (s->ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = realloc(s->ptr, new_len+1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size*nmemb;
}
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
struct string s;
init_string(&s);
curl_easy_setopt(curl, CURLOPT_URL, "http://stream.twitter.com/1/statuses/sample.json");
curl_easy_setopt(curl, CURLOPT_USERPWD, "neilmarion:password_here");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
res = curl_easy_perform(curl);
printf("%s\n", s.ptr);
free(s.ptr);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
Use ssl.
You could use curl_easy_strerror() to get a human readable error message:
printf("curl error %s", curl_easy_strerror(res));
You'll run out of memory after a while (at my end the stream is ~250Kb/s). Save interesting info to a persistent storage and discard the rest.

Trying to Access Twitter Streaming API with C

I got the code from C libcurl get output into a string. I modified it and I want to use it to access the Twitter Stream. I added curl_easy_setopt(curl, CURLOPT_URL, "http://stream.twitter.com/1/statuses/sample.json"); and curl_easy_setopt(curl, CURLOPT_USERPWD, "neilmarion:my_password"); in the code. But the problem is whenever I execute it, there is no output. What must be the problem? Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
struct string {
char *ptr;
size_t len;
};
void init_string(struct string *s) {
s->len = 0;
s->ptr = malloc(s->len+1);
if (s->ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}
size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = realloc(s->ptr, new_len+1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;
return size*nmemb;
}
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
struct string s;
init_string(&s);
curl_easy_setopt(curl, CURLOPT_URL, "http://stream.twitter.com/1/statuses/sample.json");
curl_easy_setopt(curl, CURLOPT_USERPWD, "neilmarion:my_password");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
res = curl_easy_perform(curl);
printf("%s\n", s.ptr);
free(s.ptr);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
The quickest next step is probably to set CURLOPT_HEADER, to include headers in the body output. Most likely, I would guess it is failing on security, and you'll see the details in the headers.

Resources