Im Finding the cURL Documentation to read/Understand. what im trying to do here is post a postcode and return whether or not it is valid.
This is my function so far (what i managed to pull together from tutorials)
int checkPostCode(char postCode[5])
{
printf("checkPostCode\n");
char uidPath[200] = "http://zim.cs.uow.edu.au/~dfs/cgi-bin/postcodes.cgi?pcode=";
//Concatinate poth strings
strcat (uidPath,postCode);
//Output URl
printf("%s \n ", uidPath);
CURL *curl;
CURLcode res;
// Create our curl handle
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, uidPath);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
the script returns either a "Yes" or a "No".
I just don't know what to enter into that if statement to get my result.
thanks in advance :).
It sounds like you want to read a response from the server. For that you'll need to enable the option CURLOPT_READFUNCTION and specify a callback that will receive the data from the network and store it in a array of char.
Related
When trying to send an empty array using curl the array get's received as so emptyArr['']
with quote instead of being posted as an empty emptyArr[]
how do i post the emptyArr without the quote?
#include <curl/curl.h>
CURL *curl;
CURLcode res;
curl_global_init(CURL_GLOBAL_ALL);
/* get a curl handle */
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, "http://someaddress.com");
/* Now specify the POST data */
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "emptyArr[]");
/* 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);
}
curl_global_cleanup();
Empty arrays don't really exist in URL-encoded parameters. When you send an array, it's sent as:
name[]=firstElement&name[]=secondElement&name[]=thirdElement
An empty array means you don't send any of these, but then there's no parameter at all.
It's the responsibility of the server code to handle the nonexisting parameter and treat it as an empty array.
When you write
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "emptyArr[]");
it's being treated as
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "emptyArr[]=");
so you're creating an array with one element whose value is an empty string.
You should simply leave out the parameter entirely, and the server should treat it as empty.
I'm trying to develop an application in C with GTK for the GUI, libcurl to get data by a web API and cJSON to parse JSON.
My problem is that when I do my request with libcurl after gtk_init, the data that I get can not be parsing in JSON. Otherwise, if I get the data and parse it before gtk_init, the parsing works fine.
I have an example to demonstrate it, the first printf in the main returns the JSON correctly but the second printf which is after gtk_init returns NULL (to be exact, the parsing stops at the first decimal number and fail) :
initString :
void initString(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';
}
writeFunc :
size_t writeFunc(void *ptr, size_t size, size_t nmemb, String * s)
{
size_t newLen = s->len + size*nmemb;
s->ptr = realloc(s->ptr, newLen + 1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr + s->len, ptr, size * nmemb);
s->ptr[newLen] = '\0';
s->len = newLen;
return size * nmemb;
}
My function to get data with libcurl :
char * getData(gpointer user_data)
{
curl_global_init(CURL_GLOBAL_ALL);
CURL * curl;
char * url = user_data;
CURLcode res;
String s;
struct curl_slist * headers = NULL;
curl = curl_easy_init();
if(curl)
{
initString(&s);
headers = curl_slist_append(headers, "Accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
headers = curl_slist_append(headers, "charsets: utf-8");
//curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, 6);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
//write data in a string
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeFunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
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);
return s.ptr;
}
The main :
int main(int argc, char ** argv)
{
char * str;
cJSON * json;
str = getData("https://data.culture.gouv.fr/api/records/1.0/search/?dataset=liste-et-localisation-des-musees-de-france&facet=ville&sort=ville&facet=nomdep&refine.nomdep=AIN&rows=1");
json = cJSON_Parse(str);
printf("DATA : %s\n", cJSON_Print(json));//returns the JSON perfectly
gtk_init(&argc,&argv);
str = getData("https://data.culture.gouv.fr/api/records/1.0/search/?dataset=liste-et-localisation-des-musees-de-france&facet=ville&sort=ville&facet=nomdep&refine.nomdep=AIN&rows=1");
json = cJSON_Parse(str);
printf("ERROR : %s\n", cJSON_GetErrorPtr());//returns half of data
printf("DATA : %s\n", cJSON_Print(json));//returns NULL
gtk_main();
curl_global_cleanup();
return EXIT_SUCCESS;
}
I have tried to resolve this by creating threads with g_idle_add, gdk_threads_idle_add, gdk_threads_entry and gdk_threads_leave, pthread_create and pthread_join but nothing worked.
Does someone know how to resolve this problem ?
Thanks.
You need to narrow down your problem. In other words, you need "M" in MVCE. Currently you have three libraries:
Gtk+
cURL
cJSON
that might interact in arbitrary ways. What you need to check:
Does cURL return different data before and after gtk_init call? If no, then problem is not with cURL.
If you hardcode JSON data in your program and parse it with cJSON, are results different before and after gtk_init? If so, problem is in cJSON. If no, problem is not related to cJSON.
My guess is as follows. gtk_init does several things, amongst them sets locale. Since you fetch data from .fr domain, I assume that you have French locale set on your computer.
to be exact, the parsing stops at the first decimal number and fail
In French, decimal separator is comma , instead of period ., so I suppose that after GTK+ changes locale, cJSON starts to look for , in decimal numbers but it finds . and fails.
Possible solutions
As a workaround, call gtk_disable_setlocale before gtk_init. This might cause unintended consequences, eg. your program starts to display numbers in English format instead of French in its UI.
The real solution would be to raise bug in cJSON, as JSON parsing should not take locale into account when parsing numbers. JSON mandates period . as decimal separator.
I doubt very much that this has anything at all to do with the gtk_init() call. It sounds like memory corruption. This would likely be the case e.g. if you returned a pointer to data that was allocated and then cleaned up by curl. In this case both calls are wrong, you just happened to get away with it the first time as the memory was hanging around untouched in that case. Check the API for function calls you make. Some will allocate memory that needs to be freed, others don't.
I suggest you use build with -g and use gdb to test your code. This will help narrow down where the problem lies. Take a look and see if the strings are identical.
cURL returns the same data before and after, I checked it by putting data in 2 strings and strcmp returns 0.
Indeed, I'm french and there may be a confusion between , and . .
gtk_disable_setlocale solved my problem !
I'm trying to access an airport RSS feed using the curl library in C. Whenever I try to access it, though, I get access denied error. The following is the code I'm using. It's almost identical to the example code at https://curl.haxx.se/libcurl/c/simple.html:
#include <stdio.h>
#include <curl/curl.h>
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
char *feed_addr = "http://w1.weather.gov/xml/current_obs/KUCP.rss";
//airport not in the state I live
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, feed_addr);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
// 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've tried this with other websites besides weather.gov (google, youtube, mit.edu) and they all work just fine. But when I tried this, even with other airport RSS feeds (which can be found at http://w1.weather.gov/xml/current_obs/seek.php?state=pa&Find=Find), I get the same access denied error. I also get the same error when I set feed_addr to any weather.gov page.
To make this stranger, when I tried to access the feed using Python3's urllib.request module, it worked just fine. I can also access it just fine with Google Chrome. So I can rule out the idea that it doesn't want me accessing the feed.
Is there something that I'm missing? Is there a way to get the feed via the curl library? Or is there a way using a different library?
Answering my own question (I did not originally plan to, but I solved the issue before someone else answered):
So here is the code that I got to work
#include <stdio.h>
#include <curl/curl.h>
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
char *feed_addr = "http://w1.weather.gov/xml/current_obs/KUCP.rss";
//airport not in the state I live
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, feed_addr);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
//line that solved my issue
curl_easy_setopt(curl, CURLOPT_USERAGENT, <string>);
/**
* The line as written will not work.
* I'm only using <string> as a stand-in for some personal information
* If you're having the same issue as I did, I explain how to solve it under the code
*/
// 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;
}
The way I solved this was finding a site that printed out my HTTP request. In this case, it was http://rve.org.uk/dumprequest. I visited the site like normal in one tab, and I used the program to get the source, then launched that in another tab. That was when I saw that several fields were present when I manually opened the page, but absent when I used the code.
So, I looked at curl_easy_setopt to see if there was a way to set those fields. It turns out, curl_easy_setopt has documentation for that and many more at the website https://curl.haxx.se/libcurl/c/curl_easy_setopt.html. At the suggestion of one of the comments, I looked at CURLOPT_USERAGENT first.
Since that one took a char *, I found the line in the HTTP request that started with User-Agent:, copy-and-pasted the rest, and that was <string> in the above line.
So if the request included the line:
User-Agent: Lord Voldemort (Tom Marvolo Riddle)
The line I included would be:
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Lord Voldemort (Tom Marvolo Riddle)");
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.
I am new using libcurl and I need some help for simple procedures.
I want my program to read information from a website, which will return the information in the following format:
text | xxxxx | xxxxxxxxx
text | xxxxx | xxxxxxxxx
text | xxxxx | xxxxxxxxx
and I want to save that information into an array.
Then read the information from the array, but only the second and third column, just the numbers to use them with another function.
I know how to get the information using libcurl in C from the website and I get it printed in the terminal window, but I do not know how to save it into an array. I am stuck there...
For example with this code:
How would you save the information it returns into an array?
#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:www.example.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* 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 would appreciate any help I can get.
Thank you.
Take a look at CURLOPT_WRITEFUNCTION option of curl_easy_setopt(), and follow their examples.
size_t write_callback(char *ptr, size_t size, size_t nmemb, void *userdata);
CURLcode curl_easy_setopt(CURL *handle, CURLOPT_WRITEFUNCTION, write_callback);