Memory leak when using curl_easy_setopt - c

I have the following code:
CURL *curl;
void http_init()
{
curl = curl_easy_init();
if (!curl) return -1;
}
void http_send_message(char *msg_out, char **msg_in)
{
CURLcode res;
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.133:8080/tawtaw");
curl_easy_setopt(curl, CURLOPT_USERNAME, "tawtaw");
curl_easy_setopt(curl, CURLOPT_PASSWORD, "tawtaw");
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST);
.
.
.
curl_easy_reset(curl);
}
void http_exit()
{
curl_easy_cleanup(curl);
}
int main()
{
char *msgin=NULL;
http_init();
http_send_message("message number 1", &msg_in);
free(msgin);msgin=NULL;
http_send_message("message number 2", &msg_in);
free(msgin);msgin=NULL;
http_exit();
}
If I call
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.133:8080/tawtaw");
and then
curl_easy_reset(curl)
and then
curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.1.133:8080/tawtaw");
again, does the allocated memory in the first curl_easy_setopt get freed by curl_easy_reset(curl) or by the second call of curl_easy_setopt?
Or the memory is not freed and there is a memory leak?

Does the allocated memory in the first curl_easy_setopt() get freed by curl_easy_reset(curl) or by the second call to curl_easy_setopt()?
The thing is that:
It's an implementation detail.
Arising from the preceding fact, it does not/should not matter. Either one is true, proper memory management is possible in both cases.

Related

Accessing server with authentication using libcurl

I am trying to access a company internal webpage that requires authentication using libcurl. When the code is run, it says "401 UNAUTHORIZED". I am providing the login credentials via curl_easy_setopt(curl, CURLOPT_USERPWD, "usr:pwd"), but still get the above message.
I read on this and found that 401 means it requires a SERVER authentication. However, I do not receive any available authentication schemes. My winhttp config settings are on 'Auto-detect'.
int wmain()
{
std::string content;
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "company internal URL");
curl_easy_setopt(curl, CURLOPT_USERPWD, "usr:pwd");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &content);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writer);
CURLcode code = curl_easy_perform(curl);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
std::cout << content;
std::cin.get();
return 0;
}
I am very new to using libcurl and have limited working experience with C/C++. Your help is appreciated to identify the problem. Thanks!
Try to add curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
Also of course "usr:pwd"should be replaced, but I assume you did that.
Example below
https://curl.haxx.se/libcurl/c/CURLOPT_HTTPAUTH.html
CURL *curl = curl_easy_init();
if(curl) {
CURLcode ret;
curl_easy_setopt(curl, CURLOPT_URL, "https://example.com/");
/* allow whatever auth the server speaks */
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_easy_setopt(curl, CURLOPT_USERPWD, "james:bond");
ret = curl_easy_perform(curl);
}

How to store curl responds in a variable in c

I am trying to generate curl get request using c program .Here I need to store the response in a variable and I tried with the following code.
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
function_pt(void *ptr, size_t size, size_t nmemb, void *stream){
char **response_ptr = (char**)stream;
*response_ptr = strndup(ptr, (size_t)(size *nmemb));
}
int main(void)
{
CURL *curl;
CURLcode res;
char *response =calloc(1,sizeof(char));
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, function_pt);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
res=curl_easy_perform(curl);
curl_easy_cleanup(curl);
printf("%s\n",response);
}
return 0;
}
The data I get form http get request is real time,so i need to continue with the get request and store value in a variable in an iterative manner,only so that I can use the data in all other parts of the program.But the following code works only once and then exit.
How can I do it? Are there any other methods to generate http get request?
You don't need to calloc() the pointer if you are going to strndup() the original string, assuming that the response is a string is not good because that is not necessarily true.
I would suggest a structure where you can also store the length of the response, so if it's not text but for example a jpeg file nothing bad will happen, and you should not call printf() unless you check from the response headers that the response is indeed text, and it will be nul terminated afaik.

cURL couldn't resolve host, but web browser can access it

I'm writing my server code in C on my Mac, and I need it to access Facebook's Graph API at the URL "https://graph.facebook.com/app?access_token=[insert access token here]". I'm getting a CURLE_COULDNT_RESOLVE_HOST error, maybe because I've never done this before and am probably doing something totally wrong. I'm setting up a CURL* and connecting like this:
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, true);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.8) Gecko/2009032609 Firefox/3.0.8");
char* httpURLFormat = "https://graph.facebook.com/app?access_token=%s";
char* httpURL = emalloc(sizeof(char)*(strlen(httpURLFormat)+MAX_TOKEN_LENGTH)); //emalloc is just malloc that makes sure there is free memory
sprintf(httpURL, httpURLFormat, data->password); //data->password is the access token
curl_easy_setopt(curl, CURLOPT_URL, &httpURL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
struct url_data response; //this struct contains int size and char* data
response.size = 0;
response.data = emalloc(4096);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
CURLcode curlCode = curl_easy_perform(curl);
if (curlCode!=CURLE_OK){
printf("curl failed!!!\n"); //this ends up printing
free(response.data);
free(httpURL);
free(httpURLFormat);
return false;
}
//Yes, I free everything left over afterwards...
I tested the URL it's connecting to in my web browser using the same user agent my code uses, and it connects without trouble. I tried adding a '\n' character to the end of the URL, and my code still won't work.
I found the problem: The httpURLFormat should be "https://graph.facebook.com:443/app?access_token=%s". You need to specify the port in the URL. CURL apparently doesn't use the default 443 otherwise.

libcURL inconsistent when POSTing

When I post to a certain URL via libcURL most of the time the status code will be a 401, but sometimes it will return the 200 I expect even though the credentials I pass are the same. The weird thing is that if I use the same code ported to python and using urllib2 I will get a 200 ok and I will get the data I need. Here is the relevant code that I am using to post to the website. libcURL also works fine for me to get the needed credentials for this function such as the xut_sid key and cookie, it is just this url that sometimes 401s and sometimes 200s.
CURL *curl_handle;
CURLcode res;
struct curl_slist *header = NULL;
MemoryStruct chunk;
...
header = curl_slist_append(header, l->cookie);// l just contains the data I need
header = curl_slist_append(header, l->xut_sid);
header = curl_slist_append(header, "Content-Type: application/json;charset=utf-8");
header = curl_slist_append(header, "x-http-method-override: GET");
curl_handle = curl_easy_init();
curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1);
curl_easy_setopt(curl_handle, CURLOPT_URL, searchString);
curl_easy_setopt(curl_handle, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, header);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, &chunk);
res = curl_easy_perform(curl_handle);
EDIT: I fixed it, twas a dumb mistake by me where the xut_sid would get overwritten(I'm new to C lol and didn't use strdup to copy the string) and not be sent. I don't know why it showed up in the verbose log as there, but it wasn't being sent.

Making https get with libcurl

I'm trying to connect to a google api.
This works fine in my terminal, there I'm doing:
curl https://www.googleapis.com/tasks/v1/users/#me/lists --header "Authorization: Bearer myAccessCode".
This works fine, but now I want to make this inside a c program.
For this I have:
CURL *curl;
char *header = "Authorization: Bearer myAccessCode";
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, header);
curl = curl_easy_init();
char *response = NULL;
curl_easy_setopt(curl, CURLOPT_URL, "https://www.googleapis.com/tasks/v1/users/#me/lists");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, httpsCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
curl_easy_perform(curl);
curl_easy_cleanup(curl);
But here I'm just getting a message that a login is required.
I have no idea what I'm doing wrong, is there someone who sees my failure?
Like I wrote in the comment above:
I just realized that I made: curl_slist_append(headers, header);
instead of: headers = curl_slist_append(headers, header);
So headers was always NULL and I made the get request without a header.
(I edited it in my question above, so the code works, if some)

Resources