Compare commits

..

107 Commits

Author SHA1 Message Date
Daniel Stenberg
f6163b375f 7.4.1 commit 2000-10-16 13:52:05 +00:00
Daniel Stenberg
b2d73c50d3 pre5 and pre6 fixes 2000-10-12 09:14:57 +00:00
Daniel Stenberg
834b7de33c Added lib/libcurl.def for win32 DLL creations 2000-10-12 09:13:55 +00:00
Daniel Stenberg
debdd93e1b just removed some example lines in the top comment 2000-10-12 09:13:22 +00:00
Daniel Stenberg
4e8ddedc8f Jrn added glob_cleanup() 2000-10-12 09:12:24 +00:00
Daniel Stenberg
751d503f54 sprintf() => snprintf() 2000-10-12 08:22:16 +00:00
Daniel Stenberg
b2e47dfde4 updated to better reflect reality 2000-10-11 10:59:36 +00:00
Daniel Stenberg
0af8201cc2 make curl capable of using the mozilla SSL engine 2000-10-11 10:59:16 +00:00
Daniel Stenberg
7717212912 free the URL string if that was allocated 2000-10-11 10:58:37 +00:00
Daniel Stenberg
ccb2b5d22c free the FTP struct already in the _done() function 2000-10-11 10:57:52 +00:00
Daniel Stenberg
85174ed358 memory leak adjusts 2000-10-11 10:29:25 +00:00
Daniel Stenberg
111d1d09d3 removed the header that confuses PHP 2000-10-09 22:29:35 +00:00
Daniel Stenberg
4f5a4c9bd5 added the bool typedef, moved here from curl/curl.h 2000-10-09 21:36:38 +00:00
Daniel Stenberg
8c62e337b0 bool typedef fix 2000-10-09 21:35:40 +00:00
Daniel Stenberg
51bcdb472b use this to analyze the memory debug logs MALLOCDEBUG will generate 2000-10-09 11:31:55 +00:00
Daniel Stenberg
5ee185f420 just too many to mention 2000-10-09 11:25:40 +00:00
Daniel Stenberg
fb739ac130 Added commented MALLOCDEBUG stuff for memory debugging 2000-10-09 11:24:49 +00:00
Daniel Stenberg
cdd91bed46 I commented the -DMALLOCDEBUG flag to make it easier to add 2000-10-09 11:24:18 +00:00
Daniel Stenberg
9defb83930 added memory debugging support 2000-10-09 11:13:17 +00:00
Daniel Stenberg
0f8facb49b added memory debugging include file 2000-10-09 11:12:34 +00:00
Daniel Stenberg
d49d05bce6 added for memory leak debugging etc 2000-10-09 11:11:43 +00:00
Daniel Stenberg
1e2e6a4e33 GetHost() did not properly assign the third argument pointer! 2000-10-08 12:50:51 +00:00
Daniel Stenberg
5b39a48e22 corrected the --longoption parser 2000-10-06 12:45:05 +00:00
Daniel Stenberg
2918836cef removed include "writeout.h" 2000-10-06 11:06:20 +00:00
Daniel Stenberg
b900318d8d Jrg's updated makefile 2000-10-06 11:03:43 +00:00
Daniel Stenberg
c58dc8f82f the --interface code doesn't work on win32 and is #ifndef WIN32 now 2000-10-06 11:03:20 +00:00
Daniel Stenberg
0ddacf929a added for the win32 version 2000-10-06 11:02:48 +00:00
Daniel Stenberg
a513e97464 moved the src/config.h stuff to the bottom, as automake were adding include
stuff to ../src in the lib directory's Makefile.in otherwise!
2000-10-06 10:40:43 +00:00
Daniel Stenberg
03a56b3e56 HTTP resume fix, now the range pointer may be allocated 2000-10-06 06:28:39 +00:00
Daniel Stenberg
18f67852be filled in more information on the options 2000-10-04 13:09:15 +00:00
Daniel Stenberg
693aab0e95 size_request and size_header added to the -w description 2000-10-04 13:08:54 +00:00
Daniel Stenberg
ccd0f07c41 -w supports size_header and size_request 2000-10-04 13:08:17 +00:00
Daniel Stenberg
5865860ad6 counts header and request size 2000-10-04 13:07:43 +00:00
Daniel Stenberg
bf56377865 Added Jason S. Priebe as contributor 2000-10-03 22:07:09 +00:00
Daniel Stenberg
e012d32e66 documented writeinfo as removed in 7.4 2000-10-03 22:06:26 +00:00
Daniel Stenberg
763797ab3c introduced in libcurl 7.4 2000-10-03 22:05:27 +00:00
Daniel Stenberg
2cdd150723 removed writeinfo stuff 2000-10-03 22:04:04 +00:00
Daniel Stenberg
d46b006f22 add_buffer_send() free()d the buffer *before* it was used! :-O 2000-10-03 16:53:41 +00:00
Daniel Stenberg
033263e696 added the new upload_bufsize to the connectdata struct 2000-10-03 11:05:09 +00:00
Daniel Stenberg
eee5c71aff inits the upload_bufsize at connect time 2000-10-03 11:03:55 +00:00
Daniel Stenberg
f1b8566ea2 new upload-buffer size design that starts with a smallish buffer and increases
its size in case of need
2000-10-03 11:02:52 +00:00
Daniel Stenberg
d3f9b2a490 introduced the new add_buffer() concept that makes the HTTP request to get
sent in only one shot
2000-10-03 11:01:32 +00:00
Daniel Stenberg
398d21696f Added curl_easy_getinfo.3 2000-10-02 06:49:51 +00:00
Daniel Stenberg
99fbcac6b9 added a small suggestion on how to get the curl man page in text format
without nroff
2000-10-02 06:40:14 +00:00
Daniel Stenberg
c23e387928 Uses the new "client-side" writeout function 2000-10-02 06:36:34 +00:00
Daniel Stenberg
ef77d484f0 removed writeout.[ch] and added getinfo.c 2000-10-02 06:32:31 +00:00
Daniel Stenberg
df7b9e7af6 Added writeout.c 2000-10-02 06:32:05 +00:00
Daniel Stenberg
f612f194be writeout.[ch] added in src/ 2000-10-02 06:31:10 +00:00
Daniel Stenberg
dfec172157 moved out from the library and put here, uses the new curl_easy_getinfo() 2000-10-02 06:30:40 +00:00
Daniel Stenberg
888182c16d adjusted for curl_easy_getinfo 2000-10-02 06:29:39 +00:00
Daniel Stenberg
d5ad450db6 getinfo.c replaces the former writeout.c 2000-10-02 06:28:55 +00:00
Daniel Stenberg
b0274a553b Added curl_easy_getinfo() 2000-10-02 06:27:43 +00:00
Daniel Stenberg
e372a440c0 #include <malloc.h> was removed, it causes warnings on openbsd 2000-09-29 06:34:50 +00:00
Daniel Stenberg
91bda5650c include base64.h instead of base64_krb.h 2000-09-28 10:36:31 +00:00
Daniel Stenberg
13962adcb5 7.3 commit 2000-09-28 10:26:44 +00:00
Daniel Stenberg
221f1c2ca2 replaced the old base64 stuff with the new ones 2000-09-28 08:01:52 +00:00
Daniel Stenberg
0e0b72714c more configure options explained 2000-09-26 22:32:46 +00:00
Daniel Stenberg
3396d97399 a --krb4 usage example added 2000-09-26 22:31:52 +00:00
Daniel Stenberg
c4fc231934 added krb4-info 2000-09-26 22:30:23 +00:00
Daniel Stenberg
bac96e9f49 Added strlcpy() since it turns out some krb4-implementations don't include
their own, even if mine did!
2000-09-26 22:28:46 +00:00
Daniel Stenberg
00505c9247 moved the RAND_status() and RAND_screen() checks to the openssl section
added strlcpy() check in the krb4 section
2000-09-26 22:27:24 +00:00
Daniel Stenberg
60ee571bd6 CRYPTO_free() of course, it makes it run with previous openssl versions too 2000-09-26 07:03:59 +00:00
Daniel Stenberg
bdfe654aee The last week's changes 2000-09-25 22:23:17 +00:00
Daniel Stenberg
32e013eb87 -c and -t is no longer prefered 2000-09-25 22:20:02 +00:00
Daniel Stenberg
d03db1cd11 corrected curl_write() for kerberos 2000-09-25 22:16:36 +00:00
Daniel Stenberg
1dac7f4d05 Martin Hedenfalk added sec_fflush_fd() 2000-09-25 22:15:56 +00:00
Daniel Stenberg
ad01481b28 krb4 transfers get a sec_fflush_fd() to get uploads to work 2000-09-25 22:15:28 +00:00
Daniel Stenberg
28ad7dc4a1 a single cookie does not require a trailing semicolon anymore 2000-09-25 22:14:42 +00:00
Daniel Stenberg
e40f0be7e3 No longer uses Free() as that was removed from OpenSSL with 0.9.6 2000-09-25 22:04:51 +00:00
Daniel Stenberg
f353258ff6 corrected bad data re-use and buffer problems 2000-09-25 21:49:37 +00:00
Daniel Stenberg
1754d6166c Added CURLOPT_KRB4LEVEL 2000-09-21 08:54:36 +00:00
Daniel Stenberg
481871768b updated 2000-09-21 08:53:59 +00:00
Daniel Stenberg
43d75c5f3b added docs/examples
now only includes specified files in src/ as I tend to store debug-source files
in there as well!
2000-09-21 08:53:20 +00:00
Daniel Stenberg
35e901a21e Added krb4 support for libcurl 7.3 2000-09-21 08:52:08 +00:00
Daniel Stenberg
c62cc76fdb now reports "krb4 enabled" is that's so 2000-09-21 08:51:15 +00:00
Daniel Stenberg
7bac857fdd krb4 fields structs and fields added 2000-09-21 08:50:48 +00:00
Daniel Stenberg
ce406a732f krb4 support
new GetHost() usage
new base64 encoder usage
2000-09-21 08:50:05 +00:00
Daniel Stenberg
a82eb0fc6d adjusted to support krb4 2000-09-21 08:49:16 +00:00
Daniel Stenberg
6f6dfa97a8 Uses the new interface to ssend() and the base64 encoder 2000-09-21 08:48:48 +00:00
Daniel Stenberg
aa8a2fbde3 GetHost() changed function arguments 2000-09-21 08:47:48 +00:00
Daniel Stenberg
3471e2c59d krb4 support added, new GetHost() usage 2000-09-21 08:47:20 +00:00
Daniel Stenberg
37249c3a41 new interface to the base64 encoder 2000-09-21 08:46:44 +00:00
Daniel Stenberg
def69c3087 new for kerberos support 2000-09-21 08:46:14 +00:00
Daniel Stenberg
35aa363587 new libcurl example code stuff 2000-09-20 22:32:08 +00:00
Daniel Stenberg
7eafb0f325 Stephen Kick's --interface was added 2000-09-18 21:54:46 +00:00
Daniel Stenberg
c9c7fcf411 Stephen Kick's interface fixes 2000-09-18 21:54:08 +00:00
Daniel Stenberg
4dba5750d4 Stephen Kick added CURLOPT_INTERFACE 2000-09-18 21:53:21 +00:00
Daniel Stenberg
398e3f423f GetHost() now should return NULL when it fails, even for Tru64 unix 2000-09-18 21:16:27 +00:00
Daniel Stenberg
281d4cedc7 Added --disable-shared info and updated the 'make install' section. 2000-09-18 14:14:33 +00:00
Daniel Stenberg
c23f35ce2a ftp through http proxy tunnel is now implemented 2000-09-18 06:25:50 +00:00
Daniel Stenberg
0f4444e90b Added PowerPC and sparc linux 2000-09-15 14:16:50 +00:00
Daniel Stenberg
a98648bd8c Updated to be accurate with the new proxytunnel option 2000-09-15 14:16:13 +00:00
Daniel Stenberg
4ee420f23e proxy tunnel update 2000-09-15 14:15:47 +00:00
Daniel Stenberg
31dc1f4247 spell corrections, changed some wording 2000-09-15 14:15:16 +00:00
Daniel Stenberg
ec109b3540 Added curl.linuxworx.com.au as an "official" mirror 2000-09-15 13:22:27 +00:00
Daniel Stenberg
5019fe75a7 proxytunnel added 2000-09-15 13:20:34 +00:00
Daniel Stenberg
00eaf20298 bugfixed the proxytunnel 2000-09-15 12:55:38 +00:00
Daniel Stenberg
96009453e8 -p/--proxytunnel was added 2000-09-15 06:11:46 +00:00
Daniel Stenberg
0da7057591 more "anything through http proxy tunnel" fixes 2000-09-15 06:10:52 +00:00
Daniel Stenberg
23f22bd53e Added HTTPPROXYTUNNEL 2000-09-14 14:14:03 +00:00
Daniel Stenberg
86ff2c46b7 introduced 'tunnel through http proxy' for ftp 2000-09-14 14:05:01 +00:00
Daniel Stenberg
be8b2a1e30 updated the show-off list 2000-09-14 11:25:54 +00:00
Daniel Stenberg
0a2f677374 file:// fix that prevents name lookup and sets no-upload and no-download 2000-09-14 10:41:07 +00:00
Daniel Stenberg
74be53a577 C++ adjusted 2000-09-07 11:34:08 +00:00
Daniel Stenberg
5e7cd528b0 made -I (size info only) work for ftp again 2000-08-31 12:04:55 +00:00
Daniel Stenberg
60eab89f10 in unescape(), '+' is now only converted to space after the first '?' 2000-08-31 12:03:04 +00:00
Daniel Stenberg
1cedcce3e9 patched 7.2 configure to work! 2000-08-31 06:10:02 +00:00
66 changed files with 4328 additions and 902 deletions

271
CHANGES
View File

@@ -6,6 +6,275 @@
History of Changes
Version 7.4.1
Daniel (16 October 2000)
- I forgot to remove some of the malloc debug defines from the makefiles in
the release archive (of course).
Version 7.4
Daniel (16 October 2000)
- The buffer overflow mentioned below was posted to bugtraq on Friday 13th.
Daniel (12 October 2000)
- Colin Robert Phipps elegantly corrected a buffer overflow. It could be used
by an evil ftp server to crash curl. I took the opportunity of replacing a
few other sprintf()s into snprintf()s as well.
Daniel (11 October 2000)
- Found some more memory leaks. This new simple memory debugger has turned out
really useful!
Version 7.4 pre6
Daniel (9 October 2000)
- Florian Koenig pointed out that the bool typedef in the curl/curl.h include
file was breaking PHP 4.0.3 compiling. The bool typedef is not used in the
public interface and was wrongly inserted in that header file.
- J<>rg Hartroth corrected a minor memory leak in the src/urlglob.c stuff. It
didn't harm anyone since the memory is free()ed on exit anyway.
- Corrected the src/main.c. We use the _MPRINTF_REPLACE #define to use our
libcurl-printf() functions. This gives us snprintf() et al on all
platforms. I converted the allocated useragent string to one that uses a
local buffer.
- I've set an #if 0 section around the Content-Transfer-Encoding header
generated in lib/formdata.c. This will hopefully make curl do more
PHP-friendly multi-part posts.
Version 7.4 pre5
Daniel (9 October 2000)
- Nico Baggus found out that curl's ability to force a ASCII download when
using FTP was no longer working! I corrected this. This problem was probably
introduced when I redesigned libcurl for version 7.
- Georg Horn provided a source example that proved a memory leak in libcurl.
I added simple memory debugging facilities and now we can make libcurl log
all memory fiddling functions. An additional perl script is used to analyze
the output logfile and to match malloc()s with free()s etc. The memory leak
Georg found turned out to be the main cookie struct that cookie_cleanup()
didn't free! The perl script is named memanalyze.pl and it is available in
the CVS respository, not in the release archive.
Daniel (8 October 2000)
- Georg Horn found a GetHost() problem. It turned out it never assigned the
pointer in the third argument properly! This could make a crash, or at best
a memory leak!
Version 7.4 pre4
Daniel (6 October 2000)
- Is the -F post following the RFC 1867 spec? We had this dicussion on the
mailing list since it appears curl can't post -F form posts to a PHP
receiver... I've been in touch with the PHP developers about this.
- Domenico Andreoli found out that the long option '--proxy' wasn't working
anymore! The option parser got confused when I added the --proxytunnel for
7.3. This was indeed a very old flaw that hasn't turned up until now...
- J<>rn Hartroth provided patches, updated makefiles and two new files for DLL
stuff on win32. He also pointed out that lib source files were compiled with
-I../src which isn't only wrong but plain stupid!
- Troels Walsted Hansen fixed a problem with HTTP resume. Curl previously used
a local variable badly, that could lead to crashes.
Version 7.4 pre3
Daniel (4 October 2000)
- More docs written. The curl_easy_getinfo.3 man page is now pretty accurate,
as is the -w section in curl.1. I added two options to enable the user to
get information about the received headers' size and the size of the HTTP
request. T. Bharath requested them.
Daniel (3 October 2000)
- Corrected a sever free() before use in the new add_buffer_send()! ;-)
Version 7.4 pre2
Daniel (3 October 2000)
- Jason S. Priebe sent me patches that changed the way curl issues HTTP
requests. The entire request is now issued in one single shot. It didn't do
this previously, and it has turned out that since the common browsers do it
this way, some sites have turned out to work with browsers but not with
curl! Although this is not a client-side problem, we want to be able to
fully emulate browsers, and thus we have now adjusted the networking layer
to slightly more appear as a browser. I adjusted Jason's patch, the faults
are probably mine.
Daniel (2 October 2000)
- Anyone who ever uploaded data with curl on a slow link has noticed that the
progess meter is updated very infrequently. That is due to the large buffer
size curl is using. It reads 50Kb and sends it, updates the progress meter
and loops. 50Kb is very much on a slow link, although it is pretty neat to
use on a fast one.
I've now made an adjustment that makes curl use a 2Kb buffer for uploads to
start with. If curl's average upload speed is faster than buffer size bytes
per second, curl will increase the used buffer size up to max 50Kb. It
should make the progress meter work better.
Version 7.4 pre1
Daniel (29 September 2000)
- Ripped out the -w stuff from the library and put in the curl tool. It gets
all the relevant info from the library using the new curl_easy_getinfo()
function.
- brad at openbsd.org mailed me a patch that corrected my kerberos mistake and
removed a compiler warning from hostip.c that OpenBSD people get.
Daniel (28 September 2000)
- Of course (I should probably get punished somehow) I didn't properly correct
the #include lines for the base64 stuff in the kerberos sources in the just
released 7.3 package. They still include the *_krb.h files! Now, the error
is sooo very easy to spot and fix so I won't bother with a quick bug fix
release. I'll post a patch whenever one is needed instead. It'll be
available in the CVS in a few minutes anyway.
Version 7.3
Daniel (28 September 2000)
- Removed the base64_krb.[ch] files. They've now replaced the former
base64.[ch] files.
Daniel (26 September 2000)
- Updated some docs.
- I changed the OpenSSL fix to work with older versions as well. The posted
patch was only working with 0.9.6 and no older ones.
Version 7.3-pre8
Daniel (25 September 2000)
- Erdmut Pfeifer informed us that curl didn't build with OpenSSL 0.9.6 and
showed us what needed to get patched in order to make it build properly
again.
- Dirk Kruschewski found a bug in the cookie parser. I made an alternative
approach to the solution Dirk himself suggested. The bug made a cookie
header that didn't end with a trailing semicolon to not get parsed.
- I've marked -c and -t deprecated now. If you use any of them, curl will tell
you to use "-C -" or "-T -" instead. I don't think occupying two letters for
nearly identical functions is good use. Also, -T - kind of follows the curl
tradition of using - for stdin where a file name is expected.
Daniel (23 September 2000)
- Martin Hedenfalk provided the patch that finally made the krb4 ftp upload
work!
Daniel (21 September 2000)
- The kerberos code is not quite thread-safe yet. There are a few more globals
that need to be take care of. Let's get the upload working first!
Daniel (20 September 2000)
- Richard Prescott solved another name lookup buffer size problem. I took this
opportunity to rewrite the GetHost() function. With these large buffer
sizes, I think keeping them as local arrays quickly turn ugly. I now use
malloc() to get the buffer memory. Thanks to this, I now can realloc() to a
large buffer in case of demand (errno == ERANGE) in case a solution like
that would become necessary. I still want to avoid that kind of nastiness.
- Tried to compile and run curl on Linux for alpha and FreeBSD for alpha. Went
as smooth as it could.
- Added a docs/examples directory with two tiny example sources that show how
to use libcurl. I hope users will supply me with more useful examples
further on.
- Applied a patch by J<>rn Hartroth to no longer use the word 'inteface' in the
config struct in the src/main.c file since certain compilers have that word
"reservered". I figure that is some kind of C++ decease.
- Updated the curl.1 man page with --interface and --krb4.
- Modified the base64Encode() function to work like the kerberos one, so that
I could remove the use of that. There is no need for *two* base64 encoding
functions! ;-)
Version 7.3pre5
Daniel (19 September 2000)
- The kerberos4-layer source code that is much "influenced" by the original
krb4 source code, through yafc into curl, was using quite a lot of global
variables. libcurl can't work properly with globals like that why I had to
clean up almost every function in the new security.c to make them use
connection specific variables instead of the globals. I just hope I didn't
destroy anything now... :-) configure updated, version string now reflects
krb4 built-in. It almost works now. Only uploads are still being naughty.
Version 7.3pre3
Daniel (18 September 2000)
- Martin Hedenfalk supplied a major patch that introduces krb4-ftp support to
curl. Martin is the primary author of the ftp client named yafc and he did
not hesitate to help us implement this when I asked him. Many and sincere
thanks to a splendid effort. It didn't even take many hours!
- Stephen Kick supplied a big patch that introduces the --interface flag to
the curl tool and CURLOPT_INTERFACE for libcurl. It allows you to specify an
outgoing interface to use for your request. This may not work on all
platforms. This needs testing.
- Richard Prescott noticed that curl on Tru64 unix could core dumped if the
name didn't resolve properly. This was due to the GetHost() function not
returning an error even though it failed on some platforms!
Daniel (15 September 2000)
- Updated all sorts of documents in regards to the new proxytunnel support.
Version 7.3pre2
Daniel (15 September 2000)
- Kai-Uwe Rommel pointed out a problem in the httpproxytunnel stuff for ftp.
Adjusted it. Added better info message when setting up the tunnel and the
pasv message when doing the second connect.
Version 7.3pre1
Daniel (15 September 2000)
- libcurl now allows "httpproxytunnel" to an arbitrary host and port name. The
second connection on ftp needed that.
- TheArtOfHTTPScripting was corrected all over. I both type and spell really
bad at times!
Daniel (14 September 2000)
- -p/--proxytunnel was added to 'curl'. It uses the new
CURLOPT_HTTPPROXYTUNNEL libcurl option that allows "any" protocol to tunnel
through the specified http proxy. At the moment, this should work with ftp.
Daniel (13 September 2000)
- Jochen Schaeuble found that file:// didn't work as expected. Corrected this
and mailed the patch to the mailing list.
Daniel (7 September 2000)
- I changed the #define T() in curl.h since it turned out it wasn't really
a good symbol to use (when you compiled PHP with curl as a module, that
define collided with some IMAP define or something). This was posted to the
PHP bug tracker.
- I added extern "C" stuff in two header files to better allow libcurl usage
in C++ sorces. Discussions on the libcurl list with Danny Horswell lead to
this.
Version 7.2.1
Daniel (31 August 2000)
- Albert Chin-A-Young fixed the configure script *again* and now it seems to
detect Linux name resolving properly! (heard that before?)
- Troels Walsted Hansen pointed out that downloading a file containing the
letter '+' from an ftp server didn't work. It did work from HTTP though and
the reason was my lame URL decoder.
- I happened to notice that -I didn't at all work on ftp anymore. I corrected
that.
Version 7.2
Daniel (30 August 2000)
@@ -2139,7 +2408,7 @@ Version 4 (1998-03-20)
***************************************************************************
Version 3.12
Version 3.12 (14 March 1998)
Daniel Stenberg
- End-of-header tracking still lacked support for \r\n or just \n at the
end of the last header line.

17
FILES
View File

@@ -21,6 +21,8 @@ docs/Makefile.in
docs/Makefile.am
docs/TheArtOfHttpScripting
docs/*.3
docs/examples/README
docs/examples/*.c
maketgz
Makefile.in
Makefile.am
@@ -40,9 +42,17 @@ reconf
stamp-h.in
ltconfig
ltmain.sh
src/*.[ch]
src/*in
src/*am
src/config-win32.h
src/hugehelp.c
src/main.c
src/setup.h
src/urlglob.c
src/urlglob.h
src/version.h
src/writeout.c
src/writeout.h
src/*.in
src/*.am
src/mkhelp.pl
src/Makefile.vc6
src/*m32
@@ -52,6 +62,7 @@ lib/*in
lib/*am
lib/Makefile.vc6
lib/*m32
lib/libcurl.def
include/README
include/Makefile.in
include/Makefile.am

5
README
View File

@@ -23,8 +23,9 @@ README
The official download mirror sites are:
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
Sweden -- ftp://ftp.sunet.se/pub/www/utilities/curl/
Germany -- ftp://ftp.fu-berlin.de/pub/unix/network/curl/
Australia -- http://curl.linuxworx.com.au/
To download the very latest source off the CVS server do this:

View File

@@ -33,3 +33,6 @@
/* Define if you need the _REENTRANT define for some functions */
#undef NEED_REENTRANT
/* Define if you have the Kerberos4 libraries (including -ldes) */
#undef KRB4

View File

@@ -49,6 +49,9 @@
/* 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
@@ -94,6 +97,9 @@
/* 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
@@ -124,6 +130,9 @@
/* 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
@@ -145,6 +154,9 @@
/* 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
@@ -160,6 +172,9 @@
/* 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
@@ -256,6 +271,9 @@
/* 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

View File

@@ -2,7 +2,7 @@ dnl $Id$
dnl Process this file with autoconf to produce a configure script.
AC_INIT(lib/urldata.h)
AM_CONFIG_HEADER(config.h src/config.h)
AM_INIT_AUTOMAKE(curl,"7.2")
AM_INIT_AUTOMAKE(curl,"7.4.1")
AM_PROG_LIBTOOL
dnl
@@ -72,6 +72,88 @@ AC_CHECK_FUNC(gethostname, , AC_CHECK_LIB(ucb, gethostname))
dnl dl lib?
AC_CHECK_FUNC(dlopen, , AC_CHECK_LIB(dl, dlopen))
dnl **********************************************************************
dnl Check for the presence of Kerberos4 libraries and headers
dnl **********************************************************************
AC_ARG_WITH(krb4-includes,
[ --with-krb4-includes[=DIR] Specify location of kerberos4 headers],[
CPPFLAGS="$CPPFLAGS -I$withval"
KRB4INC="$withval"
want_krb4=yes
])
AC_ARG_WITH(krb4-libs,
[ --with-krb4-libs[=DIR] Specify location of kerberos4 libs],[
LDFLAGS="$LDFLAGS -L$withval"
KRB4LIB="$withval"
want_krb4=yes
])
OPT_KRB4=off
AC_ARG_WITH(krb4,dnl
[ --with-krb4[=DIR] where to look for Kerberos4],[
OPT_KRB4="$withval"
if test X"$OPT_KRB4" != Xyes
then
LDFLAGS="$LDFLAGS -L$OPT_KRB4/lib"
KRB4LIB="$OPT_KRB4/lib"
CPPFLAGS="$CPPFLAGS -I$OPT_KRB4/include"
KRB4INC="$OPT_KRB4/include"
fi
want_krb4="yes"
])
AC_MSG_CHECKING([if Kerberos4 support is requested])
if test "$want_krb4" = yes
then
AC_MSG_RESULT(yes)
dnl Check for & handle argument to --with-krb4
AC_MSG_CHECKING(where to look for Kerberos4)
if test X"$OPT_KRB4" = Xyes
then
AC_MSG_RESULT([defaults])
else
AC_MSG_RESULT([libs in $KRB4LIB, headers in $KRB4INC])
fi
dnl Check for DES library
AC_CHECK_LIB(des, des_pcbc_encrypt,
[
AC_CHECK_HEADERS(des.h)
dnl resolv lib?
AC_CHECK_FUNC(res_search, , AC_CHECK_LIB(resolv, res_search))
dnl Check for the Kerberos4 library
AC_CHECK_LIB(krb, krb_net_read,
[
dnl Check for header files
AC_CHECK_HEADERS(krb.h)
dnl we found the required libraries, add to LIBS
LIBS="-lkrb -ldes $LIBS"
dnl Check for function krb_get_our_ip_for_realm
dnl this is needed for NAT networks
AC_CHECK_FUNCS(krb_get_our_ip_for_realm)
dnl add define KRB4
AC_DEFINE(KRB4)
dnl the krb4 stuff needs a strlcpy()
AC_CHECK_FUNCS(strlcpy)
])
])
else
AC_MSG_RESULT(no)
fi
dnl **********************************************************************
dnl Check for the presence of SSL libraries and headers
dnl **********************************************************************
@@ -118,6 +200,12 @@ else
fi
fi
dnl these can only exist if openssl exists
AC_CHECK_FUNCS( RAND_status \
RAND_screen )
fi
dnl **********************************************************************
@@ -298,13 +386,12 @@ char * address;
int length;
int type;
struct hostent h;
char buffer[10];
int buflen;
char buffer[8192];
int h_errnop;
struct hostent * hp;
hp = gethostbyaddr_r(address, length, type, &h,
buffer, buflen, &h_errnop);],[
buffer, 8192, &h_errnop);],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETHOSTBYADDR_R_7)
ac_cv_gethostbyaddr_args=7],[
@@ -317,14 +404,13 @@ char * address;
int length;
int type;
struct hostent h;
char buffer[10];
int buflen;
char buffer[8192];
int h_errnop;
struct hostent * hp;
int rc;
rc = gethostbyaddr_r(address, length, type, &h,
buffer, buflen, &hp, &h_errnop);],[
buffer, 8192, &hp, &h_errnop);],[
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_GETHOSTBYADDR_R_8)
ac_cv_gethostbyaddr_args=8],[
@@ -441,9 +527,7 @@ AC_CHECK_FUNCS( socket \
perror \
getpass \
closesocket \
setvbuf \
RAND_status \
RAND_screen
setvbuf
)
if test "$ac_cv_func_select" != "yes"; then

View File

@@ -141,6 +141,7 @@ FAQ
Solaris (native cc compiler)
HPUX (native cc compiler)
SGI IRIX (native cc compiler)
SCO UNIX (native cc compiler)
When configuring curl, I specify --with-ssl. OpenSSL is installed in
/usr/local/ssl Configure reports SSL in /usr/local/ssl, but fails to find

View File

@@ -30,7 +30,7 @@ HTTP
- follow redirects
- custom HTTP request
- cookie get/send
- understands the netscape cookie file
- understands the netscape cookie file format
- custom headers (that can replace/remove internally generated headers)
- custom user-agent string
- custom referer string
@@ -38,6 +38,7 @@ HTTP
- proxy authentication
- time conditions
- via http-proxy
- specify interface device/port
HTTPS (*1)
- (all the HTTP features)
@@ -47,6 +48,7 @@ HTTPS (*1)
FTP
- download
- authentication
- kerberos security
- PORT or PASV
- single file size information (compare to HTTP HEAD)
- 'type=' URL support
@@ -60,6 +62,7 @@ FTP
- custom ftp commands (before and/or after the transfer)
- simple "range" support
- via http-proxy
- all operations can be tunneled through a http-proxy
TELNET
- connection negotiation

View File

@@ -21,25 +21,31 @@ PORTS
- Ultrix
- SINIX-Z v5
Alpha DEC OSF 4
Alpha Digital UNIX V3.2D-1 (rev 41)
HP-PA HP-UX 10.X 11.X
MIPS IRIX 6.2, 6.5
Power AIX 4.2, 4.3.1, 4.3.2
PowerPC Darwin 1.0
PowerPC Mac OS X
Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7
Sparc SunOS 4.1.*
i386 BeOS
i386 FreeBSD
i386 Linux 1.3, 2.0, 2.2
i386 NetBSD
i386 OS/2
i386 OpenBSD
i386 Solaris 2.7
i386 Windows 95, 98, NT
m68k AmigaOS 3
m68k OpenBSD
- Alpha DEC OSF 4
- Alpha Digital UNIX v3.2
- Alpha FreeBSD 4.1
- Alpha Linux 2.2.16
- Alpha Tru64 v5.0 5.1
- HP-PA HP-UX 9.X 10.X 11.X
- MIPS IRIX 6.2, 6.5
- Power AIX 4.2, 4.3.1, 4.3.2
- PowerPC Darwin 1.0
- PowerPC Linux
- PowerPC Mac OS X
- Sparc Linux
- Sparc Solaris 2.4, 2.5, 2.5.1, 2.6, 7, 8
- Sparc SunOS 4.1.*
- i386 BeOS
- i386 FreeBSD
- i386 Linux 1.3, 2.0, 2.2, 2.3, 2.4
- i386 NetBSD
- i386 OS/2
- i386 OpenBSD
- i386 Solaris 2.7
- i386 Windows 95, 98, NT, 2000
- ia64 Linux 2.3.99
- m68k AmigaOS 3
- m68k OpenBSD
UNIX
====
@@ -95,9 +101,9 @@ UNIX
Use the executable `curl` in src/ directory.
'make install' copies the curl file to /usr/local/bin/ (or $prefix/bin
if you used the --prefix option to configure) and copies the curl.1
man page to a suitable place too.
'make install' copies the curl file to /usr/local/bin/ (or $prefix/bin if
you used the --prefix option to configure) and copies the man pages, the
lib and the include files to a suitable place too.
KNOWN PROBLEMS
@@ -119,6 +125,27 @@ UNIX
or
env Cc=cc ./configure
To force a static library compile, disable the shared library creation
by running configure like:
./configure --disable-shared
To tell the configure script to skip searching for thread-safe functions,
add an option like:
./configure --disable-thread
To build curl with kerberos4 support enabled, curl requires the krb4 libs
and headers installed. You can then use a set of options to tell
configure where those are:
--with-krb4-includes[=DIR] Specify location of kerberos4 headers
--with-krb4-libs[=DIR] Specify location of kerberos4 libs
--with-krb4[=DIR] where to look for Kerberos4
In most cases, /usr/athena is the install prefix and then it works with
./configure --with-krb4=/usr/athena
Win32
=====
@@ -245,7 +272,7 @@ MingW32/Cygwin
You'll find MingW32 and Cygwin information at:
http://www.xraylith.wisc.edu/~khan/software/gnu-win32/index.html
http://www.mingw.org
OpenLDAP
========

View File

@@ -34,8 +34,7 @@ Windows vs Unix
(3) is simply avoided by not trying any funny tricks on file descriptors.
(4) is left alone, giving windows users problems when they pipe binary data
through stdout...
(4) we set stdout to binary under windows
Inside the source code, I do make an effort to avoid '#ifdef WIN32'. All
conditionals that deal with features *should* instead be in the format
@@ -84,10 +83,6 @@ Library
called). The speedcheck functions in lib/speedcheck.c are also used to verify
that the transfer is as fast as required.
When the operation is done, the writeout() function in lib/writeout.c may be
called to report about the operation as specified previously in the arguments
to curl_easy_setopt().
When completed curl_easy_cleanup() should be called to free up used
resources.
@@ -158,3 +153,9 @@ Client
control after the curl_easy_perform() it cleans up the library, checks status
and exits.
When the operation is done, the ourWriteOut() function in src/writeout.c may
be called to report about the operation. That function is using the
curl_easy_getinfo() function to extract useful information from the curl
session.

View File

@@ -7,6 +7,7 @@ AUTOMAKE_OPTIONS = foreign no-dependencies
man_MANS = \
curl.1 \
curl_easy_cleanup.3 \
curl_easy_getinfo.3 \
curl_easy_init.3 \
curl_easy_perform.3 \
curl_easy_setopt.3 \

View File

@@ -139,9 +139,11 @@ UPLOADING
curl -T localfile -a ftp://ftp.upload.com/remotefile
NOTE: Curl does not support ftp upload through a proxy! The reason for this
is simply that proxies are seldomly configured to allow this and that no
author has supplied code that makes it possible!
Curl also supports ftp upload through a proxy, but only if the proxy is
configured to allow that kind of tunneling. If it does, you can run curl in
a fashion similar to:
curl --proxytunnel -x proxy:port -T localfile ftp.upload.com
HTTP
@@ -480,13 +482,14 @@ FTP and firewalls
connect to the client on the given (as parameters to the PORT command) IP
number and port.
The -P flag to curl allows for different options. Your machine may have
The -P flag to curl supports a few different options. Your machine may have
several IP-addresses and/or network interfaces and curl allows you to select
which of them to use. Default address can also be used:
curl -P - ftp.download.com
Download with PORT but use the IP address of our 'le0' interface:
Download with PORT but use the IP address of our 'le0' interface (this does
not work on windows):
curl -P le0 ftp.download.com
@@ -494,6 +497,16 @@ FTP and firewalls
curl -P 192.168.0.10 ftp.download.com
NETWORK INTERFACE
Get a web page from a server using a specified port for the interface:
curl --interface eth0:1 http://www.netscape.com/
or
curl --interface 192.168.1.10 http://www.netscape.com/
HTTPS
Secure HTTP requires SSL libraries to be installed and used when curl is
@@ -689,13 +702,26 @@ CUSTOM OUTPUT
curl -w 'We downloaded %{size_download} bytes\n' www.download.com
KERBEROS4 FTP TRANSFER
Curl supports kerberos4 for FTP transfers. You need the kerberos package
installed and used at curl build time for it to be used.
First, get the krb-ticket the normal way, like with the kauth tool. Then use
curl in way similar to:
curl --krb4 private ftp://krb4site.com -u username:fakepwd
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.
MAILING LIST
We have an open mailing list to discuss curl, its development and things
relevant to this.
To subscribe, mail curl-request@contactor.se with "subscribe <your email
address>" in the body.
To subscribe, mail curl-request@contactor.se with "subscribe <fill in your
email address>" in the body.
To post to the list, mail curl@contactor.se.

View File

@@ -17,3 +17,8 @@ README.win32
freely available nroff binary for win32 (*pointers appriciated*), convert
the files into plain-text on your neighbor's unix machine or run over to the
curl web site and view them as plain HTML.
The main curl.1 man page is "built-in". Use a command line similar to this
in order to extract a separate text file:
curl -M >manual.txt

View File

@@ -13,6 +13,14 @@ For the future
product! (Yes, you may add things not mentioned here, these are just a
few teasers...)
* Improve the command line option parser to accept '-m300' as well as the '-m
300' convention. It should be able to work if '-m300' is considered to be
space separated to the next option.
* Make the SSL layer option capable of using the Mozilla Security Services as
an alternative to OpenSSL:
http://www.mozilla.org/projects/security/pki/nss/
* Make sure the low-level interface works. highlevel.c should basically be
possible to write using that interface. Document the low-level interface
@@ -22,9 +30,11 @@ For the future
* Move non-URL related functions that are used by both the lib and the curl
application to a separate "portability lib".
* Add support for other languages than C (not important)
* Add support for other languages than C. C++ and perl comes to mind. Python?
* Improve the -K config file parser.
* Improve the -K config file parser (the parameter following the flag should
be possible to get specified *exactly* as it is done on a shell command
line).
* rtsp:// support -- "Real Time Streaming Protocol" (RFC 2326)
@@ -35,28 +45,13 @@ For the future
started in October 1999 but halted again since it proved more work than we
thought. It is still a good idea to implement though.
* HTTP Pipelining/persistant connections
- We should introduce HTTP "pipelining". Curl could be able to request for
several HTTP documents in one connect. It would be the beginning for
supporing more advanced functions in the future, like web site
mirroring. This will require that the urlget() function supports several
documents from a single HTTP server, which it doesn't today.
- When curl supports fetching several documents from the same server using
pipelining, I'd like to offer that function to the command line. Anyone has
a good idea how? The current way of specifying one URL with the output sent
to the stdout or a file gets in the way. Imagine a syntax that supports
"additional documents from the same server" in a way similar to:
curl <main URL> --more-doc <path> --more-doc <path>
where --more-doc specifies another document on the same server. Where are
the output files gonna be put and how should they be named? Should each
"--more-doc" parameter require a local file name to store the result in?
Like "--more-file" as in:
curl <URL> --more-doc <path> --more-file <file>
* Authentication: NTLM. It would be cool to support that MS crap called NTLM
authentication. MS proxies and servers sometime require that. Since that
protocol is a proprietary one, it involves reverse engineering and network
sniffing. This should however be a library-based functionality. There are a
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
work.
* RFC2617 compliance, "Digest Access Authentication"
A valid test page seem to exist at:
@@ -70,12 +65,6 @@ For the future
sends the password in cleartext over the network, this "Digest" method uses
a challange-response protocol which increases security quite a lot.
* Different FTP Upload Through Web Proxy
I don't know any web proxies that allow CONNECT through on port 21, but
that would be the best way to do ftp upload. All we would need to do would
be to 'CONNECT <host>:<port> HTTP/1.0\r\n\r\n' and then do business as
usual. I least I think so. It would be fun if someone tried this...
* Multiple Proxies?
Is there anyone that actually uses serial-proxies? I mean, send CONNECT to
the first proxy to connect to the second proxy to which you send CONNECT to
@@ -86,8 +75,7 @@ For the future
Ftp-kind proxy, Socks5, whatever kind of proxies are there?
* IPv6 Awareness and support
Where ever it would fit. I am not that into v6 yet to fully grasp what we
would need to do, but letting the autoconf search for v6-versions of a few
Where ever it would fit. configure search for v6-versions of a few
functions and then use them instead is of course the first thing to do...
RFC 2428 "FTP Extensions for IPv6 and NATs" will be interesting. PORT
should be replaced with EPRT for IPv6, and EPSV instead of PASV.
@@ -99,6 +87,3 @@ For the future
* Make curl capable of verifying the server's certificate when connecting
with HTTPS://.
* Kerberos-FTP

View File

@@ -1,6 +1,6 @@
Author: Daniel Stenberg <daniel@haxx.se>
Date: August 7, 2000
Version: 0.2
Date: September 15, 2000
Version: 0.3
The Art Of Scripting HTTP Requests Using Curl
=============================================
@@ -31,7 +31,7 @@ Version: 0.2
1. The HTTP Protocol
HTTP is the protocol used to fetch data from web servers. It is a very simple
protocol that is built upon TCP/IP. The protocol also allow information to
protocol that is built upon TCP/IP. The protocol also allows information to
get sent to the server from the client using a few different methods, as will
be shown here.
@@ -130,12 +130,12 @@ Version: 0.2
curl -d "birthyear=1905&press=OK" www.hotmail.com/when/junk.cgi
This kind of POST will use the Content-Type
application/x-www-form-urlencoded and is the most widly used POST kind.
application/x-www-form-urlencoded and is the most widely used POST kind.
4.3 FILE UPLOAD POST
Back in late 1995 they defined a new to post data over HTTP. It was
documented in the RFC 1867, why this method sometimes are refered to as
Back in late 1995 they defined a new way to post data over HTTP. It was
documented in the RFC 1867, why this method sometimes is refered to as
a rfc1867-posting.
This method is mainly designed to better support file uploads. A form that
@@ -165,7 +165,7 @@ Version: 0.2
<form method="POST" action="foobar.cgi">
<input type=text name="birthyear">
<input type=text name="person" value="daniel">
<input type=hidden name="person" value="daniel">
<input type=submit name="press" value="OK">
</form>
@@ -209,17 +209,18 @@ Version: 0.2
Do note that when a program is run, its parameters are possible to see when
listing the running processes of the system. Thus, other users may be able to
watch your passwords if you pass them as plain command line options.
watch your passwords if you pass them as plain command line options. There
are ways to circumvent this.
7. REFERER
A HTTP request has the ability to feature a 'referer' field, which can be
used to tell which URL that causes the client to get this particular
resource. Some programs/scripts check the referer field of requests to verify
that this wasn't arriving from an external site or unknown page. While this
is a stupid way to check something so easily forged, many scripts still do
it. Using curl, you can put anything you want in the referer-field and thus
more easily being able to fool the server into serving your request.
A HTTP request may include a 'referer' field, which can be used to tell from
which URL the client got to this particular resource. Some programs/scripts
check the referer field of requests to verify that this wasn't arriving from
an external site or an unknown page. While this is a stupid way to check
something so easily forged, many scripts still do it. Using curl, you can put
anything you want in the referer-field and thus more easily be able to fool
the server into serving your request.
Use curl to set the referer field with:
@@ -278,10 +279,10 @@ Version: 0.2
specified in a received cookie, the client sends back the cookies and their
contents to the server, unless of course they are expired.
Many applications and server use this method to connect a series of request
Many applications and servers use this method to connect a series of requests
into a single logical session. To be able to use curl in such occations, we
must be able to record and send back cookies in the way that the web
application expects them. The same way browsers deal with them.
must be able to record and send back cookies the way the web application
expects them. The same way browsers deal with them.
The simplest way to send a few cookies to the server when getting a page with
curl is to add them on the command line like:
@@ -307,15 +308,15 @@ Version: 0.2
There are a few ways to do secure HTTP transfers. The by far most common
protocol for doing this is what is generally known as HTTPS, HTTP over
SSL. SSL encrypts all the data that is send and received over the network and
SSL. SSL encrypts all the data that is sent and received over the network and
thus makes it harder for attackers to spy on sensitive information.
SSL (or TLS as the latest version of the standard is called) offers a
truckload of advanced features to allow all those encryptions and key
infrastructure mechanisms ecnrypted HTTP requires.
infrastructure mechanisms encrypted HTTP requires.
Curl supports enscrypted fetches thanks to the freely available OpenSSL
libraries. To get a pafe from a https server, simply run curl like:
Curl supports encrypted fetches thanks to the freely available OpenSSL
libraries. To get a page from a HTTPS server, simply run curl like:
curl https://that.secure.server.com

View File

@@ -2,7 +2,7 @@
.\" nroff -man curl.1
.\" Written by Daniel Stenberg
.\"
.TH curl 1 "24 August 2000" "Curl 7.2" "Curl Manual"
.TH curl 1 "26 September 2000" "Curl 7.3" "Curl Manual"
.SH NAME
curl \- get a URL with FTP, TELNET, LDAP, GOPHER, DICT, FILE, HTTP or
HTTPS syntax.
@@ -72,6 +72,7 @@ Use ASCII transfer when getting an FTP file or LDAP info. For FTP, this can
also be enforced by using an URL that ends with ";type=A". This option causes
data sent to stdout to be in text mode for win32 systems.
.IP "-c/--continue"
.B Deprecated. Use '-C -' instead.
Continue/Resume a previous file transfer. This instructs curl to
continue appending data on the file where it was previously left,
possibly because of a broken connection to the server. There must be
@@ -172,11 +173,20 @@ prevent that header from appearing.
(HTTP)
Include the HTTP-header in the output. The HTTP-header includes things
like server-name, date of the document, HTTP-version and more...
.IP "--interface <name>"
Perform an operation using a specified interface. You can enter interface
name, IP address or host name. An example could look like:
.B "curl --interface eth0:1 http://www.netscape.com/"
.IP "-I/--head"
(HTTP/FTP)
Fetch the HTTP-header only! HTTP-servers feature the command HEAD
which this uses to get nothing but the header of a document. When used
on a FTP file, curl displays the file size only.
.IP "--krb4 <level>"
(FTP) Enable kerberos4 authentication and use. The level must be entered and
should be one of 'clear', 'safe', 'confidential' or 'private'. Should you use
a level that is not one of these, 'private' will instead be used.
.IP "-K/--config <config file>"
Specify which config file to read curl arguments from. The config
file is a text file in which command line arguments can be written
@@ -241,6 +251,12 @@ or use several variables like:
.IP "-O/--remote-name"
Write output to a local file named like the remote file we get. (Only
the file part of the remote file is used, the path is cut off.)
.IP "-p/--proxytunnel"
When an HTTP proxy is used, this option will cause non-HTTP protocols to
attempt to tunnel through the proxy instead of merely using it to do HTTP-like
operations. The tunnel approach is made with the HTTP proxy CONNECT request
and requires that the proxy allows direct connect to the remote port number
curl wants to tunnel through to.
.IP "-P/--ftpport <address>"
(FTP)
Reverses the initiator/listener roles when connecting with ftp. This
@@ -317,6 +333,7 @@ Curl mute.
.IP "-S/--show-error"
When used with -s it makes curl show error message if it fails.
.IP "-t/--upload"
.B Deprecated. Use '-T -' instead.
Transfer the stdin data to the specified file. Curl will read
everything from stdin until EOF and store with the supplied name. If
this is used on a http(s) server, the PUT command will be used.
@@ -393,11 +410,17 @@ The total amount of bytes that were downloaded.
.B size_upload
The total amount of bytes that were uploaded.
.TP
.B size_header
The total amount of bytes of the downloaded headers.
.TP
.B size_request
The total amount of bytes that were sent in the HTTP request.
.TP
.B speed_download
The average download speed that curl measured for the complete download.
.TP
.B speed_upload
The average upload speed that curl measured for the complete download.
The average upload speed that curl measured for the complete upload.
.RE
.IP "-x/--proxy <proxyhost[:port]>"
Use specified proxy. If the port number is not specified, it is assumed at
@@ -616,6 +639,10 @@ If you do find any (or have other suggestions), mail Daniel Stenberg
- Fred Noz <FNoz@siac.com>
- Caolan McNamara <caolan@csn.ul.ie>
- Albert Chin-A-Young <china@thewrittenword.com>
- Stephen Kick <skick@epicrealm.com>
- Martin Hedenfalk <mhe@stacken.kth.se>
- Richard Prescott
- Jason S. Priebe <priebe@wral-tv.com>
.SH WWW
http://curl.haxx.se

81
docs/curl_easy_getinfo.3 Normal file
View File

@@ -0,0 +1,81 @@
.\" You can view this file with:
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_easy_init 3 "2 October 2000" "Curl 7.4" "libcurl Manual"
.SH NAME
curl_easy_getinfo - Extract information from a curl session (added in 7.4)
.SH SYNOPSIS
.B #include <curl/easy.h>
.sp
.BI "CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ... );"
.ad
.SH DESCRIPTION
Request internal information from the curl session with this function. The
third argument
.B MUST
be a pointer to a long, a pointer to a char * or a pointer to a double (as
this documentation describes further down). The data pointed-to will be
filled in accordingly and can be relied upon only if the function returns
CURLE_OK. This function is intended to get used *AFTER* a performed transfer,
all results from this function are undefined until the transfer is completed.
.SH AVAILABLE INFORMATION
These are informations that can be extracted:
.TP 0.8i
.B CURLINFO_EFFECTIVE_URL
Pass a pointer to a 'char *' to receive the last used effective URL.
.TP
.B CURLINFO_HTTP_CODE
Pass a pointer to a long to receive the last received HTTP code.
.TP
.B CURLINFO_TOTAL_TIME
Pass a pointer to a double to receive the total transaction time in seconds
for the previous transfer.
.TP
.B CURLINFO_NAMELOOKUP_TIME
Pass a pointer to a double to receive the time, in seconds, it took from the
start until the name resolving was completed.
.TP
.B CURLINFO_CONNECT_TIME
Pass a pointer to a double to receive the time, in seconds, it took from the
start until the connect to the remote host (or proxy) was completed.
.TP
.B CURLINFO_PRETRANSFER_TIME
Pass a pointer to a double to receive the time, in seconds, it took from the
start until the file transfer is just about to begin. This includes all
pre-transfer commands and negotiations that are specific to the particular
protocol(s) involved.
.TP
.B CURLINFO_SIZE_UPLOAD
Pass a pointer to a double to receive the total amount of bytes that were
uploaded.
.TP
.B CURLINFO_SIZE_DOWNLOAD
Pass a pointer to a double to receive the total amount of bytes that were
downloaded.
.TP
.B CURLINFO_SPEED_DOWNLOAD
Pass a pointer to a double to receive the average download speed that curl
measured for the complete download.
.TP
.B CURLINFO_SPEED_UPLOAD
Pass a pointer to a double to receive the average upload speed that curl
measured for the complete upload.
.TP
.B CURLINFO_HEADER_SIZE
Pass a pointer to a long to receive the total size of all the headers
received.
.TP
.B CURLINFO_REQUEST_SIZE
Pass a pointer to a long to receive the total size of the issued
requests. This is so far only for HTTP requests. Note that this may be more
than one request if FOLLOWLOCATION is true.
.PP
.SH RETURN VALUE
If the operation was successful, CURLE_OK is returned. Otherwise an
appropriate error code will be returned.
.SH "SEE ALSO"
.BR curl_easy_setopt "(3)"
.SH BUGS
Surely there are some, you tell me!

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_easy_init 3 "22 May 2000" "Curl 7.0" "libcurl Manual"
.TH curl_easy_init 3 "26 September 2000" "Curl 7.0" "libcurl Manual"
.SH NAME
curl_easy_init - Start a libcurl "easy" session
.SH SYNOPSIS
@@ -16,6 +16,9 @@ that you shall use as input to the other easy-functions. The init calls
intializes curl and this call MUST have a corresponding call to
.I curl_easy_cleanup
when the operation is complete.
On win32 systems, you need to init the winsock stuff manually, libcurl will
not do that for you. WSAStartup() and WSACleanup() should be used accordingly.
.SH RETURN VALUE
If this function returns NULL, something went wrong and you cannot use the
other curl functions.

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" Written by daniel@haxx.se
.\"
.TH curl_easy_setopt 3 "24 August 2000" "Curl 7.2" "libcurl Manual"
.TH curl_easy_setopt 3 "26 September 2000" "Curl 7.3" "libcurl Manual"
.SH NAME
curl_easy_setopt - Set curl easy-session options
.SH SYNOPSIS
@@ -87,6 +87,12 @@ the end of the host name. The proxy string may be prefixed with
Set this long with this option to set the proxy port to use unless it is
specified in the proxy string CURLOPT_PROXY.
.TP
.B CURLOPT_HTTPPROXYTUNNEL
Set the parameter to non-zero to get the library to tunnel all non-HTTP
operations through the given HTTP proxy. Do note that there is a big
difference to use a proxy and to tunnel through it. If you don't know what
this means, you probably don't want this tunnel option. (Added in libcurl 7.3)
.TP
.B CURLOPT_VERBOSE
Set the parameter to non-zero to get the library to display a lot of verbose
information about its operations.
@@ -194,7 +200,8 @@ post operation. See also the CURLOPT_POST.
If you want to post data to the server without letting libcurl do a strlen()
to measure the data size, this option must be used. Also, when this option is
used, you can post fully binary data which otherwise is likely to fail. If
this size is set to zero, the library will use strlen() to get the data size.
this size is set to zero, the library will use strlen() to get the data
size. (Added in libcurl 7.2)
.TP
.B CURLOPT_REFERER
Pass a pointer to a zero terminated string as parameter. It will be used to
@@ -310,7 +317,20 @@ your server supports the command first.
Pass a FILE * as parameter. This is the stream to use instead of stderr
internally when reporting errors.
.TP
.B CURLOPT_INTERFACE
Pass a char * as parameter. This set the interface name to use as outgoing
network interface. The name can be an interface name, an IP address or a host
name. (Added in libcurl 7.3)
.TP
.B CURLOPT_KRB4LEVEL
Pass a char * as parameter. Set the krb4 security level, this also enables
krb4 awareness. This is a string, 'clear', 'safe', 'confidential' or
'private'. If the string is set but doesn't match one of these, 'private'
will be used. Set the string to NULL to disable kerberos4. The kerberos
support only works for FTP. (Added in libcurl 7.3)
.TP
.B CURLOPT_WRITEINFO
(NOT PRESENT IN 7.4 or later!)
Pass a pointer to a zero terminated string as parameter. It will be used to
report information after a successful request. This string may contain
variables that will be substituted by their contents when output. Described

8
docs/examples/README Normal file
View File

@@ -0,0 +1,8 @@
EXAMPLES
This directory is for tiny libcurl programming examples. They are meant to
show some simple steps on how you can build your own application to take full
advantage of libcurl.
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.

View File

@@ -0,0 +1,63 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
written = fwrite(ptr,size,nmemb,outfile);
return written;
}
int main(int argc, char **argv)
{
CURL *curl_handle;
char *headerfilename = "head.out";
FILE *headerfile;
char *bodyfilename = "body.out";
FILE *bodyfile;
/* init the curl session */
curl_handle = curl_easy_init();
/* set URL to get */
curl_easy_setopt(curl_handle, CURLOPT_URL, "http://curl.haxx.se");
/* no progress meter please */
curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1);
/* shut up completely */
curl_easy_setopt(curl_handle, CURLOPT_MUTE, 1);
/* send all data to this function */
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
/* open the files */
headerfile = fopen(headerfilename,"w");
if (headerfile == NULL) {
curl_easy_cleanup(curl_handle);
return -1;
}
bodyfile = fopen(bodyfilename,"w");
if (bodyfile == NULL) {
curl_easy_cleanup(curl_handle);
return -1;
}
/* we want the headers to this file handle */
curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER ,headerfile);
/* get it! */
curl_easy_perform(curl_handle);
/* close the header file */
fclose(headerfile);
/* cleanup curl stuff */
curl_easy_cleanup(curl_handle);
return 0;
}

26
docs/examples/simple.c Normal file
View File

@@ -0,0 +1,26 @@
#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;
FILE *headerfile;
headerfile = fopen("dumpit", "w");
curl = curl_easy_init();
if(curl) {
/* what call to write: */
curl_easy_setopt(curl, CURLOPT_URL, "curl.haxx.se");
curl_easy_setopt(curl, CURLOPT_WRITEHEADER, headerfile);
res = curl_easy_perform(curl);
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}

View File

@@ -67,6 +67,10 @@
#include <curl/types.h>
#ifdef __cplusplus
extern "C" {
#endif
struct HttpPost {
struct HttpPost *next; /* next entry in the list */
char *name; /* pointer to allocated name */
@@ -141,6 +145,8 @@ typedef enum {
CURLE_HTTP_POST_ERROR,
CURLE_HTTP_PORT_FAILED, /* HTTP Interface operation failed */
CURLE_SSL_CONNECT_ERROR, /* something was wrong when connecting with SSL */
CURLE_FTP_BAD_DOWNLOAD_RESUME, /* couldn't resume download */
@@ -172,7 +178,10 @@ typedef enum {
/* name is uppercase CURLOPT_<name>,
type is one of the defined CURLOPTTYPE_<type>
number is unique identifier */
#define T(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
#ifdef CINIT
#undef CINIT
#endif
#define CINIT(name,type,number) CURLOPT_ ## name = CURLOPTTYPE_ ## type + number
/* long may be 32 or 64 bits, but we should never depend on anything else
but 32 */
@@ -181,74 +190,74 @@ typedef enum {
#define CURLOPTTYPE_FUNCTIONPOINT 20000
typedef enum {
T(NOTHING, LONG, 0), /********* the first one is unused ************/
CINIT(NOTHING, LONG, 0), /********* the first one is unused ************/
/* This is the FILE * the regular output should be written to. */
T(FILE, OBJECTPOINT, 1),
CINIT(FILE, OBJECTPOINT, 1),
/* The full URL to get/put */
T(URL, OBJECTPOINT, 2),
CINIT(URL, OBJECTPOINT, 2),
/* Port number to connect to, if other than default. Specify the CONF_PORT
flag in the CURLOPT_FLAGS to activate this */
T(PORT, LONG, 3),
CINIT(PORT, LONG, 3),
/* Name of proxy to use. Specify the CONF_PROXY flag in the CURLOPT_FLAGS to
activate this */
T(PROXY, OBJECTPOINT, 4),
CINIT(PROXY, OBJECTPOINT, 4),
/* Name and password to use when fetching. Specify the CONF_USERPWD flag in
the CURLOPT_FLAGS to activate this */
T(USERPWD, OBJECTPOINT, 5),
CINIT(USERPWD, OBJECTPOINT, 5),
/* Name and password to use with Proxy. Specify the CONF_PROXYUSERPWD
flag in the CURLOPT_FLAGS to activate this */
T(PROXYUSERPWD, OBJECTPOINT, 6),
CINIT(PROXYUSERPWD, OBJECTPOINT, 6),
/* Range to get, specified as an ASCII string. Specify the CONF_RANGE flag
in the CURLOPT_FLAGS to activate this */
T(RANGE, OBJECTPOINT, 7),
CINIT(RANGE, OBJECTPOINT, 7),
#if 0
/* Configuration flags */
T(FLAGS, LONG, 8),
CINIT(FLAGS, LONG, 8),
#endif
/* Specified file stream to upload from (use as input): */
T(INFILE, OBJECTPOINT, 9),
CINIT(INFILE, OBJECTPOINT, 9),
/* Buffer to receive error messages in, must be at least CURL_ERROR_SIZE
* bytes big. If this is not used, error messages go to stderr instead: */
T(ERRORBUFFER, OBJECTPOINT, 10),
CINIT(ERRORBUFFER, OBJECTPOINT, 10),
/* Function that will be called to store the output (instead of fwrite). The
* parameters will use fwrite() syntax, make sure to follow them. */
T(WRITEFUNCTION, FUNCTIONPOINT, 11),
CINIT(WRITEFUNCTION, FUNCTIONPOINT, 11),
/* Function that will be called to read the input (instead of fread). The
* parameters will use fread() syntax, make sure to follow them. */
T(READFUNCTION, FUNCTIONPOINT, 12),
CINIT(READFUNCTION, FUNCTIONPOINT, 12),
/* Time-out the read operation after this amount of seconds */
T(TIMEOUT, LONG, 13),
CINIT(TIMEOUT, LONG, 13),
/* If the CURLOPT_INFILE is used, this can be used to inform libcurl about
* how large the file being sent really is. That allows better error
* checking and better verifies that the upload was succcessful. -1 means
* unknown size. */
T(INFILESIZE, LONG, 14),
CINIT(INFILESIZE, LONG, 14),
/* POST input fields. */
T(POSTFIELDS, OBJECTPOINT, 15),
CINIT(POSTFIELDS, OBJECTPOINT, 15),
/* Set the referer page (needed by some CGIs) */
T(REFERER, OBJECTPOINT, 16),
CINIT(REFERER, OBJECTPOINT, 16),
/* Set the FTP PORT string (interface name, named or numerical IP address)
Use i.e '-' to use default address. */
T(FTPPORT, OBJECTPOINT, 17),
CINIT(FTPPORT, OBJECTPOINT, 17),
/* Set the User-Agent string (examined by some CGIs) */
T(USERAGENT, OBJECTPOINT, 18),
CINIT(USERAGENT, OBJECTPOINT, 18),
/* If the download receives less than "low speed limit" bytes/second
* during "low speed time" seconds, the operations is aborted.
@@ -257,122 +266,133 @@ typedef enum {
*/
/* Set the "low speed limit" */
T(LOW_SPEED_LIMIT, LONG , 19),
CINIT(LOW_SPEED_LIMIT, LONG , 19),
/* Set the "low speed time" */
T(LOW_SPEED_TIME, LONG, 20),
CINIT(LOW_SPEED_TIME, LONG, 20),
/* Set the continuation offset */
T(RESUME_FROM, LONG, 21),
CINIT(RESUME_FROM, LONG, 21),
/* Set cookie in request: */
T(COOKIE, OBJECTPOINT, 22),
CINIT(COOKIE, OBJECTPOINT, 22),
/* This points to a linked list of headers, struct HttpHeader kind */
T(HTTPHEADER, OBJECTPOINT, 23),
CINIT(HTTPHEADER, OBJECTPOINT, 23),
/* This points to a linked list of post entries, struct HttpPost */
T(HTTPPOST, OBJECTPOINT, 24),
CINIT(HTTPPOST, OBJECTPOINT, 24),
/* name of the file keeping your private SSL-certificate */
T(SSLCERT, OBJECTPOINT, 25),
CINIT(SSLCERT, OBJECTPOINT, 25),
/* password for the SSL-certificate */
T(SSLCERTPASSWD, OBJECTPOINT, 26),
CINIT(SSLCERTPASSWD, OBJECTPOINT, 26),
/* send TYPE parameter? */
T(CRLF, LONG, 27),
CINIT(CRLF, LONG, 27),
/* send linked-list of QUOTE commands */
T(QUOTE, OBJECTPOINT, 28),
CINIT(QUOTE, OBJECTPOINT, 28),
/* send FILE * to store headers to */
T(WRITEHEADER, OBJECTPOINT, 29),
CINIT(WRITEHEADER, OBJECTPOINT, 29),
#ifdef MULTIDOC
/* send linked list of MoreDoc structs */
T(MOREDOCS, OBJECTPOINT, 30),
CINIT(MOREDOCS, OBJECTPOINT, 30),
#endif
/* point to a file to read the initial cookies from, also enables
"cookie awareness" */
T(COOKIEFILE, OBJECTPOINT, 31),
CINIT(COOKIEFILE, OBJECTPOINT, 31),
/* What version to specifly try to use.
3 = SSLv3, 2 = SSLv2, all else makes it try v3 first then v2 */
T(SSLVERSION, LONG, 32),
CINIT(SSLVERSION, LONG, 32),
/* What kind of HTTP time condition to use, see defines */
T(TIMECONDITION, LONG, 33),
CINIT(TIMECONDITION, LONG, 33),
/* Time to use with the above condition. Specified in number of seconds
since 1 Jan 1970 */
T(TIMEVALUE, LONG, 34),
CINIT(TIMEVALUE, LONG, 34),
/* HTTP request, for odd commands like DELETE, TRACE and others */
/* OBSOLETE DEFINE, left for tradition only */
T(HTTPREQUEST, OBJECTPOINT, 35),
CINIT(HTTPREQUEST, OBJECTPOINT, 35),
/* Custom request, for customizing the get command like
HTTP: DELETE, TRACE and others
FTP: to use a different list command
*/
T(CUSTOMREQUEST, OBJECTPOINT, 36),
CINIT(CUSTOMREQUEST, OBJECTPOINT, 36),
/* HTTP request, for odd commands like DELETE, TRACE and others */
T(STDERR, OBJECTPOINT, 37),
CINIT(STDERR, OBJECTPOINT, 37),
#if 0
/* Progress mode set alternative progress mode displays. Alternative
ones should now be made by the client, not the lib! */
T(PROGRESSMODE, LONG, 38),
CINIT(PROGRESSMODE, LONG, 38),
#endif
/* send linked-list of post-transfer QUOTE commands */
T(POSTQUOTE, OBJECTPOINT, 39),
CINIT(POSTQUOTE, OBJECTPOINT, 39),
/* Pass a pointer to string of the output using full variable-replacement
as described elsewhere. */
T(WRITEINFO, OBJECTPOINT, 40),
CINIT(WRITEINFO, OBJECTPOINT, 40),
/* Previous FLAG bits */
T(VERBOSE, LONG, 41), /* talk a lot */
T(HEADER, LONG, 42), /* throw the header out too */
T(NOPROGRESS, LONG, 43), /* shut off the progress meter */
T(NOBODY, LONG, 44), /* use HEAD to get http document */
T(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
T(UPLOAD, LONG, 46), /* this is an upload */
T(POST, LONG, 47), /* HTTP POST method */
T(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */
CINIT(VERBOSE, LONG, 41), /* talk a lot */
CINIT(HEADER, LONG, 42), /* throw the header out too */
CINIT(NOPROGRESS, LONG, 43), /* shut off the progress meter */
CINIT(NOBODY, LONG, 44), /* use HEAD to get http document */
CINIT(FAILONERROR, LONG, 45), /* no output on http error codes >= 300 */
CINIT(UPLOAD, LONG, 46), /* this is an upload */
CINIT(POST, LONG, 47), /* HTTP POST method */
CINIT(FTPLISTONLY, LONG, 48), /* Use NLST when listing ftp dir */
T(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */
T(NETRC, LONG, 51), /* read user+password from .netrc */
T(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
CINIT(FTPAPPEND, LONG, 50), /* Append instead of overwrite on upload! */
CINIT(NETRC, LONG, 51), /* read user+password from .netrc */
CINIT(FOLLOWLOCATION, LONG, 52), /* use Location: Luke! */
/* This FTPASCII name is now obsolete, to be removed, use the TRANSFERTEXT
instead. It goes for more protocols than just ftp... */
T(FTPASCII, LONG, 53), /* use TYPE A for transfer */
CINIT(FTPASCII, LONG, 53), /* use TYPE A for transfer */
T(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
T(PUT, LONG, 54), /* PUT the input file */
T(MUTE, LONG, 55), /* force NOPROGRESS */
CINIT(TRANSFERTEXT, LONG, 53), /* transfer data in text/ASCII format */
CINIT(PUT, LONG, 54), /* PUT the input file */
CINIT(MUTE, LONG, 55), /* force NOPROGRESS */
/* Function that will be called instead of the internal progress display
* function. This function should be defined as the curl_progress_callback
* prototype defines. */
T(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
CINIT(PROGRESSFUNCTION, FUNCTIONPOINT, 56),
/* Data passed to the progress callback */
T(PROGRESSDATA, OBJECTPOINT, 57),
CINIT(PROGRESSDATA, OBJECTPOINT, 57),
/* We want the referer field set automatically when following locations */
T(AUTOREFERER, LONG, 58),
CINIT(AUTOREFERER, LONG, 58),
/* Port of the proxy, can be set in the proxy string as well with:
"[host]:[port]" */
T(PROXYPORT, LONG, 59),
CINIT(PROXYPORT, LONG, 59),
/* size of the POST input data, if strlen() is not good to use */
T(POSTFIELDSIZE, LONG, 60),
CINIT(POSTFIELDSIZE, LONG, 60),
/* tunnel non-http operations through a HTTP proxy */
CINIT(HTTPPROXYTUNNEL, LONG, 61),
/* Set the interface string to use as outgoing network interface */
CINIT(INTERFACE, OBJECTPOINT, 62),
/* Set the krb4 security level, this also enables krb4 awareness. This is a
* string, 'clear', 'safe', 'confidential' or 'private'. If the string is
* set but doesn't match one of these, 'private' will be used. */
CINIT(KRB4LEVEL, OBJECTPOINT, 63),
CURLOPT_LASTENTRY /* the last unusued */
} CURLoption;
@@ -392,10 +412,6 @@ typedef enum {
#ifdef __BEOS__
#include <support/SupportDefs.h>
#else
#ifndef __cplusplus /* (rabe) */
typedef char bool;
#endif /* (rabe) */
#endif
@@ -418,14 +434,14 @@ int curl_formparse(char *string,
MUST be free()ed after usage is complete. */
char *curl_getenv(char *variable);
/* returns ascii string of the libcurl version */
/* Returns a static ascii string of the libcurl version. */
char *curl_version(void);
/* This is the version number */
#define LIBCURL_VERSION "7.2"
#define LIBCURL_VERSION_NUM 0x070200
#define LIBCURL_VERSION "7.4.1"
#define LIBCURL_VERSION_NUM 0x070401
/* linked-list structure for the CURLOPT_QUOTE option */
/* linked-list structure for the CURLOPT_QUOTE option (and other) */
struct curl_slist {
char *data;
struct curl_slist *next;
@@ -622,4 +638,47 @@ CURLcode curl_disconnect(CURLconnect *connect);
*/
time_t curl_getdate(const char *p, const time_t *now);
#define CURLINFO_STRING 0x100000
#define CURLINFO_LONG 0x200000
#define CURLINFO_DOUBLE 0x300000
#define CURLINFO_MASK 0x0fffff
#define CURLINFO_TYPEMASK 0xf00000
typedef enum {
CURLINFO_NONE, /* first, never use this */
CURLINFO_EFFECTIVE_URL = CURLINFO_STRING + 1,
CURLINFO_HTTP_CODE = CURLINFO_LONG + 2,
CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE + 3,
CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE + 4,
CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE + 5,
CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE + 6,
CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE + 7,
CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE + 8,
CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE + 9,
CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE + 10,
CURLINFO_HEADER_SIZE = CURLINFO_LONG + 11,
CURLINFO_REQUEST_SIZE = CURLINFO_LONG + 12,
CURLINFO_LASTONE = 13,
} CURLINFO;
/*
* NAME curl_getinfo()
*
* DESCRIPTION
*
* Request internal information from the curl session with this function.
* The third argument MUST be a pointer to a long or a pointer to a char *.
* The data pointed to will be filled in accordingly and can be relied upon
* only if the function returns CURLE_OK.
* This function is intended to get used *AFTER* a performed transfer, all
* results are undefined before the transfer is completed.
*/
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...);
#ifdef __cplusplus
}
#endif
#endif /* __CURL_CURL_H */

View File

@@ -39,8 +39,32 @@
*
* ------------------------------------------------------------
****************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
CURL *curl_easy_init(void);
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURLcode curl_easy_perform(CURL *curl);
void curl_easy_cleanup(CURL *curl);
/*
* NAME curl_easy_getinfo()
*
* DESCRIPTION
*
* Request internal information from the curl session with this function. The
* third argument MUST be a pointer to a long, a pointer to a char * or a
* pointer to a double (as the documentation describes elsewhere). The data
* pointed to will be filled in accordingly and can be relied upon only if the
* function returns CURLE_OK. This function is intended to get used *AFTER* a
* performed transfer, all results from this function are undefined until the
* transfer is completed.
*/
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
#ifdef __cplusplus
}
#endif
#endif

View File

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

View File

@@ -77,16 +77,16 @@ RANLIB = @RANLIB@
VERSION = @VERSION@
YACC = @YACC@
AUTOMAKE_OPTIONS = foreign no-dependencies
AUTOMAKE_OPTIONS = foreign
lib_LTLIBRARIES = libcurl.la
# Some flags needed when trying to cause warnings ;-)
# CFLAGS = -g -Wall #-pedantic
# CFLAGS = -DMALLOCDEBUG -g # -Wall #-pedantic
INCLUDES = -I$(top_srcdir)/include
libcurl_la_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c telnet.h writeout.c writeout.h highlevel.c strequal.c strequal.h easy.c
libcurl_la_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c telnet.h getinfo.c highlevel.c strequal.c strequal.h easy.c security.h security.c krb4.c memdebug.c memdebug.h
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = ../config.h ../src/config.h
@@ -103,8 +103,8 @@ libcurl_la_LIBADD =
libcurl_la_OBJECTS = file.lo timeval.lo base64.lo hostip.lo progress.lo \
formdata.lo cookie.lo http.lo sendf.lo ftp.lo url.lo dict.lo if2ip.lo \
speedcheck.lo getdate.lo download.lo ldap.lo ssluse.lo version.lo \
getenv.lo escape.lo mprintf.lo telnet.lo getpass.lo netrc.lo \
writeout.lo highlevel.lo strequal.lo easy.lo
getenv.lo escape.lo mprintf.lo telnet.lo getpass.lo netrc.lo getinfo.lo \
highlevel.lo strequal.lo easy.lo security.lo krb4.lo memdebug.lo
CFLAGS = @CFLAGS@
COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)

View File

@@ -1,70 +1,81 @@
#############################################################
## Makefile for building libcurl.a with MingW32 (GCC-2.95) and
## optionally OpenSSL (0.9.4)
## Use: make -f Makefile.m32
##
## Comments to: Troy Engel <tengel@sonic.net> or
## Joern Hartroth <hartroth@acm.org>
CC = gcc
AR = ar
RANLIB = ranlib
OPENSSL_PATH = ../../openssl-0.9.5a
########################################################
## Nothing more to do below this line!
INCLUDES = -I. -I.. -I../include
CFLAGS = -g -O2 -DMINGW32
ifdef SSL
INCLUDES += -I"$(OPENSSL_PATH)/outinc" -I"$(OPENSSL_PATH)/outinc/openssl"
CFLAGS += -DUSE_SSLEAY
endif
COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
libcurl_a_LIBRARIES = libcurl.a
libcurl_a_SOURCES = base64.c getenv.c if2ip.h progress.h \
base64.h getenv.h mprintf.c setup.h url.c download.c getpass.c \
mprintf.h ssluse.c url.h download.h hostip.c netrc.c ssluse.h \
urldata.h formdata.c hostip.h netrc.h stdcheaders.h formdata.h \
if2ip.c progress.c sendf.c sendf.h speedcheck.c speedcheck.h \
ftp.c ftp.h getpass.h version.c timeval.c timeval.h cookie.c \
cookie.h escape.c escape.h getdate.c getdate.h dict.h dict.c http.c \
http.h telnet.c telnet.h file.c file.h ldap.c ldap.h writeout.c writeout.h \
highlevel.c strequal.c strequal.h easy.c
libcurl_a_OBJECTS = base64.o getenv.o mprintf.o url.o download.o \
getpass.o ssluse.o hostip.o netrc.o formdata.o if2ip.o progress.o \
sendf.o speedcheck.o ftp.o version.o timeval.o \
cookie.o escape.o getdate.o dict.o http.o telnet.o file.o ldap.o writeout.o \
highlevel.o strequal.o easy.o
LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES)
OBJECTS = $(libcurl_a_OBJECTS)
all: libcurl.a
libcurl.a: $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
-@erase libcurl.a
$(AR) cru libcurl.a $(libcurl_a_OBJECTS)
$(RANLIB) libcurl.a
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
clean:
-@erase $(libcurl_a_OBJECTS)
distrib: clean
-@erase $(libcurl_a_LIBRARIES)
#############################################################
## Makefile for building libcurl.a with MingW32 (GCC-2.95) and
## optionally OpenSSL (0.9.6)
## Use: make -f Makefile.m32
##
## Comments to: Troy Engel <tengel@sonic.net> or
## Joern Hartroth <hartroth@acm.org>
CC = gcc
AR = ar
RANLIB = ranlib
STRIP = strip -g
OPENSSL_PATH = ../../openssl-0.9.6
########################################################
## Nothing more to do below this line!
INCLUDES = -I. -I.. -I../include -I../src
CFLAGS = -g -O2 -DMINGW32
ifdef SSL
INCLUDES += -I"$(OPENSSL_PATH)/outinc" -I"$(OPENSSL_PATH)/outinc/openssl"
CFLAGS += -DUSE_SSLEAY
DLL_LIBS = -leay32 -lssl32 -lRSAglue
endif
COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
libcurl_a_LIBRARIES = libcurl.a
libcurl_a_SOURCES = arpa_telnet.h file.c getpass.h netrc.h timeval.c base64.c \
file.h hostip.c progress.c timeval.h base64.h formdata.c hostip.h progress.h \
cookie.c formdata.h http.c sendf.c cookie.h ftp.c http.h sendf.h url.c dict.c \
ftp.h if2ip.c speedcheck.c url.h dict.h getdate.c if2ip.h speedcheck.h \
urldata.h download.c getdate.h ldap.c ssluse.c version.c download.h getenv.c \
ldap.h ssluse.h escape.c getenv.h mprintf.c telnet.c escape.h getpass.c netrc.c \
telnet.h getinfo.c highlevel.c strequal.c strequal.h easy.c security.h \
security.c krb4.c
libcurl_a_OBJECTS = file.o timeval.o base64.o hostip.o progress.o \
formdata.o cookie.o http.o sendf.o ftp.o url.o dict.o if2ip.o \
speedcheck.o getdate.o download.o ldap.o ssluse.o version.o \
getenv.o escape.o mprintf.o telnet.o getpass.o netrc.o getinfo.o \
highlevel.o strequal.o easy.o security.o krb4.o
LIBRARIES = $(libcurl_a_LIBRARIES)
SOURCES = $(libcurl_a_SOURCES)
OBJECTS = $(libcurl_a_OBJECTS)
all: libcurl.a libcurl.dll libcurldll.a
libcurl.a: $(libcurl_a_OBJECTS) $(libcurl_a_DEPENDENCIES)
-@erase libcurl.a
$(AR) cru libcurl.a $(libcurl_a_OBJECTS)
$(RANLIB) libcurl.a
$(STRIP) $@
# remove the last line above to keep debug info
libcurl.dll libcurldll.a: libcurl.a libcurl.def dllinit.o
-@erase $@
dllwrap --dllname $@ --output-lib libcurldll.a --export-all --def libcurl.def $(libcurl_a_LIBRARIES) dllinit.o -L$(OPENSSL_PATH)/out $(DLL_LIBS) -lwsock32
$(STRIP) $@
# remove the last line above to keep debug info
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
clean:
-@erase $(libcurl_a_OBJECTS)
distrib: clean
-@erase $(libcurl_a_LIBRARIES)

View File

@@ -1,94 +1,152 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <daniel@haxx.se>
*
* http://curl.haxx.se
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
/*
* Copyright (c) 1995 - 1999 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include "base64.h"
/* ---- Base64 Encoding --- */
static char table64[]=
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
void base64Encode(char *intext, char *output)
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
static char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static int pos(char c)
{
unsigned char ibuf[3];
unsigned char obuf[4];
int i;
int inputparts;
while(*intext) {
for (i = inputparts = 0; i < 3; i++) {
if(*intext) {
inputparts++;
ibuf[i] = *intext;
intext++;
}
else
ibuf[i] = 0;
}
obuf [0] = (ibuf [0] & 0xFC) >> 2;
obuf [1] = ((ibuf [0] & 0x03) << 4) | ((ibuf [1] & 0xF0) >> 4);
obuf [2] = ((ibuf [1] & 0x0F) << 2) | ((ibuf [2] & 0xC0) >> 6);
obuf [3] = ibuf [2] & 0x3F;
switch(inputparts) {
case 1: /* only one byte read */
sprintf(output, "%c%c==",
table64[obuf[0]],
table64[obuf[1]]);
break;
case 2: /* two bytes read */
sprintf(output, "%c%c%c=",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]]);
break;
default:
sprintf(output, "%c%c%c%c",
table64[obuf[0]],
table64[obuf[1]],
table64[obuf[2]],
table64[obuf[3]] );
break;
}
output += 4;
}
*output=0;
char *p;
for(p = base64; *p; p++)
if(*p == c)
return p - base64;
return -1;
}
#if 1
int base64_encode(const void *data, int size, char **str)
{
char *s, *p;
int i;
int c;
const unsigned char *q;
p = s = (char*)malloc(size*4/3+4);
if (p == NULL)
return -1;
q = (const unsigned char*)data;
i=0;
for(i = 0; i < size;){
c=q[i++];
c*=256;
if(i < size)
c+=q[i];
i++;
c*=256;
if(i < size)
c+=q[i];
i++;
p[0]=base64[(c&0x00fc0000) >> 18];
p[1]=base64[(c&0x0003f000) >> 12];
p[2]=base64[(c&0x00000fc0) >> 6];
p[3]=base64[(c&0x0000003f) >> 0];
if(i > size)
p[3]='=';
if(i > size+1)
p[2]='=';
p+=4;
}
*p=0;
*str = s;
return strlen(s);
}
#endif
int base64_decode(const char *str, void *data)
{
const char *p;
unsigned char *q;
int c;
int x;
int done = 0;
q=(unsigned char*)data;
for(p=str; *p && !done; p+=4){
x = pos(p[0]);
if(x >= 0)
c = x;
else{
done = 3;
break;
}
c*=64;
x = pos(p[1]);
if(x >= 0)
c += x;
else
return -1;
c*=64;
if(p[2] == '=')
done++;
else{
x = pos(p[2]);
if(x >= 0)
c += x;
else
return -1;
}
c*=64;
if(p[3] == '=')
done++;
else{
if(done)
return -1;
x = pos(p[3]);
if(x >= 0)
c += x;
else
return -1;
}
if(done < 3)
*q++=(c&0x00ff0000)>>16;
if(done < 2)
*q++=(c&0x0000ff00)>>8;
if(done < 1)
*q++=(c&0x000000ff)>>0;
}
return q - (unsigned char*)data;
}
/* ---- End of Base64 Encoding ---- */

View File

@@ -1,44 +1,39 @@
/*
* Copyright (c) 1995, 1996, 1997 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef __BASE64_H
#define __BASE64_H
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1998.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <daniel@haxx.se>
*
* http://curl.haxx.se
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
void base64Encode(char *intext, char *output);
int base64_encode(const void *data, int size, char **str);
#endif

View File

@@ -65,6 +65,11 @@ Example set of cookies:
#include "getdate.h"
#include "strequal.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/****************************************************************************
*
* cookie_add()
@@ -99,8 +104,9 @@ struct Cookie *cookie_add(struct CookieInfo *c,
semiptr=strchr(lineptr, ';'); /* first, find a semicolon */
ptr = lineptr;
while(semiptr) {
*semiptr='\0'; /* zero terminate for a while */
do {
if(semiptr)
*semiptr='\0'; /* zero terminate for a while */
/* we have a <what>=<this> pair or a 'secure' word here */
if(strchr(ptr, '=')) {
name[0]=what[0]=0; /* init the buffers */
@@ -156,12 +162,15 @@ struct Cookie *cookie_add(struct CookieInfo *c,
; /* unsupported keyword without assign! */
}
}
if(!semiptr)
continue; /* we already know there are no more cookies */
*semiptr=';'; /* put the semicolon back */
ptr=semiptr+1;
while(ptr && *ptr && isspace((int)*ptr))
ptr++;
semiptr=strchr(ptr, ';'); /* now, find the next semicolon */
}
} while(semiptr);
}
else {
/* This line is NOT a HTTP header style line, we do offer support for
@@ -492,6 +501,7 @@ void cookie_cleanup(struct CookieInfo *c)
free(co);
co = next;
}
free(c); /* free the base struct as well */
}
}

82
lib/dllinit.c Normal file
View File

@@ -0,0 +1,82 @@
/* dllinit.c -- Portable DLL initialization.
Copyright (C) 1998, 1999 Free Software Foundation, Inc.
Contributed by Mumit Khan (khan@xraylith.wisc.edu).
I've used DllMain as the DLL "main" since that's the most common
usage. MSVC and Mingw32 both default to DllMain as the standard
callback from the linker entry point. Cygwin, as of b20.1, also
uses DllMain as the default callback from the entry point.
The real entry point is typically always defined by the runtime
library, and usually never overridden by (casual) user. What you can
override however is the callback routine that the entry point calls,
and this file provides such a callback function, DllMain.
Mingw32: The default entry point for mingw32 is DllMainCRTStartup
which is defined in libmingw32.a This in turn calls DllMain which is
defined here. If not defined, there is a stub in libmingw32.a which
does nothing.
Cygwin: The default entry point for Cygwin b20.1 or newer is
__cygwin_dll_entry which is defined in libcygwin.a. This in turn
calls the routine DllMain. If not defined, there is a stub in
libcygwin.a which does nothing.
MSVC: MSVC runtime calls DllMain, just like Mingw32.
Summary: If you need to do anything special in DllMain, just add it
here. Otherwise, the default setup should be just fine for 99%+ of
the time. I strongly suggest that you *not* change the entry point,
but rather change DllMain as appropriate.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <stdio.h>
BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason,
LPVOID reserved /* Not used. */ );
/*
*----------------------------------------------------------------------
*
* DllMain --
*
* This routine is called by the Mingw32, Cygwin32 or VC++ C run
* time library init code, or the Borland DllEntryPoint routine. It
* is responsible for initializing various dynamically loaded
* libraries.
*
* Results:
* TRUE on sucess, FALSE on failure.
*
* Side effects:
*
*----------------------------------------------------------------------
*/
BOOL APIENTRY
DllMain (
HINSTANCE hInst /* Library instance handle. */ ,
DWORD reason /* Reason this function is being called. */ ,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}

View File

@@ -109,6 +109,9 @@ CURL *curl_easy_init(void)
return NULL;
data->interf = CURLI_EASY; /* mark it as an easy one */
/* SAC */
data->device = NULL;
return data;
}
@@ -159,3 +162,13 @@ void curl_easy_cleanup(CURL *curl)
curl_close(curl);
curl_free();
}
CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
{
va_list arg;
void *paramp;
va_start(arg, info);
paramp = va_arg(arg, void *);
return curl_getinfo(curl, info, paramp);
}

View File

@@ -41,10 +41,18 @@
/* Escape and unescape URL encoding in strings. The functions return a new
* allocated string or NULL if an error occurred. */
#include "setup.h"
#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
char *curl_escape(char *string)
{
int alloc=strlen(string)+1;
@@ -88,17 +96,24 @@ char *curl_unescape(char *string, int length)
unsigned char in;
int index=0;
int hex;
char querypart=FALSE; /* everything to the right of a '?' letter is
the "query part" where '+' should become ' '.
RFC 2316, section 3.10 */
while(--alloc) {
in = *string;
if('+' == in)
in = ' ';
if(querypart && ('+' == in))
in = ' ';
else if(!querypart && ('?' == in)) {
/* we have "walked in" to the query part */
querypart=TRUE;
}
else if('%' == in) {
/* encoded part */
if(sscanf(string+1, "%02X", &hex)) {
in = hex;
string+=2;
}
/* encoded part */
if(sscanf(string+1, "%02X", &hex)) {
in = hex;
string+=2;
}
}
ns[index++] = in;

View File

@@ -63,6 +63,11 @@
#include "strequal.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* Length of the random boundary string. The risk of this being used
in binary data is very close to zero, 64^32 makes
6277101735386680763835789423207666416102355444464034512896
@@ -458,12 +463,20 @@ struct FormData *getFormData(struct HttpPost *post,
"\r\nContent-Type: %s",
file->contenttype);
}
#if 0
/* The header Content-Transfer-Encoding: seems to confuse some receivers
* (like the built-in PHP engine). While I can't see any reason why it
* should, I can just as well skip this to the benefit of the users who
* are using such confused receivers.
*/
if(file->contenttype &&
!strnequal("text/", file->contenttype, 5)) {
/* this is not a text content, mention our binary encoding */
size += AddFormData(&form, "\r\nContent-Transfer-Encoding: binary", 0);
}
#endif
size += AddFormData(&form, "\r\n\r\n", 0);

222
lib/ftp.c
View File

@@ -86,6 +86,14 @@
#include "download.h"
#include "escape.h"
#ifdef KRB4
#include "security.h"
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* returns last node in linked list */
static struct curl_slist *slist_get_last(struct curl_slist *list)
{
@@ -285,6 +293,19 @@ int GetLastResponse(int sockfd, char *buf,
}
*ptr=0; /* zero terminate */
#if KRB4
{ /* handle the security-oriented responses 6xx ***/
/* FIXME: some errorchecking perhaps... ***/
if(strncmp(buf, "631", 3) == 0)
sec_read_msg(conn, buf, prot_safe);
else if(strncmp(buf, "632", 3) == 0)
sec_read_msg(conn, buf, prot_private);
else if(strncmp(buf, "633", 3) == 0)
sec_read_msg(conn, buf, prot_confidential);
nread = strlen(buf);
}
#endif
if(data->bits.verbose && buf[0]) {
fputs("< ", data->err);
fwrite(buf, 1, nread, data->err);
@@ -372,6 +393,7 @@ CURLcode ftp_connect(struct connectdata *conn)
struct UrlData *data=conn->data;
char *buf = data->buffer; /* this is our buffer */
struct FTP *ftp;
CURLcode result;
myalarm(0); /* switch off the alarm stuff */
@@ -387,6 +409,14 @@ CURLcode ftp_connect(struct connectdata *conn)
ftp->user = data->user;
ftp->passwd = data->passwd;
if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = GetHTTPProxyTunnel(data, data->firstsocket,
data->hostname, data->remote_port);
if(CURLE_OK != result)
return result;
}
/* The first thing we do is wait for the "220*" line: */
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -396,8 +426,28 @@ CURLcode ftp_connect(struct connectdata *conn)
return CURLE_FTP_WEIRD_SERVER_REPLY;
}
#ifdef KRB4
/* if not anonymous login, try a secure login */
if(data->bits.krb4) {
/* request data protection level (default is 'clear') */
sec_request_prot(conn, "private");
/* We set private first as default, in case the line below fails to
set a valid level */
sec_request_prot(conn, data->krb4_level);
data->cmdchannel = fdopen(data->firstsocket, "w");
if(sec_login(conn) != 0)
infof(data, "Logging in with password in cleartext!\n");
else
infof(data, "Authentication successful\n");
}
#endif
/* send USER */
sendf(data->firstsocket, data, "USER %s\r\n", ftp->user);
ftpsendf(data->firstsocket, conn, "USER %s", ftp->user);
/* wait for feedback */
nread = GetLastResponse(data->firstsocket, buf, conn);
@@ -413,7 +463,7 @@ CURLcode ftp_connect(struct connectdata *conn)
else if(!strncmp(buf, "331", 3)) {
/* 331 Password required for ...
(the server requires to send the user's password too) */
sendf(data->firstsocket, data, "PASS %s\r\n", ftp->passwd);
ftpsendf(data->firstsocket, conn, "PASS %s", ftp->passwd);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
@@ -435,10 +485,23 @@ CURLcode ftp_connect(struct connectdata *conn)
return CURLE_FTP_WEIRD_PASS_REPLY;
}
}
else if(! strncmp(buf, "230", 3)) {
else if(/*! strncmp(buf, "230", 3)***/ buf[0] == '2') {
/* 230 User ... logged in.
(the user logged in without password) */
infof(data, "We have successfully logged in\n");
#ifdef KRB4
/* we are logged in (with Kerberos)
* now set the requested protection level
*/
if(conn->sec_complete)
sec_set_protection_level(conn);
/* we may need to issue a KAUTH here to have access to the files
* do it if user supplied a password
*/
if(conn->data->passwd && *conn->data->passwd)
krb_kauth(conn);
#endif
}
else {
failf(data, "Odd return code after USER");
@@ -471,25 +534,30 @@ CURLcode ftp_done(struct connectdata *conn)
failf(data, "Received only partial file");
return CURLE_PARTIAL_FILE;
}
else if(0 == *ftp->bytecountp) {
else if(!data->bits.no_body && (0 == *ftp->bytecountp)) {
failf(data, "No data was received!");
return CURLE_FTP_COULDNT_RETR_FILE;
}
}
#ifdef KRB4
sec_fflush_fd(conn, data->secondarysocket);
#endif
/* shut down the socket to inform the server we're done */
sclose(data->secondarysocket);
data->secondarysocket = -1;
/* now let's see what the server says about the transfer we
just performed: */
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
/* 226 Transfer complete, 250 Requested file action okay, completed. */
if(!strncmp(buf, "226", 3) && !strncmp(buf, "250", 3)) {
failf(data, "%s", buf+4);
return CURLE_FTP_WRITE_ERROR;
if(!data->bits.no_body) {
/* now let's see what the server says about the transfer we
just performed: */
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
/* 226 Transfer complete, 250 Requested file action okay, completed. */
if(!strncmp(buf, "226", 3) && !strncmp(buf, "250", 3)) {
failf(data, "%s", buf+4);
return CURLE_FTP_WRITE_ERROR;
}
}
/* Send any post-transfer QUOTE strings? */
@@ -499,7 +567,7 @@ CURLcode ftp_done(struct connectdata *conn)
while (qitem) {
/* Send string */
if (qitem->data) {
sendf(data->firstsocket, data, "%s\r\n", qitem->data);
ftpsendf(data->firstsocket, conn, "%s", qitem->data);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -520,7 +588,8 @@ CURLcode ftp_done(struct connectdata *conn)
if(ftp->dir)
free(ftp->dir);
/* TBD: the ftp struct is still allocated here */
free(ftp);
data->proto.ftp=NULL; /* it is gone */
return CURLE_OK;
}
@@ -556,7 +625,7 @@ CURLcode _ftp(struct connectdata *conn)
while (qitem) {
/* Send string */
if (qitem->data) {
sendf(data->firstsocket, data, "%s\r\n", qitem->data);
ftpsendf(data->firstsocket, conn, "%s", qitem->data);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -572,6 +641,19 @@ CURLcode _ftp(struct connectdata *conn)
}
}
/* change directory first! */
if(ftp->dir && ftp->dir[0]) {
ftpsendf(data->firstsocket, conn, "CWD %s", ftp->dir);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(strncmp(buf, "250", 3)) {
failf(data, "Couldn't change to directory %s", ftp->dir);
return CURLE_FTP_ACCESS_DENIED;
}
}
/* If we have selected NOBODY, it means that we only want file information.
Which in FTP can't be much more than the file size! */
if(data->bits.no_body) {
@@ -579,7 +661,7 @@ CURLcode _ftp(struct connectdata *conn)
may not support it! It is however the only way we have to get a file's
size! */
int filesize;
sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -613,23 +695,24 @@ CURLcode _ftp(struct connectdata *conn)
if(data->bits.ftp_use_port) {
struct sockaddr_in sa;
struct hostent *h=NULL;
char *hostdataptr=NULL;
size_t size;
unsigned short porttouse;
char myhost[256] = "";
if(data->ftpport) {
if(if2ip(data->ftpport, myhost, sizeof(myhost))) {
h = GetHost(data, myhost, hostent_buf, sizeof(hostent_buf));
h = GetHost(data, myhost, &hostdataptr);
}
else {
if(strlen(data->ftpport)>1)
h = GetHost(data, data->ftpport, hostent_buf, sizeof(hostent_buf));
h = GetHost(data, data->ftpport, &hostdataptr);
if(h)
strcpy(myhost,data->ftpport);
strcpy(myhost, data->ftpport); /* buffer overflow risk */
}
}
if(! *myhost) {
h=GetHost(data, getmyhost(myhost,sizeof(myhost)), hostent_buf, sizeof(hostent_buf));
h=GetHost(data, getmyhost(myhost, sizeof(myhost)), &hostdataptr);
}
infof(data, "We connect from %s\n", myhost);
@@ -658,16 +741,19 @@ CURLcode _ftp(struct connectdata *conn)
if ( listen(portsock, 1) < 0 ) {
failf(data, "listen(2) failed on socket");
free(hostdataptr);
return CURLE_FTP_PORT_FAILED;
}
}
else {
failf(data, "bind(2) failed on socket");
free(hostdataptr);
return CURLE_FTP_PORT_FAILED;
}
}
else {
failf(data, "socket(2) failed (%s)");
free(hostdataptr);
return CURLE_FTP_PORT_FAILED;
}
}
@@ -689,7 +775,7 @@ CURLcode _ftp(struct connectdata *conn)
sscanf( inet_ntoa(in), "%hu.%hu.%hu.%hu",
&ip[0], &ip[1], &ip[2], &ip[3]);
#endif
sendf(data->firstsocket, data, "PORT %d,%d,%d,%d,%d,%d\r\n",
ftpsendf(data->firstsocket, conn, "PORT %d,%d,%d,%d,%d,%d",
ip[0], ip[1], ip[2], ip[3],
porttouse >> 8,
porttouse & 255);
@@ -706,7 +792,7 @@ CURLcode _ftp(struct connectdata *conn)
}
else { /* we use the PASV command */
sendf(data->firstsocket, data, "PASV\r\n");
ftpsendf(data->firstsocket, conn, "PASV");
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -719,10 +805,12 @@ CURLcode _ftp(struct connectdata *conn)
else {
int ip[4];
int port[2];
unsigned short newport;
unsigned short newport; /* remote port, not necessary the local one */
unsigned short connectport; /* the local port connect() should use! */
char newhost[32];
struct hostent *he;
char *str=buf,*ip_addr;
char *hostdataptr=NULL;
/*
* New 227-parser June 3rd 1999.
@@ -746,21 +834,35 @@ CURLcode _ftp(struct connectdata *conn)
failf(data, "Couldn't interpret this 227-reply: %s", buf);
return CURLE_FTP_WEIRD_227_FORMAT;
}
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
he = GetHost(data, newhost, hostent_buf, sizeof(hostent_buf));
if(!he) {
failf(data, "Can't resolve new host %s", newhost);
return CURLE_FTP_CANT_GET_HOST;
}
sprintf(newhost, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
newport = (port[0]<<8) + port[1];
if(data->bits.httpproxy) {
/*
* This is a tunnel through a http proxy and we need to connect to the
* proxy again here. We already have the name info for it since the
* previous lookup.
*/
he = conn->hp;
connectport = data->port; /* we connect to the proxy's port */
}
else {
/* normal, direct, ftp connection */
he = GetHost(data, newhost, &hostdataptr);
if(!he) {
failf(data, "Can't resolve new host %s", newhost);
return CURLE_FTP_CANT_GET_HOST;
}
connectport = newport; /* we connect to the remote port */
}
data->secondarysocket = socket(AF_INET, SOCK_STREAM, 0);
memset((char *) &serv_addr, '\0', sizeof(serv_addr));
memcpy((char *)&(serv_addr.sin_addr), he->h_addr, he->h_length);
serv_addr.sin_family = he->h_addrtype;
serv_addr.sin_port = htons(newport);
serv_addr.sin_port = htons(connectport);
if(data->bits.verbose) {
struct in_addr in;
@@ -822,9 +924,12 @@ CURLcode _ftp(struct connectdata *conn)
#else
ip_addr = inet_ntoa(in),
#endif
newport);
connectport);
}
if(hostdataptr)
free(hostdataptr);
if (connect(data->secondarysocket, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0) {
switch(errno) {
@@ -845,30 +950,23 @@ CURLcode _ftp(struct connectdata *conn)
}
return CURLE_FTP_CANT_RECONNECT;
}
}
if (data->bits.tunnel_thru_httpproxy) {
/* We want "seamless" FTP operations through HTTP proxy tunnel */
result = GetHTTPProxyTunnel(data, data->secondarysocket,
newhost, newport);
if(CURLE_OK != result)
return result;
}
}
}
/* we have the (new) data connection ready */
infof(data, "Connected!\n");
/* change directory first */
if(ftp->dir && ftp->dir[0]) {
sendf(data->firstsocket, data, "CWD %s\r\n", ftp->dir);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
return CURLE_OPERATION_TIMEOUTED;
if(strncmp(buf, "250", 3)) {
failf(data, "Couldn't change to directory %s", ftp->dir);
return CURLE_FTP_ACCESS_DENIED;
}
}
infof(data, "Connected the data stream!\n");
if(data->bits.upload) {
/* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n",
ftpsendf(data->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, conn);
@@ -900,7 +998,7 @@ CURLcode _ftp(struct connectdata *conn)
/* we could've got a specified offset from the command line,
but now we know we didn't */
sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -923,7 +1021,7 @@ CURLcode _ftp(struct connectdata *conn)
infof(data, "Instructs server to resume from offset %d\n",
data->resume_from);
sendf(data->firstsocket, data, "REST %d\r\n", data->resume_from);
ftpsendf(data->firstsocket, conn, "REST %d", data->resume_from);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -975,9 +1073,9 @@ CURLcode _ftp(struct connectdata *conn)
/* Send everything on data->in to the socket */
if(data->bits.ftp_append)
/* we append onto the file instead of rewriting it */
sendf(data->firstsocket, data, "APPE %s\r\n", ftp->file);
ftpsendf(data->firstsocket, conn, "APPE %s", ftp->file);
else
sendf(data->firstsocket, data, "STOR %s\r\n", ftp->file);
ftpsendf(data->firstsocket, conn, "STOR %s", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -1063,7 +1161,7 @@ CURLcode _ftp(struct connectdata *conn)
dirlist = TRUE;
/* Set type to ASCII */
sendf(data->firstsocket, data, "TYPE A\r\n");
ftpsendf(data->firstsocket, conn, "TYPE A");
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -1078,14 +1176,14 @@ CURLcode _ftp(struct connectdata *conn)
better used since the LIST command output is not specified or
standard in any way */
sendf(data->firstsocket, data, "%s\r\n",
ftpsendf(data->firstsocket, conn, "%s",
data->customrequest?data->customrequest:
(data->bits.ftp_list_only?"NLST":"LIST"));
}
else {
/* Set type to binary (unless specified ASCII) */
sendf(data->firstsocket, data, "TYPE %s\r\n",
(data->bits.ftp_list_only)?"A":"I");
ftpsendf(data->firstsocket, conn, "TYPE %s",
(data->bits.ftp_ascii)?"A":"I");
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -1106,7 +1204,7 @@ CURLcode _ftp(struct connectdata *conn)
* 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. */
sendf(data->firstsocket, data, "SIZE %s\r\n", ftp->file);
ftpsendf(data->firstsocket, conn, "SIZE %s", ftp->file);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -1150,7 +1248,7 @@ CURLcode _ftp(struct connectdata *conn)
infof(data, "Instructs server to resume from offset %d\n",
data->resume_from);
sendf(data->firstsocket, data, "REST %d\r\n", data->resume_from);
ftpsendf(data->firstsocket, conn, "REST %d", data->resume_from);
nread = GetLastResponse(data->firstsocket, buf, conn);
if(nread < 0)
@@ -1162,7 +1260,7 @@ CURLcode _ftp(struct connectdata *conn)
}
}
sendf(data->firstsocket, data, "RETR %s\r\n", ftp->file);
ftpsendf(data->firstsocket, conn, "RETR %s", ftp->file);
}
nread = GetLastResponse(data->firstsocket, buf, conn);

View File

@@ -45,6 +45,10 @@
#include <windows.h>
#endif
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
char *GetEnv(char *variable)
{
#ifdef WIN32

124
lib/getinfo.c Normal file
View File

@@ -0,0 +1,124 @@
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1999.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <daniel@haxx.se>
*
* http://curl.haxx.se
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#include "urldata.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
CURLcode curl_getinfo(CURL *curl, CURLINFO info, ...)
{
va_list arg;
long *param_longp;
double *param_doublep;
char **param_charp;
struct UrlData *data = (struct UrlData *)curl;
va_start(arg, info);
switch(info&CURLINFO_TYPEMASK) {
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
case CURLINFO_STRING:
param_charp = va_arg(arg, char **);
if(NULL == param_charp)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLINFO_LONG:
param_longp = va_arg(arg, long *);
if(NULL == param_longp)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
case CURLINFO_DOUBLE:
param_doublep = va_arg(arg, double *);
if(NULL == param_doublep)
return CURLE_BAD_FUNCTION_ARGUMENT;
break;
}
switch(info) {
case CURLINFO_EFFECTIVE_URL:
*param_charp = data->url?data->url:"";
break;
case CURLINFO_HTTP_CODE:
*param_longp = data->progress.httpcode;
break;
case CURLINFO_HEADER_SIZE:
*param_longp = data->header_size;
break;
case CURLINFO_REQUEST_SIZE:
*param_longp = data->request_size;
break;
case CURLINFO_TOTAL_TIME:
*param_doublep = data->progress.timespent;
break;
case CURLINFO_NAMELOOKUP_TIME:
*param_doublep = tvdiff(data->progress.t_nslookup,
data->progress.start);
break;
case CURLINFO_CONNECT_TIME:
*param_doublep = tvdiff(data->progress.t_connect,
data->progress.start);
break;
case CURLINFO_PRETRANSFER_TIME:
*param_doublep = tvdiff(data->progress.t_pretransfer,
data->progress.start);
break;
case CURLINFO_SIZE_UPLOAD:
*param_doublep = data->progress.uploaded;
break;
case CURLINFO_SIZE_DOWNLOAD:
*param_doublep = data->progress.downloaded;
break;
case CURLINFO_SPEED_DOWNLOAD:
*param_doublep = data->progress.dlspeed;
break;
case CURLINFO_SPEED_UPLOAD:
*param_doublep = data->progress.ulspeed;
break;
default:
return CURLE_BAD_FUNCTION_ARGUMENT;
}
return CURLE_OK;
}

View File

@@ -107,11 +107,19 @@
#include "getpass.h"
#include "progress.h"
#include "getdate.h"
#include "writeout.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#ifndef min
#define min(a, b) ((a) < (b) ? (a) : (b))
#endif
CURLcode
_Transfer(struct connectdata *c_conn)
{
@@ -172,7 +180,9 @@ _Transfer(struct connectdata *c_conn)
if(conn->size > 0)
pgrsSetDownloadSize(data, conn->size);
}
{
/* we want header and/or body, if neither then don't do this! */
if(conn->getheader ||
!data->bits.no_body) {
fd_set readfd;
fd_set writefd;
fd_set rkeepfd;
@@ -343,6 +353,7 @@ _Transfer(struct connectdata *c_conn)
return CURLE_WRITE_ERROR;
}
}
data->header_size += p - data->headerbuff;
break; /* exit header line loop */
}
@@ -419,6 +430,7 @@ _Transfer(struct connectdata *c_conn)
return CURLE_WRITE_ERROR;
}
}
data->header_size += hbuflen;
/* reset hbufp pointer && hbuflen */
hbufp = data->headerbuff;
@@ -520,7 +532,7 @@ _Transfer(struct connectdata *c_conn)
if(data->crlf)
buf = data->buffer; /* put it back on the buffer */
nread = data->fread(buf, 1, BUFSIZE, data->in);
nread = data->fread(buf, 1, conn->upload_bufsize, data->in);
/* the signed int typecase of nread of for systems that has
unsigned size_t */
@@ -568,6 +580,15 @@ _Transfer(struct connectdata *c_conn)
if (urg)
return urg;
if(data->progress.ulspeed > conn->upload_bufsize) {
/* If we're transfering more data per second than fits in our buffer,
we increase the buffer size to adjust to the current
speed. However, we must not set it larger than BUFSIZE. We don't
adjust it downwards again since we don't see any point in that!
*/
conn->upload_bufsize=(long)min(data->progress.ulspeed, BUFSIZE);
}
if (data->timeout && (tvdiff (now, start) > data->timeout)) {
failf (data, "Operation timed out with %d out of %d bytes received",
bytecount, conn->size);
@@ -701,6 +722,7 @@ CURLcode curl_transfer(CURL *curl)
/* TBD: set the URL with curl_setopt() */
data->url = data->newurl;
data->newurl = NULL; /* don't show! */
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! */
@@ -722,10 +744,12 @@ CURLcode curl_transfer(CURL *curl)
if(data->newurl)
free(data->newurl);
#if 0
if((CURLE_OK == res) && data->writeinfo) {
/* Time to output some info to stdout */
WriteOut(data);
}
#endif
return res;
}

View File

@@ -41,7 +41,6 @@
#include "setup.h"
#include <string.h>
#include <malloc.h>
#include <errno.h>
#define _REENTRANT
@@ -73,6 +72,11 @@
#include "inet_ntoa_r.h"
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* --- resolve name or IP-number --- */
char *MakeIP(unsigned long num,char *addr, int addr_len)
@@ -103,13 +107,23 @@ char *MakeIP(unsigned long num,char *addr, int addr_len)
#endif
struct hostent *GetHost(struct UrlData *data,
char *hostname,
char *buf,
int buf_size )
char **bufp)
{
struct hostent *h = NULL;
unsigned long in;
int ret;
#define CURL_NAMELOOKUP_SIZE 9000
/* Allocate enough memory to hold the full name information structs and
* everything. OSF1 is known to require at least 8872 bytes. The buffer
* required for storing all possible aliases and IP numbers is according to
* Stevens' Unix Network Programming 2nd editor, p. 304: 8192 bytes! */
char *buf = (char *)malloc(CURL_NAMELOOKUP_SIZE);
if(!buf)
return NULL; /* major failure */
*bufp = buf;
if ( (in=inet_addr(hostname)) != INADDR_NONE ) {
struct in_addr *addrentry;
@@ -123,18 +137,20 @@ struct hostent *GetHost(struct UrlData *data,
h->h_length = sizeof(*addrentry);
h->h_name = *(h->h_addr_list) + h->h_length;
/* bad one h->h_name = (char*)(h->h_addr_list + h->h_length); */
MakeIP(ntohl(in),h->h_name,buf_size - (long)(h->h_name) + (long)buf);
MakeIP(ntohl(in),h->h_name, CURL_NAMELOOKUP_SIZE - (long)(h->h_name) + (long)buf);
}
#if defined(HAVE_GETHOSTBYNAME_R)
else {
int h_errnop;
memset(buf,0,buf_size); /* workaround for gethostbyname_r bug in qnx nto */
/* Workaround for gethostbyname_r bug in qnx nto. It is also _required_
for some of these functions. */
memset(buf, 0, CURL_NAMELOOKUP_SIZE);
#ifdef HAVE_GETHOSTBYNAME_R_5
/* Solaris, IRIX and more */
if ((h = gethostbyname_r(hostname,
(struct hostent *)buf,
buf + sizeof(struct hostent),
buf_size - sizeof(struct hostent),
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
&h_errnop)) == NULL )
#endif
#ifdef HAVE_GETHOSTBYNAME_R_6
@@ -142,22 +158,26 @@ struct hostent *GetHost(struct UrlData *data,
if( gethostbyname_r(hostname,
(struct hostent *)buf,
buf + sizeof(struct hostent),
buf_size - sizeof(struct hostent),
CURL_NAMELOOKUP_SIZE - sizeof(struct hostent),
&h, /* DIFFERENCE */
&h_errnop))
#endif
#ifdef HAVE_GETHOSTBYNAME_R_3
/* AIX, Digital Unix, HPUX 10, more? */
/* August 4th, 2000. I don't have any such system around so I write this
blindly in hope it might work or that someone else will help me fix
this. August 22nd, 2000: Albert Chin-A-Young brought an updated version
that should work! */
if(CURL_NAMELOOKUP_SIZE >=
(sizeof(struct hostent)+sizeof(struct hostent_data)))
ret = gethostbyname_r(hostname,
(struct hostent *)buf,
(struct hostent_data *)(buf + sizeof(struct hostent)));
/* August 22nd, 2000: Albert Chin-A-Young brought an updated version
* that should work! September 20: Richard Prescott worked on the buffer
* size dilemma. */
ret = gethostbyname_r(hostname,
(struct hostent *)buf,
(struct hostent_data *)(buf + sizeof(struct hostent)));
else
ret = -1; /* failure, too smallish buffer size */
/* result expected in h */
h = (struct hostent*)buf;
h_errnop= errno; /* we don't deal with this, but set it anyway */
@@ -165,11 +185,14 @@ struct hostent *GetHost(struct UrlData *data,
#endif
{
infof(data, "gethostbyname_r(2) failed for %s\n", hostname);
h = NULL; /* set return code to NULL */
free(buf);
}
#else
else {
if ((h = gethostbyname(hostname)) == NULL ) {
infof(data, "gethostbyname(2) failed for %s\n", hostname);
free(buf);
}
#endif
}

View File

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

View File

@@ -117,6 +117,11 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/*
* This function checks the linked list of custom HTTP headers for a particular
* header (prefix).
@@ -134,9 +139,58 @@ bool static checkheaders(struct UrlData *data, char *thisheader)
return FALSE;
}
/*
* GetHTTPProxyTunnel() requires that we're connected to a HTTP proxy. This
* function will issue the necessary commands to get a seamless tunnel through
* this proxy. After that, the socket can be used just as a normal socket.
*/
CURLcode GetHTTPProxyTunnel(struct UrlData *data, int tunnelsocket,
char *hostname, int remote_port)
{
int httperror=0;
int subversion=0;
infof(data, "Establish HTTP proxy tunnel to %s:%d\n", hostname, remote_port);
/* OK, now send the connect statment */
sendf(tunnelsocket, data,
"CONNECT %s:%d HTTP/1.0\015\012"
"%s"
"%s"
"\r\n",
hostname, remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"")
);
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
while(GetLine(tunnelsocket, data->buffer, data)) {
if('\r' == data->buffer[0])
break; /* end of headers */
if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
&subversion,
&httperror)) {
;
}
}
if(200 != httperror) {
if(407 == httperror)
/* Added Nov 6 1998 */
failf(data, "Proxy requires authorization!");
else
failf(data, "Received error code %d from proxy", httperror);
return CURLE_READ_ERROR;
}
infof (data, "Proxy replied to CONNECT request\n");
return CURLE_OK;
}
CURLcode http_connect(struct connectdata *conn)
{
struct UrlData *data;
CURLcode result;
data=conn->data;
@@ -146,59 +200,28 @@ CURLcode http_connect(struct connectdata *conn)
* us to the host we want to talk to. Only after the connect
* has occured, can we start talking SSL
*/
if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) {
if (conn->protocol & PROT_HTTPS) {
if (data->bits.httpproxy) {
/* HTTPS through a proxy can only be done with a tunnel */
result = GetHTTPProxyTunnel(data, data->firstsocket,
data->hostname, data->remote_port);
if(CURLE_OK != result)
return result;
}
/* OK, now send the connect statment */
sendf(data->firstsocket, data,
"CONNECT %s:%d HTTP/1.0\015\012"
"%s"
"%s"
"\r\n",
data->hostname, data->remote_port,
(data->bits.proxy_user_passwd)?data->ptr_proxyuserpwd:"",
(data->useragent?data->ptr_uagent:"")
);
/* wait for the proxy to send us a HTTP/1.0 200 OK header */
/* Daniel rewrote this part Nov 5 1998 to make it more obvious */
{
int httperror=0;
int subversion=0;
while(GetLine(data->firstsocket, data->buffer, data)) {
if('\r' == data->buffer[0])
break; /* end of headers */
if(2 == sscanf(data->buffer, "HTTP/1.%d %d",
&subversion,
&httperror)) {
;
}
}
if(200 != httperror) {
if(407 == httperror)
/* Added Nov 6 1998 */
failf(data, "Proxy requires authorization!");
else
failf(data, "Received error code %d from proxy", httperror);
return CURLE_READ_ERROR;
}
}
infof (data, "Proxy has replied to CONNECT request\n");
}
/* now, perform the SSL initialization for this socket */
if(UrgSSLConnect (data)) {
return CURLE_SSL_CONNECT_ERROR;
}
/* now, perform the SSL initialization for this socket */
if(UrgSSLConnect (data)) {
return CURLE_SSL_CONNECT_ERROR;
}
}
if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the
original host name */
data->auth_host = strdup(data->hostname);
}
if(data->bits.user_passwd && !data->bits.this_is_a_follow) {
/* Authorization: is requested, this is not a followed location, get the
original host name */
data->auth_host = strdup(data->hostname);
}
return CURLE_OK;
return CURLE_OK;
}
/* called from curl_close() when this struct is about to get wasted, free
@@ -231,7 +254,8 @@ CURLcode http_done(struct connectdata *conn)
*bytecount = http->readbytecount + http->writebytecount;
}
/* TBD: the HTTP struct remains allocated here */
free(http);
data->proto.http=NULL; /* it is gone */
return CURLE_OK;
}
@@ -269,7 +293,7 @@ CURLcode http(struct connectdata *conn)
}
if((data->bits.user_passwd) && !checkheaders(data, "Authorization:")) {
char authorization[512];
char *authorization;
/* To prevent the user+password to get sent to other than the original
host due to a location-follow, we do some weirdo checks here */
@@ -277,9 +301,12 @@ CURLcode http(struct connectdata *conn)
!data->auth_host ||
strequal(data->auth_host, data->hostname)) {
sprintf(data->buffer, "%s:%s", data->user, data->passwd);
base64Encode(data->buffer, authorization);
data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012",
authorization);
if(base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) {
data->ptr_userpwd = maprintf( "Authorization: Basic %s\015\012",
authorization);
free(authorization);
}
}
}
if((data->bits.set_range) && !checkheaders(data, "Range:")) {
@@ -319,35 +346,41 @@ CURLcode http(struct connectdata *conn)
http->p_accept = "Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*\r\n";
do {
send_buffer *req_buffer;
struct curl_slist *headers=data->headers;
sendf(data->firstsocket, data,
"%s " /* GET/HEAD/POST/PUT */
"%s HTTP/1.0\r\n" /* path */
"%s" /* proxyuserpwd */
"%s" /* userpwd */
"%s" /* range */
"%s" /* user agent */
"%s" /* cookie */
"%s" /* host */
"%s" /* pragma */
"%s" /* accept */
"%s", /* referer */
data->customrequest?data->customrequest:
(data->bits.no_body?"HEAD":
(data->bits.http_post || data->bits.http_formpost)?"POST":
(data->bits.http_put)?"PUT":"GET"),
ppath,
(data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
(data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
(data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
(data->ptr_host?data->ptr_host:""), /* Host: host */
http->p_pragma?http->p_pragma:"",
http->p_accept?http->p_accept:"",
(data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
);
/* initialize a dynamic send-buffer */
req_buffer = add_buffer_init();
/* add the main request stuff */
add_bufferf(req_buffer,
"%s " /* GET/HEAD/POST/PUT */
"%s HTTP/1.0\r\n" /* path */
"%s" /* proxyuserpwd */
"%s" /* userpwd */
"%s" /* range */
"%s" /* user agent */
"%s" /* cookie */
"%s" /* host */
"%s" /* pragma */
"%s" /* accept */
"%s", /* referer */
data->customrequest?data->customrequest:
(data->bits.no_body?"HEAD":
(data->bits.http_post || data->bits.http_formpost)?"POST":
(data->bits.http_put)?"PUT":"GET"),
ppath,
(data->bits.proxy_user_passwd && data->ptr_proxyuserpwd)?data->ptr_proxyuserpwd:"",
(data->bits.user_passwd && data->ptr_userpwd)?data->ptr_userpwd:"",
(data->bits.set_range && data->ptr_rangeline)?data->ptr_rangeline:"",
(data->useragent && *data->useragent && data->ptr_uagent)?data->ptr_uagent:"",
(data->ptr_cookie?data->ptr_cookie:""), /* Cookie: <data> */
(data->ptr_host?data->ptr_host:""), /* Host: host */
http->p_pragma?http->p_pragma:"",
http->p_accept?http->p_accept:"",
(data->bits.http_set_referer && data->ptr_ref)?data->ptr_ref:"" /* Referer: <data> <CRLF> */
);
if(co) {
int count=0;
@@ -355,19 +388,16 @@ CURLcode http(struct connectdata *conn)
while(co) {
if(co->value && strlen(co->value)) {
if(0 == count) {
sendf(data->firstsocket, data,
"Cookie:");
add_bufferf(req_buffer, "Cookie:");
}
sendf(data->firstsocket, data,
"%s%s=%s", count?"; ":"", co->name,
co->value);
add_bufferf(req_buffer,
"%s%s=%s", count?"; ":"", co->name, co->value);
count++;
}
co = co->next; /* next cookie please */
}
if(count) {
sendf(data->firstsocket, data,
"\r\n");
add_buffer(req_buffer, "\r\n", 2);
}
cookie_freelist(co); /* free the cookie list */
co=NULL;
@@ -398,16 +428,16 @@ CURLcode http(struct connectdata *conn)
switch(data->timecondition) {
case TIMECOND_IFMODSINCE:
default:
sendf(data->firstsocket, data,
"If-Modified-Since: %s\r\n", buf);
add_bufferf(req_buffer,
"If-Modified-Since: %s\r\n", buf);
break;
case TIMECOND_IFUNMODSINCE:
sendf(data->firstsocket, data,
"If-Unmodified-Since: %s\r\n", buf);
add_bufferf(req_buffer,
"If-Unmodified-Since: %s\r\n", buf);
break;
case TIMECOND_LASTMOD:
sendf(data->firstsocket, data,
"Last-Modified: %s\r\n", buf);
add_bufferf(req_buffer,
"Last-Modified: %s\r\n", buf);
break;
}
}
@@ -424,9 +454,7 @@ CURLcode http(struct connectdata *conn)
if(*ptr) {
/* only send this if the contents was non-blank */
sendf(data->firstsocket, data,
"%s\015\012",
headers->data);
add_bufferf(req_buffer, "%s\r\n", headers->data);
}
}
headers = headers->next;
@@ -447,12 +475,14 @@ CURLcode http(struct connectdata *conn)
generated form data */
data->in = (FILE *)&http->form;
sendf(data->firstsocket, data,
"Content-Length: %d\r\n",
http->postsize-2);
add_bufferf(req_buffer,
"Content-Length: %d\r\n", http->postsize-2);
/* set upload size to the progress meter */
pgrsSetUploadSize(data, http->postsize);
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
result = Transfer(conn, data->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
@@ -466,16 +496,21 @@ CURLcode http(struct connectdata *conn)
/* Let's PUT the data to the server! */
if(data->infilesize>0) {
sendf(data->firstsocket, data,
"Content-Length: %d\r\n\r\n", /* file size */
data->infilesize );
add_bufferf(req_buffer,
"Content-Length: %d\r\n\r\n", /* file size */
data->infilesize );
}
else
sendf(data->firstsocket, data,
"\015\012");
add_bufferf(req_buffer, "\015\012");
/* set the upload size to the progress meter */
pgrsSetUploadSize(data, data->infilesize);
/* this sends the buffer and frees all the buffer resources */
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
/* prepare for transfer */
result = Transfer(conn, data->firstsocket, -1, TRUE,
&http->readbytecount,
data->firstsocket,
@@ -491,28 +526,35 @@ CURLcode http(struct connectdata *conn)
if(!checkheaders(data, "Content-Length:"))
/* we allow replacing this header, although it isn't very wise to
actually set your own */
sendf(data->firstsocket, data,
"Content-Length: %d\r\n",
(data->postfieldsize?data->postfieldsize:
strlen(data->postfields)) );
add_bufferf(req_buffer,
"Content-Length: %d\r\n",
(data->postfieldsize?data->postfieldsize:
strlen(data->postfields)) );
if(!checkheaders(data, "Content-Type:"))
sendf(data->firstsocket, data,
"Content-Type: application/x-www-form-urlencoded\r\n");
add_bufferf(req_buffer,
"Content-Type: application/x-www-form-urlencoded\r\n");
/* and here comes the actual data */
if(data->postfieldsize) {
ssend(data->firstsocket, data, "\r\n", 2);
ssend(data->firstsocket, data, data->postfields, data->postfieldsize);
ssend(data->firstsocket, data, "\r\n", 2);
add_buffer(req_buffer, "\r\n", 2);
add_buffer(req_buffer, data->postfields,
data->postfieldsize);
add_buffer(req_buffer, "\r\n", 2);
}
else {
add_bufferf(req_buffer,
"\r\n"
"%s\r\n",
data->postfields );
}
sendf(data->firstsocket, data,
"\r\n"
"%s\r\n",
data->postfields );
}
else
sendf(data->firstsocket, data, "\r\n");
add_buffer(req_buffer, "\r\n", 2);
/* issue the request */
data->request_size =
add_buffer_send(data->firstsocket, conn, req_buffer);
/* HTTP GET/HEAD download: */
result = Transfer(conn, data->firstsocket, -1, TRUE, bytecount,

View File

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

497
lib/krb4.c Normal file
View File

@@ -0,0 +1,497 @@
/* modified by Martin Hedenfalk <mhe@stacken.kth.se> for use in Curl
* last modified 2000-09-18
*/
/*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "setup.h"
#ifdef KRB4
#include "security.h"
#include "base64.h"
#include <stdlib.h>
#include <netdb.h>
#include <syslog.h>
#include <string.h>
#include <krb.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#ifdef FTP_SERVER
#define LOCAL_ADDR ctrl_addr
#define REMOTE_ADDR his_addr
#else
/*#define LOCAL_ADDR myctladdr***/
/*#define REMOTE_ADDR hisctladdr***/
#endif
/*extern struct sockaddr *LOCAL_ADDR, *REMOTE_ADDR;***/
#define LOCAL_ADDR (&local_addr)
#define REMOTE_ADDR (&conn->serv_addr)
#define myctladdr LOCAL_ADDR
#define hisctladdr REMOTE_ADDR
static struct sockaddr_in local_addr;
struct krb4_data {
des_cblock key;
des_key_schedule schedule;
char name[ANAME_SZ];
char instance[INST_SZ];
char realm[REALM_SZ];
};
#ifndef HAVE_STRLCPY
size_t
strlcpy (char *dst, const char *src, size_t dst_sz)
{
size_t n;
char *p;
for (p = dst, n = 0;
n + 1 < dst_sz && *src != '\0';
++p, ++src, ++n)
*p = *src;
*p = '\0';
if (*src == '\0')
return n;
else
return n + strlen (src);
}
#endif
static int
krb4_check_prot(void *app_data, int level)
{
if(level == prot_confidential)
return -1;
return 0;
}
static int
krb4_decode(void *app_data, void *buf, int len, int level,
struct connectdata *conn)
{
MSG_DAT m;
int e;
struct krb4_data *d = app_data;
if(level == prot_safe)
e = krb_rd_safe(buf, len, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
else
e = krb_rd_priv(buf, len, d->schedule, &d->key,
(struct sockaddr_in *)REMOTE_ADDR,
(struct sockaddr_in *)LOCAL_ADDR, &m);
if(e){
syslog(LOG_ERR, "krb4_decode: %s", krb_get_err_text(e));
return -1;
}
memmove(buf, m.app_data, m.app_length);
return m.app_length;
}
static int
krb4_overhead(void *app_data, int level, int len)
{
return 31;
}
static int
krb4_encode(void *app_data, void *from, int length, int level, void **to,
struct connectdata *conn)
{
struct krb4_data *d = app_data;
*to = malloc(length + 31);
if(level == prot_safe)
return krb_mk_safe(from, *to, length, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else if(level == prot_private)
return krb_mk_priv(from, *to, length, d->schedule, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
else
return -1;
}
#ifdef FTP_SERVER
static int
krb4_adat(void *app_data, void *buf, size_t len)
{
KTEXT_ST tkt;
AUTH_DAT auth_dat;
char *p;
int kerror;
u_int32_t cs;
char msg[35]; /* size of encrypted block */
int tmp_len;
struct krb4_data *d = app_data;
char inst[INST_SZ];
struct sockaddr_in *his_addr_sin = (struct sockaddr_in *)his_addr;
memcpy(tkt.dat, buf, len);
tkt.length = len;
k_getsockinst(0, inst, sizeof(inst));
kerror = krb_rd_req(&tkt, "ftp", inst,
his_addr_sin->sin_addr.s_addr, &auth_dat, "");
if(kerror == RD_AP_UNDEC){
k_getsockinst(0, inst, sizeof(inst));
kerror = krb_rd_req(&tkt, "rcmd", inst,
his_addr_sin->sin_addr.s_addr, &auth_dat, "");
}
if(kerror){
reply(535, "Error reading request: %s.", krb_get_err_text(kerror));
return -1;
}
memcpy(d->key, auth_dat.session, sizeof(d->key));
des_set_key(&d->key, d->schedule);
strlcpy(d->name, auth_dat.pname, sizeof(d->name));
strlcpy(d->instance, auth_dat.pinst, sizeof(d->instance));
strlcpy(d->realm, auth_dat.prealm, sizeof(d->instance));
cs = auth_dat.checksum + 1;
{
unsigned char tmp[4];
KRB_PUT_INT(cs, tmp, 4, sizeof(tmp));
tmp_len = krb_mk_safe(tmp, msg, 4, &d->key,
(struct sockaddr_in *)LOCAL_ADDR,
(struct sockaddr_in *)REMOTE_ADDR);
}
if(tmp_len < 0){
reply(535, "Error creating reply: %s.", strerror(errno));
return -1;
}
len = tmp_len;
if(base64_encode(msg, len, &p) < 0) {
reply(535, "Out of memory base64-encoding.");
return -1;
}
reply(235, "ADAT=%s", p);
sec_complete = 1;
free(p);
return 0;
}
static int
krb4_userok(void *app_data, char *user)
{
struct krb4_data *d = app_data;
return krb_kuserok(d->name, d->instance, d->realm, user);
}
struct sec_server_mech krb4_server_mech = {
"KERBEROS_V4",
sizeof(struct krb4_data),
NULL, /* init */
NULL, /* end */
krb4_check_prot,
krb4_overhead,
krb4_encode,
krb4_decode,
/* */
NULL,
krb4_adat,
NULL, /* pbsz */
NULL, /* ccc */
krb4_userok
};
#else /* FTP_SERVER */
static int
mk_auth(struct krb4_data *d, KTEXT adat,
char *service, char *host, int checksum)
{
int ret;
CREDENTIALS cred;
char sname[SNAME_SZ], inst[INST_SZ], realm[REALM_SZ];
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_mk_req(adat, sname, inst, realm, checksum);
if(ret)
return ret;
strlcpy(sname, service, sizeof(sname));
strlcpy(inst, krb_get_phost(host), sizeof(inst));
strlcpy(realm, krb_realmofhost(host), sizeof(realm));
ret = krb_get_cred(sname, inst, realm, &cred);
memmove(&d->key, &cred.session, sizeof(des_cblock));
des_key_sched(&d->key, d->schedule);
memset(&cred, 0, sizeof(cred));
return ret;
}
static int
krb4_auth(void *app_data, struct connectdata *conn)
{
int ret;
char *p;
int len;
KTEXT_ST adat;
MSG_DAT msg_data;
int checksum;
u_int32_t cs;
struct krb4_data *d = app_data;
struct sockaddr_in *localaddr = (struct sockaddr_in *)LOCAL_ADDR;
struct sockaddr_in *remoteaddr = (struct sockaddr_in *)REMOTE_ADDR;
char *host = conn->hp->h_name;
size_t nread;
int l = sizeof(local_addr);
if(getsockname(conn->data->firstsocket, LOCAL_ADDR, &l) < 0)
perror("getsockname()");
checksum = getpid();
ret = mk_auth(d, &adat, "ftp", host, checksum);
if(ret == KDC_PR_UNKNOWN)
ret = mk_auth(d, &adat, "rcmd", host, checksum);
if(ret){
printf("%s\n", krb_get_err_text(ret));
return AUTH_CONTINUE;
}
#ifdef HAVE_KRB_GET_OUR_IP_FOR_REALM
if (krb_get_config_bool("nat_in_use")) {
struct in_addr natAddr;
if (krb_get_our_ip_for_realm(krb_realmofhost(host),
&natAddr) != KSUCCESS
&& krb_get_our_ip_for_realm(NULL, &natAddr) != KSUCCESS)
printf("Can't get address for realm %s\n",
krb_realmofhost(host));
else {
if (natAddr.s_addr != localaddr->sin_addr.s_addr) {
printf("Using NAT IP address (%s) for kerberos 4\n",
inet_ntoa(natAddr));
localaddr->sin_addr = natAddr;
/*
* This not the best place to do this, but it
* is here we know that (probably) NAT is in
* use!
*/
/*passivemode = 1;***/
/*printf("Setting: Passive mode on.\n");***/
}
}
}
#endif
/*printf("Local address is %s\n", inet_ntoa(localaddr->sin_addr));***/
/*printf("Remote address is %s\n", inet_ntoa(remoteaddr->sin_addr));***/
if(base64_encode(adat.dat, adat.length, &p) < 0) {
printf("Out of memory base64-encoding.\n");
return AUTH_CONTINUE;
}
/*ret = command("ADAT %s", p)*/
ftpsendf(conn->data->firstsocket, conn, "ADAT %s", p);
/* wait for feedback */
nread = GetLastResponse(conn->data->firstsocket,
conn->data->buffer, conn);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
free(p);
if(/*ret != COMPLETE*/conn->data->buffer[0] != '2'){
printf("Server didn't accept auth data.\n");
return AUTH_ERROR;
}
p = strstr(/*reply_string*/conn->data->buffer, "ADAT=");
if(!p){
printf("Remote host didn't send adat reply.\n");
return AUTH_ERROR;
}
p += 5;
len = base64_decode(p, adat.dat);
if(len < 0){
printf("Failed to decode base64 from server.\n");
return AUTH_ERROR;
}
adat.length = len;
ret = krb_rd_safe(adat.dat, adat.length, &d->key,
(struct sockaddr_in *)hisctladdr,
(struct sockaddr_in *)myctladdr, &msg_data);
if(ret){
printf("Error reading reply from server: %s.\n",
krb_get_err_text(ret));
return AUTH_ERROR;
}
krb_get_int(msg_data.app_data, &cs, 4, 0);
if(cs - checksum != 1){
printf("Bad checksum returned from server.\n");
return AUTH_ERROR;
}
return AUTH_OK;
}
struct sec_client_mech krb4_client_mech = {
"KERBEROS_V4",
sizeof(struct krb4_data),
NULL, /* init */
krb4_auth,
NULL, /* end */
krb4_check_prot,
krb4_overhead,
krb4_encode,
krb4_decode
};
#endif /* FTP_SERVER */
void krb_kauth(struct connectdata *conn)
{
int ret;
char buf[1024];
des_cblock key;
des_key_schedule schedule;
KTEXT_ST tkt, tktcopy;
char *name;
char *p;
int overbose;
char passwd[100];
int tmp;
size_t nread;
int save;
save = set_command_prot(conn, prot_private);
/*ret = command("SITE KAUTH %s", name);***/
ftpsendf(conn->data->firstsocket, conn,
"SITE KAUTH %s", conn->data->user);
/* wait for feedback */
nread = GetLastResponse(conn->data->firstsocket, conn->data->buffer, conn);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/;
if(/*ret != CONTINUE*/conn->data->buffer[0] != '3'){
/*verbose = overbose;***/
set_command_prot(conn, save);
/*code = -1;***/
return;
}
/*verbose = overbose;***/
p = strstr(/*reply_string***/conn->data->buffer, "T=");
if(!p){
printf("Bad reply from server.\n");
set_command_prot(conn, save);
/*code = -1;***/
return;
}
p += 2;
tmp = base64_decode(p, &tkt.dat);
if(tmp < 0){
printf("Failed to decode base64 in reply.\n");
set_command_prot(conn, save);
/*code = -1;***/
return;
}
tkt.length = tmp;
tktcopy.length = tkt.length;
p = strstr(/*reply_string***/conn->data->buffer, "P=");
if(!p){
printf("Bad reply from server.\n");
/*verbose = overbose;***/
set_command_prot(conn, save);
/*code = -1;***/
return;
}
name = p + 2;
for(; *p && *p != ' ' && *p != '\r' && *p != '\n'; p++);
*p = 0;
#if 0
snprintf(buf, sizeof(buf), "Password for %s:", name);
if (des_read_pw_string (passwd, sizeof(passwd)-1, buf, 0))
*passwd = '\0';
des_string_to_key (passwd, &key);
#else
des_string_to_key (conn->data->passwd, &key);
#endif
des_key_sched(&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
if (strcmp ((char*)tktcopy.dat + 8,
KRB_TICKET_GRANTING_TICKET) != 0) {
afs_string_to_key (passwd,
krb_realmofhost(/*hostname***/conn->hp->h_name),
&key);
des_key_sched (&key, schedule);
des_pcbc_encrypt((des_cblock*)tkt.dat, (des_cblock*)tktcopy.dat,
tkt.length,
schedule, &key, DES_DECRYPT);
}
memset(key, 0, sizeof(key));
memset(schedule, 0, sizeof(schedule));
memset(passwd, 0, sizeof(passwd));
if(base64_encode(tktcopy.dat, tktcopy.length, &p) < 0) {
failf(conn->data, "Out of memory base64-encoding.\n");
set_command_prot(conn, save);
/*code = -1;***/
return;
}
memset (tktcopy.dat, 0, tktcopy.length);
/*ret = command("SITE KAUTH %s %s", name, p);***/
ftpsendf(conn->data->firstsocket, conn,
"SITE KAUTH %s %s", name, p);
/* wait for feedback */
nread = GetLastResponse(conn->data->firstsocket, conn->data->buffer, conn);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/;
free(p);
set_command_prot(conn, save);
}
#endif /* KRB4 */

37
lib/libcurl.def Normal file
View File

@@ -0,0 +1,37 @@
;
; Definition file for the DLL version of the LIBCURL library from curl
;
LIBRARY LIBCURL
DESCRIPTION 'curl libcurl - http://curl.haxx.se'
EXPORTS
curl_close @ 1 ;
curl_connect @ 2 ;
curl_disconnect @ 3 ;
curl_do @ 4 ;
curl_done @ 5 ;
curl_easy_cleanup @ 6 ;
curl_easy_getinfo @ 7 ;
curl_easy_init @ 8 ;
curl_easy_perform @ 9 ;
curl_easy_setopt @ 10 ;
curl_escape @ 11 ;
curl_formparse @ 12 ;
curl_free @ 13 ;
curl_getdate @ 14 ;
curl_getenv @ 15 ;
curl_init @ 16 ;
curl_open @ 17 ;
curl_read @ 18 ;
curl_setopt @ 19 ;
curl_slist_append @ 20 ;
curl_slist_free_all @ 21 ;
curl_transfer @ 22 ;
curl_unescape @ 23 ;
curl_version @ 24 ;
curl_write @ 25 ;
maprintf @ 26 ;
strequal @ 27 ;
strnequal @ 28 ;

98
lib/memdebug.c Normal file
View File

@@ -0,0 +1,98 @@
#ifdef MALLOCDEBUG
/*****************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Curl.
*
* The Initial Developer of the Original Code is Daniel Stenberg.
*
* Portions created by the Initial Developer are Copyright (C) 1999.
* All Rights Reserved.
*
* ------------------------------------------------------------
* Main author:
* - Daniel Stenberg <daniel@haxx.se>
*
* http://curl.haxx.se
*
* $Source$
* $Revision$
* $Date$
* $Author$
* $State$
* $Locker$
*
* ------------------------------------------------------------
****************************************************************************/
#include "setup.h"
#include <curl/curl.h>
#include "urldata.h"
#include <stdio.h>
#include <string.h>
/*
* Note that these debug functions are very simple and they are meant to
* remain so. For advanced analysis, record a log file and write perl scripts
* to analyze them!
*
* Don't use these with multithreaded test programs!
*/
FILE *logfile=stderr;
/* this sets the log file name */
void curl_memdebug(char *logname)
{
logfile = fopen(logname, "w");
}
void *curl_domalloc(size_t size, int line, char *source)
{
void *mem=(malloc)(size);
fprintf(logfile, "MEM %s:%d malloc(%d) = %p\n",
source, line, size, mem);
return mem;
}
char *curl_dostrdup(char *str, int line, char *source)
{
char *mem=(strdup)(str);
size_t len=strlen(str)+1;
fprintf(logfile, "MEM %s:%d strdup(%p) (%d) = %p\n",
source, line, str, len, mem);
return mem;
}
void *curl_dorealloc(void *ptr, size_t size, int line, char *source)
{
void *mem=(realloc)(ptr, size);
fprintf(logfile, "MEM %s:%d realloc(%p, %d) = %p\n",
source, line, ptr, size, mem);
return mem;
}
void curl_dofree(void *ptr, int line, char *source)
{
(free)(ptr);
fprintf(logfile, "MEM %s:%d free(%p)\n",
source, line, ptr);
}
#endif /* MALLOCDEBUG */

13
lib/memdebug.h Normal file
View File

@@ -0,0 +1,13 @@
#ifdef MALLOCDEBUG
void *curl_domalloc(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);
char *curl_dostrdup(char *str, int line, char *source);
void curl_memdebug(char *logname);
/* Set this symbol on the command-line, recompile all lib-sources */
#define strdup(ptr) curl_dostrdup(ptr, __LINE__, __FILE__)
#define malloc(size) curl_domalloc(size, __LINE__, __FILE__)
#define realloc(ptr,size) curl_dorealloc(ptr, size, __LINE__, __FILE__)
#define free(ptr) curl_dofree(ptr, __LINE__, __FILE__)
#endif

View File

@@ -98,6 +98,10 @@ static const char rcsid[] = "@(#)$Id$";
#include <ctype.h>
#include <string.h>
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#define BUFFSIZE 256 /* buffer for long-to-str and float-to-str calcs */
#define MAX_PARAMETERS 128 /* lame static limit */

View File

@@ -183,7 +183,7 @@ int pgrsUpdate(struct UrlData *data)
struct timeval now;
int result;
char max5[6][6];
char max5[6][10];
double dlpercen=0;
double ulpercen=0;
double total_percen=0;
@@ -191,12 +191,7 @@ int pgrsUpdate(struct UrlData *data)
double total_transfer;
double total_expected_transfer;
#define CURR_TIME 5
static double speeder[ CURR_TIME ];
static int speeder_c=0;
int nowindex = speeder_c% CURR_TIME;
int nowindex = data->progress.speeder_c% CURR_TIME;
int checkindex;
int count;
@@ -241,15 +236,19 @@ int pgrsUpdate(struct UrlData *data)
/* Let's do the "current speed" thing, which should use the fastest
of the dl/ul speeds */
speeder[ nowindex ] = data->progress.downloaded>data->progress.uploaded?
data->progress.speeder[ nowindex ] =
data->progress.downloaded>data->progress.uploaded?
data->progress.downloaded:data->progress.uploaded;
speeder_c++; /* increase */
count = ((speeder_c>=CURR_TIME)?CURR_TIME:speeder_c) - 1;
checkindex = (speeder_c>=CURR_TIME)?speeder_c%CURR_TIME:0;
data->progress.speeder_c++; /* increase */
count = ((data->progress.speeder_c>=CURR_TIME)?
CURR_TIME:data->progress.speeder_c) - 1;
checkindex = (data->progress.speeder_c>=CURR_TIME)?
data->progress.speeder_c%CURR_TIME:0;
/* find out the average speed the last CURR_TIME seconds */
data->progress.current_speed =
(speeder[nowindex]-speeder[checkindex])/(count?count:1);
(data->progress.speeder[nowindex]-
data->progress.speeder[checkindex])/(count?count:1);
if(data->progress.flags & PGRS_HIDE)
return 0;
@@ -284,6 +283,7 @@ int pgrsUpdate(struct UrlData *data)
total estimate! */
total_estimate = ulestimate>dlestimate?ulestimate:dlestimate;
/* If we have a total estimate, we can display that and the expected
time left */
if(total_estimate) {
@@ -329,5 +329,5 @@ int pgrsUpdate(struct UrlData *data)
max5data(data->progress.current_speed, max5[5]) /* current speed */
);
return 0;
return 0;
}

659
lib/security.c Normal file
View File

@@ -0,0 +1,659 @@
/* modified by Martin Hedenfalk <mhe@stacken.kth.se> for use in Curl
* last modified 2000-09-18
* Even more obscurified to merge better into libcurl by Daniel Stenberg.
*/
/*
* Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "setup.h"
#ifdef KRB4
#include <curl/mprintf.h>
#include "security.h"
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include "base64.h"
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
#define min(a, b) ((a) < (b) ? (a) : (b))
static struct {
enum protection_level level;
const char *name;
} level_names[] = {
{ prot_clear, "clear" },
{ prot_safe, "safe" },
{ prot_confidential, "confidential" },
{ prot_private, "private" }
};
static const char *
level_to_name(enum protection_level level)
{
int i;
for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
if(level_names[i].level == level)
return level_names[i].name;
return "unknown";
}
#ifndef FTP_SERVER /* not used in server */
static enum protection_level
name_to_level(const char *name)
{
int i;
for(i = 0; i < sizeof(level_names) / sizeof(level_names[0]); i++)
if(!strncasecmp(level_names[i].name, name, strlen(name)))
return level_names[i].level;
return (enum protection_level)-1;
}
#endif
#ifdef FTP_SERVER
static struct sec_server_mech *mechs[] = {
#ifdef KRB5
&gss_server_mech,
#endif
#ifdef KRB4
&krb4_server_mech,
#endif
NULL
};
static struct sec_server_mech *mech;
#else
static struct sec_client_mech *mechs[] = {
#ifdef KRB5
&gss_client_mech,
#endif
#ifdef KRB4
&krb4_client_mech,
#endif
NULL
};
static struct sec_client_mech *mech;
#endif
int
sec_getc(struct connectdata *conn, FILE *F)
{
if(conn->sec_complete && conn->data_prot) {
char c;
if(sec_read(conn, fileno(F), &c, 1) <= 0)
return EOF;
return c;
} else
return getc(F);
}
static int
block_read(int fd, void *buf, size_t len)
{
unsigned char *p = buf;
int b;
while(len) {
b = read(fd, p, len);
if (b == 0)
return 0;
else if (b < 0)
return -1;
len -= b;
p += b;
}
return p - (unsigned char*)buf;
}
static int
block_write(int fd, void *buf, size_t len)
{
unsigned char *p = buf;
int b;
while(len) {
b = write(fd, p, len);
if(b < 0)
return -1;
len -= b;
p += b;
}
return p - (unsigned char*)buf;
}
static int
sec_get_data(struct connectdata *conn,
int fd, struct krb4buffer *buf, int level)
{
int len;
int b;
b = block_read(fd, &len, sizeof(len));
if (b == 0)
return 0;
else if (b < 0)
return -1;
len = ntohl(len);
buf->data = realloc(buf->data, len);
b = block_read(fd, buf->data, len);
if (b == 0)
return 0;
else if (b < 0)
return -1;
buf->size = (*mech->decode)(conn->app_data, buf->data, len,
conn->data_prot, conn);
buf->index = 0;
return 0;
}
static size_t
buffer_read(struct krb4buffer *buf, void *data, size_t len)
{
len = min(len, buf->size - buf->index);
memcpy(data, (char*)buf->data + buf->index, len);
buf->index += len;
return len;
}
static size_t
buffer_write(struct krb4buffer *buf, void *data, size_t len)
{
if(buf->index + len > buf->size) {
void *tmp;
if(buf->data == NULL)
tmp = malloc(1024);
else
tmp = realloc(buf->data, buf->index + len);
if(tmp == NULL)
return -1;
buf->data = tmp;
buf->size = buf->index + len;
}
memcpy((char*)buf->data + buf->index, data, len);
buf->index += len;
return len;
}
int
sec_read(struct connectdata *conn, int fd, void *buffer, int length)
{
size_t len;
int rx = 0;
if(conn->sec_complete == 0 || conn->data_prot == 0)
return read(fd, buffer, length);
if(conn->in_buffer.eof_flag){
conn->in_buffer.eof_flag = 0;
return 0;
}
len = buffer_read(&conn->in_buffer, buffer, length);
length -= len;
rx += len;
buffer = (char*)buffer + len;
while(length) {
if(sec_get_data(conn, fd, &conn->in_buffer, conn->data_prot) < 0)
return -1;
if(conn->in_buffer.size == 0) {
if(rx)
conn->in_buffer.eof_flag = 1;
return rx;
}
len = buffer_read(&conn->in_buffer, buffer, length);
length -= len;
rx += len;
buffer = (char*)buffer + len;
}
return rx;
}
static int
sec_send(struct connectdata *conn, int fd, char *from, int length)
{
int bytes;
void *buf;
bytes = (*mech->encode)(conn->app_data, from, length, conn->data_prot, &buf, conn);
bytes = htonl(bytes);
block_write(fd, &bytes, sizeof(bytes));
block_write(fd, buf, ntohl(bytes));
free(buf);
return length;
}
int
sec_fflush(struct connectdata *conn, FILE *F)
{
if(conn->data_prot != prot_clear) {
if(conn->out_buffer.index > 0){
sec_write(conn, fileno(F),
conn->out_buffer.data, conn->out_buffer.index);
conn->out_buffer.index = 0;
}
sec_send(conn, fileno(F), NULL, 0);
}
fflush(F);
return 0;
}
int
sec_fflush_fd(struct connectdata *conn, int fd)
{
if(conn->data_prot != prot_clear) {
if(conn->out_buffer.index > 0){
sec_write(conn, fd,
conn->out_buffer.data, conn->out_buffer.index);
conn->out_buffer.index = 0;
}
sec_send(conn, fd, NULL, 0);
}
return 0;
}
int
sec_write(struct connectdata *conn, int fd, char *buffer, int length)
{
int len = conn->buffer_size;
int tx = 0;
if(conn->data_prot == prot_clear)
return write(fd, buffer, length);
len -= (*mech->overhead)(conn->app_data, conn->data_prot, len);
while(length){
if(length < len)
len = length;
sec_send(conn, fd, buffer, len);
length -= len;
buffer += len;
tx += len;
}
return tx;
}
int
sec_vfprintf2(struct connectdata *conn, FILE *f, const char *fmt, va_list ap)
{
char *buf;
int ret;
if(conn->data_prot == prot_clear)
return vfprintf(f, fmt, ap);
else {
buf = maprintf(fmt, ap);
ret = buffer_write(&conn->out_buffer, buf, strlen(buf));
free(buf);
return ret;
}
}
int
sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = sec_vfprintf2(conn, f, fmt, ap);
va_end(ap);
return ret;
}
int
sec_putc(struct connectdata *conn, int c, FILE *F)
{
char ch = c;
if(conn->data_prot == prot_clear)
return putc(c, F);
buffer_write(&conn->out_buffer, &ch, 1);
if(c == '\n' || conn->out_buffer.index >= 1024 /* XXX */) {
sec_write(conn, fileno(F), conn->out_buffer.data, conn->out_buffer.index);
conn->out_buffer.index = 0;
}
return c;
}
int
sec_read_msg(struct connectdata *conn, char *s, int level)
{
int len;
char *buf;
int code;
buf = malloc(strlen(s));
len = base64_decode(s + 4, buf); /* XXX */
len = (*mech->decode)(conn->app_data, buf, len, level, conn);
if(len < 0)
return -1;
buf[len] = '\0';
if(buf[3] == '-')
code = 0;
else
sscanf(buf, "%d", &code);
if(buf[len-1] == '\n')
buf[len-1] = '\0';
strcpy(s, buf);
free(buf);
return code;
}
/* modified to return how many bytes written, or -1 on error ***/
int
sec_vfprintf(struct connectdata *conn, FILE *f, const char *fmt, va_list ap)
{
int ret = 0;
char *buf;
void *enc;
int len;
if(!conn->sec_complete)
return vfprintf(f, fmt, ap);
buf = maprintf(fmt, ap);
len = (*mech->encode)(conn->app_data, buf, strlen(buf),
conn->command_prot, &enc,
conn);
free(buf);
if(len < 0) {
failf(conn->data, "Failed to encode command.\n");
return -1;
}
if(base64_encode(enc, len, &buf) < 0){
failf(conn->data, "Out of memory base64-encoding.\n");
return -1;
}
#ifdef FTP_SERVER
if(command_prot == prot_safe)
fprintf(f, "631 %s\r\n", buf);
else if(command_prot == prot_private)
fprintf(f, "632 %s\r\n", buf);
else if(command_prot == prot_confidential)
fprintf(f, "633 %s\r\n", buf);
#else
if(conn->command_prot == prot_safe)
ret = fprintf(f, "MIC %s", buf);
else if(conn->command_prot == prot_private)
ret = fprintf(f, "ENC %s", buf);
else if(conn->command_prot == prot_confidential)
ret = fprintf(f, "CONF %s", buf);
#endif
free(buf);
return ret;
}
int
sec_fprintf(struct connectdata *conn, FILE *f, const char *fmt, ...)
{
va_list ap;
int ret;
va_start(ap, fmt);
ret = sec_vfprintf(conn, f, fmt, ap);
va_end(ap);
return ret;
}
/* end common stuff */
#ifdef FTP_SERVER
/* snip */
#else /* FTP_SERVER */
#if 0
void
sec_status(void)
{
if(conn->sec_complete){
printf("Using %s for authentication.\n", mech->name);
printf("Using %s command channel.\n", level_to_name(command_prot));
printf("Using %s data channel.\n", level_to_name(data_prot));
if(buffer_size > 0)
printf("Protection buffer size: %lu.\n",
(unsigned long)buffer_size);
}else{
printf("Not using any security mechanism.\n");
}
}
#endif
static int
sec_prot_internal(struct connectdata *conn, int level)
{
int ret;
char *p;
unsigned int s = 1048576;
size_t nread;
if(!conn->sec_complete){
infof(conn->data, "No security data exchange has taken place.\n");
return -1;
}
if(level){
ftpsendf(conn->data->firstsocket, conn,
"PBSZ %u", s);
/* wait for feedback */
nread = GetLastResponse(conn->data->firstsocket,
conn->data->buffer, conn);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
if(/*ret != COMPLETE*/conn->data->buffer[0] != '2'){
failf(conn->data, "Failed to set protection buffer size.\n");
return -1;
}
conn->buffer_size = s;
p = strstr(/*reply_string*/conn->data->buffer, "PBSZ=");
if(p)
sscanf(p, "PBSZ=%u", &s);
if(s < conn->buffer_size)
conn->buffer_size = s;
}
ftpsendf(conn->data->firstsocket, conn,
"PROT %c", level["CSEP"]);
/* wait for feedback */
nread = GetLastResponse(conn->data->firstsocket,
conn->data->buffer, conn);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
if(/*ret != COMPLETE*/conn->data->buffer[0] != '2'){
failf(conn->data, "Failed to set protection level.\n");
return -1;
}
conn->data_prot = (enum protection_level)level;
return 0;
}
enum protection_level
set_command_prot(struct connectdata *conn, enum protection_level level)
{
enum protection_level old = conn->command_prot;
conn->command_prot = level;
return old;
}
#if 0
void
sec_prot(int argc, char **argv)
{
int level = -1;
if(argc < 2 || argc > 3)
goto usage;
if(!sec_complete) {
printf("No security data exchange has taken place.\n");
code = -1;
return;
}
level = name_to_level(argv[argc - 1]);
if(level == -1)
goto usage;
if((*mech->check_prot)(conn->app_data, level)) {
printf("%s does not implement %s protection.\n",
mech->name, level_to_name(level));
code = -1;
return;
}
if(argc == 2 || strncasecmp(argv[1], "data", strlen(argv[1])) == 0) {
if(sec_prot_internal(level) < 0){
code = -1;
return;
}
} else if(strncasecmp(argv[1], "command", strlen(argv[1])) == 0)
set_command_prot(level);
else
goto usage;
code = 0;
return;
usage:
printf("usage: %s [command|data] [clear|safe|confidential|private]\n",
argv[0]);
code = -1;
}
#endif
void
sec_set_protection_level(struct connectdata *conn)
{
if(conn->sec_complete && conn->data_prot != conn->request_data_prot)
sec_prot_internal(conn, conn->request_data_prot);
}
int
sec_request_prot(struct connectdata *conn, char *level)
{
int l = name_to_level(level);
if(l == -1)
return -1;
conn->request_data_prot = (enum protection_level)l;
return 0;
}
int
sec_login(struct connectdata *conn)
{
int ret;
struct sec_client_mech **m;
size_t nread;
struct UrlData *data=conn->data;
for(m = mechs; *m && (*m)->name; m++) {
void *tmp;
tmp = realloc(conn->app_data, (*m)->size);
if (tmp == NULL) {
failf (data, "realloc %u failed", (*m)->size);
return -1;
}
conn->app_data = tmp;
if((*m)->init && (*(*m)->init)(conn->app_data) != 0) {
infof(data, "Skipping %s...\n", (*m)->name);
continue;
}
infof(data, "Trying %s...\n", (*m)->name);
/*ret = command("AUTH %s", (*m)->name);***/
ftpsendf(conn->data->firstsocket, conn,
"AUTH %s", (*m)->name);
/* wait for feedback */
nread = GetLastResponse(conn->data->firstsocket,
conn->data->buffer, conn);
if(nread < 0)
return /*CURLE_OPERATION_TIMEOUTED*/-1;
if(/*ret != CONTINUE*/conn->data->buffer[0] != '3'){
if(/*code == 504*/strncmp(conn->data->buffer,"504",3) == 0) {
infof(data,
"%s is not supported by the server.\n", (*m)->name);
}
else if(/*code == 534*/strncmp(conn->data->buffer,"534",3) == 0) {
infof(data, "%s rejected as security mechanism.\n", (*m)->name);
}
else if(/*ret == ERROR*/conn->data->buffer[0] == '5') {
infof(data, "The server doesn't support the FTP "
"security extensions.\n");
return -1;
}
continue;
}
ret = (*(*m)->auth)(conn->app_data, /*host***/conn);
if(ret == AUTH_CONTINUE)
continue;
else if(ret != AUTH_OK){
/* mechanism is supposed to output error string */
return -1;
}
mech = *m;
conn->sec_complete = 1;
conn->command_prot = prot_safe;
break;
}
return *m == NULL;
}
void
sec_end(struct connectdata *conn)
{
if (mech != NULL) {
if(mech->end)
(*mech->end)(conn->app_data);
memset(conn->app_data, 0, mech->size);
free(conn->app_data);
conn->app_data = NULL;
}
conn->sec_complete = 0;
conn->data_prot = (enum protection_level)0;
}
#endif /* FTP_SERVER */
#endif /* KRB4 */

134
lib/security.h Normal file
View File

@@ -0,0 +1,134 @@
/* modified by Martin Hedenfalk <mhe@stacken.kth.se> for use in Curl
* last modified 2000-09-18
*/
/*
* Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/* $Id$ */
#ifndef __security_h__
#define __security_h__
#include <stdarg.h>
#include "urldata.h" /* for struct connectdata * */
struct sec_client_mech {
char *name;
size_t size;
int (*init)(void *);
int (*auth)(void *, struct connectdata *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
int (*encode)(void *, void*, int, int, void**, struct connectdata *);
int (*decode)(void *, void*, int, int, struct connectdata *);
};
struct sec_server_mech {
char *name;
size_t size;
int (*init)(void *);
void (*end)(void *);
int (*check_prot)(void *, int);
int (*overhead)(void *, int, int);
int (*encode)(void *, void*, int, int, void**);
int (*decode)(void *, void*, int, int);
int (*auth)(void *);
int (*adat)(void *, void*, size_t);
size_t (*pbsz)(void *, size_t);
int (*ccc)(void*);
int (*userok)(void*, char*);
};
#define AUTH_OK 0
#define AUTH_CONTINUE 1
#define AUTH_ERROR 2
#ifdef FTP_SERVER
extern struct sec_server_mech krb4_server_mech, gss_server_mech;
#else
extern struct sec_client_mech krb4_client_mech, gss_client_mech;
#endif
extern int sec_complete;
#ifdef FTP_SERVER
extern char *ftp_command;
void new_ftp_command(char*);
void delete_ftp_command(void);
#endif
/* ---- */
int sec_fflush (struct connectdata *conn, FILE *);
int sec_fflush_fd(struct connectdata *conn, int fd);
int sec_fprintf (struct connectdata *, FILE *, const char *, ...);
int sec_getc (struct connectdata *conn, FILE *);
int sec_putc (struct connectdata *conn, int, FILE *);
int sec_read (struct connectdata *conn, int, void *, int);
int sec_read_msg (struct connectdata *conn, char *, int);
int sec_vfprintf(struct connectdata *, FILE *, const char *, va_list);
int sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
int sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list);
int sec_write (struct connectdata *conn, int, char *, int);
#ifdef FTP_SERVER
void adat (char *);
void auth (char *);
void ccc (void);
void mec (char *, enum protection_level);
void pbsz (int);
void prot (char *);
void delete_ftp_command (void);
void new_ftp_command (char *);
int sec_userok (char *);
int secure_command (void);
enum protection_level get_command_prot(void);
#else
void sec_end (struct connectdata *);
int sec_login (struct connectdata *);
void sec_prot (int, char **);
int sec_request_prot (struct connectdata *conn, char *);
void sec_set_protection_level(struct connectdata *conn);
void sec_status (void);
enum protection_level set_command_prot(struct connectdata *,
enum protection_level);
#endif
#endif /* __security_h__ */

View File

@@ -53,9 +53,20 @@
#include <curl/curl.h>
#include "urldata.h"
#include "sendf.h"
#define _MPRINTF_REPLACE /* use the internal *printf() functions */
#include <curl/mprintf.h>
#ifdef KRB4
#include "security.h"
#include <string.h>
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* infof() is for info message along the way */
void infof(struct UrlData *data, char *fmt, ...)
@@ -77,14 +88,14 @@ void failf(struct UrlData *data, char *fmt, ...)
va_list ap;
va_start(ap, fmt);
if(data->errorbuffer)
vsprintf(data->errorbuffer, fmt, ap);
vsnprintf(data->errorbuffer, CURL_ERROR_SIZE, fmt, ap);
else /* no errorbuffer receives this, write to data->err instead */
vfprintf(data->err, fmt, ap);
va_end(ap);
}
/* sendf() sends the formated data to the server */
int sendf(int fd, struct UrlData *data, char *fmt, ...)
size_t sendf(int fd, struct UrlData *data, char *fmt, ...)
{
size_t bytes_written;
char *s;
@@ -96,9 +107,10 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
return 0; /* failure */
if(data->bits.verbose)
fprintf(data->err, "> %s", s);
#ifndef USE_SSLEAY
bytes_written = swrite(fd, s, strlen(s));
#else
bytes_written = swrite(fd, s, strlen(s));
#else /* USE_SSLEAY */
if (data->use_ssl) {
bytes_written = SSL_write(data->ssl, s, strlen(s));
} else {
@@ -109,25 +121,150 @@ int sendf(int fd, struct UrlData *data, char *fmt, ...)
return(bytes_written);
}
/* ssend() sends plain (binary) data to the server */
size_t ssend(int fd, struct UrlData *data, void *mem, size_t len)
/*
* ftpsendf() sends the formated string as a ftp command to a ftp server
*/
size_t ftpsendf(int fd, struct connectdata *conn, char *fmt, ...)
{
size_t bytes_written;
char *s;
va_list ap;
va_start(ap, fmt);
s = mvaprintf(fmt, ap);
va_end(ap);
if(!s)
return 0; /* failure */
if(conn->data->bits.verbose)
fprintf(conn->data->err, "> %s\n", s);
if(data->bits.verbose)
fprintf(data->err, "> [binary output]\n");
#ifndef USE_SSLEAY
bytes_written = swrite(fd, mem, len);
#else
if (data->use_ssl) {
bytes_written = SSL_write(data->ssl, mem, len);
} else {
bytes_written = swrite(fd, mem, len);
#ifdef KRB4
if(conn->sec_complete && conn->data->cmdchannel) {
bytes_written = sec_fprintf(conn, conn->data->cmdchannel, s);
bytes_written += fprintf(conn->data->cmdchannel, "\r\n");
fflush(conn->data->cmdchannel);
}
#endif /* USE_SSLEAY */
return bytes_written;
else
#endif /* KRB4 */
{
bytes_written = swrite(fd, s, strlen(s));
bytes_written += swrite(fd, "\r\n", 2);
}
free(s); /* free the output string */
return(bytes_written);
}
/* ssend() sends plain (binary) data to the server */
size_t ssend(int fd, struct connectdata *conn, void *mem, size_t len)
{
size_t bytes_written;
struct UrlData *data=conn->data; /* conn knows data, not vice versa */
#ifdef USE_SSLEAY
if (data->use_ssl) {
bytes_written = SSL_write(data->ssl, mem, len);
}
else {
#endif
#ifdef KRB4
if(conn->sec_complete) {
bytes_written = sec_write(conn, fd, mem, len);
}
else
#endif /* KRB4 */
bytes_written = swrite(fd, mem, len);
#ifdef USE_SSLEAY
}
#endif
return bytes_written;
}
/*
* add_buffer_init() returns a fine buffer struct
*/
send_buffer *add_buffer_init(void)
{
send_buffer *blonk;
blonk=(send_buffer *)malloc(sizeof(send_buffer));
if(blonk) {
memset(blonk, 0, sizeof(send_buffer));
return blonk;
}
return NULL; /* failed, go home */
}
/*
* add_buffer_send() sends a buffer and frees all associated memory.
*/
size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in)
{
size_t amount;
if(conn->data->bits.verbose) {
fputs("> ", conn->data->err);
/* this data _may_ contain binary stuff */
fwrite(in->buffer, in->size_used, 1, conn->data->err);
}
amount = ssend(sockfd, conn, in->buffer, in->size_used);
if(in->buffer)
free(in->buffer);
free(in);
return amount;
}
/*
* add_bufferf() builds a buffer from the formatted input
*/
CURLcode add_bufferf(send_buffer *in, char *fmt, ...)
{
CURLcode result = CURLE_OUT_OF_MEMORY;
char *s;
va_list ap;
va_start(ap, fmt);
s = mvaprintf(fmt, ap); /* this allocs a new string to append */
va_end(ap);
if(s) {
result = add_buffer(in, s, strlen(s));
free(s);
}
return result;
}
/*
* add_buffer() appends a memory chunk to the existing one
*/
CURLcode add_buffer(send_buffer *in, void *inptr, size_t size)
{
char *new_rb;
int new_size;
if(size > 0) {
if(!in->buffer ||
((in->size_used + size) > (in->size_max - 1))) {
new_size = (in->size_used+size)*2;
if(in->buffer)
/* we have a buffer, enlarge the existing one */
new_rb = (char *)realloc(in->buffer, new_size);
else
/* create a new buffer */
new_rb = (char *)malloc(new_size);
if(!new_rb)
return CURLE_OUT_OF_MEMORY;
in->buffer = new_rb;
in->size_max = new_size;
}
memcpy(&in->buffer[in->size_used], inptr, size);
in->size_used += size;
}
return CURLE_OK;
}

View File

@@ -40,9 +40,24 @@
* ------------------------------------------------------------
****************************************************************************/
size_t ftpsendf(int fd, struct connectdata *, char *fmt, ...);
size_t sendf(int fd, struct UrlData *, char *fmt, ...);
size_t ssend(int fd, struct UrlData *, void *fmt, size_t len);
size_t ssend(int fd, struct connectdata *, void *fmt, size_t len);
void infof(struct UrlData *, char *fmt, ...);
void failf(struct UrlData *, char *fmt, ...);
struct send_buffer {
char *buffer;
long size_max;
long size_used;
};
typedef struct send_buffer send_buffer;
send_buffer *add_buffer_init(void);
CURLcode add_buffer(send_buffer *in, void *inptr, size_t size);
CURLcode add_bufferf(send_buffer *in, char *fmt, ...);
size_t add_buffer_send(int sockfd, struct connectdata *conn, send_buffer *in);
#endif

View File

@@ -57,6 +57,10 @@
#endif
#endif
#ifndef __cplusplus /* (rabe) */
typedef char bool;
#endif /* (rabe) */
#include <stdio.h>
#ifndef OS
#ifdef WIN32

View File

@@ -265,28 +265,25 @@ UrgSSLConnect (struct UrlData *data)
failf(data, "SSL: couldn't get X509-subject!");
return 4;
}
infof (data, "\t subject: %s\n", str);
Free (str);
infof(data, "\t subject: %s\n", str);
CRYPTO_free(str);
str = X509_NAME_oneline (X509_get_issuer_name (data->server_cert), NULL, 0);
if(!str) {
failf(data, "SSL: couldn't get X509-issuer name!");
return 5;
}
infof (data, "\t issuer: %s\n", str);
Free (str);
infof(data, "\t issuer: %s\n", str);
CRYPTO_free(str);
/* We could do all sorts of certificate verification stuff here before
deallocating the certificate. */
#if SSL_VERIFY_CERT
infof(data, "Verify result: %d\n", SSL_get_verify_result(data->ssl));
#endif
X509_free (data->server_cert);
X509_free(data->server_cert);
#else /* USE_SSLEAY */
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void) data;

271
lib/url.c
View File

@@ -52,7 +52,6 @@
#include <errno.h>
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
#include <winsock.h>
#include <time.h>
@@ -110,7 +109,6 @@
#include "progress.h"
#include "cookie.h"
#include "strequal.h"
#include "writeout.h"
/* And now for the protocols */
#include "ftp.h"
@@ -125,6 +123,14 @@
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#ifdef KRB4
#include "security.h"
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
#include "memdebug.h"
#endif
/* -- -- */
@@ -180,6 +186,11 @@ void static urlfree(struct UrlData *data, bool totally)
switch off that knowledge again... */
data->bits.httpproxy=FALSE;
}
if(data->bits.rangestringalloc) {
free(data->range);
data->range=NULL;
}
if(data->ptr_proxyuserpwd) {
free(data->ptr_proxyuserpwd);
@@ -224,6 +235,10 @@ void static urlfree(struct UrlData *data, bool totally)
if(data->free_referer)
free(data->referer);
if(data->bits.urlstringalloc)
/* the URL is allocated, free it! */
free(data->url);
cookie_cleanup(data->cookies);
free(data);
@@ -437,6 +452,9 @@ CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
data->proxy = va_arg(param, char *);
data->bits.httpproxy = data->proxy?1:0;
break;
case CURLOPT_HTTPPROXYTUNNEL:
data->bits.tunnel_thru_httpproxy = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_PROXYPORT:
data->proxyport = va_arg(param, long);
break;
@@ -477,9 +495,11 @@ CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
case CURLOPT_WRITEFUNCTION:
data->fwrite = va_arg(param, curl_write_callback);
break;
#if 0
case CURLOPT_WRITEINFO:
data->writeinfo = va_arg(param, char *);
break;
#endif
case CURLOPT_READFUNCTION:
data->fread = va_arg(param, curl_read_callback);
break;
@@ -495,6 +515,13 @@ CURLcode curl_setopt(CURL *curl, CURLoption option, ...)
case CURLOPT_QUOTE:
data->quote = va_arg(param, struct curl_slist *);
break;
case CURLOPT_INTERFACE:
data->device = va_arg(param, char *);
break;
case CURLOPT_KRB4LEVEL:
data->krb4_level = va_arg(param, char *);
data->bits.krb4=data->krb4_level?TRUE:FALSE;
break;
default:
/* unknown tag and its companion, just ignore: */
return CURLE_READ_ERROR; /* correct this */
@@ -571,7 +598,12 @@ CURLcode curl_write(CURLconnect *c_conn, char *buf, size_t amount,
}
else {
#endif
bytes_written = swrite(conn->writesockfd, buf, amount);
#ifdef KRB4
if(conn->sec_complete)
bytes_written = sec_write(conn, conn->writesockfd, buf, amount);
else
#endif
bytes_written = swrite(conn->writesockfd, buf, amount);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
@@ -597,7 +629,12 @@ CURLcode curl_read(CURLconnect *c_conn, char *buf, size_t buffersize,
}
else {
#endif
nread = sread (conn->sockfd, buf, buffersize);
#ifdef KRB4
if(conn->sec_complete)
nread = sec_read(conn, conn->sockfd, buf, buffersize);
else
#endif
nread = sread (conn->sockfd, buf, buffersize);
#ifdef USE_SSLEAY
}
#endif /* USE_SSLEAY */
@@ -611,6 +648,9 @@ CURLcode curl_disconnect(CURLconnect *c_connect)
struct UrlData *data = conn->data;
if(conn->hostent_buf) /* host name info */
free(conn->hostent_buf);
free(conn); /* free the connection oriented data */
/* clean up the sockets and SSL stuff from the previous "round" */
@@ -619,6 +659,7 @@ CURLcode curl_disconnect(CURLconnect *c_connect)
return CURLE_OK;
}
/*
* NAME curl_connect()
*
@@ -646,12 +687,6 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
struct UrlData *data = curl;
struct connectdata *conn;
/* I believe the longest possible name in a DNS is set to 255 letters, FQDN.
Although the buffer required for storing all possible aliases and IP
numbers is according to Stevens' Unix Network Programming 2nd editor,
p. 304: 8192 bytes. Let's go with that! */
char hostent_buf[8192];
if(!data || (data->handle != STRUCT_OPEN))
return CURLE_BAD_FUNCTION_ARGUMENT; /* TBD: make error codes */
@@ -671,6 +706,9 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
conn->data = data; /* remember our daddy */
conn->state = CONN_INIT;
conn->upload_bufsize = UPLOAD_BUFSIZE; /* the smallest upload buffer size
we use */
buf = data->buffer; /* this is our buffer */
#if 0
@@ -879,8 +917,9 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
if(data->resume_from) {
if(!data->bits.set_range) {
/* if it already was in use, we just skip this */
sprintf(resumerange, "%d-", data->resume_from);
data->range=resumerange; /* tell ourselves to fetch this range */
snprintf(resumerange, sizeof(resumerange), "%d-", data->resume_from);
data->range=strdup(resumerange); /* tell ourselves to fetch this range */
data->bits.rangestringalloc = TRUE; /* mark as allocated */
data->bits.set_range = 1; /* switch on range usage */
}
}
@@ -948,7 +987,10 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
data->remote_port = PORT_FTP;
conn->protocol |= PROT_FTP;
if(data->bits.httpproxy) {
if(data->bits.httpproxy &&
!data->bits.tunnel_thru_httpproxy) {
/* Unless we have asked to tunnel ftp operations through the proxy, we
switch and use HTTP operations only */
conn->curl_do = http;
conn->curl_done = http_done;
conn->curl_close = http_close;
@@ -1018,6 +1060,11 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
conn->curl_do = file;
/* no done() function */
result = Transfer(conn, -1, -1, FALSE, NULL, /* no download */
-1, NULL); /* no upload */
return CURLE_OK;
}
else {
@@ -1092,7 +1139,8 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
}
/* Connect to target host right on */
if(!(conn->hp = GetHost(data, conn->name, hostent_buf, sizeof(hostent_buf)))) {
conn->hp = GetHost(data, conn->name, &conn->hostent_buf);
if(!conn->hp) {
failf(data, "Couldn't resolv host '%s'", conn->name);
return CURLE_COULDNT_RESOLVE_HOST;
}
@@ -1147,7 +1195,8 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
}
/* connect to proxy */
if(!(conn->hp = GetHost(data, proxyptr, hostent_buf, sizeof(hostent_buf)))) {
conn->hp = GetHost(data, proxyptr, &conn->hostent_buf);
if(!conn->hp) {
failf(data, "Couldn't resolv proxy '%s'", proxyptr);
return CURLE_COULDNT_RESOLVE_PROXY;
}
@@ -1164,6 +1213,144 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
conn->serv_addr.sin_family = conn->hp->h_addrtype;
conn->serv_addr.sin_port = htons(data->port);
#ifndef WIN32
/* We don't generally like checking for OS-versions, we should make this
HAVE_XXXX based, although at the moment I don't have a decent test for
this! */
/* sck 8/31/2000 add support for specifing device to bind socket to */
/* I am using this, but it may not work everywhere, only tested on
RedHat 6.2 */
#ifdef HAVE_INET_NTOA
#ifndef INADDR_NONE
#define INADDR_NONE (unsigned long) ~0
#endif
if (data->device && (strlen(data->device)<255)) {
struct ifreq ifr;
struct sockaddr_in sa;
struct hostent *h=NULL;
char *hostdataptr;
size_t size;
unsigned short porttouse;
char myhost[256] = "";
unsigned long in;
if(if2ip(data->device, myhost, sizeof(myhost))) {
h = GetHost(data, myhost, &hostdataptr);
}
else {
if(strlen(data->device)>1) {
h = GetHost(data, data->device, &hostdataptr);
}
if(h) {
/* we know data->device is shorter than the myhost array */
strcpy(myhost, data->device);
}
}
if(! *myhost) {
/* need to fix this
h=GetHost(data,
getmyhost(*myhost,sizeof(myhost)),
hostent_buf,
sizeof(hostent_buf));
*/
printf("in here\n");
}
infof(data, "We connect from %s\n", myhost);
if ( (in=inet_addr(myhost)) != INADDR_NONE ) {
if ( h ) {
memset((char *)&sa, 0, sizeof(sa));
memcpy((char *)&sa.sin_addr,
h->h_addr,
h->h_length);
sa.sin_family = AF_INET;
sa.sin_addr.s_addr = in;
sa.sin_port = 0; /* get any port */
if( bind(data->firstsocket, (struct sockaddr *)&sa, sizeof(sa)) >= 0) {
/* we succeeded to bind */
struct sockaddr_in add;
size = sizeof(add);
if(getsockname(data->firstsocket, (struct sockaddr *) &add,
(int *)&size)<0) {
failf(data, "getsockname() failed");
return CURLE_HTTP_PORT_FAILED;
}
}
else {
switch(errno) {
case EBADF:
failf(data, "Invalid descriptor: %d", errno);
break;
case EINVAL:
failf(data, "Invalid request: %d", errno);
break;
case EACCES:
failf(data, "Address is protected, user not superuser: %d", errno);
break;
case ENOTSOCK:
failf(data,
"Argument is a descriptor for a file, not a socket: %d",
errno);
break;
case EFAULT:
failf(data, "Inaccessable memory error: %d", errno);
break;
case ENAMETOOLONG:
failf(data, "Address too long: %d", errno);
break;
case ENOMEM:
failf(data, "Insufficient kernel memory was available: %d", errno);
break;
#if 0
case EROFS:
failf(data,
"Socket inode would reside on a read-only file system: %d",
errno);
break;
case ENOENT:
failf(data, "File does not exist: %d", errno);
break;
case ENOTDIR:
failf(data, "Component of path prefix is not a directory: %d",
errno);
break;
case ELOOP:
failf(data,"Too many symbolic links encountered: %d",errno);
break;
#endif
default:
failf(data,"errno %d\n");
} /* end of switch */
return CURLE_HTTP_PORT_FAILED;
} /* end of else */
} /* end of if h */
else {
failf(data,"could't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
} /* end of inet_addr */
else {
failf(data, "could't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
free(hostdataptr); /* allocated by GetHost() */
} /* end of device selection support */
#endif /* end of HAVE_INET_NTOA */
#endif /* end of not WIN32 */
if (connect(data->firstsocket,
(struct sockaddr *) &(conn->serv_addr),
sizeof(conn->serv_addr)
@@ -1174,11 +1361,50 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
case ECONNREFUSED:
failf(data, "Connection refused");
break;
case EFAULT:
failf(data, "Invalid socket address: %d",errno);
break;
case EISCONN:
failf(data, "Socket already connected: %d",errno);
break;
case ETIMEDOUT:
failf(data, "Timeout while accepting connection, server busy: %d",errno);
break;
case ENETUNREACH:
failf(data, "Network is unreachable: %d",errno);
break;
case EADDRINUSE:
failf(data, "Local address already in use: %d",errno);
break;
case EINPROGRESS:
failf(data, "Socket is nonblocking and connection can not be completed immediately: %d",errno);
break;
case EALREADY:
failf(data, "Socket is nonblocking and a previous connection attempt not completed: %d",errno);
break;
case EAGAIN:
failf(data, "No more free local ports: %d",errno);
break;
case EACCES:
case EPERM:
failf(data, "Attempt to connect to broadcast address without socket broadcast flag or local firewall rule violated: %d",errno);
break;
#endif
#ifdef EINTR
case EINTR:
failf(data, "Connection timeouted");
break;
#endif
#if 0
case EAFNOSUPPORT:
failf(data, "Incorrect address family: %d",errno);
break;
case ENOTSOCK:
failf(data, "File descriptor is not a socket: %d",errno);
break;
case EBADF:
failf(data, "File descriptor is not a valid index in descriptor table: %d",errno);
break;
#endif
default:
failf(data, "Can't connect to server: %d", errno);
@@ -1188,12 +1414,15 @@ CURLcode curl_connect(CURL *curl, CURLconnect **in_connect)
}
if(data->bits.proxy_user_passwd) {
char authorization[512];
sprintf(data->buffer, "%s:%s", data->proxyuser, data->proxypasswd);
base64Encode(data->buffer, authorization);
data->ptr_proxyuserpwd = maprintf("Proxy-authorization: Basic %s\015\012",
authorization);
char *authorization;
snprintf(data->buffer, BUFSIZE, "%s:%s",
data->proxyuser, data->proxypasswd);
if(base64_encode(data->buffer, strlen(data->buffer),
&authorization) >= 0) {
data->ptr_proxyuserpwd =
maprintf("Proxy-authorization: Basic %s\015\012", authorization);
free(authorization);
}
}
if((conn->protocol&PROT_HTTP) || data->bits.httpproxy) {
if(data->useragent) {

View File

@@ -99,6 +99,11 @@
/* Download buffer size, keep it fairly big for speed reasons */
#define BUFSIZE (1024*50)
/* Upload buffer size, keep it smallish to get faster progress meter
updates. This should probably become dynamic and adjust to the upload
speed. */
#define UPLOAD_BUFSIZE (1024*2)
/* Initial size of the buffer to store headers in, it'll be enlarged in case
of need. */
#define HEADERSIZE 256
@@ -123,6 +128,20 @@ typedef enum {
CONN_LAST /* illegal state */
} ConnState;
#ifdef KRB4
struct krb4buffer {
void *data;
size_t size;
size_t index;
int eof_flag;
};
enum protection_level {
prot_clear,
prot_safe,
prot_confidential,
prot_private
};
#endif
/*
* The connectdata struct contains all fields and variables that should be
@@ -150,6 +169,7 @@ struct connectdata {
#define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8)
char *hostent_buf; /* pointer to allocated memory for name info */
struct hostent *hp;
struct sockaddr_in serv_addr;
char proto[64];
@@ -160,6 +180,9 @@ struct connectdata {
long bytecount;
struct timeval now;
long upload_bufsize; /* adjust as you see fit, never bigger than BUFSIZE
never smaller than UPLOAD_BUFSIZE */
/* These two functions MUST be set by the curl_connect() function to be
be protocol dependent */
CURLcode (*curl_do)(struct connectdata *connect);
@@ -188,6 +211,19 @@ struct connectdata {
the same we read from. -1 disables */
long *writebytecountp; /* return number of bytes written or NULL */
#ifdef KRB4
enum protection_level command_prot;
enum protection_level data_prot;
enum protection_level request_data_prot;
size_t buffer_size;
struct krb4buffer in_buffer, out_buffer;
int sec_complete;
void *app_data;
#endif
};
struct Progress {
@@ -213,6 +249,11 @@ struct Progress {
struct timeval t_connect;
struct timeval t_pretransfer;
int httpcode;
#define CURR_TIME 5
double speeder[ CURR_TIME ];
int speeder_c;
};
/****************************************************************************
@@ -245,6 +286,7 @@ struct FTP {
};
struct Configbits {
bool tunnel_thru_httpproxy;
bool ftp_append;
bool ftp_ascii;
bool ftp_list_only;
@@ -262,7 +304,6 @@ struct Configbits {
bool mute;
bool no_body;
bool proxy_user_passwd;
bool proxystringalloc; /* the http proxy string is malloc()'ed */
bool set_port;
bool set_range;
bool upload;
@@ -270,6 +311,11 @@ struct Configbits {
bool user_passwd;
bool verbose;
bool this_is_a_follow; /* this is a followed Location: request */
bool krb4; /* kerberos4 connection requested */
bool proxystringalloc; /* the http proxy string is malloc()'ed */
bool rangestringalloc; /* the range string is malloc()'ed */
bool urlstringalloc; /* the URL string is malloc()'ed */
};
/* What type of interface that intiated this struct */
@@ -313,6 +359,10 @@ struct UrlData {
proxy string features a ":[port]" that one will override
this. */
long header_size; /* size of read header(s) in bytes */
long request_size; /* the amount of bytes sent in the request(s) */
/*************** Request - specific items ************/
union {
@@ -355,6 +405,7 @@ struct UrlData {
char *useragent; /* User-Agent string */
char *ftpport; /* port to send with the PORT command */
char *device; /* Interface to use */
/* function that stores the output:*/
curl_write_callback fwrite;
@@ -418,8 +469,11 @@ struct UrlData {
char *headerbuff; /* allocated buffer to store headers in */
int headersize; /* size of the allocation */
#if 0
/* this was removed in libcurl 7.4 */
char *writeinfo; /* if non-NULL describes what to output on a successful
completion */
#endif
struct Progress progress;
@@ -444,6 +498,11 @@ struct UrlData {
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
FILE *cmdchannel;
#endif
};
#define LIBCURL_NAME "libcurl"

View File

@@ -79,8 +79,14 @@ char *curl_version(void)
ptr=strchr(ptr, '\0');
#endif
#ifdef KRB4
sprintf(ptr, " (krb4 enabled)");
ptr += strlen(ptr);
#endif
#ifdef USE_ZLIB
sprintf(ptr, " (zlib %s)", zlibVersion());
ptr += strlen(ptr);
#endif
return version;

98
memanalyze.pl Executable file
View File

@@ -0,0 +1,98 @@
#!/usr/bin/perl
#
# Example input:
#
# MEM mprintf.c:1094 malloc(32) = e5718
# MEM mprintf.c:1103 realloc(e5718, 64) = e6118
# MEM sendf.c:232 free(f6520)
do {
if($ARGV[0] eq "-v") {
$verbose=1;
}
} while (shift @ARGV);
while(<STDIN>) {
chomp $_;
$line = $_;
if($verbose) {
print "IN: $line\n";
}
if($line =~ /^MEM ([^:]*):(\d*) (.*)/) {
# generic match for the filename+linenumber
$source = $1;
$linenum = $2;
$function = $3;
if($function =~ /free\(([0-9a-f]*)/) {
$addr = $1;
if($sizeataddr{$addr} <= 0) {
print "FREE ERROR: No memory allocated: $line\n";
}
else {
$totalmem -= $sizeataddr{$addr};
$sizeataddr{$addr}=0;
$getmem{$addr}=""; # forget after a good free()
}
}
elsif($function =~ /malloc\((\d*)\) = ([0-9a-f]*)/) {
$size = $1;
$addr = $2;
$sizeataddr{$addr}=$size;
$totalmem += $size;
$getmem{$addr}="$source:$linenum";
}
elsif($function =~ /realloc\(([0-9a-f]*), (\d*)\) = ([0-9a-f]*)/) {
$oldaddr = $1;
$newsize = $2;
$newaddr = $3;
$totalmem -= $sizeataddr{$oldaddr};
$sizeataddr{$oldaddr}=0;
$totalmem += $newsize;
$sizeataddr{$newaddr}=$newsize;
$getmem{$oldaddr}="";
$getmem{$newaddr}="$source:$linenum";
}
elsif($function =~ /strdup\(([0-9a-f]*)\) \((\d*)\) = ([0-9a-f]*)/) {
# strdup(a5b50) (8) = df7c0
$dup = $1;
$size = $2;
$addr = $3;
$getmem{$addr}="$source:$linenum";
$sizeataddr{$addr}=$size;
$totalmem += $size;
}
else {
print "Not recognized input line: $function\n";
}
}
else {
print "Not recognized prefix line: $line\n";
}
if($verbose) {
print "TOTAL: $totalmem\n";
}
}
if(0 == $totalmem) {
print "No leak found\n";
exit;
}
print "Leak detected: memory still allocated: $totalmem bytes\n";
for(keys %sizeataddr) {
$addr = $_;
$size = $sizeataddr{$addr};
if($size) {
print "At $addr, there's $size bytes.\n";
print " allocated by ".$getmem{$addr}."\n";
}
}

View File

@@ -3,14 +3,17 @@
#
# Some flags needed when trying to cause warnings ;-)
# CFLAGS = -Wall -pedantic
# CFLAGS = -g -DMALLOCDEBUG # -Wall -pedantic
#CPPFLAGS = -DGLOBURL -DCURL_SEPARATORS
INCLUDES = -I$(top_srcdir)/include
bin_PROGRAMS = curl
bin_PROGRAMS = curl #memtest
curl_SOURCES = main.c hugehelp.c urlglob.c
#memtest_SOURCES = memtest.c
#memtest_LDADD = $(top_srcdir)/lib/libcurl.la
curl_SOURCES = main.c hugehelp.c urlglob.c writeout.c
curl_LDADD = $(top_srcdir)/lib/libcurl.la
curl_DEPENDENCIES = $(top_srcdir)/lib/libcurl.la
BUILT_SOURCES = hugehelp.c

View File

@@ -1,65 +1,71 @@
#############################################################
## Makefile for building curl.exe with MingW32 (GCC-2.95) and
## optionally OpenSSL (0.9.4)
##
## Use: make -f Makefile.m32 [SSL=1]
##
## Comments to: Troy Engel <tengel@sonic.net> or
## Joern Hartroth <hartroth@acm.org>
CC = gcc
STRIP = strip -s
OPENSSL_PATH = ../../openssl-0.9.5a
# We may need these someday
# PERL = perl
# NROFF = nroff
########################################################
## Nothing more to do below this line!
INCLUDES = -I. -I.. -I../include
CFLAGS = -g -O2 -DMINGW32
LDFLAGS =
COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
curl_PROGRAMS = curl.exe
curl_OBJECTS = main.o hugehelp.o urlglob.o
curl_SOURCES = main.c hugehelp.c urlglob.c
curl_DEPENDENCIES = ../lib/libcurl.a
curl_LDADD = -L../lib -lcurl -lwsock32
ifdef SSL
curl_LDADD += -L$(OPENSSL_PATH)/out -leay32 -lssl32 -lRSAglue
endif
PROGRAMS = $(curl_PROGRAMS)
SOURCES = $(curl_SOURCES)
OBJECTS = $(curl_OBJECTS)
all: curl
curl: $(curl_OBJECTS) $(curl_DEPENDENCIES)
-@erase curl.exe
$(LINK) $(curl_OBJECTS) $(curl_LDADD)
$(STRIP) $(curl_PROGRAMS)
# We don't have nroff normally under win32
# hugehelp.c: ../README.curl ../curl.1 mkhelp.pl
# -@erase hugehelp.c
# $(NROFF) -man ../curl.1 | $(PERL) mkhelp.pl ../README.curl > hugehelp.c
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
clean:
-@erase $(curl_OBJECTS)
distrib: clean
-@erase $(curl_PROGRAMS)
#############################################################
## Makefile for building curl.exe with MingW32 (GCC-2.95) and
## optionally OpenSSL (0.9.6)
##
## Use: make -f Makefile.m32 [SSL=1] [DYN=1]
##
## Comments to: Troy Engel <tengel@sonic.net> or
## Joern Hartroth <hartroth@acm.org>
CC = gcc
STRIP = strip -s
OPENSSL_PATH = ../../openssl-0.9.6
# We may need these someday
# PERL = perl
# NROFF = nroff
########################################################
## Nothing more to do below this line!
INCLUDES = -I. -I.. -I../include
CFLAGS = -g -O2 -DMINGW32
LDFLAGS =
COMPILE = $(CC) $(INCLUDES) $(CFLAGS)
LINK = $(CC) $(CFLAGS) $(LDFLAGS) -o $@
curl_PROGRAMS = curl.exe
curl_OBJECTS = main.o hugehelp.o urlglob.o writeout.o
curl_SOURCES = main.c hugehelp.c urlglob.c writeout.c
ifdef DYN
curl_DEPENDENCIES = ../lib/libcurldll.a ../lib/libcurl.dll
curl_LDADD = -L../lib -lcurldll
else
curl_DEPENDENCIES = ../lib/libcurl.a
curl_LDADD = -L../lib -lcurl
endif
curl_LDADD += -lwsock32
ifdef SSL
curl_LDADD += -L$(OPENSSL_PATH)/out -leay32 -lssl32 -lRSAglue
endif
PROGRAMS = $(curl_PROGRAMS)
SOURCES = $(curl_SOURCES)
OBJECTS = $(curl_OBJECTS)
all: curl.exe
curl.exe: $(curl_OBJECTS) $(curl_DEPENDENCIES)
-@erase $@
$(LINK) $(curl_OBJECTS) $(curl_LDADD)
$(STRIP) $@
# We don't have nroff normally under win32
# hugehelp.c: ../README.curl ../curl.1 mkhelp.pl
# -@erase hugehelp.c
# $(NROFF) -man ../curl.1 | $(PERL) mkhelp.pl ../README.curl > hugehelp.c
.c.o:
$(COMPILE) -c $<
.s.o:
$(COMPILE) -c $<
.S.o:
$(COMPILE) -c $<
clean:
-@erase $(curl_OBJECTS)
distrib: clean
-@erase $(curl_PROGRAMS)

View File

@@ -87,15 +87,15 @@ puts (
" sent to stdout to be in text mode for win32 systems.\n"
"\n"
" -c/--continue\n"
" Continue/Resume a previous file transfer. This\n"
" instructs curl to continue appending data on the file\n"
" where it was previously left, possibly because of a\n"
" broken connection to the server. There must be a named\n"
" physical file to append to for this to work. Note:\n"
" Upload resume is depening on a command named SIZE not\n"
" always present in all ftp servers! Upload resume is for\n"
" FTP only. HTTP resume is only possible with HTTP/1.1\n"
" or later servers.\n"
" Deprecated. Use '-C -' instead. Continue/Resume a pre<EFBFBD>\n"
" vious file transfer. This instructs curl to continue\n"
" appending data on the file where it was previously\n"
" left, possibly because of a broken connection to the\n"
" server. There must be a named physical file to append\n"
" to for this to work. Note: Upload resume is depening\n"
" on a command named SIZE not always present in all ftp\n"
" servers! Upload resume is for FTP only. HTTP resume is\n"
" only possible with HTTP/1.1 or later servers.\n"
"\n"
" -C/--continue-at <offset>\n"
" Continue/Resume a previous file transfer at the given\n"
@@ -214,20 +214,34 @@ puts (
" (HTTP) Include the HTTP-header in the output. The HTTP-\n"
" header includes things like server-name, date of the\n"
" document, HTTP-version and more...\n"
" --interface <name>\n"
" Perform an operation using a specified interface. You\n"
" can enter interface name, IP address or host name. An\n"
" example could look like:\n"
"\n"
" curl --interface eth0:1 http://www.netscape.com/\n"
"\n"
" -I/--head\n"
" (HTTP/FTP) Fetch the HTTP-header only! HTTP-servers\n"
" feature the command HEAD which this uses to get nothing\n"
" but the header of a document. When used on a FTP file,\n"
" curl displays the file size only.\n"
"\n"
" --krb4 <level>\n"
" (FTP) Enable kerberos4 authentication and use. The\n"
);
puts(
" level must be entered and should be one of 'clear',\n"
" 'safe', 'confidential' or 'private'. Should you use a\n"
" level that is not one of these, 'private' will instead\n"
" be used.\n"
"\n"
" -K/--config <config file>\n"
" Specify which config file to read curl arguments from.\n"
" The config file is a text file in which command line\n"
" arguments can be written which then will be used as if\n"
" they were written on the actual command line. If the\n"
" first column of a config line is a '#' character, the\n"
);
puts(
" rest of the line will be treated as a comment.\n"
"\n"
" Specify the filename as '-' to make curl read the file\n"
@@ -302,6 +316,15 @@ puts (
" we get. (Only the file part of the remote file is used,\n"
" the path is cut off.)\n"
"\n"
" -p/--proxytunnel\n"
" When an HTTP proxy is used, this option will cause non-\n"
" HTTP protocols to attempt to tunnel through the proxy\n"
" instead of merely using it to do HTTP-like operations.\n"
" The tunnel approach is made with the HTTP proxy CONNECT\n"
" request and requires that the proxy allows direct con<6F>\n"
" nect to the remote port number curl wants to tunnel\n"
" through to.\n"
"\n"
" -P/--ftpport <address>\n"
" (FTP) Reverses the initiator/listener roles when con<6F>\n"
" necting with ftp. This switch makes Curl use the PORT\n"
@@ -320,6 +343,7 @@ puts (
"\n"
" - (any single-letter string) to make it pick\n"
" the machine's default\n"
"\n"
" -q If used as the first parameter on the command line, the\n"
" $HOME/.curlrc file will not be read and used as a con<6F>\n"
" fig file.\n"
@@ -347,8 +371,8 @@ puts (
"\n"
" -500 specifies the last 500 bytes\n"
"\n"
" 9500 specifies the bytes from offset 9500 and for<6F>\n"
" ward\n"
" 9500 specifies the bytes from offset 9500 and\n"
" forward\n"
"\n"
" 0-0,-1 specifies the first and last byte only(*)(H)\n"
"\n"
@@ -372,146 +396,153 @@ puts (
" -s/--silent\n"
" Silent mode. Don't show progress meter or error mes<65>\n"
" sages. Makes Curl mute.\n"
"\n"
" -S/--show-error\n"
" When used with -s it makes curl show error message if\n"
" it fails.\n"
"\n"
" -t/--upload\n"
" Transfer the stdin data to the specified file. Curl\n"
" will read everything from stdin until EOF and store\n"
" with the supplied name. If this is used on a http(s)\n"
" server, the PUT command will be used.\n"
" Deprecated. Use '-T -' instead. Transfer the stdin\n"
" data to the specified file. Curl will read everything\n"
" from stdin until EOF and store with the supplied name.\n"
" If this is used on a http(s) server, the PUT command\n"
" will be used.\n"
"\n"
" -T/--upload-file <file>\n"
" Like -t, but this transfers the specified local file.\n"
" If there is no file part in the specified URL, Curl\n"
" Like -t, but this transfers the specified local file.\n"
" If there is no file part in the specified URL, Curl\n"
" will append the local file name. NOTE that you must use\n"
" a trailing / on the last directory to really prove to\n"
" a trailing / on the last directory to really prove to\n"
" Curl that there is no file name or curl will think that\n"
" your last directory name is the remote file name to\n"
" use. That will most likely cause the upload operation\n"
" to fail. If this is used on a http(s) server, the PUT\n"
" your last directory name is the remote file name to\n"
" use. That will most likely cause the upload operation\n"
" to fail. If this is used on a http(s) server, the PUT\n"
" command will be used.\n"
"\n"
" -u/--user <user:password>\n"
" Specify user and password to use when fetching. See\n"
" README.curl for detailed examples of how to use this.\n"
" If no password is specified, curl will ask for it\n"
" Specify user and password to use when fetching. See\n"
" README.curl for detailed examples of how to use this.\n"
" If no password is specified, curl will ask for it\n"
" interactively.\n"
"\n"
" -U/--proxy-user <user:password>\n"
" Specify user and password to use for Proxy authentica<EFBFBD>\n"
" Specify user and password to use for Proxy authentica<63>\n"
" tion. If no password is specified, curl will ask for it\n"
" interactively.\n"
"\n"
" -v/--verbose\n"
" Makes the fetching more verbose/talkative. Mostly\n"
" usable for debugging. Lines starting with '>' means\n"
" Makes the fetching more verbose/talkative. Mostly\n"
" usable for debugging. Lines starting with '>' means\n"
" data sent by curl, '<' means data received by curl that\n"
" is hidden in normal cases and lines starting with '*'\n"
" is hidden in normal cases and lines starting with '*'\n"
" means additional info provided by curl.\n"
"\n"
" -V/--version\n"
" Displays the full version of curl, libcurl and other\n"
" Displays the full version of curl, libcurl and other\n"
" 3rd party libraries linked with the executable.\n"
"\n"
" -w/--write-out <format>\n"
" Defines what to display after a completed and success<73>\n"
" ful operation. The format is a string that may contain\n"
" plain text mixed with any number of variables. The\n"
" Defines what to display after a completed and success<EFBFBD>\n"
" ful operation. The format is a string that may contain\n"
" plain text mixed with any number of variables. The\n"
" string can be specified as \"string\", to get read from a\n"
" particular file you specify it \"@filename\" and to tell\n"
" particular file you specify it \"@filename\" and to tell\n"
" curl to read the format from stdin you write \"@-\".\n"
"\n"
" The variables present in the output format will be\n"
" substituted by the value or text that curl thinks fit,\n"
" as described below. All variables are specified like\n"
" %{variable_name} and to output a normal % you just\n"
" write them like %%. You can output a newline by using\n"
" The variables present in the output format will be sub<75>\n"
" stituted by the value or text that curl thinks fit, as\n"
" described below. All variables are specified like\n"
" %{variable_name} and to output a normal % you just\n"
" write them like %%. You can output a newline by using\n"
" \\n, a carrige return with \\r and a tab space with \\t.\n"
"\n"
" NOTE: The %-letter is a special letter in the\n"
" win32-environment, where all occurrences of % must be\n"
" NOTE: The %-letter is a special letter in the\n"
" win32-environment, where all occurrences of % must be\n"
" doubled when using this option.\n"
"\n"
" Available variables are at this point:\n"
"\n"
" url_effective The URL that was fetched last. This is\n"
" url_effective The URL that was fetched last. This is\n"
" mostly meaningful if you've told curl to\n"
" follow location: headers.\n"
"\n"
" http_code The numerical code that was found in the\n"
);
puts(
" last retrieved HTTP(S) page.\n"
"\n"
" time_total The total time, in seconds, that the\n"
" full operation lasted. The time will be\n"
" time_total The total time, in seconds, that the\n"
" full operation lasted. The time will be\n"
" displayed with millisecond resolution.\n"
"\n"
" time_namelookup\n"
" The time, in seconds, it took from the\n"
" start until the name resolving was com<6F>\n"
" The time, in seconds, it took from the\n"
" start until the name resolving was com<EFBFBD>\n"
" pleted.\n"
"\n"
" time_connect The time, in seconds, it took from the\n"
" start until the connect to the remote\n"
" time_connect The time, in seconds, it took from the\n"
" start until the connect to the remote\n"
" host (or proxy) was completed.\n"
"\n"
" time_pretransfer\n"
" The time, in seconds, it took from the\n"
" start until the file transfer is just\n"
" about to begin. This includes all pre-\n"
" transfer commands and negotiations that\n"
" are specific to the particular proto<EFBFBD>\n"
" The time, in seconds, it took from the\n"
" start until the file transfer is just\n"
" about to begin. This includes all pre-\n"
" transfer commands and negotiations that\n"
" are specific to the particular proto<74>\n"
" col(s) involved.\n"
);
puts(
"\n"
" size_download The total amount of bytes that were\n"
" size_download The total amount of bytes that were\n"
" downloaded.\n"
"\n"
" size_upload The total amount of bytes that were\n"
" size_upload The total amount of bytes that were\n"
" uploaded.\n"
"\n"
" speed_download The average download speed that curl\n"
" size_header The total amount of bytes of the down<77>\n"
" loaded headers.\n"
"\n"
" size_request The total amount of bytes that were sent\n"
" in the HTTP request.\n"
"\n"
" speed_download The average download speed that curl\n"
" measured for the complete download.\n"
"\n"
" speed_upload The average upload speed that curl mea<EFBFBD>\n"
" sured for the complete download.\n"
" speed_upload The average upload speed that curl mea<65>\n"
" sured for the complete upload.\n"
"\n"
" -x/--proxy <proxyhost[:port]>\n"
" Use specified proxy. If the port number is not speci<63>\n"
" Use specified proxy. If the port number is not speci<EFBFBD>\n"
" fied, it is assumed at port 1080.\n"
"\n"
" -X/--request <command>\n"
" (HTTP) Specifies a custom request to use when communi<EFBFBD>\n"
" cating with the HTTP server. The specified request\n"
" (HTTP) Specifies a custom request to use when communi<6E>\n"
" cating with the HTTP server. The specified request\n"
" will be used instead of the standard GET. Read the HTTP\n"
" 1.1 specification for details and explanations.\n"
"\n"
" (FTP) Specifies a custom FTP command to use instead of\n"
" (FTP) Specifies a custom FTP command to use instead of\n"
" LIST when doing file lists with ftp.\n"
"\n"
" -y/--speed-time <time>\n"
" If a download is slower than speed-limit bytes per sec<65>\n"
" ond during a speed-time period, the download gets\n"
" ond during a speed-time period, the download gets\n"
" aborted. If speed-time is used, the default speed-limit\n"
" will be 1 unless set with -y.\n"
"\n"
" -Y/--speed-limit <speed>\n"
" If a download is slower than this given speed, in bytes\n"
" per second, for speed-time seconds it gets aborted.\n"
" per second, for speed-time seconds it gets aborted.\n"
" speed-time is set with -Y and is 30 if not set.\n"
"\n"
" -z/--time-cond <date expression>\n"
" (HTTP) Request to get a file that has been modified\n"
" later than the given time and date, or one that has\n"
" (HTTP) Request to get a file that has been modified\n"
" later than the given time and date, or one that has\n"
" been modified before that time. The date expression can\n"
" be all sorts of date strings or if it doesn't match any\n"
" internal ones, it tries to get the time from a given\n"
" file name instead! See the GNU date(1) or curl_get<EFBFBD>\n"
" internal ones, it tries to get the time from a given\n"
" file name instead! See the GNU date(1) or curl_get<65>\n"
" date(3) man pages for date expression details.\n"
"\n"
" Start the date expression with a dash (-) to make it\n"
" request for a document that is older than the given\n"
" Start the date expression with a dash (-) to make it\n"
" request for a document that is older than the given\n"
" date/time, default is a document that is newer than the\n"
" specified date/time.\n"
"\n"
@@ -524,15 +555,15 @@ puts (
" ing with a remote SSL server.\n"
"\n"
" -#/--progress-bar\n"
" Make curl display progress information as a progress\n"
" Make curl display progress information as a progress\n"
" bar instead of the default statistics.\n"
"\n"
" --crlf\n"
" (FTP) Convert LF to CRLF in upload. Useful for MVS\n"
" (FTP) Convert LF to CRLF in upload. Useful for MVS\n"
" (OS/390).\n"
"\n"
" --stderr <file>\n"
" Redirect all writes to stderr to the specified file\n"
" Redirect all writes to stderr to the specified file\n"
" instead. If the file name is a plain '-', it is instead\n"
" written to stdout. This option has no point when you're\n"
" using a shell with decent redirecting capabilities.\n"
@@ -550,12 +581,11 @@ puts (
"\n"
" FTP_PROXY [protocol://]<host>[:port]\n"
" Sets proxy server to use for FTP.\n"
"\n"
" GOPHER_PROXY [protocol://]<host>[:port]\n"
" Sets proxy server to use for GOPHER.\n"
"\n"
" ALL_PROXY [protocol://]<host>[:port]\n"
" Sets proxy server to use if no protocol-specific proxy\n"
" Sets proxy server to use if no protocol-specific proxy\n"
" is set.\n"
"\n"
" NO_PROXY <comma-separated list of hosts>\n"
@@ -563,12 +593,12 @@ puts (
" If set to a asterisk '*' only, it matches all hosts.\n"
"\n"
" COLUMNS <integer>\n"
" The width of the terminal. This variable only affects\n"
" The width of the terminal. This variable only affects\n"
" curl when the --progress-bar option is used.\n"
"\n"
"EXIT CODES\n"
" There exists a bunch of different error codes and their cor<6F>\n"
" responding error messages that may appear during bad condi<64>\n"
" responding error messages that may appear during bad condi<EFBFBD>\n"
" tions. At the time of this writing, the exit codes are:\n"
"\n"
" 1 Unsupported protocol. This build of curl has no support\n"
@@ -578,40 +608,40 @@ puts (
"\n"
" 3 URL malformat. The syntax was not correct.\n"
"\n"
" 4 URL user malformatted. The user-part of the URL syntax\n"
" 4 URL user malformatted. The user-part of the URL syntax\n"
" was not correct.\n"
" 5 Couldn't resolve proxy. The given proxy host could not\n"
"\n"
" 5 Couldn't resolve proxy. The given proxy host could not\n"
" be resolved.\n"
"\n"
" 6 Couldn't resolve host. The given remote host was not\n"
" 6 Couldn't resolve host. The given remote host was not\n"
" resolved.\n"
"\n"
" 7 Failed to connect to host.\n"
"\n"
" 8 FTP weird server reply. The server sent data curl\n"
" 8 FTP weird server reply. The server sent data curl\n"
" couldn't parse.\n"
"\n"
" 9 FTP access denied. The server denied login.\n"
"\n"
" 10 FTP user/password incorrect. Either one or both were\n"
" 10 FTP user/password incorrect. Either one or both were\n"
" not accepted by the server.\n"
"\n"
" 11 FTP weird PASS reply. Curl couldn't parse the reply\n"
" 11 FTP weird PASS reply. Curl couldn't parse the reply\n"
" sent to the PASS request.\n"
"\n"
" 12 FTP weird USER reply. Curl couldn't parse the reply\n"
" 12 FTP weird USER reply. Curl couldn't parse the reply\n"
" sent to the USER request.\n"
"\n"
" 13 FTP weird PASV reply, Curl couldn't parse the reply\n"
" 13 FTP weird PASV reply, Curl couldn't parse the reply\n"
" sent to the PASV request.\n"
"\n"
" 14 FTP weird 227 formay. Curl couldn't parse the 227-line\n"
" 14 FTP weird 227 formay. Curl couldn't parse the 227-line\n"
" the server sent.\n"
"\n"
" 15 FTP can't get host. Couldn't resolve the host IP we got\n"
" in the 227-line.\n"
"\n"
" 16 FTP can't reconnect. Couldn't connect to the host we\n"
" 16 FTP can't reconnect. Couldn't connect to the host we\n"
" got in the 227-line.\n"
"\n"
" 17 FTP couldn't set binary. Couldn't change transfer\n"
@@ -621,51 +651,52 @@ puts (
"\n"
" 19 FTP couldn't RETR file. The RETR command failed.\n"
"\n"
" 20 FTP write error. The transfer was reported bad by the\n"
" 20 FTP write error. The transfer was reported bad by the\n"
" server.\n"
"\n"
" 21 FTP quote error. A quote command returned error from\n"
" 21 FTP quote error. A quote command returned error from\n"
" the server.\n"
"\n"
" 22 HTTP not found. The requested page was not found. This\n"
" 22 HTTP not found. The requested page was not found. This\n"
" return code only appears if --fail is used.\n"
"\n"
" 23 Write error. Curl couldn't write data to a local\n"
" 23 Write error. Curl couldn't write data to a local\n"
" filesystem or similar.\n"
"\n"
" 24 Malformat user. User name badly specified.\n"
"\n"
" 25 FTP couldn't STOR file. The server denied the STOR\n"
" 25 FTP couldn't STOR file. The server denied the STOR\n"
" operation.\n"
"\n"
" 26 Read error. Various reading problems.\n"
"\n"
" 27 Out of memory. A memory allocation request failed.\n"
"\n"
" 28 Operation timeout. The specified time-out period was\n"
" 28 Operation timeout. The specified time-out period was\n"
" reached according to the conditions.\n"
"\n"
" 29 FTP couldn't set ASCII. The server returned an unknown\n"
" 29 FTP couldn't set ASCII. The server returned an unknown\n"
" reply.\n"
"\n"
" 30 FTP PORT failed. The PORT command failed.\n"
"\n"
" 31 FTP couldn't use REST. The REST command failed.\n"
"\n"
" 32 FTP couldn't use SIZE. The SIZE command failed. The\n"
" command is an extension to the original FTP spec RFC\n"
" 32 FTP couldn't use SIZE. The SIZE command failed. The\n"
" command is an extension to the original FTP spec RFC\n"
" 959.\n"
"\n"
" 33 HTTP range error. The range \"command\" didn't work.\n"
"\n"
" 34 HTTP post error. Internal post-request generation\n"
" 34 HTTP post error. Internal post-request generation\n"
" error.\n"
"\n"
" 35 SSL connect error. The SSL handshaking failed.\n"
"\n"
" 36 FTP bad download resume. Couldn't continue an earlier\n"
" 36 FTP bad download resume. Couldn't continue an earlier\n"
" aborted download.\n"
"\n"
" 37 FILE couldn't read file. Failed to open the file. Per<65>\n"
" 37 FILE couldn't read file. Failed to open the file. Per<65>\n"
" missions?\n"
"\n"
" 38 LDAP cannot bind. LDAP bind operation failed.\n"
@@ -674,15 +705,16 @@ puts (
"\n"
" 40 Library not found. The LDAP library was not found.\n"
"\n"
" 41 Function not found. A required LDAP function was not\n"
" 41 Function not found. A required LDAP function was not\n"
" found.\n"
"\n"
" XX There will appear more error codes here in future\n"
" releases. The existing ones are meant to never change.\n"
" XX There will appear more error codes here in future\n"
" releases. The existing ones are meant to never change.\n"
"\n"
"BUGS\n"
" If you do find any (or have other suggestions), mail Daniel\n"
" If you do find any (or have other suggestions), mail Daniel\n"
" Stenberg <Daniel.Stenberg@haxx.se>.\n"
"\n"
"AUTHORS / CONTRIBUTORS\n"
" - Daniel Stenberg <Daniel.Stenberg@haxx.se>\n"
" - Rafael Sagula <sagula@inf.ufrgs.br>\n"
@@ -717,6 +749,8 @@ puts (
" - Felix von Leitner <felix@convergence.de>\n"
" - Dan Zitter <dzitter@zitter.net>\n"
" - Jongki Suwandi <Jongki.Suwandi@eng.sun.com>\n"
);
puts(
" - Chris Maltby <chris@aurema.com>\n"
" - Ron Zapp <rzapper@yahoo.com>\n"
" - Paul Marquis <pmarquis@iname.com>\n"
@@ -733,6 +767,11 @@ puts (
" - Fred Noz <FNoz@siac.com>\n"
" - Caolan McNamara <caolan@csn.ul.ie>\n"
" - Albert Chin-A-Young <china@thewrittenword.com>\n"
" - Stephen Kick <skick@epicrealm.com>\n"
" - Martin Hedenfalk <mhe@stacken.kth.se>\n"
" - Richard Prescott\n"
" - Jason S. Priebe <priebe@wral-tv.com>\n"
"\n"
"WWW\n"
" http://curl.haxx.se\n"
"\n"
@@ -762,8 +801,6 @@ puts (
" Get a gopher document from funet's gopher server:\n"
"\n"
" curl gopher://gopher.funet.fi\n"
);
puts(
"\n"
" Get a web page from a server using port 8000:\n"
"\n"
@@ -885,9 +922,11 @@ puts (
"\n"
" curl -T localfile -a ftp://ftp.upload.com/remotefile\n"
"\n"
" NOTE: Curl does not support ftp upload through a proxy! The reason for this\n"
" is simply that proxies are seldomly configured to allow this and that no\n"
" author has supplied code that makes it possible!\n"
" Curl also supports ftp upload through a proxy, but only if the proxy is\n"
" configured to allow that kind of tunneling. If it does, you can run curl in\n"
" a fashion similar to:\n"
"\n"
" curl --proxytunnel -x proxy:port -T localfile ftp.upload.com\n"
"\n"
" HTTP\n"
"\n"
@@ -1025,6 +1064,8 @@ puts (
" being available or contain certain data.\n"
"\n"
" curl -e www.coolsite.com http://www.showme.com/\n"
);
puts(
"\n"
"USER AGENT\n"
"\n"
@@ -1058,8 +1099,6 @@ puts (
" headers that looks like 'Set-Cookie: <data>' where the data part then\n"
" typically contains a set of NAME=VALUE pairs (separated by semicolons ';'\n"
" like \"NAME1=VALUE1; NAME2=VALUE2;\"). The server can also specify for what\n"
);
puts(
" path the \"cookie\" should be used for (by specifying \"path=value\"), when the\n"
" cookie should expire (\"expire=DATE\"), for what domain to use it\n"
" (\"domain=NAME\") and if it should be used on secure connections only\n"
@@ -1228,13 +1267,14 @@ puts (
" connect to the client on the given (as parameters to the PORT command) IP\n"
" number and port.\n"
"\n"
" The -P flag to curl allows for different options. Your machine may have\n"
" The -P flag to curl supports a few different options. Your machine may have\n"
" several IP-addresses and/or network interfaces and curl allows you to select\n"
" which of them to use. Default address can also be used:\n"
"\n"
" curl -P - ftp.download.com\n"
"\n"
" Download with PORT but use the IP address of our 'le0' interface:\n"
" Download with PORT but use the IP address of our 'le0' interface (this does\n"
" not work on windows):\n"
"\n"
" curl -P le0 ftp.download.com\n"
"\n"
@@ -1242,6 +1282,16 @@ puts (
"\n"
" curl -P 192.168.0.10 ftp.download.com\n"
"\n"
"NETWORK INTERFACE\n"
"\n"
" Get a web page from a server using a specified port for the interface:\n"
"\n"
" curl --interface eth0:1 http://www.netscape.com/\n"
"\n"
" or\n"
"\n"
" curl --interface 192.168.1.10 http://www.netscape.com/\n"
"\n"
"HTTPS\n"
"\n"
" Secure HTTP requires SSL libraries to be installed and used when curl is\n"
@@ -1275,6 +1325,8 @@ puts (
"\n"
" Many older SSL-servers have problems with SSLv3 or TLS, that newer versions\n"
" of OpenSSL etc is using, therefore it is sometimes useful to specify what\n"
);
puts(
" SSL-version curl should use. Use -3 or -2 to specify that exact SSL version\n"
" to use:\n"
"\n"
@@ -1328,8 +1380,6 @@ puts (
"TIME CONDITIONS\n"
"\n"
" HTTP allows a client to specify a time condition for the document it\n"
);
puts(
" requests. It is If-Modified-Since or If-Unmodified-Since. Curl allow you to\n"
" specify them with the -z/--time-cond flag.\n"
"\n"
@@ -1439,13 +1489,26 @@ puts (
"\n"
" curl -w 'We downloaded %{size_download} bytes\\n' www.download.com\n"
"\n"
"KERBEROS4 FTP TRANSFER\n"
"\n"
" Curl supports kerberos4 for FTP transfers. You need the kerberos package\n"
" installed and used at curl build time for it to be used.\n"
"\n"
" First, get the krb-ticket the normal way, like with the kauth tool. Then use\n"
" curl in way similar to:\n"
"\n"
" curl --krb4 private ftp://krb4site.com -u username:fakepwd\n"
"\n"
" There's no use for a password on the -u switch, but a blank one will make\n"
" curl ask for one and you already entered the real password to kauth.\n"
"\n"
"MAILING LIST\n"
"\n"
" We have an open mailing list to discuss curl, its development and things\n"
" relevant to this.\n"
"\n"
" To subscribe, mail curl-request@contactor.se with \"subscribe <your email\n"
" address>\" in the body.\n"
" To subscribe, mail curl-request@contactor.se with \"subscribe <fill in your\n"
" email address>\" in the body.\n"
"\n"
" To post to the list, mail curl@contactor.se.\n"
"\n"

View File

@@ -48,6 +48,8 @@
#include <curl/curl.h>
#include <curl/types.h> /* new for v7 */
#include <curl/easy.h> /* new for v7 */
#define _MPRINTF_REPLACE /* we want curl-functions instead of native ones */
#include <curl/mprintf.h>
#include "urlglob.h"
@@ -80,6 +82,16 @@
#include <fcntl.h>
#endif
/* The last #include file should be: */
#ifdef MALLOCDEBUG
/* this is low-level hard-hacking memory leak tracking shit */
#include "../lib/memdebug.h"
#endif
#ifndef __cplusplus /* (rabe) */
typedef char bool;
#endif /* (rabe) */
typedef enum {
HTTPREQ_UNSPEC,
HTTPREQ_GET,
@@ -243,6 +255,8 @@ static void help(void)
" -H/--header <line> Custom header to pass to server. (H)\n"
" -i/--include Include the HTTP-header in the output (H)\n"
" -I/--head Fetch document info only (HTTP HEAD/FTP SIZE)\n"
" --interface <interface> Specify the interface to be used\n"
" --krb4 <level> Enable krb4 with specified security level (F)\n"
" -K/--config Specify which config file to read\n"
" -l/--list-only List only names of an FTP directory (F)\n"
" -L/--location Follow Location: hints (H)\n"
@@ -252,9 +266,7 @@ static void help(void)
" -N/--no-buffer Disables the buffering of the output stream\n"
" -o/--output <file> Write output to <file> instead of stdout\n"
" -O/--remote-name Write output to a file named as the remote file\n"
#if 0
" -p/--port <port> Use port other than default for current protocol.\n"
#endif
" -p/--proxytunnel Perform non-HTTP services through a HTTP proxy\n"
" -P/--ftpport <address> Use PORT with address instead of PASV when ftping (F)\n"
" -q When used as the first parameter disables .curlrc\n"
" -Q/--quote <cmd> Send QUOTE command to FTP before file transfer (F)\n"
@@ -301,6 +313,7 @@ struct Configurable {
char *headerfile;
char remotefile;
char *ftpport;
char *iface;
unsigned short porttouse;
char *range;
int low_speed_limit;
@@ -311,6 +324,7 @@ struct Configurable {
char *proxyuserpwd;
char *proxy;
bool configread;
bool proxytunnel;
long conf;
char *url;
char *cert;
@@ -318,6 +332,7 @@ struct Configurable {
bool crlf;
char *cookiefile;
char *customrequest;
char *krb4level;
bool progressmode;
bool nobuffer;
@@ -441,6 +456,8 @@ static int getparameter(char *flag, /* f or -long-flag */
struct LongShort aliases[]= {
{"9", "crlf", FALSE},
{"8", "stderr", TRUE},
{"7", "interface", TRUE},
{"6", "krb4", TRUE},
{"2", "sslv2", FALSE},
{"3", "sslv3", FALSE},
@@ -473,9 +490,7 @@ static int getparameter(char *flag, /* f or -long-flag */
{"N", "no-buffer", FALSE},
{"o", "output", TRUE},
{"O", "remote-name", FALSE},
#if 0
{"p", "port", TRUE},
#endif
{"p", "proxytunnel", FALSE},
{"P", "ftpport", TRUE},
{"q", "disable", FALSE},
{"Q", "quote", TRUE},
@@ -501,23 +516,26 @@ static int getparameter(char *flag, /* f or -long-flag */
if('-' == flag[0]) {
/* try a long name */
int fnam=strlen(&flag[1]);
int numhits=0;
for(j=0; j< sizeof(aliases)/sizeof(aliases[0]); j++) {
if(strnequal(aliases[j].lname, &flag[1], fnam)) {
longopt = TRUE;
numhits++;
if(strequal(aliases[j].lname, &flag[1])) {
parse = aliases[j].letter;
hit = j;
numhits = 1; /* a single unique hit */
break;
}
if(parse) {
/* this is the second match, we can't continue! */
helpf("option --%s is ambiguous\n", &flag[1]);
return CURLE_FAILED_INIT;
}
parse = aliases[j].letter;
hit = j;
}
}
if(numhits>1) {
/* this is at least the second match! */
helpf("option --%s is ambiguous\n", &flag[1]);
return CURLE_FAILED_INIT;
}
if(hit < 0) {
helpf("unknown option -%s.\n", flag);
return CURLE_FAILED_INIT;
@@ -612,6 +630,14 @@ static int getparameter(char *flag, /* f or -long-flag */
else
config->errors = stdout;
break;
case '7': /* there is no short letter for this */
/* interface */
GetStr(&config->iface, nextarg);
break;
case '6': /* there is no short letter for this */
/* krb4 level string */
GetStr(&config->krb4level, nextarg);
break;
case '#': /* added 19990617 larsa */
config->progressmode ^= CURL_PROGRESS_BAR;
break;
@@ -650,10 +676,12 @@ static int getparameter(char *flag, /* f or -long-flag */
case 'c':
/* This makes us continue an ftp transfer */
config->use_resume^=TRUE;
fprintf(stderr, "-c is a deprecated switch, use '-C -' instead!\n");
break;
case 'C':
/* This makes us continue an ftp transfer at given position */
config->resume_from= atoi(nextarg);
if(!strequal(nextarg, "-"))
config->resume_from= atoi(nextarg);
config->use_resume=TRUE;
break;
case 'd':
@@ -789,15 +817,11 @@ static int getparameter(char *flag, /* f or -long-flag */
*/
GetStr(&config->ftpport, nextarg);
break;
#if 0
case 'p':
/* specified port */
fputs("You've used the -p option, it will be removed in a future version\n",
stderr);
config->porttouse = atoi(nextarg);
config->conf |= CONF_PORT; /* changed port */
/* proxy tunnel for non-http protocols */
config->proxytunnel ^= TRUE;
break;
#endif
case 'q': /* if used first, already taken care of, we do it like
this so we don't cause an error! */
break;
@@ -828,11 +852,14 @@ static int getparameter(char *flag, /* f or -long-flag */
case 't':
/* we are uploading */
config->conf ^= CONF_UPLOAD;
fprintf(stderr, "-t is a deprecated switch, use '-T -' instead!\n");
break;
case 'T':
/* we are uploading */
config->conf |= CONF_UPLOAD;
GetStr(&config->infile, nextarg);
if(!strequal("-", nextarg))
/* make - equal stdin */
GetStr(&config->infile, nextarg);
break;
case 'u':
/* user:password */
@@ -1125,6 +1152,7 @@ void progressbarinit(struct ProgressData *bar)
int main(int argc, char *argv[])
{
char errorbuffer[CURL_ERROR_SIZE];
char useragent[128]; /* buah, we don't want a larger default user agent */
struct ProgressData progressbar;
struct OutStruct outs;
@@ -1149,11 +1177,13 @@ int main(int argc, char *argv[])
outs.stream = stdout;
#ifdef MALLOCDEBUG
/* this sends all memory debug messages to a logfile named memdump */
curl_memdebug("memdump");
#endif
memset(&config, 0, sizeof(struct Configurable));
/* set non-zero default values: */
config.useragent= maprintf(CURL_NAME "/" CURL_VERSION " (" OS ") "
"%s", curl_version());
config.showerror=TRUE;
config.conf=CONF_DEFAULT;
#if 0
@@ -1229,6 +1259,12 @@ int main(int argc, char *argv[])
helpf("no URL specified!\n");
return CURLE_FAILED_INIT;
}
if(NULL == config.useragent) {
/* set non-zero default values: */
snprintf(useragent, sizeof(useragent),
CURL_NAME "/" CURL_VERSION " (" OS ") " "%s", curl_version());
config.useragent= useragent;
}
#if 0
fprintf(stderr, "URL: %s PROXY: %s\n", url, config.proxy?config.proxy:"none");
#endif
@@ -1500,7 +1536,11 @@ int main(int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_TIMEVALUE, config.condtime);
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, config.customrequest);
curl_easy_setopt(curl, CURLOPT_STDERR, config.errors);
curl_easy_setopt(curl, CURLOPT_WRITEINFO, config.writeout);
/* three new ones in libcurl 7.3: */
curl_easy_setopt(curl, CURLOPT_HTTPPROXYTUNNEL, config.proxytunnel);
curl_easy_setopt(curl, CURLOPT_INTERFACE, config.iface);
curl_easy_setopt(curl, CURLOPT_KRB4LEVEL, config.krb4level);
if((config.progressmode == CURL_PROGRESS_BAR) &&
!(config.conf&(CONF_NOPROGRESS|CONF_MUTE))) {
@@ -1513,6 +1553,10 @@ int main(int argc, char *argv[])
res = curl_easy_perform(curl);
if(config.writeout) {
ourWriteOut(curl, config.writeout);
}
/* always cleanup */
curl_easy_cleanup(curl);
@@ -1554,6 +1598,9 @@ int main(int argc, char *argv[])
printf("--%s--\n", MIMEseparator);
#endif
/* cleanup memory used for URL globbing patterns */
glob_cleanup(urls);
curl_slist_free_all(config.quote); /* the checks for config.quote == NULL */
curl_slist_free_all(config.postquote); /* */
curl_slist_free_all(config.headers); /* */

View File

@@ -45,6 +45,10 @@
#include <curl/curl.h>
#include "urlglob.h"
#ifdef MALLOCDEBUG
#include "../lib/memdebug.h"
#endif
char glob_buffer[URL_MAX_LENGTH];
URLGlob *glob_expand;
@@ -218,6 +222,24 @@ int glob_url(URLGlob** glob, char* url, int *urlnum)
return CURLE_OK;
}
void glob_cleanup(URLGlob* glob) {
int i, elem;
for (i = glob->size - 1; i >= 0; --i) {
if (!(i & 1)) { /* even indexes contain literals */
free(glob->literal[i/2]);
} else { /* odd indexes contain sets or ranges */
if (glob->pattern[i/2].type == UPTSet) {
for (elem = glob->pattern[i/2].content.Set.size - 1; elem >= 0; --elem) {
free(glob->pattern[i/2].content.Set.elements[elem]);
}
free(glob->pattern[i/2].content.Set.elements);
}
}
}
free(glob);
}
char *next_url(URLGlob *glob)
{
static int beenhere = 0;

View File

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

View File

@@ -38,12 +38,14 @@
* ------------------------------------------------------------
****************************************************************************/
#include "setup.h"
#include <stdio.h>
#include <string.h>
#include "strequal.h"
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>
#include <curl/mprintf.h>
#include "writeout.h"
typedef enum {
@@ -57,6 +59,8 @@ typedef enum {
VAR_SPEED_DOWNLOAD,
VAR_SPEED_UPLOAD,
VAR_HTTP_CODE,
VAR_HEADER_SIZE,
VAR_REQUEST_SIZE,
VAR_EFFECTIVE_URL,
VAR_NUM_OF_VARS /* must be the last */
} replaceid;
@@ -74,6 +78,8 @@ static struct variable replacements[]={
{"time_namelookup", VAR_NAMELOOKUP_TIME},
{"time_connect", VAR_CONNECT_TIME},
{"time_pretransfer", VAR_PRETRANSFER_TIME},
{"size_header", VAR_HEADER_SIZE},
{"size_request", VAR_REQUEST_SIZE},
{"size_download", VAR_SIZE_DOWNLOAD},
{"size_upload", VAR_SIZE_UPLOAD},
{"speed_download", VAR_SPEED_DOWNLOAD},
@@ -81,10 +87,14 @@ static struct variable replacements[]={
{NULL}
};
void WriteOut(struct UrlData *data)
void ourWriteOut(CURL *curl, char *writeinfo)
{
FILE *stream = stdout;
char *ptr=data->writeinfo;
char *ptr=writeinfo;
char *stringp;
long longinfo;
double doubleinfo;
while(*ptr) {
if('%' == *ptr) {
if('%' == ptr[1]) {
@@ -105,37 +115,65 @@ void WriteOut(struct UrlData *data)
if(strequal(ptr, replacements[i].name)) {
switch(replacements[i].id) {
case VAR_EFFECTIVE_URL:
fprintf(stream, "%s", data->url?data->url:"");
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &stringp))
fputs(stringp, stream);
break;
case VAR_HTTP_CODE:
fprintf(stream, "%03d", data->progress.httpcode);
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &longinfo))
fprintf(stream, "%03d", longinfo);
break;
case VAR_HEADER_SIZE:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_HEADER_SIZE, &longinfo))
fprintf(stream, "%d", longinfo);
break;
case VAR_REQUEST_SIZE:
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_REQUEST_SIZE, &longinfo))
fprintf(stream, "%d", longinfo);
break;
case VAR_TOTAL_TIME:
fprintf(stream, "%.3f", data->progress.timespent);
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_NAMELOOKUP_TIME:
fprintf(stream, "%.3f", tvdiff(data->progress.t_nslookup,
data->progress.start));
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_NAMELOOKUP_TIME,
&doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_CONNECT_TIME:
fprintf(stream, "%.3f", tvdiff(data->progress.t_connect,
data->progress.start));
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_CONNECT_TIME, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_PRETRANSFER_TIME:
fprintf(stream, "%.3f", tvdiff(data->progress.t_pretransfer,
data->progress.start));
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_PRETRANSFER_TIME, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_SIZE_UPLOAD:
fprintf(stream, "%.0f", data->progress.uploaded);
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_SIZE_UPLOAD, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_SIZE_DOWNLOAD:
fprintf(stream, "%.0f", data->progress.downloaded);
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_SPEED_DOWNLOAD:
fprintf(stream, "%.2f", data->progress.dlspeed);
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_SPEED_DOWNLOAD, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
case VAR_SPEED_UPLOAD:
fprintf(stream, "%.2f", data->progress.ulspeed);
if(CURLE_OK ==
curl_easy_getinfo(curl, CURLINFO_SPEED_UPLOAD, &doubleinfo))
fprintf(stream, "%.3f", doubleinfo);
break;
}
break;

View File

@@ -40,8 +40,6 @@
* ------------------------------------------------------------
****************************************************************************/
#include "urldata.h"
void WriteOut(struct UrlData *data);
void ourWriteOut(CURL *curl, char *out);
#endif