1. libcurl - help needed
- Posted by jmduro Oct 23, 2016
- 3677 views
Forked from Re: HTTPS with OpenSSL
I wrote a libcurl 7.50 wrapper for Eu3, mostly from C source code with some routines borrowed form Ray's eulibcurl02. Source code is here: http://jean-marc.duro.pagesperso-orange.fr/libcurl_v0.0.3.zip
I can access https sites but there are some functionnalities I can't get to work:
- cookies (there is no error but the list of cookies remains empty)
- recover HTML body (as with Ray's curl_easy_perform_ex)
Help needed
Jean-Marc
2. Re: libcurl - help needed
- Posted by ne1uno Oct 23, 2016
- 3672 views
Forked from Re: HTTPS with OpenSSL
I wrote a libcurl 7.50 wrapper for Eu3, mostly from C source code with some routines borrowed form Ray's eulibcurl02. Source code is here: http://jean-marc.duro.pagesperso-orange.fr/libcurl_v0.0.3.zip
I can access https sites but there are some functionnalities I can't get to work:
- cookies (there is no error but the list of cookies remains empty)
- recover HTML body (as with Ray's curl_easy_perform_ex)
Help needed
Jean-Marc
I wrapped some of the easy interface a few years ago and haven't used it much recently *uses memstruct now*. I don't think I ever output the cookies, but last time I did use it on a site that needed cookies, I used both CURLOPT_COOKIEFILE amd CURLOPT_COOKIEJAR set to the same file name.
3. Re: libcurl - help needed
- Posted by jmduro Oct 23, 2016
- 3835 views
Additional libraries needed are available here: http://jean-marc.duro.pagesperso-orange.fr/myLibs3_v1.5.22_2016-10-20.zip
Jean-Marc
4. Re: libcurl - help needed
- Posted by jmduro Oct 23, 2016
- 3632 views
I wrapped some of the easy interface a few years ago and haven't used it much recently *uses memstruct now*. I don't think I ever output the cookies, but last time I did use it on a site that needed cookies, I used both CURLOPT_COOKIEFILE amd CURLOPT_COOKIEJAR set to the same file name.
I tried this, but the cookies file remains empty even with sites sending cookies (verified):
# Netscape HTTP Cookie File # https://curl.haxx.se/docs/http-cookies.html # This file was generated by libcurl! Edit at your own risk.
Jean-Marc
5. Re: libcurl - help needed
- Posted by ghaberek (admin) Oct 24, 2016
- 3641 views
I can access https sites but there are some functionnalities I can't get to work:
- cookies (there is no error but the list of cookies remains empty)
- recover HTML body (as with Ray's curl_easy_perform_ex)
To recover the HTML body from the call to curl_easy_perform(), you need to establish a write function via curl_easy_setopt() that collects the data.
This example is untested, but it's how I've done this in C code that uses cURL.
include std/eumem.e include std/machine.e function curl_write_callback( atom ptr, atom size, atom nmemb, atom userdata ) atom realsize = size * nmemb sequence data = peek({ ptr, realsize }) eumem:ram_space[userdata] = append( eumem:ram_space[userdata], data ) return realsize end function public function curl_easy_perform_ex( atom handle ) atom write_cb = call_back( routine_id("curl_write_callback") ) curl_easy_setopt( handle, CURLOPT_WRITEFUNCTION, write_cb ) atom userdata = eumem:malloc( "" ) curl_easy_setopt( handle, CURLOPT_WRITEDATA, userdata ) atom result = curl_easy_perform( handle ) sequence content = eumem:ram_space[userdata] eumem:free( userdata ) return {result,content} end function
-Greg
6. Re: libcurl - help needed
- Posted by jmduro Oct 24, 2016
- 3584 views
That is what I did. Here is the Eu 3.1 code:
global sequence curl_easy_buffer function curl_write_callback(atom bufferp, integer size, integer nmemb, atom userp) userp = userp -- stop warning curl_easy_buffer = curl_easy_buffer & peek({bufferp, size * nmemb}) return size * nmemb end function global function curl_easy_perform_ex(atom curl) integer ret atom hsp hsp = allocate_string("") -- set callback function to receive data ret = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, call_back(routine_id("curl_write_callback"))) void = curl_easy_setopt(curl, CURLOPT_WRITEDATA, hsp) -- get file curl_easy_buffer = {} ret = curl_easy_perform(curl) free(hsp) if ret != CURLE_OK then return ret else return curl_easy_buffer end if end function
This code crashes on curl_easy_perform(curl).
Jean-Marc
Nota: now I can read slist structures as used with cookies, but the cookies file remains empty.
7. Re: libcurl - help needed
- Posted by jmduro Oct 24, 2016
- 3619 views
Hi Greg,
I ported your code to Eu 3
include machine.e sequence ram_space integer ram_free_list, free_rid ram_space = {} ram_free_list = 0 function malloc(object mem_struct_p) integer temp_ if atom(mem_struct_p) then mem_struct_p = repeat(0, mem_struct_p) end if if ram_free_list = 0 then ram_space = append(ram_space, mem_struct_p) return length(ram_space) end if temp_ = ram_free_list ram_free_list = ram_space[temp_] ram_space[temp_] = mem_struct_p return temp_ end function procedure free(atom mem_p) if mem_p < 1 then return end if if mem_p > length(ram_space) then return end if ram_space[mem_p] = ram_free_list ram_free_list = floor(mem_p) end procedure free_rid = routine_id("free") function curl_write_callback( atom ptr, atom size, atom nmemb, atom userdata ) atom realsize sequence data realsize = size * nmemb data = peek({ ptr, realsize }) ram_space[userdata] = append( ram_space[userdata], data ) return realsize end function global function curl_easy_perform_ex( atom handle ) atom write_cb, userdata, result sequence content write_cb = call_back( routine_id("curl_write_callback") ) void = curl_easy_setopt( handle, CURLOPT_WRITEFUNCTION, write_cb ) userdata = malloc( "" ) void = curl_easy_setopt( handle, CURLOPT_WRITEDATA, userdata ) result = curl_easy_perform( handle ) content = ram_space[userdata] free( userdata ) return {result,content} end function
I got the same crash. Then I tried to replace
write_cb = call_back( routine_id("curl_write_callback") )
by
write_cb = call_back( { '+', routine_id("curl_write_callback")} )
and it doesn't crash anymore!
Thanks
Jean-Marc
8. Re: libcurl - help needed
- Posted by ghaberek (admin) Oct 24, 2016
- 3547 views
I got the same crash. Then I tried to replace
write_cb = call_back( routine_id("curl_write_callback") )
by
write_cb = call_back( { '+', routine_id("curl_write_callback")} )
and it doesn't crash anymore!
Oh yes, I suppose cURL is using CDECL on Windows so you'll need the '+' in there.
-Greg
9. Re: libcurl - help needed
- Posted by CraigWelch Oct 24, 2016
- 3558 views
Back, when I was using Ray's libcurl on a daily basis, this is the code I used regarding cookies. It worked as expected.
else -- Direct void = curl_easy_setopt(curl_handle, CURLOPT_PROXYTYPE, CURLPROXY_HTTP) void = curl_easy_setopt(curl_handle, CURLOPT_PROXY, "") void = curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, "C:\\EUPHORIA\\greys\\Direct_cookies") void = curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, "C:\\EUPHORIA\\greys\\Direct_cookies") void = curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "Opera/9.21 (Windows NT 5.1; U; en)") end if void = curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0) -- CURLOPT_CAINFO and CURLOPT_CAPATH would be used to point to certificates, -- but the line above says not to verify the SSL certificate
I'll be re-writing that code for re-use in the next couple of months, I'll report back.
10. Re: libcurl - help needed
- Posted by jmduro Oct 25, 2016
- 3533 views
Thanks Greg and Craig,
With your help, I have improved the library. It is still not complete but it can now read HTML data, cookies and certificates. Source is available here: http://jean-marc.duro.pagesperso-orange.fr/libcurl_v0.0.5.zip
On my TODO list, there is:
- set cookies
- manage csrf tokens
- manage forms
- and maybe more
I'm also trying to standardize my own Eu3 libraries to mimic Eu4 std library.
Regards
Jean-Marc
11. Re: libcurl - help needed
- Posted by jmduro Oct 26, 2016
- 3488 views
The last example I ported from C does write the HTML page to a file but crashes on curl_easy_perform.
C:\Data\Euphoria\v3\Personnel\libcurl\examples\../curl.e:2417 in function curl_easy_perform() A machine-level exception occurred during execution of this statement curl = 35925736 ... called from C:\Data\Euphoria\v3\Personnel\libcurl\examples\url2file.exw:82
I can't understand why it crashes. Output file page.out is well written and complete.
Here is the code. Whole library is on RDS Site and here: http://jean-marc.duro.pagesperso-orange.fr/libcurl_v0.0.7.zip
-- <DESC> -- Download a given URL into a local file named page.out. -- </DESC> include file.e include get.e include ../curl.e include myLibs/myDebug.e include myLibs/myFile.e function curl_write_callback( atom ptr, atom size, atom nmemb, atom stream ) atom realsize sequence data realsize = size * nmemb data = peek({ ptr, realsize }) puts(stream, data) return realsize end function sequence cmd, lNames atom curl, write_cb sequence res integer pagefile cmd = command_line() lNames = splitFilename(cmd[2]) void = chdir(lNames[1]) InitialDir = current_dir() f_debug = open(InitialDir & SLASH & "debug.log", "w") void = curl_global_init(CURL_GLOBAL_ALL) -- init the curl session curl = curl_easy_init() if curl then void = curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP) void = curl_easy_setopt(curl, CURLOPT_PROXY, "") void = curl_easy_setopt(curl, CURLOPT_RESOLVE, "example.com") void = curl_easy_setopt(curl, CURLOPT_URL, "http://example.com") -- Switch on full protocol/debug output while testing void = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1) -- disable progress meter, set to 0L to enable and disable debug output void = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1) write_cb = call_back( routine_id("curl_write_callback") ) -- send all data to this function void = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb ) -- open the file pagefile = open(InitialDir & SLASH & "page.out", "wb") if (pagefile) then -- write the page body to this file handle void = curl_easy_setopt(curl, CURLOPT_WRITEDATA, pagefile) -- get it! res = curl_easy_perform(curl) -- Check for errors if (res[1] != CURLE_OK) then printf(2, "curl_easy_perform() failed: %s\n", {curl_easy_strerror(res[1])}) else analyzeObject(split(res[2][1], "\n", 0), "data", 1, 0) puts(1, "curl_easy_perform() succeeded\n") end if -- close the header file close(pagefile) end if -- cleanup curl stuff curl_easy_cleanup(curl) end if curl_global_cleanup() close(f_debug) puts(1, "Press any key to continue.\n") void = wait_key()
Jean-Marc
12. Re: libcurl - help needed
- Posted by ghaberek (admin) Oct 26, 2016
- 3440 views
I'm surprised it works at all because you missed the CDECL '+' in your call to call_back() again.
this:
write_cb = call_back( routine_id("curl_write_callback") )
should be:
write_cb = call_back({ '+', routine_id("curl_write_callback") })
-Greg
13. Re: libcurl - help needed
- Posted by jmduro Oct 27, 2016
- 3438 views
I'm surprised it works at all because you missed the CDECL '+' in your call to call_back() again.
Thank you Greg,
Not only mice fall in the same trap many times, aging frenchies do also! To avoid having the same problem many times more, I will use following routine in Eu3 version of std/machine.e (updated):
-- return a CDECL call_back handle for a routine global function cdecl_callback(integer rtn) return call_back({ '+', rtn }) end function
Here is the updated code which works.
-- <DESC> -- Download a given URL into a local file named page.out. -- </DESC> include file.e include get.e include ../curl.e include myLibs/myDebug.e include myLibs/myFile.e function curl_write_callback( atom ptr, atom size, atom nmemb, atom stream ) atom realsize sequence data realsize = size * nmemb data = peek({ ptr, realsize }) puts(stream, data) return realsize end function sequence cmd, lNames atom curl, write_cb integer res integer pagefile cmd = command_line() lNames = splitFilename(cmd[2]) void = chdir(lNames[1]) InitialDir = current_dir() f_debug = open(InitialDir & SLASH & "debug.log", "w") void = curl_global_init(CURL_GLOBAL_ALL) -- init the curl session curl = curl_easy_init() if curl then void = curl_easy_setopt(curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP) void = curl_easy_setopt(curl, CURLOPT_PROXY, "http://proxy.rd.francetelecom.fr:8080") void = curl_easy_setopt(curl, CURLOPT_RESOLVE, "example.com") void = curl_easy_setopt(curl, CURLOPT_URL, "http://example.com") -- Switch on full protocol/debug output while testing void = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1) -- disable progress meter, set to 0L to enable and disable debug output void = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1) write_cb = cdecl_callback(routine_id("curl_write_callback")) -- send all data to this function void = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb ) -- open the file pagefile = open(InitialDir & SLASH & "page.out", "wb") if (pagefile) then -- write the page body to this file handle void = curl_easy_setopt(curl, CURLOPT_WRITEDATA, pagefile) -- get it! res = curl_easy_perform(curl) -- Check for errors if (res != CURLE_OK) then printf(2, "curl_easy_perform() failed: %s\n", {curl_easy_strerror(res)}) else puts(1, "curl_easy_perform() succeeded\n") end if -- close the header file close(pagefile) end if -- cleanup curl stuff curl_easy_cleanup(curl) end if curl_global_cleanup() close(f_debug) puts(1, "Press any key to continue.\n") void = wait_key()
I hope libcurl will be chosen as a replacement of std/socket.e as it covers a broader range of functionalities. Static libraries are also available.
Regards
Jean-Marc
14. Re: libcurl - help needed
- Posted by jmduro Oct 27, 2016
- 3416 views
I made some minor changes to curl.e and std/machine.e to get the library working under Linux with Eu3.
All examples work except certinfo.exw which crashes on curl_slist_free_all(). Certificates are shown in debug.log.
15. Re: libcurl - help needed
- Posted by ghaberek (admin) Oct 27, 2016
- 3410 views
I hope libcurl will be chosen as a replacement of std/socket.e as it covers a broader range of functionalities. Static libraries are also available.
I couldn't agree more. One issue with bringing cURL into Euphoria via static library is exposing all of the C functions from the backend. I had proposed this idea to Jim a while ago:
Right, for wrapping Mini-XML, I was thinking I could put all of the function addresses into a table and just peek them all from memory, get the pointer to that table with one machine_func() call, and then wrap the functions with define_c_func()/proc() as if I were wrapping a shared library. That would save me from having to burn through ~70 machine_func() constants in the backend.
That's a really clever idea!
I would imagine that exposing cURL would work the same way.
-Greg
16. Re: libcurl - help needed
- Posted by jimcbrown (admin) Oct 27, 2016
- 3416 views
I hope libcurl will be chosen as a replacement of std/socket.e as it covers a broader range of functionalities. Static libraries are also available.
socket.e is a thin wrapper for OS/libc provided socket functionality.
I don't think this is likely to go away anytime soon. But I do think that there is room for both libcurl and socket.e in Eu
I couldn't agree more. One issue with bringing cURL into Euphoria via static library is exposing all of the C functions from the backend. I had proposed this idea to Jim a while ago:
Right, for wrapping Mini-XML, I was thinking I could put all of the function addresses into a table and just peek them all from memory, get the pointer to that table with one machine_func() call, and then wrap the functions with define_c_func()/proc() as if I were wrapping a shared library. That would save me from having to burn through ~70 machine_func() constants in the backend.
That's a really clever idea!
I would imagine that exposing cURL would work the same way.
-Greg
Agreed. We should probably put this on the roadmap. If someone sends us a reasonable patch for this, I'll guarantee that it'll be committed in some form and put into the next release.
17. Re: libcurl - help needed
- Posted by _tom (admin) Oct 27, 2016
- 3450 views
Googledrive files for downloading...
"curl.e" ( edited include file )
https://drive.google.com/open?id=0B4wfRhusHmUbam9yRG05eDBjWnc
"curl.zip" ( pdf documentation for include file curl.e )
https://drive.google.com/open?id=0B4wfRhusHmUbUzBNTHh3cHIzck0
I made some cosmetic changes to curl.e so that I can generate documentation that matches the style used for oE.
If you like the output, we can work to refine the documentation.
( warning: not tested so the curl.e file may be damaged.)
_tom
18. Re: libcurl - help needed
- Posted by jmduro Oct 28, 2016
- 3377 views
I will check the changes to adopt the style allowing to generate documentation.
It may be a little early to pulish documentation because it is still a beta release. I'm improving it every day and it misses a real complete example. There are only small chunks of code today.
For example, yesterday I noticed that CURLOPT_ERRORBUFFER could not be managed as other (char *)-based options. It has to be managed apart:
elsif option = CURLOPT_ERRORBUFFER then -- char * code = c_func(xcurl_easy_setopt, {curl, option, param})
I also considered there was no reason to keep curl_easy_setopt as a function. I added this at the end of the procedure:
if (code != CURLE_OK) then o = findID(SETOPT_OPTIONS, option, 1) if atom(o) then warnError(sprintf("Unknown option '%d'", {option}), 1) else warnError(sprintf("Failed to set option '%s'", {o[2]}), 1) end if end if
Last, I intend to use the same method I used in my Low Level Windows Library to declare functions and structures and automate controls.
I think that documentation has to wait for code to be stable enough to ensure people will not use it but for testing.
Regards
Jean-Marc
19. Re: libcurl - help needed
- Posted by jmduro Oct 28, 2016
- 3373 views
I get the idea for the syntax to adopt, but something sounds bizarre:
curl_version function has curl_easy_escape documentation!
Jean-Marc
20. Re: libcurl - help needed
- Posted by _tom (admin) Oct 28, 2016
- 3353 views
I get the idea for the syntax to adopt, but something sounds bizarre:
curl_version function has curl_easy_escape documentation!
Jean-Marc
Only bizarre because I don't know exactly what you are documenting. The "easy" keyword sounded like it should be the target routine!
I created a reference tutorial on setting a standard format for creating documentation http://openeuphoria.org/wiki/view/sample.e.wc
The old way was to format using Creole markup and that was what the docs looked like.
My current thinking is to add more tags (maybe just a heading like Returns;) and use as little formatting as possible. Then, the idea is to write a utility that reads a tag and then formats text into the final docs.
For example, constants and routines appear as you write them, but a simple utility sorts them into alphabetical order. For example: an extra tag could be used to group related routines together and the docs re-arrange themselves into a new order.
We can use your curl.e for testing out new ideas.
_tom
21. Re: libcurl - help needed
- Posted by _tom (admin) Oct 28, 2016
- 3399 views
Added another page http://openeuphoria.org/wiki/view/standard%20doc.wc showing how a standard documented routine can be parsed into a new "look."
The idea is that more information can be parsed out of the signature and less typing is needed when creating documentation.
_tom
22. Re: libcurl - help needed
- Posted by petelomax Oct 28, 2016
- 3306 views
I created a reference tutorial on setting a standard format for creating documentation http://openeuphoria.org/wiki/view/sample.e.wc
I get an Internal Server Error on the doc_Sample_html link on that page
23. Re: libcurl - help needed
- Posted by jimcbrown (admin) Oct 29, 2016
- 3298 views
I created a reference tutorial on setting a standard format for creating documentation http://openeuphoria.org/wiki/view/sample.e.wc
I get an Internal Server Error on the doc_Sample_html link on that page
Fixed.
24. Re: libcurl - help needed
- Posted by CraigWelch Oct 30, 2016
- 3281 views
- cookies (there is no error but the list of cookies remains empty)
Hi Jean-Marc,
I'm not sure from the rest of the thread if you still have this problem.
Generally, there are three reasons why this might happen.
- Incorrect permissions on the directory/file, so it can't be written to.
- (Especially if your program is running as a CGI) the lack of absolute address instead of relative. LibcURL might be writing a cookie file, but not to where you expect to find it.
- This is the real deal - if your program does not end with a clean (no errors) curl_easy_cleanup(), no cookies will be written. You might have iteratively accessed thousands of urls, but not a single cookie will be written to disk until curl_easy_cleanup() is executed. This can happen when testing, for example, when you might just execute a short code snippet, and leave curl_easy_cleanup() out. There is however a new option, CURLOPT_COOKIELIST, "FLUSH", which was added in version 7.17.1, which will force cookies to be written. I have 7.15.5 on my CentOS Linux 5.11 server, and 7.43.0 on my MacBook OS X 10.11.6. So I had to ensure that it worked without 'FLUSH', which I've now done.
I've recently turned my thoughts to libcURL again, as I'm re-writing some old programs to work with Euphoria 4.x. I'm using:
Ray Smith's eulibcurl
modified by Julio C. Galaret Viera for *nix
modified by me in 2007 to allow for proxy (CURLPROXY_HTTP etc).
modified by me in 2009 to allow the CURLOPT_HTTPHEADER function to work, in particular for the use of SOAP functions that require "Content-Type: text/xml" and "SOAPaction: login"
modified by me yesterday to work on Euphoria 4.0, on *nix and OS X
So far I've tested cookies, SSL, GET, PROXY. Yet to test will be SOCKS, POST.
I have not considered documentation at all, and my test script (which I'm happy to send you) is a maze - but it serves my purpose. I've not been trying to make a distribution version, just make it work for my purpose.
Cordialement, Craig
25. Re: libcurl - help needed
- Posted by jmduro Oct 31, 2016
- 3228 views
I'm not sure from the rest of the thread if you still have this problem.
Thank you Greg,
I don't have the problem anymore. I can read cookies yet.
Regards
Jean-Marc
26. Re: libcurl - help needed
- Posted by jmduro Nov 07, 2016
- 3184 views
Now I have tested a working example: a connection to an HTTPS server with login and authentication with a CSRF token.
I comment the code and brand new library before I upload the source.
Jean-Marc
27. Re: libcurl - help needed
- Posted by jmduro Nov 10, 2016
- 3119 views
The libcurl wrapper has been uploaded: http://www.RapidEuphoria.com/uploads/libcurl2.zip
I will port it to EU4 later if someone needs it.
Jean-Marc
28. Re: libcurl - help needed
- Posted by unsteady Nov 10, 2016
- 3115 views
The libcurl wrapper has been uploaded: http://www.RapidEuphoria.com/uploads/libcurl2.zip
I will port it to EU4 later if someone needs it.
Jean-Marc
Irrespective of the need expressed or unexpressed of Libcurl for EU4, it would be a good idea to port it to EU4. My reasoning is that there are very few developers supporting/debugging problems in EU4 and a stable Libcurl wrapper replacing the current network related functions would be very welcome and useful
29. Re: libcurl - help needed
- Posted by euphoric (admin) Jan 04, 2017
- 2710 views
The libcurl wrapper has been uploaded: http://www.RapidEuphoria.com/uploads/libcurl2.zip
I will port it to EU4 later if someone needs it.
Jean-Marc
Has this been ported to EU4 yet?
30. Re: libcurl - help needed
- Posted by jmduro Jan 10, 2017
- 2574 views
The libcurl wrapper has been uploaded: http://www.RapidEuphoria.com/uploads/libcurl2.zip
I will port it to EU4 later if someone needs it.
Jean-Marc
Has this been ported to EU4 yet?
Sorry, I missed your question. An EU4 version is provided in the EU4 Standard Library (lib/_curl_.e). It relies on some other libraries of the package.
http://rapideuphoria.com/lib4_v0.7.8_2016-12-15.zip
Jean-Marc