Compare commits

..

66 Commits

Author SHA1 Message Date
Daniel Stenberg
16fe0c9be3 curl 7.7.2 2001-04-23 07:34:55 +00:00
Daniel Stenberg
f88ff705a4 borland fixes, broken host: for persistent connections 2001-04-23 07:27:12 +00:00
Daniel Stenberg
e83550f511 persistent is spelled with an 'e', not an 'a' 2001-04-23 07:09:15 +00:00
Daniel Stenberg
fde31f0988 no need to copy the name when re-using the connection, we already have the
same name in that buffer from the URL parsing!
2001-04-23 06:11:08 +00:00
Daniel Stenberg
d3090ac3f9 Rosimildo da Silva corrected them to build a proper lib and to use options
for multi-threading compiling
2001-04-22 17:39:04 +00:00
Daniel Stenberg
2cf26d4fb7 copy the name properly when re-using a connection 2001-04-22 16:47:55 +00:00
Daniel Stenberg
f470a131a6 added missing (new) man pages 2001-04-22 15:50:12 +00:00
Daniel Stenberg
04b20b7ed2 old krb4 fix for strlcat() prototype 2001-04-22 15:49:17 +00:00
Daniel Stenberg
ff4f4abe4b brand new 2001-04-22 15:48:05 +00:00
Daniel Stenberg
f4703aee2f removed done entries 2001-04-22 15:47:20 +00:00
Daniel Stenberg
4c485994db updated and spell checked 2001-04-22 15:45:27 +00:00
Daniel Stenberg
a921ee7b52 spell checked 2001-04-22 15:44:33 +00:00
Daniel Stenberg
f6d4a25f68 updated with the Java stuff and so 2001-04-22 15:44:13 +00:00
Daniel Stenberg
2dfd2c642d Added an examples section with examples I made up for the web page 2001-04-20 14:45:15 +00:00
Daniel Stenberg
a2072a1fd0 This is LIBCURL turned into man page format! 2001-04-20 14:44:55 +00:00
Daniel Stenberg
03fea9722c Cris Bailiff's 1.1.5 changes: Add latest CURLOPT_ and CURLINFO_ constants to
the constants list
2001-04-20 11:03:40 +00:00
Daniel Stenberg
a44a8cef99 Cris Bailiff's 1.1.4 changes: Fix case where curl_slists such as 'HTTPHEADERS'
need to be re-set over persistant requests
2001-04-20 06:49:58 +00:00
Daniel Stenberg
97ad165a63 minor corrections 2001-04-20 06:05:33 +00:00
Daniel Stenberg
a508e73a8d SM's real name is now used where he's credited 2001-04-20 06:00:00 +00:00
Daniel Stenberg
32f966b239 A Linus Nielsen Feltzing-patch that removes the decimals from the size
outputs...
2001-04-19 11:24:29 +00:00
Daniel Stenberg
60a43561e2 fixed an nroff syntax mistake 2001-04-19 11:19:54 +00:00
Daniel Stenberg
a91b7d461d Added a brief description of curl-config, mentioned that curl_* functions are
the only public ones
2001-04-19 10:31:23 +00:00
Daniel Stenberg
8755c44d40 Albert Chin's patch posted to the mailing list 19 Apr 2001 2001-04-19 06:01:48 +00:00
Daniel Stenberg
5dd1cb0614 added an include to build on ultrix 2001-04-18 14:06:47 +00:00
Daniel Stenberg
b34bee45ca confirmed install on ultrix 4.3a 2001-04-18 14:06:12 +00:00
Daniel Stenberg
e22fb3e7bc works! 2001-04-18 14:05:44 +00:00
Daniel Stenberg
6ea51f3cd7 Last two days' changes, loadsa 2001-04-18 14:05:18 +00:00
Daniel Stenberg
8e9f0a73d0 Georg Horn's updates, this is _also_ called 1.1.3 ! ;-) 2001-04-18 13:41:04 +00:00
Daniel Stenberg
80fbcdf2f2 Added curl-config.1 2001-04-18 13:16:57 +00:00
Daniel Stenberg
0fd9f64287 brand new command, brand new docs! 2001-04-18 13:16:34 +00:00
Daniel Stenberg
b6175ec792 Added contributors 2001-04-18 11:53:19 +00:00
Daniel Stenberg
1ee7f92ce4 configure sets variables that curl-config uses to display what features
that have been built-in
2001-04-18 09:28:55 +00:00
Daniel Stenberg
3fd65fb7d8 Remade resume stuff to keep data in the connectdata struct instead of the
main handle struct to work with persistant connections
2001-04-18 07:25:11 +00:00
Daniel Stenberg
ebcafe73b3 Cris Bailiff's and Georg Horn's big improvements 2001-04-18 06:51:30 +00:00
Daniel Stenberg
8274bee963 init the speed index variable between transfers 2001-04-17 15:00:17 +00:00
Daniel Stenberg
60aa975610 Frederic Lepied's ftp download resume fix 2001-04-17 13:21:13 +00:00
Daniel Stenberg
28a9108257 more intial fixes 2001-04-17 12:37:38 +00:00
Daniel Stenberg
d1b0b08ba0 Added curl-config as a script that now gets installed 2001-04-17 12:33:02 +00:00
Daniel Stenberg
cc7fc20251 libcurl version, not curl version 2001-04-17 12:32:37 +00:00
Daniel Stenberg
5ab751f5d0 Generates curl-config now 2001-04-17 12:27:59 +00:00
Daniel Stenberg
fb1ce5fd5b tiny tool for outputting curl config variables 2001-04-17 12:23:06 +00:00
Daniel Stenberg
fd8ea204c0 use GMT for the conditional timed gets (reported by Phil Karn) 2001-04-17 07:28:49 +00:00
Daniel Stenberg
b86674174a Added text about curl.haxx.se not being a good test target for people's
libcurl experiments...
2001-04-12 11:13:28 +00:00
Daniel Stenberg
69994f0114 we must fix SSL when IPv6 is enabled, since we can still connect to ipv4
sites and then SSL works perfectly
2001-04-12 06:16:20 +00:00
Daniel Stenberg
879c6c5711 calling curl_easy_perform() with no URL set, now returns an error as
early as possible
2001-04-11 14:14:28 +00:00
Daniel Stenberg
18f044f19d we don't use the HTTP_PROXY environment variable in uppercase anymore, since
it might become a security problem (Bugs item #415391)
2001-04-11 14:13:52 +00:00
Daniel Stenberg
d7b54eb835 now it works 2001-04-11 13:45:55 +00:00
Daniel Stenberg
5eafb69bdb minor updates, still crashes 2001-04-11 10:06:28 +00:00
Daniel Stenberg
a086e99bae added Linux hints 2001-04-11 10:03:14 +00:00
Daniel Stenberg
62056a644f oops, missed the shut-off non-blocking fix 2001-04-11 06:59:00 +00:00
Daniel Stenberg
b2362bf51c interfaces, windows non-blocking connect, progress meter fix and more 2001-04-11 06:51:43 +00:00
Daniel Stenberg
022099266e SM made the connection timeout work for windows boxes! 2001-04-11 06:41:54 +00:00
Daniel Stenberg
870cea2aea initial silly README 2001-04-10 15:41:36 +00:00
Daniel Stenberg
04c10e021c C header to java converter 2001-04-10 15:30:01 +00:00
Daniel Stenberg
d712a4e800 initial java interface commit: IT DOES NOT WORK 2001-04-10 15:29:32 +00:00
Daniel Stenberg
d9f989c8c8 Added CURLOPT_HEADERFUNCTION description 2001-04-10 07:38:59 +00:00
Daniel Stenberg
90bb87b40e setopt() works with the new CURLOPT_HEADERFUNCTION: 2001-04-10 06:51:25 +00:00
Daniel Stenberg
025fa762f6 Added new CURLOPT_HEADERFUNCTION callback for writing headers only 2001-04-10 06:49:32 +00:00
Daniel Stenberg
ac510ab6a4 corrected by SM to build better with openssl 2001-04-09 05:56:39 +00:00
Daniel Stenberg
65b286ca35 SM's updates 2001-04-09 05:55:58 +00:00
Daniel Stenberg
cc5c53454a formfree() fix, version display fixed, curl_escape() fix 2001-04-07 18:39:18 +00:00
Daniel Stenberg
f7874cad29 Andrs Garca pointed out a mistake with CURLOPT_EGDSOCKET 2001-04-07 18:36:22 +00:00
Daniel Stenberg
84e71e1c50 Andrs Garca fixed curl_escape() 2001-04-07 18:35:28 +00:00
Daniel Stenberg
88bb054e1d show openssl 0.9.6a properly 2001-04-06 08:48:42 +00:00
Daniel Stenberg
b054fbaebd NULL argument crashes this in 7.7.1 and before 2001-04-06 05:57:23 +00:00
Daniel Stenberg
53e3c225ee curl_formfree() can be called with a NULL argument 2001-04-06 05:52:23 +00:00
58 changed files with 2771 additions and 703 deletions

137
CHANGES
View File

@@ -6,6 +6,109 @@
History of Changes History of Changes
Version 7.7.2
Daniel (22 April 2001)
- Rosimildo da Silva updated the Makefiles for Borland/Windows.
- Eric Rautman pointed out a problem with persistent connections that would
lead to broken Host: headers in the second HTTP request.
Daniel (20 April 2001)
- Added man pages for the curl_strequal() and curl_mprintf() families. Wrote
a 'libcurl overview' man page.
- Spell-fixed some documents.
- S. Moonesamy corrected mistakes in the man page.
- Cris Bailiff fixed the curl_slists options in the perl interface, present
separately in the Curl::easy 1.1.4 package.
Daniel (19 April 2001)
- Linus Nielsen Feltzing removed the decimals from the size variables in the
--write-out output. We hardly ever get fraction of bytes! :-)
Version 7.7.2-pre1
Daniel (19 April 2001)
- Albert Chin provided a configure patch for the AC_SYS_LARGEFILE macro.
Daniel (18 April 2001)
- Input from Michael Mealling made me add --feature to curl-config. It
displays a list of features that have been built-in in the current
libcurl. The currently available features that can be listed are: SSL, KRB4
and IPv6.
- I committed Cris and Georg's perl interface work. They've got callbacks
working and options that receives those slist pointers.
- Puneet Pawaia detected a problem with resumed downloads that use persistent
connections and I made a rather large writeup to correct this. It is
important that all session-data is stored in the connectdata struct and not
in the main struct as this previously did.
Daniel (17 April 2001)
- Frederic Lepied fixed a ftp resumed download problem and introduced a new
error code that lets applications be able to detect when a resumed download
actually didn't download anything since the whole file is already present.
Should this return OK instead?
- I added 'curl-config.in' to the root dir and configure script. Now, a
curl-config script is made when curl is built. The script can be used to
figure out compile time options used when libcurl was built, which in turn
should be options YOU should use to build applications that use libcurl.
This *-config style is not a new idea, but something that has been used
successfully in other (library based) projects.
- Phil Karn pointed out that libcurl wrongly did not always use GMT time zone
for the If-Modified-Since style headers.
- Georg Schwarz pointed out an extra needed #include file needed in src/main.c
for curl to build on Ultrix.
Daniel (11 April 2001)
- Cris Bailiff pointed out two problems that I corrected. First, libcurl's use
of the environment variable HTTP_PROXY in uppercase may become a security
hazard when people use libcurl in a server/cgi situation where the server
sets the HTTP_*-variables according to incoming headers in the HTTP
request. Thus, a "Proxy:"-header would set that environment variable!
Then, invoking curl_easy_perform() without having an URL set caused a crash.
- S. Moonesamy brought a patch that make curl use non-blocking connects on
windows when connection timeout is set, as it allows windows users to set
that timeout!
- Hirotaka Matsuyuki wrote a Ruby interface to libcurl!
- Cris Bailiff, Forrest Cahoon and Georg Horn work on the Perl interface.
- I've written a first shot at a Java interface to libcurl. Many thanks to
Daniel Marell for tirelessly answering to all my basic Java questions. It
works, but it is still very basic.
Daniel (10 April 2001)
- The progress display could get silly when doing multiple file transfers, as
it wasn't properly reset between transfers!
- Discussions with Cris Bailiff who writes a Perl interface to libcurl, made
me add CURLOPT_HEADERFUNCTION. It can be used to set a separate callback
function for writing headers. Previously you could only set a different FILE
* when headers are written from within libcurl.
Daniel (7 April 2001)
- Andr<64>s Garc<72>a fixed a problem in curl_escape() and pointed out a flaw in
the curl_easy_setopt man page.
Daniel (6 April 2001)
- Adjusted the version code to properly display OpenSSL 0.9.6a. They sure
change their version define format often...
- curl_formfree() now accepts a NULL pointer without crashing!
Version 7.7.1 Version 7.7.1
Daniel (3 April 2001) Daniel (3 April 2001)
@@ -14,8 +117,8 @@ Daniel (3 April 2001)
Also, the lib/Makefile.vc6 was corrected. Also, the lib/Makefile.vc6 was corrected.
- More investigations in the Location: following code made me realize that - More investigations in the Location: following code made me realize that
it was not clean enough to work transparantly with persistant and non- it was not clean enough to work transparantly with persistent and non-
persistant connections. I think I've fixed it now. persistent connections. I think I've fixed it now.
Daniel (29 March 2001) Daniel (29 March 2001)
- Georg Horn mailed me some corrections for the Curl::easy perl interface. - Georg Horn mailed me some corrections for the Curl::easy perl interface.
@@ -37,7 +140,7 @@ Daniel (27 March 2001)
Version 7.7.1-beta1 Version 7.7.1-beta1
Daniel (26 March 2001) Daniel (26 March 2001)
- Mohamed Lrhazi reported problems with 7.6.1 and persistant HTTP/1.0 - Mohamed Lrhazi reported problems with 7.6.1 and persistent HTTP/1.0
connections (when the server replied a Connection: Keep-Alive) and this connections (when the server replied a Connection: Keep-Alive) and this
problem was not properly dealt with in 7.7 either. A patch was posted to the problem was not properly dealt with in 7.7 either. A patch was posted to the
curl-and-php mailing list. curl-and-php mailing list.
@@ -54,7 +157,7 @@ Daniel (23 March 2001)
- Corrected the Curl::easy perl interface to use curl_easy_setopt() and not - Corrected the Curl::easy perl interface to use curl_easy_setopt() and not
curl_setopt() which was removed in 7.7! curl_setopt() which was removed in 7.7!
- SM provided updates on three documents (MANUAL, INSTALL and FAQ). - S. Moonesamy provided updates on three documents (MANUAL, INSTALL and FAQ).
- When following a Location:, libcurl would sometimes write to the URL string - When following a Location:, libcurl would sometimes write to the URL string
in a way it shouldn't. As the pointer is passed-in to libcurl from an in a way it shouldn't. As the pointer is passed-in to libcurl from an
@@ -219,14 +322,14 @@ Daniel (12 March 2001)
test cases. test cases.
- Added 5 new libcurl options to curl/curl.h that can be used to control the - Added 5 new libcurl options to curl/curl.h that can be used to control the
persistant connection support in libcurl. They're also documented (fairly persistent connection support in libcurl. They're also documented (fairly
thoroughly) in the curl_easy_setopt.3 man page. Three of them are now thoroughly) in the curl_easy_setopt.3 man page. Three of them are now
implemented, although not really tested at this point... Anyway, the new implemented, although not really tested at this point... Anyway, the new
implemented options are named CURLOPT_MAXCONNECTS, CURLOPT_FRESH_CONNECT, implemented options are named CURLOPT_MAXCONNECTS, CURLOPT_FRESH_CONNECT,
CURLOPT_FORBID_REUSE. The ones still left to write code for are: CURLOPT_FORBID_REUSE. The ones still left to write code for are:
CURLOPT_CLOSEPOLICY and its related option CURLOPT_CLOSEFUNCTION. CURLOPT_CLOSEPOLICY and its related option CURLOPT_CLOSEFUNCTION.
- Made curl (the actual command line tool) use the new libcurl 7.7 persistant - Made curl (the actual command line tool) use the new libcurl 7.7 persistent
connection support by re-using the same curl handle for every specified file connection support by re-using the same curl handle for every specified file
transfer and after some more test case tweaking we have 100% test case OK. transfer and after some more test case tweaking we have 100% test case OK.
I made some test cases return HTTP/1.0 now to make sure that works as well. I made some test cases return HTTP/1.0 now to make sure that works as well.
@@ -246,7 +349,7 @@ Daniel (12 March 2001)
of different HTTP proxies before I feel safe. of different HTTP proxies before I feel safe.
Now I'm facing the problem with my test suite servers (both FTP and HTTP) Now I'm facing the problem with my test suite servers (both FTP and HTTP)
not supporting persistant connections and libcurl is doing them now. I have not supporting persistent connections and libcurl is doing them now. I have
to fix the test servers to get all the test cases do OK. to fix the test servers to get all the test cases do OK.
Daniel (8 March 2001) Daniel (8 March 2001)
@@ -287,7 +390,7 @@ Daniel (2 March 2001)
- Now they work intermixed as well. Major coolness! - Now they work intermixed as well. Major coolness!
- More fiddling around, my 'tiny' client I have for testing purposes now has - More fiddling around, my 'tiny' client I have for testing purposes now has
proved to download both FTP and HTTP with persistant connections. They do proved to download both FTP and HTTP with persistent connections. They do
not work intermixed yet though. not work intermixed yet though.
Daniel (1 March 2001) Daniel (1 March 2001)
@@ -296,7 +399,7 @@ Daniel (1 March 2001)
now. now.
Daniel (22 February 2001) Daniel (22 February 2001)
- The persistant connections start to look good for HTTP. On a subsequent - The persistent connections start to look good for HTTP. On a subsequent
request, it seems that libcurl now can pick an already existing connection request, it seems that libcurl now can pick an already existing connection
if a suitable one exists, or it opens a new one. if a suitable one exists, or it opens a new one.
@@ -321,7 +424,7 @@ Daniel (20 February 2001)
mailing lists for discussions around how this is gonna be implemented. Docs mailing lists for discussions around how this is gonna be implemented. Docs
and more will follow. and more will follow.
Studied the HTTP RFC to find out better how persistant connections should Studied the HTTP RFC to find out better how persistent connections should
work. Seems cool enough. work. Seems cool enough.
Daniel (19 February 2001) Daniel (19 February 2001)
@@ -340,9 +443,9 @@ Daniel (15 February 2001)
string switches off the POST again. string switches off the POST again.
- Excellent suggestions from Rich Gray, Rick Jones, Johan Nilsson and Bjorn - Excellent suggestions from Rich Gray, Rick Jones, Johan Nilsson and Bjorn
Reese helped me define a way how to incorporate persistant connections into Reese helped me define a way how to incorporate persistent connections into
libcurl in a very smooth way. If done right, no change may have to be made libcurl in a very smooth way. If done right, no change may have to be made
to older programs and they will just start using persistant connections when to older programs and they will just start using persistent connections when
applicable! applicable!
Daniel (13 February 2001) Daniel (13 February 2001)
@@ -376,16 +479,16 @@ Daniel (8 February 2001)
Version 7.6.1-pre3 Version 7.6.1-pre3
Daniel (7 February 2001) Daniel (7 February 2001)
- SM found a flaw in the response reading function for FTP that could make - S. Moonesamy found a flaw in the response reading function for FTP that
libcurl not get out of the loop properly when it should, if libcurl got -1 could make libcurl not get out of the loop properly when it should, if
returned when reading the socket. libcurl got -1 returned when reading the socket.
- I found a similar mistake in http.c when using a proxy and reading the - I found a similar mistake in http.c when using a proxy and reading the
results from the proxy connection. results from the proxy connection.
Daniel (6 February 2001) Daniel (6 February 2001)
- A friendly person named "SM" (nntp at iname.com) pointed out that the VC - S. Moonesamy pointed out that the VC makefile in src/ needed the libpath set
makefile in src/ needed the libpath set for the debug build to work. for the debug build to work.
- Daniel Gehriger stepped in to assist with the VC++ stuff Robert Weaver - Daniel Gehriger stepped in to assist with the VC++ stuff Robert Weaver
brought up yesterday. brought up yesterday.

View File

@@ -1,16 +1,27 @@
This file is only present in the CVS - never in release archives. _ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
This contains information about other files and things that the CVS repository CVS-INFO
keeps in its inner sanctum.
CHANGES.0 contains ancient changes. This file is only present in the CVS - never in release archives. It contains
information about other files and things that the CVS repository keeps in its
inner sanctum.
memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG
CHANGES.0 contains ancient changes.
memanalyze.pl is for analyzing the output generated by curl if -DMALLOCDEBUG
is used when compiling is used when compiling
Makefile.dist is included as the root Makefile in distribution archives Makefile.dist is included as the root Makefile in distribution archives
perl/contrib/ is a subdirectory with various perl scripts perl/contrib/ is a subdirectory with various perl scripts
java is a subdirectory with the Java interface to libcurl
To build after having extracted everything from CVS, do this: To build after having extracted everything from CVS, do this:

View File

@@ -8,6 +8,8 @@ EXTRA_DIST = \
CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt \ CHANGES LEGAL maketgz MITX.txt MPL-1.1.txt \
config-win32.h reconf packages/README Makefile.dist config-win32.h reconf packages/README Makefile.dist
bin_SCRIPTS = curl-config
SUBDIRS = docs lib src include tests packages perl php SUBDIRS = docs lib src include tests packages perl php
# create a root makefile in the distribution: # create a root makefile in the distribution:

View File

@@ -1,4 +1,4 @@
#serial 12 #serial 19
dnl By default, many hosts won't let programs access large files; dnl By default, many hosts won't let programs access large files;
dnl one must use special compiler options to get large-file access to work. dnl one must use special compiler options to get large-file access to work.
@@ -11,7 +11,14 @@ dnl Internal subroutine of AC_SYS_LARGEFILE.
dnl AC_SYS_LARGEFILE_TEST_INCLUDES dnl AC_SYS_LARGEFILE_TEST_INCLUDES
AC_DEFUN(AC_SYS_LARGEFILE_TEST_INCLUDES, AC_DEFUN(AC_SYS_LARGEFILE_TEST_INCLUDES,
[[#include <sys/types.h> [[#include <sys/types.h>
int a[(off_t) 9223372036854775807 == 9223372036854775807 ? 1 : -1]; /* Check that off_t can represent 2**63 - 1 correctly.
We can't simply "#define LARGE_OFF_T 9223372036854775807",
since some C++ compilers masquerading as C compilers
incorrectly reject 9223372036854775807. */
# define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62))
int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
&& LARGE_OFF_T % 2147483647 == 1)
? 1 : -1];
]]) ]])
dnl Internal subroutine of AC_SYS_LARGEFILE. dnl Internal subroutine of AC_SYS_LARGEFILE.
@@ -19,14 +26,11 @@ dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, VALUE, CACHE-VAR, COMMENT, INCLUDES, F
AC_DEFUN(AC_SYS_LARGEFILE_MACRO_VALUE, AC_DEFUN(AC_SYS_LARGEFILE_MACRO_VALUE,
[AC_CACHE_CHECK([for $1 value needed for large files], $3, [AC_CACHE_CHECK([for $1 value needed for large files], $3,
[$3=no [$3=no
AC_TRY_COMPILE(AC_SYS_LARGEFILE_TEST_INCLUDES AC_TRY_COMPILE([$5],
$5
,
[$6], [$6],
, ,
[AC_TRY_COMPILE([#define $1 $2] [AC_TRY_COMPILE([#define $1 $2]
AC_SYS_LARGEFILE_TEST_INCLUDES [$5]
$5
, ,
[$6], [$6],
[$3=$2])])]) [$3=$2])])])
@@ -35,7 +39,8 @@ $5
fi]) fi])
AC_DEFUN(AC_SYS_LARGEFILE, AC_DEFUN(AC_SYS_LARGEFILE,
[AC_ARG_ENABLE(largefile, [AC_REQUIRE([AC_PROG_CC])
AC_ARG_ENABLE(largefile,
[ --disable-largefile omit support for large files]) [ --disable-largefile omit support for large files])
if test "$enable_largefile" != no; then if test "$enable_largefile" != no; then
@@ -58,18 +63,30 @@ AC_DEFUN(AC_SYS_LARGEFILE,
AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS, 64, AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS, 64,
ac_cv_sys_file_offset_bits, ac_cv_sys_file_offset_bits,
[Number of bits in a file offset, on hosts where this is settable.]) [Number of bits in a file offset, on hosts where this is settable.],
AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE, 1, AC_SYS_LARGEFILE_TEST_INCLUDES)
ac_cv_sys_largefile_source,
[Define to make ftello visible on some hosts (e.g. HP-UX 10.20).],
[#include <stdio.h>], [return !ftello;])
AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1, AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES, 1,
ac_cv_sys_large_files, ac_cv_sys_large_files,
[Define for large files, on AIX-style hosts.]) [Define for large files, on AIX-style hosts.],
dnl lftp does not need ftello, and _XOPEN_SOURCE=500 makes resolv.h fail. AC_SYS_LARGEFILE_TEST_INCLUDES)
dnl AC_SYS_LARGEFILE_MACRO_VALUE(_XOPEN_SOURCE, 500,
dnl ac_cv_sys_xopen_source,
dnl [Define to make ftello visible on some hosts (e.g. glibc 2.1.3).],
dnl [#include <stdio.h>], [return !ftello;])
fi fi
]) ])
AC_DEFUN(AC_FUNC_FSEEKO,
[AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE, 1,
ac_cv_sys_largefile_source,
[Define to make fseeko visible on some hosts (e.g. glibc 2.2).],
[#include <stdio.h>], [return !fseeko;])
# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
# in glibc 2.1.3, but that breaks too many other things.
# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
AC_CACHE_CHECK([for fseeko], ac_cv_func_fseeko,
[ac_cv_func_fseeko=no
AC_TRY_LINK([#include <stdio.h>],
[return fseeko && fseeko (stdin, 0, 0);],
[ac_cv_func_fseeko=yes])])
if test $ac_cv_func_fseeko != no; then
AC_DEFINE(HAVE_FSEEKO, 1,
[Define if fseeko (and presumably ftello) exists and is declared.])
fi])

View File

@@ -82,6 +82,9 @@ void main(void) {
if test "$ac_cv_working_getaddrinfo" = "yes"; then if test "$ac_cv_working_getaddrinfo" = "yes"; then
AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works]) AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works])
AC_DEFINE(ENABLE_IPV6, 1, [Define if you want to enable IPv6 support]) AC_DEFINE(ENABLE_IPV6, 1, [Define if you want to enable IPv6 support])
IPV6_ENABLED=1
AC_SUBST(IPV6_ENABLED)
fi fi
]) ])
@@ -506,6 +509,10 @@ then
dnl add define KRB4 dnl add define KRB4
AC_DEFINE(KRB4) AC_DEFINE(KRB4)
dnl substitute it too!
KRB4_ENABLED=1
AC_SUBST(KRB4_ENABLED)
dnl the krb4 stuff needs a strlcpy() dnl the krb4 stuff needs a strlcpy()
AC_CHECK_FUNCS(strlcpy) AC_CHECK_FUNCS(strlcpy)
@@ -572,14 +579,45 @@ else
dnl Check for SSLeay headers dnl Check for SSLeay headers
AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h openssl/pem.h openssl/ssl.h openssl/err.h) AC_CHECK_HEADERS(openssl/x509.h openssl/rsa.h openssl/crypto.h \
openssl/pem.h openssl/ssl.h openssl/err.h)
if test $ac_cv_header_openssl_x509_h = no; then if test $ac_cv_header_openssl_x509_h = no; then
AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h) AC_CHECK_HEADERS(x509.h rsa.h crypto.h pem.h ssl.h err.h)
fi fi
dnl
dnl If all heades are present, we have enabled SSL!
if test "$ac_cv_header_openssl_x509_h" = "yes" &&
test "$ac_cv_header_openssl_rsa_h" = "yes" &&
test "$ac_cv_header_openssl_crypto_h" = "yes" &&
test "$ac_cv_header_openssl_pem_h" = "yes" &&
test "$ac_cv_header_openssl_ssl_h" = "yes" &&
test "$ac_cv_header_openssl_err_h" = "yes"; then
OPENSSL_ENABLED="1";
fi fi
dnl
dnl Check the alternative headers too
if test "$ac_cv_header_x509_h" = "yes" &&
test "$ac_cv_header_rsa_h" = "yes" &&
test "$ac_cv_header_crypto_h" = "yes" &&
test "$ac_cv_header_pem_h" = "yes" &&
test "$ac_cv_header_ssl_h" = "yes" &&
test "$ac_cv_header_err_h" = "yes"; then
OPENSSL_ENABLED="1";
fi
AC_SUBST(OPENSSL_ENABLED)
fi
if test X"$OPT_SSL" != Xoff &&
test "$OPENSSL_ENABLED" != "1"; then
AC_MSG_ERROR([OpenSSL libs and/or directories were not found where specified!])
fi
dnl these can only exist if openssl exists dnl these can only exist if openssl exists
AC_CHECK_FUNCS( RAND_status \ AC_CHECK_FUNCS( RAND_status \
@@ -801,6 +839,7 @@ AC_OUTPUT( Makefile \
perl/Makefile \ perl/Makefile \
perl/Curl_easy/Makefile \ perl/Curl_easy/Makefile \
php/Makefile \ php/Makefile \
php/examples/Makefile php/examples/Makefile \
curl-config
) )

85
curl-config.in Normal file
View File

@@ -0,0 +1,85 @@
#! /bin/sh
#
# The idea to this kind of setup info script was stolen from numerous
# other packages, such as neon, libxml and gnome.
#
# $Id$
#
prefix=@prefix@
exec_prefix=@exec_prefix@
includedir=@includedir@
usage()
{
cat <<EOF
Usage: curl-config [OPTION]
Available values for OPTION include:
--cflags pre-processor and compiler flags
--feature newline separated list of enabled features
--help display this help and exit
--libs library linking information
--prefix curl install prefix
--version output version information
EOF
exit $1
}
if test $# -eq 0; then
usage 1
fi
while test $# -gt 0; do
case "$1" in
# this deals with options in the style
# --option=value and extracts the value part
# [not currently used]
-*=*) value=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
*) value= ;;
esac
case "$1" in
--prefix)
echo $prefix
;;
--feature)
if test "@OPENSSL_ENABLED@" = "1"; then
echo "SSL"
fi
if test "@KRB4_ENABLED@" = "1"; then
echo "KRB4"
fi
if test "@IPV6_ENABLED@" = "1"; then
echo "IPv6"
fi
;;
--version)
echo libcurl @VERSION@
exit 0
;;
--help)
usage 0
;;
--cflags)
echo @CPPFLAGS@
;;
--libs)
echo @LDFLAGS@ @LIBS@
;;
*)
usage
exit 1
;;
esac
shift
done
exit 0

View File

@@ -16,7 +16,7 @@ The License Issue
the same license curl and libcurl is already using unless stated otherwise. the same license curl and libcurl is already using unless stated otherwise.
If you add a larger piece of code, you can opt to make that file or set of If you add a larger piece of code, you can opt to make that file or set of
files to use a different license as long as they don't enfore any changes to files to use a different license as long as they don't enforce any changes to
the rest of the package and they make sense. Such "separate parts" can not be the rest of the package and they make sense. Such "separate parts" can not be
GPL (as we don't want the GPL virus to attack users of libcurl) but they must GPL (as we don't want the GPL virus to attack users of libcurl) but they must
use "GPL compatible" licenses. use "GPL compatible" licenses.

View File

@@ -1,4 +1,4 @@
Updated: March 23, 2001 (http://curl.haxx.se/docs/faq.shtml) Updated: April 22, 2001 (http://curl.haxx.se/docs/faq.shtml)
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -32,7 +32,7 @@ FAQ
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y? 3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
3.7 Can I use curl to delete/rename a file through FTP? 3.7 Can I use curl to delete/rename a file through FTP?
3.8 How do I tell curl to follow HTTP redirects? 3.8 How do I tell curl to follow HTTP redirects?
3.9 How do I use curl in PHP? 3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
4. Running Problems 4. Running Problems
@@ -47,7 +47,7 @@ FAQ
4.5.4 "404 Not Found" 4.5.4 "404 Not Found"
4.5.5 "405 Method Not Allowed" 4.5.5 "405 Method Not Allowed"
4.6 Can you tell me what error code 142 means? 4.6 Can you tell me what error code 142 means?
4.7 How do I keep usernames and passwords secret in Curl command lines? 4.7 How do I keep user names and passwords secret in Curl command lines?
4.8 I found a bug! 4.8 I found a bug!
4.9 Curl can't authenticate to the server that requires NTLM? 4.9 Curl can't authenticate to the server that requires NTLM?
@@ -57,7 +57,7 @@ FAQ
5.3 How do I fetch multiple files with libcurl? 5.3 How do I fetch multiple files with libcurl?
5.4 Does libcurl do Winsock initing on win32 systems? 5.4 Does libcurl do Winsock initing on win32 systems?
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ? 5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
5.6 What about Keep-Alive or persistant connections? 5.6 What about Keep-Alive or persistent connections?
6. License Issues 6. License Issues
6.1 I have a GPL program, can I use the libcurl library? 6.1 I have a GPL program, can I use the libcurl library?
@@ -78,7 +78,7 @@ FAQ
with URL spelled in uppercase to make it obvious it deals with URLs. The with URL spelled in uppercase to make it obvious it deals with URLs. The
fact it can also be pronounced 'see URL' also helped. fact it can also be pronounced 'see URL' also helped.
Curl supports a range of common internet protocols, currently including Curl supports a range of common Internet protocols, currently including
HTTP, HTTPS, FTP, GOPHER, LDAP, DICT, TELNET and FILE. HTTP, HTTPS, FTP, GOPHER, LDAP, DICT, TELNET and FILE.
We spell it cURL or just curl. We pronounce it with an initial k sound: We spell it cURL or just curl. We pronounce it with an initial k sound:
@@ -87,7 +87,7 @@ FAQ
1.2 What is libcurl? 1.2 What is libcurl?
libcurl is a reliable and portable library which provides you with an easy libcurl is a reliable and portable library which provides you with an easy
interface to a range of common internet protocols. interface to a range of common Internet protocols.
You can use libcurl for free in your application even if it is commercial You can use libcurl for free in your application even if it is commercial
or closed-source. or closed-source.
@@ -103,8 +103,8 @@ FAQ
something: fine, go ahead and write a script that wraps around curl to make something: fine, go ahead and write a script that wraps around curl to make
it reality (like curlmirror.pl does). it reality (like curlmirror.pl does).
Curl is not an ftp site mirroring program. Sure, get and send ftp with curl Curl is not an FTP site mirroring program. Sure, get and send FTP with curl
but if you want systematic and sequential behaviour you should write a but if you want systematic and sequential behavior you should write a
script (or write a new program that interfaces libcurl) and do it. script (or write a new program that interfaces libcurl) and do it.
Curl is not a PHP tool, even though it works perfectly well when used from Curl is not a PHP tool, even though it works perfectly well when used from
@@ -162,7 +162,7 @@ FAQ
Project cURL is entirely free and open, without any commercial interests or Project cURL is entirely free and open, without any commercial interests or
money involved. No person gets paid in any way for developing curl. We all money involved. No person gets paid in any way for developing curl. We all
do this volountarily on our spare time. do this voluntarily on our spare time.
We get some help from companies. Contactor Data hosts the curl web site and We get some help from companies. Contactor Data hosts the curl web site and
the main mailing list, Haxx owns the curl web site's domain and the main mailing list, Haxx owns the curl web site's domain and
@@ -204,7 +204,7 @@ FAQ
a few functions are left out from the libssl. a few functions are left out from the libssl.
If the function names missing include RSA or RSAREF you can be certain If the function names missing include RSA or RSAREF you can be certain
that this is because libssl requires the RSA and RSASEF libs to build. that this is because libssl requires the RSA and RSAREF libs to build.
See the INSTALL file section that explains how to add those libs to See the INSTALL file section that explains how to add those libs to
configure. Make sure that you remove the config.cache file before you configure. Make sure that you remove the config.cache file before you
@@ -223,12 +223,12 @@ FAQ
Curl uses OpenSSL to do the SSL stuff. The LIBEAY32.DLL is what curl needs Curl uses OpenSSL to do the SSL stuff. The LIBEAY32.DLL is what curl needs
on a windows machine to do https://. Check out the curl web site to find on a windows machine to do https://. Check out the curl web site to find
accurate and up-to-date pointers to recent OpenSSL DDLs and other binary accurate and up-to-date pointers to recent OpenSSL DLLs and other binary
packages. packages.
2.4. Does cURL support Socks (RFC 1928) ? 2.4. Does cURL support Socks (RFC 1928) ?
No. Nobody has wanted it that badly yet. We appriciate patches that bring No. Nobody has wanted it that badly yet. We appreciate patches that bring
this functionality. this functionality.
@@ -263,10 +263,11 @@ FAQ
use the -F type. In all the most common cases, you should use -d which then use the -F type. In all the most common cases, you should use -d which then
causes a posting with the type 'application/x-www-form-urlencoded'. causes a posting with the type 'application/x-www-form-urlencoded'.
This is described in some detail in the README.curl file, and if you don't This is described in some detail in the MANUAL and TheArtOfHttpScripting
understand it the first time, read it again before you post questions about documents, and if you don't understand it the first time, read it again
this to the mailing list. Also, try reading through the mailing list before you post questions about this to the mailing list. Also, try reading
archives for old postings and questions regarding this. through the mailing list archives for old postings and questions regarding
this.
3.4. How do I tell curl to run custom FTP commands? 3.4. How do I tell curl to run custom FTP commands?
@@ -274,7 +275,7 @@ FAQ
file transfer. Study the -Q/--quote option. file transfer. Study the -Q/--quote option.
Since curl is used for file transfers, you don't use curl to just perform Since curl is used for file transfers, you don't use curl to just perform
ftp commands without transfering anything. Therefore you must always specify FTP commands without transferring anything. Therefore you must always specify
a URL to transfer to/from even when doing custom FTP commands. a URL to transfer to/from even when doing custom FTP commands.
3.5. How can I disable the Pragma: nocache header? 3.5. How can I disable the Pragma: nocache header?
@@ -286,7 +287,7 @@ FAQ
3.6. Does curl support javascript, ASP, XML, XHTML or HTML version Y? 3.6. Does curl support javascript, ASP, XML, XHTML or HTML version Y?
To curl, all contents are alike. It doesn't matter how the page was To curl, all contents are alike. It doesn't matter how the page was
generated. It may be ASP, PHP, perl, shell-script, SSI or plain generated. It may be ASP, PHP, Perl, shell-script, SSI or plain
HTML-files. There's no difference to curl and it doesn't even know what kind HTML-files. There's no difference to curl and it doesn't even know what kind
of language that generated the page. of language that generated the page.
@@ -296,7 +297,7 @@ FAQ
3.7. Can I use curl to delete/rename a file through FTP? 3.7. Can I use curl to delete/rename a file through FTP?
Yes. You specify custom ftp commands with -Q/--quote. Yes. You specify custom FTP commands with -Q/--quote.
One example would be to delete a file after you have downloaded it: One example would be to delete a file after you have downloaded it:
@@ -310,7 +311,20 @@ FAQ
curl -L http://redirector.com curl -L http://redirector.com
3.9 How do I use curl in PHP? 3.9 How do I use curl in PHP, Perl, Tcl, Ruby or Java?
There exist many language-interfaces for curl that integrates it better with
various languages. If you are fluid in a script language, you may very well
opt to use such an interface instead of using the command line tool.
At the time of writing, there are bindings for the five language mentioned
above, but chances are there are even more by the time you read this. Or you
may be able you write your own wrapper for a not-yet support language!
Find out more about which languages that support curl directly, and how to
install and use them, in the libcurl section of the curl web site:
http://curl.haxx.se/libcurl/
PHP4 has the ability to use libcurl as an internal module if built with that PHP4 has the ability to use libcurl as an internal module if built with that
option enabled. You then get a set of extra functions that can be used option enabled. You then get a set of extra functions that can be used
@@ -326,7 +340,7 @@ FAQ
3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP? 3.10 What about SOAP, WebDAV, XML-RPC or similar protocols over HTTP?
Curl adheres to the HTTP spec, which basically means you can play with *any* Curl adheres to the HTTP spec, which basically means you can play with *any*
protocol that is built ontop of HTTP. Protocols such as SOAP, WEBDAV and protocol that is built on top of HTTP. Protocols such as SOAP, WEBDAV and
XML-RPC are all such ones. You can use -X to set custom requests and -H to XML-RPC are all such ones. You can use -X to set custom requests and -H to
set custom headers (or replace internally generated ones). set custom headers (or replace internally generated ones).
@@ -354,7 +368,7 @@ FAQ
In general unix shells, the & letter is treated special and when used, it In general unix shells, the & letter is treated special and when used, it
runs the specified command in the background. To safely send the & as a part runs the specified command in the background. To safely send the & as a part
of a URL, you should qoute the entire URL by using single (') or double (") of a URL, you should quote the entire URL by using single (') or double (")
quotes around it. quotes around it.
An example that would invoke a remote CGI that uses &-letters could be: An example that would invoke a remote CGI that uses &-letters could be:
@@ -429,13 +443,13 @@ FAQ
abort from such a condition and that's why it got this undocumented abort from such a condition and that's why it got this undocumented
error. This should not occur in releases after 7.4.1. error. This should not occur in releases after 7.4.1.
4.7. How do I keep usernames and passwords secret in Curl command lines? 4.7. How do I keep user names and passwords secret in Curl command lines?
This problem has two sides: This problem has two sides:
The first part is to avoid having clear-text passwords in the command line The first part is to avoid having clear-text passwords in the command line
so that they don't appear in 'ps' outputs and similar. That is easily so that they don't appear in 'ps' outputs and similar. That is easily
avoided by using the "-K" option tho tell curl to read parameters from a avoided by using the "-K" option to tell curl to read parameters from a
file or stdin to which you can pass the secret info. file or stdin to which you can pass the secret info.
To keep the passwords in your account secret from the rest of the world is To keep the passwords in your account secret from the rest of the world is
@@ -445,11 +459,11 @@ FAQ
Also note that regular HTTP and FTP passwords are sent in clear across the Also note that regular HTTP and FTP passwords are sent in clear across the
network. All it takes for anyone to fetch them is to listen on the network. network. All it takes for anyone to fetch them is to listen on the network.
Evesdropping is very easy. Eavesdropping is very easy.
4.8 I found a bug! 4.8 I found a bug!
It is not a bug if the behaviour is documented. Read the docs first. It is not a bug if the behavior is documented. Read the docs first.
If it is a problem with a binary you've downloaded or a package for your If it is a problem with a binary you've downloaded or a package for your
particular platform, try contacting the person who built the package/archive particular platform, try contacting the person who built the package/archive
@@ -478,14 +492,14 @@ FAQ
programs. libcurl will use thread-safe functions instead of non-safe ones if programs. libcurl will use thread-safe functions instead of non-safe ones if
your system has such. your system has such.
We would appriciate some kind of report or README file from those who have We would appreciate some kind of report or README file from those who have
used libcurl in a threaded environment. used libcurl in a threaded environment.
5.2 How can I receive all data into a large memory chunk? 5.2 How can I receive all data into a large memory chunk?
You are in full control of the callback function that gets called every time You are in full control of the callback function that gets called every time
there is data received from the remote server. You can make that callback do there is data received from the remote server. You can make that callback do
whatever you want. You do not have to write the receivied data to a file. whatever you want. You do not have to write the received data to a file.
One solution to this problem could be to have a pointer to a struct that you One solution to this problem could be to have a pointer to a struct that you
pass to the callback function. You set the pointer using the pass to the callback function. You set the pointer using the
@@ -521,7 +535,7 @@ FAQ
curl_easy_setopt() and then transfer it with curl_easy_perform(). The handle curl_easy_setopt() and then transfer it with curl_easy_perform(). The handle
you get from curl_easy_init() is not only reusable starting with libcurl you get from curl_easy_init() is not only reusable starting with libcurl
7.7, but also you're encouraged to reuse it if you can, as that will enable 7.7, but also you're encouraged to reuse it if you can, as that will enable
libcurl to use persistant connections. libcurl to use persistent connections.
For libcurl prior to 7.7, there was no multiple file support. The only For libcurl prior to 7.7, there was no multiple file support. The only
available way to do multiple requests was to init/perform/cleanup for each available way to do multiple requests was to init/perform/cleanup for each
@@ -547,15 +561,15 @@ FAQ
(Provided by Joel DeYoung and Bob Schader) (Provided by Joel DeYoung and Bob Schader)
5.6 What about Keep-Alive or persistant connections? 5.6 What about Keep-Alive or persistent connections?
Starting with version 7.7, curl and libcurl will have excellent support for Starting with version 7.7, curl and libcurl will have excellent support for
persistant connections when transferring several files from the same server. persistent connections when transferring several files from the same server.
Curl will attempt to reuse connections for all URLs specified on the same Curl will attempt to reuse connections for all URLs specified on the same
command line/config file, and libcurl will reuse connections for all command line/config file, and libcurl will reuse connections for all
transfers that are made using the same libcurl handle. transfers that are made using the same libcurl handle.
Previous versions had no persistant connection support. Previous versions had no persistent connection support.
6. License Issues 6. License Issues

View File

@@ -254,7 +254,7 @@ PORTS
This is a probably incomplete list of known hardware and This is a probably incomplete list of known hardware and
operating systems that curl has been compiled for: operating systems that curl has been compiled for:
- Ultrix - Ultrix 4.3a
- SINIX-Z v5 - SINIX-Z v5
- Alpha DEC OSF 4 - Alpha DEC OSF 4
- Alpha Digital UNIX v3.2 - Alpha Digital UNIX v3.2

View File

@@ -201,10 +201,10 @@ Library
exists in lib/getpass.c. libcurl offers a custom callback that can be used exists in lib/getpass.c. libcurl offers a custom callback that can be used
instead of this, but it doesn't change much to us. instead of this, but it doesn't change much to us.
Persistant Connections Persistent Connections
====================== ======================
With curl 7.7, we added persistant connection support to libcurl which has With curl 7.7, we added persistent connection support to libcurl which has
introduced a somewhat different treatmeant of things inside of libcurl. introduced a somewhat different treatmeant of things inside of libcurl.
o The 'UrlData' struct returned in the curl_easy_init() call must never o The 'UrlData' struct returned in the curl_easy_init() call must never
@@ -227,7 +227,7 @@ Persistant Connections
o When curl_easy_cleanup() is called, we close all still opened connections. o When curl_easy_cleanup() is called, we close all still opened connections.
You do realize that the curl handle must be re-used in order for the You do realize that the curl handle must be re-used in order for the
persistant connections to work. persistent connections to work.
Library Symbols Library Symbols
=============== ===============

View File

@@ -6,8 +6,8 @@
How To Use Libcurl In Your C/C++ Program How To Use Libcurl In Your C/C++ Program
[ libcurl can be used directly from within your PHP or Perl programs as well, [ libcurl can be used directly from within your Java, PHP, Perl, Ruby or Tcl
look elsewhere for documentation on this ] programs as well, look elsewhere for documentation on this ]
The interface is meant to be very simple for applictions/programmers, hence The interface is meant to be very simple for applictions/programmers, hence
the name "easy". We have therefore minimized the number of entries. the name "easy". We have therefore minimized the number of entries.
@@ -49,6 +49,29 @@ The Easy Interface
For details on these, read the separate man pages. For details on these, read the separate man pages.
Linking with libcurl
Staring with 7.7.2 (on unix-like machines), there's a tool named curl-config
that gets installed with the rest of the curl stuff when 'make install' is
performed.
curl-config is added to make it easier for applications to link with
libcurl and developers to learn about libcurl and how to use it.
Run 'curl-config --libs' to get the (additional) linker options you need to
link with the particular version of libcurl you've installed.
For details, see the curl-config.1 man page.
libcurl symbol names
All public functions in the libcurl interface are prefixed with 'curl_' (with
a lowercase c). You can find other functions in the library source code, but
other prefixes indicate the functions are private and may change without
further notice in the next release.
Only use documented functions and functionality!
Portability Portability
libcurl works *exactly* the same, on any of the platforms it compiles and libcurl works *exactly* the same, on any of the platforms it compiles and

View File

@@ -6,6 +6,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
man_MANS = \ man_MANS = \
curl.1 \ curl.1 \
curl-config.1 \
curl_easy_cleanup.3 \ curl_easy_cleanup.3 \
curl_easy_getinfo.3 \ curl_easy_getinfo.3 \
curl_easy_init.3 \ curl_easy_init.3 \
@@ -19,7 +20,11 @@ man_MANS = \
curl_slist_free_all.3 \ curl_slist_free_all.3 \
curl_version.3 \ curl_version.3 \
curl_escape.3 \ curl_escape.3 \
curl_unescape.3 curl_unescape.3 \
curl_strequal.3 \
curl_strnequal.3 \
curl_printf.3 \
libcurl.5
EXTRA_DIST = $(man_MANS) \ EXTRA_DIST = $(man_MANS) \
MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \ MANUAL BUGS CONTRIBUTE FAQ FEATURES INTERNALS \

View File

@@ -11,14 +11,13 @@ TODO
To do for the next release: To do for the next release:
* Make sure SSL works even when IPv6 is enabled. We just can't connect to
IPv6 sites and use SSL, but we should detect that particular condition
and warn about it.
* Make SSL session ids get used if multiple HTTPS documents from the same * Make SSL session ids get used if multiple HTTPS documents from the same
host is requested. host is requested.
* Document the undocumented libcurl functions: the printf clones (like
curl_msprintf, curl_mfprintf, curl_msnprintf, curl_maprintf and
curl_mvfprintf) and the string compare functions (curl_strequal
and curl_strnequal).
To do in a future release (random order): To do in a future release (random order):
* Rewrite parts of the test suite. Make a (XML?) format to store all * Rewrite parts of the test suite. Make a (XML?) format to store all
@@ -91,5 +90,3 @@ To do in a future release (random order):
EPRT for IPv6 (done), and EPSV instead of PASV. HTTP proxies are left to EPRT for IPv6 (done), and EPSV instead of PASV. HTTP proxies are left to
add support for. add support for.
* SSL for more protocols, like SSL-FTP...
(http://search.ietf.org/internet-drafts/draft-murray-auth-ftp-ssl-05.txt)

54
docs/curl-config.1 Normal file
View File

@@ -0,0 +1,54 @@
.\" You can view this file with:
.\" nroff -man curl-config.1
.\" Written by Daniel Stenberg
.\"
.TH curl-config 1 "18 March 2001" "Curl 7.7.2" "curl-config manual"
.SH NAME
curl-config \- Get information about a libcurl installation
.SH SYNOPSIS
.B curl-config [options]
.SH DESCRIPTION
.B curl-config
displays information about a previous curl and libcurl installation.
.SH OPTIONS
.IP "--cflags"
What set of CFLAGS that was used when libcurl was built. This is mostly a
debug option that serves no particular use to most people.
.IP "--feature"
Lists what particular main features the installed libcurl was built with. At
the time of writing, this list may include SSL, KRB4 or IPv6. Do not assume
any particular order. The keywords will be separated by newlines. There may be
none, one or several keywords in the list.
.IP "--help"
Displays the available options.
.IP "--libs"
Shows the complete set of libs and other linker options you will need in order
to link your application with libcurl.
.IP "--prefix"
This is the prefix used when libcurl was installed. Libcurl is then installed
in $prefix/lib and its header files are installed in $prefix/include and so
on. The prefix is set with "configure --prefix".
.IP "--version"
Outputs version information about the installed libcurl.
.SH "EXAMPLES"
What is the path to the curl header files?
echo `curl-config --prefix`/include
What is the path to libcurl?
echo `curl-config --prefix`/lib
What other linker options do I need when I link with libcurl?
curl-config --libs
How do I know if libcurl was built with SSL support?
curl-config --feature | grep SSL
What's the installed libcurl version?
curl-config --version
.SH "SEE ALSO"
.BR curl (1)

View File

@@ -2,7 +2,7 @@
.\" nroff -man curl.1 .\" nroff -man curl.1
.\" Written by Daniel Stenberg .\" Written by Daniel Stenberg
.\" .\"
.TH curl 1 "24 March 2001" "Curl 7.7" "Curl Manual" .TH curl 1 "20 April 2001" "Curl 7.7.2" "Curl Manual"
.SH NAME .SH NAME
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or
HTTPS syntax. HTTPS syntax.
@@ -94,11 +94,12 @@ If this option is used twice, the second one will disable ASCII usage.
.IP "--connect-timeout <seconds>" .IP "--connect-timeout <seconds>"
Maximum time in seconds that you allow the connection to the server to take. Maximum time in seconds that you allow the connection to the server to take.
This only limits the connection phase, once curl has connected this option is This only limits the connection phase, once curl has connected this option is
of no more use. This option doesn't work in win32 systems. See also the of no more use. This option didn't work in win32 systems until 7.7.2. See
also the
.I "--max-time" .I "--max-time"
option. option.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-c/--continue" .IP "-c/--continue"
.B Deprecated. Use '-C -' instead. .B Deprecated. Use '-C -' instead.
Continue/Resume a previous file transfer. This instructs curl to Continue/Resume a previous file transfer. This instructs curl to
@@ -117,7 +118,7 @@ If used with uploads, the ftp server command SIZE will not be used by
curl. Upload resume is for FTP only. curl. Upload resume is for FTP only.
HTTP resume is only possible with HTTP/1.1 or later servers. HTTP resume is only possible with HTTP/1.1 or later servers.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-d/--data <data>" .IP "-d/--data <data>"
(HTTP) Sends the specified data in a POST request to the HTTP server, in a way (HTTP) Sends the specified data in a POST request to the HTTP server, in a way
that can emulate as if a user has filled in a HTML form and pressed the submit that can emulate as if a user has filled in a HTML form and pressed the submit
@@ -139,12 +140,12 @@ To post data purely binary, you should instead use the --data-binary option.
-d/--data is the same as --data-ascii. -d/--data is the same as --data-ascii.
If this option is used serveral times, the ones following the first will If this option is used several times, the ones following the first will
append data. append data.
.IP "--data-ascii <data>" .IP "--data-ascii <data>"
(HTTP) This is an alias for the -d/--data option. (HTTP) This is an alias for the -d/--data option.
If this option is used serveral times, the ones following the first will If this option is used several times, the ones following the first will
append data. append data.
.IP "--data-binary <data>" .IP "--data-binary <data>"
(HTTP) This posts data in a similar manner as --data-ascii does, although when (HTTP) This posts data in a similar manner as --data-ascii does, although when
@@ -152,9 +153,9 @@ using this option the entire context of the posted data is kept as-is. If you
want to post a binary file without the strip-newlines feature of the want to post a binary file without the strip-newlines feature of the
--data-ascii option, this is for you. --data-ascii option, this is for you.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
If this option is used serveral times, the ones following the first will If this option is used several times, the ones following the first will
append data. append data.
.IP "-D/--dump-header <file>" .IP "-D/--dump-header <file>"
(HTTP/FTP) (HTTP/FTP)
@@ -165,7 +166,7 @@ This option is handy to use when you want to store the cookies that a HTTP
site sends to you. The cookies could then be read in a second curl invoke by site sends to you. The cookies could then be read in a second curl invoke by
using the -b/--cookie option! using the -b/--cookie option!
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-e/--referer <URL>" .IP "-e/--referer <URL>"
(HTTP) Sends the "Referer Page" information to the HTTP server. This can also (HTTP) Sends the "Referer Page" information to the HTTP server. This can also
be set with the -H/--header flag of course. When used with be set with the -H/--header flag of course. When used with
@@ -174,7 +175,7 @@ you can append ";auto" to the referer URL to make curl automatically set the
previous URL when it follows a Location: header. The ";auto" string can be previous URL when it follows a Location: header. The ";auto" string can be
used alone, even if you don't set an initial referer. used alone, even if you don't set an initial referer.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "--egd-file <file>" .IP "--egd-file <file>"
(HTTPS) Specify the path name to the Entropy Gathering Daemon socket. The (HTTPS) Specify the path name to the Entropy Gathering Daemon socket. The
socket is used to seed the random engine for SSL connections. See also the socket is used to seed the random engine for SSL connections. See also the
@@ -188,12 +189,12 @@ If the optional password isn't specified, it will be queried for on
the terminal. Note that this certificate is the private key and the private the terminal. Note that this certificate is the private key and the private
certificate concatenated! certificate concatenated!
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "--cacert <CA certificate>" .IP "--cacert <CA certificate>"
(HTTPS) Tells curl to use the specified certificate file to verify the (HTTPS) Tells curl to use the specified certificate file to verify the
peer. The certificate must be in PEM format. peer. The certificate must be in PEM format.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-f/--fail" .IP "-f/--fail"
(HTTP) (HTTP)
Fail silently (no output at all) on server errors. This is mostly done Fail silently (no output at all) on server errors. This is mostly done
@@ -256,7 +257,7 @@ name, IP address or host name. An example could look like:
.B "curl --interface eth0:1 http://www.netscape.com/" .B "curl --interface eth0:1 http://www.netscape.com/"
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-I/--head" .IP "-I/--head"
(HTTP/FTP) (HTTP/FTP)
Fetch the HTTP-header only! HTTP-servers feature the command HEAD Fetch the HTTP-header only! HTTP-servers feature the command HEAD
@@ -269,7 +270,7 @@ If this option is used twice, the second will again disable header only.
should be one of 'clear', 'safe', 'confidential' or 'private'. Should you use should be one of 'clear', 'safe', 'confidential' or 'private'. Should you use
a level that is not one of these, 'private' will instead be used. a level that is not one of these, 'private' will instead be used.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-K/--config <config file>" .IP "-K/--config <config file>"
Specify which config file to read curl arguments from. The config file is a Specify which config file to read curl arguments from. The config file is a
text file in which command line arguments can be written which then will be text file in which command line arguments can be written which then will be
@@ -307,7 +308,7 @@ See also the
.I "--connect-timeout" .I "--connect-timeout"
option. option.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-M/--manual" .IP "-M/--manual"
Manual. Display the huge help text. Manual. Display the huge help text.
.IP "-n/--netrc" .IP "-n/--netrc"
@@ -385,7 +386,7 @@ i.e "my.host.domain" to specify machine
(any single-letter string) to make it pick the machine's default (any single-letter string) to make it pick the machine's default
.RE .RE
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-q" .IP "-q"
If used as the first parameter on the command line, the If used as the first parameter on the command line, the
.I $HOME/.curlrc .I $HOME/.curlrc
@@ -444,7 +445,7 @@ document.
FTP range downloads only support the simple syntax 'start-stop' (optionally FTP range downloads only support the simple syntax 'start-stop' (optionally
with one of the numbers omitted). It depends on the non-RFC command SIZE. with one of the numbers omitted). It depends on the non-RFC command SIZE.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-s/--silent" .IP "-s/--silent"
Silent mode. Don't show progress meter or error messages. Makes Silent mode. Don't show progress meter or error messages. Makes
Curl mute. Curl mute.
@@ -471,18 +472,18 @@ think that your last directory name is the remote file name to
use. That will most likely cause the upload operation to fail. If use. That will most likely cause the upload operation to fail. If
this is used on a http(s) server, the PUT command will be used. this is used on a http(s) server, the PUT command will be used.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-u/--user <user:password>" .IP "-u/--user <user:password>"
Specify user and password to use when fetching. See README.curl for detailed Specify user and password to use when fetching. See README.curl for detailed
examples of how to use this. If no password is specified, curl will examples of how to use this. If no password is specified, curl will
ask for it interactively. ask for it interactively.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-U/--proxy-user <user:password>" .IP "-U/--proxy-user <user:password>"
Specify user and password to use for Proxy authentication. If no Specify user and password to use for Proxy authentication. If no
password is specified, curl will ask for it interactively. password is specified, curl will ask for it interactively.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "--url <URL>" .IP "--url <URL>"
Specify a URL to fetch. This option is mostly handy when you wanna specify Specify a URL to fetch. This option is mostly handy when you wanna specify
URL(s) in a config file. URL(s) in a config file.
@@ -565,12 +566,12 @@ The average download speed that curl measured for the complete download.
The average upload speed that curl measured for the complete upload. The average upload speed that curl measured for the complete upload.
.RE .RE
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-x/--proxy <proxyhost[:port]>" .IP "-x/--proxy <proxyhost[:port]>"
Use specified proxy. If the port number is not specified, it is assumed at Use specified proxy. If the port number is not specified, it is assumed at
port 1080. port 1080.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-X/--request <command>" .IP "-X/--request <command>"
(HTTP) (HTTP)
Specifies a custom request to use when communicating with the HTTP server. Specifies a custom request to use when communicating with the HTTP server.
@@ -581,19 +582,19 @@ HTTP 1.1 specification for details and explanations.
Specifies a custom FTP command to use instead of LIST when doing file lists Specifies a custom FTP command to use instead of LIST when doing file lists
with ftp. with ftp.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-y/--speed-time <time>" .IP "-y/--speed-time <time>"
If a download is slower than speed-limit bytes per second during a speed-time If a download is slower than speed-limit bytes per second during a speed-time
period, the download gets aborted. If speed-time is used, the default period, the download gets aborted. If speed-time is used, the default
speed-limit will be 1 unless set with -y. speed-limit will be 1 unless set with -y.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-Y/--speed-limit <speed>" .IP "-Y/--speed-limit <speed>"
If a download is slower than this given speed, in bytes per second, for If a download is slower than this given speed, in bytes per second, for
speed-time seconds it gets aborted. speed-time is set with -Y and is 30 if speed-time seconds it gets aborted. speed-time is set with -Y and is 30 if
not set. not set.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-z/--time-cond <date expression>" .IP "-z/--time-cond <date expression>"
(HTTP) (HTTP)
Request to get a file that has been modified later than the given time and Request to get a file that has been modified later than the given time and
@@ -609,7 +610,7 @@ Start the date expression with a dash (-) to make it request for a document
that is older than the given date/time, default is a document that is newer that is older than the given date/time, default is a document that is newer
than the specified date/time. than the specified date/time.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-3/--sslv3" .IP "-3/--sslv3"
(HTTPS) (HTTPS)
Forces curl to use SSL version 3 when negotiating with a remote SSL server. Forces curl to use SSL version 3 when negotiating with a remote SSL server.
@@ -630,7 +631,7 @@ Redirect all writes to stderr to the specified file instead. If the file name
is a plain '-', it is instead written to stdout. This option has no point when is a plain '-', it is instead written to stdout. This option has no point when
you're using a shell with decent redirecting capabilities. you're using a shell with decent redirecting capabilities.
If this option is used serveral times, the last one will be used. If this option is used several times, the last one will be used.
.SH FILES .SH FILES
.I ~/.curlrc .I ~/.curlrc
.RS .RS
@@ -821,6 +822,9 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Robert Weaver <robert.weaver@sabre.com> - Robert Weaver <robert.weaver@sabre.com>
- Ingo Ralf Blum <ingoralfblum@ingoralfblum.com> - Ingo Ralf Blum <ingoralfblum@ingoralfblum.com>
- Jun-ichiro itojun Hagino <itojun@iijlab.net> - Jun-ichiro itojun Hagino <itojun@iijlab.net>
- Frederic Lepied <flepied@mandrakesoft.com>
- Georg Horn <horn@koblenz-net.de>
- Cris Bailiff <c.bailiff@awayweb.com>
.SH WWW .SH WWW
http://curl.haxx.se http://curl.haxx.se

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_setopt 3 "30 March 2001" "libcurl 7.7" "libcurl Manual" .TH curl_easy_setopt 3 "10 April 2001" "libcurl 7.7.2" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_setopt - Set curl easy-session options curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS .SH SYNOPSIS
@@ -54,7 +54,7 @@ if you set the
option. option.
.TP .TP
.B CURLOPT_WRITEFUNCTION .B CURLOPT_WRITEFUNCTION
Function pointer that should use match the following prototype: Function pointer that should match the following prototype:
.BI "size_t function( void *ptr, size_t size, size_t nmemb, FILE *stream);" .BI "size_t function( void *ptr, size_t size, size_t nmemb, FILE *stream);"
This function gets called by libcurl as soon as there is received data that This function gets called by libcurl as soon as there is received data that
needs to be written down. The size of the data pointed to by needs to be written down. The size of the data pointed to by
@@ -78,7 +78,7 @@ if you set the
option. option.
.TP .TP
.B CURLOPT_READFUNCTION .B CURLOPT_READFUNCTION
Function pointer that should use match the following prototype: Function pointer that should match the following prototype:
.BI "size_t function( void *ptr, size_t size, size_t nmemb, FILE *stream);" .BI "size_t function( void *ptr, size_t size, size_t nmemb, FILE *stream);"
This function gets called by libcurl as soon as it needs to read data in order This function gets called by libcurl as soon as it needs to read data in order
to send it to the peer. The data area pointed at by the pointer to send it to the peer. The data area pointed at by the pointer
@@ -319,7 +319,32 @@ struct curl_slist structs properly filled in as described for
.B CURLOPT_WRITEHEADER .B CURLOPT_WRITEHEADER
Pass a FILE * to be used to write the header part of the received data to. The Pass a FILE * to be used to write the header part of the received data to. The
headers are guaranteed to be written one-by-one to this file handle and only headers are guaranteed to be written one-by-one to this file handle and only
complete lines are written. Parsing headers should be easy enough using this. complete lines are written. Parsing headers should be easy enough using
this. See also the
.I CURLOPT_HEADERFUNCTION
option.
.TP
.B CURLOPT_HEADERFUNCTION
Function pointer that should match the following prototype:
.BI "size_t function( void *ptr, size_t size, size_t nmemb, FILE *stream);"
This function gets called by libcurl as soon as there is received header data
that needs to be written down. The function will be called once for each
header with a complete header line in each invoke. The size of the data
pointed to by
.I ptr
is
.I size
multiplied with
.I nmemb.
The pointer named
.I stream
will be the one you passed to libcurl with the
.I CURLOPT_WRITEHEADER
option.
Return the number of bytes actually written or return -1 to signal error to
the library (it will cause it to abort the transfer with a
.I CURLE_WRITE_ERROR
return code). (Added in libcurl 7.7.2)
.TP .TP
.B CURLOPT_COOKIEFILE .B CURLOPT_COOKIEFILE
Pass a pointer to a zero terminated string as parameter. It should contain the Pass a pointer to a zero terminated string as parameter. It should contain the
@@ -473,7 +498,7 @@ Pass a char * to a zero terminated file name. The file will be used to read
from to seed the random engine for SSL. The more random the specified file is, from to seed the random engine for SSL. The more random the specified file is,
the more secure will the SSL connection become. the more secure will the SSL connection become.
.TP .TP
.B CURLOPT_FORBID_REUSE .B CURLOPT_EGDSOCKET
Pass a char * to the zero terminated path name to the Entropy Gathering Daemon Pass a char * to the zero terminated path name to the Entropy Gathering Daemon
socket. It will be used to seed the random engine for SSL. socket. It will be used to seed the random engine for SSL.
.TP .TP

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_formfree 3 "5 March 2001" "libcurl 7.5" "libcurl Manual" .TH curl_formfree 3 "6 April 2001" "libcurl 7.7.1" "libcurl Manual"
.SH NAME .SH NAME
curl_formfree - free a previously build multipart/formdata HTTP POST chain curl_formfree - free a previously build multipart/formdata HTTP POST chain
.SH SYNOPSIS .SH SYNOPSIS
@@ -19,5 +19,7 @@ None
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_formparse "(3) " .BR curl_formparse "(3) "
.SH BUGS .SH BUGS
Surely there are some, you tell me! libcurl 7.7.1 and earlier versions does not allow a NULL pointer to be used as
argument.

88
docs/curl_printf.3 Normal file
View File

@@ -0,0 +1,88 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_printf 3 "20 April 2001" "libcurl 7.7.2" "libcurl Manual"
.SH NAME
curl_maprintf, curl_mfprintf, curl_mprintf, curl_msnprintf, curl_msprintf
curl_mvaprintf, curl_mvfprintf, curl_mvprintf, curl_mvsnprintf,
curl_mvsprintf - formatted output conversion
.SH SYNOPSIS
.B #include <curl/mprintf.h>
.sp
.BI "int curl_mprintf(const char *" format ", ...);"
.br
.BI "int curl_mfprintf(FILE *" fd ", const char *" format ", ...);"
.br
.BI "int curl_msprintf(char *" buffer ", const char *" format ", ...);"
.br
.BI "int curl_msnprintf(char *" buffer ", size_t " maxlength ", const char *" format ", ...);"
.br
.BI "int curl_mvprintf(const char *" format ", va_list " args ");"
.br
.BI "int curl_mvfprintf(FILE *" fd ", const char *" format ", va_list " args ");"
.br
.BI "int curl_mvsprintf(char *" buffer ", const char *" format ", va_list " args ");"
.br
.BI "int curl_mvsnprintf(char *" buffer ", size_t " maxlength ", const char *" format ", va_list " args ");"
.br
.BI "char *curl_maprintf(const char *" format ", ...);"
.br
.BI "char *curl_mvaprintf(const char *" format ", va_list " args ");"
.SH DESCRIPTION
These are all functions that produces output according to a format string and
given arguments. These are mostly clones of the well-known C-style functions
and there will be no detailed explanation of all available formatting rules
and usage here.
See this table for notable exceptions.
.RS
.TP
.B curl_mprintf()
Normal printf() clone.
.TP
.B curl_mfprintf()
Normal fprinf() clone.
.TP
.B curl_msprintf()
Normal sprintf() clone.
.TP
.B curl_msnprintf()
snprintf() clone. Many systems don't have this. It is just like \fBsprintf\fP
but with an extra argument after the buffer that specifies the length of the
target buffer.
.TP
.B curl_mvprintf()
Normal vprintf() clone.
.TP
.B curl_mvfprintf()
Normal vfprintf() clone.
.TP
.B curl_mvsprintf()
Normal vsprintf() clone.
.TP
.B curl_mvsnprintf()
vsnprintf() clone. Many systems don't have this. It is just like
\fBvsprintf\fP but with an extra argument after the buffer that specifies the
length of the target buffer.
.TP
.B curl_maprintf()
Like printf() but returns the output string as a malloc()ed string. The
returned string must be free()ed by the receiver.
.TP
.B curl_mvaprintf()
Like curl_maprintf() but takes a va_list pointer argument instead of a
variable amount of arguments.
.RE
To easily use all these cloned functions instead of the normal ones, #define
_MPRINTF_REPLACE before you include the <curl/mprintf.h> file. Then all the
normal names like printf, fprintf, sprintf etc will use the curl-functions
instead.
.SH RETURN VALUE
The \fBcurl_maprintf\fP and \fBcurl_mvaprintf\fP functions return a pointer to
a newly allocated string, or NULL it it failed.
All other functions return the number of character they actually outputed.
.SH "SEE ALSO"
.BR printf "(3), " sprintf "(3), " fprintf "(3), " vprintf "(3) "

30
docs/curl_strequal.3 Normal file
View File

@@ -0,0 +1,30 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_strequal 3 "20 April 2001" "libcurl 7.7.2" "libcurl Manual"
.SH NAME
curl_strequal, curl_strnequal - case insensitive string comparisons
.SH SYNOPSIS
.B #include <curl/curl.h>
.sp
.BI "int curl_strequal(char *" str1 ", char *" str2 ");"
.sp
.BI "int curl_strenqual(char *" str1 ", char *" str2 ", size_t " len ");"
.SH DESCRIPTION
The
.B curl_strequal()
function compares the two strings \fIstr1\fP and \fIstr2\fP, ignoring the case
of the characters. It returns a non-zero (TRUE) integer if the strings are
identical.
.sp
The \fBcurl_strnequal()\fP function is similar, except it only compares the
first \fIlen\fP characters of \fIstr1\fP.
.sp
These functions are provided by libcurl to enable applications to compare
strings in a truly portable manner. There are no standard portable case
insensitive string comparison functions. These two works on all platforms.
.SH RETURN VALUE
A pointer to a zero terminated string.
.SH "SEE ALSO"
.BR strcmp "(3), " strcasecmp "(3)"

1
docs/curl_strnequal.3 Normal file
View File

@@ -0,0 +1 @@
.so curl_strequal.3

View File

@@ -12,3 +12,7 @@ examples. Just edit the file according to your system and requirements first.
Try the php/examples/ directory for PHP programming snippets! Try the php/examples/ directory for PHP programming snippets!
*PLEASE* do not use the curl.haxx.se site as a test target for your libcurl
applications/experiments. Even if the examples in this directory use that
site as an example URL at some places, it doesn't mean that the URLs work or
that we expect you to actually torture our web site with your tests! Thanks.

124
docs/libcurl.5 Normal file
View File

@@ -0,0 +1,124 @@
.\" You can view this file with:
.\" nroff -man libcurl.5
.\" Written by Daniel Stenberg
.\"
.TH libcurl 5 "20 April 2001" "libcurl 7.7.2" "libcurl overview"
.SH NAME
libcurl \- client-side URL transfers
.SH DESCRIPTION
This is an overview on how to use libcurl in your c/c++ programs. There are
specific man pages for each function mentioned in here.
libcurl can also be used directly from within your Java, PHP, Perl, Ruby or
Tcl programs as well, look elsewhere for documentation on this!
When using libcurl's easy interface, you init your session and get a handle,
which you use as input to the following interface functions you use. Use
.B curl_easy_init()
to get the handle.
You continue by setting all the options you want in the upcoming transfer,
most important among them is the URL itself (you can't transfer anything
without a specified URL as you may have figured out yourself). You might want
to set some callbacks as well that will be called from the library when data
is available etc.
.B curl_easy_setopt()
is there for this.
When all is setup, you tell libcurl to perform the transfer using
.B curl_easy_perform().
It will then do the entire operation and won't return until it is done
(successfully or not).
After the transfer has been made, you can set new options and make another
transfer, or if you're done, cleanup the session by calling
.B curl_easy_cleanup().
If you want persistant connections, you don't cleanup immediately, but instead
run ahead and perform other transfers using the same handle. See the chapter
below for Persistant Connections.
There is also a series of other helpful functions to use. They are:
.RS
.TP 10
.B curl_version()
displays the libcurl version
.TP
.B curl_getdate()
converts a date string to time_t
.TP
.B curl_getenv()
portable environment variable reader
.TP
.B curl_easy_getinfo()
get information about a performed transfer
.TP
.B curl_formparse()
helps building a HTTP form POST
.TP
.B curl_formfree()
free a list built with curl_formparse()
.TP
.B curl_slist_append()
builds a linked list
.TP
.B curl_slist_free_all()
frees a whole curl_slist
.RE
.SH "LINKING WITH LIBCURL"
Starting with 7.7.2 (on unix-like machines), there's a tool named curl-config
that gets installed with the rest of the curl stuff when 'make install' is
performed.
curl-config is added to make it easier for applications to link with libcurl
and developers to learn about libcurl and how to use it.
Run 'curl-config --libs' to get the (additional) linker options you need to
link with the particular version of libcurl you've installed.
For details, see the curl-config.1 man page.
.SH "LIBCURL SYMBOL NAMES"
All public functions in the libcurl interface are prefixed with 'curl_' (with
a lowercase c). You can find other functions in the library source code, but
other prefixes indicate the functions are private and may change without
further notice in the next release.
Only use documented functions and functionality!
.SH "PORTABILITY"
libcurl works
.B exactly
the same, on any of the platforms it compiles and builds on.
There's only one caution, and that is the win32 platform that may(*) require
you to init the winsock stuff before you use the libcurl functions. Details on
this are noted on the curl_easy_init() man page.
(*) = it appears as if users of the cygwin environment get this done
automatically.
.SH "THREADS"
Never ever call curl-functions simultaneously using the same handle from
several threads. libcurl is thread-safe and can be used in any number of
threads, but you must use separate curl handles if you want to use libcurl in
more than one thread simultaneously.
.SH "PERSISTANT CONNECTIONS"
With libcurl 7.7, persistant connections were added. Persistant connections
means that libcurl can re-use the same connection for several transfers, if
the conditions are right.
libcurl will *always* attempt to use persistant connections. Whenever you use
curl_easy_perform(), libcurl will attempt to use an existing connection to do
the transfer, and if none exists it'll open a new one that will be subject
for re-use on a possible following call to curl_easy_perform().
To allow libcurl to take full advantage of persistant connections, you should
do as many of your file transfers as possible using the same curl
handle. When you call curl_easy_cleanup(), all the possibly open connections
held by libcurl will be closed and forgotten.
Note that the options set with curl_easy_setopt() will be used in on every
repeat curl_easy_perform() call
.SH "COMPATIBILITY WITH OLDER LIBCURLS"
Repeated curl_easy_perform() calls on the same handle were not supported in
pre-7.7 versions, and caused confusion and defined behaviour.

View File

@@ -146,6 +146,7 @@ typedef enum {
CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */ CURLE_TOO_MANY_REDIRECTS , /* 47 - catch endless re-direct loops */
CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */ CURLE_UNKNOWN_TELNET_OPTION, /* 48 - User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */ CURLE_TELNET_OPTION_SYNTAX , /* 49 - Malformed telnet option */
CURLE_ALREADY_COMPLETE, /* 50 - file to dowload is already complete */
CURL_LAST /* never use! */ CURL_LAST /* never use! */
} CURLcode; } CURLcode;
@@ -430,6 +431,10 @@ typedef enum {
phase. [Only works on unix-style/SIGALRM operating systems] */ phase. [Only works on unix-style/SIGALRM operating systems] */
CINIT(CONNECTTIMEOUT, LONG, 78), CINIT(CONNECTTIMEOUT, LONG, 78),
/* Function that will be called to store headers (instead of fwrite). The
* parameters will use fwrite() syntax, make sure to follow them. */
CINIT(HEADERFUNCTION, FUNCTIONPOINT, 79),
CURLOPT_LASTENTRY /* the last unusued */ CURLOPT_LASTENTRY /* the last unusued */
} CURLoption; } CURLoption;
@@ -481,8 +486,8 @@ char *curl_escape(char *string, int length);
char *curl_unescape(char *string, int length); char *curl_unescape(char *string, int length);
/* This is the version number */ /* This is the version number */
#define LIBCURL_VERSION "7.7.1" #define LIBCURL_VERSION "7.7.2"
#define LIBCURL_VERSION_NUM 0x070701 #define LIBCURL_VERSION_NUM 0x070702
/* linked-list structure for the CURLOPT_QUOTE option (and other) */ /* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist { struct curl_slist {

134
java/CurlGlue.java Normal file
View File

@@ -0,0 +1,134 @@
/**
* The curl class is a JNI wrapper for libcurl. Please bear with me, I'm no
* true java dude (yet). Improve what you think is bad and send me the
* updates!
* daniel@haxx.se
*
* This is meant as a raw, crude and low-level interface to libcurl. If you
* want fancy stuff, build upon this.
*/
public class CurlGlue
{
// start of imported generated list, make a new list with
// define2java.pl on demand
public static final int CURLOPT_NOTHING = 0;
public static final int CURLOPT_FILE = 10001;
public static final int CURLOPT_URL = 10002;
public static final int CURLOPT_PORT = 3;
public static final int CURLOPT_PROXY = 10004;
public static final int CURLOPT_USERPWD = 10005;
public static final int CURLOPT_PROXYUSERPWD = 10006;
public static final int CURLOPT_RANGE = 10007;
public static final int CURLOPT_INFILE = 10009;
public static final int CURLOPT_ERRORBUFFER = 10010;
public static final int CURLOPT_WRITEFUNCTION = 20011;
public static final int CURLOPT_READFUNCTION = 20012;
public static final int CURLOPT_TIMEOUT = 13;
public static final int CURLOPT_INFILESIZE = 14;
public static final int CURLOPT_POSTFIELDS = 10015;
public static final int CURLOPT_REFERER = 10016;
public static final int CURLOPT_FTPPORT = 10017;
public static final int CURLOPT_USERAGENT = 10018;
public static final int CURLOPT_LOW_SPEED_LIMIT = 19;
public static final int CURLOPT_LOW_SPEED_TIME = 20;
public static final int CURLOPT_RESUME_FROM = 21;
public static final int CURLOPT_COOKIE = 10022;
public static final int CURLOPT_HTTPHEADER = 10023;
public static final int CURLOPT_HTTPPOST = 10024;
public static final int CURLOPT_SSLCERT = 10025;
public static final int CURLOPT_SSLCERTPASSWD = 10026;
public static final int CURLOPT_CRLF = 27;
public static final int CURLOPT_QUOTE = 10028;
public static final int CURLOPT_WRITEHEADER = 10029;
public static final int CURLOPT_COOKIEFILE = 10031;
public static final int CURLOPT_SSLVERSION = 32;
public static final int CURLOPT_TIMECONDITION = 33;
public static final int CURLOPT_TIMEVALUE = 34;
public static final int CURLOPT_HTTPREQUEST = 10035;
public static final int CURLOPT_CUSTOMREQUEST = 10036;
public static final int CURLOPT_STDERR = 10037;
public static final int CURLOPT_POSTQUOTE = 10039;
public static final int CURLOPT_WRITEINFO = 10040;
public static final int CURLOPT_VERBOSE = 41;
public static final int CURLOPT_HEADER = 42;
public static final int CURLOPT_NOPROGRESS = 43;
public static final int CURLOPT_NOBODY = 44;
public static final int CURLOPT_FAILONERROR = 45;
public static final int CURLOPT_UPLOAD = 46;
public static final int CURLOPT_POST = 47;
public static final int CURLOPT_FTPLISTONLY = 48;
public static final int CURLOPT_FTPAPPEND = 50;
public static final int CURLOPT_NETRC = 51;
public static final int CURLOPT_FOLLOWLOCATION = 52;
public static final int CURLOPT_FTPASCII = 53;
public static final int CURLOPT_TRANSFERTEXT = 53;
public static final int CURLOPT_PUT = 54;
public static final int CURLOPT_MUTE = 55;
public static final int CURLOPT_PROGRESSFUNCTION = 20056;
public static final int CURLOPT_PROGRESSDATA = 10057;
public static final int CURLOPT_AUTOREFERER = 58;
public static final int CURLOPT_PROXYPORT = 59;
public static final int CURLOPT_POSTFIELDSIZE = 60;
public static final int CURLOPT_HTTPPROXYTUNNEL = 61;
public static final int CURLOPT_INTERFACE = 10062;
public static final int CURLOPT_KRB4LEVEL = 10063;
public static final int CURLOPT_SSL_VERIFYPEER = 64;
public static final int CURLOPT_CAINFO = 10065;
public static final int CURLOPT_PASSWDFUNCTION = 20066;
public static final int CURLOPT_PASSWDDATA = 10067;
public static final int CURLOPT_MAXREDIRS = 68;
public static final int CURLOPT_FILETIME = 10069;
public static final int CURLOPT_TELNETOPTIONS = 10070;
public static final int CURLOPT_MAXCONNECTS = 71;
public static final int CURLOPT_CLOSEPOLICY = 72;
public static final int CURLOPT_CLOSEFUNCTION = 20073;
public static final int CURLOPT_FRESH_CONNECT = 74;
public static final int CURLOPT_FORBID_REUSE = 75;
public static final int CURLOPT_RANDOM_FILE = 10076;
public static final int CURLOPT_EGDSOCKET = 10077;
public static final int CURLOPT_CONNECTTIMEOUT = 78;
public static final int CURLOPT_HEADERFUNCTION = 20079;
// end of generated list
public CurlGlue() {
javacurl_handle = jni_init();
}
public void finalize() {
jni_cleanup(javacurl_handle);
}
private int javacurl_handle;
/* constructor and destructor for the libcurl handle */
private native int jni_init();
private native void jni_cleanup(int javacurl_handle);
private native synchronized int jni_perform(int javacurl_handle);
// Instead of varargs, we have different functions for each
// kind of type setopt() can take
private native int jni_setopt(int libcurl, int option, String value);
private native int jni_setopt(int libcurl, int option, int value);
private native int jni_setopt(int libcurl, int option, CurlWrite value);
public native int getinfo();
public int perform() {
return jni_perform(javacurl_handle);
}
public int setopt(int option, int value) {
return jni_setopt(javacurl_handle, option, value);
}
public int setopt(int option, String value) {
return jni_setopt(javacurl_handle, option, value);
}
public int setopt(int option, CurlWrite value) {
return jni_setopt(javacurl_handle, option, value);
}
static {
System.loadLibrary("javacurl");
}
}

9
java/CurlWrite.java Normal file
View File

@@ -0,0 +1,9 @@
public interface CurlWrite
{
/**
* handleString gets called by libcurl on each chunk of data
* we receive from the remote server
*/
public int handleString(byte s[]);
}

35
java/Makefile Normal file
View File

@@ -0,0 +1,35 @@
TARGET = libjavacurl.so
OBJS = javacurl.o
CC = gcc
CFLAGS = -c
CPPFLAGS = -I/usr/j2se/include -I/usr/local/include -I/usr/j2se/include/solaris
# Linux might use -shared -Wl,-soname,libnative.so instead of -G
LDFLAGS = -G -lcurl -ldl -L/usr/local/ssl/lib -lssl -lcrypto
all: CurlGlue.h CurlGlue.class javacurl.o $(TARGET) test.class
test:
java test
javacurl.o: javacurl.c CurlGlue.h
$(CC) $(CPPFLAGS) $(CFLAGS) $<
CurlGlue.h: CurlGlue.java CurlGlue.class
javah CurlGlue
touch CurlGlue.h
test.class: CurlGlue.class javacurl.o
javac test.java
CurlGlue.class: CurlGlue.java
javac $<
$(TARGET): $(OBJS)
$(CC) -o $(TARGET) $(LDFLAGS) $(OBJS)
clean:
rm -f javacurl.o CurlGlue.h CurlGlue.class

13
java/README Normal file
View File

@@ -0,0 +1,13 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
Java Interface
This is very much work in progress and it does not work.
The interface is not set yet, bring your suggestions!
Feel free to grab the source files in here and help out!

22
java/define2java.pl Executable file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/perl
open(GCC, "gcc -E ../include/curl/curl.h|");
while(<GCC>) {
if($_ =~ /(CURLOPT_(.*)) += (.*)/) {
$var= $1;
$expr = $3;
$f=$3;
if($expr =~ / *(\d+) *\+ *(\d+)/) {
$expr = $1+$2;
}
# nah, keep the CURL prefix to make them look like other
# languages' defines
# $var =~ s/^CURL//g;
print " public static final int $var = $expr;\n";
}
}
close(GCC);

196
java/javacurl.c Normal file
View File

@@ -0,0 +1,196 @@
#include <curl/curl.h> /* libcurl header */
#include "CurlGlue.h" /* the JNI-generated glue header file */
/*
* This is a private struct allocated for every 'CurlGlue' object.
*/
struct javacurl {
void *libcurl;
void *whatever;
struct writecallback {
jmethodID mid;
JNIEnv *java;
jclass cls; /* global reference */
jobject object;
} write;
};
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1init(JNIEnv *java,
jobject myself)
{
void *libhandle;
struct javacurl *jcurl=NULL;
libhandle = curl_easy_init();
if(libhandle) {
jcurl=(struct javacurl *)malloc(sizeof(struct javacurl));
if(jcurl) {
memset(jcurl, 0, sizeof(struct javacurl));
jcurl->libcurl = libhandle;
}
else {
curl_easy_cleanup(libhandle);
return (jint)0;
}
}
return (jint) jcurl; /* nasty typecast */
}
JNIEXPORT void JNICALL Java_CurlGlue_jni_1cleanup(JNIEnv *java,
jobject myself,
jint jcurl)
{
struct javacurl *curl = (struct javacurl*)jcurl;
if(curl->write.cls) {
/* a global reference we must delete */
(*java)->DeleteGlobalRef(java, curl->write.cls);
(*java)->DeleteGlobalRef(java, curl->write.object);
}
curl_easy_cleanup(curl->libcurl); /* cleanup libcurl stuff */
free((void *)curl); /* free the struct too */
}
/*
* setopt() int + string
*/
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILjava_lang_String_2
(JNIEnv *java, jobject myself, jint jcurl, jint option, jstring value)
{
/* get the actual string C-style */
const char *str = (*java)->GetStringUTFChars(java, value, 0);
void *handle = (void *)((struct javacurl*)jcurl)->libcurl;
puts("setopt int + string");
return (jint)curl_easy_setopt(handle, (CURLoption)option, str);
}
/*
* setopt() int + int
*/
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__III
(JNIEnv *java, jobject myself, jint jcurl, jint option, jint value)
{
void *handle = (void *)((struct javacurl*)jcurl)->libcurl;
CURLoption opt = (CURLoption)option;
puts("setopt int + int");
switch(opt) {
case CURLOPT_FILE:
/* silently ignored, we don't need user-specified callback data when
we have an object, and besides the CURLOPT_FILE is not exported
to the java interface */
return 0;
}
return (jint)curl_easy_setopt(handle, (CURLoption)option, value);
}
static int javacurl_write_callback(void *ptr,
size_t size,
size_t nmemb,
FILE *stream)
{
struct javacurl *curl = (struct javacurl *)stream;
size_t realsize = size * nmemb;
JNIEnv *java = curl->write.java;
jbyteArray jb=NULL;
int ret=0;
fprintf(stderr, "%d bytes data received in callback:\n"
"ptr=%p, java=%p cls=%p\n",
realsize, curl, java, curl->write.cls);
jb=(*java)->NewByteArray(java, realsize);
(*java)->SetByteArrayRegion(java, jb, 0,
realsize, (jbyte *)ptr);
fprintf(stderr, "created byte-array\n");
ret = (*java)->CallIntMethod(java,
curl->write.object,
curl->write.mid,
jb);
fprintf(stderr, "java-method returned %d\n", ret);
return realsize;
}
/*
* setopt() int + object
*/
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1setopt__IILCurlWrite_2
(JNIEnv *java, jobject myself, jint jcurl, jint option, jobject object)
{
jclass cls_local = (*java)->GetObjectClass(java, object);
jmethodID mid;
struct javacurl *curl = (struct javacurl *)jcurl;
jclass cls;
jobject obj_global;
switch(option) {
case CURLOPT_WRITEFUNCTION:
/* this makes a reference that'll be alive until we kill it! */
cls = (*java)->NewGlobalRef(java, cls_local);
printf("setopt int + object, option = %d cls= %p\n",
option, cls);
if(!cls) {
puts("couldn't make local reference global");
return 0;
}
/* this is the write callback */
mid = (*java)->GetMethodID(java, cls, "handleString", "([B)I");
if(!mid) {
puts("no callback method found");
return 0;
}
obj_global = (*java)->NewGlobalRef(java, object);
curl->write.mid = mid;
curl->write.cls = cls;
curl->write.object = obj_global;
/*curl->write.java = java; stored on perform */
fprintf(stderr, "setopt write callback and write file pointer %p, java = %p\n",
curl, java);
curl_easy_setopt(curl->libcurl, CURLOPT_WRITEFUNCTION,
javacurl_write_callback);
curl_easy_setopt(curl->libcurl, CURLOPT_FILE,
curl);
break;
}
return 0;
}
JNIEXPORT jint JNICALL Java_CurlGlue_getinfo
(JNIEnv *java, jobject value)
{
return 0;
}
JNIEXPORT jint JNICALL Java_CurlGlue_jni_1perform
(JNIEnv *java, jobject myself, jint jcurl)
{
struct javacurl *curl=(struct javacurl*)jcurl;
curl->write.java = java;
return (jint)curl_easy_perform(curl->libcurl);
}

27
java/test.java Normal file
View File

@@ -0,0 +1,27 @@
import CurlGlue;
import CurlWrite;
class test implements CurlWrite {
public int handleString(byte s[])
{
/* output everything */
System.out.println("IIIIIIIIIII -------------- OOOOOOOOOOOOOOOOOOO");
try {
System.out.write(s);
}
catch (java.io.IOException moo) {
// nothing
}
return 0;
}
public static void main(String[] args)
{
CurlGlue cg = new CurlGlue();
test cw = new test();
cg.setopt(CurlGlue.CURLOPT_URL, "http://www.contactor.se/");
cg.setopt(CurlGlue.CURLOPT_WRITEFUNCTION, cw);
cg.perform();
}
}

View File

@@ -14,7 +14,7 @@ RM = del
LIB = tlib LIB = tlib
TOPDIR = .. TOPDIR = ..
CURNTDIR = . CURNTDIR = .
CXXFLAGS = -5 -O2 -w-aus -w-ccc -w-csu -w-par -w-pia -w-rch -w-inl -w-ngu -w-pro CXXFLAGS = -5 -O2 -w-aus -w-ccc -w-csu -w-par -w-pia -w-rch -w-inl -w-ngu -w-pro -tWM
DEFINES = -DLIBCURL_BIGENDIAN=0 -DNDEBUG -DWIN32 -DCONSOLE -DMBCS DEFINES = -DLIBCURL_BIGENDIAN=0 -DNDEBUG -DWIN32 -DCONSOLE -DMBCS
INCDIRS = -I$(CURNTDIR);$(TOPDIR)/include/ INCDIRS = -I$(CURNTDIR);$(TOPDIR)/include/
@@ -34,6 +34,7 @@ SOURCES = \
formdata.c \ formdata.c \
ftp.c \ ftp.c \
http.c \ http.c \
http_chunks.c \
ldap.c \ ldap.c \
dict.c \ dict.c \
telnet.c \ telnet.c \
@@ -64,11 +65,11 @@ OBJECTS = $(SOURCES:.c=.obj)
all: $(LIBCURLLIB) all: $(LIBCURLLIB)
clean: clean:
$(RM) $(LIBCURLLIB) -$(RM) $(LIBCURLLIB)
$(RM) *.obj -$(RM) *.obj
$(LIBCURLLIB): $(LINKLIB) $(OBJECTS) Makefile.b32.resp $(LIBCURLLIB): $(LINKLIB) $(OBJECTS) Makefile.b32.resp
$(RM) $(LIBCURLLIB) -$(RM) $(LIBCURLLIB)
$(LIB) $(LIBCURLLIB) @Makefile.b32.resp $(LIB) $(LIBCURLLIB) @Makefile.b32.resp

View File

@@ -5,6 +5,7 @@
+formdata.obj & +formdata.obj &
+ftp.obj & +ftp.obj &
+http.obj & +http.obj &
+http_chunks.obj &
+ldap.obj & +ldap.obj &
+dict.obj & +dict.obj &
+telnet.obj & +telnet.obj &

View File

@@ -5,10 +5,11 @@
## ##
## Comments to: Troy Engel <tengel@sonic.net> ## Comments to: Troy Engel <tengel@sonic.net>
## Updated by: Craig Davison <cd@securityfocus.com> ## Updated by: Craig Davison <cd@securityfocus.com>
## Updated by: SM <sm@technologist.com>
PROGRAM_NAME = libcurl.lib PROGRAM_NAME = libcurl.lib
PROGRAM_NAME_DEBUG = libcurld.lib PROGRAM_NAME_DEBUG = libcurld.lib
OPENSSL_PATH = ../../openssl-0.9.6 #OPENSSL_PATH = ../../openssl-0.9.6a
######################################################## ########################################################
## Nothing more to do below this line! ## Nothing more to do below this line!
@@ -22,7 +23,7 @@ CCD = cl.exe /MDd /Gm /ZI /Od /D "_DEBUG" /GZ
LINKD = link.exe -lib /out:$(PROGRAM_NAME_DEBUG) LINKD = link.exe -lib /out:$(PROGRAM_NAME_DEBUG)
## SSL Release ## SSL Release
CCRS = cl.exe /MD /O2 /D "NDEBUG" /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/include" /I "$(OPENSSL_PATH)/include/openssl" CCRS = cl.exe /MD /O2 /D "NDEBUG" /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
LINKRS = link.exe -lib /out:$(PROGRAM_NAME) /LIBPATH:$(OPENSSL_PATH)/out32dll LINKRS = link.exe -lib /out:$(PROGRAM_NAME) /LIBPATH:$(OPENSSL_PATH)/out32dll
CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS" CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS"
@@ -299,6 +300,8 @@ formdatars.obj: formdata.c
$(CCRS) $(CFLAGS) formdata.c $(CCRS) $(CFLAGS) formdata.c
ftprs.obj: ftp.c ftprs.obj: ftp.c
$(CCRS) $(CFLAGS) ftp.c $(CCRS) $(CFLAGS) ftp.c
httprs.obj: http.c
$(CCR) $(CFLAGS) http.c
http_chunksrs.obj: http_chunks.c http_chunksrs.obj: http_chunks.c
$(CCRS) $(CFLAGS) http_chunks.c $(CCRS) $(CFLAGS) http_chunks.c
ldaprs.obj: ldap.c ldaprs.obj: ldap.c

View File

@@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "C:\jdk1.3.0_01\include" /I "C:\jdk1.3.0_01\include\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG" # ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -53,7 +53,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /machine:I386 /out:"Release/curl.dll" # ADD LINK32 kernel32.lib wsock32.lib /nologo /dll /machine:I386 /out:"Release/curl.dll"
!ELSEIF "$(CFG)" == "curllib - Win32 Debug" !ELSEIF "$(CFG)" == "curllib - Win32 Debug"
@@ -69,7 +69,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0 # PROP Ignore_Export_Lib 0
# PROP Target_Dir "" # PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\jdk1.3.0_01\include" /I "C:\jdk1.3.0_01\include\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD BASE RSC /l 0x409 /d "_DEBUG"
@@ -79,7 +79,8 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo # ADD BSC32 /nologo
LINK32=link.exe LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"Debug/curl.dll" /pdbtype:sept # ADD LINK32 kernel32.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"Debug/curl.dll" /pdbtype:sept
# SUBTRACT LINK32 /nodefaultlib
!ENDIF !ENDIF
@@ -112,14 +113,6 @@ SOURCE=.\easy.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\easyswig.c
# End Source File
# Begin Source File
SOURCE=.\easyswig_wrap.c
# End Source File
# Begin Source File
SOURCE=.\escape.c SOURCE=.\escape.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -160,6 +153,10 @@ SOURCE=.\http.c
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\http_chunks.c
# End Source File
# Begin Source File
SOURCE=.\if2ip.c SOURCE=.\if2ip.c
# End Source File # End Source File
# Begin Source File # Begin Source File
@@ -288,6 +285,10 @@ SOURCE=.\http.h
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=.\http_chunks.h
# End Source File
# Begin Source File
SOURCE=.\if2ip.h SOURCE=.\if2ip.h
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@@ -45,6 +45,7 @@ char *curl_escape(char *string, int length)
int newlen = alloc; int newlen = alloc;
int index=0; int index=0;
length = alloc-1;
while(length--) { while(length--) {
in = *string; in = *string;
if(' ' == in) if(' ' == in)

View File

@@ -183,11 +183,11 @@ CURLcode Curl_file(struct connectdata *conn)
return res; return res;
now = Curl_tvnow(); now = Curl_tvnow();
if(Curl_pgrsUpdate(data)) if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK; res = CURLE_ABORTED_BY_CALLBACK;
} }
now = Curl_tvnow(); now = Curl_tvnow();
if(Curl_pgrsUpdate(data)) if(Curl_pgrsUpdate(conn))
res = CURLE_ABORTED_BY_CALLBACK; res = CURLE_ABORTED_BY_CALLBACK;
close(fd); close(fd);

View File

@@ -371,6 +371,7 @@ char *Curl_FormBoundary(void)
void Curl_FormFree(struct FormData *form) void Curl_FormFree(struct FormData *form)
{ {
struct FormData *next; struct FormData *next;
do { do {
next=form->next; /* the following form line */ next=form->next; /* the following form line */
free(form->line); /* free the line */ free(form->line); /* free the line */
@@ -383,6 +384,11 @@ void Curl_FormFree(struct FormData *form)
void curl_formfree(struct HttpPost *form) void curl_formfree(struct HttpPost *form)
{ {
struct HttpPost *next; struct HttpPost *next;
if(!form)
/* no form to free, just get out of this */
return;
do { do {
next=form->next; /* the following form line */ next=form->next; /* the following form line */

View File

@@ -1272,7 +1272,7 @@ again:;
CURLE_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
if(data->resume_from) { if(conn->resume_from) {
/* we're about to continue the uploading of a file */ /* we're about to continue the uploading of a file */
/* 1. get already existing file's size. We use the SIZE /* 1. get already existing file's size. We use the SIZE
command for this which may not exist in the server! command for this which may not exist in the server!
@@ -1286,7 +1286,7 @@ again:;
/* 4. lower the infilesize counter */ /* 4. lower the infilesize counter */
/* => transfer as usual */ /* => transfer as usual */
if(data->resume_from < 0 ) { if(conn->resume_from < 0 ) {
/* we could've got a specified offset from the command line, /* we could've got a specified offset from the command line,
but now we know we didn't */ but now we know we didn't */
@@ -1302,10 +1302,10 @@ again:;
} }
/* get the size from the ascii string: */ /* get the size from the ascii string: */
data->resume_from = atoi(buf+4); conn->resume_from = atoi(buf+4);
} }
if(data->resume_from) { if(conn->resume_from) {
/* do we still game? */ /* do we still game? */
int passed=0; int passed=0;
/* enable append instead */ /* enable append instead */
@@ -1315,7 +1315,7 @@ again:;
input. If we knew it was a proper file we could've just input. If we knew it was a proper file we could've just
fseek()ed but we only have a stream here */ fseek()ed but we only have a stream here */
do { do {
int readthisamountnow = (data->resume_from - passed); int readthisamountnow = (conn->resume_from - passed);
int actuallyread; int actuallyread;
if(readthisamountnow > BUFSIZE) if(readthisamountnow > BUFSIZE)
@@ -1331,11 +1331,11 @@ again:;
return CURLE_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
} }
while(passed != data->resume_from); while(passed != conn->resume_from);
/* now, decrease the size of the read */ /* now, decrease the size of the read */
if(data->infilesize>0) { if(data->infilesize>0) {
data->infilesize -= data->resume_from; data->infilesize -= conn->resume_from;
if(data->infilesize <= 0) { if(data->infilesize <= 0) {
failf(data, "File already completely uploaded\n"); failf(data, "File already completely uploaded\n");
@@ -1387,13 +1387,13 @@ again:;
bool dirlist=FALSE; bool dirlist=FALSE;
long downloadsize=-1; long downloadsize=-1;
if(data->bits.set_range && data->range) { if(conn->bits.use_range && conn->range) {
long from, to; long from, to;
int totalsize=-1; int totalsize=-1;
char *ptr; char *ptr;
char *ptr2; char *ptr2;
from=strtol(data->range, &ptr, 0); from=strtol(conn->range, &ptr, 0);
while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-'))) while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))
ptr++; ptr++;
to=strtol(ptr, &ptr2, 0); to=strtol(ptr, &ptr2, 0);
@@ -1403,22 +1403,23 @@ again:;
} }
if((-1 == to) && (from>=0)) { if((-1 == to) && (from>=0)) {
/* X - */ /* X - */
data->resume_from = from; conn->resume_from = from;
infof(data, "FTP RANGE %d to end of file\n", from); infof(data, "FTP RANGE %d to end of file\n", from);
} }
else if(from < 0) { else if(from < 0) {
/* -Y */ /* -Y */
totalsize = -from; totalsize = -from;
conn->maxdownload = -from; conn->maxdownload = -from;
data->resume_from = from; conn->resume_from = from;
infof(data, "FTP RANGE the last %d bytes\n", totalsize); infof(data, "FTP RANGE the last %d bytes\n", totalsize);
} }
else { else {
/* X-Y */ /* X-Y */
totalsize = to-from; totalsize = to-from;
conn->maxdownload = totalsize+1; /* include the last mentioned byte */ conn->maxdownload = totalsize+1; /* include the last mentioned byte */
data->resume_from = from; conn->resume_from = from;
infof(data, "FTP RANGE from %d getting %d bytes\n", from, conn->maxdownload); infof(data, "FTP RANGE from %d getting %d bytes\n", from,
conn->maxdownload);
} }
infof(data, "range-download from %d to %d, totally %d bytes\n", infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize); from, to, totalsize);
@@ -1466,7 +1467,7 @@ again:;
CURLE_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
if(data->resume_from) { if(conn->resume_from) {
/* Daniel: (August 4, 1999) /* Daniel: (August 4, 1999)
* *
@@ -1491,34 +1492,39 @@ again:;
int foundsize=atoi(buf+4); int foundsize=atoi(buf+4);
/* We got a file size report, so we check that there actually is a /* We got a file size report, so we check that there actually is a
part of the file left to get, or else we go home. */ part of the file left to get, or else we go home. */
if(data->resume_from< 0) { if(conn->resume_from< 0) {
/* We're supposed to download the last abs(from) bytes */ /* We're supposed to download the last abs(from) bytes */
if(foundsize < -data->resume_from) { if(foundsize < -conn->resume_from) {
failf(data, "Offset (%d) was beyond file size (%d)", failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, foundsize); conn->resume_from, foundsize);
return CURLE_FTP_BAD_DOWNLOAD_RESUME; return CURLE_FTP_BAD_DOWNLOAD_RESUME;
} }
/* convert to size to download */ /* convert to size to download */
downloadsize = -data->resume_from; downloadsize = -conn->resume_from;
/* download from where? */ /* download from where? */
data->resume_from = foundsize - downloadsize; conn->resume_from = foundsize - downloadsize;
} }
else { else {
if(foundsize <= data->resume_from) { if(foundsize < conn->resume_from) {
failf(data, "Offset (%d) was beyond file size (%d)", failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, foundsize); conn->resume_from, foundsize);
return CURLE_FTP_BAD_DOWNLOAD_RESUME; return CURLE_FTP_BAD_DOWNLOAD_RESUME;
} }
/* Now store the number of bytes we are expected to download */ /* Now store the number of bytes we are expected to download */
downloadsize = foundsize-data->resume_from; downloadsize = foundsize-conn->resume_from;
} }
} }
if (downloadsize == 0) {
failf(data, "File already complete");
return CURLE_ALREADY_COMPLETE;
}
/* Set resume file transfer offset */ /* Set resume file transfer offset */
infof(data, "Instructs server to resume from offset %d\n", infof(data, "Instructs server to resume from offset %d\n",
data->resume_from); conn->resume_from);
ftpsendf(conn->firstsocket, conn, "REST %d", data->resume_from); ftpsendf(conn->firstsocket, conn, "REST %d", conn->resume_from);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)

View File

@@ -497,7 +497,7 @@ CURLcode Curl_http(struct connectdata *conn)
if((data->bits.http_post || if((data->bits.http_post ||
data->bits.http_formpost || data->bits.http_formpost ||
data->bits.http_put) && data->bits.http_put) &&
data->resume_from) { conn->resume_from) {
/********************************************************************** /**********************************************************************
* Resuming upload in HTTP means that we PUT or POST and that we have * Resuming upload in HTTP means that we PUT or POST and that we have
* got a resume_from value set. The resume value has already created * got a resume_from value set. The resume value has already created
@@ -506,15 +506,15 @@ CURLcode Curl_http(struct connectdata *conn)
* file size before we continue this venture in the dark lands of HTTP. * file size before we continue this venture in the dark lands of HTTP.
*********************************************************************/ *********************************************************************/
if(data->resume_from < 0 ) { if(conn->resume_from < 0 ) {
/* /*
* This is meant to get the size of the present remote-file by itself. * This is meant to get the size of the present remote-file by itself.
* We don't support this now. Bail out! * We don't support this now. Bail out!
*/ */
data->resume_from = 0; conn->resume_from = 0;
} }
if(data->resume_from) { if(conn->resume_from) {
/* do we still game? */ /* do we still game? */
int passed=0; int passed=0;
@@ -522,7 +522,7 @@ CURLcode Curl_http(struct connectdata *conn)
input. If we knew it was a proper file we could've just input. If we knew it was a proper file we could've just
fseek()ed but we only have a stream here */ fseek()ed but we only have a stream here */
do { do {
int readthisamountnow = (data->resume_from - passed); int readthisamountnow = (conn->resume_from - passed);
int actuallyread; int actuallyread;
if(readthisamountnow > BUFSIZE) if(readthisamountnow > BUFSIZE)
@@ -537,11 +537,11 @@ CURLcode Curl_http(struct connectdata *conn)
passed); passed);
return CURLE_READ_ERROR; return CURLE_READ_ERROR;
} }
} while(passed != data->resume_from); /* loop until done */ } while(passed != conn->resume_from); /* loop until done */
/* now, decrease the size of the read */ /* now, decrease the size of the read */
if(data->infilesize>0) { if(data->infilesize>0) {
data->infilesize -= data->resume_from; data->infilesize -= conn->resume_from;
if(data->infilesize <= 0) { if(data->infilesize <= 0) {
failf(data, "File already completely uploaded\n"); failf(data, "File already completely uploaded\n");
@@ -551,7 +551,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* we've passed, proceed as normal */ /* we've passed, proceed as normal */
} }
} }
if(data->bits.set_range) { if(conn->bits.use_range) {
/* /*
* A range is selected. We use different headers whether we're downloading * A range is selected. We use different headers whether we're downloading
* or uploading and we always let customized headers override our internal * or uploading and we always let customized headers override our internal
@@ -559,23 +559,23 @@ CURLcode Curl_http(struct connectdata *conn)
*/ */
if((data->httpreq == HTTPREQ_GET) && if((data->httpreq == HTTPREQ_GET) &&
!checkheaders(data, "Range:")) { !checkheaders(data, "Range:")) {
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->range); conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", conn->range);
} }
else if((data->httpreq != HTTPREQ_GET) && else if((data->httpreq != HTTPREQ_GET) &&
!checkheaders(data, "Content-Range:")) { !checkheaders(data, "Content-Range:")) {
if(data->resume_from) { if(conn->resume_from) {
/* This is because "resume" was selected */ /* This is because "resume" was selected */
long total_expected_size= data->resume_from + data->infilesize; long total_expected_size= conn->resume_from + data->infilesize;
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n", conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n",
data->range, total_expected_size-1, conn->range, total_expected_size-1,
total_expected_size); total_expected_size);
} }
else { else {
/* Range was selected and then we just pass the incoming range and /* Range was selected and then we just pass the incoming range and
append total size */ append total size */
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n", conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n",
data->range, data->infilesize); conn->range, data->infilesize);
} }
} }
} }
@@ -610,7 +610,7 @@ CURLcode Curl_http(struct connectdata *conn)
conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"", conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
(conn->bits.user_passwd && conn->allocptr.userpwd)? (conn->bits.user_passwd && conn->allocptr.userpwd)?
conn->allocptr.userpwd:"", conn->allocptr.userpwd:"",
(data->bits.set_range && conn->allocptr.rangeline)? (conn->bits.use_range && conn->allocptr.rangeline)?
conn->allocptr.rangeline:"", conn->allocptr.rangeline:"",
(data->useragent && *data->useragent && conn->allocptr.uagent)? (data->useragent && *data->useragent && conn->allocptr.uagent)?
conn->allocptr.uagent:"", conn->allocptr.uagent:"",
@@ -646,12 +646,21 @@ CURLcode Curl_http(struct connectdata *conn)
if(data->timecondition) { if(data->timecondition) {
struct tm *thistime; struct tm *thistime;
/* Phil Karn (Fri, 13 Apr 2001) pointed out that the If-Modified-Since
* header family should have their times set in GMT as RFC2616 defines:
* "All HTTP date/time stamps MUST be represented in Greenwich Mean Time
* (GMT), without exception. For the purposes of HTTP, GMT is exactly
* equal to UTC (Coordinated Universal Time)." (see page 20 of RFC2616).
*/
#ifdef HAVE_LOCALTIME_R #ifdef HAVE_LOCALTIME_R
/* thread-safe version */ /* thread-safe version */
/* We assume that the presense of localtime_r() proves the presense
of gmtime_r() which is a bit ugly but might work */
struct tm keeptime; struct tm keeptime;
thistime = (struct tm *)localtime_r(&data->timevalue, &keeptime); thistime = (struct tm *)gmtime_r(&data->timevalue, &keeptime);
#else #else
thistime = localtime(&data->timevalue); thistime = gmtime(&data->timevalue);
#endif #endif
if(NULL == thistime) { if(NULL == thistime) {
failf(data, "localtime() failed!"); failf(data, "localtime() failed!");

View File

@@ -91,11 +91,12 @@ static char *max5data(double bytes, char *max5)
*/ */
void Curl_pgrsDone(struct UrlData *data) void Curl_pgrsDone(struct connectdata *conn)
{ {
struct UrlData *data = conn->data;
if(!(data->progress.flags & PGRS_HIDE)) { if(!(data->progress.flags & PGRS_HIDE)) {
data->progress.lastshow=0; data->progress.lastshow=0;
Curl_pgrsUpdate(data); /* the final (forced) update */ Curl_pgrsUpdate(conn); /* the final (forced) update */
fprintf(data->err, "\n"); fprintf(data->err, "\n");
} }
} }
@@ -134,6 +135,7 @@ void Curl_pgrsTime(struct UrlData *data, timerid timer)
void Curl_pgrsStartNow(struct UrlData *data) void Curl_pgrsStartNow(struct UrlData *data)
{ {
data->progress.speeder_c = 0; /* reset the progress meter display */
data->progress.start = Curl_tvnow(); data->progress.start = Curl_tvnow();
} }
@@ -171,7 +173,7 @@ void Curl_pgrsSetUploadSize(struct UrlData *data, double size)
*/ */
int Curl_pgrsUpdate(struct UrlData *data) int Curl_pgrsUpdate(struct connectdata *conn)
{ {
struct timeval now; struct timeval now;
int result; int result;
@@ -184,6 +186,8 @@ int Curl_pgrsUpdate(struct UrlData *data)
double total_transfer; double total_transfer;
double total_expected_transfer; double total_expected_transfer;
struct UrlData *data = conn->data;
int nowindex = data->progress.speeder_c% CURR_TIME; int nowindex = data->progress.speeder_c% CURR_TIME;
int checkindex; int checkindex;
int count; int count;
@@ -197,15 +201,16 @@ int Curl_pgrsUpdate(struct UrlData *data)
double total_estimate; double total_estimate;
if(data->progress.flags & PGRS_HIDE) if(data->progress.flags & PGRS_HIDE)
; /* We do enter this function even if we don't wanna see anything, since ; /* We do enter this function even if we don't wanna see anything, since
this is were lots of the calculations are being made that will be used this is were lots of the calculations are being made that will be used
even when not displayed! */ even when not displayed! */
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) { else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if (!data->progress.callback) { if (!data->progress.callback) {
if(data->resume_from) if(conn->resume_from)
fprintf(data->err, "** Resuming transfer from byte position %d\n", fprintf(data->err, "** Resuming transfer from byte position %d\n",
data->resume_from); conn->resume_from);
fprintf(data->err, fprintf(data->err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n" " %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n"); " Dload Upload Total Current Left Speed\n");

View File

@@ -36,13 +36,13 @@ typedef enum {
TIMER_LAST /* must be last */ TIMER_LAST /* must be last */
} timerid; } timerid;
void Curl_pgrsDone(struct UrlData *data); void Curl_pgrsDone(struct connectdata *);
void Curl_pgrsStartNow(struct UrlData *data); void Curl_pgrsStartNow(struct UrlData *data);
void Curl_pgrsSetDownloadSize(struct UrlData *data, double size); void Curl_pgrsSetDownloadSize(struct UrlData *data, double size);
void Curl_pgrsSetUploadSize(struct UrlData *data, double size); void Curl_pgrsSetUploadSize(struct UrlData *data, double size);
void Curl_pgrsSetDownloadCounter(struct UrlData *data, double size); void Curl_pgrsSetDownloadCounter(struct UrlData *data, double size);
void Curl_pgrsSetUploadCounter(struct UrlData *data, double size); void Curl_pgrsSetUploadCounter(struct UrlData *data, double size);
int Curl_pgrsUpdate(struct UrlData *data); int Curl_pgrsUpdate(struct connectdata *);
void Curl_pgrsTime(struct UrlData *data, timerid timer); void Curl_pgrsTime(struct UrlData *data, timerid timer);

View File

@@ -236,7 +236,14 @@ CURLcode Curl_client_write(struct UrlData *data,
} }
} }
if((type & CLIENTWRITE_HEADER) && data->writeheader) { if((type & CLIENTWRITE_HEADER) && data->writeheader) {
wrote = data->fwrite(ptr, 1, len, data->writeheader); /*
* Write headers to the same callback or to the especially setup
* header callback function (added after version 7.7.1).
*/
curl_write_callback writeit=
data->fwrite_header?data->fwrite_header:data->fwrite;
wrote = writeit(ptr, 1, len, data->writeheader);
if(wrote != len) { if(wrote != len) {
failf (data, "Failed writing header"); failf (data, "Failed writing header");
return CURLE_WRITE_ERROR; return CURLE_WRITE_ERROR;

View File

@@ -32,4 +32,8 @@ int curl_strnequal(const char *first, const char *second, size_t max);
#define strequal(a,b) curl_strequal(a,b) #define strequal(a,b) curl_strequal(a,b)
#define strnequal(a,b,c) curl_strnequal(a,b,c) #define strnequal(a,b,c) curl_strnequal(a,b,c)
#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t siz);
#endif
#endif #endif

View File

@@ -465,7 +465,7 @@ Transfer(struct connectdata *c_conn)
/* This second format was added August 1st 2000 by Igor /* This second format was added August 1st 2000 by Igor
Khristophorov since Sun's webserver JavaWebServer/1.1.1 Khristophorov since Sun's webserver JavaWebServer/1.1.1
obviously sends the header this way! :-( */ obviously sends the header this way! :-( */
if (data->resume_from == offset) { if (conn->resume_from == offset) {
/* we asked for a resume and we got it */ /* we asked for a resume and we got it */
content_range = TRUE; content_range = TRUE;
} }
@@ -547,7 +547,7 @@ Transfer(struct connectdata *c_conn)
infof (data, "Follow to new URL: %s\n", conn->newurl); infof (data, "Follow to new URL: %s\n", conn->newurl);
return CURLE_OK; return CURLE_OK;
} }
else if (data->resume_from && else if (conn->resume_from &&
!content_range && !content_range &&
(data->httpreq==HTTPREQ_GET)) { (data->httpreq==HTTPREQ_GET)) {
/* we wanted to resume a download, although the server /* we wanted to resume a download, although the server
@@ -557,7 +557,7 @@ Transfer(struct connectdata *c_conn)
"byte ranges. Cannot resume."); "byte ranges. Cannot resume.");
return CURLE_HTTP_RANGE_ERROR; return CURLE_HTTP_RANGE_ERROR;
} }
else if(data->timecondition && !data->range) { else if(data->timecondition && !conn->range) {
/* A time condition has been set AND no ranges have been /* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of requested. This seems to be what chapter 13.3.4 of
RFC 2616 defines to be the correct action for a RFC 2616 defines to be the correct action for a
@@ -696,7 +696,7 @@ Transfer(struct connectdata *c_conn)
} }
now = Curl_tvnow(); now = Curl_tvnow();
if(Curl_pgrsUpdate(data)) if(Curl_pgrsUpdate(conn))
urg = CURLE_ABORTED_BY_CALLBACK; urg = CURLE_ABORTED_BY_CALLBACK;
else else
urg = Curl_speedcheck (data, now); urg = Curl_speedcheck (data, now);
@@ -730,7 +730,7 @@ Transfer(struct connectdata *c_conn)
conn->proto.http->chunk.datasize); conn->proto.http->chunk.datasize);
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
if(Curl_pgrsUpdate(data)) if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK; return CURLE_ABORTED_BY_CALLBACK;
if(conn->bytecountp) if(conn->bytecountp)
@@ -749,6 +749,10 @@ CURLcode Curl_perform(CURL *curl)
bool port=TRUE; /* allow data->use_port to set port to use */ bool port=TRUE; /* allow data->use_port to set port to use */
char *newurl = NULL; /* possibly a new URL to follow to! */ char *newurl = NULL; /* possibly a new URL to follow to! */
if(!data->url)
/* we can't do anything wihout URL */
return CURLE_URL_MALFORMAT;
data->followlocation=0; /* reset the location-follow counter */ data->followlocation=0; /* reset the location-follow counter */
data->bits.this_is_a_follow = FALSE; /* reset this */ data->bits.this_is_a_follow = FALSE; /* reset this */

View File

@@ -153,13 +153,6 @@ CURLcode Curl_close(CURL *curl)
data->bits.httpproxy=FALSE; data->bits.httpproxy=FALSE;
} }
if(data->bits.rangestringalloc) {
free(data->range);
data->range=NULL;
data->bits.rangestringalloc=0; /* free now */
}
/* check for allocated [URL] memory to free: */ /* check for allocated [URL] memory to free: */
if(data->freethis) if(data->freethis)
free(data->freethis); free(data->freethis);
@@ -703,14 +696,14 @@ CURLcode Curl_setopt(CURL *curl, CURLoption option, ...)
/* /*
* What range of the file you want to transfer * What range of the file you want to transfer
*/ */
data->range = va_arg(param, char *); data->set_range = va_arg(param, char *);
data->bits.set_range = data->range?1:0; data->bits.set_range = data->set_range?1:0;
break; break;
case CURLOPT_RESUME_FROM: case CURLOPT_RESUME_FROM:
/* /*
* Resume transfer at the give file position * Resume transfer at the give file position
*/ */
data->resume_from = va_arg(param, long); data->set_resume_from = va_arg(param, long);
break; break;
case CURLOPT_STDERR: case CURLOPT_STDERR:
/* /*
@@ -719,6 +712,12 @@ CURLcode Curl_setopt(CURL *curl, CURLoption option, ...)
*/ */
data->err = va_arg(param, FILE *); data->err = va_arg(param, FILE *);
break; break;
case CURLOPT_HEADERFUNCTION:
/*
* Set header write callback
*/
data->fwrite_header = va_arg(param, curl_write_callback);
break;
case CURLOPT_WRITEFUNCTION: case CURLOPT_WRITEFUNCTION:
/* /*
* Set data write callback * Set data write callback
@@ -795,6 +794,16 @@ CURLcode Curl_disconnect(struct connectdata *conn)
if(!conn) if(!conn)
return CURLE_OK; /* this is closed and fine already */ return CURLE_OK; /* this is closed and fine already */
/*
* The range string is usually freed in curl_done(), but we might
* get here *instead* if we fail prematurely. Thus we need to be able
* to free this resource here as well.
*/
if(conn->bits.rangestringalloc) {
free(conn->range);
conn->bits.rangestringalloc = FALSE;
}
if(-1 != conn->connectindex) { if(-1 != conn->connectindex) {
/* unlink ourselves! */ /* unlink ourselves! */
infof(conn->data, "Closing live connection (#%d)\n", conn->connectindex); infof(conn->data, "Closing live connection (#%d)\n", conn->connectindex);
@@ -1054,6 +1063,11 @@ ConnectionStore(struct UrlData *data,
static CURLcode ConnectPlease(struct UrlData *data, static CURLcode ConnectPlease(struct UrlData *data,
struct connectdata *conn) struct connectdata *conn)
{ {
#if defined(WIN32)
unsigned long nonblock = 0;
fd_set connectfd;
struct timeval conntimeout;
#endif
#ifndef ENABLE_IPV6 #ifndef ENABLE_IPV6
conn->firstsocket = socket(AF_INET, SOCK_STREAM, 0); conn->firstsocket = socket(AF_INET, SOCK_STREAM, 0);
@@ -1216,10 +1230,33 @@ static CURLcode ConnectPlease(struct UrlData *data,
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
} }
#else #else
/* non-zero nonblock value sets socket as nonblocking under Win32 */
#if defined(WIN32)
FD_ZERO (&connectfd);
FD_SET(conn->firstsocket, &connectfd);
if (conn->data->connecttimeout > 0) {
nonblock = 1;
}
ioctlsocket(conn->firstsocket, FIONBIO, &nonblock);
#endif
if (connect(conn->firstsocket, if (connect(conn->firstsocket,
(struct sockaddr *) &(conn->serv_addr), (struct sockaddr *) &(conn->serv_addr),
sizeof(conn->serv_addr) sizeof(conn->serv_addr)
) < 0) { ) < 0) {
#if defined(WIN32)
conntimeout.tv_sec = conn->data->connecttimeout;
conntimeout.tv_usec = 0;
if(-1 != select (conn->firstsocket + 1, NULL, &connectfd, NULL, &conntimeout)) {
if (FD_ISSET(conn->firstsocket, &connectfd)) {
/* shut off non-blocking again */
nonblock = 0;
ioctlsocket(conn->firstsocket, FIONBIO, &nonblock);
return CURLE_OK;
}
else
errno = EINTR;
}
#endif
switch(errno) { switch(errno) {
#ifdef ECONNREFUSED #ifdef ECONNREFUSED
/* this should be made nicer */ /* this should be made nicer */
@@ -1314,6 +1351,9 @@ static CURLcode Connect(struct UrlData *data,
conn->secondarysocket = -1; /* no file descriptor */ conn->secondarysocket = -1; /* no file descriptor */
conn->connectindex = -1; /* no index */ conn->connectindex = -1; /* no index */
conn->bits.httpproxy = data->bits.httpproxy; /* proxy-or-not status */ conn->bits.httpproxy = data->bits.httpproxy; /* proxy-or-not status */
conn->bits.use_range = data->bits.set_range; /* range status */
conn->range = data->set_range; /* clone the range setting */
conn->resume_from = data->set_resume_from; /* inherite resume_from */
/* Default protocol-independent behavior doesn't support persistant /* Default protocol-independent behavior doesn't support persistant
connections, so we set this to force-close. Protocols that support connections, so we set this to force-close. Protocols that support
@@ -1545,7 +1585,19 @@ static CURLcode Connect(struct UrlData *data,
/* read the protocol proxy: */ /* read the protocol proxy: */
prox=curl_getenv(proxy_env); prox=curl_getenv(proxy_env);
if(!prox) { /*
* We don't try the uppercase version of HTTP_PROXY because of
* security reasons:
*
* When curl is used in a webserver application
* environment (cgi or php), this environment variable can
* be controlled by the web server user by setting the
* http header 'Proxy:' to some value.
*
* This can cause 'internal' http/ftp requests to be
* arbitrarily redirected by any external attacker.
*/
if(!prox && !strequal("http_proxy", proxy_env)) {
/* There was no lowercase variable, try the uppercase version: */ /* There was no lowercase variable, try the uppercase version: */
for(envp = proxy_env; *envp; envp++) for(envp = proxy_env; *envp; envp++)
*envp = toupper(*envp); *envp = toupper(*envp);
@@ -1604,13 +1656,13 @@ static CURLcode Connect(struct UrlData *data,
* server, we just fail since we can't rewind the file writing from within * server, we just fail since we can't rewind the file writing from within
* this function. * this function.
***********************************************************/ ***********************************************************/
if(data->resume_from) { if(conn->resume_from) {
if(!data->bits.set_range) { if(!conn->bits.use_range) {
/* if it already was in use, we just skip this */ /* if it already was in use, we just skip this */
snprintf(resumerange, sizeof(resumerange), "%d-", data->resume_from); snprintf(resumerange, sizeof(resumerange), "%d-", conn->resume_from);
data->range=strdup(resumerange); /* tell ourselves to fetch this range */ conn->range=strdup(resumerange); /* tell ourselves to fetch this range */
data->bits.rangestringalloc = TRUE; /* mark as allocated */ conn->bits.rangestringalloc = TRUE; /* mark as allocated */
data->bits.set_range = 1; /* switch on range usage */ conn->bits.use_range = 1; /* switch on range usage */
} }
} }
@@ -1970,8 +2022,8 @@ static CURLcode Connect(struct UrlData *data,
free(conn->path); /* free the previous path pointer */ free(conn->path); /* free the previous path pointer */
/* we need these pointers if we speak over a proxy */ /* we need these pointers if we speak over a proxy */
conn->name = old_conn->name; conn->name = conn->gname;
conn->hostname = old_conn->hostname; conn->hostname = old_conn->gname;
conn->path = path; /* use this one */ conn->path = path; /* use this one */
conn->ppath = path; /* set this too */ conn->ppath = path; /* set this too */
@@ -2164,13 +2216,20 @@ CURLcode Curl_done(struct connectdata *conn)
struct UrlData *data=conn->data; struct UrlData *data=conn->data;
CURLcode result; CURLcode result;
/* cleanups done even if the connection is re-used */
if(conn->bits.rangestringalloc) {
free(conn->range);
conn->bits.rangestringalloc = FALSE;
}
/* this calls the protocol-specific function pointer previously set */ /* this calls the protocol-specific function pointer previously set */
if(conn->curl_done) if(conn->curl_done)
result = conn->curl_done(conn); result = conn->curl_done(conn);
else else
result = CURLE_OK; result = CURLE_OK;
Curl_pgrsDone(data); /* done with the operation */ Curl_pgrsDone(conn); /* done with the operation */
/* if data->bits.reuse_forbid is TRUE, it means the libcurl client has /* if data->bits.reuse_forbid is TRUE, it means the libcurl client has
forced us to close this no matter what we think. forced us to close this no matter what we think.

View File

@@ -185,6 +185,9 @@ struct ConnectBits {
bool httpproxy; /* if set, this transfer is done through a http proxy */ bool httpproxy; /* if set, this transfer is done through a http proxy */
bool user_passwd; /* do we use user+password for this connection? */ bool user_passwd; /* do we use user+password for this connection? */
bool proxy_user_passwd; /* user+password for the proxy? */ bool proxy_user_passwd; /* user+password for the proxy? */
bool use_range;
bool rangestringalloc; /* the range string is malloc()'ed */
}; };
/* /*
@@ -228,6 +231,10 @@ struct connectdata {
char *ppath; char *ppath;
long bytecount; long bytecount;
char *range; /* range, if used. See README for detailed specification on
this syntax. */
int resume_from; /* continue [ftp] transfer from here */
char *proxyhost; /* name of the http proxy host */ char *proxyhost; /* name of the http proxy host */
struct timeval now; /* "current" time */ struct timeval now; /* "current" time */
@@ -401,7 +408,6 @@ struct Configbits {
bool this_is_a_follow; /* this is a followed Location: request */ bool this_is_a_follow; /* this is a followed Location: request */
bool krb4; /* kerberos4 connection requested */ bool krb4; /* kerberos4 connection requested */
bool proxystringalloc; /* the http proxy string is malloc()'ed */ bool proxystringalloc; /* the http proxy string is malloc()'ed */
bool rangestringalloc; /* the range string is malloc()'ed */
bool urlstringalloc; /* the URL string is malloc()'ed */ bool urlstringalloc; /* the URL string is malloc()'ed */
bool reuse_forbid; /* if this is forbidden to be reused, close bool reuse_forbid; /* if this is forbidden to be reused, close
after use */ after use */
@@ -460,7 +466,7 @@ struct UrlData {
struct ssl_config_data ssl; /* this is for ssl-stuff */ struct ssl_config_data ssl; /* this is for ssl-stuff */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on char *set_range; /* range, if used. See README for detailed specification on
this syntax. */ this syntax. */
/* stuff related to HTTP */ /* stuff related to HTTP */
@@ -485,6 +491,9 @@ struct UrlData {
/* function that stores the output:*/ /* function that stores the output:*/
curl_write_callback fwrite; curl_write_callback fwrite;
/* optional function that stores the header output:*/
curl_write_callback fwrite_header;
/* function that reads the input:*/ /* function that reads the input:*/
curl_read_callback fread; curl_read_callback fread;
@@ -507,7 +516,7 @@ struct UrlData {
long low_speed_limit; /* bytes/second */ long low_speed_limit; /* bytes/second */
long low_speed_time; /* number of seconds */ long low_speed_time; /* number of seconds */
int resume_from; /* continue [ftp] transfer from here */ int set_resume_from; /* continue [ftp] transfer from here */
char *cookie; /* HTTP cookie string to send */ char *cookie; /* HTTP cookie string to send */

View File

@@ -38,6 +38,23 @@ char *curl_version(void)
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
#if (SSLEAY_VERSION_NUMBER >= 0x906000)
{
char sub[2];
if(SSLEAY_VERSION_NUMBER&0xff0) {
sub[0]=((SSLEAY_VERSION_NUMBER>>4)&0xff) + 'a' -1;
}
else
sub[0]=0;
sprintf(ptr, " (OpenSSL %lx.%lx.%lx%s)",
(SSLEAY_VERSION_NUMBER>>28)&0xf,
(SSLEAY_VERSION_NUMBER>>20)&0xff,
(SSLEAY_VERSION_NUMBER>>12)&0xff,
sub);
}
#else
#if (SSLEAY_VERSION_NUMBER >= 0x900000) #if (SSLEAY_VERSION_NUMBER >= 0x900000)
sprintf(ptr, " (SSL %lx.%lx.%lx)", sprintf(ptr, " (SSL %lx.%lx.%lx)",
(SSLEAY_VERSION_NUMBER>>28)&0xff, (SSLEAY_VERSION_NUMBER>>28)&0xff,
@@ -57,6 +74,7 @@ char *curl_version(void)
(SSLEAY_VERSION_NUMBER>>8)&0xf, (SSLEAY_VERSION_NUMBER>>8)&0xf,
(SSLEAY_VERSION_NUMBER>>4)&0xf, sub); (SSLEAY_VERSION_NUMBER>>4)&0xf, sub);
} }
#endif
#endif #endif
ptr=strchr(ptr, '\0'); ptr=strchr(ptr, '\0');
#endif #endif

View File

@@ -1,6 +1,47 @@
Revision history for Perl extension Curl::easy. Revision history for Perl extension Curl::easy.
Check out the file README for more info. Check out the file README for more info.
1.1.5 Fri Apr 20 2001: - Cris Bailiff <c.bailiff@devsecure.com>
- Add latest CURLOPT_ and CURLINFO_ constants to the constants list
1.1.4 Fri Apr 20 2001: - Cris Bailiff <c.bailiff@devsecure.com>
- Fix case where curl_slists such as 'HTTPHEADERS' need to
be re-set over persistant requests
1.1.3 Wed Apr 18 2001: - Cris Bailiff <c.bailiff@devsecure.com>
- Change/shorten module function names: Curl::easy::curl_easy_setopt
becomes Curl::easy::setopt etc. This requires minor changes to existing
scripts....
- Added callback function support to pass arbitrary SV * (including
FILE globs) from perl through libcurl to the perl callback.
- Make callbacks still work with existing scripts which use STDIO
- Initial support for libcurl 7.7.2 HEADERFUNCTION callback feature
- Minor API cleanups/changes in the callback function signatures
- Added Curl::easy::version function to return curl version string
- Callback documentation added in easy.pm
- More tests in test.pl
1.1.2 Mon Apr 16 2001: - Georg Horn <horn@koblenz-net.de>
- Added support for callback functions. This is for the curl_easy_setopt()
options WRITEFUNCTION, READFUNCTION, PROGRESSFUNCTION and PASSWDFUNCTION.
Still missing, but not really neccessary: Passing a FILE * pointer,
that is passed in from libcurl, on to the perl callback function.
- Various cleanups, fixes and enhancements to easy.xs and test.pl.
1.1.1 Thu Apr 12 2001:
- Made more options of curl_easy_setopt() work: Options that require
a list of curl_slist structs to be passed in, like CURLOPT_HTTPHEADER,
are now working by passing a perl array containing the list elements.
As always, look at the test script test.pl for an example.
1.1.0 Wed Apr 11 2001:
- tested against libcurl 7.7
- Added new function Curl::easy::internal_setopt(). By calling
Curl::easy::internal_setopt(Curl::easy::USE_INTERNAL_VARS, 1);
the headers and content of the fetched page are no longer stored
into files (or written to stdout) but are stored into internal
Variables $Curl::easy::headers and $Curl::easy::content.
1.0.2 Tue Oct 10 2000: 1.0.2 Tue Oct 10 2000:
- runs with libcurl 7.4 - runs with libcurl 7.4
- modified curl_easy_getinfo(). It now calls curl_getinfo() that has - modified curl_easy_getinfo(). It now calls curl_getinfo() that has

View File

@@ -1,6 +1,7 @@
Changes Changes
MANIFEST MANIFEST
Makefile.PL Makefile.PL
README
easy.pm easy.pm
easy.xs easy.xs
test.pl test.pl

View File

@@ -8,7 +8,7 @@ WriteMakefile(
'NAME' => 'Curl::easy', 'NAME' => 'Curl::easy',
'VERSION_FROM' => 'easy.pm', # finds $VERSION 'VERSION_FROM' => 'easy.pm', # finds $VERSION
'LIBS' => ['-lcurl '], # e.g., '-lm' 'LIBS' => ['-lcurl '], # e.g., '-lm'
'DEFINE' => '-Wall', # e.g., '-DHAVE_SOMETHING' 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
'INC' => '', # e.g., '-I/usr/include/other' 'INC' => '', # e.g., '-I/usr/include/other'
'clean' => {FILES => "head.out body.out"} 'clean' => {FILES => "head.out body.out"}
); );

View File

@@ -12,16 +12,16 @@ installed. You then may install this module via the usual way:
make install make install
The module provides the same functionality as libcurl provides to C programs, The module provides the same functionality as libcurl provides to C programs,
please refer to the documentation of libcurl. please refer to the documentation of libcurl. Some examples may be found in
test.pl.
A short example how to use the module may be found in test.pl. This software is distributed AS IS, WITHOUT WARRANTY OF ANY KIND, either
express or implied. Send praise, patches, money, beer and pizza to the author.
Send complaints to /dev/null. ;-)
This Software is distributed AS IS, WITHOUT WARRANTY OF ANY KIND, The author of this software is Georg Horn <horn@koblenz-net.de>
either express or implied. Send praise, patches, money, beer and Parts of the callback support have been added by Cris Bailiff
pizza to the author. Send complaints to /dev/null. ;-) <c.bailiff@awayweb.com> and Forrest Cahoon <forrest.cahoon@merrillcorp.com>
The author of this module is Georg Horn <horn@koblenz-net.de> The latest version can be downloaded from http://koblenz-net.de/~horn/export/
The latest version of this module can be dowloaded from
http://koblenz-net.de/~horn/export/

View File

@@ -29,6 +29,7 @@ CURLOPT_FTPASCII
CURLOPT_FTPLISTONLY CURLOPT_FTPLISTONLY
CURLOPT_FTPPORT CURLOPT_FTPPORT
CURLOPT_HEADER CURLOPT_HEADER
CURLOPT_HEADERFUNCTION
CURLOPT_HTTPHEADER CURLOPT_HTTPHEADER
CURLOPT_HTTPPOST CURLOPT_HTTPPOST
CURLOPT_HTTPPROXYTUNNEL CURLOPT_HTTPPROXYTUNNEL
@@ -44,6 +45,8 @@ CURLOPT_NETRC
CURLOPT_NOBODY CURLOPT_NOBODY
CURLOPT_NOPROGRESS CURLOPT_NOPROGRESS
CURLOPT_NOTHING CURLOPT_NOTHING
CURLOPT_PASSWDDATA
CURLOPT_PASSWDFUNCTION
CURLOPT_PORT CURLOPT_PORT
CURLOPT_POST CURLOPT_POST
CURLOPT_POSTFIELDS CURLOPT_POSTFIELDS
@@ -75,6 +78,17 @@ CURLOPT_USERPWD
CURLOPT_VERBOSE CURLOPT_VERBOSE
CURLOPT_WRITEFUNCTION CURLOPT_WRITEFUNCTION
CURLOPT_WRITEHEADER CURLOPT_WRITEHEADER
CURLOPT_MAXREDIRS
CURLOPT_FILETIME
CURLOPT_TELNETOPTIONS
CURLOPT_MAXCONNECTS
CURLOPT_CLOSEPOLICY
CURLOPT_CLOSEFUNCTION
CURLOPT_FRESH_CONNECT
CURLOPT_FORBID_REUSE
CURLOPT_RANDOM_FILE
CURLOPT_EGD_SOCKET
CURLOPT_CONNECTTIMEOUT
CURLINFO_EFFECTIVE_URL CURLINFO_EFFECTIVE_URL
CURLINFO_HTTP_CODE CURLINFO_HTTP_CODE
@@ -88,8 +102,18 @@ CURLINFO_SPEED_DOWNLOAD
CURLINFO_SPEED_UPLOAD CURLINFO_SPEED_UPLOAD
CURLINFO_HEADER_SIZE CURLINFO_HEADER_SIZE
CURLINFO_REQUEST_SIZE CURLINFO_REQUEST_SIZE
CURLINFO_SSL_VERIFYRESULT
CURLINFO_FILETIME
CURLINFO_CONTENT_LENGTH_DOWNLOAD
CURLINFO_CONTENT_LENGTH_UPLOAD
USE_INTERNAL_VARS
); );
$VERSION = '1.0.1';
$VERSION = '1.1.5';
$Curl::easy::headers = "";
$Curl::easy::content = "";
sub AUTOLOAD { sub AUTOLOAD {
# This AUTOLOAD is used to 'autoload' constants from the constant() # This AUTOLOAD is used to 'autoload' constants from the constant()
@@ -117,21 +141,122 @@ Curl::easy - Perl extension for libcurl
use Curl::easy; use Curl::easy;
$CURL = curl_easy_init(); $curl = Curl::easy::init();
$CURLcode = curl_easy_setopt($CURL, CURLoption, Value); $CURLcode = Curl::easy::setopt($curl, CURLoption, Value);
$CURLcode = curl_easy_perform($CURL); $CURLcode = Curl::easy::perform($curl);
curl_easy_cleanup($CURL); Curl::easy::cleanup($curl);
=head1 DESCRIPTION =head1 DESCRIPTION
This perl module provides an interface to the libcurl C library. See This perl module provides an interface to the libcurl C library. See
http://curl.haxx.se/ for more information on cURL and libcurl. http://curl.haxx.se/ for more information on cURL and libcurl.
=head1 FILES and CALLBACKS
Curl::easy supports the various options of curl_easy_setopt which require either a FILE * or
a callback function.
The perl callback functions are handled through a C wrapper which takes care of converting
from C to perl variables and back again. This wrapper simplifies some C arguments to make
them behave in a more 'perl' like manner. In particular, the read and write callbacks do not
look just like the 'fread' and 'fwrite' C functions - perl variables do not need separate length
parameters, and perl functions can return a list of variables, instead of needing a pointer
to modify. The details are described below.
=head2 FILE handles (GLOBS)
Curl options which take a FILE, such as CURLOPT_FILE, CURLOPT_WRITEHEADER, CURLOPT_INFILE
can be passed a perl file handle:
open BODY,">body.out";
$CURLcode = Curl::easy::setopt($curl, CURLOPT_FILE, BODY);
=head2 WRITE callback
The CUROPT_WRITEFUNCTION option may be set which will cause libcurl to callback to
the given subroutine:
sub chunk { my ($data,$pointer)=@_; ...; return length($data) }
$CURLcode = Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, \&chunk );
$CURLcode = Curl::easy::setopt($curl, CURLOPT_FILE, );
In this case, the subroutine will be passed whatever is defined by CURLOPT_FILE. This can be
a ref to a scalar, or a GLOB or anything else you like.
The callback function must return the number of bytes 'handled' ( length($data) ) or the transfer
will abort. A transfer can be aborted by returning a 'length' of '-1'.
The option CURLOPT_WRITEHEADER can be set to pass a different '$pointer' into the CURLOPT_WRITEFUNCTION
for header values. This lets you collect the headers and body separately:
my $headers="";
my $body="";
sub chunk { my ($data,$pointer)=@_; ${$pointer}.=$data; return length($data) }
$CURLcode = Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, \&chunk );
$CURLcode = Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, \$header );
$CURLcode = Curl::easy::setopt($curl, CURLOPT_FILE, \$body );
If you have libcurl > 7.7.1, then you could instead set CURLOPT_HEADERFUNCTION to a different callback,
and have the header collected that way.
=head2 READ callback
Curl::easy supports CURLOPT_READFUNCTION. This function should look something like this:
sub read_callback {
my ($maxlength,$pointer)=@_;
....
return $data;
}
The subroutine must return an empty string "" at the end of the data. Note that this function
isn't told how much data to provide - $maxlength is just the maximum size of the buffer
provided by libcurl. If you are doing an HTTP POST or PUT for example, it is important that this
function only returns as much data as the 'Content-Length' header specifies, followed by a
an empty (0 length) buffer.
=head2 PROGRESS callback
Curl::easy supports CURLOPT_PROGRESSFUNCTION. This function should look something like this:
sub prog_callb
{
my ($clientp,$dltotal,$dlnow,$ultotal,$ulnow)=@_;
....
return 0;
}
The function should return 0 normally, or -1 which will abort/cancel the transfer. $clientp is whatever
value/scalar is set using the CURLOPT_PROGRESSDATA option.
=head2 PASSWD callback
Curl::easy supports CURLOPT_PASSWDFUNCTION. This function should look something like this:
sub passwd_callb
{
my ($clientp,$prompt,$buflen)=@_;
...
return (0,$data);
}
$clientp is whatever scalar is set using the CURLOPT_PASSWDDATA option.
$prompt is a text string which can be used to prompt for a password.
$buflen is the maximum accepted password reply.
The function must return 0 (for 'OK') and the password data as a list. Return (-1,"") to
indicate an error.
=head1 AUTHOR =head1 AUTHOR
Georg Horn <horn@koblenz-net.de> Georg Horn <horn@koblenz-net.de>
Additional callback,pod and tes work by Cris Bailiff <c.bailiff@devsecure.com>
and Forrest Cahoon <forrest.cahoon@merrillcorp.com>
=head1 SEE ALSO =head1 SEE ALSO
http://curl.haxx.se/ http://curl.haxx.se/

View File

@@ -7,6 +7,17 @@
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/easy.h> #include <curl/easy.h>
#if (LIBCURL_VERSION_NUM<0x070702)
#define CURLOPT_HEADERFUNCTION 20079
#define header_callback_func write_callback_func
#else
#define header_callback_func writeheader_callback_func
#endif
/* Lists that can be set via curl_easy_setopt() */
static struct curl_slist *httpheader = NULL, *quote = NULL, *postquote = NULL;
/* Buffer and varname for option CURLOPT_ERRORBUFFER */ /* Buffer and varname for option CURLOPT_ERRORBUFFER */
@@ -14,6 +25,339 @@ static char errbuf[CURL_ERROR_SIZE];
static char *errbufvarname = NULL; static char *errbufvarname = NULL;
/* Callback functions */
static SV *read_callback = NULL, *write_callback = NULL,
*progress_callback = NULL, *passwd_callback = NULL,
*header_callback = NULL;
/* *closepolicy_callback = NULL; */
/* For storing the content */
static char *contbuf = NULL, *bufptr = NULL;
static int bufsize = 32768, contlen = 0;
/* Internal options for this perl module */
#define USE_INTERNAL_VARS 0x01
static int internal_options = 0;
/* Setup these global vars */
static void init_globals(void)
{
if (httpheader) curl_slist_free_all(httpheader);
if (quote) curl_slist_free_all(quote);
if (postquote) curl_slist_free_all(postquote);
httpheader = quote = postquote = NULL;
if (errbufvarname) free(errbufvarname);
errbufvarname = NULL;
if (contbuf == NULL) {
contbuf = malloc(bufsize + 1);
}
bufptr = contbuf;
*bufptr = '\0';
contlen = 0;
internal_options = 0;
}
/* Register a callback function */
static void register_callback(SV **callback, SV *function)
{
if (*callback == NULL) {
/* First time, create new SV */
*callback = newSVsv(function);
} else {
/* Been there, done that. Just overwrite the SV */
SvSetSV(*callback, function);
}
}
/* generic fwrite callback, which decides which callback to call */
static size_t
fwrite_wrapper (const void *ptr,
size_t size,
size_t nmemb,
void *stream,
void *call_function)
{
dSP;
int count, status;
SV *sv;
if (call_function) {
/* then we are doing a callback to perl */
ENTER;
SAVETMPS;
PUSHMARK(SP);
if (stream == stdout) {
sv = newSViv(0); /* FIXME: should cast stdout to GLOB somehow? */
} else { /* its already an SV */
sv = stream;
}
if (ptr != NULL) {
XPUSHs(sv_2mortal(newSVpvn(ptr, size * nmemb)));
} else {
XPUSHs(sv_2mortal(newSVpv("", 0)));
}
XPUSHs(sv_2mortal(newSVsv(sv))); /* CURLOPT_FILE SV* */
PUTBACK;
count = perl_call_sv((SV *) call_function, G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Big trouble, perl_call_sv(write_callback) didn't return status\n");
status = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return status;
} else {
/* default to a normal 'fwrite' */
/* stream could be a FILE * or an SV * */
FILE *f;
if (stream == stdout) { /* the only possible FILE ? Think so */
f = stream;
} else { /* its a GLOB */
f = IoIFP(sv_2io(stream)); /* may barf if not a GLOB */
}
return fwrite(ptr, size, nmemb, f);
}
}
/* Write callback for calling a perl callback */
size_t
write_callback_func( const void *ptr, size_t size,
size_t nmemb, void *stream)
{
return fwrite_wrapper(ptr,size,nmemb,stream,
write_callback);
}
/* header callback for calling a perl callback */
size_t
writeheader_callback_func( const void *ptr, size_t size,
size_t nmemb, void *stream)
{
return fwrite_wrapper(ptr,size,nmemb,stream,
header_callback);
}
size_t
read_callback_func( void *ptr, size_t size,
size_t nmemb, void *stream)
{
dSP ;
int count;
SV *sv;
STRLEN len;
size_t maxlen,mylen;
char *p;
maxlen = size*nmemb;
if (read_callback) {
/* we are doing a callback to perl */
ENTER ;
SAVETMPS ;
PUSHMARK(SP) ;
if (stream == stdin) {
sv = newSViv(0); /* should cast stdin to GLOB somehow? */
} else { /* its an SV */
sv = stream;
}
XPUSHs(sv_2mortal(newSViv(maxlen))); /* send how many bytes please */
XPUSHs(sv_2mortal(newSVsv(sv))); /* CURLOPT_INFILE SV* */
PUTBACK ;
count = perl_call_sv(read_callback, G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Big trouble, perl_call_sv(read_callback) didn't return data\n");
sv = POPs;
p = SvPV(sv,len);
/* only allowed to return the number of bytes asked for */
mylen = len<maxlen ? len : maxlen;
memcpy(ptr,p,(size_t)mylen);
PUTBACK ;
FREETMPS ;
LEAVE ;
return (size_t) (mylen/size);
} else {
/* default to a normal 'fread' */
/* stream could be a FILE * or an SV * */
FILE *f;
if (stream == stdin) { /* the only possible FILE ? Think so*/
f = stream;
} else { /* its a GLOB */
f = IoIFP(sv_2io(stream)); /* may barf if not a GLOB */
}
return fread(ptr,size,nmemb,f);
}
}
/* Porgress callback for calling a perl callback */
static int progress_callback_func(void *clientp, size_t dltotal, size_t dlnow,
size_t ultotal, size_t ulnow)
{
dSP;
int count;
ENTER;
SAVETMPS;
PUSHMARK(sp);
if (clientp != NULL) {
XPUSHs(sv_2mortal(newSVpv(clientp, 0)));
} else {
XPUSHs(sv_2mortal(newSVpv("", 0)));
}
XPUSHs(sv_2mortal(newSViv(dltotal)));
XPUSHs(sv_2mortal(newSViv(dlnow)));
XPUSHs(sv_2mortal(newSViv(ultotal)));
XPUSHs(sv_2mortal(newSViv(ulnow)));
PUTBACK;
count = perl_call_sv(progress_callback, G_SCALAR);
SPAGAIN;
if (count != 1)
croak("Big trouble, perl_call_sv(progress_callback) didn't return 1\n");
count = POPi;
PUTBACK;
FREETMPS;
LEAVE;
return count;
}
/* Password callback for calling a perl callback */
static int passwd_callback_func(void *clientp, char *prompt, char *buffer,
int buflen)
{
dSP;
int count;
SV *sv;
STRLEN len;
size_t mylen;
char *p;
ENTER;
SAVETMPS;
PUSHMARK(sp);
if (clientp != NULL) {
XPUSHs(sv_2mortal(newSVsv(clientp)));
} else {
XPUSHs(sv_2mortal(newSVpv("", 0)));
}
XPUSHs(sv_2mortal(newSVpv(prompt, 0)));
XPUSHs(sv_2mortal(newSViv(buflen)));
PUTBACK;
count = perl_call_sv(passwd_callback, G_ARRAY);
SPAGAIN;
if (count != 2)
croak("Big trouble, perl_call_sv(passwd_callback) didn't return status + data\n");
sv = POPs;
count = POPi;
p = SvPV(sv,len);
/* only allowed to return the number of bytes asked for */
mylen = len<(buflen-1) ? len : (buflen-1);
memcpy(buffer,p,mylen);
buffer[buflen]=0; /* ensure C string terminates */
PUTBACK;
FREETMPS;
LEAVE;
return count;
}
#if 0
/* awaiting closepolicy prototype */
int
closepolicy_callback_func(void *clientp)
{
dSP;
int argc, status;
SV *pl_status;
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
argc = perl_call_sv(closepolicy_callback, G_SCALAR);
SPAGAIN;
if (argc != 1) {
croak("Unexpected number of arguments returned from closefunction callback\n");
}
pl_status = POPs;
status = SvTRUE(pl_status) ? 0 : 1;
PUTBACK;
FREETMPS;
LEAVE;
return status;
}
#endif
/* Internal write callback. Only used if USE_INTERNAL_VARS was specified */
static size_t internal_write_callback(char *data, size_t size, size_t num,
FILE *fp)
{
int i;
size *= num;
if ((contlen + size) >= bufsize) {
bufsize *= 2;
contbuf = realloc(contbuf, bufsize + 1);
bufptr = contbuf + contlen;
}
contlen += size;
for (i = 0; i < size; i++) {
*bufptr++ = *data++;
}
*bufptr = '\0';
return size;
}
static int static int
constant(char *name, int arg) constant(char *name, int arg)
{ {
@@ -24,13 +368,17 @@ constant(char *name, int arg)
case 'A': case 'A':
case 'B': case 'B':
case 'C': case 'C':
case 'D':
if (strEQ(name, "CONNECT_TIME")) return CURLINFO_CONNECT_TIME; if (strEQ(name, "CONNECT_TIME")) return CURLINFO_CONNECT_TIME;
if (strEQ(name, "CONTENT_LENGTH_DOWNLOAD")) return CURLINFO_CONTENT_LENGTH_DOWNLOAD;
if (strEQ(name, "CONTENT_LENGTH_UPLOAD")) return CURLINFO_CONTENT_LENGTH_UPLOAD;
break; break;
case 'D':
case 'E': case 'E':
case 'F':
if (strEQ(name, "EFFECTIVE_URL")) return CURLINFO_EFFECTIVE_URL; if (strEQ(name, "EFFECTIVE_URL")) return CURLINFO_EFFECTIVE_URL;
break; break;
case 'F':
if (strEQ(name, "FILETIME")) return CURLINFO_FILETIME;
break;
case 'G': case 'G':
case 'H': case 'H':
if (strEQ(name, "HEADER_SIZE")) return CURLINFO_HEADER_SIZE; if (strEQ(name, "HEADER_SIZE")) return CURLINFO_HEADER_SIZE;
@@ -53,6 +401,8 @@ constant(char *name, int arg)
if (strEQ(name, "REQUEST_SIZE")) return CURLINFO_REQUEST_SIZE; if (strEQ(name, "REQUEST_SIZE")) return CURLINFO_REQUEST_SIZE;
break; break;
case 'S': case 'S':
if (strEQ(name, "SSL_VERIFYRESULT")) return CURLINFO_SSL_VERIFYRESULT;
break;
case 'T': case 'T':
if (strEQ(name, "SIZE_DOWNLOAD")) return CURLINFO_SIZE_DOWNLOAD; if (strEQ(name, "SIZE_DOWNLOAD")) return CURLINFO_SIZE_DOWNLOAD;
if (strEQ(name, "SIZE_UPLOAD")) return CURLINFO_SIZE_UPLOAD; if (strEQ(name, "SIZE_UPLOAD")) return CURLINFO_SIZE_UPLOAD;
@@ -77,26 +427,35 @@ constant(char *name, int arg)
if (strEQ(name, "AUTOREFERER")) return CURLOPT_AUTOREFERER; if (strEQ(name, "AUTOREFERER")) return CURLOPT_AUTOREFERER;
break; break;
case 'C': case 'C':
case 'D': if (strEQ(name, "CONNECTTIMEOUT")) return CURLOPT_CONNECTTIMEOUT;
if (strEQ(name, "COOKIE")) return CURLOPT_COOKIE; if (strEQ(name, "COOKIE")) return CURLOPT_COOKIE;
if (strEQ(name, "COOKIEFILE")) return CURLOPT_COOKIEFILE; if (strEQ(name, "COOKIEFILE")) return CURLOPT_COOKIEFILE;
if (strEQ(name, "CLOSEFUNCTION")) return CURLOPT_CLOSEFUNCTION;
if (strEQ(name, "CLOSEPOLICY")) return CURLOPT_CLOSEPOLICY;
if (strEQ(name, "CRLF")) return CURLOPT_CRLF; if (strEQ(name, "CRLF")) return CURLOPT_CRLF;
if (strEQ(name, "CUSTOMREQUEST")) return CURLOPT_CUSTOMREQUEST; if (strEQ(name, "CUSTOMREQUEST")) return CURLOPT_CUSTOMREQUEST;
break; break;
case 'D':
case 'E': case 'E':
case 'F': if (strEQ(name, "EGDSOCKET")) return CURLOPT_EGDSOCKET;
if (strEQ(name, "ERRORBUFFER")) return CURLOPT_ERRORBUFFER; if (strEQ(name, "ERRORBUFFER")) return CURLOPT_ERRORBUFFER;
break;
case 'F':
if (strEQ(name, "FAILONERROR")) return CURLOPT_FAILONERROR; if (strEQ(name, "FAILONERROR")) return CURLOPT_FAILONERROR;
if (strEQ(name, "FILE")) return CURLOPT_FILE; if (strEQ(name, "FILE")) return CURLOPT_FILE;
if (strEQ(name, "FILETIME")) return CURLOPT_FILETIME;
if (strEQ(name, "FOLLOWLOCATION")) return CURLOPT_FOLLOWLOCATION; if (strEQ(name, "FOLLOWLOCATION")) return CURLOPT_FOLLOWLOCATION;
if (strEQ(name, "FORBID_REUSE")) return CURLOPT_FORBID_REUSE;
if (strEQ(name, "FTPAPPEND")) return CURLOPT_FTPAPPEND; if (strEQ(name, "FTPAPPEND")) return CURLOPT_FTPAPPEND;
if (strEQ(name, "FTPASCII")) return CURLOPT_FTPASCII; if (strEQ(name, "FTPASCII")) return CURLOPT_FTPASCII;
if (strEQ(name, "FTPLISTONLY")) return CURLOPT_FTPLISTONLY; if (strEQ(name, "FTPLISTONLY")) return CURLOPT_FTPLISTONLY;
if (strEQ(name, "FTPPORT")) return CURLOPT_FTPPORT; if (strEQ(name, "FTPPORT")) return CURLOPT_FTPPORT;
if (strEQ(name, "FRESH_CONNECT")) return CURLOPT_FRESH_CONNECT;
break; break;
case 'G': case 'G':
case 'H': case 'H':
if (strEQ(name, "HEADER")) return CURLOPT_HEADER; if (strEQ(name, "HEADER")) return CURLOPT_HEADER;
if (strEQ(name, "HEADERFUNCTION")) return CURLOPT_HEADERFUNCTION;
if (strEQ(name, "HTTPHEADER")) return CURLOPT_HTTPHEADER; if (strEQ(name, "HTTPHEADER")) return CURLOPT_HTTPHEADER;
if (strEQ(name, "HTTPPOST")) return CURLOPT_HTTPPOST; if (strEQ(name, "HTTPPOST")) return CURLOPT_HTTPPOST;
if (strEQ(name, "HTTPPROXYTUNNEL")) return CURLOPT_HTTPPROXYTUNNEL; if (strEQ(name, "HTTPPROXYTUNNEL")) return CURLOPT_HTTPPROXYTUNNEL;
@@ -115,6 +474,9 @@ constant(char *name, int arg)
if (strEQ(name, "LOW_SPEED_TIME")) return CURLOPT_LOW_SPEED_TIME; if (strEQ(name, "LOW_SPEED_TIME")) return CURLOPT_LOW_SPEED_TIME;
break; break;
case 'M': case 'M':
if (strEQ(name, "MAXCONNECTS")) return CURLOPT_MAXCONNECTS;
if (strEQ(name, "MAXREDIRS")) return CURLOPT_MAXREDIRS;
break;
case 'N': case 'N':
if (strEQ(name, "MUTE")) return CURLOPT_MUTE; if (strEQ(name, "MUTE")) return CURLOPT_MUTE;
if (strEQ(name, "NETRC")) return CURLOPT_NETRC; if (strEQ(name, "NETRC")) return CURLOPT_NETRC;
@@ -124,6 +486,8 @@ constant(char *name, int arg)
break; break;
case 'O': case 'O':
case 'P': case 'P':
if (strEQ(name, "PASSWDDATA")) return CURLOPT_PASSWDDATA;
if (strEQ(name, "PASSWDFUNCTION")) return CURLOPT_PASSWDFUNCTION;
if (strEQ(name, "PORT")) return CURLOPT_PORT; if (strEQ(name, "PORT")) return CURLOPT_PORT;
if (strEQ(name, "POST")) return CURLOPT_POST; if (strEQ(name, "POST")) return CURLOPT_POST;
if (strEQ(name, "POSTFIELDS")) return CURLOPT_POSTFIELDS; if (strEQ(name, "POSTFIELDS")) return CURLOPT_POSTFIELDS;
@@ -137,19 +501,23 @@ constant(char *name, int arg)
if (strEQ(name, "PUT")) return CURLOPT_PUT; if (strEQ(name, "PUT")) return CURLOPT_PUT;
break; break;
case 'Q': case 'Q':
case 'R':
if (strEQ(name, "QUOTE")) return CURLOPT_QUOTE; if (strEQ(name, "QUOTE")) return CURLOPT_QUOTE;
break;
case 'R':
if (strEQ(name, "RANDOM_FILE")) return CURLOPT_RANDOM_FILE;
if (strEQ(name, "RANGE")) return CURLOPT_RANGE; if (strEQ(name, "RANGE")) return CURLOPT_RANGE;
if (strEQ(name, "READFUNCTION")) return CURLOPT_READFUNCTION; if (strEQ(name, "READFUNCTION")) return CURLOPT_READFUNCTION;
if (strEQ(name, "REFERER")) return CURLOPT_REFERER; if (strEQ(name, "REFERER")) return CURLOPT_REFERER;
if (strEQ(name, "RESUME_FROM")) return CURLOPT_RESUME_FROM; if (strEQ(name, "RESUME_FROM")) return CURLOPT_RESUME_FROM;
break; break;
case 'S': case 'S':
case 'T':
if (strEQ(name, "SSLCERT")) return CURLOPT_SSLCERT; if (strEQ(name, "SSLCERT")) return CURLOPT_SSLCERT;
if (strEQ(name, "SSLCERTPASSWD")) return CURLOPT_SSLCERTPASSWD; if (strEQ(name, "SSLCERTPASSWD")) return CURLOPT_SSLCERTPASSWD;
if (strEQ(name, "SSLVERSION")) return CURLOPT_SSLVERSION; if (strEQ(name, "SSLVERSION")) return CURLOPT_SSLVERSION;
if (strEQ(name, "STDERR")) return CURLOPT_STDERR; if (strEQ(name, "STDERR")) return CURLOPT_STDERR;
break;
case 'T':
if (strEQ(name, "TELNETOPTIONS")) return CURLOPT_TELNETOPTIONS;
if (strEQ(name, "TIMECONDITION")) return CURLOPT_TIMECONDITION; if (strEQ(name, "TIMECONDITION")) return CURLOPT_TIMECONDITION;
if (strEQ(name, "TIMEOUT")) return CURLOPT_TIMEOUT; if (strEQ(name, "TIMEOUT")) return CURLOPT_TIMEOUT;
if (strEQ(name, "TIMEVALUE")) return CURLOPT_TIMEVALUE; if (strEQ(name, "TIMEVALUE")) return CURLOPT_TIMEVALUE;
@@ -173,12 +541,13 @@ constant(char *name, int arg)
break; break;
} }
} }
if (strEQ(name, "USE_INTERNAL_VARS")) return USE_INTERNAL_VARS;
errno = EINVAL; errno = EINVAL;
return 0; return 0;
} }
MODULE = Curl::easy PACKAGE = Curl::easy MODULE = Curl::easy PACKAGE = Curl::easy PREFIX = curl_easy_
int int
constant(name,arg) constant(name,arg)
@@ -189,43 +558,119 @@ constant(name,arg)
void * void *
curl_easy_init() curl_easy_init()
CODE: CODE:
if (errbufvarname) free(errbufvarname); init_globals();
errbufvarname = NULL;
RETVAL = curl_easy_init(); RETVAL = curl_easy_init();
curl_easy_setopt(RETVAL, CURLOPT_HEADERFUNCTION, header_callback_func);
curl_easy_setopt(RETVAL, CURLOPT_WRITEFUNCTION, write_callback_func);
OUTPUT: OUTPUT:
RETVAL RETVAL
char *
curl_easy_version()
CODE:
RETVAL=curl_version();
OUTPUT:
RETVAL
int int
curl_easy_setopt(curl, option, value) curl_easy_setopt(curl, option, value)
void * curl void * curl
int option int option
char * value SV * value
CODE: CODE:
if (option < CURLOPTTYPE_OBJECTPOINT) { if (option < CURLOPTTYPE_OBJECTPOINT) {
/* This is an option specifying an integer value: */ /* This is an option specifying an integer value: */
long value = (long)SvIV(ST(2)); RETVAL = curl_easy_setopt(curl, option, (long)SvIV(value));
RETVAL = curl_easy_setopt(curl, option, value);
} else if (option == CURLOPT_FILE || option == CURLOPT_INFILE || } else if (option == CURLOPT_FILE || option == CURLOPT_INFILE ||
option == CURLOPT_WRITEHEADER) { option == CURLOPT_WRITEHEADER || option == CURLOPT_PROGRESSDATA ||
/* This is an option specifying a FILE * value: */ option == CURLOPT_PASSWDDATA) {
FILE * value = IoIFP(sv_2io(ST(2))); /* This is an option specifying an SV * value: */
RETVAL = curl_easy_setopt(curl, option, value); RETVAL = curl_easy_setopt(curl, option, newSVsv(ST(2)));
} else if (option == CURLOPT_ERRORBUFFER) { } else if (option == CURLOPT_ERRORBUFFER) {
SV *sv; /* Pass in variable name for storing error messages... */
RETVAL = curl_easy_setopt(curl, option, errbuf); RETVAL = curl_easy_setopt(curl, option, errbuf);
if (errbufvarname) free(errbufvarname); if (errbufvarname) free(errbufvarname);
errbufvarname = strdup(value); errbufvarname = strdup((char *)SvPV(value, PL_na));
sv = perl_get_sv(errbufvarname, TRUE | GV_ADDMULTI);
} else if (option == CURLOPT_WRITEFUNCTION || option == } else if (option == CURLOPT_WRITEFUNCTION || option ==
CURLOPT_READFUNCTION || option == CURLOPT_PROGRESSFUNCTION) { CURLOPT_READFUNCTION || option == CURLOPT_PROGRESSFUNCTION ||
option == CURLOPT_PASSWDFUNCTION || option == CURLOPT_HEADERFUNCTION) {
/* This is an option specifying a callback function */ /* This is an option specifying a callback function */
/* not yet implemented */ switch (option) {
RETVAL = -1; case CURLOPT_WRITEFUNCTION:
} else { register_callback(&write_callback, value);
/* default, option specifying a char * value: */ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_func);
RETVAL = curl_easy_setopt(curl, option, value); break;
case CURLOPT_READFUNCTION:
register_callback(&read_callback, value);
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback_func);
break;
case CURLOPT_HEADERFUNCTION:
register_callback(&header_callback, value);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback_func);
case CURLOPT_PROGRESSFUNCTION:
register_callback(&progress_callback, value);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, progress_callback_func);
break;
case CURLOPT_PASSWDFUNCTION:
register_callback(&passwd_callback, value);
curl_easy_setopt(curl, CURLOPT_PASSWDFUNCTION, passwd_callback_func);
break;
/* awaiting a prototype for the closepolicy function callback
case CURLOPT_CLOSEFUNCTION:
register_callback(&closepolicy_callback, value);
curl_easy_setopt(curl, CURLOPT_CLOSEFUNCTION, closepolicy_callback_func);
break;
*/
} }
RETVAL = -1;
} else if (option == CURLOPT_HTTPHEADER || option == CURLOPT_QUOTE ||
option == CURLOPT_POSTQUOTE) {
/* This is an option specifying a list of curl_slist structs: */
AV *array = (AV *)SvRV(value);
struct curl_slist **slist = NULL;
/* We have to find out which list to use... */
switch (option) {
case CURLOPT_HTTPHEADER:
slist = &httpheader; break;
case CURLOPT_QUOTE:
slist = &quote; break;
case CURLOPT_POSTQUOTE:
slist = &postquote; break;
}
/* free any previous list */
if (*slist) {
curl_slist_free_all(*slist);
*slist=NULL;
}
/* ...store the values into it... */
for (;;) {
SV *sv = av_shift(array);
int len = 0;
char *str = SvPV(sv, len);
if (len == 0) break;
*slist = curl_slist_append(*slist, str);
}
/* ...and pass the list into curl_easy_setopt() */
RETVAL = curl_easy_setopt(curl, option, *slist);
} else {
/* This is an option specifying a char * value: */
RETVAL = curl_easy_setopt(curl, option, SvPV(value, PL_na));
}
OUTPUT:
RETVAL
int
internal_setopt(option, value)
int option
int value
CODE:
if (value == 1) {
internal_options |= option;
} else {
internal_options &= !option;
}
RETVAL = 0;
OUTPUT: OUTPUT:
RETVAL RETVAL
@@ -234,11 +679,46 @@ int
curl_easy_perform(curl) curl_easy_perform(curl)
void * curl void * curl
CODE: CODE:
if (internal_options & USE_INTERNAL_VARS) {
/* Use internal callback which just stores the content into a buffer. */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, internal_write_callback);
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
}
RETVAL = curl_easy_perform(curl); RETVAL = curl_easy_perform(curl);
if (RETVAL && errbufvarname) { if (RETVAL && errbufvarname) {
/* If an error occurred and a varname for error messages has been
specified, store the error message. */
SV *sv = perl_get_sv(errbufvarname, TRUE | GV_ADDMULTI); SV *sv = perl_get_sv(errbufvarname, TRUE | GV_ADDMULTI);
sv_setpv(sv, errbuf); sv_setpv(sv, errbuf);
} }
if (!RETVAL && (internal_options & USE_INTERNAL_VARS)) {
/* No error and internal variable for the content are to be used:
Split the data into headers and content and store them into
perl variables. */
SV *head_sv = perl_get_sv("Curl::easy::headers", TRUE | GV_ADDMULTI);
SV *cont_sv = perl_get_sv("Curl::easy::content", TRUE | GV_ADDMULTI);
char *p = contbuf;
int nl = 0, found = 0;
while (p < bufptr) {
if (nl && (*p == '\n' || *p == '\r')) {
/* found empty line, end of headers */
*p++ = '\0';
sv_setpv(head_sv, contbuf);
while (*p == '\n' || *p == '\r') {
p++;
}
sv_setpv(cont_sv, p);
found = 1;
break;
}
nl = (*p == '\n');
p++;
}
if (!found) {
sv_setpv(head_sv, "");
sv_setpv(cont_sv, contbuf);
}
}
OUTPUT: OUTPUT:
RETVAL RETVAL
@@ -249,6 +729,10 @@ void * curl
int option int option
double value double value
CODE: CODE:
#ifdef __GNUC__
/* a(void) warnig about unnused variable */
(void) value;
#endif
switch (option & CURLINFO_TYPEMASK) { switch (option & CURLINFO_TYPEMASK) {
case CURLINFO_STRING: { case CURLINFO_STRING: {
char * value = (char *)SvPV(ST(2), PL_na); char * value = (char *)SvPV(ST(2), PL_na);
@@ -282,8 +766,7 @@ curl_easy_cleanup(curl)
void * curl void * curl
CODE: CODE:
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
if (errbufvarname) free(errbufvarname); init_globals();
errbufvarname = NULL;
RETVAL = 0; RETVAL = 0;
OUTPUT: OUTPUT:
RETVAL RETVAL

View File

@@ -8,11 +8,14 @@
# Change 1..1 below to 1..last_test_to_print . # Change 1..1 below to 1..last_test_to_print .
# (It may become useful if the test is moved to ./t subdirectory.) # (It may become useful if the test is moved to ./t subdirectory.)
use Benchmark;
use strict;
BEGIN { $| = 1; print "1..5\n"; } BEGIN { $| = 1; print "1..13\n"; }
END {print "not ok 1\n" unless $loaded;} END {print "not ok 1\n" unless $::loaded;}
use Curl::easy; use Curl::easy;
$loaded = 1;
$::loaded = 1;
print "ok 1\n"; print "ok 1\n";
######################### End of black magic. ######################### End of black magic.
@@ -21,81 +24,292 @@ print "ok 1\n";
# (correspondingly "not ok 13") depending on the success of chunk 13 # (correspondingly "not ok 13") depending on the success of chunk 13
# of the test code): # of the test code):
print "Testing curl version ",&Curl::easy::version(),"\n";
# Read URL to get # Read URL to get
$defurl = "http://www/"; my $defurl = "http://localhost/cgi-bin/printenv";
$url = ""; my $url = "";
print "Please enter an URL to fetch [$defurl]: "; print "Please enter an URL to fetch [$defurl]: ";
$url = <STDIN>; $url = <STDIN>;
if ($url =~ /^\s*\n/) { if ($url =~ /^\s*\n/) {
$url = $defurl; $url = $defurl;
} }
# Use this for simple benchmarking
#for ($i=0; $i<1000; $i++) {
# Init the curl session # Init the curl session
if (($curl = Curl::easy::curl_easy_init()) != 0) { my $curl;
if (($curl = Curl::easy::init()) != 0) {
print "ok 2\n"; print "ok 2\n";
} else { } else {
print "ko 2\n"; print "ko 2\n";
} }
# Set URL to get
if (Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_URL, $url) == 0) {
print "ok 3\n";
} else {
print "ko 3\n";
}
# No progress meter please # No progress meter please
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_NOPROGRESS, 1); # !! Need this on for all tests, as once disabled, can't re-enable it...
#Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 1);
# Shut up completely # Shut up completely
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_MUTE, 1); Curl::easy::setopt($curl, CURLOPT_MUTE, 1);
# Follow location headers # Follow location headers
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_FOLLOWLOCATION, 1); Curl::easy::setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
# Set timeout # Set timeout
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_TIMEOUT, 30); Curl::easy::setopt($curl, CURLOPT_TIMEOUT, 30);
# Set file where to read cookies from # Set file where to read cookies from
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_COOKIEFILE, "cookies"); Curl::easy::setopt($curl, CURLOPT_COOKIEFILE, "cookies");
# Set file where to store the header # Set file where to store the header
open HEAD, ">head.out"; open HEAD, ">head.out";
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_WRITEHEADER, HEAD); Curl::easy::setopt($curl, CURLOPT_WRITEHEADER, *HEAD);
print "ok 3\n";
# Set file where to store the body # Set file where to store the body
open BODY, ">body.out"; # Send body to stdout - test difference between FILE * and SV *
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_FILE, BODY); #open BODY, ">body.out";
#Curl::easy::setopt($curl, CURLOPT_FILE,*BODY);
print "ok 4\n";
# Add some additional headers to the http-request:
my @myheaders;
$myheaders[0] = "Server: www";
$myheaders[1] = "User-Agent: Perl interface for libcURL";
Curl::easy::setopt($curl, Curl::easy::CURLOPT_HTTPHEADER, \@myheaders);
# Store error messages in variable $errbuf # Store error messages in variable $errbuf
# NOTE: The name of the variable is passed as a string! # NOTE: The name of the variable is passed as a string!
# curl_easy_setopt() creates a perl variable with that name, and # setopt() creates a perl variable with that name, and
# curl_easy_perform() stores the errormessage into it if an error occurs. # perform() stores the errormessage into it if an error occurs.
Curl::easy::curl_easy_setopt($curl, Curl::easy::CURLOPT_ERRORBUFFER, "errbuf");
Curl::easy::setopt($curl, CURLOPT_ERRORBUFFER, "errbuf");
Curl::easy::setopt($curl, CURLOPT_URL, $url);
print "ok 5\n";
my $bytes;
my $realurl;
my $httpcode;
my $errbuf;
# Go get it # Go get it
if (Curl::easy::curl_easy_perform($curl) == 0) { if (Curl::easy::perform($curl) == 0) {
Curl::easy::curl_easy_getinfo($curl, Curl::easy::CURLINFO_SIZE_DOWNLOAD, $bytes); Curl::easy::getinfo($curl, CURLINFO_SIZE_DOWNLOAD, $bytes);
print "ok 4: $bytes bytes read\n"; print "ok 6: $bytes bytes read\n";
print "check out the files head.out and body.out\n"; Curl::easy::getinfo($curl, CURLINFO_EFFECTIVE_URL, $realurl);
print "for the headers and content of the URL you just fetched...\n"; Curl::easy::getinfo($curl, CURLINFO_HTTP_CODE, $httpcode);
Curl::easy::curl_easy_getinfo($curl, Curl::easy::CURLINFO_EFFECTIVE_URL, $realurl);
Curl::easy::curl_easy_getinfo($curl, Curl::easy::CURLINFO_HTTP_CODE, $httpcode);
print "effective fetched url (http code: $httpcode) was: $url\n"; print "effective fetched url (http code: $httpcode) was: $url\n";
} else { } else {
# We can acces the error message in $errbuf here # We can acces the error message in $errbuf here
print "ko 4: '$errbuf'\n"; print "not ok 6: '$errbuf'\n";
die "basic url access failed";
}
# cleanup
#close HEAD;
# test here - BODY is still expected to be the output
# Curl-easy-1.0.2.pm core dumps if we 'perform' with a closed output FD...
#close BODY;
#exit;
#
# The header callback will only be called if your libcurl has the
# CURLOPT_HEADERFUNCTION supported, otherwise your headers
# go to CURLOPT_WRITEFUNCTION instead...
#
my $header_called=0;
sub header_callback { print "header callback called\n"; $header_called=1; return length($_[0])};
# test for sub reference and head callback
Curl::easy::setopt($curl, CURLOPT_HEADERFUNCTION, \&header_callback);
print "ok 7\n"; # so far so good
if (Curl::easy::perform($curl) != 0) {
print "not ";
};
print "ok 8\n";
print "next test will fail on libcurl < 7.7.2\n";
print "not " if (!$header_called); # ok if you have a libcurl <7.7.2
print "ok 9\n";
my $body_called=0;
sub body_callback {
my ($chunk,$handle)=@_;
print "body callback called with ",length($chunk)," bytes\n";
print "data=$chunk\n";
$body_called++;
return length($chunk); # OK
}
# test for ref to sub and body callback
my $body_ref=\&body_callback;
Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, $body_ref);
if (Curl::easy::perform($curl) != 0) {
print "not ";
};
print "ok 10\n";
print "not " if (!$body_called);
print "ok 11\n";
my $body_abort_called=0;
sub body_abort_callback {
my ($chunk,$sv)=@_;
print "body abort callback called with ",length($chunk)," bytes\n";
$body_abort_called++;
return -1; # signal a failure
}
# test we can abort a request mid-way
my $body_abort_ref=\&body_abort_callback;
Curl::easy::setopt($curl, CURLOPT_WRITEFUNCTION, $body_abort_ref);
if (Curl::easy::perform($curl) == 0) { # reverse test - this should have failed
print "not ";
};
print "ok 12\n";
print "not " if (!$body_abort_called); # should have been called
print "ok 13\n";
# reset to a working 'write' function for next tests
Curl::easy::setopt($curl,CURLOPT_WRITEFUNCTION, sub { return length($_[0])} );
# inline progress function
# tests for inline subs and progress callback
# - progress callback must return 'true' on each call.
my $progress_called=0;
sub prog_callb
{
my ($clientp,$dltotal,$dlnow,$ultotal,$ulnow)=@_;
print "\nperl progress_callback has been called!\n";
print "clientp: $clientp, dltotal: $dltotal, dlnow: $dlnow, ultotal: $ultotal, ";
print "ulnow: $ulnow\n";
$progress_called++;
return 0;
}
Curl::easy::setopt($curl, CURLOPT_PROGRESSFUNCTION, \&prog_callb);
# Turn progress meter back on - this doesn't work - once its off, its off.
Curl::easy::setopt($curl, CURLOPT_NOPROGRESS, 0);
if (Curl::easy::perform($curl) != 0) {
print "not ";
};
print "ok 14\n";
print "not " if (!$progress_called);
print "ok 15\n";
my $read_max=10;
sub read_callb
{
my ($maxlen,$sv)=@_;
print "\nperl read_callback has been called!\n";
print "max data size: $maxlen\n";
print "(upload needs $read_max bytes)\n";
print "context: ".$sv."\n";
if ($read_max > 0) {
print "\nEnter max ", $read_max, " characters to be uploaded.\n";
my $data = <STDIN>;
chomp $data;
$read_max=$read_max-length($data);
return $data;
} else {
return "";
}
}
#
# test post/read callback functions - requires a url which accepts posts, or it fails!
#
Curl::easy::setopt($curl,CURLOPT_READFUNCTION,\&read_callb);
Curl::easy::setopt($curl,CURLOPT_INFILESIZE,$read_max );
Curl::easy::setopt($curl,CURLOPT_UPLOAD,1 );
Curl::easy::setopt($curl,CURLOPT_CUSTOMREQUEST,"POST" );
if (Curl::easy::perform($curl) != 0) {
print "not ";
};
print "ok 16\n";
sub passwd_callb
{
my ($clientp,$prompt,$buflen)=@_;
print "\nperl passwd_callback has been called!\n";
print "clientp: $clientp, prompt: $prompt, buflen: $buflen\n";
print "\nEnter max $buflen characters for $prompt ";
my $data = <STDIN>;
chomp($data);
return (0,$data);
}
Curl::easy::cleanup($curl);
# Now do an ftp upload:
$defurl = "ftp://horn\@localhost//tmp/bla";
print "\n\nPlease enter an URL for ftp upload [$defurl]: ";
$url = <STDIN>;
if ($url =~ /^\s*\n/) {
$url = $defurl;
}
# Init the curl session
if (($curl = Curl::easy::init()) != 0) {
print "ok 17\n";
} else {
print "not ok 17\n";
}
# Set URL to get
if (Curl::easy::setopt($curl, Curl::easy::CURLOPT_URL, $url) == 0) {
print "ok 18\n";
} else {
print "not ok 18\n";
}
# Tell libcurl to to an upload
Curl::easy::setopt($curl, Curl::easy::CURLOPT_UPLOAD, 1);
# No progress meter please
#Curl::easy::setopt($curl, Curl::easy::CURLOPT_NOPROGRESS, 1);
# Use our own progress callback
Curl::easy::setopt($curl, Curl::easy::CURLOPT_PROGRESSFUNCTION, \&prog_callb);
# Shut up completely
Curl::easy::setopt($curl, Curl::easy::CURLOPT_MUTE, 1);
# Store error messages in $errbuf
Curl::easy::setopt($curl, Curl::easy::CURLOPT_ERRORBUFFER, "errbuf");
$read_max=10;
# Use perl read callback to read data to be uploaded
Curl::easy::setopt($curl, Curl::easy::CURLOPT_READFUNCTION,
\&read_callb);
# Use perl passwd callback to read password for login to ftp server
Curl::easy::setopt($curl, Curl::easy::CURLOPT_PASSWDFUNCTION, \&passwd_callb);
print "ok 19\n";
# Go get it
if (Curl::easy::perform($curl) == 0) {
Curl::easy::getinfo($curl, Curl::easy::CURLINFO_SIZE_UPLOAD, $bytes);
print "ok 20: $bytes bytes transferred\n\n";
} else {
# We can acces the error message in $errbuf here
print "not ok 20: '$errbuf'\n";
} }
# Cleanup # Cleanup
close HEAD; Curl::easy::cleanup($curl);
close BODY; print "ok 21\n";
Curl::easy::curl_easy_cleanup($curl);
print "ok 5\n";
# Use this for simple benchmarking
#}

View File

@@ -21,10 +21,14 @@
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
/* This is now designed to have its own local setup.h */
#include "setup.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <ctype.h> #include <ctype.h>
@@ -38,9 +42,6 @@
#define CURLseparator "--_curl_--" #define CURLseparator "--_curl_--"
/* This is now designed to have its own local setup.h */
#include "setup.h"
#if defined(WIN32)&&!defined(__CYGWIN32__) #if defined(WIN32)&&!defined(__CYGWIN32__)
#include <winsock.h> #include <winsock.h>
#endif #endif

View File

@@ -1,3 +1,3 @@
#define CURL_NAME "curl" #define CURL_NAME "curl"
#define CURL_VERSION "7.7.1" #define CURL_VERSION "7.7.2"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") " #define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "

View File

@@ -141,12 +141,12 @@ void ourWriteOut(CURL *curl, char *writeinfo)
case VAR_SIZE_UPLOAD: case VAR_SIZE_UPLOAD:
if(CURLE_OK == if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo)) curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo); fprintf(stream, "%.0f", doubleinfo);
break; break;
case VAR_SIZE_DOWNLOAD: case VAR_SIZE_DOWNLOAD:
if(CURLE_OK == if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &doubleinfo)) curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo); fprintf(stream, "%.0f", doubleinfo);
break; break;
case VAR_SPEED_DOWNLOAD: case VAR_SPEED_DOWNLOAD:
if(CURLE_OK == if(CURLE_OK ==