I am trying to test libcurl for my project, but when I want to download a test file I get error:
ERROR : Unknown error
but no reason why it happens,
my code:
#include <stdio.h>
#include <curl/curl.h>
int main(int argc, char **argv) {
CURL *curl;
FILE *fp;
char name[30] = {"Test"};
char link[100] = {"ipv4.download.thinkbroadband.com/5MB.zip"};
CURLcode error;
int result;
fp = fopen(name,"Wb");
curl = curl_easy_init();
curl_easy_setopt;(curl, CURLOPT_URL, argv[1] );
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_easy_perform(curl);
result = curl_easy_perform(curl);
if (result = CURLE_OK)
printf("Sucessful download !");
else
printf("Could not download, ERROR : %s \n",curl_easy_strerror(error));
printf("%s",error);
fclose(fp);
curl_easy_cleanup(curl);
}
There's a bunch of errors in the code.
The argument to fopen should be a lower case "w".
You declare both error and result but should use only one.
There's a stray semicolon in the middle of this line: curl_easy_setopt;(curl, CURLOPT_URL, argv[1] );
Combined with what's already mentioned, this should work:
#include <stdio.h>
#include <curl/curl.h>
int main(int argc, char **argv) {
if(argc < 2) {
puts("URL not given");
return 1;
}
CURL *curl;
FILE *fp;
char name[30] = {"Test"};
char link[100] = {"ipv4.download.thinkbroadband.com/5MB.zip"};
CURLcode result;
fp = fopen(name,"w");
curl = curl_easy_init();
curl_easy_setopt(curl, CURLOPT_URL, argv[1] );
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
result = curl_easy_perform(curl);
if (result == CURLE_OK)
printf("Sucessful download !");
else
printf("Could not download, ERROR : %s \n",curl_easy_strerror(result));
fclose(fp);
curl_easy_cleanup(curl);
return 0;
}
Don't forget to pass the URL as an argument, since you're not actually using link and don't check argc. And I advise you to learn how to use a debugger.
Complete guess - but could it have something to do with your code calling curl_easy_perform(curl); two times instead of once?
This looks suspicious:
curl_easy_perform(curl);
result = curl_easy_perform(curl);
Shouldn't it just be:
result = curl_easy_perform(curl);
Also, shouldn't link have the http prefix on it?
char link[100] = {"http://ipv4.download.thinkbroadband.com/5MB.zip"};
Regarding to your code indentation there are braces missing at least in your else path. That means that the last printf is being executed regardless of the result value...
Does it work as expected if you add the braces like this? Of course together with the other suggestions as stated by selbie and Emanuel P...
if (result == CURLE_OK) {
printf("Sucessful download !");
} else {
printf("Could not download, ERROR : %s \n",curl_easy_strerror(error));
printf("%s",error);
}
Related
I'm trying to learn how to use LoadLibrary properly in a C function, but am having difficulty and there are not a lot of good tutorials to follow. I've created a simple C program that uses the libCurl library to successfully fetch the HTML of a website and print it to console. I am now trying to re-implement the same function using LoadLibrary and GetProcAddress and the libcurl.dll.
How do I pass data back from a function that is loaded into memory?
Posted below is the function using the .lib that works and subsequently the function trying to use the DLL that is failing to compile.
Here is my working program:
#include "stdafx.h"
#include "TestWebService.h"
#include "curl/curl.h"
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_URL, "http://example.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
/* 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 */
printf("%s\n", s.ptr);
free(s.ptr);
curl_easy_cleanup(curl);
}
return 0;
}
Here is my attempt to replicate the same functionality using LoadLibrary only (i.e. Not using the libCurl.lib). But I get the following error message and cannot determine why.
1) a value of type "CURL" cannot be assigned to an entity of type "CURL *"
2) '=': cannot convert from 'CURL' to 'CURL *'
#include "stdafx.h"
#include "TestWebService.h"
#include "curl/curl.h"
typedef CURL (*CurlInitFunc)();
int main(int argc, char **argv)
{
HINSTANCE hLib = NULL;
hLib = LoadLibrary("libcurl.dll");
if (hLib != NULL)
{
CURL *curl;
CurlInitFunc _CurlInitFunc;
_CurlInitFunc = (CurlInitFunc)GetProcAddress(hLib, "curl_easy_init");
if (_CurlInitFunc)
{
curl = _CurlInitFunc();
}
}
return 0;
}
This line:
typedef CURL (*CurlInitFunc)();
declares a pointer to a function that returns a CURL. But the prototype of curl_easy_init() is:
CURL *curl_easy_init();
that means it returns a pointer to CURL, that is CURL*
Therefore the correct declaration is:
typedef CURL *(*CurlInitFunc)();
Anyone can help me? i'm new in programming. How to make str and str2 compareable? (with code if can). or any code that can find a spesific word inside CURLcode
int main(void) {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "mabinogi.nexon.net");
/* example.com is redirected, so we tell libcurl to follow redirection*/
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));
}
const char *str = curl_easy_strerror(res);
char *str2 = "nogi";
char *ff = strstr(str,str2); /*how to make this compareable?*/
if (ff) {
printf("word found!");
}
printf(*str);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
I am using this code to retrieve the data from the web browser using curl request in c language. I want to store the output in another file or buffer.
#include <stdio.h>
#include <curl/curl.h>
#include <curl/easy.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
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);
/* 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 output of this code is an html file. I want to store that html in another file or buffer. How to do that.
Thank you in advance.
Here's a modification to your code that writes the HTML response to a file:
#include <stdio.h>
#include <curl/curl.h>
#include <curl/easy.h>
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
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);
/* create an output file and prepare to write the response */
FILE *output_file = fopen("output_file.html", "w");
curl_easy_setopt(curl, CURLOPT_WRITEDATA, output_file);
/* 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: %sn",
curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
Here are some related questions:
Saving a file using libcurl in C
Download file using libcurl in C/C++
if I visit http://www.microsoft.com/
will redirect to http://www.microsoft.com/en-us/default.aspx
How can I get response/redirect url using CURL lib ?
I try
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &reUrl);
this will get http://www.microsoft.com/
curl_easy_getinfo(curl, CURLINFO_REDIRECT_URL, &reUrl);
this will always get NULL
So thanks for help
Set CURLOPT_FOLLOWLOCATION to 1
#include <stdio.h>
#include <curl/curl.h>
int main(int argc, char** argv)
{
CURL *curl;
CURLcode curl_res;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
if (curl)
{
curl_easy_setopt(curl, CURLOPT_URL, "http://www.microsoft.com");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
/* Perform the request, curl_res will get the return code */
curl_res = curl_easy_perform(curl);
/* Check for errors */
if(curl_res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(curl_res));
if(CURLE_OK == curl_res)
{
char *url;
curl_res = curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
if((CURLE_OK == curl_res) && url)
printf("CURLINFO_EFFECTIVE_URL: %s\n", url);
}
/* always cleanup */
curl_easy_cleanup(curl);
/* we're done with libcurl, so clean it up */
curl_global_cleanup();
}
else
{
printf("cURL error.\n");
}
return 0;
}
You will see:
CURLINFO_EFFECTIVE_URL: http://www.microsoft.com/en-us/default.aspx
I have the following curl code, which make a request to website and retrieve data from it, it works well, but I want to store my data in a string and not in the output window. Any idea?
#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://api.hostip.info/get_html.php?ip=xxx.xxx.xx.xxx");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
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 0;
}
int http_get_response(void *buffer, size_t size, size_t rxed, char **msg_in)
{
char *c;
if (asprintf(&c, "%s%.*s", *msg_in, size * rxed, buffer) == -1) {
free(*msg_in);
msg_in = NULL;
return -1;
}
free(*msg_in);
*msg_in = c;
return size * rxed;
}
and add the following curl option in your main
char *msg_in = calloc(1,sizeof(char));
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http_get_response);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &msg_in);
Then you will get the message in the msg_in
EDIT
do not forget to free msg_in when it become uselless in your program
free(msg_in); msg_in = NULL;
A a general (non-curl specific) method, change your standard output (path 1) (or standard error: path 2) path(s) prior to calling curl. Read the man page on dup2 to see how to duplicate a path to a specific descriptor, and the fdopen function to get a FILE * out of it.
The idea is you first dup path 1 for stdout, and/or 2 for stderr, to save copies of them somewhere. You then close the original paths. You create a pipe (man pipe) and then dup2 the second channel of the pipe to path 1 (or 2). You can now read() from the first channel of the pipe to get the output that was placed there.
Try this:
curl_easy_setopt(curl, CURLOPT_RETURNTRANSFER, true);