Mac Download a file from the internet, with C++

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
In my site, I created a folder where I store registration files. I protected that folder with a username/password so that only I can access it.
I want to insert code in my application that would access that protected folder to check if there was a file there.
So, how can I access a file in the net that is inside a protected folder, using C++?
It also needs to be cross platform because I develop in Xcode but then I send my source code to Visual Studio and compile Win32 and Win64 versions (this is for plugin development, not standalone apps).
I already solved this using python (it is sooooo easy, with python) but some of my plugins are coded in C++ and I wanted to do the same with C++.
But it seems to be rather complicated with C++ :-(
Does anyone have a solution for this?
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
Let me add that I don't want to download the file into a file.
I just want to read the content of the file. It is simply a small .txt file that I want to read from. Just 10 characters.
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
This is so extremely simple in python. This is my python code:

import urllib2
from urllib2 import URLError, HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, install_opener, build_opener

def check_online(url,username,password):

try:
password_mgr.add_password(None, url, username, password)
opener = build_opener(HTTPBasicAuthHandler(password_mgr))
file = opener.open(url+"/myfile.txt")
content=file.read()
file.close()

except:
content=""

return content

Why is it so complicated in C++?!?
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
Well, I reached as far as:

Code:
	CURL *curl;
	CURLcode res;
	char* usrpass="my_username:my_password";
	char* pointer="1234567890";
	
	curl = curl_easy_init();
	if(curl) {
		curl_easy_setopt(curl, CURLOPT_URL, "http://my_url_pointing_to_the_file");
		curl_easy_setopt(curl, CURLOPT_USERPWD , usrpass);

		curl_easy_setopt(curl, CURLOPT_READDATA, pointer); 
		curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
		
		/* 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);
	}
But, when building, I get:

Code:
Undefined symbols for architecture x86_64:
  "_curl_easy_init", referenced from:
      PluginStart() in main.o
  "_curl_easy_setopt", referenced from:
      PluginStart() in main.o
  "_curl_easy_perform", referenced from:
      PluginStart() in main.o
  "_curl_easy_strerror", referenced from:
      PluginStart() in main.o
  "_curl_easy_cleanup", referenced from:
      PluginStart() in main.o
ld: symbol(s) not found for architecture x86_64
 
Last edited by a moderator:

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
Nope... how do I do that?
Sorry for being so "stupid" but I'm really not a professional programmer.
 

Madd the Sane

macrumors 6502a
Nov 8, 2010
510
42
Utah
For the quick and dirty answer, add the following to your linker arguments:
Code:
-lcurl
Are you building your source in Xcode?
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
Yes, my source code is being typed in Xcode.
After it runs ok on Mac (it is a plugin for Cinema 4D), I take it to Visual Studio and compile it for Win32 and Win64.
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
From what I found in the internet, I should add -lcurl to the Other Linker Flags.
However, I already have stuff in there that is required for the Cinema 4D plugin project, namely:

For Debug: $(C4D_ROOTDIR)/resource/_api_lib/lib_api_debug.a
For Release: $(C4D_ROOTDIR)/resource/_api_lib/lib_api_release.a

This means that in Other Linker Flags I have <Multiple Values>

How can I add that library, then?

Oh, by the way, I'm using Xcode 4.6.3
I have to use that version for developing the plugins.
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
Definitely, in python is easier ;-)
But I still need to do it in C++.
So, any help is greatly appreciated.
 

ArtOfWarfare

macrumors G3
Nov 26, 2007
8,761
4,471
This is so extremely simple in python. This is my python code.

Why is it so complicated in C++?!?
You've got this a bit backwards. Guido wanted to know why C/C++ (and everything else) was so damn complicated so he made Python. C++ was first released in 1983 while Python didn't appear until 1991.

... Python is older than I am. That is weird.
 

Madd the Sane

macrumors 6502a
Nov 8, 2010
510
42
Utah
From what I found in the internet, I should add -lcurl to the Other Linker Flags.
However, I already have stuff in there that is required for the Cinema 4D plugin project, namely:

For Debug: $(C4D_ROOTDIR)/resource/_api_lib/lib_api_debug.a
For Release: $(C4D_ROOTDIR)/resource/_api_lib/lib_api_release.a

This means that in Other Linker Flags I have <Multiple Values>

How can I add that library, then?
Are the Other Linker Flags for the target bolded? If not, you can double-click on it and change it to this:
Code:
-lcurl $(inherited)
If it is, then it'll be a bit more complicated: you'll need to click on the disclosure triangle and add -lcurl at the end of the list of Other Linker Flags.
Another option is going into "Build Phases", expand "Link Binary With Libraries", click the add button, search for libcurl, and add "libcurl.dylib".
 
Last edited:

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
Thank you sooooo much.
I finally was able to compile it :)

However, the code still doesn't download the content of the file.
I even tried with a simple URL that does not require any username/password and it seems not to be working.
This is my current code:

Code:
CURL *curl;
CURLcode res;
char* value="1234567890"; // since I need to download just 10 characters
	
curl = curl_easy_init();
if(curl) {
	curl_easy_setopt(curl, CURLOPT_URL, "http://www.ruimac.com/files/count.txt");
		
	curl_easy_setopt(curl, CURLOPT_READDATA, *value); 
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
		
	res = curl_easy_perform(curl);
	/* Check for errors */ 
	if(res != CURLE_OK) GePrint ("Error!");
		
	/* always cleanup */ 
	curl_easy_cleanup(curl);
		
	GePrint(value);
}
What I get is an output in the Console that reads: 1234567890
This means that the value variable was not affected and, I assume, nothing was read. But the res variable returns CURLE_OK
 
Last edited by a moderator:

chown33

Moderator
Staff member
Aug 9, 2009
8,819
5,226
vertical
For libcurl, a download from a remote host uses the WRITEDATA and WRITEFUNCTION options. The READDATA and READFUNCTION options are for uploads (e.g. an HTTP POST).

See this example:
http://curl.haxx.se/libcurl/c/getinmemory.html

That example is linked to from the WRITEDATA doc page:
http://curl.haxx.se/libcurl/c/CURLOPT_WRITEDATA.html

EDIT: I see you found the correct example.

I recommend trying the example exactly as given in the curl examples, including the use of the example.com URL. That URL is valid; it's an IETF example website, and you can check it in any browser.

After the exact original example is confirmed to work, change only the URL being retrieved. Confirm it still works as expected using your non-password-protected URL. Then you can modify the working code one step at a time, compile it, test it, and make sure it continues working after every step. If it stops working, then you know that the change you just made is what broke it.

If you can't figure out why the code stops working, then post the last working code, and the non-working code.

Finally, please use code tags.
 

mrichmon

macrumors 6502a
Jun 17, 2003
873
3
The curl command will generate C code that implements the curl command-line. You can then link this C code into your C++, or refactor the C code into C++ to suit your needs.

For example, assuming the command "curl https://www.macrumors.com" retrieves the URL you want to access, then the command "curl https://www.macrumors.com --libcurl foo.c" will generate code in the foo.c file that implements the HTTP GET.
 

ruimac

macrumors newbie
Original poster
Sep 24, 2014
14
0
I managed to make it work (at least for Mac OS).
But it is good to know that.
Thank you.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.