Compare commits

...

146 Commits

Author SHA1 Message Date
Daniel Stenberg
cf8704ccdf 7.7 alpha 2 commit 2001-03-04 16:34:20 +00:00
Daniel Stenberg
5543c2f11f Added include of easy.h to enable libcurl-using programs to *only* have to
include <curl/curl.h>
2001-03-04 15:32:44 +00:00
Daniel Stenberg
90ac37a683 Curl_http() could crash on connection re-use 2001-03-04 15:25:54 +00:00
Daniel Stenberg
dd893fd8a4 ipv6 fix for the 'port' no longer in urldata 2001-03-03 17:50:01 +00:00
Daniel Stenberg
834f079918 fixed for persistant stuff 2001-03-03 16:28:59 +00:00
Daniel Stenberg
2665c763df latest 2001-03-02 15:38:06 +00:00
Daniel Stenberg
d1cfbd51b5 remade the port number stuff so that following locations work and doing
intermixed HTTP and FTP persistant connections also work!
2001-03-02 15:34:15 +00:00
Daniel Stenberg
a3ba6b7a6a Added the disconnect proto 2001-03-02 07:44:22 +00:00
Daniel Stenberg
415d2e7cb7 removed the slist -functions from here
added the Curl_ftp_disconnect function for FTP-specific disconnects
2001-03-02 07:44:05 +00:00
Daniel Stenberg
af4451ec26 improved connections 2001-03-02 07:43:20 +00:00
Daniel Stenberg
7c6562683a extending connectdata 2001-03-02 07:42:35 +00:00
Daniel Stenberg
b6fa2f882c moved the slist-functions here from FTP since they're more generic than simply
for FTP-stuff
2001-03-02 07:42:11 +00:00
Daniel Stenberg
b6c5da337a strdup() takes a const char * now 2001-03-02 07:41:40 +00:00
Daniel Stenberg
9bc24e4876 cleanup better when connects fail 2001-02-28 14:03:46 +00:00
Daniel Stenberg
4af55809e4 added some infof() calls for persistant info 2001-02-22 23:51:17 +00:00
Daniel Stenberg
9c63fcf210 we only allocate the HTTP struct if we need to 2001-02-22 23:41:15 +00:00
Daniel Stenberg
1f17fb5f89 Now persistant connection download works thanks to the Content-Length taken
into account
2001-02-22 23:32:41 +00:00
Daniel Stenberg
584dbffe60 moved the dynamicly set pointers to the connectdata struct 2001-02-22 23:32:02 +00:00
Daniel Stenberg
1c6f6f6972 Douglas R. Horner's corrections applied 2001-02-22 22:33:49 +00:00
Daniel Stenberg
da06a6e7e3 IPv6-adjustments 2001-02-21 17:15:09 +00:00
Daniel Stenberg
46e0937263 corrected memory leaks when re-using connections 2001-02-20 17:46:35 +00:00
Daniel Stenberg
a1d6ad2610 multiple connection support initial commit 2001-02-20 17:35:51 +00:00
Daniel Stenberg
5f3d63ed5b bugfix 2001-02-20 13:58:56 +00:00
Daniel Stenberg
63b5748eb6 -g runs the specified test(s) with gdb! 2001-02-20 13:58:39 +00:00
Daniel Stenberg
e2590430c5 removed the #ifdef 2001-02-20 13:57:50 +00:00
Daniel Stenberg
ada9bc2b24 win32sockets.c is now added with winsock init/cleanup example functions 2001-02-20 13:56:38 +00:00
Daniel Stenberg
43da41e73e Added three tiny PHP examples 2001-02-19 13:39:21 +00:00
Daniel Stenberg
720fa45b56 blurb about different languages and environments added 2001-02-19 13:38:29 +00:00
Daniel Stenberg
7de874c438 just a few PHP/curl examples 2001-02-19 13:38:05 +00:00
Daniel Stenberg
2078c1a01a added two VC++ files for project stuff 2001-02-19 09:29:40 +00:00
Daniel Stenberg
f7a8909372 Made CURLOPT_POST no longer necessary when CURLOPT_POSTFIELDS is used 2001-02-19 09:29:19 +00:00
Daniel Stenberg
250df30e64 Moved a bunch of prototypes from curl.h here, they're no longer public and
I merely stuffed them here before I decide where they belong and if they
are to remain at all
2001-02-19 09:28:10 +00:00
Daniel Stenberg
b887cf7521 removed a bunch of "low level" functions that were never used and are about
to never become reality either
2001-02-19 09:27:12 +00:00
Daniel Stenberg
630e932091 MS VC++ stuff 2001-02-19 09:26:29 +00:00
Daniel Stenberg
cdabd67aa9 Bob Schader updated this 2001-02-19 09:26:01 +00:00
Daniel Stenberg
42e4f9d776 added stuff to the mailing list chapter 2001-02-19 09:25:18 +00:00
Daniel Stenberg
c111033595 removed --continue task (done)
added URL to the NTLM task
2001-02-16 13:41:34 +00:00
Daniel Stenberg
26d1aaccdf 2.2 - rephrased 2001-02-16 13:41:09 +00:00
Daniel Stenberg
ce95d2020f better english timeouted => timed out, as suggested by Larry Fahnoe 2001-02-13 21:57:04 +00:00
Daniel Stenberg
948c3b3aa9 7.6.1 commit 2001-02-13 13:37:14 +00:00
Daniel Stenberg
a140e5311d moved the protocol-specific free to allow easier multiple transfers 2001-02-13 13:34:16 +00:00
Daniel Stenberg
7686ac3f2c ftp response fix, netrc fix for non-http/ftp, https put research 2001-02-12 13:20:04 +00:00
Daniel Stenberg
54778134e4 corrected the prototype 2001-02-12 13:19:09 +00:00
Daniel Stenberg
c59baa06f0 Added 3.10 and a few minor updates 2001-02-12 10:05:09 +00:00
Daniel Stenberg
c107303ade very minor indentation fix 2001-02-12 08:22:19 +00:00
Daniel Stenberg
21b05afc99 removed getenv.h from the package as it was unused 2001-02-12 08:21:45 +00:00
Daniel Stenberg
eebcf7d4f5 Not used anymore 2001-02-09 07:33:58 +00:00
Daniel Stenberg
8d169dfadd Added a failf() call in the error-check just added 2001-02-09 07:14:28 +00:00
Daniel Stenberg
b12e334d83 if netrc is parsed and our host was found in there, set data->bits.user_passwd
unconditioanlly!
2001-02-08 13:53:13 +00:00
Daniel Stenberg
7e36c4437e today's FTP response check fix 2001-02-08 13:52:38 +00:00
Daniel Stenberg
3c7a80a275 postit.c was added as a HTML form file upload example 2001-02-08 08:26:54 +00:00
Daniel Stenberg
61e2a8108b 7.6.1-pre3 2001-02-07 09:49:06 +00:00
Daniel Stenberg
abb14de7e0 GetLine() didn't properly act on -1 lengths returned from Curl_read() 2001-02-07 09:31:03 +00:00
Daniel Stenberg
ccd57e58f6 Added #define ssize_t int since ssize_t doesn't seem to exist in normal
win32 systems
2001-02-07 09:23:54 +00:00
Daniel Stenberg
58d70db92e no longer #includes "getenv.h" 2001-02-07 08:36:23 +00:00
Daniel Stenberg
09f6fc22ed silly me, corrected the strlcat() to compile 2001-02-06 09:12:39 +00:00
Daniel Stenberg
833ce37cb9 new openbsd inspired implementation of strlcat() 2001-02-06 09:08:24 +00:00
Daniel Stenberg
07e7018564 nntp@iname.com's suggested fix to set the libpath 2001-02-06 07:14:44 +00:00
Daniel Stenberg
db70cd28b3 adjusted the IPv6 stuff to compile and build on Linux as well 2001-02-05 23:35:44 +00:00
Daniel Stenberg
f6e2bfd464 Jun-ichiro itojun Hagino's IPv6 adjustments 2001-02-05 23:04:44 +00:00
Daniel Stenberg
1ae5dab8fb Robert Weaver's VC experiences 2001-02-05 22:35:55 +00:00
Daniel Stenberg
c6355e6a43 Added a telnet section 2001-02-05 22:35:21 +00:00
Daniel Stenberg
7d26eb61fe Added a few more configure option explanations 2001-02-05 10:24:12 +00:00
Daniel Stenberg
8613ce377f the new getinfo() stuff and the cygwin patch 2001-02-04 20:10:52 +00:00
Daniel Stenberg
d6b94488a1 Added blurb about the win32 thing that precents a DLL from using a pointer
passed to it from user-space!
2001-02-04 20:10:02 +00:00
Daniel Stenberg
5d7b32d09f extended 5.5 2001-02-04 20:08:42 +00:00
Daniel Stenberg
ed16d30ea8 CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD documented 2001-02-04 20:07:53 +00:00
Daniel Stenberg
6f7c70fbbc CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD were
added as suggested by Bob Schader
2001-02-04 20:03:30 +00:00
Daniel Stenberg
9ab5d30e3b Ingo Ralf Blum made it compile with the newest cygwin 2001-02-04 19:00:27 +00:00
Daniel Stenberg
3b44a3df76 7.6.1-pre2 2001-02-01 07:59:46 +00:00
Daniel Stenberg
572c29a4a3 Added support for --enable-debug 2001-02-01 07:58:49 +00:00
Daniel Stenberg
9464c5430d Curl_read() uses ssize_t now 2001-01-31 15:06:56 +00:00
Daniel Stenberg
a14aaaf23f fixed up the telnet to work (using support from Linus Nielsen) 2001-01-31 15:05:44 +00:00
Daniel Stenberg
c41c5a0ef2 curl_read() and Curl_read() now have ssize_t in the last argument 2001-01-31 13:54:12 +00:00
Daniel Stenberg
c0c0283356 Added a check for a working getaddrinfo() that is required for the IPv6
to be considered enabled
2001-01-31 13:53:31 +00:00
Daniel Stenberg
1bcd3e601a changed order of the range and follow-location checks so that a range-request
will work even when following a Location:
2001-01-30 11:52:59 +00:00
Daniel Stenberg
e721f85c83 new test case 2001-01-29 16:04:19 +00:00
Daniel Stenberg
7015c61b86 removed upload.NN files after each test 2001-01-29 15:07:28 +00:00
Daniel Stenberg
30ec0af109 test case 33, HTTP PUT resume 2001-01-29 14:36:49 +00:00
Daniel Stenberg
f585b66af7 7.6-pre1 2001-01-29 11:36:08 +00:00
Daniel Stenberg
1b77c18430 Added an extra text about % in POST data after comments from Daniel Marell 2001-01-29 10:24:51 +00:00
Daniel Stenberg
bd0bd35771 s/to I/do I/ 2001-01-29 10:16:47 +00:00
Daniel Stenberg
368e3526ea Added "3.9 How to I use curl in PHP?" 2001-01-29 10:16:21 +00:00
Daniel Stenberg
1bbe407a4d The PUT stuff is never set! It is set with the UPLOAD... 2001-01-29 07:26:50 +00:00
Daniel Stenberg
513bc44421 HTTP PUT resume now sends Content-Range: headers as I believe the RFC2616
describes, Bob Schader's research seems to agree.
2001-01-29 07:24:20 +00:00
Daniel Stenberg
4cc76d1576 upload sets HTTP request to PUT for "HTTP upload" 2001-01-29 07:23:11 +00:00
Daniel Stenberg
6dc5c6ffc7 the keep-alive issue 2001-01-27 20:51:31 +00:00
Daniel Stenberg
c69c79dd04 bettersupport for HTTP return codes 300-399 2001-01-27 20:31:51 +00:00
Daniel Stenberg
7fca24b14b PUT resume things
progress meter modified for resume
POST/GET/Location adjustments
2001-01-27 20:25:52 +00:00
Daniel Stenberg
2fa0d3dd5f test case 31 and 32 were added 2001-01-27 20:02:11 +00:00
Daniel Stenberg
3a8210c975 Resume is now done with a Content-Range header instead of a Range header if
the request isn't GET. Presumably, this is how it should be made.
2001-01-27 18:57:07 +00:00
Daniel Stenberg
d69302202d minor output fix 2001-01-27 18:51:10 +00:00
Daniel Stenberg
227662d2ed Added -d that enables easier protocol/server debug overview (it invokes
the servers with their -v options)
2001-01-27 18:50:54 +00:00
Daniel Stenberg
3cb3d43913 added test 29 and 30, HTTP resume and partial download tests 2001-01-27 18:49:48 +00:00
Daniel Stenberg
c8a546c941 The progess meter title get an extra output when a resumed transfer is
taking place
2001-01-27 18:23:59 +00:00
Daniel Stenberg
62fec1d28d data->httpreq was not set properly 2001-01-27 17:58:15 +00:00
Daniel Stenberg
ac98c73b04 7.6 2001-01-27 16:16:54 +00:00
Daniel Stenberg
a145654394 http upload resume 2001-01-26 15:53:33 +00:00
Daniel Stenberg
e8382ba290 moved the symbols talk to the library part, updated slightly to match 2001-01-26 15:52:51 +00:00
Daniel Stenberg
fcb347d124 Added a httpreq field in the main struct so that there's one field to check
for what HTTP request that is being used. The old bit-style fields are still
in there as well.
2001-01-26 15:52:01 +00:00
Daniel Stenberg
c331ef02f9 The check for that content-range is received must only be made if we requested
GET resume. Other resumes are upload-wise and don't care about this header
in the download stream
2001-01-26 15:50:56 +00:00
Daniel Stenberg
3a3f632bf0 Made it possible to do "upload resume" over HTTP 2001-01-26 15:49:39 +00:00
Daniel Stenberg
68d7b6f871 7.6-pre4 2001-01-25 13:48:28 +00:00
Daniel Stenberg
c43a9d9068 timespent is now updated in every call to the progress meter update function 2001-01-25 12:32:40 +00:00
Daniel Stenberg
64e80091db Rick's and Jeff's stuff 2001-01-25 12:31:44 +00:00
Daniel Stenberg
4f255ffbeb make the configure script die if select() or socket() is missing 2001-01-25 12:28:46 +00:00
Daniel Stenberg
80d75b0eaf Added Ingo Ralf Blum 2001-01-25 12:28:10 +00:00
Daniel Stenberg
808c4020e6 use this function only once note added 2001-01-25 12:27:44 +00:00
Daniel Stenberg
149d6363b3 modified the Curl_ConnectHTTPProxyTunnel proto 2001-01-25 12:24:34 +00:00
Daniel Stenberg
30eab8ca51 moved curl_read() and curl_write() to sendf.c 2001-01-25 12:23:57 +00:00
Daniel Stenberg
e49a82b06c converted to use Curl_read() and Curl_write() 2001-01-25 12:23:12 +00:00
Daniel Stenberg
45fdb48189 uses Curl_read() and Curl_write()
unfolded telwrite() instead of being a separate single function
2001-01-25 12:22:17 +00:00
Daniel Stenberg
3fcc9677c4 use recv()/send() instead of read()/write() with sockets 2001-01-25 12:21:10 +00:00
Daniel Stenberg
1552bd9c8c sendf is now only Curl_sendf
Curl_write() and Curl_read() are here
2001-01-25 12:20:30 +00:00
Daniel Stenberg
939c0c5521 removed two compiler warnings 2001-01-25 12:19:36 +00:00
Daniel Stenberg
f0b9aefd2e Curl_read() and Curl_write() are now used for reading/writing sockets.
Some functions changed prototype due to this change as well.
2001-01-25 12:19:02 +00:00
Daniel Stenberg
11f3c51e8f Get get-ftp-response function is now using Curl_read() for reading from a
socket. Curl_ConnectHTTPProxyTunnel changed prototype.
2001-01-25 12:17:07 +00:00
Daniel Stenberg
1a329b98a3 replaced sendf() calls with Curl_sendf() 2001-01-25 12:13:35 +00:00
Daniel Stenberg
29bcba9a90 Ingo Ralf Blum's cygwin fixes 2001-01-24 14:44:05 +00:00
Daniel Stenberg
1716dbb68a Robert Weaver's win32 getenv fix, my added comments in some files 2001-01-24 14:04:47 +00:00
Daniel Stenberg
16ecfcf62c Added Robert Weaver as contributor 2001-01-24 14:04:14 +00:00
Daniel Stenberg
8bafc3692d fixed the comment for 'path' 2001-01-24 14:03:48 +00:00
Daniel Stenberg
8a75120568 added comments all over 2001-01-24 12:32:34 +00:00
Daniel Stenberg
3d96ee7423 extended the gname field one byte to avoid a possible overflow
added lots of explaining comments
2001-01-24 12:10:10 +00:00
Daniel Stenberg
b3dbdfa306 Robert Weaver's fix 2001-01-24 09:01:32 +00:00
Daniel Stenberg
25bad589ba generated by autoheader 2001-01-23 13:00:43 +00:00
Daniel Stenberg
0b6cd75004 ipv6 adjustments 2001-01-23 10:29:16 +00:00
Daniel Stenberg
7872cc131a Enabled support for IPv6-style IP-addresses if ENABLE_IPV6 is set. If it isn't,
curl will return an error when such an address is used.
2001-01-23 10:21:30 +00:00
Daniel Stenberg
210aa4371c big reorg to make it not exit when it fails, but instead just not do any
globbing, it makes IPv6 support easier and smoother to add.
2001-01-23 10:14:43 +00:00
Daniel Stenberg
6f438bc8fb Added 'ipv6 enabled' for ipv6 compiled versions 2001-01-23 08:16:59 +00:00
Daniel Stenberg
65840f1fd1 Added simple IPv6 recognition support 2001-01-22 23:54:54 +00:00
Daniel Stenberg
5fc492e5c6 Bjrn's progress meter fix, new test cases and ftpserver.pl patch 2001-01-22 16:25:55 +00:00
Daniel Stenberg
abcd1e7d5a Bjrn Stenberg's patch for making the progress meter betterlooking 2001-01-22 16:21:05 +00:00
Daniel Stenberg
6429c378a2 the custom reply engine was not inited properly 2001-01-22 16:16:18 +00:00
Daniel Stenberg
d830f10417 test case 121 2001-01-22 16:05:12 +00:00
Daniel Stenberg
3d6fcbf97b Added test case 120, ftp with '-Q -' 2001-01-22 16:00:28 +00:00
Daniel Stenberg
609be218c2 Removed the deprecated -c and -t from the --help output. 2001-01-22 10:09:04 +00:00
Daniel Stenberg
41084e57ca Added 5.5 the CURLOPT_FILE problem on win32, DeYoung provided it! 2001-01-22 08:42:00 +00:00
Daniel Stenberg
9afab85105 Added -g/--globoff description 2001-01-19 12:24:46 +00:00
Daniel Stenberg
7822233964 Made the complaint on free-twice errors a lot better 2001-01-19 12:20:30 +00:00
Daniel Stenberg
022315089b removed URL length restrictions, added a test case 2001-01-19 12:20:02 +00:00
Daniel Stenberg
faa5c14aee No more URL length restrictions 2001-01-19 12:15:23 +00:00
Daniel Stenberg
3dd886955b removed MAX_URL_LENGTH, there is no longer any length restrictions on URLs
anywhere within libcurl
2001-01-19 12:14:55 +00:00
Daniel Stenberg
c2dbf21459 corrected url memory handling with --globoff 2001-01-19 12:14:09 +00:00
Daniel Stenberg
133eb220b9 Added files for test case 28 2001-01-19 12:13:37 +00:00
Daniel Stenberg
c5796d9e39 --globoff test case 2001-01-19 12:12:54 +00:00
112 changed files with 4902 additions and 2589 deletions

259
CHANGES
View File

@@ -6,6 +6,265 @@
History of Changes History of Changes
** curl 7.7 DOES NOT currently WORK. **
Daniel (4 March 2001)
- Now, there's even a basic check that a re-used connection is still alive
before it is assumed so. A few first tests have proven that libcurl will
then re-connect instead of re-use the dead connection!
Daniel (2 March 2001)
- Now they work intermixed as well. Major coolness!
- More fiddling around, my 'tiny' client I have for testing purposes now has
proved to download both FTP and HTTP with persistant connections. They do
not work intermixed yet though.
Daniel (1 March 2001)
- Wilfredo Sanchez pointed out a minor spelling mistake in a man page and that
curl_slist_append() should take a const char * as second argument. It does
now.
Daniel (22 February 2001)
- The persistant connections start to look good for HTTP. On a subsequent
request, it seems that libcurl now can pick an already existing connection
if a suitable one exists, or it opens a new one.
- Douglas R. Horner mailed me corrections to the curl_formparse() man page
that I applied.
Daniel (20 February 2001)
- Added the docs/examples/win32sockets.c file for our windows friends.
- Linus Nielsen Feltzing provided brand new TELNET functionality and
improvements:
* Negotiation is now passive. Curl does not negotiate until the peer does.
* Possibility to set negotiation options on the command line, currently only
XDISPLOC, TTYPE and NEW_ENVIRON (called NEW_ENV).
* Now sends the USER environment variable if the -u switch is used.
* Use -t to set telnet options (Linus even updated the man page, awesome!)
- Haven't done this big changes to curl for a while. Moved around a lot of
struct fields and stuff to make multiple connections get connection specific
data in separate structs so that they can co-exist in a nice way. See the
mailing lists for discussions around how this is gonna be implemented. Docs
and more will follow.
Studied the HTTP RFC to find out better how persistant connections should
work. Seems cool enough.
Daniel (19 February 2001)
- Bob Schader brought me two files that help set up a MS VC++ libcurl project
easier. He also provided me with an up-to-date libcurl.def file.
- I moved a bunch of prototypes from the public <curl/curl.h> file to the
library private urldata.h. This is because of the upcoming changes. The
low level interface is no longer being planned to become reality.
Daniel (15 February 2001)
- CURLOPT_POST is not required anymore. Just setting the POST string with
CURLOPT_POSTFIELDS will switch on the HTTP POST. Most other things in
libcurl already works this way, i.e they require only the parameter to
switch on a feature so I think this works well with the rest. Setting a NULL
string switches off the POST again.
- Excellent suggestions from Rich Gray, Rick Jones, Johan Nilsson and Bjorn
Reese helped me define a way how to incorporate persistant connections into
libcurl in a very smooth way. If done right, no change may have to be made
to older programs and they will just start using persistant connections when
applicable!
Daniel (13 February 2001)
- Changed the word 'timeouted' to 'timed out' in two different error messages.
Suggested by Larry Fahnoe.
Version 7.6.1
Daniel (9 February 2001)
- Frank Reid and Cain Hopwood provided information and research around a HTTPS
PUT/upload problem we seem to have. No solution found yet.
Daniel (8 February 2001)
- An interesting discussion is how to specify an empty password without having
curl ask for it interactively? The current implmentation takes an empty
password as a request for a password prompt. However, I still want to
support a blank user field. Thus, today if you enter "-u :" (without user
and password) curl will prompt for the password. Tricky. How would you
specify you want the prompt otherwise?
- Made the netrc parse result possible to use for other protocols than FTP and
HTTP (such as the upcoming TELNET fixes).
- The previously mentioned "MSVC++ problems" turned out to be a non-issue.
- Added a HTTP file upload code example in the docs/examples/ section on
request.
- Adjusted the FTP response fix slightly.
Version 7.6.1-pre3
Daniel (7 February 2001)
- SM found a flaw in the response reading function for FTP that could make
libcurl not get out of the loop properly when it should, if libcurl got -1
returned when reading the socket.
- I found a similar mistake in http.c when using a proxy and reading the
results from the proxy connection.
Daniel (6 February 2001)
- A friendly person named "SM" (nntp at iname.com) pointed out that the VC
makefile in src/ needed the libpath set for the debug build to work.
- Daniel Gehriger stepped in to assist with the VC++ stuff Robert Weaver
brought up yesterday.
Daniel (5 February 2001)
- Jun-ichiro itojun Hagino brought a big patch that brings IPv6-awareness to
a bunch of different areas within libcurl.
- Robert Weaver told me about the problems the MS VC++ 6.0 compiler has with
the 'static' keyword on a number of libcurl functions. I might need to add a
patch that redefines static when libcurl is compiled with that compiler.
How do I know when VC++ compiles, anyone?
Daniel (4 February 2001)
- curl_getinfo() was extended with two new options:
CURLINFO_CONTENT_LENGTH_DOWNLOAD and CURLINFO_CONTENT_LENGTH_UPLOAD. They
return the full assumed content length of the transfer in the given
direction. The CURLINFO_CONTENT_LENGTH_DOWNLOAD will be the Content-Length:
size of a HTTP download. Added descriptions to the man page as well. This
was done after discussions with Bob Schader.
Daniel (3 February 2001)
- Ingo Ralf Blum provided another fix that makes curl build under the more
recent cygwin installations. It seems they've changed the preset defines to
not include WIN32 anymore.
Version 7.6.1-pre2
Daniel (31 January 2001)
- Curl_read() and curl_read() now return a ssize_t for the size, as it had to
be able to return -1. The telnet support crashed due to this and there was a
possibility to weird behaviour all over. Linus Nielsen Feltzing helped me
find this.
- Added a configure.in check for a working getaddrinfo() if IPv6 is requested.
I also made the configure script feature --enable-debug which sets a couple
of compiler options when used. It assumes gcc.
Daniel (30 January 2001)
- I finally took a stab at the long-term FIXME item I've had on myself, and
now libcurl will properly work when doing a HTTP range-request that follows
a Location:. Previously that would make libcurl fail saying that the server
doesn't seem to support range requests.
Daniel (29 January 2001)
- I added a test case for the HTTP PUT resume thing (test case 33).
Version 7.6.1-pre1
Daniel (29 January 2001)
- Yet another Content-Range change. Ok now? Bob Schader checks from his end
and it works for him.
Daniel (27 January 2001)
- So the HTTP PUT resume fix wasn't good. There should appearantly be a
Content-Range header when resuming a PUT.
- I noticed I broke the download-check that verifies that a resumed HTTP
download is actually resumed. It got broke because my new 'httpreq' field
in the main curl struct. I should get slapped. I added a test case for
this now, so I won't be able to ruin this again without noticing.
- Added a test case for content-length verifying when downloading HTTP.
- Made the progress meter title say if the transfer is being transfered. It
makes the output slightly better for resumes.
- When dealing with Location: and HTTP return codes, libcurl will not attempt
to follow the spirit of RFC2616 better. It means that when POSTing to a
URL that is being following to a second place, the standard will judge on
what to do. All HTTP codes except 303 and 305 will cause curl to make a
second POST operation. 303 will make a GET and 305 is not yet supported.
I also wrote two test cases for this POST/GET/Location stuff.
Version 7.6
Daniel (26 January 2001)
- Lots of mails back and forth with Bob Schader finally made me add a small
piece of code in the HTTP engine so that HTTP upload resume works. You can
now do an operation like 'curl -T file -C <offset> <URL>' and curl will PUT
the ending part of the file starting at given offet to the specified URL.
Version 7.6-pre4
Daniel (25 January 2001)
- I took hold of Rick Jones' question why we don't use recv() and send() for
reading/writing to the sockets and I've now modified the sread() and
swrite() macros to use them instead. If nothing else, they could be tested
in the next beta-round coming right up.
- Jeff Morrow found a problem with libcurl's usage of SSL_read() and supplied
his research results in how to fix this. It turns out we have to invoke the
function several times in some cases. The same goes for the SSL_write().
I made some rather drastic changes all over libcurl to make all writes and
reads get done on one single place so that this repeated-attempts thing
would only have to be implemented at one point.
- Rick Jones spotted that the 'total time' counter really didn't measure the
total time very accurate on subsecond levels.
- Johan Nilsson pointed out the need to more clearly specify that the timeout
value you set for a download is for the *entire* download. There's currently
no option available that sets a timeout for the connection phase only.
Daniel (24 January 2001)
- Ingo Ralf Blum submitted a series of patches required to get curl to compile
properly with cygwin.
- Robert Weaver posted a fix for the win32 section of the curl_getenv() code
that corrected a potential memory leak.
- Added comments in a few files in a sudden attempt to make the sources more
easy to read and understand!
Daniel (23 January 2001)
- Added simple IPv6 detection in the configure script and made the version
string add 'ipv6' to the enable section in that case. ENABLE_IPV6 will be
set if curl is compiled with IPv6 support enabled.
- Added a parser for IPv6-style specified IP-addresses in a URL. Thus, when
IPv6 gets enabled soon, we can use URLs like '[0::1]:80'...
- Made the URL globbing in the client possible to fail silently if there's an
error in the globbing. It makes it almost intuitive, so when you don't
follow the syntax rules, globbing is simply switched off and the raw string
is used instead.
I still think we'll get problems with IPv6-style IP-addresses when we *want*
globbing on parts of the URL as the initial part of the URL will for sure
seriously confuse the globber.
Daniel (22 January 2001)
- Bj<42>rn Stenberg supplied a progress meter patch that makes it look better even
during slow starts. Previously it made some silly assumptions...
- Added two FTP tests for -Q and -Q - stuff since it was being discussed on
the mailing list. Had to correct the ftpserver.pl too as it bugged slightly.
Daniel (19 January 2001)
- Made the Location: parsers deal with any-length URLs. Thus I removed the last
code that restricts the length of URLs that curl supports.
- Added a --globoff test case (#28) and it quickly identified a memory problem
in src/main.c that I took care of.
Version 7.6-pre3
Daniel (17 January 2001) Daniel (17 January 2001)
- Made the two former files lib/download.c and lib/highlevel.c become the new - Made the two former files lib/download.c and lib/highlevel.c become the new
lib/transfer.c which makes more sense. I also did the rename from Transfer() lib/transfer.c which makes more sense. I also did the rename from Transfer()

View File

@@ -36,3 +36,10 @@
/* Define if you have the Kerberos4 libraries (including -ldes) */ /* Define if you have the Kerberos4 libraries (including -ldes) */
#undef KRB4 #undef KRB4
/* Define if you want to enable IPv6 support */
#undef ENABLE_IPV6
/* Define this to 'int' if ssize_t is not an available typedefed type */
#undef ssize_t

View File

@@ -23,6 +23,9 @@
/* Define to `unsigned' if <sys/types.h> doesn't define. */ /* Define to `unsigned' if <sys/types.h> doesn't define. */
/* #undef size_t */ /* #undef size_t */
/* Define this to 'int' if ssize_t is not an available typedefed type */
#define ssize_t int
/* Define if you have the ANSI C header files. */ /* Define if you have the ANSI C header files. */
#define STDC_HEADERS 1 #define STDC_HEADERS 1

View File

@@ -1,312 +0,0 @@
/* config.h.in. Generated automatically from configure.in by autoheader. */
/* Define if on AIX 3.
System headers sometimes define this.
We just want to avoid a redefinition error message. */
#ifndef _ALL_SOURCE
#undef _ALL_SOURCE
#endif
/* Define to empty if the keyword does not work. */
#undef const
/* Define as the return type of signal handlers (int or void). */
#undef RETSIGTYPE
/* Define to `unsigned' if <sys/types.h> doesn't define. */
#undef size_t
/* Define if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Define if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
/* Define cpu-machine-OS */
#undef OS
/* Define if you have the gethostbyaddr_r() function with 5 arguments */
#undef HAVE_GETHOSTBYADDR_R_5
/* Define if you have the gethostbyaddr_r() function with 7 arguments */
#undef HAVE_GETHOSTBYADDR_R_7
/* Define if you have the gethostbyaddr_r() function with 8 arguments */
#undef HAVE_GETHOSTBYADDR_R_8
/* Define if you have the gethostbyname_r() function with 3 arguments */
#undef HAVE_GETHOSTBYNAME_R_3
/* Define if you have the gethostbyname_r() function with 5 arguments */
#undef HAVE_GETHOSTBYNAME_R_5
/* Define if you have the gethostbyname_r() function with 6 arguments */
#undef HAVE_GETHOSTBYNAME_R_6
/* Define if you have the inet_ntoa_r function declared. */
#undef HAVE_INET_NTOA_R_DECL
/* Define if you need the _REENTRANT define for some functions */
#undef NEED_REENTRANT
/* Define if you have the Kerberos4 libraries (including -ldes) */
#undef KRB4
/* The number of bytes in a long double. */
#undef SIZEOF_LONG_DOUBLE
/* The number of bytes in a long long. */
#undef SIZEOF_LONG_LONG
/* Define if you have the RAND_screen function. */
#undef HAVE_RAND_SCREEN
/* Define if you have the RAND_status function. */
#undef HAVE_RAND_STATUS
/* Define if you have the closesocket function. */
#undef HAVE_CLOSESOCKET
/* Define if you have the gethostbyaddr function. */
#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. */
#undef HAVE_GETHOSTNAME
/* Define if you have the getpass_r function. */
#undef HAVE_GETPASS_R
/* Define if you have the getservbyname function. */
#undef HAVE_GETSERVBYNAME
/* Define if you have the gettimeofday function. */
#undef HAVE_GETTIMEOFDAY
/* Define if you have the inet_addr function. */
#undef HAVE_INET_ADDR
/* Define if you have the inet_ntoa function. */
#undef HAVE_INET_NTOA
/* Define if you have the inet_ntoa_r function. */
#undef HAVE_INET_NTOA_R
/* Define if you have the krb_get_our_ip_for_realm function. */
#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
/* Define if you have the localtime_r function. */
#undef HAVE_LOCALTIME_R
/* Define if you have the perror function. */
#undef HAVE_PERROR
/* Define if you have the select function. */
#undef HAVE_SELECT
/* Define if you have the setvbuf function. */
#undef HAVE_SETVBUF
/* Define if you have the sigaction function. */
#undef HAVE_SIGACTION
/* Define if you have the signal function. */
#undef HAVE_SIGNAL
/* Define if you have the socket function. */
#undef HAVE_SOCKET
/* Define if you have the strcasecmp function. */
#undef HAVE_STRCASECMP
/* Define if you have the strcmpi function. */
#undef HAVE_STRCMPI
/* Define if you have the strdup function. */
#undef HAVE_STRDUP
/* Define if you have the strftime function. */
#undef HAVE_STRFTIME
/* Define if you have the stricmp function. */
#undef HAVE_STRICMP
/* Define if you have the strlcpy function. */
#undef HAVE_STRLCPY
/* Define if you have the strstr function. */
#undef HAVE_STRSTR
/* Define if you have the tcgetattr function. */
#undef HAVE_TCGETATTR
/* Define if you have the tcsetattr function. */
#undef HAVE_TCSETATTR
/* Define if you have the uname function. */
#undef HAVE_UNAME
/* Define if you have the <alloca.h> header file. */
#undef HAVE_ALLOCA_H
/* Define if you have the <arpa/inet.h> header file. */
#undef HAVE_ARPA_INET_H
/* Define if you have the <crypto.h> header file. */
#undef HAVE_CRYPTO_H
/* Define if you have the <des.h> header file. */
#undef HAVE_DES_H
/* Define if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define if you have the <err.h> header file. */
#undef HAVE_ERR_H
/* Define if you have the <fcntl.h> header file. */
#undef HAVE_FCNTL_H
/* Define if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define if you have the <io.h> header file. */
#undef HAVE_IO_H
/* Define if you have the <krb.h> header file. */
#undef HAVE_KRB_H
/* Define if you have the <malloc.h> header file. */
#undef HAVE_MALLOC_H
/* Define if you have the <net/if.h> header file. */
#undef HAVE_NET_IF_H
/* Define if you have the <netdb.h> header file. */
#undef HAVE_NETDB_H
/* Define if you have the <netinet/if_ether.h> header file. */
#undef HAVE_NETINET_IF_ETHER_H
/* Define if you have the <netinet/in.h> header file. */
#undef HAVE_NETINET_IN_H
/* Define if you have the <openssl/crypto.h> header file. */
#undef HAVE_OPENSSL_CRYPTO_H
/* Define if you have the <openssl/err.h> header file. */
#undef HAVE_OPENSSL_ERR_H
/* Define if you have the <openssl/pem.h> header file. */
#undef HAVE_OPENSSL_PEM_H
/* Define if you have the <openssl/rsa.h> header file. */
#undef HAVE_OPENSSL_RSA_H
/* Define if you have the <openssl/ssl.h> header file. */
#undef HAVE_OPENSSL_SSL_H
/* Define if you have the <openssl/x509.h> header file. */
#undef HAVE_OPENSSL_X509_H
/* Define if you have the <pem.h> header file. */
#undef HAVE_PEM_H
/* Define if you have the <rsa.h> header file. */
#undef HAVE_RSA_H
/* Define if you have the <sgtty.h> header file. */
#undef HAVE_SGTTY_H
/* Define if you have the <ssl.h> header file. */
#undef HAVE_SSL_H
/* Define if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define if you have the <sys/select.h> header file. */
#undef HAVE_SYS_SELECT_H
/* Define if you have the <sys/socket.h> header file. */
#undef HAVE_SYS_SOCKET_H
/* Define if you have the <sys/sockio.h> header file. */
#undef HAVE_SYS_SOCKIO_H
/* Define if you have the <sys/stat.h> header file. */
#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. */
#undef HAVE_SYS_TYPES_H
/* Define if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <time.h> header file. */
#undef HAVE_TIME_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define if you have the <winsock.h> header file. */
#undef HAVE_WINSOCK_H
/* Define if you have the <x509.h> header file. */
#undef HAVE_X509_H
/* Define if you have the crypto library (-lcrypto). */
#undef HAVE_LIBCRYPTO
/* Define if you have the dl library (-ldl). */
#undef HAVE_LIBDL
/* Define if you have the nsl library (-lnsl). */
#undef HAVE_LIBNSL
/* Define if you have the resolv library (-lresolv). */
#undef HAVE_LIBRESOLV
/* Define if you have the resolve library (-lresolve). */
#undef HAVE_LIBRESOLVE
/* Define if you have the socket library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define if you have the ssl library (-lssl). */
#undef HAVE_LIBSSL
/* Define if you have the ucb library (-lucb). */
#undef HAVE_LIBUCB
/* Name of package */
#undef PACKAGE
/* Version number of package */
#undef VERSION
/* Number of bits in a file offset, on hosts where this is settable. */
#undef _FILE_OFFSET_BITS
/* Define to make ftello visible on some hosts (e.g. HP-UX 10.20). */
#undef _LARGEFILE_SOURCE
/* Define for large files, on AIX-style hosts. */
#undef _LARGE_FILES
/* Set to explicitly specify we don't want to use thread-safe functions */
#undef DISABLED_THREADSAFE

View File

@@ -26,6 +26,66 @@ dnl The install stuff has already been taken care of by the automake stuff
dnl AC_PROG_INSTALL dnl AC_PROG_INSTALL
AC_PROG_MAKE_SET AC_PROG_MAKE_SET
dnl ************************************************************
dnl lame option to switch on debug options
dnl
AC_MSG_CHECKING([whether to enable debug options])
AC_ARG_ENABLE(debug,
[ --enable-debug Enable pedantic debug options
--disable-debug Disable debug options],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
;;
*) AC_MSG_RESULT(yes)
CPPFLAGS="$CPPFLAGS -DMALLOCDEBUG"
CFLAGS="-Wall -pedantic -g"
;;
esac ],
AC_MSG_RESULT(no)
)
dnl
dnl check for working getaddrinfo()
dnl
AC_DEFUN(CURL_CHECK_WORKING_GETADDRINFO,[
AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[
AC_TRY_RUN( [
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
void main(void) {
struct addrinfo hints, *ai;
int error;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
error = getaddrinfo("127.0.0.1", "8080", &hints, &ai);
if (error) {
exit(1);
}
else {
exit(0);
}
}
],[
ac_cv_working_getaddrinfo="yes"
],[
ac_cv_working_getaddrinfo="no"
],[
ac_cv_working_getaddrinfo="yes"
])])
if test "$ac_cv_working_getaddrinfo" = "yes"; then
AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works])
AC_DEFINE(ENABLE_IPV6, 1, [Define if you want to enable IPv6 support])
fi
])
AC_DEFUN(CURL_CHECK_LOCALTIME_R, AC_DEFUN(CURL_CHECK_LOCALTIME_R,
[ [
dnl check for a few thread-safe functions dnl check for a few thread-safe functions
@@ -237,6 +297,47 @@ exit (rc != 0 ? 1 : 0); }],[
]) ])
dnl **********************************************************************
dnl Checks for IPv6
dnl **********************************************************************
AC_MSG_CHECKING([whether to enable ipv6])
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 Enable ipv6 (with ipv4) support
--disable-ipv6 Disable ipv6 support],
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
ipv6=no
;;
*) AC_MSG_RESULT(yes)
ipv6=yes
;;
esac ],
AC_TRY_RUN([ /* is AF_INET6 available? */
#include <sys/types.h>
#include <sys/socket.h>
main()
{
if (socket(AF_INET6, SOCK_STREAM, 0) < 0)
exit(1);
else
exit(0);
}
],
AC_MSG_RESULT(yes)
ipv6=yes,
AC_MSG_RESULT(no)
ipv6=no,
AC_MSG_RESULT(no)
ipv6=no
))
if test "$ipv6" = "yes"; then
CURL_CHECK_WORKING_GETADDRINFO
fi
dnl ********************************************************************** dnl **********************************************************************
dnl Checks for libraries. dnl Checks for libraries.
@@ -327,6 +428,10 @@ AC_MSG_CHECKING([if Kerberos4 support is requested])
if test "$want_krb4" = yes if test "$want_krb4" = yes
then then
if test "$ipv6" = "yes"; then
echo krb4 is not compatible with IPv6
exit 1
fi
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
dnl Check for & handle argument to --with-krb4 dnl Check for & handle argument to --with-krb4
@@ -554,6 +659,9 @@ AC_CHECK_SIZEOF(long double, 8)
# check for 'long long' # check for 'long long'
AC_CHECK_SIZEOF(long long, 4) AC_CHECK_SIZEOF(long long, 4)
# check for ssize_t
AC_CHECK_TYPE(ssize_t, int)
dnl Get system canonical name dnl Get system canonical name
AC_CANONICAL_HOST AC_CANONICAL_HOST
AC_DEFINE_UNQUOTED(OS, "${host}") AC_DEFINE_UNQUOTED(OS, "${host}")
@@ -584,12 +692,16 @@ AC_CHECK_FUNCS( socket \
setvbuf \ setvbuf \
sigaction \ sigaction \
signal \ signal \
getpass_r getpass_r \
strlcat
) )
dnl removed 'getpass' check on October 26, 2000 dnl removed 'getpass' check on October 26, 2000
if test "$ac_cv_func_select" != "yes"; then if test "$ac_cv_func_select" != "yes"; then
AC_MSG_ERROR(Can't work without an existing select() function)
fi
if test "$ac_cv_func_socket" != "yes"; then
AC_MSG_ERROR(Can't work without an existing socket() function) AC_MSG_ERROR(Can't work without an existing socket() function)
fi fi
@@ -621,5 +733,6 @@ AC_OUTPUT( Makefile \
packages/Linux/Makefile \ packages/Linux/Makefile \
packages/Linux/RPM/Makefile \ packages/Linux/RPM/Makefile \
packages/Linux/RPM/curl.spec \ packages/Linux/RPM/curl.spec \
packages/Linux/RPM/curl-ssl.spec ) packages/Linux/RPM/curl-ssl.spec \
tiny/Makefile )

View File

@@ -1,4 +1,4 @@
Updated: January 15, 2001 (http://curl.haxx.se/docs/faq.shtml) Updated: February 16, 2001 (http://curl.haxx.se/docs/faq.shtml)
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -30,6 +30,8 @@ FAQ
3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y? 3.6 Does curl support javascript, ASP, XML, XHTML or HTML version Y?
3.7 Can I use curl to delete/rename a file through FTP? 3.7 Can I use curl to delete/rename a file through FTP?
3.8 How do I tell curl to follow HTTP redirects? 3.8 How do I tell curl to follow HTTP redirects?
3.9 How do I use curl in PHP?
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
4. Running Problems 4. Running Problems
4.1 Problems connecting to SSL servers. 4.1 Problems connecting to SSL servers.
@@ -52,6 +54,8 @@ FAQ
5.2 How can I receive all data into a large memory chunk? 5.2 How can I receive all data into a large memory chunk?
5.3 How do I fetch multiple files with libcurl? 5.3 How do I fetch multiple files with libcurl?
5.4 Does libcurl do Winsock initing on win32 systems? 5.4 Does libcurl do Winsock initing on win32 systems?
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
5.6 What about Keep-Alive or persistant connections?
6. License Issues 6. License Issues
6.1 I have a GPL program, can I use the libcurl library? 6.1 I have a GPL program, can I use the libcurl library?
@@ -103,8 +107,8 @@ FAQ
or with PHP. or with PHP.
Curl is not a single-OS program. Curl exists, compiles, builds and runs Curl is not a single-OS program. Curl exists, compiles, builds and runs
under a wide range of operating systems, including all modern Unixes, under a wide range of operating systems, including all modern Unixes (and a
Windows, Amiga, BeOS, OS/2, OS X, QNX etc. bunch of older ones too), Windows, Amiga, BeOS, OS/2, OS X, QNX etc.
1.4 When will you make curl do XXXX ? 1.4 When will you make curl do XXXX ?
@@ -179,11 +183,8 @@ FAQ
2.2. Does curl work/build with other SSL libraries? 2.2. Does curl work/build with other SSL libraries?
Curl has been written to use OpenSSL, although I doubt there would be much 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 problems using a different library. If anyone does "port" curl to use a
that has limited my possibilities to develop against anything else. different SSL library, I am of course very interested in getting the patch!
If anyone does "port" curl to use a commercial SSL library, I am of course
very interested in getting the patch!
2.3. Where can I find a copy of LIBEAY32.DLL? 2.3. Where can I find a copy of LIBEAY32.DLL?
@@ -227,7 +228,7 @@ FAQ
You can't simply use -F or -d at your choice. The web server that will You can't simply use -F or -d at your choice. The web server that will
receive your post assumes one of the formats. If the form you're trying to receive your post assumes one of the formats. If the form you're trying to
"fake" sets the type to 'multipart/form-data', than and only then you must "fake" sets the type to 'multipart/form-data', then and only then you must
use the -F type. In all the most common cases, you should use -d which then use the -F type. In all the most common cases, you should use -d which then
causes a posting with the type 'application/x-www-form-urlencoded'. causes a posting with the type 'application/x-www-form-urlencoded'.
@@ -278,6 +279,29 @@ FAQ
curl -L http://redirector.com curl -L http://redirector.com
3.9 How do I use curl in PHP?
PHP4 has the ability to use libcurl as an internal module if built with that
option enabled. You then get a set of extra functions that can be used
within your PHP programs. You find all details about those functions in the
curl section in the PHP manual, see the online version at:
http://www.php.net/manual/ref.curl.php
PHP also offers the option to run a command line, and then you can of course
invoke the curl tool using a command line. This is the way to use curl if
you're using PHP3 or PHP4 built without curl module support.
3.10 What about SOAP, WEBDAV, XML-RPC or similar protocols over HTTP?
Curl adheres to the HTTP spec, which basically means you can play with *any*
protocol that is built ontop of HTTP. Protocols such as SOAP, WEBDAV and
XML-RPC are all such ones. You can use -X to set custom requests and -H to
set custom headers (or replace internally generated ones).
Using libcurl or PHP's curl modules is just as fine and you'd just use the
proper library options to do the same.
4. Running Problems 4. Running Problems
4.1. Problems connecting to SSL servers. 4.1. Problems connecting to SSL servers.
@@ -309,6 +333,9 @@ FAQ
In win32, the standard DOS shell treats the %-letter specially and you may In win32, the standard DOS shell treats the %-letter specially and you may
need to quote the string properly when % is used in it. need to quote the string properly when % is used in it.
Also note that if you want the literal %-letter to be part of the data you
pass in a POST using -d/--data you must encode it as '%25'.
4.3. How can I use {, }, [ or ] to specify multiple URLs? 4.3. How can I use {, }, [ or ] to specify multiple URLs?
Because those letters have a special meaning to the shell, and to be used in Because those letters have a special meaning to the shell, and to be used in
@@ -407,7 +434,8 @@ FAQ
4.9. Curl can't authenticate to the server that requires NTLM? 4.9. Curl can't authenticate to the server that requires NTLM?
NTLM is a Microsoft proprietary protocol. Unfortunately, curl does not NTLM is a Microsoft proprietary protocol. Unfortunately, curl does not
currently support that. currently support that. Proprietary formats are evil. You should not use
such ones.
5. libcurl Issues 5. libcurl Issues
@@ -472,9 +500,28 @@ FAQ
use several different libraries and parts, and there's no reason for every use several different libraries and parts, and there's no reason for every
single library to do this. single library to do this.
5.5 Does CURLOPT_FILE and CURLOPT_INFILE work on win32 ?
Yes, but you cannot open a FILE * and pass the pointer to a DLL and have
that DLL use the FILE *. If you set CURLOPT_FILE you must also use
CURLOPT_WRITEFUNCTION as well to set a function that writes the file, even
if that simply writes the data to the specified FILE*. Similarly, if you use
CURLOPT_INFILE you must also specify CURLOPT_READFUNCTION.
(Provided by Joel DeYoung and Bob Schader)
5.6 What about Keep-Alive or persistant connections?
This is closely related to issue 5.3. Since libcurl has no real support
for doing multiple file transfers, there's no support for Keep-Alive or
persistant connections either.
This is of course subject to change as soon as libcurl gets support for
multiple files. Feel free to join in and make this change happen sooner!
6. License Issues 6. License Issues
NOTE: This section is now updated to concern curl 7.5.2 or later! NOTE: This section concerns curl 7.5.2 or later!
Curl and libcurl are released under a MIT/X derivate license *or* the MPL, Curl and libcurl are released under a MIT/X derivate license *or* the MPL,
the Mozilla Public License. To get a really good answer to your license the Mozilla Public License. To get a really good answer to your license
@@ -492,27 +539,25 @@ FAQ
6.2. I have a closed-source program, can I use the libcurl library? 6.2. I have a closed-source program, can I use the libcurl library?
Yes. Yes!
libcurl does not put any restrictions on the program that uses the libcurl does not put any restrictions on the program that uses the library.
library.
6.3. I have a BSD licensed program, can I use the libcurl library? 6.3. I have a BSD licensed program, can I use the libcurl library?
Yes. Yes!
libcurl does not put any restrictions on the program that uses the libcurl does not put any restrictions on the program that uses the library.
library.
6.4. I have a program that uses LGPL libraries, can I use libcurl? 6.4. I have a program that uses LGPL libraries, can I use libcurl?
Yes. Yes!
The LGPL license don't clash with other licenses. The LGPL license doesn't clash with other licenses.
6.5. Can I modify curl/libcurl for my program and keep the changes secret? 6.5. Can I modify curl/libcurl for my program and keep the changes secret?
Yes. Yes!
The MIT/X derivate license practically allows you to do almost anything with The MIT/X derivate license practically allows you to do almost anything with
the sources, on the condition that the copyright texts in the sources are the sources, on the condition that the copyright texts in the sources are
@@ -520,9 +565,11 @@ FAQ
6.6. Can you please change the curl/libcurl license to XXXX? 6.6. Can you please change the curl/libcurl license to XXXX?
No. We carefully picked this license years ago and a large amount of people No.
have contributed with source code knowing that this is the license we
use. This license puts the restrictions we want on curl/libcurl and it does We carefully picked this license years ago and a large amount of people have
not spread to other programs or libraries that use it. The recent dual contributed with source code knowing that this is the license we use. This
license modification should make it possible for everyone to use libcurl or license puts the restrictions we want on curl/libcurl and it does not spread
curl in their projects, no matter what license they already have in use. to other programs or libraries that use it. The recent dual license
modification should make it possible for everyone to use libcurl or curl in
their projects, no matter what license they already have in use.

View File

@@ -20,6 +20,7 @@ Misc
- compiles on win32 - compiles on win32
- redirectable stderr - redirectable stderr
- use selected network interface for outgoing traffic - use selected network interface for outgoing traffic
- IPv6 support
HTTP HTTP
- GET - GET
@@ -28,7 +29,7 @@ HTTP
- POST - POST
- multipart POST - multipart POST
- authentication - authentication
- resume - resume (both GET and PUT)
- follow redirects - follow redirects
- maximum amount of redirects to follow - maximum amount of redirects to follow
- custom HTTP request - custom HTTP request

View File

@@ -84,9 +84,10 @@ UNIX
KNOWN PROBLEMS KNOWN PROBLEMS
If you happen to have autoconf installed, but a version older than If you happen to have autoconf installed, but a version older than 2.12
2.12 you will get into trouble. Then you can still build curl by you will get into trouble. Then you can still build curl by issuing these
issuing these commands: (from Ralph Beckmann) commands (note that this requires curl to be built staticly): (from Ralph
Beckmann)
./configure [...] ./configure [...]
cd lib; make; cd .. cd lib; make; cd ..
@@ -139,6 +140,14 @@ UNIX
./configure --with-krb4=/usr/athena ./configure --with-krb4=/usr/athena
If your system support shared libraries, but you want to built a static
version only, you can disable building the shared version by using:
./configure --disable-shared
If you're a curl developer and use gcc, you might want to enable more
debug options with the --enable-debug option.
Win32 Win32
===== =====

View File

@@ -1,3 +1,4 @@
Updated for curl 7.6 on January 26, 2001
_ _ ____ _ _ _ ____ _
___| | | | _ \| | ___| | | | _ \| |
/ __| | | | |_) | | / __| | | | |_) | |
@@ -12,13 +13,6 @@ INTERNALS
Thus, the largest amount of code and complexity is in the library part. Thus, the largest amount of code and complexity is in the library part.
SYMBOLS
=======
All symbols used internally must use a 'Curl_' prefix if they're used in more
than a single file. Single-file symbols must be made static. Public
(exported) symbols must use a 'curl_' prefix. (There are exceptions, but they
are destined to be changed to follow this pattern in the future.)
CVS CVS
=== ===
All changes to the sources are committed to the CVS repository as soon as All changes to the sources are committed to the CVS repository as soon as
@@ -35,10 +29,11 @@ Windows vs Unix
There are a few differences in how to program curl the unix way compared to There are a few differences in how to program curl the unix way compared to
the Windows way. The four perhaps most notable details are: the Windows way. The four perhaps most notable details are:
1. Different function names for close(), read(), write() 1. Different function names for socket operations.
In curl, this is solved with defines and macros, so that the source looks In curl, this is solved with defines and macros, so that the source looks
the same at all places except for the header file that defines them. the same at all places except for the header file that defines them. The
macros in use are sclose(), sread() and swrite().
2. Windows requires a couple of init calls for the socket stuff 2. Windows requires a couple of init calls for the socket stuff
@@ -187,6 +182,15 @@ Library
exists in lib/getpass.c. libcurl offers a custom callback that can be used exists in lib/getpass.c. libcurl offers a custom callback that can be used
instead of this, but it doesn't change much to us. instead of this, but it doesn't change much to us.
Library Symbols
===============
All symbols used internally in libcurl must use a 'Curl_' prefix if they're
used in more than a single file. Single-file symbols must be made
static. Public (exported) symbols must use a 'curl_' prefix. (There are
exceptions, but they are destined to be changed to follow this pattern in the
future.)
Return Codes and Informationals Return Codes and Informationals
=============================== ===============================

View File

@@ -726,16 +726,41 @@ KERBEROS4 FTP TRANSFER
There's no use for a password on the -u switch, but a blank one will make There's no use for a password on the -u switch, but a blank one will make
curl ask for one and you already entered the real password to kauth. curl ask for one and you already entered the real password to kauth.
MAILING LIST TELNET
We have an open mailing list to discuss curl, its development and things The curl telnet support is basic and very easy to use. Curl passes all data
relevant to this. passed to it on stdin to the remote server. Connect to a remote telnet
server using a command line similar to:
To subscribe, mail curl-request@contactor.se with "subscribe <fill in your curl telnet://remote.server.com
email address>" in the body.
To post to the list, mail curl@contactor.se. And enter the data to pass to the server on stdin. The result will be sent
to stdout or to the file you specify with -o.
To unsubcribe, mail curl-request@contactor.se with "unsubscribe <your You might want the -N/--no-buffer option to switch off the buffered output
subscribed email address>" in the body. for slow connections or similar.
NOTE: the telnet protocol does not specify any way to login with a specified
user and password so curl can't do that automatically. To do that, you need
to track when the login prompt is received and send the username and
password accordingly.
MAILING LISTS
For your convenience, we have several open mailing lists to discuss curl,
its development and things relevant to this.
To subscribe to the main curl list, mail curl-request@contactor.se with
"subscribe <fill in your email address>" in the body.
To subscribe to the libcurl users list, follow the instructions at
http://curl.haxx.se/mail/
To subscribe to the curl announce list, to only get information about new
releases, follow the instructions at http://curl.haxx.se/mail/
To subscribe to the curl-and-PHP list in which curl using with PHP is
discussed, follow the instructions at http://curl.haxx.se/mail/
Please direct curl questions, feature requests and trouble reports to one of
these mailing lists instead of mailing any individual.

View File

@@ -23,11 +23,8 @@ For the future
URLs mentioned in the list. I figure -O or something would have to be URLs mentioned in the list. I figure -O or something would have to be
implied by such an action. implied by such an action.
* Improve the regular progress meter with --continue is used. It should be
noticable when there's a resume going on.
* Add a command line option that allows the output file to get the same time * Add a command line option that allows the output file to get the same time
stamp as the remote file. We already are capable of fetching the remote stamp as the remote file. libcurl already is capable of fetching the remote
file's date. file's date.
* Make the SSL layer option capable of using the Mozilla Security Services as * Make the SSL layer option capable of using the Mozilla Security Services as
@@ -58,13 +55,15 @@ For the future
started in October 1999 but halted again since it proved more work than we started in October 1999 but halted again since it proved more work than we
thought. It is still a good idea to implement though. thought. It is still a good idea to implement though.
* Authentication: NTLM. It would be cool to support that MS crap called NTLM * Authentication: NTLM. It would be to support that MS crap called NTLM
authentication. MS proxies and servers sometime require that. Since that authentication. MS proxies and servers sometime require that. Since that
protocol is a proprietary one, it involves reverse engineering and network protocol is a proprietary one, it involves reverse engineering and network
sniffing. This should however be a library-based functionality. There are a sniffing. This should however be a library-based functionality. There are a
few different efforts "out there" to make open source HTTP clients support few different efforts "out there" to make open source HTTP clients support
this and it should be possible to take advantage of other people's hard this and it should be possible to take advantage of other people's hard
work. http://modntlm.sourceforge.net/ is one. work. http://modntlm.sourceforge.net/ is one. There's a web page at
http://www.innovation.ch/java/ntlm.html that contains detailed reverse-
engineered info.
* RFC2617 compliance, "Digest Access Authentication" * RFC2617 compliance, "Digest Access Authentication"
A valid test page seem to exist at: A valid test page seem to exist at:

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 "9 January 2001" "Curl 7.6" "Curl Manual" .TH curl 1 "19 January 2001" "Curl 7.6" "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.
@@ -205,6 +205,12 @@ To read the file's content from stdin insted of a file, use - where the file
name should've been. This goes for both @ and < constructs. name should've been. This goes for both @ and < constructs.
This option can be used multiple times. This option can be used multiple times.
.IP "-g/--globoff"
This option switches off the "URL globbing parser". When you set this option,
you can specify URLs that contain the letters {}[] without having them being
interpreted by curl itself. Note that these letters are not normal legal URL
contents but they should be encoded according to the URI standard. (Option
added in curl 7.6)
.IP "-h/--help" .IP "-h/--help"
Usage help. Usage help.
.IP "-H/--header <header>" .IP "-H/--header <header>"
@@ -419,11 +425,14 @@ If this option is used twice, the second will again disable mute.
When used with -s it makes curl show error message if it fails. When used with -s it makes curl show error message if it fails.
If this option is used twice, the second will again disable show error. If this option is used twice, the second will again disable show error.
.IP "-t/--upload" .IP "-t/--telnet-option <OPT=val>"
.B Deprecated. Use '-T -' instead. Pass options to the telnet protocol. Supported options are:
Transfer the stdin data to the specified file. Curl will read
everything from stdin until EOF and store with the supplied name. If TTYPE=<term> Sets the terminal type.
this is used on a http(s) server, the PUT command will be used.
XDISPLOC=<X display> Sets the X display location.
NEW_ENV=<var,val> Sets an environment variable.
.IP "-T/--upload-file <file>" .IP "-T/--upload-file <file>"
Like -t, but this transfers the specified local file. If there is no Like -t, but this transfers the specified local file. If there is no
file part in the specified URL, Curl will append the local file file part in the specified URL, Curl will append the local file
@@ -752,7 +761,7 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Lars J. Aas <larsa@sim.no> - Lars J. Aas <larsa@sim.no>
- J<>rn Hartroth <Joern.Hartroth@computer.org> - J<>rn Hartroth <Joern.Hartroth@computer.org>
- Matthew Clarke <clamat@van.maves.ca> - Matthew Clarke <clamat@van.maves.ca>
- Linus Nielsen <Linus.Nielsen@haxx.se> - Linus Nielsen Feltzing <linus@haxx.se>
- Felix von Leitner <felix@convergence.de> - Felix von Leitner <felix@convergence.de>
- Dan Zitter <dzitter@zitter.net> - Dan Zitter <dzitter@zitter.net>
- Jongki Suwandi <Jongki.Suwandi@eng.sun.com> - Jongki Suwandi <Jongki.Suwandi@eng.sun.com>
@@ -780,6 +789,9 @@ If you do find bugs, mail them to curl-bug@haxx.se.
- Alexander Kourakos <awk@users.sourceforge.net> - Alexander Kourakos <awk@users.sourceforge.net>
- James Griffiths <griffiths_james@yahoo.com> - James Griffiths <griffiths_james@yahoo.com>
- Loic Dachary <loic@senga.org> - Loic Dachary <loic@senga.org>
- Robert Weaver <robert.weaver@sabre.com>
- Ingo Ralf Blum <ingoralfblum@ingoralfblum.com>
- Jun-ichiro itojun Hagino <itojun@iijlab.net>
.SH WWW .SH WWW
http://curl.haxx.se http://curl.haxx.se

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_init 3 "22 November 2000" "Curl 7.5" "libcurl Manual" .TH curl_easy_init 3 "4 February 2001" "Curl 7.6.1" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_getinfo - Extract information from a curl session (added in 7.4) curl_easy_getinfo - Extract information from a curl session (added in 7.4)
.SH SYNOPSIS .SH SYNOPSIS
@@ -81,6 +81,14 @@ than one request if FOLLOWLOCATION is true.
Pass a pointer to a long to receive the result of the certification Pass a pointer to a long to receive the result of the certification
verification that was requested (using the CURLOPT_SSL_VERIFYPEER option to verification that was requested (using the CURLOPT_SSL_VERIFYPEER option to
curl_easy_setopt). (Added in 7.4.2) curl_easy_setopt). (Added in 7.4.2)
.TP
.B CURLINFO_CONTENT_LENGTH_DOWNLOAD
Pass a pointer to a double to receive the content-length of the download.
(Added in 7.6.1)
.TP
.B CURLINFO_CONTENT_LENGTH_UPLOAD
Pass a pointer to a double to receive the specified size of the upload.
(Added in 7.6.1)
.PP .PP
.SH RETURN VALUE .SH RETURN VALUE

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_perform 3 "26 May 2000" "Curl 7.0" "libcurl Manual" .TH curl_easy_perform 3 "1 Mar 2001" "Curl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_perform - Do the actual transfer in a "easy" session curl_easy_perform - Do the actual transfer in a "easy" session
.SH SYNOPSIS .SH SYNOPSIS
@@ -16,12 +16,16 @@ are made, and will perform the transfer as described in the options.
It must be called with the same It must be called with the same
.I handle .I handle
as input as the curl_easy_init call returned. as input as the curl_easy_init call returned.
You are only allowed to call this function once using the same handle. If you
want to do repeated calls, you must call curl_easy_cleanup and curl_easy_init
again first.
.SH RETURN VALUE .SH RETURN VALUE
0 means everything was ok, non-zero means an error occurred as 0 means everything was ok, non-zero means an error occurred as
.I <curl/curl.h> .I <curl/curl.h>
defines. If the CURLOPT_ERRORBUFFER was set with defines. If the CURLOPT_ERRORBUFFER was set with
.I curl_easy_setopt .I curl_easy_setopt
there willo be a readable error message in the error buffer when non-zero is there will be a readable error message in the error buffer when non-zero is
returned. returned.
.SH "SEE ALSO" .SH "SEE ALSO"
.BR curl_easy_init "(3), " curl_easy_setopt "(3), " .BR curl_easy_init "(3), " curl_easy_setopt "(3), "

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_easy_setopt 3 "28 November 2000" "Curl 7.5" "libcurl Manual" .TH curl_easy_setopt 3 "2 February 2001" "Curl 7.5" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_setopt - Set curl easy-session options curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS .SH SYNOPSIS
@@ -35,6 +35,12 @@ Data pointer to pass instead of FILE * to the file write function. Note that
if you specify the if you specify the
.I CURLOPT_WRITEFUNCTION .I CURLOPT_WRITEFUNCTION
, this is the pointer you'll get as input. , this is the pointer you'll get as input.
NOTE: If you're using libcurl as a win32 .DLL, you MUST use a
.I CURLOPT_WRITEFUNCTION
if you set the
.I CURLOPT_FILE
option.
.TP .TP
.B CURLOPT_WRITEFUNCTION .B CURLOPT_WRITEFUNCTION
Function pointer that should use match the following prototype: Function pointer that should use match the following prototype:
@@ -53,6 +59,12 @@ Data pointer to pass instead of FILE * to the file read function. Note that if
you specify the you specify the
.I CURLOPT_READFUNCTION .I CURLOPT_READFUNCTION
, this is the pointer you'll get as input. , this is the pointer you'll get as input.
NOTE: If you're using libcurl as a win32 .DLL, you MUST use a
.I CURLOPT_READFUNCTION
if you set the
.I CURLOPT_INFILE
option.
.TP .TP
.B CURLOPT_READFUNCTION .B CURLOPT_READFUNCTION
Function pointer that should use match the following prototype: Function pointer that should use match the following prototype:

View File

@@ -2,13 +2,13 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_formparse 3 "6 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_formparse 3 "22 February 2001" "Curl 7.0" "libcurl Manual"
.SH NAME .SH NAME
curl_formparse - add a section to a multipart/formdata HTTP POST curl_formparse - add a section to a multipart/formdata HTTP POST
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/curl.h> .B #include <curl/curl.h>
.sp .sp
.BI "CURLcode *curl_formparse(char *" string, "struct HttpPost **" firstitem, .BI "CURLcode curl_formparse(char *" string, "struct HttpPost **" firstitem,
.BI "struct HttpPost ** "lastitem ");" .BI "struct HttpPost ** "lastitem ");"
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
@@ -42,14 +42,14 @@ Add a form field named 'name' with the contents as read from the local files
named 'filename1' and 'filename2'. This is identical to the upper, except that named 'filename1' and 'filename2'. This is identical to the upper, except that
you get the contents of several files in one section. you get the contents of several files in one section.
.TP .TP
.B [name]=@[filename];[content-type] .B [name]=@[filename];[type=<content-type>]
Whenever you specify a file to read from, you can optionally specify the Whenever you specify a file to read from, you can optionally specify the
content-type as well. The content-type is passed to the server together with content-type as well. The content-type is passed to the server together with
the contents of the file. curl_formparse() will guess content-type for a the contents of the file. curl_formparse() will guess content-type for a
number of well-known extensions and otherwise it will set it to binary. You number of well-known extensions and otherwise it will set it to binary. You
can override the internal decision by using this option. can override the internal decision by using this option.
.TP .TP
.B [name]=@[filename1,filename2,...];[content-type] .B [name]=@[filename1,filename2,...];[type=<content-type>]
When you specify several files to read the contents from, you can set the When you specify several files to read the contents from, you can set the
content-type for all of them in the same way as with a single file. content-type for all of them in the same way as with a single file.
.PP .PP

View File

@@ -2,14 +2,14 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" Written by daniel@haxx.se .\" Written by daniel@haxx.se
.\" .\"
.TH curl_slist_append 3 "2 June 2000" "Curl 7.0" "libcurl Manual" .TH curl_slist_append 3 "1 Mar 2001" "Curl 7.7" "libcurl Manual"
.SH NAME .SH NAME
curl_slist_append - add a string to an slist curl_slist_append - add a string to an slist
.SH SYNOPSIS .SH SYNOPSIS
.B #include <curl/curl.h> .B #include <curl/curl.h>
.sp .sp
.BI "struct curl_slist *curl_slist_append(struct curl_slit *" list, .BI "struct curl_slist *curl_slist_append(struct curl_slit *" list,
.BI "char * "string ");" .BI "const char * "string ");"
.ad .ad
.SH DESCRIPTION .SH DESCRIPTION
curl_slist_append() appends a specified string to a linked list of curl_slist_append() appends a specified string to a linked list of

View File

@@ -5,7 +5,9 @@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign no-dependencies
EXTRA_DIST = EXTRA_DIST =
README curlgtk.c sepheaders.c simple.c README curlgtk.c sepheaders.c simple.c postit.c \
win32sockets.c \
getpageinvar.php simpleget.php simplepost.php
all: all:
@echo "done" @echo "done"

View File

@@ -6,3 +6,6 @@ advantage of libcurl.
If you end up with other small but still useful example sources, please mail If you end up with other small but still useful example sources, please mail
them for submission in future packages and on the web site. them for submission in future packages and on the web site.
There are examples for different languages and environments. Browse around to
find those that fit you.

View File

@@ -1,4 +1,12 @@
/* curlgtk.c */ /*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* Copyright (c) 2000 David Odin (aka DindinX) for MandrakeSoft */ /* Copyright (c) 2000 David Odin (aka DindinX) for MandrakeSoft */
/* an attempt to use the curl library in concert with a gtk-threaded application */ /* an attempt to use the curl library in concert with a gtk-threaded application */

View File

@@ -0,0 +1,10 @@
#
# The PHP curl module supports the received page to be returned in a variable
# if told.
#
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.myurl.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
$result=curl_exec ($ch);
curl_close ($ch);

71
docs/examples/postit.c Normal file
View File

@@ -0,0 +1,71 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*
* Example code that uploads a file name 'foo' to a remote script that accepts
* "HTML form based" (as described in RFC1738) uploads using HTTP POST.
*
* The imaginary form we'll fill in looks like:
*
* <form method="post" enctype="multipart/form-data" action="examplepost.cgi">
* Enter file: <input type="file" name="sendfile" size="40">
* Enter file name: <input type="text" name="filename" size="30">
* <input type="submit" value="send" name="submit">
* </form>
*
* This exact source code has not been verified to work.
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include <stdio.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
int main(int argc, char **argv)
{
CURL *curl;
CURLcode res;
struct HttpPost *formpost=NULL;
struct HttpPost *lastptr=NULL;
/* Fill in the file upload field */
curl_formparse("sendfile=@foo",
&formpost,
&lastptr);
/* Fill in the filename field */
curl_formparse("filename=foo",
&formpost,
&lastptr);
/* Fill in the submit field too, even if this is rarely needed */
curl_formparse("submit=send",
&formpost,
&lastptr);
curl = curl_easy_init();
if(curl) {
/* what URL that receives this POST */
curl_easy_setopt(curl, CURLOPT_URL, "http://curl.haxx.se/examplepost.cgi");
curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
/* then cleanup the formpost chain */
curl_formfree(formpost);
}
return 0;
}

View File

@@ -1,3 +1,16 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>

View File

@@ -1,9 +1,22 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* $Id$
*/
#include <stdio.h> #include <stdio.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h> #include <curl/types.h>
#include <curl/easy.h> #include <curl/easy.h>
/* to make this work under windows, use the win32-functions from the
win32socket.c file as well */
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
CURL *curl; CURL *curl;

View File

@@ -0,0 +1,13 @@
#
# A very simple example that gets a HTTP page.
#
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, "http://www.zend.com/");
curl_setopt ($ch, CURLOPT_HEADER, 0);
curl_exec ($ch);
curl_close ($ch);

View File

@@ -0,0 +1,12 @@
#
# A very simple PHP example that sends a HTTP POST to a remote site
#
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,"http://www.mysite.com/tester.phtml");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "postvar1=value1&postvar2=value2&postvar3=value3");
curl_exec ($ch);
curl_close ($ch);

View File

@@ -0,0 +1,40 @@
/*
* These are example functions doing socket init that Windows
* require. If you don't use windows, you can safely ignore this crap.
*/
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 1;
/* 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 1;
}
return 0; /* 0 is ok */
}

View File

@@ -158,6 +158,9 @@ typedef enum {
CURLE_BAD_PASSWORD_ENTERED, /* when the my_getpass() returns fail */ CURLE_BAD_PASSWORD_ENTERED, /* when the my_getpass() returns fail */
CURLE_TOO_MANY_REDIRECTS , /* catch endless re-direct loops */ CURLE_TOO_MANY_REDIRECTS , /* catch endless re-direct loops */
CURLE_UNKNOWN_TELNET_OPTION , /* User specified an unknown option */
CURLE_TELNET_OPTION_SYNTAX , /* Malformed telnet option */
CURL_LAST CURL_LAST
} CURLcode; } CURLcode;
@@ -166,10 +169,6 @@ typedef enum {
#define CURL_ERROR_SIZE 256 #define CURL_ERROR_SIZE 256
/* maximum URL length we deal with in headers */
#define URL_MAX_LENGTH 4096
#define URL_MAX_LENGTH_TXT "4095"
/* name is uppercase CURLOPT_<name>, /* name is uppercase CURLOPT_<name>,
type is one of the defined CURLOPTTYPE_<type> type is one of the defined CURLOPTTYPE_<type>
number is unique identifier */ number is unique identifier */
@@ -410,6 +409,9 @@ typedef enum {
document! Pass a NULL to shut it off. */ document! Pass a NULL to shut it off. */
CINIT(FILETIME, OBJECTPOINT, 69), CINIT(FILETIME, OBJECTPOINT, 69),
/* This points to a linked list of telnet options */
CINIT(TELNETOPTIONS, OBJECTPOINT, 70),
CURLOPT_LASTENTRY /* the last unusued */ CURLOPT_LASTENTRY /* the last unusued */
} CURLoption; } CURLoption;
@@ -456,8 +458,8 @@ 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 "7.6-pre3" #define LIBCURL_VERSION "7.7-alpha2"
#define LIBCURL_VERSION_NUM 0x070600 #define LIBCURL_VERSION_NUM 0x070000
/* linked-list structure for the CURLOPT_QUOTE option (and other) */ /* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist { struct curl_slist {
@@ -465,184 +467,8 @@ struct curl_slist {
struct curl_slist *next; struct curl_slist *next;
}; };
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data); struct curl_slist *curl_slist_append(struct curl_slist *, const char *);
void curl_slist_free_all(struct curl_slist *list); void curl_slist_free_all(struct curl_slist *);
/*
* 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() * NAME curl_getdate()
@@ -680,9 +506,16 @@ typedef enum {
CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13, CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG + 13,
CURLINFO_FILETIME = CURLINFO_LONG + 14, CURLINFO_FILETIME = CURLINFO_LONG + 14,
CURLINFO_LASTONE = 15 CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE + 15,
CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE + 16,
CURLINFO_LASTONE = 17
} CURLINFO; } CURLINFO;
/* unfortunately, the easy.h include file needs the options and info stuff
before it can be included! */
#include <curl/easy.h> /* nothing in curl is fun without the easy stuff */
/* /*
* NAME curl_getinfo() * NAME curl_getinfo()
* *
@@ -697,6 +530,20 @@ typedef enum {
*/ */
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...); CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...);
typedef enum {
CURLCLOSEPOLICY_NONE, /* first, never use this */
CURLCLOSEPOLICY_OLDEST,
CURLCLOSEPOLICY_LEAST_RECENTLY_USED,
CURLCLOSEPOLICY_LEAST_TRAFFIC,
CURLCLOSEPOLICY_SLOWEST,
CURLCLOSEPOLICY_CALLBACK,
CURLCLOSEPOLICY_LAST /* last, never use this */
} curl_closepolicy;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -6,7 +6,7 @@ AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = getdate.y \ EXTRA_DIST = getdate.y \
Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \ Makefile.b32 Makefile.b32.resp Makefile.m32 Makefile.vc6 \
libcurl.def dllinit.c libcurl.def dllinit.c curllib.dsp curllib.dsw
lib_LTLIBRARIES = libcurl.la lib_LTLIBRARIES = libcurl.la
@@ -55,7 +55,7 @@ dict.c ftp.h if2ip.c speedcheck.c url.h \
dict.h getdate.c if2ip.h speedcheck.h urldata.h \ dict.h getdate.c if2ip.h speedcheck.h urldata.h \
getdate.h ldap.c ssluse.c version.c \ getdate.h ldap.c ssluse.c version.c \
getenv.c ldap.h ssluse.h \ getenv.c ldap.h ssluse.h \
escape.c getenv.h mprintf.c telnet.c \ escape.c mprintf.c telnet.c \
escape.h getpass.c netrc.c telnet.h \ escape.h getpass.c netrc.c telnet.h \
getinfo.c transfer.c strequal.c strequal.h easy.c \ getinfo.c transfer.c strequal.c strequal.h easy.c \
security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h security.h security.c krb4.c krb4.h memdebug.c memdebug.h inet_ntoa_r.h

367
lib/curllib.dsp Normal file
View File

@@ -0,0 +1,367 @@
# Microsoft Developer Studio Project File - Name="curllib" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
CFG=curllib - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "curllib.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "curllib.mak" CFG="curllib - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "curllib - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE "curllib - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
MTL=midl.exe
RSC=rc.exe
!IF "$(CFG)" == "curllib - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "C:\jdk1.3.0_01\include" /I "C:\jdk1.3.0_01\include\win32" /I "..\include" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /machine:I386 /out:"Release/curl.dll"
!ELSEIF "$(CFG)" == "curllib - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "Debug"
# PROP BASE Intermediate_Dir "Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "C:\jdk1.3.0_01\include" /I "C:\jdk1.3.0_01\include\win32" /I "..\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURLLIB_EXPORTS" /YX /FD /GZ /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /debug /machine:I386 /out:"Debug/curl.dll" /pdbtype:sept
!ENDIF
# Begin Target
# Name "curllib - Win32 Release"
# Name "curllib - Win32 Debug"
# Begin Group "Source Files"
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
SOURCE=.\base64.c
# End Source File
# Begin Source File
SOURCE=.\cookie.c
# End Source File
# Begin Source File
SOURCE=.\dict.c
# End Source File
# Begin Source File
SOURCE=.\dllinit.c
# End Source File
# Begin Source File
SOURCE=.\easy.c
# End Source File
# Begin Source File
SOURCE=.\easyswig.c
# End Source File
# Begin Source File
SOURCE=.\easyswig_wrap.c
# End Source File
# Begin Source File
SOURCE=.\escape.c
# End Source File
# Begin Source File
SOURCE=.\file.c
# End Source File
# Begin Source File
SOURCE=.\formdata.c
# End Source File
# Begin Source File
SOURCE=.\ftp.c
# End Source File
# Begin Source File
SOURCE=.\getdate.c
# End Source File
# Begin Source File
SOURCE=.\getenv.c
# End Source File
# Begin Source File
SOURCE=.\getinfo.c
# End Source File
# Begin Source File
SOURCE=.\getpass.c
# End Source File
# Begin Source File
SOURCE=.\hostip.c
# End Source File
# Begin Source File
SOURCE=.\http.c
# End Source File
# Begin Source File
SOURCE=.\if2ip.c
# End Source File
# Begin Source File
SOURCE=.\krb4.c
# End Source File
# Begin Source File
SOURCE=.\ldap.c
# End Source File
# Begin Source File
SOURCE=.\libcurl.def
# End Source File
# Begin Source File
SOURCE=.\memdebug.c
# End Source File
# Begin Source File
SOURCE=.\mprintf.c
# End Source File
# Begin Source File
SOURCE=.\netrc.c
# End Source File
# Begin Source File
SOURCE=.\progress.c
# End Source File
# Begin Source File
SOURCE=.\security.c
# End Source File
# Begin Source File
SOURCE=.\sendf.c
# End Source File
# Begin Source File
SOURCE=.\speedcheck.c
# End Source File
# Begin Source File
SOURCE=.\ssluse.c
# End Source File
# Begin Source File
SOURCE=.\strequal.c
# End Source File
# Begin Source File
SOURCE=.\telnet.c
# End Source File
# Begin Source File
SOURCE=.\timeval.c
# End Source File
# Begin Source File
SOURCE=.\transfer.c
# End Source File
# Begin Source File
SOURCE=.\url.c
# End Source File
# Begin Source File
SOURCE=.\version.c
# End Source File
# End Group
# Begin Group "Header Files"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
SOURCE=.\arpa_telnet.h
# End Source File
# Begin Source File
SOURCE=.\base64.h
# End Source File
# Begin Source File
SOURCE=.\cookie.h
# End Source File
# Begin Source File
SOURCE=.\dict.h
# End Source File
# Begin Source File
SOURCE=.\escape.h
# End Source File
# Begin Source File
SOURCE=.\file.h
# End Source File
# Begin Source File
SOURCE=.\formdata.h
# End Source File
# Begin Source File
SOURCE=.\ftp.h
# End Source File
# Begin Source File
SOURCE=.\getdate.h
# End Source File
# Begin Source File
SOURCE=.\getenv.h
# End Source File
# Begin Source File
SOURCE=.\getpass.h
# End Source File
# Begin Source File
SOURCE=.\hostip.h
# End Source File
# Begin Source File
SOURCE=.\http.h
# End Source File
# Begin Source File
SOURCE=.\if2ip.h
# End Source File
# Begin Source File
SOURCE=.\inet_ntoa_r.h
# End Source File
# Begin Source File
SOURCE=.\krb4.h
# End Source File
# Begin Source File
SOURCE=.\ldap.h
# End Source File
# Begin Source File
SOURCE=.\memdebug.h
# End Source File
# Begin Source File
SOURCE=.\netrc.h
# End Source File
# Begin Source File
SOURCE=.\progress.h
# End Source File
# Begin Source File
SOURCE=.\security.h
# End Source File
# Begin Source File
SOURCE=.\sendf.h
# End Source File
# Begin Source File
SOURCE=.\setup.h
# End Source File
# Begin Source File
SOURCE=.\speedcheck.h
# End Source File
# Begin Source File
SOURCE=.\ssluse.h
# End Source File
# Begin Source File
SOURCE=.\strequal.h
# End Source File
# Begin Source File
SOURCE=.\telnet.h
# End Source File
# Begin Source File
SOURCE=.\timeval.h
# End Source File
# Begin Source File
SOURCE=.\transfer.h
# End Source File
# Begin Source File
SOURCE=.\url.h
# End Source File
# Begin Source File
SOURCE=.\urldata.h
# End Source File
# End Group
# Begin Group "Resource Files"
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
# End Group
# End Target
# End Project

29
lib/curllib.dsw Normal file
View File

@@ -0,0 +1,29 @@
Microsoft Developer Studio Workspace File, Format Version 6.00
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
###############################################################################
Project: "curllib"=".\curllib.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Global:
Package=<5>
{{{
}}}
Package=<3>
{{{
}}}
###############################################################################

View File

@@ -141,21 +141,21 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
sendf(data->firstsocket, data, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"MATCH " "MATCH "
"%s " /* database */ "%s " /* database */
"%s " /* strategy */ "%s " /* strategy */
"%s\n" /* word */ "%s\n" /* word */
"QUIT\n", "QUIT\n",
database, database,
strategy, strategy,
word word
); );
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */ -1, NULL); /* no upload */
if(result) if(result)
return result; return result;
@@ -191,20 +191,20 @@ CURLcode Curl_dict(struct connectdata *conn)
nth = atoi(nthdef); nth = atoi(nthdef);
} }
sendf(data->firstsocket, data, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"DEFINE " "DEFINE "
"%s " /* database */ "%s " /* database */
"%s\n" /* word */ "%s\n" /* word */
"QUIT\n", "QUIT\n",
database, database,
word word
); );
result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result) if(result)
return result; return result;
@@ -220,14 +220,14 @@ CURLcode Curl_dict(struct connectdata *conn)
if (ppath[i] == ':') if (ppath[i] == ':')
ppath[i] = ' '; ppath[i] = ' ';
} }
sendf(data->firstsocket, data, Curl_sendf(conn->firstsocket, conn,
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n" "CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\n"
"%s\n" "%s\n"
"QUIT\n", "QUIT\n",
ppath); ppath);
result = Curl_Transfer(conn, data->firstsocket, -1, FALSE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, FALSE, bytecount,
-1, NULL); -1, NULL);
if(result) if(result)
return result; return result;

579
lib/ftp.c
View File

@@ -88,76 +88,8 @@
/* easy-to-use macro: */ /* easy-to-use macro: */
#define ftpsendf Curl_ftpsendf #define ftpsendf Curl_ftpsendf
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
struct curl_slist *item;
/* if caller passed us a NULL, return now */
if (!list)
return NULL;
/* loop through to find the last item */
item = list;
while (item->next) {
item = item->next;
}
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data)
{
struct curl_slist *last;
struct curl_slist *new_item;
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
}
else {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL;
}
if (list) {
last = slist_get_last(list);
last->next = new_item;
return list;
}
/* if this is the first item, then new_item *is* the list */
return new_item;
}
/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
struct curl_slist *next;
struct curl_slist *item;
if (!list)
return;
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
free(item);
item = next;
} while (next);
}
static CURLcode AllowServerConnect(struct UrlData *data, static CURLcode AllowServerConnect(struct UrlData *data,
struct connectdata *conn,
int sock) int sock)
{ {
fd_set rdset; fd_set rdset;
@@ -199,7 +131,7 @@ static CURLcode AllowServerConnect(struct UrlData *data,
} }
infof(data, "Connection accepted from server\n"); infof(data, "Connection accepted from server\n");
data->secondarysocket = s; conn->secondarysocket = s;
} }
break; break;
} }
@@ -221,7 +153,7 @@ int Curl_GetFTPResponse(int sockfd, char *buf,
int *ftpcode) int *ftpcode)
{ {
int nread; int nread;
int keepon=TRUE; ssize_t keepon=TRUE;
char *ptr; char *ptr;
int timeout = 3600; /* in seconds */ int timeout = 3600; /* in seconds */
struct timeval interval; struct timeval interval;
@@ -272,22 +204,21 @@ int Curl_GetFTPResponse(int sockfd, char *buf,
break; break;
case 0: /* timeout */ case 0: /* timeout */
error = SELECT_TIMEOUT; error = SELECT_TIMEOUT;
infof(data, "Transfer aborted due to timeout\n");
failf(data, "Transfer aborted due to timeout"); failf(data, "Transfer aborted due to timeout");
break; break;
default: default:
#ifdef USE_SSLEAY /*
if (data->ssl.use) { * This code previously didn't use the kerberos sec_read() code
keepon = SSL_read(data->ssl.handle, ptr, 1); * to read, but when we use Curl_read() it may do so. Do confirm
* that this is still ok and then remove this comment!
*/
if(CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &keepon))
keepon = FALSE;
else if(keepon <= 0) {
error = SELECT_ERROR;
failf(data, "Connection aborted");
} }
else { else if ((*ptr == '\n') || (*ptr == '\r'))
#endif
keepon = sread(sockfd, ptr, 1);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
if ((*ptr == '\n') || (*ptr == '\r'))
keepon = FALSE; keepon = FALSE;
} }
if(keepon) { if(keepon) {
@@ -363,23 +294,25 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
memset(ftp, 0, sizeof(struct FTP)); memset(ftp, 0, sizeof(struct FTP));
data->proto.ftp = ftp; conn->proto.ftp = ftp;
/* get some initial data into the ftp struct */ /* get some initial data into the ftp struct */
ftp->bytecountp = &conn->bytecount; ftp->bytecountp = &conn->bytecount;
ftp->user = data->user;
ftp->passwd = data->passwd; /* duplicate to keep them even when the data struct changes */
ftp->user = strdup(data->user);
ftp->passwd = strdup(data->passwd);
if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(data, data->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
data->hostname, data->remote_port); conn->hostname, conn->remote_port);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
/* The first thing we do is wait for the "220*" line: */ /* The first thing we do is wait for the "220*" line: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -399,7 +332,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
set a valid level */ set a valid level */
sec_request_prot(conn, data->krb4_level); sec_request_prot(conn, data->krb4_level);
data->cmdchannel = fdopen(data->firstsocket, "w"); data->cmdchannel = fdopen(conn->firstsocket, "w");
if(sec_login(conn) != 0) if(sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n"); infof(data, "Logging in with password in cleartext!\n");
@@ -409,10 +342,10 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
#endif #endif
/* send USER */ /* send USER */
ftpsendf(data->firstsocket, conn, "USER %s", ftp->user); ftpsendf(conn->firstsocket, conn, "USER %s", ftp->user);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -425,8 +358,8 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
else if(ftpcode == 331) { else if(ftpcode == 331) {
/* 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) */
ftpsendf(data->firstsocket, conn, "PASS %s", ftp->passwd); ftpsendf(conn->firstsocket, conn, "PASS %s", ftp->passwd);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -470,6 +403,58 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
return CURLE_FTP_WEIRD_USER_REPLY; return CURLE_FTP_WEIRD_USER_REPLY;
} }
/* send PWD to discover our entry point */
ftpsendf(conn->firstsocket, conn, "PWD");
/* wait for feedback */
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(ftpcode == 257) {
char *dir = (char *)malloc(nread+1);
char *store=dir;
char *ptr=&buf[4]; /* start on the first letter */
/* Reply format is like
257<space>"<directory-name>"<space><commentary> and the RFC959 says
The directory name can contain any character; embedded double-quotes
should be escaped by double-quotes (the "quote-doubling" convention).
*/
if('\"' == *ptr) {
/* it started good */
ptr++;
while(ptr && *ptr) {
if('\"' == *ptr) {
if('\"' == ptr[1]) {
/* "quote-doubling" */
*store = ptr[1];
ptr++;
}
else {
/* end of path */
*store = '\0'; /* zero terminate */
break; /* get out of this loop */
}
}
else
*store = *ptr;
store++;
ptr++;
}
ftp->entrypath =dir; /* remember this */
infof(data, "Entry path is '%s'\n", ftp->entrypath);
}
else {
/* couldn't get the path */
}
}
else {
/* We couldn't read the PWD response! */
}
return CURLE_OK; return CURLE_OK;
} }
@@ -478,7 +463,7 @@ CURLcode Curl_ftp_connect(struct connectdata *conn)
CURLcode Curl_ftp_done(struct connectdata *conn) CURLcode Curl_ftp_done(struct connectdata *conn)
{ {
struct UrlData *data = conn->data; struct UrlData *data = conn->data;
struct FTP *ftp = data->proto.ftp; struct FTP *ftp = conn->proto.ftp;
size_t nread; size_t nread;
char *buf = data->buffer; /* this is our buffer */ char *buf = data->buffer; /* this is our buffer */
struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */
@@ -493,7 +478,7 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
else { else {
if((-1 != conn->size) && (conn->size != *ftp->bytecountp) && if((-1 != conn->size) && (conn->size != *ftp->bytecountp) &&
(data->maxdownload != *ftp->bytecountp)) { (conn->maxdownload != *ftp->bytecountp)) {
failf(data, "Received only partial file"); failf(data, "Received only partial file");
return CURLE_PARTIAL_FILE; return CURLE_PARTIAL_FILE;
} }
@@ -503,16 +488,16 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
} }
#ifdef KRB4 #ifdef KRB4
sec_fflush_fd(conn, data->secondarysocket); sec_fflush_fd(conn, conn->secondarysocket);
#endif #endif
/* shut down the socket to inform the server we're done */ /* shut down the socket to inform the server we're done */
sclose(data->secondarysocket); sclose(conn->secondarysocket);
data->secondarysocket = -1; conn->secondarysocket = -1;
if(!data->bits.no_body) { if(!data->bits.no_body) {
/* now let's see what the server says about the transfer we /* now let's see what the server says about the transfer we
just performed: */ just performed: */
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -530,9 +515,9 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
while (qitem) { while (qitem) {
/* Send string */ /* Send string */
if (qitem->data) { if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data); ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -546,9 +531,6 @@ CURLcode Curl_ftp_done(struct connectdata *conn)
} }
} }
free(ftp);
data->proto.ftp=NULL; /* it is gone */
return CURLE_OK; return CURLE_OK;
} }
@@ -569,10 +551,13 @@ CURLcode _ftp(struct connectdata *conn)
#if defined (HAVE_INET_NTOA_R) #if defined (HAVE_INET_NTOA_R)
char ntoa_buf[64]; char ntoa_buf[64];
#endif #endif
#ifdef ENABLE_IPV6
struct addrinfo *ai;
#endif
struct curl_slist *qitem; /* QUOTE item */ struct curl_slist *qitem; /* QUOTE item */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
struct FTP *ftp = data->proto.ftp; struct FTP *ftp = conn->proto.ftp;
long *bytecountp = ftp->bytecountp; long *bytecountp = ftp->bytecountp;
int ftpcode; /* for ftp status */ int ftpcode; /* for ftp status */
@@ -584,9 +569,9 @@ CURLcode _ftp(struct connectdata *conn)
while (qitem) { while (qitem) {
/* Send string */ /* Send string */
if (qitem->data) { if (qitem->data) {
ftpsendf(data->firstsocket, conn, "%s", qitem->data); ftpsendf(conn->firstsocket, conn, "%s", qitem->data);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -600,10 +585,27 @@ CURLcode _ftp(struct connectdata *conn)
} }
} }
if(conn->bits.reuse) {
/* This is a re-used connection. Since we change directory to where the
transfer is taking place, we must now get back to the original dir
where we ended up after login: */
ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->entrypath);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(ftpcode != 250) {
failf(data, "Couldn't change back to directory %s", ftp->entrypath);
return CURLE_FTP_ACCESS_DENIED;
}
}
/* change directory first! */ /* change directory first! */
if(ftp->dir && ftp->dir[0]) { if(ftp->dir && ftp->dir[0]) {
ftpsendf(data->firstsocket, conn, "CWD %s", ftp->dir); ftpsendf(conn->firstsocket, conn, "CWD %s", ftp->dir);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -616,9 +618,9 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.get_filetime && ftp->file) { if(data->bits.get_filetime && ftp->file) {
/* we have requested to get the modified-time of the file, this is yet /* we have requested to get the modified-time of the file, this is yet
again a grey area as the MDTM is not kosher RFC959 */ again a grey area as the MDTM is not kosher RFC959 */
ftpsendf(data->firstsocket, conn, "MDTM %s", ftp->file); ftpsendf(conn->firstsocket, conn, "MDTM %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -652,10 +654,10 @@ CURLcode _ftp(struct connectdata *conn)
/* Some servers return different sizes for different modes, and thus we /* Some servers return different sizes for different modes, and thus we
must set the proper type before we check the size */ must set the proper type before we check the size */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -666,9 +668,9 @@ CURLcode _ftp(struct connectdata *conn)
CURLE_FTP_COULDNT_SET_BINARY; CURLE_FTP_COULDNT_SET_BINARY;
} }
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -707,6 +709,178 @@ CURLcode _ftp(struct connectdata *conn)
/* We have chosen to use the PORT command */ /* We have chosen to use the PORT command */
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
#ifdef ENABLE_IPV6
struct addrinfo hints, *res, *ai;
struct sockaddr_storage ss;
int sslen;
char hbuf[NI_MAXHOST];
char *localaddr;
struct sockaddr *sa=(struct sockaddr *)&ss;
#ifdef NI_WITHSCOPEID
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
#else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif
unsigned char *ap;
unsigned char *pp;
int alen, plen;
char portmsgbuf[4096], tmp[4096];
char *p;
char *mode[] = { "EPRT", "LPRT", "PORT", NULL };
char **modep;
/*
* we should use Curl_if2ip? given pickiness of recent ftpd,
* I believe we should use the same address as the control connection.
*/
sslen = sizeof(ss);
if (getsockname(conn->firstsocket, (struct sockaddr *)&ss, &sslen) < 0)
return CURLE_FTP_PORT_FAILED;
if (getnameinfo((struct sockaddr *)&ss, sslen, hbuf, sizeof(hbuf), NULL, 0,
niflags))
return CURLE_FTP_PORT_FAILED;
memset(&hints, 0, sizeof(hints));
hints.ai_family = sa->sa_family;
/*hints.ai_family = ss.ss_family;
this way can be used if sockaddr_storage is properly defined, as glibc
2.1.X doesn't do*/
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (getaddrinfo(hbuf, "0", &hints, &res))
return CURLE_FTP_PORT_FAILED;
portsock = -1;
for (ai = res; ai; ai = ai->ai_next) {
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (portsock < 0)
continue;
if (bind(portsock, ai->ai_addr, ai->ai_addrlen) < 0) {
close(portsock);
portsock = -1;
continue;
}
if (listen(portsock, 1) < 0) {
close(portsock);
portsock = -1;
continue;
}
break;
}
if (portsock < 0) {
failf(data, strerror(errno));
freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED;
}
sslen = sizeof(ss);
if (getsockname(portsock, sa, &sslen) < 0) {
failf(data, strerror(errno));
freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED;
}
for (modep = mode; modep && *modep; modep++) {
int lprtaf, eprtaf;
switch (sa->sa_family) {
case AF_INET:
ap = (char *)&((struct sockaddr_in *)&ss)->sin_addr;
alen = sizeof(((struct sockaddr_in *)&ss)->sin_addr);
pp = (char *)&((struct sockaddr_in *)&ss)->sin_port;
plen = sizeof(((struct sockaddr_in *)&ss)->sin_port);
lprtaf = 4;
eprtaf = 1;
break;
case AF_INET6:
ap = (char *)&((struct sockaddr_in6 *)&ss)->sin6_addr;
alen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_addr);
pp = (char *)&((struct sockaddr_in6 *)&ss)->sin6_port;
plen = sizeof(((struct sockaddr_in6 *)&ss)->sin6_port);
lprtaf = 6;
eprtaf = 2;
break;
default:
ap = pp = NULL;
lprtaf = eprtaf = -1;
break;
}
if (strcmp(*modep, "EPRT") == 0) {
if (eprtaf < 0)
continue;
if (getnameinfo((struct sockaddr *)&ss, sslen,
portmsgbuf, sizeof(portmsgbuf), tmp, sizeof(tmp), niflags))
continue;
/* do not transmit IPv6 scope identifier to the wire */
if (sa->sa_family == AF_INET6) {
char *q = strchr(portmsgbuf, '%');
if (q)
*q = '\0';
}
ftpsendf(conn->firstsocket, conn, "%s |%d|%s|%s|", *modep, eprtaf,
portmsgbuf, tmp);
} else if (strcmp(*modep, "LPRT") == 0 || strcmp(*modep, "PORT") == 0) {
int i;
if (strcmp(*modep, "LPRT") == 0 && lprtaf < 0)
continue;
if (strcmp(*modep, "PORT") == 0 && sa->sa_family != AF_INET)
continue;
portmsgbuf[0] = '\0';
if (strcmp(*modep, "LPRT") == 0) {
snprintf(tmp, sizeof(tmp), "%d,%d", lprtaf, alen);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
goto again;
}
}
for (i = 0; i < alen; i++) {
if (portmsgbuf[0])
snprintf(tmp, sizeof(tmp), ",%u", ap[i]);
else
snprintf(tmp, sizeof(tmp), "%u", ap[i]);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
goto again;
}
}
if (strcmp(*modep, "LPRT") == 0) {
snprintf(tmp, sizeof(tmp), ",%d", plen);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf))
goto again;
}
for (i = 0; i < plen; i++) {
snprintf(tmp, sizeof(tmp), ",%u", pp[i]);
if (strlcat(portmsgbuf, tmp, sizeof(portmsgbuf)) >= sizeof(portmsgbuf)) {
goto again;
}
}
ftpsendf(conn->firstsocket, conn, "%s %s", *modep, portmsgbuf);
}
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if (nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if (ftpcode != 200) {
failf(data, "Server does not grok %s", *modep);
continue;
} else
break;
again:;
}
if (!*modep) {
close(portsock);
freeaddrinfo(res);
return CURLE_FTP_PORT_FAILED;
}
#else
struct sockaddr_in sa; struct sockaddr_in sa;
struct hostent *h=NULL; struct hostent *h=NULL;
char *hostdataptr=NULL; char *hostdataptr=NULL;
@@ -738,7 +912,7 @@ CURLcode _ftp(struct connectdata *conn)
/* we set the secondary socket variable to this for now, it /* we set the secondary socket variable to this for now, it
is only so that the cleanup function will close it in case is only so that the cleanup function will close it in case
we fail before the true secondary stuff is made */ we fail before the true secondary stuff is made */
data->secondarysocket = portsock; conn->secondarysocket = portsock;
memset((char *)&sa, 0, sizeof(sa)); memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr, memcpy((char *)&sa.sin_addr,
@@ -800,13 +974,13 @@ CURLcode _ftp(struct connectdata *conn)
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 #endif
ftpsendf(data->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d", ftpsendf(conn->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d",
ip[0], ip[1], ip[2], ip[3], ip[0], ip[1], ip[2], ip[3],
porttouse >> 8, porttouse >> 8,
porttouse & 255); porttouse & 255);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -814,26 +988,43 @@ CURLcode _ftp(struct connectdata *conn)
failf(data, "Server does not grok PORT, try without it!"); failf(data, "Server does not grok PORT, try without it!");
return CURLE_FTP_PORT_FAILED; return CURLE_FTP_PORT_FAILED;
} }
#endif /* ENABLE_IPV6 */
} }
else { /* we use the PASV command */ else { /* we use the PASV command */
#if 0
char *mode[] = { "EPSV", "LPSV", "PASV", NULL };
int results[] = { 229, 228, 227, 0 };
#else
char *mode[] = { "PASV", NULL };
int results[] = { 227, 0 };
#endif
int modeoff;
ftpsendf(data->firstsocket, conn, "PASV"); for (modeoff = 0; mode[modeoff]; modeoff++) {
ftpsendf(conn->firstsocket, conn, mode[modeoff]);
nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); if (ftpcode == results[modeoff])
if(nread < 0) break;
return CURLE_OPERATION_TIMEOUTED; }
if(ftpcode != 227) { if (!mode[modeoff]) {
failf(data, "Odd return code after PASV"); failf(data, "Odd return code after PASV");
return CURLE_FTP_WEIRD_PASV_REPLY; return CURLE_FTP_WEIRD_PASV_REPLY;
} }
else { else if (strcmp(mode[modeoff], "PASV") == 0) {
int ip[4]; int ip[4];
int port[2]; int port[2];
unsigned short newport; /* remote port, not necessary the local one */ unsigned short newport; /* remote port, not necessary the local one */
unsigned short connectport; /* the local port connect() should use! */ unsigned short connectport; /* the local port connect() should use! */
char newhost[32]; char newhost[32];
#ifdef ENABLE_IPV6
struct addrinfo *res;
#else
struct hostent *he; struct hostent *he;
#endif
char *str=buf,*ip_addr; char *str=buf,*ip_addr;
char *hostdataptr=NULL; char *hostdataptr=NULL;
@@ -868,21 +1059,79 @@ CURLcode _ftp(struct connectdata *conn)
* proxy again here. We already have the name info for it since the * proxy again here. We already have the name info for it since the
* previous lookup. * previous lookup.
*/ */
#ifdef ENABLE_IPV6
res = conn->hp;
#else
he = conn->hp; he = conn->hp;
#endif
connectport = connectport =
(unsigned short)data->port; /* we connect to the proxy's port */ (unsigned short)conn->port; /* we connect to the proxy's port */
} }
else { else {
/* normal, direct, ftp connection */ /* normal, direct, ftp connection */
#ifdef ENABLE_IPV6
res = Curl_getaddrinfo(data, newhost, newport);
if(!res)
#else
he = Curl_gethost(data, newhost, &hostdataptr); he = Curl_gethost(data, newhost, &hostdataptr);
if(!he) { if(!he)
#endif
{
failf(data, "Can't resolve new host %s", newhost); failf(data, "Can't resolve new host %s", newhost);
return CURLE_FTP_CANT_GET_HOST; return CURLE_FTP_CANT_GET_HOST;
} }
connectport = newport; /* we connect to the remote port */ connectport = newport; /* we connect to the remote port */
} }
data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0); #ifdef ENABLE_IPV6
conn->secondarysocket = -1;
for (ai = res; ai; ai = ai->ai_next) {
/* XXX for now, we can do IPv4 only */
if (ai->ai_family != AF_INET)
continue;
conn->secondarysocket = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
if (conn->secondarysocket < 0)
continue;
if(data->bits.verbose) {
char hbuf[NI_MAXHOST];
char nbuf[NI_MAXHOST];
char sbuf[NI_MAXSERV];
#ifdef NI_WITHSCOPEID
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV | NI_WITHSCOPEID;
#else
const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
#endif
if (getnameinfo(res->ai_addr, res->ai_addrlen, nbuf, sizeof(nbuf),
sbuf, sizeof(sbuf), niflags)) {
snprintf(nbuf, sizeof(nbuf), "?");
snprintf(sbuf, sizeof(sbuf), "?");
}
if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
NULL, 0, 0)) {
infof(data, "Connecting to %s port %s\n", nbuf, sbuf);
} else {
infof(data, "Connecting to %s (%s) port %s\n", hbuf, nbuf, sbuf);
}
}
if (connect(conn->secondarysocket, ai->ai_addr, ai->ai_addrlen) < 0) {
close(conn->secondarysocket);
conn->secondarysocket = -1;
continue;
}
break;
}
if (conn->secondarysocket < 0) {
failf(data, strerror(errno));
return CURLE_FTP_CANT_RECONNECT;
}
#else
conn->secondarysocket = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, '\0', sizeof(serv_addr)); memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length); memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length);
@@ -956,7 +1205,7 @@ CURLcode _ftp(struct connectdata *conn)
if(hostdataptr) if(hostdataptr)
free(hostdataptr); free(hostdataptr);
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr, if (connect(conn->secondarysocket, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) { sizeof(serv_addr)) < 0) {
switch(errno) { switch(errno) {
#ifdef ECONNREFUSED #ifdef ECONNREFUSED
@@ -967,7 +1216,7 @@ CURLcode _ftp(struct connectdata *conn)
#endif #endif
#ifdef EINTR #ifdef EINTR
case EINTR: case EINTR:
failf(data, "Connection timeouted to ftp server"); failf(data, "Connection timed out to ftp server");
break; break;
#endif #endif
default: default:
@@ -976,14 +1225,17 @@ CURLcode _ftp(struct connectdata *conn)
} }
return CURLE_FTP_CANT_RECONNECT; return CURLE_FTP_CANT_RECONNECT;
} }
#endif /*ENABLE_IPV6*/
if (data->bits.tunnel_thru_httpproxy) { if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */ /* We want "seamless" FTP operations through HTTP proxy tunnel */
result = Curl_ConnectHTTPProxyTunnel(data, data->secondarysocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->secondarysocket,
newhost, newport); newhost, newport);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
} else {
return CURLE_FTP_CANT_RECONNECT;
} }
} }
/* we have the (new) data connection ready */ /* we have the (new) data connection ready */
@@ -992,10 +1244,10 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.upload) { if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1024,9 +1276,9 @@ CURLcode _ftp(struct connectdata *conn)
/* 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 */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1083,11 +1335,11 @@ CURLcode _ftp(struct connectdata *conn)
/* Send everything on data->in to the socket */ /* Send everything on data->in to the socket */
if(data->bits.ftp_append) if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */ /* we append onto the file instead of rewriting it */
ftpsendf(data->firstsocket, conn, "APPE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "APPE %s", ftp->file);
else else
ftpsendf(data->firstsocket, conn, "STOR %s", ftp->file); ftpsendf(conn->firstsocket, conn, "STOR %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1098,7 +1350,7 @@ CURLcode _ftp(struct connectdata *conn)
} }
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, conn, portsock);
if( result ) if( result )
return result; return result;
} }
@@ -1111,7 +1363,7 @@ CURLcode _ftp(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, data->infilesize); Curl_pgrsSetUploadSize(data, data->infilesize);
result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */ result = Curl_Transfer(conn, -1, -1, FALSE, NULL, /* no download */
data->secondarysocket, bytecountp); conn->secondarysocket, bytecountp);
if(result) if(result)
return result; return result;
@@ -1143,16 +1395,16 @@ CURLcode _ftp(struct connectdata *conn)
else if(from < 0) { else if(from < 0) {
/* -Y */ /* -Y */
totalsize = -from; totalsize = -from;
data->maxdownload = -from; conn->maxdownload = -from;
data->resume_from = from; data->resume_from = from;
infof(data, "FTP RANGE the last %d bytes\n", totalsize); infof(data, "FTP RANGE the last %d bytes\n", totalsize);
} }
else { else {
/* X-Y */ /* X-Y */
totalsize = to-from; totalsize = to-from;
data->maxdownload = totalsize+1; /* include the last mentioned byte */ conn->maxdownload = totalsize+1; /* include the last mentioned byte */
data->resume_from = from; data->resume_from = from;
infof(data, "FTP RANGE from %d getting %d bytes\n", from, data->maxdownload); infof(data, "FTP RANGE from %d getting %d bytes\n", from, conn->maxdownload);
} }
infof(data, "range-download from %d to %d, totally %d bytes\n", infof(data, "range-download from %d to %d, totally %d bytes\n",
from, to, totalsize); from, to, totalsize);
@@ -1165,9 +1417,9 @@ CURLcode _ftp(struct connectdata *conn)
dirlist = TRUE; dirlist = TRUE;
/* Set type to ASCII */ /* Set type to ASCII */
ftpsendf(data->firstsocket, conn, "TYPE A"); ftpsendf(conn->firstsocket, conn, "TYPE A");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1180,16 +1432,16 @@ CURLcode _ftp(struct connectdata *conn)
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 */
ftpsendf(data->firstsocket, conn, "%s", ftpsendf(conn->firstsocket, conn, "%s",
data->customrequest?data->customrequest: data->customrequest?data->customrequest:
(data->bits.ftp_list_only?"NLST":"LIST")); (data->bits.ftp_list_only?"NLST":"LIST"));
} }
else { else {
/* Set type to binary (unless specified ASCII) */ /* Set type to binary (unless specified ASCII) */
ftpsendf(data->firstsocket, conn, "TYPE %s", ftpsendf(conn->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I"); (data->bits.ftp_ascii)?"A":"I");
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1208,9 +1460,9 @@ CURLcode _ftp(struct connectdata *conn)
* 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. */
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file); ftpsendf(conn->firstsocket, conn, "SIZE %s", ftp->file);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1252,9 +1504,9 @@ CURLcode _ftp(struct connectdata *conn)
infof(data, "Instructs server to resume from offset %d\n", infof(data, "Instructs server to resume from offset %d\n",
data->resume_from); data->resume_from);
ftpsendf(data->firstsocket, conn, "REST %d", data->resume_from); ftpsendf(conn->firstsocket, conn, "REST %d", data->resume_from);
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1264,10 +1516,10 @@ CURLcode _ftp(struct connectdata *conn)
} }
} }
ftpsendf(data->firstsocket, conn, "RETR %s", ftp->file); ftpsendf(conn->firstsocket, conn, "RETR %s", ftp->file);
} }
nread = Curl_GetFTPResponse(data->firstsocket, buf, conn, &ftpcode); nread = Curl_GetFTPResponse(conn->firstsocket, buf, conn, &ftpcode);
if(nread < 0) if(nread < 0)
return CURLE_OPERATION_TIMEOUTED; return CURLE_OPERATION_TIMEOUTED;
@@ -1331,7 +1583,7 @@ CURLcode _ftp(struct connectdata *conn)
size = downloadsize; size = downloadsize;
if(data->bits.ftp_use_port) { if(data->bits.ftp_use_port) {
result = AllowServerConnect(data, portsock); result = AllowServerConnect(data, conn, portsock);
if( result ) if( result )
return result; return result;
} }
@@ -1339,7 +1591,7 @@ CURLcode _ftp(struct connectdata *conn)
infof(data, "Getting file with size: %d\n", size); infof(data, "Getting file with size: %d\n", size);
/* FTP download: */ /* FTP download: */
result=Curl_Transfer(conn, data->secondarysocket, size, FALSE, result=Curl_Transfer(conn, conn->secondarysocket, size, FALSE,
bytecountp, bytecountp,
-1, NULL); /* no upload here */ -1, NULL); /* no upload here */
if(result) if(result)
@@ -1368,7 +1620,7 @@ CURLcode Curl_ftp(struct connectdata *conn)
int dirlength=0; /* 0 forces strlen() */ int dirlength=0; /* 0 forces strlen() */
/* the ftp struct is already inited in ftp_connect() */ /* the ftp struct is already inited in ftp_connect() */
ftp = data->proto.ftp; ftp = conn->proto.ftp;
/* We split the path into dir and file parts *before* we URLdecode /* We split the path into dir and file parts *before* we URLdecode
it */ it */
@@ -1457,3 +1709,16 @@ size_t Curl_ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
} }
CURLcode Curl_ftp_disconnect(struct connectdata *conn)
{
struct FTP *ftp= conn->proto.ftp;
if(ftp->user)
free(ftp->user);
if(ftp->passwd)
free(ftp->passwd);
if(ftp->entrypath)
free(ftp->entrypath);
return CURLE_OK;
}

View File

@@ -26,12 +26,10 @@
CURLcode Curl_ftp(struct connectdata *conn); CURLcode Curl_ftp(struct connectdata *conn);
CURLcode Curl_ftp_done(struct connectdata *conn); CURLcode Curl_ftp_done(struct connectdata *conn);
CURLcode Curl_ftp_connect(struct connectdata *conn); CURLcode Curl_ftp_connect(struct connectdata *conn);
CURLcode Curl_ftp_disconnect(struct connectdata *conn);
size_t Curl_ftpsendf(int fd, struct connectdata *, char *fmt, ...); size_t Curl_ftpsendf(int fd, struct connectdata *, char *fmt, ...);
struct curl_slist *curl_slist_append(struct curl_slist *list, char *data);
void curl_slist_free_all(struct curl_slist *list);
/* The kerberos stuff needs this: */ /* The kerberos stuff needs this: */
int Curl_GetFTPResponse(int sockfd, char *buf, int Curl_GetFTPResponse(int sockfd, char *buf,
struct connectdata *conn, struct connectdata *conn,

View File

@@ -390,7 +390,7 @@ 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/local/share/bison.simple" #line 3 "/usr/lib/bison.simple"
/* This file comes from bison-1.28. */ /* This file comes from bison-1.28. */
/* Skeleton output parser for bison, /* Skeleton output parser for bison,
@@ -604,7 +604,7 @@ __yy_memcpy (char *to, char *from, unsigned int count)
#endif #endif
#endif #endif
#line 217 "/usr/local/share/bison.simple" #line 217 "/usr/lib/bison.simple"
/* The user can define YYPARSE_PARAM as the name of an argument to be passed /* The user can define YYPARSE_PARAM as the name of an argument to be passed
into yyparse. The argument should have type void *. into yyparse. The argument should have type void *.
@@ -1295,7 +1295,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 543 "/usr/local/share/bison.simple" #line 543 "/usr/lib/bison.simple"
yyvsp -= yylen; yyvsp -= yylen;
yyssp -= yylen; yyssp -= yylen;

View File

@@ -41,12 +41,13 @@ char *GetEnv(char *variable)
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)); if (temp != NULL)
ExpandEnvironmentStrings(temp, env, sizeof(env));
#else #else
/* no length control */ /* no length control */
char *env = getenv(variable); char *env = getenv(variable);
#endif #endif
return env?strdup(env):NULL; return (env && env[0])?strdup(env):NULL;
} }
char *curl_getenv(char *v) char *curl_getenv(char *v)

View File

@@ -1,28 +0,0 @@
#ifndef __GETENV_H
#define __GETENV_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2000, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* In order to be useful for every potential user, curl and libcurl are
* dual-licensed under the MPL and the MIT/X-derivate licenses.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the MPL or the MIT/X-derivate
* licenses. You may pick one of these licenses.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id$
*****************************************************************************/
#include <curl/curl.h>
#endif

View File

@@ -103,6 +103,12 @@ CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...)
case CURLINFO_SSL_VERIFYRESULT: case CURLINFO_SSL_VERIFYRESULT:
*param_longp = data->ssl.certverifyresult; *param_longp = data->ssl.certverifyresult;
break; break;
case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
*param_doublep = data->progress.size_dl;
break;
case CURLINFO_CONTENT_LENGTH_UPLOAD:
*param_doublep = data->progress.size_ul;
break;
default: default:
return CURLE_BAD_FUNCTION_ARGUMENT; return CURLE_BAD_FUNCTION_ARGUMENT;
} }

View File

@@ -83,6 +83,29 @@ static char *MakeIP(unsigned long num,char *addr, int addr_len)
return (addr); return (addr);
} }
#ifdef ENABLE_IPV6
struct addrinfo *Curl_getaddrinfo(struct UrlData *data,
char *hostname,
int port)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_CANONNAME;
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s\n", hostname);
return NULL;
}
return res;
}
#endif
/* The original code to this function was once stolen from the Dancer source /* The original code to this function was once stolen from the Dancer source
code, written by Bjorn Reese, it has since been patched and modified code, written by Bjorn Reese, it has since been patched and modified
considerably. */ considerably. */

View File

@@ -23,6 +23,11 @@
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
struct addrinfo;
struct addrinfo *Curl_getaddrinfo(struct UrlData *data,
char *hostname,
int port);
struct hostent *Curl_gethost(struct UrlData *data, struct hostent *Curl_gethost(struct UrlData *data,
char *hostname, char *hostname,
char **bufp); char **bufp);

View File

@@ -94,7 +94,6 @@
#include "base64.h" #include "base64.h"
#include "cookie.h" #include "cookie.h"
#include "strequal.h" #include "strequal.h"
#include "url.h"
#include "ssluse.h" #include "ssluse.h"
#define _MPRINTF_REPLACE /* use our functions only */ #define _MPRINTF_REPLACE /* use our functions only */
@@ -141,7 +140,7 @@ size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in)
fwrite(in->buffer, in->size_used, 1, conn->data->err); fwrite(in->buffer, in->size_used, 1, conn->data->err);
} }
amount = ssend(sockfd, conn, in->buffer, in->size_used); Curl_write(conn, sockfd, in->buffer, in->size_used, &amount);
if(in->buffer) if(in->buffer)
free(in->buffer); free(in->buffer);
@@ -213,38 +212,32 @@ CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
*/ */
static static
int GetLine(int sockfd, char *buf, struct UrlData *data) int GetLine(int sockfd, char *buf, struct connectdata *conn)
{ {
int nread; ssize_t nread;
int read_rc=1; int read_rc=1;
char *ptr; char *ptr;
struct UrlData *data=conn->data;
ptr=buf; ptr=buf;
/* get us a full line, terminated with a newline */ /* get us a full line, terminated with a newline */
for(nread=0; for(nread=0;
(nread<BUFSIZE) && read_rc; (nread<BUFSIZE) && read_rc;
nread++, ptr++) { nread++, ptr++) {
#ifdef USE_SSLEAY if((CURLE_OK != Curl_read(conn, sockfd, ptr, 1, &nread)) ||
if (data->ssl.use) { (nread <= 0) ||
read_rc = SSL_read(data->ssl.handle, ptr, 1); (*ptr == '\n'))
}
else {
#endif
read_rc = sread(sockfd, ptr, 1);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
if (*ptr == '\n')
break; break;
} }
*ptr=0; /* zero terminate */ *ptr=0; /* zero terminate */
if(data->bits.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);
} }
return nread; return nread>0?nread:0;
} }
@@ -272,27 +265,29 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
* this proxy. After that, the socket can be used just as a normal socket. * this proxy. After that, the socket can be used just as a normal socket.
*/ */
CURLcode Curl_ConnectHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
int tunnelsocket,
char *hostname, int remote_port) char *hostname, int remote_port)
{ {
int httperror=0; int httperror=0;
int subversion=0; int subversion=0;
struct UrlData *data=conn->data;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port); infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
/* OK, now send the connect statment */ /* OK, now send the connect request to the proxy */
sendf(tunnelsocket, data, Curl_sendf(tunnelsocket, conn,
"CONNECT %s:%d HTTP/1.0\015\012" "CONNECT %s:%d HTTP/1.0\015\012"
"%s" "%s"
"%s" "%s"
"\r\n", "\r\n",
hostname, remote_port, hostname, remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"", (data->bits.proxy_user_passwd)?conn->allocptr.proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"") (data->useragent?conn->allocptr.uagent:"")
); );
/* wait for the proxy to send us a HTTP/1.0 200 OK header */ /* wait for the proxy to send us a HTTP/1.0 200 OK header */
while(GetLine(tunnelsocket, data->buffer, data)) { while(GetLine(tunnelsocket, data->buffer, conn)) {
if('\r' == data->buffer[0]) if('\r' == data->buffer[0])
break; /* end of headers */ break; /* end of headers */
if(2 == sscanf(data->buffer, "HTTP/1.%d %d", if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
@@ -330,21 +325,21 @@ CURLcode Curl_http_connect(struct connectdata *conn)
if (conn->protocol & PROT_HTTPS) { if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) { if (data->bits.httpproxy) {
/* HTTPS through a proxy can only be done with a tunnel */ /* HTTPS through a proxy can only be done with a tunnel */
result = Curl_ConnectHTTPProxyTunnel(data, data->firstsocket, result = Curl_ConnectHTTPProxyTunnel(conn, conn->firstsocket,
data->hostname, data->remote_port); conn->hostname, conn->remote_port);
if(CURLE_OK != result) if(CURLE_OK != result)
return result; return result;
} }
/* now, perform the SSL initialization for this socket */ /* now, perform the SSL initialization for this socket */
if(Curl_SSLConnect(data)) if(Curl_SSLConnect(conn))
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CONNECT_ERROR;
} }
if(data->bits.user_passwd && !data->bits.this_is_a_follow) { if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the /* Authorization: is requested, this is not a followed location, get the
original host name */ original host name */
data->auth_host = strdup(data->hostname); data->auth_host = strdup(conn->hostname);
} }
return CURLE_OK; return CURLE_OK;
@@ -366,7 +361,7 @@ CURLcode Curl_http_done(struct connectdata *conn)
struct HTTP *http; struct HTTP *http;
data=conn->data; data=conn->data;
http=data->proto.http; http=conn->proto.http;
if(data->bits.http_formpost) { if(data->bits.http_formpost) {
*bytecount = http->readbytecount + http->writebytecount; *bytecount = http->readbytecount + http->writebytecount;
@@ -380,9 +375,6 @@ CURLcode Curl_http_done(struct connectdata *conn)
*bytecount = http->readbytecount + http->writebytecount; *bytecount = http->readbytecount + http->writebytecount;
} }
free(http);
data->proto.http=NULL; /* it is gone */
return CURLE_OK; return CURLE_OK;
} }
@@ -398,11 +390,17 @@ CURLcode Curl_http(struct connectdata *conn)
char *host = conn->name; char *host = conn->name;
long *bytecount = &conn->bytecount; long *bytecount = &conn->bytecount;
http = (struct HTTP *)malloc(sizeof(struct HTTP)); if(!conn->proto.http) {
if(!http) /* Only allocate this struct if we don't already have it! */
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP)); http = (struct HTTP *)malloc(sizeof(struct HTTP));
data->proto.http = http; if(!http)
return CURLE_OUT_OF_MEMORY;
memset(http, 0, sizeof(struct HTTP));
conn->proto.http = http;
}
else
http = conn->proto.http;
if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) && if ( (conn->protocol&(PROT_HTTP|PROT_FTP)) &&
data->bits.upload) { data->bits.upload) {
@@ -413,9 +411,9 @@ CURLcode Curl_http(struct connectdata *conn)
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
the user-agent string specified, we erase the previously made string the user-agent string specified, we erase the previously made string
here. */ here. */
if(checkheaders(data, "User-Agent:") && data->ptr_uagent) { if(checkheaders(data, "User-Agent:") && conn->allocptr.uagent) {
free(data->ptr_uagent); free(conn->allocptr.uagent);
data->ptr_uagent=NULL; conn->allocptr.uagent=NULL;
} }
if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) { if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
@@ -425,24 +423,27 @@ CURLcode Curl_http(struct connectdata *conn)
host due to a location-follow, we do some weirdo checks here */ host due to a location-follow, we do some weirdo checks here */
if(!data->bits.this_is_a_follow || if(!data->bits.this_is_a_follow ||
!data->auth_host || !data->auth_host ||
strequal(data->auth_host, data->hostname)) { strequal(data->auth_host, conn->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd); sprintf(data->buffer, "%s:%s", data->user, data->passwd);
if(Curl_base64_encode(data->buffer, strlen(data->buffer), if(Curl_base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) { &authorization) >= 0) {
data->ptr_userpwd = aprintf( "Authorization: Basic %s\015\012", if(conn->allocptr.userpwd)
free(conn->allocptr.userpwd);
conn->allocptr.userpwd = aprintf( "Authorization: Basic %s\015\012",
authorization); authorization);
free(authorization); free(authorization);
} }
} }
} }
if((data->bits.set_range) && !checkheaders(data, "Range:")) {
data->ptr_rangeline = aprintf("Range: bytes=%s\015\012", data->range);
}
if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) { if((data->bits.http_set_referer) && !checkheaders(data, "Referer:")) {
data->ptr_ref = aprintf("Referer: %s\015\012", data->referer); if(conn->allocptr.ref)
free(conn->allocptr.ref);
conn->allocptr.ref = aprintf("Referer: %s\015\012", data->referer);
} }
if(data->cookie && !checkheaders(data, "Cookie:")) { if(data->cookie && !checkheaders(data, "Cookie:")) {
data->ptr_cookie = aprintf("Cookie: %s\015\012", data->cookie); if(conn->allocptr.cookie)
free(conn->allocptr.cookie);
conn->allocptr.cookie = aprintf("Cookie: %s\015\012", data->cookie);
} }
if(data->cookies) { if(data->cookies) {
@@ -461,14 +462,19 @@ CURLcode Curl_http(struct connectdata *conn)
http->sendit = Curl_getFormData(data->httppost, &http->postsize); http->sendit = Curl_getFormData(data->httppost, &http->postsize);
} }
if(!checkheaders(data, "Host:")) { if(!checkheaders(data, "Host:") &&
if(((conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTPS)) || !conn->allocptr.host) {
(!(conn->protocol&PROT_HTTPS) && (data->remote_port == PORT_HTTP)) ) /* if ptr_host is already set, it is OK since we only re-use connections
to the very same host and port */
if(((conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTPS)) ||
(!(conn->protocol&PROT_HTTPS) && (conn->remote_port == PORT_HTTP)) )
/* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include /* If (HTTPS on port 443) OR (non-HTTPS on port 80) then don't include
the port number in the host string */ the port number in the host string */
data->ptr_host = aprintf("Host: %s\r\n", host); conn->allocptr.host = aprintf("Host: %s\r\n", host);
else else
data->ptr_host = aprintf("Host: %s:%d\r\n", host, data->remote_port); conn->allocptr.host = aprintf("Host: %s:%d\r\n", host,
conn->remote_port);
} }
if(!checkheaders(data, "Pragma:")) if(!checkheaders(data, "Pragma:"))
@@ -477,6 +483,92 @@ CURLcode Curl_http(struct connectdata *conn)
if(!checkheaders(data, "Accept:")) if(!checkheaders(data, "Accept:"))
http->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";
if((data->bits.http_post ||
data->bits.http_formpost ||
data->bits.http_put) &&
data->resume_from) {
/**********************************************************************
* Resuming upload in HTTP means that we PUT or POST and that we have
* got a resume_from value set. The resume value has already created
* a Range: header that will be passed along. We need to "fast forward"
* the file the given number of bytes and decrease the assume upload
* file size before we continue this venture in the dark lands of HTTP.
*********************************************************************/
if(data->resume_from < 0 ) {
/*
* This is meant to get the size of the present remote-file by itself.
* We don't support this now. Bail out!
*/
data->resume_from = 0;
}
if(data->resume_from) {
/* do we still game? */
int passed=0;
/* 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
fseek()ed but we only have a stream here */
do {
int readthisamountnow = (data->resume_from - passed);
int actuallyread;
if(readthisamountnow > BUFSIZE)
readthisamountnow = BUFSIZE;
actuallyread =
data->fread(data->buffer, 1, readthisamountnow, data->in);
passed += actuallyread;
if(actuallyread != readthisamountnow) {
failf(data, "Could only read %d bytes from the input\n",
passed);
return CURLE_READ_ERROR;
}
} while(passed != data->resume_from); /* loop until done */
/* now, decrease the size of the read */
if(data->infilesize>0) {
data->infilesize -= data->resume_from;
if(data->infilesize <= 0) {
failf(data, "File already completely uploaded\n");
return CURLE_PARTIAL_FILE;
}
}
/* we've passed, proceed as normal */
}
}
if(data->bits.set_range) {
/*
* A range is selected. We use different headers whether we're downloading
* or uploading and we always let customized headers override our internal
* ones if any such are specified.
*/
if((data->httpreq == HTTPREQ_GET) &&
!checkheaders(data, "Range:")) {
conn->allocptr.rangeline = aprintf("Range: bytes=%s\r\n", data->range);
}
else if((data->httpreq != HTTPREQ_GET) &&
!checkheaders(data, "Content-Range:")) {
if(data->resume_from) {
/* This is because "resume" was selected */
long total_expected_size= data->resume_from + data->infilesize;
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s%ld/%ld\r\n",
data->range, total_expected_size-1,
total_expected_size);
}
else {
/* Range was selected and then we just pass the incoming range and
append total size */
conn->allocptr.rangeline = aprintf("Content-Range: bytes %s/%d\r\n",
data->range, data->infilesize);
}
}
}
do { do {
send_buffer *req_buffer; send_buffer *req_buffer;
struct curl_slist *headers=data->headers; struct curl_slist *headers=data->headers;
@@ -487,7 +579,7 @@ CURLcode Curl_http(struct connectdata *conn)
/* add the main request stuff */ /* add the main request stuff */
add_bufferf(req_buffer, add_bufferf(req_buffer,
"%s " /* GET/HEAD/POST/PUT */ "%s " /* GET/HEAD/POST/PUT */
"%s HTTP/1.0\r\n" /* path */ "%s HTTP/1.1\r\n" /* path */
"%s" /* proxyuserpwd */ "%s" /* proxyuserpwd */
"%s" /* userpwd */ "%s" /* userpwd */
"%s" /* range */ "%s" /* range */
@@ -503,15 +595,15 @@ CURLcode Curl_http(struct connectdata *conn)
(data->bits.http_post || data->bits.http_formpost)?"POST": (data->bits.http_post || data->bits.http_formpost)?"POST":
(data->bits.http_put)?"PUT":"GET"), (data->bits.http_put)?"PUT":"GET"),
ppath, ppath,
(data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"", (data->bits.proxy_user_passwd && conn->allocptr.proxyuserpwd)?conn->allocptr.proxyuserpwd:"",
(data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"", (data->bits.user_passwd && conn->allocptr.userpwd)?conn->allocptr.userpwd:"",
(data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"", (data->bits.set_range && conn->allocptr.rangeline)?conn->allocptr.rangeline:"",
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"", (data->useragent && *data->useragent && conn->allocptr.uagent)?conn->allocptr.uagent:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */ (conn->allocptr.cookie?conn->allocptr.cookie:""), /* Cookie: <data> */
(data->ptr_host?data->ptr_host:""), /* Host: host */ (conn->allocptr.host?conn->allocptr.host:""), /* Host: host */
http->p_pragma?http->p_pragma:"", http->p_pragma?http->p_pragma:"",
http->p_accept?http->p_accept:"", http->p_accept?http->p_accept:"",
(data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */ (data->bits.http_set_referer && conn->allocptr.ref)?conn->allocptr.ref:"" /* Referer: <data> <CRLF> */
); );
if(co) { if(co) {
@@ -615,10 +707,10 @@ CURLcode Curl_http(struct connectdata *conn)
Curl_pgrsSetUploadSize(data, http->postsize); Curl_pgrsSetUploadSize(data, http->postsize);
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
data->firstsocket, conn->firstsocket,
&http->writebytecount); &http->writebytecount);
if(result) { if(result) {
Curl_FormFree(http->sendit); /* free that whole lot */ Curl_FormFree(http->sendit); /* free that whole lot */
@@ -641,12 +733,12 @@ CURLcode Curl_http(struct connectdata *conn)
/* this sends the buffer and frees all the buffer resources */ /* this sends the buffer and frees all the buffer resources */
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
/* prepare for transfer */ /* prepare for transfer */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE,
&http->readbytecount, &http->readbytecount,
data->firstsocket, conn->firstsocket,
&http->writebytecount); &http->writebytecount);
if(result) if(result)
return result; return result;
@@ -687,10 +779,10 @@ CURLcode Curl_http(struct connectdata *conn)
/* issue the request */ /* issue the request */
data->request_size = data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer); add_buffer_send(conn->firstsocket, conn, req_buffer);
/* HTTP GET/HEAD download: */ /* HTTP GET/HEAD download: */
result = Curl_Transfer(conn, data->firstsocket, -1, TRUE, bytecount, result = Curl_Transfer(conn, conn->firstsocket, -1, TRUE, bytecount,
-1, NULL); /* nothing to upload */ -1, NULL); /* nothing to upload */
} }
if(result) if(result)

View File

@@ -25,7 +25,8 @@
*****************************************************************************/ *****************************************************************************/
/* ftp can use this as well */ /* ftp can use this as well */
CURLcode Curl_ConnectHTTPProxyTunnel(struct UrlData *data, int tunnelsocket, CURLcode Curl_ConnectHTTPProxyTunnel(struct connectdata *conn,
int tunnelsocket,
char *hostname, int remote_port); char *hostname, int remote_port);
/* protocol-specific functions set up to be called by the main engine */ /* protocol-specific functions set up to be called by the main engine */

View File

@@ -32,7 +32,7 @@
#include <unistd.h> #include <unistd.h>
#endif #endif
#if ! defined(WIN32) && ! defined(__BEOS__) #if ! defined(WIN32) && ! defined(__BEOS__) && !defined(__CYGWIN32__)
#ifdef NEED_REENTRANT #ifdef NEED_REENTRANT
#define _REENTRANT #define _REENTRANT

View File

@@ -24,7 +24,7 @@
*****************************************************************************/ *****************************************************************************/
#include "setup.h" #include "setup.h"
#if ! defined(WIN32) && ! defined(__BEOS__) #if ! defined(WIN32) && ! defined(__BEOS__) && !defined(__CYGWIN32__)
extern char *Curl_if2ip(char *interface, char *buf, int buf_size); extern char *Curl_if2ip(char *interface, char *buf, int buf_size);
#else #else
#define Curl_if2ip(a,b,c) NULL #define Curl_if2ip(a,b,c) NULL

View File

@@ -283,12 +283,14 @@ krb4_auth(void *app_data, struct connectdata *conn)
u_int32_t cs; u_int32_t cs;
struct krb4_data *d = app_data; struct krb4_data *d = app_data;
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR; struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
#if 0
struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR; struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;
#endif
char *host = conn->hp->h_name; char *host = conn->hp->h_name;
size_t nread; size_t nread;
int l = sizeof(local_addr); int l = sizeof(local_addr);
if(getsockname(conn->data->firstsocket, if(getsockname(conn->firstsocket,
(struct sockaddr *)LOCAL_ADDR, &l) < 0) (struct sockaddr *)LOCAL_ADDR, &l) < 0)
perror("getsockname()"); perror("getsockname()");
@@ -313,7 +315,7 @@ krb4_auth(void *app_data, struct connectdata *conn)
else { else {
if (natAddr.s_addr != localaddr->sin_addr.s_addr) { if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
printf("Using NAT IP address (%s) for kerberos 4\n", printf("Using NAT IP address (%s) for kerberos 4\n",
inet_ntoa(natAddr)); (char *)inet_ntoa(natAddr));
localaddr->sin_addr = natAddr; localaddr->sin_addr = natAddr;
/* /*
@@ -337,9 +339,9 @@ krb4_auth(void *app_data, struct connectdata *conn)
return AUTH_CONTINUE; return AUTH_CONTINUE;
} }
/*ret = command("ADAT %s", p)*/ /*ret = command("ADAT %s", p)*/
Curl_ftpsendf(conn->data->firstsocket, conn, "ADAT %s", p); Curl_ftpsendf(conn->firstsocket, conn, "ADAT %s", p);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@@ -399,7 +401,6 @@ void krb_kauth(struct connectdata *conn)
KTEXT_ST tkt, tktcopy; KTEXT_ST tkt, tktcopy;
char *name; char *name;
char *p; char *p;
int overbose;
char passwd[100]; char passwd[100];
int tmp; int tmp;
size_t nread; size_t nread;
@@ -408,21 +409,19 @@ void krb_kauth(struct connectdata *conn)
save = set_command_prot(conn, prot_private); save = set_command_prot(conn, prot_private);
/*ret = command("SITE KAUTH %s", name);***/ /*ret = command("SITE KAUTH %s", name);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s", conn->data->user); "SITE KAUTH %s", conn->data->user);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;
if(/*ret != CONTINUE*/conn->data->buffer[0] != '3'){ if(/*ret != CONTINUE*/conn->data->buffer[0] != '3'){
/*verbose = overbose;***/
set_command_prot(conn, save); set_command_prot(conn, save);
/*code = -1;***/ /*code = -1;***/
return; return;
} }
/*verbose = overbose;***/
p = strstr(/*reply_string***/conn->data->buffer, "T="); p = strstr(/*reply_string***/conn->data->buffer, "T=");
if(!p){ if(!p){
printf("Bad reply from server.\n"); printf("Bad reply from server.\n");
@@ -444,7 +443,6 @@ void krb_kauth(struct connectdata *conn)
p = strstr(/*reply_string***/conn->data->buffer, "P="); p = strstr(/*reply_string***/conn->data->buffer, "P=");
if(!p){ if(!p){
printf("Bad reply from server.\n"); printf("Bad reply from server.\n");
/*verbose = overbose;***/
set_command_prot(conn, save); set_command_prot(conn, save);
/*code = -1;***/ /*code = -1;***/
return; return;
@@ -488,10 +486,10 @@ void krb_kauth(struct connectdata *conn)
} }
memset (tktcopy.dat, 0, tktcopy.length); memset (tktcopy.dat, 0, tktcopy.length);
/*ret = command("SITE KAUTH %s %s", name, p);***/ /*ret = command("SITE KAUTH %s %s", name, p);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"SITE KAUTH %s %s", name, p); "SITE KAUTH %s %s", name, p);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, conn->data->buffer, nread = Curl_GetFTPResponse(conn->firstsocket, conn->data->buffer,
conn, NULL); conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/; return /*CURLE_OPERATION_TIMEOUTED*/;

View File

@@ -171,10 +171,10 @@ CURLcode Curl_ldap(struct connectdata *conn)
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text); DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long), ldap_entry2text);
DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html); DYNA_GET_FUNCTION(int (*)(void *, char *, void *, void *, char **, char **, int (*)(void *, char *, int), void *, char *, int, unsigned long, char *, char *), ldap_entry2html);
server = ldap_open(data->hostname, data->port); server = ldap_open(conn->hostname, conn->port);
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); conn->hostname, conn->port);
status = CURLE_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);

View File

@@ -2,7 +2,7 @@
; Definition file for the DLL version of the LIBCURL library from curl ; Definition file for the DLL version of the LIBCURL library from curl
; ;
LIBRARY LIBCURL LIBRARY CURL
DESCRIPTION 'curl libcurl - http://curl.haxx.se' DESCRIPTION 'curl libcurl - http://curl.haxx.se'
@@ -32,11 +32,11 @@ EXPORTS
curl_unescape @ 23 ; curl_unescape @ 23 ;
curl_version @ 24 ; curl_version @ 24 ;
curl_write @ 25 ; curl_write @ 25 ;
maprintf @ 26 ; curl_maprintf @ 26 ;
mfprintf @ 27 ; curl_mfprintf @ 27 ;
mprintf @ 28 ; curl_mprintf @ 28 ;
msprintf @ 29 ; curl_msprintf @ 29 ;
msnprintf @ 30 ; curl_msnprintf @ 30 ;
mvfprintf @ 31 ; curl_mvfprintf @ 31 ;
strequal @ 32 ; Curl_strequal @ 32 ;
strnequal @ 33 ; Curl_strnequal @ 33 ;

View File

@@ -72,7 +72,7 @@ void *curl_domalloc(size_t size, int line, char *source)
return mem; return mem;
} }
char *curl_dostrdup(char *str, int line, char *source) char *curl_dostrdup(const char *str, int line, char *source)
{ {
char *mem; char *mem;
size_t len; size_t len;

View File

@@ -7,7 +7,7 @@
void *curl_domalloc(size_t size, int line, char *source); void *curl_domalloc(size_t size, int line, char *source);
void *curl_dorealloc(void *ptr, size_t size, int line, char *source); void *curl_dorealloc(void *ptr, size_t size, int line, char *source);
void curl_dofree(void *ptr, int line, char *source); void curl_dofree(void *ptr, int line, char *source);
char *curl_dostrdup(char *str, int line, char *source); char *curl_dostrdup(const char *str, int line, char *source);
void curl_memdebug(char *logname); void curl_memdebug(char *logname);
/* file descriptor manipulators */ /* file descriptor manipulators */

View File

@@ -27,7 +27,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "getenv.h" #include <curl/curl.h>
#include "strequal.h" #include "strequal.h"
/* Debug this single source file with: /* Debug this single source file with:

View File

@@ -203,6 +203,9 @@ int Curl_pgrsUpdate(struct UrlData *data)
even when not displayed! */ even when not displayed! */
else if(!(data->progress.flags & PGRS_HEADERS_OUT)) { else if(!(data->progress.flags & PGRS_HEADERS_OUT)) {
if (!data->progress.callback) { if (!data->progress.callback) {
if(data->resume_from)
fprintf(data->err, "** Resuming transfer from byte position %d\n",
data->resume_from);
fprintf(data->err, fprintf(data->err,
" %% Total %% Received %% Xferd Average Speed Time Curr.\n" " %% Total %% Received %% Xferd Average Speed Time Curr.\n"
" Dload Upload Total Current Left Speed\n"); " Dload Upload Total Current Left Speed\n");
@@ -212,14 +215,14 @@ int Curl_pgrsUpdate(struct UrlData *data)
now = Curl_tvnow(); /* what time is it */ now = Curl_tvnow(); /* what time is it */
/* The exact time spent so far */
data->progress.timespent = Curl_tvdiff (now, data->progress.start);
if(data->progress.lastshow == Curl_tvlong(now)) if(data->progress.lastshow == Curl_tvlong(now))
return 0; /* 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;
/* The exact time spent so far */
data->progress.timespent = Curl_tvdiff (now, data->progress.start);
/* The average download speed this far */ /* The average download speed this far */
data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0); data->progress.dlspeed = data->progress.downloaded/(data->progress.timespent!=0.0?data->progress.timespent:1.0);
@@ -257,17 +260,13 @@ int Curl_pgrsUpdate(struct UrlData *data)
} }
/* 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) && data->progress.ulspeed){
if(!data->progress.ulspeed)
data->progress.ulspeed=1;
ulestimate = data->progress.size_ul / data->progress.ulspeed; ulestimate = data->progress.size_ul / data->progress.ulspeed;
ulpercen = (data->progress.uploaded / data->progress.size_ul)*100; ulpercen = (data->progress.uploaded / data->progress.size_ul)*100;
} }
/* ... and the download */ /* ... and the download */
if(data->progress.flags & PGRS_DL_SIZE_KNOWN) { if((data->progress.flags & PGRS_DL_SIZE_KNOWN) && data->progress.dlspeed) {
if(!data->progress.dlspeed)
data->progress.dlspeed=1;
dlestimate = data->progress.size_dl / data->progress.dlspeed; dlestimate = data->progress.size_dl / data->progress.dlspeed;
dlpercen = (data->progress.downloaded / data->progress.size_dl)*100; dlpercen = (data->progress.downloaded / data->progress.size_dl)*100;
} }

View File

@@ -482,10 +482,10 @@ sec_prot_internal(struct connectdata *conn, int level)
} }
if(level){ if(level){
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"PBSZ %u", s); "PBSZ %u", s);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@@ -501,10 +501,10 @@ sec_prot_internal(struct connectdata *conn, int level)
conn->buffer_size = s; conn->buffer_size = s;
} }
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"PROT %c", level["CSEP"]); "PROT %c", level["CSEP"]);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;
@@ -610,10 +610,10 @@ sec_login(struct connectdata *conn)
} }
infof(data, "Trying %s...\n", (*m)->name); infof(data, "Trying %s...\n", (*m)->name);
/*ret = command("AUTH %s", (*m)->name);***/ /*ret = command("AUTH %s", (*m)->name);***/
Curl_ftpsendf(conn->data->firstsocket, conn, Curl_ftpsendf(conn->firstsocket, conn,
"AUTH %s", (*m)->name); "AUTH %s", (*m)->name);
/* wait for feedback */ /* wait for feedback */
nread = Curl_GetFTPResponse(conn->data->firstsocket, nread = Curl_GetFTPResponse(conn->firstsocket,
conn->data->buffer, conn, NULL); conn->data->buffer, conn, NULL);
if(nread < 0) if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1; return /*CURLE_OPERATION_TIMEOUTED*/-1;

View File

@@ -50,6 +50,76 @@
#include "memdebug.h" #include "memdebug.h"
#endif #endif
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
struct curl_slist *item;
/* if caller passed us a NULL, return now */
if (!list)
return NULL;
/* loop through to find the last item */
item = list;
while (item->next) {
item = item->next;
}
return item;
}
/* append a struct to the linked list. It always retunrs the address of the
* first record, so that you can sure this function as an initialization
* function as well as an append function. If you find this bothersome,
* then simply create a separate _init function and call it appropriately from
* within the proram. */
struct curl_slist *curl_slist_append(struct curl_slist *list,
const char *data)
{
struct curl_slist *last;
struct curl_slist *new_item;
new_item = (struct curl_slist *) malloc(sizeof(struct curl_slist));
if (new_item) {
new_item->next = NULL;
new_item->data = strdup(data);
}
else {
fprintf(stderr, "Cannot allocate memory for QUOTE list.\n");
return NULL;
}
if (list) {
last = slist_get_last(list);
last->next = new_item;
return list;
}
/* if this is the first item, then new_item *is* the list */
return new_item;
}
/* be nice and clean up resources */
void curl_slist_free_all(struct curl_slist *list)
{
struct curl_slist *next;
struct curl_slist *item;
if (!list)
return;
item = list;
do {
next = item->next;
if (item->data) {
free(item->data);
}
free(item);
item = next;
} while (next);
}
/* infof() is for info message along the way */ /* infof() is for info message along the way */
void Curl_infof(struct UrlData *data, char *fmt, ...) void Curl_infof(struct UrlData *data, char *fmt, ...)
@@ -72,64 +142,94 @@ void Curl_failf(struct UrlData *data, char *fmt, ...)
va_start(ap, fmt); va_start(ap, fmt);
if(data->errorbuffer) if(data->errorbuffer)
vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap); vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap);
else /* no errorbuffer receives this, write to data->err instead */ else {
/* no errorbuffer receives this, write to data->err instead */
vfprintf(data->err, fmt, ap); vfprintf(data->err, fmt, ap);
fprintf(data->err, "\n");
}
va_end(ap); va_end(ap);
} }
/* sendf() sends the formated data to the server */ /* Curl_sendf() sends formated data to the server */
size_t Curl_sendf(int fd, struct UrlData *data, char *fmt, ...) size_t Curl_sendf(int sockfd, struct connectdata *conn,
char *fmt, ...)
{ {
struct UrlData *data = conn->data;
size_t bytes_written; size_t bytes_written;
char *s; char *s;
va_list ap; va_list ap;
va_start(ap, fmt); va_start(ap, fmt);
s = vaprintf(fmt, ap); s = vaprintf(fmt, ap); /* returns an allocated string */
va_end(ap); va_end(ap);
if(!s) if(!s)
return 0; /* failure */ return 0; /* failure */
if(data->bits.verbose) if(data->bits.verbose)
fprintf(data->err, "> %s", s); fprintf(data->err, "> %s", s);
#ifndef USE_SSLEAY /* Write the buffer to the socket */
bytes_written = swrite(fd, s, strlen(s)); Curl_write(conn, sockfd, s, strlen(s), &bytes_written);
#else /* USE_SSLEAY */
if (data->ssl.use) {
bytes_written = SSL_write(data->ssl.handle, s, strlen(s));
} else {
bytes_written = swrite(fd, s, strlen(s));
}
#endif /* USE_SSLEAY */
free(s); /* free the output string */ free(s); /* free the output string */
return(bytes_written);
return bytes_written;
} }
/* ssend() sends plain (binary) data to the server */ /*
size_t Curl_ssend(int fd, struct connectdata *conn, void *mem, size_t len) * Curl_write() is an internal write function that sends plain (binary) data
* to the server. Works with plain sockets, SSL or kerberos.
*
*/
CURLcode Curl_write(struct connectdata *conn, int sockfd,
void *mem, size_t len,
size_t *written)
{ {
size_t bytes_written; size_t bytes_written;
struct UrlData *data=conn->data; /* conn knows data, not vice versa */
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
if (data->ssl.use) { if (conn->ssl.use) {
bytes_written = SSL_write(data->ssl.handle, mem, len); int loop=100; /* just a precaution to never loop endlessly */
while(loop--) {
bytes_written = SSL_write(conn->ssl.handle, mem, len);
if((-1 != bytes_written) ||
(SSL_ERROR_WANT_WRITE != SSL_get_error(conn->ssl.handle,
bytes_written) ))
break;
}
} }
else { else {
#endif #endif
#ifdef KRB4 #ifdef KRB4
if(conn->sec_complete) { if(conn->sec_complete) {
bytes_written = sec_write(conn, fd, mem, len); bytes_written = sec_write(conn, sockfd, mem, len);
} }
else else
#endif /* KRB4 */ #endif /* KRB4 */
bytes_written = swrite(fd, mem, len); bytes_written = swrite(sockfd, mem, len);
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
} }
#endif #endif
return bytes_written; *written = bytes_written;
return CURLE_OK;
} }
/*
* External write-function, writes to the data-socket.
* Takes care of plain sockets, SSL or kerberos transparently.
*/
CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
size_t *n)
{
struct connectdata *conn = (struct connectdata *)c_conn;
if(!n || !conn || (conn->handle != STRUCT_CONNECT))
return CURLE_FAILED_INIT;
return Curl_write(conn, conn->sockfd, buf, amount, n);
}
/* client_write() sends data to the write callback(s) /* client_write() sends data to the write callback(s)
The bit pattern defines to what "streams" to write to. Body and/or header. The bit pattern defines to what "streams" to write to. Body and/or header.
@@ -163,3 +263,55 @@ CURLcode Curl_client_write(struct UrlData *data,
return CURLE_OK; return CURLE_OK;
} }
/*
* Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets.
*/
CURLcode Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize,
ssize_t *n)
{
ssize_t nread;
#ifdef USE_SSLEAY
if (conn->ssl.use) {
int loop=100; /* just a precaution to never loop endlessly */
while(loop--) {
nread = SSL_read(conn->ssl.handle, buf, buffersize);
if((-1 != nread) ||
(SSL_ERROR_WANT_READ != SSL_get_error(conn->ssl.handle, nread) ))
break;
}
}
else {
#endif
#ifdef KRB4
if(conn->sec_complete)
nread = sec_read(conn, sockfd, buf, buffersize);
else
#endif
nread = sread (sockfd, buf, buffersize);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
*n = nread;
return CURLE_OK;
}
/*
* The public read function reads from the 'sockfd' file descriptor only.
* Use the Curl_read() internally when you want to specify fd.
*/
CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
ssize_t *n)
{
struct connectdata *conn = (struct connectdata *)c_conn;
if(!n || !conn || (conn->handle != STRUCT_CONNECT))
return CURLE_FAILED_INIT;
return Curl_read(conn, conn->sockfd, buf, buffersize, n);
}

View File

@@ -23,13 +23,10 @@
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
size_t Curl_sendf(int fd, struct UrlData *, char *fmt, ...); size_t Curl_sendf(int fd, struct connectdata *, char *fmt, ...);
size_t Curl_ssend(int fd, struct connectdata *, void *fmt, size_t len);
void Curl_infof(struct UrlData *, char *fmt, ...); void Curl_infof(struct UrlData *, char *fmt, ...);
void Curl_failf(struct UrlData *, char *fmt, ...); void Curl_failf(struct UrlData *, char *fmt, ...);
#define sendf Curl_sendf
#define ssend Curl_ssend
#define infof Curl_infof #define infof Curl_infof
#define failf Curl_failf #define failf Curl_failf
@@ -47,4 +44,13 @@ typedef struct send_buffer send_buffer;
CURLcode Curl_client_write(struct UrlData *data, int type, char *ptr, CURLcode Curl_client_write(struct UrlData *data, int type, char *ptr,
size_t len); size_t len);
/* internal read-function, does plain socket, SSL and krb4 */
CURLcode Curl_read(struct connectdata *conn, int sockfd,
char *buf, size_t buffersize,
ssize_t *n);
/* internal write-function, does plain socket, SSL and krb4 */
CURLcode Curl_write(struct connectdata *conn, int sockfd,
void *mem, size_t len,
size_t *written);
#endif #endif

View File

@@ -100,7 +100,6 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
1. close a socket 1. close a socket
2. read from a socket 2. read from a socket
3. write to a socket 3. write to a socket
(Hopefully, only win32-crap do this weird name changing)
4. set the SIGALRM signal timeout 4. set the SIGALRM signal timeout
5. set dir/file naming defines 5. set dir/file naming defines
@@ -115,8 +114,8 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
#else #else
/* gcc-for-win is still good :) */ /* gcc-for-win is still good :) */
#define sclose(x) close(x) #define sclose(x) close(x)
#define sread(x,y,z) read(x,y,z) #define sread(x,y,z) recv(x,y,z,0)
#define swrite(x,y,z) write(x,y,z) #define swrite(x,y,z) send(x,y,z,0)
#define myalarm(x) alarm(x) #define myalarm(x) alarm(x)
#endif #endif

View File

@@ -64,6 +64,7 @@ static int passwd_callback(char *buf, int num, int verify
static static
int cert_stuff(struct UrlData *data, int cert_stuff(struct UrlData *data,
struct connectdata *conn,
char *cert_file, char *cert_file,
char *key_file) char *key_file)
{ {
@@ -78,10 +79,10 @@ int cert_stuff(struct UrlData *data,
*/ */
strcpy(global_passwd, data->cert_passwd); strcpy(global_passwd, data->cert_passwd);
/* Set passwd callback: */ /* Set passwd callback: */
SSL_CTX_set_default_passwd_cb(data->ssl.ctx, passwd_callback); SSL_CTX_set_default_passwd_cb(conn->ssl.ctx, passwd_callback);
} }
if (SSL_CTX_use_certificate_file(data->ssl.ctx, if (SSL_CTX_use_certificate_file(conn->ssl.ctx,
cert_file, cert_file,
SSL_FILETYPE_PEM) <= 0) { SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set certificate file (wrong password?)\n"); failf(data, "unable to set certificate file (wrong password?)\n");
@@ -90,14 +91,14 @@ int cert_stuff(struct UrlData *data,
if (key_file == NULL) if (key_file == NULL)
key_file=cert_file; key_file=cert_file;
if (SSL_CTX_use_PrivateKey_file(data->ssl.ctx, if (SSL_CTX_use_PrivateKey_file(conn->ssl.ctx,
key_file, key_file,
SSL_FILETYPE_PEM) <= 0) { SSL_FILETYPE_PEM) <= 0) {
failf(data, "unable to set public key file\n"); failf(data, "unable to set public key file\n");
return(0); return(0);
} }
ssl=SSL_new(data->ssl.ctx); ssl=SSL_new(conn->ssl.ctx);
x509=SSL_get_certificate(ssl); x509=SSL_get_certificate(ssl);
if (x509 != NULL) if (x509 != NULL)
@@ -111,7 +112,7 @@ int cert_stuff(struct UrlData *data,
/* Now we know that a key and cert have been set against /* Now we know that a key and cert have been set against
* the SSL context */ * the SSL context */
if (!SSL_CTX_check_private_key(data->ssl.ctx)) { if (!SSL_CTX_check_private_key(conn->ssl.ctx)) {
failf(data, "Private key does not match the certificate public key\n"); failf(data, "Private key does not match the certificate public key\n");
return(0); return(0);
} }
@@ -141,22 +142,23 @@ int cert_verify_callback(int ok, X509_STORE_CTX *ctx)
/* ====================================================== */ /* ====================================================== */
int int
Curl_SSLConnect (struct UrlData *data) Curl_SSLConnect(struct connectdata *conn)
{ {
#ifdef USE_SSLEAY #ifdef USE_SSLEAY
int err; struct UrlData *data = conn->data;
char * str; int err;
SSL_METHOD *req_method; char * str;
SSL_METHOD *req_method;
/* mark this is being ssl enabled from here on out. */ /* mark this is being ssl enabled from here on out. */
data->ssl.use = TRUE; conn->ssl.use = TRUE;
/* Lets get nice error messages */ /* Lets get nice error messages */
SSL_load_error_strings(); SSL_load_error_strings();
#ifdef HAVE_RAND_STATUS #ifdef HAVE_RAND_STATUS
/* RAND_status() was introduced in OpenSSL 0.9.5 */ /* RAND_status() was introduced in OpenSSL 0.9.5 */
if(0 == RAND_status()) if(0 == RAND_status())
#endif #endif
{ {
/* We need to seed the PRNG properly! */ /* We need to seed the PRNG properly! */
@@ -177,116 +179,116 @@ Curl_SSLConnect (struct UrlData *data)
#endif #endif
} }
/* Setup all the global SSL stuff */ /* Setup all the global SSL stuff */
SSLeay_add_ssl_algorithms(); SSLeay_add_ssl_algorithms();
switch(data->ssl.version) { switch(data->ssl.version) {
default: default:
req_method = SSLv23_client_method(); req_method = SSLv23_client_method();
break; break;
case 2: case 2:
req_method = SSLv2_client_method(); req_method = SSLv2_client_method();
break; break;
case 3: case 3:
req_method = SSLv3_client_method(); req_method = SSLv3_client_method();
break; break;
} }
data->ssl.ctx = SSL_CTX_new(req_method); conn->ssl.ctx = SSL_CTX_new(req_method);
if(!data->ssl.ctx) { if(!conn->ssl.ctx) {
failf(data, "SSL: couldn't create a context!"); failf(data, "SSL: couldn't create a context!");
return 1; return 1;
} }
if(data->cert) { if(data->cert) {
if (!cert_stuff(data, data->cert, data->cert)) { if (!cert_stuff(data, conn, data->cert, data->cert)) {
failf(data, "couldn't use certificate!\n"); failf(data, "couldn't use certificate!\n");
return 2; return 2;
}
} }
}
if(data->ssl.verifypeer){ if(data->ssl.verifypeer){
SSL_CTX_set_verify(data->ssl.ctx, SSL_CTX_set_verify(conn->ssl.ctx,
SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT| SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
SSL_VERIFY_CLIENT_ONCE, SSL_VERIFY_CLIENT_ONCE,
cert_verify_callback); cert_verify_callback);
if (!SSL_CTX_load_verify_locations(data->ssl.ctx, if (!SSL_CTX_load_verify_locations(conn->ssl.ctx,
data->ssl.CAfile, data->ssl.CAfile,
data->ssl.CApath)) { data->ssl.CApath)) {
failf(data,"error setting cerficate verify locations\n"); failf(data,"error setting cerficate verify locations\n");
return 2; return 2;
}
} }
else }
SSL_CTX_set_verify(data->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback); else
SSL_CTX_set_verify(conn->ssl.ctx, SSL_VERIFY_NONE, cert_verify_callback);
/* Lets make an SSL structure */ /* Lets make an SSL structure */
data->ssl.handle = SSL_new (data->ssl.ctx); conn->ssl.handle = SSL_new (conn->ssl.ctx);
SSL_set_connect_state (data->ssl.handle); SSL_set_connect_state (conn->ssl.handle);
data->ssl.server_cert = 0x0; conn->ssl.server_cert = 0x0;
/* pass the raw socket into the SSL layers */ /* pass the raw socket into the SSL layers */
SSL_set_fd (data->ssl.handle, data->firstsocket); SSL_set_fd (conn->ssl.handle, conn->firstsocket);
err = SSL_connect (data->ssl.handle); err = SSL_connect (conn->ssl.handle);
if (-1 == err) { if (-1 == err) {
err = ERR_get_error(); err = ERR_get_error();
failf(data, "SSL: %s", ERR_error_string(err, NULL)); failf(data, "SSL: %s", ERR_error_string(err, NULL));
return 10; return 10;
} }
/* Informational message */ /* Informational message */
infof (data, "SSL connection using %s\n", infof (data, "SSL connection using %s\n",
SSL_get_cipher(data->ssl.handle)); SSL_get_cipher(conn->ssl.handle));
/* Get server's certificate (note: beware of dynamic allocation) - opt */ /* Get server's certificate (note: beware of dynamic allocation) - opt */
/* major serious hack alert -- we should check certificates /* major serious hack alert -- we should check certificates
* to authenticate the server; otherwise we risk man-in-the-middle * to authenticate the server; otherwise we risk man-in-the-middle
* attack * attack
*/ */
data->ssl.server_cert = SSL_get_peer_certificate (data->ssl.handle); conn->ssl.server_cert = SSL_get_peer_certificate (conn->ssl.handle);
if(!data->ssl.server_cert) { if(!conn->ssl.server_cert) {
failf(data, "SSL: couldn't get peer certificate!"); failf(data, "SSL: couldn't get peer certificate!");
return 3; return 3;
} }
infof (data, "Server certificate:\n"); infof (data, "Server certificate:\n");
str = X509_NAME_oneline (X509_get_subject_name (data->ssl.server_cert), str = X509_NAME_oneline (X509_get_subject_name (conn->ssl.server_cert),
NULL, 0); NULL, 0);
if(!str) { if(!str) {
failf(data, "SSL: couldn't get X509-subject!"); failf(data, "SSL: couldn't get X509-subject!");
return 4; return 4;
} }
infof(data, "\t subject: %s\n", str); infof(data, "\t subject: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_issuer_name (data->ssl.server_cert), str = X509_NAME_oneline (X509_get_issuer_name (conn->ssl.server_cert),
NULL, 0); NULL, 0);
if(!str) { if(!str) {
failf(data, "SSL: couldn't get X509-issuer name!"); failf(data, "SSL: couldn't get X509-issuer name!");
return 5; return 5;
} }
infof(data, "\t issuer: %s\n", str); infof(data, "\t issuer: %s\n", str);
CRYPTO_free(str); CRYPTO_free(str);
/* We could do all sorts of certificate verification stuff here before /* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */ deallocating the certificate. */
if(data->ssl.verifypeer) { if(data->ssl.verifypeer) {
data->ssl.certverifyresult=SSL_get_verify_result(data->ssl.handle); data->ssl.certverifyresult=SSL_get_verify_result(conn->ssl.handle);
infof(data, "Verify result: %d\n", data->ssl.certverifyresult); infof(data, "Verify result: %d\n", data->ssl.certverifyresult);
} }
else else
data->ssl.certverifyresult=0; data->ssl.certverifyresult=0;
X509_free(data->ssl.server_cert); X509_free(conn->ssl.server_cert);
#else /* USE_SSLEAY */ #else /* USE_SSLEAY */
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */ /* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void) data; (void) data;
#endif #endif
return 0; return 0;
} }

View File

@@ -22,5 +22,6 @@
* *
* $Id$ * $Id$
*****************************************************************************/ *****************************************************************************/
int Curl_SSLConnect (struct UrlData *data); #include "urldata.h"
int Curl_SSLConnect(struct connectdata *conn);
#endif #endif

View File

@@ -66,3 +66,44 @@ int Curl_strnequal(const char *first, const char *second, size_t max)
#endif #endif
} }
#ifndef HAVE_STRLCAT
/*
* The strlcat() function appends the NUL-terminated string src to the end
* of dst. It will append at most size - strlen(dst) - 1 bytes, NUL-termi-
* nating the result.
*
* The strlcpy() and strlcat() functions return the total length of the
* string they tried to create. For strlcpy() that means the length of src.
* For strlcat() that means the initial length of dst plus the length of
* src. While this may seem somewhat confusing it was done to make trunca-
* tion detection simple.
*
*
*/
size_t strlcat(char *dst, const char *src, size_t siz)
{
char *d = dst;
const char *s = src;
size_t n = siz;
size_t dlen;
/* Find the end of dst and adjust bytes left but don't go past end */
while (n-- != 0 && *d != '\0')
d++;
dlen = d - dst;
n = siz - dlen;
if (n == 0)
return(dlen + strlen(s));
while (*s != '\0') {
if (n != 1) {
*d++ = *s;
n--;
}
s++;
}
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
}
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -82,7 +82,6 @@
#include <curl/types.h> #include <curl/types.h>
#include "netrc.h" #include "netrc.h"
#include "getenv.h"
#include "hostip.h" #include "hostip.h"
#include "transfer.h" #include "transfer.h"
#include "sendf.h" #include "sendf.h"
@@ -109,7 +108,7 @@
CURLcode static CURLcode static
_Transfer(struct connectdata *c_conn) _Transfer(struct connectdata *c_conn)
{ {
size_t nread; /* number of bytes read */ ssize_t nread; /* number of bytes read */
int bytecount = 0; /* total number of bytes read */ int bytecount = 0; /* total number of bytes read */
int writebytecount = 0; /* number of bytes written */ int writebytecount = 0; /* number of bytes written */
long contentlength=0; /* size of incoming data */ long contentlength=0; /* size of incoming data */
@@ -128,13 +127,12 @@ _Transfer(struct connectdata *c_conn)
int offset = 0; /* possible resume offset read from the int offset = 0; /* possible resume offset read from the
Content-Range: header */ Content-Range: header */
int code = 0; /* error code from the 'HTTP/1.? XXX' line */ int code = 0; /* error code from the 'HTTP/1.? XXX' line */
int httpversion = -1; /* the last digit in the HTTP/1.1 string */
/* for the low speed checks: */ /* for the low speed checks: */
CURLcode urg; CURLcode urg;
time_t timeofdoc=0; time_t timeofdoc=0;
long bodywrites=0; long bodywrites=0;
char newurl[URL_MAX_LENGTH]; /* buffer for Location: URL */
int writetype; int writetype;
/* the highest fd we use + 1 */ /* the highest fd we use + 1 */
@@ -163,6 +161,12 @@ _Transfer(struct connectdata *c_conn)
Curl_pgrsTime(data, TIMER_PRETRANSFER); Curl_pgrsTime(data, TIMER_PRETRANSFER);
Curl_speedinit(data); Curl_speedinit(data);
if((conn->sockfd == -1) &&
(conn->writesockfd == -1)) {
/* nothing to read, nothing to write, we're already OK! */
return CURLE_OK;
}
if (!conn->getheader) { if (!conn->getheader) {
header = FALSE; header = FALSE;
if(conn->size > 0) if(conn->size > 0)
@@ -224,7 +228,7 @@ _Transfer(struct connectdata *c_conn)
default: default:
if((keepon & KEEP_READ) && FD_ISSET(conn->sockfd, &readfd)) { if((keepon & KEEP_READ) && FD_ISSET(conn->sockfd, &readfd)) {
/* read! */ /* read! */
urg = curl_read(conn, buf, BUFSIZE -1, &nread); urg = Curl_read(conn, conn->sockfd, buf, BUFSIZE -1, &nread);
/* NULL terminate, allowing string ops to be used */ /* NULL terminate, allowing string ops to be used */
if (0 < (signed int) nread) if (0 < (signed int) nread)
@@ -316,9 +320,9 @@ _Transfer(struct connectdata *c_conn)
p++; /* pass the \r byte */ p++; /* pass the \r byte */
if ('\n' == *p) if ('\n' == *p)
p++; /* pass the \n byte */ p++; /* pass the \n byte */
#if 0 /* headers are not included in the size */
Curl_pgrsSetDownloadSize(data, conn->size); Curl_pgrsSetDownloadSize(data, conn->size);
#endif
header = FALSE; /* no more header to parse! */ header = FALSE; /* no more header to parse! */
/* now, only output this if the header AND body are requested: /* now, only output this if the header AND body are requested:
@@ -339,7 +343,7 @@ _Transfer(struct connectdata *c_conn)
if (!headerline++) { if (!headerline++) {
/* This is the first header, it MUST be the error code line /* This is the first header, it MUST be the error code line
or else we consiser this to be the body right away! */ or else we consiser this to be the body right away! */
if (sscanf (p, " HTTP/1.%*c %3d", &code)) { if (2 == sscanf (p, " HTTP/1.%d %3d", &httpversion, &code)) {
/* 404 -> URL not found! */ /* 404 -> URL not found! */
if ( if (
( ((data->bits.http_follow_location) && (code >= 400)) ( ((data->bits.http_follow_location) && (code >= 400))
@@ -363,6 +367,16 @@ _Transfer(struct connectdata *c_conn)
if (strnequal("Content-Length", p, 14) && if (strnequal("Content-Length", p, 14) &&
sscanf (p+14, ": %ld", &contentlength)) sscanf (p+14, ": %ld", &contentlength))
conn->size = contentlength; conn->size = contentlength;
else if (strnequal("Connection: close", p,
strlen("Connection: close"))) {
/*
* [RFC 2616, section 8.1.2.1]
* "Connection: close" is HTTP/1.1 language and means that
* the connection will close when this request has been
* served.
*/
conn->bits.close = TRUE; /* close when done */
}
else if (strnequal("Content-Range", p, 13)) { else if (strnequal("Content-Range", p, 13)) {
if (sscanf (p+13, ": bytes %d-", &offset) || if (sscanf (p+13, ": bytes %d-", &offset) ||
sscanf (p+13, ": bytes: %d-", &offset)) { sscanf (p+13, ": bytes: %d-", &offset)) {
@@ -389,12 +403,21 @@ _Transfer(struct connectdata *c_conn)
} }
else if ((code >= 300 && code < 400) && else if ((code >= 300 && code < 400) &&
(data->bits.http_follow_location) && (data->bits.http_follow_location) &&
strnequal("Location", p, 8) && strnequal("Location: ", p, 10)) {
sscanf (p+8, ": %" URL_MAX_LENGTH_TXT "s", /* this is the URL that the server advices us to get instead */
newurl)) { char *ptr;
/* this is the URL that the server advices us to get char *start=p;
instead */ char backup;
data->newurl = strdup (newurl);
start += 10; /* pass "Location: " */
ptr = start; /* start scanning here */
/* scan through the string to find the end */
while(*ptr && !isspace((int)*ptr))
ptr++;
backup = *ptr; /* store the ending letter */
*ptr = '\0'; /* zero terminate */
data->newurl = strdup(start); /* clone string */
*ptr = backup; /* restore ending letter */
} }
writetype = CLIENTWRITE_HEADER; writetype = CLIENTWRITE_HEADER;
@@ -437,17 +460,21 @@ _Transfer(struct connectdata *c_conn)
write a chunk of the body */ write a chunk of the body */
if(conn->protocol&PROT_HTTP) { if(conn->protocol&PROT_HTTP) {
/* HTTP-only checks */ /* HTTP-only checks */
if (data->resume_from && !content_range ) { if (data->newurl) {
/* 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 */ /* abort after the headers if "follow Location" is set */
infof (data, "Follow to new URL: %s\n", data->newurl); infof (data, "Follow to new URL: %s\n", data->newurl);
return CURLE_OK; return CURLE_OK;
} }
else if (data->resume_from &&
!content_range &&
(data->httpreq==HTTPREQ_GET)) {
/* we wanted to resume a download, although the server
doesn't seem to support this and we did this with a GET
(if it wasn't a GET we did a POST or PUT resume) */
failf (data, "HTTP server doesn't seem to support "
"byte ranges. Cannot resume.");
return CURLE_HTTP_RANGE_ERROR;
}
else if(data->timecondition && !data->range) { else if(data->timecondition && !data->range) {
/* A time condition has been set AND no ranges have been /* A time condition has been set AND no ranges have been
requested. This seems to be what chapter 13.3.4 of requested. This seems to be what chapter 13.3.4 of
@@ -473,13 +500,23 @@ _Transfer(struct connectdata *c_conn)
} /* switch */ } /* switch */
} /* two valid time strings */ } /* two valid time strings */
} /* we have a time condition */ } /* we have a time condition */
if(!conn->bits.close && (httpversion == 1)) {
/* If this is not the last request before a close, we must
set the maximum download size to the size of the expected
document or else, we won't know when to stop reading! */
if(-1 != conn->size)
conn->maxdownload = conn->size;
/* What to do if the size is *not* known? */
}
} /* this is HTTP */ } /* this is HTTP */
} /* this is the first time we write a body part */ } /* this is the first time we write a body part */
bodywrites++; bodywrites++;
if(data->maxdownload && if(conn->maxdownload &&
(bytecount + nread > data->maxdownload)) { (bytecount + nread >= conn->maxdownload)) {
nread = data->maxdownload - bytecount; nread = conn->maxdownload - bytecount;
if((signed int)nread < 0 ) /* this should be unusual */ if((signed int)nread < 0 ) /* this should be unusual */
nread = 0; nread = 0;
keepon &= ~KEEP_READ; /* we're done reading */ keepon &= ~KEEP_READ; /* we're done reading */
@@ -534,7 +571,8 @@ _Transfer(struct connectdata *c_conn)
} }
/* write to socket */ /* write to socket */
urg = curl_write(conn, buf, nread, &bytes_written); urg = Curl_write(conn, conn->writesockfd, buf, nread,
&bytes_written);
if(nread != bytes_written) { if(nread != bytes_written) {
failf(data, "Failed uploading data"); failf(data, "Failed uploading data");
@@ -594,12 +632,13 @@ CURLcode curl_transfer(CURL *curl)
CURLcode res; CURLcode res;
struct UrlData *data = curl; struct UrlData *data = curl;
struct connectdata *c_connect=NULL; struct connectdata *c_connect=NULL;
bool port=TRUE; /* allow data->use_port to set port to use */
Curl_pgrsStartNow(data); Curl_pgrsStartNow(data);
do { do {
Curl_pgrsTime(data, TIMER_STARTSINGLE); Curl_pgrsTime(data, TIMER_STARTSINGLE);
res = curl_connect(curl, (CURLconnect **)&c_connect); res = curl_connect(curl, (CURLconnect **)&c_connect, port);
if(res == CURLE_OK) { if(res == CURLE_OK) {
res = curl_do(c_connect); res = curl_do(c_connect);
if(res == CURLE_OK) { if(res == CURLE_OK) {
@@ -613,11 +652,17 @@ CURLcode curl_transfer(CURL *curl)
This is assumed to happen for HTTP(S) only! This is assumed to happen for HTTP(S) only!
*/ */
char prot[16]; char prot[16]; /* URL protocol string storage */
char path[URL_MAX_LENGTH]; char letter; /* used for a silly sscanf */
port=TRUE; /* by default we use the user set port number even after
a Location: */
if (data->maxredirs && (data->followlocation >= data->maxredirs)) { if (data->maxredirs && (data->followlocation >= data->maxredirs)) {
failf(data,"Maximum (%d) redirects followed", data->maxredirs); failf(data,"Maximum (%d) redirects followed", data->maxredirs);
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
res=CURLE_TOO_MANY_REDIRECTS; res=CURLE_TOO_MANY_REDIRECTS;
break; break;
} }
@@ -638,12 +683,11 @@ CURLcode curl_transfer(CURL *curl)
} }
data->referer = strdup(data->url); data->referer = strdup(data->url);
data->free_referer = TRUE; /* yes, free this later */ data->free_referer = TRUE; /* yes, free this later */
data->bits.http_set_referer = TRUE; /* might have been false */ data->bits.http_set_referer = TRUE; /* might have been false */
} }
if(2 != sscanf(data->newurl, "%15[^:]://%" URL_MAX_LENGTH_TXT if(2 != sscanf(data->newurl, "%15[^:]://%c", prot, &letter)) {
"s", prot, path)) {
/*** /***
*DANG* this is an RFC 2068 violation. The URL is supposed *DANG* this is an RFC 2068 violation. The URL is supposed
to be absolute and this doesn't seem to be that! to be absolute and this doesn't seem to be that!
@@ -661,9 +705,10 @@ CURLcode curl_transfer(CURL *curl)
if(!protsep) if(!protsep)
protsep=data->url; protsep=data->url;
else { else {
/* TBD: set the port with curl_setopt() */ port=FALSE; /* we got a full URL and thus we should not obey the
data->port=0; /* we got a full URL and then we should reset the port number that might have been set by the user
port number here to re-initiate it later */ in data->use_port */
protsep+=2; /* pass the slashes */ protsep+=2; /* pass the slashes */
} }
@@ -700,9 +745,8 @@ CURLcode curl_transfer(CURL *curl)
data->newurl = newest; data->newurl = newest;
} }
else { else {
/* This was an absolute URL, clear the port number! */ /* This is an absolute URL, don't use the custom port number */
/* TBD: set the port with curl_setopt() */ port = FALSE;
data->port = 0;
} }
if(data->bits.urlstringalloc) if(data->bits.urlstringalloc)
@@ -713,18 +757,57 @@ CURLcode curl_transfer(CURL *curl)
data->newurl = NULL; /* don't show! */ data->newurl = NULL; /* don't show! */
data->bits.urlstringalloc = TRUE; /* the URL is allocated */ data->bits.urlstringalloc = TRUE; /* the URL is allocated */
/* Disable both types of POSTs, since doing a second POST when
following isn't what anyone would want! */
data->bits.http_post = FALSE;
data->bits.http_formpost = FALSE;
infof(data, "Follows Location: to new URL: '%s'\n", data->url); infof(data, "Follows Location: to new URL: '%s'\n", data->url);
/*
* We get here when the HTTP code is 300-399. We need to perform
* differently based on exactly what return code there was.
* Discussed on the curl mailing list and posted about on the 26th
* of January 2001.
*/
switch(data->progress.httpcode) {
case 300: /* Multiple Choices */
case 301: /* Moved Permanently */
case 302: /* Found */
case 306: /* Not used */
case 307: /* Temporary Redirect */
default: /* for all unknown ones */
/* These are explicitly mention since I've checked RFC2616 and they
* seem to be OK to POST to.
*/
break;
case 303: /* See Other */
/* Disable both types of POSTs, since doing a second POST when
* following isn't what anyone would want! */
data->bits.http_post = FALSE;
data->bits.http_formpost = FALSE;
data->httpreq = HTTPREQ_GET; /* enfore GET request */
infof(data, "Disables POST\n");
break;
case 304: /* Not Modified */
/* 304 means we did a conditional request and it was "Not modified".
* We shouldn't get any Location: header in this response!
*/
break;
case 305: /* Use Proxy */
/* (quote from RFC2616, section 10.3.6):
* "The requested resource MUST be accessed through the proxy given
* by the Location field. The Location field gives the URI of the
* proxy. The recipient is expected to repeat this single request
* via the proxy. 305 responses MUST only be generated by origin
* servers."
*/
break;
}
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
continue; continue;
} }
#ifdef USE_OLD_DISCONNECT
curl_disconnect(c_connect); curl_disconnect(c_connect);
#endif
} }
break; /* it only reaches here when this shouldn't loop */ break; /* it only reaches here when this shouldn't loop */

1867
lib/url.c

File diff suppressed because it is too large Load Diff

View File

@@ -82,8 +82,8 @@
/* 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)
/* Upload buffer size, keep it smallish to get faster progress meter /* Defaul upload buffer size, keep it smallish to get faster progress meter
updates. This should probably become dynamic and adjust to the upload updates. This is just default, it is dynamic and adjusts to the upload
speed. */ speed. */
#define UPLOAD_BUFSIZE (1024*2) #define UPLOAD_BUFSIZE (1024*2)
@@ -91,10 +91,14 @@
of need. */ of need. */
#define HEADERSIZE 256 #define HEADERSIZE 256
/* Just a convenience macro to get the larger value out of two given */
#ifndef MAX #ifndef MAX
#define MAX(x,y) ((x)>(y)?(x):(y)) #define MAX(x,y) ((x)>(y)?(x):(y))
#endif #endif
/* Type of handle. All publicly returned 'handles' in the curl interface
have a handle first in the struct that describes what kind of handle it
is. Used to detect bad handle usage. */
typedef enum { typedef enum {
STRUCT_NONE, STRUCT_NONE,
STRUCT_OPEN, STRUCT_OPEN,
@@ -102,6 +106,8 @@ typedef enum {
STRUCT_LAST STRUCT_LAST
} Handle; } Handle;
/* Connecting to a remote server using the curl interface is moving through
a state machine, this type is used to store the current state */
typedef enum { typedef enum {
CONN_NONE, /* illegal state */ CONN_NONE, /* illegal state */
CONN_INIT, /* curl_connect() has been called */ CONN_INIT, /* curl_connect() has been called */
@@ -112,6 +118,7 @@ typedef enum {
} ConnState; } ConnState;
#ifdef KRB4 #ifdef KRB4
/* Types needed for krb4-ftp connections */
struct krb4buffer { struct krb4buffer {
void *data; void *data;
size_t size; size_t size;
@@ -126,6 +133,64 @@ enum protection_level {
}; };
#endif #endif
/* struct for data related to SSL and SSL connections */
struct ssl_connect_data {
bool use; /* use ssl encrypted communications TRUE/FALSE */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
struct ssl_config_data {
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
};
/****************************************************************************
* HTTP unique setup
***************************************************************************/
struct HTTP {
struct FormData *sendit;
int postsize;
char *p_pragma; /* Pragma: string */
char *p_accept; /* Accept: string */
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; /* user name string */
char *passwd; /* password string */
char *urlpath; /* the originally given path part of the URL */
char *dir; /* decoded directory */
char *file; /* decoded file */
char *entrypath; /* the PWD reply when we logged on */
};
/*
* Boolean values that concerns this connection.
*/
struct ConnectBits {
bool close; /* if set, we close the connection after this request */
bool reuse; /* if set, this is a re-used connection */
};
/* /*
* The connectdata struct contains all fields and variables that should be * The connectdata struct contains all fields and variables that should be
* unique for an entire connection. * unique for an entire connection.
@@ -138,6 +203,9 @@ struct connectdata {
Handle handle; /* struct identifier */ Handle handle; /* struct identifier */
struct UrlData *data; /* link to the root CURL struct */ struct UrlData *data; /* link to the root CURL struct */
int connectindex; /* what index in the connects index this particular
struct has */
/**** curl_connect() phase fields */ /**** curl_connect() phase fields */
ConnState state; /* for state dependent actions */ ConnState state; /* for state dependent actions */
@@ -152,20 +220,38 @@ struct connectdata {
#define PROT_LDAP (1<<7) #define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8) #define PROT_FILE (1<<8)
#ifdef ENABLE_IPV6
struct addrinfo *hp; /* host info pointer list */
struct addrinfo *ai; /* the particular host we use */
#else
char *hostent_buf; /* pointer to allocated memory for name info */ char *hostent_buf; /* pointer to allocated memory for name info */
struct hostent *hp; struct hostent *hp;
struct sockaddr_in serv_addr; struct sockaddr_in serv_addr;
char proto[64]; #endif
char gname[256]; char protostr[64]; /* store the protocol string in this buffer */
char *name; char gname[257]; /* store the hostname in this buffer */
char *path; /* formerly staticly this size: URL_MAX_LENGTH */ char *name; /* host name pointer to fool around with */
char *path; /* allocated buffer to store the URL's path part in */
char *hostname; /* hostname to connect, as parsed from url */
long port; /* which port to use locally */
unsigned short remote_port; /* what remote port to connect to,
not the proxy port! */
char *ppath; char *ppath;
long bytecount; long bytecount;
struct timeval now; struct timeval now; /* current time */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE
never smaller than UPLOAD_BUFSIZE */ never smaller than UPLOAD_BUFSIZE */
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */
struct ssl_connect_data ssl; /* this is for ssl-stuff */
struct ConnectBits bits; /* various state-flags for this connection */
/* These two functions MUST be set by the curl_connect() function to be /* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */ be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect); CURLcode (*curl_do)(struct connectdata *connect);
@@ -176,6 +262,11 @@ struct connectdata {
*/ */
CURLcode (*curl_connect)(struct connectdata *connect); CURLcode (*curl_connect)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run
* by the curl_disconnect(), as a step in the disconnection.
*/
CURLcode (*curl_disconnect)(struct connectdata *connect);
/* This function *MAY* be set to a protocol-dependent function that is run /* This function *MAY* be set to a protocol-dependent function that is run
* in the curl_close() function if protocol-specific cleanups are required. * in the curl_close() function if protocol-specific cleanups are required.
*/ */
@@ -194,6 +285,18 @@ struct connectdata {
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 */
/** Dynamicly allocated strings, may need to be freed before this **/
/** struct is killed. **/
struct dynamically_allocated_data {
char *proxyuserpwd; /* free later if not NULL! */
char *uagent; /* free later if not NULL! */
char *userpwd; /* free later if not NULL! */
char *rangeline; /* free later if not NULL! */
char *ref; /* free later if not NULL! */
char *cookie; /* free later if not NULL! */
char *host; /* free later if not NULL */
} allocptr;
#ifdef KRB4 #ifdef KRB4
enum protection_level command_prot; enum protection_level command_prot;
@@ -207,6 +310,24 @@ struct connectdata {
void *app_data; void *app_data;
#endif #endif
/*************** Request - specific items ************/
/* previously this was in the urldata struct */
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;
}; };
struct Progress { struct Progress {
@@ -242,36 +363,25 @@ struct Progress {
int speeder_c; int speeder_c;
}; };
/**************************************************************************** typedef enum {
* HTTP unique setup HTTPREQ_NONE, /* first in list */
***************************************************************************/ HTTPREQ_GET,
struct HTTP { HTTPREQ_POST,
struct FormData *sendit; HTTPREQ_POST_FORM, /* we make a difference internally */
int postsize; HTTPREQ_PUT,
char *p_pragma; HTTPREQ_CUSTOM,
char *p_accept; HTTPREQ_LAST /* last in list */
long readbytecount; } Curl_HttpReq;
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 */
};
/* This struct is for boolean settings that define how to behave during
this session. */
struct Configbits { struct Configbits {
/* these four request types mirror the httpreq field */
bool http_formpost;
bool http_post;
bool http_put;
bool http_get;
bool get_filetime; bool get_filetime;
bool tunnel_thru_httpproxy; bool tunnel_thru_httpproxy;
bool ftp_append; bool ftp_append;
@@ -281,10 +391,7 @@ struct Configbits {
bool hide_progress; bool hide_progress;
bool http_fail_on_error; bool http_fail_on_error;
bool http_follow_location; bool http_follow_location;
bool http_formpost;
bool http_include_header; bool http_include_header;
bool http_post;
bool http_put;
bool http_set_referer; bool http_set_referer;
bool http_auto_referer; /* set "correct" referer when following location: */ bool http_auto_referer; /* set "correct" referer when following location: */
bool httpproxy; bool httpproxy;
@@ -299,7 +406,6 @@ struct Configbits {
bool verbose; bool verbose;
bool this_is_a_follow; /* this is a followed Location: request */ bool this_is_a_follow; /* this is a followed Location: request */
bool krb4; /* kerberos4 connection requested */ bool krb4; /* kerberos4 connection requested */
bool proxystringalloc; /* the http proxy string is malloc()'ed */ bool proxystringalloc; /* the http proxy string is malloc()'ed */
bool rangestringalloc; /* the range string is malloc()'ed */ bool rangestringalloc; /* the range string is malloc()'ed */
bool urlstringalloc; /* the URL string is malloc()'ed */ bool urlstringalloc; /* the URL string is malloc()'ed */
@@ -313,21 +419,6 @@ typedef enum {
CURLI_LAST CURLI_LAST
} CurlInterface; } CurlInterface;
struct ssldata {
bool use; /* use ssl encrypted communications TRUE/FALSE */
long version; /* what version the client wants to use */
long certverifyresult; /* result from the certificate verification */
long verifypeer; /* set TRUE if this is desired */
char *CApath; /* DOES NOT WORK ON WINDOWS */
char *CAfile; /* cerficate to verify peer against */
#ifdef USE_SSLEAY
/* these ones requires specific SSL-types */
SSL_CTX* ctx;
SSL* handle;
X509* server_cert;
#endif /* USE_SSLEAY */
};
/* /*
* As of April 11, 2000 we're now trying to split up the urldata struct in * As of April 11, 2000 we're now trying to split up the urldata struct in
* three different parts: * three different parts:
@@ -342,8 +433,15 @@ struct ssldata {
* *
* (Request) * (Request)
* 3 - Request-specific. Variables that are of interest for this particular * 3 - Request-specific. Variables that are of interest for this particular
* transfer being made right now. * transfer being made right now. THIS IS WRONG STRUCT FOR THOSE.
* *
* In Febrary 2001, this is being done stricter. The 'connectdata' struct
* MUST have all the connection oriented stuff as we may now have several
* simultaneous connections and connection structs in memory.
*
* From now on, the 'UrlData' must only contain data that is set once to go
* for many (perhaps) independent connections. Values that are generated or
* calculated internally MUST NOT be a part of this struct.
*/ */
struct UrlData { struct UrlData {
@@ -355,7 +453,7 @@ struct UrlData {
char *errorbuffer; /* store failure messages in here */ char *errorbuffer; /* store failure messages in here */
/*************** Session - specific items ************/ /*************** Session - specific items ************/
char *proxy; /* if proxy, set it here, set CONF_PROXY to use this */ char *proxy; /* if proxy, set it here */
char *proxyuserpwd; /* Proxy <user:password>, if used */ char *proxyuserpwd; /* Proxy <user:password>, if used */
long proxyport; /* If non-zero, use this port number by default. If the long proxyport; /* If non-zero, use this port number by default. If the
proxy string features a ":[port]" that one will override proxy string features a ":[port]" that one will override
@@ -365,33 +463,14 @@ struct UrlData {
long header_size; /* size of read header(s) in bytes */ long header_size; /* size of read header(s) in bytes */
long request_size; /* the amount of bytes sent in the request(s) */ long request_size; /* the amount of bytes sent in the request(s) */
/*************** 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 *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 connect, as parsed from url */ long use_port; /* which port to use (when not using default) */
long port; /* which port to use (if non-protocol bind) set
CONF_PORT to use this */
unsigned short remote_port; /* what remote port to connect to, not the proxy
port! */
struct Configbits bits; /* new-style (v7) flag data */ struct Configbits bits; /* new-style (v7) flag data */
struct ssl_config_data ssl; /* this is for ssl-stuff */
char *userpwd; /* <user:password>, if used */ char *userpwd; /* <user:password>, if used */
char *range; /* range, if used. See README for detailed specification on char *range; /* range, if used. See README for detailed specification on
@@ -433,13 +512,6 @@ struct UrlData {
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 */
long maxdownload; /* in bytes, the maximum amount of data to fetch, 0
means unlimited */
/* fields only set and used within _urlget() */
int firstsocket; /* the main socket to use */
int secondarysocket; /* for i.e ftp transfers */
char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */ char buffer[BUFSIZE+1]; /* buffer with size BUFSIZE */
double current_speed; /* the ProgressShow() funcion sets this */ double current_speed; /* the ProgressShow() funcion sets this */
@@ -462,27 +534,24 @@ struct UrlData {
struct CookieInfo *cookies; struct CookieInfo *cookies;
struct ssldata ssl; /* this is for ssl-stuff */
long crlf; long crlf;
struct curl_slist *quote; /* before the transfer */ struct curl_slist *quote; /* before the transfer */
struct curl_slist *postquote; /* after the transfer */ struct curl_slist *postquote; /* after the transfer */
TimeCond timecondition; /* Telnet negotiation options */
time_t timevalue; struct curl_slist *telnet_options; /* linked list of telnet options */
TimeCond timecondition; /* kind of comparison */
time_t timevalue; /* what time to compare with */
Curl_HttpReq httpreq; /* what kind of HTTP request (if any) is this */
char *customrequest; /* http/ftp request to use */ char *customrequest; /* http/ftp request to use */
char *headerbuff; /* allocated buffer to store headers in */ char *headerbuff; /* allocated buffer to store headers in */
int headersize; /* size of the allocation */ int headersize; /* size of the allocation */
#if 0 struct Progress progress; /* for all the progress meter data */
/* this was removed in libcurl 7.4 */
char *writeinfo; /* if non-NULL describes what to output on a successful
completion */
#endif
struct Progress progress;
#define MAX_CURL_USER_LENGTH 128 #define MAX_CURL_USER_LENGTH 128
#define MAX_CURL_PASSWORD_LENGTH 128 #define MAX_CURL_PASSWORD_LENGTH 128
@@ -492,30 +561,215 @@ struct UrlData {
* host (which location-following otherwise could lead to) * host (which location-following otherwise could lead to)
*/ */
/* buffers to store authentication data in */
char user[MAX_CURL_USER_LENGTH]; char user[MAX_CURL_USER_LENGTH];
char passwd[MAX_CURL_PASSWORD_LENGTH]; char passwd[MAX_CURL_PASSWORD_LENGTH];
char proxyuser[MAX_CURL_USER_LENGTH]; char proxyuser[MAX_CURL_USER_LENGTH];
char proxypasswd[MAX_CURL_PASSWORD_LENGTH]; char proxypasswd[MAX_CURL_PASSWORD_LENGTH];
/**** Dynamicly allocated strings, may need to be freed on return ****/ char *krb4_level; /* what security level */
char *ptr_proxyuserpwd; /* free later if not NULL! */
char *ptr_uagent; /* free later if not NULL! */
char *ptr_userpwd; /* free later if not NULL! */
char *ptr_rangeline; /* free later if not NULL! */
char *ptr_ref; /* free later if not NULL! */
char *ptr_cookie; /* free later if not NULL! */
char *ptr_host; /* free later if not NULL */
char *krb4_level;
#ifdef KRB4 #ifdef KRB4
FILE *cmdchannel; FILE *cmdchannel;
#endif #endif
struct timeval keeps_speed; /* this should be request-specific */ struct timeval keeps_speed; /* this should be request-specific */
/* 'connects' will be an allocated array with pointers. If the pointer is
set, it holds an allocated connection. */
struct connectdata **connects;
size_t numconnects; /* size of the 'connects' array */
curl_closepolicy closepolicy;
}; };
#define LIBCURL_NAME "libcurl" #define LIBCURL_NAME "libcurl"
#define LIBCURL_ID LIBCURL_NAME " " LIBCURL_VERSION " " SSL_ID #define LIBCURL_ID LIBCURL_NAME " " LIBCURL_VERSION " " SSL_ID
/*
* Here follows function prototypes from what we used to plan to call
* the "low level" interface. It is no longer prioritized and it is not likely
* to ever be supported to external users.
*/
/*
* 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,
ssize_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().
*
* By setting 'allow_port' to FALSE, the data->use_port will *NOT* be
* respected.
*
* EXAMPLE
*
* CURLCode result;
* CURL curl;
* CURLconnect connect;
* result = curl_connect(curl, &connect); */
CURLcode curl_connect(CURL *curl,
CURLconnect **in_connect,
bool allow_port);
/*
* 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);
#endif #endif

View File

@@ -61,8 +61,18 @@ char *curl_version(void)
ptr=strchr(ptr, '\0'); ptr=strchr(ptr, '\0');
#endif #endif
#if defined(KRB4) || defined(ENABLE_IPV6)
strcat(ptr, " (");
ptr+=2;
#ifdef KRB4 #ifdef KRB4
sprintf(ptr, " (krb4 enabled)"); sprintf(ptr, "krb4 ");
ptr += strlen(ptr);
#endif
#ifdef ENABLE_IPV6
sprintf(ptr, "ipv6 ");
ptr += strlen(ptr);
#endif
sprintf(ptr, "enabled)");
ptr += strlen(ptr); ptr += strlen(ptr);
#endif #endif

View File

@@ -26,13 +26,17 @@ while(<STDIN>) {
if($function =~ /free\(0x([0-9a-f]*)/) { if($function =~ /free\(0x([0-9a-f]*)/) {
$addr = $1; $addr = $1;
if($sizeataddr{$addr} <= 0) { if($sizeataddr{$addr} == 0) {
print "FREE ERROR: No memory allocated: $line\n"; print "FREE ERROR: No memory allocated: $line\n";
} }
elsif(-1 == $sizeataddr{$addr}) {
print "FREE ERROR: Memory freed twice: $line\n";
print "FREE ERROR: Previously freed at: ".$getmem{$addr}."\n";
}
else { else {
$totalmem -= $sizeataddr{$addr}; $totalmem -= $sizeataddr{$addr};
$sizeataddr{$addr}=0; $sizeataddr{$addr}=-1; # set -1 to mark as freed
$getmem{$addr}=""; # forget after a good free() $getmem{$addr}="$source:$linenum";
} }
} }
elsif($function =~ /malloc\((\d*)\) = 0x([0-9a-f]*)/) { elsif($function =~ /malloc\((\d*)\) = 0x([0-9a-f]*)/) {
@@ -141,7 +145,7 @@ if($totalmem) {
for(keys %sizeataddr) { for(keys %sizeataddr) {
$addr = $_; $addr = $_;
$size = $sizeataddr{$addr}; $size = $sizeataddr{$addr};
if($size) { if($size > 0) {
print "At $addr, there's $size bytes.\n"; print "At $addr, there's $size bytes.\n";
print " allocated by ".$getmem{$addr}."\n"; print " allocated by ".$getmem{$addr}."\n";
} }

View File

@@ -17,7 +17,7 @@ LINKR = link.exe /incremental:no /libpath:"../lib"
## Debug ## Debug
CCD = cl.exe /MDd /Gm /ZI /Od /D "_DEBUG" /GZ CCD = cl.exe /MDd /Gm /ZI /Od /D "_DEBUG" /GZ
LINKD = link.exe /incremental:yes /debug LINKD = link.exe /incremental:yes /debug /libpath:"../lib"
CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c CFLAGS = /I "../include" /nologo /W3 /GX /D "WIN32" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
LFLAGS = /nologo /out:$(PROGRAM_NAME) /subsystem:console /machine:I386 LFLAGS = /nologo /out:$(PROGRAM_NAME) /subsystem:console /machine:I386

View File

@@ -48,7 +48,7 @@
/* 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 #if defined(WIN32)&&!defined(__CYGWIN32__)
#include <winsock.h> #include <winsock.h>
#endif #endif
@@ -102,14 +102,13 @@ typedef enum {
#define CONF_NOBODY (1<<11) /* use HEAD to get http document */ #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_FAILONERROR (1<<12) /* no output on http error codes >= 300 */
#define CONF_UPLOAD (1<<14) /* this is an upload */ #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_FTPLISTONLY (1<<16) /* Use NLST when listing ftp dir */
#define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */ #define CONF_FTPAPPEND (1<<20) /* Append instead of overwrite on upload! */
#define CONF_NETRC (1<<22) /* read user+password from .netrc */ #define CONF_NETRC (1<<22) /* read user+password from .netrc */
#define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */ #define CONF_FOLLOWLOCATION (1<<23) /* use Location: Luke! */
#define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */ #define CONF_GETTEXT (1<<24) /* use ASCII/text for transfer */
#define CONF_HTTPPOST (1<<25) /* multipart/form-data HTTP POST */ #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 */ #define CONF_MUTE (1<<28) /* force NOPROGRESS */
#ifndef HAVE_STRDUP #ifndef HAVE_STRDUP
@@ -244,7 +243,6 @@ static void help(void)
" -A/--user-agent <string> User-Agent to send to server (H)\n" " -A/--user-agent <string> User-Agent to send to server (H)\n"
" -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)\n" " -b/--cookie <name=string/file> Cookie string or file to read cookies from (H)\n"
" -B/--use-ascii Use ASCII/text transfer\n" " -B/--use-ascii Use ASCII/text transfer\n"
" -c/--continue Resume a previous transfer where we left it\n"
" -C/--continue-at <offset> Specify absolute resume offset\n" " -C/--continue-at <offset> Specify absolute resume offset\n"
" -d/--data <data> HTTP POST data (H)\n" " -d/--data <data> HTTP POST data (H)\n"
" --data-ascii <data> HTTP POST ASCII data (H)\n" " --data-ascii <data> HTTP POST ASCII data (H)\n"
@@ -278,7 +276,7 @@ static void help(void)
" -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n" " -r/--range <range> Retrieve a byte range from a HTTP/1.1 or FTP server\n"
" -s/--silent Silent mode. Don't output anything\n" " -s/--silent Silent mode. Don't output anything\n"
" -S/--show-error Show error. With -s, make curl show errors when they occur\n" " -S/--show-error Show error. With -s, make curl show errors when they occur\n"
" -t/--upload Transfer/upload stdin to remote site\n" " -t/--telnet-option <OPT=val> Set telnet option\n"
" -T/--upload-file <file> Transfer/upload <file> to remote site\n" " -T/--upload-file <file> Transfer/upload <file> to remote site\n"
" --url <URL> Another way to specify URL to work with\n" " --url <URL> Another way to specify URL to work with\n"
" -u/--user <user[:password]> Specify user and password to use\n" " -u/--user <user[:password]> Specify user and password to use\n"
@@ -366,6 +364,8 @@ struct Configurable {
struct HttpPost *httppost; struct HttpPost *httppost;
struct HttpPost *last_post; struct HttpPost *last_post;
struct curl_slist *telnet_options;
HttpReq httpreq; HttpReq httpreq;
}; };
@@ -565,7 +565,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"r", "range", TRUE}, {"r", "range", TRUE},
{"s", "silent", FALSE}, {"s", "silent", FALSE},
{"S", "show-error", FALSE}, {"S", "show-error", FALSE},
{"t", "upload", FALSE}, {"t", "telnet-options", TRUE},
{"T", "upload-file", TRUE}, {"T", "upload-file", TRUE},
{"u", "user", TRUE}, {"u", "user", TRUE},
{"U", "proxy-user", TRUE}, {"U", "proxy-user", TRUE},
@@ -785,8 +785,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
else else
config->postfields=postdata; config->postfields=postdata;
} }
if(config->postfields)
config->conf |= CONF_POST;
if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq)) if(SetHTTPrequest(HTTPREQ_SIMPLEPOST, &config->httpreq))
return PARAM_BAD_USE; return PARAM_BAD_USE;
break; break;
@@ -959,9 +958,8 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
config->showerror ^= TRUE; /* toggle on if used with -s */ config->showerror ^= TRUE; /* toggle on if used with -s */
break; break;
case 't': case 't':
/* we are uploading */ /* Telnet options */
config->conf ^= CONF_UPLOAD; config->telnet_options = curl_slist_append(config->telnet_options, nextarg);
fprintf(stderr, "-t is a deprecated switch, use '-T -' instead!\n");
break; break;
case 'T': case 'T':
/* we are uploading */ /* we are uploading */
@@ -1579,7 +1577,9 @@ operate(struct Configurable *config, int argc, char *argv[])
/* multiple files extracted to stdout, insert separators! */ /* multiple files extracted to stdout, insert separators! */
separator = 1; separator = 1;
} }
for (i = 0; (url = urls?next_url(urls):(i?NULL:url)); ++i) { for(i = 0;
(url = urls?next_url(urls):(i?NULL:strdup(url)));
i++) {
char *outfile; char *outfile;
outfile = outfiles?strdup(outfiles):NULL; outfile = outfiles?strdup(outfiles):NULL;
@@ -1713,7 +1713,7 @@ operate(struct Configurable *config, int argc, char *argv[])
if(!config->errors) if(!config->errors)
config->errors = stderr; config->errors = stderr;
#ifdef WIN32 #if defined(WIN32) && !defined(__CYGWIN32__)
if(!outfile && !(config->conf & CONF_GETTEXT)) { if(!outfile && !(config->conf & CONF_GETTEXT)) {
/* We get the output to stdout and we have not got the ASCII/text flag, /* We get the output to stdout and we have not got the ASCII/text flag,
then set stdout to be binary */ then set stdout to be binary */
@@ -1741,7 +1741,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FAILONERROR, curl_easy_setopt(curl, CURLOPT_FAILONERROR,
config->conf&CONF_FAILONERROR); config->conf&CONF_FAILONERROR);
curl_easy_setopt(curl, CURLOPT_UPLOAD, config->conf&CONF_UPLOAD); 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, curl_easy_setopt(curl, CURLOPT_FTPLISTONLY,
config->conf&CONF_FTPLISTONLY); config->conf&CONF_FTPLISTONLY);
curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND); curl_easy_setopt(curl, CURLOPT_FTPAPPEND, config->conf&CONF_FTPAPPEND);
@@ -1749,7 +1748,6 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION,
config->conf&CONF_FOLLOWLOCATION); config->conf&CONF_FOLLOWLOCATION);
curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT); curl_easy_setopt(curl, CURLOPT_TRANSFERTEXT, config->conf&CONF_GETTEXT);
curl_easy_setopt(curl, CURLOPT_PUT, config->conf&CONF_PUT);
curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE); curl_easy_setopt(curl, CURLOPT_MUTE, config->conf&CONF_MUTE);
curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd); curl_easy_setopt(curl, CURLOPT_USERPWD, config->userpwd);
curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd); curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, config->proxyuserpwd);
@@ -1820,6 +1818,9 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &progressbar);
} }
/* new in libcurl 7.6.2: */
curl_easy_setopt(curl, CURLOPT_TELNETOPTIONS, config->telnet_options);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
if(config->writeout) { if(config->writeout) {

View File

@@ -32,9 +32,23 @@
#include "../lib/memdebug.h" #include "../lib/memdebug.h"
#endif #endif
int glob_word(URLGlob *, char*, int); typedef enum {
GLOB_OK,
GLOB_ERROR
} GlobCode;
int glob_set(URLGlob *glob, char *pattern, int pos) /*
* glob_word()
*
* Input a full globbed string, set the forth argument to the amount of
* strings we get out of this. Return GlobCode.
*/
GlobCode glob_word(URLGlob *, /* object anchor */
char *, /* globbed string */
int, /* position */
int *); /* returned number of strings */
GlobCode glob_set(URLGlob *glob, char *pattern, int pos, int *amount)
{ {
/* processes a set expression with the point behind the opening '{' /* processes a set expression with the point behind the opening '{'
','-separated elements are collected until the next closing '}' ','-separated elements are collected until the next closing '}'
@@ -52,13 +66,15 @@ int glob_set(URLGlob *glob, char *pattern, int pos)
while (1) { while (1) {
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 (CURLE_URL_MALFORMAT); return GLOB_ERROR;
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 (CURLE_URL_MALFORMAT); return GLOB_ERROR;
case ',': case ',':
case '}': /* set element completed */ case '}': /* set element completed */
*buf = '\0'; *buf = '\0';
@@ -66,40 +82,51 @@ int glob_set(URLGlob *glob, char *pattern, int pos)
realloc(pat->content.Set.elements, realloc(pat->content.Set.elements,
(pat->content.Set.size + 1) * sizeof(char*)); (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(CURLE_OUT_OF_MEMORY); return GLOB_ERROR;
} }
pat->content.Set.elements[pat->content.Set.size] = pat->content.Set.elements[pat->content.Set.size] =
strdup(glob->glob_buffer); strdup(glob->glob_buffer);
++pat->content.Set.size; ++pat->content.Set.size;
if (*pattern == '}') /* entire set pattern completed */ if (*pattern == '}') {
/* entire set pattern completed */
int wordamount;
/* always check for a literal (may be "") between patterns */ /* always check for a literal (may be "") between patterns */
return pat->content.Set.size * glob_word(glob, ++pattern, ++pos); if(GLOB_ERROR == glob_word(glob, ++pattern, ++pos, &wordamount))
wordamount=1;
*amount = pat->content.Set.size * wordamount;
return GLOB_OK;
}
buf = glob->glob_buffer; buf = glob->glob_buffer;
++pattern; ++pattern;
++pos; ++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 (CURLE_URL_MALFORMAT); return GLOB_ERROR;
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 (CURLE_URL_MALFORMAT); return GLOB_ERROR;
} }
++pattern; ++pattern;
++pos; /* intentional fallthrough */ ++pos; /* intentional fallthrough */
default: default:
*buf++ = *pattern++; /* copy character to set element */ *buf++ = *pattern++; /* copy character to set element */
++pos; ++pos;
} }
} }
exit (CURLE_FAILED_INIT); return GLOB_ERROR;
} }
int glob_range(URLGlob *glob, char *pattern, int pos) GlobCode glob_range(URLGlob *glob, char *pattern, int pos, int *amount)
{ {
/* processes a range expression with the point behind the opening '[' /* processes a range expression with the point behind the opening '['
- char range: e.g. "a-z]", "B-Q]" - char range: e.g. "a-z]", "B-Q]"
@@ -109,6 +136,7 @@ int glob_range(URLGlob *glob, char *pattern, int pos)
*/ */
URLPattern *pat; URLPattern *pat;
char *c; char *c;
int wordamount=1;
pat = (URLPattern*)&glob->pattern[glob->size / 2]; pat = (URLPattern*)&glob->pattern[glob->size / 2];
/* patterns 0,1,2,... correspond to size=1,3,5,... */ /* patterns 0,1,2,... correspond to size=1,3,5,... */
@@ -116,44 +144,71 @@ int glob_range(URLGlob *glob, char *pattern, int pos)
if (isalpha((int)*pattern)) { /* character range detected */ if (isalpha((int)*pattern)) { /* character range detected */
pat->type = UPTCharRange; pat->type = UPTCharRange;
if (sscanf(pattern, "%c-%c]", &pat->content.CharRange.min_c, &pat->content.CharRange.max_c) != 2 || if (sscanf(pattern, "%c-%c]", &pat->content.CharRange.min_c,
&pat->content.CharRange.max_c) != 2 ||
pat->content.CharRange.min_c >= pat->content.CharRange.max_c || pat->content.CharRange.min_c >= pat->content.CharRange.max_c ||
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); #if 0
exit (CURLE_URL_MALFORMAT); printf("error: illegal pattern or range specification after pos %d\n",
pos);
#endif
return GLOB_ERROR;
} }
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 */
return (pat->content.CharRange.max_c - pat->content.CharRange.min_c + 1) *
glob_word(glob, pattern + 4, pos + 4); if(GLOB_ERROR == glob_word(glob, pattern + 4, pos + 4, &wordamount))
wordamount=1;
*amount = (pat->content.CharRange.max_c -
pat->content.CharRange.min_c + 1) *
wordamount;
return GLOB_OK;
} }
if (isdigit((int)*pattern)) { /* numeric range detected */
if (isdigit((int)*pattern)) { /* numeric range detected */
pat->type = UPTNumRange; pat->type = UPTNumRange;
pat->content.NumRange.padlength = 0; pat->content.NumRange.padlength = 0;
if (sscanf(pattern, "%d-%d]", &pat->content.NumRange.min_n, &pat->content.NumRange.max_n) != 2 || if (sscanf(pattern, "%d-%d]",
&pat->content.NumRange.min_n,
&pat->content.NumRange.max_n) != 2 ||
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); #if 0
exit (CURLE_URL_MALFORMAT); printf("error: illegal pattern or range specification after pos %d\n",
pos);
#endif
return GLOB_ERROR;
} }
if (*pattern == '0') { /* leading zero specified */ if (*pattern == '0') { /* leading zero specified */
c = pattern; c = pattern;
while (isdigit((int)*c++)) while (isdigit((int)*c++))
++pat->content.NumRange.padlength; /* padding length is set for all instances ++pat->content.NumRange.padlength; /* padding length is set for all
of this pattern */ instances of this pattern */
} }
pat->content.NumRange.ptr_n = pat->content.NumRange.min_n; pat->content.NumRange.ptr_n = pat->content.NumRange.min_n;
c = (char*)(strchr(pattern, ']') + 1); /* continue after next ']' */ c = (char*)(strchr(pattern, ']') + 1); /* continue after next ']' */
/* always check for a literal (may be "") between patterns */ /* always check for a literal (may be "") between patterns */
return (pat->content.NumRange.max_n - pat->content.NumRange.min_n + 1) *
glob_word(glob, c, pos + (c - pattern)); if(GLOB_ERROR == glob_word(glob, c, pos + (c - pattern), &wordamount))
wordamount = 1;
*amount = (pat->content.NumRange.max_n -
pat->content.NumRange.min_n + 1) *
wordamount;
return GLOB_OK;
} }
printf("error: illegal character in range specification at pos %d\n", pos); /*printf("error: illegal character in range specification at pos %d\n",
exit (CURLE_URL_MALFORMAT); pos);*/
return GLOB_ERROR;
} }
int glob_word(URLGlob *glob, char *pattern, int pos) GlobCode glob_word(URLGlob *glob, char *pattern, int pos, int *amount)
{ {
/* processes a literal string component of a URL /* processes a literal string component of a URL
special characters '{' and '[' branch to set/range processing functions special characters '{' and '[' branch to set/range processing functions
@@ -161,17 +216,17 @@ int glob_word(URLGlob *glob, char *pattern, int pos)
char* buf = glob->glob_buffer; char* buf = glob->glob_buffer;
int litindex; int litindex;
*amount = 1; /* default is one single string */
while (*pattern != '\0' && *pattern != '{' && *pattern != '[') { while (*pattern != '\0' && *pattern != '{' && *pattern != '[') {
if (*pattern == '}' || *pattern == ']') { if (*pattern == '}' || *pattern == ']') {
printf("illegal character at position %d\n", pos); return GLOB_ERROR;
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); return GLOB_ERROR;
exit (CURLE_URL_MALFORMAT);
} }
} }
*buf++ = *pattern++; /* copy character to literal */ *buf++ = *pattern++; /* copy character to literal */
@@ -182,16 +237,21 @@ int glob_word(URLGlob *glob, char *pattern, int pos)
/* literals 0,1,2,... correspond to size=0,2,4,... */ /* literals 0,1,2,... correspond to size=0,2,4,... */
glob->literal[litindex] = strdup(glob->glob_buffer); glob->literal[litindex] = strdup(glob->glob_buffer);
++glob->size; ++glob->size;
if (*pattern == '\0')
return 1; /* singular URL processed */ switch (*pattern) {
if (*pattern == '{') { case '\0':
return glob_set(glob, ++pattern, ++pos); /* process set pattern */ return GLOB_OK; /* singular URL processed */
case '{':
/* process set pattern */
return glob_set(glob, ++pattern, ++pos, amount);
case '[':
/* process range pattern */
return glob_range(glob, ++pattern, ++pos, amount);
} }
if (*pattern == '[') {
return glob_range(glob, ++pattern, ++pos);/* process range pattern */ return GLOB_ERROR; /* something got wrong */
}
printf("internal error\n");
exit (CURLE_FAILED_INIT);
} }
int glob_url(URLGlob** glob, char* url, int *urlnum) int glob_url(URLGlob** glob, char* url, int *urlnum)
@@ -201,7 +261,9 @@ int glob_url(URLGlob** glob, char* url, int *urlnum)
* as the specified URL! * as the specified URL!
*/ */
URLGlob *glob_expand; URLGlob *glob_expand;
int amount;
char *glob_buffer=(char *)malloc(strlen(url)+1); char *glob_buffer=(char *)malloc(strlen(url)+1);
if(NULL == glob_buffer) if(NULL == glob_buffer)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@@ -214,7 +276,16 @@ int glob_url(URLGlob** glob, char* url, int *urlnum)
glob_expand->urllen = strlen(url); glob_expand->urllen = strlen(url);
glob_expand->glob_buffer = glob_buffer; glob_expand->glob_buffer = glob_buffer;
glob_expand->beenhere=0; glob_expand->beenhere=0;
*urlnum = glob_word(glob_expand, url, 1); if(GLOB_OK == glob_word(glob_expand, url, 1, &amount))
*urlnum = amount;
else {
/* it failed, we cleanup */
free(glob_buffer);
free(glob_expand);
glob_expand = NULL;
*urlnum = 1;
}
*glob = glob_expand; *glob = glob_expand;
return CURLE_OK; return CURLE_OK;
} }

View File

@@ -1,3 +1,3 @@
#define CURL_NAME "curl" #define CURL_NAME "curl"
#define CURL_VERSION "7.6-pre3" #define CURL_VERSION "7.7-alpha2"
#define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") " #define CURL_ID CURL_NAME " " CURL_VERSION " (" OS ") "

View File

@@ -53,4 +53,13 @@ command8.txt name14.txt prot5.txt \
command9.txt name15.txt prot6.txt \ command9.txt name15.txt prot6.txt \
error111.txt name16.txt prot7.txt \ error111.txt name16.txt prot7.txt \
command26.txt prot26.txt command27.txt prot27.txt \ command26.txt prot26.txt command27.txt prot27.txt \
name26.txt reply26.txt name27.txt stdout27.txt name26.txt reply26.txt name27.txt stdout27.txt \
command28.txt name28.txt prot28.txt reply28.txt \
command120.txt name120.txt prot120.txt reply120.txt \
command121.txt name121.txt prot121.txt reply121.txt \
command29.txt error30.txt name30.txt prot30.txt reply30.txt \
command30.txt name29.txt prot29.txt reply29.txt \
command31.txt name32.txt reply31.txt reply32.txt \
command32.txt prot31.txt reply310001.txt reply320001.txt \
name31.txt prot32.txt reply310002.txt reply320002.txt \
command33.txt extra33.txt name33.txt prot33.txt reply33.txt

View File

@@ -0,0 +1,3 @@
ftp://%HOSTIP:%FTPPORT/106 -Q "-DELE file"

View File

@@ -0,0 +1 @@
ftp://%HOSTIP:%FTPPORT/106 -Q "-DELE after_transfer" -Q "DELE before_transfer"

1
tests/data/command28.txt Normal file
View File

@@ -0,0 +1 @@
--globoff http://%HOSTIP:%HOSTPORT/wantit/{}[]/28

1
tests/data/command29.txt Normal file
View File

@@ -0,0 +1 @@
-C 200 http://%HOSTIP:%HOSTPORT/29

1
tests/data/command30.txt Normal file
View File

@@ -0,0 +1 @@
http://%HOSTIP:%HOSTPORT/30

2
tests/data/command31.txt Normal file
View File

@@ -0,0 +1,2 @@
http://%HOSTIP:%HOSTPORT/31 -d mooo=fooo -L

2
tests/data/command32.txt Normal file
View File

@@ -0,0 +1,2 @@
http://%HOSTIP:%HOSTPORT/32 -d mooo=fooo -L

3
tests/data/command33.txt Normal file
View File

@@ -0,0 +1,3 @@
http://%HOSTIP:%HOSTPORT/33 -Tdata/extra33.txt -C 50

1
tests/data/error30.txt Normal file
View File

@@ -0,0 +1 @@
18

15
tests/data/extra33.txt Normal file
View File

@@ -0,0 +1,15 @@
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678

1
tests/data/name120.txt Normal file
View File

@@ -0,0 +1 @@
ftp download with post-quote delete operation

1
tests/data/name121.txt Normal file
View File

@@ -0,0 +1 @@
ftp download with post- and pre-transfer delete operations

1
tests/data/name28.txt Normal file
View File

@@ -0,0 +1 @@
--globoff with {][} in URL

1
tests/data/name29.txt Normal file
View File

@@ -0,0 +1 @@
HTTP download resume with Content-Length validity

1
tests/data/name30.txt Normal file
View File

@@ -0,0 +1 @@
HTTP GET uncomplete document

1
tests/data/name31.txt Normal file
View File

@@ -0,0 +1 @@
HTTP POST and follow Location: (error 301)

1
tests/data/name32.txt Normal file
View File

@@ -0,0 +1 @@
HTTP POST and follow Location: (error 303)

1
tests/data/name33.txt Normal file
View File

@@ -0,0 +1 @@
HTTP PUT resume

6
tests/data/prot120.txt Normal file
View File

@@ -0,0 +1,6 @@
USER anonymous
PASS curl_by_daniel@haxx.se
PASV
TYPE I
RETR 106
DELE file

7
tests/data/prot121.txt Normal file
View File

@@ -0,0 +1,7 @@
USER anonymous
PASS curl_by_daniel@haxx.se
DELE before_transfer
PASV
TYPE I
RETR 106
DELE after_transfer

5
tests/data/prot28.txt Normal file
View File

@@ -0,0 +1,5 @@
GET /wantit/{}[]/28 HTTP/1.0
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

7
tests/data/prot29.txt Normal file
View File

@@ -0,0 +1,7 @@
GET /29 HTTP/1.0
Range: bytes=200-
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

6
tests/data/prot30.txt Normal file
View File

@@ -0,0 +1,6 @@
GET /30 HTTP/1.0
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

9
tests/data/prot31.txt Normal file
View File

@@ -0,0 +1,9 @@
POST /moo/moo/moo/310002 HTTP/1.0
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Content-Length: 9
Content-Type: application/x-www-form-urlencoded
mooo=fooo

6
tests/data/prot32.txt Normal file
View File

@@ -0,0 +1,6 @@
GET /moo/moo/moo/320002 HTTP/1.0
User-Agent: curl/7.6 (i686-pc-linux-gnu) libcurl 7.6 (SSL 0.9.5) (ipv6 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*

18
tests/data/prot33.txt Normal file
View File

@@ -0,0 +1,18 @@
PUT /33 HTTP/1.0
Content-Range: bytes 50-149/150
User-Agent: curl/7.6 (sparc-sun-solaris2.7) libcurl 7.6-pre4 (SSL 0.9.6) (krb4 enabled)
Host: 127.0.0.1:8999
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Content-Length: 100
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678
012345678

View File

@@ -2,5 +2,6 @@ HTTP/1.1 301 This is a weirdo text message
Date: Thu, 09 Nov 2010 14:49:00 GMT Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake Server: test-server/fake
Location: data/110002.txt?coolsite=yes Location: data/110002.txt?coolsite=yes
Connection: close
This server reply is for testing a simple Location: following This server reply is for testing a simple Location: following

View File

@@ -2,6 +2,7 @@ HTTP/1.1 301 This is a weirdo text message
Date: Thu, 09 Nov 2010 14:49:00 GMT Date: Thu, 09 Nov 2010 14:49:00 GMT
Server: test-server/fake Server: test-server/fake
Location: data/110002.txt?coolsite=yes Location: data/110002.txt?coolsite=yes
Connection: close
HTTP/1.1 200 Followed here fine HTTP/1.1 200 Followed here fine
Date: Thu, 09 Nov 2010 14:49:00 GMT Date: Thu, 09 Nov 2010 14:49:00 GMT

6
tests/data/reply120.txt Normal file
View File

@@ -0,0 +1,6 @@
data
to
see
that FTP
works
so does it?

6
tests/data/reply121.txt Normal file
View File

@@ -0,0 +1,6 @@
data
to
see
that FTP
works
so does it?

5
tests/data/reply28.txt Normal file
View File

@@ -0,0 +1,5 @@
HTTP/1.1 200 OK
Server: fake
{}[] in the URL is not legal

Some files were not shown because too many files have changed in this diff Show More