Compare commits

..

186 Commits

Author SHA1 Message Date
Daniel Stenberg
e91d167ff8 release: 7.21.0 2010-06-16 13:48:27 +02:00
Yang Tse
88af6fbf98 remove unused 'tmpdata' and 'backup' ftp_parselist_data struct members 2010-06-10 04:46:30 +02:00
Yang Tse
6b6fe2a4d5 replace isprint() with ISPRINT() 2010-06-10 02:33:45 +02:00
Yang Tse
54aca3c5ec ensure that Curl_wildcard_dtor() leaves WildcardData struct zero initialized 2010-06-10 02:30:23 +02:00
Patrick Monnerat
0a9cf4365a ILE/RPG binding updated to current curl.h definitions. 2010-06-09 17:19:58 +02:00
Yang Tse
343c4c7072 code simplification 2010-06-09 16:48:19 +02:00
Yang Tse
6a0d3233ff add Curl_ prefix to conform with cURL naming standards 2010-06-09 15:45:46 +02:00
Yang Tse
d3714b016d Merge branch 'master' of git@github.com:bagder/curl 2010-06-09 01:57:37 +02:00
Yang Tse
da6e992e1d fix compiler warning using curl_socket_t to store socket descriptor 2010-06-09 01:51:46 +02:00
Daniel Stenberg
bb60fe0c1a inet_pton: warnings: use size_t to store pointer deltas 2010-06-08 23:09:42 +02:00
Yang Tse
feecf63a96 avoid redundant work when reusing same connection 2010-06-08 19:29:20 +02:00
Yang Tse
cbdd1cbcde fix function result checking 2010-06-08 16:16:34 +02:00
Daniel Stenberg
b3d7161642 transfer: warning: implicit conversion
There is an implicit conversion from "unsigned long" to "long";
rounding, sign extension, or loss of accuracy may result.

Fixed by an added typecast.
2010-06-08 10:36:06 +02:00
Daniel Stenberg
3b47d231ac TFTP: fix compiler warning
Curl_fillreadbuffer()'s second argument takes an int, so
typecasting to another is a bad idea.
2010-06-08 10:35:06 +02:00
Daniel Stenberg
7977bc3dfa TFTP: fix warning for sendto() usage on non-POSIX systems
Older unixes want an 'int' instead of 'size_t' as the 3rd
argumment so before this change it would cause warnings such as:

There is an implicit conversion from "unsigned long" to "int";
rounding, sign extension, or loss of accuracy may result.
2010-06-08 10:19:39 +02:00
Dan Fandrich
00fdafb0a1 Include Makefile.inc to get the list of source files for Amiga
Signed-off-by: Diego Casorran <dcasorran@gmail.com>
2010-06-07 14:00:16 -07:00
Yang Tse
f737e94164 Curl_updateconninfo() error handling fix 2010-06-07 16:53:31 +02:00
Constantine Sapuntzakis
a0dd9df9ab OpenSSL: fix spurious SSL connection aborts
Was seeing spurious SSL connection aborts using libcurl and
OpenSSL. I tracked it down to uncleared error state on the
OpenSSL error stack - patch attached deals with that.

Rough idea of problem:

Code that uses libcurl calls some library that uses OpenSSL but
don't clear the OpenSSL error stack after an error.

ssluse.c calls SSL_read which eventually gets an EWOULDBLOCK from
the OS. Returns -1 to indicate an error

ssluse.c calls SSL_get_error. First thing, SSL_get_error calls
ERR_get_error to check the OpenSSL error stack, finds an old
error and returns SSL_ERROR_SSL instead of SSL_ERROR_WANT_READ or
SSL_ERROR_WANT_WRITE.

ssluse.c returns an error and aborts the connection

Solution:

Clear the openssl error stack before calling SSL_* operation if
we're going to call SSL_get_error afterwards.

Notes:

This is much more likely to happen with multi because it's easier
to intersperse other calls to the OpenSSL library in the same
thread.
2010-06-05 23:41:58 +02:00
Yang Tse
4724b9d966 replace socklen_t with curl_socklen_t 2010-06-05 15:08:26 +02:00
Frank Meier
8098d9417c getinfo: added *_PRIMARY_PORT, *_LOCAL_IP and *_LOCAL_PORT 2010-06-05 00:31:36 +02:00
Daniel Stenberg
605207a3a6 RELEASE-NOTES: add contributors not mentioned 2010-06-04 16:13:05 +02:00
Yang Tse
43d20d81a5 Enable OpenLDAP support for cygwin builds.
Enable OpenLDAP support for cygwin builds. This support was disabled back
in 2008 due to incompatibilities between OpenSSL and OpenLDAP headers.
cygwin's OpenSSL 0.9.8l and OpenLDAP 2.3.43 versions on cygwin 1.5.25
allow building an OpenLDAP enabled libcurl supporting back to Windows 95.

Remove non-functional CURL_LDAP_HYBRID code and references.
2010-06-04 15:14:31 +02:00
Kamil Dudka
bc0f3dd15e ftplistparser.c: oops, fix typo in the last commit 2010-06-02 23:55:45 +02:00
Kamil Dudka
475c19c42b ftplistparser.c: avoid some invalid dereferences 2010-06-02 23:50:38 +02:00
Kamil Dudka
c072bd4609 lib: eliminate some dead code 2010-06-02 23:50:38 +02:00
Daniel Stenberg
684830cb2a SSH: corrected the inability to respect the timeout
Jason McDonald posted bug report #3006786 when he found that the
SFTP code didn't timeout properly in several places in the code
even if a timeout was set properly.

Based on his suggested patch, I wrote a different implementation
that I think addressed the issue better and also uses the connect
timeout for the initial part of the SSH/SFTP done during the
"protocol connect" phase.

(http://curl.haxx.se/bug/view.cgi?id=3006786)
2010-06-02 23:33:51 +02:00
Yang Tse
51248a9bdd mention last changes 2010-06-02 17:30:45 +02:00
Yang Tse
3b24076c3b add missing new files to non-configure target build files 2010-06-02 15:09:39 +02:00
Yang Tse
077125e4a2 include libcurl standard internal headers 2010-06-02 14:13:02 +02:00
Daniel Stenberg
df06182d86 TODO: add multi interface improvement remove ldap select 2010-06-02 13:53:29 +02:00
Yang Tse
d939e0f410 make setup.h first included file 2010-06-02 13:19:04 +02:00
Yang Tse
69d07feb14 fix spnego memory leak 2010-06-02 12:44:46 +02:00
Yang Tse
1c4538610b openldap header inclusions fix 2010-06-02 11:23:30 +02:00
Daniel Stenberg
2c72732ebf multi_socket: handles timer inaccuracy better for timeouts
Igor Novoseltsev reported a problem with the multi socket API and
using timeouts and timers. It boiled down to a problem with
libcurl's use of GetTickCount() interally to figure out the
current time, while Igor's own application code used another
function call.

It made his app call the socket API timeout function a bit
_before_ libcurl would consider the timeout to trigger, and that
could easily lead to timeouts or stalls in the app. It seems
GetTickCount() in general often has no better resolution than
16ms and switching to the alternative function
QueryPerformanceCounter has its share of problems:
http://www.virtualdub.org/blog/pivot/entry.php?id=106

We address this problem by simply having libcurl treat timers
that already has occured or will occur within 40ms subject for
treatment. I'm confident that there are other implementations and
operating systems with similarly in accurate timer functions so
it makes sense to have applied generically and I don't believe we
sacrifice much by adding a 40ms inaccuracy on these timeouts.
2010-06-01 23:20:16 +02:00
Yang Tse
e1c2c9be1a fix ldaps option issue 2010-06-01 21:26:19 +02:00
Yang Tse
89da532445 fix ldap related compilation issues 2010-06-01 17:25:03 +02:00
Yang Tse
b38189c7b4 fix compiler warning: enumerated type mixed with another type 2010-06-01 12:25:14 +02:00
Yang Tse
1bb04927f3 fix compiler warning: enumerated type mixed with another type 2010-05-31 19:55:22 +02:00
Patrick Monnerat
3fd01be648 smtp_authenticate: avoid compiler warnings 2010-05-31 17:37:00 +02:00
Yang Tse
5ae6db321f fix compiler warning: enumerated type mixed with another type 2010-05-31 17:34:28 +02:00
Yang Tse
0546d448ce fix compiler warning: enumerated type mixed with another type 2010-05-31 17:22:43 +02:00
Yang Tse
b4fa27ae4b fix compiler warning: enumerated type mixed with another type 2010-05-31 17:11:51 +02:00
Yang Tse
12043e3c9c fix compiler warning: external declaration in primary source file 2010-05-31 16:58:24 +02:00
Yang Tse
a324fa7b97 fix compiler warning: variable was set but never used 2010-05-31 16:51:36 +02:00
Yang Tse
a9483b1f4a fix compiler warning: enumerated type mixed with another type 2010-05-31 16:36:05 +02:00
Yang Tse
40f8aaedb7 fix compiler warning: external declaration in primary source file 2010-05-31 16:24:01 +02:00
Yang Tse
374f48675b update year in copyright notice 2010-05-31 13:51:29 +02:00
Kamil Dudka
20ae9d4f71 strtoofft: rename CURL_LLONG_MIN -> CURL_OFF_T_MIN
... and CURL_LLONG_MAX -> CURL_OFF_T_MAX
2010-05-29 21:28:16 +02:00
Kamil Dudka
35955179c6 CURL_LLONG_MAX: avoid constant overflow
... when (CURL_SIZEOF_CURL_OFF_T == 4)
2010-05-29 21:23:18 +02:00
Howard Chu
b1c1b9bb76 LDAPS: list availability depending on SSL's presence 2010-05-28 12:23:28 +02:00
Howard Chu
123f80ae54 LDAP: make it build without SSL if no such support is available
of course it also goes for the case where SSL is explicitly
disabled
2010-05-28 12:22:35 +02:00
Daniel Stenberg
c54ab4dca7 TODO: removed fixed items
These two items are now actually implemented:

11.1 Content-Disposition
11.5 ftp wildcard download
2010-05-28 11:57:49 +02:00
Kamil Dudka
233ec511db lib: eliminate 'statement not reached' warnings 2010-05-28 09:45:17 +02:00
Daniel Stenberg
4b96e5c70f test1115: verify that unexpected 1xx responses work fine 2010-05-28 00:55:11 +02:00
Kamil Dudka
75743b009b lib577: avoid redefinition of ERROR 2010-05-28 00:50:11 +02:00
Kamil Dudka
01459828ef test313: a new test for CRL support 2010-05-27 23:45:18 +02:00
Kamil Dudka
99179da4cc tests/certs: re-generated because of lost pass-phrase 2010-05-27 23:39:54 +02:00
Kamil Dudka
645bdd837a tests/certs/scripts: generate also CRL
... and make it possible to do so without any user interaction
2010-05-27 23:33:19 +02:00
Howard Chu
c03cbb38ad openldap: fix compiler warnings 2010-05-27 22:37:38 +02:00
Daniel Stenberg
63661d8e83 indent: some whitespace edits 2010-05-27 22:37:38 +02:00
Kamil Dudka
4a0493f789 wildcard.c: add missing include of "setup.h" 2010-05-27 20:56:01 +02:00
Tor Arntsen
eadeb5bd9a lib573: do not compare double for exact match 2010-05-27 20:20:08 +02:00
Pavel Raiskup
9190e2876e wildcard.c: add missing include of "curl_memory.h" 2010-05-27 18:41:29 +02:00
Tor Arntsen
b4f0e1291f setup_once: use enum type for 'bool' on non-C99 platforms
An enum will catch non-bool assignments to bool on platforms with
a strict compiler, e.g MIPSPro.

Signed-off-by: Kamil Dudka <kdudka@redhat.com>
2010-05-27 18:15:17 +02:00
Kamil Dudka
dd8568739c url.c: avoid implied cast to bool 2010-05-27 16:35:31 +02:00
Tor Arntsen
97b497a75f curl_fnmatch: remove use of register keyword
Using the 'register' keyword rarely improves anything with modern
compilers and architectures.
2010-05-27 16:34:57 +02:00
Julien Chaffraix
d3c813e726 RTMP: Fix compiler warnings 2010-05-26 00:41:45 +02:00
Julien Chaffraix
9e480973eb OOM fixes in http_negociate.c and lib/splay.c
Fix 2 OOM errors: a missing NULL-check in lib/http_negociate.c
and a potential NULL dereferencing in lib/splay.c
2010-05-26 00:40:26 +02:00
Howard Chu
2e056353b0 LDAP: properly implemented as a curl_handler
makes the LDAP code much cleaner, nicer and in general being a
better libcurl citizen. If a new enough OpenLDAP version is
detect, the new and shiny lib/openldap.c code is then used
instead of the old cruft

Code by Howard, minor cleanups by Daniel.
2010-05-25 00:44:42 +02:00
Tor Arntsen
606b933a4f curl_fnmatch: Use int not bool when function returns int
bool in curl internals is unsigned char and should not be used
to receive return value from functions returning int - this fails
when using IBM VisualAge and Tru64 compilers.
2010-05-21 23:42:55 +02:00
Daniel Stenberg
d17709da31 TFTP: send legal timeout value
Eric Mertens posted bug #3003705: when we made TFTP use the
correct timeout option when sent to the server (fixed May 18th
2010) it became obvious that libcurl used invalid timeout values
(300 by default while the RFC allows nothing above 255). While of
course it is obvious that as TFTP has worked thus far without
being able to set timeout at all, just removing the setting
wouldn't make any difference in behavior. I decided to still keep
it (but fix the problem) as it now actually allows for easier
(future) customization of the timeout.

(http://curl.haxx.se/bug/view.cgi?id=3003705)
2010-05-21 23:29:52 +02:00
Daniel Stenberg
0bb6deda72 TFTP: don't ack if wrong block num is received
If an unexpected block number was received, break out of the
switch loop.
2010-05-21 23:07:59 +02:00
Daniel Stenberg
0a29e2445c TFTP: block id wrap bug fix
In a normal expression, doing [unsigned short] + 1 will not wrap
at 16 bits so the comparisons and outputs were done wrong. I
added a macro do make sure it gets done right.

Douglas Kilpatrick filed bug report #3004787 about it:
http://curl.haxx.se/bug/view.cgi?id=3004787
2010-05-21 23:04:15 +02:00
Ben Greear
700335103e Fix build warnings.
Signed-off-by: Ben Greear <greearb@candelatech.com>
2010-05-20 23:16:46 +02:00
Ben Greear
368fd5d27b setopt: Fix setting of set.is_fwrite_set
Signed-off-by: Ben Greear <greearb@candelatech.com>
2010-05-20 23:15:34 +02:00
Tanguy Fautre
81239edb89 build: allow curl to build with Microsoft VC10
By undefing a bunch of E* defines that VC10 has started to define
but that we redefine internally to their WSA* alternatives when
building for Windows.
2010-05-20 22:40:48 +02:00
Tor Arntsen
22f3b01478 Test 573: Use correct type for CURLINFO_CONNECT_TIME
curl_easy_getinfo() called with a pointer to long instead of double
would sigbus on RISC processors (e.g. MIPS) due to wrong alignment
of pointer address.
2010-05-20 17:12:53 +02:00
Tor Arntsen
5f53c9d94a lib: Fix AIX build failure 2010-05-19 22:09:35 +02:00
Dan Fandrich
04cfef24a1 Fixed some memory leaks in the POP3 torture tests 2010-05-19 12:18:06 -07:00
Dan Fandrich
1d26151d5f Fixed a memory leak in the SMTP torture tests 2010-05-18 14:44:19 -07:00
Daniel Stenberg
aabd27d9aa TFTP: send timeout option correctly
Eric Mertens posted bug report #3003005 pointing out that the
libcurl TFTP code was not sending the timeout option properly to
the server, and suggested a fix.

(http://curl.haxx.se/bug/view.cgi?id=3003005)
2010-05-18 23:14:00 +02:00
Tor Arntsen
dcc061543a lib: Change some CRLF line endings to LF
An update had added a couple of lines with DOS line endings,
and some compilers will choke on that (e.g. the Tru64 compiler).
2010-05-16 22:34:02 +02:00
Kamil Dudka
2ffe834bff ftp wildcard: a new option CURLOPT_FNMATCH_DATA 2010-05-16 02:52:33 +02:00
Howard Chu
027ceb37a1 RMTP: the version code is now rtmp aware 2010-05-15 22:13:17 +02:00
Howard Chu
510836f80b RTMP: fix wrong #ifdef 2010-05-15 22:02:44 +02:00
Pavel Raiskup
e4af5d6efc ftp wildcard: fix int32_t and size/group mixups 2010-05-15 21:58:50 +02:00
Dan Fandrich
43b816538f Fixed test 577 to work when --enable-hidden-symbols is configured 2010-05-14 14:42:58 -07:00
Daniel Stenberg
77cfeadfa6 OpenSSL: multi interface handshake could hang
John-Mark Bell filed bug #3000052 that identified a problem (with
an associated patch) with the OpenSSL handshake state machine
when the multi interface is used:

Performing an https request using a curl multi handle and using
select or epoll to wait for events results in a hang. It appears
that the cause is the fix for bug #2958179, which makes
ossl_connect_common unconditionally return from the step 2 loop
when fetching from a multi handle.

When ossl_connect_step2 has completed, it updates
connssl->connecting_state to ssl_connect_3. ossl_connect_common
will then return to the caller, as a multi handle is in
use. Eventually, the client code will call curl_multi_fdset to
obtain an updated fdset to select or epoll on. For https
requests, curl_multi_fdset will cause https_getsock to be called.
https_getsock will only return a socket handle if the
connecting_state is ssl_connect_2_reading or
ssl_connect_2_writing.  Therefore, the client will never obtain a
valid fdset, and thus not drive the multi handle, resulting in a
hang.

(http://curl.haxx.se/bug/view.cgi?id=3000052)
2010-05-14 22:35:08 +02:00
Daniel Stenberg
ea521cf617 changelog: add link to bug report 2010-05-14 22:35:08 +02:00
Dan Fandrich
a82c5a39c4 Added directories.pm to the source tar ball 2010-05-14 13:31:07 -07:00
Daniel Stenberg
7764795c06 follow redirect: ignore response-body on redirect even if compressed
Sebastian V reported bug #3000056 identifying a problem with
redirect following. It showed that when curl followed redirects
it didn't properly ignore the response body of the 30X response
if that response was using compressed Content-Encoding!

(http://curl.haxx.se/bug/view.cgi?id=3000056)
2010-05-14 22:12:07 +02:00
Daniel Stenberg
d6706294e0 version: we're now going for 7.21.0 2010-05-14 20:55:54 +02:00
Hoi-Ho Chan
83305cbf9f Remove support for BSD version of PolarSSL
"The BSD version of PolarSSL was made for migratory purposes only and is not
maintained. The GPL version of PolarSSL is actually the only actively
developed version, so I would be very reluctant to use the BSD version." /
Paul Bakker, PolarSSL hacker.

Signed-off-by: Hoi-Ho Chan <hoiho.chan@gmail.com>
2010-05-13 21:50:52 +02:00
Dan Fandrich
76255cfdc9 Added Polar SSL and RTMP files to the non-autoconf build files
I didn't bother with a few that have little hope of running the required
dependent libraries.
2010-05-12 19:05:58 -07:00
Dan Fandrich
ad6bc4d82e Added the new ftp source files to the non-autoconf build files 2010-05-12 17:32:10 -07:00
Dan Fandrich
147609ca6e Copy the license file so it's seen by the Android build system 2010-05-12 15:23:28 -07:00
Daniel Stenberg
7871fbad4d updated with symbols added in recent commits for 7.21.0 2010-05-13 00:07:37 +02:00
Daniel Stenberg
46b9719bbb changelogs: mention RTMP and the FTP wildcard support 2010-05-13 00:00:55 +02:00
Daniel Stenberg
a1a98d5908 ftp wildcards: mention they're added in 7.21.0 2010-05-12 23:59:11 +02:00
Daniel Stenberg
a799162bc7 style: minor whitespace change 2010-05-12 23:32:42 +02:00
Daniel Stenberg
d62ce21249 syntax: cleanups 2010-05-12 23:18:22 +02:00
Pavel Raiskup
0825cd80a6 FTP: WILDCARDMATCH/CHUNKING/FNMATCH added 2010-05-12 23:17:51 +02:00
Howard Chu
04cb15ae9d RTMP: initial support added, powered by librtmp
librtmp is found at http://rtmpdump.mplayerhq.hu/
2010-05-12 23:07:20 +02:00
Howard Chu
bc8fc9803f sendrecv: make them two pairs of send/recv to properly deal with FTPS
FTP(S) use two connections that can be set to different recv and
send functions independently, so by introducing recv+send pairs
in the same manner we already have sockets/connections we can
work with FTPS fine.

This commit fixes the FTPS regression introduced in change d64bd82.
2010-05-11 22:48:38 +02:00
Kamil Dudka
016ce4b1da changelog: fixed CRL support in libcurl-NSS 2010-05-11 14:53:07 +02:00
Kamil Dudka
3e759f4fb6 nss: make it possible to read ASCII and DER CRL 2010-05-11 14:39:08 +02:00
Kamil Dudka
2e8b21833a nss: add CRL to cache instead of read-only NSS db 2010-05-11 14:37:43 +02:00
Daniel Stenberg
54b0e87796 git: how to write a fine commit message 2010-05-10 17:25:49 +02:00
Daniel Stenberg
a784ed6065 findtool: file name as a full path requires a slash
Kalle Vahlman's patch applied a while ago broke how the findtool
function searches for tools, as it would always check if "$file"
was present first, which thus made the bad assumption that a file
in the current directory would be a match.

I noticed when it found 'libtool' in the current directory but
libtoolize is not there, which confused the script.
2010-05-09 23:16:37 +02:00
Hacki
d2621445f1 moved vars into conditional since seems that winsock implementation doesnt use them. 2010-05-08 05:38:42 +02:00
Daniel Stenberg
adaf87530d multi interface: missed storing connection time
Dirk Manske reported a regression. When connecting with the multi
interface, there were situations where libcurl wouldn't store
connect time correctly as it used to (and is documented to) do.

Using his fine sample program we could repeat it, and I wrote up
test case 573 using that code. The problem does not easily show
itself using the local test suite though.

The fix, also as suggested by Dirk, is a bit on the ugly side as
it adds yet another call to Curl_verboseconnect() and setting the
TIMER_CONNECT time.  That situation is subject for some closer
inspection in the future.
2010-05-07 23:49:29 +02:00
Daniel Stenberg
8914857092 verboseconnect: so the verbose checking within the function
As the function is used more than once and libcurl can be built
without it, do the conditional check within the verboseconnect()
function itself.
2010-05-07 23:24:47 +02:00
Daniel Stenberg
aca0fff4e1 changelogs: split the I/O handling 2010-05-07 15:53:55 +02:00
Howard Chu
d64bd82bdc sendrecv: split the I/O handling into private handler
Howard Chu brought the bulk work of this patch that properly
moves out the sending and recving of data to the parts of the
code that are properly responsible for the various ways of doing
so.

Daniel Stenberg assisted with polishing a few bits and fixed some
minor flaws in the original patch.

Another upside of this patch is that we now abuse CURLcodes less
with the "magic" -1 return codes and instead use CURLE_AGAIN more
consistently.
2010-05-07 15:05:34 +02:00
Daniel Stenberg
cb6647ce1c changelog: PolarSSL 2010-05-05 22:36:15 +02:00
Hoi-Ho Chan
51427e1947 PolarSSL: initial support added
This is Hoi-Ho Chan's patch with some minor fixes by me. There
are some potential issues in this, but none worse than we can
sort out on the list and over time.
2010-05-05 22:30:46 +02:00
Daniel Stenberg
1de6b97a76 TODO: we've done PRET already, consider HOST for the future
... and GnuTLS connects are non-blocking, TFTP is better
integrated as a "real" protocol and RTSP is supported.
2010-04-29 23:32:33 +02:00
Daniel Stenberg
f09340de8b TODO: GnuTLS connects are now non-blocking
Since commit c288860 by Jerome Vouillon
2010-04-29 23:23:42 +02:00
Daniel Stenberg
82b55efdba INTERNALS: tftp is decent now, ldap is not
It's not quite fair to list TFTP is a "crappy" member of the
libcurl family so I removed its mentioning.
2010-04-29 21:57:41 +02:00
Daniel Stenberg
16f575ee6c changelog: mention Ben Greear's telnet work 2010-04-29 09:40:48 +02:00
Ben Greear
38d2afcefb telnet: Allow programatic use of telnet.
The main change is to allow input from user-specified methods,
when they are specified with CURLOPT_READFUNCTION.
All calls to fflush(stdout) in telnet.c were removed, which makes
using 'curl telnet://foo.com' painful since prompts and other data
are not always returned to the user promptly.  Use
'curl --no-buffer telnet://foo.com' instead.  In general,
the user should have their CURLOPT_WRITEFUNCTION do a fflush
for interactive use.

Also fix assumption that reading from stdin never returns < 0.
Old code could crash in that case.

Call progress functions in telnet main loop.

Signed-off-by: Ben Greear <greearb@candelatech.com>
2010-04-29 08:55:11 +02:00
Daniel Stenberg
7f616eb513 test: enable valgrind for 604, seems to work 2010-04-28 23:27:31 +02:00
Paul Howarth
fe818c8076 add 1s post-command delay to tests 513 and 514
addressing http://curl.haxx.se/mail/lib-2009-12/0031.html
2010-04-28 23:21:59 +02:00
Kalle Vahlman
a7b9452a6b Allow tools to be defined with full path in buildconf
This is required in Scratchbox where
LIBTOOL=/targets/links/arch_tools/bin/libtool
is set in the environment.
2010-04-26 15:54:09 +02:00
Daniel Stenberg
2c1b0624ac progress callback: can be called more than once per sec 2010-04-26 15:38:07 +02:00
Daniel Stenberg
107146676e SSH: init and cleanup libssh2 in global_init/cleanup
The necessary libssh2 functions require libssh2 1.2.5 or later.
2010-04-26 00:36:25 +02:00
Daniel Stenberg
79dc74e84d new configure option --enable-threaded-resolver 2010-04-25 23:24:05 +02:00
Daniel Stenberg
6be508dcc2 configure: check for libssh2_init and libssh2_exit 2010-04-25 23:06:41 +02:00
Kamil Dudka
82e9b78a38 nss: fix SSL handshake timeout underflow 2010-04-24 23:23:01 +02:00
Guenter Knauf
07f45946b5 encourage users to take latest lib dependencies. 2010-04-24 17:48:09 +02:00
Daniel Stenberg
7fb7f24131 socks5: please static code analyzer
Make sure we don't call memcpy() if the argument is NULL even
though we also passed a zero length then, as the clang analyzer
whined and we want to limit warnings (even false positives) when
they're this easy to fix.

The change of (char) to (unsigned char) will fix long user names
and passwords on systems that have the char type signed by
default.
2010-04-24 12:40:00 +02:00
Daniel Stenberg
5b40c11c2f gzip: Value stored to 'data' is never read 2010-04-24 12:37:11 +02:00
Daniel Stenberg
9d6a394c44 RELEASE-NOTES: update top numbers 2010-04-24 12:23:47 +02:00
Daniel Stenberg
d7b82baf97 changelog: added the --proto and -proto-redir options 2010-04-24 12:19:42 +02:00
Alex Bligh
36e245658b curl: added --proto and --proto-redir
--proto tells curl to use the listed protocols for its initial
retrieval

--proto-redir tells curl to use the listed protocols after a
redirect
2010-04-24 12:18:04 +02:00
Kamil Dudka
d487ade72c test536: do not fail with threaded DNS resolver
Also tweaked comments in certain examples using curl_multi_fdset().
2010-04-24 12:14:21 +02:00
Daniel Stenberg
71be565cf4 curl: -O crash on windows
The -O option caused curl to crash on windows and DOS due to the
tool writing out of boundary memory.
2010-04-21 23:20:18 +02:00
Yang Tse
81512cc02b hmac.c related compilation adjustment 2010-04-20 21:35:31 +02:00
Yang Tse
32236dad5e hmac.c related compilation adjustment 2010-04-20 21:23:53 +02:00
monnerat
b30ce34d84 Add compilation directives for hmac in Watcom,riscos and vc6 platform-specific makefiles. 2010-04-20 19:23:48 +02:00
Ruslan Gazizov
2164b6b463 replaced wsock32.lib usage with ws2_32.lib in MSVC makefiles 2010-04-20 16:30:10 +02:00
monnerat
7af5e3c39e Merge branch 'master' of github.com:bagder/curl 2010-04-19 17:37:51 +02:00
monnerat
42930155ab Remove null-effect leftover code. 2010-04-19 17:30:20 +02:00
Daniel Stenberg
e5b3246d0a changelog: -J/--remote-header-name strips CRLF 2010-04-19 17:08:27 +02:00
Daniel Stenberg
47dda4a1d4 parse_filename: strip trailing CRs and LFs
The feature that uses the file name given in a
Content-disposition: header didn't properly skip trailing
carriage returns and linefeed characters from the end of the file
name when it was given without quotes.
2010-04-19 17:05:46 +02:00
Daniel Stenberg
a5b7e3205d Curl_HMAC_MD5: fix the array init to not warn with picky compilers 2010-04-19 16:19:36 +02:00
monnerat
dfce37da23 Fix GnuTLS compilation problem in md5.c 2010-04-19 14:09:45 +02:00
monnerat
14bfcb96f5 Fix compilation problem: declare Curl_HMAC_MD5 as extern in include file. 2010-04-19 12:44:17 +02:00
monnerat
87fbcb4494 Merge branch 'master' of github.com:bagder/curl 2010-04-19 11:17:46 +02:00
monnerat
4bfe07640c Implement SMTP authentication 2010-04-19 11:16:30 +02:00
Daniel Stenberg
5d93525f30 parseconfig: Value stored to 'line' is never read
Make the function call with (void) as we don't care about the
return code.
2010-04-17 18:59:54 +02:00
Daniel Stenberg
b7848e4a72 parsedate: Value stored to 'found' is never read 2010-04-17 18:57:39 +02:00
Daniel Stenberg
99ec359b4d check_gzip_header: Value stored to 'data' is never read 2010-04-17 18:55:52 +02:00
Daniel Stenberg
dfad8a6dad dprintf_formatf: Value stored to 'left' is never read 2010-04-16 23:50:39 +02:00
Daniel Stenberg
d841ab82b8 curl_version: remove superfluous assignments 2010-04-16 23:49:03 +02:00
Daniel Stenberg
d6be52d80e FTP PORT: Value stored to 'rc' is never read 2010-04-16 23:45:05 +02:00
Daniel Stenberg
c0111460b0 Curl_setup_transfer: no longer returns anything
This function could only return CURLE_OK and by changing it to
a void instead, we can simplify code all over.
2010-04-16 23:43:04 +02:00
Daniel Stenberg
93981bb9b5 PASV response: Value stored to 'rc' is never read 2010-04-16 23:28:20 +02:00
Daniel Stenberg
8f136288c5 Curl_perform: Value stored to 'res2' is never read 2010-04-16 23:27:35 +02:00
Daniel Stenberg
9799dbebd6 sftp range: remove unnecessary check for NULL pointer 2010-04-16 23:20:50 +02:00
Daniel Stenberg
b025ac16a6 ftp_range: remove unnecessary check for NULL pointer 2010-04-16 23:20:07 +02:00
Daniel Stenberg
5d43c75c66 file_range: remove unnecessary check for NULL pointer 2010-04-16 23:18:43 +02:00
Daniel Stenberg
15fa5dcfe6 SOCKS4: Value stored to 'rc' is never read 2010-04-16 23:03:55 +02:00
Daniel Stenberg
516dfd1705 FTP PASV: Value stored to 'rc' is never read 2010-04-16 23:02:15 +02:00
Daniel Stenberg
743bd81e64 ftp_range: Value stored to 'totalsize' is never read
Simplified the code by removing a local variable completely.
2010-04-16 23:00:21 +02:00
Daniel Stenberg
520cee3fb7 SOCKS5: when name resolves fail return immediately
This makes the code flow more obvious and reacts on the return
code properly, even if the code acted the same way before.
2010-04-16 22:58:04 +02:00
Daniel Stenberg
fa7341143a POP3: when USER command fails, don't even try PASS 2010-04-16 22:56:13 +02:00
Daniel Stenberg
313a5b05c2 tftp_rx: Value stored to 'sbytes' is never read 2010-04-16 22:55:07 +02:00
Daniel Stenberg
01fc53e027 file_range: Value stored to 'totalsize' is never read 2010-04-16 22:52:49 +02:00
Daniel Stenberg
0a4ccce054 changelog: GnuTLS: SSL handshake phase is non-blocking 2010-04-16 22:45:06 +02:00
Jerome Vouillon
c2888604d7 GnuTLS: make the connection phase non-blocking
When multi interface is used, the SSL handshake is no longer
blocking when GnuTLS is used.
2010-04-16 22:43:01 +02:00
Daniel Stenberg
6632d957e7 krb5_auth: fix my previous change to compile 2010-04-16 20:22:46 +02:00
unknown
c5e539c312 OS400 version V5R2M0 not supported anymore by IBM: default target release changed to V5R3M0. 2010-04-16 16:55:13 +02:00
Daniel Stenberg
0338994c6a changelog: GnuTLS fix, no reverse loopkups and fixed GSS detection 2010-04-16 15:33:10 +02:00
Daniel Stenberg
2056ca9fea SSL_RECV: EOF is not an error here
The recent overhaul of the SSL recv function made this treat a
zero returned from gnutls_record_recv() as an error, and this
caused our HTTPS test cases to fail. We leave it to upper layer
code to detect if an EOF is a problem or not.
2010-04-16 15:29:25 +02:00
Paul Howarth
cca192e58f configure: GSSAPI detection on ancient Linux distros
On some ancient distributions such as RHEL-3, <gssapi/gssapi_krb5.h> needs
to be processed after <gssapi/gssapi.h>, but does not include it itself.
This patch checks for <gssapi/gssapi.h> first and then includes it
in the test for <gssapi/gssapi_krb5.h>, resolving the problem.

Without the patch, <gssapi/gssapi_krb5.h> is "present but cannot be
compiled".
2010-04-16 15:09:32 +02:00
Daniel Stenberg
f3d4b17a9c resolvers: no more using AI_CANONNAME
No resolver anymore needs to use AI_CANONNAME and do reverse
lookups.  We should work hard to avoid having code that relies on
it.
2010-04-16 15:03:52 +02:00
Daniel Stenberg
5bd38b70dd KRB5: use given host name instead of reverse lookup'ed name
This code would previously use dns_entry->addr->ai_canonname
instead of the given host name, which caused us grief and
problems since not all our resolver options do the reverse lookup
and I would also guess that it caused problems with KRB5/GSS with
virtual name-based hosts. Now the host name from the URL is used.
2010-04-16 15:02:08 +02:00
Dan Fandrich
44f1bef668 Remove redundant conditional 2010-04-15 10:51:03 -07:00
Dan Fandrich
f38510f4b5 Eliminated an unlikely race condition in some tests.
Based on a patch from the FreeBSD ports by Peter Pentchev.
2010-04-15 10:51:03 -07:00
Daniel Stenberg
689b6929c3 changelog: prevent needless reverse name lookups 2010-04-15 13:11:25 +02:00
Daniel Stenberg
68aae7f579 Curl_ipv4_resolve_r: only set AI_CANONNAME when needed
As reported in bug report #2987196, the code for ipv6 already did
the setting of this bit correctly so we copied that logic into
the Curl_ipv4_resolve_r() function as well. KRB code is the only
code we know that might need the cannonical name so only resolve
it for such requests!
2010-04-15 13:04:01 +02:00
Daniel Stenberg
a76fa17681 IGNORE: files generated by maketgz 2010-04-14 17:34:57 +02:00
Daniel Stenberg
72411118ec bumped to start the journey towards 7.20.2 2010-04-14 17:34:26 +02:00
Daniel Stenberg
5a16df5e04 added contributors from the 7.20.1 RELEASE-NOTES 2010-04-14 17:33:34 +02:00
Daniel Stenberg
5a814f6f2c ignore files generated by 'maketgz' 2010-04-14 17:12:34 +02:00
189 changed files with 9368 additions and 1808 deletions

4
.gitignore vendored
View File

@@ -5,6 +5,7 @@
*.dll
*.exe
*.obj
*.asc
.*.swp
Debug
Release
@@ -26,6 +27,9 @@ curl-config
libcurl.pc
missing
curl-*.tar.gz
curl-*.tar.bz2
curl-*.tar.lzma
curl-*.zip
INSTALL
install-sh
*.o

View File

@@ -2,7 +2,7 @@
#
# Place the curl source (including this makefile) into external/curl/ in the
# Android source tree. Then build them with 'make curl' or just 'make libcurl'
# from the Android root. Tested with Android 1.5
# from the Android root. Tested with Android 1.5 and 2.1
#
# Note: you must first create a curl_config.h file by running configure in the
# Android environment. The only way I've found to do this is tricky. Perform a
@@ -26,12 +26,15 @@
# PATH="$A/prebuilt/linux-x86/toolchain/arm-eabi-X/bin:$PATH" \
# ./configure --host=arm-linux CC=arm-eabi-gcc \
# CPPFLAGS="-I $A/system/core/include ..." \
# CFLAGS="-fno-exceptions -Wno-multichar ..." \
# CFLAGS="-nostdlib -fno-exceptions -Wno-multichar ..." \
# LIB="$A/prebuilt/linux-x86/toolchain/arm-eabi-X/lib/gcc/arm-eabi/X\
# /interwork/libgcc.a ..." \
#
# Finally, copy the file COPYING to NOTICE so that the curl license gets put
# into the right place (see the note about this below).
#
# Dan Fandrich
# September 2009
# May 2010
LOCAL_PATH:= $(call my-dir)
@@ -63,6 +66,14 @@ LOCAL_COPY_HEADERS := $(addprefix include/curl/,$(CURL_HEADERS))
LOCAL_MODULE:= libcurl
# Copy the licence to a place where Android will find it.
# Actually, this doesn't quite work because the build system searches
# for NOTICE files before it gets to this point, so it will only be seen
# on subsequent builds.
ALL_PREBUILT += $(LOCAL_PATH)/NOTICE
$(LOCAL_PATH)/NOTICE: $(LOCAL_PATH)/COPYING | $(ACP)
$(copy-file-to-target)
include $(BUILD_STATIC_LIBRARY)
@@ -79,8 +90,8 @@ LOCAL_SYSTEM_SHARED_LIBRARIES := libc
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include $(LOCAL_PATH)/lib
# This will also need to include $(CURLX_ONES) in order to correctly build
# a dynamic library
# This will also need to include $(CURLX_ONES) in order to correctly link
# against a dynamic library
LOCAL_CFLAGS += $(common_CFLAGS)
include $(BUILD_EXECUTABLE)

259
CHANGES
View File

@@ -6,6 +6,265 @@
Changelog
Version 7.21.0 (16 June 2010)
Daniel Stenberg (5 June 2010)
- Constantine Sapuntzakis fixed a case of spurious SSL connection aborts using
libcurl and OpenSSL. "I tracked it down to uncleared error state on the
OpenSSL error stack - patch attached deals with that."
Daniel Stenberg (5 June 2010)
- Frank Meier added CURLINFO_PRIMARY_PORT, CURLINFO_LOCAL_IP and
CURLINFO_LOCAL_PORT to curl_easy_getinfo().
Yang Tse (4 June 2010)
- Enabled OpenLDAP support for cygwin builds. This support was disabled back
in 2008 due to incompatibilities between OpenSSL and OpenLDAP headers.
cygwin's OpenSSL 0.9.8l and OpenLDAP 2.3.43 versions on cygwin 1.5.25
allow building an OpenLDAP enabled libcurl supporting back to Windows 95.
Removed the non-functional CURL_LDAP_HYBRID code and references.
Daniel Stenberg (2 June 2010)
- Jason McDonald posted bug report #3006786 when he found that the SFTP code
didn't timeout properly in several places in the code even if a timeout was
set properly.
Based on his suggested patch, I wrote a different implementation that I
think addressed the issue better and also uses the connect timeout for the
initial part of the SSH/SFTP done during the "protocol connect" phase.
(http://curl.haxx.se/bug/view.cgi?id=3006786)
Yang Tse (2 June 2010)
- Added missing new libcurl files to non-configure targets. Adjusted
libcurl standard internal header inclusions in new files. Fixed an
SPNEGO related memory leak. Fixed several LDAP related compilation
issues, and fixed some compiler warnings.
Daniel Stenberg (1 June 2010)
- Igor Novoseltsev reported a problem with the multi socket API and using
timeouts and timers. It boiled down to a problem with libcurl's use of
GetTickCount() interally to figure out the current time, while Igor's own
application code used another function call.
It made his app call the socket API timeout function a bit _before_ libcurl
would consider the timeout to trigger, and that could easily lead to
timeouts or stalls in the app. It seems GetTickCount() in general often has
no better resolution than 16ms and switching to the alternative function
QueryPerformanceCounter has its share of problems:
http://www.virtualdub.org/blog/pivot/entry.php?id=106
We address this problem by simply having libcurl treat timers that already
has occured or will occur within 40ms subject for treatment. I'm confident
that there are other implementations and operating systems with similarly in
accurate timer functions so it makes sense to have applied generically and I
don't believe we sacrifice much by adding a 40ms inaccuracy on these
timeouts.
Kamil Dudka (27 May 2010)
- added a new test for CRL support (test313)
- Tor Arntsen changed the alternative definition of bool to use enum instead
of unsigned char.
Daniel Stenberg (25 May 2010)
- Julien Chaffraix fixed the warning seen when compiling lib/rtmp.c: one
unused variables, several unused arguments and some missing #include.
- Julien Chaffraix fixed 2 OOM errors: a missing NULL-check in
lib/http_negociate.c and a potential NULL dereferencing in lib/splay.c
- Howard Chu brought a patch that makes the LDAP code much cleaner, nicer and
in general being a better libcurl citizen. If a new enough OpenLDAP version
is detect, the new and shiny lib/openldap.c code is then used instead of the
old cruft.
Daniel Stenberg (21 May 2010)
- Eric Mertens posted bug #3003705: when we made TFTP use the correct timeout
option when sent to the server (fixed May 18th 2010) it became obvious that
libcurl used invalid timeout values (300 by default while the RFC allows
nothing above 255). While of course it is obvious that as TFTP has worked
thus far without being able to set timeout at all, just removing the setting
wouldn't make any difference in behavior. I decided to still keep it (but
fix the problem) as it now actually allows for easier (future) customization
of the timeout.
(http://curl.haxx.se/bug/view.cgi?id=3003705)
- Douglas Kilpatrick filed bug report #3004787 and pointed out that the TFTP
code didn't handle block id wraps correctly. His suggested fix inspired the
fix I committed.
(http://curl.haxx.se/bug/view.cgi?id=3004787)
Daniel Stenberg (20 May 2010)
- Tanguy Fautre brought a fix to allow curl to build with Microsoft VC10.
Daniel Stenberg (18 May 2010)
- Eric Mertens posted bug report #3003005 pointing out that the libcurl TFTP
code was not sending the timeout option properly to the server, and
suggested a fix.
(http://curl.haxx.se/bug/view.cgi?id=3003005)
Kamil Dudka (16 May 2010)
- Pavel Raiskup introduced a new option CURLOPT_FNMATCH_DATA in order to pass
a custom data pointer to the callback specified by CURLOPT_FNMATCH_FUNCTION.
Daniel Stenberg (14 May 2010)
- John-Mark Bell filed bug #3000052 that identified a problem (with an
associated patch) with the OpenSSL handshake state machine when the multi
interface is used:
Performing an https request using a curl multi handle and using select or
epoll to wait for events results in a hang. It appears that the cause is the
fix for bug #2958179, which makes ossl_connect_common unconditionally return
from the step 2 loop when fetching from a multi handle.
When ossl_connect_step2 has completed, it updates connssl->connecting_state
to ssl_connect_3. ossl_connect_common will then return to the caller, as a
multi handle is in use. Eventually, the client code will call
curl_multi_fdset to obtain an updated fdset to select or epoll on. For https
requests, curl_multi_fdset will cause https_getsock to be called.
https_getsock will only return a socket handle if the connecting_state is
ssl_connect_2_reading or ssl_connect_2_writing. Therefore, the client will
never obtain a valid fdset, and thus not drive the multi handle, resulting
in a hang.
(http://curl.haxx.se/bug/view.cgi?id=3000052)
- Sebastian V reported bug #3000056 identifying a problem with redirect
following. It showed that when curl followed redirects it didn't properly
ignore the response body of the 30X response if that response was using
compressed Content-Encoding!
(http://curl.haxx.se/bug/view.cgi?id=3000056)
Daniel Stenberg (12 May 2010)
- Howard Chu brought support for RTMP. This is powered by the underlying
librtmp library. It supports a range of variations and "sub-protocols"
within the RTMP family.
- Pavel Raiskup brought support for FTP directory wildcard matching to allow
selective downloading. To provide that, a set of new options were added:
CURLOPT_WILDCARDMATCH
CURLOPT_CHUNK_BGN_FUNCTION
CURLOPT_CHUNK_END_FUNCTION
CURLOPT_CHUNK_DATA
CURLOPT_FNMATCH_FUNCTION
There were also a set of new tests added (574 - 577) to verify this.
Kamil Dudka (11 May 2010)
- CRL support in libcurl-NSS has been completely broken. Now it works. Original
bug report: https://bugzilla.redhat.com/581926
Daniel Stenberg (7 May 2010)
- Dirk Manske reported a regression. When connecting with the multi interface,
there were situations where libcurl wouldn't store connect time correctly as
it used to (and is documented to) do.
Using his fine sample program we could repeat it, and I wrote up test case
573 using that code. The problem does not easily show itself using the local
test suite though.
The fix, also as suggested by Dirk, is a bit on the ugly side as it adds yet
another call to Curl_verboseconnect() and setting the TIMER_CONNECT time.
That situation is subject for some closer inspection in the future.
- Howard Chu split the I/O handling functions into private handlers.
Howard Chu brought the bulk work of this patch that properly moves out the
sending and recving of data to the parts of the code that are properly
responsible for the various ways of doing so.
Daniel Stenberg assisted with polishing a few bits and fixed some minor
flaws in the original patch.
Another upside of this patch is that we now abuse CURLcodes less with the
"magic" -1 return codes and instead use CURLE_AGAIN more consistently.
Daniel Stenberg (5 May 2010)
- Hoi-Ho Chan introduced support for using the PolarSSL library. You control
this with the new configure option --with-polarssl.
Daniel Stenberg (29 Apr 2010)
- Ben Greear made telnet a lot better/easier to use by an application:
The main change is to allow input from user-specified methods, when they are
specified with CURLOPT_READFUNCTION. All calls to fflush(stdout) in
telnet.c were removed, which makes using 'curl telnet://foo.com' painful
since prompts and other data are not always returned to the user promptly.
Use 'curl --no-buffer telnet://foo.com' instead. In general, the user
should have their CURLOPT_WRITEFUNCTION do a fflush for interactive use.
Also fix assumption that reading from stdin never returns < 0.
Old code could crash in that case.
Call progress functions in telnet main loop.
Daniel Stenberg (26 Apr 2010)
- Make use of the libssh2_init/exit functions that libssh2 added in version
1.2.5. Using them will improve how libcurl works in threaded situations when
SCP and SFTP are transfered.
Daniel Stenberg (25 Apr 2010)
- Based on work by Kamil Dudka, I've introduced the new configure option
--enable-threaded-resolver. When used, the configure script will check for
pthreads and if around, it will build libcurl to use pthreads to do name
resolving in a threaded manner. Note that this is just a fix to offer an
option that can enable the code that already included. The threader resolver
code was mostly added on Jan 26 2010.
Daniel Stenberg (24 Apr 2010)
- Alex Bligh introduced the --proto and -proto-redir options that limit what
protocols curl accepts for the requests and when following redirects.
Kamil Dudka (24 Apr 2010)
- Fixed test536 in order to not fail with threaded DNS resolver and tweaked
comments in certain examples using curl_multi_fdset().
- Fixed SSL handshake timeout underflow in libcurl-NSS, which caused test405
to hang on a slow machine.
Daniel Stenberg (21 Apr 2010)
- The -O option caused curl to crash on windows and DOS due to the tool
writing out of boundary memory.
Yang Tse (20 Apr 2010)
- Ruslan Gazizov detected that MSVC makefiles were using wsock32.lib instead
of ws2_32.lib, this generated linking issues on MSVC IPv6 enabled builds
that were done using those makefiles.
Daniel Stenberg (19 Apr 2010)
- -J/--remote-header-name didn't strip trailing carriage returns or linefeeds
properly, so they could be used in the file name.
Daniel Stenberg (16 Apr 2010)
- Jerome Vouillon made the GnuTLS SSL handshake phase non-blocking.
- The recent overhaul of the SSL recv function made the GnuTLS specific code
treat a zero returned from gnutls_record_recv() as an error, and this caused
our HTTPS test cases to fail. We leave it to upper layer code to detect if
an EOF is a problem or not.
- I reverted the resolver fix from yesterday and instead removed all uses of
AI_CANONNAME all over libcurl and made the only user of that info (krb5.c)
use the host name from the URL instead. No reverse resolving is a good
thing.
- Paul Howarth made configure properly detect GSS "on ancient Linux distros"
by editing in which order we use headers to detect GSS.
Daniel Stenberg (15 Apr 2010)
- Rainer Canavan filed bug report #2987196 that identified libcurl doing
unnecesary reverse name lookups in many cases when built to use IPv4 and
getaddrinfo(). The logic for ipv6 is now used for ipv4 too.
(http://curl.haxx.se/bug/view.cgi?id=2963679)
Version 7.20.1 (14 April 2010)
Daniel Stenberg (9 Apr 2010)

View File

@@ -120,16 +120,11 @@ if(WIN32)
if( NOT HAVE_WLDAP32)
set(CURL_DISABLE_LDAP ON CACHE BOOL "" FORCE)
message(STATUS "wldap32 not found CURL_DISABLE_LDAP set ON")
option(CURL_LDAP_WIN "Use W$ LDAP implementation" OFF)
option(CURL_LDAP_WIN "Use Windows LDAP implementation" OFF)
else()
option(CURL_LDAP_WIN "Use W$ LDAP implementation" ON)
option(CURL_LDAP_WIN "Use Windows LDAP implementation" ON)
endif()
mark_as_advanced(CURL_LDAP_WIN)
set(CURL_LDAP_HYBRID OFF)
else()
option(CURL_LDAP_HYBRID "W$ LDAP with non-W$ compiler" OFF)
mark_as_advanced(CURL_LDAP_HYBRID)
set(CURL_LDAP_WIN OFF)
endif()
if(HTTP_ONLY)

View File

@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -266,22 +266,22 @@ vc8: lib/Makefile.vc8 src/Makefile.vc8
lib/Makefile.vc8: lib/Makefile.vc6
@echo "generate $@"
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/wsock32.lib/wsock32.lib bufferoverflowu.lib/g" -e "s/VC6/VC8/g" lib/Makefile.vc6 > lib/Makefile.vc8
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/ws2_32.lib/ws2_32.lib bufferoverflowu.lib/g" -e "s/VC6/VC8/g" lib/Makefile.vc6 > lib/Makefile.vc8
src/Makefile.vc8: src/Makefile.vc6
@echo "generate $@"
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/wsock32.lib/wsock32.lib bufferoverflowu.lib/g" -e "s/VC6/VC8/g" src/Makefile.vc6 > src/Makefile.vc8
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/ws2_32.lib/ws2_32.lib bufferoverflowu.lib/g" -e "s/VC6/VC8/g" src/Makefile.vc6 > src/Makefile.vc8
# VC9 makefiles are for use with VS2008
vc9: lib/Makefile.vc9 src/Makefile.vc9
lib/Makefile.vc9: lib/Makefile.vc6
@echo "generate $@"
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/wsock32.lib/ws2_32.lib/g" -e "s/vc6/vc9/g" -e "s/VC6/VC9/g" lib/Makefile.vc6 > lib/Makefile.vc9
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/ws2_32.lib/ws2_32.lib/g" -e "s/vc6/vc9/g" -e "s/VC6/VC9/g" lib/Makefile.vc6 > lib/Makefile.vc9
src/Makefile.vc9: src/Makefile.vc6
@echo "generate $@"
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/wsock32.lib/ws2_32.lib/g" -e "s/vc6/vc9/g" -e "s/VC6/VC9/g" src/Makefile.vc6 > src/Makefile.vc9
@sed -e "s#/GX /DWIN32 /YX#/EHsc /DWIN32#" -e "s#/GZ#/RTC1#" -e "s/ws2_32.lib/ws2_32.lib/g" -e "s/vc6/vc9/g" -e "s/VC6/VC9/g" src/Makefile.vc6 > src/Makefile.vc9
ca-bundle: lib/mk-ca-bundle.pl
@echo "generate a fresh ca-bundle.crt"

View File

@@ -1,51 +1,43 @@
Curl and libcurl 7.20.1
Curl and libcurl 7.21.0
Public curl releases: 115
Command line options: 136
curl_easy_setopt() options: 174
Public curl releases: 116
Command line options: 138
curl_easy_setopt() options: 180
Public functions in libcurl: 58
Known libcurl bindings: 39
Contributors: 776
Contributors: 794
This release includes the following changes:
o The 'ares' subtree has been removed from the source repository
o smoother rate limiting
o allow user+password in the URL for all protocols
o POP3: Get message listing if no mailbox in URL
o added the --proto and -proto-redir options
o new configure option --enable-threaded-resolver
o improve TELNET ability with libcurl
o added support for PolarSSL
o added support for FTP wildcard matching and downloads
o added support for RTMP
o introducing new LDAP code for new enough OpenLDAP
o OpenLDAP support enabled for cygwin builds
o added CURLINFO_PRIMARY_PORT, CURLINFO_LOCAL_IP and CURLINFO_LOCAL_PORT
This release includes the following bugfixes:
o VMS builder bad behavior when used in a batch job
o multiple recepients with SMTP
o fixed the CURL_FORMAT_* defines when building with cmake
o missing quote in libcurl.m4
o SMTP: now waits for 250 after the DATA transfer
o SMTP: use angle brackets in RCPT TO
o curl --trace-time not using local time
o off-by-one in the chunked encoding trailer parser
o superfluous blocking for OpenSSL-based SSL connects and multi interface
o TFTP upload
o FTP timeouts after file transferred completely
o skip poll() on Interix
o CURLOPT_CERTINFO memory leak
o sub-second timeouts improvements
o configure fixes for GSSAPI
o threaded resolver double free when closing curl handle
o configure fixes for building with the clang compiler
o easy interix rate limiting logic
o curl_multi_remove_handle() caused use after free
o TFTP improved error codes
o TFTP fixed TSIZE handling for uploads
o SSL possible double free when reusing curl handle
o alarm()-based DNS timeout bug
o re-used FTP connection multi interface crash
o chunked-encoding with Content-Length: header problem
o multi interface HTTP POST over a proxy using PROXYTUNNEL
o RTSP GET_PARAMETER
o timeout after last data chunk was handled
o SFTP download hang
o FTP quote commands prefixed with '*' now can fail without aborting
o prevent needless reverse name lookups
o detect GSS on ancient Linux distros
o GnuTLS: EOF caused error when it wasn't
o GnuTLS: SSL handshake phase is non-blocking
o -J/--remote-header-name strips CRLF
o MSVC makefiles now use ws2_32.lib instead of wsock32.lib
o -O crash on windows
o SSL handshake timeout underflow in libcurl-NSS
o multi interface missed storing connection time
o broken CRL support in libcurl-NSS
o ignore response-body on redirect even if compressed
o OpenSSL handshake state-machine for multi interface
o TFTP timeout option sent correctly
o TFTP block id wrap
o curl_multi_socket_action() timeout handles inaccuracy in timers better
o SCP/SFTP failure to respect the timeout
o spurious SSL connection aborts with OpenSSL
This release includes the following known bugs:
@@ -54,11 +46,11 @@ This release includes the following known bugs:
This release would not have looked like this without help, code, reports and
advice from friends like these:
Steven M. Schweda, Yang Tse, Jack Zhang, Tom Donovan, Martin Hager,
Daniel Fandrich, Patrick Monnerat, Pat Ray, Wesley Miaw, Ben Greear,
Ryan Chan, Markus Duft, Andrei Benea, Jacob Moshenko, Daniel Johnson,
Constantine Sapuntzakis, Douglas Steinwand, Thomas Lopatic, Hauke Duden,
Akos Pasztory, Kenny To, Christopher Conroy, Massimo Callegari,
Bob Richmond, Matt Wixson
Rainer Canavan, Paul Howarth, Jerome Vouillon, Ruslan Gazizov, Yang Tse,
Kamil Dudka, Alex Bligh, Ben Greear, Hoi-Ho Chan, Howard Chu, Dirk Manske,
Pavel Raiskup, John-Mark Bell, Eric Mertens, Tor Arntsen, Douglas Kilpatrick,
Igor Novoseltsev, Jason McDonald, Dan Fandrich, Tanguy Fautre, Guenter Knauf,
Julien Chaffraix, Kalle Vahlman, Frank Meier, Constantine Sapuntzakis
Thanks! (and sorry if I forgot to mention someone)

View File

@@ -6,7 +6,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -33,6 +33,17 @@ die(){
findtool(){
file="$1"
if { echo $file | grep "/" >/dev/null 2>&1; } then
# we only check for the explicit file name if the file is given
# including a slash. Use ./ for current dir. Previously this would
# otherwise always cause findtool to search the local dir first, which
# is wrong.
if test -f "$file"; then
echo "$file"
return
fi
fi
old_IFS=$IFS; IFS=':'
for path in $PATH
do

View File

@@ -121,13 +121,13 @@ AC_SUBST(PKGADD_VENDOR)
dnl
dnl initialize all the info variables
curl_ssl_msg="no (--with-ssl / --with-gnutls / --with-nss)"
curl_ssl_msg="no (--with-{ssl,gnutls,nss,polarssl} )"
curl_ssh_msg="no (--with-libssh2)"
curl_zlib_msg="no (--with-zlib)"
curl_krb4_msg="no (--with-krb4*)"
curl_gss_msg="no (--with-gssapi)"
curl_spnego_msg="no (--with-spnego)"
curl_ares_msg="no (--enable-ares)"
curl_res_msg="default (--enable-ares / --enable-threaded-resolver)"
curl_ipv6_msg="no (--enable-ipv6)"
curl_idn_msg="no (--with-libidn)"
curl_manual_msg="no (--enable-manual)"
@@ -136,6 +136,7 @@ curl_verbose_msg="enabled (--disable-verbose)"
curl_ldap_msg="no (--enable-ldap / --with-ldap-lib / --with-lber-lib)"
curl_ldaps_msg="no (--enable-ldaps)"
curl_rtsp_msg="no (--enable-rtsp)"
curl_rtmp_msg="no (--with-librtmp)"
dnl
dnl Save anything in $LIBS for later
@@ -370,28 +371,10 @@ AC_HELP_STRING([--disable-ldap],[Disable LDAP support]),
AC_SUBST(CURL_DISABLE_LDAP, [1])
;;
*)
case $host in
*-*-cygwin*)
# Force no ldap. config/build process is broken for cygwin
AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP])
AC_SUBST(CURL_DISABLE_LDAP, [1])
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
esac
AC_MSG_RESULT(yes)
;;
esac ],[
case $host in
*-*-cygwin*)
# Force no ldap. config/build process is broken for cygwin
AC_DEFINE(CURL_DISABLE_LDAP, 1, [to disable LDAP])
AC_SUBST(CURL_DISABLE_LDAP, [1])
AC_MSG_RESULT(no)
;;
*)
AC_MSG_RESULT(yes)
esac ]
AC_MSG_RESULT(yes) ]
)
AC_MSG_CHECKING([whether to support ldaps])
AC_ARG_ENABLE(ldaps,
@@ -403,20 +386,28 @@ AC_HELP_STRING([--disable-ldaps],[Disable LDAPS support]),
AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS])
AC_SUBST(CURL_DISABLE_LDAPS, [1])
;;
*) if test x$CURL_DISABLE_LDAP = x1 ; then
AC_MSG_RESULT(LDAP support needs to be enabled in order to enable LDAPS support!)
AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS])
AC_SUBST(CURL_DISABLE_LDAPS, [1])
*) if test "x$CURL_DISABLE_LDAP" = "x1" ; then
AC_MSG_RESULT(LDAP needs to be enabled to support LDAPS)
AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS])
AC_SUBST(CURL_DISABLE_LDAPS, [1])
else
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_LDAP_SSL, 1, [Use LDAPS implementation])
curl_ldaps_msg="enabled"
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_LDAP_SSL, 1, [Use LDAPS implementation])
AC_SUBST(HAVE_LDAP_SSL, [1])
curl_ldaps_msg="enabled"
fi
;;
esac ],
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS])
AC_SUBST(CURL_DISABLE_LDAPS, [1])
esac ],[
if test "x$CURL_DISABLE_LDAP" = "x1" ; then
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_LDAPS, 1, [to disable LDAPS])
AC_SUBST(CURL_DISABLE_LDAPS, [1])
else
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_LDAP_SSL, 1, [Use LDAPS implementation])
AC_SUBST(HAVE_LDAP_SSL, [1])
curl_ldaps_msg="enabled"
fi ]
)
AC_MSG_CHECKING([whether to support rtsp])
@@ -801,13 +792,11 @@ if test x$CURL_DISABLE_LDAP != x1 ; then
CURL_CHECK_HEADER_LDAP_SSL
if test -z "$LDAPLIBNAME" ; then
case $host in
*-*-cygwin* | *-*-mingw* | *-*-pw32*)
dnl Windows uses a single and unique OpenLDAP DLL name
LDAPLIBNAME="wldap32"
LBERLIBNAME="no"
;;
esac
if test "$ac_cv_native_windows" = "yes"; then
dnl Windows uses a single and unique LDAP library name
LDAPLIBNAME="wldap32"
LBERLIBNAME="no"
fi
fi
if test "$LDAPLIBNAME" ; then
@@ -849,18 +838,17 @@ if test x$CURL_DISABLE_LDAP != x1 ; then
fi
if test x$CURL_DISABLE_LDAP != x1 ; then
AC_CHECK_FUNCS([ldap_url_parse])
AC_CHECK_FUNCS([ldap_url_parse ldap_init_fd])
if test "$LDAPLIBNAME" = "wldap32"; then
curl_ldap_msg="enabled (winldap)"
AC_DEFINE(CURL_LDAP_WIN, 1, [Use W$ LDAP implementation])
case $host in
*-*-cygwin* | *-*-pw32*)
AC_DEFINE(CURL_LDAP_HYBRID, 1, [W$ LDAP with non-W$ compiler])
;;
esac
AC_DEFINE(CURL_LDAP_WIN, 1, [Use Windows LDAP implementation])
else
curl_ldap_msg="enabled (OpenLDAP)"
if test "x$ac_cv_func_ldap_init_fd" = "xyes"; then
AC_DEFINE(USE_OPENLDAP, 1, [Use OpenLDAP-specific code])
AC_SUBST(USE_OPENLDAP, [1])
fi
fi
fi
@@ -1137,10 +1125,17 @@ if test x"$want_gss" = xyes; then
],
[
dnl not found, check Heimdal or MIT
AC_CHECK_HEADERS([gssapi/gssapi.h], [], [not_mit=1])
AC_CHECK_HEADERS(
[gssapi/gssapi.h gssapi/gssapi_generic.h gssapi/gssapi_krb5.h],
[gssapi/gssapi_generic.h gssapi/gssapi_krb5.h],
[],
[not_mit=1])
[not_mit=1],
[
AC_INCLUDES_DEFAULT
#ifdef HAVE_GSSAPI_GSSAPI_H
#include <gssapi/gssapi.h>
#endif
])
if test "x$not_mit" = "x1"; then
dnl MIT not found, check for Heimdal
AC_CHECK_HEADER(gssapi.h,
@@ -1699,6 +1694,90 @@ if test "$OPENSSL_ENABLED" != "1"; then
fi dnl OPENSSL != 1
dnl ----------------------------------------------------
dnl check for PolarSSL
dnl ----------------------------------------------------
dnl Default to compiler & linker defaults for PolarSSL files & libraries.
OPT_POLARSSL=no
_cppflags=$CPPFLAGS
_ldflags=$LDFLAGS
AC_ARG_WITH(polarssl,dnl
AC_HELP_STRING([--with-polarssl=PATH],[where to look for PolarSSL, PATH points to the installation root (default: /usr/local/)])
AC_HELP_STRING([--without-polarssl], [disable PolarSSL detection]),
OPT_POLARSSL=$withval)
if test "$OPENSSL_ENABLED" != "1"; then
if test X"$OPT_POLARSSL" != Xno; then
if test "$OPT_POLARSSL" = "yes"; then
OPT_POLARSSL=""
fi
if test -z "$OPT_POLARSSL" ; then
dnl check for lib first without setting any new path
AC_CHECK_LIB(polarssl, havege_init,
dnl libpolarssl found, set the variable
[
AC_DEFINE(USE_POLARSSL, 1, [if PolarSSL is enabled])
AC_SUBST(USE_POLARSSL, [1])
POLARSSL_ENABLED=1
USE_POLARSSL="yes"
curl_ssl_msg="enabled (PolarSSL)"
])
fi
if test "x$USE_POLARSSL" != "xyes"; then
dnl add the path and test again
addld=-L$OPT_POLARSSL/lib$libsuff
addcflags=-I$OPT_POLARSSL/include
polarssllib=$OPT_POLARSSL/lib$libsuff
LDFLAGS="$LDFLAGS $addld"
if test "$addcflags" != "-I/usr/include"; then
CPPFLAGS="$CPPFLAGS $addcflags"
fi
AC_CHECK_LIB(polarssl, ssl_init,
[
AC_DEFINE(USE_POLARSSL, 1, [if PolarSSL is enabled])
AC_SUBST(USE_POLARSSL, [1])
POLARSSL_ENABLED=1
USE_POLARSSL="yes"
curl_ssl_msg="enabled (PolarSSL)"
],
[
CPPFLAGS=$_cppflags
LDFLAGS=$_ldflags
])
fi
if test "x$USE_POLARSSL" = "xyes"; then
AC_MSG_NOTICE([detected PolarSSL])
CURL_LIBS="$CURL_LIBS -lpolarssl"
LIBS="$LIBS -lpolarssl"
if test -n "$polarssllib"; then
dnl when shared libs were found in a path that the run-time
dnl linker doesn't search through, we need to add it to
dnl LD_LIBRARY_PATH to prevent further configure tests to fail
dnl due to this
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$polarssllib"
export LD_LIBRARY_PATH
AC_MSG_NOTICE([Added $polarssllib to LD_LIBRARY_PATH])
fi
fi
fi dnl PolarSSL not disabled
fi dnl OPENSSL != 1
dnl ----------------------------------------------------
dnl NSS. Only check if GnuTLS and OpenSSL are not enabled
dnl ----------------------------------------------------
@@ -1795,9 +1874,9 @@ if test "$OPENSSL_ENABLED" != "1" -a "$GNUTLS_ENABLED" != "1"; then
fi dnl OPENSSL != 1 -a GNUTLS_ENABLED != 1
if test "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED" = "x"; then
if test "x$OPENSSL_ENABLED$GNUTLS_ENABLED$NSS_ENABLED$POLARSSL_ENABLED" = "x"; then
AC_MSG_WARN([SSL disabled, you will not be able to use HTTPS, FTPS, NTLM and more.])
AC_MSG_WARN([Use --with-ssl, --with-gnutls or --with-nss to address this.])
AC_MSG_WARN([Use --with-ssl, --with-gnutls, --with-polarssl or --with-nss to address this.])
else
# SSL is enabled, genericly
AC_SUBST(SSL_ENABLED)
@@ -1882,7 +1961,8 @@ if test X"$OPT_LIBSSH2" != Xno; then
dnl to prevent further configure tests to fail due to this
dnl libssh2_version is a post 1.0 addition
AC_CHECK_FUNCS( libssh2_version )
dnl libssh2_init and libssh2_exit were added in 1.2.5
AC_CHECK_FUNCS( libssh2_version libssh2_init libssh2_exit)
LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$DIR_SSH2"
export LD_LIBRARY_PATH
@@ -1896,6 +1976,79 @@ if test X"$OPT_LIBSSH2" != Xno; then
fi
fi
dnl **********************************************************************
dnl Check for the presence of LIBRTMP libraries and headers
dnl **********************************************************************
dnl Default to compiler & linker defaults for LIBRTMP files & libraries.
OPT_LIBRTMP=off
AC_ARG_WITH(librtmp,dnl
AC_HELP_STRING([--with-librtmp=PATH],[Where to look for librtmp, PATH points to the LIBRTMP installation (default: /usr/local/lib); when possible, set the PKG_CONFIG_PATH environment variable instead of using this option])
AC_HELP_STRING([--without-librtmp], [disable LIBRTMP]),
OPT_LIBRTMP=$withval)
if test X"$OPT_LIBRTMP" != Xno; then
dnl backup the pre-librtmp variables
CLEANLDFLAGS="$LDFLAGS"
CLEANCPPFLAGS="$CPPFLAGS"
CLEANLIBS="$LIBS"
case "$OPT_LIBRTMP" in
yes)
dnl --with-librtmp (without path) used
CURL_CHECK_PKGCONFIG(librtmp)
if test "$PKGCONFIG" != "no" ; then
LIB_RTMP=`$PKGCONFIG --libs-only-l librtmp`
LD_RTMP=`$PKGCONFIG --libs-only-L librtmp`
CPP_RTMP=`$PKGCONFIG --cflags-only-I librtmp`
version=`$PKGCONFIG --modversion librtmp`
DIR_RTMP=`echo $LD_RTMP | $SED -e 's/-L//'`
fi
;;
off)
dnl no --with-librtmp option given, just check default places
;;
*)
dnl use the given --with-librtmp spot
PREFIX_RTMP=$OPT_LIBRTMP
;;
esac
dnl if given with a prefix, we set -L and -I based on that
if test -n "$PREFIX_RTMP"; then
LD_RTMP=-L${PREFIX_RTMP}/lib$libsuff
CPP_RTMP=-I${PREFIX_RTMP}/include
DIR_RTMP=${PREFIX_RTMP}/lib$libsuff
fi
LDFLAGS="$LDFLAGS $LD_RTMP"
CPPFLAGS="$CPPFLAGS $CPP_RTMP"
LIBS="$LIBS $LIB_RTMP"
AC_CHECK_LIB(rtmp, RTMP_Init)
AC_CHECK_HEADERS(librtmp/rtmp.h,
curl_rtmp_msg="enabled (librtmp)"
LIBRTMP_ENABLED=1
AC_DEFINE(USE_LIBRTMP, 1, [if librtmp is in use])
AC_SUBST(USE_LIBRTMP, [1])
)
if test X"$OPT_LIBRTMP" != Xoff &&
test "$LIBRTMP_ENABLED" != "1"; then
AC_MSG_ERROR([librtmp libs and/or directories were not found where specified!])
fi
if test "$LIBRTMP_ENABLED" != "1"; then
dnl no librtmp, revert back to clean variables
LDFLAGS=$CLEANLDFLAGS
CPPFLAGS=$CLEANCPPFLAGS
LIBS=$CLEANLIBS
fi
fi
dnl **********************************************************************
dnl Check for the presence of IDN libraries and headers
dnl **********************************************************************
@@ -2282,6 +2435,28 @@ AM_CONDITIONAL(USE_MANUAL, test x"$USE_MANUAL" = x1)
CURL_CHECK_LIB_ARES
AM_CONDITIONAL(USE_EMBEDDED_ARES, test x$embedded_ares = xyes)
CURL_CHECK_OPTION_THREADED_RESOLVER
if test "x$want_thres" = xyes && test "x$want_ares" = xyes; then
AC_MSG_ERROR(
[Options --enable-threaded-resolver and --enable-ares are mutually exclusive])
fi
if test "$want_thres" = "yes"; then
AC_CHECK_HEADER(pthread.h,
[ AC_DEFINE(HAVE_PTHREAD_H, 1, [if you have <pthread.h>])
save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -pthread"
AC_CHECK_LIB(pthread, pthread_create,
[ AC_MSG_NOTICE([using POSIX threaded DNS lookup])
AC_DEFINE(USE_THREADS_POSIX, 1, [if you want POSIX threaded DNS lookup])
USE_THREADS_POSIX=1
curl_res_msg="threaded"
],
[ CFLAGS="$save_CFLAGS"])
])
fi
dnl ************************************************************
dnl disable verbose text strings
dnl
@@ -2475,7 +2650,7 @@ fi
if test "x$HAVE_LIBZ" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES libz"
fi
if test "x$USE_ARES" = "x1"; then
if test "x$USE_ARES" = "x1" -o "x$USE_THREADS_POSIX" = "x1"; then
SUPPORT_FEATURES="$SUPPORT_FEATURES AsynchDNS"
fi
if test "x$IDN_ENABLED" = "x1"; then
@@ -2511,9 +2686,12 @@ if test "x$CURL_DISABLE_TELNET" != "x1"; then
fi
if test "x$CURL_DISABLE_LDAP" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS LDAP"
fi
if test "x$CURL_DISABLE_LDAPS" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS LDAPS"
if test "x$CURL_DISABLE_LDAPS" != "x1"; then
if (test "x$USE_OPENLDAP" = "x1" && test "x$SSL_ENABLED" = "x1") ||
(test "x$USE_OPENLDAP" != "x1" && test "x$HAVE_LDAP_SSL" = "x1"); then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS LDAPS"
fi
fi
fi
if test "x$CURL_DISABLE_DICT" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS DICT"
@@ -2546,6 +2724,9 @@ fi
if test "x$CURL_DISABLE_RTSP" != "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTSP"
fi
if test "x$USE_LIBRTMP" = "x1"; then
SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS RTMP"
fi
dnl replace spaces with newlines
dnl sort the lines
@@ -2617,7 +2798,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
krb4 support: ${curl_krb4_msg}
GSSAPI support: ${curl_gss_msg}
SPNEGO support: ${curl_spnego_msg}
c-ares support: ${curl_ares_msg}
resolver: ${curl_res_msg}
ipv6 support: ${curl_ipv6_msg}
IDN support: ${curl_idn_msg}
Build libcurl: Shared=${enable_shared}, Static=${enable_static}
@@ -2629,6 +2810,7 @@ AC_MSG_NOTICE([Configured to build curl/libcurl:
LDAP support: ${curl_ldap_msg}
LDAPS support: ${curl_ldaps_msg}
RTSP support: ${curl_rtsp_msg}
RTMP support: ${curl_rtmp_msg}
Protocols: ${SUPPORT_PROTOCOLS}
])

2
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.html
*.pdf

View File

@@ -29,9 +29,11 @@
2.11 Test Cases
3. Pushing Out Your Changes
3.1 Write Access to git Repository
3.2 How To Make a Patch with git
3.3 How To Make a Patch without git
3.4 How to get your changes into the main sources
3.5 Write good commit messages
==============================================================================
@@ -114,7 +116,7 @@
2.4 Line Lengths
We try to keep source lines shorter than 80 columns.
We write source lines shorter than 80 columns.
2.5 General Style
@@ -197,7 +199,8 @@
git commit [file]
As usual, group your commits so that you commit all changes that at once that
constitutes a logical change.
constitutes a logical change. See also section "3.5 Write good commit
messages".
Once you have done all your commits and you're happy with what you see, you
can make patches out of your changes that are suitable for mailing:
@@ -255,3 +258,22 @@
5. If you've followed the above mentioned paragraphs and your patch still
hasn't been incorporated after some weeks, consider resubmitting it to the
list.
3.5 Write good commit messages
A short guide to how to do fine commit messages in the curl project.
---- start ----
[area]: [short line describing the main effect]
[separate the above single line from the rest with an empty line]
[full description, no wider than 65 columns that describe as much as
possible as to why this change is made, and possibly what things
it fixes and everything else that is related]
---- stop ----
Don't forget to use commit --author="" if you commit someone else's work,
and make sure that you have your own user and email setup correctly in git
before you commit

View File

@@ -356,7 +356,7 @@ multi interface/non-blocking
The FTP and the SFTP/SCP protocols are thus perfect examples of how we adapt
and adjust the code to allow non-blocking operations even on multi-stage
protocols. The DICT, TELNET and TFTP are crappy examples and they are subject
protocols. The DICT, LDAP and TELNET are crappy examples and they are subject
for rewrite in the future to better fit the libcurl protocol family.
SSL libraries

View File

@@ -32,12 +32,16 @@ This document lists documents and standards used by curl.
RFC 2068 - HTTP 1.1 (obsoleted by RFC 2616)
RFC 2104 - Keyed-Hashing for Message Authentication
RFC 2109 - HTTP State Management Mechanism (cookie stuff)
- Also, read Netscape's specification at
http://curl.haxx.se/rfc/cookie_spec.html
RFC 2183 - The Content-Disposition Header Field
RFC 2195 - CRAM-MD5 authentication
RFC 2229 - A Dictionary Server Protocol
RFC 2255 - Newer LDAP URL syntax document.
@@ -73,3 +77,7 @@ This document lists documents and standards used by curl.
RFC 2965 - HTTP State Management Mechanism. Cookies. Obsoletes RFC2109
RFC 3207 - SMTP over TLS
RFC 4616 - PLAIN authentication
RFC 4954 - SMTP Authentication

View File

@@ -8,6 +8,7 @@ Aaron Oneal
Adam D. Moss
Adam Piggott
Adrian Schuur
Akos Pasztory
Alan Pinstein
Albert Chin-A-Young
Albert Choy
@@ -41,6 +42,7 @@ Andreas Olsson
Andreas Rieke
Andreas Schuldei
Andreas Wurf
Andrei Benea
Andres Garcia
Andrew Benham
Andrew Biggs
@@ -81,6 +83,7 @@ Bill Hoffman
Bjorn Augustsson
Bjorn Reese
Bj<EFBFBD>rn Stenberg
Bob Richmond
Bob Schader
Bogdan Nicula
Brad Burdick
@@ -118,6 +121,7 @@ Christian Schmitz
Christian Vogt
Christophe Demory
Christophe Legry
Christopher Conroy
Christopher Palow
Christopher R. Palmer
Ciprian Badescu
@@ -201,6 +205,7 @@ Doug Kaufman
Doug Porter
Douglas E. Wegscheid
Douglas R. Horner
Douglas Steinwand
Dov Murik
Duane Cathey
Duncan Mac-Vicar Prett
@@ -291,6 +296,7 @@ Hans Steegers
Hans-Jurgen May
Hardeep Singh
Harshal Pradhan
Hauke Duden
Heikki Korpela
Henrik Storner
Hidemoto Nakada
@@ -310,8 +316,10 @@ Immanuel Gregoire
Ingmar Runge
Ingo Ralf Blum
Ingo Wilken
Jack Zhang
Jacky Lam
Jacob Meuser
Jacob Moshenko
Jad Chamcham
James Bursa
James Cheng
@@ -408,6 +416,7 @@ Keith McGuigan
Keith Mok
Ken Hirsch
Ken Rastatter
Kenny To
Kent Boortz
Keshav Krity
Kevin Baughman
@@ -471,24 +480,28 @@ Mark Eichin
Mark Incley
Mark Karpeles
Mark Lentczner
Markus Duft
Markus Koetter
Markus Moeller
Markus Oberhumer
Martijn Koster
Martin C. Martin
Martin Drasar
Martin Hager
Martin Hedenfalk
Martin Skinner
Martin Storsjo
Marty Kuhrt
Maruko
Massimiliano Ziccardi
Massimo Callegari
Mateusz Loskot
Mathias Axelsson
Mats Lidell
Matt Kraai
Matt Veenstra
Matt Witherspoon
Matt Wixson
Matthew Blain
Matthew Clarke
Maurice Barnum
@@ -554,6 +567,7 @@ Olaf St
Oren Tirosh
P R Schaffner
Pascal Terjan
Pat Ray
Patrick Bihan-Faou
Patrick Monnerat
Patrick Scott
@@ -651,6 +665,7 @@ Ron Zapp
Rosimildo da Silva
Roy Shan
Rune Kleveland
Ryan Chan
Ryan Nelson
S. Moonesamy
Salvador D<>vila
@@ -703,6 +718,7 @@ Steve Oliphant
Steve Roskowski
Steven Bazyl
Steven G. Johnson
Steven M. Schweda
Stoned Elipot
Sven Anders
Sven Neuhaus
@@ -714,6 +730,7 @@ Tanguy Fautre
Temprimus
Thomas J. Moore
Thomas Klausner
Thomas Lopatic
Thomas Schwinge
Thomas Tonino
Tim Ansell
@@ -727,6 +744,7 @@ Toby Peterson
Todd Kulesza
Todd Vierling
Tom Benoist
Tom Donovan
Tom Lee
Tom Mattison
Tom Moers

View File

@@ -22,12 +22,13 @@
2.2 Remove easy interface internally
2.3 Avoid having to remove/readd handles
2.4 Fix HTTP Pipelining for PUT
2.5 Make curl_multi_info_read faster
3. Documentation
3.1 More and better
4. FTP
4.1 PRET
4.1 HOST
4.2 Alter passive/active on failure and retry
4.3 Earlier bad letter detection
4.4 REST for large files
@@ -60,28 +61,23 @@
8. GnuTLS
8.1 SSL engine stuff
8.2 SRP
8.3 non-blocking
8.4 check connection
8.3 check connection
9. Other protocols
9.1 ditch ldap-specific select
10. New protocols
10.1 RTSP
10.2 RSYNC
10.3 RTMP
10.1 RSYNC
10.2 RTMP
11. Client
11.1 Content-Disposition
11.2 sync
11.3 glob posts
11.4 prevent file overwriting
11.5 ftp wildcard download
11.6 simultaneous parallel transfers
11.7 provide formpost headers
11.8 url-specific options
11.9 metalink support
11.10 warning when setting an option
11.1 sync
11.2 glob posts
11.3 prevent file overwriting
11.4 simultaneous parallel transfers
11.5 provide formpost headers
11.6 url-specific options
11.7 metalink support
11.8 warning when setting an option
12. Build
12.1 roffit
@@ -148,7 +144,6 @@
EWOULDBLOCK or similar. Blocking cases include:
- Name resolves on non-windows unless c-ares is used
- GnuTLS SSL connections
- NSS SSL connections
- Active FTP connections
- HTTP proxy CONNECT operations
@@ -190,6 +185,10 @@
serial requests and currently libcurl only supports that for HEAD and GET
requests but it should also be possible for PUT.
2.5 Make curl_multi_info_read faster
When checking if there's info to return, this function scans over ALL added
easy handles every time. That makes this function unnecessary heavy and slow.
3. Documentation
@@ -199,12 +198,12 @@
4. FTP
4.1 PRET
4.1 HOST
PRET is a command that primarily "drftpd" supports, which could be useful
when using libcurl against such a server. It is a non-standard and a rather
oddly designed command, but...
http://curl.haxx.se/bug/feature.cgi?id=1729967
HOST is a suggested command in the works for a client to tell which host name
to use, to offer FTP servers named-based virtual hosting:
http://tools.ietf.org/html/draft-hethmon-mcmurray-ftp-hosts-11
4.2 Alter passive/active on failure and retry
@@ -362,39 +361,21 @@ to provide the data to send.
Work out a common method with Peter Sylvester's OpenSSL-patch for SRP on the
TLS to provide name and password. GnuTLS already supports it...
8.3 non-blocking
Fix the connection phase to be non-blocking when multi interface is used
8.4 check connection
8.3 check connection
Add a way to check if the connection seems to be alive, to correspond to the
SSL_peak() way we use with OpenSSL.
9. Other protocols
9.1 ditch ldap-specific select
* Look over the implementation. The looping will have to "go away" from the
lib/ldap.c source file and get moved to the main network code so that the
multi interface and friends will work for LDAP as well.
9.2 stop TFTP blocking
Stop TFTP from being blocking and doing its own read loop in tftp_do.
10. New protocols
10.1 RTSP
RFC2326 (protocol - very HTTP-like, also contains URL description)
10.2 RSYNC
10.1 RSYNC
There's no RFC for protocol nor URI/URL format. An implementation should
most probably use an existing rsync library, such as librsync.
10.3 RTMP
10.2 RTMP
There exists a patch that claims to introduce this protocol:
http://osdir.com/ml/gnu.gnash.devel2/2006-11/msg00278.html, further details
@@ -402,14 +383,7 @@ to provide the data to send.
11. Client
11.1 Content-Disposition
Add option that is similar to -O but that takes the output file name from the
Content-Disposition: header, and/or uses the local file name used in
redirections for the cases the server bounces the request further to a
different file (name): http://curl.haxx.se/bug/feature.cgi?id=1364676
11.2 sync
11.1 sync
"curl --sync http://example.com/feed[1-100].rss" or
"curl --sync http://example.net/{index,calendar,history}.html"
@@ -418,12 +392,12 @@ to provide the data to send.
remote file is newer than the local file. A Last-Modified HTTP date header
should also be used to set the mod date on the downloaded file.
11.3 glob posts
11.2 glob posts
Globbing support for -d and -F, as in 'curl -d "name=foo[0-9]" URL'.
This is easily scripted though.
11.4 prevent file overwriting
11.3 prevent file overwriting
Add an option that prevents cURL from overwriting existing local files. When
used, and there already is an existing file with the target file name
@@ -431,18 +405,14 @@ to provide the data to send.
existing). So that index.html becomes first index.html.1 and then
index.html.2 etc.
11.5 ftp wildcard download
"curl ftp://site.com/*.txt"
11.6 simultaneous parallel transfers
11.4 simultaneous parallel transfers
The client could be told to use maximum N simultaneous parallel transfers and
then just make sure that happens. It should of course not make more than one
connection to the same remote host. This would require the client to use the
multi interface. http://curl.haxx.se/bug/feature.cgi?id=1558595
11.7 provide formpost headers
11.5 provide formpost headers
Extending the capabilities of the multipart formposting. How about leaving
the ';type=foo' syntax as it is and adding an extra tag (headers) which
@@ -456,7 +426,7 @@ to provide the data to send.
which should overwrite the program reasonable defaults (plain/text,
8bit...)
11.8 url-specific options
11.6 url-specific options
Provide a way to make options bound to a specific URL among several on the
command line. Possibly by letting ':' separate options between URLs,
@@ -470,12 +440,12 @@ to provide the data to send.
The example would do a POST-GET-POST combination on a single command line.
11.9 metalink support
11.7 metalink support
Add metalink support to curl (http://www.metalinker.org/). This is most useful
with simultaneous parallel transfers (11.6) but not necessary.
11.10 warning when setting an option
11.8 warning when setting an option
Display a warning when libcurl returns an error when setting an option.
This can be useful to tell when support for a particular feature hasn't been

View File

@@ -927,6 +927,52 @@ in web browsers, so curl does the conversion by default to maintain
consistency. However, a server may require a POST to remain a POST after such
a redirection. This option is meaningful only when using \fI-L/--location\fP
(Added in 7.19.1)
.IP "--proto <protocols>"
Tells curl to use the listed protocols for its initial retrieval. Protocols
are evaluated left to right, are comma separated, and are each a protocol
name or 'all', optionally prefixed by zero or more modifiers. Available
modifiers are:
.RS
.TP 3
.B +
Permit this protocol in addition to protocols already permitted (this is
the default if no modifier is used).
.TP
.B -
Deny this protocol, removing it from the list of protocols already permitted.
.TP
.B =
Permit only this protocol (ignoring the list already permitted), though
subject to later modification by subsequent entries in the comma separated
list.
.RE
.IP
For example:
.RS
.TP 15
.B --proto -ftps
uses the default protocols, but disables ftps
.TP
.B --proto -all,https,+http
only enables http and https
.TP
.B --proto =http,https
also only enables http and https
.RE
.IP
Unknown protocols produce a warning. This allows scripts to safely rely on
being able to disable potentially dangerous protocols, without relying upon
support for that protocol being built into curl to avoid an error.
This option can be used multiple times, in which case the effect is the same
as concatenating the protocols into one instance of the option.
(Added in 7.20.2)
.IP "--proto-redir <protocols>"
Tells curl to use the listed protocols after a redirect. See --proto for
how protocols are represented.
(Added in 7.20.2)
.IP "--proxy-anyauth"
Tells curl to pick a suitable authentication method when communicating with
the given proxy. This might cause an extra request/response round-trip. (Added

View File

@@ -131,7 +131,6 @@ fill_buffer(URL_FILE *file,int want,int waittime)
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
struct timeval timeout;
int rc;
@@ -144,6 +143,7 @@ fill_buffer(URL_FILE *file,int want,int waittime)
/* attempt to fill buffer */
do
{
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
FD_ZERO(&fdexcep);
@@ -156,8 +156,10 @@ fill_buffer(URL_FILE *file,int want,int waittime)
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls, *and* you make sure that maxfd is bigger than -1
so that the call to select() below makes sense! */
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially
in case of (maxfd == -1), we call select(0, ...), which is basically
equal to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

View File

@@ -66,7 +66,7 @@ int main(int argc, char **argv)
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
@@ -80,8 +80,10 @@ int main(int argc, char **argv)
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls, *and* you make sure that maxfd is bigger than -1 so
that the call to select() below makes sense! */
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

View File

@@ -140,7 +140,7 @@ int main(int argc, char **argv)
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
@@ -154,8 +154,10 @@ int main(int argc, char **argv)
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls, *and* you make sure that maxfd is bigger than -1
so that the call to select() below makes sense! */
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

View File

@@ -57,7 +57,7 @@ int main(int argc, char **argv)
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
@@ -71,8 +71,10 @@ int main(int argc, char **argv)
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls, *and* you make sure that maxfd is bigger than -1 so
that the call to select() below makes sense! */
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

View File

@@ -77,7 +77,7 @@ int main(int argc, char *argv[])
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
@@ -91,8 +91,10 @@ int main(int argc, char *argv[])
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls, *and* you make sure that maxfd is bigger than -1
so that the call to select() below makes sense! */
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

View File

@@ -51,7 +51,7 @@ int main(int argc, char **argv)
fd_set fdread;
fd_set fdwrite;
fd_set fdexcep;
int maxfd;
int maxfd = -1;
FD_ZERO(&fdread);
FD_ZERO(&fdwrite);
@@ -65,8 +65,10 @@ int main(int argc, char **argv)
curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
/* In a real-world program you OF COURSE check the return code of the
function calls, *and* you make sure that maxfd is bigger than -1 so
that the call to select() below makes sense! */
function calls. On success, the value of maxfd is guaranteed to be
greater or equal than -1. We call select(maxfd + 1, ...), specially in
case of (maxfd == -1), we call select(0, ...), which is basically equal
to sleep. */
rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);

2
docs/libcurl/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
*.html
*.pdf

View File

@@ -173,6 +173,17 @@ string holding the IP address of the most recent connection done with this
\fBcurl\fP handle. This string may be IPv6 if that's enabled. Note that you
get a pointer to a memory area that will be re-used at next request so you
need to copy the string if you want to keep the information. (Added in 7.19.0)
.IP CURLINFO_PRIMARY_PORT
Pass a pointer to a long to receive the destination port of the most recent
connection done with this \fBcurl\fP handle. (Added in 7.21.0)
.IP CURLINFO_LOCAL_IP
Pass a pointer to a char pointer to receive the pointer to a zero-terminated
string holding the local (source) IP address of the most recent connection done
with this \fBcurl\fP handle. This string may be IPv6 if that's enabled. The
same restrictions apply as to \fICURLINFO_PRIMARY_IP\fP. (Added in 7.21.0)
.IP CURLINFO_LOCAL_PORT
Pass a pointer to a long to receive the local (source) port of the most recent
connection done with this \fBcurl\fP handle. (Added in 7.21.0)
.IP CURLINFO_COOKIELIST
Pass a pointer to a 'struct curl_slist *' to receive a linked-list of all
cookies cURL knows (expired ones, too). Don't forget to

View File

@@ -84,7 +84,57 @@ If this option is set and libcurl has been built with the standard name
resolver, timeouts will not occur while the name resolve takes place.
Consider building libcurl with c-ares support to enable asynchronous DNS
lookups, which enables nice timeouts for name resolves without signals.
.IP CURLOPT_WILDCARDMATCH
Set this option to 1 if you want to transfer multiple files according to a
file name pattern. The pattern can be specified as part of the
\fICURLOPT_URL\fP option, using an fnmatch-like pattern (Shell Pattern
Matching) in the last part of URL (file name).
By default, libcurl uses its internal wildcard matching implementation. You
can provide your own matching function by the \fICURLOPT_FNMATCH_FUNCTION\fP
option.
This feature is only supported by the FTP download for now.
A brief introduction of its syntax follows:
.RS
.IP "\fB*\fP - ASTERISK"
\&ftp://example.com/some/path/\fB*.txt\fP (for all txt's from the root
directory)
.RE
.RS
.IP "\fB?\fP - QUESTION MARK"
Question mark matches any (exactly one) character.
\&ftp://example.com/some/path/\fBphoto?.jpeg\fP
.RE
.RS
.IP "\fB[\fP - BRACKET EXPRESSION"
The left bracket opens a bracket expression. The question mark and asterisk have
no special meaning in a bracket expression. Each bracket expression ends by the
right bracket and matches exactly one character. Some examples follow:
\fB[a-zA-Z0\-9]\fP or \fB[f\-gF\-G]\fP \- character interval
\fB[abc]\fP - character enumeration
\fB[^abc]\fP or \fB[!abc]\fP - negation
\fB[[:\fP\fIname\fP\fB:]]\fP class expression. Supported classes are
\fBalnum\fP,\fBlower\fP, \fBspace\fP, \fBalpha\fP, \fBdigit\fP, \fBprint\fP,
\fBupper\fP, \fBblank\fP, \fBgraph\fP, \fBxdigit\fP.
\fB[][-!^]\fP - special case \- matches only '\-', ']', '[', '!' or '^'. These
characters have no special purpose.
\fB[\\[\\]\\\\]\fP - escape syntax. Matches '[', ']' or '\\'.
Using the rules above, a file name pattern can be constructed:
\&ftp://example.com/some/path/\fB[a-z[:upper:]\\\\].jpeg\fP
.RE
.PP
(This was added in 7.21.0)
.SH CALLBACK OPTIONS
.IP CURLOPT_WRITEFUNCTION
Function pointer that should match the following prototype: \fBsize_t
@@ -246,11 +296,11 @@ argument in the opensocket callback set with \fICURLOPT_OPENSOCKETFUNCTION\fP.
Function pointer that should match the \fIcurl_progress_callback\fP prototype
found in \fI<curl/curl.h>\fP. This function gets called by libcurl instead of
its internal equivalent with a frequent interval during operation (roughly
once per second) no matter if data is being transfered or not. Unknown/unused
argument values passed to the callback will be set to zero (like if you only
download data, the upload size will remain 0). Returning a non-zero value from
this callback will cause libcurl to abort the transfer and return
\fICURLE_ABORTED_BY_CALLBACK\fP.
once per second or sooner) no matter if data is being transfered or not.
Unknown/unused argument values passed to the callback will be set to zero
(like if you only download data, the upload size will remain 0). Returning a
non-zero value from this callback will cause libcurl to abort the transfer and
return \fICURLE_ABORTED_BY_CALLBACK\fP.
If you transfer data with the multi interface, this function will not be
called during periods of idleness unless you call the appropriate libcurl
@@ -424,6 +474,49 @@ in 7.20.0)
.IP CURLOPT_INTERLEAVEDATA
This is the stream that will be passed to \fICURLOPT_INTERLEAVEFUNCTION\fP when
interleaved RTP data is received. (Added in 7.20.0)
.IP CURLOPT_CHUNK_BGN_FUNCTION
Function pointer that should match the following prototype: \fBlong function
(const void *transfer_info, void *ptr, int remains)\fP. This function gets
called by libcurl before a part of the stream is going to be transferred (if
the transfer supports chunks).
This callback makes sense only when using the \fICURLOPT_WILDCARDMATCH\fP
option for now.
The target of transfer_info parameter is a "feature depended" structure. For
the FTP wildcard download, the target is curl_fileinfo structure (see
\fIcurl/curl.h\fP). The parameter ptr is a pointer given by
\fICURLOPT_CHUNK_DATA\fP. The parameter remains contains number of chunks
remaining per the transfer. If the feature is not available, the parameter has
zero value.
Return \fICURL_CHUNK_BGN_FUNC_OK\fP if everything is fine,
\fICURL_CHUNK_BGN_FUNC_SKIP\fP if you want to skip the concrete chunk or
\fICURL_CHUNK_BGN_FUNC_FAIL\fP to tell libcurl to stop if some error occurred.
(This was added in 7.21.0)
.IP CURLOPT_CHUNK_END_FUNCTION
Function pointer that should match the following prototype: \fBlong
function(void *ptr)\fP. This function gets called by libcurl as soon as a part
of the stream has been transferred (or skipped).
Return \fICURL_CHUNK_END_FUNC_OK\fP if everything is fine or
\fBCURL_CHUNK_END_FUNC_FAIL\fP to tell the lib to stop if some error occurred.
(This was added in 7.21.0)
.IP CURLOPT_CHUNK_DATA
Pass a pointer that will be untouched by libcurl and passed as the ptr
argument to the \fICURL_CHUNK_BGN_FUNTION\fP and \fICURL_CHUNK_END_FUNTION\fP.
(This was added in 7.21.0)
.IP CURLOPT_FNMATCH_FUNCTION
Function pointer that should match \fBint function(void *ptr, const char
*pattern, const char *string)\fP prototype (see \fIcurl/curl.h\fP). It is used
internally for the wildcard matching feature.
Return \fICURL_FNMATCHFUNC_MATCH\fP if pattern matches the string,
\fICURL_FNMATCHFUNC_NOMATCH\fP if not or \fICURL_FNMATCHFUNC_FAIL\fP if an
error occurred. (This was added in 7.21.0)
.IP CURLOPT_FNMATCH_DATA
Pass a pointer that will be untouched by libcurl and passed as the ptr argument
to the \fICURL_FNMATCH_FUNCTION\fP. (This was added in 7.21.0)
.SH ERROR OPTIONS
.IP CURLOPT_ERRORBUFFER
Pass a char * to a buffer that the libcurl may store human readable error

View File

@@ -218,6 +218,16 @@ return code is only returned from \fIcurl_easy_recv(3)\fP and
Failed to load CRL file (Added in 7.19.0)
.IP "CURLE_SSL_ISSUER_ERROR (83)"
Issuer check failed (Added in 7.19.0)
.IP "CURLE_FTP_PRET_FAILED (84)"
PRET command failed
.IP "CURLE_RTSP_CSEQ_ERROR (85)"
Mismatch of RTSP CSeq numbers.
.IP "CURLE_RTSP_SESSION_ERROR (86)"
Mismatch of RTSP Session Identifiers.
.IP "CURLE_FTP_BAD_FILE_LIST (87)"
Unable to parse FTP file list (during FTP wildcard downloading).
.IP "CURLE_CHUNK_FAILED (88)"
Chunk callback reported error.
.IP "CURLE_OBSOLETE*"
These error codes will never be returned. They were used in an old libcurl
version and are currently unused.

View File

@@ -151,11 +151,14 @@ CURLINFO_HTTPAUTH_AVAIL 7.10.8
CURLINFO_HTTP_CODE 7.4.1 7.10.8
CURLINFO_HTTP_CONNECTCODE 7.10.7
CURLINFO_LASTSOCKET 7.15.2
CURLINFO_LOCAL_IP 7.21.0
CURLINFO_LOCAL_PORT 7.21.0
CURLINFO_NAMELOOKUP_TIME 7.4.1
CURLINFO_NUM_CONNECTS 7.12.3
CURLINFO_OS_ERRNO 7.12.2
CURLINFO_PRETRANSFER_TIME 7.4.1
CURLINFO_PRIMARY_IP 7.19.0
CURLINFO_PRIMARY_PORT 7.21.0
CURLINFO_PRIVATE 7.10.3
CURLINFO_PRIVATE 7.10.3
CURLINFO_PROXYAUTH_AVAIL 7.10.8
@@ -188,6 +191,9 @@ CURLOPT_BUFFERSIZE 7.10
CURLOPT_CAINFO 7.4.2
CURLOPT_CAPATH 7.9.8
CURLOPT_CERTINFO 7.19.1
CURLOPT_CHUNK_BGN_FUNCTION 7.21.0
CURLOPT_CHUNK_DATA 7.21.0
CURLOPT_CHUNK_END_FUNCTION 7.21.0
CURLOPT_CLOSEFUNCTION 7.7 7.11.1 7.15.4
CURLOPT_CLOSEPOLICY 7.7 7.16.1
CURLOPT_CONNECTTIMEOUT 7.7
@@ -217,6 +223,8 @@ CURLOPT_FAILONERROR 7.1
CURLOPT_FILE 7.1 7.9.7
CURLOPT_FILETIME 7.5
CURLOPT_FLAGS 7.1 - 7.9.2
CURLOPT_FNMATCH_DATA 7.21.0
CURLOPT_FNMATCH_FUNCTION 7.21.0
CURLOPT_FOLLOWLOCATION 7.1
CURLOPT_FORBID_REUSE 7.7
CURLOPT_FRESH_CONNECT 7.7
@@ -236,14 +244,6 @@ CURLOPT_FTP_SSL_CCC 7.16.1
CURLOPT_FTP_USE_EPRT 7.10.5
CURLOPT_FTP_USE_EPSV 7.9.2
CURLOPT_FTP_USE_PRET 7.20.0
CURLOPT_RTSP_REQUEST 7.20.0
CURLOPT_RTSP_SESSION_ID 7.20.0
CURLOPT_RTSP_STREAM_URI 7.20.0
CURLOPT_RTSP_TRANSPORT 7.20.0
CURLOPT_RTSP_CLIENT_CSEQ 7.20.0
CURLOPT_RTSP_SERVER_CSEQ 7.20.0
CURLOPT_INTERLEAVEDATA 7.20.0
CURLOPT_INTERLEAVEFUNCTION 7.20.0
CURLOPT_HEADER 7.1
CURLOPT_HEADERDATA 7.10
CURLOPT_HEADERFUNCTION 7.7.2
@@ -262,6 +262,8 @@ CURLOPT_INFILE 7.1 7.9.7
CURLOPT_INFILESIZE 7.1
CURLOPT_INFILESIZE_LARGE 7.11.0
CURLOPT_INTERFACE 7.3
CURLOPT_INTERLEAVEDATA 7.20.0
CURLOPT_INTERLEAVEFUNCTION 7.20.0
CURLOPT_IOCTLDATA 7.12.3
CURLOPT_IOCTLFUNCTION 7.12.3
CURLOPT_IPRESOLVE 7.10.8
@@ -328,6 +330,12 @@ CURLOPT_REDIR_PROTOCOLS 7.19.4
CURLOPT_REFERER 7.1
CURLOPT_RESUME_FROM 7.1
CURLOPT_RESUME_FROM_LARGE 7.11.0
CURLOPT_RTSP_CLIENT_CSEQ 7.20.0
CURLOPT_RTSP_REQUEST 7.20.0
CURLOPT_RTSP_SERVER_CSEQ 7.20.0
CURLOPT_RTSP_SESSION_ID 7.20.0
CURLOPT_RTSP_STREAM_URI 7.20.0
CURLOPT_RTSP_TRANSPORT 7.20.0
CURLOPT_SEEKDATA 7.18.1
CURLOPT_SEEKFUNCTION 7.18.1
CURLOPT_SHARE 7.10
@@ -380,6 +388,7 @@ CURLOPT_USERNAME 7.19.1
CURLOPT_USERPWD 7.1
CURLOPT_USE_SSL 7.17.0
CURLOPT_VERBOSE 7.1
CURLOPT_WILDCARDMATCH 7.21.0
CURLOPT_WRITEDATA 7.9.7
CURLOPT_WRITEFUNCTION 7.1
CURLOPT_WRITEHEADER 7.1
@@ -396,6 +405,12 @@ CURLPROTO_LDAP 7.19.4
CURLPROTO_LDAPS 7.19.4
CURLPROTO_POP3 7.20.0
CURLPROTO_POP3S 7.20.0
CURLPROTO_RTMP 7.21.0
CURLPROTO_RTMPE 7.21.0
CURLPROTO_RTMPS 7.21.0
CURLPROTO_RTMPT 7.21.0
CURLPROTO_RTMPTE 7.21.0
CURLPROTO_RTMPTS 7.21.0
CURLPROTO_RTSP 7.20.0
CURLPROTO_SCP 7.19.4
CURLPROTO_SFTP 7.19.4
@@ -427,6 +442,14 @@ CURLVERSION_FIRST 7.10
CURLVERSION_NOW 7.10
CURLVERSION_SECOND 7.11.1
CURLVERSION_THIRD 7.12.0
CURL_CHUNK_BGN_FUNC_FAIL 7.21.0
CURL_CHUNK_BGN_FUNC_OK 7.21.0
CURL_CHUNK_BGN_FUNC_SKIP 7.21.0
CURL_CHUNK_END_FUNC_FAIL 7.21.0
CURL_CHUNK_END_FUNC_OK 7.21.0
CURL_FNMATCHFUNC_FAIL 7.21.0
CURL_FNMATCHFUNC_MATCH 7.21.0
CURL_FNMATCHFUNC_NOMATCH 7.21.0
CURL_HTTP_VERSION_1_0 7.9.1
CURL_HTTP_VERSION_1_1 7.9.1
CURL_HTTP_VERSION_NONE 7.9.1

View File

@@ -1,3 +1,3 @@
curlbuild.h
stamp-h3
curlver.h.dist

View File

@@ -198,6 +198,97 @@ typedef size_t (*curl_write_callback)(char *buffer,
size_t nitems,
void *outstream);
/* enumeration of file types */
typedef enum {
CURLFILETYPE_FILE = 0,
CURLFILETYPE_DIRECTORY,
CURLFILETYPE_SYMLINK,
CURLFILETYPE_DEVICE_BLOCK,
CURLFILETYPE_DEVICE_CHAR,
CURLFILETYPE_NAMEDPIPE,
CURLFILETYPE_SOCKET,
CURLFILETYPE_DOOR, /* is possible only on Sun Solaris now */
CURLFILETYPE_UNKNOWN /* should never occur */
} curlfiletype;
#define CURLFINFOFLAG_KNOWN_FILENAME (1<<0)
#define CURLFINFOFLAG_KNOWN_FILETYPE (1<<1)
#define CURLFINFOFLAG_KNOWN_TIME (1<<2)
#define CURLFINFOFLAG_KNOWN_PERM (1<<3)
#define CURLFINFOFLAG_KNOWN_UID (1<<4)
#define CURLFINFOFLAG_KNOWN_GID (1<<5)
#define CURLFINFOFLAG_KNOWN_SIZE (1<<6)
#define CURLFINFOFLAG_KNOWN_HLINKCOUNT (1<<7)
/* Content of this structure depends on information which is known and is
achievable (e.g. by FTP LIST parsing). Please see the url_easy_setopt(3) man
page for callbacks returning this structure -- some fields are mandatory,
some others are optional. The FLAG field has special meaning. */
struct curl_fileinfo {
char *filename;
curlfiletype filetype;
time_t time;
unsigned int perm;
int uid;
int gid;
curl_off_t size;
long int hardlinks;
struct {
/* If some of these fields is not NULL, it is a pointer to b_data. */
char *time;
char *perm;
char *user;
char *group;
char *target; /* pointer to the target filename of a symlink */
} strings;
unsigned int flags;
/* used internally */
char * b_data;
size_t b_size;
size_t b_used;
};
/* return codes for CURLOPT_CHUNK_BGN_FUNCTION */
#define CURL_CHUNK_BGN_FUNC_OK 0
#define CURL_CHUNK_BGN_FUNC_FAIL 1 /* tell the lib to end the task */
#define CURL_CHUNK_BGN_FUNC_SKIP 2 /* skip this chunk over */
/* if splitting of data transfer is enabled, this callback is called before
download of an individual chunk started. Note that parameter "remains" works
only for FTP wildcard downloading (for now), otherwise is not used */
typedef long (*curl_chunk_bgn_callback)(const void *transfer_info,
void *ptr,
int remains);
/* return codes for CURLOPT_CHUNK_END_FUNCTION */
#define CURL_CHUNK_END_FUNC_OK 0
#define CURL_CHUNK_END_FUNC_FAIL 1 /* tell the lib to end the task */
/* If splitting of data transfer is enabled this callback is called after
download of an individual chunk finished.
Note! After this callback was set then it have to be called FOR ALL chunks.
Even if downloading of this chunk was skipped in CHUNK_BGN_FUNC.
This is the reason why we don't need "transfer_info" parameter in this
callback and we are not interested in "remains" parameter too. */
typedef long (*curl_chunk_end_callback)(void *ptr);
/* return codes for FNMATCHFUNCTION */
#define CURL_FNMATCHFUNC_MATCH 0 /* string corresponds to the pattern */
#define CURL_FNMATCHFUNC_NOMATCH 1 /* pattern doesn't match the string */
#define CURL_FNMATCHFUNC_FAIL 2 /* an error occurred */
/* callback type for wildcard downloading pattern matching. If the
string matches the pattern, return CURL_FNMATCHFUNC_MATCH value, etc. */
typedef int (*curl_fnmatch_callback)(void *ptr,
const char *pattern,
const char *string);
/* These are the return codes for the seek callbacks */
#define CURL_SEEKFUNC_OK 0
#define CURL_SEEKFUNC_FAIL 1 /* fail the entire transfer */
@@ -409,6 +500,8 @@ typedef enum {
CURLE_FTP_PRET_FAILED, /* 84 - a PRET command failed */
CURLE_RTSP_CSEQ_ERROR, /* 85 - mismatch of RTSP CSeq numbers */
CURLE_RTSP_SESSION_ERROR, /* 86 - mismatch of RTSP Session Identifiers */
CURLE_FTP_BAD_FILE_LIST, /* 87 - unable to parse FTP file list */
CURLE_CHUNK_FAILED, /* 88 - chunk callback reported error */
CURL_LAST /* never use! */
} CURLcode;
@@ -623,6 +716,12 @@ typedef enum {
#define CURLPROTO_SMTP (1<<16)
#define CURLPROTO_SMTPS (1<<17)
#define CURLPROTO_RTSP (1<<18)
#define CURLPROTO_RTMP (1<<19)
#define CURLPROTO_RTMPT (1<<20)
#define CURLPROTO_RTMPE (1<<21)
#define CURLPROTO_RTMPTE (1<<22)
#define CURLPROTO_RTMPS (1<<23)
#define CURLPROTO_RTMPTS (1<<24)
#define CURLPROTO_ALL (~0) /* enable everything */
/* long may be 32 or 64 bits, but we should never depend on anything else
@@ -1316,6 +1415,26 @@ typedef enum {
/* Let the application define a custom write method for RTP data */
CINIT(INTERLEAVEFUNCTION, FUNCTIONPOINT, 196),
/* Turn on wildcard matching */
CINIT(WILDCARDMATCH, LONG, 197),
/* Directory matching callback called before downloading of an
individual file (chunk) started */
CINIT(CHUNK_BGN_FUNCTION, FUNCTIONPOINT, 198),
/* Directory matching callback called after the file (chunk)
was downloaded, or skipped */
CINIT(CHUNK_END_FUNCTION, FUNCTIONPOINT, 199),
/* Change match (fnmatch-like) callback for wildcard matching */
CINIT(FNMATCH_FUNCTION, FUNCTIONPOINT, 200),
/* Let the application define custom chunk data pointer */
CINIT(CHUNK_DATA, OBJECTPOINT, 201),
/* FNMATCH_FUNCTION user pointer */
CINIT(FNMATCH_DATA, OBJECTPOINT, 202),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;
@@ -1764,9 +1883,12 @@ typedef enum {
CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
CURLINFO_RTSP_SERVER_CSEQ = CURLINFO_LONG + 38,
CURLINFO_RTSP_CSEQ_RECV = CURLINFO_LONG + 39,
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
/* Fill in new entries below here! */
CURLINFO_LASTONE = 39
CURLINFO_LASTONE = 42
} CURLINFO;
/* CURLINFO_RESPONSE_CODE is the new name for the option previously known as

View File

@@ -30,13 +30,13 @@
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.20.1-DEV"
#define LIBCURL_VERSION "7.21.0-DEV"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 20
#define LIBCURL_VERSION_PATCH 1
#define LIBCURL_VERSION_MINOR 21
#define LIBCURL_VERSION_PATCH 0
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -53,7 +53,7 @@
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x071401
#define LIBCURL_VERSION_NUM 0x071500
/*
* This is the date and time when the full source package was created. The

5
lib/.gitignore vendored
View File

@@ -4,3 +4,8 @@ stamp-h1
*.orig
*.rej
TAGS
Makefile.vc8.dist
Makefile.vc9.dist
libcurl.plist.dist
libcurl.vcproj
vc6libcurl.dsp

View File

@@ -44,6 +44,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c &
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c &
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c &
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c &
curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c &
krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c &
multi.c content_encoding.c share.c http_digest.c md5.c curl_rand.c &
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c &
@@ -52,7 +53,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c &
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c &
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c &
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c &
warnless.c
warnless.c hmac.c polarssl.c curl_rtmp.c openldap.c
OBJS = $(CSOURCES:.c=.obj)
OBJS = $OBJ_DIR\$(OBJS: = $OBJ_DIR\)

View File

@@ -4,6 +4,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
curl_fnmatch.c fileinfo.c ftplistparser.c wildcard.c \
krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c \
multi.c content_encoding.c share.c http_digest.c md5.c curl_rand.c \
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
@@ -12,12 +13,13 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c \
warnless.c
warnless.c hmac.c polarssl.c curl_rtmp.c openldap.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
if2ip.h speedcheck.h urldata.h curl_ldap.h ssluse.h escape.h telnet.h \
getinfo.h strequal.h krb4.h memdebug.h http_chunks.h curl_rand.h \
curl_fnmatch.h wildcard.h fileinfo.h ftplistparser.h \
strtok.h connect.h llist.h hash.h content_encoding.h share.h \
curl_md5.h http_digest.h http_negotiate.h http_ntlm.h inet_pton.h \
strtoofft.h strerror.h inet_ntop.h curlx.h curl_memory.h setup.h \
@@ -25,4 +27,4 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h qssl.h hostip.h \
tftp.h sockaddr.h splay.h strdup.h setup_once.h socks.h ssh.h nssg.h \
curl_base64.h rawstr.h curl_addrinfo.h curl_sspi.h slist.h nonblock.h \
curl_memrchr.h imap.h pop3.h smtp.h pingpong.h rtsp.h curl_threads.h \
warnless.h
warnless.h curl_hmac.h polarssl.h curl_rtmp.h

View File

@@ -16,7 +16,7 @@
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.4
ZLIB_PATH = ../../zlib-1.2.5
endif
# Edit the path below to point to the base of your OpenSSL package.
ifndef OPENSSL_PATH
@@ -24,7 +24,7 @@ OPENSSL_PATH = ../../openssl-0.9.8n
endif
# Edit the path below to point to the base of your LibSSH2 package.
ifndef LIBSSH2_PATH
LIBSSH2_PATH = ../../libssh2-1.2.4
LIBSSH2_PATH = ../../libssh2-1.2.5
endif
# Edit the path below to point to the base of your libidn package.
ifndef LIBIDN_PATH

View File

@@ -14,7 +14,7 @@ endif
# Edit the path below to point to the base of your Zlib sources.
ifndef ZLIB_PATH
ZLIB_PATH = ../../zlib-1.2.4
ZLIB_PATH = ../../zlib-1.2.5
endif
# Edit the path below to point to the base of your OpenSSL package.
@@ -24,7 +24,7 @@ endif
# Edit the path below to point to the base of your LibSSH2 package.
ifndef LIBSSH2_PATH
LIBSSH2_PATH = ../../libssh2-1.2.4
LIBSSH2_PATH = ../../libssh2-1.2.5
endif
# Edit the path below to point to the base of your libidn package.

View File

@@ -1,6 +1,4 @@
# Makefile for project libcurl
# Generated on Sun,13 Jan 2002.16:57:00 by EasyGCC (0.1.3 [beta 2] (3 Jan 2002))
# Contact: easygcc@melotech.co.uk
# Project objects:
objs = o.base64 o.connect o.cookie o.dict \
@@ -9,13 +7,15 @@ objs = o.base64 o.connect o.cookie o.dict \
o.getinfo o.getpass o.hostip \
o.hostip4 o.hostsyn o.http \
o.http_chunks o.inet_ntop o.inet_pton o.if2ip o.krb4 o.ldap \
o.curl_fnmatch o.fileinfo o.ftplistparser o.wildcard \
o.memdebug o.mprintf o.netrc o.parsedate o.progress \
o.security o.select o.sendf o.speedcheck o.ssluse \
o.strequal o.strtok o.telnet o.timeval \
o.transfer o.url o.version o.strtoofft o.sslgen o.gtls \
o.rawstr o.curl_addrinfo o.slist o.nonblock o.curl_rand \
o.curl_memrchr o.imap o.pop3 o.smtp o.pingpong o.rtsp \
o.curl_threads o.warnless
o.curl_threads o.warnless o.hmac o.md5 o.curl_rtmp \
o.openldap o.polarssl
# Compile options:
@@ -45,6 +45,9 @@ o.curl_memrchr: c.curl_memrchr
o.curl_rand: c.curl_rand
gcc $(compileropts) -c -o curl_rand.o c.curl_rand
o.curl_rtmp: c.curl_rtmp
gcc $(compileropts) -c -o curl_rtmp.o c.curl_rtmp
o.curl_threads: c.curl_threads
gcc $(compileropts) -c -o curl_threads.o c.curl_threads
@@ -78,6 +81,9 @@ o.getinfo: c.getinfo
o.getpass: c.getpass
gcc $(compileropts) -c -o getpass.o c.getpass
o.hmac: c.hmac
gcc $(compileropts) -c -o hmac.o c.hmac
o.hostip: c.hostip
gcc $(compileropts) -c -o hostip.o c.hostip
@@ -111,6 +117,9 @@ o.krb4: c.krb4
o.ldap: c.ldap
gcc $(compileropts) -IOpenLDAP: -c -o ldap.o c.ldap
o.md5: c.md5
gcc $(compileropts) -c -o md5.o c.md5
o.memdebug: c.memdebug
gcc $(compileropts) -c -o memdebug.o c.memdebug
@@ -120,12 +129,18 @@ o.mprintf: c.mprintf
o.netrc: c.netrc
gcc $(compileropts) -c -o netrc.o c.netrc
o.openldap: c.openldap
gcc $(compileropts) -c -o openldap.o c.openldap
o.parsedate: c.parsedate
gcc $(compileropts) -c -o parsedate.o c.parsedate
o.pingpong: c.pingpong
gcc $(compileropts) -c -o pingpong.o c.pingpong
o.polarssl: c.polarssl
gcc $(compileropts) -c -o polarssl.o c.polarssl
o.pop3: c.pop3
gcc $(compileropts) -c -o pop3.o c.pop3
@@ -153,7 +168,7 @@ o.smtp: c.smtp
o.speedcheck: c.speedcheck
gcc $(compileropts) -c -o speedcheck.o c.speedcheck
o.gtls: c.gtls
o.gtls: c.gtls
gcc $(compileropts) -c -o gtls.o c.gtls
o.sslgen: c.sslgen
@@ -186,7 +201,7 @@ o.timeval: c.timeval
o.transfer: c.transfer
gcc $(compileropts) -c -o transfer.o c.transfer
o.url: c.url
o.url: c.url
gcc $(compileropts) -c -o url.o c.url
o.version: c.version
@@ -194,3 +209,15 @@ o.version: c.version
o.warnless: c.warnless
gcc $(compileropts) -c -o warnless.o c.warnless
o.curl_fnmatch: c.curl_fnmatch
gcc $(compileropts) -c -o curl_fnmatch.o c.curl_fnmatch
o.fileinfo: c.fileinfo
gcc $(compileropts) -c -o fileinfo.o c.fileinfo
o.ftplistparser: c.ftplistparser
gcc $(compileropts) -c -o ftplistparser.o c.ftplistparser
o.wildcard: c.wildcard
gcc $(compileropts) -c -o wildcard.o c.wildcard

View File

@@ -5,7 +5,7 @@
# | (__| |_| | _ <| |___
# \___|\___/|_| \_\_____|
#
# Copyright (C) 1999 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
# Copyright (C) 1999 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
@@ -18,7 +18,6 @@
# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
# KIND, either express or implied.
#
# $Id: Makefile.am,v 1.139 2008-11-03 08:50:58 bagder Exp $
###########################################################################
#
# Makefile for building libcurl with MSVC6
@@ -101,7 +100,7 @@ LFLAGS = /nologo /machine:$(MACHINE)
SSLLIBS = libeay32.lib ssleay32.lib
ZLIBLIBSDLL= zdll.lib
ZLIBLIBS = zlib.lib
WINLIBS = wsock32.lib wldap32.lib
WINLIBS = ws2_32.lib wldap32.lib
CFLAGS = $(CFLAGS)
CFGSET = FALSE
@@ -450,32 +449,37 @@ X_OBJS= \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\cookie.obj \
$(DIROBJ)\curl_addrinfo.obj \
$(DIROBJ)\curl_fnmatch.obj \
$(DIROBJ)\curl_memrchr.obj \
$(DIROBJ)\curl_rand.obj \
$(DIROBJ)\curl_rtmp.obj \
$(DIROBJ)\curl_sspi.obj \
$(DIROBJ)\curl_threads.obj \
$(DIROBJ)\dict.obj \
$(DIROBJ)\easy.obj \
$(DIROBJ)\escape.obj \
$(DIROBJ)\fileinfo.obj \
$(DIROBJ)\file.obj \
$(DIROBJ)\formdata.obj \
$(DIROBJ)\ftplistparser.obj \
$(DIROBJ)\ftp.obj \
$(DIROBJ)\getenv.obj \
$(DIROBJ)\getinfo.obj \
$(DIROBJ)\gtls.obj \
$(DIROBJ)\hash.obj \
$(DIROBJ)\hmac.obj \
$(DIROBJ)\hostares.obj \
$(DIROBJ)\hostasyn.obj \
$(DIROBJ)\hostip.obj \
$(DIROBJ)\hostip4.obj \
$(DIROBJ)\hostip6.obj \
$(DIROBJ)\hostip.obj \
$(DIROBJ)\hostsyn.obj \
$(DIROBJ)\hostthre.obj \
$(DIROBJ)\http.obj \
$(DIROBJ)\http_chunks.obj \
$(DIROBJ)\http_digest.obj \
$(DIROBJ)\http_negotiate.obj \
$(DIROBJ)\http_ntlm.obj \
$(DIROBJ)\http.obj \
$(DIROBJ)\if2ip.obj \
$(DIROBJ)\imap.obj \
$(DIROBJ)\inet_ntop.obj \
@@ -488,8 +492,10 @@ X_OBJS= \
$(DIROBJ)\multi.obj \
$(DIROBJ)\netrc.obj \
$(DIROBJ)\nonblock.obj \
$(DIROBJ)\openldap.obj \
$(DIROBJ)\parsedate.obj \
$(DIROBJ)\pingpong.obj \
$(DIROBJ)\polarssl.obj \
$(DIROBJ)\pop3.obj \
$(DIROBJ)\progress.obj \
$(DIROBJ)\rawstr.obj \
@@ -499,8 +505,8 @@ X_OBJS= \
$(DIROBJ)\share.obj \
$(DIROBJ)\slist.obj \
$(DIROBJ)\smtp.obj \
$(DIROBJ)\socks.obj \
$(DIROBJ)\socks_gssapi.obj \
$(DIROBJ)\socks.obj \
$(DIROBJ)\socks_sspi.obj \
$(DIROBJ)\speedcheck.obj \
$(DIROBJ)\splay.obj \
@@ -518,6 +524,7 @@ X_OBJS= \
$(DIROBJ)\url.obj \
$(DIROBJ)\version.obj \
$(DIROBJ)\warnless.obj \
$(DIROBJ)\wildcard.obj \
$(RESOURCE)
all : $(TARGET)

View File

@@ -48,10 +48,7 @@
/* to enable hidden symbols */
/*#define CURL_HIDDEN_SYMBOLS 1*/
/* W$ LDAP with non-W$ compiler */
/* #undef CURL_LDAP_HYBRID */
/* Use W$ LDAP implementation */
/* Use Windows LDAP implementation */
/* #undef CURL_LDAP_WIN */
/* when not building a shared library */

View File

@@ -59,10 +59,7 @@
/* to enable hidden symbols */
/* #undef CURL_HIDDEN_SYMBOLS */
/* W$ LDAP with non-W$ compiler */
/* #undef CURL_LDAP_HYBRID */
/* Use W$ LDAP implementation */
/* Use Windows LDAP implementation */
/* #undef CURL_LDAP_WIN */
/* when not building a shared library */

View File

@@ -535,16 +535,13 @@
/* ---------------------------------------------------------------- */
#if defined(CURL_HAS_NOVELL_LDAPSDK) || defined(CURL_HAS_MOZILLA_LDAPSDK)
#undef CURL_LDAP_HYBRID
#undef CURL_LDAP_WIN
#define HAVE_LDAP_SSL_H 1
#define HAVE_LDAP_URL_PARSE 1
#elif defined(CURL_HAS_OPENLDAP_LDAPSDK)
#undef CURL_LDAP_HYBRID
#undef CURL_LDAP_WIN
#define HAVE_LDAP_URL_PARSE 1
#else
#undef CURL_LDAP_HYBRID
#undef HAVE_LDAP_URL_PARSE
#define CURL_LDAP_WIN 1
#endif

View File

@@ -379,7 +379,6 @@
/* ---------------------------------------------------------------- */
#define CURL_LDAP_WIN 1
#undef CURL_LDAP_HYBRID
#undef HAVE_LDAP_URL_PARSE
/* ---------------------------------------------------------------- */

View File

@@ -523,6 +523,90 @@ static bool trynextip(struct connectdata *conn,
return TRUE;
}
/* retrieves ip address and port from a sockaddr structure */
static bool getaddressinfo(struct sockaddr* sa, char* addr,
long* port)
{
unsigned short us_port;
struct sockaddr_in* si = NULL;
#ifdef ENABLE_IPV6
struct sockaddr_in6* si6 = NULL;
#endif
switch (sa->sa_family) {
case AF_INET:
si = (struct sockaddr_in*) sa;
if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
addr, MAX_IPADR_LEN) == NULL)
return FALSE;
us_port = ntohs(si->sin_port);
*port = us_port;
break;
#ifdef ENABLE_IPV6
case AF_INET6:
si6 = (struct sockaddr_in6*)sa;
if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
addr, MAX_IPADR_LEN) == NULL)
return FALSE;
us_port = ntohs(si6->sin6_port);
*port = us_port;
break;
#endif
default:
addr[0] = '\0';
*port = 0;
}
return TRUE;
}
/* retrieves the start/end point information of a socket of an established
connection */
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
{
int error;
curl_socklen_t len;
struct Curl_sockaddr_storage ssrem;
struct Curl_sockaddr_storage ssloc;
struct SessionHandle *data = conn->data;
struct PureInfo *info = &conn->data->info;
if(conn->bits.reuse)
/* reusing same connection */
return;
len = sizeof(struct Curl_sockaddr_storage);
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
error = SOCKERRNO;
failf(data, "getpeername() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
len = sizeof(struct Curl_sockaddr_storage);
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
if(!getaddressinfo((struct sockaddr*)&ssrem,
info->ip, &info->port)) {
error = ERRNO;
failf(data, "ssrem inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
if(!getaddressinfo((struct sockaddr*)&ssloc,
info->localip, &info->localport)) {
error = ERRNO;
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
error, Curl_strerror(conn, error));
return;
}
}
/*
* Curl_is_connected() is used from the multi interface to check if the
* firstsocket has connected.
@@ -575,6 +659,10 @@ CURLcode Curl_is_connected(struct connectdata *conn,
/* we are connected, awesome! */
conn->bits.tcpconnect = TRUE;
*connected = TRUE;
Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
Curl_verboseconnect(conn);
Curl_updateconninfo(conn, sockfd);
return CURLE_OK;
}
/* nope, not connected for real */
@@ -864,6 +952,7 @@ singleipconnect(struct connectdata *conn,
/* we are connected, awesome! */
*connected = TRUE; /* this is a true connect */
infof(data, "connected\n");
Curl_updateconninfo(conn, sockfd);
return sockfd;
}
else if(WAITCONN_TIMEOUT == rc)

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -68,4 +68,6 @@ void Curl_sndbufset(curl_socket_t sockfd);
#define Curl_sndbufset(y)
#endif
void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd);
#endif

View File

@@ -103,7 +103,7 @@ inflate_stream(struct connectdata *conn,
status = inflate(z, Z_SYNC_FLUSH);
if(status == Z_OK || status == Z_STREAM_END) {
allow_restart = 0;
if(DSIZ - z->avail_out) {
if((DSIZ - z->avail_out) && (!k->ignorebody)) {
result = Curl_client_write(conn, CLIENTWRITE_BODY, decomp,
DSIZ - z->avail_out);
/* if !CURLE_OK, clean up, return */
@@ -247,7 +247,6 @@ static enum {
/* Skip over the NUL */
--len;
++data;
}
if(flags & HEAD_CRC) {
@@ -255,7 +254,6 @@ static enum {
return GZIP_UNDERFLOW;
len -= 2;
data += 2;
}
*headerlen = totallen - len;

View File

@@ -58,10 +58,7 @@
/* to enable hidden symbols */
#cmakedefine CURL_HIDDEN_SYMBOLS ${CURL_HIDDEN_SYMBOLS}
/* W$ LDAP with non-W$ compiler */
#cmakedefine CURL_LDAP_HYBRID ${CURL_LDAP_HYBRID}
/* Use W$ LDAP implementation */
/* Use Windows LDAP implementation */
#cmakedefine CURL_LDAP_WIN ${CURL_LDAP_WIN}
/* when not building a shared library */
@@ -889,6 +886,9 @@
/* if GnuTLS is enabled */
#cmakedefine USE_GNUTLS ${USE_GNUTLS}
/* if PolarSSL is enabled */
#cmakedefine USE_POLARSSL ${USE_POLARSSL}
/* if libSSH2 is in use */
#cmakedefine USE_LIBSSH2 ${USE_LIBSSH2}

424
lib/curl_fnmatch.c Normal file
View File

@@ -0,0 +1,424 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include "curl_fnmatch.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#define CURLFNM_CHARSET_LEN (sizeof(char) * 256)
#define CURLFNM_CHSET_SIZE (CURLFNM_CHARSET_LEN + 15)
#define CURLFNM_NEGATE CURLFNM_CHARSET_LEN
#define CURLFNM_ALNUM (CURLFNM_CHARSET_LEN + 1)
#define CURLFNM_DIGIT (CURLFNM_CHARSET_LEN + 2)
#define CURLFNM_XDIGIT (CURLFNM_CHARSET_LEN + 3)
#define CURLFNM_ALPHA (CURLFNM_CHARSET_LEN + 4)
#define CURLFNM_PRINT (CURLFNM_CHARSET_LEN + 5)
#define CURLFNM_BLANK (CURLFNM_CHARSET_LEN + 6)
#define CURLFNM_LOWER (CURLFNM_CHARSET_LEN + 7)
#define CURLFNM_GRAPH (CURLFNM_CHARSET_LEN + 8)
#define CURLFNM_SPACE (CURLFNM_CHARSET_LEN + 9)
#define CURLFNM_UPPER (CURLFNM_CHARSET_LEN + 10)
typedef enum {
CURLFNM_LOOP_DEFAULT = 0,
CURLFNM_LOOP_BACKSLASH
} loop_state;
typedef enum {
CURLFNM_SCHS_DEFAULT = 0,
CURLFNM_SCHS_MAYRANGE,
CURLFNM_SCHS_MAYRANGE2,
CURLFNM_SCHS_RIGHTBR,
CURLFNM_SCHS_RIGHTBRLEFTBR
} setcharset_state;
typedef enum {
CURLFNM_PKW_INIT = 0,
CURLFNM_PKW_DDOT
} parsekey_state;
#define SETCHARSET_OK 1
#define SETCHARSET_FAIL 0
static int parsekeyword(unsigned char **pattern, unsigned char *charset)
{
parsekey_state state = CURLFNM_PKW_INIT;
#define KEYLEN 10
char keyword[KEYLEN] = { 0 };
int found = FALSE;
int i;
unsigned char *p = *pattern;
for(i = 0; !found; i++) {
char c = *p++;
if(i >= KEYLEN)
return SETCHARSET_FAIL;
switch(state) {
case CURLFNM_PKW_INIT:
if(ISALPHA(c) && ISLOWER(c))
keyword[i] = c;
else if(c == ':')
state = CURLFNM_PKW_DDOT;
else
return 0;
break;
case CURLFNM_PKW_DDOT:
if(c == ']')
found = TRUE;
else
return SETCHARSET_FAIL;
}
}
#undef KEYLEN
*pattern = p; /* move caller's pattern pointer */
if(strcmp(keyword, "digit") == 0)
charset[CURLFNM_DIGIT] = 1;
else if(strcmp(keyword, "alnum") == 0)
charset[CURLFNM_ALNUM] = 1;
else if(strcmp(keyword, "alpha") == 0)
charset[CURLFNM_ALPHA] = 1;
else if(strcmp(keyword, "xdigit") == 0)
charset[CURLFNM_XDIGIT] = 1;
else if(strcmp(keyword, "print") == 0)
charset[CURLFNM_PRINT] = 1;
else if(strcmp(keyword, "graph") == 0)
charset[CURLFNM_GRAPH] = 1;
else if(strcmp(keyword, "space") == 0)
charset[CURLFNM_SPACE] = 1;
else if(strcmp(keyword, "blank") == 0)
charset[CURLFNM_BLANK] = 1;
else if(strcmp(keyword, "upper") == 0)
charset[CURLFNM_UPPER] = 1;
else if(strcmp(keyword, "lower") == 0)
charset[CURLFNM_LOWER] = 1;
else
return SETCHARSET_FAIL;
return SETCHARSET_OK;
}
/* returns 1 (true) if pattern is OK, 0 if is bad ("p" is pattern pointer) */
static int setcharset(unsigned char **p, unsigned char *charset)
{
setcharset_state state = CURLFNM_SCHS_DEFAULT;
unsigned char rangestart = 0;
unsigned char lastchar = 0;
bool something_found = FALSE;
unsigned char c;
for(;;) {
c = **p;
switch(state) {
case CURLFNM_SCHS_DEFAULT:
if(ISALNUM(c)) { /* ASCII value */
rangestart = c;
charset[c] = 1;
(*p)++;
state = CURLFNM_SCHS_MAYRANGE;
something_found = TRUE;
}
else if(c == ']') {
if(something_found)
return SETCHARSET_OK;
else
something_found = TRUE;
state = CURLFNM_SCHS_RIGHTBR;
charset[c] = 1;
(*p)++;
}
else if(c == '[') {
char c2 = *((*p)+1);
if(c2 == ':') { /* there has to be a keyword */
(*p) += 2;
if(parsekeyword(p, charset)) {
state = CURLFNM_SCHS_DEFAULT;
}
else
return SETCHARSET_FAIL;
}
else {
charset[c] = 1;
(*p)++;
}
something_found = TRUE;
}
else if(c == '?' || c == '*') {
something_found = TRUE;
charset[c] = 1;
(*p)++;
}
else if(c == '^' || c == '!') {
if(!something_found) {
if(charset[CURLFNM_NEGATE]) {
charset[c] = 1;
something_found = TRUE;
}
else
charset[CURLFNM_NEGATE] = 1; /* negate charset */
}
else
charset[c] = 1;
(*p)++;
}
else if(c == '\\') {
c = *(++(*p));
if(ISPRINT((c))) {
something_found = TRUE;
state = CURLFNM_SCHS_MAYRANGE;
charset[c] = 1;
rangestart = c;
(*p)++;
}
else
return SETCHARSET_FAIL;
}
else if(c == '\0') {
return SETCHARSET_FAIL;
}
else {
charset[c] = 1;
(*p)++;
something_found = TRUE;
}
break;
case CURLFNM_SCHS_MAYRANGE:
if(c == '-') {
charset[c] = 1;
(*p)++;
lastchar = '-';
state = CURLFNM_SCHS_MAYRANGE2;
}
else if(c == '[') {
state = CURLFNM_SCHS_DEFAULT;
}
else if(ISALNUM(c)) {
charset[c] = 1;
(*p)++;
}
else if(c == '\\') {
c = *(++(*p));
if(ISPRINT(c)) {
charset[c] = 1;
(*p)++;
}
else
return SETCHARSET_FAIL;
}
else if(c == ']') {
return SETCHARSET_OK;
}
else
return SETCHARSET_FAIL;
break;
case CURLFNM_SCHS_MAYRANGE2:
if(c == '\\') {
c = *(++(*p));
if(!ISPRINT(c))
return SETCHARSET_FAIL;
}
if(c == ']') {
return SETCHARSET_OK;
}
else if(c == '\\') {
c = *(++(*p));
if(ISPRINT(c)) {
charset[c] = 1;
state = CURLFNM_SCHS_DEFAULT;
(*p)++;
}
else
return SETCHARSET_FAIL;
}
if(c >= rangestart) {
if((ISLOWER(c) && ISLOWER(rangestart)) ||
(ISDIGIT(c) && ISDIGIT(rangestart)) ||
(ISUPPER(c) && ISUPPER(rangestart))) {
charset[lastchar] = 0;
rangestart++;
while(rangestart++ <= c)
charset[rangestart-1] = 1;
(*p)++;
state = CURLFNM_SCHS_DEFAULT;
}
else
return SETCHARSET_FAIL;
}
break;
case CURLFNM_SCHS_RIGHTBR:
if(c == '[') {
state = CURLFNM_SCHS_RIGHTBRLEFTBR;
charset[c] = 1;
(*p)++;
}
else if(c == ']') {
return SETCHARSET_OK;
}
else if(c == '\0') {
return SETCHARSET_FAIL;
}
else if(ISPRINT(c)) {
charset[c] = 1;
(*p)++;
state = CURLFNM_SCHS_DEFAULT;
}
else
/* used 'goto fail' instead of 'return SETCHARSET_FAIL' to avoid a
* nonsense warning 'statement not reached' at end of the fnc when
* compiling on Solaris */
goto fail;
break;
case CURLFNM_SCHS_RIGHTBRLEFTBR:
if(c == ']') {
return SETCHARSET_OK;
}
else {
state = CURLFNM_SCHS_DEFAULT;
charset[c] = 1;
(*p)++;
}
break;
}
}
fail:
return SETCHARSET_FAIL;
}
static int loop(const unsigned char *pattern, const unsigned char *string)
{
loop_state state = CURLFNM_LOOP_DEFAULT;
unsigned char *p = (unsigned char *)pattern;
unsigned char *s = (unsigned char *)string;
unsigned char charset[CURLFNM_CHSET_SIZE] = { 0 };
int rc = 0;
for (;;) {
switch(state) {
case CURLFNM_LOOP_DEFAULT:
if(*p == '*') {
while(*(p+1) == '*') /* eliminate multiple stars */
p++;
if(*s == '\0' && *(p+1) == '\0')
return CURL_FNMATCH_MATCH;
rc = loop(p + 1, s); /* *.txt matches .txt <=> .txt matches .txt */
if(rc == CURL_FNMATCH_MATCH)
return CURL_FNMATCH_MATCH;
if(*s) /* let the star eat up one character */
s++;
else
return CURL_FNMATCH_NOMATCH;
}
else if(*p == '?') {
if(ISPRINT(*s)) {
s++;
p++;
}
else if(*s == '\0')
return CURL_FNMATCH_NOMATCH;
else
return CURL_FNMATCH_FAIL; /* cannot deal with other character */
}
else if(*p == '\0') {
if(*s == '\0')
return CURL_FNMATCH_MATCH;
else
return CURL_FNMATCH_NOMATCH;
}
else if(*p == '\\') {
state = CURLFNM_LOOP_BACKSLASH;
p++;
}
else if(*p == '[') {
unsigned char *pp = p+1; /* cannot handle with pointer to register */
if(setcharset(&pp, charset)) {
int found = FALSE;
if(charset[(unsigned int)*s])
found = TRUE;
else if(charset[CURLFNM_ALNUM])
found = ISALNUM(*s);
else if(charset[CURLFNM_ALPHA])
found = ISALPHA(*s);
else if(charset[CURLFNM_DIGIT])
found = ISDIGIT(*s);
else if(charset[CURLFNM_XDIGIT])
found = ISXDIGIT(*s);
else if(charset[CURLFNM_PRINT])
found = ISPRINT(*s);
else if(charset[CURLFNM_SPACE])
found = ISSPACE(*s);
else if(charset[CURLFNM_UPPER])
found = ISUPPER(*s);
else if(charset[CURLFNM_LOWER])
found = ISLOWER(*s);
else if(charset[CURLFNM_BLANK])
found = ISBLANK(*s);
else if(charset[CURLFNM_GRAPH])
found = ISGRAPH(*s);
if(charset[CURLFNM_NEGATE])
found = !found;
if(found) {
p = pp+1;
s++;
memset(charset, 0, CURLFNM_CHSET_SIZE);
}
else
return CURL_FNMATCH_NOMATCH;
}
else
return CURL_FNMATCH_FAIL;
}
else {
if(*p++ != *s++)
return CURL_FNMATCH_NOMATCH;
}
break;
case CURLFNM_LOOP_BACKSLASH:
if(ISPRINT(*p)) {
if(*p++ == *s++)
state = CURLFNM_LOOP_DEFAULT;
else
return CURL_FNMATCH_NOMATCH;
}
else
return CURL_FNMATCH_FAIL;
break;
}
}
}
int Curl_fnmatch(void *ptr, const char *pattern, const char *string)
{
(void)ptr; /* the argument is specified by the curl_fnmatch_callback
prototype, but not used by Curl_fnmatch() */
if(!pattern || !string) {
return CURL_FNMATCH_FAIL;
}
return loop((unsigned char *)pattern, (unsigned char *)string);
}

44
lib/curl_fnmatch.h Normal file
View File

@@ -0,0 +1,44 @@
#ifndef HEADER_CURL_FNMATCH_H
#define HEADER_CURL_FNMATCH_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#define CURL_FNMATCH_MATCH 0
#define CURL_FNMATCH_NOMATCH 1
#define CURL_FNMATCH_FAIL 2
/* default pattern matching function
* =================================
* Implemented with recursive backtracking, if you want to use Curl_fnmatch,
* please note that there is not implemented UTF/UNICODE support.
*
* Implemented features:
* '?' notation, does not match UTF characters
* '*' can also work with UTF string
* [a-zA-Z0-9] enumeration support
*
* keywords: alnum, digit, xdigit, alpha, print, blank, lower, graph, space
* and upper (use as "[[:alnum:]]")
*/
int Curl_fnmatch(void *ptr, const char *pattern, const char *string);
#endif /* HEADER_CURL_FNMATCH_H */

67
lib/curl_hmac.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef HEADER_CURL_HMAC_H
#define HEADER_CURL_HMAC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
typedef void (* HMAC_hinit_func)(void * context);
typedef void (* HMAC_hupdate_func)(void * context,
const unsigned char * data,
unsigned int len);
typedef void (* HMAC_hfinal_func)(unsigned char * result, void * context);
/* Per-hash function HMAC parameters. */
typedef struct {
HMAC_hinit_func hmac_hinit; /* Initialize context procedure. */
HMAC_hupdate_func hmac_hupdate; /* Update context with data. */
HMAC_hfinal_func hmac_hfinal; /* Get final result procedure. */
unsigned int hmac_ctxtsize; /* Context structure size. */
unsigned int hmac_maxkeylen; /* Maximum key length (bytes). */
unsigned int hmac_resultlen; /* Result length (bytes). */
} HMAC_params;
/* HMAC computation context. */
typedef struct {
const HMAC_params * hmac_hash; /* Hash function definition. */
void * hmac_hashctxt1; /* Hash function context 1. */
void * hmac_hashctxt2; /* Hash function context 2. */
} HMAC_context;
/* Prototypes. */
HMAC_context * Curl_HMAC_init(const HMAC_params * hashparams,
const unsigned char * key,
unsigned int keylen);
int Curl_HMAC_update(HMAC_context * context,
const unsigned char * data,
unsigned int len);
int Curl_HMAC_final(HMAC_context * context, unsigned char * result);
#endif
#endif /* HEADER_CURL_HMAC_H */

View File

@@ -8,7 +8,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,7 +25,8 @@
#ifndef CURL_DISABLE_LDAP
extern const struct Curl_handler Curl_handler_ldap;
#ifdef HAVE_LDAP_SSL
#if (defined(USE_OPENLDAP) && defined(USE_SSL)) || \
(!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL))
extern const struct Curl_handler Curl_handler_ldaps;
#endif

View File

@@ -22,7 +22,13 @@
*
***************************************************************************/
#ifndef CURL_DISABLE_CRYPTO_AUTH
#include "curl_hmac.h"
extern const HMAC_params Curl_HMAC_MD5[1];
void Curl_md5it(unsigned char *output,
const unsigned char *input);
#endif
#endif /* HEADER_CURL_MD5_H */

284
lib/curl_rtmp.c Normal file
View File

@@ -0,0 +1,284 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#ifdef USE_LIBRTMP
#include "urldata.h"
#include "nonblock.h" /* for curlx_nonblock */
#include "progress.h" /* for Curl_pgrsSetUploadSize */
#include "transfer.h"
#include <curl/curl.h>
#include <librtmp/rtmp.h>
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
#ifdef _WIN32
#define setsockopt(a,b,c,d,e) (setsockopt)(a,b,c,(const char *)d,(int)e)
#define SET_RCVTIMEO(tv,s) int tv = s*1000
#else
#define SET_RCVTIMEO(tv,s) struct timeval tv = {s,0}
#endif
#define DEF_BUFTIME (2*60*60*1000) /* 2 hours */
static CURLcode rtmp_setup(struct connectdata *conn);
static CURLcode rtmp_do(struct connectdata *conn, bool *done);
static CURLcode rtmp_done(struct connectdata *conn, CURLcode, bool premature);
static CURLcode rtmp_connect(struct connectdata *conn, bool *done);
static CURLcode rtmp_disconnect(struct connectdata *conn);
static Curl_recv rtmp_recv;
static Curl_send rtmp_send;
/*
* RTMP protocol handler.h, based on http://rtmpdump.mplayerhq.hu
*/
const struct Curl_handler Curl_handler_rtmp = {
"RTMP", /* scheme */
rtmp_setup, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
PORT_RTMP, /* defport */
PROT_RTMP /* protocol */
};
const struct Curl_handler Curl_handler_rtmpt = {
"RTMPT", /* scheme */
rtmp_setup, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
PORT_RTMPT, /* defport */
PROT_RTMPT /* protocol */
};
const struct Curl_handler Curl_handler_rtmpe = {
"RTMPE", /* scheme */
rtmp_setup, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
PORT_RTMP, /* defport */
PROT_RTMPE /* protocol */
};
const struct Curl_handler Curl_handler_rtmpte = {
"RTMPTE", /* scheme */
rtmp_setup, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
PORT_RTMPT, /* defport */
PROT_RTMPTE /* protocol */
};
const struct Curl_handler Curl_handler_rtmps = {
"RTMPS", /* scheme */
rtmp_setup, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
PORT_RTMPS, /* defport */
PROT_RTMPS /* protocol */
};
const struct Curl_handler Curl_handler_rtmpts = {
"RTMPTS", /* scheme */
rtmp_setup, /* setup_connection */
rtmp_do, /* do_it */
rtmp_done, /* done */
ZERO_NULL, /* do_more */
rtmp_connect, /* connect_it */
ZERO_NULL, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
rtmp_disconnect, /* disconnect */
PORT_RTMPS, /* defport */
PROT_RTMPTS /* protocol */
};
static CURLcode rtmp_setup(struct connectdata *conn)
{
RTMP *r = RTMP_Alloc();
if (!r)
return CURLE_OUT_OF_MEMORY;
RTMP_Init(r);
RTMP_SetBufferMS(r, DEF_BUFTIME);
if (!RTMP_SetupURL(r, conn->data->change.url)) {
RTMP_Free(r);
return CURLE_URL_MALFORMAT;
}
conn->proto.generic = r;
return CURLE_OK;
}
static CURLcode rtmp_connect(struct connectdata *conn, bool *done)
{
RTMP *r = conn->proto.generic;
SET_RCVTIMEO(tv,10);
r->m_sb.sb_socket = conn->sock[FIRSTSOCKET];
/* We have to know if it's a write before we send the
* connect request packet
*/
if (conn->data->set.upload)
r->Link.protocol |= RTMP_FEATURE_WRITE;
/* For plain streams, use the buffer toggle trick to keep data flowing */
if (!(r->Link.lFlags & RTMP_LF_LIVE) && !(r->Link.protocol & RTMP_FEATURE_HTTP))
r->Link.lFlags |= RTMP_LF_BUFX;
curlx_nonblock(r->m_sb.sb_socket, FALSE);
setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
if (!RTMP_Connect1(r, NULL))
return CURLE_FAILED_INIT;
/* Clients must send a periodic BytesReceived report to the server */
r->m_bSendCounter = true;
*done = TRUE;
conn->recv[FIRSTSOCKET] = rtmp_recv;
conn->send[FIRSTSOCKET] = rtmp_send;
return CURLE_OK;
}
static CURLcode rtmp_do(struct connectdata *conn, bool *done)
{
RTMP *r = conn->proto.generic;
if (!RTMP_ConnectStream(r, 0))
return CURLE_FAILED_INIT;
if (conn->data->set.upload) {
Curl_pgrsSetUploadSize(conn->data, conn->data->set.infilesize);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
} else
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
*done = TRUE;
return CURLE_OK;
}
static CURLcode rtmp_done(struct connectdata *conn, CURLcode status,
bool premature)
{
(void)conn; /* unused */
(void)status; /* unused */
(void)premature; /* unused */
return CURLE_OK;
}
static CURLcode rtmp_disconnect(struct connectdata *conn)
{
RTMP *r = conn->proto.generic;
if (r) {
conn->proto.generic = NULL;
RTMP_Close(r);
RTMP_Free(r);
}
return CURLE_OK;
}
static ssize_t rtmp_recv(struct connectdata *conn, int sockindex, char *buf,
size_t len, CURLcode *err)
{
RTMP *r = conn->proto.generic;
ssize_t nread;
(void)sockindex; /* unused */
nread = RTMP_Read(r, buf, len);
if (nread < 0) {
if (r->m_read.status == RTMP_READ_COMPLETE ||
r->m_read.status == RTMP_READ_EOF) {
conn->data->req.size = conn->data->req.bytecount;
nread = 0;
} else
*err = CURLE_RECV_ERROR;
}
return nread;
}
static ssize_t rtmp_send(struct connectdata *conn, int sockindex,
const void *buf, size_t len, CURLcode *err)
{
RTMP *r = conn->proto.generic;
ssize_t num;
(void)sockindex; /* unused */
num = RTMP_Write(r, (char *)buf, len);
if (num < 0) {
*err = CURLE_SEND_ERROR;
}
return num;
}
#endif /* USE_LIBRTMP */

33
lib/curl_rtmp.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef HEADER_CURL_RTMP_H
#define HEADER_CURL_RTMP_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Howard Chu, <hyc@highlandsun.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#ifdef USE_LIBRTMP
extern const struct Curl_handler Curl_handler_rtmp;
extern const struct Curl_handler Curl_handler_rtmpt;
extern const struct Curl_handler Curl_handler_rtmpe;
extern const struct Curl_handler Curl_handler_rtmpte;
extern const struct Curl_handler Curl_handler_rtmps;
extern const struct Curl_handler Curl_handler_rtmpts;
#endif
#endif /* HEADER_CURL_RTMP_H */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -217,13 +217,12 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
free(eword);
if(result)
if(result) {
failf(data, "Failed sending DICT request");
else
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
return result;
}
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
}
else if(Curl_raw_nequal(path, DICT_DEFINE, sizeof(DICT_DEFINE)-1) ||
Curl_raw_nequal(path, DICT_DEFINE2, sizeof(DICT_DEFINE2)-1) ||
@@ -265,15 +264,12 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
free(eword);
if(result)
if(result) {
failf(data, "Failed sending DICT request");
else
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
if(result)
return result;
}
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL); /* no upload */
}
else {
@@ -290,13 +286,12 @@ static CURLcode dict_do(struct connectdata *conn, bool *done)
"CLIENT " LIBCURL_NAME " " LIBCURL_VERSION "\r\n"
"%s\r\n"
"QUIT\r\n", ppath);
if(result)
if(result) {
failf(data, "Failed sending DICT request");
else
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount,
-1, NULL);
if(result)
return result;
}
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, bytecount, -1, NULL);
}
}

View File

@@ -287,6 +287,13 @@ CURLcode curl_global_init(long flags)
}
#endif
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_INIT)
if(libssh2_init(0)) {
DEBUGF(fprintf(stderr, "Error: libssh2_init failed\n"));
return CURLE_FAILED_INIT;
}
#endif
init_flags = flags;
/* Preset pseudo-random number sequence. */
@@ -355,6 +362,10 @@ void curl_global_cleanup(void)
amiga_cleanup();
#endif
#if defined(USE_LIBSSH2) && defined(HAVE_LIBSSH2_EXIT)
(void)libssh2_exit();
#endif
init_flags = 0;
}
@@ -1097,7 +1108,6 @@ CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
{
curl_socket_t sfd;
CURLcode ret;
int ret1;
ssize_t n1;
struct connectdata *c;
struct SessionHandle *data = (struct SessionHandle *)curl;
@@ -1107,13 +1117,10 @@ CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
return ret;
*n = 0;
ret1 = Curl_read(c, sfd, buffer, buflen, &n1);
ret = Curl_read(c, sfd, buffer, buflen, &n1);
if(ret1 == -1)
return CURLE_AGAIN;
if(ret1 != CURLE_OK)
return (CURLcode)ret1;
if(ret != CURLE_OK)
return ret;
*n = (size_t)n1;

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -146,7 +146,7 @@ static CURLcode file_range(struct connectdata *conn)
if(data->state.use_range && data->state.range) {
from=curlx_strtoofft(data->state.range, &ptr, 0);
while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))
while(*ptr && (isspace((int)*ptr) || (*ptr=='-')))
ptr++;
to=curlx_strtoofft(ptr, &ptr2, 0);
if(ptr == ptr2) {
@@ -161,11 +161,10 @@ static CURLcode file_range(struct connectdata *conn)
}
else if(from < 0) {
/* -Y */
totalsize = -from;
data->req.maxdownload = -from;
data->state.resume_from = from;
DEBUGF(infof(data, "RANGE the last %" FORMAT_OFF_T " bytes\n",
totalsize));
-from));
}
else {
/* X-Y */

75
lib/fileinfo.c Normal file
View File

@@ -0,0 +1,75 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#include <stdlib.h>
#include "strdup.h"
#include "fileinfo.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
struct curl_fileinfo *Curl_fileinfo_alloc(void)
{
struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo));
if(!tmp)
return NULL;
memset(tmp, 0, sizeof(struct curl_fileinfo));
return tmp;
}
void Curl_fileinfo_dtor(void *user, void *element)
{
struct curl_fileinfo *finfo = element;
(void) user;
if(!finfo)
return;
if(finfo->b_data){
free(finfo->b_data);
}
free(finfo);
}
struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src)
{
struct curl_fileinfo *ptr = malloc(sizeof(struct curl_fileinfo));
if(!ptr)
return NULL;
*ptr = *src;
ptr->b_data = malloc(src->b_size);
if(!ptr->b_data) {
free(ptr);
return NULL;
}
else {
memcpy(ptr->b_data, src->b_data, src->b_size);
return ptr;
}
}

33
lib/fileinfo.h Normal file
View File

@@ -0,0 +1,33 @@
#ifndef HEADER_CURL_FILEINFO_H
#define HEADER_CURL_FILEINFO_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <curl/curl.h>
struct curl_fileinfo *Curl_fileinfo_alloc(void);
void Curl_fileinfo_dtor(void *, void *);
struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src);
#endif /* HEADER_CURL_FILEINFO_H */

297
lib/ftp.c
View File

@@ -71,6 +71,8 @@
#include "http.h" /* for HTTP proxy tunnel stuff */
#include "socks.h"
#include "ftp.h"
#include "fileinfo.h"
#include "ftplistparser.h"
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
#include "krb4.h"
@@ -144,6 +146,14 @@ static CURLcode ftp_doing(struct connectdata *conn,
bool *dophase_done);
static CURLcode ftp_setup_connection(struct connectdata * conn);
static CURLcode init_wc_data(struct connectdata *conn);
static CURLcode wc_statemach(struct connectdata *conn);
static void wc_data_dtor(void *ptr);
static CURLcode ftp_state_post_retr_size(struct connectdata *conn,
curl_off_t filesize);
/* easy-to-use macro: */
#define FTPSENDF(x,y,z) if((result = Curl_ftpsendf(x,y,z)) != CURLE_OK) \
return result
@@ -820,7 +830,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
/* resolv ip/host to ip */
rc = Curl_resolv(conn, host, 0, &h);
if(rc == CURLRESOLV_PENDING)
rc = Curl_wait_for_resolv(conn, &h);
(void)Curl_wait_for_resolv(conn, &h);
if(h) {
res = h->addr;
/* when we return from this function, we can forget about this entry
@@ -1378,7 +1388,7 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
infof(data, "File already completely uploaded\n");
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
/* Set ->transfer so that we won't get any error in
* ftp_done() because we didn't transfer anything! */
@@ -1469,8 +1479,14 @@ static CURLcode ftp_state_quote(struct connectdata *conn,
if(ftp->transfer != FTPTRANSFER_BODY)
state(conn, FTP_STOP);
else {
PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
state(conn, FTP_RETR_SIZE);
if(ftpc->known_filesize != -1) {
Curl_pgrsSetDownloadSize(data, ftpc->known_filesize);
result = ftp_state_post_retr_size(conn, ftpc->known_filesize);
}
else {
PPSENDF(&ftpc->pp, "SIZE %s", ftpc->file);
state(conn, FTP_RETR_SIZE);
}
}
break;
case FTP_STOR_PREQUOTE:
@@ -1630,8 +1646,9 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
*/
rc = Curl_resolv(conn, conn->proxy.name, (int)conn->port, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING */
rc = Curl_wait_for_resolv(conn, &addr);
/* BLOCKING, ignores the return code but 'addr' will be NULL in
case of failure */
(void)Curl_wait_for_resolv(conn, &addr);
connectport =
(unsigned short)conn->port; /* we connect to the proxy's port */
@@ -1647,7 +1664,7 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
rc = Curl_resolv(conn, newhost, newport, &addr);
if(rc == CURLRESOLV_PENDING)
/* BLOCKING */
rc = Curl_wait_for_resolv(conn, &addr);
(void)Curl_wait_for_resolv(conn, &addr);
connectport = newport; /* we connect to the remote port */
@@ -1973,7 +1990,7 @@ static CURLcode ftp_state_post_retr_size(struct connectdata *conn,
if(ftp->downloadsize == 0) {
/* no data to transfer */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
infof(data, "File already completely downloaded\n");
/* Set ->transfer so that we won't get any error in ftp_done()
@@ -2115,8 +2132,8 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
/* set the SO_SNDBUF for the secondary socket for those who need it */
Curl_sndbufset(conn->sock[SECONDARYSOCKET]);
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
SECONDARYSOCKET, ftp->bytecountp);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
SECONDARYSOCKET, ftp->bytecountp);
state(conn, FTP_STOP);
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect a server response */
@@ -2229,11 +2246,8 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
infof(data, "Getting file with size: %" FORMAT_OFF_T "\n", size);
/* FTP download: */
result=Curl_setup_transfer(conn, SECONDARYSOCKET, size, FALSE,
ftp->bytecountp,
-1, NULL); /* no upload here */
if(result)
return result;
Curl_setup_transfer(conn, SECONDARYSOCKET, size, FALSE,
ftp->bytecountp, -1, NULL); /* no upload here */
conn->proto.ftpc.pp.pending_resp = TRUE; /* expect server response */
state(conn, FTP_STOP);
@@ -2857,6 +2871,8 @@ static CURLcode ftp_init(struct connectdata *conn)
if(TRUE == isBadFtpString(ftp->passwd))
return CURLE_URL_MALFORMAT;
conn->proto.ftpc.known_filesize = -1; /* unknown size for now */
return CURLE_OK;
}
@@ -3020,6 +3036,13 @@ static CURLcode ftp_done(struct connectdata *conn, CURLcode status,
if(ftpc->prevpath)
free(ftpc->prevpath);
if(data->set.wildcardmatch) {
if(data->set.chunk_end && ftpc->file) {
data->set.chunk_end(data->wildcard.customptr);
}
ftpc->known_filesize = -1;
}
/* get the "raw" path */
path = curl_easy_unescape(data, path_to_use, 0, NULL);
if(!path) {
@@ -3285,7 +3308,6 @@ ftp_pasv_verbose(struct connectdata *conn,
static CURLcode ftp_range(struct connectdata *conn)
{
curl_off_t from, to;
curl_off_t totalsize=-1;
char *ptr;
char *ptr2;
struct SessionHandle *data = conn->data;
@@ -3293,7 +3315,7 @@ static CURLcode ftp_range(struct connectdata *conn)
if(data->state.use_range && data->state.range) {
from=curlx_strtoofft(data->state.range, &ptr, 0);
while(ptr && *ptr && (ISSPACE(*ptr) || (*ptr=='-')))
while(*ptr && (ISSPACE(*ptr) || (*ptr=='-')))
ptr++;
to=curlx_strtoofft(ptr, &ptr2, 0);
if(ptr == ptr2) {
@@ -3308,16 +3330,14 @@ static CURLcode ftp_range(struct connectdata *conn)
}
else if(from < 0) {
/* -Y */
totalsize = -from;
data->req.maxdownload = -from;
data->state.resume_from = from;
DEBUGF(infof(conn->data, "FTP RANGE the last %" FORMAT_OFF_T " bytes\n",
totalsize));
-from));
}
else {
/* X-Y */
totalsize = to-from;
data->req.maxdownload = totalsize+1; /* include last byte */
data->req.maxdownload = (to-from)+1; /* include last byte */
data->state.resume_from = from;
DEBUGF(infof(conn->data, "FTP RANGE from %" FORMAT_OFF_T
" getting %" FORMAT_OFF_T " bytes\n",
@@ -3393,7 +3413,7 @@ static CURLcode ftp_nextconnect(struct connectdata *conn)
if((result == CURLE_OK) && (ftp->transfer != FTPTRANSFER_BODY))
/* no data to transfer. FIX: it feels like a kludge to have this here
too! */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
/* end of transfer */
DEBUGF(infof(data, "DO-MORE phase ends with %d\n", (int)result));
@@ -3450,6 +3470,219 @@ CURLcode ftp_perform(struct connectdata *conn,
return result;
}
static void wc_data_dtor(void *ptr)
{
struct ftp_wc_tmpdata *tmp = ptr;
if(tmp)
Curl_ftp_parselist_data_free(&tmp->parser);
Curl_safefree(tmp);
}
static CURLcode init_wc_data(struct connectdata *conn)
{
char *last_slash;
char *path = conn->data->state.path;
struct WildcardData *wildcard = &(conn->data->wildcard);
CURLcode ret = CURLE_OK;
struct ftp_wc_tmpdata *ftp_tmp;
last_slash = strrchr(conn->data->state.path, '/');
if(last_slash) {
last_slash++;
if(last_slash[0] == '\0') {
wildcard->state = CURLWC_CLEAN;
ret = ftp_parse_url_path(conn);
return ret;
}
else {
wildcard->pattern = strdup(last_slash);
if (!wildcard->pattern)
return CURLE_OUT_OF_MEMORY;
last_slash[0] = '\0'; /* cut file from path */
}
}
else { /* there is only 'wildcard pattern' or nothing */
if(path[0]) {
wildcard->pattern = strdup(path);
if (!wildcard->pattern)
return CURLE_OUT_OF_MEMORY;
path[0] = '\0';
}
else { /* only list */
conn->data->set.wildcardmatch = FALSE;
ret = ftp_parse_url_path(conn);
return ret;
}
}
/* program continues only if URL is not ending with slash, allocate needed
resources for wildcard transfer */
/* allocate ftp protocol specific temporary wildcard data */
ftp_tmp = malloc(sizeof(struct ftp_wc_tmpdata));
if(!ftp_tmp) {
return CURLE_OUT_OF_MEMORY;
}
/* INITIALIZE parselist structure */
ftp_tmp->parser = Curl_ftp_parselist_data_alloc();
if(!ftp_tmp->parser)
return CURLE_OUT_OF_MEMORY;
wildcard->tmp = ftp_tmp; /* put it to the WildcardData tmp pointer */
wildcard->tmp_dtor = wc_data_dtor;
/* wildcard does not support NOCWD option (assert it?) */
if(conn->data->set.ftp_filemethod == FTPFILE_NOCWD)
conn->data->set.ftp_filemethod = FTPFILE_MULTICWD;
/* try to parse ftp url */
ret = ftp_parse_url_path(conn);
if(ret) {
return ret;
}
/* backup old write_function */
ftp_tmp->backup.write_function = conn->data->set.fwrite_func;
/* parsing write function (callback included directly from ftplistparser.c) */
conn->data->set.fwrite_func = Curl_ftp_parselist;
/* backup old file descriptor */
ftp_tmp->backup.file_descriptor = conn->data->set.out;
/* let the writefunc callback know what curl pointer is working with */
conn->data->set.out = conn;
wildcard->path = strdup(conn->data->state.path);
if(!wildcard->path) {
return CURLE_OUT_OF_MEMORY;
}
infof(conn->data, "Wildcard - Parsing started\n");
return CURLE_OK;
}
static CURLcode wc_statemach(struct connectdata *conn)
{
struct ftp_conn *ftpc = &conn->proto.ftpc;
struct WildcardData *wildcard = &(conn->data->wildcard);
struct ftp_wc_tmpdata *ftp_tmp = wildcard->tmp;
char *tmp_path;
CURLcode ret = CURLE_OK;
long userresponse = 0;
switch (wildcard->state) {
case CURLWC_INIT:
ret = init_wc_data(conn);
if(wildcard->state == CURLWC_CLEAN)
/* only listing! */
break;
else
wildcard->state = ret ? CURLWC_ERROR : CURLWC_MATCHING;
break;
case CURLWC_MATCHING:
/* In this state is LIST response successfully parsed, so lets restore
previous WRITEFUNCTION callback and WRITEDATA pointer */
ftp_tmp = wildcard->tmp;
conn->data->set.fwrite_func = ftp_tmp->backup.write_function;
conn->data->set.out = ftp_tmp->backup.file_descriptor;
wildcard->state = CURLWC_DOWNLOADING;
if(Curl_ftp_parselist_geterror(ftp_tmp->parser)) {
/* error found in LIST parsing */
wildcard->state = CURLWC_CLEAN;
return wc_statemach(conn);
}
else if(wildcard->filelist->size == 0) {
/* no corresponding file */
wildcard->state = CURLWC_CLEAN;
return CURLE_REMOTE_FILE_NOT_FOUND;
}
ret = wc_statemach(conn);
break;
case CURLWC_DOWNLOADING: {
/* filelist has at least one file, lets get first one */
struct curl_fileinfo *finfo = wildcard->filelist->head->ptr;
tmp_path = malloc(strlen(conn->data->state.path) +
strlen(finfo->filename) + 1);
if(!tmp_path) {
return CURLE_OUT_OF_MEMORY;
}
tmp_path[0] = 0;
/* make full path to matched file */
strcat(tmp_path, wildcard->path);
strcat(tmp_path, finfo->filename);
/* switch default "state.pathbuffer" and tmp_path, good to see
ftp_parse_url_path function to understand this trick */
if(conn->data->state.pathbuffer)
free(conn->data->state.pathbuffer);
conn->data->state.pathbuffer = tmp_path;
conn->data->state.path = tmp_path;
infof(conn->data, "Wildcard - START of \"%s\"\n", finfo->filename);
if(conn->data->set.chunk_bgn) {
userresponse = conn->data->set.chunk_bgn(
finfo, wildcard->customptr, (int)wildcard->filelist->size);
switch(userresponse) {
case CURL_CHUNK_BGN_FUNC_SKIP:
infof(conn->data, "Wildcard - \"%s\" skipped by user\n",
finfo->filename);
wildcard->state = CURLWC_SKIP;
return wc_statemach(conn);
case CURL_CHUNK_BGN_FUNC_FAIL:
return CURLE_CHUNK_FAILED;
}
}
if(finfo->filetype != CURLFILETYPE_FILE) {
wildcard->state = CURLWC_SKIP;
return wc_statemach(conn);
}
if(finfo->flags & CURLFINFOFLAG_KNOWN_SIZE)
ftpc->known_filesize = finfo->size;
ret = ftp_parse_url_path(conn);
if(ret) {
return ret;
}
/* we don't need the Curl_fileinfo of first file anymore */
Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
if(wildcard->filelist->size == 0) { /* remains only one file to down. */
wildcard->state = CURLWC_CLEAN;
/* after that will be ftp_do called once again and no transfer
will be done because of CURLWC_CLEAN state */
return CURLE_OK;
}
} break;
case CURLWC_SKIP: {
if(conn->data->set.chunk_end)
conn->data->set.chunk_end(conn->data->wildcard.customptr);
Curl_llist_remove(wildcard->filelist, wildcard->filelist->head, NULL);
wildcard->state = (wildcard->filelist->size == 0) ?
CURLWC_CLEAN : CURLWC_DOWNLOADING;
ret = wc_statemach(conn);
} break;
case CURLWC_CLEAN:
ret = CURLE_OK;
if(ftp_tmp) {
ret = Curl_ftp_parselist_geterror(ftp_tmp->parser);
}
wildcard->state = ret ? CURLWC_ERROR : CURLWC_DONE;
break;
case CURLWC_DONE:
case CURLWC_ERROR:
break;
}
return ret;
}
/***********************************************************************
*
* ftp_do()
@@ -3476,9 +3709,21 @@ static CURLcode ftp_do(struct connectdata *conn, bool *done)
if(retcode)
return retcode;
retcode = ftp_parse_url_path(conn);
if(retcode)
return retcode;
if(conn->data->set.wildcardmatch) {
retcode = wc_statemach(conn);
if(conn->data->wildcard.state == CURLWC_SKIP ||
conn->data->wildcard.state == CURLWC_DONE) {
/* do not call ftp_regular_transfer */
return CURLE_OK;
}
if(retcode) /* error, loop or skipping the file */
return retcode;
}
else { /* no wildcard FSM needed */
retcode = ftp_parse_url_path(conn);
if(retcode)
return retcode;
}
retcode = ftp_regular_transfer(conn, done);
@@ -3820,7 +4065,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
if(ftp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
else if(!connected)
/* since we didn't connect now, we want do_more to get called */
conn->bits.do_more = TRUE;

View File

@@ -79,6 +79,17 @@ typedef enum {
FTP_LAST /* never used */
} ftpstate;
struct ftp_parselist_data; /* defined later in ftplistparser.c */
struct ftp_wc_tmpdata {
struct ftp_parselist_data *parser;
struct {
curl_write_callback write_function;
FILE *file_descriptor;
} backup;
};
typedef enum {
FTPFILE_MULTICWD = 1, /* as defined by RFC1738 */
FTPFILE_NOCWD = 2, /* use SIZE / RETR / STOR on the full path */
@@ -135,6 +146,8 @@ struct ftp_conn {
int count3; /* general purpose counter for the state machine */
ftpstate state; /* always use ftp.c:state() to change state! */
char * server_os; /* The target server operating system. */
curl_off_t known_filesize; /* file size is different from -1, if wildcard
LIST parsing was done and wc_statemach set it */
};
#endif /* HEADER_CURL_FTP_H */

996
lib/ftplistparser.c Normal file
View File

@@ -0,0 +1,996 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/**
* Now implemented:
*
* 1) UNIX version 1
* drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
* 2) UNIX version 2
* drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
* 3) UNIX version 3
* drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
* 4) UNIX symlink
* lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
* 5) DOS style
* 01-29-97 11:32PM <DIR> prog
*/
#include "setup.h"
#include <time.h>
#include "ftplistparser.h"
#include "curl_fnmatch.h"
#include "urldata.h"
#include "ftp.h"
#include "fileinfo.h"
#include "llist.h"
#include "strtoofft.h"
#include "rawstr.h"
#include "ftp.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* allocs buffer which will contain one line of LIST command response */
#define FTP_BUFFER_ALLOCSIZE 160
typedef enum {
PL_UNIX_FILETYPE = 0,
PL_UNIX_PERMISSION,
PL_UNIX_HLINKS,
PL_UNIX_USER,
PL_UNIX_GROUP,
PL_UNIX_SIZE,
PL_UNIX_TIME,
PL_UNIX_FILENAME,
PL_UNIX_SYMLINK
} pl_unix_mainstate;
typedef union {
enum {
PL_UNIX_HLINKS_PRESPACE = 0,
PL_UNIX_HLINKS_NUMBER
} hlinks;
enum {
PL_UNIX_USER_PRESPACE = 0,
PL_UNIX_USER_PARSING
} user;
enum {
PL_UNIX_GROUP_PRESPACE = 0,
PL_UNIX_GROUP_NAME
} group;
enum {
PL_UNIX_SIZE_PRESPACE = 0,
PL_UNIX_SIZE_NUMBER
} size;
enum {
PL_UNIX_TIME_PREPART1 = 0,
PL_UNIX_TIME_PART1,
PL_UNIX_TIME_PREPART2,
PL_UNIX_TIME_PART2,
PL_UNIX_TIME_PREPART3,
PL_UNIX_TIME_PART3
} time;
enum {
PL_UNIX_FILENAME_PRESPACE = 0,
PL_UNIX_FILENAME_NAME,
PL_UNIX_FILENAME_WINDOWSEOL
} filename;
enum {
PL_UNIX_SYMLINK_PRESPACE = 0,
PL_UNIX_SYMLINK_NAME,
PL_UNIX_SYMLINK_PRETARGET1,
PL_UNIX_SYMLINK_PRETARGET2,
PL_UNIX_SYMLINK_PRETARGET3,
PL_UNIX_SYMLINK_PRETARGET4,
PL_UNIX_SYMLINK_TARGET,
PL_UNIX_SYMLINK_WINDOWSEOL
} symlink;
} pl_unix_substate;
typedef enum {
PL_WINNT_DATE = 0,
PL_WINNT_TIME,
PL_WINNT_DIRORSIZE,
PL_WINNT_FILENAME
} pl_winNT_mainstate;
typedef union {
enum {
PL_WINNT_TIME_PRESPACE = 0,
PL_WINNT_TIME_TIME
} time;
enum {
PL_WINNT_DIRORSIZE_PRESPACE = 0,
PL_WINNT_DIRORSIZE_CONTENT
} dirorsize;
enum {
PL_WINNT_FILENAME_PRESPACE = 0,
PL_WINNT_FILENAME_CONTENT,
PL_WINNT_FILENAME_WINEOL
} filename;
} pl_winNT_substate;
/* This struct is used in wildcard downloading - for parsing LIST response */
struct ftp_parselist_data {
enum {
OS_TYPE_UNKNOWN = 0,
OS_TYPE_UNIX,
OS_TYPE_WIN_NT
} os_type;
union {
struct {
pl_unix_mainstate main;
pl_unix_substate sub;
} UNIX;
struct {
pl_winNT_mainstate main;
pl_winNT_substate sub;
} NT;
} state;
CURLcode error;
struct curl_fileinfo *file_data;
unsigned int item_length;
size_t item_offset;
struct {
size_t filename;
size_t user;
size_t group;
size_t time;
size_t perm;
size_t symlink_target;
} offsets;
};
struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void)
{
return calloc(1, sizeof(struct ftp_parselist_data));
}
void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data)
{
if(*pl_data)
free(*pl_data);
*pl_data = NULL;
}
CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data)
{
return pl_data->error;
}
#define FTP_LP_MALFORMATED_PERM 0x01000000
static int ftp_pl_get_permission(const char *str)
{
int permissions = 0;
/* USER */
if(str[0] == 'r')
permissions |= 1 << 8;
else if(str[0] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
if(str[1] == 'w')
permissions |= 1 << 7;
else if(str[1] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
if(str[2] == 'x')
permissions |= 1 << 6;
else if(str[2] == 's') {
permissions |= 1 << 6;
permissions |= 1 << 11;
}
else if(str[2] == 'S')
permissions |= 1 << 11;
else if(str[2] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
/* GROUP */
if(str[3] == 'r')
permissions |= 1 << 5;
else if(str[3] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
if(str[4] == 'w')
permissions |= 1 << 4;
else if(str[4] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
if(str[5] == 'x')
permissions |= 1 << 3;
else if(str[5] == 's') {
permissions |= 1 << 3;
permissions |= 1 << 10;
}
else if(str[5] == 'S')
permissions |= 1 << 10;
else if(str[5] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
/* others */
if(str[6] == 'r')
permissions |= 1 << 2;
else if(str[6] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
if(str[7] == 'w')
permissions |= 1 << 1;
else if(str[7] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
if(str[8] == 'x')
permissions |= 1;
else if(str[8] == 't') {
permissions |= 1;
permissions |= 1 << 9;
}
else if(str[8] == 'T')
permissions |= 1 << 9;
else if(str[8] != '-')
permissions |= FTP_LP_MALFORMATED_PERM;
return permissions;
}
static void PL_ERROR(struct connectdata *conn, CURLcode err)
{
struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
struct ftp_parselist_data *parser = tmpdata->parser;
if(parser->file_data)
Curl_fileinfo_dtor(NULL, parser->file_data);
parser->file_data = NULL;
parser->error = err;
}
static bool ftp_pl_gettime(struct ftp_parselist_data *parser, char *string)
{
(void)parser;
(void)string;
/* TODO
* There could be possible parse timestamp from server. Leaving unimplemented
* for now.
* If you want implement this, please add CURLFINFOFLAG_KNOWN_TIME flag to
* parser->file_data->flags
*
* Ftp servers are giving usually these formats:
* Apr 11 1998 (unknown time.. set it to 00:00:00?)
* Apr 11 12:21 (unknown year -> set it to NOW() time?)
* 08-05-09 02:49PM (ms-dos format)
* 20100421092538 -> for MLST/MLSD response
*/
return FALSE;
}
static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
struct curl_fileinfo *finfo)
{
curl_fnmatch_callback compare;
struct WildcardData *wc = &conn->data->wildcard;
struct ftp_wc_tmpdata *tmpdata = wc->tmp;
struct curl_llist *llist = wc->filelist;
struct ftp_parselist_data *parser = tmpdata->parser;
bool add = TRUE;
/* move finfo pointers to b_data */
char *str = finfo->b_data;
finfo->filename = str + parser->offsets.filename;
finfo->strings.group = parser->offsets.group ?
str + parser->offsets.group : NULL;
finfo->strings.perm = parser->offsets.perm ?
str + parser->offsets.perm : NULL;
finfo->strings.target = parser->offsets.symlink_target ?
str + parser->offsets.symlink_target : NULL;
finfo->strings.time = str + parser->offsets.time;
finfo->strings.user = parser->offsets.user ?
str + parser->offsets.user : NULL;
/* get correct fnmatch callback */
compare = conn->data->set.fnmatch;
if(!compare)
compare = Curl_fnmatch;
/* filter pattern-corresponding filenames */
if(compare(conn->data->set.fnmatch_data, wc->pattern, finfo->filename) == 0) {
/* discard symlink which is containing multiple " -> " */
if((finfo->filetype == CURLFILETYPE_SYMLINK) && finfo->strings.target &&
(strstr(finfo->strings.target, " -> "))) {
add = FALSE;
}
}
else {
add = FALSE;
}
if(add) {
if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
Curl_fileinfo_dtor(NULL, finfo);
tmpdata->parser->file_data = NULL;
return CURLE_OUT_OF_MEMORY;
}
}
else {
Curl_fileinfo_dtor(NULL, finfo);
}
tmpdata->parser->file_data = NULL;
return CURLE_OK;
}
size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr)
{
size_t bufflen = size*nmemb;
struct connectdata *conn = (struct connectdata *)connptr;
struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
struct ftp_parselist_data *parser = tmpdata->parser;
struct curl_fileinfo *finfo;
unsigned long i = 0;
CURLcode rc;
if(parser->error) { /* error in previous call */
/* scenario:
* 1. call => OK..
* 2. call => OUT_OF_MEMORY (or other error)
* 3. (last) call => is skipped RIGHT HERE and the error is hadled later
* in wc_statemach()
*/
return bufflen;
}
if(parser->os_type == OS_TYPE_UNKNOWN && bufflen > 0) {
/* considering info about FILE response format */
parser->os_type = (buffer[0] >= '0' && buffer[0] <= '9') ?
OS_TYPE_WIN_NT : OS_TYPE_UNIX;
}
while(i < bufflen) { /* FSM */
char c = buffer[i];
if(!parser->file_data) { /* tmp file data is not allocated yet */
parser->file_data = Curl_fileinfo_alloc();
if(!parser->file_data) {
parser->error = CURLE_OUT_OF_MEMORY;
return bufflen;
}
parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
if(!parser->file_data->b_data) {
PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
return bufflen;
}
parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
parser->item_offset = 0;
parser->item_length = 0;
}
finfo = parser->file_data;
finfo->b_data[finfo->b_used++] = buffer[i];
if(finfo->b_used >= finfo->b_size - 1) {
/* if it is important, extend buffer space for file data */
char *tmp = realloc(finfo->b_data,
finfo->b_size + FTP_BUFFER_ALLOCSIZE);
if(tmp) {
finfo->b_size += FTP_BUFFER_ALLOCSIZE;
finfo->b_data = tmp;
}
else {
Curl_fileinfo_dtor(NULL, parser->file_data);
parser->file_data = NULL;
parser->error = CURLE_OUT_OF_MEMORY;
PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
return bufflen;
}
}
switch (parser->os_type) {
case OS_TYPE_UNIX:
switch (parser->state.UNIX.main) {
case PL_UNIX_FILETYPE:
switch (c) {
case '-':
finfo->filetype = CURLFILETYPE_FILE;
break;
case 'd':
finfo->filetype = CURLFILETYPE_DIRECTORY;
break;
case 'l':
finfo->filetype = CURLFILETYPE_SYMLINK;
break;
case 'p':
finfo->filetype = CURLFILETYPE_NAMEDPIPE;
break;
case 's':
finfo->filetype = CURLFILETYPE_SOCKET;
break;
case 'c':
finfo->filetype = CURLFILETYPE_DEVICE_CHAR;
break;
case 'b':
finfo->filetype = CURLFILETYPE_DEVICE_BLOCK;
break;
case 'D':
finfo->filetype = CURLFILETYPE_DOOR;
break;
default:
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
parser->state.UNIX.main = PL_UNIX_PERMISSION;
parser->item_length = 0;
parser->item_offset = 1;
break;
case PL_UNIX_PERMISSION:
parser->item_length++;
if(parser->item_length <= 9) {
if(!strchr("rwx-tTsS", c)) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
else if(parser->item_length == 10) {
unsigned int perm;
if(c != ' ') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
finfo->b_data[10] = 0; /* terminate permissions */
perm = ftp_pl_get_permission(finfo->b_data + parser->item_offset);
if(perm & FTP_LP_MALFORMATED_PERM) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
parser->file_data->perm = perm;
parser->offsets.perm = parser->item_offset;
parser->item_length = 0;
parser->state.UNIX.main = PL_UNIX_HLINKS;
parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_PRESPACE;
}
break;
case PL_UNIX_HLINKS:
switch(parser->state.UNIX.sub.hlinks) {
case PL_UNIX_HLINKS_PRESPACE:
if(c != ' ') {
if(c >= '0' && c <= '9') {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.UNIX.sub.hlinks = PL_UNIX_HLINKS_NUMBER;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
break;
case PL_UNIX_HLINKS_NUMBER:
parser->item_length ++;
if(c == ' ') {
char *p;
long int hlinks;
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
parser->file_data->hardlinks = hlinks;
}
parser->item_length = 0;
parser->item_offset = 0;
parser->state.UNIX.main = PL_UNIX_USER;
parser->state.UNIX.sub.user = PL_UNIX_USER_PRESPACE;
}
else if(c < '0' || c > '9') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
case PL_UNIX_USER:
switch(parser->state.UNIX.sub.user) {
case PL_UNIX_USER_PRESPACE:
if(c != ' ') {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.UNIX.sub.user = PL_UNIX_USER_PARSING;
}
break;
case PL_UNIX_USER_PARSING:
parser->item_length++;
if(c == ' ') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.user = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_GROUP;
parser->state.UNIX.sub.group = PL_UNIX_GROUP_PRESPACE;
parser->item_offset = 0;
parser->item_length = 0;
}
break;
}
break;
case PL_UNIX_GROUP:
switch(parser->state.UNIX.sub.group) {
case PL_UNIX_GROUP_PRESPACE:
if(c != ' ') {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.UNIX.sub.group = PL_UNIX_GROUP_NAME;
}
break;
case PL_UNIX_GROUP_NAME:
parser->item_length++;
if(c == ' ') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.group = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_SIZE;
parser->state.UNIX.sub.size = PL_UNIX_SIZE_PRESPACE;
parser->item_offset = 0;
parser->item_length = 0;
}
break;
}
break;
case PL_UNIX_SIZE:
switch(parser->state.UNIX.sub.size) {
case PL_UNIX_SIZE_PRESPACE:
if(c != ' ') {
if(c >= '0' && c <= '9') {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.UNIX.sub.size = PL_UNIX_SIZE_NUMBER;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
break;
case PL_UNIX_SIZE_NUMBER:
parser->item_length++;
if(c == ' ') {
char *p;
curl_off_t fsize;
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
fsize != CURL_OFF_T_MIN) {
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
parser->file_data->size = fsize;
}
parser->item_length = 0;
parser->item_offset = 0;
parser->state.UNIX.main = PL_UNIX_TIME;
parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART1;
}
else if (!ISDIGIT(c)) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
case PL_UNIX_TIME:
switch(parser->state.UNIX.sub.time) {
case PL_UNIX_TIME_PREPART1:
if(c != ' ') {
if(ISALNUM(c)) {
parser->item_offset = finfo->b_used -1;
parser->item_length = 1;
parser->state.UNIX.sub.time = PL_UNIX_TIME_PART1;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
break;
case PL_UNIX_TIME_PART1:
parser->item_length++;
if(c == ' ') {
parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART2;
}
else if(!ISALNUM(c) && c != '.') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
case PL_UNIX_TIME_PREPART2:
parser->item_length++;
if(c != ' ') {
if(ISALNUM(c)) {
parser->state.UNIX.sub.time = PL_UNIX_TIME_PART2;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
break;
case PL_UNIX_TIME_PART2:
parser->item_length++;
if(c == ' ') {
parser->state.UNIX.sub.time = PL_UNIX_TIME_PREPART3;
}
else if(!ISALNUM(c) && c != '.') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
case PL_UNIX_TIME_PREPART3:
parser->item_length++;
if(c != ' ') {
if(ISALNUM(c)) {
parser->state.UNIX.sub.time = PL_UNIX_TIME_PART3;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
break;
case PL_UNIX_TIME_PART3:
parser->item_length++;
if(c == ' ') {
finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
parser->offsets.time = parser->item_offset;
if(ftp_pl_gettime(parser, finfo->b_data + parser->item_offset)) {
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_TIME;
}
if(finfo->filetype == CURLFILETYPE_SYMLINK) {
parser->state.UNIX.main = PL_UNIX_SYMLINK;
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRESPACE;
}
else {
parser->state.UNIX.main = PL_UNIX_FILENAME;
parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_PRESPACE;
}
}
else if(!ISALNUM(c) && c != '.' && c != ':') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
case PL_UNIX_FILENAME:
switch(parser->state.UNIX.sub.filename) {
case PL_UNIX_FILENAME_PRESPACE:
if(c != ' ') {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_NAME;
}
break;
case PL_UNIX_FILENAME_NAME:
parser->item_length++;
if(c == '\r') {
parser->item_length--;
parser->state.UNIX.sub.filename = PL_UNIX_FILENAME_WINDOWSEOL;
}
else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
rc = ftp_pl_insert_finfo(conn, finfo);
if(rc) {
PL_ERROR(conn, rc);
return bufflen;
}
}
break;
case PL_UNIX_FILENAME_WINDOWSEOL:
if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
rc = ftp_pl_insert_finfo(conn, finfo);
if(rc) {
PL_ERROR(conn, rc);
return bufflen;
}
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
case PL_UNIX_SYMLINK:
switch(parser->state.UNIX.sub.symlink) {
case PL_UNIX_SYMLINK_PRESPACE:
if(c != ' ') {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
}
break;
case PL_UNIX_SYMLINK_NAME:
parser->item_length++;
if(c == ' ') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET1;
}
else if(c == '\r' || c == '\n') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
case PL_UNIX_SYMLINK_PRETARGET1:
parser->item_length++;
if(c == '-') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET2;
}
else if(c == '\r' || c == '\n') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
else {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
}
break;
case PL_UNIX_SYMLINK_PRETARGET2:
parser->item_length++;
if(c == '>') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET3;
}
else if(c == '\r' || c == '\n') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
else {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
}
break;
case PL_UNIX_SYMLINK_PRETARGET3:
parser->item_length++;
if(c == ' ') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_PRETARGET4;
/* now place where is symlink following */
finfo->b_data[parser->item_offset + parser->item_length - 4] = 0;
parser->offsets.filename = parser->item_offset;
parser->item_length = 0;
parser->item_offset = 0;
}
else if(c == '\r' || c == '\n') {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
else {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_NAME;
}
break;
case PL_UNIX_SYMLINK_PRETARGET4:
if(c != '\r' && c != '\n') {
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_TARGET;
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
case PL_UNIX_SYMLINK_TARGET:
parser->item_length ++;
if(c == '\r') {
parser->item_length --;
parser->state.UNIX.sub.symlink = PL_UNIX_SYMLINK_WINDOWSEOL;
}
else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
rc = ftp_pl_insert_finfo(conn, finfo);
if(rc) {
PL_ERROR(conn, rc);
return bufflen;
}
parser->state.UNIX.main = PL_UNIX_FILETYPE;
}
break;
case PL_UNIX_SYMLINK_WINDOWSEOL:
if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
rc = ftp_pl_insert_finfo(conn, finfo);
if(rc) {
PL_ERROR(conn, rc);
return bufflen;
}
parser->state.UNIX.main = PL_UNIX_FILETYPE;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
}
break;
case OS_TYPE_WIN_NT:
switch(parser->state.NT.main) {
case PL_WINNT_DATE:
parser->item_length++;
if(parser->item_length < 9) {
if(!strchr("0123456789-", c)) { /* only simple control */
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
else if(parser->item_length == 9) {
if(c == ' ') {
parser->state.NT.main = PL_WINNT_TIME;
parser->state.NT.sub.time = PL_WINNT_TIME_PRESPACE;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
case PL_WINNT_TIME:
parser->item_length++;
switch(parser->state.NT.sub.time) {
case PL_WINNT_TIME_PRESPACE:
if(!ISSPACE(c)) {
parser->state.NT.sub.time = PL_WINNT_TIME_TIME;
}
break;
case PL_WINNT_TIME_TIME:
if(c == ' ') {
parser->offsets.time = parser->item_offset;
finfo->b_data[parser->item_offset + parser->item_length -1] = 0;
parser->state.NT.main = PL_WINNT_DIRORSIZE;
parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_PRESPACE;
parser->item_length = 0;
}
else if(!strchr("APM0123456789:", c)) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
case PL_WINNT_DIRORSIZE:
switch(parser->state.NT.sub.dirorsize) {
case PL_WINNT_DIRORSIZE_PRESPACE:
if(c == ' ') {
}
else {
parser->item_offset = finfo->b_used - 1;
parser->item_length = 1;
parser->state.NT.sub.dirorsize = PL_WINNT_DIRORSIZE_CONTENT;
}
break;
case PL_WINNT_DIRORSIZE_CONTENT:
parser->item_length ++;
if(c == ' ') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
if(strcmp("<DIR>", finfo->b_data + parser->item_offset) == 0) {
finfo->filetype = CURLFILETYPE_DIRECTORY;
finfo->size = 0;
}
else {
char *endptr;
finfo->size = curlx_strtoofft(finfo->b_data + parser->item_offset,
&endptr, 10);
if(!*endptr) {
if(finfo->size == CURL_OFF_T_MAX ||
finfo->size == CURL_OFF_T_MIN) {
if(errno == ERANGE) {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
}
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
/* correct file type */
parser->file_data->filetype = CURLFILETYPE_FILE;
}
parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
parser->item_length = 0;
parser->state.NT.main = PL_WINNT_FILENAME;
parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
}
break;
}
break;
case PL_WINNT_FILENAME:
switch (parser->state.NT.sub.filename) {
case PL_WINNT_FILENAME_PRESPACE:
if(c != ' ') {
parser->item_offset = finfo->b_used -1;
parser->item_length = 1;
parser->state.NT.sub.filename = PL_WINNT_FILENAME_CONTENT;
}
break;
case PL_WINNT_FILENAME_CONTENT:
parser->item_length++;
if(c == '\r') {
parser->state.NT.sub.filename = PL_WINNT_FILENAME_WINEOL;
finfo->b_data[finfo->b_used - 1] = 0;
}
else if(c == '\n') {
parser->offsets.filename = parser->item_offset;
finfo->b_data[finfo->b_used - 1] = 0;
parser->offsets.filename = parser->item_offset;
rc = ftp_pl_insert_finfo(conn, finfo);
if(rc) {
PL_ERROR(conn, rc);
return bufflen;
}
parser->state.NT.main = PL_WINNT_DATE;
parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
}
break;
case PL_WINNT_FILENAME_WINEOL:
if(c == '\n') {
parser->offsets.filename = parser->item_offset;
rc = ftp_pl_insert_finfo(conn, finfo);
if(rc) {
PL_ERROR(conn, rc);
return bufflen;
}
parser->state.NT.main = PL_WINNT_DATE;
parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
}
else {
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
break;
}
break;
}
break;
default:
return bufflen+1;
}
i++;
}
return bufflen;
}

39
lib/ftplistparser.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef HEADER_CURL_FTPLISTPARSER_H
#define HEADER_CURL_FTPLISTPARSER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include <curl/curl.h>
/* WRITEFUNCTION callback for parsing LIST responses */
size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
void *connptr);
struct ftp_parselist_data; /* defined inside ftplibparser.c */
CURLcode Curl_ftp_parselist_geterror(struct ftp_parselist_data *pl_data);
struct ftp_parselist_data *Curl_ftp_parselist_data_alloc(void);
void Curl_ftp_parselist_data_free(struct ftp_parselist_data **pl_data);
#endif /* HEADER_CURL_FTPLISTPARSER_H */

View File

@@ -66,6 +66,12 @@ CURLcode Curl_initinfo(struct SessionHandle *data)
info->header_size = 0;
info->request_size = 0;
info->numconnects = 0;
info->ip[0] = 0;
info->port = 0;
info->localip[0] = 0;
info->localport = 0;
return CURLE_OK;
}
@@ -224,6 +230,19 @@ CURLcode Curl_getinfo(struct SessionHandle *data, CURLINFO info, ...)
/* Return the ip address of the most recent (primary) connection */
*param_charp = data->info.ip;
break;
case CURLINFO_PRIMARY_PORT:
/* Return the (remote) port of the most recent (primary) connection */
*param_longp = data->info.port;
break;
case CURLINFO_LOCAL_IP:
/* Return the source/local ip address of the most recent (primary)
connection */
*param_charp = data->info.localip;
break;
case CURLINFO_LOCAL_PORT:
/* Return the local port of the most recent (primary) connection */
*param_longp = data->info.localport;
break;
case CURLINFO_CERTINFO:
/* Return the a pointer to the certinfo struct. Not really an slist
pointer but we can pretend it is here */

View File

@@ -182,54 +182,76 @@ static void unload_file(gnutls_datum data) {
}
/* this function does a BLOCKING SSL/TLS (re-)handshake */
/* this function does a SSL/TLS (re-)handshake */
static CURLcode handshake(struct connectdata *conn,
gnutls_session session,
int sockindex,
bool duringconnect)
bool duringconnect,
bool nonblocking)
{
struct SessionHandle *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
gnutls_session session = conn->ssl[sockindex].session;
curl_socket_t sockfd = conn->sock[sockindex];
long timeout_ms;
int rc;
if(!gtls_inited)
Curl_gtls_init();
do {
rc = gnutls_handshake(session);
int what;
if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
long timeout_ms = Curl_timeleft(conn, NULL, duringconnect);
while(1) {
/* check allowed time left */
timeout_ms = Curl_timeleft(conn, NULL, duringconnect);
if(timeout_ms < 0) {
/* a precaution, no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
if(timeout_ms < 0) {
/* no need to continue if time already is up */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
rc = Curl_socket_ready(conn->sock[sockindex],
conn->sock[sockindex], (int)timeout_ms);
if(rc > 0)
/* reabable or writable, go loop*/
continue;
else if(0 == rc) {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
else {
/* anything that gets here is fatally bad */
/* if ssl is expecting something, check if it's available. */
if(connssl->connecting_state == ssl_connect_2_reading
|| connssl->connecting_state == ssl_connect_2_writing) {
curl_socket_t writefd = ssl_connect_2_writing==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
curl_socket_t readfd = ssl_connect_2_reading==
connssl->connecting_state?sockfd:CURL_SOCKET_BAD;
what = Curl_socket_ready(readfd, writefd,
nonblocking?0:(int)timeout_ms);
if(what < 0) {
/* fatal error */
failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO);
return CURLE_SSL_CONNECT_ERROR;
}
else if(0 == what) {
if(nonblocking) {
return CURLE_OK;
}
else {
/* timeout */
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
}
/* socket is readable or writable */
}
else
break;
} while(1);
if(rc < 0) {
failf(data, "gnutls_handshake() failed: %s", gnutls_strerror(rc));
return CURLE_SSL_CONNECT_ERROR;
rc = gnutls_handshake(session);
if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) {
connssl->connecting_state =
gnutls_record_get_direction(session)?
ssl_connect_2_writing:ssl_connect_2_reading;
if(nonblocking) {
return CURLE_OK;
}
} else if (rc < 0) {
failf(data, "gnutls_handshake() failed: %s", gnutls_strerror(rc));
} else {
/* Reset our connect state machine */
connssl->connecting_state = ssl_connect_1;
return CURLE_OK;
}
}
return CURLE_OK;
}
static gnutls_x509_crt_fmt do_file_type(const char *type)
@@ -243,31 +265,14 @@ static gnutls_x509_crt_fmt do_file_type(const char *type)
return -1;
}
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic.
*/
CURLcode
Curl_gtls_connect(struct connectdata *conn,
int sockindex)
static CURLcode
gtls_connect_step1(struct connectdata *conn,
int sockindex)
{
static const int cert_type_priority[] = { GNUTLS_CRT_X509, 0 };
struct SessionHandle *data = conn->data;
gnutls_session session;
int rc;
unsigned int cert_list_size;
const gnutls_datum *chainp;
unsigned int verify_status;
gnutls_x509_crt x509_cert,x509_issuer;
gnutls_datum issuerp;
char certbuf[256]; /* big enough? */
size_t size;
unsigned int algo;
unsigned int bits;
time_t certclock;
const char *ptr;
void *ssl_sessionid;
size_t ssl_idsize;
bool sni = TRUE; /* default is SNI enabled */
@@ -411,10 +416,32 @@ Curl_gtls_connect(struct connectdata *conn,
infof (data, "SSL re-using session ID\n");
}
rc = handshake(conn, session, sockindex, TRUE);
if(rc)
/* handshake() sets its own error message with failf() */
return rc;
return CURLE_OK;
}
static Curl_recv gtls_recv;
static Curl_send gtls_send;
static CURLcode
gtls_connect_step3(struct connectdata *conn,
int sockindex)
{
unsigned int cert_list_size;
const gnutls_datum *chainp;
unsigned int verify_status;
gnutls_x509_crt x509_cert,x509_issuer;
gnutls_datum issuerp;
char certbuf[256]; /* big enough? */
size_t size;
unsigned int algo;
unsigned int bits;
time_t certclock;
const char *ptr;
struct SessionHandle *data = conn->data;
gnutls_session session = conn->ssl[sockindex].session;
int rc;
int incache;
void *ssl_sessionid;
/* This function will return the peer's raw certificate (chain) as sent by
the peer. These certificates are in raw format (DER encoded for
@@ -606,6 +633,8 @@ Curl_gtls_connect(struct connectdata *conn,
infof(data, "\t MAC: %s\n", ptr);
conn->ssl[sockindex].state = ssl_connection_complete;
conn->recv[sockindex] = gtls_recv;
conn->send[sockindex] = gtls_send;
{
/* we always unconditionally get the session id here, as even if we
@@ -623,33 +652,100 @@ Curl_gtls_connect(struct connectdata *conn,
/* extract session ID to the allocated buffer */
gnutls_session_get_data(session, connect_sessionid, &connect_idsize);
if(ssl_sessionid)
incache = !(Curl_ssl_getsessionid(conn, &ssl_sessionid, NULL));
if (incache) {
/* there was one before in the cache, so instead of risking that the
previous one was rejected, we just kill that and store the new */
Curl_ssl_delsessionid(conn, ssl_sessionid);
}
/* store this session id */
return Curl_ssl_addsessionid(conn, connect_sessionid, connect_idsize);
}
}
return CURLE_OK;
}
/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_gtls_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
int *curlcode)
/*
* This function is called after the TCP connect has completed. Setup the TLS
* layer and do all necessary magic.
*/
/* We use connssl->connecting_state to keep track of the connection status;
there are three states: 'ssl_connect_1' (not started yet or complete),
'ssl_connect_2_reading' (waiting for data from server), and
'ssl_connect_2_writing' (waiting to be able to write).
*/
static CURLcode
gtls_connect_common(struct connectdata *conn,
int sockindex,
bool nonblocking,
bool *done)
{
int rc;
struct ssl_connect_data *connssl = &conn->ssl[sockindex];
/* Initiate the connection, if not already done */
if(ssl_connect_1==connssl->connecting_state) {
rc = gtls_connect_step1 (conn, sockindex);
if(rc)
return rc;
}
rc = handshake(conn, sockindex, TRUE, nonblocking);
if(rc)
/* handshake() sets its own error message with failf() */
return rc;
/* Finish connecting once the handshake is done */
if(ssl_connect_1==connssl->connecting_state) {
rc = gtls_connect_step3(conn, sockindex);
if(rc)
return rc;
}
*done = ssl_connect_1==connssl->connecting_state;
return CURLE_OK;
}
CURLcode
Curl_gtls_connect_nonblocking(struct connectdata *conn,
int sockindex,
bool *done)
{
return gtls_connect_common(conn, sockindex, TRUE, done);
}
CURLcode
Curl_gtls_connect(struct connectdata *conn,
int sockindex)
{
CURLcode retcode;
bool done = FALSE;
retcode = gtls_connect_common(conn, sockindex, FALSE, &done);
if(retcode)
return retcode;
DEBUGASSERT(done);
return CURLE_OK;
}
static ssize_t gtls_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
ssize_t rc = gnutls_record_send(conn->ssl[sockindex].session, mem, len);
if(rc < 0 ) {
*curlcode = (rc == GNUTLS_E_AGAIN)
? /* EWOULDBLOCK */ -1
? CURLE_AGAIN
: CURLE_SEND_ERROR;
rc = -1;
@@ -751,36 +847,29 @@ int Curl_gtls_shutdown(struct connectdata *conn, int sockindex)
return retval;
}
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_gtls_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
int *curlcode)
static ssize_t gtls_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
ssize_t ret;
ret = gnutls_record_recv(conn->ssl[num].session, buf, buffersize);
if((ret == GNUTLS_E_AGAIN) || (ret == GNUTLS_E_INTERRUPTED)) {
*curlcode = -1;
*curlcode = CURLE_AGAIN;
return -1;
}
if(ret == GNUTLS_E_REHANDSHAKE) {
/* BLOCKING call, this is bad but a work-around for now. Fixing this "the
proper way" takes a whole lot of work. */
CURLcode rc = handshake(conn, conn->ssl[num].session, num, FALSE);
CURLcode rc = handshake(conn, num, FALSE, FALSE);
if(rc)
/* handshake() writes error message on its own */
*curlcode = rc;
else
*curlcode = -1; /* then return as if this was a wouldblock */
return -1;
}
if(!ret) {
failf(conn->data, "Peer closed the TLS connection");
*curlcode = CURLE_RECV_ERROR;
*curlcode = CURLE_AGAIN; /* then return as if this was a wouldblock */
return -1;
}

View File

@@ -27,6 +27,9 @@
int Curl_gtls_init(void);
int Curl_gtls_cleanup(void);
CURLcode Curl_gtls_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_gtls_connect_nonblocking(struct connectdata *conn,
int sockindex,
bool *done);
/* tell GnuTLS to close down all open information regarding connections (and
thus session ID caching etc) */
@@ -35,14 +38,6 @@ void Curl_gtls_close_all(struct SessionHandle *data);
/* close a SSL connection */
void Curl_gtls_close(struct connectdata *conn, int sockindex);
/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_gtls_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, int *curlcode);
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_gtls_recv(struct connectdata *conn, int num, char *buf,
size_t buffersize, int *curlcode);
void Curl_gtls_session_free(void *ptr);
size_t Curl_gtls_version(char *buffer, size_t size);
int Curl_gtls_shutdown(struct connectdata *conn, int sockindex);
@@ -52,6 +47,7 @@ int Curl_gtls_seed(struct SessionHandle *data);
#define curlssl_init Curl_gtls_init
#define curlssl_cleanup Curl_gtls_cleanup
#define curlssl_connect Curl_gtls_connect
#define curlssl_connect_nonblocking Curl_gtls_connect_nonblocking
#define curlssl_session_free(x) Curl_gtls_session_free(x)
#define curlssl_close_all Curl_gtls_close_all
#define curlssl_close Curl_gtls_close
@@ -59,8 +55,6 @@ int Curl_gtls_seed(struct SessionHandle *data);
#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
#define curlssl_send Curl_gtls_send
#define curlssl_recv Curl_gtls_recv
#define curlssl_version Curl_gtls_version
#define curlssl_check_cxn(x) (x=x, -1)
#define curlssl_data_pending(x,y) (x=x, y=y, 0)

131
lib/hmac.c Normal file
View File

@@ -0,0 +1,131 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* RFC2104 Keyed-Hashing for Message Authentication
*
***************************************************************************/
#include "setup.h"
#ifndef CURL_DISABLE_CRYPTO_AUTH
#include "curl_hmac.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/*
* Generic HMAC algorithm.
*
* This module computes HMAC digests based on any hash function. Parameters
* and computing procedures are set-up dynamically at HMAC computation
* context initialisation.
*/
static const unsigned char hmac_ipad = 0x36;
static const unsigned char hmac_opad = 0x5C;
HMAC_context *
Curl_HMAC_init(const HMAC_params * hashparams,
const unsigned char * key,
unsigned int keylen)
{
size_t i;
HMAC_context * ctxt;
unsigned char * hkey;
unsigned char b;
/* Create HMAC context. */
i = sizeof *ctxt + 2 * hashparams->hmac_ctxtsize + hashparams->hmac_resultlen;
ctxt = (HMAC_context *) malloc(i);
if(!ctxt)
return ctxt;
ctxt->hmac_hash = hashparams;
ctxt->hmac_hashctxt1 = (void *) (ctxt + 1);
ctxt->hmac_hashctxt2 = (void *) ((char *) ctxt->hmac_hashctxt1 +
hashparams->hmac_ctxtsize);
/* If the key is too long, replace it by its hash digest. */
if(keylen > hashparams->hmac_maxkeylen) {
(*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
(*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, key, keylen);
hkey = (unsigned char *) ctxt->hmac_hashctxt2 + hashparams->hmac_ctxtsize;
(*hashparams->hmac_hfinal)(hkey, ctxt->hmac_hashctxt1);
key = hkey;
keylen = hashparams->hmac_resultlen;
}
/* Prime the two hash contexts with the modified key. */
(*hashparams->hmac_hinit)(ctxt->hmac_hashctxt1);
(*hashparams->hmac_hinit)(ctxt->hmac_hashctxt2);
for (i = 0; i < keylen; i++) {
b = *key ^ hmac_ipad;
(*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &b, 1);
b = *key++ ^ hmac_opad;
(*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &b, 1);
}
for (; i < hashparams->hmac_maxkeylen; i++) {
(*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt1, &hmac_ipad, 1);
(*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2, &hmac_opad, 1);
}
/* Done, return pointer to HMAC context. */
return ctxt;
}
int Curl_HMAC_update(HMAC_context * ctxt,
const unsigned char * data,
unsigned int len)
{
/* Update first hash calculation. */
(*ctxt->hmac_hash->hmac_hupdate)(ctxt->hmac_hashctxt1, data, len);
return 0;
}
int Curl_HMAC_final(HMAC_context * ctxt, unsigned char * result)
{
const HMAC_params * hashparams = ctxt->hmac_hash;
/* Do not get result if called with a null parameter: only release storage. */
if(!result)
result = (unsigned char *) ctxt->hmac_hashctxt2 +
ctxt->hmac_hash->hmac_ctxtsize;
(*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt1);
(*hashparams->hmac_hupdate)(ctxt->hmac_hashctxt2,
result, hashparams->hmac_resultlen);
(*hashparams->hmac_hfinal)(result, ctxt->hmac_hashctxt2);
free((char *) ctxt);
return 0;
}
#endif /* CURL_DISABLE_CRYPTO_AUTH */

View File

@@ -251,7 +251,7 @@ CURLcode Curl_wait_for_resolv(struct connectdata *conn,
second is left, otherwise just use 1000ms to make sure the progress
callback gets called frequent enough */
if(!tvp->tv_sec)
timeout_ms = tvp->tv_usec/1000;
timeout_ms = (int)(tvp->tv_usec/1000);
else
timeout_ms = 1000;

View File

@@ -160,7 +160,7 @@ Curl_addrinfo *Curl_ipv4_resolve_r(const char *hostname,
snprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr = sbuf;
}
hints.ai_flags = AI_CANONNAME;
(void)Curl_getaddrinfo_ex(hostname, sbufptr, &hints, &ai);
#elif defined(HAVE_GETHOSTBYNAME_R)

View File

@@ -213,11 +213,6 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
/* the given address is numerical only, prevent a reverse lookup */
hints.ai_flags = AI_NUMERICHOST;
}
#ifdef HAVE_GSSAPI
if(conn->data->set.krb)
/* if krb is used, we (might) need the canonical host name */
hints.ai_flags |= AI_CANONNAME;
#endif
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);

View File

@@ -561,9 +561,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = conn->socktype;
#if 0 /* removed nov 8 2005 before 7.15.1 */
hints.ai_flags = AI_CANONNAME;
#endif
snprintf(sbuf, sizeof(sbuf), "%d", port);
/* fire up a new resolver thread! */

View File

@@ -1283,7 +1283,6 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
struct SessionHandle *data=conn->data;
struct SingleRequest *k = &data->req;
CURLcode result;
int res;
long timeout =
data->set.timeout?data->set.timeout:PROXY_TIMEOUT; /* in milliseconds */
curl_socket_t tunnelsocket = conn->sock[sockindex];
@@ -1467,11 +1466,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
break;
default:
DEBUGASSERT(ptr+BUFSIZE-nread <= data->state.buffer+BUFSIZE+1);
res = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
if(res< 0)
/* EWOULDBLOCK */
result = Curl_read(conn, tunnelsocket, ptr, BUFSIZE-nread, &gotbytes);
if(result==CURLE_AGAIN)
continue; /* go loop yourself */
else if(res)
else if(result)
keepon = FALSE;
else if(gotbytes <= 0) {
keepon = FALSE;
@@ -1817,9 +1815,9 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
}
#endif
#ifdef USE_SSLEAY
/* This function is OpenSSL-specific. It should be made to query the generic
SSL layer instead. */
#if defined(USE_SSLEAY) || defined(USE_GNUTLS)
/* This function is for OpenSSL and GnuTLS only. It should be made to query
the generic SSL layer instead. */
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
@@ -1844,17 +1842,6 @@ static int https_getsock(struct connectdata *conn,
return CURLE_OK;
}
#else
#ifdef USE_GNUTLS
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
(void)conn;
(void)socks;
(void)numsocks;
return GETSOCK_BLANK;
}
#else
#ifdef USE_NSS
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
@@ -1876,6 +1863,17 @@ static int https_getsock(struct connectdata *conn,
(void)numsocks;
return GETSOCK_BLANK;
}
#else
#ifdef USE_POLARSSL
static int https_getsock(struct connectdata *conn,
curl_socket_t *socks,
int numsocks)
{
(void)conn;
(void)socks;
(void)numsocks;
return GETSOCK_BLANK;
}
#endif
#endif
#endif
@@ -2665,14 +2663,13 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
return result;
result = Curl_add_buffer_send(req_buffer, conn,
&data->info.request_size, 0, FIRSTSOCKET);
&data->info.request_size, 0, FIRSTSOCKET);
if(result)
failf(data, "Failed sending POST request");
else
/* setup variables for the upcoming transfer */
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
-1, NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
-1, NULL);
break;
}
@@ -2740,10 +2737,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
failf(data, "Failed sending POST request");
else
/* setup variables for the upcoming transfer */
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
FIRSTSOCKET,
&http->writebytecount);
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, FIRSTSOCKET,
&http->writebytecount);
if(result) {
Curl_formclean(&http->sendit); /* free that whole lot */
@@ -2793,10 +2789,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
failf(data, "Failed sending PUT request");
else
/* prepare for transfer */
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
postsize?FIRSTSOCKET:-1,
postsize?&http->writebytecount:NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, postsize?FIRSTSOCKET:-1,
postsize?&http->writebytecount:NULL);
if(result)
return result;
break;
@@ -2943,11 +2938,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(result)
failf(data, "Failed sending HTTP POST request");
else
result =
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
http->postdata?FIRSTSOCKET:-1,
http->postdata?&http->writebytecount:NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, http->postdata?FIRSTSOCKET:-1,
http->postdata?&http->writebytecount:NULL);
break;
default:
@@ -2963,10 +2956,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
failf(data, "Failed sending HTTP request");
else
/* HTTP GET/HEAD download: */
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
http->postdata?FIRSTSOCKET:-1,
http->postdata?&http->writebytecount:NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
http->postdata?FIRSTSOCKET:-1,
http->postdata?&http->writebytecount:NULL);
}
if(result)
return result;

View File

@@ -305,9 +305,15 @@ CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
infof(conn->data, "Make SPNEGO Initial Token failed\n");
}
else {
free(neg_ctx->output_token.value);
free(responseToken);
responseToken = NULL;
free(neg_ctx->output_token.value);
neg_ctx->output_token.value = malloc(spnegoTokenLength);
if(neg_ctx->output_token.value == NULL) {
free(spnegoToken);
spnegoToken = NULL;
return CURLE_OUT_OF_MEMORY;
}
memcpy(neg_ctx->output_token.value, spnegoToken,spnegoTokenLength);
neg_ctx->output_token.length = spnegoTokenLength;
free(spnegoToken);

View File

@@ -436,12 +436,11 @@ static CURLcode imap_state_fetch_resp(struct connectdata *conn,
if(!filesize)
/* the entire data is already transfered! */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
else
/* IMAP download */
result=Curl_setup_transfer(conn, FIRSTSOCKET, filesize, FALSE,
imap->bytecountp,
-1, NULL); /* no upload here */
Curl_setup_transfer(conn, FIRSTSOCKET, filesize, FALSE,
imap->bytecountp, -1, NULL); /* no upload here */
data->req.maxdownload = filesize;
}
@@ -924,15 +923,14 @@ static CURLcode imap_parse_url_path(struct connectdata *conn)
static CURLcode imap_dophase_done(struct connectdata *conn,
bool connected)
{
CURLcode result = CURLE_OK;
struct FTP *imap = conn->data->state.proto.imap;
(void)connected;
if(imap->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
return result;
return CURLE_OK;
}
/* called from multi.c while DOing */

View File

@@ -159,7 +159,7 @@ inet_pton6(const char *src, unsigned char *dst)
unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
unsigned int val;
size_t val;
memset((tp = tmp), 0, IN6ADDRSZ);
endp = tp + IN6ADDRSZ;
@@ -218,8 +218,8 @@ inet_pton6(const char *src, unsigned char *dst)
* Since some memmove()'s erroneously fail to handle
* overlapping regions, we'll do the shift by hand.
*/
const long n = tp - colonp;
long i;
const size_t n = tp - colonp;
size_t i;
if(tp == endp)
return (0);

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -51,14 +51,11 @@ int Curl_sec_fflush_fd(struct connectdata *conn, int fd);
int Curl_sec_fprintf (struct connectdata *, FILE *, const char *, ...);
int Curl_sec_getc (struct connectdata *conn, FILE *);
int Curl_sec_putc (struct connectdata *conn, int, FILE *);
int Curl_sec_read (struct connectdata *conn, int, void *, int);
int Curl_sec_read_msg (struct connectdata *conn, char *, int);
int Curl_sec_vfprintf(struct connectdata *, FILE *, const char *, va_list);
int Curl_sec_fprintf2(struct connectdata *conn, FILE *f, const char *fmt, ...);
int Curl_sec_vfprintf2(struct connectdata *conn, FILE *, const char *, va_list);
ssize_t Curl_sec_send(struct connectdata *conn, int, const char *, int);
int Curl_sec_write(struct connectdata *conn, int, const char *, int);
void Curl_sec_end (struct connectdata *);
int Curl_sec_login (struct connectdata *);

View File

@@ -1,6 +1,6 @@
/* GSSAPI/krb5 support for FTP - loosely based on old krb4.c
*
* Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H<>gskolan
* Copyright (c) 1995, 1996, 1997, 1998, 1999, 2010 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* Copyright (c) 2004 - 2009 Daniel Stenberg
* All rights reserved.
@@ -163,7 +163,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
{
int ret;
char *p;
const char *host = conn->dns_entry->addr->ai_canonname;
const char *host = conn->host.name;
ssize_t nread;
curl_socklen_t l = sizeof(conn->local_addr);
struct SessionHandle *data = conn->data;

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -22,7 +22,19 @@
#include "setup.h"
#ifndef CURL_DISABLE_LDAP
#if !defined(CURL_DISABLE_LDAP) && !defined(USE_OPENLDAP)
/*
* Notice that USE_OPENLDAP is only a source code selection switch. When
* libcurl is built with USE_OPENLDAP defined the libcurl source code that
* gets compiled is the code from openldap.c, otherwise the code that gets
* compiled is the code from ldap.c.
*
* When USE_OPENLDAP is defined a recent version of the OpenLDAP library
* might be required for compilation and runtime. In order to use ancient
* OpenLDAP library versions, USE_OPENLDAP shall not be defined.
*/
/* -- WIN32 approved -- */
#include <stdio.h>
#include <string.h>
@@ -31,15 +43,7 @@
#include <ctype.h>
#include <errno.h>
#ifdef CURL_LDAP_HYBRID /* If W$ definitions are needed. */
# include <windows.h>
/* Remember we are NOT in a W$ compiler! */
# undef WIN32
# undef _WIN32
# undef __WIN32__
#endif
#ifdef CURL_LDAP_WIN /* Use W$ LDAP implementation. */
#ifdef CURL_LDAP_WIN /* Use Windows LDAP implementation. */
# include <winldap.h>
# ifndef LDAP_VENDOR_NAME
# error Your Platform SDK is NOT sufficient for LDAP support! Update your Platform SDK, or disable LDAP support!
@@ -47,14 +51,14 @@
# include <winber.h>
# endif
#else
#define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */
#ifdef HAVE_LBER_H
# include <lber.h>
#endif
# define LDAP_DEPRECATED 1 /* Be sure ldap_init() is defined. */
# ifdef HAVE_LBER_H
# include <lber.h>
# endif
# include <ldap.h>
#if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H))
# include <ldap_ssl.h>
#endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
# if (defined(HAVE_LDAP_SSL) && defined(HAVE_LDAP_SSL_H))
# include <ldap_ssl.h>
# endif /* HAVE_LDAP_SSL && HAVE_LDAP_SSL_H */
#endif
#ifdef HAVE_UNISTD_H
@@ -715,4 +719,4 @@ static void _ldap_free_urldesc (LDAPURLDesc *ludp)
free (ludp);
}
#endif /* !HAVE_LDAP_URL_PARSE */
#endif /* CURL_DISABLE_LDAP */
#endif /* !CURL_DISABLE_LDAP && !USE_OPENLDAP */

View File

@@ -1,5 +1,5 @@
#
# $VER: LibcURL Makefile for AmigaOS ...
# libcurl Makefile for AmigaOS ...
#
# change the follow to where you have the AmiTCP SDK v4.3 includes:
@@ -10,23 +10,12 @@ ATCPSDKI= /GG/netinclude
CC = m68k-amigaos-gcc
CFLAGS = -I$(ATCPSDKI) -m68020-60 -O2 -msoft-float -noixemul -g -I. -I../include -W -Wall
OBJS = amigaos.c \
file.c timeval.c base64.c hostip.c progress.c formdata.c \
cookie.c http.c sendf.c ftp.c url.c dict.c if2ip.c speedcheck.c \
ldap.c ssluse.c version.c getenv.c escape.c mprintf.c telnet.c \
netrc.c getinfo.c transfer.c strequal.c easy.c security.c krb4.c \
krb5.c memdebug.c http_chunks.c strtok.c connect.c llist.c hash.c \
multi.c content_encoding.c share.c http_digest.c md5.c curl_rand.c \
http_negotiate.c http_ntlm.c inet_pton.c strtoofft.c strerror.c \
hostares.c hostasyn.c hostip4.c hostip6.c hostsyn.c hostthre.c \
inet_ntop.c parsedate.c select.c gtls.c sslgen.c tftp.c splay.c \
strdup.c socks.c ssh.c nss.c qssl.c rawstr.c curl_addrinfo.c \
socks_gssapi.c socks_sspi.c curl_sspi.c slist.c nonblock.c \
curl_memrchr.c imap.c pop3.c smtp.c pingpong.c rtsp.c curl_threads.c \
warnless.c
include Makefile.inc
CSOURCES += amigaos.c
OBJS = $(CSOURCES:.c=.o)
all: $(OBJS:.c=.o)
ar cru libcurl.a $(OBJS:.c=.o)
all: $(OBJS)
ar cru libcurl.a $(OBJS)
ranlib libcurl.a
install:

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -27,19 +27,30 @@
#include <string.h>
#include "curl_md5.h"
#include "curl_hmac.h"
#ifdef USE_GNUTLS
#include <gcrypt.h>
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
const unsigned char *input)
typedef gcry_md_hd_t MD5_CTX;
static void MD5_Init(MD5_CTX * ctx)
{
gcry_md_hd_t ctx;
gcry_md_open(&ctx, GCRY_MD_MD5, 0);
gcry_md_write(ctx, input, (unsigned int)strlen((char *)input));
memcpy (outbuffer, gcry_md_read (ctx, 0), 16);
gcry_md_close(ctx);
gcry_md_open(ctx, GCRY_MD_MD5, 0);
}
static void MD5_Update(MD5_CTX * ctx,
const unsigned char * input,
unsigned int inputLen)
{
gcry_md_write(*ctx, input, inputLen);
}
static void MD5_Final(unsigned char digest[16], MD5_CTX * ctx)
{
memcpy(digest, gcry_md_read(*ctx, 0), 16);
gcry_md_close(*ctx);
}
#else
@@ -358,6 +369,20 @@ static void Decode (UINT4 *output,
#endif /* USE_SSLEAY */
#endif /* USE_GNUTLS */
const HMAC_params Curl_HMAC_MD5[] = {
{
(HMAC_hinit_func) MD5_Init, /* Hash initialization function. */
(HMAC_hupdate_func) MD5_Update, /* Hash update function. */
(HMAC_hfinal_func) MD5_Final, /* Hash computation end function. */
sizeof(MD5_CTX), /* Size of hash context structure. */
64, /* Maximum key length. */
16 /* Result size. */
}
};
void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
const unsigned char *input)
{
@@ -367,6 +392,4 @@ void Curl_md5it(unsigned char *outbuffer, /* 16 bytes */
MD5_Final(outbuffer, &ctx);
}
#endif /* USE_GNUTLS */
#endif /* CURL_DISABLE_CRYPTO_AUTH */

View File

@@ -963,7 +963,6 @@ static int dprintf_formatf(
/* RECURSIVE USAGE */
len = curl_msnprintf(fptr, left, ".%ld", prec);
fptr += len;
left -= len;
}
if(p->flags & FLAGS_LONG)
*fptr++ = 'l';

View File

@@ -1128,6 +1128,17 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(CURLE_OK == easy->result) {
if(!dophase_done) {
/* some steps needed for wildcard matching */
if(easy->easy_handle->set.wildcardmatch) {
struct WildcardData *wc = &easy->easy_handle->wildcard;
if(wc->state == CURLWC_DONE || wc->state == CURLWC_SKIP) {
/* skip some states if it is important */
Curl_done(&easy->easy_conn, CURLE_OK, FALSE);
multistate(easy, CURLM_STATE_DONE);
result = CURLM_CALL_MULTI_PERFORM;
break;
}
}
/* DO was not completed in one function call, we must continue
DOING... */
multistate(easy, CURLM_STATE_DOING);
@@ -1338,7 +1349,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->easy_conn->writechannel_inuse = FALSE;
}
if(easy->result) {
if(easy->result) {
/* The transfer phase returned error, we mark the connection to get
* closed to prevent being re-used. This is because we can't possibly
* know if the connection is in a good shape or not now. Unless it is
@@ -1449,6 +1460,16 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
easy->easy_conn = NULL;
}
if(easy->easy_handle->set.wildcardmatch) {
if(easy->easy_handle->wildcard.state != CURLWC_DONE) {
/* if a wildcard is set and we are not ending -> lets start again
with CURLM_STATE_INIT */
result = CURLM_CALL_MULTI_PERFORM;
multistate(easy, CURLM_STATE_INIT);
break;
}
}
/* after we have DONE what we're supposed to do, go COMPLETED, and
it doesn't matter what the Curl_done() returned! */
multistate(easy, CURLM_STATE_COMPLETED);
@@ -1550,11 +1571,26 @@ CURLMcode curl_multi_perform(CURLM *multi_handle, int *running_handles)
easy=multi->easy.next;
while(easy != &multi->easy) {
CURLMcode result;
struct WildcardData *wc = &easy->easy_handle->wildcard;
if(easy->easy_handle->set.wildcardmatch) {
if(!wc->filelist) {
CURLcode ret = Curl_wildcard_init(wc); /* init wildcard structures */
if(ret)
return CURLM_OUT_OF_MEMORY;
}
}
do
result = multi_runsingle(multi, easy);
while (CURLM_CALL_MULTI_PERFORM == result);
if(easy->easy_handle->set.wildcardmatch) {
/* destruct wildcard structures if it is needed */
if(wc->state == CURLWC_DONE || result)
Curl_wildcard_dtor(wc);
}
if(result)
returncode = result;
@@ -1757,11 +1793,12 @@ static void singlesocket(struct Curl_multi *multi,
return;
}
/* we know (entry != NULL) at this point, see the logic above */
multi->socket_cb(easy->easy_handle,
s,
action,
multi->socket_userp,
entry ? entry->socketp : NULL);
entry->socketp);
entry->action = action; /* store the current action state */
}
@@ -1958,9 +1995,11 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
extracts a matching node if there is one */
now = Curl_tvnow();
now.tv_usec += 1000; /* to compensate for the truncating of 999us to 0ms,
we always add time here to make the comparison
below better */
now.tv_usec += 40000; /* compensate for bad precision timers */
if(now.tv_usec > 1000000) {
now.tv_sec++;
now.tv_usec -= 1000000;
}
multi->timetree = Curl_splaygetbest(now, multi->timetree, &t);
if(t) {

192
lib/nss.c
View File

@@ -63,6 +63,7 @@
#include <secport.h>
#include <certdb.h>
#include <base64.h>
#include <cert.h>
#include "curl_memory.h"
#include "rawstr.h"
@@ -79,6 +80,7 @@
PRFileDesc *PR_ImportTCPSocket(PRInt32 osfd);
PRLock * nss_initlock = NULL;
PRLock * nss_crllock = NULL;
volatile int initialized = 0;
@@ -411,78 +413,90 @@ static int nss_load_cert(struct ssl_connect_data *ssl,
return 1;
}
static int nss_load_crl(const char* crlfilename, PRBool ascii)
/* add given CRL to cache if it is not already there */
static SECStatus nss_cache_crl(SECItem *crlDER)
{
CERTCertDBHandle *db = CERT_GetDefaultCertDB();
CERTSignedCrl *crl = SEC_FindCrlByDERCert(db, crlDER, 0);
if(crl) {
/* CRL already cached */
SEC_DestroyCrl(crl);
SECITEM_FreeItem(crlDER, PR_FALSE);
return SECSuccess;
}
/* acquire lock before call of CERT_CacheCRL() */
PR_Lock(nss_crllock);
if(SECSuccess != CERT_CacheCRL(db, crlDER)) {
/* unable to cache CRL */
PR_Unlock(nss_crllock);
SECITEM_FreeItem(crlDER, PR_FALSE);
return SECFailure;
}
/* we need to clear session cache, so that the CRL could take effect */
SSL_ClearSessionCache();
PR_Unlock(nss_crllock);
return SECSuccess;
}
static SECStatus nss_load_crl(const char* crlfilename)
{
PRFileDesc *infile;
PRStatus prstat;
PRFileInfo info;
PRInt32 nb;
int rv;
SECItem crlDER;
CERTSignedCrl *crl=NULL;
PK11SlotInfo *slot=NULL;
SECItem filedata = { 0, NULL, 0 };
SECItem crlDER = { 0, NULL, 0 };
char *body;
infile = PR_Open(crlfilename,PR_RDONLY,0);
if (!infile) {
return 0;
}
crlDER.data = NULL;
prstat = PR_GetOpenFileInfo(infile,&info);
if (prstat!=PR_SUCCESS)
return 0;
if (ascii) {
SECItem filedata;
char *asc,*body;
filedata.data = NULL;
if (!SECITEM_AllocItem(NULL,&filedata,info.size))
return 0;
nb = PR_Read(infile,filedata.data,info.size);
if (nb!=info.size)
return 0;
asc = (char*)filedata.data;
if (!asc)
return 0;
infile = PR_Open(crlfilename, PR_RDONLY, 0);
if(!infile)
return SECFailure;
body=strstr(asc,"-----BEGIN");
if (body != NULL) {
char *trailer=NULL;
asc = body;
body = PORT_Strchr(asc,'\n');
if (!body)
body = PORT_Strchr(asc,'\r');
if (body)
trailer = strstr(++body,"-----END");
if (trailer!=NULL)
*trailer='\0';
else
return 0;
}
else {
body = asc;
}
rv = ATOB_ConvertAsciiToItem(&crlDER,body);
PORT_Free(filedata.data);
if (rv)
return 0;
}
else {
if (!SECITEM_AllocItem(NULL,&crlDER,info.size))
return 0;
nb = PR_Read(infile,crlDER.data,info.size);
if (nb!=info.size)
return 0;
}
if(PR_SUCCESS != PR_GetOpenFileInfo(infile, &info))
goto fail;
slot = PK11_GetInternalKeySlot();
crl = PK11_ImportCRL(slot,&crlDER,
NULL,SEC_CRL_TYPE,
NULL,CRL_IMPORT_DEFAULT_OPTIONS,
NULL,(CRL_DECODE_DEFAULT_OPTIONS|
CRL_DECODE_DONT_COPY_DER));
if (slot) PK11_FreeSlot(slot);
if (!crl) return 0;
SEC_DestroyCrl(crl);
return 1;
if(!SECITEM_AllocItem(NULL, &filedata, info.size + /* zero ended */ 1))
goto fail;
if(info.size != PR_Read(infile, filedata.data, info.size))
goto fail;
/* place a trailing zero right after the visible data */
body = (char*)filedata.data;
body[--filedata.len] = '\0';
body = strstr(body, "-----BEGIN");
if(body) {
/* assume ASCII */
char *trailer;
char *begin = PORT_Strchr(body, '\n');
if(!begin)
begin = PORT_Strchr(body, '\r');
if(!begin)
goto fail;
trailer = strstr(++begin, "-----END");
if(!trailer)
goto fail;
/* retrieve DER from ASCII */
*trailer = '\0';
if(ATOB_ConvertAsciiToItem(&crlDER, begin))
goto fail;
SECITEM_FreeItem(&filedata, PR_FALSE);
}
else
/* assume DER */
crlDER = filedata;
PR_Close(infile);
return nss_cache_crl(&crlDER);
fail:
PR_Close(infile);
SECITEM_FreeItem(&filedata, PR_FALSE);
return SECFailure;
}
static int nss_load_key(struct connectdata *conn, int sockindex,
@@ -889,6 +903,7 @@ int Curl_nss_init(void)
if (nss_initlock == NULL) {
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
}
/* We will actually initialize NSS later */
@@ -918,6 +933,7 @@ void Curl_nss_cleanup(void)
PR_Unlock(nss_initlock);
PR_DestroyLock(nss_initlock);
PR_DestroyLock(nss_crllock);
nss_initlock = NULL;
initialized = 0;
@@ -1010,6 +1026,9 @@ static bool handle_cc_error(PRInt32 err, struct SessionHandle *data)
}
}
static Curl_recv nss_recv;
static Curl_send nss_send;
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{
PRInt32 err;
@@ -1025,6 +1044,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
int curlerr;
const int *cipher_to_enable;
PRSocketOptionData sock_opt;
long time_left;
PRUint32 timeout;
curlerr = CURLE_SSL_CONNECT_ERROR;
@@ -1243,8 +1263,7 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
data->set.ssl.CApath ? data->set.ssl.CApath : "none");
if (data->set.ssl.CRLfile) {
int rc = nss_load_crl(data->set.ssl.CRLfile, PR_FALSE);
if (!rc) {
if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) {
curlerr = CURLE_SSL_CRL_BADFILE;
goto error;
}
@@ -1302,8 +1321,15 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
SSL_SetURL(connssl->handle, conn->host.name);
/* check timeout situation */
time_left = Curl_timeleft(conn, NULL, TRUE);
if(time_left < 0L) {
failf(data, "timed out before SSL handshake");
goto error;
}
timeout = PR_MillisecondsToInterval((PRUint32) time_left);
/* Force the handshake now */
timeout = PR_MillisecondsToInterval((PRUint32)Curl_timeleft(conn, NULL, TRUE));
if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
curlerr = CURLE_PEER_FAILED_VERIFICATION;
@@ -1313,6 +1339,8 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
}
connssl->state = ssl_connection_complete;
conn->recv[sockindex] = nss_recv;
conn->send[sockindex] = nss_send;
display_conn_info(conn, connssl->handle);
@@ -1365,12 +1393,11 @@ CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
return curlerr;
}
/* for documentation see Curl_ssl_send() in sslgen.h */
int Curl_nss_send(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
const void *mem, /* send this data */
size_t len, /* amount to write */
int *curlcode)
static ssize_t nss_send(struct connectdata *conn, /* connection data */
int sockindex, /* socketindex */
const void *mem, /* send this data */
size_t len, /* amount to write */
CURLcode *curlcode)
{
int rc;
@@ -1379,7 +1406,7 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
if(rc < 0) {
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
else if(handle_cc_error(err, conn->data))
*curlcode = CURLE_SSL_CERTPROBLEM;
else {
@@ -1391,12 +1418,11 @@ int Curl_nss_send(struct connectdata *conn, /* connection data */
return rc; /* number of bytes */
}
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
int *curlcode)
static ssize_t nss_recv(struct connectdata * conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
CURLcode *curlcode)
{
ssize_t nread;
@@ -1406,7 +1432,7 @@ ssize_t Curl_nss_recv(struct connectdata * conn, /* connection data */
PRInt32 err = PR_GetError();
if(err == PR_WOULD_BLOCK_ERROR)
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
else if(handle_cc_error(err, conn->data))
*curlcode = CURLE_SSL_CERTPROBLEM;
else {

View File

@@ -42,20 +42,6 @@ int Curl_nss_close_all(struct SessionHandle *data);
int Curl_nss_init(void);
void Curl_nss_cleanup(void);
/* for documentation see Curl_ssl_send() in sslgen.h */
int Curl_nss_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
int *curlcode);
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_nss_recv(struct connectdata *conn, /* connection data */
int num, /* socketindex */
char *buf, /* store read data here */
size_t buffersize, /* max amount to read */
int *curlcode);
size_t Curl_nss_version(char *buffer, size_t size);
int Curl_nss_check_cxn(struct connectdata *cxn);
int Curl_nss_seed(struct SessionHandle *data);
@@ -74,8 +60,6 @@ int Curl_nss_seed(struct SessionHandle *data);
#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
#define curlssl_send Curl_nss_send
#define curlssl_recv Curl_nss_recv
#define curlssl_version Curl_nss_version
#define curlssl_check_cxn(x) Curl_nss_check_cxn(x)
#define curlssl_data_pending(x,y) (x=x, y=y, 0)

605
lib/openldap.c Normal file
View File

@@ -0,0 +1,605 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Howard Chu, <hyc@openldap.org>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
#include "setup.h"
#if !defined(CURL_DISABLE_LDAP) && defined(USE_OPENLDAP)
/*
* Notice that USE_OPENLDAP is only a source code selection switch. When
* libcurl is built with USE_OPENLDAP defined the libcurl source code that
* gets compiled is the code from openldap.c, otherwise the code that gets
* compiled is the code from ldap.c.
*
* When USE_OPENLDAP is defined a recent version of the OpenLDAP library
* might be required for compilation and runtime. In order to use ancient
* OpenLDAP library versions, USE_OPENLDAP shall not be defined.
*/
#include <ldap.h>
#include "urldata.h"
#include <curl/curl.h>
#include "sendf.h"
#include "sslgen.h"
#include "transfer.h"
#include "curl_ldap.h"
#include "curl_memory.h"
#include "curl_base64.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "memdebug.h"
#ifndef _LDAP_PVT_H
extern int ldap_pvt_url_scheme2proto(const char *);
extern int ldap_init_fd(ber_socket_t fd, int proto, const char *url, LDAP **ld);
#endif
static CURLcode ldap_setup(struct connectdata *conn);
static CURLcode ldap_do(struct connectdata *conn, bool *done);
static CURLcode ldap_done(struct connectdata *conn, CURLcode, bool);
static CURLcode ldap_connect(struct connectdata *conn, bool *done);
static CURLcode ldap_connecting(struct connectdata *conn, bool *done);
static CURLcode ldap_disconnect(struct connectdata *conn);
static Curl_recv ldap_recv;
/*
* LDAP protocol handler.
*/
const struct Curl_handler Curl_handler_ldap = {
"LDAP", /* scheme */
ldap_setup, /* setup_connection */
ldap_do, /* do_it */
ldap_done, /* done */
ZERO_NULL, /* do_more */
ldap_connect, /* connect_it */
ldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
ldap_disconnect, /* disconnect */
PORT_LDAP, /* defport */
PROT_LDAP /* protocol */
};
#ifdef USE_SSL
/*
* LDAPS protocol handler.
*/
const struct Curl_handler Curl_handler_ldaps = {
"LDAPS", /* scheme */
ldap_setup, /* setup_connection */
ldap_do, /* do_it */
ldap_done, /* done */
ZERO_NULL, /* do_more */
ldap_connect, /* connect_it */
ldap_connecting, /* connecting */
ZERO_NULL, /* doing */
ZERO_NULL, /* proto_getsock */
ZERO_NULL, /* doing_getsock */
ZERO_NULL, /* perform_getsock */
ldap_disconnect, /* disconnect */
PORT_LDAPS, /* defport */
PROT_LDAP | PROT_SSL /* protocol */
};
#endif
static const char *url_errs[] = {
"success",
"out of memory",
"bad parameter",
"unrecognized scheme",
"unbalanced delimiter",
"bad URL",
"bad host or port",
"bad or missing attributes",
"bad or missing scope",
"bad or missing filter",
"bad or missing extensions"
};
typedef struct ldapconninfo {
LDAP *ld;
Curl_recv *recv; /* for stacking SSL handler */
Curl_send *send;
int proto;
int msgid;
bool ssldone;
bool sslinst;
bool didbind;
} ldapconninfo;
typedef struct ldapreqinfo {
int msgid;
int nument;
} ldapreqinfo;
static CURLcode ldap_setup(struct connectdata *conn)
{
ldapconninfo *li;
LDAPURLDesc *lud;
struct SessionHandle *data=conn->data;
int rc, proto;
CURLcode status;
rc = ldap_url_parse(data->change.url, &lud);
if (rc != LDAP_URL_SUCCESS) {
const char *msg = "url parsing problem";
status = CURLE_URL_MALFORMAT;
if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
if (rc == LDAP_URL_ERR_MEM)
status = CURLE_OUT_OF_MEMORY;
msg = url_errs[rc];
}
failf(conn->data, "LDAP local: %s", msg);
return status;
}
proto = ldap_pvt_url_scheme2proto(lud->lud_scheme);
ldap_free_urldesc(lud);
li = calloc(1, sizeof(ldapconninfo));
li->proto = proto;
conn->proto.generic = li;
/* TODO:
* - provide option to choose SASL Binds instead of Simple
*/
return CURLE_OK;
}
#ifdef USE_SSL
static Sockbuf_IO ldapsb_tls;
#endif
static CURLcode ldap_connect(struct connectdata *conn, bool *done)
{
ldapconninfo *li = conn->proto.generic;
struct SessionHandle *data=conn->data;
int rc, proto = LDAP_VERSION3;
char hosturl[1024], *ptr;
strcpy(hosturl, "ldap");
ptr = hosturl+4;
if (conn->protocol & PROT_SSL)
*ptr++ = 's';
snprintf(ptr, sizeof(hosturl)-(ptr-hosturl), "://%s:%d",
conn->host.name, conn->port);
rc = ldap_init_fd(conn->sock[FIRSTSOCKET], li->proto, hosturl, &li->ld);
if (rc) {
failf(data, "LDAP local: Cannot connect to %s, %s",
hosturl, ldap_err2string(rc));
return CURLE_COULDNT_CONNECT;
}
ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
#ifdef USE_SSL
if (conn->protocol & PROT_SSL) {
CURLcode res;
if (data->state.used_interface == Curl_if_easy) {
res = Curl_ssl_connect(conn, FIRSTSOCKET);
if (res)
return res;
li->ssldone = TRUE;
} else {
res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
if (res)
return res;
}
}
#endif
if (data->state.used_interface == Curl_if_easy)
return ldap_connecting(conn, done);
return CURLE_OK;
}
static CURLcode ldap_connecting(struct connectdata *conn, bool *done)
{
ldapconninfo *li = conn->proto.generic;
struct SessionHandle *data=conn->data;
LDAPMessage *result = NULL;
struct timeval tv = {0,1}, *tvp;
int rc, err;
char *info = NULL;
#ifdef USE_SSL
if (conn->protocol & PROT_SSL) {
/* Is the SSL handshake complete yet? */
if (!li->ssldone) {
CURLcode res = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &li->ssldone);
if (res || !li->ssldone)
return res;
}
/* Have we installed the libcurl SSL handlers into the sockbuf yet? */
if (!li->sslinst) {
Sockbuf *sb;
ldap_get_option(li->ld, LDAP_OPT_SOCKBUF, &sb);
ber_sockbuf_add_io(sb, &ldapsb_tls, LBER_SBIOD_LEVEL_TRANSPORT, conn);
li->sslinst = TRUE;
li->recv = conn->recv[FIRSTSOCKET];
li->send = conn->send[FIRSTSOCKET];
}
}
#endif
if (data->state.used_interface == Curl_if_easy)
tvp = NULL; /* let ldap_result block indefinitely */
else
tvp = &tv;
retry:
if (!li->didbind) {
char *binddn;
struct berval passwd;
if (conn->bits.user_passwd) {
binddn = conn->user;
passwd.bv_val = conn->passwd;
passwd.bv_len = strlen(passwd.bv_val);
} else {
binddn = NULL;
passwd.bv_val = NULL;
passwd.bv_len = 0;
}
rc = ldap_sasl_bind(li->ld, binddn, LDAP_SASL_SIMPLE, &passwd,
NULL, NULL, &li->msgid);
if (rc)
return CURLE_LDAP_CANNOT_BIND;
li->didbind = TRUE;
if (tvp)
return CURLE_OK;
}
rc = ldap_result(li->ld, li->msgid, LDAP_MSG_ONE, tvp, &result);
if (rc < 0) {
failf(data, "LDAP local: bind ldap_result %s", ldap_err2string(rc));
return CURLE_LDAP_CANNOT_BIND;
}
if (rc == 0) {
/* timed out */
return CURLE_OK;
}
rc = ldap_parse_result(li->ld, result, &err, NULL, &info, NULL, NULL, 1);
if (rc) {
failf(data, "LDAP local: bind ldap_parse_result %s", ldap_err2string(rc));
return CURLE_LDAP_CANNOT_BIND;
}
/* Try to fallback to LDAPv2? */
if (err == LDAP_PROTOCOL_ERROR) {
int proto;
ldap_get_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
if (proto == LDAP_VERSION3) {
ldap_memfree(info);
proto = LDAP_VERSION2;
ldap_set_option(li->ld, LDAP_OPT_PROTOCOL_VERSION, &proto);
li->didbind = FALSE;
goto retry;
}
}
if (err) {
failf(data, "LDAP remote: bind failed %s %s", ldap_err2string(rc),
info ? info : "");
return CURLE_LOGIN_DENIED;
}
conn->recv[FIRSTSOCKET] = ldap_recv;
*done = TRUE;
return CURLE_OK;
}
static CURLcode ldap_disconnect(struct connectdata *conn)
{
ldapconninfo *li = conn->proto.generic;
if (li) {
if (li->ld) {
ldap_unbind_ext(li->ld, NULL, NULL);
li->ld = NULL;
}
conn->proto.generic = NULL;
free(li);
}
return CURLE_OK;
}
static CURLcode ldap_do(struct connectdata *conn, bool *done)
{
ldapconninfo *li = conn->proto.generic;
ldapreqinfo *lr;
CURLcode status = CURLE_OK;
int rc = 0;
LDAPURLDesc *ludp = NULL;
int msgid;
struct SessionHandle *data=conn->data;
conn->bits.close = FALSE;
infof(data, "LDAP local: %s\n", data->change.url);
rc = ldap_url_parse(data->change.url, &ludp);
if (rc != LDAP_URL_SUCCESS) {
const char *msg = "url parsing problem";
status = CURLE_URL_MALFORMAT;
if (rc > LDAP_URL_SUCCESS && rc <= LDAP_URL_ERR_BADEXTS) {
if (rc == LDAP_URL_ERR_MEM)
status = CURLE_OUT_OF_MEMORY;
msg = url_errs[rc];
}
failf(conn->data, "LDAP local: %s", msg);
return status;
}
rc = ldap_search_ext(li->ld, ludp->lud_dn, ludp->lud_scope,
ludp->lud_filter, ludp->lud_attrs, 0,
NULL, NULL, NULL, 0, &msgid);
ldap_free_urldesc(ludp);
if (rc != LDAP_SUCCESS) {
failf(data, "LDAP local: ldap_search_ext %s", ldap_err2string(rc));
return CURLE_LDAP_SEARCH_FAILED;
}
lr = calloc(1,sizeof(ldapreqinfo));
lr->msgid = msgid;
data->state.proto.generic = lr;
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, NULL, -1, NULL);
*done = TRUE;
return CURLE_OK;
}
static CURLcode ldap_done(struct connectdata *conn, CURLcode res,
bool premature)
{
ldapreqinfo *lr = conn->data->state.proto.generic;
(void)res;
(void)premature;
if (lr) {
/* if there was a search in progress, abandon it */
if (lr->msgid) {
ldapconninfo *li = conn->proto.generic;
ldap_abandon_ext(li->ld, lr->msgid, NULL, NULL);
lr->msgid = 0;
}
conn->data->state.proto.generic = NULL;
free(lr);
}
return CURLE_OK;
}
static ssize_t ldap_recv(struct connectdata *conn, int sockindex, char *buf,
size_t len, CURLcode *err)
{
ldapconninfo *li = conn->proto.generic;
struct SessionHandle *data=conn->data;
ldapreqinfo *lr = data->state.proto.generic;
int rc, ret;
LDAPMessage *result = NULL;
LDAPMessage *ent;
BerElement *ber = NULL;
struct timeval tv = {0,1};
(void)len;
(void)buf;
(void)sockindex;
rc = ldap_result(li->ld, lr->msgid, LDAP_MSG_RECEIVED, &tv, &result);
if (rc < 0) {
failf(data, "LDAP local: search ldap_result %s", ldap_err2string(rc));
*err = CURLE_RECV_ERROR;
return -1;
}
*err = CURLE_AGAIN;
ret = -1;
/* timed out */
if (result == NULL)
return ret;
for (ent = ldap_first_message(li->ld, result); ent;
ent = ldap_next_message(li->ld, ent)) {
struct berval bv, *bvals, **bvp = &bvals;
int binary = 0, msgtype;
msgtype = ldap_msgtype(ent);
if (msgtype == LDAP_RES_SEARCH_RESULT) {
int code;
char *info = NULL;
rc = ldap_parse_result(li->ld, ent, &code, NULL, &info, NULL, NULL, 0);
if (rc) {
failf(data, "LDAP local: search ldap_parse_result %s", ldap_err2string(rc));
*err = CURLE_LDAP_SEARCH_FAILED;
} else if (code && code != LDAP_SIZELIMIT_EXCEEDED) {
failf(data, "LDAP remote: search failed %s %s", ldap_err2string(rc),
info ? info : "");
*err = CURLE_LDAP_SEARCH_FAILED;
} else {
/* successful */
if (code == LDAP_SIZELIMIT_EXCEEDED)
infof(data, "There are more than %d entries\n", lr->nument);
data->req.size = data->req.bytecount;
*err = CURLE_OK;
ret = 0;
}
lr->msgid = 0;
ldap_memfree(info);
break;
} else if (msgtype != LDAP_RES_SEARCH_ENTRY) {
continue;
}
lr->nument++;
rc = ldap_get_dn_ber(li->ld, ent, &ber, &bv);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
data->req.bytecount += bv.bv_len + 5;
for (rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp);
rc == LDAP_SUCCESS;
rc = ldap_get_attribute_ber(li->ld, ent, ber, &bv, bvp)) {
int i;
if (bv.bv_val == NULL) break;
if (bv.bv_len > 7 && !strncmp(bv.bv_val + bv.bv_len - 7, ";binary", 7))
binary = 1;
for (i=0; bvals[i].bv_val != NULL; i++) {
int binval = 0;
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)bv.bv_val, bv.bv_len);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)":", 1);
data->req.bytecount += bv.bv_len + 2;
if (!binary) {
/* check for leading or trailing whitespace */
if (isspace(bvals[i].bv_val[0]) ||
isspace(bvals[i].bv_val[bvals[i].bv_len-1])) {
binval = 1;
} else {
/* check for unprintable characters */
unsigned int j;
for (j=0; j<bvals[i].bv_len; j++)
if (!isprint(bvals[i].bv_val[j])) {
binval = 1;
break;
}
}
}
if (binary || binval) {
char *val_b64;
/* Binary value, encode to base64. */
size_t val_b64_sz = Curl_base64_encode(data,
bvals[i].bv_val,
bvals[i].bv_len,
&val_b64);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
data->req.bytecount += 2;
if(val_b64_sz > 0) {
Curl_client_write(conn, CLIENTWRITE_BODY, val_b64, val_b64_sz);
free(val_b64);
data->req.bytecount += val_b64_sz;
}
} else {
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)" ", 1);
Curl_client_write(conn, CLIENTWRITE_BODY, bvals[i].bv_val,
bvals[i].bv_len);
data->req.bytecount += bvals[i].bv_len + 1;
}
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
data->req.bytecount++;
}
ber_memfree(bvals);
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
data->req.bytecount++;
}
Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
data->req.bytecount++;
ber_free(ber, 0);
}
ldap_msgfree(result);
return ret;
}
#ifdef USE_SSL
static int
ldapsb_tls_setup(Sockbuf_IO_Desc *sbiod, void *arg)
{
sbiod->sbiod_pvt = arg;
return 0;
}
static int
ldapsb_tls_remove(Sockbuf_IO_Desc *sbiod)
{
sbiod->sbiod_pvt = NULL;
return 0;
}
/* We don't need to do anything because libcurl does it already */
static int
ldapsb_tls_close(Sockbuf_IO_Desc *sbiod)
{
(void)sbiod;
return 0;
}
static int
ldapsb_tls_ctrl(Sockbuf_IO_Desc *sbiod, int opt, void *arg)
{
(void)arg;
if (opt == LBER_SB_OPT_DATA_READY) {
struct connectdata *conn = sbiod->sbiod_pvt;
return Curl_ssl_data_pending(conn, FIRSTSOCKET);
}
return 0;
}
static ber_slen_t
ldapsb_tls_read(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
struct connectdata *conn = sbiod->sbiod_pvt;
ldapconninfo *li = conn->proto.generic;
ber_slen_t ret;
CURLcode err = CURLE_RECV_ERROR;
ret = li->recv(conn, FIRSTSOCKET, buf, len, &err);
if (ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK);
}
return ret;
}
static ber_slen_t
ldapsb_tls_write(Sockbuf_IO_Desc *sbiod, void *buf, ber_len_t len)
{
struct connectdata *conn = sbiod->sbiod_pvt;
ldapconninfo *li = conn->proto.generic;
ber_slen_t ret;
CURLcode err = CURLE_SEND_ERROR;
ret = li->send(conn, FIRSTSOCKET, buf, len, &err);
if (ret < 0 && err == CURLE_AGAIN) {
SET_SOCKERRNO(EWOULDBLOCK);
}
return ret;
}
static Sockbuf_IO ldapsb_tls =
{
ldapsb_tls_setup,
ldapsb_tls_remove,
ldapsb_tls_ctrl,
ldapsb_tls_read,
ldapsb_tls_write,
ldapsb_tls_close
};
#endif /* USE_SSL */
#endif /* !CURL_DISABLE_LDAP && USE_OPENLDAP */

View File

@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -370,7 +370,6 @@ int Curl_parsedate(const char *date, time_t *output)
(3 == sscanf(date, "%02d:%02d:%02d", &hournum, &minnum, &secnum))) {
/* time stamp! */
date += 8;
found = TRUE;
}
else {
val = (int)strtol(date, &end, 10);

View File

@@ -340,8 +340,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
#if defined(HAVE_KRB4) || defined(HAVE_GSSAPI)
conn->data_prot = prot;
#endif
if(res < 0)
/* EWOULDBLOCK */
if(res == CURLE_AGAIN)
return CURLE_OK; /* return */
#ifdef CURL_DOES_CONVERSIONS

375
lib/polarssl.c Normal file
View File

@@ -0,0 +1,375 @@
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
***************************************************************************/
/*
* Source file for all PolarSSL-specific code for the TLS/SSL layer. No code
* but sslgen.c should ever call or use these functions.
*
*/
#include "setup.h"
#ifdef USE_POLARSSL
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#include <polarssl/net.h>
#include <polarssl/ssl.h>
#include <polarssl/havege.h>
#include <polarssl/certs.h>
#include <polarssl/x509.h>
#include "urldata.h"
#include "sendf.h"
#include "inet_pton.h"
#include "polarssl.h"
#include "sslgen.h"
#include "parsedate.h"
#include "connect.h" /* for the connect timeout */
#include "select.h"
#include "rawstr.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
#include "curl_memory.h"
/* The last #include file should be: */
#include "memdebug.h"
/* Define this to enable lots of debugging for PolarSSL */
#undef POLARSSL_DEBUG
#ifdef POLARSSL_DEBUG
static void polarssl_debug(void *context, int level, char *line)
{
struct SessionHandle *data = NULL;
if(!context)
return;
data = (struct SessionHandle *)context;
infof(data, "%s", line);
}
#else
#endif
static Curl_recv polarssl_recv;
static Curl_send polarssl_send;
/*
* This function loads all the client/CA certificates and CRLs. Setup the TLS
* layer and do all necessary magic.
*/
CURLcode
Curl_polarssl_connect(struct connectdata *conn,
int sockindex)
{
struct SessionHandle *data = conn->data;
bool sni = TRUE; /* default is SNI enabled */
int ret = -1;
#ifdef ENABLE_IPV6
struct in6_addr addr;
#else
struct in_addr addr;
#endif
void *old_session = NULL;
size_t old_session_size = 0;
char buffer[1024];
if(conn->ssl[sockindex].state == ssl_connection_complete)
return CURLE_OK;
/* PolarSSL only supports SSLv3 and TLSv1 */
if(data->set.ssl.version == CURL_SSLVERSION_SSLv2) {
failf(data, "PolarSSL does not support SSLv2");
return CURLE_SSL_CONNECT_ERROR;
} else if(data->set.ssl.version == CURL_SSLVERSION_SSLv3) {
sni = FALSE; /* SSLv3 has no SNI */
}
havege_init(&conn->ssl[sockindex].hs);
/* Load the trusted CA */
memset(&conn->ssl[sockindex].cacert, 0, sizeof(x509_cert));
if(data->set.str[STRING_SSL_CAFILE]) {
ret = x509parse_crtfile(&conn->ssl[sockindex].cacert,
data->set.str[STRING_SSL_CAFILE]);
if(ret) {
failf(data, "Error reading ca cert file %s: -0x%04X",
data->set.str[STRING_SSL_CAFILE], -ret);
if(data->set.ssl.verifypeer)
return CURLE_SSL_CACERT_BADFILE;
}
}
/* Load the client certificate */
memset(&conn->ssl[sockindex].clicert, 0, sizeof(x509_cert));
if(data->set.str[STRING_CERT]) {
ret = x509parse_crtfile(&conn->ssl[sockindex].clicert,
data->set.str[STRING_CERT]);
if(ret) {
failf(data, "Error reading client cert file %s: -0x%04X",
data->set.str[STRING_CERT], -ret);
return CURLE_SSL_CERTPROBLEM;
}
}
/* Load the client private key */
if(data->set.str[STRING_KEY]) {
ret = x509parse_keyfile(&conn->ssl[sockindex].rsa,
data->set.str[STRING_KEY],
data->set.str[STRING_KEY_PASSWD]);
if(ret) {
failf(data, "Error reading private key %s: -0x%04X",
data->set.str[STRING_KEY], -ret);
return CURLE_SSL_CERTPROBLEM;
}
}
/* Load the CRL */
memset(&conn->ssl[sockindex].crl, 0, sizeof(x509_crl));
if(data->set.str[STRING_SSL_CRLFILE]) {
ret = x509parse_crlfile(&conn->ssl[sockindex].crl,
data->set.str[STRING_SSL_CRLFILE]);
if(ret) {
failf(data, "Error reading CRL file %s: -0x%04X",
data->set.str[STRING_SSL_CRLFILE], -ret);
return CURLE_SSL_CRL_BADFILE;
}
}
infof(data, "PolarSSL: Connected to %s:%d\n",
conn->host.name, conn->remote_port);
havege_init(&conn->ssl[sockindex].hs);
if(ssl_init(&conn->ssl[sockindex].ssl)) {
failf(data, "PolarSSL: ssl_init failed");
return CURLE_SSL_CONNECT_ERROR;
}
ssl_set_endpoint(&conn->ssl[sockindex].ssl, SSL_IS_CLIENT);
ssl_set_authmode(&conn->ssl[sockindex].ssl, SSL_VERIFY_OPTIONAL);
ssl_set_rng(&conn->ssl[sockindex].ssl, havege_rand,
&conn->ssl[sockindex].hs);
ssl_set_bio(&conn->ssl[sockindex].ssl,
net_recv, &conn->sock[sockindex],
net_send, &conn->sock[sockindex]);
ssl_set_ciphers(&conn->ssl[sockindex].ssl, ssl_default_ciphers);
if(!Curl_ssl_getsessionid(conn, &old_session, &old_session_size)) {
memcpy(&conn->ssl[sockindex].ssn, old_session, old_session_size);
infof(data, "PolarSSL re-using session\n");
}
ssl_set_session(&conn->ssl[sockindex].ssl, 1, 600,
&conn->ssl[sockindex].ssn);
ssl_set_ca_chain(&conn->ssl[sockindex].ssl,
&conn->ssl[sockindex].cacert,
&conn->ssl[sockindex].crl,
conn->host.name);
ssl_set_own_cert(&conn->ssl[sockindex].ssl,
&conn->ssl[sockindex].clicert, &conn->ssl[sockindex].rsa);
if(!Curl_inet_pton(AF_INET, conn->host.name, &addr) &&
#ifdef ENABLE_IPV6
!Curl_inet_pton(AF_INET6, conn->host.name, &addr) &&
#endif
sni && ssl_set_hostname(&conn->ssl[sockindex].ssl, conn->host.name)) {
infof(data, "WARNING: failed to configure "
"server name indication (SNI) TLS extension\n");
}
infof(data, "PolarSSL: performing SSL/TLS handshake...\n");
#ifdef POLARSSL_DEBUG
ssl_set_dbg(&conn->ssl[sockindex].ssl, polarssl_debug, data);
#endif
do {
if (!(ret = ssl_handshake(&conn->ssl[sockindex].ssl))) {
break;
} else if(ret != POLARSSL_ERR_NET_TRY_AGAIN) {
failf(data, "ssl_handshake returned -0x%04X", -ret);
return CURLE_SSL_CONNECT_ERROR;
} else {
/* wait for data from server... */
long timeout_ms = Curl_timeleft(conn, NULL, TRUE);
if(timeout_ms < 0) {
failf(data, "SSL connection timeout");
return CURLE_OPERATION_TIMEDOUT;
}
switch(Curl_socket_ready(conn->sock[sockindex],
CURL_SOCKET_BAD, timeout_ms)) {
case 0:
failf(data, "SSL handshake timeout");
return CURLE_OPERATION_TIMEDOUT;
break;
case CURL_CSELECT_IN:
continue;
break;
default:
return CURLE_SSL_CONNECT_ERROR;
break;
}
}
} while (1);
infof(data, "PolarSSL: Handshake complete, cipher is %s\n",
ssl_get_cipher(&conn->ssl[sockindex].ssl));
ret = ssl_get_verify_result(&conn->ssl[sockindex].ssl);
if(ret && data->set.ssl.verifypeer) {
if(ret & BADCERT_EXPIRED)
failf(data, "Cert verify failed: BADCERT_EXPIRED\n");
if(ret & BADCERT_REVOKED)
failf(data, "Cert verify failed: BADCERT_REVOKED");
if(ret & BADCERT_CN_MISMATCH)
failf(data, "Cert verify failed: BADCERT_CN_MISMATCH");
if(ret & BADCERT_NOT_TRUSTED)
failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED");
return CURLE_SSL_CACERT;
}
if(conn->ssl[sockindex].ssl.peer_cert) {
/* If the session was resumed, there will be no peer certs */
memset(buffer, 0, sizeof(buffer));
if(x509parse_cert_info(buffer, sizeof(buffer), (char *)"* ",
conn->ssl[sockindex].ssl.peer_cert) != -1)
infof(data, "Dumping cert info:\n%s\n", buffer);
}
conn->ssl[sockindex].state = ssl_connection_complete;
conn->recv[sockindex] = polarssl_recv;
conn->send[sockindex] = polarssl_send;
/* Save the current session data for possible re-use */
{
void *new_session = malloc(sizeof(conn->ssl[sockindex].ssn));
if(new_session) {
memcpy(new_session, &conn->ssl[sockindex].ssn,
sizeof(conn->ssl[sockindex].ssn));
if(old_session)
Curl_ssl_delsessionid(conn, old_session);
return Curl_ssl_addsessionid(conn, new_session,
sizeof(conn->ssl[sockindex].ssn));
}
}
return CURLE_OK;
}
static ssize_t polarssl_send(struct connectdata *conn,
int sockindex,
const void *mem,
size_t len,
CURLcode *curlcode)
{
int ret = -1;
ret = ssl_write(&conn->ssl[sockindex].ssl,
(unsigned char *)mem, len);
if(ret < 0) {
*curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ?
CURLE_AGAIN : CURLE_SEND_ERROR;
ret = -1;
}
return ret;
}
void Curl_polarssl_close_all(struct SessionHandle *data)
{
(void)data;
}
void Curl_polarssl_close(struct connectdata *conn, int sockindex)
{
rsa_free(&conn->ssl[sockindex].rsa);
x509_free(&conn->ssl[sockindex].clicert);
x509_free(&conn->ssl[sockindex].cacert);
x509_crl_free(&conn->ssl[sockindex].crl);
ssl_free(&conn->ssl[sockindex].ssl);
}
static ssize_t polarssl_recv(struct connectdata *conn,
int num,
char *buf,
size_t buffersize,
CURLcode *curlcode)
{
int ret = -1;
ssize_t len = -1;
memset(buf, 0, buffersize);
ret = ssl_read(&conn->ssl[num].ssl, (unsigned char *)buf, buffersize);
if(ret <= 0) {
*curlcode = (ret == POLARSSL_ERR_NET_TRY_AGAIN) ?
CURLE_AGAIN : CURLE_RECV_ERROR;
return -1;
}
len = ret;
return len;
}
void Curl_polarssl_session_free(void *ptr)
{
free(ptr);
}
size_t Curl_polarssl_version(char *buffer, size_t size)
{
return snprintf(buffer, size, "PolarSSL");
}
#endif

57
lib/polarssl.h Normal file
View File

@@ -0,0 +1,57 @@
#ifndef HEADER_CURL_POLARSSL_H
#define HEADER_CURL_POLARSSL_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 2010, Hoi-Ho Chan, <hoiho.chan@gmail.com>
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: polarssl.h,v 1.10 2009-02-12 20:48:43 danf Exp $
***************************************************************************/
#ifdef USE_POLARSSL
CURLcode Curl_polarssl_connect(struct connectdata *conn, int sockindex);
/* tell PolarSSL to close down all open information regarding connections (and
thus session ID caching etc) */
void Curl_polarssl_close_all(struct SessionHandle *data);
/* close a SSL connection */
void Curl_polarssl_close(struct connectdata *conn, int sockindex);
void Curl_polarssl_session_free(void *ptr);
size_t Curl_polarssl_version(char *buffer, size_t size);
int Curl_polarssl_shutdown(struct connectdata *conn, int sockindex);
/* API setup for PolarSSL */
#define curlssl_init() (1)
#define curlssl_cleanup()
#define curlssl_connect Curl_polarssl_connect
#define curlssl_session_free(x) Curl_polarssl_session_free(x)
#define curlssl_close_all Curl_polarssl_close_all
#define curlssl_close Curl_polarssl_close
#define curlssl_shutdown(x,y) 0
#define curlssl_set_engine(x,y) (x=x, y=y, CURLE_FAILED_INIT)
#define curlssl_set_engine_default(x) (x=x, CURLE_FAILED_INIT)
#define curlssl_engines_list(x) (x=x, (struct curl_slist *)NULL)
#define curlssl_version Curl_polarssl_version
#define curlssl_check_cxn(x) (x=x, -1)
#define curlssl_data_pending(x,y) (x=x, y=y, 0)
#endif /* USE_POLARSSL */
#endif /* HEADER_CURL_POLARSSL_H */

View File

@@ -311,10 +311,10 @@ static CURLcode pop3_state_user_resp(struct connectdata *conn,
failf(data, "Access denied. %c", pop3code);
result = CURLE_LOGIN_DENIED;
}
/* send PASS */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
pop3->passwd?pop3->passwd:"");
else
/* send PASS */
result = Curl_pp_sendf(&conn->proto.pop3c.pp, "PASS %s",
pop3->passwd?pop3->passwd:"");
if(result)
return result;
@@ -359,9 +359,8 @@ static CURLcode pop3_state_retr_resp(struct connectdata *conn,
}
/* POP3 download */
result=Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE,
pop3->bytecountp,
-1, NULL); /* no upload here */
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE,
pop3->bytecountp, -1, NULL); /* no upload here */
if(pp->cache) {
/* At this point there is a bunch of data in the header "cache" that is
@@ -403,9 +402,8 @@ static CURLcode pop3_state_list_resp(struct connectdata *conn,
}
/* POP3 download */
result=Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE,
pop3->bytecountp,
-1, NULL); /* no upload here */
Curl_setup_transfer(conn, FIRSTSOCKET, -1, FALSE, pop3->bytecountp,
-1, NULL); /* no upload here */
if(pp->cache) {
/* cache holds the email ID listing */
@@ -830,7 +828,8 @@ static CURLcode pop3_disconnect(struct connectdata *conn)
/* The POP3 session may or may not have been allocated/setup at this
point! */
(void)pop3_quit(conn); /* ignore errors on the LOGOUT */
if(pop3c->pp.conn)
(void)pop3_quit(conn); /* ignore errors on the LOGOUT */
Curl_pp_disconnect(&pop3c->pp);
@@ -851,10 +850,11 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
struct pop3_conn *pop3c = &conn->proto.pop3c;
struct SessionHandle *data = conn->data;
const char *path = data->state.path;
int len;
/* url decode the path and use this mailbox */
pop3c->mailbox = curl_easy_unescape(data, path, 0, &len);
pop3c->mailbox = curl_easy_unescape(data, path, 0, NULL);
if (!pop3c->mailbox)
return CURLE_OUT_OF_MEMORY;
return CURLE_OK;
}
@@ -863,18 +863,17 @@ static CURLcode pop3_parse_url_path(struct connectdata *conn)
static CURLcode pop3_dophase_done(struct connectdata *conn,
bool connected)
{
CURLcode result = CURLE_OK;
struct FTP *pop3 = conn->data->state.proto.pop3;
struct pop3_conn *pop3c = &conn->proto.pop3c;
(void)connected;
(void)connected;
if(pop3->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
free(pop3c->mailbox);
return result;
return CURLE_OK;
}
/* called from multi.c while DOing */

View File

@@ -242,6 +242,9 @@ static CURLcode Curl_qsossl_handshake(struct connectdata * conn, int sockindex)
}
static Curl_recv qsossl_recv;
static Curl_send qsossl_send;
CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
{
@@ -263,8 +266,11 @@ CURLcode Curl_qsossl_connect(struct connectdata * conn, int sockindex)
connssl->state = ssl_connection_none;
}
}
if (rc == CURLE_OK)
if (rc == CURLE_OK) {
connssl->state = ssl_connection_complete;
conn->recv[sockindex] = qsossl_recv;
conn->send[sockindex] = qsossl_send;
}
return rc;
}
@@ -374,9 +380,8 @@ int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex)
}
/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex,
const void * mem, size_t len, int * curlcode)
static ssize_t qsossl_send(struct connectdata * conn, int sockindex,
const void * mem, size_t len, CURLcode * curlcode)
{
/* SSL_Write() is said to return 'int' while write() and send() returns
@@ -392,14 +397,14 @@ ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex,
/* The operation did not complete; the same SSL I/O function
should be called again later. This is basicly an EWOULDBLOCK
equivalent. */
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
case SSL_ERROR_IO:
switch (errno) {
case EWOULDBLOCK:
case EINTR:
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
}
@@ -419,9 +424,8 @@ ssize_t Curl_qsossl_send(struct connectdata * conn, int sockindex,
}
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf,
size_t buffersize, int * curlcode)
static ssize_t qsossl_recv(struct connectdata * conn, int num, char * buf,
size_t buffersize, CURLcode * curlcode)
{
char error_buffer[120]; /* OpenSSL documents that this must be at
@@ -440,13 +444,13 @@ ssize_t Curl_qsossl_recv(struct connectdata * conn, int num, char * buf,
case SSL_ERROR_BAD_STATE:
/* there's data pending, re-invoke SSL_Read(). */
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
case SSL_ERROR_IO:
switch (errno) {
case EWOULDBLOCK:
*curlcode = -1; /* EWOULDBLOCK */
*curlcode = CURLE_AGAIN;
return -1;
}

View File

@@ -36,20 +36,6 @@ void Curl_qsossl_close(struct connectdata *conn, int sockindex);
int Curl_qsossl_close_all(struct SessionHandle * data);
int Curl_qsossl_shutdown(struct connectdata * conn, int sockindex);
/* for documentation see Curl_ssl_send() in sslgen.h */
ssize_t Curl_qsossl_send(struct connectdata * conn,
int sockindex,
const void * mem,
size_t len,
int * curlcode);
/* for documentation see Curl_ssl_recv() in sslgen.h */
ssize_t Curl_qsossl_recv(struct connectdata * conn, /* connection data */
int num, /* socketindex */
char * buf, /* store read data here */
size_t buffersize, /* max amount to read */
int * curlcode);
size_t Curl_qsossl_version(char * buffer, size_t size);
int Curl_qsossl_check_cxn(struct connectdata * cxn);
@@ -66,8 +52,6 @@ int Curl_qsossl_check_cxn(struct connectdata * cxn);
#define curlssl_set_engine(x,y) CURLE_FAILED_INIT
#define curlssl_set_engine_default(x) CURLE_FAILED_INIT
#define curlssl_engines_list(x) NULL
#define curlssl_send Curl_qsossl_send
#define curlssl_recv Curl_qsossl_recv
#define curlssl_version Curl_qsossl_version
#define curlssl_check_cxn(x) Curl_qsossl_check_cxn(x)
#define curlssl_data_pending(x,y) 0

View File

@@ -254,8 +254,8 @@ CURLcode Curl_rtsp(struct connectdata *conn, bool *done)
}
if(rtspreq == RTSPREQ_RECEIVE) {
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, -1, NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount, -1, NULL);
return result;
}
@@ -503,15 +503,9 @@ CURLcode Curl_rtsp(struct connectdata *conn, bool *done)
return result;
}
result = Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE,
&http->readbytecount,
putsize?FIRSTSOCKET:-1,
putsize?&http->writebytecount:NULL);
if(result) {
failf(data, "Failed RTSP transfer");
return result;
}
Curl_setup_transfer(conn, FIRSTSOCKET, -1, TRUE, &http->readbytecount,
putsize?FIRSTSOCKET:-1,
putsize?&http->writebytecount:NULL);
/* Increment the CSeq on success */
data->state.rtsp_next_client_CSeq++;

View File

@@ -10,7 +10,7 @@
* Copyright (c) 1998, 1999 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
*
* Copyright (C) 2001 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 2001 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* All rights reserved.
*
@@ -101,20 +101,6 @@ static const struct Curl_sec_client_mech * const mechs[] = {
NULL
};
/* TODO: This function isn't actually used anywhere and should be removed */
int
Curl_sec_getc(struct connectdata *conn, FILE *F)
{
if(conn->sec_complete && conn->data_prot) {
char c;
if(Curl_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)
{
@@ -189,35 +175,16 @@ buffer_read(struct krb4buffer *buf, void *data, size_t 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
Curl_sec_read(struct connectdata *conn, int fd, void *buffer, int length)
static ssize_t sec_read(struct connectdata *conn, int num,
char *buffer, size_t length, CURLcode *err)
{
size_t len;
int rx = 0;
curl_socket_t fd = conn->sock[num];
if(conn->sec_complete == 0 || conn->data_prot == 0)
return read(fd, buffer, length);
*err = CURLE_OK;
if(conn->in_buffer.eof_flag){
if(conn->in_buffer.eof_flag) {
conn->in_buffer.eof_flag = 0;
return 0;
}
@@ -284,29 +251,12 @@ sec_send(struct connectdata *conn, int fd, const char *from, int length)
return length;
}
int
Curl_sec_fflush_fd(struct connectdata *conn, int fd)
{
if(conn->data_prot != prot_clear) {
if(conn->out_buffer.index > 0){
Curl_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
Curl_sec_write(struct connectdata *conn, int fd, const char *buffer, int length)
static ssize_t sec_write(struct connectdata *conn, int fd,
const char *buffer, int length)
{
int len = conn->buffer_size;
int tx = 0;
if(conn->data_prot == prot_clear)
return write(fd, buffer, length);
len -= (conn->mech->overhead)(conn->app_data, conn->data_prot, len);
if(len <= 0)
len = length;
@@ -321,27 +271,25 @@ Curl_sec_write(struct connectdata *conn, int fd, const char *buffer, int length)
return tx;
}
ssize_t
Curl_sec_send(struct connectdata *conn, int num, const char *buffer, int length)
int
Curl_sec_fflush_fd(struct connectdata *conn, int fd)
{
curl_socket_t fd = conn->sock[num];
return (ssize_t)Curl_sec_write(conn, fd, buffer, length);
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
Curl_sec_putc(struct connectdata *conn, int c, FILE *F)
static ssize_t _sec_send(struct connectdata *conn, int num,
const void *buffer, size_t length, CURLcode *err)
{
char ch = (char)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 */) {
Curl_sec_write(conn, fileno(F), conn->out_buffer.data,
conn->out_buffer.index);
conn->out_buffer.index = 0;
}
return c;
curl_socket_t fd = conn->sock[num];
*err = CURLE_OK;
return sec_write(conn, fd, buffer, length);
}
int
@@ -517,6 +465,12 @@ Curl_sec_login(struct connectdata *conn)
}
conn->mech = *m;
conn->sec_complete = 1;
if (conn->data_prot != prot_clear) {
conn->recv[FIRSTSOCKET] = sec_read;
conn->send[FIRSTSOCKET] = _sec_send;
conn->recv[SECONDARYSOCKET] = sec_read;
conn->send[SECONDARYSOCKET] = _sec_send;
}
conn->command_prot = prot_safe;
/* Set the requested protection level */
/* BLOCKING */

View File

@@ -234,14 +234,53 @@ CURLcode Curl_sendf(curl_socket_t sockfd, struct connectdata *conn,
return res;
}
static ssize_t send_plain(struct connectdata *conn,
int num,
const void *mem,
size_t len)
/*
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
*
* If the write would block (CURLE_AGAIN), we return CURLE_OK and
* (*written == 0). Otherwise we return regular CURLcode value.
*/
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
const void *mem,
size_t len,
ssize_t *written)
{
ssize_t bytes_written;
CURLcode curlcode = CURLE_OK;
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
bytes_written = conn->send[num](conn, num, mem, len, &curlcode);
*written = bytes_written;
if(-1 != bytes_written)
/* we completely ignore the curlcode value when -1 is not returned */
return CURLE_OK;
/* handle CURLE_AGAIN or a send failure */
switch(curlcode) {
case CURLE_AGAIN:
*written = 0;
return CURLE_OK;
case CURLE_OK:
/* general send failure */
return CURLE_SEND_ERROR;
default:
/* we got a specific curlcode, forward it */
return (CURLcode)curlcode;
}
}
ssize_t Curl_send_plain(struct connectdata *conn, int num,
const void *mem, size_t len, CURLcode *code)
{
curl_socket_t sockfd = conn->sock[num];
ssize_t bytes_written = swrite(sockfd, mem, len);
*code = CURLE_OK;
if(-1 == bytes_written) {
int err = SOCKERRNO;
@@ -255,65 +294,19 @@ static ssize_t send_plain(struct connectdata *conn,
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
)
) {
/* this is just a case of EWOULDBLOCK */
bytes_written=0;
else
*code = CURLE_AGAIN;
} else {
failf(conn->data, "Send failure: %s",
Curl_strerror(conn, err));
*code = CURLE_SEND_ERROR;
}
}
return bytes_written;
}
/*
* Curl_write() is an internal write function that sends data to the
* server. Works with plain sockets, SCP, SSL or kerberos.
*
* If the write would block (EWOULDBLOCK), we return CURLE_OK and
* (*written == 0). Otherwise we return regular CURLcode value.
*/
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,
const void *mem,
size_t len,
ssize_t *written)
{
ssize_t bytes_written;
int curlcode = CURLE_OK;
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
if(conn->ssl[num].state == ssl_connection_complete)
bytes_written = Curl_ssl_send(conn, num, mem, len, &curlcode);
else if(Curl_ssh_enabled(conn, PROT_SCP))
bytes_written = Curl_scp_send(conn, num, mem, len);
else if(Curl_ssh_enabled(conn, PROT_SFTP))
bytes_written = Curl_sftp_send(conn, num, mem, len);
else if(conn->sec_complete)
bytes_written = Curl_sec_send(conn, num, mem, len);
else
bytes_written = send_plain(conn, num, mem, len);
*written = bytes_written;
if(-1 != bytes_written)
/* we completely ignore the curlcode value when -1 is not returned */
return CURLE_OK;
/* handle EWOULDBLOCK or a send failure */
switch(curlcode) {
case /* EWOULDBLOCK */ -1:
*written = /* EWOULDBLOCK */ 0;
return CURLE_OK;
case CURLE_OK:
/* general send failure */
return CURLE_SEND_ERROR;
default:
/* we got a specific curlcode, forward it */
return (CURLcode)curlcode;
}
}
/*
* Curl_write_plain() is an internal write function that sends data to the
* server using plain sockets only. Otherwise meant to have the exact same
@@ -329,14 +322,45 @@ CURLcode Curl_write_plain(struct connectdata *conn,
CURLcode retcode;
int num = (sockfd == conn->sock[SECONDARYSOCKET]);
bytes_written = send_plain(conn, num, mem, len);
bytes_written = Curl_send_plain(conn, num, mem, len, &retcode);
*written = bytes_written;
retcode = (-1 != bytes_written)?CURLE_OK:CURLE_SEND_ERROR;
return retcode;
}
ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
size_t len, CURLcode *code)
{
curl_socket_t sockfd = conn->sock[num];
ssize_t nread = sread(sockfd, buf, len);
*code = CURLE_OK;
if(-1 == nread) {
int err = SOCKERRNO;
if(
#ifdef WSAEWOULDBLOCK
/* This is how Windows does it */
(WSAEWOULDBLOCK == err)
#else
/* errno may be EWOULDBLOCK or on some systems EAGAIN when it returned
due to its inability to send off data without blocking. We therefor
treat both error codes the same here */
(EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err)
#endif
) {
/* this is just a case of EWOULDBLOCK */
*code = CURLE_AGAIN;
} else {
failf(conn->data, "Recv failure: %s",
Curl_strerror(conn, err));
*code = CURLE_RECV_ERROR;
}
}
return nread;
}
static CURLcode pausewrite(struct SessionHandle *data,
int type, /* what type of data */
const char *ptr,
@@ -476,7 +500,7 @@ CURLcode Curl_client_write(struct connectdata *conn,
return CURLE_OK;
}
int Curl_read_plain(curl_socket_t sockfd,
CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
ssize_t *n)
@@ -490,7 +514,7 @@ int Curl_read_plain(curl_socket_t sockfd,
#else
if((EWOULDBLOCK == err) || (EAGAIN == err) || (EINTR == err))
#endif
return -1;
return CURLE_AGAIN;
else
return CURLE_RECV_ERROR;
}
@@ -504,15 +528,15 @@ int Curl_read_plain(curl_socket_t sockfd,
* Internal read-from-socket function. This is meant to deal with plain
* sockets, SSL sockets and kerberos sockets.
*
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
* Returns a regular CURLcode value.
*/
int Curl_read(struct connectdata *conn, /* connection data */
CURLcode Curl_read(struct connectdata *conn, /* connection data */
curl_socket_t sockfd, /* read from this socket */
char *buf, /* store read data here */
size_t sizerequested, /* max amount to read */
ssize_t *n) /* amount bytes read */
{
CURLcode curlcode = CURLE_RECV_ERROR;
ssize_t nread = 0;
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
@@ -552,50 +576,17 @@ int Curl_read(struct connectdata *conn, /* connection data */
buffertofill = buf;
}
if(conn->ssl[num].state == ssl_connection_complete) {
int curlcode = CURLE_RECV_ERROR;
nread = Curl_ssl_recv(conn, num, buffertofill, bytesfromsocket, &curlcode);
nread = conn->recv[num](conn, num, buffertofill, bytesfromsocket, &curlcode);
if(nread == -1)
return curlcode;
if(nread == -1)
return curlcode;
if(pipelining) {
memcpy(buf, conn->master_buffer, nread);
conn->buf_len = nread;
conn->read_pos = nread;
}
else if(Curl_ssh_enabled(conn, (PROT_SCP|PROT_SFTP))) {
if(conn->protocol & PROT_SCP)
nread = Curl_scp_recv(conn, num, buffertofill, bytesfromsocket);
else if(conn->protocol & PROT_SFTP)
nread = Curl_sftp_recv(conn, num, buffertofill, bytesfromsocket);
#ifdef LIBSSH2CHANNEL_EAGAIN
if(nread == LIBSSH2CHANNEL_EAGAIN)
/* EWOULDBLOCK */
return -1;
#endif
if(nread < 0)
/* since it is negative and not EAGAIN, it was a protocol-layer error */
return CURLE_RECV_ERROR;
}
else {
if(conn->sec_complete)
nread = Curl_sec_read(conn, sockfd, buffertofill,
bytesfromsocket);
/* TODO: Need to handle EAGAIN here somehow, similar to how it
* is done in Curl_read_plain, either right here or in Curl_sec_read
* itself. */
else {
int ret = Curl_read_plain(sockfd, buffertofill, bytesfromsocket,
&nread);
if(ret)
return ret;
}
}
if(nread >= 0) {
if(pipelining) {
memcpy(buf, conn->master_buffer, nread);
conn->buf_len = nread;
conn->read_pos = nread;
}
*n += nread;
}
*n += nread;
return CURLE_OK;
}

View File

@@ -55,15 +55,20 @@ CURLcode Curl_client_write(struct connectdata *conn, int type, char *ptr,
size_t len);
/* internal read-function, does plain socket only */
int Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
ssize_t *n);
CURLcode Curl_read_plain(curl_socket_t sockfd,
char *buf,
size_t bytesfromsocket,
ssize_t *n);
ssize_t Curl_recv_plain(struct connectdata *conn, int num, char *buf,
size_t len, CURLcode *code);
ssize_t Curl_send_plain(struct connectdata *conn, int num,
const void *mem, size_t len, CURLcode *code);
/* internal read-function, does plain socket, SSL and krb4 */
int Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
CURLcode Curl_read(struct connectdata *conn, curl_socket_t sockfd,
char *buf, size_t buffersize,
ssize_t *n);
/* internal write-function, does plain socket, SSL, SCP, SFTP and krb4 */
CURLcode Curl_write(struct connectdata *conn,
curl_socket_t sockfd,

View File

@@ -497,7 +497,7 @@
#if defined(_MSC_VER) && !defined(__POCC__)
# if !defined(HAVE_WINDOWS_H) || ((_MSC_VER < 1300) && !defined(_FILETIME_))
# if !defined(ALLOW_MSVC6_WITHOUT_PSDK)
# error MSVC 6.0 requires 'February 2003 Platform SDK' a.k.a. 'Windows Server 2003 PSDK'
# error MSVC 6.0 requires "February 2003 Platform SDK" a.k.a. "Windows Server 2003 PSDK"
# else
# define CURL_DISABLE_LDAP 1
# endif
@@ -525,7 +525,7 @@ int netware_init(void);
#define LIBIDN_REQUIRED_VERSION "0.4.1"
#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || defined(USE_QSOSSL)
#if defined(USE_GNUTLS) || defined(USE_SSLEAY) || defined(USE_NSS) || defined(USE_QSOSSL) || defined(USE_POLARSSL)
#define USE_SSL /* SSL support has been enabled */
#endif

View File

@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -261,24 +261,42 @@ struct timeval {
/*
* Typedef to 'unsigned char' if bool is not an available 'typedefed' type.
* 'bool' exists on platforms with <stdbool.h>, i.e. C99 platforms.
* On non-C99 platforms there's no bool, so define an enum for that.
* On C99 platforms 'false' and 'true' also exist. Enum uses a
* global namespace though, so use bool_false and bool_true.
*/
#ifndef HAVE_BOOL_T
typedef unsigned char bool;
#define HAVE_BOOL_T
typedef enum {
bool_false = 0,
bool_true = 1
} bool;
/*
* Use a define to let 'true' and 'false' use those enums. There
* are currently no use of true and false in libcurl proper, but
* there are some in the examples. This will cater for any later
* code happening to use true and false.
*/
# define false bool_false
# define true bool_true
# define HAVE_BOOL_T
#endif
/*
* Default definition of uppercase TRUE and FALSE.
* Redefine TRUE and FALSE too, to catch current use. With this
* change, 'bool found = 1' will give a warning on MIPSPro, but
* 'bool found = TRUE' will not. Change tested on IRIX/MIPSPro,
* AIX 5.1/Xlc, Tru64 5.1/cc, w/make test too.
*/
#ifndef TRUE
#define TRUE 1
#define TRUE true
#endif
#ifndef FALSE
#define FALSE 0
#define FALSE false
#endif
@@ -373,38 +391,63 @@ typedef int sig_atomic_t;
#define EINTR WSAEINTR
#undef EINVAL /* override definition in errno.h */
#define EINVAL WSAEINVAL
#undef EWOULDBLOCK /* override definition in errno.h */
#define EWOULDBLOCK WSAEWOULDBLOCK
#undef EINPROGRESS /* override definition in errno.h */
#define EINPROGRESS WSAEINPROGRESS
#undef EALREADY /* override definition in errno.h */
#define EALREADY WSAEALREADY
#undef ENOTSOCK /* override definition in errno.h */
#define ENOTSOCK WSAENOTSOCK
#undef EDESTADDRREQ /* override definition in errno.h */
#define EDESTADDRREQ WSAEDESTADDRREQ
#undef EMSGSIZE /* override definition in errno.h */
#define EMSGSIZE WSAEMSGSIZE
#undef EPROTOTYPE /* override definition in errno.h */
#define EPROTOTYPE WSAEPROTOTYPE
#undef ENOPROTOOPT /* override definition in errno.h */
#define ENOPROTOOPT WSAENOPROTOOPT
#undef EPROTONOSUPPORT /* override definition in errno.h */
#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
#undef EOPNOTSUPP /* override definition in errno.h */
#define EOPNOTSUPP WSAEOPNOTSUPP
#define EPFNOSUPPORT WSAEPFNOSUPPORT
#undef EAFNOSUPPORT /* override definition in errno.h */
#define EAFNOSUPPORT WSAEAFNOSUPPORT
#undef EADDRINUSE /* override definition in errno.h */
#define EADDRINUSE WSAEADDRINUSE
#undef EADDRNOTAVAIL /* override definition in errno.h */
#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
#undef ENETDOWN /* override definition in errno.h */
#define ENETDOWN WSAENETDOWN
#undef ENETUNREACH /* override definition in errno.h */
#define ENETUNREACH WSAENETUNREACH
#undef ENETRESET /* override definition in errno.h */
#define ENETRESET WSAENETRESET
#undef ECONNABORTED /* override definition in errno.h */
#define ECONNABORTED WSAECONNABORTED
#undef ECONNRESET /* override definition in errno.h */
#define ECONNRESET WSAECONNRESET
#undef ENOBUFS /* override definition in errno.h */
#define ENOBUFS WSAENOBUFS
#undef EISCONN /* override definition in errno.h */
#define EISCONN WSAEISCONN
#undef ENOTCONN /* override definition in errno.h */
#define ENOTCONN WSAENOTCONN
#define ESHUTDOWN WSAESHUTDOWN
#define ETOOMANYREFS WSAETOOMANYREFS
#undef ETIMEDOUT /* override definition in errno.h */
#define ETIMEDOUT WSAETIMEDOUT
#undef ECONNREFUSED /* override definition in errno.h */
#define ECONNREFUSED WSAECONNREFUSED
#undef ELOOP /* override definition in errno.h */
#define ELOOP WSAELOOP
#ifndef ENAMETOOLONG /* possible previous definition in errno.h */
#define ENAMETOOLONG WSAENAMETOOLONG
#endif
#define EHOSTDOWN WSAEHOSTDOWN
#undef EHOSTUNREACH /* override definition in errno.h */
#define EHOSTUNREACH WSAEHOSTUNREACH
#ifndef ENOTEMPTY /* possible previous definition in errno.h */
#define ENOTEMPTY WSAENOTEMPTY

View File

@@ -20,6 +20,9 @@
*
* RFC2821 SMTP protocol
* RFC3207 SMTP over TLS
* RFC4954 SMTP Authentication
* RFC2195 CRAM-MD5 authentication
* RFC4616 PLAIN authentication
*
***************************************************************************/
@@ -85,6 +88,9 @@
#include "url.h"
#include "rawstr.h"
#include "strtoofft.h"
#include "curl_base64.h"
#include "curl_md5.h"
#include "curl_hmac.h"
#define _MPRINTF_REPLACE /* use our functions only */
#include <curl/mprintf.h>
@@ -202,26 +208,72 @@ static const struct Curl_handler Curl_handler_smtps_proxy = {
#endif
/* fucntion that checks for an ending smtp status code at the start of the
given string */
/* Function that checks for an ending smtp status code at the start of the
given string.
As a side effect, it also flags allowed authentication mechanisms according
to EHLO AUTH response. */
static int smtp_endofresp(struct pingpong *pp, int *resp)
{
char *line = pp->linestart_resp;
size_t len = pp->nread_resp;
struct connectdata *conn = pp->conn;
struct smtp_conn *smtpc = &conn->proto.smtpc;
int result;
size_t wordlen;
if( (len >= 4) && (' ' == line[3]) &&
ISDIGIT(line[0]) && ISDIGIT(line[1]) && ISDIGIT(line[2])) {
*resp=atoi(line);
return TRUE;
if(len < 4 || !ISDIGIT(line[0]) || !ISDIGIT(line[1]) || !ISDIGIT(line[2]))
return FALSE; /* Nothing for us. */
if((result = line[3] == ' '))
*resp = atoi(line);
line += 4;
len -= 4;
if(smtpc->state == SMTP_EHLO && len >= 5 && !memcmp(line, "AUTH ", 5)) {
line += 5;
len -= 5;
for (;;) {
while (len &&
(*line == ' ' || *line == '\t' || *line == '\r' || *line == '\n')) {
line++;
len--;
}
if(!len)
break;
for (wordlen = 0; wordlen < len && line[wordlen] != ' ' &&
line[wordlen] != '\t' && line[wordlen] != '\r' && line[wordlen] != '\n';)
wordlen++;
if(wordlen == 5 && !memcmp(line, "LOGIN", 5))
smtpc->authmechs |= SMTP_AUTH_LOGIN;
else if(wordlen == 5 && !memcmp(line, "PLAIN", 5))
smtpc->authmechs |= SMTP_AUTH_PLAIN;
else if(wordlen == 8 && !memcmp(line, "CRAM-MD5", 8))
smtpc->authmechs |= SMTP_AUTH_CRAM_MD5;
else if(wordlen == 10 && !memcmp(line, "DIGEST-MD5", 10))
smtpc->authmechs |= SMTP_AUTH_DIGEST_MD5;
else if(wordlen == 6 && !memcmp(line, "GSSAPI", 6))
smtpc->authmechs |= SMTP_AUTH_GSSAPI;
else if(wordlen == 8 && !memcmp(line, "EXTERNAL", 8))
smtpc->authmechs |= SMTP_AUTH_EXTERNAL;
line += wordlen;
len -= wordlen;
}
}
return FALSE; /* nothing for us */
return result;
}
/* This is the ONLY way to change SMTP state! */
static void state(struct connectdata *conn,
smtpstate newstate)
{
struct smtp_conn *smtpc = &conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
/* for debug purposes */
static const char * const names[]={
@@ -230,6 +282,11 @@ static void state(struct connectdata *conn,
"EHLO",
"HELO",
"STARTTLS",
"AUTHPLAIN",
"AUTHLOGIN",
"AUTHPASSWD",
"AUTHCRAM",
"AUTH",
"MAIL",
"RCPT",
"DATA",
@@ -237,9 +294,6 @@ static void state(struct connectdata *conn,
"QUIT",
/* LAST */
};
#endif
struct smtp_conn *smtpc = &conn->proto.smtpc;
#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS)
if(smtpc->state != newstate)
infof(conn->data, "SMTP %p state change from %s to %s\n",
smtpc, names[smtpc->state], names[newstate]);
@@ -252,8 +306,10 @@ static CURLcode smtp_state_ehlo(struct connectdata *conn)
CURLcode result;
struct smtp_conn *smtpc = &conn->proto.smtpc;
smtpc->authmechs = 0; /* No known authentication mechanisms yet. */
/* send EHLO */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "EHLO %s", smtpc->domain);
result = Curl_pp_sendf(&smtpc->pp, "EHLO %s", smtpc->domain);
if(result)
return result;
@@ -268,7 +324,7 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
struct smtp_conn *smtpc = &conn->proto.smtpc;
/* send HELO */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "HELO %s", smtpc->domain);
result = Curl_pp_sendf(&smtpc->pp, "HELO %s", smtpc->domain);
if(result)
return result;
@@ -277,6 +333,109 @@ static CURLcode smtp_state_helo(struct connectdata *conn)
return CURLE_OK;
}
static size_t smtp_auth_plain_data(struct connectdata * conn, char * * outptr)
{
char plainauth[2 * MAX_CURL_USER_LENGTH + MAX_CURL_PASSWORD_LENGTH];
size_t ulen;
size_t plen;
ulen = strlen(conn->user);
plen = strlen(conn->passwd);
if(2 * ulen + plen + 2 > sizeof plainauth)
return -1;
memcpy(plainauth, conn->user, ulen);
plainauth[ulen] = '\0';
memcpy(plainauth + ulen + 1, conn->user, ulen);
plainauth[2 * ulen + 1] = '\0';
memcpy(plainauth + 2 * ulen + 2, conn->passwd, plen);
return Curl_base64_encode(conn->data, plainauth, 2 * ulen + plen + 2, outptr);
}
static size_t smtp_auth_login_user(struct connectdata * conn, char * * outptr)
{
size_t ulen;
ulen = strlen(conn->user);
if(!ulen) {
*outptr = strdup("=");
return *outptr? 1: -1;
}
return Curl_base64_encode(conn->data, conn->user, ulen, outptr);
}
static CURLcode smtp_authenticate(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
struct smtp_conn *smtpc = &conn->proto.smtpc;
char * initresp;
const char * mech;
size_t l;
smtpstate state1;
smtpstate state2;
if(!conn->bits.user_passwd)
state(conn, SMTP_STOP); /* End of connect phase. */
else {
initresp = (char *) NULL;
l = 1;
/* Check supported authentication mechanisms by decreasing order of
preference. */
mech = (const char *) NULL; /* Avoid compiler warnings. */
state1 = SMTP_STOP;
state2 = SMTP_STOP;
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(smtpc->authmechs & SMTP_AUTH_CRAM_MD5) {
mech = "CRAM-MD5";
state1 = SMTP_AUTHCRAM;
}
else
#endif
if(smtpc->authmechs & SMTP_AUTH_PLAIN) {
mech = "PLAIN";
state1 = SMTP_AUTHPLAIN;
state2 = SMTP_AUTH;
l = smtp_auth_plain_data(conn, &initresp);
}
else if(smtpc->authmechs & SMTP_AUTH_LOGIN) {
mech = "LOGIN";
state1 = SMTP_AUTHLOGIN;
state2 = SMTP_AUTHPASSWD;
l = smtp_auth_login_user(conn, &initresp);
}
else
result = CURLE_LOGIN_DENIED; /* Other mechanisms not supported. */
if(!result) {
if(l <= 0)
result = CURLE_OUT_OF_MEMORY;
else if(initresp &&
l + strlen(mech) <= 512 - 8) { /* AUTH <mech> ...<crlf> */
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s %s", mech, initresp);
free(initresp);
if(!result)
state(conn, state2);
}
else {
Curl_safefree(initresp);
result = Curl_pp_sendf(&smtpc->pp, "AUTH %s", mech);
if(!result)
state(conn, state1);
}
}
}
return result;
}
/* For the SMTP "protocol connect" and "doing" phases only */
static int smtp_getsock(struct connectdata *conn,
curl_socket_t *socks,
@@ -295,12 +454,12 @@ static CURLcode smtp_state_starttls_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
if(smtpcode != 220) {
if(data->set.ftp_ssl == CURLUSESSL_TRY)
state(conn, SMTP_STOP);
else {
if(data->set.ftp_ssl != CURLUSESSL_TRY) {
failf(data, "STARTTLS denied. %c", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else
result = smtp_authenticate(conn);
}
else {
/* Curl_ssl_connect is BLOCKING */
@@ -324,23 +483,23 @@ static CURLcode smtp_state_ehlo_resp(struct connectdata *conn,
(void)instate; /* no use for this yet */
if(smtpcode/100 != 2) {
if(data->set.ftp_ssl <= CURLUSESSL_TRY)
if((data->set.ftp_ssl <= CURLUSESSL_TRY || conn->ssl[FIRSTSOCKET].use) &&
!conn->bits.user_passwd)
result = smtp_state_helo(conn);
else {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
}
}
else if(data->set.ftp_ssl && !conn->ssl[FIRSTSOCKET].use) {
/* We don't have a SSL/TLS connection yet, but SSL is requested. Switch
to TLS connection now */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "STARTTLS", NULL);
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "STARTTLS");
state(conn, SMTP_STARTTLS);
}
else {
/* end the connect phase */
state(conn, SMTP_STOP);
}
else
result = smtp_authenticate(conn);
return result;
}
@@ -357,7 +516,7 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn,
if(smtpcode/100 != 2) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
}
else {
/* end the connect phase */
state(conn, SMTP_STOP);
@@ -365,6 +524,223 @@ static CURLcode smtp_state_helo_resp(struct connectdata *conn,
return result;
}
/* for AUTH PLAIN (without initial response) responses */
static CURLcode smtp_state_authplain_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t l;
char * plainauth;
(void)instate; /* no use for this yet */
if(smtpcode != 334) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else {
l = smtp_auth_plain_data(conn, &plainauth);
if(l <= 0)
result = CURLE_OUT_OF_MEMORY;
else {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", plainauth);
free(plainauth);
if(!result)
state(conn, SMTP_AUTH);
}
}
return result;
}
/* for AUTH LOGIN (without initial response) responses */
static CURLcode smtp_state_authlogin_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t l;
char * authuser;
(void)instate; /* no use for this yet */
if(smtpcode != 334) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else {
l = smtp_auth_login_user(conn, &authuser);
if(l <= 0)
result = CURLE_OUT_OF_MEMORY;
else {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authuser);
free(authuser);
if(!result)
state(conn, SMTP_AUTHPASSWD);
}
}
return result;
}
/* for responses to user entry of AUTH LOGIN. */
static CURLcode smtp_state_authpasswd_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
size_t plen;
size_t l;
char * authpasswd;
(void)instate; /* no use for this yet */
if(smtpcode != 334) {
failf(data, "Access denied: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else {
plen = strlen(conn->passwd);
if(!plen)
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "=");
else {
l = Curl_base64_encode(data, conn->passwd, plen, &authpasswd);
if(l <= 0)
result = CURLE_OUT_OF_MEMORY;
else {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", authpasswd);
free(authpasswd);
if(!result)
state(conn, SMTP_AUTH);
}
}
}
return result;
}
#ifndef CURL_DISABLE_CRYPTO_AUTH
/* for AUTH CRAM-MD5 responses. */
static CURLcode smtp_state_authcram_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
char * chlg64 = data->state.buffer;
unsigned char * chlg;
size_t chlglen;
size_t l;
char * rplyb64;
HMAC_context * ctxt;
unsigned char digest[16];
char reply[MAX_CURL_USER_LENGTH + 32 /* 2 * size of MD5 digest */ + 1];
(void)instate; /* no use for this yet */
if(smtpcode != 334) {
failf(data, "Access denied: %d", smtpcode);
return CURLE_LOGIN_DENIED;
}
/* Get the challenge. */
for (chlg64 += 4; *chlg64 == ' ' || *chlg64 == '\t'; chlg64++)
;
chlg = (unsigned char *) NULL;
chlglen = 0;
if(*chlg64 != '=') {
for (l = strlen(chlg64); l--;)
if(chlg64[l] != '\r' && chlg64[l] != '\n' && chlg64[l] != ' ' &&
chlg64[l] != '\t')
break;
if(++l) {
chlg64[l] = '\0';
if(!(chlglen = Curl_base64_decode(chlg64, &chlg)))
return CURLE_OUT_OF_MEMORY;
}
}
/* Compute digest. */
ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
(const unsigned char *) conn->passwd,
(unsigned int)(strlen(conn->passwd)));
if(!ctxt) {
if(chlg)
free(chlg);
return CURLE_OUT_OF_MEMORY;
}
if(chlglen > 0)
Curl_HMAC_update(ctxt, chlg, (unsigned int)(chlglen));
if(chlg)
free(chlg);
Curl_HMAC_final(ctxt, digest);
/* Prepare the reply. */
snprintf(reply, sizeof reply,
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
conn->user, digest[0], digest[1], digest[2], digest[3], digest[4], digest[5],
digest[6], digest[7], digest[8], digest[9], digest[10], digest[11],
digest[12], digest[13], digest[14], digest[15]);
/* Encode it to base64 and send it. */
l = Curl_base64_encode(data, reply, 0, &rplyb64);
if(l <= 0)
result = CURLE_OUT_OF_MEMORY;
else {
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "%s", rplyb64);
free(rplyb64);
if(!result)
state(conn, SMTP_AUTH);
}
return result;
}
#endif
/* for final responses to AUTH sequences. */
static CURLcode smtp_state_auth_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
(void)instate; /* no use for this yet */
if(smtpcode != 235) {
failf(data, "Authentication failed: %d", smtpcode);
result = CURLE_LOGIN_DENIED;
}
else
state(conn, SMTP_STOP); /* End of connect phase. */
return result;
}
/* start the DO phase */
static CURLcode smtp_mail(struct connectdata *conn)
{
@@ -451,7 +827,7 @@ static CURLcode smtp_state_rcpt_resp(struct connectdata *conn,
}
/* send DATA */
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA", "");
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "DATA");
if(result)
return result;
@@ -465,7 +841,6 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
struct FTP *smtp = data->state.proto.smtp;
@@ -477,11 +852,11 @@ static CURLcode smtp_state_data_resp(struct connectdata *conn,
}
/* SMTP upload */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
FIRSTSOCKET, smtp->bytecountp);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
FIRSTSOCKET, smtp->bytecountp);
state(conn, SMTP_STOP);
return result;
return CURLE_OK;
}
/* for the POSTDATA response, which is received after the entire DATA
@@ -542,6 +917,32 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
result = smtp_state_helo_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_STARTTLS:
result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_AUTHPLAIN:
result = smtp_state_authplain_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_AUTHLOGIN:
result = smtp_state_authlogin_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_AUTHPASSWD:
result = smtp_state_authpasswd_resp(conn, smtpcode, smtpc->state);
break;
#ifndef CURL_DISABLE_CRYPTO_AUTH
case SMTP_AUTHCRAM:
result = smtp_state_authcram_resp(conn, smtpcode, smtpc->state);
break;
#endif
case SMTP_AUTH:
result = smtp_state_auth_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_MAIL:
result = smtp_state_mail_resp(conn, smtpcode, smtpc->state);
break;
@@ -550,10 +951,6 @@ static CURLcode smtp_statemach_act(struct connectdata *conn)
result = smtp_state_rcpt_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_STARTTLS:
result = smtp_state_starttls_resp(conn, smtpcode, smtpc->state);
break;
case SMTP_DATA:
result = smtp_state_data_resp(conn, smtpcode, smtpc->state);
break;
@@ -723,7 +1120,7 @@ static CURLcode smtp_connect(struct connectdata *conn,
/* url decode the path and use it as domain with EHLO */
smtpc->domain = curl_easy_unescape(conn->data, path, 0, &len);
if (!smtpc->domain)
if(!smtpc->domain)
return CURLE_OUT_OF_MEMORY;
/* When we connect, we start in the state where we await the server greeting
@@ -894,7 +1291,7 @@ static CURLcode smtp_quit(struct connectdata *conn)
{
CURLcode result = CURLE_OK;
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT", NULL);
result = Curl_pp_sendf(&conn->proto.smtpc.pp, "QUIT");
if(result)
return result;
state(conn, SMTP_QUIT);
@@ -922,11 +1319,15 @@ static CURLcode smtp_disconnect(struct connectdata *conn)
/* The SMTP session may or may not have been allocated/setup at this
point! */
if (smtpc->pp.conn)
if(smtpc->pp.conn)
(void)smtp_quit(conn); /* ignore errors on the LOGOUT */
Curl_pp_disconnect(&smtpc->pp);
/* This won't already be freed in some error cases */
Curl_safefree(smtpc->domain);
smtpc->domain = NULL;
return CURLE_OK;
}
@@ -934,18 +1335,18 @@ static CURLcode smtp_disconnect(struct connectdata *conn)
static CURLcode smtp_dophase_done(struct connectdata *conn,
bool connected)
{
CURLcode result = CURLE_OK;
struct FTP *smtp = conn->data->state.proto.smtp;
struct smtp_conn *smtpc= &conn->proto.smtpc;
(void)connected;
if(smtp->transfer != FTPTRANSFER_BODY)
/* no data to transfer */
result=Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
free(smtpc->domain);
smtpc->domain = NULL;
return result;
return CURLE_OK;
}
/* called from multi.c while DOing */

View File

@@ -34,6 +34,11 @@ typedef enum {
SMTP_EHLO,
SMTP_HELO,
SMTP_STARTTLS,
SMTP_AUTHPLAIN,
SMTP_AUTHLOGIN,
SMTP_AUTHPASSWD,
SMTP_AUTHCRAM,
SMTP_AUTH,
SMTP_MAIL, /* MAIL FROM */
SMTP_RCPT, /* RCPT TO */
SMTP_DATA,
@@ -49,10 +54,19 @@ struct smtp_conn {
char *domain; /* what to send in the EHLO */
size_t eob; /* number of bytes of the EOB (End Of Body) that has been
received thus far */
unsigned int authmechs; /* Accepted authentication methods. */
smtpstate state; /* always use smtp.c:state() to change state! */
struct curl_slist *rcpt;
};
/* Authentication mechanism flags. */
#define SMTP_AUTH_LOGIN 0x0001
#define SMTP_AUTH_PLAIN 0x0002
#define SMTP_AUTH_CRAM_MD5 0x0004
#define SMTP_AUTH_DIGEST_MD5 0x0008
#define SMTP_AUTH_GSSAPI 0x0010
#define SMTP_AUTH_EXTERNAL 0x0020
extern const struct Curl_handler Curl_handler_smtp;
extern const struct Curl_handler Curl_handler_smtps;

View File

@@ -77,7 +77,7 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
conntime = Curl_tvdiff(tvnow, conn->created);
if(conntime > conn_timeout) {
/* we already got the timeout */
result = ~CURLE_OK;
result = CURLE_OPERATION_TIMEDOUT;
break;
}
if(Curl_socket_ready(sockfd, CURL_SOCKET_BAD,
@@ -86,7 +86,9 @@ int Curl_blockread_all(struct connectdata *conn, /* connection data */
break;
}
result = Curl_read_plain(sockfd, buf, buffersize, &nread);
if(result)
if(CURLE_AGAIN == result)
continue;
else if(result)
break;
if(buffersize == nread) {
@@ -172,8 +174,8 @@ CURLcode Curl_SOCKS4(const char *proxy_name,
return CURLE_COULDNT_RESOLVE_PROXY;
if(rc == CURLRESOLV_PENDING)
/* this requires that we're in "wait for resolve" state */
rc = Curl_wait_for_resolv(conn, &dns);
/* ignores the return code, but 'dns' remains NULL on failure */
(void)Curl_wait_for_resolv(conn, &dns);
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It
@@ -511,11 +513,13 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
*/
len = 0;
socksreq[len++] = 1; /* username/pw subnegotiation version */
socksreq[len++] = (char) userlen;
memcpy(socksreq + len, proxy_name, userlen);
socksreq[len++] = (unsigned char) userlen;
if(proxy_name && userlen)
memcpy(socksreq + len, proxy_name, userlen);
len += (int)userlen;
socksreq[len++] = (char) pwlen;
memcpy(socksreq + len, proxy_password, pwlen);
socksreq[len++] = (unsigned char) pwlen;
if(proxy_password && pwlen)
memcpy(socksreq + len, proxy_password, pwlen);
len += (int)pwlen;
code = Curl_write_plain(conn, sock, (char *)socksreq, len, &written);
@@ -597,9 +601,12 @@ CURLcode Curl_SOCKS5(const char *proxy_name,
if(rc == CURLRESOLV_ERROR)
return CURLE_COULDNT_RESOLVE_HOST;
if(rc == CURLRESOLV_PENDING)
if(rc == CURLRESOLV_PENDING) {
/* this requires that we're in "wait for resolve" state */
rc = Curl_wait_for_resolv(conn, &dns);
code = Curl_wait_for_resolv(conn, &dns);
if(code != CURLE_OK)
return code;
}
/*
* We cannot use 'hostent' as a struct that Curl_resolv() returns. It

View File

@@ -394,6 +394,10 @@ int main(int argc, argv_item_t argv[])
for (i = 0; i < MAX; i++) {
struct timeval key;
ptrs[i] = t = malloc(sizeof(struct Curl_tree));
if(!t) {
puts("out of memory!");
return 0;
}
key.tv_sec = 0;
#ifdef TEST2
@@ -405,10 +409,6 @@ int main(int argc, argv_item_t argv[])
#endif
t->payload = (void *)key.tv_usec; /* for simplicity */
if(!t) {
puts("out of memory!");
return 0;
}
root = Curl_splayinsert(key, root, t);
}

View File

@@ -1556,8 +1556,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
Curl_pgrsSetUploadSize(data, data->set.infilesize);
}
/* upload data */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL,
FIRSTSOCKET, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, FIRSTSOCKET, NULL);
/* not set by Curl_setup_transfer to preserve keepon bits */
conn->sockfd = conn->writesockfd;
@@ -1850,7 +1849,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
sshc->readdir_longentry = NULL;
/* no data to transfer */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
state(conn, SSH_STOP);
break;
@@ -1910,7 +1909,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
char *ptr2;
from=curlx_strtoofft(conn->data->state.range, &ptr, 0);
while(ptr && *ptr && (isspace((int)*ptr) || (*ptr=='-')))
while(*ptr && (isspace((int)*ptr) || (*ptr=='-')))
ptr++;
to=curlx_strtoofft(ptr, &ptr2, 0);
if((ptr == ptr2) /* no "to" value given */
@@ -1975,14 +1974,14 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* Setup the actual download */
if(data->req.size == 0) {
/* no data to transfer */
result = Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
infof(data, "File already completely downloaded\n");
state(conn, SSH_STOP);
break;
}
else {
result = Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, data->req.size,
FALSE, NULL, -1, NULL);
/* not set by Curl_setup_transfer to preserve keepon bits */
conn->writesockfd = conn->sockfd;
@@ -2107,8 +2106,8 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
}
/* upload data */
result = Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
FIRSTSOCKET, NULL);
Curl_setup_transfer(conn, -1, data->req.size, FALSE, NULL,
FIRSTSOCKET, NULL);
/* not set by Curl_setup_transfer to preserve keepon bits */
conn->sockfd = conn->writesockfd;
@@ -2159,8 +2158,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* download data */
bytecount = (curl_off_t)sb.st_size;
data->req.maxdownload = (curl_off_t)sb.st_size;
result = Curl_setup_transfer(conn, FIRSTSOCKET,
bytecount, FALSE, NULL, -1, NULL);
Curl_setup_transfer(conn, FIRSTSOCKET, bytecount, FALSE, NULL, -1, NULL);
/* not set by Curl_setup_transfer to preserve keepon bits */
conn->writesockfd = conn->sockfd;
@@ -2410,15 +2408,28 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
return result;
}
static CURLcode ssh_easy_statemach(struct connectdata *conn)
static CURLcode ssh_easy_statemach(struct connectdata *conn,
bool duringconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data;
while((sshc->state != SSH_STOP) && !result) {
bool block;
long left;
result = ssh_statemach_act(conn, &block);
if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK;
left = Curl_timeleft(conn, NULL, duringconnect);
if(left < 0) {
failf(data, "Operation timed out\n");
return CURLE_OPERATION_TIMEDOUT;
}
#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
if((CURLE_OK == result) && block) {
int dir = libssh2_session_block_directions(sshc->ssh_session);
@@ -2432,7 +2443,8 @@ static CURLcode ssh_easy_statemach(struct connectdata *conn)
fd_write = sock;
}
/* wait for the socket to become ready */
Curl_socket_ready(fd_read, fd_write, 1000); /* ignore result */
Curl_socket_ready(fd_read, fd_write,
left>1000?1000:left); /* ignore result */
}
#endif
@@ -2466,6 +2478,9 @@ static CURLcode ssh_init(struct connectdata *conn)
return CURLE_OK;
}
static Curl_recv scp_recv, sftp_recv;
static Curl_send scp_send, sftp_send;
/*
* Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
* do protocol-specific actions at connect-time.
@@ -2491,6 +2506,13 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
if(result)
return result;
if(conn->protocol & PROT_SCP) {
conn->recv[FIRSTSOCKET] = scp_recv;
conn->send[FIRSTSOCKET] = scp_send;
} else {
conn->recv[FIRSTSOCKET] = sftp_recv;
conn->send[FIRSTSOCKET] = sftp_send;
}
ssh = &conn->proto.sshc;
#ifdef CURL_LIBSSH2_DEBUG
@@ -2540,7 +2562,7 @@ static CURLcode ssh_connect(struct connectdata *conn, bool *done)
if(data->state.used_interface == Curl_if_multi)
result = ssh_multi_statemach(conn, done);
else {
result = ssh_easy_statemach(conn);
result = ssh_easy_statemach(conn, TRUE);
if(!result)
*done = TRUE;
}
@@ -2576,7 +2598,7 @@ CURLcode scp_perform(struct connectdata *conn,
result = ssh_multi_statemach(conn, dophase_done);
}
else {
result = ssh_easy_statemach(conn);
result = ssh_easy_statemach(conn, FALSE);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
*connected = conn->bits.tcpconnect;
@@ -2657,7 +2679,7 @@ static CURLcode scp_disconnect(struct connectdata *conn)
state(conn, SSH_SESSION_DISCONNECT);
result = ssh_easy_statemach(conn);
result = ssh_easy_statemach(conn, FALSE);
}
return result;
@@ -2678,7 +2700,7 @@ static CURLcode ssh_done(struct connectdata *conn, CURLcode status)
non-blocking DONE operations, not in the multi state machine and with
Curl_done() invokes on several places in the code!
*/
result = ssh_easy_statemach(conn);
result = ssh_easy_statemach(conn, FALSE);
}
else
result = status;
@@ -2705,8 +2727,8 @@ static CURLcode scp_done(struct connectdata *conn, CURLcode status,
}
/* return number of received (decrypted) bytes */
ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len)
static ssize_t scp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
@@ -2717,8 +2739,10 @@ ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN)
return 0;
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nwrite = 0;
}
return nwrite;
}
@@ -2727,8 +2751,8 @@ ssize_t Curl_scp_send(struct connectdata *conn, int sockindex,
* If the read would block (EWOULDBLOCK) we return -1. Otherwise we return
* a regular CURLcode value.
*/
ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len)
static ssize_t scp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
(void)sockindex; /* we only support SCP on the fixed known primary socket */
@@ -2738,6 +2762,10 @@ ssize_t Curl_scp_recv(struct connectdata *conn, int sockindex,
libssh2_channel_read(conn->proto.sshc.ssh_channel, mem, len);
ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if (nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
return nread;
}
@@ -2774,7 +2802,7 @@ CURLcode sftp_perform(struct connectdata *conn,
result = ssh_multi_statemach(conn, dophase_done);
}
else {
result = ssh_easy_statemach(conn);
result = ssh_easy_statemach(conn, FALSE);
*dophase_done = TRUE; /* with the easy interface we are done here */
}
*connected = conn->bits.tcpconnect;
@@ -2814,7 +2842,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn)
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN);
result = ssh_easy_statemach(conn);
result = ssh_easy_statemach(conn, FALSE);
}
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
@@ -2842,8 +2870,8 @@ static CURLcode sftp_done(struct connectdata *conn, CURLcode status,
}
/* return number of sent bytes */
ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len)
static ssize_t sftp_send(struct connectdata *conn, int sockindex,
const void *mem, size_t len, CURLcode *err)
{
ssize_t nwrite; /* libssh2_sftp_write() used to return size_t in 0.14
but is changed to ssize_t in 0.15. These days we don't
@@ -2854,8 +2882,10 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nwrite == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nwrite == LIBSSH2_ERROR_EAGAIN)
return 0;
if(nwrite == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nwrite = 0;
}
return nwrite;
}
@@ -2863,8 +2893,8 @@ ssize_t Curl_sftp_send(struct connectdata *conn, int sockindex,
/*
* Return number of received (decrypted) bytes
*/
ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len)
static ssize_t sftp_recv(struct connectdata *conn, int sockindex,
char *mem, size_t len, CURLcode *err)
{
ssize_t nread;
(void)sockindex;
@@ -2873,6 +2903,10 @@ ssize_t Curl_sftp_recv(struct connectdata *conn, int sockindex,
ssh_block2waitfor(conn, (nread == LIBSSH2_ERROR_EAGAIN)?TRUE:FALSE);
if(nread == LIBSSH2_ERROR_EAGAIN) {
*err = CURLE_AGAIN;
nread = -1;
}
return nread;
}

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