Share Tips, Code Samples, etc. with the Visual Prolog community.
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

VPcURL revised

Unread post by Jan de Lint »

Code: Select all

class predicates     http_simple_next : vPcURL::connectionReturnHandlerP. clauses     http_simple() :-   % http simple download         C1 = vPcURL::new(http_simple_next),         C1:curl_easy_setopt(cURLOPT_URL, s("http://192.168.178.24/tkal2009.css")),         C1:curl_easy_perform().       http_simple_next(_Returncode, Conn) :-         Content = Conn:getOutput(),         stdIO::write("\n",Content).
Need foreground processing (do nothing until curl is finished), use vPcURLforeground:

Code: Select all

class predicates     http_simple_next : vPcURL::connectionReturnHandlerP. clauses     http_simple() :-   % http simple download         C1 = vPcURLforeground::new(http_simple_next),         C1:curl_easy_setopt(cURLOPT_URL, s("http://192.168.178.24/tkal2009.css")),         C1:curl_easy_perform().       http_simple_next(_Returncode, Conn) :-         Content = Conn:getOutput(),         stdIO::write("\n",Content).
As you can see, the structure is the same in both situations.
Curl debug output can be caught by setting C1:setDebugOn() and DebugInfo = Conn:getDebugOutput(). Debug output also contains protocol header info.
This header info can also be retrieved separately by C1:setHeadersOn() and HeaderInfo = Conn:getHeadersOutput().
More sophisticated (binary upload/download, cascaded requests, http posting, etc.) examples are included.
What can Curl do?
Curl is an Internet protocol handler and is also able to do authentication. Secure connections e.g. https are also supported.
For the moment I would like to refer to the examples package and to the Curl website: http://curl.haxx.se/.
VPcURL supports all curl features, a number of them is in my opinion deprecated by the added VIP features, especially multithreading (use of curl-multi is disencouraged). The required Windows binaries (dll's) can be downloaded from the download page: http://curl.haxx.se/download.html.
Have fun!
Attachments
VPcURL.zip
VPcURL package v2
(21.67 KiB) Downloaded 1713 times
zlib.zip
zip package
(3.03 KiB) Downloaded 1804 times
CurlExample.zip
examples package v2
(6.08 KiB) Downloaded 1817 times
Last edited by Jan de Lint on 27 Apr 2011 20:44, edited 4 times in total.
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Constructors and URL's

Unread post by Jan de Lint »

There are four types of constructors:

Code: Select all

Conn = vPcURL::new(http_download_next) % get result in memory Conn = vPcURL::new("tkal2009.css", http_download_next) % get result in a file Conn = vPcURLforeground::new(http_download_next) % get result in memory Conn = vPcURLforeground::new("tkal2009.css", http_download_next) % get result in a file
The callback (e.g. http_download_next) to process the result after the transfer has taken place is always required. Note that the callback can be an empty function.
The next thing to do is to set the protocol and the url - examples:

Code: Select all

- Conn:curl_easy_setopt(cURLOPT_URL, s("http://192.168.178.24/tkal2009.css")) - Conn:curl_easy_setopt(cURLOPT_URL, s("https://192.168.178.24/tkal2009.css")) - Conn:curl_easy_setopt(cURLOPT_URL, s("ftp://192.168.178.24/tkal2009.css"))
Curl supports many protocols, even SMTP and POP, and is able to do authentication. For a complete list, see the Curl website. Protocols generally come with specific "header" information (up and downstream). Curl recognizes what is data and what is header info. Normally it generates headers, it transfers the data and keeps the recieved header info for itself. But it allows you to put a tap on the recieved header info:

Code: Select all

- Conn:setHeadersOn(),
and in the callback:

Code: Select all

ReceivedHeaders = Conn:getHeadersOutput(),
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

callback

Unread post by Jan de Lint »

Callback.
All constructors need a callback. The callback is performed after Curl has made a transfer to/from the URL. The function domain of a callback is

Code: Select all

connectionReturnHandlerP = (curlcode Returncode, vPcURL Connection) procedure.
The returncode lets you decide whether you want to trust the result or not. If the returncode equals cURLE_OK, the output can be trusted otherwise a network error may have occurred. The connection gives access to the object. Taken from the Curl examples:

Code: Select all

example_callback(cURLE_OK, Conn) :-     [Received|_] = Conn:getOutput(codepage(codePageId::codePage_iso88591)),  % download codepage is ISO-8859-1     stdio::write("\n",Received,"\n-----------"),     X = Conn:curl_easy_getinfoS(cURLINFO_EFFECTIVE_URL, ResultUrl),     stdIO::write("\nUrl in effect: ", ResultUrl,"  curl-returncode= ",  X ), % gives the resulting new URL if location was changed/followed     _ = Conn:curl_easy_getinfoI(cURLINFO_RESPONSE_CODE, ResultCode),     stdIO::write("\nHttp responsecode: ", ResultCode ). example_callback(_CurlCode, _Conn) :-     stdio::write("Network error while performing example.").
Download in memory (constructor/1) can be retrieved by either:

Code: Select all

Conn:getOutput() -> string % the budget version Conn:getOutput(codepage) -> stringlist % deluxe Conn:getOutputBin() -> binary % most versatile
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Housekeeping

Unread post by Jan de Lint »

The following Curl commands are now given automatically:

Code: Select all

curl_easy_init() curl_easy_cleanup() curl_formfree()          % free a previously built form POST curl_slist_free_all()     % frees a whole curl_slist as made with curl_slist_append()
They have been removed from the VPcURL interface.
Also, do NOT use any of the curl commands to establish inputs or outputs. VPcURL does the opening and closing of streams for you.
The download-stream is most of the time handled by the constructor, and if applicable the upload-stream is set by

Code: Select all

setInput : (string) determ. setInputBin : (binary). % in case of upload from memory.
The file-streams are closed just before returning to the callback and the memory-streams are closed after performing the callback. That is why the callback has to be a procedure.
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Unread post by Jan de Lint »

Code: Select all

 stdIO::write("\nHttp responsecode: ", ResultCode),
should be replaced by something like:

Code: Select all

 write_to_ui("\nHttp responsecode: ", ResultCode),
Where write_to_ui is as follows:

Code: Select all

class predicates     write_to_ui : (...).   % the ellipsis are real! clauses     write_to_ui(...) :-         applicationwindow::get():postaction({         :-             stdio::write(...)         }).
The examples have been updated.
Note Please be aware that in a few places in the VPcURL package, output is also still directly written to the windows UI. This is true for error messages and the like. I don't think this does much harm, but time for another (the last?) update to do proper exception processing!
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Unread post by Jan de Lint »

That is supposed to work yes. I never tried it and I don't know how the required certificate is provided. Perhaps you should have Firefox installed first for that.
Also, try the curl command line utility first.
Succes,
]an
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Re: VPcURL revised

Unread post by Jan de Lint »

After some 10 years, the "VPcURL revised" package needs some minor updating for version 10. Just use the guidance of warnings and errors(2) messages. Change uncheckedConvert into convert
User avatar
drspro2
VIP Member
Posts: 97
Joined: 28 Apr 2006 12:03

Re: VPcURL revised

Unread post by drspro2 »

dear Jan,

it is unclear to me how the Libcurl.dll from the Haxxe website should be loaded,

should it be placed next to the .exe file

or does it have to be loaded through : useDll::load("libcurl.dll")

thankyou
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Re: VPcURL revised

Unread post by Jan de Lint »

Hi Rene,
the libcurl.dll must be placed in the same directory as the program exe. After all these years there is still no apparent change in the libcurl.dll interface. The libcurl.dll can be obtained from one of the binary downloads provided on the Haxxe website. On the other hand I use a -very - old libcurl dll which still does the job for me. So the VPcURL package is still valid!
As you mentioned: the https certificate provided by Haxxe can be placed in the exe directory also.
]an
User avatar
Thomas Linder Puls
VIP Member
Posts: 1398
Joined: 28 Feb 2000 0:01

Re: VPcURL revised

Unread post by Thomas Linder Puls »

I have (slightly) tried the package and updated it (slightly) to fit Vip10. I have also done 10 seconds of research to get it to use the Windows schannel system for certificate handling:

Code: Select all

clauses     run() :-         curl_api::curl_global_sslset(), % use schannel (first argument is actually 8)         vPcURL::curl_global_init(),         TaskWindow = taskWindow::new(),         TaskWindow:show().
The code have the general problem that it shows message boxes instead of raising exceptions. Users of a library cannot have it showing message boxes, they might want a quite different behavior.
Attachments
curlDemo.zip
curlDemo
(45.5 KiB) Downloaded 456 times
Regards Thomas Linder Puls
PDC
User avatar
Jan de Lint
VIP Member
Posts: 83
Joined: 6 Mar 2000 0:01

Re: VPcURL revised

Unread post by Jan de Lint »

Thanks! If I remember correctly (it's been a long time!), the libcurl dll returns an error code in case of an error. That code could be easily used to raise an exception. Depending on the scenario that exception could include the error message text which can be extracted from that dll as per the example.
The error text is the same as provided by the curl command line interface, so one can expect robust error messages.
User avatar
drspro2
VIP Member
Posts: 97
Joined: 28 Apr 2006 12:03

Re: VPcURL revised

Unread post by drspro2 »

is it possible to give any hint as how to implement a progress-bar if you download for example a file of 100 MB?

i see this constant in the Curl api file but it is not used : cURLOPT_PROGRESSFUNCTION = 20056. %not implemented/tested

can it be put here in this place where the code cURLE_OK is ?

Code: Select all

example_callback(cURLE_OK, Conn) :-     [Received|_] = Conn:getOutput(codepage(codePageId::codePage_iso88591)),  % download codepage is ISO-8859-1     stdio::write("\n",Received,"\n-----------"),     X = Conn:curl_easy_getinfoS(cURLINFO_EFFECTIVE_URL, ResultUrl),     stdIO::write("\nUrl in effect: ", ResultUrl,"  curl-returncode= ",  X ), % gives the resulting new URL if location was changed/followed     _ = Conn:curl_easy_getinfoI(cURLINFO_RESPONSE_CODE, ResultCode),  
Post Reply