Compare commits

...

72 Commits

Author SHA1 Message Date
Daniel Stenberg
5d39dde961 pre-release commit 2000-05-30 16:31:46 +00:00
Daniel Stenberg
15c143bba9 modified to the new curl_getenv() style 2000-05-29 23:09:31 +00:00
Daniel Stenberg
6d522c9c1d made getenv() more threadsafe for win32 2000-05-29 23:07:22 +00:00
Daniel Stenberg
45885f30c2 updated 2000-05-29 22:54:17 +00:00
Daniel Stenberg
1ea12e705e had to add this since it was missing in the system includes! 2000-05-29 22:52:17 +00:00
Daniel Stenberg
a0ce95e155 David LeBlanc's fixes! 2000-05-29 22:51:13 +00:00
Daniel Stenberg
abc751ae13 generated with bison 1.28 which removes the alloca() mess! 2000-05-29 22:50:40 +00:00
Daniel Stenberg
b6d06a9590 URLGET_ERROR_SIZE is now CURL_ERROR_SIZE 2000-05-26 13:58:10 +00:00
Daniel Stenberg
784e9406ae silly mistake corrected 2000-05-26 13:57:11 +00:00
Daniel Stenberg
9e157ad2ec added the new man pages docs/*.3 2000-05-26 13:55:13 +00:00
Daniel Stenberg
85e6e935c5 updated 2000-05-26 11:59:43 +00:00
Daniel Stenberg
9a85060cde more documented stuff 2000-05-26 08:50:13 +00:00
Daniel Stenberg
fb3a5ab6ee fixed the CURL_ERROR_SIZE and renamed a urlget() leftover 2000-05-26 08:12:14 +00:00
Daniel Stenberg
52585e8b31 Added a list of stuff to do for version 7 2000-05-26 07:48:38 +00:00
Daniel Stenberg
3ad1df668e AIX wants sys/time.h included 2000-05-25 15:18:34 +00:00
Daniel Stenberg
d5bc98fcec added sys/time.h check 2000-05-25 15:18:02 +00:00
Daniel Stenberg
c10684ac3f fixed the new path to the curl man page 2000-05-24 22:56:00 +00:00
Daniel Stenberg
f81e775954 fixed the new docs path 2000-05-24 22:53:37 +00:00
Daniel Stenberg
e92a10c36f now splits the text into several puts() calls 2000-05-23 10:25:30 +00:00
Daniel Stenberg
9b20d0a47f Jrn's fixes mentioned 2000-05-22 19:15:18 +00:00
Daniel Stenberg
67fea90f3f moved many docs to the new docs/ dir 2000-05-22 19:13:37 +00:00
Daniel Stenberg
ceda25398b more changes! ;-) 2000-05-22 19:11:39 +00:00
Daniel Stenberg
285994a5ae slightly adjusted 2000-05-22 19:10:53 +00:00
Daniel Stenberg
e27e490c7e oops 2000-05-22 19:09:31 +00:00
Daniel Stenberg
dbd864a2a6 adjusted to work even without RTLD_GLOBAL defined 2000-05-22 19:04:18 +00:00
Daniel Stenberg
dc98405114 libcurl v7 adjustments 2000-05-22 19:02:54 +00:00
Daniel Stenberg
7c37c6a8e9 moved here from the root directory 2000-05-22 17:35:35 +00:00
Daniel Stenberg
4341671545 moved to the new docs/ directory 2000-05-22 17:33:31 +00:00
Daniel Stenberg
2bd72eb53d Jrn's fixes 2000-05-22 17:20:29 +00:00
Daniel Stenberg
c35238e0a3 Jrt Hartroth's updates 2000-05-22 17:18:55 +00:00
Daniel Stenberg
39b1801c63 moved here from the newlib branch 2000-05-22 17:17:57 +00:00
Daniel Stenberg
98e5d82a34 unused 2000-05-22 14:13:05 +00:00
Daniel Stenberg
96dde76b99 moved here from the newlib branch 2000-05-22 14:12:12 +00:00
Daniel Stenberg
fb9d1ff00f files moved to main branch from the newlib branch 2000-05-22 14:09:31 +00:00
Daniel Stenberg
c9053bf3d4 moved the win32 init stuff here from the lib 2000-05-17 21:21:10 +00:00
Daniel Stenberg
601b8e78c7 "Will you write a script for me getting ZZZ from YYY?" added 2000-05-14 15:33:47 +00:00
Daniel Stenberg
bc10563c98 Added BOTH nsl+socket lib check
Added HOST and TARGET checks
Added automatic update of the *spec.in files (Linux RPM stuff)
2000-05-14 15:21:45 +00:00
Daniel Stenberg
5330a85133 the last days' changes 2000-05-14 13:36:38 +00:00
Daniel Stenberg
95c2534a95 string checks added 2000-05-14 13:33:53 +00:00
Daniel Stenberg
febd0e7059 lots of stuff 2000-05-14 13:12:11 +00:00
Daniel Stenberg
984878ed7a Removed all #ifdef GLOBURL lines, we always use them 2000-05-09 22:42:53 +00:00
Daniel Stenberg
de275780a9 Support for systems where RTLD_LAZY_GLOBAL is defined instead of
RTLD_GLOBAL and RTLD_LAZY separately.
2000-05-09 22:23:55 +00:00
Daniel Stenberg
b64dd9c13f changed the glob_url() call, after Janne Johansson's buffer overflow report 2000-05-09 12:29:28 +00:00
Daniel Stenberg
fac113a275 configure having problem with openssl 2000-04-24 15:20:58 +00:00
Daniel Stenberg
89f05410d9 added a missing prototype, removed unused code 2000-04-11 21:48:33 +00:00
Daniel Stenberg
0d12792514 now uses a tiny bit of the new library interface! 2000-04-11 21:47:28 +00:00
Daniel Stenberg
7aae77f0fd Added Darwin to the list of platforms 2000-04-10 18:05:29 +00:00
Daniel Stenberg
72cb0f7a69 updated the ports list 2000-04-08 20:45:42 +00:00
Daniel Stenberg
d0e640deba Added the *spec.in files 2000-04-08 19:33:11 +00:00
Daniel Stenberg
f9ec7d3a0f new files to generate .spec files automatically 2000-04-08 19:32:40 +00:00
Daniel Stenberg
75cd7f482d now sends user agent to all requests that go through a http proxy 2000-04-08 19:29:58 +00:00
Daniel Stenberg
eb856b04fe Improved the looks of the progress meter when the file size is between
9999 KB and 100 MB since it then can display the size as XX.X MB instead of
just XX as before.
2000-04-08 19:28:23 +00:00
Daniel Stenberg
cd9ad9e54b some rpm build improvements
adjusted progress bar
user agent sent when talking non-http through a http proxy
2000-04-08 19:27:06 +00:00
Daniel Stenberg
c30a3913b5 Marco's fix got adjusted 2000-04-04 18:08:34 +00:00
Daniel Stenberg
d620ada259 two location problems and one OS/2 patch 2000-04-04 17:47:05 +00:00
Daniel Stenberg
00ad88408d Marco G. Salvagno's OS/2 patch is applied 2000-04-04 17:44:24 +00:00
Daniel Stenberg
d62d25bdb4 Marco G. Salvagno's patch applied 2000-04-04 17:42:43 +00:00
Daniel Stenberg
ae6a5018dd added INTERNALS 2000-04-02 18:28:26 +00:00
Daniel Stenberg
c0c225b938 describes internal code design 2000-04-02 18:09:50 +00:00
Daniel Stenberg
0059911261 James Atwill correctly pointed out that curl didn't follow Location: headers
properly when the new URL is an absolute one to a different port than the
first URL...
2000-04-02 12:08:12 +00:00
Daniel Stenberg
e67157b5a2 Added some more explanatory text about HTTP posts 2000-03-27 21:42:40 +00:00
Daniel Stenberg
2f668aba96 "H. Daphne Luong" <daphne@tellme.com> pointed out that curl cannot destroy
the proxy server data internally as it did, since when doing a location:
following it needs the proxy server string several times.
2000-03-27 21:36:05 +00:00
Daniel Stenberg
4a33436663 spelling errors corrected 2000-03-23 11:02:08 +00:00
Daniel Stenberg
0eb1f1e5d0 download.c, configure, VC fix and OS/2 fix 2000-03-23 10:43:14 +00:00
Daniel Stenberg
9849c76d88 yet another tiny OS/2 fix 2000-03-23 10:41:39 +00:00
Daniel Stenberg
e541da93fe in case the select() returns -1 and errno is EINTR, it should not abort
the download (MT-adjustment)
2000-03-23 10:41:16 +00:00
Daniel Stenberg
0fac349c62 Wham Bang's fixes 2000-03-23 10:40:14 +00:00
Daniel Stenberg
83acbda569 Troy Engel's latest updates 2000-03-23 10:39:38 +00:00
Daniel Stenberg
1acda9ef9c HAVE_UNAME was bad
HAVE_UNISTD_H is now not set if VC6 is defined
2000-03-23 10:39:00 +00:00
Daniel Stenberg
20161c38f2 Added a question about other SSL libraries 2000-03-23 10:36:49 +00:00
Daniel Stenberg
7b6394b75a just a little reformatted 2000-03-23 09:33:03 +00:00
Daniel Stenberg
d1a1fcc6f1 removed the double BSD install check 2000-03-21 17:12:27 +00:00
91 changed files with 5584 additions and 2905 deletions

174
CHANGES
View File

@@ -6,19 +6,151 @@
History of Changes History of Changes
Daniel (29 May 2000)
- Corrected the bits.* assignments when using CURLOPT options that only
toggles one of those bits.
- Applied the huge patches from David LeBlanc <dleblanc at qnx.com> that add
usage of the gethostbyname_r() and similar functions in case they're around,
since that make libcurl much better threadsafe in many systems (such as
solaris). I added the checks for these functions to the configure script.
I can't explain why, but the inet_ntoa_r() function did not appear in my
Solaris include files, I had to add my own include file for this for now.
Daniel (22 May 2000)
- J<>rn Hartroth brought me fixes to make the win32 version compile properly as
well as a rename of the 'interface' field in the urldata struct, as it seems
to be reserved in some gcc versions!
- Rich Gray struck back with yet some portability reports. Data General DG/UX
needed a little fix in lib/ldap.c since it doesn't have RTLD_GLOBAL defined.
More fixes are expected as a result of Richies very helpful work.
Version 7.0.1beta released
Daniel (21 May 2000)
- Updated lots of #defines, enums and variable type names in the library. No
more weird URG or URLTAG prefixes. All types and names should be curl-
prefixed to avoid name space clashes. The FLAGS-parameter to the former
curl_urlget() has been converted into a bunch of flags to use in separate
setopt calls. I'm still focusing on the easy-interface, as the curl tool is
now using that.
- Bjorn Reese has provided me with an asynchronous name resolver that I plan
to use in upcoming versions of curl to be able to gracefully timeout name
lookups.
Version 7.0beta released
Daniel (18 May 2000)
- Introduced LIBCURL_VERSION_NUM to the curl.h include file to better allow
source codes to be dependent on the lib version. This define is now set to
a dexadecimal number, with 8 bits each for major number, minor number and
patch number. In other words, version 1.2.3 would make it 0x010203. It also
makes a larger number a newer version.
Daniel (17 May 2000)
- Martin Kammerhofer correctly pointed out several flaws in the FTP range
option. I corrected them.
- Removed the win32 winsock init crap from the lib to the src/main.c file
in the application instead. They can't be in the lib, especially not for
multithreaded purposes.
Daniel (16 May 2000)
- Rewrote the src/main.c source to use the new easy-interface to libcurl 7.
There is still more work to do, but the first step is now taken.
<curl/easy.h> is the include file to use.
Daniel (14 May 2000)
- FTP URLs are now treated slightly different, more according to RFC 1738.
- FTP sessions are now performed differently, with CWD commands to change
directory instead of RETR/STOR/LIST with the full path. Discussions with
Rich Gray made me notice these problems.
- Janne Johansson discovered and corrected a buffer overflow in the
src/usrglob.c file.
- I had to add a lib/strequal.c file for doing case insensitive string
compares on all platforms.
Daniel (8 May 2000):
- Been working lots on the new lib.
- Together with Rich Gray, I've tried to adjust the configure script to work
better on the NCR MP-RAS Unix.
Daniel (2 May 2000):
- Albert Chin-A-Young pointed out that I had a few too many instructions in
configure.in that didn't do any good.
Daniel (24 April 2000):
- Added a new paragraph to the FAQ about what to do when configure can't
find OpenSSL even though it is installed. Supplied by Bob Allison
<allisonb@users.sourceforge.net>.
Daniel (12 April 2000):
- Started messing around big-time to convert the old library interface to a
better one...
Daniel (8 April 2000):
- Made the progress bar look better for file sizes between 9999 kilobytes
and 100 megabytes. They're now displayed XX.XM.
- I also noticed that ftp fetches through HTTP proxies didn't add the user
agent string. It does now.
- Habibie <habibie@MailandNews.com> supplied a pretty good way to build RPMs
on a Linux machine. It still a) requires me to be root to do it, b) leaves
the rpm packages laying at some odd place on my disk c) doesn't work to
build the ssl version of curl since I didn't install openssl from an rpm
package so now the rpm crap thinks I don't have openssl and refuses to build
a package that depends on ssl... Did I mention I don't get along with RPM?
- Once again I received a bug report about autoconf not setting -L prior to -l
on the command line when checking for libs. In this case it made the native
cc compiler on Solaris 7 to fail the OpenSSL check. This has previously been
reported to cause problems on HP-UX and is a known flaw in autoconf 2.13. It
is a pity there's no newer release around...
Daniel (4 April 2000):
- Marco G. Salvagno <mgs@whiz.cjb.net> supplied me with two fixes that
appearantly makes the OS/2 port work better with multiple URLs.
Daniel (2 April 2000):
- Another Location: fix. This time, when curl connected to a port and then
followed a location with an absolute URL to another port, it misbehaved.
Daniel (27 March 2000):
- H. Daphne Luong <daphne@tellme.com> pointed out that curl was wrongly
messing up the proxy string when fetching a document through a http proxy,
which screwed up multiple fetches such as in location: followings.
Daniel (23 March 2000):
- Marco G. Salvagno <mgs@whiz.cjb.net> corrected my badly applied patch he
actually already told me about!
- H. Daphne Luong <daphne@tellme.com> brought me a fix that now makes curl
ignore select() errors in the download if errno is EINTR, which turns out to
happen every now and then when using libcurl multi-threaded...
Daniel (22 March 2000):
- Wham Bang <wham_bang@yahoo.com> supplied a couple of win32 fixes. HAVE_UNAME
was accidentally #defined in config-win32.h, which it shouldn't have been.
The HAVE_UNISTD_H is not defined when compiling with the Makefile.vc6
makefile for MS VC++.
Daniel (21 March 2000):
- I removed the AC_PROG_INSTALL macro from configure.in, since it appears that
one of the AM_* macros searches for a BSD compatible install already. Janne
Johansson made me aware of this.
Version 6.5.2 Version 6.5.2
Daniel (21 March 2000): Daniel (21 March 2000):
- Paul Harrington <paul@pizza.org> quickly pointed out to me that 6.5.1 - Paul Harrington <paul@pizza.org> quickly pointed out to me that 6.5.1
crashes hard. I upload 6.5.2 now as quickly as possible! The problem was crashes hard. I upload 6.5.2 now as quickly as possible! The problem was
the -D adjustments in src/main.c, see also a separate 6.5.1-patch on the the -D adjustments in src/main.c.
web site.
Version 6.5.1 Version 6.5.1
Daniel (20 March 2000): Daniel (20 March 2000):
- An anynomous post on sourceforge correctly pointed out a possible buffer - An anonymous post on sourceforge correctly pointed out a possible buffer
overflow in the curl_unescape() function for URL convertions. The main overflow in the curl_unescape() function for URL conversions. The main
problem with this bug is that the ftp download uses that function and this problem with this bug is that the ftp download uses that function and this
single- byte overflow could lead to very odd bugs (as one reported by Janne single- byte overflow could lead to very odd bugs (as one reported by Janne
Johansson). Johansson).
@@ -29,10 +161,10 @@ Daniel (19 March 2000):
the INSTALL file. Very nice job! the INSTALL file. Very nice job!
Daniel (17 March 2000): Daniel (17 March 2000):
- Wham Bang <wham_bang@yahoo.com> (is that Pascal Gaudette?) supplied a patch - Wham Bang <wham_bang@yahoo.com> supplied a patch for the lib/Makefile.vc6
for the lib/Makefile.vc6 file. We still need some fixes for the file. We still need some fixes for the config-win32.h since it appears that
config-win32.h since it appears that VC++ and mingw32 have different VC++ and mingw32 have different opinions about (at least) unistd.h's
opinions about (at least) unistd.h's existance. existence.
Daniel (15 March 2000): Daniel (15 March 2000):
- I modified the -D/--dump-header workings so that it doesn't write anything - I modified the -D/--dump-header workings so that it doesn't write anything
@@ -85,13 +217,13 @@ Daniel (2 March 2000):
- J<>rn Hartroth <Joern.Hartroth@telekom.de>, Chris <cbayliss@csc.come> and Ulf - J<>rn Hartroth <Joern.Hartroth@telekom.de>, Chris <cbayliss@csc.come> and Ulf
M<>ller from the openssl development team helped bringing me the details for M<>ller from the openssl development team helped bringing me the details for
fixing an OpenSSL usage flaw. It became appearant when they released openssl fixing an OpenSSL usage flaw. It became apparent when they released openssl
0.9.5 since that barfed on curl's bad behaviour (not seeding a random number 0.9.5 since that barfed on curl's bad behavior (not seeding a random number
thing). thing).
- Yet another option: -N/--no-buffer disables buffering in the output stream. - Yet another option: -N/--no-buffer disables buffering in the output stream.
Probably most useful for very slow transfers when you really want to get Probably most useful for very slow transfers when you really want to get
every byte curl receives within some prefered time. Andrew <tmr@gci.net> every byte curl receives within some preferred time. Andrew <tmr@gci.net>
suggested this. suggested this.
- Damien Adant <dams@usa.net> mailed me his fixes for making curl compile - Damien Adant <dams@usa.net> mailed me his fixes for making curl compile
@@ -124,7 +256,7 @@ Daniel (21 February 2000):
- I added the -w/--write-out flag and some variables to go with it. -w is a - I added the -w/--write-out flag and some variables to go with it. -w is a
single string, whatever you enter there will be written out when curl has single string, whatever you enter there will be written out when curl has
completed a successful request. There are some variable substitutions and completed a successful request. There are some variable substitutions and
they are specifed as '%{variable}' (without the quotes). Variables that they are specified as '%{variable}' (without the quotes). Variables that
exist as of this moment are: exist as of this moment are:
total_time - total transfer time in seconds (with 2 decimals) total_time - total transfer time in seconds (with 2 decimals)
@@ -158,7 +290,7 @@ Daniel (11 February 2000):
- Eetu Ojanen <esojanen@jyu.fi>'s suggestion of supporting the @-style for -b - Eetu Ojanen <esojanen@jyu.fi>'s suggestion of supporting the @-style for -b
is implemented. Now -b@<filename> works as well as the old style. -b@- also is implemented. Now -b@<filename> works as well as the old style. -b@- also
similarily reads the cookies from stdin. similarly reads the cookies from stdin.
- Reminder: -D should not write to the file until it needs to, in the same way - Reminder: -D should not write to the file until it needs to, in the same way
-o does. That would enable curl to use -b and -D on the same file... -o does. That would enable curl to use -b and -D on the same file...
@@ -166,7 +298,7 @@ Daniel (11 February 2000):
- Ellis Pritchard <ellis@citria.com> made getdate.y work for MacOS X. - Ellis Pritchard <ellis@citria.com> made getdate.y work for MacOS X.
- Paul Harrington <paul@pizza.org> helped me out finding the crash in the - Paul Harrington <paul@pizza.org> helped me out finding the crash in the
cookie parser. He also pointed out curl's habbit of sending empty cookies to cookie parser. He also pointed out curl's habit of sending empty cookies to
the server. the server.
Daniel (8 February 2000): Daniel (8 February 2000):
@@ -196,7 +328,7 @@ Daniel (31 January 2000):
and let them get "uploaded" in Transfer() as well. and let them get "uploaded" in Transfer() as well.
- Zhibiao Wu <wuzb@erols.com> pointed out a curl bug in the location: area, - Zhibiao Wu <wuzb@erols.com> pointed out a curl bug in the location: area,
although I did not get a reproducable way to do this why I have to wait although I did not get a reproducible way to do this why I have to wait
with fixing anything. with fixing anything.
- Bob Schader <rschader@product-des.com> suggested I should implement resume - Bob Schader <rschader@product-des.com> suggested I should implement resume
@@ -251,7 +383,7 @@ Daniel (10 January 2000):
- Jim Gallagher <jmgallag@usa.net> properly tracked down a bug in autoconf - Jim Gallagher <jmgallag@usa.net> properly tracked down a bug in autoconf
2.13. The AC_CHECK_LIB() macro wrongfully uses the -l flag before the -L 2.13. The AC_CHECK_LIB() macro wrongfully uses the -l flag before the -L
flag to 'ld' which causes the HP-UX 10.20 flavour to fail on all libchecks flag to 'ld' which causes the HP-UX 10.20 flavour to fail on all libchecks
and thefore you can't make the configure script find the openssl libs! and therefore you can't make the configure script find the openssl libs!
Daniel (28 December 1999): Daniel (28 December 1999):
- Tim Verhoeven <dj@walhalla.sin.khk.be> correctly identified that curl - Tim Verhoeven <dj@walhalla.sin.khk.be> correctly identified that curl
@@ -265,7 +397,7 @@ Daniel (28 December 1999):
Daniel (27 December 1999): Daniel (27 December 1999):
- When curl parsed cookies straight off a remote site, it corrupted the input - When curl parsed cookies straight off a remote site, it corrupted the input
data, which, if the downloaded headers were stored made very odd characters data, which, if the downloaded headers were stored made very odd characters
in the saved data. Correctfully identified and reported by Paul Harrington in the saved data. Correctly identified and reported by Paul Harrington
<paul@pizza.org>. <paul@pizza.org>.
Daniel (13 December 1999): Daniel (13 December 1999):
@@ -344,7 +476,7 @@ Version 6.3
Daniel (8 November 1999): Daniel (8 November 1999):
- I made the -b/--cookie option capable of reading netscape formatted cookie - I made the -b/--cookie option capable of reading netscape formatted cookie
files as well as normal http-header files. It should be able to files as well as normal http-header files. It should be able to
transparantly figure out what kind of file it got as input. transparently figure out what kind of file it got as input.
Daniel (29 October 1999): Daniel (29 October 1999):
- Another one of Sebastiaan van Erk's ideas (that has been requested before - Another one of Sebastiaan van Erk's ideas (that has been requested before
@@ -364,7 +496,7 @@ Version 6.3
makes sense since if you access ftp through a HTTP proxy, you'd get the makes sense since if you access ftp through a HTTP proxy, you'd get the
file size the same way. file size the same way.
I changed the order of the QUOTE command execusions. They're now executed I changed the order of the QUOTE command executions. They're now executed
just after the login and before any other command. I made this to enable just after the login and before any other command. I made this to enable
quote commands to run before the -I stuff is done too. quote commands to run before the -I stuff is done too.
@@ -610,7 +742,7 @@ Version 5.10
OpenSSL. Now why couldn't they simply add a *new* function instead of OpenSSL. Now why couldn't they simply add a *new* function instead of
modifying the parameters of an already existing function? This way, we get modifying the parameters of an already existing function? This way, we get
a compiler warning if compiling with 0.9.4 but not with earlier. So, I had a compiler warning if compiling with 0.9.4 but not with earlier. So, I had
to come up with a #if contruction that deals with this... to come up with a #if construction that deals with this...
- Made curl output the SSL version number get displayed properly with 0.9.4. - Made curl output the SSL version number get displayed properly with 0.9.4.
@@ -694,7 +826,7 @@ Version 5.10
T. Yamada <tai@imasy.or.jp> (30 July 1999) T. Yamada <tai@imasy.or.jp> (30 July 1999)
- It breaks with segfault when 1) curl is using .netrc to obtain - It breaks with segfault when 1) curl is using .netrc to obtain
username/password (option '-n'), and 2) is auto-matically redirected to username/password (option '-n'), and 2) is automatically redirected to
another location (option '-L'). another location (option '-L').
There is a small bug in lib/url.c (block starting from line 641), which There is a small bug in lib/url.c (block starting from line 641), which

23
FILES
View File

@@ -1,19 +1,22 @@
BUGS
CHANGES CHANGES
CONTRIBUTE
FEATURES
FAQ
FILES FILES
INSTALL
LEGAL LEGAL
MPL-1.0.txt MPL-1.0.txt
README README
README.curl
README.libcurl
curl.1
*spec *spec
RESOURCES *spec.in
TODO docs/BUGS
docs/CONTRIBUTE
docs/FAQ
docs/FEATURES
docs/INSTALL
docs/INTERNALS
docs/README.curl
docs/README.libcurl
docs/RESOURCES
docs/TODO
docs/curl.1
docs/*.3
maketgz maketgz
Makefile.in Makefile.in
Makefile.am Makefile.am

View File

@@ -4,7 +4,7 @@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
man_MANS = curl.1 man_MANS = docs/curl.1
EXTRA_DIST = $(man_MANS) EXTRA_DIST = $(man_MANS)

View File

@@ -1,108 +0,0 @@
_ _ _ _
| (_) |__ ___ _ _ _ __| |
| | | '_ \ / __| | | | '__| |
| | | |_) | (__| |_| | | | |
|_|_|_.__/ \___|\__,_|_| |_|
How To Use Libcurl In Your Program:
(by Ralph Beckmann <rabe@uni-paderborn.de>)
NOTE: If you plan to use libcurl.a in Threads under Linux, do not use the old
gcc-2.7.x because the function 'gethostbyname' seems not to be thread-safe,
that is to say an unavoidable SEGMENTATION FAULT might occur.
1. a) In a C-Program:
#include "curl.h"
b) In a C++-Program:
extern "C" {
#include "curl.h"
}
2. char *url="http://www.domain.com";
curl_urlget (URGTAG_URL, url,
URGTAG_FLAGS, CONF_NOPROGRESS,
URGTAG_ERRORBUFFER, errorBuffer,
URGTAG_WRITEFUNCTION, (size_t (*)(void *, int, int, FILE
*))handle_data,
URGTAG_TIMEOUT, 30, /* or anything You want */
...
URGTAG_DONE);
3. size_t handle_data (const void *ptr, size_t size, size_t nitems,
FILE *stream)
{
(void)stream; /* stop complaining using g++ -Wall */
if ((int)nitems <= 0) {
return (size_t)0;
}
fprintf(stdout, (char *)ptr); /* or do anything else with it */
return nitems;
}
4. Compile Your Program with -I$(CURL_DIR)/include
5. Link Your Program together with $(CURL_DIR)/lib/libcurl.a
Small Example of How To Use libcurl
----------------------------------------------------------------------
/* Full example that uses libcurl.a to fetch web pages. */
/* curlthreads.c */
/* - Test-Program by Ralph Beckmann for using curl in POSIX-Threads */
/* Change *url1 and *url2 to textual long and slow non-FRAMESET websites! */
/*
1. Compile with gcc or g++ as $(CC):
$(CC) -c -Wall -pedantic curlthreads.c -I$(CURL_DIR)/include
2. Link with:
- Linux:
$(CC) -o curlthreads curlthreads.o $(CURL_DIR)/lib/libcurl.a -lpthread
-lm
- Solaris:
$(CC) -o curlthreads curlthreads.o $(CURL_DIR)/lib/libcurl.a -lpthread
-lm -lsocket -lnsl
*/
#include <pthread.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#include "curl.h"
}
#else
#include "curl.h"
#endif
size_t storedata (const void *ptr, size_t size, size_t nitems, FILE *stream) {
(void)ptr; (void)stream; /* just to stop g++ -Wall complaining */
fprintf(stdout, "Thread #%i reads %i Bytes.\n",
(int)pthread_self(), (int)(nitems*size));
return (nitems);
}
void *urlfetcher(void *url) {
curl_urlget (URGTAG_URL, url,
URGTAG_FLAGS, CONF_NOPROGRESS | CONF_FAILONERROR,
URGTAG_WRITEFUNCTION, (size_t (*)(void *, int, int, FILE
*))storedata,
URGTAG_DONE);
return NULL;
}
int main(void) {
char *url1="www.sun.com";
char *url2="www.microsoft.com";
pthread_t thread_id1, thread_id2;
pthread_create(&thread_id1, NULL, urlfetcher, (void *)url1);
pthread_create(&thread_id2, NULL, urlfetcher, (void *)url2);
pthread_join(thread_id1, NULL);
pthread_join(thread_id2, NULL);
fprintf(stdout, "Ready.\n");
return 0;
}

View File

@@ -71,6 +71,9 @@
/* Define if you have the strcasecmp function. */ /* Define if you have the strcasecmp function. */
/*#define HAVE_STRCASECMP 1*/ /*#define HAVE_STRCASECMP 1*/
/* Define if you have the stricmp function. */
#define HAVE_STRICMP 1
/* Define if you have the strdup function. */ /* Define if you have the strdup function. */
#define HAVE_STRDUP 1 #define HAVE_STRDUP 1
@@ -87,7 +90,7 @@
/*#define HAVE_TCSETATTR 1*/ /*#define HAVE_TCSETATTR 1*/
/* Define if you have the uname function. */ /* Define if you have the uname function. */
#define HAVE_UNAME 1 /*#define HAVE_UNAME 1*/
/* Define if you have the <alloca.h> header file. */ /* Define if you have the <alloca.h> header file. */
/*#define HAVE_ALLOCA_H 1*/ /*#define HAVE_ALLOCA_H 1*/
@@ -146,15 +149,9 @@
/* Define if you have the <termios.h> header file. */ /* Define if you have the <termios.h> header file. */
#define HAVE_TERMIOS_H 1 #define HAVE_TERMIOS_H 1
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Name of package */ /* Name of package */
#define PACKAGE "curl" #define PACKAGE "curl"
/* Version number of package */
#define VERSION "6.3.1"
/* Define if you have the <io.h> header file. */ /* Define if you have the <io.h> header file. */
#define HAVE_IO_H 1 #define HAVE_IO_H 1
@@ -172,3 +169,13 @@
/* Define if you have the RAND_screen function when using SSL */ /* Define if you have the RAND_screen function when using SSL */
#define HAVE_RAND_SCREEN 1 #define HAVE_RAND_SCREEN 1
/*************************************************
* This section is for compiler specific defines.*
*************************************************/
#ifndef VC6 /* VC6 => Microsoft Visual C++ 6 */
/* Define if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
#endif

View File

@@ -49,6 +49,12 @@
/* Define if you have the gethostbyaddr function. */ /* Define if you have the gethostbyaddr function. */
#undef HAVE_GETHOSTBYADDR #undef HAVE_GETHOSTBYADDR
/* Define if you have the gethostbyaddr_r function. */
#undef HAVE_GETHOSTBYADDR_R
/* Define if you have the gethostbyname_r function. */
#undef HAVE_GETHOSTBYNAME_R
/* Define if you have the gethostname function. */ /* Define if you have the gethostname function. */
#undef HAVE_GETHOSTNAME #undef HAVE_GETHOSTNAME
@@ -67,6 +73,9 @@
/* Define if you have the inet_ntoa function. */ /* Define if you have the inet_ntoa function. */
#undef HAVE_INET_NTOA #undef HAVE_INET_NTOA
/* Define if you have the inet_ntoa_r function. */
#undef HAVE_INET_NTOA_R
/* Define if you have the perror function. */ /* Define if you have the perror function. */
#undef HAVE_PERROR #undef HAVE_PERROR
@@ -82,12 +91,18 @@
/* Define if you have the strcasecmp function. */ /* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP #undef HAVE_STRCASECMP
/* Define if you have the strcmpi function. */
#undef HAVE_STRCMPI
/* Define if you have the strdup function. */ /* Define if you have the strdup function. */
#undef HAVE_STRDUP #undef HAVE_STRDUP
/* Define if you have the strftime function. */ /* Define if you have the strftime function. */
#undef HAVE_STRFTIME #undef HAVE_STRFTIME
/* Define if you have the stricmp function. */
#undef HAVE_STRICMP
/* Define if you have the strstr function. */ /* Define if you have the strstr function. */
#undef HAVE_STRSTR #undef HAVE_STRSTR
@@ -184,6 +199,9 @@
/* Define if you have the <sys/stat.h> header file. */ /* Define if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H #undef HAVE_SYS_STAT_H
/* Define if you have the <sys/time.h> header file. */
#undef HAVE_SYS_TIME_H
/* Define if you have the <sys/types.h> header file. */ /* Define if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H #undef HAVE_SYS_TYPES_H

View File

@@ -2,11 +2,12 @@ dnl $Id$
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(lib/urldata.h) AC_INIT(lib/urldata.h)
AM_CONFIG_HEADER(config.h src/config.h) AM_CONFIG_HEADER(config.h src/config.h)
AM_INIT_AUTOMAKE(curl,"6.5.2") AM_INIT_AUTOMAKE(curl,"7.0.1beta")
dnl Checks for programs. dnl Checks for programs.
AC_PROG_CC AC_PROG_CC
AC_PROG_INSTALL dnl The install stuff has already been taken care of by the automake stuff
dnl AC_PROG_INSTALL
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
dnl Check for AIX weirdos dnl Check for AIX weirdos
@@ -130,6 +131,7 @@ AC_CHECK_HEADERS( \
sys/sockio.h \ sys/sockio.h \
sys/stat.h \ sys/stat.h \
sys/types.h \ sys/types.h \
sys/time.h \
getopt.h \ getopt.h \
sys/param.h \ sys/param.h \
termios.h \ termios.h \
@@ -173,12 +175,17 @@ AC_CHECK_FUNCS( socket \
strftime \ strftime \
uname \ uname \
strcasecmp \ strcasecmp \
stricmp \
strcmpi \
gethostname \ gethostname \
gethostbyname_r \
gethostbyaddr \ gethostbyaddr \
gethostbyaddr_r \
getservbyname \ getservbyname \
gettimeofday \ gettimeofday \
inet_addr \ inet_addr \
inet_ntoa \ inet_ntoa \
inet_ntoa_r \
tcsetattr \ tcsetattr \
tcgetattr \ tcgetattr \
perror \ perror \
@@ -189,8 +196,6 @@ AC_CHECK_FUNCS( socket \
RAND_screen RAND_screen
) )
AC_PATH_PROG( PERL, perl, , AC_PATH_PROG( PERL, perl, ,
$PATH:/usr/local/bin/perl:/usr/bin/:/usr/local/bin ) $PATH:/usr/local/bin/perl:/usr/bin/:/usr/local/bin )
AC_SUBST(PERL) AC_SUBST(PERL)

View File

@@ -1,6 +1,6 @@
%define name curl-ssl %define name curl-ssl
%define tarball curl %define tarball curl
%define version 6.0 %define version 6.5.2
%define release 1 %define release 1
%define prefix /usr/local %define prefix /usr/local
@@ -35,11 +35,12 @@ rm -rf %{builddir}
%setup -n %{tarball}-%{version} %setup -n %{tarball}-%{version}
%build %build
CFLAGS=$RPM_OPT_FLAGS ./configure --prefix=$RPM_BUILD_ROOT%{prefix} --with-ssl CFLAGS=$RPM_OPT_FLAGS ./configure --prefix=$RPM_BUILD_ROOT%{prefix}
make CFLAGS="-DUSE_SSLEAY -I/usr/include/openssl" make
%install %install
make install-strip make install-strip
install -m 0644 curl.1 $RPM_BUILD_ROOT%{prefix}/man/man1
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
@@ -48,5 +49,6 @@ rm -rf %{builddir}
%files %files
%defattr(-,root,root) %defattr(-,root,root)
%attr(0755,root,root) %{prefix}/bin/curl %attr(0755,root,root) %{prefix}/bin/curl
%doc curl.1 README* CHANGES CONTRIBUTE FAQ FILES INSTALL LEGAL MPL-1.0.txt RESOURCES TODO perl/ %attr(0644,root,root) %{prefix}/man/man1/curl.1
%doc BUGS CHANGES CONTRIBUTE FAQ FEATURES FILES INSTALL LEGAL MPL-1.0.txt README* RESOURCES TODO

98
curl-ssl.spec.in Normal file
View File

@@ -0,0 +1,98 @@
%define ver @VERSION@
%define rel 1
%define prefix /usr
Summary: get a file from a FTP, GOPHER or HTTP server.
Name: @PACKAGE@-ssl
Version: %ver
Release: %rel
Copyright: MPL
Group: Utilities/Console
Source: @PACKAGE@-%{version}.tar.gz
URL: http://@PACKAGE@.haxx.nu
BuildPrereq: openssl
BuildRoot: /tmp/%{name}-%{version}-%{rel}-root
Packager: Fill In As You Wish
Docdir: %{prefix}/doc
%description
@PACKAGE@-ssl is a client to get documents/files from servers, using
any of the supported protocols. The command is designed to
work without user interaction or any kind of interactivity.
@PACKAGE@-ssl offers a busload of useful tricks like proxy support,
user authentication, ftp upload, HTTP post, file transfer
resume and more.
Note: this version is compiled with SSL (https:) support.
Authors:
Daniel Stenberg <Daniel.Stenberg@haxx.nu>
%prep
%setup -n @PACKAGE@-@VERSION@
%build
# Needed for snapshot releases.
if [ ! -f configure ]; then
CONF="./autogen.sh"
else
CONF="./configure"
fi
#
# Configuring the package
#
CFLAGS="${RPM_OPT_FLAGS}" ${CONF} \
--prefix=%{prefix} \
--with-ssl
[ "$SMP" != "" ] && JSMP = '"MAKE=make -k -j $SMP"'
make ${JSMP} CFLAGS="-DUSE_SSLEAY -I/usr/include/openssl";
%install
[ -d ${RPM_BUILD_ROOT} ] && rm -rf ${RPM_BUILD_ROOT}
make prefix=${RPM_BUILD_ROOT}%{prefix} install-strip
#
# Generating file lists and store them in file-lists
# Starting with the directory listings
#
find ${RPM_BUILD_ROOT}%{prefix}/{bin,lib,man} -type d | sed "s#^${RPM_BUILD_ROOT}#\%attr (-\,root\,root) \%dir #" > file-lists
#
# Then, the file listings
#
echo "%defattr (-, root, root)" >> file-lists
find ${RPM_BUILD_ROOT}%{prefix} -type f | sed -e "s#^${RPM_BUILD_ROOT}##g" >> file-lists
%clean
(cd ..; rm -rf @PACKAGE@-@VERSION@ ${RPM_BUILD_ROOT})
%files -f file-lists
%defattr (-, root, root)
%doc BUGS
%doc CHANGES
%doc CONTRIBUTE
%doc FAQ
%doc FEATURES
%doc FILES
%doc INSTALL
%doc LEGAL
%doc MPL-1.0.txt
%doc README
%doc README.curl
%doc README.lib@PACKAGE@
%doc RESOURCES
%doc TODO
%doc %{name}-ssl.spec.in
%doc %{name}.spec.in

View File

@@ -1,5 +1,5 @@
%define name curl %define name curl
%define version 6.0 %define version 6.5.2
%define release 1 %define release 1
%define prefix /usr/local %define prefix /usr/local
@@ -35,11 +35,12 @@ rm -rf %{builddir}
%build %build
export CFLAGS=$RPM_OPT_FLAGS export CFLAGS=$RPM_OPT_FLAGS
./configure --prefix=$RPM_BUILD_ROOT%{prefix} ./configure --prefix=$RPM_BUILD_ROOT%{prefix} --without-ssl
make make
%install %install
make install-strip make install-strip
install -m 0644 curl.1 $RPM_BUILD_ROOT%{prefix}/man/man1
%clean %clean
rm -rf $RPM_BUILD_ROOT rm -rf $RPM_BUILD_ROOT
@@ -48,5 +49,6 @@ rm -rf %{builddir}
%files %files
%defattr(-,root,root) %defattr(-,root,root)
%attr(0755,root,root) %{prefix}/bin/curl %attr(0755,root,root) %{prefix}/bin/curl
%doc curl.1 README* CHANGES CONTRIBUTE FAQ FILES INSTALL LEGAL MPL-1.0.txt RESOURCES TODO perl/ %attr(0644,root,root) %{prefix}/man/man1/curl.1
%doc BUGS CHANGES CONTRIBUTE FAQ FEATURES FILES INSTALL LEGAL MPL-1.0.txt README* RESOURCES TODO

96
curl.spec.in Normal file
View File

@@ -0,0 +1,96 @@
%define ver @VERSION@
%define rel 1
%define prefix /usr
Summary: get a file from a FTP, GOPHER or HTTP server.
Name: @PACKAGE@
Version: %ver
Release: %rel
Copyright: MPL
Group: Utilities/Console
Source: %{name}-%{version}.tar.gz
URL: http://@PACKAGE@.haxx.nu
BuildRoot: /tmp/%{name}-%{version}-%{rel}-root
Packager: Fill In As You Wish
Docdir: %{prefix}/doc
%description
@PACKAGE@ is a client to get documents/files from servers, using
any of the supported protocols. The command is designed to
work without user interaction or any kind of interactivity.
@PACKAGE@ offers a busload of useful tricks like proxy support,
user authentication, ftp upload, HTTP post, file transfer
resume and more.
Note: this version is compiled without SSL (https:) support.
Authors:
Daniel Stenberg <Daniel.Stenberg@haxx.nu>
%prep
%setup -n %{name}-%{version}
%build
# Needed for snapshot releases.
if [ ! -f configure ]; then
CONF="./autogen.sh"
else
CONF="./configure"
fi
#
# Configuring the package
#
CFLAGS="${RPM_OPT_FLAGS}" ${CONF} \
--prefix=%{prefix}
[ "$SMP" != "" ] && JSMP = '"MAKE=make -k -j $SMP"'
make ${JSMP};
%install
[ -d ${RPM_BUILD_ROOT} ] && rm -rf ${RPM_BUILD_ROOT}
make prefix=${RPM_BUILD_ROOT}%{prefix} install-strip
#
# Generating file lists and store them in file-lists
# Starting with the directory listings
#
find ${RPM_BUILD_ROOT}%{prefix}/{bin,lib,man} -type d | sed "s#^${RPM_BUILD_ROOT}#\%attr (-\,root\,root) \%dir #" > file-lists
#
# Then, the file listings
#
echo "%defattr (-, root, root)" >> file-lists
find ${RPM_BUILD_ROOT}%{prefix} -type f | sed -e "s#^${RPM_BUILD_ROOT}##g" >> file-lists
%clean
(cd ..; rm -rf %{name}-%{version} ${RPM_BUILD_ROOT})
%files -f file-lists
%defattr (-, root, root)
%doc BUGS
%doc CHANGES
%doc CONTRIBUTE
%doc FAQ
%doc FEATURES
%doc FILES
%doc INSTALL
%doc LEGAL
%doc MPL-1.0.txt
%doc README
%doc README.curl
%doc README.lib@PACKAGE@
%doc RESOURCES
%doc TODO
%doc %{name}-ssl.spec.in
%doc %{name}.spec.in

View File

@@ -46,11 +46,11 @@ BUGS
should be replaced with the name of your debugger, in most cases that will should be replaced with the name of your debugger, in most cases that will
be 'gdb', but 'dbx' and others also occur. be 'gdb', but 'dbx' and others also occur.
When the debugger has finnished loading the core file and presents you a When the debugger has finished loading the core file and presents you a
prompt, you can give the compiler instructions. Enter 'where' (without the prompt, you can give the compiler instructions. Enter 'where' (without the
quotes) and press return. quotes) and press return.
The list that is presented is the stack trace. If everything worked, it is The list that is presented is the stack trace. If everything worked, it is
supposed to contain the chaing of functions that were called when curl supposed to contain the chain of functions that were called when curl
crashed. crashed.

View File

@@ -37,7 +37,7 @@ Commenting
General Style General Style
Keep your functions small. If they're small you avoid a lot of mistakes and Keep your functions small. If they're small you avoid a lot of mistakes and
you don't accidentaly mix up variables. you don't accidentally mix up variables.
Non-clobbering All Over Non-clobbering All Over

View File

@@ -56,4 +56,30 @@ Does curl support custom FTP commands?
ftp commands without transfering anything. Therefore you must always specify ftp commands without transfering 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.
Does curl work with other SSL libraries?
========================================
Curl has been written to use OpenSSL, although I doubt there would be much
problems using a different library. I just don't know any other free one and
that has limited my possibilities to develop against anything else.
If anyone does "port" curl to use a commercial SSL library, I am of course
very interested in getting the patch!
configre doesn't find OpenSSL even when it is installed
=======================================================
Platforms: Solaris (native cc compiler) and HPUX (native cc compiler)
When configuring curl, I specify --with-ssl. OpenSSL is installed in
/usr/local/ssl Configure reports SSL in /usr/local/ssl, but fails to find
CRYPTO_lock in -lcrypto
Cause: The cc for this test places the -L/usr/local/ssl/lib AFTER -lcrypto,
so ld can't find the library. This is due to a bug in the GNU autoconf tool.
Workaround: Specifying "LDFLAGS=-L/usr/local/ssl/lib" in front of ./configure
places the -L/usr/local/ssl/lib early enough in the command line to make
things work
Submitted by: Bob Allison <allisonb@users.sourceforge.net>

View File

@@ -7,51 +7,55 @@
How To Compile How To Compile
Curl has been compiled and built on numerous different operating systems. The Curl has been compiled and built on numerous different operating systems. The
way to proceed is mainly devided in two different ways: the unix way or the way to proceed is mainly divided in two different ways: the unix way or the
windows way. windows way.
If you're using Windows (95, 98, NT) or OS/2, you should continue reading from If you're using Windows (95, 98, NT) or OS/2, you should continue reading from
the Win32 header below. All other systems should be capable of being installed the Win32 header below. All other systems should be capable of being installed
as described un the the UNIX header. as described in the the UNIX header.
PORTS PORTS
===== =====
Just to show off, this is a probably incomplete list of known hardware and Just to show off, 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
- SINIX-Z v5
Alpha DEC OSF 4
Alpha Digital UNIX V3.2D-1 (rev 41)
HP-PA HP-UX 10.X 11.X
MIPS IRIX 6.2, 6.5
Power AIX 4.2, 4.3.1, 4.3.2
PowerPC Darwin 1.0
PowerPC Mac OS X
Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7 Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7
Sparc SunOS 4.1.* Sparc SunOS 4.1.*
i386 Linux 1.3, 2.0, 2.2 i386 BeOS
MIPS IRIX 6.2, 6.5
HP-PA HP-UX
Alpha DEC OSF 4
i386 Solaris 2.7
PowerPC Mac OS X
Power AIX 4.3.1
- Ultrix
i386 FreeBSD i386 FreeBSD
i386 Linux 1.3, 2.0, 2.2
i386 NetBSD i386 NetBSD
i386 OpenBSD
m68k OpenBSD
i386 Windows 95, 98, NT
i386 OS/2 i386 OS/2
i386 OpenBSD
i386 Solaris 2.7
i386 Windows 95, 98, NT
m68k AmigaOS 3 m68k AmigaOS 3
m68k OpenBSD
UNIX UNIX
==== ====
The configure script *always* tries to find a working SSL library unless The configure script *always* tries to find a working SSL library unless
explicitely told not to. If you have SSLeay or OpenSSL installed in the explicitly told not to. If you have OpenSSL installed in the default
default search path for your compiler/linker, you don't need to do anything search path for your compiler/linker, you don't need to do anything
special. special.
If you have SSLeay or OpenSSL installed in /usr/local/ssl, you can If you have OpenSSL installed in /usr/local/ssl, you can run configure
run configure like so: like:
./configure --with-ssl ./configure --with-ssl
If you have SSLeay or OpenSSL installed somewhere else (for example, If you have OpenSSL installed somewhere else (for example, /opt/OpenSSL,)
/opt/OpenSSL,) you can run configure like this: you can run configure like this:
./configure --with-ssl=/opt/OpenSSL ./configure --with-ssl=/opt/OpenSSL
@@ -60,10 +64,10 @@ UNIX
./configure --without-ssl ./configure --without-ssl
If you have SSLeay or OpenSSL installed, but with the libraries in If you have OpenSSL installed, but with the libraries in one place and the
one place and the header files somewhere else, you'll have to set the header files somewhere else, you'll have to set the LDFLAGS and CPPFLAGS
LDFLAGS and CPPFLAGS environment variables prior to running configure. environment variables prior to running configure. Something like this
Something like this should work: should work:
(with the Bourne shell and its clones): (with the Bourne shell and its clones):
@@ -193,9 +197,9 @@ Win32
Microsoft / Borland style Microsoft / Borland style
------------------------- -------------------------
If you have OpenSSL/SSLeay, and want curl to take advantage of it, If you have OpenSSL, and want curl to take advantage of it, edit your
edit your project properties to use the SSL include path, link with project properties to use the SSL include path, link with the SSL libs
the SSL libs and define the USE_SSLEAY symbol. and define the USE_SSLEAY symbol.
IBM OS/2 IBM OS/2
@@ -213,10 +217,10 @@ IBM OS/2
- GNU sed - GNU sed
- autoconf 2.13 - autoconf 2.13
If you want to build with OpenSSL, SSLeay, or OpenLDAP support, you'll If you want to build with OpenSSL or OpenLDAP support, you'll need to
need to download those libraries, too. Dirk Ohme has done some work to download those libraries, too. Dirk Ohme has done some work to port SSL
port SSL libraries under OS/2, but it looks like he doesn't care about emx. libraries under OS/2, but it looks like he doesn't care about emx. You'll
You'll find his patches on: http://come.to/Dirk.Ohme find his patches on: http://come.to/Dirk.Ohme
If during the linking you get an error about _errno being an undefined If during the linking you get an error about _errno being an undefined
symbol referenced from the text segment, you need to add -D__ST_MT_ERRNO__ symbol referenced from the text segment, you need to add -D__ST_MT_ERRNO__
@@ -228,8 +232,8 @@ IBM OS/2
If you're getting huge binaries, probably your makefiles have the -g in If you're getting huge binaries, probably your makefiles have the -g in
CFLAGS. CFLAGS.
OpenSSL/SSLeay OpenSSL
============== =======
You'll find OpenSSL information at: You'll find OpenSSL information at:

140
docs/INTERNALS Normal file
View File

@@ -0,0 +1,140 @@
_ _ ____ _
___| | | | _ \| |
/ __| | | | |_) | |
| (__| |_| | _ <| |___
\___|\___/|_| \_\_____|
INTERNALS
The project is kind of split in two. The library and the client. The client
part uses the library, but the library is meant to be designed to allow other
applications to use it.
Thus, the largest amount of code and complexity is in the library part.
Windows vs Unix
===============
There are a few differences in how to program curl the unix way compared to
the Windows way. The four most notable details are:
1. Different function names for close(), read(), write()
2. Windows requires a couple of init calls
3. The file descriptors for network communication and file operations are
not easily interchangable as in unix
4. When writing data to stdout, Windows makes end-of-lines the DOS way, thus
destroying binary data, although you do want that conversion if it is
text coming through... (sigh)
In curl, (1) and (2) are done with defines and macros, so that the source
looks the same at all places except for the header file that defines them.
(3) is simply avoided by not trying any funny tricks on file descriptors.
(4) is left alone, giving windows users problems when they pipe binary data
through stdout...
Inside the source code, I do make an effort to avoid '#ifdef WIN32'. All
conditionals that deal with features *should* instead be in the format
'#ifdef HAVE_THAT_WEIRD_FUNCTION'. Since Windows can't run configure scripts,
I maintain two config-win32.h files (one in / and one in src/) that are
supposed to look exactly as a config.h file would have looked like on a
Windows machine!
Library
=======
There is a few entry points to the library, namely each publicly defined
function that libcurl offers to applications. All of those functions are
rather small and easy-to-follow, accept the one single and do-it-all named
curl_urlget() (entry point in lib/url.c).
curl_urlget() takes a variable amount of arguments, and they must all be
passed in pairs, the parameter-ID and the parameter-value. The list of
arguments must be ended with a end-of-arguments parameter-ID.
The function then continues to analyze the URL, get the different components
and connects to the remote host. This may involve using a proxy and/or using
SSL. The GetHost() function in lib/hostip.c is used for looking up host
names.
When connected, the proper function is called. The functions are named after
the protocols they handle. ftp(), http(), dict(), etc. They all reside in
their respective files (ftp.c, http.c and dict.c).
The protocol-specific functions deal with protocol-specific negotiations and
setup. They have access to the sendf() (from lib/sendf.c) function to send
printf-style formatted data to the remote host and when they're ready to make
the actual file transfer they call the Transfer() function (in
lib/download.c) to do the transfer. All printf()-style functions use the
supplied clones in lib/mprintf.c.
While transfering, the progress functions in lib/progress.c are called at a
frequent interval. The speedcheck functions in lib/speedcheck.c are also used
to verify that the transfer is as fast as required.
When the operation is done, the writeout() function in lib/writeout.c may be
called to report about the operation as specified previously in the arguments
to curl_urlget().
HTTP(S)
HTTP offers a lot and is the protocol in curl that uses the most lines of
code. There is a special file (lib/formdata.c) that offers all the multipart
post functions.
base64-functions for user+password stuff is in (lib/base64.c) and all
functions for parsing and sending cookies are found in
(lib/cookie.c).
HTTPS uses in almost every means the same procedure as HTTP, with only two
exceptions: the connect procedure is different and the function used
FTP
The if2ip() function can be used for getting the IP number of a specified
network interface, and it resides in lib/if2ip.c
TELNET
Telnet is implemented in lib/telnet.c.
FILE
The file:// protocol is dealt with in lib/file.c.
LDAP
Everything LDAP is in lib/ldap.c.
GENERAL
URL encoding and decoding, called escaping and unescaping in the source code,
is found in lib/escape.c.
While transfering data in Transfer() a few functions might get
used. get_date() in lib/getdate.c is for HTTP date comparisons.
lib/getenv.c is for reading environment variables in a neat platform
independent way. That's used in the client, but also in lib/url.c when
checking the PROXY variables.
lib/netrc.c keeps the .netrc parser
lib/timeval.c features replacement functions for systems that don't have
A function named curl_version() that returns the full curl version string is
found in lib/version.c.
Client
======
main() resides in src/main.c together with most of the client
code. src/hugehelp.c is automatically generated by the mkhelp.pl perl script
to display the complete "manual" and the src/urlglob.c file holds the
functions used for the multiple-URL support.
The client mostly mess around to setup its config struct properly, then it
calls the curl_urlget() function in the library and when it gets back control
it checks status and exits.

View File

@@ -194,6 +194,41 @@ POST (HTTP)
curl -d "name=Rafael%20Sagula&phone=3320780" \ curl -d "name=Rafael%20Sagula&phone=3320780" \
http://www.where.com/guest.cgi http://www.where.com/guest.cgi
How to post a form with curl, lesson #1:
Dig out all the <input> tags in the form that you want to fill in. (There's
a perl program called formfind.pl on the curl site that helps with this).
If there's a "normal" post, you use -d to post. -d takes a full "post
string", which is in the format
<variable1>=<data1>&<variable2>=<data2>&...
The 'variable' names are the names set with "name=" in the <input> tags, and
the data is the contents you want to fill in for the inputs. The data *must*
be properly URL encoded. That means you replace space with + and that you
write weird letters with %XX where XX is the hexadecimal representation of
the letter's ASCII code.
Example:
(page located at http://www.formpost.com/getthis/
<form action="post.cgi" method="post">
<input name=user size=10>
<input name=pass type=password size=10>
<input name=id type=hidden value="blablabla">
<input name=ding value="submit">
</form>
We want to enter user 'foobar' with password '12345'.
To post to this, you enter a curl command line like:
curl -d "user=foobar&pass=12345&id=blablabla&dig=submit" (continues)
http://www.formpost.com/getthis/post.cgi
While -d uses the application/x-www-form-urlencoded mime-type, generally While -d uses the application/x-www-form-urlencoded mime-type, generally
understood by CGI's and similar, curl also supports the more capable understood by CGI's and similar, curl also supports the more capable
multipart/form-data type. This latter type supports things like file upload. multipart/form-data type. This latter type supports things like file upload.

51
docs/README.libcurl Normal file
View File

@@ -0,0 +1,51 @@
_ _ _ _
| (_) |__ ___ _ _ _ __| |
| | | '_ \ / __| | | | '__| |
| | | |_) | (__| |_| | | | |
|_|_|_.__/ \___|\__,_|_| |_|
How To Use Libcurl In Your Program
Interfaces
libcurl currently offers two different interfaces to the URL transfer
engine. They can be seen as one low-level and one high-level, in the sense
that the low-level one will allow you to deal with a lot more details but on
the other hand not offer as many fancy features (such as Location:
following). The high-level interface is supposed to be a built-in
implementation of the low-level interface. You will not be able to mix
function calls from the different layers.
As we currently ONLY support the high-level interface, the so called easy
interface, I will not attempt to describe any low-level functions at this
point.
Function descriptions
The interface is meant to be very simple for very simple
implementations. Thus, we have minimized the number of entries.
The Easy Interface
When using the easy interface, you init your easy-session and get a handle,
which you use as input to the following interface functions you use.
You continue be setting all the options you want in the upcoming transfer,
most important among them is the URL itself. You might want to set some
callbacks as well that will be called from the library when data is available
etc.
When all is setup, you tell libcurl to perform the transfer. It will then do
the entire operation and won't return until it is done or failed.
After the performance is made, you cleanup the easy-session's handle and
libcurl is entire off the hook!
See the separate man pages for the libcurl functions for details:
curl_easy_init()
curl_easy_setopt()
curl_easy_perform()
curl_easy_cleanup()

View File

@@ -12,34 +12,51 @@ specify standards used by curl, software that extends curl and web pages with
Standards Standards
RFC 959 - Defines how FTP works RFC 959 - Defines how FTP works
RFC 1738 - Uniform Resource Locators RFC 1738 - Uniform Resource Locators
RFC 1777 - defines the LDAP protocol RFC 1777 - defines the LDAP protocol
RFC 1808 - Relative Uniform Resource Locators RFC 1808 - Relative Uniform Resource Locators
RFC 1867 - Form-based File Upload in HTML RFC 1867 - Form-based File Upload in HTML
RFC 1950 - ZLIB Compressed Data Format Specification RFC 1950 - ZLIB Compressed Data Format Specification
RFC 1951 - DEFLATE Compressed Data Format Specification RFC 1951 - DEFLATE Compressed Data Format Specification
RFC 1952 - gzip compression format RFC 1952 - gzip compression format
RFC 1959 - LDAP URL syntax RFC 1959 - LDAP URL syntax
RFC 2045-2049 - Everything you need to know about MIME! (needed for form RFC 2045-2049 - Everything you need to know about MIME! (needed for form
based upload) based upload)
RFC 2068 - HTTP 1.1 (obsoleted by RFC 2616) RFC 2068 - HTTP 1.1 (obsoleted by RFC 2616)
RFC 2109 - HTTP State Management Mechanism (cookie stuff) RFC 2109 - HTTP State Management Mechanism (cookie stuff)
- Also, read Netscape's specification at - Also, read Netscape's specification at
http://www.netscape.com/newsref/std/cookie_spec.html http://www.netscape.com/newsref/std/cookie_spec.html
RFC 2183 - "The Content-Disposition Header Field" RFC 2183 - "The Content-Disposition Header Field"
RFC 2229 - "A Dictionary Server Protocol" RFC 2229 - "A Dictionary Server Protocol"
RFC 2231 - "MIME Parameter Value and Encoded Word Extensions: RFC 2231 - "MIME Parameter Value and Encoded Word Extensions:
Character Sets, Languages, and Continuations" Character Sets, Languages, and Continuations"
RFC 2388 - "Returning Values from Forms: multipart/form-data" RFC 2388 - "Returning Values from Forms: multipart/form-data"
Use this as an addition to the 1867 Use this as an addition to the 1867
RFC 2396 - "Uniform Resource Identifiers: Generic Syntax and Semantics" RFC 2396 - "Uniform Resource Identifiers: Generic Syntax and Semantics"
This one obsoletes 1738, but since 1738 is often mentioned I've left it This one obsoletes 1738, but since 1738 is often mentioned I've left it
in this list. in this list.
RFC 2428 - "FTP Extensions for IPv6 and NATs" RFC 2428 - "FTP Extensions for IPv6 and NATs"
This should be considered when introducing IPv6 awareness. This should be considered when introducing IPv6 awareness.
RFC 2616 - HTTP 1.1 RFC 2616 - HTTP 1.1
RFC 2617 - HTTP Authentication RFC 2617 - HTTP Authentication
Compilers Compilers

View File

@@ -6,6 +6,33 @@
TODO TODO
For version 7. Stuff I palnned to have included in curl for version
seven. Let's do a serious attempt to include most of this.
Document the easy-interface completely
Make sure the low-level interface works. highlevel.c should basically be
possible to write using that interface.
Document the low-level interface
Add asynchronous name resolving, as this enables full timeout support for
fork() systems.
Make sure you can set the progress callback
Add libtool stuff
Move non-URL related functions that are used by both the lib and the curl
application to a separate "portability lib".
Add support for other languages than C (not important)
Improve the -K config file parser.
For the future
Ok, this is what I wanna do with Curl. Please tell me what you think, and Ok, this is what I wanna do with Curl. Please tell me what you think, and
please don't hesitate to contribute and send me patches that improve this please don't hesitate to contribute and send me patches that improve this
product! (Yes, you may add things not mentioned here, these are just a product! (Yes, you may add things not mentioned here, these are just a
@@ -72,7 +99,7 @@ TODO
* Other proxies * Other proxies
Ftp-kind proxy, Socks5, whatever kind of proxies are there? Ftp-kind proxy, Socks5, whatever kind of proxies are there?
* IPv6 Awareness * IPv6 Awareness and support
Where ever it would fit. I am not that into v6 yet to fully grasp what we Where ever it would fit. I am not that into v6 yet to fully grasp what we
would need to do, but letting the autoconf search for v6-versions of a few would need to do, but letting the autoconf search for v6-versions of a few
functions and then use them instead is of course the first thing to do... functions and then use them instead is of course the first thing to do...
@@ -90,4 +117,3 @@ TODO
* Make curl capable of verifying the server's certificate when connecting * Make curl capable of verifying the server's certificate when connecting
with HTTPS://. with HTTPS://.
* Make the timeout work as expected!

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 "13 March 2000" "Curl 6.5" "Curl Manual" .TH curl 1 "22 May 2000" "Curl 7.0" "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.
@@ -204,7 +204,7 @@ A quick and very simple example of how to setup a
to allow curl to ftp to the machine host.domain.com with user name to allow curl to ftp to the machine host.domain.com with user name
'myself' and password 'secret' should look similar to: 'myself' and password 'secret' should look similar to:
.B "machine host.domain.com user myself password secret" .B "machine host.domain.com login myself password secret"
.IP "-N/--no-buffer" .IP "-N/--no-buffer"
Disables the buffering of the output stream. In normal work situations, curl Disables the buffering of the output stream. In normal work situations, curl
will use a standard buffered output stream that will have the effect that it will use a standard buffered output stream that will have the effect that it
@@ -588,6 +588,10 @@ If you do find any (or have other suggestions), mail Daniel Stenberg
- Damien Adant <dams@usa.net> - Damien Adant <dams@usa.net>
- Chris <cbayliss@csc.come> - Chris <cbayliss@csc.come>
- Marco G. Salvagno <mgs@whiz.cjb.net> - Marco G. Salvagno <mgs@whiz.cjb.net>
- Paul Marquis <pmarquis@iname.com>
- David LeBlanc <dleblanc@qnx.com>
- Rich Gray at Plus Technologies
.SH WWW .SH WWW
http://curl.haxx.nu http://curl.haxx.nu
.SH FTP .SH FTP

25
docs/curl_easy_cleanup.3 Normal file
View File

@@ -0,0 +1,25 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by Daniel.Stenberg@haxx.nu
.\"
.TH curl_easy_cleanup 3 "22 May 2000" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_easy_cleanup - End a libcurl "easy" session
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "curl_easy_cleanup(CURL *" handle ");
.ad
.SH DESCRIPTION
This function must be the last function to call for a curl session. It is the
opposite of the
.I curl_easy_init
function and must be called with the same
.I handle
as input as the curl_easy_init call returned.
.SH RETURN VALUE
None
.SH "SEE ALSO"
.BR curl_easy_init "(3), "
.SH BUGS
Surely there are some, you tell me!

25
docs/curl_easy_init.3 Normal file
View File

@@ -0,0 +1,25 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by Daniel.Stenberg@haxx.nu
.\"
.TH curl_easy_init 3 "22 May 2000" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_easy_init - Start a libcurl "easy" session
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURL *curl_easy_init( );"
.ad
.SH DESCRIPTION
This function must be the first function to call, and it returns a CURL handle
that you shall use as input to the other easy-functions. The init calls
intializes curl and this call MUST have a corresponding call to
.I curl_easy_cleanup
when the operation is complete.
.SH RETURN VALUE
If this function returns NULL, something went wrong and you cannot use the
other curl functions.
.SH "SEE ALSO"
.BR curl_easy_cleanup "(3), "
.SH BUGS
Surely there are some, you tell me!

29
docs/curl_easy_perform.3 Normal file
View File

@@ -0,0 +1,29 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by Daniel.Stenberg@haxx.nu
.\"
.TH curl_easy_perform 3 "26 May 2000" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_easy_perform - Do the actual transfer in a "easy" session
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_perform(CURL *" handle ");
.ad
.SH DESCRIPTION
This function is called after the init and all the curl_easy_setopt() calls
are made, and will perform the transfer as described in the options.
It must be called with the same
.I handle
as input as the curl_easy_init call returned.
.SH RETURN VALUE
0 means everything was ok, non-zero means an error occurred as
.I <curl/curl.h>
defines. If the CURLOPT_ERRORBUFFER was set with
.I curl_easy_setopt
there willo be a readable error message in the error buffer when non-zero is
returned.
.SH "SEE ALSO"
.BR curl_easy_init "(3), " curl_easy_setopt "(3), "
.SH BUGS
Surely there are some, you tell me!

300
docs/curl_easy_setopt.3 Normal file
View File

@@ -0,0 +1,300 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by Daniel.Stenberg@haxx.nu
.\"
.TH curl_easy_setopt 3 "22 May 2000" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_setopt(CURL *" handle ", CURLoption "option ", ...);
.ad
.SH DESCRIPTION
curl_easy_setopt() is called to tell libcurl how to behave in a number of
ways. Most operations in libcurl have default actions, and by using the
appropriate options you can make them behave differently (as documented). All
options are set with the
.I option
followed by a parameter. That parameter can be a long, a function pointer or
an object pointer, all depending on what the option in question expects. Read
this manual carefully as bad input values may cause libcurl to behave badly!
The
.I "handle"
is the return code from the
.I "curl_easy_init"
call.
.SH OPTIONS
.TP 0.8i
.B CURLOPT_FILE
Data pointer to pass instead of FILE * to the file write function. Note that
if you specify the
.I CURLOPT_WRITEFUNCTION
, this is the pointer you'll get as input.
.TP
.B CURLOPT_WRITEFUNCTION
Function pointer that should use 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 data that
needs to be written down. The size of the data pointed to by
.I ptr
is
.I size
multiplied with
.I nmemb.
Return the number of bytes actually written or return -1 to signal error to the library (it will cause it to abort the transfer).
.TP
.B CURLOPT_INFILE
Data pointer to pass instead of FILE * to the file read function. Note that if
you specify the
.I CURLOPT_READFUNCTION
, this is the pointer you'll get as input.
.TP
.B CURLOPT_READFUNCTION
Function pointer that should use 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 it needs to read data in order
to send it to the peer. The data area pointed at by the pointer
.I ptr
may be filled with at most
.I size
multiplied with
.I nmemb
number of bytes. Your function must return the actual number of bytes that you
stored in that memory area. Returning -1 will signal an error to the library
and cause it to abort the current transfer immediately.
.TP
.B CURLOPT_INFILESIZE
When uploading a file to a remote site, this option should be used to tell
libcurl what the expected size of the infile is.
.TP
.B CURLOPT_URL
The actual URL to deal with. The parameter should be a char * to a zero
terminated string. NOTE: this option is currently required!
.TP
.B CURLOPT_PROXY
If you need libcurl to use a http proxy to access the outside world, set the
proxy string with this option. The parameter should be a char * to a zero
terminated string.
.TP
.B CURLOPT_VERBOSE
Set the parameter to non-zero to get the library to display a lot of verbose
information about its operations.
.TP
.B CURLOPT_HEADER
A non-zero parameter tells the library to include the header in the
output. This is only relevant for protocols that actually has a header
preceeding the data (like HTTP).
.TP
.B CURLOPT_NOPROGRESS
A non-zero parameter tells the library to shut of the built-in progress meter
completely. (NOTE: future versions of the lib is likely to not have any
built-in progress meter at all).
.TP
.B CURLOPT_NOBODY
A non-zero parameter tells the library to not include the body-part in the
output. This is only relevant for protocols that have a separate header and
body part.
.TP
.B CURLOPT_FAILONERROR
A non-zero parameter tells the library to fail silently if the HTTP code
returned is equal or larger than 300. The default action would be to return
the page normally, ignoring that code.
.TP
.B CURLOPT_UPLOAD
A non-zero parameter tells the library to prepare for an upload. The
CURLOPT_INFILE and CURLOPT_INFILESIZE are also interesting for uploads.
.TP
.B CURLOPT_POST
A non-zero parameter tells the library to do a regular HTTP post. This is a
normal application/x-www-form-urlencoded kind, which is the most commonly used
one by HTML forms. See the CURLOPT_POSTFIELDS option for how to specify the
data to post.
.TP
.B CURLOPT_FTPLISTONLY
A non-zero parameter tells the library to just list the names of an ftp
directory, instead of doing a full directory listin that would include file
sizes, dates etc.
.TP
.B CURLOPT_FTPAPPEND
A non-zero parameter tells the library to append to the remote file instead of
overwrite it. This is only useful when uploading to a ftp site.
.TP
.B CURLOPT_NETRC
A non-zero parameter tells the library to scan your
.I ~/.netrc
file to find user name and password for the remote site you are about to
access. Do note that curl does not verify that the file has the correct
properties set (as the standard unix ftp client does), and that only machine
name, user name and password is taken into account (init macros and similar
things aren't supported).
.TP
.B CURLOPT_FOLLOWLOCATION
A non-zero parameter tells the library to follow any Location: header that the
server sends as part of a HTTP header. NOTE that this means that the library
will resend the same request on the new location and follow new Location:
headers all the way until no more such headers are returned.
.TP
.B CURLOPT_FTPASCII
A non-zero parameter tells the library to use ASCII mode for ftp transfers,
instead of the default binary transfer. This will only be useable when
transfering text data between system with different views on certain
characters, such as newlines or similar.
.TP
.B CURLOPT_PUT
A non-zero parameter tells the library to use HTTP PUT a file. The file to put
must be set with CURLOPT_INFILE and CURLOPT_INFILESIZE.
.TP
.B CURLOPT_MUTE
A non-zero parameter tells the library to be completely quiet.
.TP
.B CURLOPT_USERPWD
Pass a char * as parameter, which should be [username]:[password] to use for
the connection. If the password is left out, you will be prompted for it.
.TP
.B CURLOPT_PROXYUSERPWD
Pass a char * as parameter, which should be [username]:[password] to use for
the connection to the HTTP proxy. If the password is left out, you will be
prompted for it.
.TP
.B CURLOPT_RANGE
Pass a char * as parameter, which should contain the specified range you
want. It should be in the format "X-Y", where X or Y may be left out. The HTTP
transfers also support several intervals, separated with commas as in
.I "X-Y,N-M".
.TP
.B CURLOPT_ERRORBUFFER
Pass a char * to a buffer that the libcurl may store human readable error
messages in. This may be more helpful than just the return code from the
library. The buffer must be at least CURL_ERROR_SIZE big.
.TP
.B CURLOPT_TIMEOUT
Pass a long as parameter containing the maximum time in seconds that you allow
the libcurl transfer operation to take. Do note that normally, name lookups
maky take a considerable time and that limiting the operation to less than a
few minutes risk aborting perfectly normal operations.
.TP
.B CURLOPT_POSTFIELDS
Pass a char * as parameter, which should be the full data to post in a HTTP
post operation. See also the CURLOPT_POST.
.TP
.B CURLOPT_REFERER
Pass a pointer to a zero terminated string as parameter. It will be used to
set the referer: header in the http request sent to the remote server. This
can be used to fool servers or scripts.
.TP
.B CURLOPT_USERAGENT
Pass a pointer to a zero terminated string as parameter. It will be used to
set the user-agent: header in the http request sent to the remote server. This
can be used to fool servers or scripts.
.TP
.B CURLOPT_FTPPORT
Pass a pointer to a zero terminated string as parameter. It will be used to
get the IP address to use for the ftp PORT instruction. The PORT instruction
tells the remote server to connect to our specified IP address. The string may
be a plain IP address, a host name, an network interface name (under unix) or
just a '-' letter to let the library use your systems default IP address.
.TP
.B CURLOPT_LOW_SPEED_LIMIT
Pass a long as parameter. It contains the transfer speed in bytes per second
that the transfer should be below during CURLOPT_LOW_SPEED_TIME seconds for
the library to consider it too slow and abort.
.TP
.B CURLOPT_LOW_SPEED_TIME
Pass a long as parameter. It contains the time in seconds that the transfer
should be below the CURLOPT_LOW_SPEED_LIMIT for the library to consider it too
slow and abort.
.TP
.B CURLOPT_RESUME_FROM
Pass a long as parameter. It contains the offset in number of bytes that you
want the transfer to start from.
.TP
.B CURLOPT_COOKIE
Pass a pointer to a zero terminated string as parameter. It will be used to
set a cookie in the http request. The format of the string should be
'[NAME]=[CONTENTS];' Where NAME is the cookie name.
.TP
.B CURLOPT_HTTPHEADER
Pass a pointer to a linked list of HTTP headers to pass to the server in your
HTTP request. The linked list should be a fully valid list of 'struct
HttpHeader' structs properly filled in. TBD!
.TP
.B CURLOPT_HTTPPOST
Pass a pointer to a linked list of HTTP post data to pass to the server in
your http request. The linked list should be a fully valid list of 'struct
HttpPost' structs properly filled in. TBD!
.TP
.B CURLOPT_SSLCERT
Pass a pointer to a zero terminated string as parameter. The string should be
the file name of your certficicate in PEM format.
.TP
.B CURLOPT_SSLCERTPASSWD
Pass a pointer to a zero terminated string as parameter. It will be used as
the password required to use the CURLOPT_SSLCERT certificate. If the password
is not supplied, you will be prompted for it.
.TP
.B CURLOPT_CRLF
TBD.
.TP
.B CURLOPT_QUOTE
Pass a pointer to a linked list of FTP commands to pass to the server prior to
your ftp request. The linked list should be a fully valid list of 'struct
curl_slist' structs properly filled in. TBD!
.TP
.B CURLOPT_POSTQUOTE
Pass a pointer to a linked list of FTP commands to pass to the server after
your ftp transfer request. The linked list should be a fully valid list of
'struct curl_slist' structs properly filled in. TBD!
.TP
.B CURLOPT_WRITEHEADER
Pass a FILE * to be used to write the header part of the received data to.
.TP
.B CURLOPT_COOKIEFILE
Pass a pointer to a zero terminated string as parameter. It should contain the
name of your file holding cookie data. The cookie data may be in netscape
cookie data format or just regular HTTP-style headers dumped to a file.
.TP
.B CURLOPT_SSLVERSION
Pass a long as parameter. Set what version of SSL to attempt to use, 2 or
3. By default, the SSL library will try to solve this by itself although some
servers make this difficult why you at times will have to use this option.
.TP
.B CURLOPT_TIMECONDITION
Pass a long as parameter. This defines how the CURLOPT_TIMEVALUE time value is
treated. You can set this parameter to TIMECOND_IFMODSINCE or
TIMECOND_IFUNMODSINCE. This is aa HTTP-only feature. (TBD)
.TP
.B CURLOPT_TIMEVALUE
Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
and the time will be used as specified in CURLOPT_TIMECONDITION or if that
isn't used, it will be TIMECOND_IFMODSINCE by default.
.TP
.B CURLOPT_CUSTOMREQUEST
Pass a pointer to a zero terminated string as parameter. It will be user
instead of GET or HEAD when doing the HTTP request. This is useful for doing
DELETE or other more obscure HTTP requests. Don't do this at will, make sure
your server supports the command first.
.TP
.B CURLOPT_STDERR
Pass a FILE * as parameter. This is the stream to use instead of stderr
internally when reporting errors.
.TP
.B CURLOPT_PROGRESSMODE
This is currently unsupported, and is likely to be removed in future
versions. TBD
.TP
.B CURLOPT_WRITEINFO
Pass a pointer to a zero terminated string as parameter. It will be used to
report information after a successful request. This string may contain
variables that will be substituted by their contents when output. Described
elsewhere.
.PP
.SH RETURN VALUE
0 means the option was set properly, non-zero means an error as
.I <curl/curl.h>
defines
.SH "SEE ALSO"
.BR curl_easy_init "(3), " curl_easy_cleanup "(3), "
.SH BUGS
Surely there are some, you tell me!

View File

@@ -1,5 +1,5 @@
#ifndef __CURL_H #ifndef __CURL_CURL_H
#define __CURL_H #define __CURL_CURL_H
/***************************************************************************** /*****************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@@ -39,6 +39,25 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
/* The include stuff here is mainly for time_t! */
#ifdef vms
# include <types.h>
# include <time.h>
#else
# include <sys/types.h>
# if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
# else
# if HAVE_SYS_TIME_H
# include <sys/time.h>
# else
# include <time.h>
# endif
# endif
#endif /* defined (vms) */
#ifndef TRUE #ifndef TRUE
#define TRUE 1 #define TRUE 1
#endif #endif
@@ -46,71 +65,8 @@
#define FALSE 0 #define FALSE 0
#endif #endif
#include <curl/types.h>
#define CONF_DEFAULT 0
#define CONF_PROXY (1<<0) /* set if proxy is in use */
#define CONF_PORT (1<<1) /* set if different port than protcol-defines is
used */
#define CONF_HTTP (1<<2) /* http get */
#define CONF_GOPHER (1<<3) /* gopher get */
#define CONF_FTP (1<<4) /* ftp get (binary mode) */
#define CONF_VERBOSE (1<<5) /* talk a lot */
#define CONF_TELNET (1<<6)
#define CONF_HEADER (1<<8) /* throw the header out too */
#define CONF_USERPWD (1<<9) /* user+passwd has been specified */
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter (auto)
see also _MUTE */
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
#define CONF_FAILONERROR (1<<12) /* Makes urlget() fail with a return code
WITHOUT writing anything to the output if
a return code >=300 is returned from the
server. */
#define CONF_RANGE (1<<13) /* Byte-range request, specified parameter is set */
#define CONF_UPLOAD (1<<14) /* this is an upload, only supported for ftp
currently */
#define CONF_POST (1<<15) /* HTTP POST method */
/* When getting an FTP directory, this switch makes the listing only show file
names and nothing else. Makes machine parsing of the output possible. This
enforces the NLST command to the ftp server, compared to the otherwise
used: LIST. */
#define CONF_FTPLISTONLY (1<<16)
/* Set the referer string */
#define CONF_REFERER (1<<17)
#define CONF_PROXYUSERPWD (1<<18) /* Proxy user+passwd has been specified */
/* For FTP, use PORT instead of PASV! */
#define CONF_FTPPORT (1<<19)
/* FTP: Append instead of overwrite on upload! */
#define CONF_FTPAPPEND (1<<20)
#define CONF_HTTPS (1<<21) /* Use SSLeay for encrypted communication */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* get the page that the Location: tells
us to get */
#define CONF_FTPASCII (1<<24) /* use TYPE A for transfer */
#define CONF_HTTPPOST (1<<25) /* this causes a multipart/form-data
HTTP POST */
#define CONF_NOPROT (1<<26) /* host name specified without protocol */
#define CONF_PUT (1<<27) /* PUT the input file */
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
#define CONF_DICT (1<<29) /* DICT:// protocol */
#define CONF_FILE (1<<30) /* FILE:// protocol */
#define CONF_LDAP (1<<31) /* LDAP:// protocol */
struct HttpHeader { struct HttpHeader {
struct HttpHeader *next; /* next entry in the list */ struct HttpHeader *next; /* next entry in the list */
@@ -132,88 +88,89 @@ struct HttpPost {
may return other values, stay prepared. */ may return other values, stay prepared. */
typedef enum { typedef enum {
URG_OK = 0, CURLE_OK = 0,
URG_UNSUPPORTED_PROTOCOL, CURLE_UNSUPPORTED_PROTOCOL,
URG_FAILED_INIT, CURLE_FAILED_INIT,
URG_URL_MALFORMAT, CURLE_URL_MALFORMAT,
URG_URL_MALFORMAT_USER, CURLE_URL_MALFORMAT_USER,
URG_COULDNT_RESOLVE_PROXY, CURLE_COULDNT_RESOLVE_PROXY,
URG_COULDNT_RESOLVE_HOST, CURLE_COULDNT_RESOLVE_HOST,
URG_COULDNT_CONNECT, CURLE_COULDNT_CONNECT,
URG_FTP_WEIRD_SERVER_REPLY, CURLE_FTP_WEIRD_SERVER_REPLY,
URG_FTP_ACCESS_DENIED, CURLE_FTP_ACCESS_DENIED,
URG_FTP_USER_PASSWORD_INCORRECT, CURLE_FTP_USER_PASSWORD_INCORRECT,
URG_FTP_WEIRD_PASS_REPLY, CURLE_FTP_WEIRD_PASS_REPLY,
URG_FTP_WEIRD_USER_REPLY, CURLE_FTP_WEIRD_USER_REPLY,
URG_FTP_WEIRD_PASV_REPLY, CURLE_FTP_WEIRD_PASV_REPLY,
URG_FTP_WEIRD_227_FORMAT, CURLE_FTP_WEIRD_227_FORMAT,
URG_FTP_CANT_GET_HOST, CURLE_FTP_CANT_GET_HOST,
URG_FTP_CANT_RECONNECT, CURLE_FTP_CANT_RECONNECT,
URG_FTP_COULDNT_SET_BINARY, CURLE_FTP_COULDNT_SET_BINARY,
URG_PARTIAL_FILE, CURLE_PARTIAL_FILE,
URG_FTP_COULDNT_RETR_FILE, CURLE_FTP_COULDNT_RETR_FILE,
URG_FTP_WRITE_ERROR, CURLE_FTP_WRITE_ERROR,
URG_FTP_QUOTE_ERROR, CURLE_FTP_QUOTE_ERROR,
URG_HTTP_NOT_FOUND, CURLE_HTTP_NOT_FOUND,
URG_WRITE_ERROR, CURLE_WRITE_ERROR,
URG_MALFORMAT_USER, /* the user name is illegally specified */ CURLE_MALFORMAT_USER, /* the user name is illegally specified */
URG_FTP_COULDNT_STOR_FILE, /* failed FTP upload */ CURLE_FTP_COULDNT_STOR_FILE, /* failed FTP upload */
URG_READ_ERROR, /* could open/read from file */ CURLE_READ_ERROR, /* could open/read from file */
URG_OUT_OF_MEMORY, CURLE_OUT_OF_MEMORY,
URG_OPERATION_TIMEOUTED, /* the timeout time was reached */ CURLE_OPERATION_TIMEOUTED, /* the timeout time was reached */
URG_FTP_COULDNT_SET_ASCII, /* TYPE A failed */ CURLE_FTP_COULDNT_SET_ASCII, /* TYPE A failed */
URG_FTP_PORT_FAILED, /* FTP PORT operation failed */ CURLE_FTP_PORT_FAILED, /* FTP PORT operation failed */
URG_FTP_COULDNT_USE_REST, /* the REST command failed */ CURLE_FTP_COULDNT_USE_REST, /* the REST command failed */
URG_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */ CURLE_FTP_COULDNT_GET_SIZE, /* the SIZE command failed */
URG_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */ CURLE_HTTP_RANGE_ERROR, /* The RANGE "command" didn't seem to work */
URG_HTTP_POST_ERROR, CURLE_HTTP_POST_ERROR,
URG_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */ CURLE_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
URG_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */ CURLE_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
URG_FILE_COULDNT_READ_FILE, CURLE_FILE_COULDNT_READ_FILE,
URG_LDAP_CANNOT_BIND, CURLE_LDAP_CANNOT_BIND,
URG_LDAP_SEARCH_FAILED, CURLE_LDAP_SEARCH_FAILED,
URG_LIBRARY_NOT_FOUND, CURLE_LIBRARY_NOT_FOUND,
URG_FUNCTION_NOT_FOUND, CURLE_FUNCTION_NOT_FOUND,
URL_LAST CURLE_ABORTED_BY_CALLBACK,
} UrgError;
CURLE_BAD_FUNCTION_ARGUMENT,
CURLE_BAD_CALLING_ORDER,
CURL_LAST
} CURLcode;
/* This is just to make older programs not break: */ /* This is just to make older programs not break: */
#define URG_FTP_PARTIAL_FILE URG_PARTIAL_FILE #define CURLE_FTP_PARTIAL_FILE CURLE_PARTIAL_FILE
#define URGTAG_DONE -1 #define CURL_ERROR_SIZE 256
#define URGTAG_LAST -1
#define URGTAG_END -1
#define URLGET_ERROR_SIZE 256
/* maximum URL length we deal with */ /* maximum URL length we deal with */
#define URL_MAX_LENGTH 4096 #define URL_MAX_LENGTH 4096
#define URL_MAX_LENGTH_TXT "4095" #define URL_MAX_LENGTH_TXT "4095"
/* name is uppercase URGTAG_<name>, /* name is uppercase CURLOPT_<name>,
type is one of the defined URGTYPE_<type> type is one of the defined CURLOPTTYPE_<type>
number is unique identifier */ number is unique identifier */
#define T(name,type,number) URGTAG_ ## name = URGTYPE_ ## type + number #define T(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
/* long may be 32 or 64 bits, but we should never depend on anything else /* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */ but 32 */
#define URGTYPE_LONG 0 #define CURLOPTTYPE_LONG 0
#define URGTYPE_OBJECTPOINT 10000 #define CURLOPTTYPE_OBJECTPOINT 10000
#define URGTYPE_FUNCTIONPOINT 20000 #define CURLOPTTYPE_FUNCTIONPOINT 20000
typedef enum { typedef enum {
URGTAG_NOTHING, /* the first unused */ T(NOTHING, LONG, 0), /********* the first one is unused ************/
/* This is the FILE * the regular output should be written to. */ /* This is the FILE * the regular output should be written to. */
T(FILE, OBJECTPOINT, 1), T(FILE, OBJECTPOINT, 1),
@@ -222,50 +179,51 @@ typedef enum {
T(URL, OBJECTPOINT, 2), T(URL, OBJECTPOINT, 2),
/* Port number to connect to, if other than default. Specify the CONF_PORT /* Port number to connect to, if other than default. Specify the CONF_PORT
flag in the URGTAG_FLAGS to activate this */ flag in the CURLOPT_FLAGS to activate this */
T(PORT, LONG, 3), T(PORT, LONG, 3),
/* Name of proxy to use. Specify the CONF_PROXY flag in the URGTAG_FLAGS to /* Name of proxy to use. Specify the CONF_PROXY flag in the CURLOPT_FLAGS to
activate this */ activate this */
T(PROXY, OBJECTPOINT, 4), T(PROXY, OBJECTPOINT, 4),
/* Name and password to use when fetching. Specify the CONF_USERPWD flag in /* Name and password to use when fetching. Specify the CONF_USERPWD flag in
the URGTAG_FLAGS to activate this */ the CURLOPT_FLAGS to activate this */
T(USERPWD, OBJECTPOINT, 5), T(USERPWD, OBJECTPOINT, 5),
/* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD /* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD
flag in the URGTAG_FLAGS to activate this */ flag in the CURLOPT_FLAGS to activate this */
T(PROXYUSERPWD, OBJECTPOINT, 6), T(PROXYUSERPWD, OBJECTPOINT, 6),
/* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag /* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag
in the URGTAG_FLAGS to activate this */ in the CURLOPT_FLAGS to activate this */
T(RANGE, OBJECTPOINT, 7), T(RANGE, OBJECTPOINT, 7),
#if 0
/* Configuration flags */ /* Configuration flags */
T(FLAGS, LONG, 8), T(FLAGS, LONG, 8),
#endif
/* Specified file stream to upload from (use as input): */ /* Specified file stream to upload from (use as input): */
T(INFILE, OBJECTPOINT, 9), T(INFILE, OBJECTPOINT, 9),
/* Buffer to receive error messages in, must be at least URLGET_ERROR_SIZE /* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
bytes big. If this is not used, error messages go to stderr instead: */ * bytes big. If this is not used, error messages go to stderr instead: */
T(ERRORBUFFER, OBJECTPOINT, 10), T(ERRORBUFFER, OBJECTPOINT, 10),
/* Function that will be called to store the output (instead of fwrite). The /* Function that will be called to store the output (instead of fwrite). The
parameters will use fwrite() syntax, make sure to follow them. */ * parameters will use fwrite() syntax, make sure to follow them. */
T(WRITEFUNCTION, FUNCTIONPOINT, 11), T(WRITEFUNCTION, FUNCTIONPOINT, 11),
/* Function that will be called to read the input (instead of fread). The /* Function that will be called to read the input (instead of fread). The
parameters will use fread() syntax, make sure to follow them. */ * parameters will use fread() syntax, make sure to follow them. */
T(READFUNCTION, FUNCTIONPOINT, 12), T(READFUNCTION, FUNCTIONPOINT, 12),
/* Time-out the read operation after this amount of seconds */ /* Time-out the read operation after this amount of seconds */
T(TIMEOUT, LONG, 13), T(TIMEOUT, LONG, 13),
/* If the URGTAG_INFILE is used, this can be used to inform urlget about how /* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
large the file being sent really is. That allows better error checking * how large the file being sent really is. That allows better error
and better verifies that the upload was succcessful. -1 means unknown * checking and better verifies that the upload was succcessful. -1 means
size. */ * unknown size. */
T(INFILESIZE, LONG, 14), T(INFILESIZE, LONG, 14),
/* POST input fields. */ /* POST input fields. */
@@ -364,8 +322,25 @@ typedef enum {
as described elsewhere. */ as described elsewhere. */
T(WRITEINFO, OBJECTPOINT, 40), T(WRITEINFO, OBJECTPOINT, 40),
URGTAG_LASTENTRY /* the last unusued */ /* Previous FLAG bits */
} UrgTag; T(VERBOSE, LONG, 41), /* talk a lot */
T(HEADER, LONG, 42), /* throw the header out too */
T(NOPROGRESS, LONG, 43), /* shut off the progress meter */
T(NOBODY, LONG, 44), /* use HEAD to get http document */
T(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
T(UPLOAD, LONG, 46), /* this is an upload */
T(POST, LONG, 47), /* HTTP POST method */
T(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */
T(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */
T(NETRC, LONG, 51), /* read user+password from .netrc */
T(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
T(FTPASCII, LONG, 53), /* use TYPE A for transfer */
T(PUT, LONG, 54), /* PUT the input file */
T(MUTE, LONG, 55), /* force NOPROGRESS */
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
#define CURL_PROGRESS_STATS 0 /* default progress display */ #define CURL_PROGRESS_STATS 0 /* default progress display */
#define CURL_PROGRESS_BAR 1 #define CURL_PROGRESS_BAR 1
@@ -388,23 +363,11 @@ typedef char bool;
#endif /* (rabe) */ #endif /* (rabe) */
#endif #endif
/********************************************************************** #if 0
* /* At last, I stand here in front of you today and can officially proclaim
* >>> urlget() interface #defines changed in v5! <<< this function prototype as history... 17th of May, 2000 */
*
* You enter parameters as tags. Tags are specified as a pair of parameters.
* The first parameter in a pair is the tag identifier, telling urlget what
* kind of tag it is, and the second is the data. The tags may come in any
* order but MUST ALWAYS BE TERMINATED with an ending URGTAG_DONE (which
* needs no data).
*
* _Very_ simple example:
*
* curl_urlget(URGTAG_URL, "http://www.fts.frontec.se/~dast/", URGTAG_DONE);
*
***********************************************************************/
UrgError curl_urlget(UrgTag, ...); UrgError curl_urlget(UrgTag, ...);
#endif
/* external form function */ /* external form function */
int curl_FormParse(char *string, int curl_FormParse(char *string,
@@ -418,9 +381,10 @@ char *curl_GetEnv(char *variable);
char *curl_version(void); char *curl_version(void);
/* This is the version number */ /* This is the version number */
#define LIBCURL_VERSION "6.5.2" #define LIBCURL_VERSION "7.0.1beta"
#define LIBCURL_VERSION_NUM 0x070001
/* linked-list structure for QUOTE */ /* linked-list structure for the CURLOPT_QUOTE option */
struct curl_slist { struct curl_slist {
char *data; char *data;
struct curl_slist *next; struct curl_slist *next;
@@ -429,4 +393,192 @@ struct curl_slist {
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data); struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list); void curl_slist_free_all(struct curl_slist *list);
#endif /* __URLGET_H */ /*
* NAME curl_init()
*
* DESCRIPTION
*
* Inits libcurl globally. This must be used before any libcurl calls can
* be used. This may install global plug-ins or whatever. (This does not
* do winsock inits in Windows.)
*
* EXAMPLE
*
* curl_init();
*
*/
CURLcode curl_init(void);
/*
* NAME curl_init()
*
* DESCRIPTION
*
* Frees libcurl globally. This must be used after all libcurl calls have
* been used. This may remove global plug-ins or whatever. (This does not
* do winsock cleanups in Windows.)
*
* EXAMPLE
*
* curl_free(curl);
*
*/
void curl_free(void);
/*
* NAME curl_open()
*
* DESCRIPTION
*
* Opens a general curl session. It does not try to connect or do anything
* on the network because of this call. The specified URL is only required
* to enable curl to figure out what protocol to "activate".
*
* A session should be looked upon as a series of requests to a single host. A
* session interacts with one host only, using one single protocol.
*
* The URL is not required. If set to "" or NULL, it can still be set later
* using the curl_setopt() function. If the curl_connect() function is called
* without the URL being known, it will return error.
*
* EXAMPLE
*
* CURLcode result;
* CURL *curl;
* result = curl_open(&curl, "http://curl.haxx.nu/libcurl/");
* if(result != CURL_OK) {
* return result;
* }
* */
CURLcode curl_open(CURL **curl, char *url);
/*
* NAME curl_setopt()
*
* DESCRIPTION
*
* Sets a particular option to the specified value.
*
* EXAMPLE
*
* CURL curl;
* curl_setopt(curl, CURL_HTTP_FOLLOW_LOCATION, TRUE);
*/
CURLcode curl_setopt(CURL *handle, CURLoption option, ...);
/*
* NAME curl_close()
*
* DESCRIPTION
*
* Closes a session previously opened with curl_open()
*
* EXAMPLE
*
* CURL *curl;
* CURLcode result;
*
* result = curl_close(curl);
*/
CURLcode curl_close(CURL *curl); /* the opposite of curl_open() */
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
size_t *n);
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n);
/*
* NAME curl_connect()
*
* DESCRIPTION
*
* Connects to the peer server and performs the initial setup. This function
* writes a connect handle to its second argument that is a unique handle for
* this connect. This allows multiple connects from the same handle returned
* by curl_open().
*
* EXAMPLE
*
* CURLCode result;
* CURL curl;
* CURLconnect connect;
* result = curl_connect(curl, &connect);
*/
CURLcode curl_connect(CURL *curl, CURLconnect **in_connect);
/*
* NAME curl_do()
*
* DESCRIPTION
*
* (Note: May 3rd 2000: this function does not currently allow you to
* specify a document, it will use the one set previously)
*
* This function asks for the particular document, file or resource that
* resides on the server we have connected to. You may specify a full URL,
* just an absolute path or even a relative path. That means, if you're just
* getting one file from the remote site, you can use the same URL as input
* for both curl_open() as well as for this function.
*
* In the even there is a host name, port number, user name or password parts
* in the URL, you can use the 'flags' argument to ignore them completely, or
* at your choice, make the function fail if you're trying to get a URL from
* different host than you connected to with curl_connect().
*
* You can only get one document at a time using the same connection. When one
* document has been received you can although request again.
*
* When the transfer is done, curl_done() MUST be called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_do(connect, url, CURL_DO_NONE); */
CURLcode curl_do(CURLconnect *in_conn);
/*
* NAME curl_done()
*
* DESCRIPTION
*
* When the transfer following a curl_do() call is done, this function should
* get called.
*
* EXAMPLE
*
* CURLCode result;
* char *url;
* CURLconnect *connect;
* result = curl_done(connect); */
CURLcode curl_done(CURLconnect *connect);
/*
* NAME curl_disconnect()
*
* DESCRIPTION
*
* Disconnects from the peer server and performs connection cleanup.
*
* EXAMPLE
*
* CURLcode result;
* CURLconnect *connect;
* result = curl_disconnect(connect); */
CURLcode curl_disconnect(CURLconnect *connect);
/*
* NAME curl_getdate()
*
* DESCRIPTION
*
* Returns the time, in seconds since 1 Jan 1970 of the time string given in
* the first argument. The time argument in the second parameter is for cases
* where the specified time is relative now, like 'two weeks' or 'tomorrow'
* etc.
*/
time_t curl_getdate(const char *p, const time_t *now);
#endif /* __CURL_CURL_H */

46
include/curl/easy.h Normal file
View File

@@ -0,0 +1,46 @@
#ifndef __CURL_EASY_H
#define __CURL_EASY_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
CURL *curl_easy_init(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURLcode curl_easy_perform(CURL *curl);
void curl_easy_cleanup(CURL *curl);
#endif

View File

45
include/curl/types.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __CURL_TYPES_H
#define __CURL_TYPES_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
typedef void CURL;
typedef void CURLconnect;
#endif /* __CURL_TYPES_H */

View File

@@ -7,7 +7,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
noinst_LIBRARIES = libcurl.a noinst_LIBRARIES = libcurl.a
# Some flags needed when trying to cause warnings ;-) # Some flags needed when trying to cause warnings ;-)
#CFLAGS = -g -Wall -pedantic CFLAGS = -g -Wall #-pedantic
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
@@ -23,7 +23,7 @@ download.c getdate.h ldap.c ssluse.c version.c \
download.h getenv.c ldap.h ssluse.h \ download.h getenv.c ldap.h ssluse.h \
escape.c getenv.h mprintf.c telnet.c \ escape.c getenv.h mprintf.c telnet.c \
escape.h getpass.c netrc.c telnet.h \ escape.h getpass.c netrc.c telnet.h \
writeout.c writeout.h writeout.c writeout.h highlevel.c strequal.c strequal.h easy.c
# Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule. # Say $(srcdir), so GNU make does not report an ambiguity with the .y.c rule.
$(srcdir)/getdate.c: getdate.y $(srcdir)/getdate.c: getdate.y

View File

@@ -77,11 +77,11 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
noinst_LIBRARIES = libcurl.a noinst_LIBRARIES = libcurl.a
# Some flags needed when trying to cause warnings ;-) # Some flags needed when trying to cause warnings ;-)
#CFLAGS = -g -Wall -pedantic CFLAGS = -g -Wall #-pedantic
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c telnet.h writeout.c writeout.h libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c telnet.h writeout.c writeout.h highlevel.c strequal.c strequal.h easy.c
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h ../src/config.h CONFIG_HEADER = ../config.h ../src/config.h
@@ -97,9 +97,9 @@ libcurl_a_LIBADD =
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \ libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \ formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
speedcheck.o getdate.o download.o ldap.o ssluse.o version.o getenv.o \ speedcheck.o getdate.o download.o ldap.o ssluse.o version.o getenv.o \
escape.o mprintf.o telnet.o getpass.o netrc.o writeout.o escape.o mprintf.o telnet.o getpass.o netrc.o writeout.o highlevel.o \
strequal.o easy.o
AR = ar AR = ar
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC) CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@
@@ -117,7 +117,7 @@ all: all-redirect
.SUFFIXES: .SUFFIXES:
.SUFFIXES: .S .c .o .s .SUFFIXES: .S .c .o .s
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) $(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
cd $(top_srcdir) && $(AUTOMAKE) --foreign --include-deps lib/Makefile cd $(top_srcdir) && $(AUTOMAKE) --foreign lib/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) \ cd $(top_builddir) \

View File

@@ -9,7 +9,7 @@
CC = gcc CC = gcc
AR = ar AR = ar
RANLIB = ranlib RANLIB = ranlib
OPENSSL_PATH = ../../openssl-0.9.4 OPENSSL_PATH = ../../openssl-0.9.5a
######################################################## ########################################################
## Nothing more to do below this line! ## Nothing more to do below this line!
@@ -31,12 +31,14 @@ urldata.h formdata.c hostip.h netrc.h stdcheaders.h formdata.h \
if2ip.c progress.c sendf.c sendf.h speedcheck.c speedcheck.h \ if2ip.c progress.c sendf.c sendf.h speedcheck.c speedcheck.h \
ftp.c ftp.h getpass.c getpass.h version.c timeval.c timeval.h cookie.c \ ftp.c ftp.h getpass.c getpass.h version.c timeval.c timeval.h cookie.c \
cookie.h escape.c escape.h getdate.c getdate.h dict.h dict.c http.c \ cookie.h escape.c escape.h getdate.c getdate.h dict.h dict.c http.c \
http.h telnet.c telnet.h file.c file.h ldap.c ldap.h writeout.c writeout.h http.h telnet.c telnet.h file.c file.h ldap.c ldap.h writeout.c writeout.h \
highlevel.c strequal.c strequal.h easy.c
libcurl_a_OBJECTS = base64.o getenv.o mprintf.o url.o download.o \ libcurl_a_OBJECTS = base64.o getenv.o mprintf.o url.o download.o \
getpass.o ssluse.o hostip.o netrc.o formdata.o if2ip.o progress.o \ getpass.o ssluse.o hostip.o netrc.o formdata.o if2ip.o progress.o \
sendf.o speedcheck.o ftp.o getpass.o version.o timeval.o \ sendf.o speedcheck.o ftp.o getpass.o version.o timeval.o \
cookie.o escape.o getdate.o dict.o http.o telnet.o file.o ldap.o writeout.o cookie.o escape.o getdate.o dict.o http.o telnet.o file.o ldap.o writeout.o \
highlevel.o strequal.o easy.o
LIBRARIES = $(libcurl_a_LIBRARIES) LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES) SOURCES = $(libcurl_a_SOURCES)
@@ -63,5 +65,6 @@ clean:
-@erase $(libcurl_a_OBJECTS) -@erase $(libcurl_a_OBJECTS)
distrib: clean distrib: clean
-@erase $(libcurl_a_LIBRARIES) -@erase $(libcurl_a_LIBRARIES)

View File

@@ -23,7 +23,7 @@ LINKD = link.exe -lib
CCRS = cl.exe /ML /O2 /D "NDEBUG" /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl" CCRS = cl.exe /ML /O2 /D "NDEBUG" /D "USE_SSLEAY" /I "$(OPENSSL_PATH)/inc32" /I "$(OPENSSL_PATH)/inc32/openssl"
LINKRS = link.exe -lib /LIBPATH:$(OPENSSL_PATH)/out32dll LINKRS = link.exe -lib /LIBPATH:$(OPENSSL_PATH)/out32dll
CFLAGS = /nologo /W3 /GX /D "WIN32" /D "_MBCS" /D "_LIB" /YX /FD /c CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "VC6" /D "_MBCS" /D "_LIB" /YX /FD /c /D "MSDOS"
LFLAGS = /nologo /out:$(PROGRAM_NAME) LFLAGS = /nologo /out:$(PROGRAM_NAME)
LINKLIBS = kernel32.lib wsock32.lib LINKLIBS = kernel32.lib wsock32.lib
LINKSLIBS = libeay32.lib ssleay32.lib RSAglue.lib LINKSLIBS = libeay32.lib ssleay32.lib RSAglue.lib

View File

@@ -62,6 +62,7 @@ Example set of cookies:
#include "cookie.h" #include "cookie.h"
#include "setup.h" #include "setup.h"
#include "getdate.h" #include "getdate.h"
#include "strequal.h"
/**************************************************************************** /****************************************************************************
* *
@@ -131,7 +132,7 @@ struct Cookie *cookie_add(struct CookieInfo *c,
} }
else if(strequal("expires", name)) { else if(strequal("expires", name)) {
co->expirestr=strdup(what); co->expirestr=strdup(what);
co->expires = get_date(what, &now); co->expires = curl_getdate(what, &now);
} }
else if(!co->name) { else if(!co->name) {
co->name = strdup(name); co->name = strdup(name);
@@ -173,9 +174,11 @@ struct Cookie *cookie_add(struct CookieInfo *c,
return NULL; return NULL;
} }
/* strip off the possible end-of-line characters */ /* strip off the possible end-of-line characters */
if(ptr=strchr(lineptr, '\r')) ptr=strchr(lineptr, '\r');
if(ptr)
*ptr=0; /* clear it */ *ptr=0; /* clear it */
if(ptr=strchr(lineptr, '\n')) ptr=strchr(lineptr, '\n');
if(ptr)
*ptr=0; /* clear it */ *ptr=0; /* clear it */
firstptr=strtok(lineptr, "\t"); /* first tokenize it on the TAB */ firstptr=strtok(lineptr, "\t"); /* first tokenize it on the TAB */

View File

@@ -92,12 +92,17 @@
#include "sendf.h" #include "sendf.h"
#include "progress.h" #include "progress.h"
#include "strequal.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
CURLcode dict_done(struct connectdata *conn)
{
return CURLE_OK;
}
UrgError dict(struct UrlData *data, char *path, long *bytecount) CURLcode dict(struct connectdata *conn)
{ {
int nth; int nth;
char *word; char *word;
@@ -106,9 +111,13 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
char *strategy = NULL; char *strategy = NULL;
char *nthdef = NULL; /* This is not part of the protocol, but required char *nthdef = NULL; /* This is not part of the protocol, but required
by RFC 2229 */ by RFC 2229 */
UrgError result=URG_OK; CURLcode result=CURLE_OK;
struct UrlData *data=conn->data;
if(data->conf & CONF_USERPWD) { char *path = conn->path;
long *bytecount = &conn->bytecount;
if(data->bits.user_passwd) {
/* AUTH is missing */ /* AUTH is missing */
} }
@@ -162,7 +171,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
word word
); );
result = Transfer(data, data->firstsocket, -1, FALSE, bytecount, result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
@@ -210,7 +219,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
word word
); );
result = Transfer(data, data->firstsocket, -1, FALSE, bytecount, result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
@@ -234,7 +243,7 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
"QUIT\n", "QUIT\n",
ppath); ppath);
result = Transfer(data, data->firstsocket, -1, FALSE, bytecount, result = Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); -1, NULL);
if(result) if(result)
@@ -243,10 +252,5 @@ UrgError dict(struct UrlData *data, char *path, long *bytecount)
} }
} }
#if 0 return CURLE_OK;
ProgressEnd(data);
#endif
pgrsDone(data);
return URG_OK;
} }

View File

@@ -40,6 +40,7 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError dict(struct UrlData *data, char *path, long *bytecountp); CURLcode dict(struct connectdata *conn);
CURLcode dict_done(struct connectdata *conn);
#endif #endif

View File

@@ -78,19 +78,15 @@
#include "speedcheck.h" #include "speedcheck.h"
#include "sendf.h" #include "sendf.h"
#ifdef USE_ZLIB #include <curl/types.h>
#include <zlib.h>
#endif
#define MAX(x,y) ((x)>(y)?(x):(y))
/* --- download and upload a stream from/to a socket --- */ /* --- download and upload a stream from/to a socket --- */
/* Parts of this function was brought to us by the friendly Mark Butler /* Parts of this function was brought to us by the friendly Mark Butler
<butlerm@xmission.com>. */ <butlerm@xmission.com>. */
UrgError CURLcode
Transfer (struct UrlData *data, Transfer(CURLconnect *c_conn,
/* READ stuff */ /* READ stuff */
int sockfd, /* socket to read from or -1 */ int sockfd, /* socket to read from or -1 */
int size, /* -1 if unknown at this point */ int size, /* -1 if unknown at this point */
@@ -101,485 +97,21 @@ Transfer (struct UrlData *data,
int writesockfd, /* socket to write to, it may very well be int writesockfd, /* socket to write to, it may very well be
the same we read from. -1 disables */ the same we read from. -1 disables */
long *writebytecountp /* return number of bytes written or NULL */ long *writebytecountp /* return number of bytes written or NULL */
)
)
{ {
char *buf = data->buffer; struct connectdata *conn = (struct connectdata *)c_conn;
size_t nread; if(!conn)
int bytecount = 0; /* number of bytes read */ return CURLE_BAD_FUNCTION_ARGUMENT;
int writebytecount = 0; /* number of bytes written */
long contentlength=0; /* size of incoming data */
struct timeval start = tvnow();
struct timeval now = start;
bool header = TRUE; /* incoming data has HTTP header */
int headerline = 0; /* counts header lines to better track the
first one */
char *hbufp; /* points at *end* of header line */ /* now copy all input parameters */
int hbuflen = 0; conn->sockfd = sockfd;
char *str; /* within buf */ conn->size = size;
char *str_start; /* within buf */ conn->getheader = getheader;
char *end_ptr; /* within buf */ conn->bytecountp = bytecountp;
char *p; /* within headerbuff */ conn->writesockfd = writesockfd;
bool content_range = FALSE; /* set TRUE if Content-Range: was found */ conn->writebytecountp = writebytecountp;
int offset = 0; /* possible resume offset read from the
Content-Range: header */
int code = 0; /* error code from the 'HTTP/1.? XXX' line */
/* for the low speed checks: */ return CURLE_OK;
UrgError urg;
time_t timeofdoc=0;
long bodywrites=0;
char newurl[URL_MAX_LENGTH]; /* buffer for Location: URL */
/* the highest fd we use + 1 */
int maxfd = (sockfd>writesockfd?sockfd:writesockfd)+1;
hbufp = data->headerbuff;
myalarm (0); /* switch off the alarm-style timeout */
now = tvnow();
start = now;
#define KEEP_READ 1
#define KEEP_WRITE 2
pgrsTime(data, TIMER_PRETRANSFER);
if (!getheader) {
header = FALSE;
if(size > 0)
pgrsSetDownloadSize(data, size);
}
{
fd_set readfd;
fd_set writefd;
fd_set rkeepfd;
fd_set wkeepfd;
struct timeval interval;
int keepon=0;
/* timeout every X second
- makes a better progressmeter (i.e even when no data is read, the
meter can be updated and reflect reality)
- allows removal of the alarm() crap
- variable timeout is easier
*/
FD_ZERO (&readfd); /* clear it */
if(sockfd != -1) {
FD_SET (sockfd, &readfd); /* read socket */
keepon |= KEEP_READ;
}
FD_ZERO (&writefd); /* clear it */
if(writesockfd != -1) {
FD_SET (writesockfd, &writefd); /* write socket */
keepon |= KEEP_WRITE;
}
/* get these in backup variables to be able to restore them on each lap in
the select() loop */
rkeepfd = readfd;
wkeepfd = writefd;
while (keepon) {
readfd = rkeepfd; /* set those every lap in the loop */
writefd = wkeepfd;
interval.tv_sec = 1;
interval.tv_usec = 0;
switch (select (maxfd, &readfd, &writefd, NULL, &interval)) {
case -1: /* select() error, stop reading */
keepon = 0; /* no more read or write */
continue;
case 0: /* timeout */
break;
default:
if((keepon & KEEP_READ) && FD_ISSET(sockfd, &readfd)) {
/* read! */
#ifdef USE_SSLEAY
if (data->use_ssl) {
nread = SSL_read (data->ssl, buf, BUFSIZE - 1);
}
else {
#endif
nread = sread (sockfd, buf, BUFSIZE - 1);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
/* NULL terminate, allowing string ops to be used */
if (0 < (signed int) nread)
buf[nread] = 0;
/* if we receive 0 or less here, the server closed the connection and
we bail out from this! */
else if (0 >= (signed int) nread) {
keepon &= ~KEEP_READ;
break;
}
str = buf; /* Default buffer to use when we write the
buffer, it may be changed in the flow below
before the actual storing is done. */
/* Since this is a two-state thing, we check if we are parsing
headers at the moment or not. */
if (header) {
/* we are in parse-the-header-mode */
/* header line within buffer loop */
do {
int hbufp_index;
str_start = str; /* str_start is start of line within buf */
end_ptr = strchr (str_start, '\n');
if (!end_ptr) {
/* no more complete header lines within buffer */
/* copy what is remaining into headerbuff */
int str_length = (int)strlen(str);
if (hbuflen + (int)str_length >= data->headersize) {
char *newbuff;
long newsize=MAX((hbuflen+str_length)*3/2,
data->headersize*2);
hbufp_index = hbufp - data->headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize);
if(!newbuff) {
failf (data, "Failed to alloc memory for big header!");
return URG_READ_ERROR;
}
data->headersize=newsize;
data->headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index;
}
strcpy (hbufp, str);
hbufp += strlen (str);
hbuflen += strlen (str);
break; /* read more and try again */
}
str = end_ptr + 1; /* move just past new line */
if (hbuflen + (str - str_start) >= data->headersize) {
char *newbuff;
long newsize=MAX((hbuflen+(str-str_start))*3/2,
data->headersize*2);
hbufp_index = hbufp - data->headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize);
if(!newbuff) {
failf (data, "Failed to alloc memory for big header!");
return URG_READ_ERROR;
}
data->headersize= newsize;
data->headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index;
}
/* copy to end of line */
strncpy (hbufp, str_start, str - str_start);
hbufp += str - str_start;
hbuflen += str - str_start;
*hbufp = 0;
p = data->headerbuff;
/* we now have a full line that p points to */
if (('\n' == *p) || ('\r' == *p)) {
/* Zero-length line means end of header! */
if (-1 != size) /* if known */
size += bytecount; /* we append the already read size */
if ('\r' == *p)
p++; /* pass the \r byte */
if ('\n' == *p)
p++; /* pass the \n byte */
pgrsSetDownloadSize(data, size);
header = FALSE; /* no more header to parse! */
/* now, only output this if the header AND body are requested:
*/
if ((data->conf & (CONF_HEADER | CONF_NOBODY)) ==
CONF_HEADER) {
if((p - data->headerbuff) !=
data->fwrite (data->headerbuff, 1,
p - data->headerbuff, data->out)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
if(data->writeheader) {
/* obviously, the header is requested to be written to
this file: */
if((p - data->headerbuff) !=
data->fwrite (data->headerbuff, 1, p - data->headerbuff,
data->writeheader)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
break; /* exit header line loop */
}
if (!headerline++) {
/* This is the first header, it MUST be the error code line
or else we consiser this to be the body right away! */
if (sscanf (p, " HTTP/1.%*c %3d", &code)) {
/* 404 -> URL not found! */
if (
( ((data->conf & CONF_FOLLOWLOCATION) && (code >= 400))
||
!(data->conf & CONF_FOLLOWLOCATION) && (code >= 300))
&& (data->conf & CONF_FAILONERROR)) {
/* If we have been told to fail hard on HTTP-errors,
here is the check for that: */
/* serious error, go home! */
failf (data, "The requested file was not found");
return URG_HTTP_NOT_FOUND;
}
data->progress.httpcode = code;
}
else {
header = FALSE; /* this is not a header line */
break;
}
}
/* check for Content-Length: header lines to get size */
if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength))
size = contentlength;
else if (strnequal("Content-Range", p, 13) &&
sscanf (p+13, ": bytes %d-", &offset)) {
if (data->resume_from == offset) {
/* we asked for a resume and we got it */
content_range = TRUE;
}
}
else if(data->cookies &&
strnequal("Set-Cookie: ", p, 11)) {
cookie_add(data->cookies, TRUE, &p[12]);
}
else if(strnequal("Last-Modified:", p,
strlen("Last-Modified:")) &&
data->timecondition) {
time_t secs=time(NULL);
timeofdoc = get_date(p+strlen("Last-Modified:"), &secs);
}
else if ((code >= 300 && code < 400) &&
(data->conf & CONF_FOLLOWLOCATION) &&
strnequal("Location", p, 8) &&
sscanf (p+8, ": %" URL_MAX_LENGTH_TXT "s", newurl)) {
/* this is the URL that the server advices us to get
instead */
data->newurl = strdup (newurl);
}
if (data->conf & CONF_HEADER) {
if(hbuflen != data->fwrite (p, 1, hbuflen, data->out)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
if(data->writeheader) {
/* the header is requested to be written to this file */
if(hbuflen != data->fwrite (p, 1, hbuflen,
data->writeheader)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
}
/* reset hbufp pointer && hbuflen */
hbufp = data->headerbuff;
hbuflen = 0;
}
while (*str); /* header line within buffer */
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
if (!header) {
/* the next token and forward is not part of
the header! */
/* we subtract the remaining header size from the buffer */
nread -= (str - buf);
}
} /* end if header mode */
/* This is not an 'else if' since it may be a rest from the header
parsing, where the beginning of the buffer is headers and the end
is non-headers. */
if (str && !header && (nread > 0)) {
if(0 == bodywrites) {
/* These checks are only made the first time we are about to
write a chunk of the body */
if(data->conf&CONF_HTTP) {
/* HTTP-only checks */
if (data->resume_from && !content_range ) {
/* we wanted to resume a download, although the server
doesn't seem to support this */
failf (data, "HTTP server doesn't seem to support byte ranges. Cannot resume.");
return URG_HTTP_RANGE_ERROR;
}
else if (data->newurl) {
/* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl);
return URG_OK;
}
else if(data->timecondition && !data->range) {
/* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of
RFC 2616 defines to be the correct action for a
HTTP/1.1 client */
if((timeofdoc > 0) && (data->timevalue > 0)) {
switch(data->timecondition) {
case TIMECOND_IFMODSINCE:
default:
if(timeofdoc < data->timevalue) {
infof(data,
"The requested document is not new enough");
return URG_OK;
}
break;
case TIMECOND_IFUNMODSINCE:
if(timeofdoc > data->timevalue) {
infof(data,
"The requested document is not old enough");
return URG_OK;
}
break;
} /* switch */
} /* two valid time strings */
} /* we have a time condition */
} /* this is HTTP */
} /* this is the first time we write a body part */
bodywrites++;
if(data->maxdownload &&
(bytecount + nread > data->maxdownload)) {
nread = data->maxdownload - bytecount;
if(nread < 0 ) /* this should be unusual */
nread = 0;
keepon &= ~KEEP_READ; /* we're done reading */
}
bytecount += nread;
pgrsSetDownloadCounter(data, (double)bytecount);
if (nread != data->fwrite (str, 1, nread, data->out)) {
failf (data, "Failed writing output");
return URG_WRITE_ERROR;
}
} /* if (! header and data to read ) */
} /* if( read from socket ) */
if((keepon & KEEP_WRITE) && FD_ISSET(writesockfd, &writefd)) {
/* write */
char scratch[BUFSIZE * 2];
int i, si;
int bytes_written;
if(data->crlf)
buf = data->buffer; /* put it back on the buffer */
nread = data->fread(buf, 1, BUFSIZE, data->in);
writebytecount += nread;
pgrsSetUploadCounter(data, (double)writebytecount);
if (nread<=0) {
/* done */
keepon &= ~KEEP_WRITE; /* we're done writing */
break;
}
/* convert LF to CRLF if so asked */
if (data->crlf) {
for(i = 0, si = 0; i < (int)nread; i++, si++) {
if (buf[i] == 0x0a) {
scratch[si++] = 0x0d;
scratch[si] = 0x0a;
}
else {
scratch[si] = buf[i];
}
}
nread = si;
buf = scratch; /* point to the new buffer */
}
/* write to socket */
#ifdef USE_SSLEAY
if (data->use_ssl) {
bytes_written = SSL_write(data->ssl, buf, nread);
}
else {
#endif
bytes_written = swrite(writesockfd, buf, nread);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
if(nread != bytes_written) {
failf(data, "Failed uploading data");
return URG_WRITE_ERROR;
}
}
break;
}
now = tvnow();
pgrsUpdate(data);
urg = speedcheck (data, now);
if (urg)
return urg;
if (data->timeout && (tvdiff (now, start) > data->timeout)) {
failf (data, "Operation timed out with %d out of %d bytes received",
bytecount, size);
return URG_OPERATION_TIMEOUTED;
}
#ifdef MULTIDOC
if(contentlength && bytecount >= contentlength) {
/* we're done with this download, now stop it */
break;
}
#endif
}
}
if(!(data->conf&CONF_NOBODY) && contentlength &&
(bytecount != contentlength)) {
failf(data, "transfer closed with %d bytes remaining to read",
contentlength-bytecount);
return URG_PARTIAL_FILE;
}
pgrsUpdate(data);
if(bytecountp)
*bytecountp = bytecount; /* read count */
if(writebytecountp)
*writebytecountp = writebytecount; /* write count */
return URG_OK;
} }

View File

@@ -39,8 +39,8 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError CURLcode
Transfer (struct UrlData *data, Transfer (struct connectdata *data,
int sockfd, /* socket to read from or -1 */ int sockfd, /* socket to read from or -1 */
int size, /* -1 if unknown at this point */ int size, /* -1 if unknown at this point */
bool getheader, /* TRUE if header parsing is wanted */ bool getheader, /* TRUE if header parsing is wanted */

160
lib/easy.c Normal file
View File

@@ -0,0 +1,160 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "setup.h"
#include "strequal.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#endif
#include "urldata.h"
#include <curl/curl.h>
#include "highlevel.h"
#include <curl/types.h>
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
CURL *curl_easy_init(void)
{
CURLcode res;
struct UrlData *data;
if(curl_init())
return NULL;
/* We use curl_open() with undefined URL so far */
res = curl_open((CURL **)&data, NULL);
if(res != CURLE_OK)
return NULL;
data->interf = CURLI_EASY; /* mark it as an easy one */
return data;
}
typedef int (*func_T)(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
{
va_list arg;
func_T param_func = (func_T)0;
long param_long = 0;
void *param_obj = NULL;
struct UrlData *data = curl;
va_start(arg, tag);
/* PORTING NOTE:
Object pointers can't necessarily be casted to function pointers and
therefore we need to know what type it is and read the correct type
at once. This should also correct problems with different sizes of
the types.
*/
if(tag < CURLOPTTYPE_OBJECTPOINT) {
/* This is a LONG type */
param_long = va_arg(arg, long);
curl_setopt(data, tag, param_long);
}
else if(tag < CURLOPTTYPE_FUNCTIONPOINT) {
/* This is a object pointer type */
param_obj = va_arg(arg, void *);
curl_setopt(data, tag, param_obj);
}
else {
param_func = va_arg(arg, func_T );
curl_setopt(data, tag, param_func);
}
va_end(arg);
return CURLE_OK;
}
CURLcode curl_easy_perform(CURL *curl)
{
return curl_transfer(curl);
}
void curl_easy_cleanup(CURL *curl)
{
curl_close(curl);
curl_free();
}

View File

@@ -81,16 +81,15 @@ char *curl_escape(char *string)
return ns; return ns;
} }
char *curl_unescape(char *string) char *curl_unescape(char *string, int length)
{ {
int alloc = strlen(string)+1; int alloc = (length?length:strlen(string))+1;
char *ns = malloc(alloc); char *ns = malloc(alloc);
unsigned char in; unsigned char in;
int index=0; int index=0;
int hex; int hex;
while(--alloc) {
while(*string) {
in = *string; in = *string;
if('+' == in) if('+' == in)
in = ' '; in = ' ';

View File

@@ -44,6 +44,6 @@
* allocated string or NULL if an error occurred. */ * allocated string or NULL if an error occurred. */
char *curl_escape(char *string); char *curl_escape(char *string);
char *curl_unescape(char *string); char *curl_unescape(char *string, int length);
#endif #endif

View File

@@ -100,23 +100,25 @@
#include <curl/mprintf.h> #include <curl/mprintf.h>
UrgError file(struct UrlData *data, char *path, long *bytecountp) CURLcode file(struct connectdata *conn)
{ {
/* This implementation ignores the host name in conformance with /* This implementation ignores the host name in conformance with
RFC 1738. Only local files (reachable via the standard file system) RFC 1738. Only local files (reachable via the standard file system)
are supported. This means that files on remotely mounted directories are supported. This means that files on remotely mounted directories
(via NFS, Samba, NT sharing) can be accessed through a file:// URL (via NFS, Samba, NT sharing) can be accessed through a file:// URL
*/ */
CURLcode res = CURLE_OK;
char *path = conn->path;
struct stat statbuf; struct stat statbuf;
size_t expected_size=-1; size_t expected_size=-1;
size_t nread; size_t nread;
struct UrlData *data = conn->data;
char *buf = data->buffer; char *buf = data->buffer;
int bytecount = 0; int bytecount = 0;
struct timeval start = tvnow(); struct timeval start = tvnow();
struct timeval now = start; struct timeval now = start;
int fd; int fd;
char *actual_path = curl_unescape(path); char *actual_path = curl_unescape(path, 0);
#if defined(WIN32) || defined(__EMX__) #if defined(WIN32) || defined(__EMX__)
int i; int i;
@@ -134,7 +136,7 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
if(fd == -1) { if(fd == -1) {
failf(data, "Couldn't open file %s", path); failf(data, "Couldn't open file %s", path);
return URG_FILE_COULDNT_READ_FILE; return CURLE_FILE_COULDNT_READ_FILE;
} }
if( -1 != fstat(fd, &statbuf)) { if( -1 != fstat(fd, &statbuf)) {
/* we could stat it, then read out the size */ /* we could stat it, then read out the size */
@@ -151,7 +153,7 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
if(expected_size != -1) if(expected_size != -1)
pgrsSetDownloadSize(data, expected_size); pgrsSetDownloadSize(data, expected_size);
while (1) { while (res == CURLE_OK) {
nread = read(fd, buf, BUFSIZE-1); nread = read(fd, buf, BUFSIZE-1);
if (0 <= nread) if (0 <= nread)
@@ -166,21 +168,19 @@ UrgError file(struct UrlData *data, char *path, long *bytecountp)
file descriptor). */ file descriptor). */
if(nread != data->fwrite (buf, 1, nread, data->out)) { if(nread != data->fwrite (buf, 1, nread, data->out)) {
failf (data, "Failed writing output"); failf (data, "Failed writing output");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
now = tvnow(); now = tvnow();
pgrsUpdate(data); if(pgrsUpdate(data))
#if 0 res = CURLE_ABORTED_BY_CALLBACK;
ProgressShow (data, bytecount, start, now, FALSE);
#endif
} }
now = tvnow(); now = tvnow();
#if 0 if(pgrsUpdate(data))
ProgressShow (data, bytecount, start, now, TRUE); res = CURLE_ABORTED_BY_CALLBACK;
#endif
pgrsUpdate(data);
close(fd); close(fd);
return URG_OK; free(actual_path);
return res;
} }

View File

@@ -40,6 +40,6 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError file(struct UrlData *data, char *path, long *bytecountp); CURLcode file(struct connectdata *conn);
#endif #endif

View File

@@ -60,6 +60,8 @@
#include <curl/curl.h> #include <curl/curl.h>
#include "formdata.h" #include "formdata.h"
#include "strequal.h"
/* Length of the random boundary string. The risk of this being used /* Length of the random boundary string. The risk of this being used
in binary data is very close to zero, 64^32 makes in binary data is very close to zero, 64^32 makes
6277101735386680763835789423207666416102355444464034512896 6277101735386680763835789423207666416102355444464034512896
@@ -377,7 +379,7 @@ void FormFree(struct FormData *form)
free(form->line); /* free the line */ free(form->line); /* free the line */
free(form); /* free the struct */ free(form); /* free the struct */
} while(form=next); /* continue */ } while((form=next)); /* continue */
} }
struct FormData *getFormData(struct HttpPost *post, struct FormData *getFormData(struct HttpPost *post,
@@ -513,12 +515,17 @@ struct FormData *getFormData(struct HttpPost *post,
int FormInit(struct Form *form, struct FormData *formdata ) int FormInit(struct Form *form, struct FormData *formdata )
{ {
form->data = formdata;
form->sent = 0;
if(!formdata) if(!formdata)
return 1; /* error */ return 1; /* error */
/* First, make sure that we'll send a nice terminating sequence at the end
* of the post. We *DONT* add this string to the size of the data since this
* is actually AFTER the data. */
AddFormDataf(&formdata, "\r\n\r\n");
form->data = formdata;
form->sent = 0;
return 0; return 0;
} }

516
lib/ftp.c
View File

@@ -56,7 +56,10 @@
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__) #if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h> #include <winsock.h>
#else /* some kind of unix */ #else /* some kind of unix */
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <sys/types.h>
#include <netinet/in.h> #include <netinet/in.h>
#ifdef HAVE_ARPA_INET_H #ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h> #include <arpa/inet.h>
@@ -69,6 +72,9 @@
#include <errno.h> #include <errno.h>
#endif #endif
#ifdef HAVE_INET_NTOA_R
#include "inet_ntoa_r.h"
#endif
#include <curl/curl.h> #include <curl/curl.h>
#include "urldata.h" #include "urldata.h"
@@ -149,7 +155,7 @@ void curl_slist_free_all(struct curl_slist *list)
} }
static UrgError AllowServerConnect(struct UrlData *data, static CURLcode AllowServerConnect(struct UrlData *data,
int sock) int sock)
{ {
fd_set rdset; fd_set rdset;
@@ -167,11 +173,11 @@ static UrgError AllowServerConnect(struct UrlData *data,
case -1: /* error */ case -1: /* error */
/* let's die here */ /* let's die here */
failf(data, "Error while waiting for server connect"); failf(data, "Error while waiting for server connect");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
case 0: /* timeout */ case 0: /* timeout */
/* let's die here */ /* let's die here */
failf(data, "Timeout while waiting for server connect"); failf(data, "Timeout while waiting for server connect");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
default: default:
/* we have received data here */ /* we have received data here */
{ {
@@ -185,7 +191,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
if( -1 == s) { if( -1 == s) {
/* DIE! */ /* DIE! */
failf(data, "Error accept()ing server connect"); failf(data, "Error accept()ing server connect");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
infof(data, "Connection accepted from server\n"); infof(data, "Connection accepted from server\n");
@@ -193,7 +199,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
} }
break; break;
} }
return URG_OK; return CURLE_OK;
} }
@@ -202,7 +208,7 @@ static UrgError AllowServerConnect(struct UrlData *data,
#define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \ #define lastline(line) (isdigit((int)line[0]) && isdigit((int)line[1]) && \
isdigit((int)line[2]) && (' ' == line[3])) isdigit((int)line[2]) && (' ' == line[3]))
static int GetLastResponse(int sockfd, char *buf, int GetLastResponse(int sockfd, char *buf,
struct UrlData *data) struct UrlData *data)
{ {
int nread; int nread;
@@ -230,7 +236,7 @@ static int GetLastResponse(int sockfd, char *buf,
} }
*ptr=0; /* zero terminate */ *ptr=0; /* zero terminate */
if(data->conf & CONF_VERBOSE) { if(data->bits.verbose) {
fputs("< ", data->err); fputs("< ", data->err);
fwrite(buf, 1, nread, data->err); fwrite(buf, 1, nread, data->err);
fputs("\n", data->err); fputs("\n", data->err);
@@ -241,26 +247,20 @@ static int GetLastResponse(int sockfd, char *buf,
} }
/* -- who are we? -- */ /* -- who are we? -- */
char *getmyhost(void) char *getmyhost(char *buf, int buf_size)
{ {
static char myhost[256]; #if defined(HAVE_GETHOSTNAME)
#ifdef HAVE_UNAME gethostname(buf, buf_size);
#elif defined(HAVE_UNAME)
struct utsname ugnm; struct utsname ugnm;
strncpy(buf, uname(&ugnm) < 0 ? "localhost" : ugnm.nodename, buf_size - 1);
if (uname(&ugnm) < 0) buf[buf_size - 1] = '\0';
return "localhost"; #else
(void) strncpy(myhost, ugnm.nodename, 255);
myhost[255] = '\0';
#endif
#ifdef HAVE_GETHOSTNAME
gethostname(myhost, 256);
#endif
#if !defined(HAVE_UNAME) && !defined(HAVE_GETHOSTNAME)
/* We have no means of finding the local host name! */ /* We have no means of finding the local host name! */
strcpy(myhost, "localhost"); strncpy(buf, "localhost", buf_size);
buf[buf_size - 1] = '\0';
#endif #endif
return myhost; return buf;
} }
#if 0 #if 0
@@ -310,32 +310,37 @@ static char *URLfix(char *string)
} }
#endif #endif
static /* ftp_connect() should do everything that is to be considered a part
UrgError _ftp(struct UrlData *data, of the connection phase. */
long *bytecountp, CURLcode ftp_connect(struct connectdata *conn)
char *ftpuser,
char *ftppasswd,
char *ppath)
{ {
/* this is FTP and no proxy */ /* this is FTP and no proxy */
size_t nread; size_t nread;
UrgError result; struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is our buffer */ char *buf = data->buffer; /* this is our buffer */
/* for the ftp PORT mode */ struct FTP *ftp;
int portsock=-1;
struct sockaddr_in serv_addr;
struct curl_slist *qitem; /* QUOTE item */ ftp = (struct FTP *)malloc(sizeof(struct FTP));
if(!ftp)
return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp;
/* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount;
ftp->user = data->user;
ftp->passwd = data->passwd;
/* The first thing we do is wait for the "220*" line: */ /* The first thing we do is wait for the "220*" line: */
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "220", 3)) { if(strncmp(buf, "220", 3)) {
failf(data, "This doesn't seem like a nice ftp-server response"); failf(data, "This doesn't seem like a nice ftp-server response");
return URG_FTP_WEIRD_SERVER_REPLY; return CURLE_FTP_WEIRD_SERVER_REPLY;
} }
/* send USER */ /* send USER */
sendf(data->firstsocket, data, "USER %s\r\n", ftpuser); sendf(data->firstsocket, data, "USER %s\r\n", ftp->user);
/* wait for feedback */ /* wait for feedback */
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
@@ -344,19 +349,19 @@ UrgError _ftp(struct UrlData *data,
/* 530 User ... access denied /* 530 User ... access denied
(the server denies to log the specified user) */ (the server denies to log the specified user) */
failf(data, "Access denied: %s", &buf[4]); failf(data, "Access denied: %s", &buf[4]);
return URG_FTP_ACCESS_DENIED; return CURLE_FTP_ACCESS_DENIED;
} }
else if(!strncmp(buf, "331", 3)) { else if(!strncmp(buf, "331", 3)) {
/* 331 Password required for ... /* 331 Password required for ...
(the server requires to send the user's password too) */ (the server requires to send the user's password too) */
sendf(data->firstsocket, data, "PASS %s\r\n", ftppasswd); sendf(data->firstsocket, data, "PASS %s\r\n", ftp->passwd);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(!strncmp(buf, "530", 3)) { if(!strncmp(buf, "530", 3)) {
/* 530 Login incorrect. /* 530 Login incorrect.
(the username and/or the password are incorrect) */ (the username and/or the password are incorrect) */
failf(data, "the username and/or the password are incorrect"); failf(data, "the username and/or the password are incorrect");
return URG_FTP_USER_PASSWORD_INCORRECT; return CURLE_FTP_USER_PASSWORD_INCORRECT;
} }
else if(!strncmp(buf, "230", 3)) { else if(!strncmp(buf, "230", 3)) {
/* 230 User ... logged in. /* 230 User ... logged in.
@@ -366,7 +371,7 @@ UrgError _ftp(struct UrlData *data,
} }
else { else {
failf(data, "Odd return code after PASS"); failf(data, "Odd return code after PASS");
return URG_FTP_WEIRD_PASS_REPLY; return CURLE_FTP_WEIRD_PASS_REPLY;
} }
} }
else if(! strncmp(buf, "230", 3)) { else if(! strncmp(buf, "230", 3)) {
@@ -376,9 +381,109 @@ UrgError _ftp(struct UrlData *data,
} }
else { else {
failf(data, "Odd return code after USER"); failf(data, "Odd return code after USER");
return URG_FTP_WEIRD_USER_REPLY; return CURLE_FTP_WEIRD_USER_REPLY;
} }
return CURLE_OK;
}
/* argument is already checked for validity */
CURLcode ftp_done(struct connectdata *conn)
{
struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp;
size_t nread;
char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */
if(data->bits.upload) {
if((-1 != data->infilesize) && (data->infilesize != *ftp->bytecountp)) {
failf(data, "Wrote only partial file (%d out of %d bytes)",
*ftp->bytecountp, data->infilesize);
return CURLE_PARTIAL_FILE;
}
}
else {
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
(data->maxdownload != *ftp->bytecountp)) {
failf(data, "Received only partial file");
return CURLE_PARTIAL_FILE;
}
else if(0 == *ftp->bytecountp) {
failf(data, "No data was received!");
return CURLE_FTP_COULDNT_RETR_FILE;
}
}
/* shut down the socket to inform the server we're done */
sclose(data->secondarysocket);
data->secondarysocket = -1;
/* now let's see what the server says about the transfer we
just performed: */
nread = GetLastResponse(data->firstsocket, buf, data);
/* 226 Transfer complete */
if(strncmp(buf, "226", 3)) {
failf(data, "%s", buf+4);
return CURLE_FTP_WRITE_ERROR;
}
/* Send any post-transfer QUOTE strings? */
if(data->postquote) {
qitem = data->postquote;
/* Send all QUOTE strings in same order as on command-line */
while (qitem) {
/* Send string */
if (qitem->data) {
sendf(data->firstsocket, data, "%s\r\n", qitem->data);
nread = GetLastResponse(data->firstsocket, buf, data);
if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s",
qitem->data);
return CURLE_FTP_QUOTE_ERROR;
}
}
qitem = qitem->next;
}
}
if(ftp->file)
free(ftp->file);
if(ftp->dir)
free(ftp->dir);
/* TBD: the ftp struct is still allocated here */
return CURLE_OK;
}
static
CURLcode _ftp(struct connectdata *conn)
{
/* this is FTP and no proxy */
size_t nread;
CURLcode result;
struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is our buffer */
/* for the ftp PORT mode */
int portsock=-1;
struct sockaddr_in serv_addr;
char hostent_buf[512];
#if defined (HAVE_INET_NTOA_R)
char ntoa_buf[64];
#endif
struct curl_slist *qitem; /* QUOTE item */
/* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->proto.ftp;
long *bytecountp = ftp->bytecountp;
/* Send any QUOTE strings? */ /* Send any QUOTE strings? */
if(data->quote) { if(data->quote) {
qitem = data->quote; qitem = data->quote;
@@ -393,7 +498,7 @@ UrgError _ftp(struct UrlData *data,
if (buf[0] != '2') { if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s", failf(data, "QUOT string not accepted: %s",
qitem->data); qitem->data);
return URG_FTP_QUOTE_ERROR; return CURLE_FTP_QUOTE_ERROR;
} }
} }
qitem = qitem->next; qitem = qitem->next;
@@ -402,18 +507,18 @@ UrgError _ftp(struct UrlData *data,
/* If we have selected NOBODY, it means that we only want file information. /* If we have selected NOBODY, it means that we only want file information.
Which in FTP can't be much more than the file size! */ Which in FTP can't be much more than the file size! */
if(data->conf & CONF_NOBODY) { if(data->bits.no_body) {
/* The SIZE command is _not_ RFC 959 specified, and therefor many servers /* The SIZE command is _not_ RFC 959 specified, and therefor many servers
may not support it! It is however the only way we have to get a file's may not support it! It is however the only way we have to get a file's
size! */ size! */
int filesize; int filesize;
sendf(data->firstsocket, data, "SIZE %s\r\n", ppath); sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "213", 3)) { if(strncmp(buf, "213", 3)) {
failf(data, "Couldn't get file size: %s", buf+4); failf(data, "Couldn't get file size: %s", buf+4);
return URG_FTP_COULDNT_GET_SIZE; return CURLE_FTP_COULDNT_GET_SIZE;
} }
/* get the size from the ascii string: */ /* get the size from the ascii string: */
filesize = atoi(buf+4); filesize = atoi(buf+4);
@@ -422,43 +527,40 @@ UrgError _ftp(struct UrlData *data,
if(strlen(buf) != data->fwrite(buf, 1, strlen(buf), data->out)) { if(strlen(buf) != data->fwrite(buf, 1, strlen(buf), data->out)) {
failf (data, "Failed writing output"); failf (data, "Failed writing output");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
if(data->writeheader) { if(data->writeheader) {
/* the header is requested to be written to this file */ /* the header is requested to be written to this file */
if(strlen(buf) != data->fwrite (buf, 1, strlen(buf), if(strlen(buf) != data->fwrite (buf, 1, strlen(buf),
data->writeheader)) { data->writeheader)) {
failf (data, "Failed writing output"); failf (data, "Failed writing output");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
return URG_OK; return CURLE_OK;
} }
/* We have chosen to use the PORT command */ /* We have chosen to use the PORT command */
if(data->conf & CONF_FTPPORT) { if(data->bits.ftp_use_port) {
struct sockaddr_in sa; struct sockaddr_in sa;
struct hostent *h=NULL; struct hostent *h=NULL;
size_t size; size_t size;
unsigned short porttouse; unsigned short porttouse;
char myhost[256] = "";
char *myhost=NULL;
if(data->ftpport) { if(data->ftpport) {
myhost = if2ip(data->ftpport); if(if2ip(data->ftpport, myhost, sizeof(myhost))) {
if(myhost) { h = GetHost(data, myhost, hostent_buf, sizeof(hostent_buf));
h = GetHost(data, myhost);
} }
else { else {
if(strlen(data->ftpport)>1) if(strlen(data->ftpport)>1)
h = GetHost(data, data->ftpport); h = GetHost(data, data->ftpport, hostent_buf, sizeof(hostent_buf));
if(h) if(h)
myhost=data->ftpport; strcpy(myhost,data->ftpport);
} }
} }
if(!myhost) { if(! *myhost) {
myhost = getmyhost(); h=GetHost(data, getmyhost(myhost,sizeof(myhost)), hostent_buf, sizeof(hostent_buf));
h=GetHost(data, myhost);
} }
infof(data, "We connect from %s\n", myhost); infof(data, "We connect from %s\n", myhost);
@@ -481,35 +583,40 @@ UrgError _ftp(struct UrlData *data,
if(getsockname(portsock, (struct sockaddr *) &add, if(getsockname(portsock, (struct sockaddr *) &add,
(int *)&size)<0) { (int *)&size)<0) {
failf(data, "getsockname() failed"); failf(data, "getsockname() failed");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
porttouse = ntohs(add.sin_port); porttouse = ntohs(add.sin_port);
if ( listen(portsock, 1) < 0 ) { if ( listen(portsock, 1) < 0 ) {
failf(data, "listen(2) failed on socket"); failf(data, "listen(2) failed on socket");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { else {
failf(data, "bind(2) failed on socket"); failf(data, "bind(2) failed on socket");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { else {
failf(data, "socket(2) failed (%s)"); failf(data, "socket(2) failed (%s)");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { else {
failf(data, "could't find my own IP address (%s)", myhost); failf(data, "could't find my own IP address (%s)", myhost);
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
{ {
struct in_addr in; struct in_addr in;
unsigned short ip[5]; unsigned short ip[5];
(void) memcpy(&in.s_addr, *h->h_addr_list, sizeof (in.s_addr)); (void) memcpy(&in.s_addr, *h->h_addr_list, sizeof (in.s_addr));
#if defined (HAVE_INET_NTOA_R)
sscanf( inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]);
#else
sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu", sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]); &ip[0], &ip[1], &ip[2], &ip[3]);
#endif
sendf(data->firstsocket, data, "PORT %d,%d,%d,%d,%d,%d\n", sendf(data->firstsocket, data, "PORT %d,%d,%d,%d,%d,%d\n",
ip[0], ip[1], ip[2], ip[3], ip[0], ip[1], ip[2], ip[3],
porttouse >> 8, porttouse >> 8,
@@ -520,7 +627,7 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Server does not grok PORT, try without it!"); failf(data, "Server does not grok PORT, try without it!");
return URG_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
} }
else { /* we use the PASV command */ else { /* we use the PASV command */
@@ -531,7 +638,7 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "227", 3)) { if(strncmp(buf, "227", 3)) {
failf(data, "Odd return code after PASV"); failf(data, "Odd return code after PASV");
return URG_FTP_WEIRD_PASV_REPLY; return CURLE_FTP_WEIRD_PASV_REPLY;
} }
else { else {
int ip[4]; int ip[4];
@@ -539,7 +646,7 @@ UrgError _ftp(struct UrlData *data,
unsigned short newport; unsigned short newport;
char newhost[32]; char newhost[32];
struct hostent *he; struct hostent *he;
char *str=buf; char *str=buf,*ip_addr;
/* /*
* New 227-parser June 3rd 1999. * New 227-parser June 3rd 1999.
@@ -561,13 +668,13 @@ UrgError _ftp(struct UrlData *data,
} }
if(!*str) { if(!*str) {
failf(data, "Couldn't interpret this 227-reply: %s", buf); failf(data, "Couldn't interpret this 227-reply: %s", buf);
return URG_FTP_WEIRD_227_FORMAT; return CURLE_FTP_WEIRD_227_FORMAT;
} }
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
he = GetHost(data, newhost); he = GetHost(data, newhost, hostent_buf, sizeof(hostent_buf));
if(!he) { if(!he) {
failf(data, "Can't resolve new host %s", newhost); failf(data, "Can't resolve new host %s", newhost);
return URG_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST;
} }
@@ -579,27 +686,38 @@ UrgError _ftp(struct UrlData *data,
serv_addr.sin_family = he->h_addrtype; serv_addr.sin_family = he->h_addrtype;
serv_addr.sin_port = htons(newport); serv_addr.sin_port = htons(newport);
if(data->conf & CONF_VERBOSE) { if(data->bits.verbose) {
struct in_addr in; struct in_addr in;
#if 1
struct hostent * answer; struct hostent * answer;
unsigned long address;
#if defined(HAVE_INET_ADDR) #if defined(HAVE_INET_ADDR)
unsigned long address;
#if defined(HAVE_GETHOSTBYADDR_R)
int h_errnop;
#endif
address = inet_addr(newhost); address = inet_addr(newhost);
answer = gethostbyaddr((char *) &address, sizeof(address), #if defined(HAVE_GETHOSTBYADDR_R)
AF_INET); answer = gethostbyaddr_r((char *) &address, sizeof(address), AF_INET,
(struct hostent *)hostent_buf,
hostent_buf + sizeof(*answer),
sizeof(hostent_buf) - sizeof(*answer),
&h_errnop);
#else
answer = gethostbyaddr((char *) &address, sizeof(address), AF_INET);
#endif
#else #else
answer = NULL; answer = NULL;
#endif #endif
(void) memcpy(&in.s_addr, *he->h_addr_list, sizeof (in.s_addr)); (void) memcpy(&in.s_addr, *he->h_addr_list, sizeof (in.s_addr));
infof(data, "Connecting to %s (%s) port %u\n", infof(data, "Connecting to %s (%s) port %u\n",
answer?answer->h_name:newhost, inet_ntoa(in), newport); answer?answer->h_name:newhost,
#if defined(HAVE_INET_NTOA_R)
ip_addr = inet_ntoa_r(in, ntoa_buf, sizeof(ntoa_buf)),
#else #else
(void) memcpy(&in.s_addr, *he->h_addr_list, sizeof (in.s_addr)); ip_addr = inet_ntoa(in),
infof(data, "Connecting to %s (%s) port %u\n",
he->h_name, inet_ntoa(in), newport);
#endif #endif
newport);
} }
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr, if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr,
@@ -620,26 +738,39 @@ UrgError _ftp(struct UrlData *data,
failf(data, "Can't connect to ftp server"); failf(data, "Can't connect to ftp server");
break; break;
} }
return URG_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT;
} }
} }
} }
/* we have the (new) data connection ready */ /* we have the (new) data connection ready */
infof(data, "Connected!\n");
if(data->conf & CONF_UPLOAD) { /* change directory first */
if(ftp->dir && ftp->dir[0]) {
sendf(data->firstsocket, data, "CWD %s\r\n", ftp->dir);
nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "250", 3)) {
failf(data, "Couldn't change to directory %s", ftp->dir);
return CURLE_FTP_ACCESS_DENIED;
}
}
if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n", sendf(data->firstsocket, data, "TYPE %s\r\n",
(data->conf&CONF_FTPASCII)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set %s mode", failf(data, "Couldn't set %s mode",
(data->conf&CONF_FTPASCII)?"ASCII":"binary"); (data->bits.ftp_ascii)?"ASCII":"binary");
return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII: return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
URG_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
if(data->resume_from) { if(data->resume_from) {
@@ -660,13 +791,13 @@ UrgError _ftp(struct UrlData *data,
/* 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 */
sendf(data->firstsocket, data, "SIZE %s\r\n", ppath); sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "213", 3)) { if(strncmp(buf, "213", 3)) {
failf(data, "Couldn't get file size: %s", buf+4); failf(data, "Couldn't get file size: %s", buf+4);
return URG_FTP_COULDNT_GET_SIZE; return CURLE_FTP_COULDNT_GET_SIZE;
} }
/* get the size from the ascii string: */ /* get the size from the ascii string: */
@@ -687,11 +818,11 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "350", 3)) { if(strncmp(buf, "350", 3)) {
failf(data, "Couldn't use REST: %s", buf+4); failf(data, "Couldn't use REST: %s", buf+4);
return URG_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
#else #else
/* enable append instead */ /* enable append instead */
data->conf |= CONF_FTPAPPEND; data->bits.ftp_append = 1;
#endif #endif
/* Now, let's read off the proper amount of bytes from the /* Now, let's read off the proper amount of bytes from the
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
@@ -710,7 +841,7 @@ UrgError _ftp(struct UrlData *data,
if(actuallyread != readthisamountnow) { if(actuallyread != readthisamountnow) {
failf(data, "Could only read %d bytes from the input\n", failf(data, "Could only read %d bytes from the input\n",
passed); passed);
return URG_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
} }
while(passed != data->resume_from); while(passed != data->resume_from);
@@ -721,7 +852,7 @@ UrgError _ftp(struct UrlData *data,
if(data->infilesize <= 0) { if(data->infilesize <= 0) {
infof(data, "File already completely uploaded\n"); infof(data, "File already completely uploaded\n");
return URG_OK; return CURLE_OK;
} }
} }
/* we've passed, proceed as normal */ /* we've passed, proceed as normal */
@@ -729,21 +860,21 @@ UrgError _ftp(struct UrlData *data,
} }
/* Send everything on data->in to the socket */ /* Send everything on data->in to the socket */
if(data->conf & CONF_FTPAPPEND) if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */ /* we append onto the file instead of rewriting it */
sendf(data->firstsocket, data, "APPE %s\r\n", ppath); sendf(data->firstsocket, data, "APPE %s\r\n", ftp->file);
else else
sendf(data->firstsocket, data, "STOR %s\r\n", ppath); sendf(data->firstsocket, data, "STOR %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(atoi(buf)>=400) { if(atoi(buf)>=400) {
failf(data, "Failed FTP upload:%s", buf+3); failf(data, "Failed FTP upload:%s", buf+3);
/* oops, we never close the sockets! */ /* oops, we never close the sockets! */
return URG_FTP_COULDNT_STOR_FILE; return CURLE_FTP_COULDNT_STOR_FILE;
} }
if(data->conf & CONF_FTPPORT) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, portsock);
if( result ) if( result )
return result; return result;
@@ -758,24 +889,19 @@ UrgError _ftp(struct UrlData *data,
#if 0 #if 0
ProgressInit(data, data->infilesize); ProgressInit(data, data->infilesize);
#endif #endif
result = Transfer(data, -1, -1, FALSE, NULL, /* no download */ result = Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp); data->secondarysocket, bytecountp);
if(result) if(result)
return result; return result;
if((-1 != data->infilesize) && (data->infilesize != *bytecountp)) {
failf(data, "Wrote only partial file (%d out of %d bytes)",
*bytecountp, data->infilesize);
return URG_PARTIAL_FILE;
}
} }
else { else {
/* Retrieve file or directory */ /* Retrieve file or directory */
bool dirlist=FALSE; bool dirlist=FALSE;
long downloadsize=-1; long downloadsize=-1;
if(data->conf&CONF_RANGE && data->range) { if(data->bits.set_range && data->range) {
int from, to; long from, to;
int totalsize=-1; int totalsize=-1;
char *ptr; char *ptr;
char *ptr2; char *ptr2;
@@ -788,32 +914,34 @@ UrgError _ftp(struct UrlData *data,
/* we didn't get any digit */ /* we didn't get any digit */
to=-1; to=-1;
} }
if(-1 == to) { if((-1 == to) && (from>=0)) {
/* X - */ /* X - */
data->resume_from = from; data->resume_from = from;
infof(data, "FTP RANGE %d to end of file\n", from);
} }
else if(from < 0) { else if(from < 0) {
/* -Y */ /* -Y */
from = 0; totalsize = -from;
to = -from; data->maxdownload = -from;
totalsize = to-from; data->resume_from = from;
data->maxdownload = totalsize; infof(data, "FTP RANGE the last %d bytes\n", totalsize);
} }
else { else {
/* X- */ /* X-Y */
totalsize = to-from; totalsize = to-from;
data->maxdownload = totalsize; data->maxdownload = totalsize+1; /* include the last mentioned byte */
data->resume_from = from;
infof(data, "FTP RANGE from %d getting %d bytes\n", from, data->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);
} }
#if 0
if(!ppath[0]) if(!ppath[0])
/* make sure this becomes a valid name */ /* make sure this becomes a valid name */
ppath="./"; ppath="./";
#endif
if((data->conf & CONF_FTPLISTONLY) || if((data->bits.ftp_list_only) || !ftp->file) {
('/' == ppath[strlen(ppath)-1] )) {
/* The specified path ends with a slash, and therefore we think this /* The specified path ends with a slash, and therefore we think this
is a directory that is requested, use LIST. But before that we is a directory that is requested, use LIST. But before that we
need to set ASCII transfer mode. */ need to set ASCII transfer mode. */
@@ -826,30 +954,29 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set ascii mode"); failf(data, "Couldn't set ascii mode");
return URG_FTP_COULDNT_SET_ASCII; return CURLE_FTP_COULDNT_SET_ASCII;
} }
/* if this output is to be machine-parsed, the NLST command will be /* if this output is to be machine-parsed, the NLST command will be
better used since the LIST command output is not specified or better used since the LIST command output is not specified or
standard in any way */ standard in any way */
sendf(data->firstsocket, data, "%s %s\r\n", sendf(data->firstsocket, data, "%s\r\n",
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->conf&CONF_FTPLISTONLY?"NLST":"LIST"), (data->bits.ftp_list_only?"NLST":"LIST"));
ppath);
} }
else { else {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n", sendf(data->firstsocket, data, "TYPE %s\r\n",
(data->conf&CONF_FTPASCII)?"A":"I"); (data->bits.ftp_list_only)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
if(strncmp(buf, "200", 3)) { if(strncmp(buf, "200", 3)) {
failf(data, "Couldn't set %s mode", failf(data, "Couldn't set %s mode",
(data->conf&CONF_FTPASCII)?"ASCII":"binary"); (data->bits.ftp_ascii)?"ASCII":"binary");
return (data->conf&CONF_FTPASCII)? URG_FTP_COULDNT_SET_ASCII: return (data->bits.ftp_ascii)? CURLE_FTP_COULDNT_SET_ASCII:
URG_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
if(data->resume_from) { if(data->resume_from) {
@@ -860,7 +987,7 @@ UrgError _ftp(struct UrlData *data,
* of the file we're gonna get. If we can get the size, this is by far * of the file we're gonna get. If we can get the size, this is by far
* the best way to know if we're trying to resume beyond the EOF. */ * the best way to know if we're trying to resume beyond the EOF. */
sendf(data->firstsocket, data, "SIZE %s\r\n", ppath); sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
@@ -875,14 +1002,28 @@ UrgError _ftp(struct UrlData *data,
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) {
/* We're supposed to download the last abs(from) bytes */
if(foundsize < -data->resume_from) {
failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, foundsize);
return CURLE_FTP_BAD_DOWNLOAD_RESUME;
}
/* convert to size to download */
downloadsize = -data->resume_from;
/* download from where? */
data->resume_from = foundsize - downloadsize;
}
else {
if(foundsize <= data->resume_from) { if(foundsize <= data->resume_from) {
failf(data, "Offset (%d) was beyond file size (%d)", failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, foundsize); data->resume_from, foundsize);
return URG_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-data->resume_from;
} }
}
/* 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",
@@ -894,11 +1035,11 @@ UrgError _ftp(struct UrlData *data,
if(strncmp(buf, "350", 3)) { if(strncmp(buf, "350", 3)) {
failf(data, "Couldn't use REST: %s", buf+4); failf(data, "Couldn't use REST: %s", buf+4);
return URG_FTP_COULDNT_USE_REST; return CURLE_FTP_COULDNT_USE_REST;
} }
} }
sendf(data->firstsocket, data, "RETR %s\r\n", ppath); sendf(data->firstsocket, data, "RETR %s\r\n", ftp->file);
} }
nread = GetLastResponse(data->firstsocket, buf, data); nread = GetLastResponse(data->firstsocket, buf, data);
@@ -968,12 +1109,12 @@ UrgError _ftp(struct UrlData *data,
if(size <= 0) { if(size <= 0) {
failf(data, "Offset (%d) was beyond file size (%d)", failf(data, "Offset (%d) was beyond file size (%d)",
data->resume_from, data->resume_from+size); data->resume_from, data->resume_from+size);
return URG_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
} }
#endif #endif
if(data->conf & CONF_FTPPORT) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, portsock);
if( result ) if( result )
return result; return result;
@@ -982,95 +1123,74 @@ UrgError _ftp(struct UrlData *data,
infof(data, "Getting file with size: %d\n", size); infof(data, "Getting file with size: %d\n", size);
/* FTP download: */ /* FTP download: */
result=Transfer(data, data->secondarysocket, size, FALSE, result=Transfer(conn, data->secondarysocket, size, FALSE,
bytecountp, bytecountp,
-1, NULL); /* no upload here */ -1, NULL); /* no upload here */
if(result) if(result)
return result; return result;
if((-1 != size) && (size != *bytecountp)) {
failf(data, "Received only partial file");
return URG_PARTIAL_FILE;
}
else if(0 == *bytecountp) {
failf(data, "No data was received!");
return URG_FTP_COULDNT_RETR_FILE;
}
} }
else { else {
failf(data, "%s", buf+4); failf(data, "%s", buf+4);
return URG_FTP_COULDNT_RETR_FILE; return CURLE_FTP_COULDNT_RETR_FILE;
} }
} }
/* end of transfer */ /* end of transfer */
#if 0
ProgressEnd(data);
#endif
pgrsDone(data);
/* shut down the socket to inform the server we're done */ return CURLE_OK;
sclose(data->secondarysocket);
data->secondarysocket = -1;
/* now let's see what the server says about the transfer we
just performed: */
nread = GetLastResponse(data->firstsocket, buf, data);
/* 226 Transfer complete */
if(strncmp(buf, "226", 3)) {
failf(data, "%s", buf+4);
return URG_FTP_WRITE_ERROR;
}
/* Send any post-transfer QUOTE strings? */
if(data->postquote) {
qitem = data->postquote;
/* Send all QUOTE strings in same order as on command-line */
while (qitem) {
/* Send string */
if (qitem->data) {
sendf(data->firstsocket, data, "%s\r\n", qitem->data);
nread = GetLastResponse(data->firstsocket, buf, data);
if (buf[0] != '2') {
failf(data, "QUOT string not accepted: %s",
qitem->data);
return URG_FTP_QUOTE_ERROR;
}
}
qitem = qitem->next;
}
}
return URG_OK;
} }
/* -- deal with the ftp server! -- */ /* -- deal with the ftp server! -- */
UrgError ftp(struct UrlData *data, /* argument is already checked for validity */
long *bytecountp, CURLcode ftp(struct connectdata *conn)
char *ftpuser,
char *ftppasswd,
char *urlpath)
{ {
char *realpath; CURLcode retcode;
UrgError retcode;
#if 0 struct UrlData *data = conn->data;
realpath = URLfix(urlpath); struct FTP *ftp;
#else int dirlength=0; /* 0 forces strlen() */
realpath = curl_unescape(urlpath);
#endif /* the ftp struct is already inited in ftp_connect() */
if(realpath) { ftp = data->proto.ftp;
retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, realpath);
free(realpath); /* We split the path into dir and file parts *before* we URLdecode
it */
ftp->file = strrchr(conn->ppath, '/');
if(ftp->file) {
ftp->file++; /* point to the first letter in the file name part or
remain NULL */
}
else {
ftp->file = conn->ppath; /* there's only a file part */
}
dirlength=ftp->file-conn->ppath;
if(*ftp->file) {
ftp->file = curl_unescape(ftp->file, 0);
if(NULL == ftp->file) {
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY;
}
} }
else else
/* then we try the original path */ ftp->file=NULL; /* instead of point to a zero byte, we make it a NULL
retcode = _ftp(data, bytecountp, ftpuser, ftppasswd, urlpath); pointer */
ftp->urlpath = conn->ppath;
if(dirlength) {
ftp->dir = curl_unescape(ftp->urlpath, dirlength);
if(NULL == ftp->dir) {
if(ftp->file)
free(ftp->file);
failf(data, "no memory");
return CURLE_OUT_OF_MEMORY; /* failure */
}
}
else
ftp->dir = NULL;
retcode = _ftp(conn);
return retcode; return retcode;
} }

View File

@@ -40,11 +40,9 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError ftp(struct UrlData *data, CURLcode ftp(struct connectdata *conn);
long *bytecountp, CURLcode ftp_done(struct connectdata *conn);
char *ftpuser, CURLcode ftp_connect(struct connectdata *conn);
char *ftppasswd,
char *ppath);
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data); struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list); void curl_slist_free_all(struct curl_slist *list);

View File

@@ -1,25 +1,25 @@
/* A Bison parser, made from getdate.y with Bison version GNU Bison version 1.21 /* A Bison parser, made from getdate.y
*/ by GNU Bison version 1.28 */
#define YYBISON 1 /* Identify Bison output. */ #define YYBISON 1 /* Identify Bison output. */
#define tAGO 258 #define tAGO 257
#define tDAY 259 #define tDAY 258
#define tDAY_UNIT 260 #define tDAY_UNIT 259
#define tDAYZONE 261 #define tDAYZONE 260
#define tDST 262 #define tDST 261
#define tHOUR_UNIT 263 #define tHOUR_UNIT 262
#define tID 264 #define tID 263
#define tMERIDIAN 265 #define tMERIDIAN 264
#define tMINUTE_UNIT 266 #define tMINUTE_UNIT 265
#define tMONTH 267 #define tMONTH 266
#define tMONTH_UNIT 268 #define tMONTH_UNIT 267
#define tSEC_UNIT 269 #define tSEC_UNIT 268
#define tSNUMBER 270 #define tSNUMBER 269
#define tUNUMBER 271 #define tUNUMBER 270
#define tYEAR_UNIT 272 #define tYEAR_UNIT 271
#define tZONE 273 #define tZONE 272
#line 1 "getdate.y" #line 1 "getdate.y"
@@ -217,23 +217,6 @@ typedef union {
int Number; int Number;
enum _MERIDIAN Meridian; enum _MERIDIAN Meridian;
} YYSTYPE; } YYSTYPE;
#ifndef YYLTYPE
typedef
struct yyltype
{
int timestamp;
int first_line;
int first_column;
int last_line;
int last_column;
char *text;
}
yyltype;
#define YYLTYPE yyltype
#endif
#include <stdio.h> #include <stdio.h>
#ifndef __cplusplus #ifndef __cplusplus
@@ -248,7 +231,7 @@ typedef
#define YYFLAG -32768 #define YYFLAG -32768
#define YYNTBASE 22 #define YYNTBASE 22
#define YYTRANSLATE(x) ((unsigned)(x) <= 273 ? yytranslate[x] : 32) #define YYTRANSLATE(x) ((unsigned)(x) <= 272 ? yytranslate[x] : 32)
static const char yytranslate[] = { 0, static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -276,9 +259,9 @@ static const char yytranslate[] = { 0,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
16, 17, 18 17, 18
}; };
#if YYDEBUG != 0 #if YYDEBUG != 0
@@ -318,12 +301,16 @@ static const short yyrline[] = { 0,
366, 369, 372, 375, 378, 381, 384, 387, 390, 393, 366, 369, 372, 375, 378, 381, 384, 387, 390, 393,
396, 399, 402, 405, 408, 411, 414, 419, 452, 456 396, 399, 402, 405, 408, 411, 414, 419, 452, 456
}; };
#endif
static const char * const yytname[] = { "$","error","$illegal.","tAGO","tDAY",
#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
static const char * const yytname[] = { "$","error","$undefined.","tAGO","tDAY",
"tDAY_UNIT","tDAYZONE","tDST","tHOUR_UNIT","tID","tMERIDIAN","tMINUTE_UNIT", "tDAY_UNIT","tDAYZONE","tDST","tHOUR_UNIT","tID","tMERIDIAN","tMINUTE_UNIT",
"tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tYEAR_UNIT","tZONE", "tMONTH","tMONTH_UNIT","tSEC_UNIT","tSNUMBER","tUNUMBER","tYEAR_UNIT","tZONE",
"':'","','","'/'","spec","item","time","zone","day","date","rel","relunit","number", "':'","','","'/'","spec","item","time","zone","day","date","rel","relunit","number",
"o_merid","" "o_merid", NULL
}; };
#endif #endif
@@ -393,14 +380,15 @@ static const short yycheck[] = { 0,
56 56
}; };
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ /* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "/usr/gnu/lib/bison.simple" #line 3 "/usr/local/share/bison.simple"
/* This file comes from bison-1.28. */
/* Skeleton output parser for bison, /* Skeleton output parser for bison,
Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option) the Free Software Foundation; either version 2, or (at your option)
any later version. any later version.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
@@ -410,43 +398,67 @@ static const short yycheck[] = { 0,
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* As a special exception, when this file is copied by Bison into a
#ifndef alloca Bison output file, you may use that output file without restriction.
#ifdef __GNUC__ This special exception was added by the Free Software Foundation
#define alloca __builtin_alloca in version 1.24 of Bison. */
#else /* not GNU C. */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi)
#include <alloca.h>
#else /* not sparc */
#if defined (MSDOS) && !defined (__TURBOC__)
#include <malloc.h>
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
#include <malloc.h>
#pragma alloca
#else /* not MSDOS, __TURBOC__, or _AIX */
#ifdef __hpux
#ifdef __cplusplus
extern "C" {
void *alloca (unsigned int);
};
#else /* not __cplusplus */
void *alloca (unsigned int);
#endif /* not __cplusplus */
#endif /* __hpux */
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc. */
#endif /* not GNU C. */
#endif /* alloca not defined. */
/* This is the parser code that is written into each bison parser /* This is the parser code that is written into each bison parser
when the %semantic_parser declaration is not specified in the grammar. when the %semantic_parser declaration is not specified in the grammar.
It was written by Richard Stallman by simplifying the hairy parser It was written by Richard Stallman by simplifying the hairy parser
used when %semantic_parser is specified. */ used when %semantic_parser is specified. */
#ifndef YYSTACK_USE_ALLOCA
#ifdef alloca
#define YYSTACK_USE_ALLOCA
#else /* alloca not defined */
#ifdef __GNUC__
#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#else /* not GNU C. */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
#define YYSTACK_USE_ALLOCA
#include <alloca.h>
#else /* not sparc */
/* We think this test detects Watcom and Microsoft C. */
/* This used to test MSDOS, but that is a bad idea
since that symbol is in the user namespace. */
#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
#if 0 /* No need for malloc.h, which pollutes the namespace;
instead, just don't use alloca. */
#include <malloc.h>
#endif
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
/* I don't know what this was needed for, but it pollutes the namespace.
So I turned it off. rms, 2 May 1997. */
/* #include <malloc.h> */
#pragma alloca
#define YYSTACK_USE_ALLOCA
#else /* not MSDOS, or __TURBOC__, or _AIX */
#if 0
#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
and on HPUX 10. Eventually we can turn this on. */
#define YYSTACK_USE_ALLOCA
#define alloca __builtin_alloca
#endif /* __hpux */
#endif
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc */
#endif /* not GNU C */
#endif /* alloca not defined */
#endif /* YYSTACK_USE_ALLOCA not defined */
#ifdef YYSTACK_USE_ALLOCA
#define YYSTACK_ALLOC alloca
#else
#define YYSTACK_ALLOC malloc
#endif
/* Note: there must be only one dollar sign in this file. /* Note: there must be only one dollar sign in this file.
It is replaced by the list of actions, each action It is replaced by the list of actions, each action
as one case of the switch. */ as one case of the switch. */
@@ -455,8 +467,8 @@ void *alloca (unsigned int);
#define yyclearin (yychar = YYEMPTY) #define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2 #define YYEMPTY -2
#define YYEOF 0 #define YYEOF 0
#define YYACCEPT return(0) #define YYACCEPT goto yyacceptlab
#define YYABORT return(1) #define YYABORT goto yyabortlab
#define YYERROR goto yyerrlab1 #define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror. /* Like YYERROR except do call yyerror.
This remains here temporarily to ease the This remains here temporarily to ease the
@@ -485,10 +497,18 @@ while (0)
#ifdef YYPURE #ifdef YYPURE
#ifdef YYLSP_NEEDED #ifdef YYLSP_NEEDED
#ifdef YYLEX_PARAM
#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
#else
#define YYLEX yylex(&yylval, &yylloc) #define YYLEX yylex(&yylval, &yylloc)
#endif
#else /* not YYLSP_NEEDED */
#ifdef YYLEX_PARAM
#define YYLEX yylex(&yylval, YYLEX_PARAM)
#else #else
#define YYLEX yylex(&yylval) #define YYLEX yylex(&yylval)
#endif #endif
#endif /* not YYLSP_NEEDED */
#endif #endif
/* If nonreentrant, generate the variables here */ /* If nonreentrant, generate the variables here */
@@ -529,24 +549,24 @@ int yydebug; /* nonzero means print parse trace */
#ifndef YYMAXDEPTH #ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000 #define YYMAXDEPTH 10000
#endif #endif
/* Prevent warning if -Wstrict-prototypes. */
#ifdef __GNUC__
int yyparse (void);
#endif
/* Define __yy_memcpy. Note that the size argument
should be passed with type unsigned int, because that is what the non-GCC
definitions require. With GCC, __builtin_memcpy takes an arg
of type size_t, but it can handle unsigned int. */
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ #if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT) #define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */ #else /* not GNU C or C++ */
#ifndef __cplusplus #ifndef __cplusplus
/* This is the most reliable way to avoid incompatibilities /* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */ in available built-in functions on various systems. */
static void static void
__yy_bcopy (from, to, count) __yy_memcpy (to, from, count)
char *from;
char *to; char *to;
int count; char *from;
unsigned int count;
{ {
register char *f = from; register char *f = from;
register char *t = to; register char *t = to;
@@ -561,10 +581,10 @@ __yy_bcopy (from, to, count)
/* This is the most reliable way to avoid incompatibilities /* This is the most reliable way to avoid incompatibilities
in available built-in functions on various systems. */ in available built-in functions on various systems. */
static void static void
__yy_bcopy (char *from, char *to, int count) __yy_memcpy (char *to, char *from, unsigned int count)
{ {
register char *f = from;
register char *t = to; register char *t = to;
register char *f = from;
register int i = count; register int i = count;
while (i-- > 0) while (i-- > 0)
@@ -574,16 +594,46 @@ __yy_bcopy (char *from, char *to, int count)
#endif #endif
#endif #endif
#line 184 "/usr/gnu/lib/bison.simple" #line 217 "/usr/local/share/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *.
It should actually point to an object.
Grammar actions can access the variable by casting it
to the proper pointer type. */
#ifdef YYPARSE_PARAM
#ifdef __cplusplus
#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
#define YYPARSE_PARAM_DECL
#else /* not __cplusplus */
#define YYPARSE_PARAM_ARG YYPARSE_PARAM
#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
#endif /* not __cplusplus */
#else /* not YYPARSE_PARAM */
#define YYPARSE_PARAM_ARG
#define YYPARSE_PARAM_DECL
#endif /* not YYPARSE_PARAM */
/* Prevent warning if -Wstrict-prototypes. */
#ifdef __GNUC__
#ifdef YYPARSE_PARAM
int yyparse (void *);
#else
int yyparse (void);
#endif
#endif
int int
yyparse() yyparse(YYPARSE_PARAM_ARG)
YYPARSE_PARAM_DECL
{ {
register int yystate; register int yystate;
register int yyn; register int yyn;
register short *yyssp; register short *yyssp;
register YYSTYPE *yyvsp; register YYSTYPE *yyvsp;
int yyerrstatus; /* number of tokens to shift before error messages enabled */ int yyerrstatus; /* number of tokens to shift before error messages enabled */
int yychar1; /* lookahead token as an internal (translated) token number */ int yychar1 = 0; /* lookahead token as an internal (translated) token number */
short yyssa[YYINITDEPTH]; /* the state stack */ short yyssa[YYINITDEPTH]; /* the state stack */
YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
@@ -602,6 +652,7 @@ yyparse()
#endif #endif
int yystacksize = YYINITDEPTH; int yystacksize = YYINITDEPTH;
int yyfree_stacks = 0;
#ifdef YYPURE #ifdef YYPURE
int yychar; int yychar;
@@ -662,13 +713,20 @@ yynewstate:
#ifdef yyoverflow #ifdef yyoverflow
/* Each stack pointer address is followed by the size of /* Each stack pointer address is followed by the size of
the data in use in that stack, in bytes. */ the data in use in that stack, in bytes. */
#ifdef YYLSP_NEEDED
/* This used to be a conditional around just the two extra args,
but that might be undefined if yyoverflow is a macro. */
yyoverflow("parser stack overflow", yyoverflow("parser stack overflow",
&yyss1, size * sizeof (*yyssp), &yyss1, size * sizeof (*yyssp),
&yyvs1, size * sizeof (*yyvsp), &yyvs1, size * sizeof (*yyvsp),
#ifdef YYLSP_NEEDED
&yyls1, size * sizeof (*yylsp), &yyls1, size * sizeof (*yylsp),
#endif
&yystacksize); &yystacksize);
#else
yyoverflow("parser stack overflow",
&yyss1, size * sizeof (*yyssp),
&yyvs1, size * sizeof (*yyvsp),
&yystacksize);
#endif
yyss = yyss1; yyvs = yyvs1; yyss = yyss1; yyvs = yyvs1;
#ifdef YYLSP_NEEDED #ifdef YYLSP_NEEDED
@@ -679,18 +737,32 @@ yynewstate:
if (yystacksize >= YYMAXDEPTH) if (yystacksize >= YYMAXDEPTH)
{ {
yyerror("parser stack overflow"); yyerror("parser stack overflow");
if (yyfree_stacks)
{
free (yyss);
free (yyvs);
#ifdef YYLSP_NEEDED
free (yyls);
#endif
}
return 2; return 2;
} }
yystacksize *= 2; yystacksize *= 2;
if (yystacksize > YYMAXDEPTH) if (yystacksize > YYMAXDEPTH)
yystacksize = YYMAXDEPTH; yystacksize = YYMAXDEPTH;
yyss = (short *) alloca (yystacksize * sizeof (*yyssp)); #ifndef YYSTACK_USE_ALLOCA
__yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp)); yyfree_stacks = 1;
yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp)); #endif
__yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp)); yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
__yy_memcpy ((char *)yyss, (char *)yyss1,
size * (unsigned int) sizeof (*yyssp));
yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
__yy_memcpy ((char *)yyvs, (char *)yyvs1,
size * (unsigned int) sizeof (*yyvsp));
#ifdef YYLSP_NEEDED #ifdef YYLSP_NEEDED
yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp)); yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
__yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp)); __yy_memcpy ((char *)yyls, (char *)yyls1,
size * (unsigned int) sizeof (*yylsp));
#endif #endif
#endif /* no yyoverflow */ #endif /* no yyoverflow */
@@ -829,6 +901,7 @@ yydefault:
/* Do a reduction. yyn is the number of a rule to reduce with. */ /* Do a reduction. yyn is the number of a rule to reduce with. */
yyreduce: yyreduce:
yylen = yyr2[yyn]; yylen = yyr2[yyn];
if (yylen > 0)
yyval = yyvsp[1-yylen]; /* implement default value of the action */ yyval = yyvsp[1-yylen]; /* implement default value of the action */
#if YYDEBUG != 0 #if YYDEBUG != 0
@@ -1212,7 +1285,7 @@ case 50:
break;} break;}
} }
/* the action file gets copied in in place of this dollarsign */ /* the action file gets copied in in place of this dollarsign */
#line 457 "/usr/gnu/lib/bison.simple" #line 543 "/usr/local/share/bison.simple"
yyvsp -= yylen; yyvsp -= yylen;
yyssp -= yylen; yyssp -= yylen;
@@ -1407,6 +1480,30 @@ yyerrhandle:
yystate = yyn; yystate = yyn;
goto yynewstate; goto yynewstate;
yyacceptlab:
/* YYACCEPT comes here. */
if (yyfree_stacks)
{
free (yyss);
free (yyvs);
#ifdef YYLSP_NEEDED
free (yyls);
#endif
}
return 0;
yyabortlab:
/* YYABORT comes here. */
if (yyfree_stacks)
{
free (yyss);
free (yyvs);
#ifdef YYLSP_NEEDED
free (yyls);
#endif
}
return 1;
} }
#line 462 "getdate.y" #line 462 "getdate.y"
@@ -1864,7 +1961,7 @@ difftm (struct tm *a, struct tm *b)
} }
time_t time_t
get_date (const char *p, const time_t *now) curl_getdate (const char *p, const time_t *now)
{ {
struct tm tm, tm0, *tmp; struct tm tm, tm0, *tmp;
time_t Start; time_t Start;
@@ -1998,7 +2095,7 @@ main (ac, av)
buff[MAX_BUFF_LEN] = 0; buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{ {
d = get_date (buff, (time_t *) NULL); d = curl_getdate (buff, (time_t *) NULL);
if (d == -1) if (d == -1)
(void) printf ("Bad format - couldn't convert.\n"); (void) printf ("Bad format - couldn't convert.\n");
else else

View File

@@ -1,18 +1,11 @@
/* Copyright (C) 1995, 1997, 1998 Free Software Foundation, Inc. /*
** Originally written by Steven M. Bellovin <smb@research.att.com> while
This program is free software; you can redistribute it and/or modify ** at the University of North Carolina at Chapel Hill. Later tweaked by
it under the terms of the GNU General Public License as published by ** a couple of people on Usenet. Completely overhauled by Rich $alz
the Free Software Foundation; either version 2, or (at your option) ** <rsalz@bbn.com> and Jim Berets <jberets@bbn.com> in August, 1990.
any later version. **
** This code is in the public domain and has no copyright.
This program is distributed in the hope that it will be useful, */
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#if HAVE_CONFIG_H #if HAVE_CONFIG_H
# include <config.h> # include <config.h>
@@ -43,4 +36,4 @@
# endif # endif
#endif /* defined (vms) */ #endif /* defined (vms) */
time_t get_date PARAMS ((const char *p, const time_t *now)); time_t curl_getdate PARAMS ((const char *p, const time_t *now));

View File

@@ -914,7 +914,7 @@ difftm (struct tm *a, struct tm *b)
} }
time_t time_t
get_date (const char *p, const time_t *now) curl_getdate (const char *p, const time_t *now)
{ {
struct tm tm, tm0, *tmp; struct tm tm, tm0, *tmp;
time_t Start; time_t Start;
@@ -1048,7 +1048,7 @@ main (ac, av)
buff[MAX_BUFF_LEN] = 0; buff[MAX_BUFF_LEN] = 0;
while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0]) while (fgets (buff, MAX_BUFF_LEN, stdin) && buff[0])
{ {
d = get_date (buff, (time_t *) NULL); d = curl_getdate (buff, (time_t *) NULL);
if (d == -1) if (d == -1)
(void) printf ("Bad format - couldn't convert.\n"); (void) printf ("Bad format - couldn't convert.\n");
else else

View File

@@ -22,18 +22,6 @@
* Portions created by the Initial Developer are Copyright (C) 1998. * Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved. * All Rights Reserved.
* *
* Contributor(s):
* Rafael Sagula <sagula@inf.ufrgs.br>
* Sampo Kellomaki <sampo@iki.fi>
* Linas Vepstas <linas@linas.org>
* Bjorn Reese <breese@imada.ou.dk>
* Johan Anderson <johan@homemail.com>
* Kjell Ericson <Kjell.Ericson@haxx.nu>
* Troy Engel <tengel@palladium.net>
* Ryan Nelson <ryan@inch.com>
* Bjorn Stenberg <Bjorn.Stenberg@haxx.nu>
* Angus Mackay <amackay@gus.ml.org>
*
* ------------------------------------------------------------ * ------------------------------------------------------------
* Main author: * Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu> * - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
@@ -47,28 +35,11 @@
* $State$ * $State$
* $Locker$ * $Locker$
* *
* ------------------------------------------------------------
* $Log$
* Revision 1.2 2000-01-10 23:36:14 bagder
* syncing with local edit
*
* Revision 1.4 1999/09/06 06:59:40 dast
* Changed email info
*
* Revision 1.3 1999/08/13 07:34:48 dast
* Changed the URL in the header
*
* Revision 1.2 1999/03/13 00:56:09 dast
* Big changes done due to url.c being split up in X smaller files and that
* the lib is now more stand-alone.
*
* Revision 1.1.1.1 1999/03/11 22:23:34 dast
* Imported sources
*
****************************************************************************/ ****************************************************************************/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
@@ -78,7 +49,7 @@ char *GetEnv(char *variable)
{ {
#ifdef WIN32 #ifdef WIN32
/* This shit requires windows.h (HUGE) to be included */ /* This shit requires windows.h (HUGE) to be included */
static char env[MAX_PATH]; /* MAX_PATH is from windef.h */ char env[MAX_PATH]; /* MAX_PATH is from windef.h */
char *temp = getenv(variable); char *temp = getenv(variable);
env[0] = '\0'; env[0] = '\0';
ExpandEnvironmentStrings(temp, env, sizeof(env)); ExpandEnvironmentStrings(temp, env, sizeof(env));
@@ -86,7 +57,7 @@ char *GetEnv(char *variable)
/* no length control */ /* no length control */
char *env = getenv(variable); char *env = getenv(variable);
#endif #endif
return env; return env?strdup(env):NULL;
} }
char *curl_GetEnv(char *v) char *curl_GetEnv(char *v)

View File

@@ -175,7 +175,9 @@ char *getpass(const char *prompt)
#endif #endif
signal(SIGINT, sigint); signal(SIGINT, sigint);
#ifndef __EMX__
signal(SIGTSTP, sigtstp); signal(SIGTSTP, sigtstp);
#endif
return(buf); return(buf);
} }

766
lib/highlevel.c Normal file
View File

@@ -0,0 +1,766 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include "setup.h"
#include "strequal.h"
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
#include <io.h>
#else
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/resource.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <netdb.h>
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#include <sys/ioctl.h>
#include <signal.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifndef HAVE_VPRINTF
#error "We can't compile without vprintf() support!"
#endif
#ifndef HAVE_SELECT
#error "We can't compile without select() support!"
#endif
#ifndef HAVE_SOCKET
#error "We can't compile without socket() support!"
#endif
#endif
#include "urldata.h"
#include <curl/curl.h>
#include <curl/types.h>
#include "netrc.h"
#include "getenv.h"
#include "hostip.h"
#include "download.h"
#include "sendf.h"
#include "speedcheck.h"
#include "getpass.h"
#include "progress.h"
#include "getdate.h"
#include "writeout.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
CURLcode
_Transfer (struct connectdata *c_conn)
{
size_t nread; /* number of bytes read */
int bytecount = 0; /* total number of bytes read */
int writebytecount = 0; /* number of bytes written */
long contentlength=0; /* size of incoming data */
struct timeval start = tvnow();
struct timeval now = start; /* current time */
bool header = TRUE; /* incoming data has HTTP header */
int headerline = 0; /* counts header lines to better track the
first one */
char *hbufp; /* points at *end* of header line */
int hbuflen = 0;
char *str; /* within buf */
char *str_start; /* within buf */
char *end_ptr; /* within buf */
char *p; /* within headerbuff */
bool content_range = FALSE; /* set TRUE if Content-Range: was found */
int offset = 0; /* possible resume offset read from the
Content-Range: header */
int code = 0; /* error code from the 'HTTP/1.? XXX' line */
/* for the low speed checks: */
CURLcode urg;
time_t timeofdoc=0;
long bodywrites=0;
char newurl[URL_MAX_LENGTH]; /* buffer for Location: URL */
/* the highest fd we use + 1 */
struct UrlData *data;
struct connectdata *conn = (struct connectdata *)c_conn;
char *buf;
int maxfd;
if(!conn || (conn->handle != STRUCT_CONNECT))
return CURLE_BAD_FUNCTION_ARGUMENT;
data = conn->data; /* there's the root struct */
buf = data->buffer;
maxfd = (conn->sockfd>conn->writesockfd?conn->sockfd:conn->writesockfd)+1;
hbufp = data->headerbuff;
myalarm (0); /* switch off the alarm-style timeout */
now = tvnow();
start = now;
#define KEEP_READ 1
#define KEEP_WRITE 2
pgrsTime(data, TIMER_PRETRANSFER);
if (!conn->getheader) {
header = FALSE;
if(conn->size > 0)
pgrsSetDownloadSize(data, conn->size);
}
{
fd_set readfd;
fd_set writefd;
fd_set rkeepfd;
fd_set wkeepfd;
struct timeval interval;
int keepon=0;
/* timeout every X second
- makes a better progressmeter (i.e even when no data is read, the
meter can be updated and reflect reality)
- allows removal of the alarm() crap
- variable timeout is easier
*/
FD_ZERO (&readfd); /* clear it */
if(conn->sockfd != -1) {
FD_SET (conn->sockfd, &readfd); /* read socket */
keepon |= KEEP_READ;
}
FD_ZERO (&writefd); /* clear it */
if(conn->writesockfd != -1) {
FD_SET (conn->writesockfd, &writefd); /* write socket */
keepon |= KEEP_WRITE;
}
/* get these in backup variables to be able to restore them on each lap in
the select() loop */
rkeepfd = readfd;
wkeepfd = writefd;
while (keepon) {
readfd = rkeepfd; /* set those every lap in the loop */
writefd = wkeepfd;
interval.tv_sec = 1;
interval.tv_usec = 0;
switch (select (maxfd, &readfd, &writefd, NULL, &interval)) {
case -1: /* select() error, stop reading */
#ifdef EINTR
/* The EINTR is not serious, and it seems you might get this more
ofen when using the lib in a multi-threaded environment! */
if(errno == EINTR)
;
else
#endif
keepon = 0; /* no more read or write */
continue;
case 0: /* timeout */
break;
default:
if((keepon & KEEP_READ) && FD_ISSET(conn->sockfd, &readfd)) {
/* read! */
urg = curl_read(conn, buf, BUFSIZE -1, &nread);
/* NULL terminate, allowing string ops to be used */
if (0 < (signed int) nread)
buf[nread] = 0;
/* if we receive 0 or less here, the server closed the connection and
we bail out from this! */
else if (0 >= (signed int) nread) {
keepon &= ~KEEP_READ;
break;
}
str = buf; /* Default buffer to use when we write the
buffer, it may be changed in the flow below
before the actual storing is done. */
/* Since this is a two-state thing, we check if we are parsing
headers at the moment or not. */
if (header) {
/* we are in parse-the-header-mode */
/* header line within buffer loop */
do {
int hbufp_index;
str_start = str; /* str_start is start of line within buf */
end_ptr = strchr (str_start, '\n');
if (!end_ptr) {
/* no more complete header lines within buffer */
/* copy what is remaining into headerbuff */
int str_length = (int)strlen(str);
if (hbuflen + (int)str_length >= data->headersize) {
char *newbuff;
long newsize=MAX((hbuflen+str_length)*3/2,
data->headersize*2);
hbufp_index = hbufp - data->headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize);
if(!newbuff) {
failf (data, "Failed to alloc memory for big header!");
return CURLE_READ_ERROR;
}
data->headersize=newsize;
data->headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index;
}
strcpy (hbufp, str);
hbufp += strlen (str);
hbuflen += strlen (str);
break; /* read more and try again */
}
str = end_ptr + 1; /* move just past new line */
if (hbuflen + (str - str_start) >= data->headersize) {
char *newbuff;
long newsize=MAX((hbuflen+(str-str_start))*3/2,
data->headersize*2);
hbufp_index = hbufp - data->headerbuff;
newbuff = (char *)realloc(data->headerbuff, newsize);
if(!newbuff) {
failf (data, "Failed to alloc memory for big header!");
return CURLE_READ_ERROR;
}
data->headersize= newsize;
data->headerbuff = newbuff;
hbufp = data->headerbuff + hbufp_index;
}
/* copy to end of line */
strncpy (hbufp, str_start, str - str_start);
hbufp += str - str_start;
hbuflen += str - str_start;
*hbufp = 0;
p = data->headerbuff;
/* we now have a full line that p points to */
if (('\n' == *p) || ('\r' == *p)) {
/* Zero-length line means end of header! */
if (-1 != conn->size) /* if known */
conn->size += bytecount; /* we append the already read size */
if ('\r' == *p)
p++; /* pass the \r byte */
if ('\n' == *p)
p++; /* pass the \n byte */
pgrsSetDownloadSize(data, conn->size);
header = FALSE; /* no more header to parse! */
/* now, only output this if the header AND body are requested:
*/
if (data->bits.http_include_header) {
if((p - data->headerbuff) !=
data->fwrite (data->headerbuff, 1,
p - data->headerbuff, data->out)) {
failf (data, "Failed writing output");
return CURLE_WRITE_ERROR;
}
}
if(data->writeheader) {
/* obviously, the header is requested to be written to
this file: */
if((p - data->headerbuff) !=
data->fwrite (data->headerbuff, 1, p - data->headerbuff,
data->writeheader)) {
failf (data, "Failed writing output");
return CURLE_WRITE_ERROR;
}
}
break; /* exit header line loop */
}
if (!headerline++) {
/* This is the first header, it MUST be the error code line
or else we consiser this to be the body right away! */
if (sscanf (p, " HTTP/1.%*c %3d", &code)) {
/* 404 -> URL not found! */
if (
( ((data->bits.http_follow_location) && (code >= 400))
||
(!data->bits.http_follow_location && (code >= 300)))
&& (data->bits.http_fail_on_error)) {
/* If we have been told to fail hard on HTTP-errors,
here is the check for that: */
/* serious error, go home! */
failf (data, "The requested file was not found");
return CURLE_HTTP_NOT_FOUND;
}
data->progress.httpcode = code;
}
else {
header = FALSE; /* this is not a header line */
break;
}
}
/* check for Content-Length: header lines to get size */
if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength))
conn->size = contentlength;
else if (strnequal("Content-Range", p, 13) &&
sscanf (p+13, ": bytes %d-", &offset)) {
if (data->resume_from == offset) {
/* we asked for a resume and we got it */
content_range = TRUE;
}
}
else if(data->cookies &&
strnequal("Set-Cookie: ", p, 11)) {
cookie_add(data->cookies, TRUE, &p[12]);
}
else if(strnequal("Last-Modified:", p,
strlen("Last-Modified:")) &&
data->timecondition) {
time_t secs=time(NULL);
timeofdoc = curl_getdate(p+strlen("Last-Modified:"), &secs);
}
else if ((code >= 300 && code < 400) &&
(data->bits.http_follow_location) &&
strnequal("Location", p, 8) &&
sscanf (p+8, ": %" URL_MAX_LENGTH_TXT "s",
newurl)) {
/* this is the URL that the server advices us to get
instead */
data->newurl = strdup (newurl);
}
if (data->bits.http_include_header) {
if(hbuflen != data->fwrite (p, 1, hbuflen, data->out)) {
failf (data, "Failed writing output");
return CURLE_WRITE_ERROR;
}
}
if(data->writeheader) {
/* the header is requested to be written to this file */
if(hbuflen != data->fwrite (p, 1, hbuflen,
data->writeheader)) {
failf (data, "Failed writing output");
return CURLE_WRITE_ERROR;
}
}
/* reset hbufp pointer && hbuflen */
hbufp = data->headerbuff;
hbuflen = 0;
}
while (*str); /* header line within buffer */
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read
buffer. */
if (!header) {
/* the next token and forward is not part of
the header! */
/* we subtract the remaining header size from the buffer */
nread -= (str - buf);
}
} /* end if header mode */
/* This is not an 'else if' since it may be a rest from the header
parsing, where the beginning of the buffer is headers and the end
is non-headers. */
if (str && !header && (nread > 0)) {
if(0 == bodywrites) {
/* These checks are only made the first time we are about to
write a chunk of the body */
if(conn->protocol&PROT_HTTP) {
/* HTTP-only checks */
if (data->resume_from && !content_range ) {
/* we wanted to resume a download, although the server
doesn't seem to support this */
failf (data, "HTTP server doesn't seem to support byte ranges. Cannot resume.");
return CURLE_HTTP_RANGE_ERROR;
}
else if (data->newurl) {
/* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl);
return CURLE_OK;
}
else if(data->timecondition && !data->range) {
/* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of
RFC 2616 defines to be the correct action for a
HTTP/1.1 client */
if((timeofdoc > 0) && (data->timevalue > 0)) {
switch(data->timecondition) {
case TIMECOND_IFMODSINCE:
default:
if(timeofdoc < data->timevalue) {
infof(data,
"The requested document is not new enough");
return CURLE_OK;
}
break;
case TIMECOND_IFUNMODSINCE:
if(timeofdoc > data->timevalue) {
infof(data,
"The requested document is not old enough");
return CURLE_OK;
}
break;
} /* switch */
} /* two valid time strings */
} /* we have a time condition */
} /* this is HTTP */
} /* this is the first time we write a body part */
bodywrites++;
if(data->maxdownload &&
(bytecount + nread > data->maxdownload)) {
nread = data->maxdownload - bytecount;
if(nread < 0 ) /* this should be unusual */
nread = 0;
keepon &= ~KEEP_READ; /* we're done reading */
}
bytecount += nread;
pgrsSetDownloadCounter(data, (double)bytecount);
if (nread != data->fwrite (str, 1, nread, data->out)) {
failf (data, "Failed writing output");
return CURLE_WRITE_ERROR;
}
} /* if (! header and data to read ) */
} /* if( read from socket ) */
if((keepon & KEEP_WRITE) && FD_ISSET(conn->writesockfd, &writefd)) {
/* write */
char scratch[BUFSIZE * 2];
int i, si;
int bytes_written;
if(data->crlf)
buf = data->buffer; /* put it back on the buffer */
nread = data->fread(buf, 1, BUFSIZE, data->in);
writebytecount += nread;
pgrsSetUploadCounter(data, (double)writebytecount);
if (nread<=0) {
/* done */
keepon &= ~KEEP_WRITE; /* we're done writing */
break;
}
/* convert LF to CRLF if so asked */
if (data->crlf) {
for(i = 0, si = 0; i < (int)nread; i++, si++) {
if (buf[i] == 0x0a) {
scratch[si++] = 0x0d;
scratch[si] = 0x0a;
}
else {
scratch[si] = buf[i];
}
}
nread = si;
buf = scratch; /* point to the new buffer */
}
/* write to socket */
urg = curl_write(conn, buf, nread, &bytes_written);
if(nread != bytes_written) {
failf(data, "Failed uploading data");
return CURLE_WRITE_ERROR;
}
}
break;
}
now = tvnow();
if(pgrsUpdate(data))
urg = CURLE_ABORTED_BY_CALLBACK;
else
urg = speedcheck (data, now);
if (urg)
return urg;
if (data->timeout && (tvdiff (now, start) > data->timeout)) {
failf (data, "Operation timed out with %d out of %d bytes received",
bytecount, conn->size);
return CURLE_OPERATION_TIMEOUTED;
}
}
}
if(!(data->bits.no_body) && contentlength &&
(bytecount != contentlength)) {
failf(data, "transfer closed with %d bytes remaining to read",
contentlength-bytecount);
return CURLE_PARTIAL_FILE;
}
if(pgrsUpdate(data))
return CURLE_ABORTED_BY_CALLBACK;
if(conn->bytecountp)
*conn->bytecountp = bytecount; /* read count */
if(conn->writebytecountp)
*conn->writebytecountp = writebytecount; /* write count */
return CURLE_OK;
}
typedef int (*func_T)(void);
CURLcode curl_transfer(CURL *curl)
{
CURLcode res;
struct UrlData *data = curl;
struct connectdata *c_connect;
do {
res = curl_connect(curl, (CURLconnect **)&c_connect);
if(res == CURLE_OK) {
res = curl_do(c_connect);
if(res == CURLE_OK) {
res = _Transfer(c_connect); /* now fetch that URL please */
if(res == CURLE_OK)
res = curl_done(c_connect);
}
if((res == CURLE_OK) && data->newurl) {
/* Location: redirect */
char prot[16];
char path[URL_MAX_LENGTH];
if(2 != sscanf(data->newurl, "%15[^:]://%" URL_MAX_LENGTH_TXT
"s", prot, path)) {
/***
*DANG* this is an RFC 2068 violation. The URL is supposed
to be absolute and this doesn't seem to be that!
***
Instead, we have to TRY to append this new path to the old URL
to the right of the host part. Oh crap, this is doomed to cause
problems in the future...
*/
char *protsep;
char *pathsep;
char *newest;
/* protsep points to the start of the host name */
protsep=strstr(data->url, "//");
if(!protsep)
protsep=data->url;
else {
/* TBD: set the port with curl_setopt() */
data->port=0; /* we got a full URL and then we should reset the
port number here to re-initiate it later */
protsep+=2; /* pass the slashes */
}
if('/' != data->newurl[0]) {
/* First we need to find out if there's a ?-letter in the URL,
and cut it and the right-side of that off */
pathsep = strrchr(protsep, '?');
if(pathsep)
*pathsep=0;
/* we have a relative path to append to the last slash if
there's one available */
pathsep = strrchr(protsep, '/');
if(pathsep)
*pathsep=0;
}
else {
/* We got a new absolute path for this server, cut off from the
first slash */
pathsep = strchr(protsep, '/');
if(pathsep)
*pathsep=0;
}
newest=(char *)malloc( strlen(data->url) +
1 + /* possible slash */
strlen(data->newurl) + 1/* zero byte */);
if(!newest)
return CURLE_OUT_OF_MEMORY;
sprintf(newest, "%s%s%s", data->url, ('/' == data->newurl[0])?"":"/",
data->newurl);
free(data->newurl);
data->newurl = newest;
}
else {
/* This was an absolute URL, clear the port number! */
/* TBD: set the port with curl_setopt() */
data->port = 0;
}
/* TBD: set the URL with curl_setopt() */
data->url = data->newurl;
data->newurl = NULL; /* don't show! */
infof(data, "Follows Location: to new URL: '%s'\n", data->url);
curl_disconnect(c_connect);
continue;
}
curl_disconnect(c_connect);
}
break; /* it only reaches here when this shouldn't loop */
} while(1); /* loop if Location: */
if(data->newurl)
free(data->newurl);
if((CURLE_OK == res) && data->writeinfo) {
/* Time to output some info to stdout */
WriteOut(data);
}
return res;
}
#if 0
CURLcode curl_urlget(UrgTag tag, ...)
{
va_list arg;
func_T param_func = (func_T)0;
long param_long = 0;
void *param_obj = NULL;
CURLcode res;
struct UrlData *data;
/* this is for the lame win32 socket crap */
if(curl_init())
return CURLE_FAILED_INIT;
/* We use curl_open() with undefined URL so far */
res = curl_open(&data, NULL);
if(res != CURLE_OK)
return CURLE_FAILED_INIT;
/* data is now filled with good-looking zeroes */
va_start(arg, tag);
while(tag != URGTAG_DONE) {
/* PORTING NOTE:
Object pointers can't necessarily be casted to function pointers and
therefore we need to know what type it is and read the correct type
at once. This should also correct problems with different sizes of
the types.
*/
if(tag < URGTYPE_OBJECTPOINT) {
/* This is a LONG type */
param_long = va_arg(arg, long);
curl_setopt(data, tag, param_long);
}
else if(tag < URGTYPE_FUNCTIONPOINT) {
/* This is a object pointer type */
param_obj = va_arg(arg, void *);
curl_setopt(data, tag, param_obj);
}
else {
param_func = va_arg(arg, func_T );
curl_setopt(data, tag, param_func);
}
/* printf("tag: %d\n", tag); */
tag = va_arg(arg, UrgTag);
}
va_end(arg);
pgrsMode(data, data->progress.mode);
pgrsStartNow(data);
/********* Now, connect to the remote site **********/
res = curl_transfer(data);
curl_close(data);
return res;
}
#endif

43
lib/highlevel.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef __HIGHLEVEL_H
#define __HIGHLEVEL_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
CURLcode curl_transfer(CURL *curl);
#endif

View File

@@ -39,6 +39,7 @@
****************************************************************************/ ****************************************************************************/
#include <string.h> #include <string.h>
#include <malloc.h>
#include "setup.h" #include "setup.h"
@@ -61,51 +62,77 @@
#include "urldata.h" #include "urldata.h"
#include "sendf.h" #include "sendf.h"
#ifdef HAVE_INET_NTOA_R
#include "inet_ntoa_r.h"
#endif
/* --- resolve name or IP-number --- */ /* --- resolve name or IP-number --- */
char *MakeIP(unsigned long num) char *MakeIP(unsigned long num,char *addr, int addr_len)
{ {
#ifdef HAVE_INET_NTOA #if defined(HAVE_INET_NTOA) || defined(HAVE_INET_NTOA_R)
struct in_addr in; struct in_addr in;
in.s_addr = htonl(num); in.s_addr = htonl(num);
return (inet_ntoa(in));
#if defined(HAVE_INET_NTOA_R)
inet_ntoa_r(in,addr,addr_len);
#else
strncpy(addr,inet_ntoa(in),addr_len);
#endif
#else #else
static char addr[128];
unsigned char *paddr; unsigned char *paddr;
num = htonl(num); /* htonl() added to avoid endian probs */ num = htonl(num); /* htonl() added to avoid endian probs */
paddr = (unsigned char *)&num; paddr = (unsigned char *)&num;
sprintf(addr, "%u.%u.%u.%u", paddr[0], paddr[1], paddr[2], paddr[3]); sprintf(addr, "%u.%u.%u.%u", paddr[0], paddr[1], paddr[2], paddr[3]);
return (addr);
#endif #endif
return (addr);
} }
/* Stolen from Dancer source code, written by /* The original code to this function was stolen from the Dancer source code,
Bjorn Reese <breese@imada.ou.dk> */ written by Bjorn Reese, it has since been patched and modified. */
#ifndef INADDR_NONE #ifndef INADDR_NONE
#define INADDR_NONE (unsigned long) ~0 #define INADDR_NONE (unsigned long) ~0
#endif #endif
struct hostent *GetHost(struct UrlData *data, char *hostname) struct hostent *GetHost(struct UrlData *data,
char *hostname,
char *buf,
int buf_size )
{ {
struct hostent *h = NULL; struct hostent *h = NULL;
unsigned long in; unsigned long in;
static struct hostent he;
static char name[MAXHOSTNAMELEN];
static char *addrlist[2];
static struct in_addr addrentry;
if ( (in=inet_addr(hostname)) != INADDR_NONE ) { if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
addrentry.s_addr = in; struct in_addr *addrentry;
addrlist[0] = (char *)&addrentry;
addrlist[1] = NULL; h = (struct hostent*)buf;
he.h_name = strncpy(name, MakeIP(ntohl(in)), MAXHOSTNAMELEN); h->h_addr_list = (char**)(buf + sizeof(*h));
he.h_addrtype = AF_INET; addrentry = (struct in_addr*)(h->h_addr_list + 2);
he.h_length = sizeof(struct in_addr); addrentry->s_addr = in;
he.h_addr_list = addrlist; h->h_addr_list[0] = (char*)addrentry;
h = &he; h->h_addr_list[1] = NULL;
} else if ( (h=gethostbyname(hostname)) == NULL ) { h->h_addrtype = AF_INET;
h->h_length = sizeof(*addrentry);
h->h_name = (char*)(h->h_addr_list + h->h_length);
MakeIP(ntohl(in),h->h_name,buf_size - (long)(h->h_name) + (long)buf);
#if defined(HAVE_GETHOSTBYNAME_R)
}
else {
int h_errnop;
memset(buf,0,buf_size); /* workaround for gethostbyname_r bug in qnx nto */
if ((h = gethostbyname_r(hostname,
(struct hostent *)buf,buf +
sizeof(struct hostent),buf_size -
sizeof(struct hostent),&h_errnop)) == NULL ) {
infof(data, "gethostbyname_r(2) failed for %s\n", hostname);
}
#else
}
else {
if ((h = gethostbyname(hostname)) == NULL ) {
infof(data, "gethostbyname(2) failed for %s\n", hostname); infof(data, "gethostbyname(2) failed for %s\n", hostname);
} }
#endif
}
return (h); return (h);
} }

View File

@@ -40,7 +40,7 @@
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
struct hostent *GetHost(struct UrlData *data, char *hostname); extern struct hostent *GetHost(struct UrlData *data, char *hostname, char *buf, int buf_size );
char *MakeIP(unsigned long num); extern char *MakeIP(unsigned long num,char *addr, int addr_len);
#endif #endif

View File

@@ -94,6 +94,9 @@
#include "progress.h" #include "progress.h"
#include "base64.h" #include "base64.h"
#include "cookie.h" #include "cookie.h"
#include "strequal.h"
#include "url.h"
#include "ssluse.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h> #include <curl/mprintf.h>
@@ -115,33 +118,114 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
return FALSE; return FALSE;
} }
UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount) CURLcode http_connect(struct connectdata *conn)
{ {
/* Send the GET line to the HTTP server */ struct UrlData *data;
struct FormData *sendit=NULL; data=conn->data;
int postsize=0;
UrgError result;
char *buf;
struct Cookie *co = NULL;
char *p_pragma = NULL;
char *p_accept = NULL;
long readbytecount;
long writebytecount;
buf = data->buffer; /* this is our buffer */ /* If we are not using a proxy and we want a secure connection,
* perform SSL initialization & connection now.
* If using a proxy with https, then we must tell the proxy to CONNECT
* us to the host we want to talk to. Only after the connect
* has occured, can we start talking SSL
*/
if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) {
if ( (data->conf&(CONF_HTTP|CONF_FTP)) && /* OK, now send the connect statment */
(data->conf&CONF_UPLOAD)) { sendf(data->firstsocket, data,
data->conf |= CONF_PUT; "CONNECT %s:%d HTTP/1.0\015\012"
"%s"
"%s"
"\r\n",
data->hostname, data->remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"")
);
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
/* Daniel rewrote this part Nov 5 1998 to make it more obvious */
{
int httperror=0;
int subversion=0;
while(GetLine(data->firstsocket, data->buffer, data)) {
if('\r' == data->buffer[0])
break; /* end of headers */
if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
&subversion,
&httperror)) {
;
} }
#if 0 /* old version */
if((data->conf&(CONF_HTTP|CONF_UPLOAD)) ==
(CONF_HTTP|CONF_UPLOAD)) {
/* enable PUT! */
data->conf |= CONF_PUT;
} }
#endif if(200 != httperror) {
if(407 == httperror)
/* Added Nov 6 1998 */
failf(data, "Proxy requires authorization!");
else
failf(data, "Received error code %d from proxy", httperror);
return CURLE_READ_ERROR;
}
}
infof (data, "Proxy has replied to CONNECT request\n");
}
/* now, perform the SSL initialization for this socket */
if(UrgSSLConnect (data)) {
return CURLE_SSL_CONNECT_ERROR;
}
}
return CURLE_OK;
}
CURLcode http_done(struct connectdata *conn)
{
struct UrlData *data;
long *bytecount = &conn->bytecount;
struct HTTP *http;
data=conn->data;
http=data->proto.http;
if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount;
FormFree(http->sendit); /* Now free that whole lot */
data->fread = http->storefread; /* restore */
data->in = http->in; /* restore */
}
else if(data->bits.http_put) {
*bytecount = http->readbytecount + http->writebytecount;
}
/* TBD: the HTTP struct remains allocated here */
return CURLE_OK;
}
CURLcode http(struct connectdata *conn)
{
struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is a short cut to the buffer */
CURLcode result;
struct HTTP *http;
struct Cookie *co=NULL; /* no cookies from start */
char *ppath = conn->ppath; /* three previous function arguments */
char *host = conn->name;
long *bytecount = &conn->bytecount;
http = (struct HTTP *)malloc(sizeof(struct HTTP));
if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
data->proto.http = http;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) {
data->bits.http_put=1;
}
/* The User-Agent string has been built in url.c already, because it might /* The User-Agent string has been built in url.c already, because it might
have been used in the proxy connect, but if we have got a header with have been used in the proxy connect, but if we have got a header with
@@ -152,17 +236,17 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
data->ptr_uagent=NULL; data->ptr_uagent=NULL;
} }
if((data->conf & CONF_USERPWD) && !checkheaders(data, "Authorization:")) { if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
char authorization[512]; char authorization[512];
sprintf(data->buffer, "%s:%s", data->user, data->passwd); sprintf(data->buffer, "%s:%s", data->user, data->passwd);
base64Encode(data->buffer, authorization); base64Encode(data->buffer, authorization);
data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012", data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012",
authorization); authorization);
} }
if((data->conf & CONF_RANGE) && !checkheaders(data, "Range:")) { if((data->bits.set_range) && !checkheaders(data, "Range:")) {
data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range); data->ptr_rangeline = maprintf("Range: bytes=%s\015\012", data->range);
} }
if((data->conf & CONF_REFERER) && !checkheaders(data, "Referer:")) { if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) {
data->ptr_ref = maprintf("Referer: %s\015\012", data->referer); data->ptr_ref = maprintf("Referer: %s\015\012", data->referer);
} }
if(data->cookie && !checkheaders(data, "Cookie:")) { if(data->cookie && !checkheaders(data, "Cookie:")) {
@@ -173,16 +257,16 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
co = cookie_getlist(data->cookies, co = cookie_getlist(data->cookies,
host, host,
ppath, ppath,
data->conf&CONF_HTTPS?TRUE:FALSE); conn->protocol&PROT_HTTPS?TRUE:FALSE);
} }
if ((data->conf & CONF_PROXY) && (!(data->conf & CONF_HTTPS))) { if ((data->bits.httpproxy) && !(conn->protocol&PROT_HTTPS)) {
/* The path sent to the proxy is in fact the entire URL */ /* The path sent to the proxy is in fact the entire URL */
strncpy(ppath, data->url, URL_MAX_LENGTH-1); strncpy(ppath, data->url, URL_MAX_LENGTH-1);
} }
if(data->conf & CONF_HTTPPOST) { if(data->bits.http_formpost) {
/* we must build the whole darned post sequence first, so that we have /* we must build the whole darned post sequence first, so that we have
a size of the whole shebang before we start to send it */ a size of the whole shebang before we start to send it */
sendit = getFormData(data->httppost, &postsize); http->sendit = getFormData(data->httppost, &http->postsize);
} }
if(!checkheaders(data, "Host:")) if(!checkheaders(data, "Host:"))
@@ -190,10 +274,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
if(!checkheaders(data, "Pragma:")) if(!checkheaders(data, "Pragma:"))
p_pragma = "Pragma: no-cache\r\n"; http->p_pragma = "Pragma: no-cache\r\n";
if(!checkheaders(data, "Accept:")) if(!checkheaders(data, "Accept:"))
p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n"; http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
do { do {
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
@@ -210,19 +294,19 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
"%s", /* referer */ "%s", /* referer */
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->conf&CONF_NOBODY?"HEAD": (data->bits.no_body?"HEAD":
(data->conf&(CONF_POST|CONF_HTTPPOST))?"POST": (data->bits.http_post || data->bits.http_formpost)?"POST":
(data->conf&CONF_PUT)?"PUT":"GET"), (data->bits.http_put)?"PUT":"GET"),
ppath, ppath,
(data->conf&CONF_PROXYUSERPWD && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"", (data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
(data->conf&CONF_USERPWD && data->ptr_userpwd)?data->ptr_userpwd:"", (data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
(data->conf&CONF_RANGE && data->ptr_rangeline)?data->ptr_rangeline:"", (data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"", (data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */ (data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
(data->ptr_host?data->ptr_host:""), /* Host: host */ (data->ptr_host?data->ptr_host:""), /* Host: host */
p_pragma?p_pragma:"", http->p_pragma?http->p_pragma:"",
p_accept?p_accept:"", http->p_accept?http->p_accept:"",
(data->conf&CONF_REFERER && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */ (data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
); );
if(co) { if(co) {
@@ -234,9 +318,10 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"Cookie:"); "Cookie:");
} }
count++;
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
" %s=%s;", co->name, co->value); "%s%s=%s", count?"; ":"", co->name,
co->value);
count++;
} }
co = co->next; /* next cookie please */ co = co->next; /* next cookie please */
} }
@@ -284,8 +369,8 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
data->headers = data->headers->next; data->headers = data->headers->next;
} }
if(data->conf&(CONF_POST|CONF_HTTPPOST)) { if(data->bits.http_post || data->bits.http_formpost) {
if(data->conf & CONF_POST) { if(data->bits.http_post) {
/* this is the simple x-www-form-urlencoded style */ /* this is the simple x-www-form-urlencoded style */
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"Content-Length: %d\015\012" "Content-Length: %d\015\012"
@@ -295,53 +380,39 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
data->postfields ); data->postfields );
} }
else { else {
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
long conf;
if(FormInit(&form, sendit)) { if(FormInit(&http->form, http->sendit)) {
failf(data, "Internal HTTP POST error!\n"); failf(data, "Internal HTTP POST error!\n");
return URG_HTTP_POST_ERROR; return CURLE_HTTP_POST_ERROR;
} }
storefread = data->fread; /* backup */ http->storefread = data->fread; /* backup */
in = data->in; /* backup */ http->in = data->in; /* backup */
data->fread = data->fread =
(size_t (*)(char *, size_t, size_t, FILE *)) (size_t (*)(char *, size_t, size_t, FILE *))
FormReader; /* set the read function to read from the FormReader; /* set the read function to read from the
generated form data */ generated form data */
data->in = (FILE *)&form; data->in = (FILE *)&http->form;
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"Content-Length: %d\r\n", "Content-Length: %d\r\n",
postsize-2); http->postsize-2);
pgrsSetUploadSize(data, postsize); pgrsSetUploadSize(data, http->postsize);
#if 0
ProgressInit(data, postsize);
#endif
result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, result = Transfer(conn, data->firstsocket, -1, TRUE,
data->firstsocket, &writebytecount); &http->readbytecount,
*bytecount = readbytecount + writebytecount; data->firstsocket,
&http->writebytecount);
FormFree(sendit); /* Now free that whole lot */ if(result) {
FormFree(http->sendit); /* free that whole lot */
if(result)
return result; return result;
data->fread = storefread; /* restore */
data->in = in; /* restore */
sendf(data->firstsocket, data,
"\r\n\r\n");
} }
} }
else if(data->conf&CONF_PUT) { }
else if(data->bits.http_put) {
/* Let's PUT the data to the server! */ /* Let's PUT the data to the server! */
long conf;
if(data->infilesize>0) { if(data->infilesize>0) {
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
@@ -352,39 +423,28 @@ UrgError http(struct UrlData *data, char *ppath, char *host, long *bytecount)
sendf(data->firstsocket, data, sendf(data->firstsocket, data,
"\015\012"); "\015\012");
#if 0
ProgressInit(data, data->infilesize);
#endif
pgrsSetUploadSize(data, data->infilesize); pgrsSetUploadSize(data, data->infilesize);
result = Transfer(data, data->firstsocket, -1, TRUE, &readbytecount, result = Transfer(conn, data->firstsocket, -1, TRUE,
data->firstsocket, &writebytecount); &http->readbytecount,
data->firstsocket,
*bytecount = readbytecount + writebytecount; &http->writebytecount);
if(result) if(result)
return result; return result;
} }
else { else {
sendf(data->firstsocket, data, "\r\n"); sendf(data->firstsocket, data, "\r\n");
}
if(0 == *bytecount) {
/* HTTP GET/HEAD download: */ /* HTTP GET/HEAD download: */
result = Transfer(data, data->firstsocket, -1, TRUE, bytecount, result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */ -1, NULL); /* nothing to upload */
} }
if(result) if(result)
return result; return result;
#if 0
ProgressEnd(data);
#endif
pgrsDone(data);
} while (0); /* this is just a left-over from the multiple document download } while (0); /* this is just a left-over from the multiple document download
attempts */ attempts */
return URG_OK; return CURLE_OK;
} }

View File

@@ -40,6 +40,9 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError http(struct UrlData *data, char *path, char *host, long *bytecountp);
CURLcode http(struct connectdata *conn);
CURLcode http_done(struct connectdata *conn);
CURLcode http_connect(struct connectdata *conn);
#endif #endif

View File

@@ -66,13 +66,21 @@
#include <netdb.h> #include <netdb.h>
#endif #endif
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H #ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h> #include <sys/sockio.h>
#endif #endif
#ifdef HAVE_INET_NTOA_R
#include "inet_ntoa_r.h"
#endif
#define SYS_ERROR -1 #define SYS_ERROR -1
char *if2ip(char *interface) char *if2ip(char *interface, char *buf, int buf_size)
{ {
int dummy; int dummy;
char *ip=NULL; char *ip=NULL;
@@ -97,7 +105,12 @@ char *if2ip(char *interface)
struct sockaddr_in *s = (struct sockaddr_in *)&req.ifr_dstaddr; struct sockaddr_in *s = (struct sockaddr_in *)&req.ifr_dstaddr;
memcpy(&in, &(s->sin_addr.s_addr), sizeof(in)); memcpy(&in, &(s->sin_addr.s_addr), sizeof(in));
ip = (char *)strdup(inet_ntoa(in)); #if defined(HAVE_INET_NTOA_R)
ip = inet_ntoa_r(in,buf,buf_size);
#else
ip = strncpy(buf,inet_ntoa(in),buf_size);
ip[buf_size - 1] = 0;
#endif
} }
close(dummy); close(dummy);
} }

View File

@@ -42,9 +42,9 @@
#include "setup.h" #include "setup.h"
#if ! defined(WIN32) && ! defined(__BEOS__) #if ! defined(WIN32) && ! defined(__BEOS__)
char *if2ip(char *interface); extern char *if2ip(char *interface, char *buf, int buf_size);
#else #else
#define if2ip(x) NULL #define if2ip(a,b,c) NULL
#endif #endif
#endif #endif

9
lib/inet_ntoa_r.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef __INET_NTOA_R_H
#define __INET_NTOA_R_H
/*
* My solaris 5.6 system running gcc 2.8.1 does *not* have this prototype
* in any system include file! Isn't that weird?
*/
char *inet_ntoa_r(const struct in_addr in, char *buffer, int buflen);
#endif

View File

@@ -72,7 +72,7 @@
#define DYNA_GET_FUNCTION(type, fnc) \ #define DYNA_GET_FUNCTION(type, fnc) \
(fnc) = (type)DynaGetFunction(#fnc); \ (fnc) = (type)DynaGetFunction(#fnc); \
if ((fnc) == NULL) { \ if ((fnc) == NULL) { \
return URG_FUNCTION_NOT_FOUND; \ return CURLE_FUNCTION_NOT_FOUND; \
} \ } \
/*********************************************************************** /***********************************************************************
@@ -89,7 +89,18 @@ static void DynaOpen(void)
* liblber.so automatically, but since it does not we will * liblber.so automatically, but since it does not we will
* handle it here by opening liblber.so as global. * handle it here by opening liblber.so as global.
*/ */
dlopen("liblber.so", RTLD_LAZY | RTLD_GLOBAL); dlopen("liblber.so",
#ifdef RTLD_LAZY_GLOBAL /* It turns out some systems use this: */
RTLD_LAZY_GLOBAL
#else
#ifdef RTLD_GLOBAL
RTLD_LAZY | RTLD_GLOBAL
#else
/* and some systems don't have the RTLD_GLOBAL symbol */
RTLD_LAZY
#endif
#endif
);
libldap = dlopen("libldap.so", RTLD_LAZY); libldap = dlopen("libldap.so", RTLD_LAZY);
} }
#endif #endif
@@ -124,15 +135,20 @@ static int WriteProc(void *param, char *text, int len)
{ {
struct UrlData *data = (struct UrlData *)param; struct UrlData *data = (struct UrlData *)param;
printf("%s\n", text); data->fwrite(text, 1, strlen(text), data->out);
return 0; return 0;
} }
CURLcode ldap_done(struct connectdata *conn)
{
return CURLE_OK;
}
/*********************************************************************** /***********************************************************************
*/ */
UrgError ldap(struct UrlData *data, char *path, long *bytecount) CURLcode ldap(struct connectdata *conn)
{ {
UrgError status = URG_OK; CURLcode status = CURLE_OK;
int rc; int rc;
void *(*ldap_open)(char *, int); void *(*ldap_open)(char *, int);
int (*ldap_simple_bind_s)(void *, char *, char *); int (*ldap_simple_bind_s)(void *, char *, char *);
@@ -146,24 +162,19 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
void *server; void *server;
void *result; void *result;
void *entryIterator; void *entryIterator;
#if 0
char *dn;
char **attrArray;
char *attrIterator;
char *attrString;
void *dummy;
#endif
int ldaptext; int ldaptext;
struct UrlData *data=conn->data;
infof(data, "LDAP: %s %s\n", data->url); infof(data, "LDAP: %s %s\n", data->url);
DynaOpen(); DynaOpen();
if (libldap == NULL) { if (libldap == NULL) {
failf(data, "The needed LDAP library/libraries couldn't be opened"); failf(data, "The needed LDAP library/libraries couldn't be opened");
return URG_LIBRARY_NOT_FOUND; return CURLE_LIBRARY_NOT_FOUND;
} }
ldaptext = data->conf & CONF_FTPASCII; /* This is a dirty hack */ ldaptext = data->bits.ftp_ascii; /* This is a dirty hack */
/* The types are needed because ANSI C distinguishes between /* The types are needed because ANSI C distinguishes between
* pointer-to-object (data) and pointer-to-function. * pointer-to-object (data) and pointer-to-function.
@@ -182,17 +193,17 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
if (server == NULL) { if (server == NULL) {
failf(data, "LDAP: Cannot connect to %s:%d", failf(data, "LDAP: Cannot connect to %s:%d",
data->hostname, data->port); data->hostname, data->port);
status = URG_COULDNT_CONNECT; status = CURLE_COULDNT_CONNECT;
} else { } else {
rc = ldap_simple_bind_s(server, data->user, data->passwd); rc = ldap_simple_bind_s(server, data->user, data->passwd);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_CANNOT_BIND; status = CURLE_LDAP_CANNOT_BIND;
} else { } else {
rc = ldap_url_search_s(server, data->url, 0, &result); rc = ldap_url_search_s(server, data->url, 0, &result);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
} else { } else {
for (entryIterator = ldap_first_entry(server, result); for (entryIterator = ldap_first_entry(server, result);
entryIterator; entryIterator;
@@ -204,7 +215,7 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
"", 0, 0); "", 0, 0);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
} }
} else { } else {
rc = ldap_entry2html(server, NULL, entryIterator, NULL, rc = ldap_entry2html(server, NULL, entryIterator, NULL,
@@ -212,7 +223,7 @@ UrgError ldap(struct UrlData *data, char *path, long *bytecount)
"", 0, 0, NULL, NULL); "", 0, 0, NULL, NULL);
if (rc != 0) { if (rc != 0) {
failf(data, "LDAP: %s", ldap_err2string(rc)); failf(data, "LDAP: %s", ldap_err2string(rc));
status = URG_LDAP_SEARCH_FAILED; status = CURLE_LDAP_SEARCH_FAILED;
} }
} }
} }

View File

@@ -40,6 +40,7 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError ldap(struct UrlData *data, char *path, long *bytecount); CURLcode ldap(struct connectdata *conn);
CURLcode ldap_done(struct connectdata *conn);
#endif /* __LDAP_H */ #endif /* __LDAP_H */

View File

@@ -56,6 +56,7 @@
#include "setup.h" #include "setup.h"
#include "getenv.h" #include "getenv.h"
#include "strequal.h"
/* Debug this single source file with: /* Debug this single source file with:
'make netrc' then run './netrc'! 'make netrc' then run './netrc'!
@@ -94,9 +95,14 @@ int ParseNetrc(char *host,
#define NETRC DOT_CHAR "netrc" #define NETRC DOT_CHAR "netrc"
if(!home || (strlen(home)>(sizeof(netrcbuffer)-strlen(NETRC)))) if(!home)
return -1; return -1;
if(strlen(home)>(sizeof(netrcbuffer)-strlen(NETRC))) {
free(home);
return -1;
}
sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC); sprintf(netrcbuffer, "%s%s%s", home, DIR_CHAR, NETRC);
file = fopen(netrcbuffer, "r"); file = fopen(netrcbuffer, "r");
@@ -161,6 +167,8 @@ int ParseNetrc(char *host,
fclose(file); fclose(file);
} }
free(home);
return retcode; return retcode;
} }

View File

@@ -72,15 +72,23 @@ void time2str(char *r, int t)
but never longer than 5 columns. Add suffix k, M, G when suitable... */ but never longer than 5 columns. Add suffix k, M, G when suitable... */
char *max5data(double bytes, char *max5) char *max5data(double bytes, char *max5)
{ {
#define ONE_KILOBYTE 1024
#define ONE_MEGABYTE (1024*1024)
if(bytes < 100000) { if(bytes < 100000) {
sprintf(max5, "%5d", (int)bytes); sprintf(max5, "%5d", (int)bytes);
return max5; return max5;
} }
if(bytes < (9999*1024)) { if(bytes < (9999*ONE_KILOBYTE)) {
sprintf(max5, "%4dk", (int)bytes/1024); sprintf(max5, "%4dk", (int)bytes/ONE_KILOBYTE);
return max5; return max5;
} }
sprintf(max5, "%4dM", (int)bytes/(1024*1024)); if(bytes < (100*ONE_MEGABYTE)) {
/* 'XX.XM' is good as long as we're less than 100 megs */
sprintf(max5, "%2.1fM", bytes/ONE_MEGABYTE);
return max5;
}
sprintf(max5, "%4dM", (int)bytes/ONE_MEGABYTE);
return max5; return max5;
} }
@@ -110,7 +118,7 @@ void pgrsDone(struct UrlData *data)
void pgrsMode(struct UrlData *data, int mode) void pgrsMode(struct UrlData *data, int mode)
{ {
/* mode should include a hidden mode as well */ /* mode should include a hidden mode as well */
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE)) if(data->bits.hide_progress || data->bits.mute)
data->progress.flags |= PGRS_HIDE; /* don't show anything */ data->progress.flags |= PGRS_HIDE; /* don't show anything */
else { else {
data->progress.mode = mode; /* store type */ data->progress.mode = mode; /* store type */
@@ -179,29 +187,10 @@ void pgrsSetUploadSize(struct UrlData *data, double size)
*/ */
void pgrsUpdate(struct UrlData *data) int pgrsUpdate(struct UrlData *data)
{ {
struct timeval now; struct timeval now;
if(data->progress.flags & PGRS_HIDE)
; /* 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
even when not displayed! */
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if ( data->progress.mode == CURL_PROGRESS_STATS ) {
fprintf(data->err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n");
}
data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
}
now = tvnow(); /* what time is it */
switch(data->progress.mode) {
case CURL_PROGRESS_STATS:
default:
{
char max5[6][6]; char max5[6][6];
double dlpercen=0; double dlpercen=0;
double ulpercen=0; double ulpercen=0;
@@ -228,8 +217,23 @@ void pgrsUpdate(struct UrlData *data)
double total_estimate; double total_estimate;
if(data->progress.flags & PGRS_HIDE)
; /* 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
even when not displayed! */
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if ( data->progress.mode == CURL_PROGRESS_STATS ) {
fprintf(data->err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n");
}
data->progress.flags |= PGRS_HEADERS_OUT; /* headers are shown */
}
now = tvnow(); /* what time is it */
if(data->progress.lastshow == tvlong(now)) if(data->progress.lastshow == tvlong(now))
return; /* never update this more than once a second if the end isn't return 0; /* never update this more than once a second if the end isn't
reached */ reached */
data->progress.lastshow = now.tv_sec; data->progress.lastshow = now.tv_sec;
@@ -256,7 +260,14 @@ void pgrsUpdate(struct UrlData *data)
(speeder[nowindex]-speeder[checkindex])/(count?count:1); (speeder[nowindex]-speeder[checkindex])/(count?count:1);
if(data->progress.flags & PGRS_HIDE) if(data->progress.flags & PGRS_HIDE)
return; return 0;
else if(data->fprogress) {
return data->fprogress(data->progress_client,
data->progress.size_dl,
data->progress.downloaded,
data->progress.size_ul,
data->progress.uploaded);
}
/* Figure out the estimated time of arrival for the upload */ /* Figure out the estimated time of arrival for the upload */
if(data->progress.flags & PGRS_UL_SIZE_KNOWN) { if(data->progress.flags & PGRS_UL_SIZE_KNOWN) {
@@ -306,7 +317,6 @@ void pgrsUpdate(struct UrlData *data)
if(total_expected_transfer) if(total_expected_transfer)
total_percen=(double)(total_transfer/total_expected_transfer)*100; total_percen=(double)(total_transfer/total_expected_transfer)*100;
fprintf(stderr, fprintf(stderr,
"\r%3d %s %3d %s %3d %s %s %s %s %s %s %s", "\r%3d %s %3d %s %3d %s %s %s %s %s %s %s",
(int)total_percen, /* total % */ (int)total_percen, /* total % */
@@ -323,8 +333,8 @@ void pgrsUpdate(struct UrlData *data)
time_left, /* time left */ time_left, /* time left */
max5data(data->progress.current_speed, max5[5]) /* current speed */ max5data(data->progress.current_speed, max5[5]) /* current speed */
); );
}
break;
#if 0 #if 0
case CURL_PROGRESS_BAR: case CURL_PROGRESS_BAR:
/* original progress bar code by Lars Aas */ /* original progress bar code by Lars Aas */
@@ -357,7 +367,8 @@ void pgrsUpdate(struct UrlData *data)
prev = point; prev = point;
break; break;
#endif #endif
}
return 0;
} }
@@ -376,6 +387,7 @@ void ProgressInit(struct UrlData *data, int max/*, int options, int moremax*/)
/* 20000318 mgs */ /* 20000318 mgs */
int scr_size [2]; int scr_size [2];
#endif #endif
char *colp;
if(data->conf&(CONF_NOPROGRESS|CONF_MUTE)) if(data->conf&(CONF_NOPROGRESS|CONF_MUTE))
return; return;
@@ -388,8 +400,11 @@ void ProgressInit(struct UrlData *data, int max/*, int options, int moremax*/)
/* 20000318 mgs /* 20000318 mgs
* OS/2 users most likely won't have this env var set, and besides that * OS/2 users most likely won't have this env var set, and besides that
* we're using our own way to determine screen width */ * we're using our own way to determine screen width */
if (curl_GetEnv("COLUMNS") != NULL) colp = curl_GetEnv("COLUMNS");
width = atoi(curl_GetEnv("COLUMNS")); if (colp != NULL) {
width = atoi(colp);
free(colp);
}
else else
width = 79; width = 79;
#else #else

View File

@@ -42,21 +42,25 @@
#include "timeval.h" #include "timeval.h"
#if 0
void ProgressInit(struct UrlData *data, int max);
void ProgressShow(struct UrlData *data,
int point, struct timeval start, struct timeval now, bool force);
void ProgressEnd(struct UrlData *data);
void ProgressMode(int mode);
#endif
typedef enum {
TIMER_NONE,
TIMER_NAMELOOKUP,
TIMER_CONNECT,
TIMER_PRETRANSFER,
TIMER_POSTRANSFER,
TIMER_LAST /* must be last */
} timerid;
void pgrsDone(struct UrlData *data);
void pgrsMode(struct UrlData *data, int mode); void pgrsMode(struct UrlData *data, int mode);
void pgrsStartNow(struct UrlData *data); void pgrsStartNow(struct UrlData *data);
void pgrsSetDownloadSize(struct UrlData *data, double size); void pgrsSetDownloadSize(struct UrlData *data, double size);
void pgrsSetUploadSize(struct UrlData *data, double size); void pgrsSetUploadSize(struct UrlData *data, double size);
void pgrsSetDownloadCounter(struct UrlData *data, double size); void pgrsSetDownloadCounter(struct UrlData *data, double size);
void pgrsSetUploadCounter(struct UrlData *data, double size); void pgrsSetUploadCounter(struct UrlData *data, double size);
void pgrsUpdate(struct UrlData *data); int pgrsUpdate(struct UrlData *data);
void pgrsTime(struct UrlData *data, timerid timer);
/* Don't show progress for sizes smaller than: */ /* Don't show progress for sizes smaller than: */
@@ -77,14 +81,4 @@ void pgrsUpdate(struct UrlData *data);
#define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */ #define PGRS_HEADERS_OUT (1<<7) /* set when the headers have been written */
typedef enum {
TIMER_NONE,
TIMER_NAMELOOKUP,
TIMER_CONNECT,
TIMER_PRETRANSFER,
TIMER_POSTRANSFER,
TIMER_LAST /* must be last */
} timerid;
#endif /* __PROGRESS_H */ #endif /* __PROGRESS_H */

View File

@@ -61,7 +61,7 @@
void infof(struct UrlData *data, char *fmt, ...) void infof(struct UrlData *data, char *fmt, ...)
{ {
va_list ap; va_list ap;
if(data->conf & CONF_VERBOSE) { if(data->bits.verbose) {
va_start(ap, fmt); va_start(ap, fmt);
fputs("* ", data->err); fputs("* ", data->err);
vfprintf(data->err, fmt, ap); vfprintf(data->err, fmt, ap);
@@ -95,7 +95,7 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
va_end(ap); va_end(ap);
if(!s) if(!s)
return 0; /* failure */ return 0; /* failure */
if(data->conf & CONF_VERBOSE) if(data->bits.verbose)
fprintf(data->err, "> %s", s); fprintf(data->err, "> %s", s);
#ifndef USE_SSLEAY #ifndef USE_SSLEAY
bytes_written = swrite(fd, s, strlen(s)); bytes_written = swrite(fd, s, strlen(s));

View File

@@ -57,8 +57,6 @@
#endif #endif
#endif #endif
#ifndef OS #ifndef OS
#ifdef WIN32 #ifdef WIN32
#define OS "win32" #define OS "win32"
@@ -99,6 +97,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#endif #endif
#endif #endif
#if 0
#ifdef HAVE_STRCASECMP #ifdef HAVE_STRCASECMP
#define strnequal(x,y,z) !(strncasecmp)(x,y,z) #define strnequal(x,y,z) !(strncasecmp)(x,y,z)
#define strequal(x,y) !(strcasecmp)(x,y) #define strequal(x,y) !(strcasecmp)(x,y)
@@ -107,6 +106,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#define strnequal(x,y,z) !strnicmp(x,y,z) #define strnequal(x,y,z) !strnicmp(x,y,z)
#define strequal(x,y) !stricmp(x,y) #define strequal(x,y) !stricmp(x,y)
#endif #endif
#endif
/* Below we define four functions. They should /* Below we define four functions. They should
1. close a socket 1. close a socket

View File

@@ -48,7 +48,7 @@
#include "sendf.h" #include "sendf.h"
#include "speedcheck.h" #include "speedcheck.h"
UrgError speedcheck(struct UrlData *data, CURLcode speedcheck(struct UrlData *data,
struct timeval now) struct timeval now)
{ {
static struct timeval keeps_speed; static struct timeval keeps_speed;
@@ -69,13 +69,13 @@ UrgError speedcheck(struct UrlData *data,
"Less than %d bytes/sec transfered the last %d seconds", "Less than %d bytes/sec transfered the last %d seconds",
data->low_speed_limit, data->low_speed_limit,
data->low_speed_time); data->low_speed_time);
return URG_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
} }
} }
else { else {
/* we keep up the required speed all right */ /* we keep up the required speed all right */
keeps_speed = now; keeps_speed = now;
} }
return URG_OK; return CURLE_OK;
} }

View File

@@ -44,7 +44,7 @@
#include "timeval.h" #include "timeval.h"
UrgError speedcheck(struct UrlData *data, CURLcode speedcheck(struct UrlData *data,
struct timeval now); struct timeval now);
#endif #endif

View File

@@ -38,6 +38,12 @@
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
/*
* The original SSL code was written by
* Linas Vepstas <linas@linas.org> and Sampo Kellomaki <sampo@iki.fi>
*/
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>

83
lib/strequal.c Normal file
View File

@@ -0,0 +1,83 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 2000.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
#include "setup.h"
int strequal(const char *first, const char *second)
{
#if defined(HAVE_STRCASECMP)
return !strcasecmp(first, second);
#elif defined(HAVE_STRCMPI)
return !strcmpi(first, second);
#elif defined(HAVE_STRICMP)
return !strcmpi(first, second);
#else
while (*first && *second) {
if (toupper(*first) != toupper(*second)) {
break;
}
first++;
second++;
}
return toupper(*first) == toupper(*second);
#endif
}
int strnequal(const char *first, const char *second, size_t max)
{
#if defined(HAVE_STRCASECMP)
return !strncasecmp(first, second, max);
#elif defined(HAVE_STRCMPI)
return !strncmpi(first, second, max);
#elif defined(HAVE_STRICMP)
return !strnicmp(first, second, max);
#else
while (*first && *second && max) {
if (toupper(*first) != toupper(*second)) {
break;
}
max--;
first++;
second++;
}
return toupper(*first) == toupper(*second);
#endif
}

45
lib/strequal.h Normal file
View File

@@ -0,0 +1,45 @@
#ifndef __STREQUAL_H
#define __STREQUAL_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 2000.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
int strequal(const char *first, const char *second);
int strnequal(const char *first, const char *second, size_t max);
#endif

View File

@@ -225,7 +225,7 @@ static void printoption(struct UrlData *data,
char *fmt; char *fmt;
char *opt; char *opt;
if (data->conf & CONF_VERBOSE) if (data->bits.verbose)
{ {
if (cmd == IAC) if (cmd == IAC)
{ {
@@ -628,7 +628,7 @@ static void printsub(struct UrlData *data,
{ {
int i = 0; int i = 0;
if (data->conf & CONF_VERBOSE) if (data->bits.verbose)
{ {
if (direction) if (direction)
{ {
@@ -871,8 +871,14 @@ void telwrite(struct UrlData *data,
} }
} }
UrgError telnet(struct UrlData *data) CURLcode telnet_done(struct connectdata *conn)
{ {
return CURLE_OK;
}
CURLcode telnet(struct connectdata *conn)
{
struct UrlData *data = conn->data;
int sockfd = data->firstsocket; int sockfd = data->firstsocket;
fd_set readfd; fd_set readfd;
fd_set keepfd; fd_set keepfd;
@@ -931,7 +937,7 @@ UrgError telnet(struct UrlData *data)
telrcv(data, (unsigned char *)buf, nread); telrcv(data, (unsigned char *)buf, nread);
} }
} }
return URG_OK; return CURLE_OK;
} }

View File

@@ -40,6 +40,7 @@
* *
* ------------------------------------------------------------ * ------------------------------------------------------------
****************************************************************************/ ****************************************************************************/
UrgError telnet(struct UrlData *data); CURLcode telnet(struct connectdata *conn);
CURLcode telnet_done(struct connectdata *conn);
#endif #endif

1060
lib/url.c

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,44 @@
#ifndef __URL_H
#define __URL_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <Daniel.Stenberg@haxx.nu>
*
* http://curl.haxx.nu
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
int GetLine(int sockfd, char *buf, struct UrlData *data);
#endif

View File

@@ -67,6 +67,7 @@
#define CURL_DEFAULT_PASSWORD "curl_by_Daniel.Stenberg@haxx.nu" #define CURL_DEFAULT_PASSWORD "curl_by_Daniel.Stenberg@haxx.nu"
#include "cookie.h" #include "cookie.h"
#include "formdata.h"
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
/* SSLeay stuff usually in /usr/local/ssl/include */ /* SSLeay stuff usually in /usr/local/ssl/include */
@@ -87,8 +88,12 @@
#endif #endif
#endif #endif
#include <netinet/in.h>
#include "timeval.h" #include "timeval.h"
/* Download buffer size, keep it fairly big for speed reasons */ /* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50) #define BUFSIZE (1024*50)
@@ -96,6 +101,88 @@
of need. */ of need. */
#define HEADERSIZE 256 #define HEADERSIZE 256
#ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y))
#endif
typedef enum {
STRUCT_NONE,
STRUCT_OPEN,
STRUCT_CONNECT,
STRUCT_LAST
} Handle;
typedef enum {
CONN_NONE, /* illegal state */
CONN_INIT, /* curl_connect() has been called */
CONN_DO, /* curl_do() has been called successfully */
CONN_DONE, /* curl_done() has been called successfully */
CONN_ERROR, /* and error has occurred */
CONN_LAST /* illegal state */
} ConnState;
/*
* The connectdata struct contains all fields and variables that should be
* unique for an entire connection.
*/
struct connectdata {
/**** Fields set when inited and not modified again */
/* To better see what kind of struct that is passed as input, *ALL* publicly
returned handles MUST have this initial 'Handle'. */
Handle handle; /* struct identifier */
struct UrlData *data; /* link to the root CURL struct */
/**** curl_connect() phase fields */
ConnState state; /* for state dependent actions */
long protocol; /* PROT_* flags concerning the protocol set */
#define PROT_MISSING (1<<0)
#define PROT_GOPHER (1<<1)
#define PROT_HTTP (1<<2)
#define PROT_HTTPS (1<<3)
#define PROT_FTP (1<<4)
#define PROT_TELNET (1<<5)
#define PROT_DICT (1<<6)
#define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8)
struct hostent *hp;
struct sockaddr_in serv_addr;
char proto[64];
char gname[256];
char *name;
char path[URL_MAX_LENGTH];
char *ppath;
long bytecount;
struct timeval now;
/* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect);
CURLcode (*curl_done)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run
* after the connect() and everything is done, as a step in the connection.
*/
CURLcode (*curl_connect)(struct connectdata *connect);
/**** curl_get() phase fields */
/* READ stuff */
int sockfd; /* socket to read from or -1 */
int size; /* -1 if unknown at this point */
bool getheader; /* TRUE if header parsing is wanted */
long *bytecountp; /* return number of bytes read or NULL */
/* WRITE stuff */
int writesockfd; /* socket to write to, it may very well be
the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */
};
struct Progress { struct Progress {
long lastshow; /* time() of the last displayed progress meter or NULL to long lastshow; /* time() of the last displayed progress meter or NULL to
force redraw at next call */ force redraw at next call */
@@ -121,42 +208,161 @@ struct Progress {
int httpcode; int httpcode;
}; };
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma;
char *p_accept;
long readbytecount;
long writebytecount;
/* For FORM posting */
struct Form form;
size_t (*storefread)(char *, size_t , size_t , FILE *);
FILE *in;
};
/****************************************************************************
* FTP unique setup
***************************************************************************/
struct FTP {
long *bytecountp;
char *user;
char *passwd;
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
};
struct Configbits {
bool ftp_append;
bool ftp_ascii;
bool ftp_list_only;
bool ftp_use_port;
bool hide_progress;
bool http_fail_on_error;
bool http_follow_location;
bool http_formpost;
bool http_include_header;
bool http_post;
bool http_put;
bool http_set_referer;
bool httpproxy;
bool mute;
bool no_body;
bool proxy_user_passwd;
bool proxystringalloc; /* the http proxy string is malloc()'ed */
bool set_port;
bool set_range;
bool upload;
bool use_netrc;
bool user_passwd;
bool verbose;
};
typedef size_t (*progress_callback)(void *clientp,
size_t dltotal,
size_t dlnow,
size_t ultotal,
size_t ulnow);
typedef size_t (*write_callback)(char *buffer,
size_t size,
size_t nitems,
FILE *outstream);
typedef size_t (*read_callback)(char *buffer,
size_t size,
size_t nitems,
FILE *instream);
/* What type of interface that intiated this struct */
typedef enum {
CURLI_NONE,
CURLI_EASY,
CURLI_NORMAL,
CURLI_LAST
} CurlInterface;
/*
* As of April 11, 2000 we're now trying to split up the urldata struct in
* three different parts:
*
* (Global)
* 1 - No matter how many hosts and requests that are being performed, this
* goes for all of them.
*
* (Session)
* 2 - Host and protocol-specific. No matter if we do several transfers to and
* from this host, these variables stay the same.
*
* (Request)
* 3 - Request-specific. Variables that are of interest for this particular
* transfer being made right now.
*
*/
struct UrlData { struct UrlData {
Handle handle; /* struct identifier */
CurlInterface interf; /* created by WHAT interface? */
/*************** Global - specific items ************/
FILE *err; /* the stderr writes goes here */
char *errorbuffer; /* store failure messages in here */
/*************** Session - specific items ************/
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */
char *proxyuserpwd; /* Proxy <user:password>, if used */
/*************** Request - specific items ************/
union {
struct HTTP *http;
struct HTTP *gopher; /* alias, just for the sake of being more readable */
struct HTTP *https; /* alias, just for the sake of being more readable */
struct FTP *ftp;
#if 0 /* no need for special ones for these: */
struct TELNET *telnet;
struct FILE *file;
struct LDAP *ldap;
struct DICT *dict;
#endif
void *generic;
} proto;
FILE *out; /* the fetched file goes here */ FILE *out; /* the fetched file goes here */
FILE *in; /* the uploaded file is read from here */ FILE *in; /* the uploaded file is read from here */
FILE *err; /* the stderr writes goes here */
FILE *writeheader; /* write the header to this is non-NULL */ FILE *writeheader; /* write the header to this is non-NULL */
char *url; /* what to get */ char *url; /* what to get */
char *freethis; /* if non-NULL, an allocated string for the URL */ char *freethis; /* if non-NULL, an allocated string for the URL */
char *hostname; /* hostname to contect, as parsed from url */ char *hostname; /* hostname to connect, as parsed from url */
unsigned short port; /* which port to use (if non-protocol bind) set unsigned short port; /* which port to use (if non-protocol bind) set
CONF_PORT to use this */ CONF_PORT to use this */
unsigned short remote_port; /* what remote port to connect to, not the proxy unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */ port! */
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */ struct Configbits bits; /* new-style (v7) flag data */
long conf; /* configure flags */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
char *proxyuserpwd; /* Proxy <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on char *range; /* range, if used. See README for detailed specification on
this syntax. */ this syntax. */
char *postfields; /* if POST, set the fields' values here */ char *postfields; /* if POST, set the fields' values here */
char *referer; char *referer;
char *errorbuffer; /* store failure messages in here */
char *useragent; /* User-Agent string */ char *useragent; /* User-Agent string */
char *ftpport; /* port to send with the PORT command */ char *ftpport; /* port to send with the PORT command */
/* function that stores the output:*/ /* function that stores the output:*/
size_t (*fwrite)(char *buffer, write_callback fwrite;
size_t size,
size_t nitems,
FILE *outstream);
/* function that reads the input:*/ /* function that reads the input:*/
size_t (*fread)(char *buffer, read_callback fread;
size_t size,
size_t nitems, /* function that wants progress information */
FILE *outstream); progress_callback fprogress;
void *progress_client; /* pointer to pass to the progress callback */
long timeout; /* in seconds, 0 means no timeout */ long timeout; /* in seconds, 0 means no timeout */
long infilesize; /* size of file to upload, -1 means unknown */ long infilesize; /* size of file to upload, -1 means unknown */

View File

@@ -58,7 +58,7 @@ char *curl_version(void)
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
#if (SSLEAY_VERSION_NUMBER >= 0x900000) #if (SSLEAY_VERSION_NUMBER >= 0x900000)
sprintf(ptr, " (SSL %x.%x.%x)", sprintf(ptr, " (SSL %lx.%lx.%lx)",
(SSLEAY_VERSION_NUMBER>>28)&0xff, (SSLEAY_VERSION_NUMBER>>28)&0xff,
(SSLEAY_VERSION_NUMBER>>20)&0xff, (SSLEAY_VERSION_NUMBER>>20)&0xff,
(SSLEAY_VERSION_NUMBER>>12)&0xf); (SSLEAY_VERSION_NUMBER>>12)&0xf);

View File

@@ -41,6 +41,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "strequal.h"
#include "writeout.h" #include "writeout.h"
typedef enum { typedef enum {

View File

@@ -1,3 +1,5 @@
#ifndef __WRITEOUT_H
#define __WRITEOUT_H
/***************************************************************************** /*****************************************************************************
* _ _ ____ _ * _ _ ____ _
* Project ___| | | | _ \| | * Project ___| | | | _ \| |
@@ -41,3 +43,5 @@
#include "urldata.h" #include "urldata.h"
void WriteOut(struct UrlData *data); void WriteOut(struct UrlData *data);
#endif

13
maketgz
View File

@@ -7,15 +7,24 @@ read version
libversion="$version" libversion="$version"
#
# Now we have a section to get the major, minor and patch number from the
# full version string. We create a single hexadecimal number from it '0xMMmmpp'
#
perl='$a=<STDIN>;@p=split("\\.",$a);for(0..2){printf STDOUT ("%02x",$p[0+$_]);}';
numeric=`echo $libversion | perl -e "$perl"`
echo "CURL version number?" echo "CURL version number?"
read curlversion read curlversion
HEADER=include/curl/curl.h HEADER=include/curl/curl.h
CHEADER=src/version.h CHEADER=src/version.h
# Replace version number in header file: # Replace version number in header file:
sed 's/#define LIBCURL_VERSION.*/#define LIBCURL_VERSION "'$libversion'"/g' $HEADER >$HEADER.new sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
-e 's/^#define LIBCURL_VERSION_NUM .*/#define LIBCURL_VERSION_NUM 0x'$numeric'/g' \
$HEADER >$HEADER.new
# Save old header file # Save old header file
cp -p $HEADER $HEADER.old cp -p $HEADER $HEADER.old

View File

@@ -4,7 +4,7 @@
# Some flags needed when trying to cause warnings ;-) # Some flags needed when trying to cause warnings ;-)
# CFLAGS = -Wall -pedantic # CFLAGS = -Wall -pedantic
CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS #CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS
INCLUDES = -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/include
@@ -21,7 +21,11 @@ EXTRA_DIST = mkhelp.pl Makefile.vc6
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
MANPAGE=$(top_srcdir)/docs/curl.1
README=$(top_srcdir)/docs/README.curl
MKHELP=$(top_srcdir)/src/mkhelp.pl
# This generates the hugehelp.c file # This generates the hugehelp.c file
hugehelp.c: $(top_srcdir)/README.curl $(top_srcdir)/curl.1 mkhelp.pl hugehelp.c: $(README) $(MANPAGE) mkhelp.pl
rm -f hugehelp.c rm -f hugehelp.c
$(NROFF) -man $(top_srcdir)/curl.1 | $(PERL) $(top_srcdir)/src/mkhelp.pl $(top_srcdir)/README.curl > hugehelp.c $(NROFF) -man $(MANPAGE) | $(PERL) $(MKHELP) $(README) > hugehelp.c

View File

@@ -9,7 +9,7 @@
CC = gcc CC = gcc
STRIP = strip -s STRIP = strip -s
OPENSSL_PATH = ../../openssl-0.9.4 OPENSSL_PATH = ../../openssl-0.9.5a
# We may need these someday # We may need these someday
# PERL = perl # PERL = perl
@@ -19,7 +19,7 @@ OPENSSL_PATH = ../../openssl-0.9.4
## Nothing more to do below this line! ## Nothing more to do below this line!
INCLUDES = -I. -I.. -I../include INCLUDES = -I. -I.. -I../include
CFLAGS = -g -O2 -DGLOBURL -DCURL_SEPARATORS CFLAGS = -g -O2
LDFLAGS = LDFLAGS =
COMPILE = $(CC) $(INCLUDES) $(CFLAGS) COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@

View File

@@ -2,6 +2,9 @@
/* Define if you have the strcasecmp function. */ /* Define if you have the strcasecmp function. */
/*#define HAVE_STRCASECMP 1*/ /*#define HAVE_STRCASECMP 1*/
/* Define if you have the stricmp function. */
#define HAVE_STRICMP 1
/* Define cpu-machine-OS */ /* Define cpu-machine-OS */
#define OS "win32" #define OS "win32"

File diff suppressed because it is too large Load Diff

View File

@@ -46,17 +46,27 @@
#include <ctype.h> #include <ctype.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h> /* new for v7 */
#include <curl/easy.h> /* new for v7 */
#include <curl/mprintf.h> #include <curl/mprintf.h>
#include "../lib/getdate.h" #include "../lib/getdate.h"
#ifdef GLOBURL
#include "urlglob.h" #include "urlglob.h"
#define CURLseparator "--_curl_--" #define CURLseparator "--_curl_--"
#define MIMEseparator "_curl_" #define MIMEseparator "_curl_"
#endif
/* This define make use of the "Curlseparator" as opposed to the
MIMEseparator. We might add support for the latter one in the
future, and that's why this is left in the source. */
#define CURL_SEPARATORS
/* This is now designed to have its own local setup.h */ /* This is now designed to have its own local setup.h */
#include "setup.h" #include "setup.h"
#ifdef WIN32
#include <winsock.h>
#endif
#include "version.h" #include "version.h"
#ifdef HAVE_IO_H /* typical win32 habit */ #ifdef HAVE_IO_H /* typical win32 habit */
@@ -67,6 +77,25 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
/* Just a set of bits */
#define CONF_DEFAULT 0
#define CONF_VERBOSE (1<<5) /* talk a lot */
#define CONF_HEADER (1<<8) /* throw the header out too */
#define CONF_NOPROGRESS (1<<10) /* shut off the progress meter */
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */
#define CONF_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
#define CONF_UPLOAD (1<<14) /* this is an upload */
#define CONF_POST (1<<15) /* HTTP POST method */
#define CONF_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
#define CONF_FTPASCII (1<<24) /* use TYPE A for transfer */
#define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */
#define CONF_PUT (1<<27) /* PUT the input file */
#define CONF_MUTE (1<<28) /* force NOPROGRESS */
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
/* Ultrix doesn't have strdup(), so make a quick clone: */ /* Ultrix doesn't have strdup(), so make a quick clone: */
char *strdup(char *str) char *strdup(char *str)
@@ -88,6 +117,72 @@ char *strdup(char *str)
extern void hugehelp(void); extern void hugehelp(void);
/***********************************************************************
* Start with some silly functions to make win32-systems survive
***********************************************************************/
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
static void win32_cleanup(void)
{
WSACleanup();
}
static CURLcode win32_init(void)
{
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(1, 1);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
return CURLE_FAILED_INIT;
/* Confirm that the Windows Sockets DLL supports 1.1.*/
/* Note that if the DLL supports versions greater */
/* than 1.1 in addition to 1.1, it will still return */
/* 1.1 in wVersion since that is the version we */
/* requested. */
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
/* Tell the user that we couldn't find a useable */
/* winsock.dll. */
WSACleanup();
return CURLE_FAILED_INIT;
}
return CURLE_OK;
}
/* The Windows Sockets DLL is acceptable. Proceed. */
#else
static CURLcode win32_init(void) { return CURLE_OK; }
#define win32_cleanup()
#endif
/*
* This is the main global constructor for the app. Call this before
* _any_ libcurl usage. If this fails, *NO* libcurl functions may be
* used, or havoc may be the result.
*/
CURLcode main_init(void)
{
return win32_init();
}
/*
* This is the main global destructor for the app. Call this after
* _all_ libcurl usage is done.
*/
void main_free(void)
{
win32_cleanup();
}
static void helpf(char *fmt, ...) static void helpf(char *fmt, ...)
{ {
va_list ap; va_list ap;
@@ -227,7 +322,10 @@ static void GetStr(char **string,
{ {
if(*string) if(*string)
free(*string); free(*string);
if(value && *value)
*string = strdup(value); *string = strdup(value);
else
*string = NULL;
} }
static char *file2string(FILE *file) static char *file2string(FILE *file)
@@ -350,7 +448,7 @@ static int getparameter(char *flag, /* f or -long-flag */
if(parse) { if(parse) {
/* this is the second match, we can't continue! */ /* this is the second match, we can't continue! */
helpf("option --%s is ambiguous\n", &flag[1]); helpf("option --%s is ambiguous\n", &flag[1]);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
parse = aliases[j].letter; parse = aliases[j].letter;
hit = j; hit = j;
@@ -358,7 +456,7 @@ static int getparameter(char *flag, /* f or -long-flag */
} }
if(hit < 0) { if(hit < 0) {
helpf("unknown option -%s.\n", flag); helpf("unknown option -%s.\n", flag);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
} }
else { else {
@@ -384,18 +482,18 @@ static int getparameter(char *flag, /* f or -long-flag */
} }
if(hit < 0) { if(hit < 0) {
helpf("unknown option -%c.\n", letter); helpf("unknown option -%c.\n", letter);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
} }
if(hit < 0) { if(hit < 0) {
helpf("unknown option -%c.\n", letter); helpf("unknown option -%c.\n", letter);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
if(!nextarg && aliases[hit].extraparam) { if(!nextarg && aliases[hit].extraparam) {
helpf("option -%s/--%s requires an extra argument!\n", helpf("option -%s/--%s requires an extra argument!\n",
aliases[hit].letter, aliases[hit].letter,
aliases[hit].lname); aliases[hit].lname);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
else if(nextarg && aliases[hit].extraparam) else if(nextarg && aliases[hit].extraparam)
*usedarg = TRUE; /* mark it as used */ *usedarg = TRUE; /* mark it as used */
@@ -421,7 +519,7 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
} }
now=time(NULL); now=time(NULL);
config->condtime=get_date(nextarg, &now); config->condtime=curl_getdate(nextarg, &now);
if(-1 == config->condtime) { if(-1 == config->condtime) {
/* now let's see if it is a file name to get the time from instead! */ /* now let's see if it is a file name to get the time from instead! */
struct stat statbuf; struct stat statbuf;
@@ -516,7 +614,6 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
case 'e': case 'e':
GetStr(&config->referer, nextarg); GetStr(&config->referer, nextarg);
config->conf |= CONF_REFERER;
break; break;
case 'E': case 'E':
{ {
@@ -540,13 +637,12 @@ static int getparameter(char *flag, /* f or -long-flag */
if(curl_FormParse(nextarg, if(curl_FormParse(nextarg,
&config->httppost, &config->httppost,
&config->last_post)) &config->last_post))
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
config->conf |= CONF_HTTPPOST; /* no toggle, OR! */
break; break;
case 'h': /* h for help */ case 'h': /* h for help */
help(); help();
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
case 'H': case 'H':
head = (struct HttpHeader *)malloc(sizeof(struct HttpHeader)); head = (struct HttpHeader *)malloc(sizeof(struct HttpHeader));
if(head) { if(head) {
@@ -589,7 +685,7 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
case 'M': /* M for manual, huge help */ case 'M': /* M for manual, huge help */
hugehelp(); hugehelp();
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
case 'n': case 'n':
/* pick info from .netrc, if this is used for http, curl will /* pick info from .netrc, if this is used for http, curl will
automatically enfore user+password with the request */ automatically enfore user+password with the request */
@@ -613,7 +709,6 @@ static int getparameter(char *flag, /* f or -long-flag */
this will make us try to get the "default" address. this will make us try to get the "default" address.
NOTE: this is a changed behaviour since the released 4.1! NOTE: this is a changed behaviour since the released 4.1!
*/ */
config->conf |= CONF_FTPPORT;
GetStr(&config->ftpport, nextarg); GetStr(&config->ftpport, nextarg);
break; break;
#if 0 #if 0
@@ -642,7 +737,6 @@ static int getparameter(char *flag, /* f or -long-flag */
case 'r': case 'r':
/* byte range requested */ /* byte range requested */
GetStr(&config->range, nextarg); GetStr(&config->range, nextarg);
config->conf |= CONF_RANGE;
break; break;
case 's': case 's':
/* don't show progress meter, don't show errors : */ /* don't show progress meter, don't show errors : */
@@ -665,19 +759,17 @@ static int getparameter(char *flag, /* f or -long-flag */
case 'u': case 'u':
/* user:password */ /* user:password */
GetStr(&config->userpwd, nextarg); GetStr(&config->userpwd, nextarg);
config->conf |= CONF_USERPWD;
break; break;
case 'U': case 'U':
/* Proxy user:password */ /* Proxy user:password */
GetStr(&config->proxyuserpwd, nextarg); GetStr(&config->proxyuserpwd, nextarg);
config->conf |= CONF_PROXYUSERPWD;
break; break;
case 'v': case 'v':
config->conf ^= CONF_VERBOSE; /* talk a lot */ config->conf ^= CONF_VERBOSE; /* talk a lot */
break; break;
case 'V': case 'V':
printf(CURL_ID "%s\n", curl_version()); printf(CURL_ID "%s\n", curl_version());
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
case 'w': case 'w':
/* get the output string */ /* get the output string */
if('@' == *nextarg) { if('@' == *nextarg) {
@@ -698,14 +790,7 @@ static int getparameter(char *flag, /* f or -long-flag */
break; break;
case 'x': case 'x':
/* proxy */ /* proxy */
if(!*nextarg) {
/* disable proxy when no proxy is given */
config->conf &= ~CONF_PROXY;
}
else {
config->conf |= CONF_PROXY;
GetStr(&config->proxy, nextarg); GetStr(&config->proxy, nextarg);
}
break; break;
case 'X': case 'X':
/* HTTP request */ /* HTTP request */
@@ -729,13 +814,13 @@ static int getparameter(char *flag, /* f or -long-flag */
helpf("Unknown option '%c'\n", letter); helpf("Unknown option '%c'\n", letter);
else else
helpf("Unknown option\n"); /* short help blurb */ helpf("Unknown option\n"); /* short help blurb */
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
hit = -1; hit = -1;
} while(*++parse && !*usedarg); } while(*++parse && !*usedarg);
return URG_OK; return CURLE_OK;
} }
@@ -747,16 +832,21 @@ static int parseconfig(char *filename,
char configbuffer[4096]; char configbuffer[4096];
char filebuffer[256]; char filebuffer[256];
bool usedarg; bool usedarg;
char *home=NULL;
if(!filename || !*filename) { if(!filename || !*filename) {
/* NULL or no file name attempts to load .curlrc from the homedir! */ /* NULL or no file name attempts to load .curlrc from the homedir! */
#define CURLRC DOT_CHAR "curlrc" #define CURLRC DOT_CHAR "curlrc"
char *home = curl_GetEnv("HOME"); /* portable environment reader */ home = curl_GetEnv("HOME"); /* portable environment reader */
if(!home || (strlen(home)>(sizeof(filebuffer)-strlen(CURLRC)))) if(!home)
return URG_OK; return CURLE_OK;
if(strlen(home)>(sizeof(filebuffer)-strlen(CURLRC))) {
free(home);
return CURLE_OK;
}
sprintf(filebuffer, "%s%s%s", home, DIR_CHAR, CURLRC); sprintf(filebuffer, "%s%s%s", home, DIR_CHAR, CURLRC);
@@ -824,7 +914,9 @@ static int parseconfig(char *filename,
if(file != stdin) if(file != stdin)
fclose(file); fclose(file);
} }
return URG_OK; if(home)
free(home);
return CURLE_OK;
} }
struct OutStruct { struct OutStruct {
@@ -856,18 +948,17 @@ int my_fwrite(void *buffer, size_t size, size_t nmemb, FILE *stream)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char errorbuffer[URLGET_ERROR_SIZE]; char errorbuffer[CURL_ERROR_SIZE];
struct OutStruct outs; struct OutStruct outs;
struct OutStruct heads; struct OutStruct heads;
char *url = NULL; char *url = NULL;
#ifdef GLOBURL
URLGlob *urls; URLGlob *urls;
int urlnum; int urlnum;
char *outfiles = NULL; char *outfiles = NULL;
int separator = 0; int separator = 0;
#endif
FILE *infd = stdin; FILE *infd = stdin;
FILE *headerfilep = NULL; FILE *headerfilep = NULL;
@@ -875,17 +966,11 @@ int main(int argc, char *argv[])
int infilesize=-1; /* -1 means unknown */ int infilesize=-1; /* -1 means unknown */
bool stillflags=TRUE; bool stillflags=TRUE;
int res=URG_OK; CURL *curl;
int res=CURLE_OK;
int i; int i;
outs.stream = stdout; outs.stream = stdout;
#ifdef __EMX__
/* 20000318 mgs
* we call _fsetmode to fix the problem with fwrite converting newline
* characters (you get mangled text files, and corrupted binary files when
* you download to stdout and redirect it to a file). */
_fsetmode(stdout, "b");
#endif
memset(&config, 0, sizeof(struct Configurable)); memset(&config, 0, sizeof(struct Configurable));
@@ -919,7 +1004,7 @@ int main(int argc, char *argv[])
if ((argc < 2) && !config.url) { if ((argc < 2) && !config.url) {
helpf(NULL); helpf(NULL);
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
/* Parse options */ /* Parse options */
@@ -952,7 +1037,7 @@ int main(int argc, char *argv[])
else { else {
if(url) { if(url) {
helpf("only one URL is supported!\n"); helpf("only one URL is supported!\n");
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
url = argv[i]; url = argv[i];
} }
@@ -965,15 +1050,18 @@ int main(int argc, char *argv[])
if(!url) { if(!url) {
helpf("no URL specified!\n"); helpf("no URL specified!\n");
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
#if 0 #if 0
fprintf(stderr, "URL: %s PROXY: %s\n", url, config.proxy?config.proxy:"none"); fprintf(stderr, "URL: %s PROXY: %s\n", url, config.proxy?config.proxy:"none");
#endif #endif
#ifdef GLOBURL /* expand '{...}' and '[...]' expressions and return total number of URLs
urlnum = glob_url(&urls, url); /* expand '{...}' and '[...]' expressions and return in pattern set */
total number of URLs in pattern set */ res = glob_url(&urls, url, &urlnum);
if(res != CURLE_OK)
return res;
outfiles = config.outfile; /* save outfile pattern befor expansion */ outfiles = config.outfile; /* save outfile pattern befor expansion */
if (!outfiles && !config.remotefile && urlnum > 1) { if (!outfiles && !config.remotefile && urlnum > 1) {
#ifdef CURL_SEPARATORS #ifdef CURL_SEPARATORS
@@ -990,11 +1078,10 @@ int main(int argc, char *argv[])
for (i = 0; (url = next_url(urls)); ++i) { for (i = 0; (url = next_url(urls)); ++i) {
if (outfiles) if (outfiles)
config.outfile = strdup(outfiles); config.outfile = strdup(outfiles);
#endif
if(config.outfile && config.infile) { if(config.outfile && config.infile) {
helpf("you can't both upload and download!\n"); helpf("you can't both upload and download!\n");
return URG_FAILED_INIT; return CURLE_FAILED_INIT;
} }
if (config.outfile || config.remotefile) { if (config.outfile || config.remotefile) {
@@ -1013,13 +1100,11 @@ int main(int argc, char *argv[])
config.outfile = strrchr(config.outfile, '/'); config.outfile = strrchr(config.outfile, '/');
if(!config.outfile || !strlen(++config.outfile)) { if(!config.outfile || !strlen(++config.outfile)) {
helpf("Remote file name has no length!\n"); helpf("Remote file name has no length!\n");
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
#ifdef GLOBURL
else /* fill '#1' ... '#9' terms from URL pattern */ else /* fill '#1' ... '#9' terms from URL pattern */
config.outfile = match_url(config.outfile, *urls); config.outfile = match_url(config.outfile, *urls);
#endif
if((0 == config.resume_from) && config.use_resume) { if((0 == config.resume_from) && config.use_resume) {
/* we're told to continue where we are now, then we get the size of the /* we're told to continue where we are now, then we get the size of the
@@ -1038,7 +1123,7 @@ int main(int argc, char *argv[])
outs.stream=(FILE *) fopen(config.outfile, config.resume_from?"ab":"wb"); outs.stream=(FILE *) fopen(config.outfile, config.resume_from?"ab":"wb");
if (!outs.stream) { if (!outs.stream) {
helpf("Can't open '%s'!\n", config.outfile); helpf("Can't open '%s'!\n", config.outfile);
return URG_WRITE_ERROR; return CURLE_WRITE_ERROR;
} }
} }
else { else {
@@ -1065,7 +1150,7 @@ int main(int argc, char *argv[])
urlbuffer=(char *)malloc(strlen(url) + strlen(config.infile) + 3); urlbuffer=(char *)malloc(strlen(url) + strlen(config.infile) + 3);
if(!urlbuffer) { if(!urlbuffer) {
helpf("out of memory\n"); helpf("out of memory\n");
return URG_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
if(ptr) if(ptr)
/* there is a trailing slash on the URL */ /* there is a trailing slash on the URL */
@@ -1080,7 +1165,7 @@ int main(int argc, char *argv[])
infd=(FILE *) fopen(config.infile, "rb"); infd=(FILE *) fopen(config.infile, "rb");
if (!infd || stat(config.infile, &fileinfo)) { if (!infd || stat(config.infile, &fileinfo)) {
helpf("Can't open '%s'!\n", config.infile); helpf("Can't open '%s'!\n", config.infile);
return URG_READ_ERROR; return CURLE_READ_ERROR;
} }
infilesize=fileinfo.st_size; infilesize=fileinfo.st_size;
@@ -1108,7 +1193,7 @@ int main(int argc, char *argv[])
we switch off the progress meter */ we switch off the progress meter */
config.conf |= CONF_NOPROGRESS; config.conf |= CONF_NOPROGRESS;
#ifdef GLOBURL
if (urlnum > 1) { if (urlnum > 1) {
fprintf(stderr, "\n[%d/%d]: %s --> %s\n", i+1, urlnum, url, config.outfile ? config.outfile : "<stdout>"); fprintf(stderr, "\n[%d/%d]: %s --> %s\n", i+1, urlnum, url, config.outfile ? config.outfile : "<stdout>");
if (separator) { if (separator) {
@@ -1121,50 +1206,127 @@ int main(int argc, char *argv[])
#endif #endif
} }
} }
#endif
if(!config.errors) if(!config.errors)
config.errors = stderr; config.errors = stderr;
res = curl_urlget(URGTAG_FILE, (FILE *)&outs, /* where to store */ main_init();
URGTAG_WRITEFUNCTION, my_fwrite, /* what call to write */
URGTAG_INFILE, infd, /* for uploads */ #if 0
URGTAG_INFILESIZE, infilesize, /* size of uploaded file */ /* This is code left from the pre-v7 time, left here mainly as a reminder
URGTAG_URL, url, /* what to fetch */ and possibly as a warning! ;-) */
URGTAG_PROXY, config.proxy, /* proxy to use */
URGTAG_FLAGS, config.conf, /* flags */ res = curl_urlget(CURLOPT_FILE, (FILE *)&outs, /* where to store */
URGTAG_USERPWD, config.userpwd, /* user + passwd */ CURLOPT_WRITEFUNCTION, my_fwrite, /* what call to write */
URGTAG_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */ CURLOPT_INFILE, infd, /* for uploads */
URGTAG_RANGE, config.range, /* range of document */ CURLOPT_INFILESIZE, infilesize, /* size of uploaded file */
URGTAG_ERRORBUFFER, errorbuffer, CURLOPT_URL, url, /* what to fetch */
URGTAG_TIMEOUT, config.timeout, CURLOPT_PROXY, config.proxy, /* proxy to use */
URGTAG_POSTFIELDS, config.postfields, CURLOPT_FLAGS, config.conf, /* flags */
URGTAG_REFERER, config.referer, CURLOPT_USERPWD, config.userpwd, /* user + passwd */
URGTAG_USERAGENT, config.useragent, CURLOPT_PROXYUSERPWD, config.proxyuserpwd, /* Proxy user + passwd */
URGTAG_FTPPORT, config.ftpport, CURLOPT_RANGE, config.range, /* range of document */
URGTAG_LOW_SPEED_LIMIT, config.low_speed_limit, CURLOPT_ERRORBUFFER, errorbuffer,
URGTAG_LOW_SPEED_TIME, config.low_speed_time, CURLOPT_TIMEOUT, config.timeout,
URGTAG_RESUME_FROM, config.use_resume?config.resume_from:0, CURLOPT_POSTFIELDS, config.postfields,
URGTAG_COOKIE, config.cookie, CURLOPT_REFERER, config.referer,
URGTAG_HTTPHEADER, config.headers, CURLOPT_USERAGENT, config.useragent,
URGTAG_HTTPPOST, config.httppost, CURLOPT_FTPPORT, config.ftpport,
URGTAG_SSLCERT, config.cert, CURLOPT_LOW_SPEED_LIMIT, config.low_speed_limit,
URGTAG_SSLCERTPASSWD, config.cert_passwd, CURLOPT_LOW_SPEED_TIME, config.low_speed_time,
URGTAG_CRLF, config.crlf, CURLOPT_RESUME_FROM, config.use_resume?config.resume_from:0,
URGTAG_QUOTE, config.quote, CURLOPT_COOKIE, config.cookie,
URGTAG_POSTQUOTE, config.postquote, CURLOPT_HTTPHEADER, config.headers,
URGTAG_WRITEHEADER, config.headerfile?&heads:NULL, CURLOPT_HTTPPOST, config.httppost,
URGTAG_COOKIEFILE, config.cookiefile, CURLOPT_SSLCERT, config.cert,
URGTAG_SSLVERSION, config.ssl_version, CURLOPT_SSLCERTPASSWD, config.cert_passwd,
URGTAG_TIMECONDITION, config.timecond, CURLOPT_CRLF, config.crlf,
URGTAG_TIMEVALUE, config.condtime, CURLOPT_QUOTE, config.quote,
URGTAG_CUSTOMREQUEST, config.customrequest, CURLOPT_POSTQUOTE, config.postquote,
URGTAG_STDERR, config.errors, CURLOPT_WRITEHEADER, config.headerfile?&heads:NULL,
URGTAG_PROGRESSMODE, config.progressmode, CURLOPT_COOKIEFILE, config.cookiefile,
URGTAG_WRITEINFO, config.writeout, CURLOPT_SSLVERSION, config.ssl_version,
URGTAG_DONE); /* always terminate the list of tags */ CURLOPT_TIMECONDITION, config.timecond,
if((res!=URG_OK) && config.showerror) CURLOPT_TIMEVALUE, config.condtime,
CURLOPT_CUSTOMREQUEST, config.customrequest,
CURLOPT_STDERR, config.errors,
CURLOPT_PROGRESSMODE, config.progressmode,
CURLOPT_WRITEINFO, config.writeout,
CURLOPT_DONE); /* always terminate the list of tags */
#endif
/* The new, v7-style easy-interface! */
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_FILE, (FILE *)&outs); /* where to store */
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_fwrite); /* what call to write */
curl_easy_setopt(curl, CURLOPT_INFILE, infd); /* for uploads */
curl_easy_setopt(curl, CURLOPT_INFILESIZE, infilesize); /* size of uploaded file */
curl_easy_setopt(curl, CURLOPT_URL, url); /* what to fetch */
curl_easy_setopt(curl, CURLOPT_PROXY, config.proxy); /* proxy to use */
#if 0
curl_easy_setopt(curl, CURLOPT_FLAGS, config.conf); /* flags */
#else
curl_easy_setopt(curl, CURLOPT_VERBOSE, config.conf&CONF_VERBOSE);
curl_easy_setopt(curl, CURLOPT_HEADER, config.conf&CONF_HEADER);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, config.conf&CONF_NOPROGRESS);
curl_easy_setopt(curl, CURLOPT_NOBODY, config.conf&CONF_NOBODY);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, config.conf&CONF_FAILONERROR);
curl_easy_setopt(curl, CURLOPT_UPLOAD, config.conf&CONF_UPLOAD);
curl_easy_setopt(curl, CURLOPT_POST, config.conf&CONF_POST);
curl_easy_setopt(curl, CURLOPT_FTPLISTONLY, config.conf&CONF_FTPLISTONLY);
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config.conf&CONF_FTPAPPEND);
curl_easy_setopt(curl, CURLOPT_NETRC, config.conf&CONF_NETRC);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, config.conf&CONF_FOLLOWLOCATION);
curl_easy_setopt(curl, CURLOPT_FTPASCII, config.conf&CONF_FTPASCII);
curl_easy_setopt(curl, CURLOPT_PUT, config.conf&CONF_PUT);
curl_easy_setopt(curl, CURLOPT_MUTE, config.conf&CONF_MUTE);
#endif
curl_easy_setopt(curl, CURLOPT_USERPWD, config.userpwd); /* user + passwd */
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config.proxyuserpwd); /* Proxy user + passwd */
curl_easy_setopt(curl, CURLOPT_RANGE, config.range); /* range of document */
curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, errorbuffer);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, config.timeout);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, config.postfields);
curl_easy_setopt(curl, CURLOPT_REFERER, config.referer);
curl_easy_setopt(curl, CURLOPT_USERAGENT, config.useragent);
curl_easy_setopt(curl, CURLOPT_FTPPORT, config.ftpport);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, config.low_speed_limit);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, config.low_speed_time);
curl_easy_setopt(curl, CURLOPT_RESUME_FROM, config.use_resume?config.resume_from:0);
curl_easy_setopt(curl, CURLOPT_COOKIE, config.cookie);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, config.headers);
curl_easy_setopt(curl, CURLOPT_HTTPPOST, config.httppost);
curl_easy_setopt(curl, CURLOPT_SSLCERT, config.cert);
curl_easy_setopt(curl, CURLOPT_SSLCERTPASSWD, config.cert_passwd);
curl_easy_setopt(curl, CURLOPT_CRLF, config.crlf);
curl_easy_setopt(curl, CURLOPT_QUOTE, config.quote);
curl_easy_setopt(curl, CURLOPT_POSTQUOTE, config.postquote);
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, config.headerfile?&heads:NULL);
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, config.cookiefile);
curl_easy_setopt(curl, CURLOPT_SSLVERSION, config.ssl_version);
curl_easy_setopt(curl, CURLOPT_TIMECONDITION, config.timecond);
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config.condtime);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config.customrequest);
curl_easy_setopt(curl, CURLOPT_STDERR, config.errors);
curl_easy_setopt(curl, CURLOPT_PROGRESSMODE, config.progressmode);
curl_easy_setopt(curl, CURLOPT_WRITEINFO, config.writeout);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
if((res!=CURLE_OK) && config.showerror)
fprintf(config.errors, "curl: (%d) %s\n", res, errorbuffer); fprintf(config.errors, "curl: (%d) %s\n", res, errorbuffer);
}
else
fprintf(config.errors, "curl: failed to init libcurl!\n");
main_free();
if((config.errors != stderr) && if((config.errors != stderr) &&
(config.errors != stdout)) (config.errors != stdout))
@@ -1186,7 +1348,6 @@ int main(int argc, char *argv[])
if(config.url) if(config.url)
free(config.url); free(config.url);
#ifdef GLOBURL
if(url) if(url)
free(url); free(url);
if(config.outfile && !config.remotefile) if(config.outfile && !config.remotefile)
@@ -1195,7 +1356,6 @@ int main(int argc, char *argv[])
#ifdef MIME_SEPARATORS #ifdef MIME_SEPARATORS
if (separator) if (separator)
printf("--%s--\n", MIMEseparator); printf("--%s--\n", MIMEseparator);
#endif
#endif #endif
curl_slist_free_all(config.quote); /* the checks for config.quote == NULL */ curl_slist_free_all(config.quote); /* the checks for config.quote == NULL */

View File

@@ -69,16 +69,25 @@ print "void hugehelp(void)\n";
print "{\n"; print "{\n";
print "puts (\n"; print "puts (\n";
$outsize=0;
for(@out) { for(@out) {
chop; chop;
$new = $_; $new = $_;
$outsize += length($new);
$new =~ s/\\/\\\\/g; $new =~ s/\\/\\\\/g;
$new =~ s/\"/\\\"/g; $new =~ s/\"/\\\"/g;
printf("\"%s\\n\"\n", $new); printf("\"%s\\n\"\n", $new);
if($outsize > 10000) {
# terminate and make another puts() call here
print ");\n puts(\n";
$outsize=0;
}
} }
print " ) ;\n}\n" print " ) ;\n}\n"

View File

@@ -69,18 +69,18 @@ int glob_set(char *pattern, int pos) {
switch (*pattern) { switch (*pattern) {
case '\0': /* URL ended while set was still open */ case '\0': /* URL ended while set was still open */
printf("error: unmatched brace at pos %d\n", pos); printf("error: unmatched brace at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
case '{': case '{':
case '[': /* no nested expressions at this time */ case '[': /* no nested expressions at this time */
printf("error: nested braces not supported %d\n", pos); printf("error: nested braces not supported %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
case ',': case ',':
case '}': /* set element completed */ case '}': /* set element completed */
*buf = '\0'; *buf = '\0';
pat->content.Set.elements = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*)); pat->content.Set.elements = realloc(pat->content.Set.elements, (pat->content.Set.size + 1) * sizeof(char*));
if (!pat->content.Set.elements) { if (!pat->content.Set.elements) {
printf("out of memory in set pattern\n"); printf("out of memory in set pattern\n");
exit(URG_OUT_OF_MEMORY); exit(CURLE_OUT_OF_MEMORY);
} }
pat->content.Set.elements[pat->content.Set.size] = strdup(glob_buffer); pat->content.Set.elements[pat->content.Set.size] = strdup(glob_buffer);
++pat->content.Set.size; ++pat->content.Set.size;
@@ -95,11 +95,11 @@ int glob_set(char *pattern, int pos) {
break; break;
case ']': /* illegal closing bracket */ case ']': /* illegal closing bracket */
printf("error: illegal pattern at pos %d\n", pos); printf("error: illegal pattern at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
case '\\': /* escaped character, skip '\' */ case '\\': /* escaped character, skip '\' */
if (*(buf+1) == '\0') { /* but no escaping of '\0'! */ if (*(buf+1) == '\0') { /* but no escaping of '\0'! */
printf("error: illegal pattern at pos %d\n", pos); printf("error: illegal pattern at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
++pattern; ++pattern;
++pos; /* intentional fallthrough */ ++pos; /* intentional fallthrough */
@@ -108,7 +108,7 @@ int glob_set(char *pattern, int pos) {
++pos; ++pos;
} }
} }
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
int glob_range(char *pattern, int pos) { int glob_range(char *pattern, int pos) {
@@ -132,7 +132,7 @@ int glob_range(char *pattern, int pos) {
pat->content.CharRange.max_c - pat->content.CharRange.min_c > 'z' - 'a') { pat->content.CharRange.max_c - pat->content.CharRange.min_c > 'z' - 'a') {
/* the pattern is not well-formed */ /* the pattern is not well-formed */
printf("error: illegal pattern or range specification after pos %d\n", pos); printf("error: illegal pattern or range specification after pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
pat->content.CharRange.ptr_c = pat->content.CharRange.min_c; pat->content.CharRange.ptr_c = pat->content.CharRange.min_c;
/* always check for a literal (may be "") between patterns */ /* always check for a literal (may be "") between patterns */
@@ -146,7 +146,7 @@ int glob_range(char *pattern, int pos) {
pat->content.NumRange.min_n >= pat->content.NumRange.max_n) { pat->content.NumRange.min_n >= pat->content.NumRange.max_n) {
/* the pattern is not well-formed */ /* the pattern is not well-formed */
printf("error: illegal pattern or range specification after pos %d\n", pos); printf("error: illegal pattern or range specification after pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
if (*pattern == '0') { /* leading zero specified */ if (*pattern == '0') { /* leading zero specified */
c = pattern; c = pattern;
@@ -161,7 +161,7 @@ int glob_range(char *pattern, int pos) {
glob_word(c, pos + (c - pattern)); glob_word(c, pos + (c - pattern));
} }
printf("error: illegal character in range specification at pos %d\n", pos); printf("error: illegal character in range specification at pos %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
int glob_word(char *pattern, int pos) { int glob_word(char *pattern, int pos) {
@@ -174,14 +174,14 @@ int glob_word(char *pattern, int pos) {
while (*pattern != '\0' && *pattern != '{' && *pattern != '[') { while (*pattern != '\0' && *pattern != '{' && *pattern != '[') {
if (*pattern == '}' || *pattern == ']') { if (*pattern == '}' || *pattern == ']') {
printf("illegal character at position %d\n", pos); printf("illegal character at position %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
if (*pattern == '\\') { /* escape character, skip '\' */ if (*pattern == '\\') { /* escape character, skip '\' */
++pattern; ++pattern;
++pos; ++pos;
if (*pattern == '\0') { /* but no escaping of '\0'! */ if (*pattern == '\0') { /* but no escaping of '\0'! */
printf("illegal character at position %d\n", pos); printf("illegal character at position %d\n", pos);
exit (URG_URL_MALFORMAT); exit (CURLE_URL_MALFORMAT);
} }
} }
*buf++ = *pattern++; /* copy character to literal */ *buf++ = *pattern++; /* copy character to literal */
@@ -201,20 +201,25 @@ int glob_word(char *pattern, int pos) {
return glob_range(++pattern, ++pos);/* process range pattern */ return glob_range(++pattern, ++pos);/* process range pattern */
} }
printf("internal error\n"); printf("internal error\n");
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
int glob_url(URLGlob** glob, char* url) { int glob_url(URLGlob** glob, char* url, int *urlnum)
int urlnum; /* counts instances of a globbed pattern */ {
if (strlen(url)>URL_MAX_LENGTH) {
printf("Illegally sized URL\n");
return CURLE_URL_MALFORMAT;
}
glob_expand = (URLGlob*)malloc(sizeof(URLGlob)); glob_expand = (URLGlob*)malloc(sizeof(URLGlob));
glob_expand->size = 0; glob_expand->size = 0;
urlnum = glob_word(url, 1); *urlnum = glob_word(url, 1);
*glob = glob_expand; *glob = glob_expand;
return urlnum; return CURLE_OK;
} }
char *next_url(URLGlob *glob) { char *next_url(URLGlob *glob)
{
static int beenhere = 0; static int beenhere = 0;
char *buf = glob_buffer; char *buf = glob_buffer;
URLPattern *pat; URLPattern *pat;
@@ -253,7 +258,7 @@ char *next_url(URLGlob *glob) {
break; break;
default: default:
printf("internal error: invalid pattern type (%d)\n", pat->type); printf("internal error: invalid pattern type (%d)\n", pat->type);
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
} }
if (carry) /* first pattern ptr has run into overflow, done! */ if (carry) /* first pattern ptr has run into overflow, done! */
@@ -282,7 +287,7 @@ char *next_url(URLGlob *glob) {
break; break;
default: default:
printf("internal error: invalid pattern type (%d)\n", pat->type); printf("internal error: invalid pattern type (%d)\n", pat->type);
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
} }
} }
@@ -300,12 +305,12 @@ char *match_url(char *filename, URLGlob glob) {
if (!isdigit((int)*++filename) || if (!isdigit((int)*++filename) ||
*filename == '0') { /* only '#1' ... '#9' allowed */ *filename == '0') { /* only '#1' ... '#9' allowed */
printf("illegal matching expression\n"); printf("illegal matching expression\n");
exit(URG_URL_MALFORMAT); exit(CURLE_URL_MALFORMAT);
} }
i = *filename - '1'; i = *filename - '1';
if (i + 1 > glob.size / 2) { if (i + 1 > glob.size / 2) {
printf("match against nonexisting pattern\n"); printf("match against nonexisting pattern\n");
exit(URG_URL_MALFORMAT); exit(CURLE_URL_MALFORMAT);
} }
pat = glob.pattern[i]; pat = glob.pattern[i];
switch (pat.type) { switch (pat.type) {
@@ -322,7 +327,7 @@ char *match_url(char *filename, URLGlob glob) {
break; break;
default: default:
printf("internal error: invalid pattern type (%d)\n", pat.type); printf("internal error: invalid pattern type (%d)\n", pat.type);
exit (URG_FAILED_INIT); exit (CURLE_FAILED_INIT);
} }
++filename; ++filename;
} }

View File

@@ -67,7 +67,7 @@ typedef struct {
int size; int size;
} URLGlob; } URLGlob;
int glob_url(URLGlob**, char*); int glob_url(URLGlob**, char*, int *);
char* next_url(URLGlob*); char* next_url(URLGlob*);
char* match_url(char*, URLGlob); char* match_url(char*, URLGlob);

View File

@@ -1,3 +1,3 @@
#define CURL_NAME "curl" #define CURL_NAME "curl"
#define CURL_VERSION "6.5.2" #define CURL_VERSION "7.0.1beta"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") " #define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "