initial checkin of TclCurl

This commit is contained in:
Steve Havelka 2014-02-05 16:43:59 -08:00
commit 639b49517b
95 changed files with 30934 additions and 0 deletions

1246
ChangeLog.txt Executable file

File diff suppressed because it is too large Load Diff

895
Changes.txt Executable file
View File

@ -0,0 +1,895 @@
Version 7.22.0 released 03-Oct-2011
* New configure options:
* resolve: Pass a list of strings with host name resolve information to use for
requests with this handle.
Each single name resolve string should be written using the format
HOST:PORT:ADDRESS where HOST is the name TclCurl will try to resolve, PORT is
the port number of the service where TclCurl wants to connect to the HOST and
ADDRESS is the numerical IP address. If libcurl is built to support IPv6,
ADDRESS can be either IPv4 or IPv6 style addressing.
* tlsauthusername, tlsauthpassword: Pass a string with the username or password to
use for the TLS authentication method specified with the 'tlsauthtype' option.
* tlsauthtype: Use it to tell TclCurl which authentication method(s) you want it to
use for TLS authentication. So far the only method is 'tlsauthsrp' for TLS-SRP
authentication. Secure Remote Password authentication for TLS is defined in
RFC 5054 and provides mutual authentication if both sides have a shared secret.
You need to build libcurl with GnuTLS or OpenSSL with TLS-SRP support for this
to work.
* transferencoding: Adds a request for compressed Transfer Encoding in the outgoing
HTTP request. If the server supports this and so desires, it can respond with the
HTTP resonse sent using a compressed Transfer-Encoding that will be automatically
uncompressed by TclCurl on receival.
Transfer-Encoding differs slightly from the Content-Encoding you ask for with
'encoding' in that a Transfer-Encoding is strictly meant to be for the transfer
and thus MUST be decoded before the data arrives in the client. Traditionally,
Transfer-Encoding has been much less used and supported by both HTTP clients and
HTTP servers.
* wildcard: Set this option to 1 if you want to transfer multiple files according to
a file name pattern. The pattern can be specified as part of the url, using an
fnmatch-like pattern (Shell Pattern Matching) in the last part of URL (file name).
So far it only works with FTP.
* fnmatchfunction: Name of the procedure that will be called instead of the internal
wildcard matching function, it should match the following prototype:
FnMatchProc {pattern string}
Returns '0' if it matches, '1' if it doesn't.
* chunkbgnproc: Name of the procedure that will be called before a file will be transfered
by ftp, it should match the following prototype:
ChunkBgnProc {remains}
Where remains is the number of files still to be transfered (or skipped)
This callback makes sense only when using the 'wildcard' option.
* chunkendproc: Name of the procedure that will be called after a file is transfered
(or skipped) by ftp when using the wildcard option, it should match the following
prototype:
ChunkEndProc {}
It should return '0' if everyhting is fine and '1' if some error occurred.
* chunkbgnvar: Name of the variable in the global scope that will contain the data of
the file about to be transfered. If you don't use this option '::fileData' will be used.
The available data is: filename, filetype (file, directory, symlink, device block,
device char, named pipe, socket, door or error if it couldn't be identified), time, perm,
uid, gid, size, hardlinks and flags.
* mailfrom: Pass a string to specify the sender address in a mail when sending an SMTP mail
with TclCurl.
* mailrcpt: Pass a list of recipients to pass to the server in your SMTP mail request.
* ftpusepret: Set to 1 to tell TclCurl to use the EPRT (and LPRT) command when doing
active FTP downloads (which is enabled by 'ftpport'). Using EPRT means that it will
first attempt to use EPRT and then LPRT before using PORT, if you pass zero to this
option, it will not try using EPRT or LPRT, only plain PORT.
* gssapidelegation: Set the option to 'flag' to allow unconditional GSSAPI
credential delegation. The delegation is disabled by default. Set the parameter
to 'policyflag' to delegate only if the OK-AS-DELEGATE flag is set in the service
ticket in case this feature is supported by the GSSAPI implementation and the
definition of GSS_C_DELEG_POLICY_FLAG was available at compile-time.
* telnetoptions: Pass a list with variables to pass to the telnet negotiations.
The variables should be in the format <option=value>. TclCurl supports the
options'TTYPE', 'XDISPLOC' and 'NEW_ENV'. See the TELNET standard for details.
* Updated configure options:
* httpauth new method 'ntlmwb': NTLM delegating to winbind helper. Authentication is
performed by a separate binary application that is executed when needed. The name
of the application is specified at libcurl's compile time but is typically
/usr/bin/ntlm_auth.
* new proxy type 'socsk5h' to enable socks5 and asking the proxy to do the resolving
* New info available through the 'getinfo' command:
* primaryport: Returns the destination port of the most recent connection done.
* localip: Returns the local (source) IP address of the most recent connection done.
This string may be IPv6 if that's enabled.
* localport: Returns the local (source) port of the most recent connection done.
* Bug fixes:
* Sven Hoexter let me know that TclCurl no longer build as curl/types.h and curl/easy.h
no longer exists:
* Gary Nigg noticed that 'bodyvar' had to be reconfigured for each transfer.
* John Coppens got an error when he tried the 'curl::transfer' command.
* Gerald Dumas reported that TclCurl wouldn't compile in FreeBSD, it so happens that
the upstart type 'ulong' isn't good enough for it.
Version 7.19.0 released 1-Sep-2008
* New commands:
* curlHandle pause and curlHandle resume: Pause and resume a
tranfer from within a progress callback procedure.
* New configure options:
* addressscope: Pass a number specifying the scope_id value to
use when connecting to IPv6 link-local or site-local addresses.
* proxytranfermode: Pass a number. If the value is set to 1 (one),
it tells TclCurl to set the transfer mode (binary or ASCII) for
FTP transfers done via an HTTP proxy, by appending ;type=a or
;type=i to the URL. Without this setting, or if set to 0 (zero,
the default), '-tranfertext' has no effect when doing FTP via a
proxy. Beware that not all proxies support this feature.
* Added two new types for the '-proxytype' option: 'socks4a'
and 'socks5hostname'.
* New info available through the 'getinfo' command:
* appconnecttime: Returns the time, in seconds, it took from the start
until the SSL/SSH connect/handshake to the remote host was completed.
* primaryip: Returns the IP address of the most recent connection done
with this handle.
* redirecturl: Returns the URL a redirect would take you to if you would
enable 'followlocation'. This can come very handy if you think using
the built-in redirect logic isn't good enough for you but you would
still prefer to avoid implementing all the magic of figuring out the
new URL.
* Bug fix: The 'writeproc' option didn't work right.
* Internal changes:
* When compìling against Tcl 8.5.3 I had to remove a lot of CONSTs to
prevent warnings, and then I had to add them back with Tcl 8.5.4,
so, depending on which version you use you might get quite a few
warnings while compiling, they should be harmless though.
* The internal workings of the 'any' http authentication has been changed.
Version 7.17.1 released 1-Nov-2007
* New configure options:
* post301: A non-zero parameter tells TclCurl to respect
RFC 2616/10.3.2 and not convert POST requests into GET
requests when following a 301 redirection like browsers
usually do.
* sshhostpublickeymd5: Pass a string containing 32 hexadecimal
digits. The string should be the 128 bit MD5 cheksum of the
remote host public key, and TclCurl will reject the connection
to the host unless the md5sums match.
* If you pass the magic string 'FLUSH' to the '-cookielist'
option all known cookies will be written to the file
specified by '-cookiejar'.
* Renamed options:
Some configure options have been renamed so they get more general
names, the old names are deprecated even if they may be supported
forever.
* sslpasswd => keypasswd
* ftpappend => append
* ftplistonly => dirlistonly
* ftpssl => usessl
* Internal changes:
Up until the current version when we wanted libcurl to use a value
in a string, like the URL to download, we had to keep the string as
long as libcurl could use it. Since 7.17.0 libcurl keeps it own
copies, so I no longer make TclCurl do it.
That means this is a handle-with-care release, please report any
problems you may have.
Version 7.16.4 released 19-July-07
* New configure options:
* newfileperms: Used to set the permissions, defalt 0664, that will be
assigned to newly created files on the remote server.
* newdirectoryperms: Used to set the permissions, default 0755, that
will be assigned to newly created directories on the remote server.
They can both be used for SFTP, SCP and FILE transfers.
* Changed option: The option to set the Kerberos security
level for FTP is now called 'krblevel', the old name
'krb4level' will be kept for some time for compatibility.
* New option for multi handles:
* maxconnects: Sets the maximum amount of simultaneously open
connections that TclCurl may cache. Default is 10.
* Bug fix: Sven Hoexter fixed a couple of errors in the man page.
Version 7.16.2 released 16-April-07
* New feature: TclCurl now supports SSH for SFTP and SCP transfers as long
as libcurl has been compiled with libssh2 support.
* New configure options:
* publickeyfile: name of the file with the public key to use with SSH.
* privatekeyfile: name of the file with the provate key to use with SSH.
* sshauthtypes: Allowed types are "publickey", "password", "host",
"keyboard", or "any" to let TclCurl choose one.
* timeoutms and connectimeoutms: The work like 'timeout' and
'connectimeout' except the timout is given in miliseconds.
* ftpsslccc: If enabled, it will make libcurl shutdown SSL/TLS after
the authentication is done on a FTP-SSL operation.
* httpcontentdecoding: If set to zero content decoding is disabled.
* httptransferdecoding: If set to zero Set transfer decoding is
disabled. TclCurl does chunked transfer decoding by default
unless this option is set to zero.
* ftpsslccc: If enabled, it will make libcurl shutdown SSL/TLS after
the authentication is done on a FTP-SSL operation.
* Bug fixes:
* Olivier Lenormand reported that in case the server sends more than
one 'Set-Cookie' header, TclCurl would only save the last one in
the header array. Now the array will contain a list with all the
cookies.
* Jos Decoster reported and helped fixing a crash that happened when
changing a handle from using a 'writeproc' to not using one.
* I have updated the configure scripts to TEA 3.6, hope you don't bump into
any regressions.
Version 7.16.0 released 15-November-06
* Removed feature: TclCurl no longer supports third party FTP transfers.
* New configure options:
* ftpalternativetouser: Pass a string which will be used to authenticate
if the usual FTP "USER user" and "PASS password" negotiation fails. This
is currently only known to be required when connecting to Tumbleweed's
Secure Transport FTPS server using client certificates for
authentication.
* ftpentrypath: Returns a string holding the path of the entry path.
That is the initial path TclCurl ended up in when logging on to the
remote FTP server. Returns an empty string if something is wrong.
* maxsendspeed: Pass a speed in bytes per seconds. If an upload exceeds this
speed on cumulative average during the transfer, the transfer will pause to
keep the average rate less than or equal to the parameter value.
* maxrecvspeed: Pass a speed in bytes per second. If a download exceeds this
speed on cumulative average during the transfer, the transfer will pause to
keep the average rate less than or equal to the parameter value.
* New command for multi handles 'configure', so far the is only one option to set:
* pipelining: Pass a 1 to enable or 0 to disable. Enabling pipelining on a multi
handle will make it attempt to perform HTTP Pipelining as far as possible for
transfers using this handle. This means that if you add a second request that
can use an already existing connection, the second request will be "piped" on
the same connection rather than being executed in parallel.
Version 0.15.3 released 17-April-06
* I updated the autoconf scripts to TEA 3.5, this seems to prevent
the warnings about how the headers files couldn't be compiled,
but it may have (re)introduced other bugs.
* Removed feature: TclCurl no longer supports Gopher, it probably
didn't work anyway.
* New configure options:
* localport: Sets the local port number of the socket used for
the connection. This can be used in combination with '-interface'
and you are recommended to use 'localportrange' as well when this
is set.
* localportrange: Number of attempts TclCurl should do to find a
working local port number. It starts with the given 'localport'
and adds one to the number for each retry.
Version 0.15.1 released 10-January-06
* New configure options:
* ftpskippasvip: If set to a non-zero value, it instructs TclCurl
not to use the IP address the server suggests in its 227-response
to TclCurl's PASV command when TclCurl connects the data connection.
Instead TclCurl will re-use the same IP address it already uses for
the control connection. But it will use the port number from the
227-response.
* ftpfilemethod: It allows three values:
* multicwd: the default, TclCurl will do a single CWD operation
for each path part in the given URL. For deep hierarchies this
means very many commands. This is how RFC1738 says it should
be done.
* nocwd: no CWD at all is done, TclCurl will do SIZE, RETR, STOR
etc and give a full path to the server.
* singlecwd: make one CWD with the full target directory and then
operate on the file "normally".
The support for this options is still experimental, comments whether
the methods work or don't with different methods are welcome.
Likewise, the options, or their names, may change in future releases,
so they are not yet documented elsewhere.
* Bug fix: The Windows packages had defective 'doc' directories. Thanks to
Alex Hisen for letting me know.
Version 0.14.1 released 4-September-05
* New configure options:
* ingnorecontentlength: Ignore the Content-Length header. This is
useful for Apache 1.x (and similar servers) which will report
incorrect content length for files over 2 gigabytes.
* cookielist: Pass a string with a cookie. The cookie can be
either in Netscape / Mozilla format or just regular HTTP-style
header (Set-Cookie: ...) format.
'$curlHandle getinfo cookielist' will return a list of all
cookies TclCurl knows (expired ones, too).
* When posting data, you can use the new 'filecontent' option to
read a file and use its contents as data.
* Bug fix: The code to post data was filled with memory leaks, I hope
I have fixed them all.
Version 0.14.0 released 3-June-05
* BEHAVIOUR CHANGE: To set the version SSL/TLS to use with
'-sslversion' you can know use the values:
* default
The default action. When libcurl built with OpenSSL, this will
attempt to figure out the remote SSL protocol version.
Unfortunately there are a lot of ancient and broken servers in
use which cannot handle this technique and will fail to
connect. When libcurl is built with GnuTLS, this will mean SSLv3.
* tlsv1
Force TLSv1
* sslv2
Force SSLv2
* sslv3
Force SSLv3
* Bug fix: A report by Melissa Millard made me realize that the
options 'httpauth', 'proxyauth', 'ipresolve', 'ftpssl' and
'ftpsslauth' have, probably, never worked. They should now.
* I updated 'configure.in' and 'Makefile.in' to the latest versions
in Tcl's sample extension, unfortunately that's likely to introduce
some bugs, so, please, report any problems.
Version 0.13.2 released 16-April-05
* New features:
* New configure options:
* ftpaccount: When an FTP server asks for "account data"
after user name and password has been provided.
* sourceurl: When set, it enables a FTP third party transfer.
* sourcequote: Exactly like '-quote', but for the source host.
* The following options are now obsolete 'sourcehost', 'sourcepath',
'sourceport' and 'pasvhost'.
* curl::versioninfo will indicate if there is support for
SSPI.
* More information can be obtained using 'curl::getinfo':
* numconnects: to get the number of new connections
TclCurl had to create to achieve the previous transfer.
* sslengines: returns a list of the OpenSSL crypto-engines
supported.
* httpconnectcode: returns the last received proxy
response code to a CONNECT request
* Bug fix:
* Fixed the "-sourcepostquote" option.
* Daniel A. Steffen fixed a bug with parallel builds.
Version 0.12.2 released 18-October-04
* New features:
* You can now share dns and cookie information among TclCurl
handles, please check the docs for details.
* New configure option: 'ftpsslauth', you may need this option
because of servers like BSDFTPD-SSL from won't work properly
when "AUTH SSL" is issued but require "AUTH TLS" instead.
* Added three new commands to the 'curl' namespace:
* curl::easystrerror errorCode
* curl::sharestrerror errorCode
* curl::multistrerror errorCode
All three will return a string explaining what the given error
number means.
* Bug fix:
* Ralph Mitchell reported that the 'cookiejar' option wouldn't
work in the latest version, it should now.
Version 0.12.1 released 30-September-04
* New features:
* Third party ftp support, you can now transfer a file between
two different ftp servers. Check the 'ftp options' in the docs
page for details.
* A new command for curl handles 'reset' which re-initializes all
options previously set on a specified handle to the default values.
This puts back the handle to the same state as it was in when it
was just created with curl::init.
It does not change the following information kept in the handle:
live connections, the Session ID cache, the DNS cache, the cookies
and shares.
* Hooked the multi interface to Tcl's event loop, so you can have
fire-and-forget transfers:
set multiHandle [curl::multiinit]
set easyHandle [curl::init]
$easyHandle configure -file home.tar.gz \
-url http://127.0.0.1/~andres/HomePage.tar.gz
$multiHandle addhandle $easyHandle
$multiHandle auto -command "CleanUp $multiHandle $easyHandle"
This support is experimental, so any comments are welcome.
Thanks to Eric Boudaillier who answered my question about how to
do it.
* New ssl data types have been added to 'debugproc'.
* In case of error when setting post data, the error will include a
code about the nature of the error.
* Bug fix:
* The 'autoreferer' option should now work.
Version 0.12.0 released 09-July-04
* New configure options:
* '-port': Pass the number specifying what remote port to connect to,
instead of the one specified in the URL or the default port for the
used protocol.
* '-tcpnodelay': To specify whether the TCP_NODELAY option should be
set or cleared.
Setting this option will disable TCP's Nagle algorithm. The purpose
of this algorithm is to try to minimize the number of small packets
on the network.
* '-autoreferer': When enabled, TclCurl will automatically set the
'Referer:' field in requests where it follows a 'Location:' redirect.
* Bug fix:
* Thanks to Stefano Federici I noticed that the 'ftpssl' option didn't
work.
Version 0.11.0 released 04-febrary-04
* New configure options:
* 'ftpssl': You can use ftps:// URLs to explicitly switch on SSL/TSL
for the control connection and the data connection.
Alternatively you can set this option to one of these values:
* 'nope': Do not attempt to use SSL
* 'try': Try using SSL, proceed anyway otherwise.
* 'control': Use SSL for the control conecction or fail.
* 'all': Use SSL for all communication or fail.
* 'netrcfile': Pass a string containing the full path name to the
file you want to use as .netrc file. For the option to work, you
have to set the 'netrc' option to 'required'. If this option is
omitted, and 'netrc' is set, TclCurl will attempt to find the a
.netrc file in the current user's home directory.
* Bug fix: Fixed the 'netrc' option.
Version 0.10.8 released 29-december-03
* New 'configure' options:
* 'ftpresponsetimeout': Causes TclCurl to set a timeout period
on the amount of time that the server is allowed to take in
order to generate a response message for a command before the
session is considered hung.
* 'ipresolve': Allows an application to select what kind of
IP addresses to use when resolving host names. This is only
interesting when using host names that resolve addresses
using more than one version of IP.
* 'maxfilesize': Allows you to specify the maximum size
of a file to download.
* New 'getinfo' options:
* 'httpauthavail': Returns a list with the authentication method(s)
available.
* 'proxyauthavail': Returns a list with the authentication method(s)
available for your proxy athentication.
* Misc:
* 'curl::versioninfo' will now say if there is support for
asynchronus DNS and SPNEGO.
* The 'httpcode' for 'getinfo' is now called 'responsecode'
since it will now work with FTP transfers. The old option
name, while deprecated, will continue to work.
* Bug fixes:
* TclCurl still thought it was in version 0.10.4.
* Fixed the 'httpauth' option.
* The configure scripts would sometimes use the cURL in
'/usr/bin' instead of the one in '/usr/local/bin' despite
the '--with-curlprefix' tag.
Version 0.10.7 released 03-September-03
* New configure options:
* 'ftpcreatemissingdirs': If set to non-zero, TclCurl
will attempt to create any remote directory that it
fails to CWD into. CWD is the command that changes
working directory.
* 'httpauth': Set to the authentication method you want,
the available ones are:
* 'basic': HTTP Basic authentication. This is the
default choice, and the only method that is in
widespread use and supported virtually everywhere.
It sends the user name and password over the network
in plain text, easily captured by others.
* 'digest': HTTP Digest authentication. Digest
authentication is a more secure way to do
authentication over public networks than the
regular old-fashioned Basic method.
* 'gssnegotiate': HTTP GSS-Negotiate authentication.
The GSS-Negotiate method was designed by Microsoft
and is used in their web aplications. It is primarily
meant as a support for Kerberos5 authentication
but may be also used along with another authenti-
cation methods.
* 'ntlm': HTTP NTLM authentication. A proprietary
protocol invented and used by Microsoft.
* 'any':TclCurl will automaticaly select the one it
finds most secure.
* 'anysafe': It may use anything but basic, TclCurl
will automaticly select the one it finds most secure.
* 'command': Executes a Tcl command after the transfer
is done. So far it only works in blocking transfers
which is pretty much useless.
Version 0.10.5 released 21-May-03
* New configure option:
* 'ftpuseeptr': Set to non-zero, to tell TclCurl to use the EPRT
(and LPRT) command when doing active FTP downloads (which is
enabled by 'ftpport'). Using EPRT means that it will first attempt
to use EPRT and then LPRT before using PORT, if you pass zero to
this option, it will not try using EPRT or LPRT, only plain PORT
* Bug fixes:
* The multi handles couldn't store the data of more than two
easy handles.
* Using the 'progressproc' option in Windows would crash Tcl.
* The '$multiHandle active' command wasn't returning anything.
* Misc:
* Updated ssl in Windows binaries to version 0.9.7b.
* Changed the way the http reponse header is dealt with in
the 'headervar' option. Now the whole header is put into
foo(http).
************** POTENTIAL INCOMPATIBILITY **************
Version 0.10.4 released 31-March-03
* New features:
* Added 'getinfo' features to the 'curl::transfer' command.
You can now do things like:
curl::transfer -url http://www.curl.com \
-infohttpcode httpCode \
-infocontenttype contentType \
puts "Http code: $httpCode"
puts "Content type: $contentType"
* New configure option: -unrestrictedauth, a non-zero parameter
tells the extension it can continue to send authentication
(user+password) when following locations, even when hostname
changed. Note that this is meaningful only when setting
-followlocation
* The makefile now has an 'uninstall' target.
* The Windows packages are now zlib enabled.
* Added a 'packages' directory with a makefile to create the
Windows packages and the spec file for rpm.
* Bug fix:
* The configure script will no longer choke with the version
string of cURL's prereleases.
* Misc
* If there is an error, the 'curl::transfer' command will now
return the code of the error, without the 'Couldn't perform
transfer' message.
************** POTENTIAL INCOMPATIBILITY **************
* So that they have the same name in Windows and Linux, I have
changed the name of the certificate file in Windows to
'curl-ca-bundle.crt' and it will placed in the 'Windows'
directory.
************** POTENTIAL INCOMPATIBILITY **************
* Alex Khassin suggested using fully qualified in 'tclcurl.tcl'
names to prevent problems with namespaces.
Version 0.10.3 released 30-January-03
* New configure option:
* 'http200alieases': To pass a list of aliases to be treated as valid
HTTP 200 responses.
* Bug fixes:
* When using '-headervar' in Windows you could end up with carriage
returns in the name of the header.
* Julian let me know that TclCurl would crash when used in a thread
enabled Tcl.
* Enhancements:
* Since compiling TclCurl in Windows is a real pain, I will provide
more packages for it, thread and ssl enabled.
* Alex Khassin has written instructions on how to get TclCurl to work
with AOLSever.
Version 0.10.1 released 14-October-02
* New configure options:
* 'proxytype': Allows you to set type of the proxy. Available options
are 'http' and 'socks5', with the HTTP one being default.
* 'encoding': TclCurl can now request compressed contents using the
'deflate' method.
* 'buffersize': To set prefered size for the receive buffer in TclCurl,
so that the write callback is called more often with smaller chunks.
* 'nosignal': Tells TclCurl not use any functions that install signal
handlers or any functions that cause signals to be sent to the process.
* New command:
* 'curl::versioninfo': Returns information about various run-time
features in TclCurl.
* Bug fixes:
* Fixed to 'buffer' option to post data.
* Asif Haswarey reported that '--with-curlinclude' wouldn't work.
* The multi interface examples suddenly stopped working, they
should now.
Version 0.9.8 released 25-June-02
* Support for libcurl's multi interface, the main features are:
* Enable a "pull" interface. The application that uses TclCurl
decides where and when to get/send data.
* Enable multiple simultaneous transfers in the same thread
without making it complicated for the application.
* Keep Tk GUIs 'alive' while transfers are taking place.
* New 'httppost' options
* 'bufferName' and 'buffer', the contents of buffer will be sent
to the server as if they were a file whose name is in bufferName,
please check the 'httpBufferPost.tcl' example.
* New 'getinfo' options
* redirectime: Returns the total time, in seconds, it took for all
redirection steps including name lookup, connect, pretransfer and
transfer before the final transaction was started, it returns the
complete execution time for multiple redirections.
* redirectcount: Returns the total number of redirections that were
actually followed.
Version 0.9.6 released 30-April-02
* New configure options:
* dnscachetimeout, to set the timeout in seconds for keeping the name resolves
in memory.
* dnsuseglobalcache, if set to '1' the DNS cache will be shared among
curl handles.
* debugproc, to set a procedure that will receive the debug data
produced by the 'verbose' option.
* Jonathan Matthew found and fixed a seg fault when you used
the 'httpheader' option twice with the same handle.
* The configure scripts saw more work in this release:
* I merged the latest changes to the TEA sample extension by
Jeff Hobbs.
* Suresh K. Sastry found and fixed an incompatibility with Solaris.
* And I hope I have not forgotten any 'DESTDIR' this time.
Version 0.9.5 released 01-April-2002
* I have adapted the configure scripts to the new TEA scripts released by
Jeff Hobbs, for example, now it will compile 'out of the box' for freeBSD
systems (well, you may need to use '--with-curlprefix' and '--with-curlinclude')
* New configure option:
* prequote: use it to pass a list of ftp commands to execute *just before*
the transfer.
* New getinfo option:
* contenttype: if the servers bothers to tell you, this will return the type
of the downloadad object.
* Bug fix: 'curl::transfer' will return '0' if the transfer was successful.
*** POTENTIAL INCOMPATIBILITY ***
Version 0.9.3 released 29-Jan-2002
* Bug fix: There should no more seg faults because of trailing options
in configure commands.
* Bug fix: Binary transfer weren't done right in Windows, thanks to
Peter Waltenberg and Darren Blee for the report.
* TclCurl now supports OpenSSL engines, which allow you to keep your private
key stored in external hardware.
In order to manage this there are a few new configure options:
* sslcerttype: Set SSL cert type (PEM/DER).
* sslkey: Set SSL private key (file).
* sslkeytype: Set SSL key type (PEM/DER/ENG).
* sslkeypasswd: Set the passphrase for your private key.
* sslengine: Set the name of the crypto engine.
* sslenginedefault: Set the default engine.
* You can now add a set of headers for a particular part in a
multipart/form-post using the 'contentheader' option.
* It is now possible to execute commands in ftp servers without
transfering files, you have to set 'nobody' to '1' and 'header' to
'0'.

458
Makefile.in Executable file
View File

@ -0,0 +1,458 @@
# Makefile.in --
#
# This file is a Makefile for Sample TEA Extension. If it has the name
# "Makefile.in" then it is a template for a Makefile; to generate the
# actual Makefile, run "./configure", which is a configuration script
# generated by the "autoconf" program (constructs like "@foo@" will get
# replaced in the actual Makefile.
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.66 2009/03/18 18:39:42 stwo Exp $
#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================
#SAMPLE_NEW_VAR = @SAMPLE_NEW_VAR@
#========================================================================
# Nothing of the variables below this line should need to be changed.
# Please check the TARGETS section below to make sure the make targets
# are correct.
#========================================================================
#========================================================================
# The names of the source files is defined in the configure script.
# The object files are used for linking into the final library.
# This will be used when a dist target is added to the Makefile.
# It is not important to specify the directory, as long as it is the
# $(srcdir) or in the generic, win or unix subdirectory.
#========================================================================
PKG_SOURCES = @PKG_SOURCES@
TCLCURL_SCRIPTS = @TCLCURL_SCRIPTS@
PKG_OBJECTS = @PKG_OBJECTS@
PKG_STUB_SOURCES = @PKG_STUB_SOURCES@
PKG_STUB_OBJECTS = @PKG_STUB_OBJECTS@
#========================================================================
# PKG_TCL_SOURCES identifies Tcl runtime files that are associated with
# this package that need to be installed, if any.
#========================================================================
PKG_TCL_SOURCES = @PKG_TCL_SOURCES@
#========================================================================
# This is a list of public header files to be installed, if any.
#========================================================================
PKG_HEADERS = @PKG_HEADERS@
#========================================================================
# "PKG_LIB_FILE" refers to the library (dynamic or static as per
# configuration options) composed of the named objects.
#========================================================================
PKG_LIB_FILE = @PKG_LIB_FILE@
PKG_STUB_LIB_FILE = @PKG_STUB_LIB_FILE@
lib_BINARIES = $(PKG_LIB_FILE)
BINARIES = $(lib_BINARIES)
SHELL = @SHELL@
srcdir = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
libdir = @libdir@
includedir = @includedir@
datarootdir = @datarootdir@
datadir = @datadir@
mandir = @mandir@
DESTDIR =
PKG_DIR = $(PACKAGE_NAME)$(PACKAGE_VERSION)
pkgdatadir = $(datadir)/$(PKG_DIR)
pkglibdir = $(libdir)/$(PKG_DIR)
pkgincludedir = $(includedir)/$(PKG_DIR)
top_builddir = .
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_LIBRARY = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
CC = @CC@
CFLAGS_DEFAULT = @CFLAGS_DEFAULT@
CFLAGS_WARNING = @CFLAGS_WARNING@
EXEEXT = @EXEEXT@
LDFLAGS_DEFAULT = @LDFLAGS_DEFAULT@
MAKE_LIB = @MAKE_LIB@
MAKE_SHARED_LIB = @MAKE_SHARED_LIB@
MAKE_STATIC_LIB = @MAKE_STATIC_LIB@
MAKE_STUB_LIB = @MAKE_STUB_LIB@
OBJEXT = @OBJEXT@
RANLIB = @RANLIB@
RANLIB_STUB = @RANLIB_STUB@
SHLIB_CFLAGS = @SHLIB_CFLAGS@
SHLIB_LD = @SHLIB_LD@
SHLIB_LD_LIBS = @SHLIB_LD_LIBS@
STLIB_LD = @STLIB_LD@
#TCL_DEFS = @TCL_DEFS@
TCL_BIN_DIR = @TCL_BIN_DIR@
TCL_SRC_DIR = @TCL_SRC_DIR@
#TK_BIN_DIR = @TK_BIN_DIR@
#TK_SRC_DIR = @TK_SRC_DIR@
# Not used, but retained for reference of what libs Tcl required
#TCL_LIBS = @TCL_LIBS@
#========================================================================
# TCLLIBPATH seeds the auto_path in Tcl's init.tcl so we can test our
# package without installing. The other environment variables allow us
# to test against an uninstalled Tcl. Add special env vars that you
# require for testing here (like TCLX_LIBRARY).
#========================================================================
EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR)
#EXTRA_PATH = $(top_builddir):$(TCL_BIN_DIR):$(TK_BIN_DIR)
TCLLIBPATH = $(top_builddir)
TCLSH_ENV = TCL_LIBRARY=`@CYGPATH@ $(TCL_SRC_DIR)/library`
PKG_ENV = @LD_LIBRARY_PATH_VAR@="$(EXTRA_PATH):$(@LD_LIBRARY_PATH_VAR@)" \
PATH="$(EXTRA_PATH):$(PATH)" \
TCLLIBPATH="$(TCLLIBPATH)"
TCLSH_PROG = @TCLSH_PROG@
TCLSH = $(PKG_ENV) $(TCLSH_ENV) $(TCLSH_PROG)
#WISH_ENV = TK_LIBRARY=`@CYGPATH@ $(TK_SRC_DIR)/library`
#WISH_PROG = @WISH_PROG@
#WISH = $(PKG_ENV) $(TCLSH_ENV) $(WISH_ENV) $(WISH_PROG)
SHARED_BUILD = @SHARED_BUILD@
INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@
#INCLUDES = @PKG_INCLUDES@ @TCL_INCLUDES@ @TK_INCLUDES@ @TK_XINCLUDES@
PKG_CFLAGS = @PKG_CFLAGS@
# TCL_DEFS is not strictly need here, but if you remove it, then you
# must make sure that configure.in checks for the necessary components
# that your library may use. TCL_DEFS can actually be a problem if
# you do not compile with a similar machine setup as the Tcl core was
# compiled with.
#DEFS = $(TCL_DEFS) @DEFS@ $(PKG_CFLAGS)
DEFS = @DEFS@ $(PKG_CFLAGS)
# Move pkgIndex.tcl to 'BINARIES' var if it is generated in the Makefile
CONFIG_CLEAN_FILES = Makefile pkgIndex.tcl
CLEANFILES = @CLEANFILES@
CPPFLAGS = @CPPFLAGS@
LIBS = @PKG_LIBS@ @LIBS@
AR = @AR@
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
#========================================================================
# Start of user-definable TARGETS section
#========================================================================
#========================================================================
# TEA TARGETS. Please note that the "libraries:" target refers to platform
# independent files, and the "binaries:" target inclues executable programs and
# platform-dependent libraries. Modify these targets so that they install
# the various pieces of your package. The make and install rules
# for the BINARIES that you specified above have already been done.
#========================================================================
all: binaries libraries doc
#========================================================================
# The binaries target builds executable programs, Windows .dll's, unix
# shared/static libraries, and any other platform-dependent files.
# The list of targets to build for "binaries:" is specified at the top
# of the Makefile, in the "BINARIES" variable.
#========================================================================
binaries: $(BINARIES)
libraries:
scripts: $(TCLCURL_SCRIPTS)
#========================================================================
# Your doc target should differentiate from doc builds (by the developer)
# and doc installs (see install-doc), which just install the docs on the
# end user machine when building from source.
#========================================================================
doc:
install: all install-binaries install-scripts install-libraries install-doc
install-binaries: binaries install-lib-binaries install-bin-binaries
#========================================================================
# This rule installs platform-independent files, such as header files.
# The list=...; for p in $$list handles the empty list case x-platform.
#========================================================================
install-libraries: libraries
@mkdir -p $(DESTDIR)$(includedir)
@echo "Installing header files in $(DESTDIR)$(includedir)"
@list='$(PKG_HEADERS)'; for i in $$list; do \
echo "Installing $(srcdir)/$$i" ; \
$(INSTALL_DATA) $(srcdir)/$$i $(DESTDIR)$(includedir) ; \
done;
#========================================================================
# Install documentation. Unix manpages should go in the $(mandir)
# directory.
#========================================================================
install-doc: doc
@mkdir -p $(DESTDIR)$(mandir)/mann
@echo "Installing documentation in $(DESTDIR)$(mandir)"
@list='$(srcdir)/doc/*.n'; for i in $$list; do \
echo "Installing $$i"; \
rm -f $(DESTDIR)$(mandir)/mann/`basename $$i`; \
gzip $$i; \
$(INSTALL_DATA) $$i.gz $(DESTDIR)$(mandir)/mann ; \
gunzip $$i.gz; \
done
test: binaries libraries
$(TCLSH) `@CYGPATH@ $(srcdir)/tests/all.tcl` $(TESTFLAGS)
shell: binaries libraries
@$(TCLSH) $(SCRIPT)
gdb:
$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)
depend:
#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above. That will ensure that this target is built when you
# run "make binaries".
#
# The $(PKG_OBJECTS) objects are created and linked into the final
# library. In most cases these object files will correspond to the
# source files above.
#========================================================================
$(PKG_LIB_FILE): $(PKG_OBJECTS)
-rm -f $(PKG_LIB_FILE)
${MAKE_LIB}
$(RANLIB) $(PKG_LIB_FILE)
$(PKG_STUB_LIB_FILE): $(PKG_STUB_OBJECTS)
-rm -f $(PKG_STUB_LIB_FILE)
${MAKE_STUB_LIB}
$(RANLIB_STUB) $(PKG_STUB_LIB_FILE)
#========================================================================
# We need to enumerate the list of .c to .o lines here.
#
# In the following lines, $(srcdir) refers to the toplevel directory
# containing your extension. If your sources are in a subdirectory,
# you will have to modify the paths to reflect this:
#
# sample.$(OBJEXT): $(srcdir)/generic/sample.c
# $(COMPILE) -c `@CYGPATH@ $(srcdir)/generic/sample.c` -o $@
#
# Setting the VPATH variable to a list of paths will cause the makefile
# to look into these paths when resolving .c to .obj dependencies.
# As necessary, add $(srcdir):$(srcdir)/compat:....
#========================================================================
VPATH = $(srcdir):$(srcdir)/generic:$(srcdir)/unix:$(srcdir)/win
.c.@OBJEXT@:
$(COMPILE) -c `@CYGPATH@ $<` -o $@
#========================================================================
# Distribution creation
# You may need to tweak this target to make it work correctly.
#========================================================================
#COMPRESS = tar cvf $(PKG_DIR).tar $(PKG_DIR); compress $(PKG_DIR).tar
COMPRESS = gtar zcvf $(PKG_DIR).tar.gz $(PKG_DIR)
DIST_ROOT = /tmp/dist
DIST_DIR = $(DIST_ROOT)/$(PKG_DIR)
dist-clean:
rm -rf $(DIST_DIR) $(DIST_ROOT)/$(PKG_DIR).tar.*
dist: dist-clean
mkdir -p $(DIST_DIR)
cp -p $(srcdir)/ChangeLog $(srcdir)/README* $(srcdir)/license* \
$(srcdir)/aclocal.m4 $(srcdir)/configure $(srcdir)/*.in \
$(DIST_DIR)/
chmod 664 $(DIST_DIR)/Makefile.in $(DIST_DIR)/aclocal.m4
chmod 775 $(DIST_DIR)/configure $(DIST_DIR)/configure.in
for i in $(srcdir)/*.[ch]; do \
if [ -f $$i ]; then \
cp -p $$i $(DIST_DIR)/ ; \
fi; \
done;
mkdir $(DIST_DIR)/tclconfig
cp $(srcdir)/tclconfig/install-sh $(srcdir)/tclconfig/tcl.m4 \
$(DIST_DIR)/tclconfig/
chmod 664 $(DIST_DIR)/tclconfig/tcl.m4
chmod +x $(DIST_DIR)/tclconfig/install-sh
list='demos doc generic library mac tests unix win'; \
for p in $$list; do \
if test -d $(srcdir)/$$p ; then \
mkdir $(DIST_DIR)/$$p; \
cp -p $(srcdir)/$$p/*.* $(DIST_DIR)/$$p/; \
fi; \
done
(cd $(DIST_ROOT); $(COMPRESS);)
#========================================================================
# End of user-definable section
#========================================================================
#========================================================================
# Don't modify the file to clean here. Instead, set the "CLEANFILES"
# variable in configure.in
#========================================================================
clean:
-test -z "$(BINARIES)" || rm -f $(BINARIES)
-rm -f *.$(OBJEXT) core *.core
-test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean: clean
-rm -f *.tab.c
-rm -f $(CONFIG_CLEAN_FILES)
-rm -f config.cache config.log config.status
#========================================================================
# Install binary object libraries. On Windows this includes both .dll and
# .lib files. Because the .lib files are not explicitly listed anywhere,
# we need to deduce their existence from the .dll file of the same name.
# Library files go into the lib directory.
# In addition, this will generate the pkgIndex.tcl
# file in the install location (assuming it can find a usable tclsh shell)
#
# You should not have to modify this target.
#========================================================================
install-lib-binaries: binaries
@mkdir -p $(DESTDIR)$(pkglibdir)
@list='$(lib_BINARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p"; \
$(INSTALL_LIBRARY) $$p $(DESTDIR)$(pkglibdir)/$$p; \
stub=`echo $$p|sed -e "s/.*\(stub\).*/\1/"`; \
if test "x$$stub" = "xstub"; then \
echo " $(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p"; \
$(RANLIB_STUB) $(DESTDIR)$(pkglibdir)/$$p; \
else \
echo " $(RANLIB) $(DESTDIR)$(pkglibdir)/$$p"; \
$(RANLIB) $(DESTDIR)$(pkglibdir)/$$p; \
fi; \
ext=`echo $$p|sed -e "s/.*\.//"`; \
if test "x$$ext" = "xdll"; then \
lib=`basename $$p|sed -e 's/.[^.]*$$//'`.lib; \
if test -f $$lib; then \
echo " $(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib"; \
$(INSTALL_DATA) $$lib $(DESTDIR)$(pkglibdir)/$$lib; \
fi; \
fi; \
fi; \
done
@list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
if test -f $(srcdir)/$$p; then \
destp=`basename $$p`; \
echo " Install $$destp $(DESTDIR)$(pkglibdir)/$$destp"; \
$(INSTALL_DATA) $(srcdir)/$$p $(DESTDIR)$(pkglibdir)/$$destp; \
fi; \
done
@if test "x$(SHARED_BUILD)" = "x1"; then \
echo " Install pkgIndex.tcl $(DESTDIR)$(pkglibdir)"; \
$(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(pkglibdir); \
fi
#========================================================================
# Install binary executables (e.g. .exe files and dependent .dll files)
# This is for files that must go in the bin directory (located next to
# wish and tclsh), like dependent .dll files on Windows.
#
# You should not have to modify this target, except to define bin_BINARIES
# above if necessary.
#========================================================================
install-bin-binaries: binaries
@mkdir -p $(DESTDIR)$(bindir)
@list='$(bin_BINARIES)'; for p in $$list; do \
if test -f $$p; then \
echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p"; \
$(INSTALL_PROGRAM) $$p $(DESTDIR)$(bindir)/$$p; \
fi; \
done
#========================================================================
# This rule installs the scripts that are part of TclCurl.
#========================================================================
install-scripts: scripts
@for i in generic/$(TCLCURL_SCRIPTS) ; do \
echo "Installing $$i" ; \
$(INSTALL_DATA) $$i $(DESTDIR)$(pkglibdir) ; \
done;
.SUFFIXES: .c .$(OBJEXT)
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \
&& CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) ./config.status
uninstall-binaries:
list='$(lib_BINARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
done
list='$(PKG_TCL_SOURCES)'; for p in $$list; do \
p=`basename $$p`; \
rm -f $(DESTDIR)$(pkglibdir)/$$p; \
done
list='$(bin_BINARIES)'; for p in $$list; do \
rm -f $(DESTDIR)$(bindir)/$$p; \
done
checkAutoPath:
@if test "x$(DESTDIR)$(libdir)" != x/usr; then \
echo "Checking Tcl's autoPath variable" ; \
$(TCLSH_PROG) $(srcdir)/checkAutoPath.tcl $(DESTDIR)$(libdir); \
fi;
.PHONY: all binaries clean depend distclean doc install libraries test
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

59
ReadMe.txt Executable file
View File

@ -0,0 +1,59 @@
TclCurl - get a URL with FTP, TELNET, LDAP, DICT, FILE, HTTP or HTTPS syntax.
TclCurl gives the Tcl programmer access to the facilities of libcurl, for more information
about what libcurl is capable of check http://curl.haxx.se.
To make type:
./configure ?--enable-threads?
make
make install
The configure script will deduce $PREFIX from the tcl installation.
The generated Makefile uses the file $PREFIX/lib/tclConfig.sh that was left by
the make of tcl for most of its configuration parameters.
There is another README to explain how to compile in Windows.
Troubleshooting
If you are running Red Hat or Fedora and you are compiling from source,
make sure the directory '/usr/local/lib' is listed in '/etc/ld.so.conf',
if it isn't add it before installing cURL.
If the configure script doesn't detect Tcl even though it is there, it
is probably because there is no 'tclConfig.sh' file, maybe you need
to install a 'tcl-devel' package or maybe it would be a good idea
to download the latest version, and install that.
Usage:
package require TclCurl
set curlHandle [curl::init]
curlHandle perform
curlHandle getinfo curlinfo_option
curlHandle duphandle
curlhandle cleanup
curl::transfer
curl::version
curl::escape url
curl::unescape url
curl::curlConfig option
Check the man page for details.
Written by: Andres Garcia (fandom@telefonica.net)
Use at your own risk. No support.
BSD like license, check 'license.terms' for details.

113
ReadMeW32.txt Executable file
View File

@ -0,0 +1,113 @@
To install TclCurl in Windows you simply have to double-click on the 'SetUp.tcl'
file, provided you already have Tcl/Tk installed, the script will take care of
everything.
By the way, Tcl's console doesn't seem to like the output sent by TclCurl,
for example, if you type:
curl::transfer -url www.scriptics.com
you will only get an error, you will have to dump it to a file with the
'file' option, read it in to a variable with 'bodyvar', use Cygwin's console
or use tkCon from msys-mingw.
Compiling TclCurl in Windows
First of all a little disclaimer:
I know nothing about Windows programming, no kidding, not a thing,
zip, zilch, nada. I can barely manage using tools, like Tcl/Tk and
gcc, whose origin is in the Unix world, but that is just about it, so
if you think that the following is just plain stupid, that is because
it probably is, but in that case, don't forget to tell me all about it.
To compile TclCurl in Windows you are going to need several things:
- A msys-mingw enviroment, you can get it at SourceForge:
http://sourceforge.net/projects/tcl/
or you can get MinGW and Msys from their project page:
http://sourceforge.net/projects/mingw/
- Since you are already at Tcl's page at SF, you can download the
lastest Tcl version, 8.4.13 at this writing. (These instructions won't
work with 8.3.x versions)
- Download zlib from http://www.gzip.org/zlib/
- Download bc from http://gnuwin32.sourceforge.net/packages/bc.htm and
install it.
- Extract Tcl, cURL, zlib and TclCurl in the same directory.
- Copy the 'tclcurl.mk' file in TclCurl/packages/windows to this directory.
- Start msys, go to the directory and type:
$ make -f tclcurl.mk tclcurl-plain
This command will compile and install Tcl, zlib, cURL and TclCurl, if
you want to have Tk though, you will have to install it yourself.
After compiling and installing all the elements, the make file will
try to create the self-extracting archive using 'rar', if you don't
have it installed it will fail, but don't worry, everything is already
installed. If you have rar and you want to create the archives, don't
forget to change the path at the end of the make file.
- If you want to use TclCurl with the Tcl/Tk you have installed in
c:\Program Files or anywhere else, copy the directory
'/usr/local/lib/tclcurl0.110' to 'c:\Program Files\Tcl\lib'
- And now you should have a working TclCurl, run Tcl/Tk and type:
$ package require TclCurl.
Tcl should return TclCurl's version, if it doesn't something went wrong,
could you please tell me?
- Wish console doesn't really like TclCurl, so if you do:
$ curl::transfer -url slashdot.org
It will return a '0' to tell you that the transfer was successful, but it will
show you nothing, you will have to dump the page into a file to be able to read
it or use Cygwin's console.
Compiling TclCurl with threads support
You have to do basically the same thing, except that the command to compile is:
$ make -f tclcurl.mk tclcurl-threaded
Compiling TclCurl with SSL support
Since 1.0.0 openssl is easier to compile, you can find the instructions to it in
the INSTALL.W32 file in the openssl tarball.
You can get the cacert.pem at http://curl.haxx.se/ca/, you need to put in the
directory from which you are going to compile
- $ make -f tclcurl.mk tclcurl-ssl
- If you want to have threads support:
- $ make -f tclcurl.mk tclcurl-threaded-ssl
Sounds like a lot of work to run a little extension, but then again, you could
have downloaded the self-extracting archive file.
Share the wonders,
Andres
fandom@telefonica.net

9
aclocal.m4 vendored Executable file
View File

@ -0,0 +1,9 @@
#
# Include the TEA standard macro set
#
builtin(include,tclconfig/tcl.m4)
#
# Add here whatever m4 macros you want to define for your package
#

17
checkAutoPath.tcl Executable file
View File

@ -0,0 +1,17 @@
# This file checks that the directory where TclCurl is going to be
# installed is actually in the auto_path variable, if it isn't it
# modifies 'init.tcl'.
set tclCurlDir [lindex $argv 0]
set initTclDir [lindex $argv 1]
set initFile [file join $tcl_library init.tcl]
if {[file writable $initFile]==0} exit
if {[lsearch $auto_path $tclCurlDir]==-1} {
set handle [open "$initFile" a]
puts $handle "\nlappend auto_path $tclCurlDir\n"
}
exit

9204
configure vendored Executable file

File diff suppressed because it is too large Load Diff

248
configure.in Executable file
View File

@ -0,0 +1,248 @@
#!/bin/bash -norc
dnl This file is an input file used by the GNU "autoconf" program to
dnl generate the file "configure", which is run during Tcl installation
dnl to configure the system for the local environment.
#
# RCS: @(#) $Id: configure.in,v 1.48 2008/11/05 00:13:00 hobbs Exp $
#-----------------------------------------------------------------------
# Sample configure.in for Tcl Extensions. The only places you should
# need to modify this file are marked by the string __CHANGE__
#-----------------------------------------------------------------------
#-----------------------------------------------------------------------
# __CHANGE__
# Set your package name and version numbers here.
#
# This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION
# set as provided. These will also be added as -D defs in your Makefile
# so you can encode the package version directly into the source files.
#-----------------------------------------------------------------------
AC_INIT([TclCurl], [7.22.0])
#--------------------------------------------------------------------
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
# This will define a ${TEA_PLATFORM} variable == "unix" or "windows"
# as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE.
#--------------------------------------------------------------------
TEA_INIT([3.7])
AC_CONFIG_AUX_DIR(tclconfig)
#--------------------------------------------------------------------
# Load the tclConfig.sh file
#--------------------------------------------------------------------
TEA_PATH_TCLCONFIG
TEA_LOAD_TCLCONFIG
#--------------------------------------------------------------------
# Load the tkConfig.sh file if necessary (Tk extension)
#--------------------------------------------------------------------
#TEA_PATH_TKCONFIG
#TEA_LOAD_TKCONFIG
#-----------------------------------------------------------------------
# Handle the --prefix=... option by defaulting to what Tcl gave.
# Must be called after TEA_LOAD_TCLCONFIG and before TEA_SETUP_COMPILER.
#-----------------------------------------------------------------------
TEA_PREFIX
#-----------------------------------------------------------------------
# Standard compiler checks.
# This sets up CC by using the CC env var, or looks for gcc otherwise.
# This also calls AC_PROG_CC, AC_PROG_INSTALL and a few others to create
# the basic setup necessary to compile executables.
#-----------------------------------------------------------------------
TEA_SETUP_COMPILER
#-----------------------------------------------------------------------
# __CHANGE__
# Specify the C source files to compile in TEA_ADD_SOURCES,
# public headers that need to be installed in TEA_ADD_HEADERS,
# stub library C source files to compile in TEA_ADD_STUB_SOURCES,
# and runtime Tcl library files in TEA_ADD_TCL_SOURCES.
# This defines PKG(_STUB)_SOURCES, PKG(_STUB)_OBJECTS, PKG_HEADERS
# and PKG_TCL_SOURCES.
#-----------------------------------------------------------------------
TEA_ADD_SOURCES([tclcurl.c multi.c])
TCLCURL_SCRIPTS=tclcurl.tcl
AC_SUBST(TCLCURL_SCRIPTS)
#--------------------------------------------------------------------
# Find libcurl, if it's not present, it makes no sense to compile
# this.
#--------------------------------------------------------------------
AC_ARG_WITH(curlprefix,
[ --with-curlprefix base directory for the cURL install '/usr', '/usr/local',...],
[
curlprefix=$withval
curlpath=$curlprefix/bin
AC_CHECK_PROG(curl,curl,yes,no,$curlpath)
if test "x$curl" = xno ; then
AC_MSG_ERROR([can not find cURL in $curlpath])
fi
],[
AC_CHECK_PROG(curl,curl-config,yes,no)
if test "x$curl" = xno ; then
AC_MSG_ERROR([can not find cURL or libcurl... go to http://curl.haxx.se/ to download and then install it first])
else
curlprefix=`curl-config --prefix`
curlpath=$curlprefix/bin
fi
])
AC_ARG_WITH(curlinclude,
[ --with-curlinclude directory containing the public libcurl header files],[
TEA_ADD_INCLUDES([-I$withval])
curlinclude=$withval
],
[
TEA_ADD_INCLUDES([-I$curlprefix/include])
curlinclude=$curlprefix/include
])
AC_CHECK_HEADER(curl/curl.h,headercurl=yes, headercurl=no)
if test "x$headercurl" = xno ; then
AC_MSG_CHECKING([checking for headers at $curlinclude])
if test [ ! -r $curlinclude/curl/curl.h ] ; then
AC_MSG_ERROR([cURL headers not found, you may need to install a curl-devel package])
fi
AC_MSG_RESULT([found])
fi
AC_ARG_WITH(libcurl,
[ --with-libcurl directory containing libcurl],[
TEA_ADD_LIBS([-L$withval])
],
[
TEA_ADD_LIBS([-L$curlprefix/lib])
])
AC_MSG_CHECKING([if libcurl version is recent enough])
CURL_VERSION=`$curlpath/curl-config --checkfor 7.21.7`
if test "${CURL_VERSION}" != "" ; then
echo ${CURL_VERSION}
AC_MSG_ERROR([libcurl version too old, please upgrade])
fi
AC_MSG_RESULT(yes)
TEA_ADD_LIBS([`$curlpath/curl-config --libs`])
#--------------------------------------------------------------------
# __CHANGE__
# A few miscellaneous platform-specific items:
#
# Define a special symbol for Windows (BUILD_sample in this case) so
# that we create the export library with the dll.
#
# Windows creates a few extra files that need to be cleaned up.
# You can add more files to clean if your extension creates any extra
# files.
#
# TEA_ADD_* any platform specific compiler/build info here.
#--------------------------------------------------------------------
# Add pkgIndex.tcl if it is generated in the Makefile instead of ./configure
# and change Makefile.in to move it from CONFIG_CLEAN_FILES to BINARIES var.
#CLEANFILES="pkgIndex.tcl"
if test "${TEA_PLATFORM}" = "windows" ; then
AC_DEFINE(BUILD_sample, 1, [Build windows export dll])
CLEANFILES="$CLEANFILES *.lib *.dll *.exp *.ilk *.pdb vc*.pch"
#TEA_ADD_SOURCES([win/winFile.c])
#TEA_ADD_INCLUDES([-I\"$(${CYGPATH} ${srcdir}/win)\"])
else
# Ensure no empty else clauses
:
#TEA_ADD_SOURCES([unix/unixFile.c])
#TEA_ADD_LIBS([-lsuperfly])
fi
AC_SUBST(CLEANFILES)
#--------------------------------------------------------------------
# __CHANGE__
# Choose which headers you need. Extension authors should try very
# hard to only rely on the Tcl public header files. Internal headers
# contain private data structures and are subject to change without
# notice.
# This MUST be called after TEA_LOAD_TCLCONFIG / TEA_LOAD_TKCONFIG
#--------------------------------------------------------------------
TEA_PUBLIC_TCL_HEADERS
#TEA_PRIVATE_TCL_HEADERS
#TEA_PUBLIC_TK_HEADERS
#TEA_PRIVATE_TK_HEADERS
#TEA_PATH_X
#--------------------------------------------------------------------
# Check whether --enable-threads or --disable-threads was given.
# This auto-enables if Tcl was compiled threaded.
#--------------------------------------------------------------------
TEA_ENABLE_THREADS
#--------------------------------------------------------------------
# The statement below defines a collection of symbols related to
# building as a shared library instead of a static library.
#--------------------------------------------------------------------
TEA_ENABLE_SHARED
#--------------------------------------------------------------------
# This macro figures out what flags to use with the compiler/linker
# when building shared/static debug/optimized objects. This information
# can be taken from the tclConfig.sh file, but this figures it all out.
#--------------------------------------------------------------------
TEA_CONFIG_CFLAGS
#--------------------------------------------------------------------
# Set the default compiler switches based on the --enable-symbols option.
#--------------------------------------------------------------------
TEA_ENABLE_SYMBOLS
#--------------------------------------------------------------------
# Everyone should be linking against the Tcl stub library. If you
# can't for some reason, remove this definition. If you aren't using
# stubs, you also need to modify the SHLIB_LD_LIBS setting below to
# link against the non-stubbed Tcl library. Add Tk too if necessary.
#--------------------------------------------------------------------
AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs])
#AC_DEFINE(USE_TK_STUBS, 1, [Use Tk stubs])
#--------------------------------------------------------------------
# This macro generates a line to use when building a library. It
# depends on values set by the TEA_ENABLE_SHARED, TEA_ENABLE_SYMBOLS,
# and TEA_LOAD_TCLCONFIG macros above.
#--------------------------------------------------------------------
TEA_MAKE_LIB
#--------------------------------------------------------------------
# Determine the name of the tclsh and/or wish executables in the
# Tcl and Tk build directories or the location they were installed
# into. These paths are used to support running test cases only,
# the Makefile should not be making use of these paths to generate
# a pkgIndex.tcl file or anything else at extension build time.
#--------------------------------------------------------------------
TEA_PROG_TCLSH
#TEA_PROG_WISH
#--------------------------------------------------------------------
# Finally, substitute all of the various values into the Makefile.
# You may alternatively have a special pkgIndex.tcl.in or other files
# which require substituting th AC variables in. Include these here.
#--------------------------------------------------------------------
AC_OUTPUT([Makefile pkgIndex.tcl])

127
doc/OpenSSL-LICENSE.txt Executable file
View File

@ -0,0 +1,127 @@
LICENSE ISSUES
==============
The OpenSSL toolkit stays under a dual license, i.e. both the conditions of
the OpenSSL License and the original SSLeay license apply to the toolkit.
See below for the actual license texts. Actually both licenses are BSD-style
Open Source licenses. In case of any license issues related to OpenSSL
please contact openssl-core@openssl.org.
OpenSSL License
---------------
/* ====================================================================
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
*
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
* endorse or promote products derived from this software without
* prior written permission. For written permission, please contact
* openssl-core@openssl.org.
*
* 5. Products derived from this software may not be called "OpenSSL"
* nor may "OpenSSL" appear in their names without prior written
* permission of the OpenSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the OpenSSL Project
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================
*
* This product includes cryptographic software written by Eric Young
* (eay@cryptsoft.com). This product includes software written by Tim
* Hudson (tjh@cryptsoft.com).
*
*/
Original SSLeay License
-----------------------
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
* by Eric Young (eay@cryptsoft.com).
* The implementation was written so as to conform with Netscapes SSL.
*
* This library is free for commercial and non-commercial use as long as
* the following conditions are aheared to. The following conditions
* apply to all code found in this distribution, be it the RC4, RSA,
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
* included with this distribution is covered by the same copyright terms
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
*
* Copyright remains Eric Young's, and as such any Copyright notices in
* the code are not to be removed.
* If this package is used in a product, Eric Young should be given attribution
* as the author of the parts of the library used.
* This can be in the form of a textual message at program startup or
* in documentation (online or textual) provided with the package.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* "This product includes cryptographic software written by
* Eric Young (eay@cryptsoft.com)"
* The word 'cryptographic' can be left out if the rouines from the library
* being used are not cryptographic related :-).
* 4. If you include any Windows specific code (or a derivative thereof) from
* the apps directory (application code) you must include an acknowledgement:
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
*
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* The licence and distribution terms for any publically available version or
* derivative of this code cannot be changed. i.e. this code cannot simply be
* copied and put under another distribution licence
* [including the GNU Public Licence.]
*/

64
doc/aolserver.txt Executable file
View File

@ -0,0 +1,64 @@
There are a number of issues with namespaces in AOLserver 3.x, which I believe
are fixed in 4.0, which should be released within a few months. But in the
meantime this is what we've had to do for AOLserver 3.2 on Windows 2000.
Alex Khassin
1. Under [ns_library shared] directory, create a directory called
packages.
2. Register this directory as a Tcl module in nsd.tcl:
ns_section "ns/server/${servername}/modules"
ns_param packages Tcl
3. Place each package into a subdirectory of the same name as the
package name (i.e. [ns_library shared]/packages/TclCurl)
4. Copy S:\NaviSoft\Server\modules\tcl\am\packages.init.tcl to the
[ns_library shared]/packages directory and rename to just init.tcl
5. Under AOLserver 4.x (and hopefully in 3.5.x) add to the bottom
of this file appropriate commands to register each package:
_am_pregister shared <packageName>
6. In your code, when you need to use a particular package, instead
of 'package require <packageName>', execute 'am_pinit <packageName>'
7. This will use the existing package registration under AOLserver
4.x and, under AOLserver 3.2, it will first register the package
in this interpreter and then use it.
8. This is necessary because in AOLserver 3.2, namespaces aren't
properly imported into child interpreters.
Currently dnscrub.com is set up like this for TclCurl and it works.
Example usage:
am_pinit TclCurl
curl::transfer -url http://am.net/index.htm -file d:/test.htm
FYI, the code for am_pinit and _am_pregister procs:
proc am_pinit {package} {
# AOLserver 3.2 package/namespace-handling is broken
# (namespace/packages don't get imported into child interpreters)
# so use this workaround proc instead of 'package require' to
# load the package into the current interpreter
# (this is obviously slower than copying from master interpeter)
# Package names are case-sensitive!
# Returns the version of the loaded package
set library shared
if {[lsearch -exact [package names] $package] == -1} {
ns_log Notice "packages: registering $library/$package"
_am_pregister $library $package
}
package require $package
}
proc _am_pregister {library package} {
# Registers the package. library is 'shared' or 'private'
set dir [ns_library $library]/packages/$package
source $dir/pkgIndex.tcl
}

3141
doc/tclcurl.html Executable file

File diff suppressed because it is too large Load Diff

2579
doc/tclcurl.n Executable file

File diff suppressed because it is too large Load Diff

320
doc/tclcurl_multi.html Executable file
View File

@ -0,0 +1,320 @@
<HTML><HEAD><TITLE>Manpage of TclCurl</TITLE>
</HEAD><BODY>
<H1>TclCurl</H1>
Section: TclCurl Multi Interface (n)<BR>Updated: 03 September 2011<BR><HR>
<A NAME="lbAB">&nbsp;</A>
<H2>NAME</H2>
TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP,
LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.
<A NAME="lbAC">&nbsp;</A>
<H2>SYNOPSIS</H2>
<B>curl::multiinit</B>
<P>
<I>multiHandle</I><B> addhandle</B>
<P>
<I>multiHandle</I><B> removehandle</B>
<P>
<I>multiHandle</I><B> configure</B>
<P>
<I>multiHandle</I><B> perform</B>
<P>
<I>multiHandle</I><B> active</B>
<P>
<I>multiHandle</I><B> getinfo </B>
<P>
<I>multihandle</I><B> cleanup</B>
<P>
<I>multihandle</I><B> auto</B>
<P>
<B>curl::multistrerror </B><I>errorCode</I>
<P>
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
TclCurl's multi interface introduces several new abilities that the easy
interface refuses to offer. They are mainly:
<ul>
<li>Enable a &quot;pull&quot; interface. The application that uses TclCurl decides where
and when to get/send data.<br><br>
<li>Enable multiple simultaneous transfers in the same thread without making it
complicated for the application.<br><br>
<li>Keep Tk GUIs 'alive' while transfers are taking place.<br><br>
</ul>
<P>
</DL>
<A NAME="lbAE">&nbsp;</A>
<H2>Blocking</H2>
A few areas in the code are still using blocking code, even when used from the
multi interface. While we certainly want and intend for these to get fixed in
the future, you should be aware of the following current restrictions:
<ul>
<li>Name resolves on non-windows unless c-ares is used.</B>
<li>GnuTLS SSL connections.</B>
<li>Active FTP connections.</B>
<li>HTTP proxy CONNECT operations.</B>
<li>SCP and SFTP connections.</B>
<li>SFTP transfers.</B>
<li>TFTP transfers</B>
<li>file:// transfers.</B>
</ul>
<P>
<A NAME="lbAF">&nbsp;</A>
<H2>curl::multiinit</H2>
This procedure must be the first one to call, it returns a <I>multiHandle</I>
that you need to use to invoke TclCurl procedures. The init MUST have a
corresponding call to <I>cleanup</I> when the operation is completed.
<P>
<B>RETURN VALUE</B>
<P>
<I>multiHandle</I>
to use.
<P>
<A NAME="lbAG">&nbsp;</A>
<H2>multiHandle addhandle ?easyHandle?</H2>
<P>
Each single transfer is built up with an 'easy' handle, the kind we have been
using so far with TclCurl, you must create them and setup the appropriate
options for each of them. Then we add them to the 'multi stack' using the
<I>addhandle</I> command.
<P>
If the easy handle is not set to use a shared or global DNS cache, it will be made
to use the DNS cache that is shared between all easy handles within the multi handle.
<P>
When an easy handle has been added to a multi stack, you can not and you must not use
<I>perform</I> on that handle!
<P>
<P>
<I>multiHandle</I>
is the return code from the <I>curl::multiinit</I> call.
<P>
<B>RETURN VALUE</B>
The possible return values are:
<DL COMPACT>
<DT>-1<DD>
Handle added to the multi stack, please call
<I>perform</I>
soon
<DT>0<DD>
Handle added ok.
<DT>1<DD>
Invalid multi handle.
<DT>2<DD>
Invalid 'easy' handle. It could mean that it isn't an easy handle at all, or possibly that
the handle already is in used by this or another multi handle.
<DT>3<DD>
Out of memory, you should never get this.
<DT>4<DD>
You found a bug in TclCurl.
<P>
</DL>
<A NAME="lbAH">&nbsp;</A>
<H2>multiHandle removehandle ?easyHandle?</H2>
<P>
When a transfer is done or if we want to stop a transfer before it is completed,
we can use the <I>removehandle</I> command. Once removed from the multi handle,
we can again use other easy interface functions on it.
<P>
Please note that when a single transfer is completed, the easy handle is still
left added to the multi stack. You need to remove it and then close or, possibly,
set new options to it and add it again to the multi handle to start another transfer.
<P>
<P>
<B>RETURN VALUE</B>
The possible return values are:
<DL COMPACT>
<DT>0<DD>
Handle removed ok.
<DT>1<DD>
Invalid multi handle.
<DT>2<DD>
Invalid 'easy' handle.
<DT>3<DD>
Out of memory, you should never get this.
<DT>4<DD>
You found a bug in TclCurl.
<P>
</DL>
<A NAME="lbAI">&nbsp;</A>
<H2>multiHandle configure</H2>
So far the only option is:
<DL COMPACT>
<DT><B>-pipelining</B>
<DD>
Pass a 1 to enable or 0 to disable. Enabling pipelining on a multi handle will
make it attempt to perform HTTP Pipelining as far as possible for transfers using
this handle. This means that if you add a second request that can use an already
existing connection, the second request will be &quot;piped&quot; on the same connection
rather than being executed in parallel.
<DT><B>-maxconnects</B>
<DD>
Pass a number which will be used as the maximum amount of simultaneously open
connections that TclCurl may cache. Default is 10, and TclCurl will enlarge
the size for each added easy handle to make it fit 4 times the number of added
easy handles.
<P>
By setting this option, you can prevent the cache size to grow beyond the limit
set by you. When the cache is full, curl closes the oldest one in the cache to
prevent the number of open connections to increase.
<P>
This option is for the multi handle's use only, when using the easy interface you should instead use it's own <B>maxconnects</B> option.
<P>
</DL>
<A NAME="lbAJ">&nbsp;</A>
<H2>multiHandle perform</H2>
Adding the easy handles to the multi stack does not start any transfer.
Remember that one of the main ideas with this interface is to let your
application drive. You drive the transfers by invoking
<I>perform.</I>
TclCurl will then transfer data if there is anything available to transfer.
It'll use the callbacks and everything else we have setup in the individual
easy handles. It'll transfer data on all current transfers in the multi stack
that are ready to transfer anything. It may be all, it may be none.
<P>
When you call <B>perform</B> and the amount of Irunning handles is
changed from the previous call (or is less than the amount of easy handles
you added to the multi handle), you know that there is one or more
transfers less &quot;running&quot;. You can then call <I>getinfo</I> to
get information about each individual completed transfer.
<P>
<B>RETURN VALUE</B>
If everything goes well, it returns the number of running handles, '0' if all
are done. In case of error, it will return the error code.
<P>
<A NAME="lbAK">&nbsp;</A>
<H2>multiHandle active</H2>
In order to know if any of the easy handles are ready to transfer data before
invoking
<I>perform</I>
you can use the
<I>active</I>
command, it will return the number of transfers currently active.
<P>
<B>RETURN VALUE</B>
The number of active transfers or '-1' in case of error.
<P>
<A NAME="lbAL">&nbsp;</A>
<H2>multiHandle getinfo</H2>
This procedure returns very simple information about the transfers, you
can get more detail information using the <I>getinfo</I>
command on each of the easy handles.
<P>
<P>
<B>RETURN VALUE</B>
A list with the following elements:
<DL COMPACT>
<DT>easyHandle about which the info is about.<DD>
<DT>state of the transfer, '1' if it is done.<DD>
<DT>exit code of the transfer, '0' if there was no error,...<DD>
<DT>Number of messages still in the info queue.<DD>
<DT>In case there are no messages in the queue it will return {&quot;&quot; 0 0 0}.<DD>
<P>
</DL>
<A NAME="lbAM">&nbsp;</A>
<H2>multiHandle cleanup</H2>
This procedure must be the last one to call for a multi stack, it is the opposite of the
<I>curl::multiinit</I>
procedure and must be called with the same
<I>multiHandle</I>
as input as the
<B>curl::multiinit</B>
call returned.
<P>
<A NAME="lbAN">&nbsp;</A>
<H2>multiHandle auto ?-command <I>command</I>?</H2>
Using this command Tcl's event loop will take care of periodically invoking <B>perform</B>
for you, before using it, you must have already added at least one easy handle to
the multi handle.
<P>
The <B>command</B> option allows you to specify a command to invoke after all the easy
handles have finished their transfers, even though I say it is an option, the truth is
you must use this command to cleanup all the handles, otherwise the transfered files
may not be complete.
<P>
This support is still in a very experimental state, it may still change without warning.
Any and all comments are welcome.
<P>
You can find a couple of examples at <B>tests/multi</B>.
<P>
<A NAME="lbAO">&nbsp;</A>
<H2>curl::multistrerror errorCode</H2>
This procedure returns a string describing the error code passed in the argument.
<P>
<A NAME="lbAP">&nbsp;</A>
<H2>SEE ALSO</H2>
<I>tclcurl, curl.</I>
<P>
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
<DL>
<DT><A HREF="#lbAB">NAME</A><DD>
<DT><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT><A HREF="#lbAE">Blocking</A><DD>
<DT><A HREF="#lbAF">curl::multiinit</A><DD>
<DT><A HREF="#lbAG">multiHandle addhandle ?easyHandle?</A><DD>
<DT><A HREF="#lbAH">multiHandle removehandle ?easyHandle?</A><DD>
<DT><A HREF="#lbAI">multiHandle configure</A><DD>
<DT><A HREF="#lbAJ">multiHandle perform</A><DD>
<DT><A HREF="#lbAK">multiHandle active</A><DD>
<DT><A HREF="#lbAL">multiHandle getinfo</A><DD>
<DT><A HREF="#lbAM">multiHandle cleanup</A><DD>
<DT><A HREF="#lbAN">multiHandle auto ?-command <I>command</I>?</A><DD>
<DT><A HREF="#lbAO">curl::multistrerror errorCode</A><DD>
<DT><A HREF="#lbAP">SEE ALSO</A><DD>
</DL>
<HR>
This document was created by man2html, using the manual pages.<BR>
</BODY>
</HTML>

238
doc/tclcurl_multi.n Executable file
View File

@ -0,0 +1,238 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Adapted from libcurl docs by fandom@telefonica.net
.TH TclCurl n "3 October 2011" "TclCurl 7.22.0 "TclCurl Easy Interface"
.SH NAME
TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP,
LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.
.SH SYNOPSIS
.BI "curl::multiinit"
.sp
.IB multiHandle " addhandle"
.sp
.IB multiHandle " removehandle"
.sp
.IB multiHandle " configure"
.sp
.IB multiHandle " perform"
.sp
.IB multiHandle " active"
.sp
.IB multiHandle " getinfo "
.sp
.IB multihandle " cleanup"
.sp
.IB multihandle " auto"
.sp
.BI "curl::multistrerror " errorCode
.sp
.SH DESCRIPTION
TclCurl's multi interface introduces several new abilities that the easy
interface refuses to offer. They are mainly:
.TP
Enable a "pull" interface. The application that uses TclCurl decides where and when to get/send data.
.TP
Enable multiple simultaneous transfers in the same thread without making it complicated for the application.
.TP
Keep Tk GUIs 'alive' while transfers are taking place.
.SH Blocking
A few areas in the code are still using blocking code, even when used from the
multi interface. While we certainly want and intend for these to get fixed in
the future, you should be aware of the following current restrictions:
.RS
.TP 5
.B Name resolves on non-windows unless c-ares is used.
.TP
.B GnuTLS SSL connections.
.TP
.B GnuTLS SSL connections
.TP
.B Active FTP connections.
.TP
.B HTTP proxy CONNECT operations.
.TP
.B SOCKS proxy handshakes
.TP
.B file:// transfers.
.TP
.B TELNET transfers
.RE
.SH curl::multiinit
This procedure must be the first one to call, it returns a \fImultiHandle\fP
that you need to use to invoke TclCurl procedures. The init MUST have a
corresponding call to \fIcleanup\fP when the operation is completed.
.sp
.B RETURN VALUE
.sp
.I multiHandle
to use.
.sp
.SH multiHandle addhandle ?easyHandle?
.sp
Each single transfer is built up with an 'easy' handle, the kind we have been
using so far with TclCurl, you must create them and setup the appropriate
options for each of them. Then we add them to the 'multi stack' using the
\fIaddhandle\fP command.
If the easy handle is not set to use a shared or global DNS cache, it will be made
to use the DNS cache that is shared between all easy handles within the multi handle.
When an easy handle has been added to a multi stack, you can not and you must not use
\fIperform\fP on that handle!
.sp
.I "multiHandle"
is the return code from the \fIcurl::multiinit\fP call.
.sp
.B RETURN VALUE
The possible return values are:
.IP -1
Handle added to the multi stack, please call
.I perform
soon
.IP 0
Handle added ok.
.IP 1
Invalid multi handle.
.IP 2
Invalid 'easy' handle. It could mean that it isn't an easy handle at all, or possibly that
the handle already is in used by this or another multi handle.
.IP 3
Out of memory, you should never get this.
.IP 4
You found a bug in TclCurl.
.sp
.SH multiHandle removehandle ?easyHandle?
.sp
When a transfer is done or if we want to stop a transfer before it is completed,
we can use the \fIremovehandle\fP command. Once removed from the multi handle,
we can again use other easy interface functions on it.
Please note that when a single transfer is completed, the easy handle is still
left added to the multi stack. You need to remove it and then close or, possibly,
set new options to it and add it again to the multi handle to start another transfer.
.sp
.B RETURN VALUE
The possible return values are:
.IP 0
Handle removed ok.
.IP 1
Invalid multi handle.
.IP 2
Invalid 'easy' handle.
.IP 3
Out of memory, you should never get this.
.IP 4
You found a bug in TclCurl.
.sp
.SH multiHandle configure
So far the only options are:
.TP
.B -pipelining
Pass a 1 to enable or 0 to disable. Enabling pipelining on a multi handle will
make it attempt to perform HTTP Pipelining as far as possible for transfers using
this handle. This means that if you add a second request that can use an already
existing connection, the second request will be "piped" on the same connection
rather than being executed in parallel.
.TP
.B -maxconnects
Pass a number which will be used as the maximum amount of simultaneously open
connections that TclCurl may cache. Default is 10, and TclCurl will enlarge
the size for each added easy handle to make it fit 4 times the number of added
easy handles.
By setting this option, you can prevent the cache size to grow beyond the limit
set by you. When the cache is full, curl closes the oldest one in the cache to
prevent the number of open connections to increase.
This option is for the multi handle's use only, when using the easy interface you should instead use it's own \fBmaxconnects\fP option.
.sp
.SH multiHandle perform
Adding the easy handles to the multi stack does not start any transfer.
Remember that one of the main ideas with this interface is to let your
application drive. You drive the transfers by invoking
.I perform.
TclCurl will then transfer data if there is anything available to transfer.
It'll use the callbacks and everything else we have setup in the individual
easy handles. It'll transfer data on all current transfers in the multi stack
that are ready to transfer anything. It may be all, it may be none.
When you call \fBperform\fP and the amount of running handles is
changed from the previous call (or is less than the amount of easy handles
you added to the multi handle), you know that there is one or more
transfers less "running". You can then call \fIgetinfo\fP to
get information about each individual completed transfer. If an added handle
fails very quickly, it may never be counted as a running handle.
.sp
.B RETURN VALUE
If everything goes well, it returns the number of running handles, '0' if all
are done. In case of error, it will return the error code.
This function only returns errors etc regarding the whole multi stack.
Problems still might have occurred on individual transfers even when this
function returns ok.
.sp
.SH multiHandle active
In order to know if any of the easy handles are ready to transfer data before
invoking
.I perform
you can use the
.I active
command, it will return the number of transfers currently active.
.sp
.B RETURN VALUE
The number of active transfers or '-1' in case of error.
.SH multiHandle getinfo
This procedure returns very simple information about the transfers, you
can get more detail information using the \fIgetinfo\fP
command on each of the easy handles.
.sp
.B RETURN VALUE
A list with the following elements:
.TP
easyHandle about which the info is about.
.TP
state of the transfer, '1' if it is done.
.TP
exit code of the transfer, '0' if there was no error,...
.TP
Number of messages still in the info queue.
.TP
In case there are no messages in the queue it will return {"" 0 0 0}.
.SH multiHandle cleanup
This procedure must be the last one to call for a multi stack, it is the opposite of the
.I curl::multiinit
procedure and must be called with the same
.I multiHandle
as input as the
.B curl::multiinit
call returned.
.SH multiHandle auto ?-command \fIcommand\fP?
Using this command Tcl's event loop will take care of periodically invoking \fBperform\fP
for you, before using it, you must have already added at least one easy handle to
the multi handle.
The \fBcommand\fP option allows you to specify a command to invoke after all the easy
handles have finished their transfers, even though I say it is an option, the truth is
you must use this command to cleanup all the handles, otherwise the transfered files
may not be complete.
This support is still in a very experimental state, it may still change without warning.
Any and all comments are welcome.
You can find a couple of examples at \fBtests/multi\fP.
.SH curl::multistrerror errorCode
This procedure returns a string describing the error code passed in the argument.
.SH "SEE ALSO"
.I tclcurl, curl.

112
doc/tclcurl_share.html Executable file
View File

@ -0,0 +1,112 @@
<HTML><HEAD><TITLE>Manpage of TclCurl</TITLE>
</HEAD><BODY>
<H1>TclCurl</H1>
Section: TclCurl share data api (n)<BR>Updated: 03 October 2011<BR><HR>
<A NAME="lbAB">&nbsp;</A>
<H2>NAME</H2>
TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP,
LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.
<A NAME="lbAC">&nbsp;</A>
<H2>SYNOPSIS</H2>
<B>curl::shareinit</B>
<P>
<I>shareHandle</I><B> share </B><I>?data?</I>
<P>
<I>shareHandle</I><B> unshare </B><I>?data?</I>
<P>
<I>shareHandle</I><B> cleanup</B>
<P>
<B>curl::sharestrerror </B><I>errorCode</I>
<P>
<P>
<A NAME="lbAD">&nbsp;</A>
<H2>DESCRIPTION</H2>
<P>
With the share API, you can have two or more 'easy' handles sharing data
among them, so far they can only share cookies and DNS data.
<P>
<A NAME="lbAE">&nbsp;</A>
<H2>curl::shareinit</H2>
This procedure must be the first one to call, it returns a <B>shareHandle</B>
that you need to use to share data among handles using the <B>-share</B> option
to the <B>configure</B> command. The init MUST have a corresponding call to
<B>cleanup</B> when the operation is completed.
<P>
<B>RETURN VALUE</B>
<P>
<B>shareHandle</B> to use.
<P>
<A NAME="lbAF">&nbsp;</A>
<H2>shareHandle share ?data?</H2>
<P>
The parameter specifies a type of data that should be shared. This may be set
to one of the values described below:
<P>
<DL COMPACT><DT><DD>
<DL COMPACT>
<DT><B>cookies</B>
<DD>
Cookie data will be shared across the easy handles using this shared object.
<P>
<DT><B>dns</B>
<DD>
Cached DNS hosts will be shared across the easy handles using this shared object.
</DL>
</DL>
<P>
<A NAME="lbAG">&nbsp;</A>
<H2>shareHandle unshare ?data?</H2>
This command does the opposite of <B>share</B>. The specified parameter will no
longer be shared. Valid values are the same as those for <B>share</B>.
<P>
<A NAME="lbAH">&nbsp;</A>
<H2>sharehandle cleanup</H2>
<P>
Deletes a shared object. The share handle cannot be used anymore after this
function has been called.
<P>
<A NAME="lbAI">&nbsp;</A>
<H2>curl::sharestrerror errorCode</H2>
Returns a string describing the error code passed in the argument.
<P>
<A NAME="lbAJ">&nbsp;</A>
<H2>SEE ALSO</H2>
<I>curl, TclCurl</I>
<P>
<HR>
<A NAME="index">&nbsp;</A><H2>Index</H2>
<DL>
<DT><A HREF="#lbAB">NAME</A><DD>
<DT><A HREF="#lbAC">SYNOPSIS</A><DD>
<DT><A HREF="#lbAD">DESCRIPTION</A><DD>
<DT><A HREF="#lbAE">curl::shareinit</A><DD>
<DT><A HREF="#lbAF">shareHandle share ?data?</A><DD>
<DT><A HREF="#lbAG">shareHandle unshare ?data?</A><DD>
<DT><A HREF="#lbAH">sharehandle cleanup</A><DD>
<DT><A HREF="#lbAI">curl::sharestrerror errorCode</A><DD>
<DT><A HREF="#lbAJ">SEE ALSO</A><DD>
</DL>
<HR>
This document was created by man2html, using the manual pages.<BR>
</BODY>
</HTML>

65
doc/tclcurl_share.n Executable file
View File

@ -0,0 +1,65 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Adapted from libcurl docs by fandom@telefonica.net
.TH TclCurl n "3 October 2011" "TclCurl 7.22.0 "TclCurl Easy Interface"
.SH NAME
TclCurl: - get a URL with FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP,
LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.
.SH SYNOPSIS
.BI "curl::shareinit"
.sp
.IB shareHandle " share " "?data?"
.sp
.IB shareHandle " unshare " "?data?"
.sp
.IB shareHandle " cleanup"
.sp
.BI "curl::sharestrerror " errorCode
.SH DESCRIPTION
With the share API, you can have two or more 'easy' handles sharing data
among them, so far they can only share cookies and DNS data.
.SH curl::shareinit
This procedure must be the first one to call, it returns a \fBshareHandle\fP
that you need to use to share data among handles using the \fB-share\fP option
to the \fBconfigure\fP command. The init MUST have a corresponding call to
\fBcleanup\fP when the operation is completed.
.B RETURN VALUE
.sp
\fBshareHandle\fP to use.
.SH shareHandle share ?data?
The parameter specifies a type of data that should be shared. This may be set
to one of the values described below:
.RS
.TP 5
.B cookies
Cookie data will be shared across the easy handles using this shared object.
.TP
.B dns
Cached DNS hosts will be shared across the easy handles using this shared object.
Note that when you use the multi interface, all easy handles added to the same multi
handle will share DNS cache by default without this having to be used!
.RE
.SH shareHandle unshare ?data?
This command does the opposite of \fBshare\fP. The specified parameter will no
longer be shared. Valid values are the same as those for \fBshare\fP.
.SH sharehandle cleanup
Deletes a shared object. The share handle cannot be used anymore after this
function has been called.
.SH curl::sharestrerror errorCode
Returns a string describing the error code passed in the argument.
.SH "SEE ALSO"
.I curl, TclCurl

905
generic/multi.c Executable file
View File

@ -0,0 +1,905 @@
/*
* multi.c --
*
* Implementation of the part of the TclCurl extension that deals with libcurl's
* 'multi' interface.
*
* Copyright (c)2002-2011 Andres Garcia Garcia.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#include "multi.h"
#include <sys/time.h>
/*
*----------------------------------------------------------------------
*
* Tclcurl_MultiInit --
*
* This procedure initializes the 'multi' part of the package
*
* Results:
* A standard Tcl result.
*
*----------------------------------------------------------------------
*/
int
Tclcurl_MultiInit (Tcl_Interp *interp) {
Tcl_CreateObjCommand (interp,"::curl::multiinit",curlInitMultiObjCmd,
(ClientData)NULL,(Tcl_CmdDeleteProc *)NULL);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* curlCreateMultiObjCmd --
*
* Looks for the first free handle (mcurl1, mcurl2,...) and creates a
* Tcl command for it.
*
* Results:
* A string with the name of the handle, don't forget to free it.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
char *
curlCreateMultiObjCmd (Tcl_Interp *interp,struct curlMultiObjData *curlMultiData) {
char *handleName;
int i;
Tcl_CmdInfo info;
Tcl_Command cmdToken;
/* We try with mcurl1, if it already exists with mcurl2, ... */
handleName=(char *)Tcl_Alloc(10);
for (i=1;;i++) {
sprintf(handleName,"mcurl%d",i);
if (!Tcl_GetCommandInfo(interp,handleName,&info)) {
cmdToken=Tcl_CreateObjCommand(interp,handleName,curlMultiObjCmd,
(ClientData)curlMultiData,
(Tcl_CmdDeleteProc *)curlMultiDeleteCmd);
break;
}
}
curlMultiData->token=cmdToken;
return handleName;
}
/*
*----------------------------------------------------------------------
*
* curlInitMultiObjCmd --
*
* This procedure is invoked to process the "curl::multiInit" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
int
curlInitMultiObjCmd (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]) {
Tcl_Obj *result;
struct curlMultiObjData *curlMultiData;
char *multiHandleName;
curlMultiData=(struct curlMultiObjData *)Tcl_Alloc(sizeof(struct curlMultiObjData));
if (curlMultiData==NULL) {
result=Tcl_NewStringObj("Couldn't allocate memory",-1);
Tcl_SetObjResult(interp,result);
return TCL_ERROR;
}
memset(curlMultiData, 0, sizeof(struct curlMultiObjData));
curlMultiData->interp=interp;
curlMultiData->mcurl=curl_multi_init();
if (curlMultiData->mcurl==NULL) {
result=Tcl_NewStringObj("Couldn't open curl multi handle",-1);
Tcl_SetObjResult(interp,result);
return TCL_ERROR;
}
multiHandleName=curlCreateMultiObjCmd(interp,curlMultiData);
result=Tcl_NewStringObj(multiHandleName,-1);
Tcl_SetObjResult(interp,result);
Tcl_Free(multiHandleName);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* curlMultiObjCmd --
*
* This procedure is invoked to process the "multi curl" commands.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
int
curlMultiObjCmd (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]) {
struct curlMultiObjData *curlMultiData=(struct curlMultiObjData *)clientData;
CURLMcode errorCode;
int tableIndex;
if (objc<2) {
Tcl_WrongNumArgs(interp,1,objv,"option arg ?arg?");
return TCL_ERROR;
}
if (Tcl_GetIndexFromObj(interp, objv[1], multiCommandTable, "option",
TCL_EXACT,&tableIndex)==TCL_ERROR) {
return TCL_ERROR;
}
switch(tableIndex) {
case 0:
/* fprintf(stdout,"Multi add handle\n"); */
errorCode=curlAddMultiHandle(interp,curlMultiData->mcurl,objv[2]);
return curlReturnCURLMcode(interp,errorCode);
break;
case 1:
/* fprintf(stdout,"Multi remove handle\n"); */
errorCode=curlRemoveMultiHandle(interp,curlMultiData->mcurl,objv[2]);
return curlReturnCURLMcode(interp,errorCode);
break;
case 2:
/* fprintf(stdout,"Multi perform\n"); */
errorCode=curlMultiPerform(interp,curlMultiData->mcurl);
return errorCode;
break;
case 3:
/* fprintf(stdout,"Multi cleanup\n"); */
Tcl_DeleteCommandFromToken(interp,curlMultiData->token);
break;
case 4:
/* fprintf(stdout,"Multi getInfo\n"); */
curlMultiGetInfo(interp,curlMultiData->mcurl);
break;
case 5:
/* fprintf(stdout,"Multi activeTransfers\n"); */
curlMultiActiveTransfers(interp,curlMultiData);
break;
case 6:
/* fprintf(stdout,"Multi auto transfer\n");*/
curlMultiAutoTransfer(interp,curlMultiData,objc,objv);
break;
case 7:
/* fprintf(stdout,"Multi configure\n");*/
curlMultiConfigTransfer(interp,curlMultiData,objc,objv);
break;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* curlAddMultiHandle --
*
* Adds an 'easy' curl handle to the stack of a 'multi' handle.
*
* Parameter:
* interp: Pointer to the interpreter we are using.
* curlMultiHandle: The handle into which we will add the easy one.
* objvPtr: The Tcl object with the name of the easy handle.
*
* Results:
* '0' all went well.
* 'non-zero' in case of error.
*----------------------------------------------------------------------
*/
CURLMcode
curlAddMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandlePtr
,Tcl_Obj *objvPtr) {
struct curlObjData *curlDataPtr;
CURLMcode errorCode;
curlDataPtr=curlGetEasyHandle(interp,objvPtr);
if (curlOpenFiles(interp,curlDataPtr)) {
return TCL_ERROR;
}
if (curlSetPostData(interp,curlDataPtr)) {
return TCL_ERROR;
}
errorCode=curl_multi_add_handle(curlMultiHandlePtr,curlDataPtr->curl);
curlEasyHandleListAdd(curlMultiHandlePtr,curlDataPtr->curl
,Tcl_GetString(objvPtr));
return errorCode;
}
/*
*----------------------------------------------------------------------
*
* curlRemoveMultiHandle --
*
* Removes an 'easy' curl handle to the stack of a 'multi' handle.
*
* Parameter:
* interp: Pointer to the interpreter we are using.
* curlMultiHandle: The handle into which we will add the easy one.
* objvPtr: The Tcl object with the name of the easy handle.
*
* Results:
* '0' all went well.
* 'non-zero' in case of error.
*----------------------------------------------------------------------
*/
CURLMcode
curlRemoveMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandle
,Tcl_Obj *objvPtr) {
struct curlObjData *curlDataPtr;
CURLMcode errorCode;
curlDataPtr=curlGetEasyHandle(interp,objvPtr);
errorCode=curl_multi_remove_handle(curlMultiHandle,curlDataPtr->curl);
curlEasyHandleListRemove(curlMultiHandle,curlDataPtr->curl);
curlCloseFiles(curlDataPtr);
curlResetPostData(curlDataPtr);
if (curlDataPtr->bodyVarName) {
curlSetBodyVarName(interp,curlDataPtr);
}
return errorCode;
}
/*
*----------------------------------------------------------------------
*
* curlMultiPerform --
*
* Invokes the 'curl_multi_perform' function to update the current
* transfers.
*
* Parameter:
* interp: Pointer to the interpreter we are using.
* curlMultiHandle: The handle of the transfer to update.
* objvPtr: The Tcl object with the name of the easy handle.
*
* Results:
Usual Tcl result.
*----------------------------------------------------------------------
*/
int
curlMultiPerform(Tcl_Interp *interp,CURLM *curlMultiHandlePtr) {
CURLMcode errorCode;
int runningTransfers;
for (errorCode=-1;errorCode<0;) {
errorCode=curl_multi_perform(curlMultiHandlePtr,&runningTransfers);
}
if (errorCode==0) {
curlReturnCURLMcode(interp,runningTransfers);
return TCL_OK;
}
curlReturnCURLMcode(interp,errorCode);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* curlMultiDeleteCmd --
*
* This procedure is invoked when curl multi handle is deleted.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* Cleans the curl handle and frees the memory.
*
*----------------------------------------------------------------------
*/
int
curlMultiDeleteCmd(ClientData clientData) {
struct curlMultiObjData *curlMultiData=(struct curlMultiObjData *)clientData;
CURLM *curlMultiHandle=curlMultiData->mcurl;
CURLMcode errorCode;
Tcl_Interp *interp=curlMultiData->interp;
struct easyHandleList *listPtr1,*listPtr2;
listPtr1=curlMultiData->handleListFirst;
while (listPtr1!=NULL) {
listPtr2=listPtr1->next;
Tcl_Free(listPtr1->name);
Tcl_Free((char *)listPtr1);
listPtr1=listPtr2;
}
errorCode=curl_multi_cleanup(curlMultiHandle);
curlMultiFreeSpace(curlMultiData);
return curlReturnCURLMcode(interp,errorCode);
}
/*
*----------------------------------------------------------------------
*
* curlGetMultiInfo --
* Invokes the curl_multi_info_read function in libcurl to get
* some info about the transfer, like if they are done and
* things like that.
*
* Parameter:
* interp: The Tcl interpreter we are using, mainly to report errors.
* curlMultiHandlePtr: Pointer to the multi handle of the transfer.
*
* Results:
* Standard Tcl codes. The Tcl command will return a list with the
* name of the Tcl command and other info.
*----------------------------------------------------------------------
*/
int
curlMultiGetInfo(Tcl_Interp *interp,CURLM *curlMultiHandlePtr) {
struct CURLMsg *multiInfo;
int msgLeft;
Tcl_Obj *resultPtr;
multiInfo=curl_multi_info_read(curlMultiHandlePtr, &msgLeft);
resultPtr=Tcl_NewListObj(0,(Tcl_Obj **)NULL);
if (multiInfo==NULL) {
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewStringObj("",-1));
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(0));
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(0));
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(0));
} else {
Tcl_ListObjAppendElement(interp,resultPtr,
Tcl_NewStringObj(curlGetEasyName(curlMultiHandlePtr,multiInfo->easy_handle),-1));
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(multiInfo->msg));
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(multiInfo->data.result));
Tcl_ListObjAppendElement(interp,resultPtr,Tcl_NewIntObj(msgLeft));
}
Tcl_SetObjResult(interp,resultPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* curlMultiActiveTransfers --
* This function is used to know whether an connection is ready to
* transfer data. This code has been copied almost verbatim from
* libcurl's examples.
*
* Parameter:
* multiHandlePtr: Pointer to the multi handle of the transfer.
*
* Results:
*
*----------------------------------------------------------------------
*/
int
curlMultiGetActiveTransfers( struct curlMultiObjData *curlMultiData) {
struct timeval timeout;
int selectCode;
int maxfd;
FD_ZERO(&(curlMultiData->fdread));
FD_ZERO(&(curlMultiData->fdwrite));
FD_ZERO(&(curlMultiData->fdexcep));
/* set a suitable timeout to play around with */
timeout.tv_sec = 1;
timeout.tv_usec = 0;
/* get file descriptors from the transfers */
curl_multi_fdset(curlMultiData->mcurl,
&(curlMultiData->fdread),
&(curlMultiData->fdwrite),
&(curlMultiData->fdexcep), &maxfd);
selectCode = select(maxfd+1, &(curlMultiData->fdread)
, &(curlMultiData->fdwrite), &(curlMultiData->fdexcep)
, &timeout);
return selectCode;
}
/*
*----------------------------------------------------------------------
*
* curlMultiActiveTransfers --
* Implements the Tcl 'active', it queries the multi handle to know
* if any of the connections are ready to transfer data.
*
* Parameter:
* interp: The Tcl interpreter we are using, mainly to report errors.
* curlMultiHandlePtr: Pointer to the multi handle of the transfer.
*
* Results:
* Standard Tcl codes. The Tcl command will return the number of
* transfers.
*----------------------------------------------------------------------
*/
int
curlMultiActiveTransfers(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData) {
int selectCode;
Tcl_Obj *resultPtr;
selectCode = curlMultiGetActiveTransfers(curlMultiData);
if (selectCode==-1) {
return TCL_ERROR;
}
resultPtr=Tcl_NewIntObj(selectCode);
Tcl_SetObjResult(interp,resultPtr);
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* curlGetEasyHandle --
*
* Given the name of an easy curl handle (curl1,...), in a Tcl object
* this function will return the pointer the 'internal' libcurl handle.
*
* Parameter:
* The Tcl object with the name.
*
* Results:
* The pointer to the libcurl handle
*----------------------------------------------------------------------
*/
struct curlObjData *
curlGetEasyHandle(Tcl_Interp *interp,Tcl_Obj *nameObjPtr) {
char *handleName;
Tcl_CmdInfo *infoPtr=(Tcl_CmdInfo *)Tcl_Alloc(sizeof(Tcl_CmdInfo));
struct curlObjData *curlDataPtr;
handleName=Tcl_GetString(nameObjPtr);
if (0==Tcl_GetCommandInfo(interp,handleName,infoPtr)) {
return NULL;
}
curlDataPtr=(struct curlObjData *)(infoPtr->objClientData);
Tcl_Free((char *)infoPtr);
return curlDataPtr;
}
/*
*----------------------------------------------------------------------
*
* curlMultiFreeSpace --
*
* Frees the space taken by a curlMultiObjData struct.
*
* Parameter:
* interp: Pointer to the interpreter we are using.
* curlMultiHandle: the curl handle for which the option is set.
* objc and objv: The usual in Tcl.
*
* Results:
* A standard Tcl result.
*----------------------------------------------------------------------
*/
void
curlMultiFreeSpace(struct curlMultiObjData *curlMultiData) {
curl_multi_cleanup(curlMultiData->mcurl);
Tcl_Free(curlMultiData->postCommand);
Tcl_Free((char *)curlMultiData);
}
/*
*----------------------------------------------------------------------
*
* curlEasyHandleListAdd
* Adds an easy handle to the list of handles in a multiHandle.
*
* Parameter:
* multiDataPtr: Pointer to the struct of the multi handle.
* easyHandle: The easy handle to add to the list.
*
* Results:
*----------------------------------------------------------------------
*/
void
curlEasyHandleListAdd(struct curlMultiObjData *multiDataPtr,CURL *easyHandlePtr,char *name) {
struct easyHandleList *easyHandleListPtr;
easyHandleListPtr=(struct easyHandleList *)Tcl_Alloc(sizeof(struct easyHandleList));
easyHandleListPtr->curl =easyHandlePtr;
easyHandleListPtr->name =curlstrdup(name);
easyHandleListPtr->next=NULL;
if (multiDataPtr->handleListLast==NULL) {
multiDataPtr->handleListFirst=easyHandleListPtr;
multiDataPtr->handleListLast =easyHandleListPtr;
} else {
multiDataPtr->handleListLast->next=easyHandleListPtr;
multiDataPtr->handleListLast=easyHandleListPtr;
}
}
/*
*----------------------------------------------------------------------
*
* curlEasyHandleListRemove
* When we remove an easy handle from the multiHandle, this function
* will remove said handle from the linked list.
*
* Parameter:
* multiDataPtr: Pointer to the struct of the multi handle.
* easyHandle: The easy handle to add to the list.
*
* Results:
*----------------------------------------------------------------------
*/
void
curlEasyHandleListRemove(struct curlMultiObjData *multiDataPtr,CURL *easyHandle) {
struct easyHandleList *listPtr1,*listPtr2;
listPtr1=NULL;
listPtr2=multiDataPtr->handleListFirst;
while(listPtr2!=NULL) {
if (listPtr2->curl==easyHandle) {
if (listPtr1==NULL) {
multiDataPtr->handleListFirst=listPtr2->next;
} else {
listPtr1->next=listPtr2->next;
}
if (listPtr2==multiDataPtr->handleListLast) {
multiDataPtr->handleListLast=listPtr1;
}
Tcl_Free(listPtr2->name);
Tcl_Free((char *)listPtr2);
break;
}
listPtr1=listPtr2;
listPtr2=listPtr2->next;
}
}
/*
*----------------------------------------------------------------------
*
* curlGetEasyName
*
* Given the pointer to an easy handle, this function will return
* the name of the Tcl command.
*
* Parameter:
* multiDataPtr: Multi handle we are using.
* easyHandle: The easy handle whose Tcl command we want to know.
*
* Results:
* A string with the name of the command.
*----------------------------------------------------------------------
*/
char *
curlGetEasyName(struct curlMultiObjData *multiDataPtr,CURL *easyHandle) {
struct easyHandleList *listPtr;
listPtr=multiDataPtr->handleListFirst;
while(listPtr!=NULL) {
if (listPtr->curl==easyHandle) {
return listPtr->name;
}
listPtr=listPtr->next;
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* curlReturnCURLMcode
*
* When one of the command wants to return a CURLMcode, it calls
* this function.
*
* Parameter:
* interp: Pointer to the interpreter we are using.
* errorCode: the value to be returned.
*
* Results:
* A standard Tcl result.
*----------------------------------------------------------------------
*/
int
curlReturnCURLMcode (Tcl_Interp *interp,CURLMcode errorCode) {
Tcl_Obj *resultPtr;
resultPtr=Tcl_NewIntObj(errorCode);
Tcl_SetObjResult(interp,resultPtr);
if (errorCode>0) {
return TCL_ERROR;
}
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* curlMultiAutoTransfer --
*
* Creates the event source that will take care of downloading using
* the multi interface driven by Tcl's event loop.
*
* Parameters:
* The usual Tcl command parameters.
*
* Results:
* Standard Tcl return code.
*----------------------------------------------------------------------
*/
int
curlMultiAutoTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData,
int objc,Tcl_Obj *CONST objv[]) {
if (objc==4) {
Tcl_Free(curlMultiData->postCommand);
curlMultiData->postCommand=curlstrdup(Tcl_GetString(objv[3]));
}
Tcl_CreateEventSource((Tcl_EventSetupProc *)curlEventSetup,
(Tcl_EventCheckProc *)curlEventCheck, (ClientData *)curlMultiData);
/* We have to call perform once to boot the transfer, otherwise it seems nothing
works *shrug* */
while(CURLM_CALL_MULTI_PERFORM ==
curl_multi_perform(curlMultiData->mcurl,&(curlMultiData->runningTransfers))) {
}
return TCL_OK;
}
/*----------------------------------------------------------------------
*
* curlMultiConfigTrasnfer --
* This procedure is invoked by the user command 'configure', it reads
* the options passed by the user to configure a multi handle.
*
* Parameters:
* The usual Tcl command parameters.
*
* Results:
* Standard Tcl return code.
*----------------------------------------------------------------------
*/
int
curlMultiConfigTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData,
int objc,Tcl_Obj *CONST objv[]) {
int tableIndex;
int i,j;
Tcl_Obj *resultPtr;
char errorMsg[500];
for(i=2,j=3;i<objc;i=i+2,j=j+2) {
if (Tcl_GetIndexFromObj(interp, objv[i], multiConfigTable, "option",
TCL_EXACT, &tableIndex)==TCL_ERROR) {
return TCL_ERROR;
}
if (i==objc-1) {
snprintf(errorMsg,500,"Empty value for %s",multiConfigTable[tableIndex]);
resultPtr=Tcl_NewStringObj(errorMsg,-1);
Tcl_SetObjResult(interp,resultPtr);
return TCL_ERROR;
}
if (curlMultiSetOpts(interp,curlMultiData,objv[j],tableIndex)==TCL_ERROR) {
return TCL_ERROR;
}
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* curlMultiSetOpts --
*
* This procedure takes care of setting the transfer options.
*
* Parameter:
* interp: Pointer to the interpreter we are using.
* curlMultiHandle: the curl handle for which the option is set.
* objv: A pointer to the object where the data to set is stored.
* tableIndex: The index of the option in the options table.
*
* Results:
* A standard Tcl result.
*----------------------------------------------------------------------
*/
int
curlMultiSetOpts(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData,
Tcl_Obj *CONST objv,int tableIndex) {
switch(tableIndex) {
case 0:
if (SetMultiOptLong(interp,curlMultiData->mcurl,
CURLMOPT_PIPELINING,tableIndex,objv)) {
return TCL_ERROR;
}
break;
case 1:
if (SetMultiOptLong(interp,curlMultiData->mcurl,
CURLMOPT_MAXCONNECTS,tableIndex,objv)) {
return TCL_ERROR;
}
break;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* SetMultiOptLong --
*
* Set the curl options that require a long
*
* Parameter:
* interp: The interpreter we are working with.
* curlMultiHandle: and the multi curl handle
* opt: the option to set
* tclObj: The Tcl with the value for the option.
*
* Results:
* 0 if all went well.
* 1 in case of error.
*----------------------------------------------------------------------
*/
int
SetMultiOptLong(Tcl_Interp *interp,CURLM *curlMultiHandle,CURLMoption opt,
int tableIndex,Tcl_Obj *tclObj) {
long longNumber;
char *parPtr;
if (Tcl_GetLongFromObj(interp,tclObj,&longNumber)) {
parPtr=curlstrdup(Tcl_GetString(tclObj));
curlErrorSetOpt(interp,multiConfigTable,tableIndex,parPtr);
Tcl_Free(parPtr);
return 1;
}
if (curl_multi_setopt(curlMultiHandle,opt,longNumber)) {
parPtr=curlstrdup(Tcl_GetString(tclObj));
curlErrorSetOpt(interp,multiConfigTable,tableIndex,parPtr);
Tcl_Free(parPtr);
return 1;
}
return 0;
}
/*----------------------------------------------------------------------
*
* curlEventSetup --
*
* This function is invoked by Tcl just after curlMultiAutoTransfer and
* then every time just before curlEventCheck, I only use to set the
* maximun time without checking for events
*
* NOTE: I hate having a fixed value, I will have to look into it.
*
* Parameters:
* They are passed automagically by Tcl, but I don't use them.
*----------------------------------------------------------------------
*/
void
curlEventSetup(ClientData clientData, int flags) {
Tcl_Time time = {0 , 0};
Tcl_SetMaxBlockTime(&time);
}
/*----------------------------------------------------------------------
*
* curlEventCheck --
*
* Invoked automagically by Tcl from time to time, we check if there
* are any active transfer, if so we put an event in the queue so that
* 'curl_multi_perfom' will be eventually called, if not we delete
* the event source.
*
* Parameters:
* They are passed automagically by Tcl.
*----------------------------------------------------------------------
*/
void
curlEventCheck(ClientData clientData, int flags) {
struct curlMultiObjData *curlMultiData=(struct curlMultiObjData *)clientData;
struct curlEvent *curlEventPtr;
int selectCode;
selectCode=curlMultiGetActiveTransfers(curlMultiData);
if (curlMultiData->runningTransfers==0) {
Tcl_DeleteEventSource((Tcl_EventSetupProc *)curlEventSetup,
(Tcl_EventCheckProc *)curlEventCheck, (ClientData *)curlMultiData);
} else {
if (selectCode>=0) {
curlEventPtr=(struct curlEvent *)Tcl_Alloc(sizeof(struct curlEvent));
curlEventPtr->proc=curlEventProc;
curlEventPtr->curlMultiData=curlMultiData;
Tcl_QueueEvent((Tcl_Event *)curlEventPtr, TCL_QUEUE_TAIL);
}
}
}
/*----------------------------------------------------------------------
*
* curlEventProc --
*
* Finally Tcl event loop decides it is time to transfer something.
*
* Parameters:
* They are passed automagically by Tcl.
*----------------------------------------------------------------------
*/
int
curlEventProc(Tcl_Event *evPtr,int flags) {
struct curlMultiObjData *curlMultiData
=(struct curlMultiObjData *)((struct curlEvent *)evPtr)->curlMultiData;
CURLMcode errorCode;
Tcl_Obj *tclCommandObjPtr;
char tclCommand[300];
errorCode=curl_multi_perform(curlMultiData->mcurl,&curlMultiData->runningTransfers);
if (curlMultiData->runningTransfers==0) {
if (curlMultiData->postCommand!=NULL) {
snprintf(tclCommand,299,"%s",curlMultiData->postCommand);
tclCommandObjPtr=Tcl_NewStringObj(tclCommand,-1);
if (Tcl_EvalObjEx(curlMultiData->interp,tclCommandObjPtr,TCL_EVAL_GLOBAL)!=TCL_OK) {
/*
fprintf(stdout,"Error invoking command\n");
fprintf(stdout,"Error: %s\n",Tcl_GetString(Tcl_GetObjResult(curlMultiData->interp)));
*/
}
}
}
return 1;
}

115
generic/multi.h Executable file
View File

@ -0,0 +1,115 @@
/*
* multi.h --
*
* Header file for the part of the TclCurl extension that deals with libcurl's
* 'multi' interface.
*
* Copyright (c) 2002-2011 Andres Garcia Garcia.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#define multi_h
#include "tclcurl.h"
#ifdef __cplusplus
extern "C" {
#endif
struct easyHandleList {
CURL *curl;
char *name;
struct easyHandleList *next;
};
struct curlMultiObjData {
CURLM *mcurl;
Tcl_Command token;
Tcl_Interp *interp;
struct easyHandleList *handleListFirst;
struct easyHandleList *handleListLast;
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int runningTransfers;
char *postCommand;
};
struct curlEvent {
Tcl_EventProc *proc;
struct Tcl_Event *nextPtr;
struct curlMultiObjData *curlMultiData;
};
CONST static char *multiCommandTable[] = {
"addhandle",
"removehandle",
"perform",
"cleanup",
"getinfo",
"active",
"auto",
"configure",
(char *) NULL
};
CONST static char *multiConfigTable[] = {
"-pipelining", "-maxconnects",
(char *)NULL
};
char *curlCreateMultiObjCmd (Tcl_Interp *interp,struct curlMultiObjData *curlMultiData);
int Tclcurl_MultiInit (Tcl_Interp *interp);
int curlMultiDeleteCmd(ClientData clientData);
int curlInitMultiObjCmd (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlMultiObjCmd (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
CURLMcode curlAddMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandle
,Tcl_Obj *objvPtr);
CURLMcode curlRemoveMultiHandle(Tcl_Interp *interp,CURLM *curlMultiHandle
,Tcl_Obj *objvPtr);
int curlMultiPerform(Tcl_Interp *interp,CURLM *curlMultiHandle);
int curlMultiGetInfo(Tcl_Interp *interp,CURLM *curlMultiHandlePtr);
int curlMultiGetActiveTransfers( struct curlMultiObjData *curlMultiData);
int curlMultiActiveTransfers(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData);
struct curlObjData *curlGetEasyHandle(Tcl_Interp *interp,Tcl_Obj *nameObjPtr);
void curlMultiFreeSpace(struct curlMultiObjData *curlMultiData);
int curlReturnCURLMcode(Tcl_Interp *interp,CURLMcode errorCode);
void curlEasyHandleListAdd(struct curlMultiObjData *multiDataPtr,CURL *easyHandle,char *name);
void curlEasyHandleListRemove(struct curlMultiObjData *multiDataPtr,CURL *easyHandle);
char *curlGetEasyName(struct curlMultiObjData *multiDataPtr,CURL *easyHandle);
int curlMultiAutoTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc,Tcl_Obj *CONST objv[]);
int curlMultiSetOpts(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData,Tcl_Obj *CONST objv,int tableIndex);
int SetMultiOptLong(Tcl_Interp *interp,CURLM *curlMultiHandle,CURLMoption opt,
int tableIndex,Tcl_Obj *tclObj);
int curlMultiConfigTransfer(Tcl_Interp *interp, struct curlMultiObjData *curlMultiData, int objc,Tcl_Obj *CONST objv[]);
void curlEventSetup(ClientData clientData, int flags);
void curlEventCheck(ClientData clientData, int flags);
int curlEventProc(Tcl_Event *evPtr,int flags);
#ifdef __cplusplus
}
#endif

4500
generic/tclcurl.c Executable file

File diff suppressed because it is too large Load Diff

512
generic/tclcurl.h Executable file
View File

@ -0,0 +1,512 @@
/*
* tclcurl.h --
*
* Header file for the TclCurl extension to enable Tcl interpreters
* to access libcurl.
*
* Copyright (c) 2001-2011 Andres Garcia Garcia.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
*/
#if (defined(WIN32) || defined(_WIN32))
#define CURL_STATICLIB 1
#endif
#include <curl/curl.h>
#include <curl/easy.h>
#include <tcl.h>
#include <tclDecls.h>
#include <stdio.h>
#include <string.h>
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Windows needs to know which symbols to export. Unix does not.
* BUILD_tclcurl should be undefined for Unix.
* Actually I don't use this, but it was in TEA so I keep in case
* I ever understand what it is for.
*/
#ifdef BUILD_tclcurl
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLEXPORT
#endif
#define TclCurlVersion "7.22.0"
/*
* This struct will contain the data of a transfer if the user wants
* to put the body into a Tcl variable
*/
struct MemoryStruct {
char *memory;
size_t size;
};
/*
* Struct that will be used for a linked list with all the
* data for a post
*/
struct formArrayStruct {
struct curl_forms *formArray;
struct curl_slist *formHeaderList;
struct formArrayStruct *next;
};
struct curlObjData {
CURL *curl;
Tcl_Command token;
Tcl_Command shareToken;
Tcl_Interp *interp;
struct curl_slist *headerList;
struct curl_slist *quote;
struct curl_slist *prequote;
struct curl_slist *postquote;
struct curl_httppost *postListFirst;
struct curl_httppost *postListLast;
struct formArrayStruct *formArray;
char *outFile;
FILE *outHandle;
int outFlag;
char *inFile;
FILE *inHandle;
int inFlag;
char *proxy;
int transferText;
char *errorBuffer;
char *errorBufferName;
char *errorBufferKey;
char *headerFile;
FILE *headerHandle;
int headerFlag;
char *stderrFile;
FILE *stderrHandle;
int stderrFlag;
char *randomFile;
char *headerVar;
char *bodyVarName;
struct MemoryStruct bodyVar;
char *progressProc;
char *cancelTransVarName;
int cancelTrans;
char *writeProc;
char *readProc;
char *debugProc;
struct curl_slist *http200aliases;
char *command;
int anyAuthFlag;
char *sshkeycallProc;
struct curl_slist *mailrcpt;
char *chunkBgnProc;
char *chunkBgnVar;
char *chunkEndProc;
char *fnmatchProc;
struct curl_slist *resolve;
struct curl_slist *telnetoptions;
};
struct shcurlObjData {
Tcl_Command token;
CURLSH *shandle;
};
#ifndef multi_h
CONST static char *commandTable[] = {
"setopt",
"perform",
"getinfo",
"cleanup",
"configure",
"duphandle",
"reset",
"pause",
"resume",
(char *) NULL
};
CONST static char *optionTable[] = {
"CURLOPT_URL", "CURLOPT_FILE", "CURLOPT_READDATA",
"CURLOPT_USERAGENT", "CURLOPT_REFERER", "CURLOPT_VERBOSE",
"CURLOPT_HEADER", "CURLOPT_NOBODY", "CURLOPT_PROXY",
"CURLOPT_PROXYPORT", "CURLOPT_HTTPPROXYTUNNEL", "CURLOPT_FAILONERROR",
"CURLOPT_TIMEOUT", "CURLOPT_LOW_SPEED_LIMIT", "CURLOPT_LOW_SPEED_TIME",
"CURLOPT_RESUME_FROM", "CURLOPT_INFILESIZE", "CURLOPT_UPLOAD",
"CURLOPT_FTPLISTONLY", "CURLOPT_FTPAPPEND", "CURLOPT_NETRC",
"CURLOPT_FOLLOWLOCATION","CURLOPT_TRANSFERTEXT", "CURLOPT_PUT",
"CURLOPT_MUTE", "CURLOPT_USERPWD", "CURLOPT_PROXYUSERPWD",
"CURLOPT_RANGE", "CURLOPT_ERRORBUFFER", "CURLOPT_HTTPGET",
"CURLOPT_POST", "CURLOPT_POSTFIELDS", "CURLOPT_POSTFIELDSIZE",
"CURLOPT_FTPPORT", "CURLOPT_COOKIE", "CURLOPT_COOKIEFILE",
"CURLOPT_HTTPHEADER", "CURLOPT_HTTPPOST", "CURLOPT_SSLCERT",
"CURLOPT_SSLCERTPASSWD", "CURLOPT_SSLVERSION", "CURLOPT_CRLF",
"CURLOPT_QUOTE", "CURLOPT_POSTQUOTE", "CURLOPT_WRITEHEADER",
"CURLOPT_TIMECONDITION", "CURLOPT_TIMEVALUE", "CURLOPT_CUSTOMREQUEST",
"CURLOPT_STDERR", "CURLOPT_INTERFACE", "CURLOPT_KRB4LEVEL",
"CURLOPT_SSL_VERIFYPEER","CURLOPT_CAINFO", "CURLOPT_FILETIME",
"CURLOPT_MAXREDIRS", "CURLOPT_MAXCONNECTS", "CURLOPT_CLOSEPOLICY",
"CURLOPT_RANDOM_FILE", "CURLOPT_EGDSOCKET", "CURLOPT_CONNECTTIMEOUT",
"CURLOPT_NOPROGRESS", "CURLOPT_HEADERVAR", "CURLOPT_BODYVAR",
"CURLOPT_PROGRESSPROC","CURLOPT_CANCELTRANSVARNAME","CURLOPT_WRITEPROC",
"CURLOPT_READPROC", "CURLOPT_SSL_VERIFYHOST", "CURLOPT_COOKIEJAR",
"CURLOPT_SSL_CIPHER_LIST","CURLOPT_HTTP_VERSION", "CURLOPT_FTP_USE_EPSV",
"CURLOPT_SSLCERTTYPE", "CURLOPT_SSLKEY", "CURLOPT_SSLKEYTYPE",
"CURLOPT_SSLKEYPASSWD", "CURLOPT_SSL_ENGINE", "CURLOPT_SSL_ENGINEDEFAULT",
"CURLOPT_PREQUOTE", "CURLOPT_DEBUGPROC", "CURLOPT_DNS_CACHE_TIMEOUT",
"CURLOPT_DNS_USE_GLOBAL_CACHE", "CURLOPT_COOKIESESSION","CURLOPT_CAPATH",
"CURLOPT_BUFFERSIZE", "CURLOPT_NOSIGNAL", "CURLOPT_ENCODING",
"CURLOPT_PROXYTYPE", "CURLOPT_HTTP200ALIASES", "CURLOPT_UNRESTRICTED_AUTH",
"CURLOPT_FTP_USE_EPRT", "CURLOPT_NOSUCHOPTION", "CURLOPT_HTTPAUTH",
"CURLOPT_FTP_CREATE_MISSING_DIRS", "CURLOPT_PROXYAUTH",
"CURLOPT_FTP_RESPONSE_TIMEOUT", "CURLOPT_IPRESOLVE",
"CURLOPT_MAXFILESIZE", "CURLOPT_NETRC_FILE", "CURLOPT_FTP_SSL",
"CURLOPT_SHARE", "CURLOPT_PORT", "CURLOPT_TCP_NODELAY",
"CURLOPT_AUTOREFERER", "CURLOPT_SOURCE_HOST", "CURLOPT_SOURCE_USERPWD",
"CURLOPT_SOURCE_PATH", "CURLOPT_SOURCE_PORT", "CURLOPT_PASV_HOST",
"CURLOPT_SOURCE_PREQUOTE","CURLOPT_SOURCE_POSTQUOTE",
"CURLOPT_FTPSSLAUTH", "CURLOPT_SOURCE_URL", "CURLOPT_SOURCE_QUOTE",
"CURLOPT_FTP_ACCOUNT", "CURLOPT_IGNORE_CONTENT_LENGTH",
"CURLOPT_COOKIELIST", "CURLOPT_FTP_SKIP_PASV_IP",
"CURLOPT_FTP_FILEMETHOD", "CURLOPT_LOCALPORT", "CURLOPT_LOCALPORTRANGE",
"CURLOPT_MAX_SEND_SPEED_LARGE", "CURLOPT_MAX_RECV_SPEED_LARGE",
"CURLOPT_FTP_ALTERNATIVE_TO_USER", "CURLOPT_SSL_SESSIONID_CACHE",
"CURLOPT_SSH_AUTH_TYPES", "CURLOPT_SSH_PUBLIC_KEYFILE",
"CURLOPT_SSH_PRIVATE_KEYFILE", "CURLOPT_TIMEOUT_MS",
"CURLOPT_CONNECTTIMEOUT_MS", "CURLOPT_HTTP_CONTENT_DECODING",
"CURLOPT_HTTP_TRANSFER_DECODING", "CURLOPT_KRBLEVEL",
"CURLOPT_NEW_FILE_PERMS", "CURLOPT_NEW_DIRECTORY_PERMS",
"CURLOPT_KEYPASSWD", "CURLOPT_APPEND", "CURLOPT_DIRLISTONLY",
"CURLOPT_USE_SSL", "CURLOPT_POST301", "CURLOPT_SSH_HOST_PUBLIC_KEY_MD5",
"CURLOPT_PROXY_TRANSFER_MODE", "CURLOPT_CRLFILE",
"CURLOPT_ISSUERCERT", "CURLOPT_ADDRESS_SCOPE", "CURLOPT_CERTINFO",
"CURLOPT_POSTREDIR", "CURLOPT_USERNAME", "CURLOPT_PASSWORD",
"CURLOPT_PROXYUSERNAME", "CURLOPT_PROXYPASSWORD", "CURLOPT_TFTP_BLKSIZE",
"CURLOPT_SOCKS5_GSSAPI_SERVICE", "CURLOPT_SOCKS5_GSSAPI_NEC",
"CURLOPT_PROTOCOLS", "CURLOPT_REDIR_PROTOCOLS","CURLOPT_FTP_SSL_CC",
"CURLOPT_SSH_KNOWNHOSTS", "CURLOPT_SSH_KEYFUNCTION","CURLOPT_MAIL_FROM",
"CURLOPT_MAIL_RCPT", "CURLOPT_FTP_USE_PRET", "CURLOPT_WILDCARDMATCH",
"CURLOPT_CHUNK_BGN_PROC", "CURLOPT_CHUNK_BGN_VAR", "CURLOPT_CHUNK_END_PROC",
"CURLOPT_FNMATCH_PROC", "CURLOPT_RESOLVE", "CURLOPT_TLSAUTH_USERNAME",
"CURLOPT_TLSAUTH_PASSWORD","CURLOPT_GSSAPI_DELEGATION", "CURLOPT_NOPROXY",
"CURLOPT_TELNETOPTIONS",
(char *)NULL
};
CONST static char *configTable[] = {
"-url", "-file", "-infile",
"-useragent", "-referer", "-verbose",
"-header", "-nobody", "-proxy",
"-proxyport", "-httpproxytunnel", "-failonerror",
"-timeout", "-lowspeedlimit", "-lowspeedtime",
"-resumefrom", "-infilesize", "-upload",
"-ftplistonly", "-ftpappend", "-netrc",
"-followlocation", "-transfertext", "-put",
"-mute", "-userpwd", "-proxyuserpwd",
"-range", "-errorbuffer", "-httpget",
"-post", "-postfields", "-postfieldssize",
"-ftpport", "-cookie", "-cookiefile",
"-httpheader", "-httppost", "-sslcert",
"-sslcertpasswd", "-sslversion", "-crlf",
"-quote", "-postquote", "-writeheader",
"-timecondition", "-timevalue", "-customrequest",
"-stderr", "-interface", "-krb4level",
"-sslverifypeer", "-cainfo", "-filetime",
"-maxredirs", "-maxconnects", "-closepolicy",
"-randomfile", "-egdsocket", "-connecttimeout",
"-noprogress", "-headervar", "-bodyvar",
"-progressproc", "-canceltransvarname", "-writeproc",
"-readproc", "-sslverifyhost", "-cookiejar",
"-sslcipherlist", "-httpversion", "-ftpuseepsv",
"-sslcerttype", "-sslkey", "-sslkeytype",
"-sslkeypasswd", "-sslengine", "-sslenginedefault",
"-prequote", "-debugproc", "-dnscachetimeout",
"-dnsuseglobalcache", "-cookiesession", "-capath",
"-buffersize", "-nosignal", "-encoding",
"-proxytype", "-http200aliases", "-unrestrictedauth",
"-ftpuseeprt", "-command", "-httpauth",
"-ftpcreatemissingdirs", "-proxyauth",
"-ftpresponsetimeout", "-ipresolve",
"-maxfilesize", "-netrcfile", "-ftpssl",
"-share", "-port", "-tcpnodelay",
"-autoreferer", "-sourcehost", "-sourceuserpwd",
"-sourcepath", "-sourceport", "-pasvhost",
"-sourceprequote", "-sourcepostquote", "-ftpsslauth",
"-sourceurl", "-sourcequote", "-ftpaccount",
"-ignorecontentlength", "-cookielist",
"-ftpskippasvip", "-ftpfilemethod", "-localport",
"-localportrange",
"-maxsendspeed", "-maxrecvspeed",
"-ftpalternativetouser", "-sslsessionidcache",
"-sshauthtypes", "-sshpublickeyfile", "-sshprivatekeyfile",
"-timeoutms", "-connecttimeoutms", "-contentdecoding",
"-transferdecoding", "-krblevel", "-newfileperms",
"-newdirectoryperms", "-keypasswd", "-append",
"-dirlistonly", "-usessl", "-post301",
"-sshhostpublickeymd5", "-proxytransfermode",
"-crlfile", "-issuercert", "-addressscope",
"-certinfo", "-postredir", "-username",
"-password", "-proxyuser", "-proxypassword",
"-tftpblksize", "-socks5gssapiservice","-socks5gssapinec",
"-protocols", "-redirprotocols", "-ftpsslcc",
"-sshknownhosts", "-sshkeyproc", "-mailfrom",
"-mailrcpt", "-ftpusepret", "-wildcardmatch",
"-chunkbgnproc", "-chunkbgnvar", "-chunkendproc",
"-fnmatchproc", "-resolve", "-tlsauthusername",
"-tlsauthpassword", "-gssapidelegation", "-noproxy",
"-telnetoptions",
(char *) NULL
};
CONST static char *timeCond[] = {
"ifmodsince", "ifunmodsince",
(char *)NULL
};
CONST static char *getInfoTable[]={
"effectiveurl", "httpcode", "responsecode",
"filetime", "totaltime", "namelookuptime",
"connecttime", "pretransfertime","sizeupload",
"sizedownload", "speeddownload", "speedupload",
"headersize", "requestsize", "sslverifyresult",
"contentlengthdownload", "contentlengthupload",
"starttransfertime", "contenttype",
"redirecttime", "redirectcount", "httpauthavail",
"proxyauthavail", "oserrno", "numconnects",
"sslengines", "httpconnectcode","cookielist",
"ftpentrypath", "redirecturl", "primaryip",
"appconnecttime", "certinfo", "conditionunmet",
"primaryport", "localip", "localport",
(char *)NULL
};
CONST static char *curlFormTable[]={
"name", "contents", "file", "contenttype", "contentheader", "filename",
"bufferName", "buffer", "filecontent", (char *)NULL
};
CONST static char *httpVersionTable[] = {
"none", "1.0", "1.1", (char *)NULL
};
CONST static char *netrcTable[] = {
"optional", "ignored", "required", (char *)NULL
};
CONST static char *encodingTable[] = {
"identity", "deflated", "all", (char *)NULL
};
CONST static char *versionInfoTable[] = {
"-version", "-versionnum", "-host", "-features",
"-sslversion", "-sslversionnum", "-libzversion",
"-protocols", (char *)NULL
};
CONST static char *proxyTypeTable[] = {
"http", "http1.0", "socks4", "socks4a", "socks5", "socks5h", (char *)NULL
};
CONST static char *httpAuthMethods[] = {
"basic", "digest", "digestie", "gssnegotiate", "ntlm", "any", "anysafe", "ntlmwb",(char *)NULL
};
CONST static char *ipresolve[] = {
"whatever", "v4", "v6", (char *)NULL
};
CONST static char *ftpssl[] = {
"nope", "try", "control", "all", (char *)NULL
};
CONST static char *shareCmd[] = {
"share", "unshare", "cleanup", (char *)NULL
};
CONST static char *lockData[] = {
"cookies", "dns", (char *)NULL
};
CONST static char *ftpsslauth[] = {
"default", "ssl", "tls", (char *)NULL
};
CONST static char *ftpsslccc[] = {
"none", "passive", "active", (char *)NULL
};
CONST static char *sslversion[] = {
"default", "tlsv1", "sslv2", "sslv3", (char *)NULL
};
CONST static char *ftpfilemethod[] = {
"default", "multicwd", "nocwd", "singlecwd", (char *)NULL
};
CONST static char *sshauthtypes[] = {
"publickey", "password", "host", "keyboard", "any", (char *)NULL
};
CONST static char *postredir[] = {
"301", "302", "all", (char *)NULL
};
CONST static char *protocolNames[] = {
"http", "https", "ftp", "ftps", "scp", "sftp", "telnet", "ldap",
"ldaps","dict", "file","tftp", "all", "imap", "imaps", "pop3",
"pop3s", "smtp", "smtps", "rtsp", "rtmp", "rtmpt", "rtmpe",
"rtmpte", "rtmps", "rtmpts", "gopher", (char*)NULL
};
CONST static char *tlsauth[] = {
"none", "srp", (char *)NULL
};
CONST static char *gssapidelegation[] = {
"flag", "policyflag", (char *) NULL
};
int curlseek(void *instream, curl_off_t offset, int origin);
int Tclcurl_MultiInit (Tcl_Interp *interp);
#endif
int Tclcurl_Init(Tcl_Interp *interp);
char *curlCreateObjCmd(Tcl_Interp *interp,struct curlObjData *curlData);
int curlInitObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]);
int curlObjCmd(ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj *CONST objv[]);
int curlDeleteCmd(ClientData clientData);
int curlPerform(Tcl_Interp *interp,CURL *curlHandle,struct curlObjData *curlData);
int curlSetOptsTransfer(Tcl_Interp *interp, struct curlObjData *curlData,int objc,
Tcl_Obj *CONST objv[]);
int curlConfigTransfer(Tcl_Interp *interp, struct curlObjData *curlData,int objc,
Tcl_Obj *CONST objv[]);
int curlDupHandle(Tcl_Interp *interp, struct curlObjData *curlData,int objc,
Tcl_Obj *CONST objv[]);
int curlResetHandle(Tcl_Interp *interp, struct curlObjData *curlData);
int curlSetOpts(Tcl_Interp *interp, struct curlObjData *curlData,
Tcl_Obj *CONST objv,int tableIndex);
int SetoptInt(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,
Tcl_Obj *tclObj);
int SetoptLong(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,
Tcl_Obj *tclObj);
int SetoptCurlOffT(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,int tableIndex,
Tcl_Obj *tclObj);
int SetoptChar(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,
int tableIndex,Tcl_Obj *tclObj);
int SetoptSHandle(Tcl_Interp *interp,CURL *curlHandle,CURLoption opt,
int tableIndex,Tcl_Obj *tclObj);
int SetoptsList(Tcl_Interp *interp,struct curl_slist **slistPtr,Tcl_Obj *CONST objv);
CURLcode curlGetInfo(Tcl_Interp *interp,CURL *curlHandle,int tableIndex);
void curlFreeSpace(struct curlObjData *curlData);
void curlErrorSetOpt(Tcl_Interp *interp,CONST char **configTable, int option,CONST char *parPtr);
size_t curlHeaderReader(void *ptr,size_t size,size_t nmemb,FILE *stream);
size_t curlBodyReader(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr);
int curlProgressCallback(void *clientp,double dltotal,double dlnow,
double ultotal,double ulnow);
size_t curlWriteProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr);
size_t curlReadProcInvoke(void *ptr,size_t size,size_t nmemb,FILE *curlDataPtr);
long curlChunkBgnProcInvoke (const void *transfer_info, void *curlDataPtr, int remains);
long curlChunkEndProcInvoke (void *curlDataPtr);
int curlfnmatchProcInvoke(void *curlDataPtr, const char *pattern, const char *filename);
/* Puts a ssh key into a Tcl object */
Tcl_Obj *curlsshkeyextract(Tcl_Interp *interp,const struct curl_khkey *key);
/* Function that will be invoked by libcurl to see what the user wants to
do about the new ssh host */
size_t curlsshkeycallback(CURL *easy, /* easy handle */
const struct curl_khkey *knownkey, /* known */
const struct curl_khkey *foundkey, /* found */
enum curl_khmatch, /* libcurl's view on the keys */
void *curlData);
int curlDebugProcInvoke(CURL *curlHandle, curl_infotype infoType,
char * dataPtr, size_t size, void *curlData);
int curlVersion (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlEscape(ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlUnescape(ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlVersionInfo (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlCopyCurlData (struct curlObjData *curlDataOld,
struct curlObjData *curlDataNew);
int curlOpenFile(Tcl_Interp *interp,char *fileName, FILE **handle, int writing, int text);
int curlOpenFiles (Tcl_Interp *interp,struct curlObjData *curlData);
void curlCloseFiles(struct curlObjData *curlData);
int curlSetPostData(Tcl_Interp *interp,struct curlObjData *curlData);
void curlResetPostData(struct curlObjData *curlDataPtr);
void curlResetFormArray(struct curl_forms *formArray);
void curlSetBodyVarName(Tcl_Interp *interp,struct curlObjData *curlDataPtr);
char *curlstrdup (char *old);
char *curlCreateShareObjCmd (Tcl_Interp *interp,struct shcurlObjData *shcurlData);
int curlShareInitObjCmd (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlShareObjCmd (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlCleanUpShareCmd(ClientData clientData);
#ifdef TCL_THREADS
TCL_DECLARE_MUTEX(cookieLock)
TCL_DECLARE_MUTEX(dnsLock)
TCL_DECLARE_MUTEX(sslLock)
TCL_DECLARE_MUTEX(connectLock)
void curlShareLockFunc (CURL *handle, curl_lock_data data
, curl_lock_access access, void *userptr);
void curlShareUnLockFunc(CURL *handle, curl_lock_data data, void *userptr);
#endif
int curlErrorStrings (Tcl_Interp *interp, Tcl_Obj *CONST objv,int type);
int curlEasyStringError (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlShareStringError (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
int curlMultiStringError (ClientData clientData, Tcl_Interp *interp,
int objc,Tcl_Obj *CONST objv[]);
#ifdef __cplusplus
}
#endif

145
generic/tclcurl.tcl Executable file
View File

@ -0,0 +1,145 @@
################################################################################
################################################################################
#### tclcurl.tcl
################################################################################
################################################################################
## Includes the tcl part of TclCurl
################################################################################
################################################################################
## (c) 2001-2011 Andres Garcia Garcia. fandom@telefonica.net
## See the file "license.terms" for information on usage and redistribution
## of this file and for a DISCLAIMER OF ALL WARRANTIES.
################################################################################
################################################################################
package provide TclCurl 7.22.0
namespace eval curl {
################################################################################
# configure
# Invokes the 'curl-config' script to be able to know what features have
# been compiled in the installed version of libcurl.
# Possible options are '-prefix', '-feature' and 'vernum'
################################################################################
proc ::curl::curlConfig {option} {
if {$::tcl_platform(platform)=="windows"} {
error "This command is not available in Windows"
}
switch -exact -- $option {
-prefix {
return [exec curl-config --prefix]
}
-feature {
set featureList [exec curl-config --feature]
regsub -all {\\n} $featureList { } featureList
return $featureList
}
-vernum {
return [exec curl-config --vernum]
}
-ca {
return [exec curl-config --ca]
}
default {
error "bad option '$option': must be '-prefix', '-feature', '-vernum' or '-ca'"
}
}
return
}
################################################################################
# transfer
# The transfer command is used for simple transfers in which you don't
# want to request more than one file.
#
# Parameters:
# Use the same parameters you would use in the 'configure' command to
# configure the download and the same as in 'getinfo' with a 'info'
# prefix to get info about the transfer.
################################################################################
proc ::curl::transfer {args} {
variable getInfo
variable curlBodyVar
set i 0
set newArgs ""
catch {unset getInfo}
if {[llength $args]==0} {
puts "No transfer configured"
return
}
foreach {option value} $args {
set noPassOption 0
set block 1
switch -regexp -- $option {
-info.* {
set noPassOption 1
regsub -- {-info} $option {} option
set getInfo($option) $value
}
-block {
set noPassOption 1
set block $value
}
-bodyvar {
upvar $value curlBodyVar
set value curlBodyVar
}
-headervar {
upvar $value curlHeaderVar
set value curlHeaderVar
}
-errorbuffer {
upvar $value curlErrorVar
set value curlErrorVar
}
}
if {$noPassOption==0} {
lappend newArgs $option $value
}
}
if {[catch {::curl::init} curlHandle]} {
error "Could not init a curl session: $curlHandle"
}
if {[catch {eval $curlHandle configure $newArgs} result]} {
$curlHandle cleanup
error $result
}
if {$block==1} {
if {[catch {$curlHandle perform} result]} {
$curlHandle cleanup
error $result
}
if {[info exists getInfo]} {
foreach {option var} [array get getInfo] {
upvar $var info
set info [eval $curlHandle getinfo $option]
}
}
if {[catch {$curlHandle cleanup} result]} {
error $result
}
} else {
# We create a multiHandle
set multiHandle [curl::multiinit]
# We add the easy handle to the multi handle.
$multiHandle addhandle $curlHandle
# So now we create the event source passing the multiHandle as a parameter.
curl::createEventSource $multiHandle
# And we return, it is non blocking after all.
}
return 0
}
}

38
license.terms Executable file
View File

@ -0,0 +1,38 @@
This software is copyrighted by Andres Garcia Garcia and other parties.
The following terms apply to all files associated with the
software unless explicitly disclaimed in individual files.
The authors hereby grant permission to use, copy, modify, distribute,
and license this software and its documentation for any purpose, provided
that existing copyright notices are retained in all copies and that this
notice is included verbatim in any distributions. No written agreement,
license, or royalty fee is required for any of the authorized uses.
Modifications to this software may be copyrighted by their authors
and need not follow the licensing terms described here, provided that
the new terms are clearly indicated on the first page of each file where
they apply.
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
MODIFICATIONS.
GOVERNMENT USE: If you are acquiring this software on behalf of the
U.S. government, the Government shall have only "Restricted Rights"
in the software and related documentation as defined in the Federal
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
are acquiring the software on behalf of the Department of Defense, the
software shall be classified as "Commercial Computer Software" and the
Government shall have only "Restricted Rights" as defined in Clause
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.

View File

@ -0,0 +1,42 @@
Name: tclcurl
Version: 7.22.0
Release: 1
License: BSD revised
Group: Development/Libraries
Packager: Andres Garcia <fandom@telefonica.net>
Vendor: Fandom Enterprise
Source: http://personal1.iddeo.es/andresgarci/tclcurl/download/tarball/tclcurl-7.22.0.tar.gz
Summary: A Tcl interface for libcurl.
%description
TclCurl provides a binding to libcurl, with it you can upload
and download files using FTP, FTPS, HTTP, HTTPS, SCP, SFTP, TFTP, TELNET, DICT, FILE, LDAP,
LDAPS, IMAP, IMAPS, POP, POP3, SMTP, SMTPS and gopher syntax.
%prep
%setup
%build
./configure --mandir=/usr/share/man --prefix=/usr
make
%install
make install
mkdir -p /usr/share/doc/tclcurl-7.22.0/tests
cp -f ReadMe.txt /usr/share/doc/tclcurl-7.22.0/
cp -f license.terms /usr/share/doc/tclcurl-7.22.0/
cp -f doc/tclcurl.html /usr/share/doc/tclcurl-7.22.0/
cp -f doc/tclcurl_multi.html /usr/share/doc/tclcurl-7.22.0/
cp -f doc/tclcurl_share.html /usr/share/doc/tclcurl-7.22.0/
cp -f doc/aolserver.txt /usr/share/doc/tclcurl-7.22.0/
cp -f tests/*.tcl /usr/share/doc/tclcurl-7.22.0/tests
%files
/usr/lib/TclCurl7.22.0/
/usr/share/doc/tclcurl-7.22.0/
/usr/share/man/mann/tclcurl.n.gz
/usr/share/man/mann/tclcurl_multi.n.gz
/usr/share/man/mann/tclcurl_share.n.gz

42
packages/Windows/SetUp.tcl Executable file
View File

@ -0,0 +1,42 @@
# This script inst`pwd+alls TclCurl in a Windows system, you only
# have to double-click on it and, provided Tcl/Tk is already
# installed, TclCurl will be ready to use.
#
# Copyright (c) 2001-2011 Andres Garcia Garcia.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
wm withdraw .
set tclLibDir [file dirname $tcl_library]
set tclBinDir [file join [file dirname $tclLibDir] bin]
set windowsSystem [file join $env(windir) SYSTEM]
cd [file dirname [info script]]
foreach oldie [glob -nocomplain $tclLibDir/tclcurl*] {
catch {file delete -force $oldie}
}
file copy -force tclcurl7.22.0 $tclLibDir
foreach sslFile [glob -nocomplain ssl/*] {
catch {file copy -force $sslFile $windowsSystem}
}
foreach sslFile [glob -nocomplain certs/*] {
file copy -force $sslFile [file join $env(windir) cacert.pem]
}
package forget TclCurl
if {[catch {package require TclCurl} version]} {
tk_messageBox -icon error -type ok -title Error \
-message "Install failed\n$version"
} else {
tk_messageBox -icon info -type ok -title Installed \
-message "Version $version installed"
}
exit

97
packages/Windows/tclcurl.mk Executable file
View File

@ -0,0 +1,97 @@
TCL_VERSION = 8.5.10
TCLCURL_VERSION = 7.22.0
TclCurl_nodot = 7.220
CURL_VERSION = 7.22.0
ZLIB_VERSION = 1.2.5
installFiles = ChangeLog.txt changes.txt license.terms ReadMe.txt ReadMeW32.txt packages/Windows/SetUp.tcl
installDirs = tests
certFiles = cacert.pem
sslFiles = libeay32.dll ssleay32.dll
docFiles = aolserver.txt OpenSSL-LICENSE.txt tclcurl.html tclcurl_multi.html tclcurl_share.html
tclcurl-plain: DESTDIR = TclCurl-${TCLCURL_VERSION}
tclcurl-plain: TclCurlFlags= --disable-threads
tclcurl-ssl: DESTDIR = TclCurl-SSL-${TCLCURL_VERSION}
tclcurl-ssl: TclCurlFlags = --enable-ssl --disable-threads
tclcurl-ssl: curlFlags = --with-ssl=/usr/local/
tclcurl-threaded: DESTDIR = TclCurl-THREADED-${TCLCURL_VERSION}
tclcurl-threaded: TclFlags = --enable-threads
tclcurl-threaded-ssl: DESTDIR = TclCurl-THREADED-SSL-${TCLCURL_VERSION}
tclcurl-threaded-ssl: TclFlags = --enable-threads
tclcurl-threaded-ssl: TclCurlFlags = --enable-ssl
tclcurl-threaded-ssl: curlFlags = --with-ssl=/usr/local/
tclcurl-plain: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs rar
tclcurl-ssl: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs ssl rar
tclcurl-threaded: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs rar
tclcurl-threaded-ssl: tcl zlib curl tclcurlComp createDir extraFiles extraDirs docs ssl rar
clean:
rm TclCurl-${TCLCURL_VERSION}.exe TclCurl-SSL-${TCLCURL_VERSION}.exe TclCurl-THREADED-${TCLCURL_VERSION}.exe TclCurl-THREADED-SSL-${TCLCURL_VERSION}.exe
tcl:
cd tcl${TCL_VERSION}/win ;\
make distclean ;\
./configure ${TclFlags} ;\
make ;\
make install
curl:
cd curl-${CURL_VERSION} ;\
./configure ${curlFlags} --enable-shared=no ;\
make ;\
make install-strip
zlib:
cd zlib-${ZLIB_VERSION} ;\
make distclean ;\
./configure ;\
make ;\
make install ;\
tclcurlComp:
cd TclCurl ;\
make distclean ;\
CC=gcc ./configure ${TclFlags} ${TclCurlFlags} -enable-zlib ;\
make ;\
make install
createDir:
mkdir ${DESTDIR} ;\
cp -r /usr/local/lib/TclCurl${TCLCURL_VERSION} ${DESTDIR} ;\
extraFiles:
for f in $(installFiles) ; do \
cp TclCurl/$$f ${DESTDIR} ;\
done
extraDirs:
for f in $(installDirs) ; do \
cp -r TclCurl/$$f ${DESTDIR}/TclCurl${TCLCURL_VERSION} ;\
done
ssl:
mkdir ${DESTDIR}/certs ;\
cp ${certFiles} ${DESTDIR}/certs ;\
mkdir ${DESTDIR}/ssl ;\
for f in $(sslFiles) ; do \
cp -r /usr/local/bin/$$f ${DESTDIR}/ssl ;\
done
docs:
mkdir ${DESTDIR}/tclcurl${TCLCURL_VERSION}/doc ;\
for f in $(docFiles) ; do \
cp -r TclCurl/doc/$$f ${DESTDIR}/tclcurl${TCLCURL_VERSION}/doc;\
done
rar:
"c:/Program Files (x86)/WinRAR/rar" a -r -s -sfx ${DESTDIR}.exe ${DESTDIR};\
rm -r ${DESTDIR}

5
pkgIndex.tcl.in Executable file
View File

@ -0,0 +1,5 @@
#
# Tcl package index file
#
package ifneeded @PACKAGE_NAME@ @PACKAGE_VERSION@ \
[list load [file join $dir @PKG_LIB_FILE@]]\n[list source [file join $dir @TCLCURL_SCRIPTS@]]

119
tclconfig/install-sh Executable file
View File

@ -0,0 +1,119 @@
#!/bin/sh
#
# install - install a program, script, or datafile
# This comes from X11R5; it is not part of GNU.
#
# $XConsortium: install.sh,v 1.2 89/12/18 14:47:22 jim Exp $
#
# This script is compatible with the BSD install script, but was written
# from scratch.
#
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit="${DOITPROG-}"
# put in absolute paths if you don't have them in your path; or use env. vars.
mvprog="${MVPROG-mv}"
cpprog="${CPPROG-cp}"
chmodprog="${CHMODPROG-chmod}"
chownprog="${CHOWNPROG-chown}"
chgrpprog="${CHGRPPROG-chgrp}"
stripprog="${STRIPPROG-strip}"
rmprog="${RMPROG-rm}"
instcmd="$mvprog"
chmodcmd=""
chowncmd=""
chgrpcmd=""
stripcmd=""
rmcmd="$rmprog -f"
mvcmd="$mvprog"
src=""
dst=""
while [ x"$1" != x ]; do
case $1 in
-c) instcmd="$cpprog"
shift
continue;;
-m) chmodcmd="$chmodprog $2"
shift
shift
continue;;
-o) chowncmd="$chownprog $2"
shift
shift
continue;;
-g) chgrpcmd="$chgrpprog $2"
shift
shift
continue;;
-s) stripcmd="$stripprog"
shift
continue;;
*) if [ x"$src" = x ]
then
src=$1
else
dst=$1
fi
shift
continue;;
esac
done
if [ x"$src" = x ]
then
echo "install: no input file specified"
exit 1
fi
if [ x"$dst" = x ]
then
echo "install: no destination specified"
exit 1
fi
# If destination is a directory, append the input filename; if your system
# does not like double slashes in filenames, you may need to add some logic
if [ -d $dst ]
then
dst="$dst"/`basename $src`
fi
# Make a temp file name in the proper directory.
dstdir=`dirname $dst`
dsttmp=$dstdir/#inst.$$#
# Move or copy the file name to the temp name
$doit $instcmd $src $dsttmp
# and set any options; do chmod last to preserve setuid bits
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; fi
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; fi
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; fi
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; fi
# Now rename the file to the real destination.
$doit $rmcmd $dst
$doit $mvcmd $dsttmp $dst
exit 0

4148
tclconfig/tcl.m4 Executable file

File diff suppressed because it is too large Load Diff

8
tests/basic.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url "127.0.0.1"

36
tests/bodyVar.tcl Executable file
View File

@ -0,0 +1,36 @@
package require TclCurl
# These tests has some urls that don't exists outside my system,
# so IT WON'T WORK FOR YOU unless you change them.
set curlHandle [curl::init]
$curlHandle configure -url "127.0.0.1" -bodyvar body -noprogress 1
$curlHandle perform
$curlHandle configure -url "127.0.0.1/~andres/" -bodyvar newBody
$curlHandle perform
$curlHandle cleanup
puts "First page:"
puts $body
puts "Second page:"
puts $newBody
# You can also use it for binary transfers
curl::transfer \
-url {127.0.0.1/~andres/HomePage/getleft/images/getleft.png} \
-bodyvar image -noprogress 1 -verbose 1
if [catch {open "getleft.png" w} out] {
puts "Could not open $out."
exit
}
fconfigure $out -translation binary
puts $out $image
close $out

24
tests/bufferSize.tcl Executable file
View File

@ -0,0 +1,24 @@
package require TclCurl
# This is one contrived example, but it works.
proc writeToFile {readData} {
puts "writeToFile called [incr ::i]"
puts -nonewline $::inFile $readData
return
}
set i 0
set inFile [open "cosa.tar" w+]
fconfigure $inFile -translation binary
curl::transfer -url "127.0.0.1/~andres/cosa&co.tar" \
-writeproc writeToFile -buffersize 250
close $inFile

10
tests/command.tcl Executable file
View File

@ -0,0 +1,10 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -command "puts \"\nTransfer complete\n\""

8
tests/cookie.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -cookie "name=andres;" -verbose 1

13
tests/cookieFile.tcl Executable file
View File

@ -0,0 +1,13 @@
package require TclCurl
if {![file exists /home/andres/.getleft/cookies]} {
puts "The given cookie file doesn't exist"
}
curl::transfer -url 127.0.0.1 \
-cookiefile "/home/andres/.getleft/cookies" -verbose 1

12
tests/curlConfig.tcl Executable file
View File

@ -0,0 +1,12 @@
package require TclCurl
puts "cURL is installed in: [curl::curlConfig -prefix]"
set compiledOptions [curl::curlConfig -feature]
regsub -all {\n} $compiledOptions { - } compiledOptions
puts "The compiled options: $compiledOptions"
puts "The version in hex: [curl::curlConfig -vernum]"
puts "The built-in path to the CA cert bundle:\n\t[curl::curlConfig -ca]"

41
tests/debugProc.tcl Executable file
View File

@ -0,0 +1,41 @@
package require TclCurl
proc DebugProc {infoType data} {
switch $infoType {
0 {
set type "text"
}
1 {
set type "incoming header"
}
2 {
set type "outgoing header"
}
3 {
set type "incoming data"
}
4 {
set type "outgoing data"
}
5 {
set type "incoming SSL data"
}
6 {
set type "outgoing SSL data"
}
}
puts "Type: $type - Data:"
puts "$data"
return 0
}
set curlHandle [curl::init]
$curlHandle configure -url 127.0.0.1 -verbose 1 \
-debugproc DebugProc
$curlHandle perform
$curlHandle cleanup

7
tests/dict.tcl Executable file
View File

@ -0,0 +1,7 @@
package require TclCurl
curl::transfer -url "dict://dict.org/m:curl"

16
tests/dupHandle.tcl Executable file
View File

@ -0,0 +1,16 @@
package require TclCurl
set curlHandle1 [curl::init]
$curlHandle1 configure -url 127.0.0.1
set curlHandle2 [$curlHandle1 duphandle]
$curlHandle1 configure -url 127.0.0.1/~andres/
$curlHandle2 perform
$curlHandle1 cleanup
$curlHandle2 cleanup

9
tests/encoding.tcl Executable file
View File

@ -0,0 +1,9 @@
package require TclCurl
curl::transfer -url "http://127.0.0.1" -encoding deflated -verbose 1
curl::transfer -url "http://127.0.0.1" -encoding all -verbose 1

23
tests/errorBuffer.tcl Executable file
View File

@ -0,0 +1,23 @@
package require TclCurl
set curlHandle [curl::init]
$curlHandle configure -url "Shire.Asturias.com" -errorbuffer errorMsg
if {[catch {$curlHandle perform}]} {
puts "The error message: $errorMsg"
}
$curlHandle configure -url "Shire.Asturias.com" -errorbuffer error(msg)
if {[catch {$curlHandle perform}]} {
puts "The error message: $error(msg)"
}
$curlHandle cleanup
unset error
catch {curl::transfer -url "Shire.Asturias.com" -errorbuffer error(msg)}
puts "Error: $error(msg)"

6
tests/escape.tcl Executable file
View File

@ -0,0 +1,6 @@
package require TclCurl
set escaped [curl::escape {What about this?}]
puts "String to escape: What about this? - $escaped"
puts "And the reverse: [curl::unescape $escaped]"

17
tests/failOnError.tcl Executable file
View File

@ -0,0 +1,17 @@
package require TclCurl
set curlHandle [curl::init]
$curlHandle configure -url "127.0.0.1/cosa.html"
$curlHandle configure -failonerror 0 ; # This is the default
puts "With failonerror==0:"
catch {$curlHandle perform}
puts "\n\n\n\n\n"
puts "With failonerror==1:"
$curlHandle configure -failonerror 1
catch {$curlHandle perform}
$curlHandle cleanup

17
tests/file.tcl Executable file
View File

@ -0,0 +1,17 @@
package require TclCurl
set curlHandle [curl::init]
$curlHandle configure -url "127.0.0.1" -file "index.html"
$curlHandle perform
puts "First transfer finished\n"
$curlHandle configure -header 1 -file cosa.html
$curlHandle perform
$curlHandle cleanup

20
tests/fileNoFile.tcl Executable file
View File

@ -0,0 +1,20 @@
package require TclCurl
set curlHandle [curl::init]
puts "First we save in 'index.html'"
$curlHandle configure -noprogress 1 -url "127.0.0.1" -file "index.html"
$curlHandle perform
puts "And now in stdout"
$curlHandle configure -file ""
$curlHandle perform
$curlHandle cleanup

13
tests/formGet.tcl Executable file
View File

@ -0,0 +1,13 @@
package require TclCurl
curl::transfer -url "http://www.google.com/search?q=TclCurl&hl=en&btnG=Google+Search+&lr=" \
-file tclcurl.html -cookiejar [file join [file dirname [info script]] cookieJar.txt]
puts "Transfer saved in 'tclcurl.html'"
puts "Cookies en el fichero: [file join [file dirname [info script]] cookieJar.txt]"

22
tests/ftp.tcl Executable file
View File

@ -0,0 +1,22 @@
package require TclCurl
puts "nobody==1 --- header==1"
curl::transfer -url "ftp://127.0.0.1/pub/indust2.gif" -nobody 1 -header 1
puts "nobody==0 --- header ignored"
curl::transfer -url "ftp://127.0.0.1/pub/indust2.gif" -nobody 0 \
-file cosa.gif
puts "nobody==1 --- HEADERS==0"
curl::transfer -url "ftp://127.0.0.1/pub/indust2.gif" -nobody 1 \
-header 0 -postquote [list "mkdir nada"]

9
tests/ftpList.tcl Executable file
View File

@ -0,0 +1,9 @@
package require TclCurl
curl::transfer -url "ftp://127.0.0.1/pub/" -ftplistonly 1

25
tests/ftpUpload.tcl Executable file
View File

@ -0,0 +1,25 @@
package require TclCurl
set buffer ""
if {[catch {curl::transfer -url ftp://127.0.0.1/Test/cosa.tcl \
-userpwd "user:pwd" -verbose 1 \
-infile ftpUpload.tcl -upload 1 -errorbuffer buffer \
-quote [list "mkd Test"] \
-postquote [list "rnfr cosa.tcl" "rnto script.tcl"] \
} buffer]} {
puts "Error: $buffer"
} else {
puts "Upload complete"
}

81
tests/ftpWildcard.tcl Executable file
View File

@ -0,0 +1,81 @@
package require TclCurl
proc FtpMatch {pattern filename} {
puts "Pattern: $pattern - File: $filename"
# For this example everything matches
return 0
}
proc FtpCheck {remains} {
global someVar
# Lets forget about directories:
if {($someVar(filetype) eq "directory") || ([regexp {^\.} $someVar(filename)])} {
return 1
}
puts -nonewline "File to download $someVar(filename) ($someVar(size)B) (y/N): "
flush stdout
set line [string tolower [gets stdin]]
if {$line eq y} {
return 0
}
return 1
}
proc FtpSaveFile {readData} {
global outFile
global openedFile
global someVar
if {$openedFile==0} {
if {![file exists downloads]} {
file mkdir downloads
}
set outFile [open "downloads/$someVar(filename)" w+]
fconfigure $outFile -translation binary
}
puts -nonewline $outFile $readData
return 0
}
proc FtpDone {} {
global outFile
global openedFile
puts "Done\n"
close $outFile
set openedFile 0
return 0
}
set openedFile 0
set curlHandle [curl::init]
$curlHandle configure -url ftp://sunsite.rediris.es/sites/metalab.unc.edu/ldp/*
$curlHandle configure -chunkbgnproc FtpCheck
$curlHandle configure -chunkbgnvar someVar
$curlHandle configure -chunkendproc FtpDone
$curlHandle configure -writeproc FtpSaveFile
$curlHandle configure -wildcardmatch 1
$curlHandle configure -fnmatchproc FtpMatch
$curlHandle perform
$curlHandle cleanup

55
tests/getInfo.tcl Executable file
View File

@ -0,0 +1,55 @@
package require TclCurl
set curlHandle [curl::init]
$curlHandle configure -url "127.0.0.1" -filetime 1 -verbose 1 \
-cookielist "127.0.0.1\tFALSE\t/\tFALSE\t1262307600\tad_browser_id\t 18864635"
$curlHandle perform
puts "Url: [$curlHandle getinfo effectiveurl]"
puts "Primary IP: [$curlHandle getinfo primaryip]"
puts "Primary port: [$curlHandle getinfo primaryport]"
puts "Local IP: [$curlHandle getinfo localip]"
puts "Local port: [$curlHandle getinfo localport]"
puts "Redirect url: [$curlHandle getinfo redirecturl]"
puts "Http-code: [$curlHandle getinfo responsecode]"
puts "Proxy response code: [$curlHandle getinfo httpconnectcode]"
set fileTime [$curlHandle getinfo filetime]
puts "Filetime: $fileTime - [clock format $fileTime]"
puts "Total time: [$curlHandle getinfo totaltime]"
puts "Name lookup time: [$curlHandle getinfo namelookuptime]"
puts "Name connect time: [$curlHandle getinfo connecttime]"
puts "Name pretransfer time: [$curlHandle getinfo pretransfertime]"
puts "Name start transfer time: [$curlHandle getinfo starttransfertime]"
puts "Name app connect time: [$curlHandle getinfo appconnecttime]"
puts "Name size upload: [$curlHandle getinfo sizeupload]"
puts "Name size download: [$curlHandle getinfo sizedownload]"
puts "Name speed download: [$curlHandle getinfo speeddownload]"
puts "Name speed upload: [$curlHandle getinfo speedupload]"
puts "Name header size: [$curlHandle getinfo headersize]"
puts "Name request size: [$curlHandle getinfo requestsize]"
puts "Name ssl verifyresult: [$curlHandle getinfo sslverifyresult]"
puts "SSL engines: [$curlHandle getinfo sslengines]"
puts "Name length download: [$curlHandle getinfo contentlengthdownload]"
puts "Name length upload: [$curlHandle getinfo contentlengthupload]"
puts "Content-Type: [$curlHandle getinfo contenttype]"
puts "Redirect time: [$curlHandle getinfo redirecttime]"
puts "Redirect count: [$curlHandle getinfo redirectcount]"
puts "Authentication methods available: [$curlHandle getinfo httpauthavail]"
puts "Authentication methods at the proxy: [$curlHandle getinfo proxyauthavail]"
puts "Operating System error number: [$curlHandle getinfo oserrno]"
puts "Number of successful connects: [$curlHandle getinfo numconnects]"
puts "Known cookies: [$curlHandle getinfo cookielist]"
set certList [$curlHandle getinfo certinfo]
set certNum [lindex $certList 0]
puts "Nº de certificados: $certNum"
for {set i 1} {$i<=$certNum} {incr i} {
puts [lindex $certList $i]
}
$curlHandle cleanup

21
tests/headNoHead.tcl Executable file
View File

@ -0,0 +1,21 @@
package require TclCurl
set curlHandle [curl::init]
puts "First we save the headers in 'header.txt'"
$curlHandle configure -noprogress 1 -nobody 1 -url "127.0.0.1" \
-writeheader header.txt
$curlHandle perform
puts "And now we dump them to the console"
$curlHandle configure -writeheader ""
$curlHandle perform
$curlHandle cleanup

8
tests/header.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -header 1 -nobody 1

13
tests/headerVar.tcl Executable file
View File

@ -0,0 +1,13 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -header 1 -nobody 1 -headervar headers
puts "The received headers"
foreach {key content} [array get headers] {
puts "headers($key): $content"
}

12
tests/http200Aliases.tcl Executable file
View File

@ -0,0 +1,12 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 -header 1 \
-http200aliases [list "yummy/4.5 200 OK" "great/1.3 350 WRONG"]

14
tests/httpBufferPost.tcl Executable file
View File

@ -0,0 +1,14 @@
package require TclCurl
set fileContent "This is what we will send as if it was the content of a file"
curl::transfer -url 127.0.0.1/cgi-bin/post1.tcl -verbose 1 -post 1 \
-httppost [list name "firstName" contents "Andres" contenttype "text/plain" contentheader [list "adios: goodbye"]] \
-httppost [list name "lastName" contents "Garcia"] \
-httppost [list name "nombre" bufferName noFile.txt buffer $fileContent contenttype "text/html"] \
-httppost [list name "submit" contents "send"] -verbose 1

12
tests/httpHeader.tcl Executable file
View File

@ -0,0 +1,12 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 \
-httpheader [list "hola: hello" "adios: goodbye"]

14
tests/httpPost.tcl Executable file
View File

@ -0,0 +1,14 @@
package require TclCurl
curl::transfer -url 127.0.0.1/cgi-bin/post1.tcl -verbose 1 -post 1 \
-httppost [list name "firstName" contents "Andres" contenttype "text/plain" contentheader [list "adios: goodbye"]] \
-httppost [list name "lastName" contents "Garcia"] \
-httppost [list name "file" file "httpPost.tcl" file "basico.tcl" contenttype text/plain filename "c:\\basico.tcl"] \
-httppost [list name "AnotherFile" filecontent "httpBufferPost.tcl"] \
-httppost [list name "submit" contents "send"] -verbose 1

13
tests/httpVersion.tcl Executable file
View File

@ -0,0 +1,13 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -httpversion none -verbose 1 -nobody 1
curl::transfer -url "127.0.0.1" -httpversion 1.0 -verbose 1 -nobody 1
curl::transfer -url "127.0.0.1" -httpversion 1.1 -verbose 1 -nobody 1

13
tests/https.tcl Executable file
View File

@ -0,0 +1,13 @@
package require TclCurl
if {$tcl_platform(platform)=="windows"} {
set certFile [file join $env(windir) curl-ca-bundle.crt]
} else {
set certFile /usr/local/share/curl/curl-ca-bundle.crt
}
::curl::transfer -url https://www.paypal.com/ -cainfo $certFile \
-file paypal.html
puts "https://www.paypal.com/ saved in 'paypal.html'"

11
tests/interface.tcl Executable file
View File

@ -0,0 +1,11 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -verbose 1 -interface 127.0.0.1 -nobody 1

14
tests/ipresolve.tcl Executable file
View File

@ -0,0 +1,14 @@
package require TclCurl
set curlHandle [curl::init]
$curlHandle configure -url "http://127.0.0.1" -filetime 1 -ipresolve v4 \
-verbose 1 -nobody 1
$curlHandle perform
$curlHandle cleanup

31
tests/multi/auto.tcl Executable file
View File

@ -0,0 +1,31 @@
#!/usr/local/bin/wish8.4
package require TclCurl
#wm withdraw .
proc CleanUp {multiHandle easyHandle} {
puts "\n\nCleaning up\n\n"
$::multiHandle removehandle $::easyHandle
$::multiHandle cleanup
$::easyHandle cleanup
puts "\n\nAll done\n\n"
exit
}
set multiHandle [curl::multiinit]
set easyHandle [curl::init]
$easyHandle configure -url http://127.0.0.1/~andres/HomePage.tar.gz -file home.tar.gz
$multiHandle addhandle $easyHandle
puts "Starting transfer..."
$multiHandle auto -command "CleanUp $multiHandle $easyHandle"

31
tests/multi/autoGUI.tcl Executable file
View File

@ -0,0 +1,31 @@
#!/usr/local/bin/wish8.4
package require TclCurl
proc CleanUp {multiHandle easyHandle} {
puts "\n\nCleaning up $multiHandle - $easyHandle\n\n"
$multiHandle removehandle $easyHandle
$multiHandle cleanup
$easyHandle cleanup
puts "\n\nAll done\n\n"
exit
}
proc StartTransfer {} {
set multiHandle [curl::multiinit]
set easyHandle [curl::init]
$easyHandle configure -url http://127.0.0.1/~andres/HomePage.tar.gz -file home.tar.gz
$multiHandle addhandle $easyHandle
$multiHandle auto -command "CleanUp $multiHandle $easyHandle"
}
set start [button .start -text Start -command StartTransfer]
set stop [button .stop -text Stop -command StopTransfer]
pack $start $stop -side left -padx 10 -pady 10

80
tests/multi/cancelTrans.tcl Executable file
View File

@ -0,0 +1,80 @@
#!/usr/local/bin/wish8.4
package require TclCurl
proc ProgressCallback {dltotal dlnow ultotal ulnow} {
set dltotal [expr round($dltotal)]
set dlnow [expr round($dlnow)]
set ultotal [expr round($ultotal)]
set ulnow [expr round($ulnow)]
puts "Progress callback: $dltotal - $dlnow - $ultotal - $ulnow"
return
}
proc Perform {multiHandle} {
if {[catch {$multiHandle active} activeTransfers]} {
puts "Error checking active transfers: $activeTransfers"
return -1
}
if {[catch {$multiHandle perform} running]} {
puts "Error: $running"
return -1
}
return $running
}
proc Transfer {multiHandle easyHandle} {
global eventId
set runningTransfers [Perform $multiHandle]
if {$runningTransfers>0} {
set eventId [after 200 "Transfer $multiHandle $easyHandle"]
} else {
puts "Were are done, cleaning up..."
$multiHandle removehandle $easyHandle
$easyHandle cleanup
$multiHandle cleanup
puts "All done"
}
return
}
proc StartTransfer {} {
set curlEasyHandle [curl::init]
$curlEasyHandle configure -url "127.0.0.1/~andres/cosa&co.tar" \
-canceltransvarname cancel -progressproc ProgressCallback\
-file cosa.tar -noprogress 0
set curlMultiHandle [curl::multiinit]
$curlMultiHandle addhandle $curlEasyHandle
after 100 "Transfer $curlMultiHandle $curlEasyHandle"
return
}
proc StopTransfer {} {
global cancel eventId
puts "The download has been cancelled"
set cancel 1
return
}
set start [button .start -text Start -command StartTransfer]
set stop [button .stop -text Stop -command StopTransfer]
pack $start $stop -side left -padx 10 -pady 10

57
tests/multi/double.tcl Executable file
View File

@ -0,0 +1,57 @@
package require TclCurl
proc Perform {multiHandle} {
if {[catch {$multiHandle active} activeTransfers]} {
puts "Error checking active transfers: $activeTransfers"
return -1
}
if {[catch {$multiHandle perform} running]} {
puts "Error: $running"
return 1
}
return $running
}
proc StartTransfer {multiHandle} {
while {1==1} {
set runningTransfers [Perform $multiHandle]
if {$runningTransfers>0} {
after 500
} else {
break
}
}
}
puts "We create and configure the easy handles"
set curlEasyHandle1 [curl::init]
set curlEasyHandle2 [curl::init]
$curlEasyHandle1 configure -url http://127.0.0.1/~andres/ -file index.html
$curlEasyHandle2 configure -url http://127.0.0.1/ -file index2.html
puts "Creating the multi handle"
set curlMultiHandle [curl::multiinit]
puts "Adding easy handles to the multi one"
$curlMultiHandle addhandle $curlEasyHandle1
$curlMultiHandle addhandle $curlEasyHandle2
puts "We start the transfer"
StartTransfer $curlMultiHandle
puts "Transfer done, cleanning up"
$curlMultiHandle removehandle $curlEasyHandle1
$curlMultiHandle removehandle $curlEasyHandle2
$curlMultiHandle cleanup
$curlEasyHandle1 cleanup
$curlEasyHandle2 cleanup

52
tests/multi/single.tcl Executable file
View File

@ -0,0 +1,52 @@
package require TclCurl
proc Perform {multiHandle} {
if {[catch {$multiHandle active} activeTransfers]} {
puts "Error checking active transfers: $activeTransfers"
return -1
}
if {[catch {$multiHandle perform} running]} {
puts "Error: $running"
return 1
}
return $running
}
proc StartTransfer {multiHandle} {
while {1==1} {
set runningTransfers [Perform $multiHandle]
if {$runningTransfers>0} {
after 500
} else {
break
}
}
}
set curlEasyHandle [curl::init]
$curlEasyHandle configure -url http://127.0.0.1/ -file index.html
if {[catch {curl::multiinit} curlMultiHandle]} {
puts "Error with multi handle init"
}
puts "The multi handle: $curlMultiHandle"
puts -nonewline "We add the easy handle: "
puts [$curlMultiHandle addhandle $curlEasyHandle]
StartTransfer $curlMultiHandle
puts "Calling getinfo [$curlMultiHandle getinfo]"
puts -nonewline "Removing the easy handle: "
puts [$curlMultiHandle removehandle $curlEasyHandle]
puts -nonewline "Cleanup the multi handle handle: "
puts [$curlMultiHandle cleanup]
$curlEasyHandle cleanup

10
tests/netrcfile.tcl Executable file
View File

@ -0,0 +1,10 @@
package require TclCurl
curl::transfer -url "ftp://Strider.Asturias.es" -verbose 1 \
-netrc required -netrcfile "/home/andres/testnetrc"

12
tests/noProgress.tcl Executable file
View File

@ -0,0 +1,12 @@
package require TclCurl
# The default is not to show the progress meter.
curl::transfer -url 127.0.0.1 -noprogress 1

8
tests/nobody.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -header 1 -nobody 1

16
tests/ntlm.tcl Executable file
View File

@ -0,0 +1,16 @@
# Contributed by Jos Decoster
set curlHandle [curl::init]
$curlHandle configure \
-verbose 1 -failonerror 1 -errorbuffer ::errorBuffer \
-url $::url -file $::file \
-proxy $::proxy_host -proxyport $::proxy_port \
-proxyauth ntlm \
-proxyuserpwd $::proxy_user:$::proxy_password
if { [catch {$curlHandle perform} r] } {
return -code error "$r $::errorBuffer"
}
$curlHandle cleanup

26
tests/pop3.tcl Executable file
View File

@ -0,0 +1,26 @@
package require TclCurl
set curlHandle [curl::init]
# This just checks the server for messages, if you want to download them
# you need: -url "pop3://pop3.telefonica.net:110/1", -url "pop3://pop3.telefonica.net:110/2", etc
$curlHandle configure -url "pop3://pop3.telefonica.net:110"
$curlHandle configure -username "fandom\$telefonica.net"
$curlHandle configure -password "XXXXXXXX"
$curlHandle configure -bodyvar recieved
$curlHandle configure -verbose 1
$curlHandle perform
$curlHandle cleanup
puts "Recieved:"
puts \n$recieved\n\n

27
tests/progressProc.tcl Executable file
View File

@ -0,0 +1,27 @@
package require TclCurl
proc ProgressCallback {dltotal dlnow ultotal ulnow} {
set dltotal [expr int($dltotal)]
set dlnow [expr int($dlnow)]
set ultotal [expr int($ultotal)]
set ulnow [expr int($ulnow)]
puts "Progress callback: $dltotal - $dlnow - $ultotal - $ulnow"
return
}
set curlHandle [curl::init]
$curlHandle configure -url "127.0.0.1/~andres/cosa&co.tar" \
-progressproc ProgressCallback -file cosa.tar -noprogress 0
$curlHandle perform
$curlHandle cleanup

39
tests/progressProcPause.tcl Executable file
View File

@ -0,0 +1,39 @@
package require TclCurl
# Another one of my contrived but working examples.
proc ProgressCallback {dltotal dlnow ultotal ulnow} {
global i curlHandle
set dltotal [expr int($dltotal)]
set dlnow [expr int($dlnow)]
set ultotal [expr int($ultotal)]
set ulnow [expr int($ulnow)]
puts "$i Progress callback: $dlnow of $dltotal downloaded"
if {$i==10} {
$curlHandle pause
} elseif {$i==30} {
$curlHandle resume
}
incr i
return
}
set i 0
set curlHandle [curl::init]
$curlHandle configure -url "127.0.0.1/~andres/cosa&co.tar" \
-progressproc ProgressCallback -file cosa.tar -noprogress 0
$curlHandle perform
$curlHandle cleanup

11
tests/proxy.tcl Executable file
View File

@ -0,0 +1,11 @@
package require TclCurl
curl::transfer -url http://curl.haxx.se -verbose 1 -proxy "192.168.0.0"

12
tests/proxyPort.tcl Executable file
View File

@ -0,0 +1,12 @@
package require TclCurl
curl::transfer -url http://curl.haxx.com -verbose 1 \
-proxy 192.168.0.0 -proxyport 8080

11
tests/proxyTunnel.tcl Executable file
View File

@ -0,0 +1,11 @@
package require TclCurl
curl::transfer -url http://curl.haxx.se -verbose 1 \
-proxy "192.168.0.0:8080" -httpproxytunnel 1

8
tests/range.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -range "100-500"

23
tests/readProc.tcl Executable file
View File

@ -0,0 +1,23 @@
package require TclCurl
# As an example this is very contrived, but it works.
proc readFile {size} {
set chunk [read $::inFile $size]
return $chunk
}
set inFile [open "cosa.tar" r]
fconfigure $inFile -translation binary
curl::transfer -url "ftp://127.0.0.1/cosa.tar" -verbose 1 \
-username user -password pass -readproc readFile -upload 1
close $inFile

9
tests/referer.tcl Executable file
View File

@ -0,0 +1,9 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -referer "127.0.0.1/cosa.html" \
-verbose 1 -nobody 1

21
tests/reset.tcl Executable file
View File

@ -0,0 +1,21 @@
package require TclCurl
set curlHandle [curl::init]
puts "First we save in 'index.html'"
$curlHandle configure -noprogress 1 -url "127.0.0.1" -file "index.html"
$curlHandle perform
puts "And now in stdout"
$curlHandle reset
$curlHandle configure -url "http://127.0.0.1/"
$curlHandle perform
$curlHandle cleanup

8
tests/resume.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -resumefrom 500

23
tests/share.tcl Executable file
View File

@ -0,0 +1,23 @@
# The share interface support is not yet completely done, since
# you can't use it with the multi interface.
package require TclCurl
set sHandle [curl::shareinit]
$sHandle share dns
set easyHandle1 [curl::init]
set easyHandle2 [curl::init]
$easyHandle1 configure -url http://127.0.0.1/ -share $sHandle
$easyHandle2 configure -url http://127.0.0.1/~andres/ -share $sHandle
$easyHandle1 perform
$easyHandle2 perform
$easyHandle1 cleanup
$easyHandle2 cleanup
$sHandle unshare dns
$sHandle cleanup

52
tests/smtp.tcl Executable file
View File

@ -0,0 +1,52 @@
package require TclCurl
# As an example this is contrived, but it works.
set alreadySent 0
set mailToSend \
"Date: Mon, 12 Sep 2011 20:34:29 +0200
To: fandom@telefonica.net
From: andres@verot.com
Subject: SMTP example
The body of the message starts here.
It could be a lot of lines, could be MIME encoded, whatever.
Check RFC5322.
"
proc sendString {size} {
global alreadySent mailToSend
set toSend [string range $mailToSend $alreadySent [incr $alreadySent $size]]
incr alreadySent [string length $toSend]
return $toSend
}
set curlHandle [curl::init]
$curlHandle configure -url "smtp://smtp.telefonica.net:25"
$curlHandle configure -username "fandom\$telefonica.net"
$curlHandle configure -password "XXXXXXXX"
$curlHandle configure -mailfrom "fandom@telefonica.net"
$curlHandle configure -mailrcpt [list "fandom@telefonica.net" "andresgarci@telefonica.net"]
# You could put the mail in a file and use the '-infile' option
$curlHandle configure -readproc sendString
$curlHandle configure -verbose 1
$curlHandle perform
$curlHandle cleanup

22
tests/stderrNoStderr.tcl Executable file
View File

@ -0,0 +1,22 @@
package require TclCurl
set curlHandle [curl::init]
puts "First it goes into error.txt"
$curlHandle configure -url 127.0.0.1/~andres/cosa&co.tar -stderr error.txt \
-noprogress 0 -file cosa.tar
catch {$curlHandle perform}
puts "And then to stderr:"
$curlHandle configure -stderr ""
catch {$curlHandle perform}
$curlHandle cleanup

14
tests/strerror.tcl Executable file
View File

@ -0,0 +1,14 @@
package require TclCurl
puts "The error string for code 6 is '[curl::easystrerror 6]'"
puts "If the number is too big: '[curl::easystrerror 2000]'"
puts "It works the same way for the multi interface: '[curl::multistrerror 1]'"
puts "And the share interface: '[curl::sharestrerror 1]'"
catch {curl::easystrerror frelled} errorMsg
puts "And if we use a nonsensical code: '$errorMsg'"
catch {curl::sharestrerror} errorMsg
puts "And if we forget the error code:\n '$errorMsg'"

8
tests/timeout.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -timeout 0 -url 127.0.0.1

47
tests/transfer.tcl Executable file
View File

@ -0,0 +1,47 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -filetime 1 \
-infoeffectiveurl effectiveUrl -inforesponsecode httpCode \
-infofiletime fileTime -infototaltime totalTime \
-infonamelookuptime nameLookUpTime \
-infoconnecttime connectTime -infopretransfertime preTime \
-infostarttransfertime startTransferTime \
-infosizeupload sizeUpload -infosizedownload sizeDownload \
-infospeeddownload speedDownload -infospeedupload speedUpload \
-infoheadersize headerSize -inforequestsize requestSize \
-infosslverifyresult sslVerifyResult \
-infocontentlengthupload contentLengthUpload \
-infocontentlengthdownload contentLengthDownload \
-infocontenttype contentType \
-inforedirecttime redirectTime \
-inforedirectcount redirectCount
puts "Url: $effectiveUrl"
puts "Response code: $httpCode"
puts "Filetime: $fileTime - [clock format $fileTime]"
puts "Total time: $totalTime"
puts "Name lookup time: $nameLookUpTime"
puts "Name connect time: $connectTime"
puts "Name pretransfer time: $preTime"
puts "Name start transfer time: $startTransferTime"
puts "Name size upload: $sizeUpload"
puts "Name size download: $sizeDownload"
puts "Name speed download: $speedDownload"
puts "Name speed upload: $speedUpload"
puts "Name header size: $headerSize"
puts "Name request size: $requestSize"
puts "Name ssl verifyresult: $sslVerifyResult"
puts "Name length download: $contentLengthDownload"
puts "Name length upload: $contentLengthUpload"
puts "Content-Type: $contentType"
puts "Redirect time: $redirectTime"
puts "Redirect count: $redirectCount"

8
tests/upload.tcl Executable file
View File

@ -0,0 +1,8 @@
package require TclCurl
curl::transfer -url ftp://andres:ciclope4@127.0.01/cosa.tcl \
-infilesize [file size writeProc.tcl] -infile writeProc.tcl -upload 1 \
-verbose 1

11
tests/userAgent.tcl Executable file
View File

@ -0,0 +1,11 @@
package require TclCurl
curl::transfer -url "127.0.0.1" -verbose 1 -nobody 1 \
-useragent "Mozilla 4.0 (compatible; Getleft 0.10.4)"

23
tests/verbose.tcl Executable file
View File

@ -0,0 +1,23 @@
package require TclCurl
set curlHandle [curl::init]
$curlHandle configure -url 127.0.0.1 -verbose 1 -nobody 1
puts "First one is verbose"
$curlHandle perform
puts "The second isn't"
$curlHandle configure -verbose 0
$curlHandle perform
$curlHandle cleanup

9
tests/version.tcl Executable file
View File

@ -0,0 +1,9 @@
package require TclCurl
puts "[curl::version]"

13
tests/versionInfo.tcl Executable file
View File

@ -0,0 +1,13 @@
package require TclCurl
puts "Version [curl::versioninfo -version]"
puts "Version (num): [curl::versioninfo -versionnum]"
puts "Host: [curl::versioninfo -host]"
puts "Features: [curl::versioninfo -features]"
puts "SSL version: [curl::versioninfo -sslversion]"
puts "SSL version (num): [curl::versioninfo -sslversionnum]"
puts "libz version: [curl::versioninfo -libzversion]"
puts "Protocols [curl::versioninfo -protocols]"

9
tests/writeHeader.tcl Executable file
View File

@ -0,0 +1,9 @@
package require TclCurl
curl::transfer -url 127.0.0.1 -header 1 -nobody 1 \
-writeheader header.txt

23
tests/writeProc.tcl Executable file
View File

@ -0,0 +1,23 @@
package require TclCurl
# This is one contrived example, but it works.
proc writeToFile {readData} {
puts "writeToFile called [incr ::i]"
puts -nonewline $::outFile $readData
return
}
set i 0
set outFile [open "cosa.tar" w+]
fconfigure $outFile -translation binary
curl::transfer -url "127.0.0.1/~andres/cosa&co.tar" -writeproc writeToFile
close $outFile